Skip to main content
Install the @rhinestone/deposit-modal package, render the modal, and handle a completed deposit. This quickstart has the modal connect the wallet itself, via Reown. If you don’t want to set up Reown, the modal also works with a wallet your app already has connected (Privy, Dynamic, Turnkey, wagmi) or with no wallet at all — QR transfer, fiat on-ramp, or exchange connect.

Prerequisites

  • A React 18+ app (Next.js, Vite, or similar)
  • A Rhinestone API key
  • A Reown project ID, if the modal is connecting the wallet

Install

If you want the modal to connect the wallet — that is, you pass reownAppId — add all five of these:
The Solana three are not optional on this path, despite being marked optional peers. Reown’s connect view always registers the Solana adapter, so the chunk that loads it imports all three statically — an EVM-only app that omits them gets a module-resolution failure when the modal opens.
Supply your own walletClient instead and you need none of the five. Reown is imported lazily, so it stays out of your bundle entirely — which is what makes them optional peers in package.json.
The modal ships with its own wagmi and @tanstack/react-query providers — you do not need to wrap your app with WagmiProvider or QueryClientProvider. The package ships no "use client" directive, so in the Next.js App Router put it in a component that has one.
1

Run a backend

The modal can’t hold your API key, so every request it makes goes through a proxy you run. Clone Rhinestone’s and start it locally:
No Bun? docker build -t deposit-widget-proxy . && docker run -p 4000:4000 -e RHINESTONE_API_KEY=your-key deposit-widget-proxy does the same.Check it:
You should see {"ok":true}. That URL is your backendUrl below. See backend for deploying it properly, or for writing your own instead.
2

Render the deposit modal

Import the modal and its styles. Pass the target chain, token, and your Reown project ID.
Click the button and the modal should open on the wallet-connect screen. From there the user picks a source chain and token, enters an amount, and confirms the deposit; bridging to the target chain is handled automatically.If the modal opens but the token list is empty, the proxy isn’t reachable — check the terminal running it.
3

Handle completion

Add the onLifecycle callback and react to the "complete" event when tokens arrive on the target chain.
onLifecycle is a single callback that emits every state transition as a discriminated event — switch on event.type. See status tracking for all event variants and payloads.

Before production

localhost:4000 is fine while you build, not for your users. Deploy the proxy somewhere real and point backendUrl at it — see backend for the routes it must forward. This quickstart runs on mainnet, so a deposit moves real funds. Start with an amount you don’t mind losing to a mistake. You’ll also want webhooks for anything that must happen whether or not the modal is still open. See it running in the live demo, whose source is a working integration you can read.

Next steps

Deposit modal

Wallet options, funding methods, transfer configuration, and full props reference.

Customization

Theme and UI configuration.

Status tracking

Lifecycle events, callbacks, and error handling.

Withdraw modal

Withdraw tokens to any supported chain, with your app performing the transfer.

Claim modal

Let users recover a failed or rejected deposit from its transaction hash.