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-unichain-mainnet.n.dwellir.com/YOUR_API_KEY');

// 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,
unichainFee: block.unichainFeePerGas ?
ethers.formatGwei(block.unichainFeePerGas) : 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 Unichain documentation.