Skip to main content
TradeWidget can manage wallets internally or reuse wallet state from the host application. The built-in wallet flow is enough for standalone embeds. Host wallet management is useful when your app already has wallet connection UI, account state, and providers. Current widget execution supports two wallet namespaces:
  • EVM for Ethereum-compatible chains
  • SVM for Solana-compatible chains
The widget also keeps origin and destination wallet state separate:
  • origin is the sell-side wallet and signs the transaction
  • destination is the optional receiver-side wallet on the buy side
Users can also paste a receiver address instead of connecting a destination wallet.

Packages

Wallet integration is split into two layers.
PackageUse forExports
@deloraprotocol/widgetBuilt-in wallet management and low-level manual adaptersTradeWidget, TradeWidgetWalletProvider, useTradeWidgetWalletManagement
@deloraprotocol/widget-wallet-managementReady-made adapters for common host wallet stacksWagmi adapter, Solana Wallet Adapter adapter, composite adapter, auto-detect provider
Install the optional package only when the host app already manages wallets:
npm install @deloraprotocol/widget-wallet-management
Install the peer wallet stack you actually use:
npm install wagmi
npm install @solana/wallet-adapter-react
Use subpath imports when installing only one wallet stack:
import { useWagmiManagedWallet } from "@deloraprotocol/widget-wallet-management/wagmi";
import { useSolanaWalletAdapterManagedWallet } from "@deloraprotocol/widget-wallet-management/solana";
The root package and @deloraprotocol/widget-wallet-management/auto import both adapters, so use them only when both optional peer stacks are available in your app.

Built-in wallet management

If you render TradeWidget by itself, the widget shows its own wallet connection UI and owns the wallet state.
import "@deloraprotocol/widget/styles.css";
import { TradeWidget } from "@deloraprotocol/widget";

export function WidgetPage() {
  return <TradeWidget theme="dark" config={{}} />;
}
The built-in wallet list currently includes:
  • MetaMask
  • Rabby Wallet
  • Wallet Connect
  • Backpack
  • Phantom
  • Solflare
  • Trust Wallet
  • OKX Wallet
  • Coinbase Wallet
  • Magic Eden
Built-in behavior:
  • EVM wallets use injected providers or WalletConnect
  • Solana wallets use injected providers or Wallet Standard providers
  • wallet selection is persisted in browser localStorage
  • the connect modal requires the user to accept Terms and Privacy Policy before connection
If config.termsUrl or config.privacyPolicyUrl is omitted, the modal falls back to same-origin /documentation/termsofuse and /documentation/privacypolicy links. Third-party embeds should pass explicit URLs. Set config.walletConnectProjectId to override the WalletConnect Cloud project id used by the built-in EVM QR flow.

Auto wallet management

DeloraAutoWalletManagementProvider is the auto-detected integration layer for apps that already use Wagmi and/or Solana Wallet Adapter. It detects those React contexts above the widget and wires them into TradeWidget. Use this when:
  • your EVM wallet UI is built on Wagmi, RainbowKit, Reown, Dynamic, or a similar Wagmi-based stack
  • your Solana wallet UI is built on Solana Wallet Adapter
  • you want the widget connect button to open the host app’s wallet modal
  • you want the widget to fall back to built-in wallets for namespaces the host does not manage
import "@deloraprotocol/widget/styles.css";
import { TradeWidget } from "@deloraprotocol/widget";
import { DeloraAutoWalletManagementProvider } from "@deloraprotocol/widget-wallet-management/auto";
import { useConnectModal } from "@rainbow-me/rainbowkit";
import { useWalletModal } from "@solana/wallet-adapter-react-ui";

