-
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 6 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,78 @@ | ||
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. | ||
* | ||
* This handler performs the following steps: | ||
* - Fetches the metadata for the profile from the metadata provider | ||
* - Parses the metadata to extract the project type | ||
* - Returns the changeset to update the project with the metadata | ||
*/ | ||
export class ProfileMetadataUpdatedHandler | ||
implements IEventHandler<"Registry", "ProfileMetadataUpdated"> | ||
{ | ||
constructor( | ||
readonly event: ProcessorEvent<"Registry", "ProfileMetadataUpdated">, | ||
readonly chainId: ChainId, | ||
private dependencies: Dependencies, | ||
) {} | ||
/* @inheritdoc */ | ||
async handle(): Promise<Changeset[]> { | ||
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) { | ||
return [ | ||
{ | ||
type: "UpdateProject", | ||
args: { | ||
chainId: this.chainId, | ||
projectId: this.event.params.profileId, | ||
project: { | ||
metadataCid: metadataCid, | ||
metadata: null, | ||
projectType: "canonical", | ||
}, | ||
}, | ||
}, | ||
]; | ||
} | ||
|
||
const projectType = this.getProjectTypeFromMetadata(parsedMetadata.data); | ||
|
||
return [ | ||
{ | ||
type: "UpdateProject", | ||
args: { | ||
chainId: this.chainId, | ||
projectId: this.event.params.profileId, | ||
project: { | ||
metadataCid: metadataCid, | ||
metadata: metadata, | ||
projectType, | ||
}, | ||
}, | ||
}, | ||
]; | ||
} | ||
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,37 @@ | ||
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. | ||
* | ||
* This handler performs the following steps: | ||
* - Returns the changeset to update the project with the new name | ||
*/ | ||
export class ProfileNameUpdatedHandler implements IEventHandler<"Registry", "ProfileNameUpdated"> { | ||
constructor( | ||
readonly event: ProcessorEvent<"Registry", "ProfileNameUpdated">, | ||
readonly chainId: ChainId, | ||
private dependencies: Dependencies, | ||
) {} | ||
/* @inheritdoc */ | ||
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,52 @@ | ||
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. | ||
* | ||
* This handler performs the following steps: | ||
* | ||
* - Returns the changeset to delete all project roles with the role "owner" | ||
* for the profile and insert a new project role with the new owner address. | ||
*/ | ||
export class ProfileOwnerUpdatedHandler | ||
implements IEventHandler<"Registry", "ProfileOwnerUpdated"> | ||
{ | ||
constructor( | ||
readonly event: ProcessorEvent<"Registry", "ProfileOwnerUpdated">, | ||
readonly chainId: ChainId, | ||
private dependencies: Dependencies, | ||
) {} | ||
/* @inheritdoc */ | ||
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,52 @@ | ||
import { getAddress } from "viem"; | ||
|
||
import { Changeset } from "@grants-stack-indexer/repository"; | ||
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; | ||
|
||
import { IEventHandler, ProcessorDependencies, ProjectByRoleNotFound } from "../../../internal.js"; | ||
|
||
type Dependencies = Pick<ProcessorDependencies, "projectRepository" | "logger">; | ||
/** | ||
* Handles the RoleRevoked event for the Registry contract from Allo protocol. | ||
* | ||
* This handler performs the following steps: | ||
* | ||
* - Returns the changeset to delete all project roles with the role "member" | ||
* for the profile and address. | ||
* | ||
* If the project with the role id doesn't exist, it throws an error. | ||
*/ | ||
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) { | ||
throw new ProjectByRoleNotFound(this.chainId, role); | ||
} | ||
|
||
return [ | ||
{ | ||
type: "DeleteAllProjectRolesByRoleAndAddress", | ||
args: { | ||
projectRole: { | ||
chainId: this.chainId, | ||
projectId: project.id, | ||
address: account, | ||
role: "member", | ||
}, | ||
}, | ||
}, | ||
]; | ||
} | ||
} |
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 guess the above exception should be called ProjectByAnchorNotFound since there are multiple of these but just a suggestion