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

feat: events fetcher & indexer client #4

Merged
merged 8 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions packages/data-flow/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# @grants-stack-indexer/data-flow

Is a library that provides the core components of the processing pipeline for gitcoin grants-stack-indexer.

## Available Scripts

Available scripts that can be run using `pnpm`:

| Script | Description |
| ------------- | ------------------------------------------------------- |
| `build` | Build library using tsc |
| `check-types` | Check types issues using tsc |
| `clean` | Remove `dist` folder |
| `lint` | Run ESLint to check for coding standards |
| `lint:fix` | Run linter and automatically fix code formatting issues |
| `format` | Check code formatting and style using Prettier |
| `format:fix` | Run formatter and automatically fix issues |
| `test` | Run tests using vitest |
| `test:cov` | Run tests with coverage report |

## Usage

### Importing the Package

You can import the package in your TypeScript or JavaScript files as follows:

```typescript
import { EventsFetcher } from "@grants-stack-indexer/data-flow";
```

### Example

```typescript
const eventsFetcher = new EventsFetcher(indexerClient);

const chainId = 1;
const blockNumber = 1000;
const logIndex = 0;

const result = await eventsFetcher.fetcEventsByBlockNumberAndLogIndex(
chainId,
blockNumber,
logIndex,
);
```
35 changes: 35 additions & 0 deletions packages/data-flow/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"name": "@grants-stack-indexer/data-flow",
"version": "0.0.1",
"private": true,
"description": "",
"license": "MIT",
"author": "Wonderland",
"type": "module",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"directories": {
"src": "src"
},
"files": [
"dist/*",
"package.json",
"!**/*.tsbuildinfo"
],
"scripts": {
"build": "tsc -p tsconfig.build.json",
"check-types": "tsc --noEmit -p ./tsconfig.json",
"clean": "rm -rf dist/",
"format": "prettier --check \"{src,test}/**/*.{js,ts,json}\"",
"format:fix": "prettier --write \"{src,test}/**/*.{js,ts,json}\"",
"lint": "eslint \"{src,test}/**/*.{js,ts,json}\"",
"lint:fix": "pnpm lint --fix",
"test": "vitest run --config vitest.config.ts --passWithNoTests",
"test:cov": "vitest run --config vitest.config.ts --coverage"
},
"dependencies": {
"@grants-stack-indexer/indexer-client": "workspace:*",
"@grants-stack-indexer/shared": "workspace:*",
"viem": "2.21.19"
}
}
22 changes: 22 additions & 0 deletions packages/data-flow/src/eventsFetcher.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { IIndexerClient } from "@grants-stack-indexer/indexer-client";
import { AnyProtocolEvent } from "@grants-stack-indexer/shared";

import { IEventsFetcher } from "./interfaces/index.js";

export class EventsFetcher implements IEventsFetcher {
constructor(private indexerClient: IIndexerClient) {}
/* @inheritdoc */
async fetchEventsByBlockNumberAndLogIndex(
chainId: bigint,
blockNumber: bigint,
logIndex: number,
limit: number = 100,
): Promise<AnyProtocolEvent[]> {
return await this.indexerClient.getEventsAfterBlockNumberAndLogIndex(
chainId,
blockNumber,
logIndex,
limit,
);
}
}
Empty file.
1 change: 1 addition & 0 deletions packages/data-flow/src/external.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { EventsFetcher } from "./internal.js";
1 change: 1 addition & 0 deletions packages/data-flow/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./external.js";
20 changes: 20 additions & 0 deletions packages/data-flow/src/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { AnyProtocolEvent } from "@grants-stack-indexer/shared";

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add natspec

