Divided evm tx in batchs
This commit is contained in:
parent
ff39767e76
commit
827e34366f
|
@ -30,37 +30,61 @@ 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}]`
|
||||||
);
|
);
|
||||||
for (let block = fromBlock; block <= toBlock; block++) {
|
|
||||||
const evmBlock = await this.blockRepo.getBlock(chain, block, isTransactionsPresent);
|
|
||||||
const transactions = evmBlock.transactions ?? [];
|
|
||||||
|
|
||||||
// Only process transactions to the contract address configured
|
let currentBlock = fromBlock;
|
||||||
const transactionsByAddressConfigured = transactions.filter(
|
const batchSize = 9;
|
||||||
(transaction) =>
|
|
||||||
opts.addresses?.includes(String(transaction.to).toLowerCase()) ||
|
|
||||||
opts.addresses?.includes(String(transaction.from).toLowerCase())
|
|
||||||
);
|
|
||||||
|
|
||||||
if (transactionsByAddressConfigured.length > 0) {
|
while (currentBlock <= toBlock) {
|
||||||
const hashNumbers = new Set(
|
const batchPromises = [];
|
||||||
transactionsByAddressConfigured.map((transaction) => transaction.hash)
|
|
||||||
);
|
|
||||||
const receiptTransactions = await this.blockRepo.getTransactionReceipt(chain, hashNumbers);
|
|
||||||
|
|
||||||
const filterTransactions = this.filterTransactions(
|
for (let i = 0; i < batchSize && currentBlock <= toBlock; i++, currentBlock++) {
|
||||||
opts,
|
// Push each getBlock call as a promise into the batchPromises array
|
||||||
transactionsByAddressConfigured,
|
batchPromises.push(this.blockRepo.getBlock(chain, currentBlock, isTransactionsPresent));
|
||||||
receiptTransactions
|
|
||||||
);
|
|
||||||
|
|
||||||
await this.populateTransaction(
|
|
||||||
opts,
|
|
||||||
evmBlock,
|
|
||||||
receiptTransactions,
|
|
||||||
filterTransactions,
|
|
||||||
populatedTransactions
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const results = await Promise.allSettled(batchPromises);
|
||||||
|
|
||||||
|
results.forEach(async (result, index) => {
|
||||||
|
if (result.status === "fulfilled") {
|
||||||
|
const evmBlock = result.value;
|
||||||
|
const transactions = evmBlock.transactions ?? [];
|
||||||
|
|
||||||
|
// Only process transactions to the contract address configured
|
||||||
|
const transactionsByAddressConfigured = transactions.filter(
|
||||||
|
(transaction) =>
|
||||||
|
opts.addresses?.includes(String(transaction.to).toLowerCase()) ||
|
||||||
|
opts.addresses?.includes(String(transaction.from).toLowerCase())
|
||||||
|
);
|
||||||
|
|
||||||
|
if (transactionsByAddressConfigured.length > 0) {
|
||||||
|
const hashNumbers = new Set(
|
||||||
|
transactionsByAddressConfigured.map((transaction) => transaction.hash)
|
||||||
|
);
|
||||||
|
const receiptTransactions = await this.blockRepo.getTransactionReceipt(
|
||||||
|
chain,
|
||||||
|
hashNumbers
|
||||||
|
);
|
||||||
|
|
||||||
|
const filterTransactions = this.filterTransactions(
|
||||||
|
opts,
|
||||||
|
transactionsByAddressConfigured,
|
||||||
|
receiptTransactions
|
||||||
|
);
|
||||||
|
|
||||||
|
await this.populateTransaction(
|
||||||
|
opts,
|
||||||
|
evmBlock,
|
||||||
|
receiptTransactions,
|
||||||
|
filterTransactions,
|
||||||
|
populatedTransactions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else if (result.status === "rejected") {
|
||||||
|
this.logger.warn(
|
||||||
|
`[${chain}][exec] Invalid range [fromBlock: ${fromBlock} - toBlock: ${toBlock}]`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.info(
|
this.logger.info(
|
||||||
|
@ -71,24 +95,6 @@ export class GetEvmTransactions {
|
||||||
return populatedTransactions;
|
return populatedTransactions;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async populateTransaction(
|
|
||||||
opts: GetEvmOpts,
|
|
||||||
evmBlock: EvmBlock,
|
|
||||||
receiptTransactions: Record<string, ReceiptTransaction>,
|
|
||||||
filterTransactions: EvmTransaction[],
|
|
||||||
populatedTransactions: EvmTransaction[]
|
|
||||||
) {
|
|
||||||
filterTransactions.forEach((transaction) => {
|
|
||||||
transaction.status = receiptTransactions[transaction.hash].status;
|
|
||||||
transaction.timestamp = evmBlock.timestamp;
|
|
||||||
transaction.environment = opts.environment;
|
|
||||||
transaction.chainId = opts.chainId;
|
|
||||||
transaction.chain = opts.chain;
|
|
||||||
transaction.logs = receiptTransactions[transaction.hash].logs;
|
|
||||||
populatedTransactions.push(transaction);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method filter the transactions in base your logs with the topic and address configured in the job
|
* This method filter the transactions in base your logs with the topic and address configured in the job
|
||||||
* For example: Redeemed or MintAndWithdraw transactions
|
* For example: Redeemed or MintAndWithdraw transactions
|
||||||
|
@ -108,6 +114,24 @@ export class GetEvmTransactions {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async populateTransaction(
|
||||||
|
opts: GetEvmOpts,
|
||||||
|
evmBlock: EvmBlock,
|
||||||
|
receiptTransactions: Record<string, ReceiptTransaction>,
|
||||||
|
filterTransactions: EvmTransaction[],
|
||||||
|
populatedTransactions: EvmTransaction[]
|
||||||
|
) {
|
||||||
|
filterTransactions.forEach((transaction) => {
|
||||||
|
transaction.status = receiptTransactions[transaction.hash].status;
|
||||||
|
transaction.timestamp = evmBlock.timestamp;
|
||||||
|
transaction.environment = opts.environment;
|
||||||
|
transaction.chainId = opts.chainId;
|
||||||
|
transaction.chain = opts.chain;
|
||||||
|
transaction.logs = receiptTransactions[transaction.hash].logs;
|
||||||
|
populatedTransactions.push(transaction);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private populateLog(opts: GetEvmOpts, fromBlock: bigint, toBlock: bigint): string {
|
private populateLog(opts: GetEvmOpts, fromBlock: bigint, toBlock: bigint): string {
|
||||||
return `[addresses:${opts.addresses}][topics:${opts.topics}][blocks:${fromBlock} - ${toBlock}]`;
|
return `[addresses:${opts.addresses}][topics:${opts.topics}][blocks:${fromBlock} - ${toBlock}]`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ export class PollSuiTransactions extends RunPollingJob {
|
||||||
protected async preHook(): Promise<void> {
|
protected async preHook(): Promise<void> {
|
||||||
const metadata = await this.metadataRepo.get(this.cfg.id);
|
const metadata = await this.metadataRepo.get(this.cfg.id);
|
||||||
if (metadata) {
|
if (metadata) {
|
||||||
|
this.lastCheckpoint = metadata.lastCursor?.checkpoint;
|
||||||
this.cursor = metadata.lastCursor;
|
this.cursor = metadata.lastCursor;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,23 +49,6 @@ export class PollSuiTransactions extends RunPollingJob {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected report(): void {
|
|
||||||
const labels = {
|
|
||||||
job: this.cfg.id,
|
|
||||||
chain: "sui",
|
|
||||||
commitment: "immediate",
|
|
||||||
};
|
|
||||||
this.statsRepo.count("job_execution", labels);
|
|
||||||
this.statsRepo.measure("polling_cursor", BigInt(this.lastCheckpoint ?? 0), {
|
|
||||||
...labels,
|
|
||||||
type: "max",
|
|
||||||
});
|
|
||||||
this.statsRepo.measure("polling_cursor", BigInt(this.cursor?.checkpoint ?? 0n), {
|
|
||||||
...labels,
|
|
||||||
type: "current",
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected async get(): Promise<any[]> {
|
protected async get(): Promise<any[]> {
|
||||||
this.cursor = await this.getCursor();
|
this.cursor = await this.getCursor();
|
||||||
|
|
||||||
|
@ -119,6 +103,23 @@ export class PollSuiTransactions extends RunPollingJob {
|
||||||
await this.metadataRepo.save(this.cfg.id, { lastCursor: this.cursor });
|
await this.metadataRepo.save(this.cfg.id, { lastCursor: this.cursor });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected report(): void {
|
||||||
|
const labels = {
|
||||||
|
job: this.cfg.id,
|
||||||
|
chain: "sui",
|
||||||
|
commitment: "immediate",
|
||||||
|
};
|
||||||
|
this.statsRepo.count("job_execution", labels);
|
||||||
|
this.statsRepo.measure("polling_cursor", BigInt(this.cursor?.checkpoint ?? 0), {
|
||||||
|
...labels,
|
||||||
|
type: "max",
|
||||||
|
});
|
||||||
|
this.statsRepo.measure("polling_cursor", BigInt(this.lastCheckpoint ?? 0n), {
|
||||||
|
...labels,
|
||||||
|
type: "current",
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class PollSuiTransactionsConfig {
|
export class PollSuiTransactionsConfig {
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
/**
|
||||||
|
* This method divide in batches the object to send, because we have one restriction about how many object send to the endpoint
|
||||||
|
* the maximum is 10 object per request
|
||||||
|
*/
|
||||||
export function divideIntoBatches<T>(set: Set<T>, batchSize = 10): Set<T>[] {
|
export function divideIntoBatches<T>(set: Set<T>, batchSize = 10): Set<T>[] {
|
||||||
const batches: Set<T>[] = [];
|
const batches: Set<T>[] = [];
|
||||||
let batch: any[] = [];
|
let batch: any[] = [];
|
||||||
|
|
|
@ -250,10 +250,6 @@ export class EvmJsonRPCBlockRepository implements EvmBlockRepository {
|
||||||
let results: ResultTransactionReceipt[] = [];
|
let results: ResultTransactionReceipt[] = [];
|
||||||
let id = 1;
|
let id = 1;
|
||||||
|
|
||||||
/**
|
|
||||||
* This method divide in batches the object to send, because we have one restriction about how many object send to the endpoint
|
|
||||||
* the maximum is 10 object per request
|
|
||||||
*/
|
|
||||||
const batches = divideIntoBatches(hashNumbers, TX_BATCH_SIZE);
|
const batches = divideIntoBatches(hashNumbers, TX_BATCH_SIZE);
|
||||||
let combinedResults: ResultTransactionReceipt[] = [];
|
let combinedResults: ResultTransactionReceipt[] = [];
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue