Skip to Content
Avail Nexus is now live! Check out our docs to get started.

Avail Nexus SDK API Reference

The Avail Nexus SDK provides a comprehensive set of APIs for cross-chain bridging, token transfers, and balance management across multiple EVM chains.

Note:
This page will focus on the UI widgets available as part of the Avail Nexus SDK. If you are looking for the API reference for the headless SDK, please refer to this page.

Quick Start

Wrap your app with NexusProvider

TSX
import { NexusProvider } from '@avail-project/nexus-widgets'; export default function App() { return ( <NexusProvider config={{ debug: false, // true to view debug logs network: 'testnet', // "mainnet" (default) or "testnet" }} > <YourApp /> </NexusProvider> ); }

Forward the user’s wallet provider

TSX
import { useEffect } from 'react'; import { useAccount } from '@wagmi/react'; // any wallet lib works import { useNexus } from '@avail-project/nexus-widgets'; export function WalletBridge() { const { connector, isConnected } = useAccount(); const { setProvider } = useNexus(); useEffect(() => { if (isConnected && connector?.getProvider) { connector.getProvider().then(setProvider); } }, [isConnected, connector, setProvider]); return null; }

Alternative: Manual SDK Initialization

For developers who need to use SDK methods directly (like getUnifiedBalances) before using UI components:

TSX
import { useNexus } from '@avail-project/nexus-widgets'; function MyComponent() { const { initializeSdk, sdk, isSdkInitialized } = useNexus(); const handleInitialize = async () => { const provider = await window.ethereum; // or get from your wallet library await initializeSdk(provider); // Initializes both SDK and UI state // Now you can use SDK methods directly const balances = await sdk.getUnifiedBalances(); console.log('Balances:', balances); // UI components will already be initialized when used }; return ( <button onClick={handleInitialize} disabled={isSdkInitialized}> {isSdkInitialized ? 'SDK Ready' : 'Initialize SDK'} </button> ); }

Benefits of manual initialization:

  • Use SDK methods immediately after initialization
  • No duplicate initialization when UI components are used
  • Full control over initialization timing
  • Access to unified balances and other SDK features before transactions

Configuration Options

Supported Chains

NetworkChain IDNative CurrencyStatus
Ethereum1ETH
Optimism10ETH
Polygon137MATIC
Arbitrum42161ETH
Avalanche43114AVAX
Base8453ETH
Scroll534352ETH
Sophon50104SOPH
Kaia8217KAIA
BNB56BNB
HyperEVM999HYPE

Supported Tokens

TokenNameDecimalsNetworks
ETHEthereum18All EVM chains
USDCUSD Coin6All supported
USDTTether USD6All supported

Use Nexus Widgets

TSX
import { BridgeButton, TransferButton, BridgeAndExecuteButton, SwapButton, TOKEN_CONTRACT_ADDRESSES, TOKEN_METADATA, SUPPORTED_CHAINS, DESTINATION_SWAP_TOKENS, type SUPPORTED_TOKENS, type SUPPORTED_CHAIN_IDS } from '@avail-project/nexus-widgets'; import { parseUnits } from 'viem'; /* Bridge ----------------------------------------------------------- */ <BridgeButton prefill={{ chainId: 137, token: 'USDC', amount: '100' }}> {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading}> {isLoading ? 'Bridging…' : 'Bridge 100 USDC → Polygon'} </button> )} </BridgeButton> /* Transfer --------------------------------------------------------- */ <TransferButton> {({ onClick }) => <YourStyledBtn onClick={onClick}>Send Funds</YourStyledBtn>} </TransferButton> /* Bridge + Execute ------------------------------------------------- */ <BridgeAndExecuteButton contractAddress={'0x794a61358D6845594F94dc1DB02A252b5b4814aD'} contractAbi={ [ { name: 'supply', type: 'function', stateMutability: 'nonpayable', inputs: [ { name: 'asset', type: 'address' }, { name: 'amount', type: 'uint256' }, { name: 'onBehalfOf', type: 'address' }, { name: 'referralCode', type: 'uint16' }, ], outputs: [], }, ] as const } functionName="supply" buildFunctionParams={(token, amount, _chainId, user) => { const decimals = TOKEN_METADATA[token].decimals const amountWei = parseUnits(amount, decimals) const tokenAddr = TOKEN_CONTRACT_ADDRESSES[token][_chainId] return { functionParams: [tokenAddr, amountWei, user, 0] } }} prefill={{ toChainId: 42161, token: 'USDT', }} > {({ onClick, isLoading }) => ( <Button onClick={onClick} disabled={isLoading} className="w-full" > {isLoading ? 'Processing…' : 'Bridge & Stake'} </Button> )} </BridgeAndExecuteButton> /* Swap | EXACT_IN ------------------------------------------------------------- */ <SwapButton prefill={{ fromChainID: 137, fromTokenAddress: 'USDC', toChainID: 1, toTokenAddress: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', fromAmount: '100' }} > {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading}> {isLoading ? 'Swapping…' : 'Swap USDC to ETH'} </button> )} </SwapButton>

Component APIs

BridgeButton

Bridge tokens between chains with a customizable button interface.

TSX
interface BridgeButtonProps { title?: string; // Will appear once intialization is completed prefill?: Partial<BridgeParams>; // chainId, token, amount className?: string; children(props: { onClick(): void; isLoading: boolean }): React.ReactNode; }

Example:

TSX
<BridgeButton prefill={{ chainId: 137, token: 'USDC', amount: '100' }}> {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading}> {isLoading ? 'Bridging…' : 'Bridge USDC to Polygon'} </button> )} </BridgeButton>

TransferButton

Send tokens to any address with automatic optimization (direct transfer when possible).

TSX
interface TransferButtonProps { title?: string; // Will appear once intialization is completed prefill?: Partial<TransferParams>; // chainId, token, amount, recipient className?: string; children(props: { onClick(): void; isLoading: boolean }): React.ReactNode; }

Example:

TSX
<TransferButton prefill={{ chainId: 42161, token: 'USDC', amount: '50', recipient: '0x742d35Cc6634C0532925a3b8D4C9db96c4b4Db45', }} > {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading}> {isLoading ? 'Sending…' : 'Send 50 USDC'} </button> )} </TransferButton>

BridgeAndExecuteButton

Bridge tokens and execute a smart contract function in a single flow.

TSX
type DynamicParamBuilder = ( token: SUPPORTED_TOKENS, amount: string, chainId: SUPPORTED_CHAINS_IDS, userAddress: `0x${string}`, ) => { functionParams: readonly unknown[]; value?: string; // wei; defaults to "0" }; interface BridgeAndExecuteButtonProps { title?: string; // Will appear once intialization is completed contractAddress: `0x${string}`; // REQUIRED contractAbi: Abi; // REQUIRED functionName: string; // REQUIRED buildFunctionParams: DynamicParamBuilder; // REQUIRED prefill?: { toChainId?: number; token?: SUPPORTED_TOKENS; amount?: string }; className?: string; children(props: { onClick(): void; isLoading: boolean; disabled: boolean }): React.ReactNode; }

Example - Aave Supply:

TSX
<BridgeAndExecuteButton contractAddress="0x794a61358D6845594F94dc1DB02A252b5b4814aD" // Aave Pool contractAbi={ [ { name: 'supply', type: 'function', stateMutability: 'nonpayable', inputs: [ { name: 'asset', type: 'address' }, { name: 'amount', type: 'uint256' }, { name: 'onBehalfOf', type: 'address' }, { name: 'referralCode', type: 'uint16' }, ], outputs: [], }, ] as const } functionName="supply" buildFunctionParams={(token, amount, chainId, userAddress) => { const decimals = TOKEN_METADATA[token].decimals; const amountWei = parseUnits(amount, decimals); const tokenAddress = TOKEN_CONTRACT_ADDRESSES[token][chainId]; return { functionParams: [tokenAddress, amountWei, userAddress, 0], }; }} prefill={{ toChainId: 1, token: 'USDC' }} > {({ onClick, isLoading, disabled }) => ( <button onClick={onClick} disabled={isLoading || disabled}> {isLoading ? 'Processing…' : 'Bridge & Supply to Aave'} </button> )} </BridgeAndExecuteButton>

buildFunctionParams receives the validated UX input (token, amount, destination chainId) plus the connected wallet address and must return the encoded functionParams (and optional ETH value) used in the destination call.

Nexus then:

  1. Bridges the asset to toChainId
  2. Sets ERC-20 allowance if required
  3. Executes contractAddress.functionName(functionParams, { value })

SwapButton

Cross-chain token swapping with support for both EXACT_IN and EXACT_OUT modes.

TSX
interface SwapButtonProps { title?: string; // Will appear once initialization is completed prefill?: Omit<SwapInputData, 'toAmount'>; // fromChainID, toChainID, fromTokenAddress, toTokenAddress, fromAmount className?: string; children(props: { onClick(): void; isLoading: boolean }): React.ReactNode; } interface SwapInputData { fromChainID?: number; toChainID?: number; fromTokenAddress?: string; toTokenAddress?: string; fromAmount?: string | number; toAmount?: string | number; }

EXACT_IN Swap Example:

TSX
// Swap exactly 100 USDC from Polygon to LDO on Arbitrum <SwapButton prefill={{ fromChainID: 137, // Polygon fromTokenAddress: 'USDC', toChainID: 42161, // Arbitrum toTokenAddress: 'LDO', // LDO fromAmount: '100', // Exact input amount }} > {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading}> {isLoading ? 'Swapping...' : 'Swap 100 USDC → ETH'} </button> )} </SwapButton>

Swap Utilities

Discovering Available Swap Options

TSX
import { useNexus, DESTINATION_SWAP_TOKENS } from '@avail-project/nexus-widgets'; function SwapOptionsExample() { const { sdk, isSdkInitialized } = useNexus(); const [swapOptions, setSwapOptions] = useState(null); useEffect(() => { if (isSdkInitialized) { // Get supported source chains and tokens for swaps const supportedOptions = sdk.utils.getSwapSupportedChainsAndTokens(); setSwapOptions(supportedOptions); } }, [sdk, isSdkInitialized]); return ( <div> {/* Source chains and tokens */} {swapOptions?.map(chain => ( <div key={chain.id}> <h3>{chain.name} (Chain ID: {chain.id})</h3> {chain.tokens.map(token => ( <div key={token.tokenAddress}> {token.symbol}: {token.tokenAddress} </div> ))} </div> ))} {/* Popular destination options */} <h3>Popular Destinations:</h3> {Array.from(DESTINATION_SWAP_TOKENS.entries()).map(([chainId, tokens]) => ( <div key={chainId}> <h4>Chain {chainId}</h4> {tokens.map(token => ( <div key={token.tokenAddress}> {token.symbol} - {token.name} </div> ))} </div> ))} </div> ); }

Key Points:

  • Source restrictions: Source chains/tokens are limited to what getSwapSupportedChainsAndTokens() returns
  • Destination flexibility: Destination can be any supported chain and token address
  • DESTINATION_SWAP_TOKENS: Provides popular destination options for UI building, but is not exhaustive

Prefill Behavior

WidgetSupported keysLocked in UI
BridgeButtonchainId, token, amount
TransferButtonchainId, token, amount, recipient
BridgeAndExecuteButtontoChainId, token, amount
SwapButtonfromChainID, toChainID, fromTokenAddress, toTokenAddress, fromAmount, toAmount

Values passed in prefill appear as read-only fields, enforcing your desired flow.

Widget Examples

Cross-Chain Swapping

TSX
// Multi-step cross-chain swap with destination selection <SwapButton> {({ onClick, isLoading }) => ( <div className="swap-card bg-gradient-to-r from-purple-500 to-blue-600 p-6 rounded-lg text-white"> <h3 className="text-xl font-bold mb-2">Cross-Chain Swap</h3> <p className="mb-4">Swap tokens across any supported chains</p> <button onClick={onClick} disabled={isLoading} className="bg-white text-purple-600 px-6 py-2 rounded-full font-semibold hover:bg-gray-100" > {isLoading ? ( <div className="flex items-center"> <Spinner className="mr-2" /> Processing Swap... </div> ) : ( 'Start Swap' )} </button> </div> )} </SwapButton> // Fixed-route swap for arbitrage or specific pairs <SwapButton prefill={{ fromChainID: 42161, // Arbitrum fromTokenAddress: 'USDC', toChainID: 10, // Optimism toTokenAddress: '0x4200000000000000000000000000000000000006', // WETH fromAmount: '1000', }} > {({ onClick, isLoading }) => ( <div className="arbitrage-card"> <h3>Arbitrage Opportunity</h3> <p>Better WETH rates on Optimism</p> <button onClick={onClick} disabled={isLoading}> {isLoading ? 'Executing...' : 'Swap 1000 USDC → WETH'} </button> </div> )} </SwapButton>

DeFi Protocol Integration

TSX
// Compound V3 Supply Widget <BridgeAndExecuteButton contractAddress="0xc3d688B66703497DAA19211EEdff47f25384cdc3" // Compound V3 USDC contractAbi={ [ { inputs: [ { internalType: 'address', name: 'asset', type: 'address' }, { internalType: 'uint256', name: 'amount', type: 'uint256' }, ], name: 'supply', outputs: [], stateMutability: 'nonpayable', type: 'function', }, ] as const } functionName="supply" buildFunctionParams={(token, amount, chainId, userAddress) => { const decimals = TOKEN_METADATA[token].decimals; const amountWei = parseUnits(amount, decimals); const tokenAddress = TOKEN_CONTRACT_ADDRESSES[token][chainId]; return { functionParams: [tokenAddress, amountWei], }; }} prefill={{ toChainId: 1, token: 'USDC' }} > {({ onClick, isLoading }) => ( <div className="bg-blue-500 hover:bg-blue-600 rounded-lg p-4"> <h3 className="text-white font-bold">Earn with Compound</h3> <button onClick={onClick} disabled={isLoading} className="mt-2 bg-white text-blue-500 px-4 py-2 rounded" > {isLoading ? 'Processing...' : 'Supply & Earn'} </button> </div> )} </BridgeAndExecuteButton>

Simple Payment Flow

TSX
// Payment button for e-commerce <TransferButton prefill={{ token: 'USDC', amount: '25.00', recipient: merchantAddress, chainId: 137, // Polygon for low fees }} > {({ onClick, isLoading }) => ( <button className="checkout-btn" onClick={onClick} disabled={isLoading}> {isLoading ? 'Processing Payment...' : 'Pay $25 USDC'} </button> )} </TransferButton>

Multi-Chain Liquidity

TSX
// Bridge to specific chain for better rates <BridgeButton prefill={{ chainId: 42161, token: 'ETH', amount: '0.1' }}> {({ onClick, isLoading }) => ( <div className="liquidity-card"> <h3>Better rates on Arbitrum</h3> <p>Save 60% on gas fees</p> <button onClick={onClick} disabled={isLoading}> {isLoading ? 'Bridging...' : 'Bridge to Arbitrum'} </button> </div> )} </BridgeButton>

Advanced Usage

Custom Loading States

TSX
<BridgeButton prefill={{ chainId: 137, token: 'USDC', amount: '100' }}> {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading} className={`btn ${isLoading ? 'btn-loading' : 'btn-primary'}`} > {isLoading ? ( <div className="flex items-center"> <Spinner className="mr-2" /> Bridging USDC... </div> ) : ( 'Bridge 100 USDC → Polygon' )} </button> )} </BridgeButton>

Error Handling

TSX
function MyBridgeComponent() { const [error, setError] = useState(null); return ( <div> {error && <div className="error-banner">{error}</div>} <BridgeButton prefill={{ chainId: 137, token: 'USDC', amount: '100' }}> {({ onClick, isLoading }) => ( <button onClick={async () => { try { setError(null); await onClick(); } catch (err) { setError(err.message); } }} disabled={isLoading} > {isLoading ? 'Processing...' : 'Bridge USDC'} </button> )} </BridgeButton> </div> ); }

Access to SDK Methods

TSX
function BalanceAwareWidget() { const { sdk, isSdkInitialized } = useNexus(); const [balances, setBalances] = useState([]); useEffect(() => { if (isSdkInitialized) { sdk.getUnifiedBalances().then(setBalances); } }, [sdk, isSdkInitialized]); return ( <div> <div className="balances"> {balances.map((balance) => ( <div key={balance.symbol}> {balance.symbol}: {balance.balance} </div> ))} </div> <BridgeButton> {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading}> Bridge Assets </button> )} </BridgeButton> </div> ); }

Best Practices

1. Always simulate first

TSX
// Good: Let the widget handle simulation internally <BridgeButton> {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading}> Bridge </button> )} </BridgeButton>

2. Handle loading states gracefully

TSX
// Good: Provide clear feedback <TransferButton> {({ onClick, isLoading }) => ( <button onClick={onClick} disabled={isLoading}> {isLoading ? ( <div className="flex items-center"> <Spinner className="mr-2" /> Transferring... </div> ) : ( 'Send Tokens' )} </button> )} </TransferButton>

3. Use appropriate confirmation levels

TSX
// Good: For high-value transactions, the widget will automatically // request higher confirmation levels <BridgeAndExecuteButton prefill={{ amount: '10000' }}> {/* Widget handles confirmation requirements */} </BridgeAndExecuteButton>

4. Clean up resources

TSX
function MyComponent() { const { deinitializeSdk } = useNexus(); useEffect(() => { return () => { deinitializeSdk(); }; }, []); return <BridgeButton>{/* ... */}</BridgeButton>; }
Last updated on