export function WidgetPage() {
  const { openConnectModal } = useConnectModal();
  const { setVisible: setSolanaModalVisible } = useWalletModal();

  return (
    <DeloraAutoWalletManagementProvider
      evm={{
        walletOptions: [],
        openConnectModal: () => {
          openConnectModal?.();
        },
      }}
      solana={{
        walletOptions: [],
        openConnectModal: () => {
          setSolanaModalVisible(true);
        },
      }}
    >
      <TradeWidget config={{}} />
    </DeloraAutoWalletManagementProvider>
  );
}
The auto provider does not create Wagmi or Solana providers for you. It must be rendered below the host app’s WagmiProvider and, for Solana, below ConnectionProvider and WalletProvider from Solana Wallet Adapter. The example uses RainbowKit and Solana Wallet Adapter UI only as host wallet modals. Replace those callbacks with your own Wagmi-based or Solana wallet UI if your app uses a different provider.

EVM wallet connection

For EVM, the optional package reads wallet state from Wagmi through useWagmiManagedWallet.
import { TradeWidget } from "@deloraprotocol/widget";
import { DeloraWalletManagementProvider } from "@deloraprotocol/widget-wallet-management/provider";
import { useWagmiManagedWallet } from "@deloraprotocol/widget-wallet-management/wagmi";
import { useConnectModal } from "@rainbow-me/rainbowkit";

function WidgetWithWagmi() {
  const { openConnectModal } = useConnectModal();
  const evm = useWagmiManagedWallet({
    walletOptions: [],
    openConnectModal: () => {
      openConnectModal?.();
    },
  });

  return (
    <DeloraWalletManagementProvider wallet={evm}>
      <TradeWidget config={{}} />
    </DeloraWalletManagementProvider>
  );
}
useWagmiManagedWallet returns a TradeWidgetManagedWallet object with:
  • connected Wagmi address and connector name
  • EIP-1193 provider access through getEvmProvider
  • connect, disconnect, and error handlers
  • optional wallet rows derived from Wagmi connectors
The widget still performs execution itself. For EVM routes it switches to the selected sell chain with wallet_switchEthereumChain and falls back to wallet_addEthereumChain when the chain is missing from the wallet. If your host wallet UI restricts supported chains, keep that host configuration aligned with the chains you allow in the widget.

SVM wallet connection

For Solana, the optional package reads wallet state from Solana Wallet Adapter through useSolanaWalletAdapterManagedWallet.
import { TradeWidget } from "@deloraprotocol/widget";
import { DeloraWalletManagementProvider } from "@deloraprotocol/widget-wallet-management/provider";
import { useSolanaWalletAdapterManagedWallet } from "@deloraprotocol/widget-wallet-management/solana";
import { useWalletModal } from "@solana/wallet-adapter-react-ui";

function WidgetWithSolanaWalletAdapter() {
  const { setVisible } = useWalletModal();
  const solana = useSolanaWalletAdapterManagedWallet({
    walletOptions: [],
    openConnectModal: () => {
      setVisible(true);
    },
  });

  return (
    <DeloraWalletManagementProvider wallet={solana}>
      <TradeWidget config={{}} />
    </DeloraWalletManagementProvider>
  );
}
useSolanaWalletAdapterManagedWallet returns a TradeWidgetManagedWallet object with:
  • connected public key
  • wallet name and icon when available
  • connect, disconnect, and error handlers
  • a Solana provider wrapper that exposes signTransaction
  • optional wallet rows derived from Solana Wallet Adapter wallets
For Solana execution, the wallet must be able to sign a transaction. If the connected adapter does not expose signTransaction, execution cannot continue.

Connect button modes

The optional adapters support two host-wallet UX modes.

Host modal

Pass walletOptions: [] and openConnectModal.
useWagmiManagedWallet({
  walletOptions: [],
  openConnectModal: () => {
    openConnectModal?.();
  },
});
In this mode the Delora connect button opens your wallet UI directly. The widget waits until the host wallet state changes or the connection times out.

Widget picker

