> ## Documentation Index
> Fetch the complete documentation index at: https://docs.delora.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Wallet & Receiver Management

> Built-in, auto-detected, and host-managed wallet flows for TradeWidget.

`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.

| Package                                    | Use for                                                  | Exports                                                                               |
| ------------------------------------------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `@deloraprotocol/widget`                   | Built-in wallet management and low-level manual adapters | `TradeWidget`, `TradeWidgetWalletProvider`, `useTradeWidgetWalletManagement`          |
| `@deloraprotocol/widget-wallet-management` | Ready-made adapters for common host wallet stacks        | Wagmi adapter, Solana Wallet Adapter adapter, composite adapter, auto-detect provider |

Install the optional package only when the host app already manages wallets:

```bash theme={null}
npm install @deloraprotocol/widget-wallet-management
```

Install the peer wallet stack you actually use:

```bash theme={null}
npm install wagmi
npm install @solana/wallet-adapter-react
```

Use subpath imports when installing only one wallet stack:

```ts theme={null}
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.

```tsx theme={null}
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 by default

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.requireWalletConsent` to `false` to hide the entire consent footer
and allow wallet selection without acceptance. When the footer is hidden,
`termsUrl` and `privacyPolicyUrl` are not rendered.

Set `config.walletConnectProjectId` to override the WalletConnect Cloud project id used by the built-in EVM QR flow.

### Control the built-in wallet picker

The `config.wallets` object controls only widget-managed wallet rows:

```tsx theme={null}
<TradeWidget
  config={{
    wallets: {
      order: ["walletconnect", "metamask", "solflare"],
      exclude: ["rabby-wallet"],
    },
  }}
/>
```

* `include` allows only the listed wallet ids.
* `exclude` removes listed wallet ids and takes precedence over `include`.
* `order` prioritizes listed, enabled wallets but leaves every other eligible wallet available in its normal group.

To expose only WalletConnect, use `include: ["walletconnect"]`. Do not use
`order` as an allowlist: ordering does not filter the picker.

Supported ids are `metamask`, `rabby-wallet`, `walletconnect`, `backpack`,
`phantom`, `solflare`, `trust-wallet`, `okx-wallet`, `coinbase-wallet`, and
`magic-eden`.

The same allowlist and denylist are checked during built-in session restoration.
An excluded or non-included persisted wallet is not reconnected automatically.
For partial wallet management, this configuration applies only to the namespaces
that still use Delora's built-in wallet flow. Host-provided `walletOptions`
remain controlled by the host.

## 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

```tsx theme={null}
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`.

```tsx theme={null}
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`.

```tsx theme={null}
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`.

```tsx theme={null}
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.

```tsx theme={null}
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.

```tsx theme={null}
<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.

```tsx theme={null}
<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.

```tsx theme={null}
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.

```tsx theme={null}
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](./widget-api-reference).
