Docs

sui_getTransactionBlock - Get Executed T...

Get comprehensive transaction details on Sui blockchain using sui_getTransactionBlock RPC method. Access transaction data, effects, events, and execution results with Dwellir's high-performance Sui infrastructure.

Retrieves comprehensive information about an executed transaction on the Sui blockchain, including transaction data, effects, events, and execution results.

Overview

The sui_getTransactionBlock method is essential for analyzing executed transactions on Sui. It provides detailed information about transaction inputs, outputs, gas usage, events emitted, and the overall execution status. This method is crucial for transaction monitoring, debugging, and building analytical tools.

Code Examples

Common Use Cases

1. Transaction Status Verification

JavaScript
async function checkTransactionStatus(digest) {
  const txn = await client.getTransactionBlock({
    digest: digest,
    options: { showEffects: true }
  });
  
  const status = txn.effects?.status?.status;
  const successful = status === 'success';
  
  console.log(`Transaction ${digest}: ${status}`);
  
  if (!successful) {
    console.error('Transaction failed:', txn.effects?.status?.error);
  }
  
  return successful;
}

2. Gas Usage Analysis

JavaScript
async function analyzeGasUsage(digest) {
  const txn = await client.getTransactionBlock({
    digest: digest,
    options: { showEffects: true }
  });
  
  const gasUsed = txn.effects?.gasUsed;
  if (gasUsed) {
    const totalGas = parseInt(gasUsed.computationCost) + 
                    parseInt(gasUsed.storageCost) - 
                    parseInt(gasUsed.storageRebate);
    
    console.log('Gas Analysis:', {
      computation: gasUsed.computationCost,
      storage: gasUsed.storageCost,
      rebate: gasUsed.storageRebate,
      total: totalGas,
      totalInSUI: totalGas / 1_000_000_000
    });
  }
}

3. Event Processing

JavaScript
async function processTransactionEvents(digest) {
  const txn = await client.getTransactionBlock({
    digest: digest,
    options: { showEvents: true }
  });
  
  const events = txn.events || [];
  
  for (const event of events) {
    console.log('Event:', {
      type: event.type,
      sender: event.sender,
      packageId: event.packageId,
      module: event.transactionModule,
      data: event.parsedJson
    });
    
    // Handle specific event types
    if (event.type.includes('Transfer')) {
      console.log('Transfer event detected');
    } else if (event.type.includes('Mint')) {
      console.log('Mint event detected');
    }
  }
}

4. Object Change Tracking

JavaScript
async function trackObjectChanges(digest) {
  const txn = await client.getTransactionBlock({
    digest: digest,
    options: { showObjectChanges: true }
  });
  
  const changes = txn.objectChanges || [];
  const changesByType = {
    created: [],
    mutated: [],
    deleted: [],
    wrapped: [],
    published: []
  };
  
  changes.forEach(change => {
    if (changesByType[change.type]) {
      changesByType[change.type].push(change);
    }
  });
  
  console.log('Object Changes Summary:', {
    created: changesByType.created.length,
    mutated: changesByType.mutated.length,
    deleted: changesByType.deleted.length,
    wrapped: changesByType.wrapped.length,
    published: changesByType.published.length
  });
  
  return changesByType;
}

Transaction Types and Patterns

Programmable Transaction Blocks

JavaScript
function analyzeProgrammableTransaction(txn) {
  const transaction = txn.transaction?.data?.transaction;
  
  if (transaction?.kind === 'ProgrammableTransaction') {
    console.log('Programmable Transaction:', {
      inputCount: transaction.inputs?.length || 0,
      commandCount: transaction.transactions?.length || 0,
      commands: transaction.transactions?.map(cmd => Object.keys(cmd)[0])
    });
    
    // Analyze specific commands
    transaction.transactions?.forEach((cmd, index) => {
      const commandType = Object.keys(cmd)[0];
      console.log(`Command ${index}: ${commandType}`);
      
      switch (commandType) {
        case 'TransferObjects':
          console.log('  - Transfer operation detected');
          break;
        case 'MoveCall':
          console.log('  - Function call detected');
          break;
        case 'MakeMoveVec':
          console.log('  - Vector creation detected');
          break;
        case 'SplitCoins':
          console.log('  - Coin splitting detected');
          break;
        case 'MergeCoins':
          console.log('  - Coin merging detected');
          break;
      }
    });
  }
}

Balance Change Analysis

JavaScript
async function analyzeBalanceChanges(digest) {
  const txn = await client.getTransactionBlock({
    digest: digest,
    options: { showBalanceChanges: true }
  });
  
  const balanceChanges = txn.balanceChanges || [];
  const changesByAddress = {};
  
  balanceChanges.forEach(change => {
    const owner = change.owner.AddressOwner || 
                 change.owner.ObjectOwner || 
                 'Shared';
    
    if (!changesByAddress[owner]) {
      changesByAddress[owner] = [];
    }
    
    changesByAddress[owner].push({
      coinType: change.coinType,
      amount: change.amount,
      isPositive: parseInt(change.amount) > 0
    });
  });
  
  console.log('Balance Changes by Address:');
  Object.entries(changesByAddress).forEach(([address, changes]) => {
    console.log(`  ${address}:`);
    changes.forEach(change => {
      const symbol = change.coinType.includes('::sui::SUI') ? 'SUI' : 'Token';
      const amount = parseInt(change.amount) / 1_000_000_000;
      console.log(`    ${change.isPositive ? '+' : ''}${amount} ${symbol}`);
    });
  });
}

