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
Spending a specific amount of tokens
Liquidating positions
Converting all available balance
Fixed-budget transactions
Browser Example
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'.
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_000 n , // 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_000 n },
{ chainId: 42161 , tokenAddress: '0x...' , amount: 500_000_000 n },
]
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' ]));
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_000 n , // 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
Parameter Type Required Description fromArray<{ chainId, tokenAddress, amount }>Yes Source tokens and amounts to swap toChainIdnumberYes Destination chain ID toTokenAddressHexYes Output 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