sui_getTransactionBlock
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.
Parameters​
Parameter | Type | Required | Description |
---|---|---|---|
digest | string | Yes | The transaction digest (64-character hex string with 0x prefix) |
options | object | No | Options for controlling the response content |
Options Object​
Field | Type | Default | Description |
---|---|---|---|
showInput | boolean | false | Include transaction input data and arguments |
showRawInput | boolean | false | Include raw BCS-encoded input data |
showEffects | boolean | false | Include transaction effects and state changes |
showEvents | boolean | false | Include events emitted during execution |
showObjectChanges | boolean | false | Include object changes and mutations |
showBalanceChanges | boolean | false | Include balance changes for all addresses |
showRawEffects | boolean | false | Include raw BCS-encoded effects |
Returns​
Returns an object containing the requested transaction information.
Field | Type | Description |
---|---|---|
digest | string | Transaction digest (unique identifier) |
transaction | object | Transaction data including inputs and kind |
effects | object | Transaction effects and state changes |
events | array | Events emitted during transaction execution |
objectChanges | array | Changes to objects during execution |
balanceChanges | array | Balance changes for involved addresses |
timestampMs | string | Transaction execution timestamp |
checkpoint | string | Checkpoint number containing this transaction |
Transaction Structure​
Field | Type | Description |
---|---|---|
data | object | Transaction input data and parameters |
txSignatures | array | Cryptographic signatures |
Effects Structure​
Field | Type | Description |
---|---|---|
messageVersion | string | Protocol version |
status | object | Execution status (success or failure) |
executedEpoch | string | Epoch when transaction was executed |
gasUsed | object | Gas consumption details |
modifiedAtVersions | array | Versions of modified objects |
sharedObjects | array | Shared objects accessed |
transactionDigest | string | Transaction digest |
created | array | Objects created during execution |
mutated | array | Objects modified during execution |
deleted | array | Objects deleted during execution |
gasObject | object | Gas coin used for transaction |
dependencies | array | Transaction dependencies |
Code Examples​
- cURL
- JavaScript
- Python
curl -X POST https://sui-mainnet.dwellir.com/YOUR_API_KEY \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "sui_getTransactionBlock",
"params": [
"0x8c123c0b23c456789abcdef0123456789abcdef0123456789abcdef0123456789a",
{
"showInput": true,
"showEffects": true,
"showEvents": true,
"showObjectChanges": true,
"showBalanceChanges": true
}
],
"id": 1
}'
import { SuiClient } from '@mysten/sui.js/client';
const client = new SuiClient({
url: 'https://sui-mainnet.dwellir.com/YOUR_API_KEY'
});
async function getTransactionDetails(digest) {
const txn = await client.getTransactionBlock({
digest: digest,
options: {
showInput: true,
showEffects: true,
showEvents: true,
showObjectChanges: true,
showBalanceChanges: true
}
});
console.log('Transaction Details:', {
digest: txn.digest,
status: txn.effects?.status?.status,
gasUsed: txn.effects?.gasUsed,
timestamp: new Date(parseInt(txn.timestampMs || '0')),
eventCount: txn.events?.length || 0,
objectChanges: txn.objectChanges?.length || 0
});
return txn;
}
// Analyze transaction effects
function analyzeTransaction(txn) {
const analysis = {
successful: txn.effects?.status?.status === 'success',
gasUsed: txn.effects?.gasUsed,
objectsCreated: txn.objectChanges?.filter(c => c.type === 'created').length || 0,
objectsMutated: txn.objectChanges?.filter(c => c.type === 'mutated').length || 0,
objectsDeleted: txn.objectChanges?.filter(c => c.type === 'deleted').length || 0,
eventsEmitted: txn.events?.length || 0,
balanceChanges: txn.balanceChanges?.length || 0
};
console.log('Transaction Analysis:', analysis);
return analysis;
}
// Example usage
const digest = '0x8c123c0b23c456789abcdef0123456789abcdef0123456789abcdef0123456789a';
const transaction = await getTransactionDetails(digest);
const analysis = analyzeTransaction(transaction);
import requests
import json
from datetime import datetime
class SuiTransactionAnalyzer:
def __init__(self, rpc_url):
self.rpc_url = rpc_url
def get_transaction(self, digest, show_all=True):
"""Get detailed transaction information"""
options = {
"showInput": show_all,
"showEffects": show_all,
"showEvents": show_all,
"showObjectChanges": show_all,
"showBalanceChanges": show_all
}
payload = {
"jsonrpc": "2.0",
"method": "sui_getTransactionBlock",
"params": [digest, options],
"id": 1
}
response = requests.post(
self.rpc_url,
headers={'Content-Type': 'application/json'},
data=json.dumps(payload)
)
result = response.json()
if 'error' in result:
raise Exception(f"RPC Error: {result['error']}")
return result['result']
def analyze_transaction(self, txn_data):
"""Analyze transaction data and extract key metrics"""
effects = txn_data.get('effects', {})
object_changes = txn_data.get('objectChanges', [])
events = txn_data.get('events', [])
balance_changes = txn_data.get('balanceChanges', [])
analysis = {
'digest': txn_data['digest'],
'status': effects.get('status', {}).get('status'),
'gas_used': effects.get('gasUsed', {}),
'timestamp': datetime.fromtimestamp(
int(txn_data.get('timestampMs', '0')) / 1000
),
'objects_created': len([c for c in object_changes if c.get('type') == 'created']),
'objects_mutated': len([c for c in object_changes if c.get('type') == 'mutated']),
'objects_deleted': len([c for c in object_changes if c.get('type') == 'deleted']),
'events_count': len(events),
'balance_changes_count': len(balance_changes)
}
return analysis
def print_summary(self, analysis):
"""Print human-readable transaction summary"""
print(f"Transaction: {analysis['digest']}")
print(f"Status: {analysis['status']}")
print(f"Timestamp: {analysis['timestamp']}")
print(f"Gas Used: {analysis['gas_used']}")
print(f"Objects Created: {analysis['objects_created']}")
print(f"Objects Modified: {analysis['objects_mutated']}")
print(f"Objects Deleted: {analysis['objects_deleted']}")
print(f"Events Emitted: {analysis['events_count']}")
print(f"Balance Changes: {analysis['balance_changes_count']}")
# Usage example
analyzer = SuiTransactionAnalyzer('https://sui-mainnet.dwellir.com/YOUR_API_KEY')
digest = '0x8c123c0b23c456789abcdef0123456789abcdef0123456789abcdef0123456789a'
transaction = analyzer.get_transaction(digest)
analysis = analyzer.analyze_transaction(transaction)
analyzer.print_summary(analysis)
Response Example​
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"digest": "0x8c123c0b23c456789abcdef0123456789abcdef0123456789abcdef0123456789a",
"transaction": {
"data": {
"messageVersion": "v1",
"transaction": {
"kind": "ProgrammableTransaction",
"inputs": [
{
"type": "pure",
"valueType": "address",
"value": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
}
],
"transactions": [
{
"TransferObjects": [
[
{
"Input": 0
}
],
{
"Input": 1
}
]
}
]
},
"sender": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f",
"gasData": {
"payment": [
{
"objectId": "0x5d3c87e88bc566e3f10c66e0275a366001ffa8b86142adc78c744de6afffeb34",
"version": 31823924,
"digest": "HpSeCiMLG53N9FcHDrRTxwGhc4RVJa1seZhXYJ7KFpJe"
}
],
"owner": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f",
"price": "750",
"budget": "7500000"
}
},
"txSignatures": [
"AIXfGNvFvVwrVlOJQCAjNZ1mJ7QfOdxzQDQmHgdEGurBTGEpTKyKtIfxWq0YyL9JcF2JHGvglq3SqfX9VgwjJ+AONmH8/BbLSvdNuKLJAMjnafcTq4JxFRZGBKPhZCDn5w=="
]
},
"effects": {
"messageVersion": "v1",
"status": {
"status": "success"
},
"executedEpoch": "251",
"gasUsed": {
"computationCost": "750000",
"storageCost": "2340000",
"storageRebate": "1956000",
"nonRefundableStorageFee": "19764"
},
"modifiedAtVersions": [
{
"objectId": "0x5d3c87e88bc566e3f10c66e0275a366001ffa8b86142adc78c744de6afffeb34",
"sequenceNumber": "31823924"
}
],
"transactionDigest": "0x8c123c0b23c456789abcdef0123456789abcdef0123456789abcdef0123456789a",
"created": [],
"mutated": [
{
"owner": {
"AddressOwner": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
},
"reference": {
"objectId": "0x5d3c87e88bc566e3f10c66e0275a366001ffa8b86142adc78c744de6afffeb34",
"version": 31823925,
"digest": "7dBx2Q5KDhz9AjZgWwHqGEKhWu9sF4fE2yNzYtGqHx8P"
}
}
],
"gasObject": {
"owner": {
"AddressOwner": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
},
"reference": {
"objectId": "0x5d3c87e88bc566e3f10c66e0275a366001ffa8b86142adc78c744de6afffeb34",
"version": 31823925,
"digest": "7dBx2Q5KDhz9AjZgWwHqGEKhWu9sF4fE2yNzYtGqHx8P"
}
},
"dependencies": []
},
"events": [
{
"id": {
"txDigest": "0x8c123c0b23c456789abcdef0123456789abcdef0123456789abcdef0123456789a",
"eventSeq": "0"
},
"packageId": "0x2",
"transactionModule": "pay",
"sender": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f",
"type": "0x2::balance::Supply<0x2::sui::SUI>",
"parsedJson": {
"value": "1000000000"
},
"bcs": "NNTJCEGnC4Ts7hGJYJzbeUXJZYwmGDL8DELcD9fv2N2k"
}
],
"objectChanges": [
{
"type": "mutated",
"sender": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f",
"owner": {
"AddressOwner": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
},
"objectType": "0x2::coin::Coin<0x2::sui::SUI>",
"objectId": "0x5d3c87e88bc566e3f10c66e0275a366001ffa8b86142adc78c744de6afffeb34",
"version": "31823925",
"previousVersion": "31823924",
"digest": "7dBx2Q5KDhz9AjZgWwHqGEKhWu9sF4fE2yNzYtGqHx8P"
}
],
"balanceChanges": [
{
"owner": {
"AddressOwner": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
},
"coinType": "0x2::sui::SUI",
"amount": "-1134000"
}
],
"timestampMs": "1703097600000",
"checkpoint": "18523456"
}
}
Common Use Cases​
1. Transaction Status Verification​
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​
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​
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​
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​
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​
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​
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​
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:
// 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​
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​
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);
}
}
Related Methods​
- sui_executeTransactionBlock - Execute transaction blocks
- sui_dryRunTransactionBlock - Simulate transaction execution
- suix_queryTransactionBlocks - Query multiple transactions
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.