Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: implemented base for new indexer event handling approach #590

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
16 changes: 14 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,20 @@
"deploy:development": "docker buildx build . --platform=linux/amd64 -t registry.fly.io/indexer-development:latest && docker push registry.fly.io/indexer-development:latest && flyctl -c fly.development.toml --app indexer-development deploy -i registry.fly.io/indexer-development:latest"
},
"imports": {
"#abis/*": {
"default": "./src/indexer/abis/*"
"#src/*": {
"default": "./src/*"
},
"#database/*": {
"default": "./src/database/*"
},
"#indexer/*": {
"default": "./src/indexer/*"
},
"#prices/*": {
"default": "./src/prices/*"
},
"#test/*": {
"default": "./src/test/*"
}
},
"author": "",
Expand Down
43 changes: 40 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { decodeJsonWithBigInts } from "./utils/index.js";
import { Block } from "chainsauce/dist/cache.js";
import { createPublicClient, http } from "viem";
import { IndexerEvents } from "chainsauce/dist/indexer.js";
import { getEventHandler } from "./indexer/utils/getEventHandler.js";

const RESOURCE_MONITOR_INTERVAL_MS = 1 * 60 * 1000; // every minute

Expand Down Expand Up @@ -539,9 +540,45 @@ async function catchupAndWatchChain(

indexer.on("event", async (args) => {
try {
// console.time(args.event.name);
// do not await donation inserts as they are write only
if (args.event.name === "Voted") {
const {
event: { contractName, name: eventName },
} = args;

// for now we check for handlers based on:
// - protocol name: AlloV1 / AlloV2
// - contract name example: ProjectRegistry
// - contract version: V1 / V2
// and then the event name.
// but we can combine in the future this way
// with another object that has event handlers by name
// like generic event handlers that are not depending on Protocol/Name/Version contracts
const handler = getEventHandler(contractName, eventName);
if (handler) {
const changesets = await handler(args);
if (["Voted", "Allocated"].includes(eventName)) {
try {
await db.applyChanges(changesets);
} catch (err: unknown) {
if (args.event.name === "Voted") {
indexerLogger.warn({
msg: "error while processing vote",
err,
});
} else if (args.event.name === "Allocated") {
indexerLogger.warn({
msg: "error while processing allocation",
err,
});
}
}
} else {
for (const changeset of changesets) {
await db.applyChange(changeset);
}
}
} else if (args.event.name === "Voted") {
// console.time(args.event.name);
// do not await donation inserts as they are write only
handleAlloV1Event(args)
.then((changesets) => db.applyChanges(changesets))
.catch((err: unknown) => {
Expand Down
4 changes: 2 additions & 2 deletions src/indexer/abis/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// V1.1
import ProjectRegistryV1 from "./allo-v1/v1/ProjectRegistry.js";
import ProjectRegistryV1 from "../contracts/alloV1/projectRegistry/v1/abi/ProjectRegistry.js";
import RoundFactoryV1 from "./allo-v1/v1/RoundFactory.js";
import RoundImplementationV1 from "./allo-v1/v1/RoundImplementation.js";
import QuadraticFundingVotingStrategyFactoryV1 from "./allo-v1/v1/QuadraticFundingVotingStrategyFactory.js";
Expand All @@ -8,7 +8,7 @@ import ProgramFactoryV1 from "./allo-v1/v1/ProgramFactory.js";
import ProgramImplementationV1 from "./allo-v1/v1/ProgramImplementation.js";

// V1.2
import ProjectRegistryV2 from "./allo-v1/v2/ProjectRegistry.js";
import ProjectRegistryV2 from "../contracts/alloV1/projectRegistry/v2/abi/ProjectRegistry.js";
import RoundFactoryV2 from "./allo-v1/v2/RoundFactory.js";
import RoundImplementationV2 from "./allo-v1/v2/RoundImplementation.js";
import QuadraticFundingVotingStrategyFactoryV2 from "./allo-v1/v2/QuadraticFundingVotingStrategyFactory.js";
Expand Down
53 changes: 0 additions & 53 deletions src/indexer/allo/v1/handleEvent.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,59 +112,6 @@ describe("handleEvent", () => {
vi.resetAllMocks();
});

describe("ProjectCreated", () => {
test("should insert project", async () => {
const changesets = await handleEvent({
...DEFAULT_ARGS,
event: {
...DEFAULT_ARGS.event,
contractName: "AlloV1/ProjectRegistry/V2",
name: "ProjectCreated",
params: {
projectID: 1n,
owner: addressTwo,
},
},
context: {
...DEFAULT_ARGS.context,
rpcClient: MOCK_RPC_CLIENT(),
},
});

expect(changesets).toHaveLength(2);

expect(changesets[0]).toEqual({
type: "InsertProject",
project: {
chainId: 1,
createdByAddress: addressTwo,
createdAtBlock: 1n,
updatedAtBlock: 1n,
id: "0xe31382b762a33e568e1e9ef38d64f4a2b4dbb51ec0f79ec41779fc5be79ead32",
name: "",
metadata: null,
metadataCid: null,
projectNumber: 1,
registryAddress: addressOne,
tags: ["allo-v1"],
projectType: "canonical",
},
});

expect(changesets[1]).toEqual({
type: "InsertProjectRole",
projectRole: {
chainId: 1,
projectId:
"0xe31382b762a33e568e1e9ef38d64f4a2b4dbb51ec0f79ec41779fc5be79ead32",
address: addressTwo,
role: "owner",
createdAtBlock: 1n,
},
});
});
});

describe("MetadataUpdated", () => {
test("should fetch and update metadata", async () => {
const changesets = await handleEvent({
Expand Down
55 changes: 1 addition & 54 deletions src/indexer/allo/v1/handleEvent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import {
import { ProjectMetadataSchema } from "../../projectMetadata.js";
import { updateApplicationStatus } from "../application.js";
import { getDateFromTimestamp } from "../../../utils/index.js";
import { fullProjectId } from "../../utils/index.js";

enum ApplicationStatus {
PENDING = 0,
Expand All @@ -43,17 +44,6 @@ enum ApplicationStatus {
IN_REVIEW,
}

function fullProjectId(
projectChainId: number,
projectId: number,
projectRegistryAddress: string
) {
return ethers.utils.solidityKeccak256(
["uint256", "address", "uint256"],
[projectChainId, projectRegistryAddress, projectId]
);
}

export async function handleEvent(
args: EventHandlerArgs<Indexer>
): Promise<Changeset[]> {
Expand All @@ -75,49 +65,6 @@ export async function handleEvent(

switch (event.name) {
// -- PROJECTS
case "ProjectCreated": {
const projectId = fullProjectId(
chainId,
Number(event.params.projectID),
event.address
);

const tx = await rpcClient.getTransaction({
hash: event.transactionHash,
});

const createdBy = tx.from;

return [
{
type: "InsertProject",
project: {
tags: ["allo-v1"],
chainId,
registryAddress: parseAddress(event.address),
id: projectId,
name: "",
projectNumber: Number(event.params.projectID),
metadataCid: null,
metadata: null,
createdByAddress: parseAddress(createdBy),
createdAtBlock: event.blockNumber,
updatedAtBlock: event.blockNumber,
projectType: "canonical",
},
},
{
type: "InsertProjectRole",
projectRole: {
chainId,
projectId,
address: parseAddress(event.params.owner),
role: "owner",
createdAtBlock: event.blockNumber,
},
},
];
}

case "MetadataUpdated": {
const projectId = fullProjectId(
Expand Down
Loading