Skip to main content

v0.11.x → v0.12.0

Two changes: one proxy-side, one a single line to delete.

Forward GET /chains

The modal has read the chain set from /chains since v0.11.0, but it still carried a compiled-in table it fell back to. That table is gone. A proxy that does not forward the route no longer degrades to a built-in chain list — it leaves every picker empty, and the deposit flow reports that supported chains are unavailable. deposit-widget-proxy has forwarded it since 2026-08-11, so redeploying the packaged proxy is enough. A hand-written proxy needs the route added to its allowlist — see required routes. This is not a CORS change: it is a GET using headers the modal already sends, so it cannot break a preflight.
The upside of the removal is that the chain set is now whatever the backend serves, in both directions — a chain we add appears without a modal release, and one we withdraw stops being offered instead of lingering until you upgrade.

Delete uiConfig.showHistoryButton

Deposit history is now always available, so the flag has nothing left to switch. Delete the line; the button renders regardless, from the screen where the user picks a deposit method.
If your proxy does not forward GET /deposits, this is the release where that becomes visible: the panel is now reachable and shows the failure, where before the button could be switched off and the gap stayed hidden.

v0.8.x → v0.9.0

v0.9.0 moves both modals onto service-managed accounts, hands the withdrawal transfer to your app, and renames or removes props that no longer described what they did. The account and withdraw changes need code; the prop renames are mechanical.

Deploy your proxy first

Four of these changes are proxy-side and take effect the moment the new modal loads in a browser. None of them degrades — the request 404s, or the browser blocks it at preflight. See required routes for the full table. /setup-account and /register are no longer called and can be dropped once no older modal version is in use.
Bare Hono cors() is safe for the version header — with no allowHeaders it reflects whatever the preflight asks for. An explicit allow-list is what breaks, and it breaks on upgrade rather than on first deploy.
Both modals — the signerAddress and sessionChainIds props are gone, along with the DEFAULT_SIGNER_ADDRESS, EnableSessionDetails, and AccountInitData exports. Registration now goes through POST /register-managed, which a self-hosted proxy must forward before you ship — see required routes. There is no session key and no signature prompt during setup. <WithdrawModal> no longer moves funds. It previously built and submitted a Safe execTransaction, which only worked for apps whose funds sat in a Safe. It now asks your app to perform one transfer:
Send to to exactly, and return the on-chain transaction hash — not a userOp hash. See executing the transfer for both rules and a Safe-backed example, including how to keep gas sponsored. Also on <WithdrawModal>: onRequestConnect is removed (the modal needs no wallet, so there is no connect step — it opens on the withdraw form), the SafeTransactionRequest export is replaced by WithdrawTransferRequest, and the "submitted" lifecycle event renames safeAddress to accountAddress. POST /safe/withdraw still exists — the modal simply stopped calling it.

Renamed and removed props

Renames, plus the removal of config the server already owns. Nothing here changes what the modal can do.
dappAddress is removed with no replacement. The modal reads the address off walletClient.account, which nothing previously validated it against — so the modal could read balances for one address while the user was connected as another. allowedRoutes and the RouteConfig type are removed from both modals. They filtered the pickers client-side with nothing enforcing it, so a list that drifted from your deposit whitelist offered the user a source the processor then rejected. Set the whitelist via POST /setup; to offer a restricted subset, use an API key whose whitelist matches. enableSolana is removed for the same reason — Solana sources follow the deposit whitelist. uiConfig.checkLiquidity is removed. It cost an orchestrator round trip per continue to compute a warning the review screen never rendered. The cap is still checked and shown on the QR / transfer screen. rhinestoneApiKey is removed from both modals. It was never read — the key belongs on your backend proxy, which attaches it upstream. Delete it; nothing consumed it. FiatPaymentMethodOption is no longer exported. It described a row descriptor that fiatMethods no longer takes. backendUrl is now required on all three modals, and the DEFAULT_BACKEND_URL export is gone. The old default pointed at a Rhinestone-internal service running on our API key, so any integration that omitted the prop was silently routing its users’ deposits through it.
If you already set backendUrl, nothing changes. If you didn’t, you were on our key and need a proxy before upgrading. TypeScript flags the omission; each modal also logs a console.error when the value is missing, empty or whitespace, since backendUrl={process.env.X ?? ""} typechecks fine. fiatOnrampMethods becomes fiatMethods, a boolean map keyed by Swapped payment_group instead of a list of row descriptors:
The old prop made you supply each row’s label, sublabel and icon, which meant pasting our copy and freezing a claim like "Instant - $10,000 limit" into your bundle.
fiatOnrampMethods={[]} used to fall through to offering every payment method. An empty or all-false fiatMethods now offers none. If you computed the list dynamically and could produce an empty one, check which you wanted.

Optional where it was mandatory

