Skip to content

Commit 759c2fb

Browse files
committed
Merge branch 'dev' into feat/dummy-pricing-provider
2 parents 99eb985 + 81254f2 commit 759c2fb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+799
-110
lines changed

packages/data-flow/test/unit/eventsRegistry.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ describe("InMemoryEventsRegistry", () => {
4848
expect(retrievedEvent).toEqual(mockEvent);
4949
});
5050

51-
it("should update the last processed event when saving multiple times", async () => {
51+
it("updates the last processed event when saving multiple times", async () => {
5252
const registry = new InMemoryEventsRegistry(logger);
5353

5454
const firstEvent: ProcessorEvent<"Allo", "PoolCreated"> = {

packages/processors/src/exceptions/projectNotFound.exception.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,9 @@ export class ProjectNotFound extends Error {
55
super(`Project not found for chainId: ${chainId} and anchorAddress: ${anchorAddress}`);
66
}
77
}
8+
9+
export class ProjectByRoleNotFound extends Error {
10+
constructor(chainId: ChainId, role: string) {
11+
super(`Project not found for chainId: ${chainId} and role: ${role}`);
12+
}
13+
}

packages/processors/src/internal.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ export * from "./interfaces/index.js";
66
export * from "./exceptions/index.js";
77

88
// Allo
9-
export * from "./allo/index.js";
9+
export * from "./processors/allo/index.js";
1010

1111
// Strategy
12-
export * from "./strategy/index.js";
13-
export * from "./registry/index.js";
12+
export * from "./processors/strategy/index.js";
13+
export * from "./processors/registry/index.js";

packages/processors/src/allo/allo.processor.ts renamed to packages/processors/src/processors/allo/allo.processor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Changeset } from "@grants-stack-indexer/repository";
22
import { AlloEvent, ChainId, ProcessorEvent } from "@grants-stack-indexer/shared";
33

4-
import type { IProcessor, ProcessorDependencies } from "../internal.js";
5-
import { UnsupportedEventException } from "../internal.js";
4+
import type { IProcessor, ProcessorDependencies } from "../../internal.js";
5+
import { UnsupportedEventException } from "../../internal.js";
66
import { PoolCreatedHandler } from "./handlers/index.js";
77

88
/**

packages/processors/src/allo/handlers/poolCreated.handler.ts renamed to packages/processors/src/processors/allo/handlers/poolCreated.handler.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import type { Changeset, NewRound, PendingRoundRole } from "@grants-stack-indexe
44
import type { ChainId, ProcessorEvent, Token } from "@grants-stack-indexer/shared";
55
import { getToken, isAlloNativeToken } from "@grants-stack-indexer/shared";
66

7-
import type { IEventHandler, ProcessorDependencies, StrategyTimings } from "../../internal.js";
8-
import { calculateAmountInUsd, getRoundRoles } from "../../helpers/index.js";
9-
import { StrategyHandlerFactory, TokenPriceNotFoundError } from "../../internal.js";
10-
import { RoundMetadataSchema } from "../../schemas/index.js";
7+
import type { IEventHandler, ProcessorDependencies, StrategyTimings } from "../../../internal.js";
8+
import { calculateAmountInUsd, getRoundRoles } from "../../../helpers/index.js";
9+
import { StrategyHandlerFactory, TokenPriceNotFoundError } from "../../../internal.js";
10+
import { RoundMetadataSchema } from "../../../schemas/index.js";
1111

1212
type Dependencies = Pick<
1313
ProcessorDependencies,
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export * from "./profileCreated.handler.js";
2+
export * from "./profileMetadataUpdated.handler.js";
3+
export * from "./profileNameUpdated.handler.js";
4+
export * from "./profileOwnerUpdated.handler.js";
5+
export * from "./roleGranted.handler.js";
6+
export * from "./roleRevoked.handler.js";

packages/processors/src/registry/handlers/profileCreated.handler.ts renamed to packages/processors/src/processors/registry/handlers/profileCreated.handler.ts

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,22 @@ import { getAddress } from "viem";
33
import { Changeset, ProjectType } from "@grants-stack-indexer/repository";
44
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared";
55

6-
import { IEventHandler, ProcessorDependencies } from "../../internal.js";
7-
import { ProjectMetadata, ProjectMetadataSchema } from "../../schemas/projectMetadata.js";
6+
import { IEventHandler, ProcessorDependencies } from "../../../internal.js";
7+
import { ProjectMetadata, ProjectMetadataSchema } from "../../../schemas/projectMetadata.js";
88

99
type Dependencies = Pick<
1010
ProcessorDependencies,
1111
"projectRepository" | "evmProvider" | "metadataProvider" | "logger"
1212
>;
1313
/**
1414
* Handles the ProfileCreated event for the Registry contract from Allo protocol.
15+
*
16+
* This handler performs the following steps:
17+
* - Fetches the metadata for the profile from the metadata provider
18+
* - Parses the metadata to extract the project type
19+
* - Returns the changeset to insert the project with the metadata
20+
*
21+
* If the metadata is not valid, it sets the metadata to null and the project type to canonical.
1522
*/
1623
export class ProfileCreatedHandler implements IEventHandler<"Registry", "ProfileCreated"> {
1724
constructor(
@@ -35,14 +42,6 @@ export class ProfileCreatedHandler implements IEventHandler<"Registry", "Profile
3542
projectType = this.getProjectTypeFromMetadata(parsedMetadata.data);
3643
isProgram = parsedMetadata.data.type === "program";
3744
metadataValue = parsedMetadata.data;
38-
} else {
39-
//TODO: Replace with logger
40-
// this.logger.warn({
41-
// msg: `ProfileCreated: Failed to parse metadata for profile ${profileId}`,
42-
// event: this.event,
43-
// metadataCid,
44-
// metadata,
45-
// });
4645
}
4746

4847
const createdBy =
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import { Changeset, ProjectType } from "@grants-stack-indexer/repository";
2+
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared";
3+
4+
import { IEventHandler, ProcessorDependencies } from "../../../internal.js";
5+
import { ProjectMetadata, ProjectMetadataSchema } from "../../../schemas/index.js";
6+
7+
type Dependencies = Pick<
8+
ProcessorDependencies,
9+
"projectRepository" | "evmProvider" | "metadataProvider" | "logger"
10+
>;
11+
12+
/**
13+
* Handles the ProfileMetadataUpdated event for the Registry contract from Allo protocol.
14+
*
15+
* This handler performs the following steps:
16+
* - Fetches the metadata for the profile from the metadata provider
17+
* - Parses the metadata to extract the project type
18+
* - Returns the changeset to update the project with the metadata
19+
*/
20+
export class ProfileMetadataUpdatedHandler
21+
implements IEventHandler<"Registry", "ProfileMetadataUpdated">
22+
{
23+
constructor(
24+
readonly event: ProcessorEvent<"Registry", "ProfileMetadataUpdated">,
25+
readonly chainId: ChainId,
26+
private dependencies: Dependencies,
27+
) {}
28+
/* @inheritdoc */
29+
async handle(): Promise<Changeset[]> {
30+
const { metadataProvider } = this.dependencies;
31+
32+
const metadataCid = this.event.params.metadata[1];
33+
const metadata = await metadataProvider.getMetadata(metadataCid);
34+
const parsedMetadata = ProjectMetadataSchema.safeParse(metadata);
35+
36+
if (!parsedMetadata.success) {
37+
return [
38+
{
39+
type: "UpdateProject",
40+
args: {
41+
chainId: this.chainId,
42+
projectId: this.event.params.profileId,
43+
project: {
44+
metadataCid: metadataCid,
45+
metadata: null,
46+
projectType: "canonical",
47+
},
48+
},
49+
},
50+
];
51+
}
52+
53+
const projectType = this.getProjectTypeFromMetadata(parsedMetadata.data);
54+
55+
return [
56+
{
57+
type: "UpdateProject",
58+
args: {
59+
chainId: this.chainId,
60+
projectId: this.event.params.profileId,
61+
project: {
62+
metadataCid: metadataCid,
63+
metadata: metadata,
64+
projectType,
65+
},
66+
},
67+
},
68+
];
69+
}
70+
private getProjectTypeFromMetadata(metadata: ProjectMetadata): ProjectType {
71+
// if the metadata contains a canonical reference, it's a linked project
72+
if ("canonical" in metadata) {
73+
return "linked";
74+
}
75+
76+
return "canonical";
77+
}
78+
}
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { getAddress } from "viem";
2+
3+
import { Changeset } from "@grants-stack-indexer/repository";
4+
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared";
5+
6+
import { IEventHandler, ProcessorDependencies } from "../../../internal.js";
7+
8+
type Dependencies = Pick<ProcessorDependencies, "logger">;
9+
/**
10+
* Handles the ProfileNameUpdated event for the Registry contract from Allo protocol.
11+
*
12+
* This handler performs the following steps:
13+
* - Returns the changeset to update the project with the new name
14+
*/
15+
export class ProfileNameUpdatedHandler implements IEventHandler<"Registry", "ProfileNameUpdated"> {
16+
constructor(
17+
readonly event: ProcessorEvent<"Registry", "ProfileNameUpdated">,
18+
readonly chainId: ChainId,
19+
private dependencies: Dependencies,
20+
) {}
21+
/* @inheritdoc */
22+
async handle(): Promise<Changeset[]> {
23+
return [
24+
{
25+
type: "UpdateProject",
26+
args: {
27+
chainId: this.chainId,
28+
projectId: this.event.params.profileId,
29+
project: {
30+
name: this.event.params.name,
31+
anchorAddress: getAddress(this.event.params.anchor),
32+
},
33+
},
34+
},
35+
];
36+
}
37+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { getAddress } from "viem";
2+
3+
import { Changeset } from "@grants-stack-indexer/repository";
4+
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared";
5+
6+
import { IEventHandler, ProcessorDependencies } from "../../../internal.js";
7+
8+
type Dependencies = Pick<ProcessorDependencies, "logger">;
9+
/**
10+
* Handles the ProfileOwnerUpdated event for the Registry contract from Allo protocol.
11+
*
12+
* This handler performs the following steps:
13+
*
14+
* - Returns the changeset to delete all project roles with the role "owner"
15+
* for the profile and insert a new project role with the new owner address.
16+
*/
17+
export class ProfileOwnerUpdatedHandler
18+
implements IEventHandler<"Registry", "ProfileOwnerUpdated">
19+
{
20+
constructor(
21+
readonly event: ProcessorEvent<"Registry", "ProfileOwnerUpdated">,
22+
readonly chainId: ChainId,
23+
private dependencies: Dependencies,
24+
) {}
25+
/* @inheritdoc */
26+
async handle(): Promise<Changeset[]> {
27+
return [
28+
{
29+
type: "DeleteAllProjectRolesByRole",
30+
args: {
31+
projectRole: {
32+
chainId: this.chainId,
33+
projectId: this.event.params.profileId,
34+
role: "owner",
35+
},
36+
},
37+
},
38+
{
39+
type: "InsertProjectRole",
40+
args: {
41+
projectRole: {
42+
chainId: this.chainId,
43+
projectId: this.event.params.profileId,
44+
address: getAddress(this.event.params.owner),
45+
role: "owner",
46+
createdAtBlock: BigInt(this.event.blockNumber),
47+
},
48+
},
49+
},
50+
];
51+
}
52+
}

packages/processors/src/registry/handlers/roleGranted.handler.ts renamed to packages/processors/src/processors/registry/handlers/roleGranted.handler.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import { getAddress } from "viem";
33
import { Changeset } from "@grants-stack-indexer/repository";
44
import { ALLO_OWNER_ROLE, ChainId, ProcessorEvent } from "@grants-stack-indexer/shared";
55

6-
import { IEventHandler } from "../../internal.js";
7-
import { ProcessorDependencies } from "../../types/processor.types.js";
6+
import { IEventHandler } from "../../../internal.js";
7+
import { ProcessorDependencies } from "../../../types/processor.types.js";
88

99
/**
1010
* Handles the RoleGranted event for the Registry contract from Allo protocol.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import { getAddress } from "viem";
2+
3+
import { Changeset } from "@grants-stack-indexer/repository";
4+
import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared";
5+
6+
import { IEventHandler, ProcessorDependencies, ProjectByRoleNotFound } from "../../../internal.js";
7+
8+
type Dependencies = Pick<ProcessorDependencies, "projectRepository" | "logger">;
9+
/**
10+
* Handles the RoleRevoked event for the Registry contract from Allo protocol.
11+
*
12+
* This handler performs the following steps:
13+
*
14+
* - Returns the changeset to delete all project roles with the role "member"
15+
* for the profile and address.
16+
*
17+
* If the project with the role id doesn't exist, it throws an error.
18+
*/
19+
export class RoleRevokedHandler implements IEventHandler<"Registry", "RoleRevoked"> {
20+
constructor(
21+
readonly event: ProcessorEvent<"Registry", "RoleRevoked">,
22+
readonly chainId: ChainId,
23+
private dependencies: Dependencies,
24+
) {}
25+
/* @inheritdoc */
26+
async handle(): Promise<Changeset[]> {
27+
const { projectRepository } = this.dependencies;
28+
const account = getAddress(this.event.params.account);
29+
const role = this.event.params.role.toLowerCase();
30+
const project = await projectRepository.getProjectById(this.chainId, role);
31+
32+
// The role value for a member is the profileId in Allo V1
33+
// which is the project id in this database.
34+
// If we don't find a project with that id we can't remove the role.
35+
if (!project) {
36+
throw new ProjectByRoleNotFound(this.chainId, role);
37+
}
38+
39+
return [
40+
{
41+
type: "DeleteAllProjectRolesByRoleAndAddress",
42+
args: {
43+
projectRole: {
44+
chainId: this.chainId,
45+
projectId: project.id,
46+
address: account,
47+
role: "member",
48+
},
49+
},
50+
},
51+
];
52+
}
53+
}

0 commit comments

Comments
 (0)