Build Transactions
Use buildTransaction() to create unsigned transactions for review, simulation, and custom signing workflows before execution.
buildTransaction() constructs an unsigned transaction without signing or broadcasting it. Use this when you want to inspect or display a transaction before committing, or when you need to implement a custom signing flow.
When to Use
- Show users a preview of what will happen before they confirm
- Custom multi-step flows (build → evaluate → sign)
- Integrating with hardware wallets or external signers
For most cases, sendAssets() (build + sign + broadcast in one call) is simpler.
Build via Client API
import { WalletChain } from "@tatumio/wallet-sdk";
const tx = await client.buildTransaction({
path: { chain: WalletChain.ETHEREUM_MAINNET },
body: {
to: "0xRecipientAddress",
token: "NATIVE",
amount: "0.01",
},
});Build via Custodian API
Build on behalf of a specific client from the custodian side:
const tx = await wallets.custodian.buildTransaction({
path: {
clientId: "cli_...",
chain: WalletChain.ETHEREUM_MAINNET,
},
body: {
to: "0xRecipientAddress",
token: "NATIVE",
amount: "0.01",
},
});Response Shapes
The response type depends on the chain.
EVM Chains
{
transaction: {
from?: string; // sender address
to?: string; // recipient or contract
data?: string; // calldata (empty for native transfers)
value?: string; // amount in wei
};
metadata: {
amount?: string;
fromAddress?: string;
toAddress?: string;
tokenAddress?: string;
tokenDecimals?: number;
tokenSymbol?: string;
rawAmount?: string;
};
}Solana
{
transaction?: string; // base64-encoded serialized transaction
metadata: {
amount?: string;
fromAddress?: string;
toAddress?: string;
tokenMintAddress?: string;
tokenDecimals?: number;
tokenProgramId?: string;
tokenSymbol?: string;
rawAmount?: string;
lastValidBlockHeight?: string;
serializedTransactionBase64Encoded?: string;
serializedTransactionBase58Encoded?: string;
};
}Bitcoin
{
transaction: {
publicKey?: string;
rawTxHex?: string;
signatureHashes?: string[]; // one hash per input to sign
};
metadata: {
amount?: string;
fromAddress?: string;
toAddress?: string;
rawAmount?: string;
feeInSatoshis?: string;
changeInSatoshis?: string;
};
}Stellar
{
transaction: {
xdr?: string; // XDR-encoded transaction envelope
networkPassphrase?: string;
};
metadata: {
amount?: string;
fromAddress?: string;
toAddress?: string;
assetCode?: string;
assetIssuer?: string | null;
rawAmount?: string;
};
}Tron
{
transaction: {
id?: string;
network?: "mainnet" | "nile" | "shasta";
};
metadata: {
amount?: string;
fromAddress?: string;
toAddress?: string;
tokenSymbol?: string;
contractAddress?: string | null;
};
}Build → Evaluate → Sign Flow
const chain = WalletChain.ETHEREUM_MAINNET;
// 1. Build
const tx = await client.buildTransaction({
path: { chain },
body: { to: "0xRecipient", token: "NATIVE", amount: "0.01" },
});
// 2. Evaluate (optional but recommended)
const evaluation = await client.evaluateTransaction({
query: { chainId: chain },
body: {
network: "ethereum",
transaction: {
toAddress: "0xRecipient",
value: tx.transaction?.value ?? "0",
},
operationType: "simulation",
},
});
if ((evaluation.evaluation?.riskScore ?? 0) > 70) {
throw new Error("Transaction risk score too high");
}
// 3. Sign and broadcast
const signed = await client.sign({
body: {
share: shares.SECP256K1.share,
method: "eth_sendTransaction",
params: [tx.transaction],
chainId: chain,
to: "0xRecipient",
},
});
console.log(signed.data); // transaction hash