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

eth_getTransactionReceipt

Returns the receipt of a transaction by transaction hash. The receipt is available only for mined transactions.

Parameters

  1. Transaction Hash - DATA, 32 Bytes
    • Hash of a transaction

Returns

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

  • transactionHash - Hash of the transaction
  • transactionIndex - Index position in the block
  • blockHash - Hash of the block containing this transaction
  • blockNumber - Block number containing this transaction
  • from - Address of the sender
  • to - Address of the receiver (null for contract creation)
  • cumulativeGasUsed - Total gas used in the block up to this transaction
  • gasUsed - Gas used by this specific transaction
  • contractAddress - Contract address created (if contract creation)
  • logs - Array of log objects generated by this transaction
  • logsBloom - Bloom filter for the logs
  • status - 1 (success) or 0 (failure)

Request Example

{
"jsonrpc": "2.0",
"method": "eth_getTransactionReceipt",
"params": [
"0xc6ef2fc5426d6ad6fd9e2a26a6b2e2b7e7e5d4f3c8a9b8a7c6d5e4f3b2a1c9d8"
],
"id": 1
}

Implementation Examples

import { JsonRpcProvider } from 'ethers';

const provider = new JsonRpcProvider('https://api-linea-mainnet-archive.n.dwellir.com/YOUR_API_KEY');

// Get transaction receipt
async function getReceipt(txHash) {
const receipt = await provider.getTransactionReceipt(txHash);

if (!receipt) {
console.log('Transaction not yet mined');
return null;
}

return {
status: receipt.status === 1 ? 'Success' : 'Failed',
blockNumber: receipt.blockNumber,
gasUsed: receipt.gasUsed.toString(),
effectiveGasPrice: receipt.effectiveGasPrice?.toString(),
logs: receipt.logs.length,
confirmations: receipt.confirmations
};
}

// Wait for receipt with timeout
async function waitForReceipt(txHash, timeout = 60000) {
const startTime = Date.now();

while (Date.now() - startTime < timeout) {
const receipt = await provider.getTransactionReceipt(txHash);

if (receipt) {
return receipt;
}

// Check every 2 seconds
await new Promise(resolve => setTimeout(resolve, 2000));
}

throw new Error(`Transaction receipt not found after ${timeout}ms`);
}

// Parse receipt logs
async function parseReceiptLogs(txHash, contractABI) {
const receipt = await provider.getTransactionReceipt(txHash);

if (!receipt) {
throw new Error('Receipt not found');
}

const iface = new ethers.Interface(contractABI);
const parsedLogs = [];

for (const log of receipt.logs) {
try {
const parsed = iface.parseLog(log);
parsedLogs.push({
name: parsed.name,
args: parsed.args,
address: log.address,
blockNumber: log.blockNumber
});
} catch (e) {
// Log doesn't match this ABI
}
}

return parsedLogs;
}

// Analyze gas usage
async function analyzeGasUsage(txHash) {
const [receipt, tx, block] = await Promise.all([
provider.getTransactionReceipt(txHash),
provider.getTransaction(txHash),
provider.getBlock('latest')
]);

if (!receipt) {
throw new Error('Receipt not found');
}

const gasPrice = tx.gasPrice || tx.effectiveGasPrice;
const gasUsed = receipt.gasUsed;
const gasLimit = tx.gasLimit;

return {
gasUsed: gasUsed.toString(),
gasLimit: gasLimit.toString(),
gasEfficiency: `${(Number(gasUsed) * 100 / Number(gasLimit)).toFixed(2)}%`,
actualCost: ethers.formatEther(gasUsed * gasPrice),
status: receipt.status === 1 ? 'Success' : 'Failed',
blockGasUsed: block.gasUsed.toString(),
percentOfBlock: `${(Number(gasUsed) * 100 / Number(block.gasUsed)).toFixed(2)}%`
};
}

Common Use Cases

1. Contract Deployment Verification