Omit walletOptions to let the adapter expose wallet rows to the Delora connect modal.
useWagmiManagedWallet({
  walletOptionIds: ["metamask", "rabby-wallet", "walletconnect"],
});
When the user selects a row, Delora delegates that selection back to the host adapter through connectWalletOption. For Wagmi, unknown or service connectors are hidden by default. Use:
  • walletOptionIds for an explicit allowlist
  • includeUnknownWalletOptions: true to expose custom connectors
For Solana Wallet Adapter, undetected adapters are hidden by default. Use includeUndetectedWallets: true when you want installable Solana wallet rows.

Partial wallet management

Partial wallet management lets the host manage one namespace while the widget keeps built-in management for the other namespace. Examples:
  • host manages EVM through Wagmi, Delora manages Solana internally
  • host manages Solana through Solana Wallet Adapter, Delora manages EVM internally
  • host manages both namespaces through a composite wallet adapter
DeloraAutoWalletManagementProvider enables partial wallet management by default.
<DeloraAutoWalletManagementProvider
  evm={evmOptions}
  solana={false}
  usePartialWalletManagement
>
  <TradeWidget config={{}} />
</DeloraAutoWalletManagementProvider>
Set usePartialWalletManagement={false} when the host wants full wallet ownership and does not want Delora to fall back to its built-in wallet flow for unmanaged namespaces.

Force internal wallet management

Use forceInternalWalletManagement on the auto provider to ignore detected host wallet contexts and use only Delora’s built-in wallet flow.
<DeloraAutoWalletManagementProvider forceInternalWalletManagement>
  <TradeWidget config={{}} />
</DeloraAutoWalletManagementProvider>
For the low-level TradeWidgetWalletProvider API, the equivalent is to not render the provider around TradeWidget.

Manual core provider

TradeWidgetWalletProvider is the low-level API from @deloraprotocol/widget. Use it when you have custom wallet state that is not represented by Wagmi or Solana Wallet Adapter.
import {
  TradeWidget,
  TradeWidgetWalletProvider,
} from "@deloraprotocol/widget";

<TradeWidgetWalletProvider
  value={{
    origin: {
      namespace: connected ? "EVM" : null,
      address: connectedAddress ?? null,
      walletName: "My App Wallet",
      evmProvider,
      connect: async ({ namespace }) => {
        await openWalletModal(namespace);
        return true;
      },
      disconnect: async () => {
        await disconnectWallet();
      },
    },
  }}
>
  <TradeWidget config={{}} />
</TradeWidgetWalletProvider>;
TradeWidgetWalletProvider is a React context provider. It does not connect to wallets by itself and it does not replace an EVM or Solana provider. Its job is to expose two optional wallet adapters to TradeWidget:
  • origin for the sell-side wallet
  • destination for the receiver-side wallet
When TradeWidget mounts, it reads that context and passes origin and destination into its wallet hooks. If one side is present, that side switches into externally managed mode. If one side is missing, the widget falls back to its built-in wallet flow for that side. This is presence-based, not connection-based. If you pass an origin or destination object at all, that side is considered externally managed even when namespace and address are currently null. If you want the widget to keep its built-in wallet flow for a side, omit that side from the provider value entirely.

What the widget reads from your wallet adapter

For each externally managed side, the widget reads values such as:
  • namespace
  • address
  • status
  • walletName
  • connectedWalletId
  • connectedWalletVisualId
  • connectedWalletIconUrl
  • errorMessage
So your application remains the source of truth for connection state, while the widget only renders that state. In externally managed mode, the host app is also responsible for pushing state updates back into the widget after connect, disconnect, account change, or chain change. The widget does not subscribe to external provider events on your behalf. The provider accepts:
  • origin for the sell-side wallet
  • destination for the receiver-side wallet
If one side is omitted, the widget falls back to its internal wallet flow for that side.

Managed wallet shape

At minimum, a managed wallet exposes:
  • namespace
  • address
To let the widget initiate connection, also provide at least one connect handler:
  • connectWalletOption
  • connectPreferred
  • connect
