[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:
parent
140d05468a
commit
bc2d98d889
|
@ -33,7 +33,11 @@
|
||||||
},
|
},
|
||||||
"avalanche": {
|
"avalanche": {
|
||||||
"network": "mainnet",
|
"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": {
|
"oasis": {
|
||||||
"network": "mainnet",
|
"network": "mainnet",
|
||||||
|
@ -89,7 +93,12 @@
|
||||||
},
|
},
|
||||||
"base": {
|
"base": {
|
||||||
"network": "mainnet",
|
"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": {
|
"sui": {
|
||||||
"network": "mainnet",
|
"network": "mainnet",
|
||||||
|
|
|
@ -28,7 +28,7 @@ export class GetEvmLogs {
|
||||||
});
|
});
|
||||||
|
|
||||||
const blockNumbers = new Set(logs.map((log) => log.blockNumber));
|
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) => {
|
logs.forEach((log) => {
|
||||||
const block = blocks[log.blockHash];
|
const block = blocks[log.blockHash];
|
||||||
log.blockTime = block.timestamp;
|
log.blockTime = block.timestamp;
|
||||||
|
|
|
@ -30,8 +30,15 @@ export class GetEvmTransactions {
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
`[${chain}][exec] Processing blocks [fromBlock: ${fromBlock} - toBlock: ${toBlock}]`
|
`[${chain}][exec] Processing blocks [fromBlock: ${fromBlock} - toBlock: ${toBlock}]`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const blockNumbers: Set<bigint> = new Set();
|
||||||
for (let block = fromBlock; block <= toBlock; block++) {
|
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 ?? [];
|
const transactions = evmBlock.transactions ?? [];
|
||||||
|
|
||||||
// Only process transactions to the contract address configured
|
// Only process transactions to the contract address configured
|
||||||
|
@ -42,9 +49,7 @@ export class GetEvmTransactions {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (transactionsByAddressConfigured.length > 0) {
|
if (transactionsByAddressConfigured.length > 0) {
|
||||||
const hashNumbers = new Set(
|
const hashNumbers = new Set(transactionsByAddressConfigured.map((tx) => tx.hash));
|
||||||
transactionsByAddressConfigured.map((transaction) => transaction.hash)
|
|
||||||
);
|
|
||||||
const receiptTransactions = await this.blockRepo.getTransactionReceipt(chain, hashNumbers);
|
const receiptTransactions = await this.blockRepo.getTransactionReceipt(chain, hashNumbers);
|
||||||
|
|
||||||
const filterTransactions = this.filterTransactions(
|
const filterTransactions = this.filterTransactions(
|
||||||
|
|
|
@ -21,7 +21,11 @@ import { SuiTransactionBlockReceipt } from "./entities/sui";
|
||||||
|
|
||||||
export interface EvmBlockRepository {
|
export interface EvmBlockRepository {
|
||||||
getBlockHeight(chain: string, finality: string): Promise<bigint>;
|
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[]>;
|
getFilteredLogs(chain: string, filter: EvmLogFilter): Promise<EvmLog[]>;
|
||||||
getTransactionReceipt(
|
getTransactionReceipt(
|
||||||
chain: string,
|
chain: string,
|
||||||
|
|
|
@ -36,7 +36,7 @@ export const evmRedeemedTransactionFoundMapper = (
|
||||||
|
|
||||||
if (protocol && protocol.type && protocol.method) {
|
if (protocol && protocol.type && protocol.method) {
|
||||||
logger.debug(
|
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 {
|
return {
|
||||||
|
|
|
@ -59,7 +59,7 @@ export const solanaTransferRedeemedMapper = async (
|
||||||
const protocol = findProtocol(instruction, programIdIndex, programId, chain);
|
const protocol = findProtocol(instruction, programIdIndex, programId, chain);
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`[${chain}}] Transaction info: [hash: ${txHash}][VAA: ${emitterChain}/${emitterAddress.toString(
|
`[${chain}}] Redeemed transaction info: [hash: ${txHash}][VAA: ${emitterChain}/${emitterAddress.toString(
|
||||||
"hex"
|
"hex"
|
||||||
)}/${sequence}]`
|
)}/${sequence}]`
|
||||||
);
|
);
|
||||||
|
|
|
@ -21,7 +21,7 @@ export const suiRedeemedTransactionFoundMapper = (
|
||||||
const { emitterAddress, emitterChainId: emitterChain, sequence } = vaa;
|
const { emitterAddress, emitterChainId: emitterChain, sequence } = vaa;
|
||||||
|
|
||||||
logger.info(
|
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 {
|
return {
|
||||||
|
|
|
@ -49,7 +49,11 @@ export class EvmJsonRPCBlockRepository implements EvmBlockRepository {
|
||||||
* @param blockNumbers
|
* @param blockNumbers
|
||||||
* @returns a record of block hash -> EvmBlock
|
* @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 {};
|
if (!blockNumbers.size) return {};
|
||||||
|
|
||||||
let combinedResults: ResultBlocks[] = [];
|
let combinedResults: ResultBlocks[] = [];
|
||||||
|
@ -66,7 +70,7 @@ export class EvmJsonRPCBlockRepository implements EvmBlockRepository {
|
||||||
jsonrpc: "2.0",
|
jsonrpc: "2.0",
|
||||||
id: blockNumberStrId,
|
id: blockNumberStrId,
|
||||||
method: "eth_getBlockByNumber",
|
method: "eth_getBlockByNumber",
|
||||||
params: [blockNumberStrParam, false],
|
params: [blockNumberStrParam, isTransactionsPresent],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,8 +23,14 @@ export class RateLimitedEvmJsonRPCBlockRepository
|
||||||
return this.breaker.fn(() => this.delegate.getBlockHeight(chain, finality)).execute();
|
return this.breaker.fn(() => this.delegate.getBlockHeight(chain, finality)).execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
getBlocks(chain: string, blockNumbers: Set<bigint>): Promise<Record<string, EvmBlock>> {
|
getBlocks(
|
||||||
return this.breaker.fn(() => this.delegate.getBlocks(chain, blockNumbers)).execute();
|
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[]> {
|
getFilteredLogs(chain: string, filter: EvmLogFilter): Promise<EvmLog[]> {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import { EvmBlockRepository } from "../../../../src/domain/repositories";
|
||||||
import { EvmBlock, EvmLog, ReceiptTransaction } from "../../../../src/domain/entities/evm";
|
import { EvmBlock, EvmLog, ReceiptTransaction } from "../../../../src/domain/entities/evm";
|
||||||
|
|
||||||
let getTransactionReceipt: jest.SpiedFunction<EvmBlockRepository["getTransactionReceipt"]>;
|
let getTransactionReceipt: jest.SpiedFunction<EvmBlockRepository["getTransactionReceipt"]>;
|
||||||
let getBlockSpy: jest.SpiedFunction<EvmBlockRepository["getBlock"]>;
|
let getBlocksSpy: jest.SpiedFunction<EvmBlockRepository["getBlocks"]>;
|
||||||
|
|
||||||
let getEvmTransactions: GetEvmTransactions;
|
let getEvmTransactions: GetEvmTransactions;
|
||||||
let evmBlockRepo: EvmBlockRepository;
|
let evmBlockRepo: EvmBlockRepository;
|
||||||
|
@ -68,7 +68,7 @@ describe("GetEvmTransactions", () => {
|
||||||
// Then
|
// Then
|
||||||
result.then((response) => {
|
result.then((response) => {
|
||||||
expect(response).toEqual([]);
|
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].from).toEqual("0x3ee123456786797000d974cf647e7c347e8fa585");
|
||||||
expect(response[0].to).toEqual("0x3ee18b2214aff97000d974cf647e7c347e8fa585");
|
expect(response[0].to).toEqual("0x3ee18b2214aff97000d974cf647e7c347e8fa585");
|
||||||
expect(getTransactionReceipt).toHaveReturnedTimes(1);
|
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].from).toEqual("0x3ee123456786797000d974cf647e7c347e8fa585");
|
||||||
expect(response[0].to).toEqual("0x4cb69fae7e7af841e44e1a1c30af640739378bb2");
|
expect(response[0].to).toEqual("0x4cb69fae7e7af841e44e1a1c30af640739378bb2");
|
||||||
expect(getTransactionReceipt).toHaveReturnedTimes(2);
|
expect(getTransactionReceipt).toHaveReturnedTimes(2);
|
||||||
expect(getBlockSpy).toHaveReturnedTimes(2);
|
expect(getBlocksSpy).toHaveReturnedTimes(1);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -192,7 +192,7 @@ const givenEvmBlockRepository = (
|
||||||
const blocksResponse: Record<string, EvmBlock> = {};
|
const blocksResponse: Record<string, EvmBlock> = {};
|
||||||
const receiptResponse: Record<string, ReceiptTransaction> = {};
|
const receiptResponse: Record<string, ReceiptTransaction> = {};
|
||||||
if (height) {
|
if (height) {
|
||||||
for (let index = 0n; index <= (blocksAhead ?? 1n); index++) {
|
for (let index = height; index <= (blocksAhead ?? 1n); index++) {
|
||||||
logsResponse.push({
|
logsResponse.push({
|
||||||
blockNumber: height + index,
|
blockNumber: height + index,
|
||||||
blockHash: `0x0${index}`,
|
blockHash: `0x0${index}`,
|
||||||
|
@ -254,7 +254,7 @@ const givenEvmBlockRepository = (
|
||||||
getBlock: () => Promise.resolve(blocksResponse[`0x01`]),
|
getBlock: () => Promise.resolve(blocksResponse[`0x01`]),
|
||||||
};
|
};
|
||||||
|
|
||||||
getBlockSpy = jest.spyOn(evmBlockRepo, "getBlock");
|
getBlocksSpy = jest.spyOn(evmBlockRepo, "getBlocks");
|
||||||
getTransactionReceipt = jest.spyOn(evmBlockRepo, "getTransactionReceipt");
|
getTransactionReceipt = jest.spyOn(evmBlockRepo, "getTransactionReceipt");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { afterEach, describe, it, expect, jest } from "@jest/globals";
|
import { afterEach, describe, it, expect, jest } from "@jest/globals";
|
||||||
import { setTimeout } from "timers/promises";
|
|
||||||
import { PollEvmLogsMetadata, PollEvm, PollEvmLogsConfig } from "../../../../src/domain/actions";
|
import { PollEvmLogsMetadata, PollEvm, PollEvmLogsConfig } from "../../../../src/domain/actions";
|
||||||
import {
|
import {
|
||||||
EvmBlockRepository,
|
EvmBlockRepository,
|
||||||
|
@ -46,7 +45,8 @@ describe("PollEvm", () => {
|
||||||
() =>
|
() =>
|
||||||
expect(getBlocksSpy).toHaveBeenCalledWith(
|
expect(getBlocksSpy).toHaveBeenCalledWith(
|
||||||
"acala",
|
"acala",
|
||||||
new Set([currentHeight, currentHeight + 1n])
|
new Set([currentHeight, currentHeight + 1n]),
|
||||||
|
false
|
||||||
),
|
),
|
||||||
() =>
|
() =>
|
||||||
expect(getLogsSpy).toBeCalledWith("acala", {
|
expect(getLogsSpy).toBeCalledWith("acala", {
|
||||||
|
|
Loading…
Reference in New Issue