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

# Configure Widget

> Props and runtime settings for configuring TradeWidget.

Use `TradeWidget` props to control the widget's runtime behavior, preselected assets, and available networks or tokens.

## Runtime configuration

All runtime options live under the required `config` prop.

```tsx theme={null}
<TradeWidget
  config={{
    apiKey: "your-api-key",
    apiUrl: "https://your-app.com/api/delora",
    rpcUrls: {
      1: [
        "https://your-primary-ethereum-rpc.example",
        "https://your-fallback-ethereum-rpc.example",
      ],
      1000000001: [
        "https://your-primary-solana-rpc.example",
        "https://your-fallback-solana-rpc.example",
      ],
    },
    integrator: "my-dapp",
    fee: 0.01,
    slippage: 0.005,
    walletConnectProjectId: "your-walletconnect-project-id",
    termsUrl: "/legal/terms",
    privacyPolicyUrl: "/legal/privacy",
    requireWalletConsent: true,
    wallets: {
      order: ["walletconnect", "metamask"],
      exclude: ["rabby-wallet"],
    },
    showPoweredByDelora: true,
    poweredByDeloraPosition: "center",
  }}
/>
```

By default, the widget uses `https://api.delora.build`. Set `apiUrl` when you want a custom upstream, such as your own backend proxy:

```tsx theme={null}
<TradeWidget
  config={{
    apiUrl: "https://your-app.com/api/delora",
    integrator: "my-dapp",
    fee: 0.01,
  }}
/>
```

Use `rpcUrls` to provide preferred endpoints for a supported chain. Map each numeric chain ID to an ordered URL array; the widget tries those URLs first and keeps its default endpoints as fallbacks. For supported chain IDs, see [Connected chains](/integrations/connected-chains).

| Field                     | Type                            | Description                                                                                                 |
| ------------------------- | ------------------------------- | ----------------------------------------------------------------------------------------------------------- |
| `apiUrl`                  | `string`                        | Optional Delora API base used for `/v1/chains`, `/v1/tokens`, `/v1/tools`, and `/v1/quotes`                 |
| `apiKey`                  | `string`                        | Optional `x-api-key` header for Delora API requests. Avoid using this directly in browser-rendered widgets. |
| `rpcUrls`                 | `TradeWidgetRpcUrlsByChainId`   | Preferred per-chain RPC endpoints used for on-chain reads and execution helpers                             |
| `integrator`              | `string`                        | Forwarded to quote requests                                                                                 |
| `fee`                     | `number`                        | Forwarded to quote requests. Valid range: `0..0.1`                                                          |
| `slippage`                | `number`                        | Initial slippage value. Valid range: `0..1`                                                                 |
| `excludeBridges`          | `string[]`                      | Quote denylist for bridges                                                                                  |
| `excludeExchanges`        | `string[]`                      | Quote denylist for exchanges                                                                                |
| `assetBaseUrl`            | `string`                        | Base URL for resolving relative token and network image paths                                               |
| `termsUrl`                | `string`                        | URL used in the wallet consent footer                                                                       |
| `privacyPolicyUrl`        | `string`                        | URL used in the wallet consent footer                                                                       |
| `requireWalletConsent`    | `boolean`                       | Require acceptance before choosing a wallet. Defaults to `true`; `false` hides the consent footer.          |
| `walletConnectProjectId`  | `string`                        | WalletConnect Cloud project id for the EVM QR flow                                                          |
| `wallets`                 | `TradeWidgetWalletConfig`       | Allowlist, denylist, and display order for widget-managed wallets                                           |
| `showPoweredByDelora`     | `boolean`                       | Show the linked Powered by Delora label. Defaults to `true`.                                                |
| `poweredByDeloraPosition` | `"left" \| "center" \| "right"` | Horizontal label position. Defaults to `"center"`.                                                          |

If `assetBaseUrl` is not set, it falls back to `config.apiUrl` and then to `https://api.delora.build`.

For browser-based widget integrations, prefer not to pass `apiKey` directly from the client. Instead:

* keep your Delora API key on your backend
* expose a proxy that forwards `/v1/chains`, `/v1/tokens`, `/v1/tools`, and `/v1/quotes` to `https://api.delora.build`
* point `config.apiUrl` to that proxy
* if your proxy does not also serve Delora relative image assets, set `assetBaseUrl: "https://api.delora.build"` or proxy those asset paths as well

`TradeWidget` already supports this pattern because all Delora API reads go through `config.apiUrl`.

If `termsUrl` or `privacyPolicyUrl` is omitted, the connect modal falls back to:

* `${window.location.origin}/documentation/termsofuse`
* `${window.location.origin}/documentation/privacypolicy`

For third-party embeds, it is usually better to set both URLs explicitly.

The consent footer is enabled by default. To remove the checkbox, links, and
acceptance requirement from the connect modal, set:

```tsx theme={null}
<TradeWidget
  config={{
    requireWalletConsent: false,
  }}
/>
```

