02
Quickstart
Minimal integration for both deposit and withdraw from @rhinestone/deposit-modal.
1) Install + styles
bash
bun add @rhinestone/deposit-modal
tsx
import "@rhinestone/deposit-modal/styles.css";
2) Deposit
tsx
import { DepositModal } from "@rhinestone/deposit-modal";
<DepositModal
isOpen={isDepositOpen}
onClose={() => setDepositOpen(false)}
reownAppId={process.env.NEXT_PUBLIC_REOWN_PROJECT_ID!}
targetChain={8453}
targetToken="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" // USDC on Base
recipient="0xYourRecipient"
onLifecycle={(event) => {
if (event.type === "complete") console.log("deposit complete", event);
if (event.type === "failed") console.log("deposit failed", event);
}}
/>3) Withdraw
tsx
import { WithdrawModal } from "@rhinestone/deposit-modal";
<WithdrawModal
isOpen={isWithdrawOpen}
onClose={() => setWithdrawOpen(false)}
reownAppId={process.env.NEXT_PUBLIC_REOWN_PROJECT_ID!}
safeAddress="0xYourSafe"
sourceChain={8453}
sourceToken="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913" // USDC on Base
targetChain={42161}
targetToken="0xaf88d065e77c8cC2239327C5EDb3A432268e5831" // USDC on Arbitrum
recipient="0xYourRecipient"
onLifecycle={(event) => {
if (event.type === "complete") console.log("withdraw complete", event);
if (event.type === "failed") console.log("withdraw failed", event);
}}
/>4) Embedded wallet / host-managed owner
If your app already manages wallet auth, pass dappAddress to skip wallet connect in the modal and keep using the same deposit/withdraw flow.
tsx
<DepositModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
dappAddress={embeddedOwnerAddress}
targetChain={8453}
targetToken="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913"
recipient="0xYourRecipient"
/>5) Runtime behavior
The modal calls backend endpoints for account setup/registration, processing, and status. The processing step polls GET /status/:address?txHash=... with backoff and resolves on bridge-complete (or earlier onbridge-started if waitForFinalTx is false).