diff --git a/apps/processing/src/config/env.ts b/apps/processing/src/config/env.ts index de2e782..0275a03 100644 --- a/apps/processing/src/config/env.ts +++ b/apps/processing/src/config/env.ts @@ -1,6 +1,8 @@ import dotenv from "dotenv"; import { z } from "zod"; +import { stringify } from "@grants-stack-indexer/shared"; + dotenv.config(); const stringToJSONSchema = z.string().transform((str, ctx): z.infer> => { @@ -33,7 +35,7 @@ const env = validationSchema.safeParse(process.env); if (!env.success) { console.error( "Invalid environment variables:", - env.error.issues.map((issue) => JSON.stringify(issue)).join("\n"), + env.error.issues.map((issue) => stringify(issue)).join("\n"), ); process.exit(1); } diff --git a/apps/processing/src/services/processing.service.ts b/apps/processing/src/services/processing.service.ts index 4f7ee02..9451057 100644 --- a/apps/processing/src/services/processing.service.ts +++ b/apps/processing/src/services/processing.service.ts @@ -26,7 +26,7 @@ export class ProcessingService { constructor(private readonly env: Environment) { const { core, registries, indexerClient, kyselyDatabase } = - SharedDependenciesService.initialize(env); + SharedDependenciesService.initialize(env, this.logger); this.kyselyDatabase = kyselyDatabase; // Initialize EVM provider @@ -39,6 +39,7 @@ export class ProcessingService { registries, env.FETCH_LIMIT, env.FETCH_DELAY_MS, + this.logger, ); } diff --git a/apps/processing/src/services/sharedDependencies.service.ts b/apps/processing/src/services/sharedDependencies.service.ts index 7ca798c..3b927ee 100644 --- a/apps/processing/src/services/sharedDependencies.service.ts +++ b/apps/processing/src/services/sharedDependencies.service.ts @@ -12,6 +12,7 @@ import { KyselyProjectRepository, KyselyRoundRepository, } from "@grants-stack-indexer/repository"; +import { ILogger } from "@grants-stack-indexer/shared"; import { Environment } from "../config/index.js"; @@ -32,7 +33,7 @@ export type SharedDependencies = { * - Initializes indexer client */ export class SharedDependenciesService { - static initialize(env: Environment): SharedDependencies { + static initialize(env: Environment, logger: ILogger): SharedDependencies { // Initialize repositories const kyselyDatabase = createKyselyDatabase({ connectionString: env.DATABASE_URL, @@ -44,16 +45,19 @@ export class SharedDependenciesService { kyselyDatabase, env.DATABASE_SCHEMA, ); - const pricingProvider = new CoingeckoProvider({ - apiKey: env.COINGECKO_API_KEY, - apiType: env.COINGECKO_API_TYPE, - }); + const pricingProvider = new CoingeckoProvider( + { + apiKey: env.COINGECKO_API_KEY, + apiType: env.COINGECKO_API_TYPE, + }, + logger, + ); - const metadataProvider = new IpfsProvider(env.IPFS_GATEWAYS_URL); + const metadataProvider = new IpfsProvider(env.IPFS_GATEWAYS_URL, logger); // Initialize registries - const eventsRegistry = new InMemoryEventsRegistry(); - const strategyRegistry = new InMemoryStrategyRegistry(); + const eventsRegistry = new InMemoryEventsRegistry(logger); + const strategyRegistry = new InMemoryStrategyRegistry(logger); // Initialize indexer client const indexerClient = new EnvioIndexerClient( diff --git a/packages/data-flow/src/data-loader/dataLoader.ts b/packages/data-flow/src/data-loader/dataLoader.ts index 9c1098b..6797f79 100644 --- a/packages/data-flow/src/data-loader/dataLoader.ts +++ b/packages/data-flow/src/data-loader/dataLoader.ts @@ -4,6 +4,7 @@ import { IProjectRepository, IRoundRepository, } from "@grants-stack-indexer/repository"; +import { ILogger, stringify } from "@grants-stack-indexer/shared"; import { ExecutionResult, IDataLoader, InvalidChangeset } from "../internal.js"; import { @@ -35,6 +36,7 @@ export class DataLoader implements IDataLoader { round: IRoundRepository; application: IApplicationRepository; }, + private readonly logger: ILogger, ) { this.handlers = { ...createProjectHandlers(repositories.project), @@ -73,7 +75,7 @@ export class DataLoader implements IDataLoader { error instanceof Error ? error.message : String(error) }`, ); - console.error(error); + this.logger.error(`${stringify(error, Object.getOwnPropertyNames(error))}`); break; } } diff --git a/packages/data-flow/src/eventsRegistry.ts b/packages/data-flow/src/eventsRegistry.ts index ba361a4..b009215 100644 --- a/packages/data-flow/src/eventsRegistry.ts +++ b/packages/data-flow/src/eventsRegistry.ts @@ -1,4 +1,5 @@ -import type { AnyEvent, ContractName, ProcessorEvent } from "@grants-stack-indexer/shared"; +import type { AnyEvent, ContractName, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; +import { stringify } from "@grants-stack-indexer/shared"; import type { IEventsRegistry } from "./internal.js"; @@ -9,6 +10,8 @@ import type { IEventsRegistry } from "./internal.js"; export class InMemoryEventsRegistry implements IEventsRegistry { private lastProcessedEvent: ProcessorEvent | undefined; + constructor(private logger: ILogger) {} + /** * @inheritdoc */ @@ -20,6 +23,7 @@ export class InMemoryEventsRegistry implements IEventsRegistry { * @inheritdoc */ async saveLastProcessedEvent(event: ProcessorEvent): Promise { + this.logger.debug(`Saving last processed event: ${stringify(event, undefined, 4)}`); this.lastProcessedEvent = event; } } diff --git a/packages/data-flow/src/orchestrator.ts b/packages/data-flow/src/orchestrator.ts index c361044..1cb623a 100644 --- a/packages/data-flow/src/orchestrator.ts +++ b/packages/data-flow/src/orchestrator.ts @@ -10,6 +10,7 @@ import { ChainId, ContractName, Hex, + ILogger, isAlloEvent, isStrategyEvent, ProcessorEvent, @@ -75,16 +76,23 @@ export class Orchestrator { }, private fetchLimit: number = 1000, private fetchDelayInMs: number = 10000, + private logger: ILogger, ) { this.eventsFetcher = new EventsFetcher(this.indexerClient); - this.eventsProcessor = new EventsProcessor(this.chainId, this.dependencies); + this.eventsProcessor = new EventsProcessor(this.chainId, { + ...this.dependencies, + logger: this.logger, + }); this.eventsRegistry = registries.eventsRegistry; this.strategyRegistry = registries.strategyRegistry; - this.dataLoader = new DataLoader({ - project: this.dependencies.projectRepository, - round: this.dependencies.roundRepository, - application: this.dependencies.applicationRepository, - }); + this.dataLoader = new DataLoader( + { + project: this.dependencies.projectRepository, + round: this.dependencies.roundRepository, + application: this.dependencies.applicationRepository, + }, + this.logger, + ); this.eventsQueue = new Queue>(fetchLimit); } @@ -107,7 +115,7 @@ export class Orchestrator { if (!existsHandler(event.strategyId)) { //TODO: save to registry as unsupported strategy, so when the strategy is handled it will be backwards compatible and process all of the events //TODO: decide if we want to log this - // console.log( + // this.logger.info( // `No handler found for strategyId: ${event.strategyId}. Event: ${stringify( // event, // )}`, @@ -121,7 +129,7 @@ export class Orchestrator { if (executionResult.numFailed > 0) { //TODO: should we retry the failed changesets? - console.error( + this.logger.error( `Failed to apply changesets. ${executionResult.errors.join("\n")} Event: ${stringify( event, )}`, @@ -134,16 +142,16 @@ export class Orchestrator { error instanceof InvalidEvent || error instanceof UnsupportedEventException ) { - // console.error( + // this.logger.error( // `Current event cannot be handled. ${error.name}: ${error.message}. Event: ${stringify(event)}`, // ); } else { - console.error(`Error processing event: ${stringify(event)}`, error); + this.logger.error(`Error processing event: ${stringify(event)} ${error}`); } } } - console.log("Shutdown signal received. Exiting..."); + this.logger.info("Shutdown signal received. Exiting..."); } /** diff --git a/packages/data-flow/src/strategyRegistry.ts b/packages/data-flow/src/strategyRegistry.ts index c370c58..d32fd59 100644 --- a/packages/data-flow/src/strategyRegistry.ts +++ b/packages/data-flow/src/strategyRegistry.ts @@ -1,5 +1,7 @@ import type { Address, Hex } from "viem"; +import { ILogger } from "@grants-stack-indexer/shared"; + import type { IStrategyRegistry } from "./internal.js"; /** @@ -8,6 +10,7 @@ import type { IStrategyRegistry } from "./internal.js"; //TODO: Implement storage to persist strategies. since we're using address, do we need ChainId? export class InMemoryStrategyRegistry implements IStrategyRegistry { private strategiesMap: Map = new Map(); + constructor(private logger: ILogger) {} /** @inheritdoc */ async getStrategyId(strategyAddress: Address): Promise { @@ -16,6 +19,7 @@ export class InMemoryStrategyRegistry implements IStrategyRegistry { /** @inheritdoc */ async saveStrategyId(strategyAddress: Address, strategyId: Hex): Promise { + this.logger.debug(`Saving strategy id ${strategyId} for address ${strategyAddress}`); this.strategiesMap.set(strategyAddress, strategyId); } } diff --git a/packages/data-flow/test/data-loader/dataLoader.spec.ts b/packages/data-flow/test/data-loader/dataLoader.spec.ts index 85e16b5..ee3130d 100644 --- a/packages/data-flow/test/data-loader/dataLoader.spec.ts +++ b/packages/data-flow/test/data-loader/dataLoader.spec.ts @@ -6,6 +6,7 @@ import { IProjectRepository, IRoundRepository, } from "@grants-stack-indexer/repository"; +import { ILogger } from "@grants-stack-indexer/shared"; import { DataLoader } from "../../src/data-loader/dataLoader.js"; import { InvalidChangeset } from "../../src/internal.js"; @@ -26,12 +27,21 @@ describe("DataLoader", () => { updateApplication: vi.fn(), } as unknown as IApplicationRepository; + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; const createDataLoader = (): DataLoader => - new DataLoader({ - project: mockProjectRepository, - round: mockRoundRepository, - application: mockApplicationRepository, - }); + new DataLoader( + { + project: mockProjectRepository, + round: mockRoundRepository, + application: mockApplicationRepository, + }, + logger, + ); beforeEach(() => { vi.clearAllMocks(); diff --git a/packages/data-flow/test/unit/eventsRegistry.spec.ts b/packages/data-flow/test/unit/eventsRegistry.spec.ts index 33736d5..7a293f2 100644 --- a/packages/data-flow/test/unit/eventsRegistry.spec.ts +++ b/packages/data-flow/test/unit/eventsRegistry.spec.ts @@ -1,18 +1,24 @@ -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; -import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; +import { ChainId, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; import { InMemoryEventsRegistry } from "../../src/eventsRegistry.js"; describe("InMemoryEventsRegistry", () => { + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; it("return null when no event has been saved", async () => { - const registry = new InMemoryEventsRegistry(); + const registry = new InMemoryEventsRegistry(logger); const lastEvent = await registry.getLastProcessedEvent(); expect(lastEvent).toBeUndefined(); }); it("save and retrieve the last processed event", async () => { - const registry = new InMemoryEventsRegistry(); + const registry = new InMemoryEventsRegistry(logger); const mockEvent: ProcessorEvent<"Allo", "PoolCreated"> = { contractName: "Allo", eventName: "PoolCreated", @@ -43,7 +49,7 @@ describe("InMemoryEventsRegistry", () => { }); it("should update the last processed event when saving multiple times", async () => { - const registry = new InMemoryEventsRegistry(); + const registry = new InMemoryEventsRegistry(logger); const firstEvent: ProcessorEvent<"Allo", "PoolCreated"> = { contractName: "Allo", diff --git a/packages/data-flow/test/unit/orchestrator.spec.ts b/packages/data-flow/test/unit/orchestrator.spec.ts index 87d4baa..db80a70 100644 --- a/packages/data-flow/test/unit/orchestrator.spec.ts +++ b/packages/data-flow/test/unit/orchestrator.spec.ts @@ -17,6 +17,7 @@ import { ContractToEventName, EventParams, Hex, + ILogger, ProcessorEvent, StrategyEvent, stringify, @@ -59,6 +60,12 @@ describe("Orchestrator", { sequential: true }, () => { const chainId = 1 as ChainId; const mockFetchLimit = 10; const mockFetchDelay = 100; + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; beforeEach(() => { // Setup mock implementations @@ -105,6 +112,7 @@ describe("Orchestrator", { sequential: true }, () => { }, mockFetchLimit, mockFetchDelay, + logger, ); }); @@ -468,7 +476,6 @@ describe("Orchestrator", { sequential: true }, () => { it("keeps running when there is an error", async () => { const eventsProcessorSpy = vi.spyOn(orchestrator["eventsProcessor"], "processEvent"); - const consoleSpy = vi.spyOn(console, "error"); const errorEvent = createMockEvent("Allo", "Unknown" as unknown as AlloEvent, 1); const error = new Error("test"); @@ -503,10 +510,9 @@ describe("Orchestrator", { sequential: true }, () => { expect(eventsProcessorSpy).toHaveBeenCalledTimes(2); expect(orchestrator["dataLoader"].applyChanges).toHaveBeenCalledTimes(1); expect(mockEventsRegistry.saveLastProcessedEvent).toHaveBeenCalledTimes(2); - expect(consoleSpy).toHaveBeenCalledTimes(1); - expect(consoleSpy).toHaveBeenCalledWith( + expect(logger.error).toHaveBeenCalledTimes(1); + expect(logger.error).toHaveBeenCalledWith( expect.stringContaining(`Error processing event: ${stringify(errorEvent)}`), - error, ); }); diff --git a/packages/data-flow/test/unit/strategyRegistry.spec.ts b/packages/data-flow/test/unit/strategyRegistry.spec.ts index 4ace8ee..01e4806 100644 --- a/packages/data-flow/test/unit/strategyRegistry.spec.ts +++ b/packages/data-flow/test/unit/strategyRegistry.spec.ts @@ -1,11 +1,19 @@ import { Address, Hex } from "viem"; -import { describe, expect, it } from "vitest"; +import { describe, expect, it, vi } from "vitest"; + +import { ILogger } from "@grants-stack-indexer/shared"; import { InMemoryStrategyRegistry } from "../../src/strategyRegistry.js"; describe("InMemoryStrategyRegistry", () => { + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; it("return undefined for non-existent strategy address", async () => { - const registry = new InMemoryStrategyRegistry(); + const registry = new InMemoryStrategyRegistry(logger); const strategyAddress = "0x123" as Address; const strategyId = await registry.getStrategyId(strategyAddress); @@ -13,7 +21,7 @@ describe("InMemoryStrategyRegistry", () => { }); it("save and retrieve strategy id", async () => { - const registry = new InMemoryStrategyRegistry(); + const registry = new InMemoryStrategyRegistry(logger); const strategyAddress = "0x123" as Address; const strategyId = "0xabc" as Hex; @@ -24,7 +32,7 @@ describe("InMemoryStrategyRegistry", () => { }); it("handle multiple strategy addresses independently", async () => { - const registry = new InMemoryStrategyRegistry(); + const registry = new InMemoryStrategyRegistry(logger); const firstAddress = "0x123" as Address; const secondAddress = "0x456" as Address; const firstStrategyId = "0xabc" as Hex; diff --git a/packages/indexer-client/src/providers/envioIndexerClient.ts b/packages/indexer-client/src/providers/envioIndexerClient.ts index 68366a7..ef2a615 100644 --- a/packages/indexer-client/src/providers/envioIndexerClient.ts +++ b/packages/indexer-client/src/providers/envioIndexerClient.ts @@ -1,6 +1,6 @@ import { gql, GraphQLClient } from "graphql-request"; -import { AnyIndexerFetchedEvent, ChainId } from "@grants-stack-indexer/shared"; +import { AnyIndexerFetchedEvent, ChainId, stringify } from "@grants-stack-indexer/shared"; import { IndexerClientError, InvalidIndexerResponse } from "../exceptions/index.js"; import { IIndexerClient } from "../internal.js"; @@ -64,13 +64,13 @@ export class EnvioIndexerClient implements IIndexerClient { if (response?.raw_events) { return response.raw_events; } else { - throw new InvalidIndexerResponse(JSON.stringify(response)); + throw new InvalidIndexerResponse(stringify(response)); } } catch (error) { if (error instanceof InvalidIndexerResponse) { throw error; } - throw new IndexerClientError(JSON.stringify(error, Object.getOwnPropertyNames(error))); + throw new IndexerClientError(stringify(error, Object.getOwnPropertyNames(error))); } } } diff --git a/packages/metadata/src/providers/ipfs.provider.ts b/packages/metadata/src/providers/ipfs.provider.ts index a499dfb..3399faa 100644 --- a/packages/metadata/src/providers/ipfs.provider.ts +++ b/packages/metadata/src/providers/ipfs.provider.ts @@ -1,13 +1,18 @@ import axios, { AxiosInstance } from "axios"; import { z } from "zod"; +import { ILogger, stringify } from "@grants-stack-indexer/shared"; + import type { IMetadataProvider } from "../internal.js"; import { EmptyGatewaysUrlsException, InvalidContentException, isValidCid } from "../internal.js"; export class IpfsProvider implements IMetadataProvider { private readonly axiosInstance: AxiosInstance; - constructor(private readonly gateways: string[]) { + constructor( + private readonly gateways: string[], + private readonly logger: ILogger, + ) { if (gateways.length === 0) { throw new EmptyGatewaysUrlsException(); } @@ -35,14 +40,14 @@ export class IpfsProvider implements IMetadataProvider { if (error instanceof InvalidContentException) throw error; if (axios.isAxiosError(error)) { - console.warn(`Failed to fetch from ${url}: ${error.message}`); + this.logger.warn(`Failed to fetch from ${url}: ${error.message}`); } else { - console.error(`Failed to fetch from ${url}: ${error}`); + this.logger.error(`Failed to fetch from ${url}: ${error}`); } } } - console.error(`Failed to fetch IPFS data for CID ${ipfsCid} from all gateways.`); + this.logger.error(`Failed to fetch IPFS data for CID ${ipfsCid} from all gateways.`); return undefined; } @@ -61,7 +66,7 @@ export class IpfsProvider implements IMetadataProvider { return parsedData.data; } else { throw new InvalidContentException( - parsedData.error.issues.map((issue) => JSON.stringify(issue)).join("\n"), + parsedData.error.issues.map((issue) => stringify(issue)).join("\n"), ); } } diff --git a/packages/metadata/test/providers/ipfs.provider.spec.ts b/packages/metadata/test/providers/ipfs.provider.spec.ts index bca53c9..491d7c2 100644 --- a/packages/metadata/test/providers/ipfs.provider.spec.ts +++ b/packages/metadata/test/providers/ipfs.provider.spec.ts @@ -1,7 +1,9 @@ import MockAdapter from "axios-mock-adapter"; -import { afterEach, beforeEach, describe, expect, it } from "vitest"; +import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; import { z } from "zod"; +import { ILogger } from "@grants-stack-indexer/shared"; + import { EmptyGatewaysUrlsException, InvalidContentException, @@ -9,13 +11,19 @@ import { } from "../../src/external.js"; describe("IpfsProvider", () => { + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; let mock: MockAdapter; let provider: IpfsProvider; const gateways = ["https://ipfs.io", "https://cloudflare-ipfs.com"]; const validCid = "QmW2WQi7j6c7UgJTarActp7tDNikE4B2qXtFCfLPdsgaTQ"; beforeEach(() => { - provider = new IpfsProvider(gateways); + provider = new IpfsProvider(gateways, logger); mock = new MockAdapter(provider["axiosInstance"]); }); @@ -25,7 +33,7 @@ describe("IpfsProvider", () => { describe("constructor", () => { it("throw EmptyGatewaysUrlsException when initialized with empty gateways array", () => { - expect(() => new IpfsProvider([])).toThrow(EmptyGatewaysUrlsException); + expect(() => new IpfsProvider([], logger)).toThrow(EmptyGatewaysUrlsException); }); }); diff --git a/packages/pricing/src/providers/coingecko.provider.ts b/packages/pricing/src/providers/coingecko.provider.ts index 883d941..4c3d562 100644 --- a/packages/pricing/src/providers/coingecko.provider.ts +++ b/packages/pricing/src/providers/coingecko.provider.ts @@ -1,7 +1,6 @@ -import { isNativeError } from "util/types"; import axios, { AxiosInstance, isAxiosError } from "axios"; -import { TokenCode } from "@grants-stack-indexer/shared"; +import { ILogger, stringify, TokenCode } from "@grants-stack-indexer/shared"; import { IPricingProvider } from "../interfaces/index.js"; import { @@ -62,7 +61,10 @@ export class CoingeckoProvider implements IPricingProvider { * @param options.apiKey - Coingecko API key. * @param options.apiType - Coingecko API type (demo or pro). */ - constructor(options: CoingeckoOptions) { + constructor( + options: CoingeckoOptions, + private readonly logger: ILogger, + ) { const { apiKey, apiType } = options; const { baseURL, authHeader } = getApiTypeConfig(apiType); @@ -111,7 +113,9 @@ export class CoingeckoProvider implements IPricingProvider { //TODO: notify if (isAxiosError(error)) { if (error.status! >= 400 && error.status! < 500) { - console.error(`Coingecko API error: ${error.message}. Stack: ${error.stack}`); + this.logger.error( + `Coingecko API error: ${error.message}. Stack: ${error.stack}`, + ); return undefined; } @@ -119,11 +123,11 @@ export class CoingeckoProvider implements IPricingProvider { throw new NetworkException(error.message, error.status!); } } - console.error(error); - throw new UnknownPricingException( - isNativeError(error) ? error.message : JSON.stringify(error), - isNativeError(error) ? error.stack : undefined, - ); + const errorMessage = + `Coingecko API error: failed to fetch token price ` + + stringify(error, Object.getOwnPropertyNames(error)); + this.logger.error(errorMessage); + throw new UnknownPricingException(errorMessage); } } } diff --git a/packages/pricing/test/providers/coingecko.provider.spec.ts b/packages/pricing/test/providers/coingecko.provider.spec.ts index a6e1660..2b750ac 100644 --- a/packages/pricing/test/providers/coingecko.provider.spec.ts +++ b/packages/pricing/test/providers/coingecko.provider.spec.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; -import { TokenCode } from "@grants-stack-indexer/shared"; +import { ILogger, TokenCode } from "@grants-stack-indexer/shared"; import type { TokenPrice } from "../../src/external.js"; import { CoingeckoProvider, NetworkException, UnsupportedToken } from "../../src/external.js"; @@ -29,12 +29,20 @@ vi.mock("axios", async (importActual) => { }); describe("CoingeckoProvider", () => { let provider: CoingeckoProvider; - + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; beforeEach(() => { - provider = new CoingeckoProvider({ - apiKey: "test-api-key", - apiType: "demo", - }); + provider = new CoingeckoProvider( + { + apiKey: "test-api-key", + apiType: "demo", + }, + logger, + ); }); afterEach(() => { diff --git a/packages/processors/src/registry/handlers/profileCreated.handler.ts b/packages/processors/src/registry/handlers/profileCreated.handler.ts index 872f001..bf3eaad 100644 --- a/packages/processors/src/registry/handlers/profileCreated.handler.ts +++ b/packages/processors/src/registry/handlers/profileCreated.handler.ts @@ -8,7 +8,7 @@ import { ProjectMetadata, ProjectMetadataSchema } from "../../schemas/projectMet type Dependencies = Pick< ProcessorDependencies, - "projectRepository" | "evmProvider" | "metadataProvider" + "projectRepository" | "evmProvider" | "metadataProvider" | "logger" >; /** * Handles the ProfileCreated event for the Registry contract from Allo protocol. @@ -37,7 +37,7 @@ export class ProfileCreatedHandler implements IEventHandler<"Registry", "Profile metadataValue = parsedMetadata.data; } else { //TODO: Replace with logger - // console.warn({ + // this.logger.warn({ // msg: `ProfileCreated: Failed to parse metadata for profile ${profileId}`, // event: this.event, // metadataCid, diff --git a/packages/processors/src/strategy/common/baseDistributed.handler.ts b/packages/processors/src/strategy/common/baseDistributed.handler.ts index f978be6..b80225b 100644 --- a/packages/processors/src/strategy/common/baseDistributed.handler.ts +++ b/packages/processors/src/strategy/common/baseDistributed.handler.ts @@ -5,7 +5,7 @@ import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; import { IEventHandler, ProcessorDependencies } from "../../internal.js"; -type Dependencies = Pick; +type Dependencies = Pick; /** * BaseDistributedHandler: Processes 'Distributed' events @@ -29,7 +29,7 @@ export class BaseDistributedHandler ) {} async handle(): Promise { - const { roundRepository } = this.dependencies; + const { roundRepository, logger } = this.dependencies; const strategyAddress = getAddress(this.event.srcAddress); const round = await roundRepository.getRoundByStrategyAddress( this.chainId, @@ -38,7 +38,7 @@ export class BaseDistributedHandler if (!round) { //TODO: add logging that round was not found - console.log("Round not found for strategy address", strategyAddress); + logger.info(`Round not found for strategy address ${strategyAddress}`); return []; } diff --git a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts b/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts index 7487142..8f22b36 100644 --- a/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts +++ b/packages/processors/src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.ts @@ -18,7 +18,12 @@ import { DVMDRegisteredHandler } from "./handlers/index.js"; type Dependencies = Pick< ProcessorDependencies, - "projectRepository" | "roundRepository" | "metadataProvider" | "evmProvider" | "pricingProvider" + | "projectRepository" + | "roundRepository" + | "metadataProvider" + | "evmProvider" + | "pricingProvider" + | "logger" >; const STRATEGY_NAME = "allov2.DonationVotingMerkleDistributionDirectTransferStrategy"; diff --git a/packages/processors/src/types/processor.types.ts b/packages/processors/src/types/processor.types.ts index 101a7aa..0ef5c58 100644 --- a/packages/processors/src/types/processor.types.ts +++ b/packages/processors/src/types/processor.types.ts @@ -5,6 +5,7 @@ import type { IProjectReadRepository, IRoundReadRepository, } from "@grants-stack-indexer/repository"; +import { ILogger } from "@grants-stack-indexer/shared"; export type ProcessorDependencies = { evmProvider: EvmProvider; @@ -12,4 +13,5 @@ export type ProcessorDependencies = { metadataProvider: IMetadataProvider; roundRepository: IRoundReadRepository; projectRepository: IProjectReadRepository; + logger: ILogger; }; diff --git a/packages/processors/test/allo/allo.processor.spec.ts b/packages/processors/test/allo/allo.processor.spec.ts index bc47ef0..8deac5a 100644 --- a/packages/processors/test/allo/allo.processor.spec.ts +++ b/packages/processors/test/allo/allo.processor.spec.ts @@ -7,7 +7,7 @@ import type { IProjectReadRepository, IRoundReadRepository, } from "@grants-stack-indexer/repository"; -import type { AlloEvent, ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; +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"; @@ -30,7 +30,12 @@ describe("AlloProcessor", () => { let mockPricingProvider: IPricingProvider; let mockMetadataProvider: IMetadataProvider; let mockRoundRepository: IRoundReadRepository; - + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; beforeEach(() => { mockEvmProvider = {} as EvmProvider; mockPricingProvider = {} as IPricingProvider; @@ -43,6 +48,7 @@ describe("AlloProcessor", () => { metadataProvider: mockMetadataProvider, roundRepository: mockRoundRepository, projectRepository: {} as IProjectReadRepository, + logger, }); // Reset mocks before each test diff --git a/packages/processors/test/registry/handlers/profileCreated.handler.spec.ts b/packages/processors/test/registry/handlers/profileCreated.handler.spec.ts index 4c0f1c4..f6cb01f 100644 --- a/packages/processors/test/registry/handlers/profileCreated.handler.spec.ts +++ b/packages/processors/test/registry/handlers/profileCreated.handler.spec.ts @@ -5,7 +5,7 @@ import { EvmProvider } from "@grants-stack-indexer/chain-providers"; import { IMetadataProvider } from "@grants-stack-indexer/metadata"; import { IPricingProvider } from "@grants-stack-indexer/pricing"; import { IProjectReadRepository, IRoundReadRepository } from "@grants-stack-indexer/repository"; -import { Bytes32String, ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; +import { Bytes32String, ChainId, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; import { ProcessorDependencies } from "../../../src/internal.js"; import { ProfileCreatedHandler } from "../../../src/registry/handlers/index.js"; @@ -16,7 +16,12 @@ describe("ProfileCreatedHandler", () => { let mockDependencies: ProcessorDependencies; const mockedTxHash = "0x6e5a7115323ac1712f7c27adff46df2216324a4ad615a8c9ce488c32a1f3a035"; const mockedAddress = "0x48f33AE41E1762e1688125C4f1C536B1491dF803"; - + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; beforeEach(() => { mockEvent = { blockTimestamp: 123123123, @@ -56,6 +61,7 @@ describe("ProfileCreatedHandler", () => { getMetadata: vi.fn(), } as unknown as IMetadataProvider, roundRepository: {} as unknown as IRoundReadRepository, + logger, }; }); diff --git a/packages/processors/test/strategy/common/baseDistributed.handler.spec.ts b/packages/processors/test/strategy/common/baseDistributed.handler.spec.ts index 74042c7..4d19ac7 100644 --- a/packages/processors/test/strategy/common/baseDistributed.handler.spec.ts +++ b/packages/processors/test/strategy/common/baseDistributed.handler.spec.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, it, vi } from "vitest"; import { IRoundReadRepository, Round } from "@grants-stack-indexer/repository"; -import { ChainId, ProcessorEvent } from "@grants-stack-indexer/shared"; +import { ChainId, ILogger, ProcessorEvent } from "@grants-stack-indexer/shared"; import { BaseDistributedHandler } from "../../../src/strategy/common/baseDistributed.handler.js"; @@ -38,7 +38,12 @@ describe("BaseDistributedHandler", () => { let mockRoundRepository: IRoundReadRepository; let mockEvent: ProcessorEvent<"Strategy", "DistributedWithRecipientAddress">; const chainId = 10 as ChainId; - + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; beforeEach(() => { mockRoundRepository = { getRoundByStrategyAddress: vi.fn(), @@ -53,6 +58,7 @@ describe("BaseDistributedHandler", () => { handler = new BaseDistributedHandler(mockEvent, chainId, { roundRepository: mockRoundRepository, + logger, }); const result = await handler.handle(); @@ -76,6 +82,7 @@ describe("BaseDistributedHandler", () => { handler = new BaseDistributedHandler(mockEvent, chainId, { roundRepository: mockRoundRepository, + logger, }); const result = await handler.handle(); diff --git a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.spec.ts b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.spec.ts index 6e5eaa6..81fb0d0 100644 --- a/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.spec.ts +++ b/packages/processors/test/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.spec.ts @@ -10,6 +10,7 @@ import { EvmProvider } from "@grants-stack-indexer/chain-providers"; import { IPricingProvider } from "@grants-stack-indexer/pricing"; import { ChainId, + ILogger, ProcessorEvent, StrategyEvent, Token, @@ -49,7 +50,12 @@ describe("DVMDDirectTransferHandler", () => { let mockProjectRepository: IProjectReadRepository; let mockEVMProvider: EvmProvider; let mockPricingProvider: IPricingProvider; - + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; beforeEach(() => { mockMetadataProvider = {} as IMetadataProvider; mockRoundRepository = {} as IRoundReadRepository; @@ -69,6 +75,7 @@ describe("DVMDDirectTransferHandler", () => { projectRepository: mockProjectRepository, evmProvider: mockEVMProvider, pricingProvider: mockPricingProvider, + logger, }); }); @@ -95,6 +102,7 @@ describe("DVMDDirectTransferHandler", () => { projectRepository: mockProjectRepository, evmProvider: mockEVMProvider, pricingProvider: mockPricingProvider, + logger, }); expect(DVMDRegisteredHandler.prototype.handle).toHaveBeenCalled(); }); @@ -114,6 +122,7 @@ describe("DVMDDirectTransferHandler", () => { projectRepository: mockProjectRepository, evmProvider: mockEVMProvider, pricingProvider: mockPricingProvider, + logger, }); expect(BaseDistributedHandler.prototype.handle).toHaveBeenCalled(); }); diff --git a/packages/processors/test/strategy/strategy.processor.spec.ts b/packages/processors/test/strategy/strategy.processor.spec.ts index b195c90..4d2e73a 100644 --- a/packages/processors/test/strategy/strategy.processor.spec.ts +++ b/packages/processors/test/strategy/strategy.processor.spec.ts @@ -7,7 +7,7 @@ import type { IProjectReadRepository, IRoundReadRepository, } from "@grants-stack-indexer/repository"; -import type { ChainId, ProcessorEvent, StrategyEvent } from "@grants-stack-indexer/shared"; +import type { ChainId, ILogger, ProcessorEvent, StrategyEvent } from "@grants-stack-indexer/shared"; import { StrategyProcessor, UnsupportedStrategy } from "../../src/internal.js"; @@ -18,7 +18,12 @@ describe("StrategyProcessor", () => { let mockPricingProvider: IPricingProvider; let mockMetadataProvider: IMetadataProvider; let mockRoundRepository: IRoundReadRepository; - + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; beforeEach(() => { mockEvmProvider = {} as EvmProvider; mockPricingProvider = {} as IPricingProvider; @@ -31,6 +36,7 @@ describe("StrategyProcessor", () => { metadataProvider: mockMetadataProvider, roundRepository: mockRoundRepository, projectRepository: {} as IProjectReadRepository, + logger, }); // Reset mocks before each test diff --git a/packages/processors/test/strategy/strategyHandler.factory.spec.ts b/packages/processors/test/strategy/strategyHandler.factory.spec.ts index 2bc3902..ffbe3eb 100644 --- a/packages/processors/test/strategy/strategyHandler.factory.spec.ts +++ b/packages/processors/test/strategy/strategyHandler.factory.spec.ts @@ -5,7 +5,7 @@ import { EvmProvider } from "@grants-stack-indexer/chain-providers"; import { IMetadataProvider } from "@grants-stack-indexer/metadata"; import { IPricingProvider } from "@grants-stack-indexer/pricing"; import { IProjectReadRepository, IRoundReadRepository } from "@grants-stack-indexer/repository"; -import { ChainId } from "@grants-stack-indexer/shared"; +import { ChainId, ILogger } from "@grants-stack-indexer/shared"; import { ProcessorDependencies, StrategyHandlerFactory } from "../../src/internal.js"; import { DVMDDirectTransferStrategyHandler } from "../../src/strategy/donationVotingMerkleDistributionDirectTransfer/dvmdDirectTransfer.handler.js"; @@ -18,7 +18,12 @@ describe("StrategyHandlerFactory", () => { let mockRoundRepository: IRoundReadRepository; let mockProjectRepository: IProjectReadRepository; let mockProcessorDependencies: ProcessorDependencies; - + const logger: ILogger = { + debug: vi.fn(), + error: vi.fn(), + info: vi.fn(), + warn: vi.fn(), + }; beforeEach(() => { mockEvmProvider = {} as EvmProvider; mockPricingProvider = {} as IPricingProvider; @@ -31,6 +36,7 @@ describe("StrategyHandlerFactory", () => { metadataProvider: mockMetadataProvider, roundRepository: mockRoundRepository, projectRepository: mockProjectRepository, + logger, }; });