Skip to main content

Documentation Index

Fetch the complete documentation index at: https://sidiorresearchlabs.mintlify.app/llms.txt

Use this file to discover all available pages before exploring further.

Overview

Understanding transaction statuses helps you build reliable applications on Paxeer Network. This guide explains the lifecycle and finality of transactions.

Transaction Lifecycle

1

Pending

Transaction is in the mempool, waiting to be included in a block.
const tx = await signer.sendTransaction(txData);
console.log('Transaction hash:', tx.hash);
// Status: Pending
2

Mined

Transaction has been included in a block.
const receipt = await tx.wait(1); // Wait for 1 confirmation
console.log('Block number:', receipt.blockNumber);
// Status: Mined (1 confirmation)
3

Confirmed

Transaction has received multiple block confirmations.
const receipt = await tx.wait(3); // Wait for 3 confirmations
// Status: Confirmed (3 confirmations)
4

Finalized

Transaction is considered final and irreversible.
const receipt = await tx.wait(12); // Wait for 12 confirmations
// Status: Finalized

Checking Transaction Status

Using Transaction Hash

import { ethers } from 'ethers';

const provider = new ethers.JsonRpcProvider('https://public-rpc.paxeer.app/rpc');

async function getTransactionStatus(txHash) {
  // Get transaction data
  const tx = await provider.getTransaction(txHash);
  
  if (!tx) {
    return { status: 'not_found' };
  }
  
  // Get transaction receipt
  const receipt = await provider.getTransactionReceipt(txHash);
  
  if (!receipt) {
    return { 
      status: 'pending',
      nonce: tx.nonce,
    };
  }
  
  // Get current block number
  const currentBlock = await provider.getBlockNumber();
  const confirmations = currentBlock - receipt.blockNumber + 1;
  
  return {
    status: receipt.status === 1 ? 'success' : 'failed',
    blockNumber: receipt.blockNumber,
    confirmations: confirmations,
    gasUsed: receipt.gasUsed.toString(),
    effectiveGasPrice: receipt.gasPrice.toString(),
  };
}

// Usage
const status = await getTransactionStatus('0x...');
console.log('Transaction status:', status);

Finality Levels

Paxeer Network has different finality levels based on block confirmations:
LevelConfirmationsTimeUse Case
Unsafe0ImmediateUI updates only
Safe1-2~4 secondsMost dApps
Confirmed3-11~6-22 secondsImportant operations
Finalized12+~24+ secondsCritical/irreversible actions
For high-value or critical operations, wait for at least 12 confirmations before considering the transaction finalized.

Monitoring Transactions

Real-time Status Updates

useTransactionStatus.ts
import { useState, useEffect } from 'react';
import { usePublicClient, useWaitForTransactionReceipt } from 'wagmi';

export function useTransactionStatus(hash?: `0x${string}`) {
  const [status, setStatus] = useState<'pending' | 'success' | 'failed'>('pending');
  const [confirmations, setConfirmations] = useState(0);
  
  const { data: receipt, isLoading } = useWaitForTransactionReceipt({
    hash,
  });
  
  const client = usePublicClient();

  useEffect(() => {
    if (!receipt || !client) return;

    setStatus(receipt.status === 'success' ? 'success' : 'failed');

    // Update confirmations periodically
    const interval = setInterval(async () => {
      const currentBlock = await client.getBlockNumber();
      const confs = currentBlock - receipt.blockNumber + 1n;
      setConfirmations(Number(confs));
    }, 2000);

    return () => clearInterval(interval);
  }, [receipt, client]);

  return { status, confirmations, receipt, isLoading };
}

Usage in React Component

function TransactionTracker({ txHash }) {
  const { status, confirmations, receipt } = useTransactionStatus(txHash);

  return (
    <div>
      <p>Status: {status}</p>
      <p>Confirmations: {confirmations}</p>
      
      {status === 'success' && confirmations >= 12 && (
        <p className="text-green-600">Transaction Finalized</p>
      )}
      
      {status === 'failed' && (
        <p className="text-red-600">Transaction Failed</p>
      )}
    </div>
  );
}

Transaction Receipt Details

async function getDetailedReceipt(txHash) {
  const receipt = await provider.getTransactionReceipt(txHash);
  
  return {
    // Status
    status: receipt.status, // 1 = success, 0 = failed
    
    // Block information
    blockNumber: receipt.blockNumber,
    blockHash: receipt.blockHash,
    
    // Gas usage
    gasUsed: receipt.gasUsed.toString(),
    gasPrice: receipt.gasPrice.toString(),
    effectiveGasPrice: receipt.gasPrice.toString(),
    
    // Fee calculation
    totalFee: (receipt.gasUsed * receipt.gasPrice).toString(),
    
    // Addresses
    from: receipt.from,
    to: receipt.to,
    contractAddress: receipt.contractAddress, // If contract creation
    
    // Transaction details
    transactionHash: receipt.hash,
    transactionIndex: receipt.index,
    
    // Logs (events)
    logs: receipt.logs,
  };
}

Best Practices

Different use cases need different confirmation levels:
// UI update only - show immediately
const receipt = await tx.wait(0);

// Standard dApp - wait for 1 confirmation
const receipt = await tx.wait(1);

// Financial operation - wait for 3+ confirmations
const receipt = await tx.wait(3);

// Critical operation - wait for finality
const receipt = await tx.wait(12);
Although rare, block reorganizations can happen:
async function waitForSafeConfirmation(txHash) {
  let previousBlockHash = null;
  
  while (true) {
    const receipt = await provider.getTransactionReceipt(txHash);
    
    if (receipt && receipt.confirmations >= 3) {
      const block = await provider.getBlock(receipt.blockNumber);
      
      if (previousBlockHash && block.hash !== previousBlockHash) {
        console.warn('Reorg detected! Waiting more...');
        previousBlockHash = block.hash;
        continue;
      }
      
      if (!previousBlockHash) {
        previousBlockHash = block.hash;
      }
      
      // No reorg detected
      return receipt;
    }
    
    await new Promise(resolve => setTimeout(resolve, 2000));
  }
}
Don’t wait indefinitely:
async function waitWithTimeout(txPromise, timeoutMs = 60000) {
  return Promise.race([
    txPromise,
    new Promise((_, reject) =>
      setTimeout(() => reject(new Error('Transaction timeout')), timeoutMs)
    ),
  ]);
}

// Usage
try {
  const receipt = await waitWithTimeout(tx.wait());
  console.log('Success:', receipt.hash);
} catch (error) {
  if (error.message === 'Transaction timeout') {
    console.log('Transaction taking too long, check status manually');
  }
}

Event Monitoring

Watch for transaction events in real-time:
// Listen for pending transactions
provider.on('pending', (txHash) => {
  console.log('New pending transaction:', txHash);
});

// Listen for mined blocks
provider.on('block', async (blockNumber) => {
  console.log('New block mined:', blockNumber);
  
  const block = await provider.getBlock(blockNumber);
  console.log('Transactions in block:', block.transactions.length);
});

// Clean up listeners
provider.removeAllListeners('pending');
provider.removeAllListeners('block');

Resources

Block Explorer

Track transactions on PaxeerScan

Network Status

Check network health

Next Steps

Transaction Fees

Understand fee components

Troubleshooting

Fix transaction issues

Examples

View complete examples