Implement sophisticated contract call patterns for production applications. Learn advanced techniques for complex workflows and robust error handling.

Transaction Batching

Aggregate, Swap, and Stake Pattern

This pattern combines multiple DeFi operations into a single transaction, using aggregated funds to open leveraged positions across protocols.

cross-chain-leverage.ts
async function openLeveragedPosition(
  marginAmount: bigint,
  leverage: number,
  marginAsset: string,
  isLong: boolean
) {
  const calls = [];
  
  // 1. Swap aggregated USDC to margin asset if needed
  if (marginAsset !== USDC_ADDRESS) {
    calls.push({
      to: DEX_ROUTER,
      data: encodeFunctionData({
        abi: parseAbi(['function swap(address,address,uint256,uint256,address)']),
        functionName: 'swap',
        args: [USDC_ADDRESS, marginAsset, marginAmount, minOut, account.accountAddress]
      }),
      value: '0'
    });
  }
  
  // 2. Deposit margin to perpetual protocol
  calls.push({
    to: PERP_CONTRACT,
    data: encodeFunctionData({
      abi: parseAbi(['function depositMargin(address,uint256)']),
      functionName: 'depositMargin',
      args: [marginAsset, marginAmount]
    }),
    value: '0'
  });
  
  // 3. Open leveraged position
  calls.push({
    to: PERP_CONTRACT,
    data: encodeFunctionData({
      abi: parseAbi(['function openPosition(uint256,bool)']),
      functionName: 'openPosition',
      args: [marginAmount * BigInt(leverage), isLong]
    }),
    value: '0'
  });

  return await executeCall({
    targetChain: 'eip155:42161', // Arbitrum
    calls,
    tokensRequired: [{
      assetType: `eip155:42161/erc20:${marginAsset}`,
      amount: marginAmount.toString()
    }],
    allowanceRequirements: [
      {
        assetType: `eip155:42161/erc20:${USDC_ADDRESS}`,
        amount: marginAmount.toString(),
        spender: DEX_ROUTER
      },
      {
        assetType: `eip155:42161/erc20:${marginAsset}`,
        amount: marginAmount.toString(),
        spender: PERP_CONTRACT
      }
    ],
    fromAggregatedAssetId: 'ds:usdc' // Pull from any chain
  });
}

Cross-Chain Swap and Stake

Use USDC from multiple chains to swap and stake in a single operation. This pattern optimizes for users who want to participate in staking protocols using their distributed token holdings.

cross-chain-staking.ts
const crossChainStake = async (stakeAmount: bigint) => {
  const WETH = '0x4200000000000000000000000000000000000006';
  const STAKING_CONTRACT = '0x796f1793599D7b6acA6A87516546DdF8E5F3aA9d';
  const UNISWAP_ROUTER = '0x2626664c2603336E57B271c5C0b26F421741e481';
  
  // 1. Swap USDC to WETH on Base
  const swapData = encodeFunctionData({
    abi: parseAbi([
      'function exactInputSingle((address,address,uint24,address,uint256,uint256,uint256,uint160)) returns (uint256)'
    ]),
    functionName: 'exactInputSingle',
    args: [{
      tokenIn: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913', // USDC
      tokenOut: WETH,
      fee: 3000,
      recipient: account.accountAddress,
      deadline: Math.floor(Date.now() / 1000) + 1800,
      amountIn: stakeAmount,
      amountOutMinimum: 0n,
      sqrtPriceLimitX96: 0n
    }]
  });

  // 2. Stake WETH (approval handled by allowanceRequirements)
  const stakeData = encodeFunctionData({
    abi: parseAbi(['function stake(uint256 amount)']),
    functionName: 'stake',
    args: [stakeAmount] // Will use actual WETH received from swap
  });

  return await executeCall({
    targetChain: 'eip155:8453', // Base
    calls: [
      {
        to: UNISWAP_ROUTER,
        data: swapData,
        value: '0'
      },
      {
        to: STAKING_CONTRACT,
        data: stakeData,
        value: '0'
      }
    ],
    tokensRequired: [{
      assetType: 'eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
      amount: stakeAmount.toString()
    }],
    allowanceRequirements: [
      {
        assetType: 'eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
        amount: stakeAmount.toString(),
        spender: UNISWAP_ROUTER
      },
      {
        assetType: `eip155:8453/erc20:${WETH}`,
        amount: stakeAmount.toString(), // Approximate amount for approval
        spender: STAKING_CONTRACT
      }
    ],
    fromAggregatedAssetId: 'ds:usdc'
  });
};

Batch Operations

Multi-Recipient Payment System

Process multiple payments efficiently by grouping them by token type and using multicall patterns to reduce gas costs.

batch-payments.ts
interface Payment {
  recipient: string;
  amount: bigint;
  token: string;
}

async function batchPayout(payments: Payment[]) {
  const calls = [];
  const tokensRequired = [];
  
  // Group payments by token to optimize gas usage
  const paymentsByToken = payments.reduce((acc, payment) => {
    if (!acc[payment.token]) acc[payment.token] = [];
    acc[payment.token].push(payment);
    return acc;
  }, {} as Record<string, Payment[]>);
  
  for (const [token, tokenPayments] of Object.entries(paymentsByToken)) {
    // Use multicall for same-token transfers
    const multicallData = encodeFunctionData({
      abi: parseAbi(['function multicall(bytes[] calldata data)']),
      functionName: 'multicall',
      args: [
        tokenPayments.map(p => 
          encodeFunctionData({
            abi: parseAbi(['function transfer(address,uint256)']),
            functionName: 'transfer',
            args: [p.recipient, p.amount]
          })
        )
      ]
    });
    
    calls.push({
      to: token,
      data: multicallData,
      value: '0'
    });
    
    const totalAmount = tokenPayments.reduce(
      (sum, p) => sum + p.amount, 
      0n
    );
    
    tokensRequired.push({
      assetType: `eip155:8453/erc20:${token}`,
      amount: totalAmount.toString()
    });
  }
  
  return await executeCall({
    targetChain: 'eip155:8453',
    calls,
    tokensRequired,
    fromAggregatedAssetId: 'ds:usdc'
  });
}

Gas Optimization Patterns

Conditional Execution Pattern

Skip unnecessary operations by checking on-chain state before execution, reducing gas costs for operations that may not be needed.

conditional-execution.ts
async function optimizedDeFiOperation(amount: bigint) {
  const calls = [];
  const AAVE_POOL = '0xA238Dd80C259a72e81d7e4664a9801593F98d1c5';
  const USDC_ADDRESS = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
  
  // Check if we need to withdraw from lending protocol first
  const currentDeposit = await checkAaveDeposit(account.accountAddress);
  
  if (currentDeposit > 0n) {
    calls.push({
      to: AAVE_POOL,
      data: encodeFunctionData({
        abi: parseAbi(['function withdraw(address,uint256,address)']),
        functionName: 'withdraw',
        args: [USDC_ADDRESS, currentDeposit, account.accountAddress]
      }),
      value: '0'
    });
  }
  
  // Main operation (e.g., swap, stake, etc.)
  calls.push({
    to: TARGET_CONTRACT,
    data: mainOperationData,
    value: '0'
  });
  
  // Only re-deposit excess if amount justifies gas cost
  const minDepositAmount = parseUnits('100', 6); // $100 minimum
  if (amount > minDepositAmount) {
    calls.push({
      to: AAVE_POOL,
      data: encodeFunctionData({
        abi: parseAbi(['function supply(address,uint256,address,uint16)']),
        functionName: 'supply',
        args: [USDC_ADDRESS, amount, account.accountAddress, 0]
      }),
      value: '0'
    });
  }
  
  return await executeCall({
    targetChain: 'eip155:8453',
    calls,
    tokensRequired: [{
      assetType: 'eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
      amount: amount.toString()
    }],
    allowanceRequirements: [{
      assetType: 'eip155:8453/erc20:0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',
      amount: amount.toString(),
      spender: AAVE_POOL
    }]
  });
}

Error Recovery Patterns

Safe Execution with Fallbacks

Implement fallback mechanisms for DEX operations when primary routes fail due to liquidity or slippage issues.

error-recovery.ts
interface CallData {
  to: string;
  data: string;
  value: string;
}

async function safeExecuteWithFallback(
  primaryOperation: CallData[],
  fallbackOperation: CallData[]
) {
  try {
    // Attempt primary operation first
    return await executeCall({
      targetChain: 'eip155:8453',
      calls: primaryOperation,
      tokensRequired: calculateTokensRequired(primaryOperation)
    });
  } catch (error: any) {
    // Handle specific errors with fallback strategies
    if (error.message.includes('INSUFFICIENT_LIQUIDITY') || 
        error.message.includes('EXCESSIVE_SLIPPAGE')) {
      console.log('Primary route failed, attempting fallback...');
      
      return await executeCall({
        targetChain: 'eip155:8453',
        calls: fallbackOperation,
        tokensRequired: calculateTokensRequired(fallbackOperation)
      });
    }
    
    // Re-throw unexpected errors
    throw error;
  }
}

function calculateTokensRequired(calls: CallData[]) {
  // Implementation to analyze calls and determine token requirements
  return [];
}

State Management Patterns

Transaction Lifecycle Tracking

Track and monitor complex transactions with automatic retry and status monitoring capabilities.

transaction-tracker.ts
interface OperationStatus {
  status: 'PENDING' | 'COMPLETED' | 'FAILED' | 'IN_PROGRESS' | 'REFUNDED';
}

interface OperationDetails {
  hash: string;
  chainId: number;
  explorerUrl: string;
}

interface OriginAssetUsed {
  aggregatedAssetId: string;
  amount: string;
  assetType: string[];
  fiatValue: Array<{
    assetType: string;
    fiatValue: string;
  }>;
}

interface DestinationAssetUsed {
  aggregatedAssetId: string;
  amount: string;
  assetType: string;
  fiatValue: string;
  minimumAmount?: string;
  minimumFiatValue?: string;
}

interface Transaction {
  quoteId: string;
  status: OperationStatus;
  user: string;
  recipientAccountId: string;
  originChainOperations: OperationDetails[];
  destinationChainOperations: OperationDetails[];
  type: string;
  originToken: OriginAssetUsed;
  destinationToken: DestinationAssetUsed;
  timestamp: string;
}

interface LocalTransactionState {
  id: string;
  request: any;
  localStatus: 'preparing' | 'executing' | 'monitoring' | 'completed' | 'failed';
  preparedAt: number;
  transaction?: Transaction;
  error?: any;
}

class TransactionTracker {
  private pending = new Map<string, LocalTransactionState>();
  
  async executeAndTrack(request: any): Promise<Transaction> {
    const txId = this.generateId();
    
    // Store initial transaction state
    this.pending.set(txId, {
      id: txId,
      request,
      localStatus: 'preparing',
      preparedAt: Date.now()
    });
    
    try {
      // Step 1: Prepare and sign
      const quote = await this.prepareAndSign(request);
      this.updateLocalStatus(txId, 'executing');
      
      // Step 2: Execute
      const result = await this.executeQuote(quote);
      this.updateLocalStatus(txId, 'monitoring');
      
      // Step 3: Monitor with exponential backoff
      const finalResult = await this.monitorWithBackoff(quote.id);
      
      this.updateLocalStatus(txId, 'completed', finalResult);
      return finalResult;
      
    } catch (error) {
      this.updateLocalStatus(txId, 'failed', undefined, error);
      throw error;
    } finally {
      // Cleanup after 24 hours
      setTimeout(() => this.pending.delete(txId), 86400000);
    }
  }
  
  private async monitorWithBackoff(quoteId: string): Promise<Transaction> {
    const delays = [1000, 2000, 5000, 10000, 15000]; // Progressive delays
    const maxAttempts = 30;
    
    for (let attempt = 0; attempt < maxAttempts; attempt++) {
      const status = await getQuoteStatus(quoteId);
      
      if (['COMPLETED', 'FAILED', 'REFUNDED'].includes(status.status.status)) {
        return status;
      }
      
      const delay = delays[Math.min(attempt, delays.length - 1)];
      await new Promise(resolve => setTimeout(resolve, delay));
    }
    
    throw new Error('Transaction monitoring timeout');
  }
  
  private generateId(): string {
    return `tx_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
  }
  
  private updateLocalStatus(
    id: string, 
    localStatus: LocalTransactionState['localStatus'], 
    transaction?: Transaction,
    error?: any
  ) {
    const tx = this.pending.get(id);
    if (tx) {
      tx.localStatus = localStatus;
      if (transaction) tx.transaction = transaction;
      if (error) tx.error = error;
    }
  }
  
  // Get current transaction status
  getTransactionStatus(id: string): LocalTransactionState | undefined {
    return this.pending.get(id);
  }
  
  // Get all pending transactions
  getPendingTransactions(): LocalTransactionState[] {
    return Array.from(this.pending.values());
  }
}

Integration Patterns

Wallet-Agnostic Implementation

Create universal interfaces that work with any wallet provider, making your integration flexible across different wallet ecosystems.

wallet-integration.ts
interface WalletAdapter {
  signTypedData(data: any): Promise<string>;
  getAddress(): Promise<string>;
  isConnected(): Promise<boolean>;
}

class UniversalOneBalance {
  constructor(
    private apiKey: string,
    private wallet: WalletAdapter
  ) {}
  
  async executeCall(params: any) {
    // Ensure wallet is connected
    const isConnected = await this.wallet.isConnected();
    if (!isConnected) {
      throw new Error('Wallet not connected');
    }
    
    // Prepare operation
    const account = await this.getAccount();
    const preparedQuote = await this.prepare({
      ...params,
      account
    });
    
    // Sign with wallet adapter
    const signature = await this.wallet.signTypedData(
      preparedQuote.chainOperation.typedDataToSign
    );
    
    preparedQuote.chainOperation.userOp.signature = signature;
    
    // Execute operation
    return await this.execute(preparedQuote);
  }
  
  private async getAccount() {
    const address = await this.wallet.getAddress();
    return {
      sessionAddress: address,
      adminAddress: address, // Simplified for basic account
      accountAddress: await this.predictAccountAddress(address)
    };
  }
}

// MetaMask adapter example
const metamaskAdapter: WalletAdapter = {
  signTypedData: (data) => window.ethereum.request({
    method: 'eth_signTypedData_v4',
    params: [address, JSON.stringify(data)]
  }),
  getAddress: async () => {
    const accounts = await window.ethereum.request({ 
      method: 'eth_accounts' 
    });
    return accounts[0];
  },
  isConnected: async () => {
    const accounts = await window.ethereum.request({ 
      method: 'eth_accounts' 
    });
    return accounts.length > 0;
  }
};

// Usage
const oneBalance = new UniversalOneBalance(apiKey, metamaskAdapter);

Performance Optimization Tips

Batch Operations

Group similar operations to reduce transaction overhead and gas costs

Use Multicall

Combine multiple calls to the same contract in a single transaction

Cache Quotes

Store prepared quotes for retry scenarios (valid for ~30 seconds)

Async Monitoring

Don’t block UI while monitoring transaction status - use background polling

Implementation Best Practices

1

Plan Your Operations

Design your call sequence to minimize gas usage and maximize success probability

2

Handle Edge Cases

Implement fallbacks for common failure scenarios like insufficient liquidity

3

Monitor Actively

Track transaction status and provide users with real-time updates

4

Test Thoroughly

Validate complex patterns with small amounts before production deployment

Advanced Features: For even more sophisticated patterns, consider combining these techniques with OneBalance’s resource locks and time-based permissions for enhanced security and user experience.