⚠️Blast API (blastapi.io) ends Oct 31. Migrate to Dwellir and skip the expensive compute units.
Switch Today →
Skip to main content

eth_getTransactionByHash

Returns information about a transaction requested by transaction hash. Essential for tracking transaction status and details.

When to Use This Method

eth_getTransactionByHash is crucial for:

  • Transaction Tracking - Monitor transaction status after submission
  • Payment Verification - Confirm payment details and recipients
  • Transaction Explorers - Build transaction detail pages
  • Debugging - Investigate failed or stuck transactions

Parameters

  1. Transaction Hash - DATA, 32 Bytes
    • Hash of the transaction to retrieve
    • Format: 0x followed by 64 hexadecimal characters
{
"jsonrpc": "2.0",
"method": "eth_getTransactionByHash",
"params": [
"0x88df016429689c079f3b2f6ad39fa052532c56795b733da78a91ebe6a713944b"
],
"id": 1
}

Returns

Object - Transaction object, or null when no transaction was found:

  • blockHash - Hash of the block containing this transaction
  • blockNumber - Block number containing this transaction
  • from - Address of the sender
  • gas - Gas provided by the sender
  • gasPrice - Gas price in wei
  • maxFeePerGas - Maximum fee per gas (EIP-1559)
  • maxPriorityFeePerGas - Maximum priority fee per gas (EIP-1559)
  • hash - Transaction hash
  • input - Input data sent with transaction
  • nonce - Number of transactions from sender
  • to - Receiver address (null for contract creation)
  • transactionIndex - Position in the block
  • value - Value transferred in wei
  • type - Transaction type (0x0, 0x1, 0x2)
  • v, r, s - Signature values

Implementation Examples

import { JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider('https://api-zora-mainnet.n.dwellir.com/2307f636-d01d-4f85-ba5e-514ff37069f5');

// Transaction tracking system
class TransactionTracker {
constructor(provider) {
this.provider = provider;
this.cache = new Map();
}

async getTransaction(txHash) {
// Check cache first
if (this.cache.has(txHash)) {
const cached = this.cache.get(txHash);
if (Date.now() - cached.timestamp < 5000) {
return cached.data;
}
}

// Fetch transaction
const tx = await this.provider.getTransaction(txHash);

if (!tx) {
return { status: 'not_found' };
}

// Cache the result
const result = {
hash: tx.hash,
from: tx.from,
to: tx.to,
value: tx.value.toString(),
gasPrice: tx.gasPrice?.toString(),
gasLimit: tx.gasLimit.toString(),
nonce: tx.nonce,
data: tx.data,
blockNumber: tx.blockNumber,
blockHash: tx.blockHash,
confirmations: tx.confirmations,
status: tx.blockNumber ? 'confirmed' : 'pending',
type: tx.type,
maxFeePerGas: tx.maxFeePerGas?.toString(),
maxPriorityFeePerGas: tx.maxPriorityFeePerGas?.toString()
};

this.cache.set(txHash, {
data: result,
timestamp: Date.now()
});

return result;
}

async waitForConfirmation(txHash, confirmations = 1, timeout = 60000) {
const startTime = Date.now();

while (Date.now() - startTime < timeout) {
const tx = await this.getTransaction(txHash);

if (tx.status === 'not_found') {
await new Promise(resolve => setTimeout(resolve, 2000));
continue;
}

if (tx.confirmations >= confirmations) {
return tx;
}

await new Promise(resolve => setTimeout(resolve, 2000));
}

throw new Error('Transaction confirmation timeout');
}

async getTransactionWithReceipt(txHash) {
const [tx, receipt] = await Promise.all([
this.getTransaction(txHash),
this.provider.getTransactionReceipt(txHash)
]);

if (tx.status === 'not_found') {
return tx;
}

return {
...tx,
receipt: receipt ? {
status: receipt.status,
gasUsed: receipt.gasUsed.toString(),
effectiveGasPrice: receipt.effectiveGasPrice?.toString(),
logs: receipt.logs.length,
contractAddress: receipt.contractAddress
} : null
};
}
}

// Usage example
async function trackPayment(txHash) {
const tracker = new TransactionTracker(provider);

console.log('Tracking transaction:', txHash);

// Get initial status
const tx = await tracker.getTransaction(txHash);
console.log('Status:', tx.status);

if (tx.status === 'pending') {
console.log('Waiting for confirmation...');
const confirmed = await tracker.waitForConfirmation(txHash, 2);
console.log('Confirmed in block:', confirmed.blockNumber);
}

// Get full details with receipt
const fullDetails = await tracker.getTransactionWithReceipt(txHash);
console.log('Transaction details:', fullDetails);

return fullDetails;
}

Common Use Cases

1. Payment Verification System

// Verify payment received
async function verifyPayment(txHash, expectedAmount, expectedRecipient) {
const tx = await provider.getTransaction(txHash);

if (!tx) {
return { valid: false, reason: 'Transaction not found' };
}

// Check recipient
if (tx.to?.toLowerCase() !== expectedRecipient.toLowerCase()) {
return { valid: false, reason: 'Wrong recipient' };
}

// Check amount
if (tx.value.toString() !== expectedAmount) {
return { valid: false, reason: 'Wrong amount' };
}

// Check confirmations
if (!tx.blockNumber) {
return { valid: false, reason: 'Transaction pending' };
}

const receipt = await provider.getTransactionReceipt(txHash);
if (receipt.status === 0) {
return { valid: false, reason: 'Transaction failed' };
}

return {
valid: true,
confirmations: tx.confirmations,
blockNumber: tx.blockNumber
};
}

2. Transaction History Builder

// Build transaction history for address
async function getAddressTransactions(address, txHashes) {
const transactions = [];

for (const hash of txHashes) {
const tx = await provider.getTransaction(hash);

if (!tx) continue;

const isIncoming = tx.to?.toLowerCase() === address.toLowerCase();
const isOutgoing = tx.from.toLowerCase() === address.toLowerCase();

transactions.push({
hash: tx.hash,
type: isIncoming ? 'incoming' : 'outgoing',
from: tx.from,
to: tx.to,
value: ethers.formatEther(tx.value),
timestamp: tx.blockNumber ?
(await provider.getBlock(tx.blockNumber)).timestamp : null,
status: tx.blockNumber ? 'confirmed' : 'pending',
gasPrice: tx.gasPrice ? ethers.formatGwei(tx.gasPrice) : null,
confirmations: tx.confirmations
});
}

return transactions.sort((a, b) => b.timestamp - a.timestamp);
}

3. Gas Price Analysis

// Analyze gas usage patterns
async function analyzeGasUsage(txHash) {
const tx = await provider.getTransaction(txHash);

if (!tx) {
throw new Error('Transaction not found');
}

const receipt = await provider.getTransactionReceipt(txHash);
const block = await provider.getBlock(tx.blockNumber);

return {
txHash: tx.hash,
gasLimit: tx.gasLimit.toString(),
gasUsed: receipt ? receipt.gasUsed.toString() : null,
gasPrice: tx.gasPrice ? ethers.formatGwei(tx.gasPrice) : null,
maxFeePerGas: tx.maxFeePerGas ? ethers.formatGwei(tx.maxFeePerGas) : null,
maxPriorityFee: tx.maxPriorityFeePerGas ?
ethers.formatGwei(tx.maxPriorityFeePerGas) : null,
baseFee: block.baseFeePerGas ?
ethers.formatGwei(block.baseFeePerGas) : null,
efficiency: receipt ?
((Number(receipt.gasUsed) / Number(tx.gasLimit)) * 100).toFixed(2) + '%' : null,
totalCost: receipt && tx.gasPrice ?
ethers.formatEther(receipt.gasUsed * tx.gasPrice) : null
};
}

Error Handling

Error ScenarioDescriptionSolution
null responseTransaction not foundCheck hash validity, wait for propagation
Network timeoutRPC connection issuesRetry with exponential backoff
Invalid hashMalformed transaction hashValidate hash format (66 characters)
async function safeGetTransaction(txHash, retries = 3) {
// Validate hash format
if (!/^0x[a-fA-F0-9]{64}$/.test(txHash)) {
throw new Error('Invalid transaction hash format');
}

for (let i = 0; i < retries; i++) {
try {
const tx = await provider.getTransaction(txHash);

if (tx) {
return tx;
}

// Wait before retry if not found
if (i < retries - 1) {
await new Promise(resolve => setTimeout(resolve, 2000 * (i + 1)));
}
} catch (error) {
if (i === retries - 1) {
throw error;
}
await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1)));
}
}

return null;
}

Need help? Contact our support team or check the Zora documentation.