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

# Widget configuration

> Configure deposit destinations, funding methods, routing, display, and shared widget props.

`DepositModal` handles funding method selection, source chain and token selection, amount input, and cross-chain routing. Complete the [widget quickstart](/deposits/overview/widget/quickstart) and [backend setup](/deposits/overview/widget/backend-setup) before configuring optional behavior.

## Destination

`recipient` is the address that receives funds on the target chain. The service-managed deposit account is derived from `(recipient, targetChain, targetToken)`, so it does not depend on the payment wallet. Changing the target changes the deposit address.

For a checkout, pass [an order-specific account salt](#checkout-payments) instead. Each order then has its own deposit address.

| Prop | Type | Required | Description |
| - | - | - | - |
| `targetChain` | `Chain \| number \| "solana" \| "hypercore:spot"` | Yes | Destination chain as a viem `Chain`, chain ID, or non-EVM identifier |
| `targetToken` | `Address \| string` | Yes | Token on the destination chain; use a base58 mint for Solana |
| `recipient` | `Address \| string` | Yes | Address receiving funds; use a base58 address for Solana |
| `defaultAmount` | `string` | No | Pre-filled USD amount, or `"max"` for the full available balance |
| `payment` | `PaymentConfig` | — | Checkout for one order: `{ salt: Hex, amount: string }`. Amount is destination token base units; salt is the order's registered account salt. |
| `sourceChain` | `Chain \| number` | No | Pre-selected source chain |
| `sourceToken` | `Address` | No | Pre-selected source token |
| `outputTokenRules` | `OutputTokenRule[]` | No | Route deposits to different final tokens based on the source deposit |
| `rejectUnmapped` | `boolean` | No | Reject an unmatched routing input instead of using `targetToken` |
| `appBalanceUsd` | `number` | No | Current in-app USD balance; shows the balance after deposit |

For supported destinations and assets, see [supported chains and tokens](/deposits/overview/resources/supported-chains-and-tokens).

## Checkout payments

Register a managed account for each order on your server with a unique 32-byte salt. Store the returned `evmDepositAddress` with the order, then pass the same salt and the required destination amount to the modal:

```tsx theme={null}
<DepositModal
  // ...required props, including the order's target and recipient
  payment={{ salt: order.salt, amount: order.amountBaseUnits }}
/>
```

`payment.amount` is an integer string in **destination token base units**. It is not a USD amount. The salt replaces the modal's normal `(recipient, targetChain, targetToken)` account derivation, so it must match the salt used in [managed account registration](/deposits/headless/setup/account-registration#register-an-account). The modal displays a fixed order amount and withholds the recipient's deposit history from the payer.

On the EVM wallet path, the modal asks `POST /quotes/preview` for an `exactOut` quote and uses its `input.amount` as the source amount to send. The proxy must forward that route to a processor that supports `exactOut`; an older processor cannot price the checkout. The quote is indicative, and a QR, exchange, or card payer can send a different amount.

Reconcile deposits against the order's account using [processor webhooks](/deposits/headless/processing-and-tracking/webhooks) or `GET /deposits?account=<orderAccount>`. Compare the delivered destination amount with the order amount before marking it paid. The modal's `complete` lifecycle event also carries `destinationAmount` in destination token base units when available.

## Account setup

The widget uses service-managed accounts. Rhinestone owns the deposit account and settles to your `recipient`, so there is no session key to configure and the user is not asked to sign during setup.

| Prop | Type | Default | Description |
| - | - | - | - |
| `forceRegister` | `boolean` | `false` | Re-register even when the account is cached. Registration remains idempotent |

### Restrict accepted sources

Your project's deposit whitelist controls the chains and tokens the processor accepts. Configure it through project setup rather than filtering the widget's source picker.

<Warning>
  A client-side filter can drift from the processor configuration and offer a source the processor rejects. The project whitelist is the enforced source of truth.
</Warning>

## Funding methods

Each enabled method appears on the widget home screen. When exactly one is enabled, the widget skips the chooser and opens that flow directly.

| Prop | Type | Default | Guide |
| - | - | - | - |
| `enableWallet` | `boolean` | `true` | [Deposit from a wallet](/deposits/crypto/deposit-from-a-wallet) |
| `enableQrTransfer` | `boolean` | `true` | [Deposit addresses and QR codes](/deposits/crypto/deposit-addresses-and-qr-codes) |
| `enableFiatOnramp` | `boolean` | `false` | [Accept fiat payments](/deposits/onramps/accept-fiat-payments) |
| `fiatMethods` | `FiatMethodsConfig` | Regional | [Payment methods and availability](/deposits/onramps/payment-methods-and-availability) |
| `enableExchangeConnect` | `boolean` | `false` | [Connect an exchange](/deposits/exchanges/connect-an-exchange) |
| `assetMigrations` | `AssetMigrationsConfig` | None | [Asset migrations](/deposits/crypto/asset-migrations) |
| `initialAssetMigration` | `keyof AssetMigrationsConfig` | — | Open directly into an enabled migration provider |

Fiat onramps and exchange connect require Swapped routes and credentials on your [backend proxy](/deposits/overview/widget/backend-setup).

## Output token routing

Pass `outputTokenRules` to choose the final token based on the source deposit. Rules can match chain, token address, or symbol. Unmatched deposits use `targetToken` unless `rejectUnmapped` is `true`.

```tsx theme={null}
<DepositModal
  // ...required props
  targetToken="0xFALLBACK_TOKEN_ADDRESS"
  outputTokenRules={[
    {
      match: { symbol: "USDC" },
      outputToken: "0x7f5c764cbc14f9669b88837ca1490cca17c31607",
    },
    {
      match: { symbol: "ETH" },
      outputToken: "0x4200000000000000000000000000000000000006",
    },
  ]}
/>
```

When several rules match, the most specific wins: `chain + token`, then `chain + symbol`, `token`, `symbol`, and `chain`. See [token routing](/deposits/headless/setup/token-routing) for full semantics and examples.

## Non-EVM destinations

### Solana

Use `targetChain="solana"`, a base58 mint as `targetToken`, and a base58 `recipient`. `rpcUrls` accepts a literal `solana` key when you need to override the default connection.

### HyperCore destinations

Use `targetChain="hypercore:spot"`, exported as `HYPERCORE_SPOT_CAIP2`. HyperCore accepts USDC only. `recipient` can be an EOA or smart account: delivery calls the MulticallHandler's `depositFor(recipient)`, which funds either address type without executing on the recipient.

A HyperCore destination names the venue it credits. Spot and perp margin are separate balances; deposits support spot only because the deposit account cannot produce the signature required to move funds back out of perp margin.

<Note>
  `targetChain: 1337`, exported as `HYPERCORE_CHAIN_ID`, is the older spelling and still resolves to the same venue and deposit address. Migrating to `HYPERCORE_SPOT_CAIP2` does not move user accounts.
</Note>

<Note>
  Earlier versions pre-screened recipient bytecode and could emit `HYPERCORE_RECIPIENT_NOT_EOA`. That check did not match orchestrator behavior and was removed in v0.9.0.
</Note>

HyperCore is also available as a transfer source. The address and QR flow uses the account's EVM address as the deposit address; a native Hyperliquid L1 spot transfer lands there.

## Display modes

The widget renders as a centered overlay by default. Set `inline={true}` to place it in your page layout without a backdrop.

```tsx theme={null}
<DepositModal
  isOpen
  onClose={() => {}}
  inline
  // ...other props
/>
```

Backdrop closing is opt-in with `closeOnOverlayClick={true}`. Configure visual appearance in [theming and customization](/deposits/overview/widget/theming-and-customization).

## Package entry points

Everything is exported from the root. Subpaths let you bundle only what you use.

| Import | Contains |
| - | - |
| `@rhinestone/deposit-modal` | Both modals, types, chain helpers, and token helpers |
| `@rhinestone/deposit-modal/deposit` | `DepositModal` and its types |
| `@rhinestone/deposit-modal/withdraw` | `WithdrawModal` and its types |
| `@rhinestone/deposit-modal/server` | `createRefundHandler`; server-only because it holds your API key |
| `@rhinestone/deposit-modal/constants` | `MODAL_VERSION`, chain registry, token helpers, and explorer helpers |
| `@rhinestone/deposit-modal/polymarket` | Headless [`getPolymarketAccount`](/deposits/crypto/asset-migrations#headless-account-lookup) |
| `@rhinestone/deposit-modal/styles.css` | Required stylesheet |

## Props reference

### Required

| Prop | Type | Description |
| - | - | - |
| `isOpen` | `boolean` | Controls widget visibility |
| `onClose` | `() => void` | Called when the user closes the widget |
| `targetChain` | `Chain \| number \| "solana" \| "hypercore:spot"` | Destination chain |
| `targetToken` | `Address \| string` | Destination token |
| `recipient` | `Address \| string` | Address receiving funds on the destination |
| `backendUrl` | `string` | Your [backend proxy](/deposits/overview/widget/backend-setup) |

### Wallet

| Prop | Type | Default | Description |
| - | - | - | - |
| `reownAppId` | `string` | — | Reown project ID; lets the widget connect a wallet |
| `walletClient` | `WalletClient \| null` | — | Wallet your app already connected; the widget reads `.account` |
| `publicClient` | `PublicClient \| null` | — | Read client paired with `walletClient`; defaults to the widget client |
| `enableWallet` | `boolean` | `true` | Offer wallet funding |
| `onRequestConnect` | `() => void` | — | Called when the widget needs your app to connect a wallet |

See [deposit from a wallet](/deposits/crypto/deposit-from-a-wallet) for widget-managed, app-supplied, and loading-state behavior.

### Transfer

| Prop | Type | Default | Description |
| - | - | - | - |
| `defaultAmount` | `string` | — | Pre-filled USD amount or `"max"` |
| `payment` | `PaymentConfig` | — | Checkout for one order: `{ salt: Hex, amount: string }`. Amount is destination token base units; salt is the order's registered account salt. |
| `sourceChain` | `Chain \| number` | — | Pre-selected source chain |
| `sourceToken` | `Address` | — | Pre-selected source token |
| `appBalanceUsd` | `number` | — | In-app USD balance used for the balance-after-deposit row |
| `outputTokenRules` | `OutputTokenRule[]` | — | Per-deposit output token rules |
| `rejectUnmapped` | `boolean` | `false` | Reject deposits that match no output rule |

### Funding

| Prop | Type | Default | Description |
| - | - | - | - |
| `enableWallet` | `boolean` | `true` | Offer a connected wallet as a source |
| `enableQrTransfer` | `boolean` | `true` | Offer the address and QR transfer flow |
| `enableFiatOnramp` | `boolean` | `false` | Offer fiat payment through Swapped |
| `fiatMethods` | `FiatMethodsConfig` | Regional | Restrict to `{ creditcard?, "bank-transfer"?, "apple-pay"? }`; empty means none |
| `enableExchangeConnect` | `boolean` | `false` | Offer Connect exchange through Swapped |
| `assetMigrations` | `AssetMigrationsConfig` | — | Enable supported migration providers |
| `initialAssetMigration` | `keyof AssetMigrationsConfig` | — | Open directly into an enabled migration provider |

### Account

| Prop | Type | Default | Description |
| - | - | - | - |
| `forceRegister` | `boolean` | `false` | Re-register even when the account is cached |

### Backend

| Prop | Type | Default | Description |
| - | - | - | - |
| `rpcUrls` | `RpcUrlMap` | Chain defaults | RPC overrides keyed by EVM chain ID or `solana`; applies to EVM clients, connected wallets, HyperEVM, and Solana |

### Display

| Prop | Type | Default | Description |
| - | - | - | - |
| `inline` | `boolean` | `false` | Render without the overlay |
| `closeOnOverlayClick` | `boolean` | `false` | Close when the backdrop is clicked |
| `className` | `string` | — | CSS class for the widget container |
| `theme` | `DepositModalTheme` | — | [Theme configuration](/deposits/overview/widget/theming-and-customization#theme) |
| `uiConfig` | `DepositModalUIConfig` | — | [UI configuration](/deposits/overview/widget/theming-and-customization#ui-configuration) |
| `debug` | `boolean` | `false` | Enable debug logging |

### Recovery

| Prop | Type | Default | Description |
| - | - | - | - |
| `signRecovery` | `SignRecovery` | — | Enable signed recovery from [history](/deposits/overview/widget/history-and-recovery#signing-contract); omit for read-only history |

### Callbacks

| Prop | Type | Description |
| - | - | - |
| `onReady` | `() => void` | Widget initialized |
| `onLifecycle` | `(event: DepositLifecycleEvent) => void` | Deposit state transitions; see [callbacks and error handling](/deposits/overview/widget/callbacks-and-error-handling#onlifecycle) |
| `onError` | `(data: ErrorEventData) => void` | Error at any stage |
| `onEvent` | `(event: DepositAnalyticsEvent \| ClaimAnalyticsEvent \| AnalyticsIngestFailureEvent) => void` | Funnel events and ingest diagnostics; see [analytics](/deposits/overview/widget/analytics) |

### Analytics

| Prop | Type | Default | Description |
| - | - | - | - |
| `enableAnalyticsIngest` | `boolean` | `true` | Send session analytics to Rhinestone. `false` disables collection without changing `onEvent` |

## Content security policy

The widget loads chain, token, and exchange logos from Rhinestone's asset CDN. Apps with an explicit `img-src` must allow it:

```text theme={null}
img-src 'self' data: https://s3.rhinestone.dev;
```

A blocked image fails silently and renders blank. Apps without an explicit `img-src`, or with `img-src *`, need no change.

Fiat onramps and Connect exchange embed Swapped in an iframe, so those flows also need:

```text theme={null}
frame-src https://widget.swapped.com https://sandbox.swapped.com https://connect.swapped.com;
```

Deposit and withdraw sessions send analytics from the browser. An explicit `connect-src` must include Rhinestone, your proxy, and every RPC override:

```text theme={null}
connect-src 'self' https://v1.orchestrator.rhinestone.dev https://your-proxy.example.com;
```

That directive controls every widget request, not only analytics. A blocked ingest origin does not interrupt deposits, but it drops analytics and reports an `analytics_ingest_failure` event with `reason: "network"`; see [analytics](/deposits/overview/widget/analytics#ingest-failures).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.