Simulates a Solana transaction and returns a breakdown of expected asset changes, security validation
results, and optionally an estimated SOL fee — all before the transaction is sent to the network.
Supports both legacy Transaction and VersionedTransaction objects. Powered by
Blockaid for security validation.
Installation
npm install @dynamic-labs-sdk/solana
Usage
import { simulateSolanaTransaction } from '@dynamic-labs-sdk/solana';
import { isSolanaWalletAccount } from '@dynamic-labs-sdk/solana';
import { getPrimaryWalletAccount } from '@dynamic-labs-sdk/client';
import {
Transaction,
SystemProgram,
PublicKey,
} from '@solana/web3.js';
const walletAccount = getPrimaryWalletAccount();
if (walletAccount && isSolanaWalletAccount(walletAccount)) {
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: new PublicKey(walletAccount.address),
toPubkey: new PublicKey(recipientAddress),
lamports: 1_000_000_000, // 1 SOL
})
);
const result = await simulateSolanaTransaction({
walletAccount,
transaction,
});
console.log('Assets going out:', result.outAssets);
console.log('Security check:', result.validation?.result);
}
Parameters
| Parameter | Type | Description |
|---|
walletAccount | SolanaWalletAccount | The wallet account initiating the transaction |
transaction | Transaction | VersionedTransaction | The Solana transaction to simulate |
includeFees | boolean (optional) | Whether to include a SOL fee estimate. Default: false |
client | DynamicClient (optional) | Only required when using multiple clients |
Returns
Promise<SolanaSimulationResult> — an object with the following fields:
| Field | Type | Description |
|---|
inAssets | AssetDiff[] | Assets the wallet will receive |
outAssets | AssetDiff[] | Assets the wallet will send |
validation | BlockaidValidation (optional) | Security assessment from Blockaid |
validation.result | 'benign' | 'warning' | 'malicious' | Overall security verdict |
validation.description | string (optional) | Human-readable description |
validation.reason | string (optional) | Reason for the verdict |
feeData | SolanaTransactionFeeData (optional) | Present only when includeFees: true |
feeData.humanReadableAmount | string | Fee in SOL, formatted for display |
feeData.nativeAmount | bigint | Fee in lamports (0n for sponsored transactions) |
feeData.usdAmount | string (optional) | Fee in USD if price data is available |
priceData | PriceData | Price information for the assets involved |
counterparties | string[] (optional) | Other addresses involved in the transaction |
When the transaction’s fee payer is different from the wallet address, feeData.nativeAmount is 0n
— indicating the transaction fee is sponsored.
Examples
SOL transfer
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: new PublicKey(walletAccount.address),
toPubkey: new PublicKey(recipientAddress),
lamports: 500_000_000, // 0.5 SOL
})
);
const result = await simulateSolanaTransaction({
walletAccount,
transaction,
});
console.log('Assets out:', result.outAssets);
With fee estimation
const result = await simulateSolanaTransaction({
walletAccount,
transaction,
includeFees: true,
});
if (result.feeData) {
if (result.feeData.nativeAmount === 0n) {
console.log('Transaction fee is sponsored');
} else {
console.log(`Estimated fee: ${result.feeData.humanReadableAmount} SOL`);
}
}
Versioned transaction
import {
VersionedTransaction,
TransactionMessage,
PublicKey,
} from '@solana/web3.js';
const messageV0 = new TransactionMessage({
payerKey: new PublicKey(walletAccount.address),
recentBlockhash: latestBlockhash,
instructions: [instruction],
}).compileToV0Message();
const versionedTx = new VersionedTransaction(messageV0);
const result = await simulateSolanaTransaction({
walletAccount,
transaction: versionedTx,
});
Security validation
const result = await simulateSolanaTransaction({ walletAccount, transaction });
if (result.validation?.result === 'malicious') {
console.warn('Transaction flagged as malicious. Blocking.');
return;
}
if (result.validation?.result === 'warning') {
console.warn('Warning:', result.validation.description);
}
Error handling
import { SimulationFailedError } from '@dynamic-labs-sdk/client';
try {
const result = await simulateSolanaTransaction({ walletAccount, transaction });
} catch (error) {
if (error instanceof SimulationFailedError) {
console.error('Simulation failed:', error.message);
}
}