-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: registry handlers #31
Changes from 4 commits
c035059
b038c42
38947f8
00f4a92
1d60049
9e4e78d
0df4dc9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
export * from "./profileCreated.handler.js"; | ||
export * from "./profileMetadataUpdated.handler.js"; | ||
export * from "./profileNameUpdated.handler.js"; | ||
export * from "./profileOwnerUpdated.handler.js"; | ||
export * from "./roleGranted.handler.js"; | ||
export * from "./roleRevoked.handler.js"; |
Original file line number | Diff line number | Diff line change | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|
@@ -0,0 +1,65 @@ | ||||||||||||
import { Changeset, ProjectType } from "@grants-stack-indexer/repository"; | ||||||||||||
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; | ||||||||||||
|
||||||||||||
import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; | ||||||||||||
import { ProjectMetadata, ProjectMetadataSchema } from "../../../schemas/index.js"; | ||||||||||||
|
||||||||||||
type Dependencies = Pick< | ||||||||||||
ProcessorDependencies, | ||||||||||||
"projectRepository" | "evmProvider" | "metadataProvider" | "logger" | ||||||||||||
>; | ||||||||||||
/** | ||||||||||||
* Handles the ProfileMetadataUpdated event for the Registry contract from Allo protocol. | ||||||||||||
*/ | ||||||||||||
export class ProfileMetadataUpdatedHandler | ||||||||||||
implements IEventHandler<"Registry", "ProfileMetadataUpdated"> | ||||||||||||
{ | ||||||||||||
constructor( | ||||||||||||
readonly event: ProcessorEvent<"Registry", "ProfileMetadataUpdated">, | ||||||||||||
readonly chainId: ChainId, | ||||||||||||
private dependencies: Dependencies, | ||||||||||||
) {} | ||||||||||||
async handle(): Promise<Changeset[]> { | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
or a more specific description |
||||||||||||
const { metadataProvider } = this.dependencies; | ||||||||||||
|
||||||||||||
const metadataCid = this.event.params.metadata[1]; | ||||||||||||
const metadata = await metadataProvider.getMetadata(metadataCid); | ||||||||||||
const parsedMetadata = ProjectMetadataSchema.safeParse(metadata); | ||||||||||||
|
||||||||||||
if (!parsedMetadata.success) { | ||||||||||||
// logger.warn({ | ||||||||||||
// msg: `ProfileMetadataUpdated: Failed to parse metadata`, | ||||||||||||
// event, | ||||||||||||
// metadataCid, | ||||||||||||
// metadata, | ||||||||||||
// }); | ||||||||||||
return []; | ||||||||||||
} | ||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we throw or return empty? |
||||||||||||
|
||||||||||||
const projectType = this.getProjectTypeFromMetadata(parsedMetadata.data); | ||||||||||||
|
||||||||||||
return [ | ||||||||||||
{ | ||||||||||||
type: "UpdateProject", | ||||||||||||
args: { | ||||||||||||
chainId: this.chainId, | ||||||||||||
projectId: this.event.params.profileId, | ||||||||||||
project: { | ||||||||||||
metadataCid: metadataCid, | ||||||||||||
metadata: metadata, | ||||||||||||
projectType, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
}, | ||||||||||||
]; | ||||||||||||
return []; | ||||||||||||
} | ||||||||||||
private getProjectTypeFromMetadata(metadata: ProjectMetadata): ProjectType { | ||||||||||||
// if the metadata contains a canonical reference, it's a linked project | ||||||||||||
if ("canonical" in metadata) { | ||||||||||||
return "linked"; | ||||||||||||
} | ||||||||||||
|
||||||||||||
return "canonical"; | ||||||||||||
} | ||||||||||||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto for description and inheritdoc |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
import { getAddress } from "viem"; | ||
|
||
import { Changeset } from "@grants-stack-indexer/repository"; | ||
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; | ||
|
||
import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; | ||
|
||
type Dependencies = Pick<ProcessorDependencies, "logger">; | ||
0xkenj1 marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/** | ||
* Handles the ProfileNameUpdated event for the Registry contract from Allo protocol. | ||
*/ | ||
export class ProfileNameUpdatedHandler implements IEventHandler<"Registry", "ProfileNameUpdated"> { | ||
constructor( | ||
readonly event: ProcessorEvent<"Registry", "ProfileNameUpdated">, | ||
readonly chainId: ChainId, | ||
private dependencies: Dependencies, | ||
) {} | ||
async handle(): Promise<Changeset[]> { | ||
return [ | ||
{ | ||
type: "UpdateProject", | ||
args: { | ||
chainId: this.chainId, | ||
projectId: this.event.params.profileId, | ||
project: { | ||
name: this.event.params.name, | ||
anchorAddress: getAddress(this.event.params.anchor), | ||
}, | ||
}, | ||
}, | ||
]; | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto for description and inheritdoc |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
import { getAddress } from "viem"; | ||
|
||
import { Changeset } from "@grants-stack-indexer/repository"; | ||
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; | ||
|
||
import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; | ||
|
||
type Dependencies = Pick<ProcessorDependencies, "logger">; | ||
/** | ||
* Handles the ProfileOwnerUpdated event for the Registry contract from Allo protocol. | ||
*/ | ||
export class ProfileOwnerUpdatedHandler | ||
implements IEventHandler<"Registry", "ProfileOwnerUpdated"> | ||
{ | ||
constructor( | ||
readonly event: ProcessorEvent<"Registry", "ProfileOwnerUpdated">, | ||
readonly chainId: ChainId, | ||
private dependencies: Dependencies, | ||
) {} | ||
async handle(): Promise<Changeset[]> { | ||
return [ | ||
{ | ||
type: "DeleteAllProjectRolesByRole", | ||
args: { | ||
projectRole: { | ||
chainId: this.chainId, | ||
projectId: this.event.params.profileId, | ||
role: "owner", | ||
}, | ||
}, | ||
}, | ||
{ | ||
type: "InsertProjectRole", | ||
args: { | ||
projectRole: { | ||
chainId: this.chainId, | ||
projectId: this.event.params.profileId, | ||
address: getAddress(this.event.params.owner), | ||
role: "owner", | ||
createdAtBlock: BigInt(this.event.blockNumber), | ||
}, | ||
}, | ||
}, | ||
]; | ||
} | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto for description and inheritdoc |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { getAddress } from "viem"; | ||
|
||
import { Changeset } from "@grants-stack-indexer/repository"; | ||
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; | ||
|
||
import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; | ||
|
||
type Dependencies = Pick<ProcessorDependencies, "projectRepository" | "logger">; | ||
/** | ||
* Handles the RoleRevoked event for the Registry contract from Allo protocol. | ||
*/ | ||
export class RoleRevokedHandler implements IEventHandler<"Registry", "RoleRevoked"> { | ||
constructor( | ||
readonly event: ProcessorEvent<"Registry", "RoleRevoked">, | ||
readonly chainId: ChainId, | ||
private dependencies: Dependencies, | ||
) {} | ||
async handle(): Promise<Changeset[]> { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
const { projectRepository } = this.dependencies; | ||
const account = getAddress(this.event.params.account); | ||
const role = this.event.params.role.toLowerCase(); | ||
const project = await projectRepository.getProjectById(this.chainId, role); | ||
|
||
// The role value for a member is the profileId in Allo V1 | ||
// which is the project id in this database. | ||
// If we don't find a project with that id we can't remove the role. | ||
if (!project) { | ||
return []; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should we throw here? |
||
|
||
return [ | ||
{ | ||
type: "DeleteAllProjectRolesByRoleAndAddress", | ||
args: { | ||
projectRole: { | ||
chainId: this.chainId, | ||
projectId: project.id, | ||
address: account, | ||
role: "member", | ||
}, | ||
}, | ||
}, | ||
]; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
import { Changeset } from "@grants-stack-indexer/repository"; | ||
import { ChainId, ProcessorEvent, RegistryEvent } from "@grants-stack-indexer/shared"; | ||
|
||
import type { IProcessor } from "../../internal.js"; | ||
import { UnsupportedEventException } from "../../internal.js"; | ||
import { ProcessorDependencies } from "../../types/processor.types.js"; | ||
import { | ||
ProfileCreatedHandler, | ||
ProfileMetadataUpdatedHandler, | ||
ProfileNameUpdatedHandler, | ||
ProfileOwnerUpdatedHandler, | ||
RoleGrantedHandler, | ||
RoleRevokedHandler, | ||
} from "./handlers/index.js"; | ||
|
||
export class RegistryProcessor implements IProcessor<"Registry", RegistryEvent> { | ||
constructor( | ||
private readonly chainId: ChainId, | ||
private readonly dependencies: ProcessorDependencies, | ||
) {} | ||
|
||
async process(event: ProcessorEvent<"Registry", RegistryEvent>): Promise<Changeset[]> { | ||
//TODO: Implement robust error handling and retry logic | ||
switch (event.eventName) { | ||
case "ProfileCreated": | ||
return new ProfileCreatedHandler( | ||
event as ProcessorEvent<"Registry", "ProfileCreated">, | ||
this.chainId, | ||
this.dependencies, | ||
).handle(); | ||
case "ProfileMetadataUpdated": | ||
return new ProfileMetadataUpdatedHandler( | ||
event as ProcessorEvent<"Registry", "ProfileMetadataUpdated">, | ||
this.chainId, | ||
this.dependencies, | ||
).handle(); | ||
case "ProfileNameUpdated": | ||
return new ProfileNameUpdatedHandler( | ||
event as ProcessorEvent<"Registry", "ProfileNameUpdated">, | ||
this.chainId, | ||
this.dependencies, | ||
).handle(); | ||
case "ProfileOwnerUpdated": | ||
return new ProfileOwnerUpdatedHandler( | ||
event as ProcessorEvent<"Registry", "ProfileOwnerUpdated">, | ||
this.chainId, | ||
this.dependencies, | ||
).handle(); | ||
case "RoleGranted": | ||
return new RoleGrantedHandler( | ||
event as ProcessorEvent<"Registry", "RoleGranted">, | ||
this.chainId, | ||
this.dependencies, | ||
).handle(); | ||
case "RoleRevoked": | ||
return new RoleRevokedHandler( | ||
event as ProcessorEvent<"Registry", "RoleRevoked">, | ||
this.chainId, | ||
this.dependencies, | ||
).handle(); | ||
|
||
default: | ||
throw new UnsupportedEventException("Registry", event.eventName); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i like adding here a general overview of the main actions performed by the handler
for example for
PoolCreatedHandler
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is great, i saw it on your prs 💯