Skip to content

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
}