@elephant-xyz/cli
Version:
CLI tool for Elephant Network
111 lines • 4.54 kB
JavaScript
import { ethers } from 'ethers';
import { logger } from '../utils/logger.js';
export class TransactionStatusService {
provider;
pollingInterval = 2000; // 2 seconds
maxPollingTime = 15 * 60 * 1000; // 15 minutes
constructor(rpcUrl) {
this.provider = new ethers.JsonRpcProvider(rpcUrl);
logger.technical(`Transaction status service initialized with RPC: ${rpcUrl}`);
}
/**
* Wait for a transaction to be confirmed on the blockchain
*/
async waitForTransaction(txHash, timeout = this.maxPollingTime) {
const startTime = Date.now();
logger.info(`Waiting for transaction ${txHash} to be confirmed...`);
while (Date.now() - startTime < timeout) {
try {
// Check if transaction exists
const tx = await this.provider.getTransaction(txHash);
if (!tx) {
// Transaction not found yet, continue polling
await new Promise((resolve) => setTimeout(resolve, this.pollingInterval));
continue;
}
// Transaction found, wait for receipt
const receipt = await this.provider.getTransactionReceipt(txHash);
if (receipt) {
const status = {
hash: txHash,
status: receipt.status === 1 ? 'success' : 'failed',
blockNumber: receipt.blockNumber,
gasUsed: receipt.gasUsed.toString(),
};
if (receipt.status === 0) {
status.error = 'Transaction reverted by EVM';
}
logger.info(`Transaction ${txHash} confirmed in block ${receipt.blockNumber} with status: ${status.status}`);
return status;
}
// Transaction exists but no receipt yet, continue polling
await new Promise((resolve) => setTimeout(resolve, this.pollingInterval));
}
catch (error) {
logger.warn(`Error checking transaction status: ${error instanceof Error ? error.message : String(error)}`);
// Continue polling on error
await new Promise((resolve) => setTimeout(resolve, this.pollingInterval));
}
}
// Timeout reached
logger.error(`Transaction ${txHash} confirmation timeout after ${timeout / 1000}s`);
return {
hash: txHash,
status: 'pending',
error: `Transaction confirmation timeout after ${timeout / 1000}s`,
};
}
/**
* Wait for multiple transactions in parallel
*/
async waitForMultipleTransactions(txHashes, onProgress) {
logger.info(`Waiting for ${txHashes.length} transactions to be confirmed...`);
let completed = 0;
const results = await Promise.all(txHashes.map(async (txHash) => {
const status = await this.waitForTransaction(txHash);
completed++;
if (onProgress) {
onProgress(completed, txHashes.length);
}
return status;
}));
return results;
}
/**
* Get current transaction status without waiting
*/
async getTransactionStatus(txHash) {
try {
const receipt = await this.provider.getTransactionReceipt(txHash);
if (receipt) {
return {
hash: txHash,
status: receipt.status === 1 ? 'success' : 'failed',
blockNumber: receipt.blockNumber,
gasUsed: receipt.gasUsed.toString(),
};
}
const tx = await this.provider.getTransaction(txHash);
if (tx) {
return {
hash: txHash,
status: 'pending',
};
}
return {
hash: txHash,
status: 'pending',
error: 'Transaction not found on chain',
};
}
catch (error) {
logger.warn(`Error checking transaction ${txHash}: ${error instanceof Error ? error.message : String(error)}`);
return {
hash: txHash,
status: 'pending',
error: error instanceof Error ? error.message : String(error),
};
}
}
}
//# sourceMappingURL=transaction-status.service.js.map