Nexus Elements - Deposit
Install
- Install widget:
npx shadcn@latest add @nexus-elements/deposit
- Ensure
NexusProvider is installed and initialized before rendering.
Required setup before rendering
- Ensure
useNexus().nexusSDK is initialized.
- Ensure
exchangeRate contains destination token rate (widget requires it for amount simulation).
- Provide a correct
destination config and executeDeposit builder.
- If using the built-in
MAX interaction, ensure the widget can compute current source selections so it can call sdk.calculateMaxForSwap(...).
Initialize SDK (required once per app)
- On wallet connect, resolve an EIP-1193 provider and call
useNexus().handleInit(provider).
- Wait for
useNexus().nexusSDK before allowing amount confirmation.
- Re-run init after reconnect if wallet session resets.
Render widget
"use client";
import NexusDeposit from "@/components/deposit/nexus-deposit";
import {
SUPPORTED_CHAINS,
TOKEN_CONTRACT_ADDRESSES,
TOKEN_METADATA,
CHAIN_METADATA,
} from "@avail-project/nexus-core";
import { encodeFunctionData, type Abi } from "viem";
export function DepositPanel() {
return (
<NexusDeposit
heading="Deposit USDC"
destination={{
chainId: SUPPORTED_CHAINS.BASE,
tokenAddress: TOKEN_CONTRACT_ADDRESSES["USDC"][SUPPORTED_CHAINS.BASE],
tokenSymbol: "USDC",
tokenDecimals: TOKEN_METADATA["USDC"].decimals,
tokenLogo: TOKEN_METADATA["USDC"].icon,
label: "Deposit to protocol",
gasTokenSymbol: CHAIN_METADATA[SUPPORTED_CHAINS.BASE].nativeCurrency.symbol,
explorerUrl: CHAIN_METADATA[SUPPORTED_CHAINS.BASE].blockExplorerUrls[0],
estimatedTime: "~30s",
}}
executeDeposit={(tokenSymbol, tokenAddress, amount, _chainId, user) => {
const contract = "0x0000000000000000000000000000000000000000" as const;
const abi: Abi = [
{
type: "function",
name: "deposit",
stateMutability: "nonpayable",
inputs: [
{ name: "asset", type: "address" },
{ name: "amount", type: "uint256" },
{ name: "beneficiary", type: "address" },
],
outputs: [],
},
];
const data = encodeFunctionData({
abi,
functionName: "deposit",
args: [tokenAddress, amount, user],
});
return {
to: contract,
data,
tokenApproval: {
token: tokenAddress,
amount,
spender: contract,
},
};
}}
onSuccess={() => {
// success
}}
onError={(message) => {
console.error(message);
}}
/>
);
}
Live prop contract
- Required:
destination: DestinationConfig
executeDeposit(tokenSymbol, tokenAddress, amount, chainId, user)
- Optional:
heading, embed, className
open, onOpenChange, defaultOpen (dialog mode)
onSuccess, onError, onClose
SDK flow details (under the hood)
- Main execute call:
sdk.swapAndExecute({ toChainId, toTokenAddress, toAmount, fromSources?, execute }, { onEvent })
- Max amount call:
sdk.calculateMaxForSwap({ toChainId, toTokenAddress, fromSources? })
- Step and status behavior:
- amount step starts simulation-loading
- waits for
swapIntent hook to enter previewing state
- confirm order calls
activeIntent.allow() and moves to executing
- Event mapping:
- listens to
NEXUS_EVENTS.SWAP_STEP_COMPLETE
- handles
DETERMINING_SWAP and SWAP_SKIPPED
- Fee handling:
- destination execute receipt computes actual gas USD in success path
Important amount semantics
- Amount input is interpreted as USD in this widget flow.
- Widget converts USD amount to destination token amount via provider exchange rates.
MAX is destination-token aware:
- widget computes
MaxSwapInput from the current destination and selected source pool
- widget calls
sdk.calculateMaxForSwap(...)
- returned destination-token max is converted back to USD for the input field
- If destination token exchange rate is missing/invalid, widget shows error and blocks confirmation.
Source selection semantics
- Amount changes reset source selection back to auto mode.
- In auto mode, the widget derives source balances from the current filter and current widget logic before simulation.
- Preset filters in the source picker (
Any token, Stablecoins, Native) act as explicit source selections for that pool.
- Manual source edits are treated as exact selected sources until the amount changes again.
Pay using and the fromSources sent to sdk.swapAndExecute(...) should reflect the same current source set.
Preview cancellation behavior
- Backing out from the confirmation screen before
activeIntent.allow() denies the preview intent.
- This intentional preview cancellation should not surface as the widget's own local error banner, though external
onError handlers may still observe the rejection if the app wants it.
E2E verification
- Enter amount and continue to confirmation.
- Confirm simulation appears and updates every polling cycle.
- Confirm order and verify status screen transitions.
- Verify both source and destination explorer links when available.
- Verify
onSuccess and balance refresh after completion.
- Verify error screen appears on failed simulation/execution.
Common failure cases
Nexus SDK is not initialized:
- ensure
handleInit(provider) ran after wallet connect.
Unable to fetch pricing for <token>:
- ensure rates loaded in provider and token symbol is valid.
- Execute revert:
- validate
executeDeposit target, calldata, and token approval spender.