ERC20 Operations

Complete ERC20 token management including balance checks, approvals, transfers, and direct bridge operations

Overview

ERC20 operations provide comprehensive token management through direct blockchain interactions, including balance checking, allowance management, token transfers, and direct bridge operations with built-in gas estimation and error handling.

Creating Token Instances

Basic Token Instance Creation

import { AggLayerSDK, SDK_MODES } from '@agglayer/sdk';

const sdk = new AggLayerSDK({
  mode: [SDK_MODES.NATIVE],
  native: {
    defaultNetwork: 1, // Ethereum mainnet
    customRpcUrls: {
      1: 'https://eth-mainnet.g.alchemy.com/v2/your-key',
      747474: 'https://rpc.katana.network',
    },
  },
});

const native = sdk.getNative();

// Create ERC20 token instance
const usdcToken = native.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1); // USDC on Ethereum
const katanaUsdc = native.erc20('0x203a662b0bd271a6ed5a60edfbd04bfce608fd36', 747474); // USDC on Katana

// Create native ETH instance
const ethToken = native.erc20('0x0000000000000000000000000000000000000000', 1); // Native ETH

Token Instance Methods

interface ERC20Token {
  // Balance operations
  getBalance(address: string): Promise<string>;
  
  // Allowance operations
  getAllowance(owner: string, spender: string): Promise<string>;
  buildApprove(spender: string, amount: string, from?: string): Promise<TransactionParams>;
  
  // Transfer operations
  buildTransfer(to: string, amount: string, from?: string): Promise<TransactionParams>;
  buildTransferFrom(from: string, to: string, amount: string, spender?: string): Promise<TransactionParams>;
  
  // Bridge operations
  bridgeTo(destinationNetwork: number, destinationAddress: string, amount: string, from?: string, options?: BridgeOptions): Promise<TransactionParams>;
  getWrappedToken(): Promise<string>;
  
  // Claim operations
  claimAsset(bridgeTxHash: string, sourceNetwork: number, bridgeIndex: number, claimer: string): Promise<TransactionParams>;
  claimMessage(bridgeTxHash: string, sourceNetwork: number, bridgeIndex: number, claimer: string): Promise<TransactionParams>;
  
  // Event operations
  getBridgeEventInfo(bridgeTxHash: string, sourceNetwork: number, bridgeIndex: number): Promise<BridgeEventInfo>;
}

Balance Operations

Checking Token Balances

Check ERC20 token balances and native currency balances for any address on any supported network.

// Check ERC20 token balance
const balance = await usdcToken.getBalance('0xUserAddress');
console.log(`Balance: ${formatAmount(balance, 6)} USDC`);

// Check native ETH balance
const ethBalance = await native.getNativeBalance('0xUserAddress', 1);
console.log(`ETH Balance: ${formatAmount(ethBalance)} ETH`);

// Helper function for formatting amounts
function formatAmount(amount: string, decimals: number = 18): string {
  const value = BigInt(amount);
  const divisor = BigInt(10 ** decimals);
  return (Number(value) / Number(divisor)).toString();
}

Allowance Operations

Managing Token Approvals

Check current token allowances and build approval transactions for bridge contracts or other spenders.

// Check current allowance for bridge contract
const bridgeAddress = '0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe';
const allowance = await usdcToken.getAllowance('0xUserAddress', bridgeAddress);
console.log(`Allowance: ${formatAmount(allowance, 6)} USDC`);

// Build approval transaction
const approvalTx = await usdcToken.buildApprove(
  bridgeAddress,
  '100000000000', // 100,000 USDC
  '0xUserAddress'
);

Transfer Operations

Building Transfer Transactions

Build standard ERC20 transfer transactions and transferFrom transactions for approved spending scenarios.

// Build transfer transaction
const transferTx = await usdcToken.buildTransfer(
  '0xRecipientAddress',
  '1000000000', // 1000 USDC
  '0xUserAddress'
);

// Build transferFrom transaction
const transferFromTx = await usdcToken.buildTransferFrom(
  '0xOwnerAddress',
  '0xRecipientAddress',
  '1000000000',
  '0xSpenderAddress'
);

Bridge Operations

Direct Bridge-to Operations

Bridge ERC20 tokens directly to another network using the Agglayer bridge contract. Get wrapped token addresses for destination networks.

// Build bridge transaction
const bridgeTx = await usdcToken.bridgeTo(
  747474, // Katana network ID
  '0xRecipientOnKatana',
  '1000000000', // 1000 USDC
  '0xUserAddress',
  {
    forceUpdateGlobalExitRoot: true,
    permitData: '0x',
  }
);

// Get wrapped token address
const wrappedAddress = await usdcToken.getWrappedToken();

Claim Operations

⚠️ Local Development Note: The SDK's claimAsset() method doesn't work with AggSandbox locally due to API endpoint differences. For local development, use AggSandbox's auto-claiming service instead.

Claiming Bridged Assets

Claim bridged assets on the destination network after the bridge transaction has been processed by AggKit.

// Claim assets on destination network
const bridgeTxHash = '0xYourBridgeTransactionHash';
const sourceNetwork = 1; // Ethereum
const bridgeIndex = 0;   // Bridge index

const claimTx = await katanaUsdc.claimAsset(
  bridgeTxHash,
  sourceNetwork,
  bridgeIndex,
  userAddress
);

Claiming Bridge Messages

Claim bridge messages sent via contract-to-contract communication on the destination network.

// Claim bridge messages (for contract-to-contract communication)
const messageClaimTx = await katanaUsdc.claimMessage(
  bridgeTxHash,
  sourceNetwork,
  bridgeIndex,
  userAddress
);

console.log('Message claim transaction built:');
console.log(`  To: ${messageClaimTx.to}`);
console.log(`  From: ${messageClaimTx.from}`);
console.log(`  Gas: ${messageClaimTx.gas}`);

Bridge Event Information

Get comprehensive information about a bridge transaction including origin network, token details, and deposit count for claiming.

// Get bridge event information
const bridgeEventInfo = await usdcToken.getBridgeEventInfo(
  bridgeTxHash,
  sourceNetwork,
  bridgeIndex
);

Working Example

import { AggLayerSDK, SDK_MODES } from '@agglayer/sdk';

const sdk = new AggLayerSDK({
  mode: [SDK_MODES.NATIVE],
  native: {
    defaultNetwork: 1,
    customRpcUrls: {
      1: 'https://eth-mainnet.g.alchemy.com/v2/your-key',
      747474: 'https://rpc.katana.network',
    },
  },
});

const native = sdk.getNative();
const usdcToken = native.erc20('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1);

// Check balance
const balance = await usdcToken.getBalance('0xUserAddress');

// Check allowance
const allowance = await usdcToken.getAllowance(
  '0xUserAddress',
  '0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe'
);

// Build approval
const approvalTx = await usdcToken.buildApprove(
  '0x2a3DD3EB832aF982ec71669E178424b10Dca2EDe',
  '100000000000',
  '0xUserAddress'
);

// Build bridge transaction
const bridgeTx = await usdcToken.bridgeTo(
  747474,
  '0xRecipientOnKatana',
  '1000000000',
  '0xUserAddress',
  { forceUpdateGlobalExitRoot: true, permitData: '0x' }
);
Edit on GitHub

Last updated on