Transaction Building
Build and simulate transactions with the Altitrace SDK.
Transaction Format
interface TransactionCall {
from?: string | null // Sender address
to?: string | null // Recipient (null for contract creation)
data?: string | null // Transaction data
value?: string | null // ETH value in wei (hex)
gas?: string | null // Gas limit (hex)
accessList?: AccessList | null // EIP-2930 access list
}Basic Examples
ETH Transfer
const ethTransfer: TransactionCall = {
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0x1234567890123456789012345678901234567890',
value: '0xde0b6b3a7640000', // 1 ETH
gas: '0x5208' // 21000 gas
}
const result = await client.simulateCall(ethTransfer)
console.log('Gas used:', result.getTotalGasUsed())ERC-20 Transfer
const tokenTransfer: TransactionCall = {
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // USDC
data: '0xa9059cbb' + // transfer(address,uint256)
'0000000000000000000000001234567890123456789012345678901234567890' + // to
'0000000000000000000000000000000000000000000000000000000000000064' // 100 USDC
}
const result = await client.simulateCall(tokenTransfer)Contract Deployment
const deployment: TransactionCall = {
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
data: '0x608060405234801561001057600080fd5b50...', // bytecode
gas: '0x3d0900' // 4M gas
}
const result = await client.simulateCall(deployment)
if (result.isSuccess()) {
console.log('Contract deployed at:', result.calls[0].address)
}Using Viem
Integrate with viem for encoding and decoding.
import { encodeFunctionData, parseAbi, parseEther } from 'viem'
// Encode function call
const data = encodeFunctionData({
abi: parseAbi(['function transfer(address to, uint256 amount)']),
functionName: 'transfer',
args: ['0x1234567890123456789012345678901234567890', parseEther('1')]
})
const transaction: TransactionCall = {
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data
}
const result = await client.simulateCall(transaction)Decoding Results
import { decodeAbiParameters, parseAbi } from 'viem'
const result = await client.simulateCall({
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: encodeFunctionData({
abi: parseAbi(['function balanceOf(address) view returns (uint256)']),
functionName: 'balanceOf',
args: ['0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c']
})
})
if (result.isSuccess()) {
const [balance] = decodeAbiParameters(
parseAbi(['uint256']),
result.calls[0].returnData
)
console.log('Balance:', balance)
}Gas Estimation
Estimate gas by simulating first.
// Simulate to get gas estimate
const simulation = await client.simulateCall({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: '0xa9059cbb...'
})
if (simulation.isSuccess()) {
const gasUsed = simulation.getTotalGasUsed()
console.log('Estimated gas:', gasUsed)
}Multicall Pattern
import { encodeFunctionData, parseAbi } from 'viem'
const multicallAbi = parseAbi([
'function multicall(bytes[] calldata data) returns (bytes[] memory results)'
])
// Batch multiple calls
const calls = [
encodeFunctionData({
abi: parseAbi(['function approve(address spender, uint256 amount)']),
functionName: 'approve',
args: ['0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D', parseEther('100')]
}),
encodeFunctionData({
abi: parseAbi(['function transfer(address to, uint256 amount)']),
functionName: 'transfer',
args: ['0x1234567890123456789012345678901234567890', parseEther('10')]
})
]
const multicallTx: TransactionCall = {
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0x5BA1e12693Dc8F9c48aAD8770482f4739bEeD696', // Multicall3
data: encodeFunctionData({
abi: multicallAbi,
functionName: 'multicall',
args: [calls]
})
}
const result = await client.simulateCall(multicallTx)Common Patterns
Safe Transfer
// Check balance before transfer
const balanceCheck = await client.simulateCall({
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: encodeFunctionData({
abi: parseAbi(['function balanceOf(address) view returns (uint256)']),
functionName: 'balanceOf',
args: ['0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c']
})
})
if (balanceCheck.isSuccess()) {
const [balance] = decodeAbiParameters(
parseAbi(['uint256']),
balanceCheck.calls[0].returnData
)
const transferAmount = parseEther('10')
if (balance >= transferAmount) {
// Proceed with transfer
const transfer = await client.simulateCall({
from: '0x742d35Cc6634C0532925a3b844Bc9e7595f06e8c',
to: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48',
data: encodeFunctionData({
abi: parseAbi(['function transfer(address to, uint256 amount)']),
functionName: 'transfer',
args: ['0x1234567890123456789012345678901234567890', transferAmount]
})
})
}
}Transaction Validation
import { isAddress, isHex } from 'viem'
function validateTransaction(tx: TransactionCall): boolean {
if (tx.from && !isAddress(tx.from)) return false
if (tx.to && !isAddress(tx.to)) return false
if (tx.data && !isHex(tx.data)) return false
if (tx.value && !isHex(tx.value)) return false
if (tx.gas && !isHex(tx.gas)) return false
return true
}