/**
* Interface for the events fetcher
*/
export interface IEventsFetcher {
/**
* Fetch the events by block number and log index for a chain
* @param chainId id of the chain
* @param blockNumber block number to fetch events from
* @param logIndex log index in the block to fetch events from
* @param limit limit of events to fetch
*/
fetchEventsByBlockNumberAndLogIndex(
chainId: bigint,
blockNumber: bigint,
logIndex: number,
limit?: number,
): Promise<AnyProtocolEvent[]>;
}
1 change: 1 addition & 0 deletions packages/data-flow/src/internal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./eventsFetcher.js";
78 changes: 78 additions & 0 deletions packages/data-flow/test/unit/eventsFetcher.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { beforeEach, describe, expect, it, Mocked, vi } from "vitest";

import { IIndexerClient } from "@grants-stack-indexer/indexer-client";
import { AnyProtocolEvent } from "@grants-stack-indexer/shared";

import { EventsFetcher } from "../../src/eventsFetcher.js";

describe("EventsFetcher", () => {
let indexerClientMock: Mocked<IIndexerClient>;
let eventsFetcher: EventsFetcher;

beforeEach(() => {
indexerClientMock = {
getEventsAfterBlockNumberAndLogIndex: vi.fn(),
};

eventsFetcher = new EventsFetcher(indexerClientMock);
});

it("should fetch events by block number and log index", async () => {
const mockEvents: AnyProtocolEvent[] = [
{
chain_id: 1,
block_number: 12345,
block_timestamp: 123123123,
contract_name: "Allo",
event_name: "PoolCreated",
src_address: "0x1234567890123456789012345678901234567890",
log_index: 0,
params: { contractAddress: "0x1234" },
},
{
chain_id: 1,
block_number: 12345,
block_timestamp: 123123123,
contract_name: "Allo",
event_name: "PoolCreated",
src_address: "0x1234567890123456789012345678901234567890",
log_index: 0,
params: { contractAddress: "0x1234" },
},
];
const chainId = 1n;
const blockNumber = 1000n;
const logIndex = 0;
const limit = 100;

indexerClientMock.getEventsAfterBlockNumberAndLogIndex.mockResolvedValue(mockEvents);

const result = await eventsFetcher.fetchEventsByBlockNumberAndLogIndex(
chainId,
blockNumber,
logIndex,
);

expect(indexerClientMock.getEventsAfterBlockNumberAndLogIndex).toHaveBeenCalledWith(
chainId,
blockNumber,
logIndex,
limit,
);
expect(result).toEqual(mockEvents);
});

it("should handle errors thrown by indexer client", async () => {
const chainId = 1n;
const blockNumber = 1000n;
const logIndex = 0;

indexerClientMock.getEventsAfterBlockNumberAndLogIndex.mockRejectedValue(
new Error("Network error"),
);

await expect(
eventsFetcher.fetchEventsByBlockNumberAndLogIndex(chainId, blockNumber, logIndex),
).rejects.toThrow("Network error");
});
});
13 changes: 13 additions & 0 deletions packages/data-flow/tsconfig.build.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/* Based on total-typescript no-dom library config */
/* https://github.com/total-typescript/tsconfig */
{
"extends": "../../tsconfig.build.json",
"compilerOptions": {
"composite": true,
"declarationMap": true,
"declaration": true,
"outDir": "dist"
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "tests"]
}
4 changes: 4 additions & 0 deletions packages/data-flow/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"extends": "../../tsconfig.json",
"include": ["src/**/*"]
}
22 changes: 22 additions & 0 deletions packages/data-flow/vitest.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import path from "path";
import { configDefaults, defineConfig } from "vitest/config";

export default defineConfig({
test: {
globals: true, // Use Vitest's global API without importing it in each file
environment: "node", // Use the Node.js environment
include: ["test/**/*.spec.ts"], // Include test files
exclude: ["node_modules", "dist"], // Exclude certain directories
coverage: {
provider: "v8",
reporter: ["text", "json", "html"], // Coverage reporters
exclude: ["node_modules", "dist", "src/index.ts", ...configDefaults.exclude], // Files to exclude from coverage
},
},
resolve: {
alias: {
// Setup path alias based on tsconfig paths
"@": path.resolve(__dirname, "src"),
},
},
});
36 changes: 36 additions & 0 deletions packages/indexer-client/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# @grants-stack-indexer/indexer-client

