Skip to main content
This guide demonstrates how to swap tokens by specifying the exact input amount. The SDK will calculate the output amount you’ll receive based on current market rates.

Overview

Exact input swaps allow you to:
  • Specify exactly how much you want to spend
  • Swap across multiple chains in a single operation
  • Get the best available rate automatically
  • Track swap progress with real-time events

When to Use Exact Input Swaps

  • Spending a specific amount of tokens
  • Liquidating positions
  • Converting all available balance
  • Fixed-budget transactions

Browser Example

1

Initialize the SDK

Set up the Nexus SDK for swap operations:
import { NexusSDK, type EthereumProvider } from '@avail-project/nexus-core';

async function getWallet(): Promise<EthereumProvider> {
  const provider = (window as any).ethereum;
  if (!provider) {
    throw new Error('Install a wallet like MetaMask to continue');
  }
  return provider;
}

const provider = await getWallet();
const sdk = new NexusSDK({ network: 'mainnet' });
await sdk.initialize(provider);
Swap operations are available on mainnet only. Make sure your network is set to 'mainnet'.
2

Configure swap parameters

Define the swap with exact input amounts:
import {
  SUPPORTED_CHAINS,
  TOKEN_CONTRACT_ADDRESSES,
  type ExactInSwapInput,
} from '@avail-project/nexus-core';

const swapParams: ExactInSwapInput = {
  from: [
    {
      chainId: SUPPORTED_CHAINS.ARBITRUM,
      tokenAddress: TOKEN_CONTRACT_ADDRESSES.USDT[SUPPORTED_CHAINS.ARBITRUM],
      amount: 1_000_000_000n, // 1000 USDT (6 decimals)
    },
  ],
  toChainId: SUPPORTED_CHAINS.ARBITRUM,
  toTokenAddress: TOKEN_CONTRACT_ADDRESSES.USDC[SUPPORTED_CHAINS.ARBITRUM],
};
You can specify multiple source chains to aggregate liquidity:
from: [
  { chainId: 10, tokenAddress: '0x...', amount: 500_000_000n },
  { chainId: 42161, tokenAddress: '0x...', amount: 500_000_000n },
]
3

Set up swap intent hook

Configure the swap intent hook to handle user approvals:
sdk.setOnSwapIntentHook(async ({ intent, allow, deny, refresh }) => {
  // Display swap details to user
  console.log('You will send:');
  intent.sources.forEach((source) => {
    console.log(`  ${source.amount} ${source.token.symbol} on ${source.chain.name}`);
  });

  console.log('You will receive:');
  console.log(`  ${intent.destination.amount} ${intent.destination.token.symbol}`);
  console.log(`  on ${intent.destination.chain.name}`);

  console.log('Gas supplied:', intent.destination.gas.amount);

  // Get updated quote if needed
  const refreshedIntent = await refresh();

  // User confirms
  if (userApproves()) {
    allow();
  } else {
    deny();
  }
});

// Also set allowance hook
sdk.setOnAllowanceHook(({ allow }) => allow(['min']));
4

Execute the swap

Run the swap with event tracking:
import { NEXUS_EVENTS } from '@avail-project/nexus-core';

try {
  const result = await sdk.swapWithExactIn(swapParams, {
    onEvent: (event) => {
      if (event.name === NEXUS_EVENTS.SWAP_STEP_COMPLETE) {
        console.log('Swap step completed:', event.args);

        // Handle specific steps
        if (event.args.type === 'SOURCE_SWAP_HASH') {
          console.log('Source swap TX:', event.args.explorerURL);
        }

        if (event.args.type === 'DESTINATION_SWAP_HASH') {
          console.log('Destination swap TX:', event.args.explorerURL);
        }

        if (event.args.type === 'SWAP_COMPLETE') {
          console.log('Swap completed successfully!');
        }
      }
    },
  });

  console.log('Swap result:', result);
} catch (error) {
  console.error('Swap failed:', error);
}

Node.js Example

For backend applications:
import {
  NEXUS_EVENTS,
  NexusSDK,
  type ExactInSwapInput,
} from '@avail-project/nexus-core';
import { ethers } from 'ethers';

async function executeSwap(params: ExactInSwapInput): Promise<boolean> {
  // Initialize with wallet
  const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!);
  const sdk = new NexusSDK({ network: 'mainnet' });
  await sdk.initialize(wallet);

  // Auto-approve hooks (careful in production!)
  sdk.setOnSwapIntentHook(({ allow }) => allow());
  sdk.setOnAllowanceHook(({ allow }) => allow(['min']));

  try {
    const result = await sdk.swapWithExactIn(params, {
      onEvent: (event) => {
        if (event.name === NEXUS_EVENTS.SWAP_STEP_COMPLETE) {
          console.log(`[${new Date().toISOString()}] ${event.args.type}`);
        }
      },
    });

    console.log('Swap successful:', result);
    return true;
  } catch (error) {
    console.error('Swap failed:', error);
    return false;
  }
}

// Execute swap
await executeSwap({
  from: [
    {
      chainId: 42161,
      tokenAddress: '0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9', // USDT on Arbitrum
      amount: 1_000_000_000n, // 1000 USDT
    },
  ],
  toChainId: 42161,
  toTokenAddress: '0xaf88d065e77c8cC2239327C5EDb3A432268e5831', // USDC on Arbitrum
});

Getting Balances for Swaps

Fetch available tokens before swapping:
// Get all swap-supported tokens
const allBalances = await sdk.getBalancesForSwap();

// Get only native tokens and stablecoins
const stableBalances = await sdk.getBalancesForSwap(true);

// Display balances
allBalances.forEach((asset) => {
  console.log(`${asset.symbol}: ${asset.balance} ($${asset.balanceInFiat})`);
  asset.breakdown.forEach((breakdown) => {
    console.log(`  ${breakdown.chain.name}: ${breakdown.balance}`);
  });
});

Swap Parameters

ExactInSwapInput

ParameterTypeRequiredDescription
fromArray<{ chainId, tokenAddress, amount }>YesSource tokens and amounts to swap
toChainIdnumberYesDestination chain ID
toTokenAddressHexYesOutput token contract address
Unlike bridge operations which use token symbols ('USDC'), swap operations require contract addresses. Use TOKEN_CONTRACT_ADDRESSES for convenience.

Swap Events

The SDK emits these events during swap execution:
const steps: string[] = [];

sdk.swapWithExactIn(params, {
  onEvent: (event) => {
    if (event.name === NEXUS_EVENTS.SWAP_STEP_COMPLETE) {
      const step = event.args;
      steps.push(step.type);

      switch (step.type) {
        case 'SWAP_START':
          console.log('Starting swap...');
          break;

        case 'DETERMINING_SWAP':
          console.log('Finding best route...');
          break;

        case 'SOURCE_SWAP_HASH':
          console.log('Source swap:', step.explorerURL);
          break;

        case 'DESTINATION_SWAP_HASH':
          console.log('Destination swap:', step.explorerURL);
          break;

        case 'SWAP_COMPLETE':
          console.log('Swap completed successfully!');
          break;

        case 'SWAP_SKIPPED':
          console.log('Swap skipped - balance already sufficient');
          break;
      }
    }
  },
});

Error Handling

import { NexusError, ERROR_CODES } from '@avail-project/nexus-core';

try {
  await sdk.swapWithExactIn(params);
} catch (error) {
  if (error instanceof NexusError) {
    switch (error.code) {
      case ERROR_CODES.INSUFFICIENT_BALANCE:
        console.error('Not enough tokens to complete swap');
        break;

      case ERROR_CODES.SWAP_FAILED:
        console.error('Swap operation failed:', error.data?.details);
        break;

      case ERROR_CODES.RATES_CHANGED_BEYOND_TOLERANCE:
        console.error('Price moved too much - refresh and retry');
        break;

      case ERROR_CODES.QUOTE_FAILED:
        console.error('Could not get swap quote - try again');
        break;

      default:
        console.error('Swap error:', error.message);
    }
  }
}

Supported Chains

Swap operations are available on these mainnet chains:
  • Base (8453)
  • Arbitrum One (42161)
  • Optimism (10)
  • Polygon (137)
  • Avalanche (43114)
  • Scroll (534352)
  • BNB Smart Chain (56)
Check supported chains programmatically:
const chains = sdk.getSwapSupportedChains();
console.log('Swap-enabled chains:', chains);

Next Steps

Swap Exact Out

Specify exact output amount instead of input

Bridge and Execute

Combine swaps with smart contract execution

Progress UI

Build real-time progress indicators

API Reference

View complete swap API documentation

Build docs developers (and LLMs) love