[Blockchain Watcher] (RPC QUERIES) Improve rpc queries (#1131)

* Improve evm block search

* Resolve test

* Add more rpc for base

* Add new rpc for avalanche

* Improve logs

---------

Co-authored-by: julian merlo <julianmerlo@julians-MacBook-Pro.local>
This commit is contained in:
Julian 2024-02-20 13:30:08 -03:00 committed by GitHub
parent 140d05468a
commit bc2d98d889
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 51 additions and 23 deletions

View File

@ -33,7 +33,11 @@
},
"avalanche": {
"network": "mainnet",
"rpcs": ["https://api.avax.network/ext/bc/C/rpc", "https://avalanche.public-rpc.com"]
"rpcs": [
"https://avalanche.blockpi.network/v1/rpc/public",
"https://api.avax.network/ext/bc/C/rpc",
"https://avalanche.public-rpc.com"
]
},
"oasis": {
"network": "mainnet",
@ -89,7 +93,12 @@
},
"base": {
"network": "mainnet",
"rpcs": ["https://base.publicnode.com", "https://mainnet.base.org"]
"rpcs": [
"https://base-pokt.nodies.app",
"https://base.publicnode.com",
"https://mainnet.base.org",
"https://rpc.notadegen.com/base"
]
},
"sui": {
"network": "mainnet",

View File

@ -28,7 +28,7 @@ export class GetEvmLogs {
});
const blockNumbers = new Set(logs.map((log) => log.blockNumber));
const blocks = await this.blockRepo.getBlocks(opts.chain, blockNumbers);
const blocks = await this.blockRepo.getBlocks(opts.chain, blockNumbers, false);
logs.forEach((log) => {
const block = blocks[log.blockHash];
log.blockTime = block.timestamp;

View File

@ -30,8 +30,15 @@ export class GetEvmTransactions {
this.logger.info(
`[${chain}][exec] Processing blocks [fromBlock: ${fromBlock} - toBlock: ${toBlock}]`
);
const blockNumbers: Set<bigint> = new Set();
for (let block = fromBlock; block <= toBlock; block++) {
const evmBlock = await this.blockRepo.getBlock(chain, block, isTransactionsPresent);
blockNumbers.add(block);
}
const evmBlocks = await this.blockRepo.getBlocks(chain, blockNumbers, isTransactionsPresent);
for (const blockKey in evmBlocks) {
const evmBlock = evmBlocks[blockKey];
const transactions = evmBlock.transactions ?? [];
// Only process transactions to the contract address configured
@ -42,9 +49,7 @@ export class GetEvmTransactions {
);
if (transactionsByAddressConfigured.length > 0) {
const hashNumbers = new Set(
transactionsByAddressConfigured.map((transaction) => transaction.hash)
);
const hashNumbers = new Set(transactionsByAddressConfigured.map((tx) => tx.hash));
const receiptTransactions = await this.blockRepo.getTransactionReceipt(chain, hashNumbers);
const filterTransactions = this.filterTransactions(

View File

@ -21,7 +21,11 @@ import { SuiTransactionBlockReceipt } from "./entities/sui";
export interface EvmBlockRepository {
getBlockHeight(chain: string, finality: string): Promise<bigint>;
getBlocks(chain: string, blockNumbers: Set<bigint>): Promise<Record<string, EvmBlock>>;
getBlocks(
chain: string,
blockNumbers: Set<bigint>,
isTransactionsPresent: boolean
): Promise<Record<string, EvmBlock>>;
getFilteredLogs(chain: string, filter: EvmLogFilter): Promise<EvmLog[]>;
getTransactionReceipt(
chain: string,

View File

@ -36,7 +36,7 @@ export const evmRedeemedTransactionFoundMapper = (
if (protocol && protocol.type && protocol.method) {
logger.debug(
`[${transaction.chain}] Transaction info: [hash: ${transaction.hash}][VAA: ${emitterChain}/${emitterAddress}/${sequence}][protocol: ${protocol.type}/${protocol.method}]`
`[${transaction.chain}] Redeemed transaction info: [hash: ${transaction.hash}][VAA: ${emitterChain}/${emitterAddress}/${sequence}][protocol: ${protocol.type}/${protocol.method}]`
);
return {

View File

@ -59,7 +59,7 @@ export const solanaTransferRedeemedMapper = async (
const protocol = findProtocol(instruction, programIdIndex, programId, chain);
logger.debug(
`[${chain}}] Transaction info: [hash: ${txHash}][VAA: ${emitterChain}/${emitterAddress.toString(
`[${chain}}] Redeemed transaction info: [hash: ${txHash}][VAA: ${emitterChain}/${emitterAddress.toString(
"hex"
)}/${sequence}]`
);

View File

@ -21,7 +21,7 @@ export const suiRedeemedTransactionFoundMapper = (
const { emitterAddress, emitterChainId: emitterChain, sequence } = vaa;
logger.info(
`[sui] Redeemed Transfer info: [digest: ${receipt.digest}][VAA: ${emitterChain}/${emitterAddress}/${sequence}]`
`[sui] Redeemed transaction info: [digest: ${receipt.digest}][VAA: ${emitterChain}/${emitterAddress}/${sequence}]`
);
return {

View File

@ -49,7 +49,11 @@ export class EvmJsonRPCBlockRepository implements EvmBlockRepository {
* @param blockNumbers
* @returns a record of block hash -> EvmBlock
*/
async getBlocks(chain: string, blockNumbers: Set<bigint>): Promise<Record<string, EvmBlock>> {
async getBlocks(
chain: string,
blockNumbers: Set<bigint>,
isTransactionsPresent: boolean = false
): Promise<Record<string, EvmBlock>> {
if (!blockNumbers.size) return {};
let combinedResults: ResultBlocks[] = [];
@ -66,7 +70,7 @@ export class EvmJsonRPCBlockRepository implements EvmBlockRepository {
jsonrpc: "2.0",
id: blockNumberStrId,
method: "eth_getBlockByNumber",
params: [blockNumberStrParam, false],
params: [blockNumberStrParam, isTransactionsPresent],
});
}

View File

@ -23,8 +23,14 @@ export class RateLimitedEvmJsonRPCBlockRepository
return this.breaker.fn(() => this.delegate.getBlockHeight(chain, finality)).execute();
}
getBlocks(chain: string, blockNumbers: Set<bigint>): Promise<Record<string, EvmBlock>> {
return this.breaker.fn(() => this.delegate.getBlocks(chain, blockNumbers)).execute();
getBlocks(
chain: string,
blockNumbers: Set<bigint>,
isTransactionsPresent: boolean
): Promise<Record<string, EvmBlock>> {
return this.breaker
.fn(() => this.delegate.getBlocks(chain, blockNumbers, isTransactionsPresent))
.execute();
}
getFilteredLogs(chain: string, filter: EvmLogFilter): Promise<EvmLog[]> {

View File

@ -4,7 +4,7 @@ import { EvmBlockRepository } from "../../../../src/domain/repositories";
import { EvmBlock, EvmLog, ReceiptTransaction } from "../../../../src/domain/entities/evm";
let getTransactionReceipt: jest.SpiedFunction<EvmBlockRepository["getTransactionReceipt"]>;
let getBlockSpy: jest.SpiedFunction<EvmBlockRepository["getBlock"]>;
let getBlocksSpy: jest.SpiedFunction<EvmBlockRepository["getBlocks"]>;
let getEvmTransactions: GetEvmTransactions;
let evmBlockRepo: EvmBlockRepository;
@ -68,7 +68,7 @@ describe("GetEvmTransactions", () => {
// Then
result.then((response) => {
expect(response).toEqual([]);
expect(getBlockSpy).toHaveReturnedTimes(1);
expect(getBlocksSpy).toHaveReturnedTimes(1);
});
});
@ -101,7 +101,7 @@ describe("GetEvmTransactions", () => {
expect(response[0].from).toEqual("0x3ee123456786797000d974cf647e7c347e8fa585");
expect(response[0].to).toEqual("0x3ee18b2214aff97000d974cf647e7c347e8fa585");
expect(getTransactionReceipt).toHaveReturnedTimes(1);
expect(getBlockSpy).toHaveReturnedTimes(1);
expect(getBlocksSpy).toHaveReturnedTimes(1);
});
});
@ -161,7 +161,7 @@ describe("GetEvmTransactions", () => {
expect(response[0].from).toEqual("0x3ee123456786797000d974cf647e7c347e8fa585");
expect(response[0].to).toEqual("0x4cb69fae7e7af841e44e1a1c30af640739378bb2");
expect(getTransactionReceipt).toHaveReturnedTimes(2);
expect(getBlockSpy).toHaveReturnedTimes(2);
expect(getBlocksSpy).toHaveReturnedTimes(1);
});
});
});
@ -192,7 +192,7 @@ const givenEvmBlockRepository = (
const blocksResponse: Record<string, EvmBlock> = {};
const receiptResponse: Record<string, ReceiptTransaction> = {};
if (height) {
for (let index = 0n; index <= (blocksAhead ?? 1n); index++) {
for (let index = height; index <= (blocksAhead ?? 1n); index++) {
logsResponse.push({
blockNumber: height + index,
blockHash: `0x0${index}`,
@ -254,7 +254,7 @@ const givenEvmBlockRepository = (
getBlock: () => Promise.resolve(blocksResponse[`0x01`]),
};
getBlockSpy = jest.spyOn(evmBlockRepo, "getBlock");
getBlocksSpy = jest.spyOn(evmBlockRepo, "getBlocks");
getTransactionReceipt = jest.spyOn(evmBlockRepo, "getTransactionReceipt");
};

View File

@ -1,5 +1,4 @@
import { afterEach, describe, it, expect, jest } from "@jest/globals";
import { setTimeout } from "timers/promises";
import { PollEvmLogsMetadata, PollEvm, PollEvmLogsConfig } from "../../../../src/domain/actions";
import {
EvmBlockRepository,
@ -46,7 +45,8 @@ describe("PollEvm", () => {
() =>
expect(getBlocksSpy).toHaveBeenCalledWith(
"acala",
new Set([currentHeight, currentHeight + 1n])
new Set([currentHeight, currentHeight + 1n]),
false
),
() =>
expect(getLogsSpy).toBeCalledWith("acala", {