When `requireWalletConsent` is `false`, `termsUrl` and `privacyPolicyUrl` are not
rendered because the entire consent footer is hidden.

## Configure built-in wallets

Use `config.wallets` to control the widget-managed wallet picker. These three
fields have independent purposes:

* `include` is an allowlist. When present, only listed wallets are eligible.
* `exclude` is a denylist. It removes listed wallets and takes precedence over `include`.
* `order` moves listed, enabled wallets to the front in the specified order. It does not hide unlisted wallets.

For example, offer only WalletConnect:

```tsx theme={null}
<TradeWidget
  config={{
    wallets: {
      include: ["walletconnect"],
    },
  }}
/>
```

Or prioritize WalletConnect, MetaMask, and Solflare while keeping all other
wallets except Rabby available:

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

Supported wallet ids are:

* `metamask`
* `rabby-wallet`
* `walletconnect`
* `backpack`
* `phantom`
* `solflare`
* `trust-wallet`
* `okx-wallet`
* `coinbase-wallet`
* `magic-eden`

Wallet filtering also applies to persisted built-in sessions, so an excluded or
non-included wallet is not restored automatically. Namespace compatibility still
applies after configuration; for example, WalletConnect is available for EVM and
Solflare is available for Solana.

`config.wallets` controls only built-in wallet management. When the host supplies
`walletOptions` through external wallet management, that host-provided array
remains the source of truth.

## Initial selections

You can preselect both networks and tokens.

```tsx theme={null}
<TradeWidget
  config={{}}
  initialSellNetworkId={1}
  initialBuyNetworkId={1000000001}
  initialSellToken={{
    chainId: 1,
    address: "0x0000000000000000000000000000000000000000",
  }}
  initialBuyToken={{
    chainId: 1000000001,
    address: "11111111111111111111111111111111",
  }}
/>
```

If an initial network or token is not available in loaded metadata, the widget reports it through `onError`. The same happens when a host-provided initial selection becomes invalid after filters are applied.

## Lock tokens or networks

Use lock props when you want the host app to keep part of the form fixed.

```tsx theme={null}
<TradeWidget
  config={{}}
  initialBuyToken={{ chainId: 1, address: "0xA0b86991c6218b36c1d19d4a2e9eb0ce3606eb48" }}
  lockBuyToken
/>
```

Supported lock props:

* `lockSellToken`
* `lockBuyToken`
* `lockSellNetwork`
* `lockBuyNetwork`

Behavior:

* Locking a token also locks its network, because the token already implies a chain
* Locking a network still allows token changes inside that network
* Any lock disables the center "swap sides" button to avoid breaking host-provided constraints

## Filter available networks and tokens

Use `filters` to restrict the sell and buy sides independently.

```tsx theme={null}
<TradeWidget
  config={{}}
  filters={{
    sell: {
      includeNetworkIds: [1, 8453],
      excludeTokens: [
        {
          chainId: 1,
          address: "0x0000000000000000000000000000000000000000",
        },
      ],
    },
    buy: {
      includeTokens: [
        {
          chainId: 1000000001,
          address: "11111111111111111111111111111111",
        },
      ],
    },
  }}
/>
```

Each side supports:

* `includeNetworkIds`
* `excludeNetworkIds`
* `includeTokens`
* `excludeTokens`

Important filter behavior:

* Filters are applied per side, so sell and buy restrictions can be different
* Networks that end up with no available tokens are removed automatically
* Conflicting filters produce `onError` events with `source: "configuration"`
* If no networks remain on a side after filtering, the widget enters a configuration error state

## Custom token lookup

When a side does not use `includeTokens`, the token selector can import a token by contract or mint address if the address is valid for the active network. Imported tokens become part of the current browser session and can also be restored from persisted selection state.

When `includeTokens` is set for a side, custom token import is disabled on that side.

## Persistence

The widget stores the latest selected sell and buy networks and tokens in browser `localStorage`, so the next mount can restore the previous selection when the host app does not explicitly override it.

Slippage and internal wallet choices are also persisted separately.

## Quote lifecycle and refresh behavior

The widget does not request a quote on every keystroke. Quote loading has a small client-side lifecycle:

* sell input is debounced by about 1 second before a quote request is sent
* successful quotes auto-refresh every 60 seconds while the current selection stays stable
* auto-refresh stops after 5 consecutive refresh cycles until the user changes the selection or amount
* the quote countdown ring in the UI can also be clicked to request a manual refresh immediately

The widget also applies a local cooldown around quote refreshes to avoid excessive request loops:

* more than 15 quote requests within 5 seconds starts a local cooldown
* the cooldown lasts 5 seconds
* during that window, the widget can emit `onError({ source: "quote", statusCode: 429 })` even if the backend did not return 429

If you build analytics or retry logic around quote errors, treat this as widget-side throttling as well as possible API-side rate limiting.