<WithdrawModal>’s targetChain and targetToken are now optional. They only ever seeded the form — the user can pick any supported destination — so omitting them opens on a same-chain, same-token withdrawal. @reown/appkit and @reown/appkit-adapter-wagmi are now optional peer dependencies. An app that passes its own walletClient never opens AppKit and no longer needs it installed. See install.

New

  • enableWallet?: boolean (default true) on <DepositModal> — turn off to present a flow with no wallet even when a walletClient or reownAppId is supplied.
  • <ClaimModal> and the ./claim subpath — a user pastes a failed or rejected deposit’s transaction hash and gets the funds returned. The user’s own signature authorizes it, so this needs no backend of your own: pass signRecovery and forward POST /deposits/recover on your proxy. For recipients that can’t sign, @rhinestone/deposit-modal/server exports createRefundHandler to authorize against your own session instead.

Behavior changes worth checking

  • connected no longer fires for flows with no wallet (QR, fiat, exchange). It previously reported the declared address as though a wallet had connected. If you used it as a “flow started” signal, switch to onReady.
  • A QR-only integration no longer auto-locks to the wallet. The connect step’s auto-skip never accounted for enableQrTransfer or asset migrations, so it could skip past the only funding option you had enabled.
  • Logos load from Rhinestone’s asset CDN. Apps with an explicit img-src CSP must allow https://s3.rhinestone.dev — a blocked image fails silently. See content security policy.
  • HYPERCORE_RECIPIENT_NOT_EOA is no longer emitted. HyperCore deposits now accept a smart-account recipient, and the pre-screen that blocked one is gone. If you branch on that onError code, the branch is dead.
  • A chain your deposit whitelist allows nothing on is no longer offered in the QR flow’s chain picker, instead of appearing with built-in tokens the deposit would then be rejected for. Chains the shortlist says nothing about keep their existing set.
  • Fiat payment methods are personalized by region unless you pass fiatMethods. See regional payment methods.
  • The deposit review shows a single “Fees” row. The per-category breakdown and its tooltips are gone; uiConfig.feeSponsored and uiConfig.feeTooltip still apply on the processing and result screens.

Removed prop warnings

Both modals log a console.error naming the replacement when passed any prop removed in this release. TypeScript already catches these; the runtime warning is for plain JavaScript hosts, spread props, and loosely typed call sites, where several of the removals fail silently rather than visibly.

v0.1.x / v0.2.x → v0.3.0

v0.3.0 collapses each modal’s per-event callbacks into a single onLifecycle callback, renames the analytics event types, removes the /reown and /safe subpath entry points, and drops connectButtonLabel. <DepositModal> and <WithdrawModal> share the same callback shape, but their lifecycle payloads are not identical — see Asymmetries below.

Callback collapse — onLifecycle

Both modals replace their individual callbacks with one onLifecycle that receives a discriminated event. Switch on event.type; the payload fields keep the same names as before.
DepositModal
See status tracking for the full event payloads.

Asymmetries

The two unions look alike but differ — don’t assume one helper typechecks against both.
sourceChain: "unknown" is deposit-only. A webhook-detected deposit can arrive without chain or token info, in which case deposit events carry sourceChain: "unknown" and sourceToken: undefined. Handle this branch in your deposit onLifecycle switch — the wrong branch picks the wrong explorer URL. Withdraw flows always know the source chain.

Analytics type rename

The onEvent prop name is unchanged on both modals, but its parameter type was renamed. The payload shape is unchanged.

Removed

  • connectButtonLabel — gone from both modals. The connect-step copy is controlled internally; delete any consumer-side label, there is no replacement.
  • /reown and /safe subpath imports — they re-exported nothing that isn’t already on the root entry point.
    The ./deposit, ./withdraw, ./constants, and ./styles.css subpaths remain for tree-shaking.

Additive — no action required

New in v0.3.0; existing code keeps working:
  • appBalanceUsd?: number on <DepositModal> — renders a “Balance after deposit” row (appBalanceUsd + amount) instead of fetching a portfolio balance.
  • dappImports?: DappImportsConfig on <DepositModal> — pull balances from third-party apps. See migrating assets.
  • defaultAmount: "max" — defaults the input to the user’s full source-token balance.
  • Solana destinationstargetChain: Chain | number | "solana", targetToken: Address | string, recipient: Address | string.
  • New root exportsDepositLifecycleEvent, WithdrawLifecycleEvent, DappImportsConfig, OutputTokenRule, plus the renamed analytics types.

Unchanged

onError, onReady, onRequestConnect, the onEvent prop name, dappWalletClient / dappPublicClient / reownAppId, <WithdrawModal>’s onSignTransaction, and the @rhinestone/deposit-modal/styles.css export all keep their names and signatures.
Scoped to v0.3.0. Several of these changed again in v0.9.0 — see the v0.8.x → v0.9.0 section at the top of this page.