Additional fields let the widget render connection state and execute transactions:
  • status
  • managedNamespaces
  • walletsByNamespace
  • walletName
  • connectedWalletId, connectedWalletVisualId, connectedWalletIconUrl
  • walletOptions
  • evmProvider or getEvmProvider
  • evmBrowserProvider or getEvmBrowserProvider
  • solanaProvider or getSolanaProvider
  • walletStandardSolanaAccount or getConnectedWalletStandardSolanaAccount
  • disconnect
  • errorMessage, clearError, and peekLastConnectionError
When the widget connects an externally managed wallet, it delegates in this order:
  1. connectWalletOption(walletId, namespace)
  2. connectPreferred(namespace)
  3. connect(params)
If none of those handlers exists, the widget reports a wallet error instead of silently falling back for that externally managed side.

Composite wallets

Use useCompositeManagedWallet when EVM and Solana are managed by separate hooks but should be passed to the widget as one wallet object.
import { DeloraWalletManagementProvider } from "@deloraprotocol/widget-wallet-management/provider";
import { useCompositeManagedWallet } from "@deloraprotocol/widget-wallet-management/composite";

const wallet = useCompositeManagedWallet({ evm, solana });

<DeloraWalletManagementProvider wallet={wallet}>
  <TradeWidget config={{}} />
</DeloraWalletManagementProvider>;
The composite wallet exposes:
  • managedNamespaces for the namespaces it controls
  • walletsByNamespace so the widget can route EVM and Solana operations to the correct adapter
  • merged wallet rows for the connect modal

Receiver and destination behavior

The widget has a separate receiver flow on the buy side. At runtime, users can:
  • receive to the origin wallet when the buy-side namespace matches
  • connect a separate destination wallet
  • paste a receiver address directly in the UI
Pasted receiver addresses are validated and normalized for the active buy-side chain before execution. If a separate destination wallet is connected, it can be disconnected independently from the origin wallet. This works with all wallet-management modes:
  • built-in wallet management
  • auto wallet management through @deloraprotocol/widget-wallet-management
  • manual origin and destination adapters through TradeWidgetWalletProvider

Provider access and execution

Wallet management only provides connection state and provider access. Transaction orchestration stays inside TradeWidget. The widget still handles:
  • metadata and quote loading
  • balance checks
  • allowance checks
  • approve vs swap state transitions
  • transaction submission callbacks
  • confirmation callbacks
  • bridge and swap tracking
For externally managed EVM execution, the current widget implementation requires a raw EIP-1193 provider. Provide one of:
  • getEvmProvider()
  • evmProvider
The widget uses this provider to:
  • read the active account with eth_accounts
  • switch to the selected sell chain with wallet_switchEthereumChain
  • add missing chains with wallet_addEthereumChain
  • submit transactions with eth_sendTransaction
  • try EIP-5792 batching for approve plus swap when the wallet supports it
If the widget needs an ethers BrowserProvider, it wraps the raw EIP-1193 provider internally. evmBrowserProvider and getEvmBrowserProvider() are optional helpers, not a replacement for the raw provider in the current execution path. For externally managed Solana wallets, provide:
  • getSolanaProvider() or solanaProvider
For Wallet Standard Solana flows, also provide:
  • walletStandardSolanaAccount
  • getConnectedWalletStandardSolanaAccount()
For Solana execution, the widget uses:
  • Wallet Standard signAndSendTransaction when available
  • otherwise the connected wallet’s signTransaction
When an external side does not provide walletOptions, the widget calls the host’s connect function directly. When walletOptions are present, the widget can show its own wallet chooser and call the host’s connectWalletOption logic. Each option’s availableNamespaces should reflect the ecosystems that wallet can actually connect to.

Mental model

The shortest way to choose an integration is:
  • use plain TradeWidget for standalone embeds
  • use DeloraAutoWalletManagementProvider when your app already has Wagmi and/or Solana Wallet Adapter contexts
  • use TradeWidgetWalletProvider when you need a custom low-level adapter
For the full list of exported types, see Widget API Reference.