Skip to content

Commit 064c661

Browse files
0xkenj1thelostone-mc0xnigir1
authored
feat: hedera (#74)
## Description - Add hedera to indexed chains - Add more docs about adding new chain - Add more decimals for amounts in usd on the db ## Checklist before requesting a review - [x] I have conducted a self-review of my code. - [x] I have conducted a QA. - [x] If it is a core feature, I have included comprehensive tests. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **Documentation** - Added detailed step-by-step guides for integrating new blockchains and tokens. - Expanded setup instructions with additional environment configuration details. - **New Features** - Introduced support for a new blockchain network and HBAR token pricing. - Increased currency precision for more accurate financial calculations. - Enhanced validation to ensure only supported networks are processed. - **Tests** - Included new test scenarios to verify proper error handling for unsupported chains. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: Aditya Anand M C <[email protected]> Co-authored-by: nigiri <[email protected]>
1 parent f80492e commit 064c661

File tree

14 files changed

+257
-101
lines changed

14 files changed

+257
-101
lines changed

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,13 @@ http://localhost:8082/
112112

113113
Use the default password: `my-admin-secret`.
114114

115+
## To add a new chain
116+
117+
1. On `indexer` package add the chain to `config.yaml` (refer to : [[How to add a new chain](apps/indexer/README.md)] )
118+
2. On `shared` package modify `tokens.ts` and add the tokens you will search price for (Refer to : [[How to add a new token](apps/shared/README.md)] )
119+
3. Wait until the new chain is fully indexed
120+
4. Run bootstrap pricing and metadata scripts (refer to: [[How to run bootstrap for specific chain](scripts/bootstrap/README.md)] )
121+
115122
## Contributing
116123

117124
Wonderland is a team of top Web3 researchers, developers, and operators who believe that the future needs to be open-source, permissionless, and decentralized.

apps/indexer/README.md

+21
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,27 @@ Create a handler for the new event. This handler is essential for ensuring the e
4343

4444
After making the necessary changes, redeploy your environment to apply the updates.
4545

46+
## Adding a new chain
47+
48+
### Step 1: Add the Chain to `config.yaml`
49+
50+
Example:
51+
Use your values for the chain and the contracts you want to index.
52+
53+
```yaml
54+
- id: 1 # ethereum
55+
start_block: 17423042
56+
rpc_url: https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID
57+
contracts:
58+
- name: Registry
59+
address:
60+
- 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
61+
- name: Strategy
62+
- name: Allo
63+
address:
64+
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
65+
```
66+
4667
## 🔍 Notes
4768
4869
Ensure each event is properly handled and thoroughly tested before redeploying the environment to prevent issues in the indexing process.

apps/indexer/config.yaml

+108-89
Original file line numberDiff line numberDiff line change
@@ -144,82 +144,82 @@ networks:
144144
address:
145145
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
146146

147-
- id: 250 # fantom
148-
start_block: 77624278
149-
contracts:
150-
- name: Registry
151-
address:
152-
- 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
153-
- name: Strategy
154-
- name: Allo
155-
address:
156-
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
157-
158-
- id: 42161 # arbitrum
159-
start_block: 146489425
160-
contracts:
161-
- name: Registry
162-
address:
163-
- 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
164-
- name: Strategy
165-
- name: Allo
166-
address:
167-
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
168-
169-
- id: 137 # polygon
170-
start_block: 49466006
171-
contracts:
172-
- name: Registry
173-
address:
174-
- 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
175-
- name: Strategy
176-
- name: Allo
177-
address:
178-
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
179-
180-
- id: 8453 # base
181-
start_block: 6083365
182-
contracts:
183-
- name: Registry
184-
address:
185-
- 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
186-
- name: Strategy
187-
- name: Allo
188-
address:
189-
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
190-
191-
- id: 324 # zksync-era-mainnet
192-
start_block: 31154341
193-
contracts:
194-
- name: Registry
195-
address:
196-
- 0xaa376Ef759c1f5A8b0B5a1e2FEC5C23f3bF30246
197-
- name: Strategy
198-
- name: Allo
199-
address:
200-
- 0x9D1D1BF2835935C291C0f5228c86d5C4e235A249
201-
202-
- id: 43114 # avalanche
203-
start_block: 34540051
204-
contracts:
205-
- name: Registry
206-
address:
207-
- 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
208-
- name: Strategy
209-
- name: Allo
210-
address:
211-
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
212-
213-
- id: 534352 # scroll
214-
start_block: 2683205
215-
contracts:
216-
- name: Registry
217-
address:
218-
- 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
219-
- name: Strategy
220-
- name: Allo
221-
address:
222-
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
147+
# - id: 250 # fantom
148+
# start_block: 77624278
149+
# contracts:
150+
# - name: Registry
151+
# address:
152+
# - 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
153+
# - name: Strategy
154+
# - name: Allo
155+
# address:
156+
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
157+
158+
# - id: 42161 # arbitrum
159+
# start_block: 146489425
160+
# contracts:
161+
# - name: Registry
162+
# address:
163+
# - 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
164+
# - name: Strategy
165+
# - name: Allo
166+
# address:
167+
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
168+
169+
# - id: 137 # polygon
170+
# start_block: 49466006
171+
# contracts:
172+
# - name: Registry
173+
# address:
174+
# - 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
175+
# - name: Strategy
176+
# - name: Allo
177+
# address:
178+
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
179+
180+
# - id: 8453 # base
181+
# start_block: 6083365
182+
# contracts:
183+
# - name: Registry
184+
# address:
185+
# - 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
186+
# - name: Strategy
187+
# - name: Allo
188+
# address:
189+
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
190+
191+
# - id: 324 # zksync-era-mainnet
192+
# start_block: 31154341
193+
# contracts:
194+
# - name: Registry
195+
# address:
196+
# - 0xaa376Ef759c1f5A8b0B5a1e2FEC5C23f3bF30246
197+
# - name: Strategy
198+
# - name: Allo
199+
# address:
200+
# - 0x9D1D1BF2835935C291C0f5228c86d5C4e235A249
201+
202+
# - id: 43114 # avalanche
203+
# start_block: 34540051
204+
# contracts:
205+
# - name: Registry
206+
# address:
207+
# - 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
208+
# - name: Strategy
209+
# - name: Allo
210+
# address:
211+
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
212+
213+
# - id: 534352 # scroll
214+
# start_block: 2683205
215+
# contracts:
216+
# - name: Registry
217+
# address:
218+
# - 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
219+
# - name: Strategy
220+
# - name: Allo
221+
# address:
222+
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
223223

224224
# - id: 1329 # sei-mainnet
225225
# rpc_config:
@@ -234,19 +234,38 @@ networks:
234234
# address:
235235
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
236236

237-
- id: 42220 # celo-mainnet
238-
start_block: 22257475
239-
contracts:
240-
- name: Registry
241-
address:
242-
- 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
243-
- name: Strategy
244-
- name: Allo
245-
address:
246-
- 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
247-
248-
- id: 42 # lukso-mainnet
249-
start_block: 2400000
237+
# - id: 42220 # celo-mainnet
238+
# start_block: 22257475
239+
# contracts:
240+
# - name: Registry
241+
# address:
242+
# - 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
243+
# - name: Strategy
244+
# - name: Allo
245+
# address:
246+
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
247+
248+
# - id: 42 # lukso-mainnet
249+
# start_block: 2400000
250+
# contracts:
251+
# - name: Registry
252+
# address:
253+
# - 0x4AAcca72145e1dF2aeC137E1f3C5E3D75DB8b5f3
254+
# - name: Strategy
255+
# - name: Allo
256+
# address:
257+
# - 0x1133eA7Af70876e64665ecD07C0A0476d09465a1
258+
259+
- id: 295 # hedera-mainnet
260+
rpc_config:
261+
url: https://mainnet.hashio.io/api
262+
initial_block_interval: 1000 # Number of blocks to request initially
263+
backoff_multiplicative: 0 # Factor to reduce batch size on error
264+
acceleration_additive: 0 # Increase batch size if no errors
265+
interval_ceiling: 1000 # Maximum blocks per request
266+
backoff_millis: 1000 # Wait time before retrying in milliseconds
267+
query_timeout_millis: 20000 # Timeout for RPC requests in milliseconds
268+
start_block: 75239000
250269
contracts:
251270
- name: Registry
252271
address:
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./invalidChainId.exception.js";
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export class InvalidChainId extends Error {
2+
constructor(chainId: number) {
3+
super(`Chain ${chainId} not found`);
4+
this.name = "InvalidChainId";
5+
}
6+
}

apps/processing/src/services/processing.service.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import { optimism } from "viem/chains";
1+
import { Chain, extractChain } from "viem";
2+
import * as viemChains from "viem/chains";
23

34
import { EvmProvider } from "@grants-stack-indexer/chain-providers";
45
import {
@@ -11,6 +12,7 @@ import {
1112
import { ChainId, ILogger } from "@grants-stack-indexer/shared";
1213

1314
import { Environment } from "../config/env.js";
15+
import { InvalidChainId } from "../exceptions/index.js";
1416
import { SharedDependencies, SharedDependenciesService } from "./index.js";
1517

1618
/**
@@ -63,9 +65,18 @@ export class ProcessingService {
6365
const strategyRegistry = new DatabaseStrategyRegistry(logger, strategyRegistryRepository);
6466
const eventsRegistry = new DatabaseEventRegistry(logger, eventRegistryRepository);
6567

68+
const viemChainsArray = Object.values(viemChains) as Chain[];
69+
6670
for (const chain of chains) {
6771
// Initialize EVM provider
68-
const evmProvider = new EvmProvider(chain.rpcUrls, optimism, logger);
72+
const viemChain = extractChain({
73+
chains: viemChainsArray,
74+
id: chain.id,
75+
});
76+
if (!viemChain) {
77+
throw new InvalidChainId(chain.id);
78+
}
79+
const evmProvider = new EvmProvider(chain.rpcUrls, viemChain, logger);
6980

7081
const cachedStrategyRegistry = await InMemoryCachedStrategyRegistry.initialize(
7182
logger,

apps/processing/test/unit/processing.service.spec.ts

+26-3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
} from "@grants-stack-indexer/data-flow";
1111

1212
import type { Environment } from "../../src/config/env.js";
13+
import { InvalidChainId } from "../../src/exceptions/index.js";
1314
import { ProcessingService } from "../../src/services/processing.service.js";
1415

1516
vi.mock("../../src/services/sharedDependencies.service.js", () => ({
@@ -91,7 +92,7 @@ describe("ProcessingService", () => {
9192
fetchDelayMs: 1000,
9293
},
9394
{
94-
id: 2,
95+
id: 10,
9596
rpcUrls: ["http://localhost:8546"],
9697
name: "Chain 2",
9798
fetchLimit: 200,
@@ -154,8 +155,14 @@ describe("ProcessingService", () => {
154155
expect.any(AbortSignal),
155156
expect.any(AbortSignal),
156157
]);
157-
expect(logSpy).toHaveBeenNthCalledWith(2, "Starting orchestrator for chain 1...");
158-
expect(logSpy).toHaveBeenNthCalledWith(3, "Starting orchestrator for chain 2...");
158+
expect(logSpy).toHaveBeenNthCalledWith(
159+
2,
160+
`Starting orchestrator for chain ${mockEnv.CHAINS[0]?.id}...`,
161+
);
162+
expect(logSpy).toHaveBeenNthCalledWith(
163+
3,
164+
`Starting orchestrator for chain ${mockEnv.CHAINS[1]?.id}...`,
165+
);
159166

160167
// Simulate SIGINT
161168
process.emit("SIGINT");
@@ -201,6 +208,22 @@ describe("ProcessingService", () => {
201208

202209
expect(logSpy).toHaveBeenCalledWith(`Error releasing resources: ${mockError}`);
203210
});
211+
it("throws an error if the chain is not supported", async () => {
212+
const unsupportedChain = {
213+
id: 2,
214+
rpcUrls: ["http://localhost:8546"],
215+
name: "Chain 2",
216+
fetchLimit: 200,
217+
fetchDelayMs: 2000,
218+
};
219+
const env = {
220+
...mockEnv,
221+
CHAINS: [unsupportedChain],
222+
};
223+
await expect(ProcessingService.initialize(env as Environment)).rejects.toThrow(
224+
InvalidChainId,
225+
);
226+
});
204227
});
205228

206229
describe("retroactiveProcessing", () => {

packages/pricing/src/providers/coingecko.provider.ts

+1
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ const TokenMapping: { [key: string]: CoingeckoTokenId | undefined } = {
5959
AVAX: "avalanche-2" as CoingeckoTokenId,
6060
// MTK: undefined,
6161
WSEI: "wrapped-sei" as CoingeckoTokenId,
62+
HBAR: "hedera-hashgraph" as CoingeckoTokenId,
6263
};
6364

6465
// sometimes coingecko returns no prices for 1 hour range, 2 hours works better

packages/pricing/src/types/coingecko.types.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ export type CoingeckoSupportedChainId =
1111
| 1329
1212
| 42
1313
| 42220
14-
| 1088;
14+
| 1088
15+
| 295;
1516

1617
export type CoingeckoTokenId = Branded<string, "CoingeckoTokenId">;
1718
export type CoingeckoPlatformId = Branded<string, "CoingeckoPlatformId">;

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

+1
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ export class PoolCreatedHandler implements IEventHandler<"Allo", "PoolCreated">
4949
round?: unknown;
5050
application?: unknown;
5151
}>(metadataPointer);
52+
// TODO: this might not work for other gitcoin strategies like retro funding
5253
const parsedRoundMetadata = RoundMetadataSchema.safeParse(metadata?.round);
5354

5455
const checksummedTokenAddress = getAddress(tokenAddress);

0 commit comments

Comments
 (0)