From c035059b4581a844eea04686566516fc72b1dc3c Mon Sep 17 00:00:00 2001 From: 0xkenj1 Date: Tue, 12 Nov 2024 12:18:19 -0300 Subject: [PATCH 1/6] feat: registry events skeleton --- packages/processors/src/internal.ts | 6 +- .../{ => processors}/allo/allo.processor.ts | 4 +- .../{ => processors}/allo/handlers/index.ts | 0 .../allo/handlers/poolCreated.handler.ts | 8 +-- .../src/{ => processors}/allo/index.ts | 0 .../src/processors/registry/handlers/index.ts | 6 ++ .../handlers/profileCreated.handler.ts | 4 +- .../profileMetadataUpdated.handler.ts | 24 +++++++ .../handlers/profileNameUpdated.handler.ts | 22 +++++++ .../handlers/profileOwnerUpdated.handler.ts | 24 +++++++ .../registry/handlers/roleGranted.handler.ts | 4 +- .../registry/handlers/roleRevoked.handler.ts | 22 +++++++ .../src/{ => processors}/registry/index.ts | 0 .../processors/registry/registry.processor.ts | 66 +++++++++++++++++++ .../strategy/common/base.strategy.ts | 2 +- .../common/baseDistributed.handler.ts | 2 +- .../{ => processors}/strategy/common/index.ts | 0 .../dvmdDirectTransfer.handler.ts | 8 +-- .../handlers/index.ts | 0 .../handlers/registered.handler.ts | 2 +- .../helpers/decoder.ts | 0 .../helpers/index.ts | 0 .../types/index.ts | 0 .../src/{ => processors}/strategy/index.ts | 0 .../src/{ => processors}/strategy/mapping.ts | 2 +- .../strategy/strategy.processor.ts | 4 +- .../strategy/strategyHandler.factory.ts | 2 +- .../processors/src/registry/handlers/index.ts | 2 - .../src/registry/registry.processor.ts | 34 ---------- .../test/allo/allo.processor.spec.ts | 6 +- .../allo/handlers/poolCreated.handler.spec.ts | 2 +- .../handlers/profileCreated.handler.spec.ts | 2 +- .../handlers/roleGranted.handler.spec.ts | 2 +- .../test/registry/registry.processor.spec.ts | 10 +-- .../strategy/common/base.strategy.spec.ts | 2 +- .../common/baseDistributed.handler.spec.ts | 2 +- .../dvmdDirectTransfer.handler.spec.ts | 10 +-- .../handlers/registered.handler.spec.ts | 2 +- .../helpers/decoder.spec.ts | 4 +- .../processors/test/strategy/mapping.spec.ts | 2 +- .../strategy/strategyHandler.factory.spec.ts | 2 +- packages/shared/src/types/events/registry.ts | 39 ++++++++++- 42 files changed, 248 insertions(+), 85 deletions(-) rename packages/processors/src/{ => processors}/allo/allo.processor.ts (86%) rename packages/processors/src/{ => processors}/allo/handlers/index.ts (100%) rename packages/processors/src/{ => processors}/allo/handlers/poolCreated.handler.ts (97%) rename packages/processors/src/{ => processors}/allo/index.ts (100%) create mode 100644 packages/processors/src/processors/registry/handlers/index.ts rename packages/processors/src/{ => processors}/registry/handlers/profileCreated.handler.ts (96%) create mode 100644 packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts create mode 100644 packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts create mode 100644 packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts rename packages/processors/src/{ => processors}/registry/handlers/roleGranted.handler.ts (94%) create mode 100644 packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts rename packages/processors/src/{ => processors}/registry/index.ts (100%) create mode 100644 packages/processors/src/processors/registry/registry.processor.ts rename packages/processors/src/{ => processors}/strategy/common/base.strategy.ts (94%) rename packages/processors/src/{ => processors}/strategy/common/baseDistributed.handler.ts (95%) rename packages/processors/src/{ => processors}/strategy/common/index.ts (100%) rename packages/processors/src/{ => processors}/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts (97%) rename packages/processors/src/{ => processors}/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.ts (100%) rename packages/processors/src/{ => processors}/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.ts (99%) rename packages/processors/src/{ => processors}/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.ts (100%) rename packages/processors/src/{ => processors}/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/index.ts (100%) rename packages/processors/src/{ => processors}/strategy/donationVotingMerkleDistributionDirectTransfer/types/index.ts (100%) rename packages/processors/src/{ => processors}/strategy/index.ts (100%) rename packages/processors/src/{ => processors}/strategy/mapping.ts (96%) rename packages/processors/src/{ => processors}/strategy/strategy.processor.ts (86%) rename packages/processors/src/{ => processors}/strategy/strategyHandler.factory.ts (97%) delete mode 100644 packages/processors/src/registry/handlers/index.ts delete mode 100644 packages/processors/src/registry/registry.processor.ts diff --git a/packages/processors/src/internal.ts b/packages/processors/src/internal.ts index ec599c0..265ae03 100644 --- a/packages/processors/src/internal.ts +++ b/packages/processors/src/internal.ts @@ -6,8 +6,8 @@ export * from "./interfaces/index.js"; export * from "./exceptions/index.js"; // Allo -export * from "./allo/index.js"; +export * from "./processors/allo/index.js"; // Strategy -export * from "./strategy/index.js"; -export * from "./registry/index.js"; +export * from "./processors/strategy/index.js"; +export * from "./processors/registry/index.js"; diff --git a/packages/processors/src/allo/allo.processor.ts b/packages/processors/src/processors/allo/allo.processor.ts similarity index 86% rename from packages/processors/src/allo/allo.processor.ts rename to packages/processors/src/processors/allo/allo.processor.ts index 87430a0..fa783c8 100644 --- a/packages/processors/src/allo/allo.processor.ts +++ b/packages/processors/src/processors/allo/allo.processor.ts @@ -1,8 +1,8 @@ import { Changeset } from "@grants-stack-indexer/repository"; import { AlloEvent, ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; -import type { IProcessor, ProcessorDependencies } from "../internal.js"; -import { UnsupportedEventException } from "../internal.js"; +import type { IProcessor, ProcessorDependencies } from "../../internal.js"; +import { UnsupportedEventException } from "../../internal.js"; import { PoolCreatedHandler } from "./handlers/index.js"; /** diff --git a/packages/processors/src/allo/handlers/index.ts b/packages/processors/src/processors/allo/handlers/index.ts similarity index 100% rename from packages/processors/src/allo/handlers/index.ts rename to packages/processors/src/processors/allo/handlers/index.ts diff --git a/packages/processors/src/allo/handlers/poolCreated.handler.ts b/packages/processors/src/processors/allo/handlers/poolCreated.handler.ts similarity index 97% rename from packages/processors/src/allo/handlers/poolCreated.handler.ts rename to packages/processors/src/processors/allo/handlers/poolCreated.handler.ts index e1dc9ae..aed83db 100644 --- a/packages/processors/src/allo/handlers/poolCreated.handler.ts +++ b/packages/processors/src/processors/allo/handlers/poolCreated.handler.ts @@ -4,10 +4,10 @@ import type { Changeset, NewRound, PendingRoundRole } from "@grants-stack-indexe import type { ChainId, ProcessorEvent, Token } from "@grants-stack-indexer/shared"; import { getToken, isAlloNativeToken } from "@grants-stack-indexer/shared"; -import type { IEventHandler, ProcessorDependencies, StrategyTimings } from "../../internal.js"; -import { calculateAmountInUsd, getRoundRoles } from "../../helpers/index.js"; -import { StrategyHandlerFactory, TokenPriceNotFoundError } from "../../internal.js"; -import { RoundMetadataSchema } from "../../schemas/index.js"; +import type { IEventHandler, ProcessorDependencies, StrategyTimings } from "../../../internal.js"; +import { calculateAmountInUsd, getRoundRoles } from "../../../helpers/index.js"; +import { StrategyHandlerFactory, TokenPriceNotFoundError } from "../../../internal.js"; +import { RoundMetadataSchema } from "../../../schemas/index.js"; type Dependencies = Pick< ProcessorDependencies, diff --git a/packages/processors/src/allo/index.ts b/packages/processors/src/processors/allo/index.ts similarity index 100% rename from packages/processors/src/allo/index.ts rename to packages/processors/src/processors/allo/index.ts diff --git a/packages/processors/src/processors/registry/handlers/index.ts b/packages/processors/src/processors/registry/handlers/index.ts new file mode 100644 index 0000000..dd16069 --- /dev/null +++ b/packages/processors/src/processors/registry/handlers/index.ts @@ -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"; diff --git a/packages/processors/src/registry/handlers/profileCreated.handler.ts b/packages/processors/src/processors/registry/handlers/profileCreated.handler.ts similarity index 96% rename from packages/processors/src/registry/handlers/profileCreated.handler.ts rename to packages/processors/src/processors/registry/handlers/profileCreated.handler.ts index bf3eaad..a0796b1 100644 --- a/packages/processors/src/registry/handlers/profileCreated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileCreated.handler.ts @@ -3,8 +3,8 @@ import { getAddress } from "viem"; 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/projectMetadata.js"; +import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; +import { ProjectMetadata, ProjectMetadataSchema } from "../../../schemas/projectMetadata.js"; type Dependencies = Pick< ProcessorDependencies, diff --git a/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts new file mode 100644 index 0000000..4a34bc2 --- /dev/null +++ b/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts @@ -0,0 +1,24 @@ +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" | "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 { + return []; + } +} diff --git a/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts new file mode 100644 index 0000000..e7261d4 --- /dev/null +++ b/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts @@ -0,0 +1,22 @@ +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" | "evmProvider" | "metadataProvider" | "logger" +>; +/** + * 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 { + return []; + } +} diff --git a/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts new file mode 100644 index 0000000..76f8335 --- /dev/null +++ b/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts @@ -0,0 +1,24 @@ +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" | "evmProvider" | "metadataProvider" | "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 { + return []; + } +} diff --git a/packages/processors/src/registry/handlers/roleGranted.handler.ts b/packages/processors/src/processors/registry/handlers/roleGranted.handler.ts similarity index 94% rename from packages/processors/src/registry/handlers/roleGranted.handler.ts rename to packages/processors/src/processors/registry/handlers/roleGranted.handler.ts index 461043e..2308eee 100644 --- a/packages/processors/src/registry/handlers/roleGranted.handler.ts +++ b/packages/processors/src/processors/registry/handlers/roleGranted.handler.ts @@ -3,8 +3,8 @@ import { getAddress } from "viem"; import { Changeset } from "@grants-stack-indexer/repository"; import { ALLO_OWNER_ROLE, ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; -import { IEventHandler } from "../../internal.js"; -import { ProcessorDependencies } from "../../types/processor.types.js"; +import { IEventHandler } from "../../../internal.js"; +import { ProcessorDependencies } from "../../../types/processor.types.js"; /** * Handles the RoleGranted event for the Registry contract from Allo protocol. diff --git a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts new file mode 100644 index 0000000..5a71b13 --- /dev/null +++ b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts @@ -0,0 +1,22 @@ +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" | "evmProvider" | "metadataProvider" | "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 { + return []; + } +} diff --git a/packages/processors/src/registry/index.ts b/packages/processors/src/processors/registry/index.ts similarity index 100% rename from packages/processors/src/registry/index.ts rename to packages/processors/src/processors/registry/index.ts diff --git a/packages/processors/src/processors/registry/registry.processor.ts b/packages/processors/src/processors/registry/registry.processor.ts new file mode 100644 index 0000000..07ba60c --- /dev/null +++ b/packages/processors/src/processors/registry/registry.processor.ts @@ -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 { + //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); + } + } +} diff --git a/packages/processors/src/strategy/common/base.strategy.ts b/packages/processors/src/processors/strategy/common/base.strategy.ts similarity index 94% rename from packages/processors/src/strategy/common/base.strategy.ts rename to packages/processors/src/processors/strategy/common/base.strategy.ts index 83fcc7b..e7bed16 100644 --- a/packages/processors/src/strategy/common/base.strategy.ts +++ b/packages/processors/src/processors/strategy/common/base.strategy.ts @@ -1,7 +1,7 @@ import { Changeset } from "@grants-stack-indexer/repository"; import { Address, ProcessorEvent, StrategyEvent, Token } from "@grants-stack-indexer/shared"; -import { IStrategyHandler, StrategyTimings } from "../../internal.js"; +import { IStrategyHandler, StrategyTimings } from "../../../internal.js"; /** * @abstract diff --git a/packages/processors/src/strategy/common/baseDistributed.handler.ts b/packages/processors/src/processors/strategy/common/baseDistributed.handler.ts similarity index 95% rename from packages/processors/src/strategy/common/baseDistributed.handler.ts rename to packages/processors/src/processors/strategy/common/baseDistributed.handler.ts index b80225b..d938130 100644 --- a/packages/processors/src/strategy/common/baseDistributed.handler.ts +++ b/packages/processors/src/processors/strategy/common/baseDistributed.handler.ts @@ -3,7 +3,7 @@ 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"; +import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; type Dependencies = Pick; diff --git a/packages/processors/src/strategy/common/index.ts b/packages/processors/src/processors/strategy/common/index.ts similarity index 100% rename from packages/processors/src/strategy/common/index.ts rename to packages/processors/src/processors/strategy/common/index.ts diff --git a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts b/packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts similarity index 97% rename from packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts rename to packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts index 8f22b36..1313c76 100644 --- a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts +++ b/packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts @@ -9,10 +9,10 @@ import { Token, } from "@grants-stack-indexer/shared"; -import type { ProcessorDependencies, StrategyTimings } from "../../internal.js"; -import DonationVotingMerkleDistributionDirectTransferStrategy from "../../abis/allo-v2/v1/DonationVotingMerkleDistributionDirectTransferStrategy.js"; -import { calculateAmountInUsd, getDateFromTimestamp } from "../../helpers/index.js"; -import { TokenPriceNotFoundError, UnsupportedEventException } from "../../internal.js"; +import type { ProcessorDependencies, StrategyTimings } from "../../../internal.js"; +import DonationVotingMerkleDistributionDirectTransferStrategy from "../../../abis/allo-v2/v1/DonationVotingMerkleDistributionDirectTransferStrategy.js"; +import { calculateAmountInUsd, getDateFromTimestamp } from "../../../helpers/index.js"; +import { TokenPriceNotFoundError, UnsupportedEventException } from "../../../internal.js"; import { BaseDistributedHandler, BaseStrategyHandler } from "../common/index.js"; import { DVMDRegisteredHandler } from "./handlers/index.js"; diff --git a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.ts b/packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.ts similarity index 100% rename from packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.ts rename to packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.ts diff --git a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.ts b/packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.ts similarity index 99% rename from packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.ts rename to packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.ts index 99cd2a0..9250ca6 100644 --- a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.ts +++ b/packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.ts @@ -8,7 +8,7 @@ import { ProcessorDependencies, ProjectNotFound, RoundNotFound, -} from "../../../internal.js"; +} from "../../../../internal.js"; import { decodeDVMDApplicationData } from "../helpers/index.js"; type Dependencies = Pick< diff --git a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.ts b/packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.ts similarity index 100% rename from packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.ts rename to packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.ts diff --git a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/index.ts b/packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/index.ts similarity index 100% rename from packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/index.ts rename to packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/index.ts diff --git a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/types/index.ts b/packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/types/index.ts similarity index 100% rename from packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/types/index.ts rename to packages/processors/src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/types/index.ts diff --git a/packages/processors/src/strategy/index.ts b/packages/processors/src/processors/strategy/index.ts similarity index 100% rename from packages/processors/src/strategy/index.ts rename to packages/processors/src/processors/strategy/index.ts diff --git a/packages/processors/src/strategy/mapping.ts b/packages/processors/src/processors/strategy/mapping.ts similarity index 96% rename from packages/processors/src/strategy/mapping.ts rename to packages/processors/src/processors/strategy/mapping.ts index 9913bf2..98eb429 100644 --- a/packages/processors/src/strategy/mapping.ts +++ b/packages/processors/src/processors/strategy/mapping.ts @@ -1,6 +1,6 @@ import { Hex } from "viem"; -import type { StrategyHandlerConstructor } from "../internal.js"; +import type { StrategyHandlerConstructor } from "../../internal.js"; import { DVMDDirectTransferStrategyHandler } from "./donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.js"; /** diff --git a/packages/processors/src/strategy/strategy.processor.ts b/packages/processors/src/processors/strategy/strategy.processor.ts similarity index 86% rename from packages/processors/src/strategy/strategy.processor.ts rename to packages/processors/src/processors/strategy/strategy.processor.ts index c41557e..035e91b 100644 --- a/packages/processors/src/strategy/strategy.processor.ts +++ b/packages/processors/src/processors/strategy/strategy.processor.ts @@ -1,8 +1,8 @@ import { Changeset } from "@grants-stack-indexer/repository"; import { ChainId, ProcessorEvent, StrategyEvent } from "@grants-stack-indexer/shared"; -import type { IProcessor, ProcessorDependencies } from "../internal.js"; -import { UnsupportedStrategy } from "../internal.js"; +import type { IProcessor, ProcessorDependencies } from "../../internal.js"; +import { UnsupportedStrategy } from "../../internal.js"; import { StrategyHandlerFactory } from "./strategyHandler.factory.js"; export class StrategyProcessor implements IProcessor<"Strategy", StrategyEvent> { diff --git a/packages/processors/src/strategy/strategyHandler.factory.ts b/packages/processors/src/processors/strategy/strategyHandler.factory.ts similarity index 97% rename from packages/processors/src/strategy/strategyHandler.factory.ts rename to packages/processors/src/processors/strategy/strategyHandler.factory.ts index 7b466db..357ffc0 100644 --- a/packages/processors/src/strategy/strategyHandler.factory.ts +++ b/packages/processors/src/processors/strategy/strategyHandler.factory.ts @@ -2,7 +2,7 @@ import { Hex } from "viem"; import { ChainId, StrategyEvent } from "@grants-stack-indexer/shared"; -import { getHandler, IStrategyHandler, ProcessorDependencies } from "../internal.js"; +import { getHandler, IStrategyHandler, ProcessorDependencies } from "../../internal.js"; /** * Factory for creating strategy handlers diff --git a/packages/processors/src/registry/handlers/index.ts b/packages/processors/src/registry/handlers/index.ts deleted file mode 100644 index 59fea08..0000000 --- a/packages/processors/src/registry/handlers/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./profileCreated.handler.js"; -export * from "./roleGranted.handler.js"; diff --git a/packages/processors/src/registry/registry.processor.ts b/packages/processors/src/registry/registry.processor.ts deleted file mode 100644 index b23ab6c..0000000 --- a/packages/processors/src/registry/registry.processor.ts +++ /dev/null @@ -1,34 +0,0 @@ -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, RoleGrantedHandler } 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 { - //TODO: Implement robust error handling and retry logic - switch (event.eventName) { - case "RoleGranted": - return new RoleGrantedHandler( - event as ProcessorEvent<"Registry", "RoleGranted">, - this.chainId, - this.dependencies, - ).handle(); - case "ProfileCreated": - return new ProfileCreatedHandler( - event as ProcessorEvent<"Registry", "ProfileCreated">, - this.chainId, - this.dependencies, - ).handle(); - default: - throw new UnsupportedEventException("Registry", event.eventName); - } - } -} diff --git a/packages/processors/test/allo/allo.processor.spec.ts b/packages/processors/test/allo/allo.processor.spec.ts index 8deac5a..e9a292e 100644 --- a/packages/processors/test/allo/allo.processor.spec.ts +++ b/packages/processors/test/allo/allo.processor.spec.ts @@ -9,12 +9,12 @@ import type { } from "@grants-stack-indexer/repository"; import type { AlloEvent, ChainId, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; -import { AlloProcessor } from "../../src/allo/allo.processor.js"; -import { PoolCreatedHandler } from "../../src/allo/handlers/poolCreated.handler.js"; import { UnsupportedEventException } from "../../src/internal.js"; +import { AlloProcessor } from "../../src/processors/allo/allo.processor.js"; +import { PoolCreatedHandler } from "../../src/processors/allo/handlers/poolCreated.handler.js"; // Mock the handlers -vi.mock("../../src/allo/handlers/poolCreated.handler.js", () => { +vi.mock("../../src/processors/allo/handlers/poolCreated.handler.js", () => { const PoolCreatedHandler = vi.fn(); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access PoolCreatedHandler.prototype.handle = vi.fn(); diff --git a/packages/processors/test/allo/handlers/poolCreated.handler.spec.ts b/packages/processors/test/allo/handlers/poolCreated.handler.spec.ts index b508ca5..a5e1dfb 100644 --- a/packages/processors/test/allo/handlers/poolCreated.handler.spec.ts +++ b/packages/processors/test/allo/handlers/poolCreated.handler.spec.ts @@ -11,7 +11,7 @@ import { mergeDeep } from "@grants-stack-indexer/shared"; import { PoolCreatedHandler, TIMESTAMP_DELTA_RANGE, -} from "../../../src/allo/handlers/poolCreated.handler.js"; +} from "../../../src/processors/allo/handlers/poolCreated.handler.js"; // Function to create a mock event with optional overrides function createMockEvent( diff --git a/packages/processors/test/registry/handlers/profileCreated.handler.spec.ts b/packages/processors/test/registry/handlers/profileCreated.handler.spec.ts index f6cb01f..f722066 100644 --- a/packages/processors/test/registry/handlers/profileCreated.handler.spec.ts +++ b/packages/processors/test/registry/handlers/profileCreated.handler.spec.ts @@ -8,7 +8,7 @@ import { IProjectReadRepository, IRoundReadRepository } from "@grants-stack-inde import { Bytes32String, ChainId, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; import { ProcessorDependencies } from "../../../src/internal.js"; -import { ProfileCreatedHandler } from "../../../src/registry/handlers/index.js"; +import { ProfileCreatedHandler } from "../../../src/processors/registry/handlers/index.js"; describe("ProfileCreatedHandler", () => { let mockEvent: ProcessorEvent<"Registry", "ProfileCreated">; diff --git a/packages/processors/test/registry/handlers/roleGranted.handler.spec.ts b/packages/processors/test/registry/handlers/roleGranted.handler.spec.ts index 72f23c4..c6a6da1 100644 --- a/packages/processors/test/registry/handlers/roleGranted.handler.spec.ts +++ b/packages/processors/test/registry/handlers/roleGranted.handler.spec.ts @@ -9,7 +9,7 @@ import { } from "@grants-stack-indexer/shared"; import { ProcessorDependencies } from "../../../src/internal.js"; -import { RoleGrantedHandler } from "../../../src/registry/handlers/index.js"; // Adjust path if needed +import { RoleGrantedHandler } from "../../../src/processors/registry/handlers/index.js"; // Adjust path if needed describe("RoleGrantedHandler", () => { const mockProjectRepository = { diff --git a/packages/processors/test/registry/registry.processor.spec.ts b/packages/processors/test/registry/registry.processor.spec.ts index c26647c..030b6b0 100644 --- a/packages/processors/test/registry/registry.processor.spec.ts +++ b/packages/processors/test/registry/registry.processor.spec.ts @@ -3,12 +3,12 @@ import { afterEach, describe, expect, it, vi } from "vitest"; import type { ChainId, ProcessorEvent, RegistryEvent } from "@grants-stack-indexer/shared"; import { ProcessorDependencies, UnsupportedEventException } from "../../src/internal.js"; -import { ProfileCreatedHandler } from "../../src/registry/handlers/profileCreated.handler.js"; -import { RoleGrantedHandler } from "../../src/registry/handlers/roleGranted.handler.js"; -import { RegistryProcessor } from "../../src/registry/registry.processor.js"; +import { ProfileCreatedHandler } from "../../src/processors/registry/handlers/profileCreated.handler.js"; +import { RoleGrantedHandler } from "../../src/processors/registry/handlers/roleGranted.handler.js"; +import { RegistryProcessor } from "../../src/processors/registry/registry.processor.js"; // Mock the handlers and their handle methods -vi.mock("../../src/registry/handlers/roleGranted.handler.js", () => { +vi.mock("../../src/processors/registry/handlers/roleGranted.handler.js", () => { const RoleGrantedHandler = vi.fn(); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access RoleGrantedHandler.prototype.handle = vi.fn(); @@ -18,7 +18,7 @@ vi.mock("../../src/registry/handlers/roleGranted.handler.js", () => { }); // Mock the handlers and their handle methods -vi.mock("../../src/registry/handlers/profileCreated.handler.js", () => { +vi.mock("../../src/processors/registry/handlers/profileCreated.handler.js", () => { const ProfileCreatedHandler = vi.fn(); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access ProfileCreatedHandler.prototype.handle = vi.fn(); diff --git a/packages/processors/test/strategy/common/base.strategy.spec.ts b/packages/processors/test/strategy/common/base.strategy.spec.ts index 7ff9c51..2ec4086 100644 --- a/packages/processors/test/strategy/common/base.strategy.spec.ts +++ b/packages/processors/test/strategy/common/base.strategy.spec.ts @@ -3,7 +3,7 @@ import { describe, expect, it } from "vitest"; import { Changeset } from "@grants-stack-indexer/repository"; import { Address, Token, TokenCode } from "@grants-stack-indexer/shared"; -import { BaseStrategyHandler } from "../../../src/strategy/common/base.strategy.js"; +import { BaseStrategyHandler } from "../../../src/processors/strategy/common/base.strategy.js"; // Create a concrete implementation of BaseStrategyHandler for testing class TestStrategyHandler extends BaseStrategyHandler { diff --git a/packages/processors/test/strategy/common/baseDistributed.handler.spec.ts b/packages/processors/test/strategy/common/baseDistributed.handler.spec.ts index 4d19ac7..a774933 100644 --- a/packages/processors/test/strategy/common/baseDistributed.handler.spec.ts +++ b/packages/processors/test/strategy/common/baseDistributed.handler.spec.ts @@ -3,7 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { IRoundReadRepository, Round } from "@grants-stack-indexer/repository"; import { ChainId, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; -import { BaseDistributedHandler } from "../../../src/strategy/common/baseDistributed.handler.js"; +import { BaseDistributedHandler } from "../../../src/processors/strategy/common/baseDistributed.handler.js"; function createMockEvent( overrides: Partial> = {}, diff --git a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.spec.ts b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.spec.ts index 81fb0d0..f638afc 100644 --- a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.spec.ts +++ b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.spec.ts @@ -18,12 +18,12 @@ import { } from "@grants-stack-indexer/shared"; import { TokenPriceNotFoundError, UnsupportedEventException } from "../../../src/internal.js"; -import { BaseDistributedHandler } from "../../../src/strategy/common/index.js"; -import { DVMDDirectTransferStrategyHandler } from "../../../src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.js"; -import { DVMDRegisteredHandler } from "../../../src/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.js"; +import { BaseDistributedHandler } from "../../../src/processors/strategy/common/index.js"; +import { DVMDDirectTransferStrategyHandler } from "../../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.js"; +import { DVMDRegisteredHandler } from "../../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.js"; vi.mock( - "../../../src/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.js", + "../../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.js", () => { const DVMDRegisteredHandler = vi.fn(); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access @@ -33,7 +33,7 @@ vi.mock( }; }, ); -vi.mock("../../../src/strategy/common/baseDistributed.handler.js", () => { +vi.mock("../../../src/processors/strategy/common/baseDistributed.handler.js", () => { const BaseDistributedHandler = vi.fn(); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access BaseDistributedHandler.prototype.handle = vi.fn(); diff --git a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.spec.ts b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.spec.ts index c76b4a1..74bf6e0 100644 --- a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.spec.ts +++ b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/registered.handler.spec.ts @@ -11,7 +11,7 @@ import { import { ChainId, DeepPartial, mergeDeep, ProcessorEvent } from "@grants-stack-indexer/shared"; import { ProjectNotFound, RoundNotFound } from "../../../../src/exceptions/index.js"; -import { DVMDRegisteredHandler } from "../../../../src/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.js"; +import { DVMDRegisteredHandler } from "../../../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/handlers/index.js"; function createMockEvent( overrides: DeepPartial> = {}, diff --git a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.spec.ts b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.spec.ts index 51aa787..2c77c8b 100644 --- a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.spec.ts +++ b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.spec.ts @@ -1,7 +1,7 @@ import { describe, expect, it } from "vitest"; -import { decodeDVMDApplicationData } from "../../../../src/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.js"; -import { DVMDApplicationData } from "../../../../src/strategy/donationVotingMerkleDistributionDirectTransfer/types/index.js"; +import { decodeDVMDApplicationData } from "../../../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.js"; +import { DVMDApplicationData } from "../../../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/types/index.js"; describe("decodeDVMDApplicationData", () => { it("should correctly decode the encoded data", () => { diff --git a/packages/processors/test/strategy/mapping.spec.ts b/packages/processors/test/strategy/mapping.spec.ts index caa64a0..811b4a8 100644 --- a/packages/processors/test/strategy/mapping.spec.ts +++ b/packages/processors/test/strategy/mapping.spec.ts @@ -2,7 +2,7 @@ import { describe, expect, expectTypeOf, it } from "vitest"; import { existsHandler } from "../../src/external.js"; import { getHandler, StrategyHandlerConstructor } from "../../src/internal.js"; -import { DVMDDirectTransferStrategyHandler } from "../../src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.js"; +import { DVMDDirectTransferStrategyHandler } from "../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.js"; describe("Strategy Mapping", () => { describe("getHandler", () => { diff --git a/packages/processors/test/strategy/strategyHandler.factory.spec.ts b/packages/processors/test/strategy/strategyHandler.factory.spec.ts index ffbe3eb..26315c3 100644 --- a/packages/processors/test/strategy/strategyHandler.factory.spec.ts +++ b/packages/processors/test/strategy/strategyHandler.factory.spec.ts @@ -8,7 +8,7 @@ import { IProjectReadRepository, IRoundReadRepository } from "@grants-stack-inde import { ChainId, ILogger } from "@grants-stack-indexer/shared"; import { ProcessorDependencies, StrategyHandlerFactory } from "../../src/internal.js"; -import { DVMDDirectTransferStrategyHandler } from "../../src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.js"; +import { DVMDDirectTransferStrategyHandler } from "../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.js"; describe("StrategyHandlerFactory", () => { const chainId = 10 as ChainId; diff --git a/packages/shared/src/types/events/registry.ts b/packages/shared/src/types/events/registry.ts index 5871ec9..6bcec46 100644 --- a/packages/shared/src/types/events/registry.ts +++ b/packages/shared/src/types/events/registry.ts @@ -5,7 +5,14 @@ import { Address, AnyEvent, Bytes32String, ContractName, ProcessorEvent } from " /** * This array is used to represent all Registry events. */ -const RegistryEventArray = ["ProfileCreated", "RoleGranted"] as const; +const RegistryEventArray = [ + "ProfileCreated", + "ProfileMetadataUpdated", + "ProfileNameUpdated", + "ProfileOwnerUpdated", + "RoleGranted", + "RoleRevoked", +] as const; /** * This type is used to represent a Registry events. @@ -19,7 +26,15 @@ export type RegistryEventParams = T extends "ProfileCre ? ProfileCreatedParams : T extends "RoleGranted" ? RoleGrantedParams - : never; + : T extends "ProfileMetadataUpdated" + ? ProfileMetadataUpdatedParams + : T extends "ProfileNameUpdated" + ? ProfileNameUpdatedParams + : T extends "ProfileOwnerUpdated" + ? ProfileOwnerUpdatedParams + : T extends "RoleRevoked" + ? RoleRevokedParams + : never; // ============================================================================= // =============================== Event Parameters ============================ @@ -32,12 +47,32 @@ export type ProfileCreatedParams = { owner: Address; anchor: Address; }; +export type ProfileMetadataUpdatedParams = { + profileId: Bytes32String; + metadata: [protocol: bigint, pointer: string]; +}; +export type ProfileNameUpdatedParams = { + profileId: Bytes32String; + name: string; + anchor: Address; +}; +export type ProfileOwnerUpdatedParams = { + profileId: Bytes32String; + owner: Address; +}; + export type RoleGrantedParams = { role: Bytes32String; account: Address; sender: Address; }; +export type RoleRevokedParams = { + role: Bytes32String; + account: Address; + sender: Address; +}; + /** * Type guard for Registry events. * @param event The event to check. From b038c4205e2b89db8849482ba776e85ae7e7f150 Mon Sep 17 00:00:00 2001 From: 0xkenj1 Date: Tue, 12 Nov 2024 13:19:41 -0300 Subject: [PATCH 2/6] feat: handlers implemented --- .../profileMetadataUpdated.handler.ts | 43 ++++++++++++++++++- .../handlers/profileNameUpdated.handler.ts | 16 ++++++- .../handlers/profileOwnerUpdated.handler.ts | 27 +++++++++++- .../registry/handlers/roleRevoked.handler.ts | 28 +++++++++++- 4 files changed, 110 insertions(+), 4 deletions(-) diff --git a/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts index 4a34bc2..cf68451 100644 --- a/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts @@ -1,7 +1,8 @@ -import { Changeset } from "@grants-stack-indexer/repository"; +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, @@ -19,6 +20,46 @@ export class ProfileMetadataUpdatedHandler private dependencies: Dependencies, ) {} async handle(): Promise { + 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 []; + } + + 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"; + } } diff --git a/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts index e7261d4..14ac422 100644 --- a/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts @@ -1,3 +1,5 @@ +import { getAddress } from "viem"; + import { Changeset } from "@grants-stack-indexer/repository"; import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; @@ -17,6 +19,18 @@ export class ProfileNameUpdatedHandler implements IEventHandler<"Registry", "Pro private dependencies: Dependencies, ) {} async handle(): Promise { - return []; + return [ + { + type: "UpdateProject", + args: { + chainId: this.chainId, + projectId: this.event.params.profileId, + project: { + name: this.event.params.name, + anchorAddress: getAddress(this.event.params.anchor), + }, + }, + }, + ]; } } diff --git a/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts index 76f8335..e75579f 100644 --- a/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts @@ -1,3 +1,5 @@ +import { getAddress } from "viem"; + import { Changeset } from "@grants-stack-indexer/repository"; import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; @@ -19,6 +21,29 @@ export class ProfileOwnerUpdatedHandler private dependencies: Dependencies, ) {} async handle(): Promise { - return []; + 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), + }, + }, + }, + ]; } } diff --git a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts index 5a71b13..ba6514a 100644 --- a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts +++ b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts @@ -1,3 +1,5 @@ +import { getAddress } from "viem"; + import { Changeset } from "@grants-stack-indexer/repository"; import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; @@ -17,6 +19,30 @@ export class RoleRevokedHandler implements IEventHandler<"Registry", "RoleRevoke private dependencies: Dependencies, ) {} async handle(): Promise { - return []; + 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 []; + } + + return [ + { + type: "DeleteAllProjectRolesByRoleAndAddress", + args: { + projectRole: { + chainId: this.chainId, + projectId: project.id, + address: account, + role: "member", + }, + }, + }, + ]; } } From 38947f8302759faa7fc087357368f10b752d7431 Mon Sep 17 00:00:00 2001 From: 0xkenj1 Date: Tue, 12 Nov 2024 17:43:21 -0300 Subject: [PATCH 3/6] feat: add tests --- .../test/unit/eventsRegistry.spec.ts | 2 +- .../handlers/profileNameUpdated.handler.ts | 5 +- .../handlers/profileOwnerUpdated.handler.ts | 5 +- .../registry/handlers/roleRevoked.handler.ts | 5 +- .../processors/test/helpers/tokenMath.spec.ts | 4 +- .../profileMetadataUpdated.handler.spec.ts | 80 +++++++++++++++++++ .../profileNameUpdated.handler.spec.ts | 57 +++++++++++++ .../profileOwnerUpdated.handler.spec.ts | 72 +++++++++++++++++ .../handlers/roleRevoked.handler.spec.ts | 80 +++++++++++++++++++ .../test/registry/registry.processor.spec.ts | 4 +- .../helpers/decoder.spec.ts | 2 +- .../processors/test/strategy/mapping.spec.ts | 12 +-- 12 files changed, 304 insertions(+), 24 deletions(-) create mode 100644 packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts create mode 100644 packages/processors/test/registry/handlers/profileNameUpdated.handler.spec.ts create mode 100644 packages/processors/test/registry/handlers/profileOwnerUpdated.handler.spec.ts create mode 100644 packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts diff --git a/packages/data-flow/test/unit/eventsRegistry.spec.ts b/packages/data-flow/test/unit/eventsRegistry.spec.ts index 7a293f2..59920e4 100644 --- a/packages/data-flow/test/unit/eventsRegistry.spec.ts +++ b/packages/data-flow/test/unit/eventsRegistry.spec.ts @@ -48,7 +48,7 @@ describe("InMemoryEventsRegistry", () => { expect(retrievedEvent).toEqual(mockEvent); }); - it("should update the last processed event when saving multiple times", async () => { + it("updates the last processed event when saving multiple times", async () => { const registry = new InMemoryEventsRegistry(logger); const firstEvent: ProcessorEvent<"Allo", "PoolCreated"> = { diff --git a/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts index 14ac422..e7a9088 100644 --- a/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts @@ -5,10 +5,7 @@ import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; -type Dependencies = Pick< - ProcessorDependencies, - "projectRepository" | "evmProvider" | "metadataProvider" | "logger" ->; +type Dependencies = Pick; /** * Handles the ProfileNameUpdated event for the Registry contract from Allo protocol. */ diff --git a/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts index e75579f..38aff7b 100644 --- a/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts @@ -5,10 +5,7 @@ import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; -type Dependencies = Pick< - ProcessorDependencies, - "projectRepository" | "evmProvider" | "metadataProvider" | "logger" ->; +type Dependencies = Pick; /** * Handles the ProfileOwnerUpdated event for the Registry contract from Allo protocol. */ diff --git a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts index ba6514a..c5fd532 100644 --- a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts +++ b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts @@ -5,10 +5,7 @@ import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; -type Dependencies = Pick< - ProcessorDependencies, - "projectRepository" | "evmProvider" | "metadataProvider" | "logger" ->; +type Dependencies = Pick; /** * Handles the RoleRevoked event for the Registry contract from Allo protocol. */ diff --git a/packages/processors/test/helpers/tokenMath.spec.ts b/packages/processors/test/helpers/tokenMath.spec.ts index 3aee76c..4c4d9c7 100644 --- a/packages/processors/test/helpers/tokenMath.spec.ts +++ b/packages/processors/test/helpers/tokenMath.spec.ts @@ -33,7 +33,7 @@ describe("calculateAmountInUsd", () => { }); // Test case for 8 decimal token with float price - it("should correctly calculate USD amount for 8 decimal token with float price", () => { + it("correctly calculates USD amount for 8 decimal token with float price", () => { const amount = 150000000n; // 1.5 tokens const tokenPriceInUsd = 12.75; // $12.75 per token const tokenDecimals = 8; @@ -89,7 +89,7 @@ describe("calculateAmountInUsd", () => { expect(result).toBe("0"); }); - it("should return zero for zero token price", () => { + it("returns zero for zero token price", () => { const amount = 1000000000000000000n; // 1 token const tokenPriceInUsd = 0; const tokenDecimals = 18; diff --git a/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts b/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts new file mode 100644 index 0000000..a2165d2 --- /dev/null +++ b/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts @@ -0,0 +1,80 @@ +import { afterEach, describe, expect, it, vi } from "vitest"; + +import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; + +import { ProcessorDependencies } from "../../../src/internal.js"; +import { ProfileMetadataUpdatedHandler } from "../../../src/processors/registry/handlers/profileMetadataUpdated.handler.js"; + +describe("ProfileMetadataUpdatedHandler", () => { + const mockCid = "mockCid"; + const mockEvent: ProcessorEvent<"Registry", "ProfileMetadataUpdated"> = { + params: { + metadata: [0, mockCid], + profileId: "mockProfileId", + }, + // Add other necessary event properties here + } as ProcessorEvent<"Registry", "ProfileMetadataUpdated">; + + const mockDependencies = { + metadataProvider: { + getMetadata: vi.fn(), + }, + logger: { + warn: vi.fn(), + }, + } as unknown as ProcessorDependencies; + + const chainId = 1 as ChainId; + + afterEach(() => { + vi.resetAllMocks(); + }); + + it("handles valid metadata", async () => { + const mockMetadata = { + type: "program", + name: "Test Project", + }; + vi.spyOn(mockDependencies.metadataProvider, "getMetadata").mockResolvedValueOnce( + mockMetadata, + ); + + const handler = new ProfileMetadataUpdatedHandler(mockEvent, chainId, mockDependencies); + const result = await handler.handle(); + + expect(mockDependencies.metadataProvider.getMetadata).toHaveBeenCalledWith(mockCid); + expect(result).toEqual([ + { + type: "UpdateProject", + args: { + chainId, + projectId: mockEvent.params.profileId, + project: { + metadataCid: mockCid, + metadata: mockMetadata, + projectType: "canonical", + }, + }, + }, + ]); + }); + + it("returns an empty array for invalid metadata", async () => { + vi.spyOn(mockDependencies.metadataProvider, "getMetadata").mockResolvedValueOnce(null); + + const handler = new ProfileMetadataUpdatedHandler(mockEvent, chainId, mockDependencies); + const result = await handler.handle(); + + expect(result).toEqual([]); + }); + + it("throws an error if getMetadata fails", async () => { + vi.spyOn(mockDependencies.metadataProvider, "getMetadata").mockRejectedValueOnce( + new Error("Failed to fetch metadata"), + ); + + const handler = new ProfileMetadataUpdatedHandler(mockEvent, chainId, mockDependencies); + + await expect(handler.handle()).rejects.toThrow("Failed to fetch metadata"); + }); +}); diff --git a/packages/processors/test/registry/handlers/profileNameUpdated.handler.spec.ts b/packages/processors/test/registry/handlers/profileNameUpdated.handler.spec.ts new file mode 100644 index 0000000..68230b2 --- /dev/null +++ b/packages/processors/test/registry/handlers/profileNameUpdated.handler.spec.ts @@ -0,0 +1,57 @@ +import { getAddress } from "viem"; +import { describe, expect, it, vi } from "vitest"; + +import { Changeset } from "@grants-stack-indexer/repository"; +import { Bytes32String, ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; + +import { ProfileNameUpdatedHandler } from "../../../src/processors/registry/handlers/profileNameUpdated.handler.js"; + +describe("ProfileNameUpdatedHandler", () => { + const mockEvent: ProcessorEvent<"Registry", "ProfileNameUpdated"> = { + contractName: "Registry", + eventName: "ProfileNameUpdated", + params: { + profileId: "0xprofile1" as Bytes32String, + name: "New Profile Name", + anchor: "0x5aD1D85Bb68791Cb3cE598f56E00F5D5694FAd14", + }, + blockNumber: 1, + blockTimestamp: 1, + chainId: 1 as ChainId, + logIndex: 1, + srcAddress: "0x0", + transactionFields: { + hash: "0x0", + transactionIndex: 1, + }, + }; + + it("returns a changeset with updated project name and anchor address", async () => { + const handler = new ProfileNameUpdatedHandler(mockEvent, 1 as ChainId, { + logger: { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }, + }); + + const result = await handler.handle(); + + const expectedChangeset: Changeset[] = [ + { + type: "UpdateProject", + args: { + chainId: mockEvent.chainId as ChainId, + projectId: mockEvent.params.profileId, + project: { + name: mockEvent.params.name, + anchorAddress: getAddress(mockEvent.params.anchor), + }, + }, + }, + ]; + + expect(result).toEqual(expectedChangeset); + }); +}); diff --git a/packages/processors/test/registry/handlers/profileOwnerUpdated.handler.spec.ts b/packages/processors/test/registry/handlers/profileOwnerUpdated.handler.spec.ts new file mode 100644 index 0000000..396ad2e --- /dev/null +++ b/packages/processors/test/registry/handlers/profileOwnerUpdated.handler.spec.ts @@ -0,0 +1,72 @@ +import { describe, expect, it, vi } from "vitest"; + +import { Changeset } from "@grants-stack-indexer/repository"; +import { Bytes32String, ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; + +import { ProfileOwnerUpdatedHandler } from "../../../src/processors/registry/handlers/profileOwnerUpdated.handler.js"; + +describe("ProfileOwnerUpdatedHandler", () => { + it("handles ProfileOwnerUpdated event correctly", async () => { + const mockEvent: ProcessorEvent<"Registry", "ProfileOwnerUpdated"> = { + blockNumber: 123456, + blockTimestamp: 123456, + chainId: 1 as ChainId, + contractName: "Registry", + eventName: "ProfileOwnerUpdated", + logIndex: 0, + srcAddress: "0x1234567890123456789012345678901234567890", + params: { + profileId: "0xprofile123" as Bytes32String, + owner: "0x5aD1D85Bb68791Cb3cE598f56E00F5D5694FAd14", + }, + transactionFields: { + hash: "0xhash", + transactionIndex: 0, + }, + }; + + const mockDependencies = { + logger: { + info: vi.fn(), + warn: vi.fn(), + error: vi.fn(), + debug: vi.fn(), + }, + }; + + const handler = new ProfileOwnerUpdatedHandler( + mockEvent, + mockEvent.chainId as ChainId, + mockDependencies, + ); + + const result = await handler.handle(); + + const expectedChangeset: Changeset[] = [ + { + type: "DeleteAllProjectRolesByRole", + args: { + projectRole: { + chainId: mockEvent.chainId as ChainId, + projectId: mockEvent.params.profileId, + role: "owner", + }, + }, + }, + { + type: "InsertProjectRole", + args: { + projectRole: { + chainId: mockEvent.chainId as ChainId, + projectId: mockEvent.params.profileId, + address: mockEvent.params.owner, + role: "owner", + createdAtBlock: BigInt(mockEvent.blockNumber), + }, + }, + }, + ]; + + expect(result).toEqual(expectedChangeset); + }); +}); diff --git a/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts b/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts new file mode 100644 index 0000000..6a0b80b --- /dev/null +++ b/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts @@ -0,0 +1,80 @@ +import { beforeEach, describe, expect, it, vi } from "vitest"; + +import { IProjectRepository, Project } from "@grants-stack-indexer/repository"; +import { ChainId, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; + +import { RoleRevokedHandler } from "../../../src/processors/registry/handlers/roleRevoked.handler.js"; + +describe("RoleRevokedHandler", () => { + let mockEvent: ProcessorEvent<"Registry", "RoleRevoked">; + let mockChainId: ChainId; + let mockDependencies: { projectRepository: IProjectRepository; logger: ILogger }; + let mockedRole: string; + let mockedAccount: string; + + beforeEach(() => { + mockedRole = "0x5aD1D85Bb68791Cb3cE598f56E00F5D5694FAd14ASD"; + mockedAccount = "0x5aD1D85Bb68791Cb3cE598f56E00F5D5694FAd14"; + mockEvent = { + params: { + account: mockedAccount, + role: mockedRole, + }, + } as ProcessorEvent<"Registry", "RoleRevoked">; + + mockChainId = 1 as ChainId; + + mockDependencies = { + projectRepository: { + getProjectById: vi.fn(), + } as unknown as IProjectRepository, + logger: { + info: vi.fn(), + } as unknown as ILogger, + }; + }); + + it("return a changeset when project is found", async () => { + const project = { id: "project-1" }; + vi.spyOn(mockDependencies.projectRepository, "getProjectById").mockResolvedValueOnce({ + ...project, + } as Project); + + const handler = new RoleRevokedHandler(mockEvent, mockChainId, mockDependencies); + const result = await handler.handle(); + + expect(result).toEqual([ + { + type: "DeleteAllProjectRolesByRoleAndAddress", + args: { + projectRole: { + chainId: mockChainId, + projectId: project.id, + address: mockedAccount, + role: "member", + }, + }, + }, + ]); + }); + + it("return an empty array when project is not found", async () => { + vi.spyOn(mockDependencies.projectRepository, "getProjectById").mockResolvedValueOnce( + undefined, + ); + + const handler = new RoleRevokedHandler(mockEvent, mockChainId, mockDependencies); + const result = await handler.handle(); + + expect(result).toEqual([]); + }); + + it("throw an error when getProjectById fails", async () => { + const error = new Error("Database error"); + vi.spyOn(mockDependencies.projectRepository, "getProjectById").mockRejectedValueOnce(error); + + const handler = new RoleRevokedHandler(mockEvent, mockChainId, mockDependencies); + + await expect(handler.handle()).rejects.toThrow(error); + }); +}); diff --git a/packages/processors/test/registry/registry.processor.spec.ts b/packages/processors/test/registry/registry.processor.spec.ts index 030b6b0..80c0b98 100644 --- a/packages/processors/test/registry/registry.processor.spec.ts +++ b/packages/processors/test/registry/registry.processor.spec.ts @@ -45,7 +45,7 @@ describe("RegistryProcessor", () => { await expect(processor.process(event)).rejects.toThrow(UnsupportedEventException); }); - it("should call ProfileCreatedHandler", async () => { + it("calls ProfileCreatedHandler", async () => { const event: ProcessorEvent<"Registry", "ProfileCreated"> = { eventName: "ProfileCreated", } as ProcessorEvent<"Registry", "ProfileCreated">; @@ -59,7 +59,7 @@ describe("RegistryProcessor", () => { expect(result).toEqual([]); // Check if handle returns [] }); - it("should call RoleGrantedHandler", async () => { + it("calls RoleGrantedHandler", async () => { const event: ProcessorEvent<"Registry", "RoleGranted"> = { eventName: "RoleGranted", } as ProcessorEvent<"Registry", "RoleGranted">; diff --git a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.spec.ts b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.spec.ts index 2c77c8b..7bfdfc7 100644 --- a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.spec.ts +++ b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/helpers/decoder.spec.ts @@ -4,7 +4,7 @@ import { decodeDVMDApplicationData } from "../../../../src/processors/strategy/d import { DVMDApplicationData } from "../../../../src/processors/strategy/donationVotingMerkleDistributionDirectTransfer/types/index.js"; describe("decodeDVMDApplicationData", () => { - it("should correctly decode the encoded data", () => { + it("correctly decodes the encoded data", () => { const encodedData = "0x0000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000001000000000000000000000000002c7296a5ec0539f0a018c7176c97c92a9c44e2b4000000000000000000000000e7eb5d2b5b188777df902e89c54570e7ef4f59ce000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000003b6261666b72656967796334336366696e786c6e6168713561617773676869626574763675737273376b6b78663776786d7a626a79726f37366977790000000000"; diff --git a/packages/processors/test/strategy/mapping.spec.ts b/packages/processors/test/strategy/mapping.spec.ts index 811b4a8..913bd82 100644 --- a/packages/processors/test/strategy/mapping.spec.ts +++ b/packages/processors/test/strategy/mapping.spec.ts @@ -6,7 +6,7 @@ import { DVMDDirectTransferStrategyHandler } from "../../src/processors/strategy describe("Strategy Mapping", () => { describe("getHandler", () => { - it("should return the correct handler for a valid strategy ID", () => { + it("returns the correct handler for a valid strategy ID", () => { const validStrategyId = "0x6f9291df02b2664139cec5703c124e4ebce32879c74b6297faa1468aa5ff9ebf"; @@ -17,7 +17,7 @@ describe("Strategy Mapping", () => { expectTypeOf(handler).toEqualTypeOf(); }); - it("should return the correct handler for a valid strategy ID in uppercase", () => { + it("returns the correct handler for a valid strategy ID in uppercase", () => { const validStrategyId = "0x6F9291DF02B2664139CEC5703C124E4EBCE32879C74B6297FAA1468AA5FF9EBF"; @@ -28,7 +28,7 @@ describe("Strategy Mapping", () => { expectTypeOf(handler).toEqualTypeOf(); }); - it("should return undefined for an invalid strategy ID", () => { + it("returns undefined for an invalid strategy ID", () => { const invalidStrategyId = "0x1234567890123456789012345678901234567890123456789012345678901234"; @@ -39,7 +39,7 @@ describe("Strategy Mapping", () => { }); describe("existsHandler", () => { - it("should return true for a valid strategy ID", () => { + it("returns true for a valid strategy ID", () => { const validStrategyId = "0x2f46bf157821dc41daa51479e94783bb0c8699eac63bf75ec450508ab03867ce"; @@ -48,7 +48,7 @@ describe("Strategy Mapping", () => { expect(exists).toBe(true); }); - it("should return true for a valid strategy ID in uppercase", () => { + it("returns true for a valid strategy ID in uppercase", () => { const validStrategyId = "0x2F46BF157821DC41DAA51479E94783BB0C8699EAC63BF75EC450508AB03867CE"; @@ -57,7 +57,7 @@ describe("Strategy Mapping", () => { expect(exists).toBe(true); }); - it("should return false for an invalid strategy ID", () => { + it("returns false for an invalid strategy ID", () => { const invalidStrategyId = "0x1234567890123456789012345678901234567890123456789012345678901234"; From 1d600498906b246dede580289d700912ef117d64 Mon Sep 17 00:00:00 2001 From: 0xkenj1 Date: Tue, 12 Nov 2024 19:32:04 -0300 Subject: [PATCH 4/6] fix: pr comments --- .../exceptions/projectNotFound.exception.ts | 6 ++ .../handlers/profileCreated.handler.ts | 15 ++- .../profileMetadataUpdated.handler.ts | 29 ++++-- .../handlers/profileNameUpdated.handler.ts | 4 + .../handlers/profileOwnerUpdated.handler.ts | 6 ++ .../registry/handlers/roleRevoked.handler.ts | 11 ++- .../profileMetadataUpdated.handler.spec.ts | 15 ++- .../handlers/roleRevoked.handler.spec.ts | 4 +- .../test/registry/registry.processor.spec.ts | 91 ++++++++++++++++++- .../repository/src/types/project.types.ts | 2 +- 10 files changed, 160 insertions(+), 23 deletions(-) diff --git a/packages/processors/src/exceptions/projectNotFound.exception.ts b/packages/processors/src/exceptions/projectNotFound.exception.ts index ba9d367..9ff64cd 100644 --- a/packages/processors/src/exceptions/projectNotFound.exception.ts +++ b/packages/processors/src/exceptions/projectNotFound.exception.ts @@ -5,3 +5,9 @@ export class ProjectNotFound extends Error { super(`Project not found for chainId: ${chainId} and anchorAddress: ${anchorAddress}`); } } + +export class ProjectByRoleNotFound extends Error { + constructor(chainId: ChainId, role: string) { + super(`Project not found for chainId: ${chainId} and role: ${role}`); + } +} diff --git a/packages/processors/src/processors/registry/handlers/profileCreated.handler.ts b/packages/processors/src/processors/registry/handlers/profileCreated.handler.ts index a0796b1..0fc5eb1 100644 --- a/packages/processors/src/processors/registry/handlers/profileCreated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileCreated.handler.ts @@ -12,6 +12,13 @@ type Dependencies = Pick< >; /** * Handles the ProfileCreated 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 insert the project with the metadata + * + * If the metadata is not valid, it sets the metadata to null and the project type to canonical. */ export class ProfileCreatedHandler implements IEventHandler<"Registry", "ProfileCreated"> { constructor( @@ -35,14 +42,6 @@ export class ProfileCreatedHandler implements IEventHandler<"Registry", "Profile projectType = this.getProjectTypeFromMetadata(parsedMetadata.data); isProgram = parsedMetadata.data.type === "program"; metadataValue = parsedMetadata.data; - } else { - //TODO: Replace with logger - // this.logger.warn({ - // msg: `ProfileCreated: Failed to parse metadata for profile ${profileId}`, - // event: this.event, - // metadataCid, - // metadata, - // }); } const createdBy = diff --git a/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts index cf68451..0da4627 100644 --- a/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileMetadataUpdated.handler.ts @@ -8,8 +8,14 @@ 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"> @@ -19,6 +25,7 @@ export class ProfileMetadataUpdatedHandler readonly chainId: ChainId, private dependencies: Dependencies, ) {} + /* @inheritdoc */ async handle(): Promise { const { metadataProvider } = this.dependencies; @@ -27,13 +34,20 @@ export class ProfileMetadataUpdatedHandler const parsedMetadata = ProjectMetadataSchema.safeParse(metadata); if (!parsedMetadata.success) { - // logger.warn({ - // msg: `ProfileMetadataUpdated: Failed to parse metadata`, - // event, - // metadataCid, - // metadata, - // }); - return []; + 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); @@ -52,7 +66,6 @@ export class ProfileMetadataUpdatedHandler }, }, ]; - return []; } private getProjectTypeFromMetadata(metadata: ProjectMetadata): ProjectType { // if the metadata contains a canonical reference, it's a linked project diff --git a/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts index e7a9088..b246111 100644 --- a/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileNameUpdated.handler.ts @@ -8,6 +8,9 @@ import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; type Dependencies = Pick; /** * 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( @@ -15,6 +18,7 @@ export class ProfileNameUpdatedHandler implements IEventHandler<"Registry", "Pro readonly chainId: ChainId, private dependencies: Dependencies, ) {} + /* @inheritdoc */ async handle(): Promise { return [ { diff --git a/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts b/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts index 38aff7b..45fefca 100644 --- a/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts +++ b/packages/processors/src/processors/registry/handlers/profileOwnerUpdated.handler.ts @@ -8,6 +8,11 @@ import { IEventHandler, ProcessorDependencies } from "../../../internal.js"; type Dependencies = Pick; /** * 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"> @@ -17,6 +22,7 @@ export class ProfileOwnerUpdatedHandler readonly chainId: ChainId, private dependencies: Dependencies, ) {} + /* @inheritdoc */ async handle(): Promise { return [ { diff --git a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts index c5fd532..dc22880 100644 --- a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts +++ b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts @@ -3,11 +3,18 @@ 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"; +import { IEventHandler, ProcessorDependencies, ProjectByRoleNotFound } from "../../../internal.js"; type Dependencies = Pick; /** * 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( @@ -25,7 +32,7 @@ export class RoleRevokedHandler implements IEventHandler<"Registry", "RoleRevoke // 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 []; + throw new ProjectByRoleNotFound(this.chainId, role); } return [ diff --git a/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts b/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts index a2165d2..710666c 100644 --- a/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts +++ b/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts @@ -65,7 +65,20 @@ describe("ProfileMetadataUpdatedHandler", () => { const handler = new ProfileMetadataUpdatedHandler(mockEvent, chainId, mockDependencies); const result = await handler.handle(); - expect(result).toEqual([]); + expect(result).toEqual([ + { + type: "UpdateProject", + args: { + chainId, + projectId: mockEvent.params.profileId, + project: { + metadataCid: mockCid, + metadata: null, + projectType: "canonical", + }, + }, + }, + ]); }); it("throws an error if getMetadata fails", async () => { diff --git a/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts b/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts index 6a0b80b..432c43d 100644 --- a/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts +++ b/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts @@ -3,6 +3,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { IProjectRepository, Project } from "@grants-stack-indexer/repository"; import { ChainId, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; +import { ProjectByRoleNotFound } from "../../../src/internal.js"; import { RoleRevokedHandler } from "../../../src/processors/registry/handlers/roleRevoked.handler.js"; describe("RoleRevokedHandler", () => { @@ -64,9 +65,8 @@ describe("RoleRevokedHandler", () => { ); const handler = new RoleRevokedHandler(mockEvent, mockChainId, mockDependencies); - const result = await handler.handle(); - expect(result).toEqual([]); + await expect(handler.handle()).rejects.toThrow(ProjectByRoleNotFound); }); it("throw an error when getProjectById fails", async () => { diff --git a/packages/processors/test/registry/registry.processor.spec.ts b/packages/processors/test/registry/registry.processor.spec.ts index 80c0b98..321e0b1 100644 --- a/packages/processors/test/registry/registry.processor.spec.ts +++ b/packages/processors/test/registry/registry.processor.spec.ts @@ -4,7 +4,11 @@ import type { ChainId, ProcessorEvent, RegistryEvent } from "@grants-stack-index import { ProcessorDependencies, UnsupportedEventException } from "../../src/internal.js"; import { ProfileCreatedHandler } from "../../src/processors/registry/handlers/profileCreated.handler.js"; +import { ProfileMetadataUpdatedHandler } from "../../src/processors/registry/handlers/profileMetadataUpdated.handler.js"; +import { ProfileNameUpdatedHandler } from "../../src/processors/registry/handlers/profileNameUpdated.handler.js"; +import { ProfileOwnerUpdatedHandler } from "../../src/processors/registry/handlers/profileOwnerUpdated.handler.js"; import { RoleGrantedHandler } from "../../src/processors/registry/handlers/roleGranted.handler.js"; +import { RoleRevokedHandler } from "../../src/processors/registry/handlers/roleRevoked.handler.js"; import { RegistryProcessor } from "../../src/processors/registry/registry.processor.js"; // Mock the handlers and their handle methods @@ -17,7 +21,6 @@ vi.mock("../../src/processors/registry/handlers/roleGranted.handler.js", () => { }; }); -// Mock the handlers and their handle methods vi.mock("../../src/processors/registry/handlers/profileCreated.handler.js", () => { const ProfileCreatedHandler = vi.fn(); // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access @@ -27,6 +30,40 @@ vi.mock("../../src/processors/registry/handlers/profileCreated.handler.js", () = }; }); +vi.mock("../../src/processors/registry/handlers/profileOwnerUpdated.handler.js", () => { + const ProfileOwnerUpdatedHandler = vi.fn(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + ProfileOwnerUpdatedHandler.prototype.handle = vi.fn(); + return { + ProfileOwnerUpdatedHandler, + }; +}); + +vi.mock("../../src/processors/registry/handlers/roleRevoked.handler.js", () => { + const RoleRevokedHandler = vi.fn(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + RoleRevokedHandler.prototype.handle = vi.fn(); + return { + RoleRevokedHandler, + }; +}); +vi.mock("../../src/processors/registry/handlers/profileMetadataUpdated.handler.js", () => { + const ProfileMetadataUpdatedHandler = vi.fn(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + ProfileMetadataUpdatedHandler.prototype.handle = vi.fn(); + return { + ProfileMetadataUpdatedHandler, + }; +}); +vi.mock("../../src/processors/registry/handlers/profileNameUpdated.handler.js", () => { + const ProfileNameUpdatedHandler = vi.fn(); + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + ProfileNameUpdatedHandler.prototype.handle = vi.fn(); + return { + ProfileNameUpdatedHandler, + }; +}); + describe("RegistryProcessor", () => { const chainId: ChainId = 10 as ChainId; // Replace with appropriate chainId const dependencies: ProcessorDependencies = {} as ProcessorDependencies; // Replace with actual dependencies @@ -72,4 +109,56 @@ describe("RegistryProcessor", () => { expect(RoleGrantedHandler.prototype.handle).toHaveBeenCalled(); expect(result).toEqual([]); // Check if handle returns [] }); + it("calls ProfileOwnerUpdatedHandler", async () => { + const event: ProcessorEvent<"Registry", "ProfileOwnerUpdated"> = { + eventName: "ProfileOwnerUpdated", + } as ProcessorEvent<"Registry", "ProfileOwnerUpdated">; + + vi.spyOn(ProfileOwnerUpdatedHandler.prototype, "handle").mockResolvedValue([]); + + const processor = new RegistryProcessor(chainId, dependencies); + const result = await processor.process(event); + + expect(ProfileOwnerUpdatedHandler.prototype.handle).toHaveBeenCalled(); + expect(result).toEqual([]); // Check if handle returns [] + }); + it("calls RoleRevokedHandler", async () => { + const event: ProcessorEvent<"Registry", "RoleRevoked"> = { + eventName: "RoleRevoked", + } as ProcessorEvent<"Registry", "RoleRevoked">; + + vi.spyOn(RoleRevokedHandler.prototype, "handle").mockResolvedValue([]); + + const processor = new RegistryProcessor(chainId, dependencies); + const result = await processor.process(event); + + expect(RoleRevokedHandler.prototype.handle).toHaveBeenCalled(); + expect(result).toEqual([]); // Check if handle returns [] + }); + it("calls ProfileMetadataUpdatedHandler", async () => { + const event: ProcessorEvent<"Registry", "ProfileMetadataUpdated"> = { + eventName: "ProfileMetadataUpdated", + } as ProcessorEvent<"Registry", "ProfileMetadataUpdated">; + + vi.spyOn(ProfileMetadataUpdatedHandler.prototype, "handle").mockResolvedValue([]); + + const processor = new RegistryProcessor(chainId, dependencies); + const result = await processor.process(event); + + expect(ProfileMetadataUpdatedHandler.prototype.handle).toHaveBeenCalled(); + expect(result).toEqual([]); // Check if handle returns [] + }); + it("calls ProfileNameUpdatedHandler", async () => { + const event: ProcessorEvent<"Registry", "ProfileNameUpdated"> = { + eventName: "ProfileNameUpdated", + } as ProcessorEvent<"Registry", "ProfileNameUpdated">; + + vi.spyOn(ProfileNameUpdatedHandler.prototype, "handle").mockResolvedValue([]); + + const processor = new RegistryProcessor(chainId, dependencies); + const result = await processor.process(event); + + expect(ProfileNameUpdatedHandler.prototype.handle).toHaveBeenCalled(); + expect(result).toEqual([]); // Check if handle returns [] + }); }); diff --git a/packages/repository/src/types/project.types.ts b/packages/repository/src/types/project.types.ts index e4d4d79..e4a87ca 100644 --- a/packages/repository/src/types/project.types.ts +++ b/packages/repository/src/types/project.types.ts @@ -1,6 +1,6 @@ import { Address, ChainId } from "@grants-stack-indexer/shared"; -export type ProjectType = "canonical" | "linked"; +export type ProjectType = "canonical" | "linked" | "unknown"; export type Project = { id: string; From 9e4e78d1e0d4804df1424936574509f9b822e0a8 Mon Sep 17 00:00:00 2001 From: 0xkenj1 Date: Tue, 12 Nov 2024 23:25:24 -0300 Subject: [PATCH 5/6] fix: pr comments --- packages/repository/src/types/project.types.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/repository/src/types/project.types.ts b/packages/repository/src/types/project.types.ts index e4a87ca..e4d4d79 100644 --- a/packages/repository/src/types/project.types.ts +++ b/packages/repository/src/types/project.types.ts @@ -1,6 +1,6 @@ import { Address, ChainId } from "@grants-stack-indexer/shared"; -export type ProjectType = "canonical" | "linked" | "unknown"; +export type ProjectType = "canonical" | "linked"; export type Project = { id: string; From 0df4dc97a1fd4696eb184ce9ca0f6f3d753de5eb Mon Sep 17 00:00:00 2001 From: 0xkenj1 Date: Wed, 13 Nov 2024 12:42:34 -0300 Subject: [PATCH 6/6] fix: pr comments --- .../src/processors/registry/handlers/roleRevoked.handler.ts | 1 + .../registry/handlers/profileMetadataUpdated.handler.spec.ts | 1 - .../test/registry/handlers/roleGranted.handler.spec.ts | 2 +- .../test/registry/handlers/roleRevoked.handler.spec.ts | 5 ++++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts index dc22880..a6154bc 100644 --- a/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts +++ b/packages/processors/src/processors/registry/handlers/roleRevoked.handler.ts @@ -22,6 +22,7 @@ export class RoleRevokedHandler implements IEventHandler<"Registry", "RoleRevoke readonly chainId: ChainId, private dependencies: Dependencies, ) {} + /* @inheritdoc */ async handle(): Promise { const { projectRepository } = this.dependencies; const account = getAddress(this.event.params.account); diff --git a/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts b/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts index 710666c..7404bf2 100644 --- a/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts +++ b/packages/processors/test/registry/handlers/profileMetadataUpdated.handler.spec.ts @@ -12,7 +12,6 @@ describe("ProfileMetadataUpdatedHandler", () => { metadata: [0, mockCid], profileId: "mockProfileId", }, - // Add other necessary event properties here } as ProcessorEvent<"Registry", "ProfileMetadataUpdated">; const mockDependencies = { diff --git a/packages/processors/test/registry/handlers/roleGranted.handler.spec.ts b/packages/processors/test/registry/handlers/roleGranted.handler.spec.ts index c6a6da1..1a7aaa4 100644 --- a/packages/processors/test/registry/handlers/roleGranted.handler.spec.ts +++ b/packages/processors/test/registry/handlers/roleGranted.handler.spec.ts @@ -9,7 +9,7 @@ import { } from "@grants-stack-indexer/shared"; import { ProcessorDependencies } from "../../../src/internal.js"; -import { RoleGrantedHandler } from "../../../src/processors/registry/handlers/index.js"; // Adjust path if needed +import { RoleGrantedHandler } from "../../../src/processors/registry/handlers/index.js"; describe("RoleGrantedHandler", () => { const mockProjectRepository = { diff --git a/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts b/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts index 432c43d..a602ad2 100644 --- a/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts +++ b/packages/processors/test/registry/handlers/roleRevoked.handler.spec.ts @@ -70,7 +70,10 @@ describe("RoleRevokedHandler", () => { }); it("throw an error when getProjectById fails", async () => { - const error = new Error("Database error"); + const error = new ProjectByRoleNotFound( + mockEvent.chainId as ChainId, + mockEvent.params.role, + ); vi.spyOn(mockDependencies.projectRepository, "getProjectById").mockRejectedValueOnce(error); const handler = new RoleRevokedHandler(mockEvent, mockChainId, mockDependencies);