sui_dryRunTransactionBlock
Simulates transaction execution without committing to the blockchain, providing detailed effects and gas estimates.
Overview​
The sui_dryRunTransactionBlock
method allows you to simulate transaction execution to preview effects, estimate gas costs, and validate transaction logic before submission. This is essential for testing complex transactions, estimating costs, and ensuring transactions will succeed before spending gas.
Parameters​
Parameter | Type | Required | Description |
---|---|---|---|
transactionBlockBytes | string | Yes | BCS serialized transaction data as base64 string |
Returns​
Returns simulated transaction effects and execution results.
Field | Type | Description |
---|---|---|
effects | object | Simulated transaction effects including status and changes |
events | array | Events that would be emitted |
objectChanges | array | Objects that would be created, modified, or deleted |
balanceChanges | array | Balance changes that would occur |
input | object | Transaction input data |
Effects Object​
Field | Type | Description |
---|---|---|
status | object | Execution status (success/failure) |
executedEpoch | string | Epoch when simulated |
gasUsed | object | Gas cost breakdown |
modifiedAtVersions | array | Objects and their versions |
created | array | Objects that would be created |
mutated | array | Objects that would be modified |
deleted | array | Objects that would be deleted |
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_dryRunTransactionBlock",
"params": [
"AAACAAgAypo7AAAAAAAg7Vgw...transaction_bytes_base64..."
],
"id": 1
}'
import { TransactionBlock } from '@mysten/sui.js/transactions';
import { SuiClient } from '@mysten/sui.js/client';
const client = new SuiClient({
url: 'https://sui-mainnet.dwellir.com/YOUR_API_KEY'
});
// Build transaction
const tx = new TransactionBlock();
tx.transferObjects(
[tx.object('0x...')],
tx.pure('0xrecipient_address')
);
// Dry run to estimate gas
const result = await client.dryRunTransactionBlock({
transactionBlock: await tx.build({ client })
});
console.log('Status:', result.effects.status);
console.log('Gas estimate:', {
computation: result.effects.gasUsed.computationCost,
storage: result.effects.gasUsed.storageCost,
rebate: result.effects.gasUsed.storageRebate
});
// Check if transaction would succeed
if (result.effects.status.status === 'success') {
console.log('Transaction would succeed');
console.log('Objects created:', result.effects.created?.length || 0);
console.log('Objects modified:', result.effects.mutated?.length || 0);
} else {
console.error('Transaction would fail:', result.effects.status.error);
}
import requests
import json
url = "https://sui-mainnet.dwellir.com/YOUR_API_KEY"
# Example transaction bytes (base64 encoded)
transaction_bytes = "AAACAAgAypo7AAAAAAAg7Vgw..."
payload = {
"jsonrpc": "2.0",
"method": "sui_dryRunTransactionBlock",
"params": [transaction_bytes],
"id": 1
}
response = requests.post(url, json=payload)
result = response.json()['result']
# Analyze simulation results
effects = result['effects']
gas_used = effects['gasUsed']
print(f"Status: {effects['status']['status']}")
print(f"Gas estimate: {
int(gas_used['computationCost']) +
int(gas_used['storageCost']) -
int(gas_used['storageRebate'])
}")
# Check for errors
if effects['status']['status'] != 'success':
print(f"Error: {effects['status'].get('error', 'Unknown error')}")
Response Example​
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"effects": {
"messageVersion": "v1",
"status": {
"status": "success"
},
"executedEpoch": "251",
"gasUsed": {
"computationCost": "1000000",
"storageCost": "2588000",
"storageRebate": "978120",
"nonRefundableStorageFee": "9880"
},
"modifiedAtVersions": [
{
"objectId": "0x5d3c87e88bc566e3f10c66e0275a366001ffa8b86142adc78c744de6afffeb34",
"sequenceNumber": "31823925"
}
],
"created": [],
"mutated": [
{
"owner": {
"AddressOwner": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
},
"reference": {
"objectId": "0x5d3c87e88bc566e3f10c66e0275a366001ffa8b86142adc78c744de6afffeb34",
"version": 31823925,
"digest": "2VivvnKSj89drLLNdkKhDxPFXTzPFkVH4V4DpCwN6pJk"
}
}
],
"deleted": [],
"dependencies": [
"5yxPx9j5yQVhR3NmM9vHkvPq98zng3kFgPvL5pb6MfmT"
]
},
"events": [],
"objectChanges": [
{
"type": "mutated",
"sender": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f",
"owner": {
"AddressOwner": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
},
"objectType": "0x2::coin::Coin<0x2::sui::SUI>",
"objectId": "0x5d3c87e88bc566e3f10c66e0275a366001ffa8b86142adc78c744de6afffeb34",
"version": "31823925",
"previousVersion": "31823924",
"digest": "2VivvnKSj89drLLNdkKhDxPFXTzPFkVH4V4DpCwN6pJk"
}
],
"balanceChanges": [
{
"owner": {
"AddressOwner": "0xd77955e670601c2c2e6e8637e383695c166aac0a86b741c266bdfb23c2e3369f"
},
"coinType": "0x2::sui::SUI",
"amount": "-2609880"
}
]
}
}
Use Cases​
Gas Estimation​
async function estimateGas(tx) {
const result = await client.dryRunTransactionBlock({
transactionBlock: await tx.build({ client })
});
const gasUsed = result.effects.gasUsed;
const totalGas =
Number(gasUsed.computationCost) +
Number(gasUsed.storageCost) -
Number(gasUsed.storageRebate);
// Add 10% buffer for safety
return Math.ceil(totalGas * 1.1);
}
Transaction Validation​
async function validateTransaction(tx) {
const result = await client.dryRunTransactionBlock({
transactionBlock: await tx.build({ client })
});
if (result.effects.status.status !== 'success') {
throw new Error(`Transaction would fail: ${result.effects.status.error}`);
}
// Check specific conditions
const created = result.effects.created || [];
const deleted = result.effects.deleted || [];
console.log(`Transaction would create ${created.length} objects`);
console.log(`Transaction would delete ${deleted.length} objects`);
return true;
}
Complex Transaction Testing​
async function testDeFiTransaction() {
const tx = new TransactionBlock();
// Complex DeFi operation
const [coin] = tx.splitCoins(tx.gas, [tx.pure(1000000000)]);
tx.moveCall({
target: '0xdefi::pool::swap',
arguments: [
coin,
tx.pure('0x2::sui::SUI'),
tx.pure('0xcustom::token::TOKEN')
]
});
// Test without executing
const result = await client.dryRunTransactionBlock({
transactionBlock: await tx.build({ client })
});
// Analyze events that would be emitted
const swapEvents = result.events.filter(e =>
e.type.includes('SwapExecuted')
);
console.log('Swap events:', swapEvents);
return result;
}
Best Practices​
- Always dry run before execution for critical transactions
- Add gas buffer of 10-20% to estimates for safety
- Validate object versions before submission
- Check for expected events in simulation results
- Handle simulation failures gracefully
Common Errors​
Error | Description | Solution |
---|---|---|
InsufficientGas | Gas budget too low | Increase gas budget based on estimate |
ObjectNotFound | Referenced object doesn't exist | Verify object IDs |
InvalidInput | Malformed transaction | Check transaction construction |
ObjectVersionMismatch | Object was modified | Refresh object references |
Related Methods​
- sui_executeTransactionBlock - Execute the transaction
- sui_devInspectTransactionBlock - Debug transaction execution
- sui_getObject - Verify object state
Need help? Contact our support team or check the Sui documentation.