Is library for interacting with blockchain event indexing services.

## Available Scripts

Available scripts that can be run using `pnpm`:

| Script | Description |
| ------------- | ------------------------------------------------------- |
| `build` | Build library using tsc |
| `check-types` | Check types issues using tsc |
| `clean` | Remove `dist` folder |
| `lint` | Run ESLint to check for coding standards |
| `lint:fix` | Run linter and automatically fix code formatting issues |
| `format` | Check code formatting and style using Prettier |
| `format:fix` | Run formatter and automatically fix issues |
| `test` | Run tests using vitest |
| `test:cov` | Run tests with coverage report |

## Usage

### Importing the Package

You can import the package in your TypeScript or JavaScript files as follows:

```typescript
import { EnvioIndexerClient } from "@grants-stack-indexer/indexer-client";
```

### Example

```typescript
const envioIndexerClient = new EnvioIndexerClient("http://example.com/graphql", "secret");
await envioIndexerClient.getEventsByBlockNumberAndLogIndex(1, 12345, 0);
```
34 changes: 34 additions & 0 deletions packages/indexer-client/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"name": "@grants-stack-indexer/indexer-client",
"version": "0.0.1",
"private": true,
"description": "",
"license": "MIT",
"author": "Wonderland",
"type": "module",
"main": "./dist/src/index.js",
"types": "./dist/src/index.d.ts",
"directories": {
"src": "src"
},
"files": [
"dist/*",
"package.json",
"!**/*.tsbuildinfo"
],
"scripts": {
"build": "tsc -p tsconfig.build.json",
"check-types": "tsc --noEmit -p ./tsconfig.json",
"clean": "rm -rf dist/",
"format": "prettier --check \"{src,test}/**/*.{js,ts,json}\"",
"format:fix": "prettier --write \"{src,test}/**/*.{js,ts,json}\"",
"lint": "eslint \"{src,test}/**/*.{js,ts,json}\"",
"lint:fix": "pnpm lint --fix",
"test": "vitest run --config vitest.config.ts --passWithNoTests",
"test:cov": "vitest run --config vitest.config.ts --coverage"
},
"dependencies": {
"@grants-stack-indexer/shared": "workspace:*",
"graphql-request": "7.1.0"
}
}
2 changes: 2 additions & 0 deletions packages/indexer-client/src/exceptions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from "./invalidIndexerResponse.exception.js";
export * from "./indexerClientError.exception.js";
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class IndexerClientError extends Error {
constructor(message: string) {
super(`Indexer client error - ${message}`);
this.name = "IndexerClientError";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export class InvalidIndexerResponse extends Error {
constructor(response: string) {
super(`Indexer response is invalid - ${response}`);
this.name = "InvalidIndexerResponse";
}
}
3 changes: 3 additions & 0 deletions packages/indexer-client/src/external.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type { IIndexerClient } from "./internal.js";

export { EnvioIndexerClient } from "./internal.js";
1 change: 1 addition & 0 deletions packages/indexer-client/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./external.js";
1 change: 1 addition & 0 deletions packages/indexer-client/src/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./indexerClient.js";
20 changes: 20 additions & 0 deletions packages/indexer-client/src/interfaces/indexerClient.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { AnyProtocolEvent } from "@grants-stack-indexer/shared";

/**
* Interface for the indexer client
*/
export interface IIndexerClient {
/**
* Get the events by block number and log index from the indexer service
* @param chainId Id of the chain
* @param fromBlock Block number to start fetching events from
* @param logIndex Log index in the block
0xkenj1 marked this conversation as resolved.
Show resolved Hide resolved
* @param limit Limit of events to fetch
*/
getEventsAfterBlockNumberAndLogIndex(
chainId: bigint,
fromBlock: bigint,
logIndex: number,
limit?: number,
): Promise<AnyProtocolEvent[]>;
}
3 changes: 3 additions & 0 deletions packages/indexer-client/src/internal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from "./exceptions/index.js";
export * from "./interfaces/index.js";
export * from "./providers/index.js";
Loading