// Verify contract deployment
async function verifyDeployment(txHash) {
const receipt = await provider.getTransactionReceipt(txHash);

if (!receipt) {
return { status: 'Pending' };
}

if (receipt.status === 0) {
return {
status: 'Failed',
reason: 'Deployment transaction reverted'
};
}

if (!receipt.contractAddress) {
return {
status: 'Failed',
reason: 'Not a contract deployment transaction'
};
}

// Verify contract code exists
const code = await provider.getCode(receipt.contractAddress);

if (code === '0x') {
return {
status: 'Failed',
reason: 'No code at contract address'
};
}

return {
status: 'Success',
contractAddress: receipt.contractAddress,
deploymentBlock: receipt.blockNumber,
gasUsed: receipt.gasUsed.toString()
};
}

2. Event Monitoring

// Monitor specific events from receipt
async function getTransferEvents(txHash) {
const receipt = await provider.getTransactionReceipt(txHash);

if (!receipt) {
throw new Error('Receipt not found');
}

// ERC20 Transfer event signature
const transferTopic = ethers.id('Transfer(address,address,uint256)');

const transfers = receipt.logs
.filter(log => log.topics[0] === transferTopic)
.map(log => ({
from: ethers.getAddress('0x' + log.topics[1].slice(26)),
to: ethers.getAddress('0x' + log.topics[2].slice(26)),
value: BigInt(log.data),
token: log.address,
logIndex: log.logIndex
}));

return transfers;
}

3. Transaction Confirmation Status

// Get detailed confirmation status
async function getConfirmationStatus(txHash) {
const receipt = await provider.getTransactionReceipt(txHash);

if (!receipt) {
return {
status: 'Pending',
confirmed: false
};
}

const currentBlock = await provider.getBlockNumber();
const confirmations = currentBlock - receipt.blockNumber;

// Linea zkEVM finality
const zkFinalityBlocks = 12; // ~2.4 minutes at 12s blocks

return {
status: receipt.status === 1 ? 'Success' : 'Failed',
confirmed: true,
confirmations: confirmations,
finalized: confirmations >= zkFinalityBlocks,
blockNumber: receipt.blockNumber,
currentBlock: currentBlock,
gasUsed: receipt.gasUsed.toString(),
effectiveGasPrice: receipt.effectiveGasPrice?.toString()
};
}

zkEVM-Specific Receipt Features

Linea zkEVM receipts have unique characteristics:

// Analyze zkEVM-specific receipt data
async function analyzeZkEvmReceipt(txHash) {
const receipt = await provider.getTransactionReceipt(txHash);

if (!receipt) {
throw new Error('Receipt not found');
}

// Get block for additional zkEVM data
const block = await provider.getBlock(receipt.blockNumber);

// zkEVM-specific analysis
const zkEvmData = {
// Basic receipt data
transactionHash: receipt.transactionHash,
blockNumber: receipt.blockNumber,
status: receipt.status === 1 ? 'Success' : 'Failed',

// Gas analysis for zkEVM
gasUsed: receipt.gasUsed.toString(),
cumulativeGasUsed: receipt.cumulativeGasUsed.toString(),
gasEfficiency: `${(Number(receipt.gasUsed) * 100 / Number(receipt.cumulativeGasUsed)).toFixed(2)}%`,

// zkEVM batch information (if available)
zkBatch: {
timestamp: block.timestamp,
transactionsInBlock: block.transactions.length,
blockGasUsed: block.gasUsed.toString()
},

// Finality status
finality: {
l2Finalized: true, // zkProofs provide instant L2 finality
confirmations: await provider.getBlockNumber() - receipt.blockNumber
}
};

return zkEvmData;
}

Error Handling

// Robust receipt fetching with retry
async function getReceiptWithRetry(txHash, maxRetries = 60) {
for (let i = 0; i < maxRetries; i++) {
try {
const receipt = await provider.getTransactionReceipt(txHash);

if (receipt) {
// Validate receipt structure
if (!receipt.blockNumber || !receipt.transactionHash) {
throw new Error('Invalid receipt structure');
}

return receipt;
}

// Transaction might still be pending
const tx = await provider.getTransaction(txHash);

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

// Wait before retry (longer wait as attempts increase)
await new Promise(resolve =>
setTimeout(resolve, Math.min(2000 * (i + 1), 10000))
);

} catch (error) {
if (error.message.includes('not found') && i === maxRetries - 1) {
throw new Error(`Transaction ${txHash} not found after ${maxRetries} attempts`);
}

if (i === maxRetries - 1) {
throw error;
}
}
}

return null;
}

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