Error Handling and Debugging

Transaction Failure Analysis

JavaScript
async function debugFailedTransaction(digest) {
  try {
    const txn = await client.getTransactionBlock({
      digest: digest,
      options: {
        showInput: true,
        showEffects: true,
        showEvents: true
      }
    });
    
    const status = txn.effects?.status;
    
    if (status?.status !== 'success') {
      console.error('Transaction Failed:');
      console.error('Status:', status?.status);
      console.error('Error:', status?.error);
      
      // Analyze potential causes
      const gasUsed = txn.effects?.gasUsed;
      if (gasUsed) {
        const totalCost = parseInt(gasUsed.computationCost) + 
                         parseInt(gasUsed.storageCost);
        console.log('Gas Analysis:', {
          budgetExceeded: totalCost > 7500000, // Typical budget
          computationCost: gasUsed.computationCost,
          storageCost: gasUsed.storageCost
        });
      }
    }
    
    return txn;
  } catch (error) {
    console.error('Error fetching transaction:', error.message);
    
    if (error.message.includes('Could not find the referenced transaction')) {
      console.error('Transaction digest may be invalid or transaction not yet indexed');
    }
    
    throw error;
  }
}

Comprehensive Transaction Monitor

JavaScript
class TransactionMonitor {
  constructor(client) {
    this.client = client;
    this.cache = new Map();
  }
  
  async monitorTransaction(digest, options = {}) {
    const startTime = Date.now();
    let attempts = 0;
    const maxAttempts = options.maxAttempts || 30;
    const interval = options.interval || 2000;
    
    console.log(`Monitoring transaction: ${digest}`);
    
    while (attempts < maxAttempts) {
      try {
        const txn = await this.client.getTransactionBlock({
          digest: digest,
          options: {
            showEffects: true,
            showEvents: true,
            showObjectChanges: true
          }
        });
        
        const analysis = {
          digest: txn.digest,
          status: txn.effects?.status?.status,
          gasUsed: txn.effects?.gasUsed,
          eventCount: txn.events?.length || 0,
          objectChanges: txn.objectChanges?.length || 0,
          elapsedTime: Date.now() - startTime,
          attempts: attempts + 1
        };
        
        console.log('Transaction found:', analysis);
        this.cache.set(digest, { txn, analysis, timestamp: Date.now() });
        
        return { txn, analysis };
      } catch (error) {
        attempts++;
        console.log(`Attempt ${attempts}/${maxAttempts} failed: ${error.message}`);
        
        if (attempts < maxAttempts) {
          await new Promise(resolve => setTimeout(resolve, interval));
        }
      }
    }
    
    throw new Error(`Transaction ${digest} not found after ${maxAttempts} attempts`);
  }
  
  getCachedTransaction(digest) {
    return this.cache.get(digest);
  }
  
  clearCache() {
    this.cache.clear();
  }
}

Best Practices

1. Selective Data Fetching

Only request the data you need to minimize response size and improve performance:

JavaScript
// Minimal request for status check
const statusCheck = await client.getTransactionBlock({
  digest: digest,
  options: { showEffects: true }
});

// Full analysis request
const fullAnalysis = await client.getTransactionBlock({
  digest: digest,
  options: {
    showInput: true,
    showEffects: true,
    showEvents: true,
    showObjectChanges: true,
    showBalanceChanges: true
  }
});

2. Implement Caching

JavaScript
const transactionCache = new Map();

async function getCachedTransaction(digest) {
  if (transactionCache.has(digest)) {
    return transactionCache.get(digest);
  }
  
  const txn = await client.getTransactionBlock({
    digest: digest,
    options: { showEffects: true, showEvents: true }
  });
  
  // Cache successful transactions (they don't change)
  if (txn.effects?.status?.status === 'success') {
    transactionCache.set(digest, txn);
  }
  
  return txn;
}

3. Handle Rate Limits

JavaScript
class RateLimitedClient {
  constructor(client, requestsPerSecond = 10) {
    this.client = client;
    this.interval = 1000 / requestsPerSecond;
    this.lastRequest = 0;
  }
  
  async getTransactionBlock(params) {
    const now = Date.now();
    const timeSinceLastRequest = now - this.lastRequest;
    
    if (timeSinceLastRequest < this.interval) {
      await new Promise(resolve => 
        setTimeout(resolve, this.interval - timeSinceLastRequest)
      );
    }
    
    this.lastRequest = Date.now();
    return this.client.getTransactionBlock(params);
  }
}

Performance Considerations

  • Selective Options: Only request data you need (events, object changes, etc.)
  • Caching: Cache transaction results as they are immutable once executed
  • Rate Limiting: Implement rate limiting for high-frequency queries
  • Batch Processing: Process multiple transactions in parallel when possible
  • Error Handling: Implement retry logic for network failures

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