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 Nexus Core SDK, please refer to this page.
Quick Start
Wrap your app with NexusProvider
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
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:
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
Mainnet
| Network | Chain ID | Native Currency | Status | 
|---|---|---|---|
| Ethereum | 1 | ETH | ✅ | 
| Optimism | 10 | ETH | ✅ | 
| Polygon | 137 | MATIC | ✅ | 
| Arbitrum | 42161 | ETH | ✅ | 
| Avalanche | 43114 | AVAX | ✅ | 
| Base | 8453 | ETH | ✅ | 
| Scroll | 534352 | ETH | ✅ | 
| Sophon | 50104 | SOPH | ✅ | 
| Kaia | 8217 | KAIA | ✅ | 
| BNB | 56 | BNB | ✅ | 
| HyperEVM | 999 | HYPE | ✅ | 
Supported Tokens
| Token | Name | Decimals | Networks | 
|---|---|---|---|
| ETH | Ethereum | 18 | All EVM chains | 
| USDC | USD Coin | 6 | All supported | 
| USDT | Tether USD | 6 | All supported | 
Use Nexus Widgets
import {
  BridgeButton,
  TransferButton,
  BridgeAndExecuteButton,
  TOKEN_CONTRACT_ADDRESSES,
  TOKEN_METADATA,
  SUPPORTED_CHAINS,
  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>Component APIs
BridgeButton
Bridge tokens between chains with a customizable button interface.
interface BridgeButtonProps {
  title?: string; // Will appear once initialization is completed
  prefill?: Partial<BridgeParams>; // chainId, token, amount
  className?: string;
  children(props: { onClick(): void; isLoading: boolean }): React.ReactNode;
}Example:
<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).
interface TransferButtonProps {
  title?: string; // Will appear once initialization is completed
  prefill?: Partial<TransferParams>; // chainId, token, amount, recipient
  className?: string;
  children(props: { onClick(): void; isLoading: boolean }): React.ReactNode;
}Example:
<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.
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 initialization 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:
<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:
- Bridges the asset to toChainId
- Sets ERC-20 allowance if required
- Executes contractAddress.functionName(functionParams, { value })
Prefill Behavior
| Widget | Supported keys | Locked in UI | 
|---|---|---|
| BridgeButton | chainId,token,amount | ✅ | 
| TransferButton | chainId,token,amount,recipient | ✅ | 
| BridgeAndExecuteButton | toChainId,token,amount | ✅ | 
Values passed in prefill appear as read-only fields, enforcing your desired flow.
DeFi Protocol Integration
// 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
// 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
// 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
<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
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
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
// Good: Let the widget handle simulation internally
<BridgeButton>
  {({ onClick, isLoading }) => (
    <button onClick={onClick} disabled={isLoading}>
      Bridge
    </button>
  )}
</BridgeButton>2. Handle loading states gracefully
// 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
// 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
function MyComponent() {
  const { deinitializeSdk } = useNexus();
 
  useEffect(() => {
    return () => {
      deinitializeSdk();
    };
  }, []);
 
  return <BridgeButton>{/* ... */}</BridgeButton>;
}