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.
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.
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:
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.
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:
label, sublabel and icon, which meant
pasting our copy and freezing a claim like "Instant - $10,000 limit" into your
bundle.
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(defaulttrue) on<DepositModal>— turn off to present a flow with no wallet even when awalletClientorreownAppIdis supplied.<ClaimModal>and the./claimsubpath — 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: passsignRecoveryand forwardPOST /deposits/recoveron your proxy. For recipients that can’t sign,@rhinestone/deposit-modal/serverexportscreateRefundHandlerto authorize against your own session instead.
Behavior changes worth checking
connectedno 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 toonReady.- A QR-only integration no longer auto-locks to the wallet. The connect step’s
auto-skip never accounted for
enableQrTransferor 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-srcCSP must allowhttps://s3.rhinestone.dev— a blocked image fails silently. See content security policy. HYPERCORE_RECIPIENT_NOT_EOAis no longer emitted. HyperCore deposits now accept a smart-accountrecipient, and the pre-screen that blocked one is gone. If you branch on thatonErrorcode, 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.feeSponsoredanduiConfig.feeTooltipstill apply on the processing and result screens.
Removed prop warnings
Both modals log aconsole.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 singleonLifecycle
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 oneonLifecycle that
receives a discriminated event. Switch on event.type; the payload fields keep
the same names as before.
DepositModal
Asymmetries
The two unions look alike but differ — don’t assume one helper typechecks against both.Analytics type rename
TheonEvent 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. -
/reownand/safesubpath imports — they re-exported nothing that isn’t already on the root entry point.The./deposit,./withdraw,./constants, and./styles.csssubpaths remain for tree-shaking.
Additive — no action required
New in v0.3.0; existing code keeps working:appBalanceUsd?: numberon<DepositModal>— renders a “Balance after deposit” row (appBalanceUsd + amount) instead of fetching a portfolio balance.dappImports?: DappImportsConfigon<DepositModal>— pull balances from third-party apps. See migrating assets.defaultAmount: "max"— defaults the input to the user’s full source-token balance.- Solana destinations —
targetChain: Chain | number | "solana",targetToken: Address | string,recipient: Address | string. - New root exports —
DepositLifecycleEvent,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.