Skip to main content
The WithdrawModal handles outbound transfers in the crypto product. The user selects a destination chain and token, enters a recipient and an amount, and the modal registers the account that routes the funds — then asks your app to perform one transfer. Complete the shared widget quickstart and backend setup first. The modal never holds a key and never moves funds itself, so it works with any account model: an EOA, a smart account, an embedded or in-app wallet, or a relayer.

Basic usage

accountAddress is the account holding the funds. The modal reads its balance and stops the user sending to themselves; it never transacts from it.

Executing the transfer

onSendTransaction is required. The modal calls it once, when the user confirms on the review screen, with everything needed for a single transfer:
Two rules, both silent-failure modes if missed:
Send to to, and nothing else. It is the Rhinestone account that receives the funds and bridges them on to the recipient — except on a same-route withdrawal (source chain and token identical to the target), where the modal skips the bridge and to is the recipient directly. Substituting an address of your own either bypasses the bridge or strands the funds.Return the on-chain transaction hash. Progress is tracked by looking the deposit up by that hash. An ERC-4337 wallet must await the receipt and return the bundled transaction hash, not the userOp hash — returning the wrong one leaves the modal waiting on a withdrawal that already succeeded.
Reject the promise to surface a failure in the modal. The user can retry from the review screen.

If your funds are in a Safe

A 1/1 Safe signs with personal_sign over the SafeTx hash, relayed by whoever pays the gas. Build the EIP-712 SafeTx, sign it, and submit execTransaction:
Safe’s eth_sign path requires adding 4 to the v value of a personal_sign signature. This adjustment is specific to Safe’s signature verification — see the Safe docs for details.
To keep gas sponsored, relay the signed transaction through POST /safe/withdraw on your proxy rather than submitting execTransaction from the user’s wallet. Note that a relayed transaction cannot use Safe’s pre-validated (v = 1) signature shortcut: that only validates when msg.sender is the owner, and for a relayed call the sender is the relayer.

History and recovery

Available from v0.15.0, history follows the currently valid withdrawal destination, not accountAddress. Changing the destination re-scopes the list and status badge; an invalid or absent destination has no history entry point. The entry point appears before a transaction and on terminal screens, but not while signing, submitting, polling, or inside an external provider. Pass signRecovery only when your app can sign for destinations the user selects. Without it, history remains available but read-only, transaction-hash fallback is hidden, and the badge does not promise recovery. See history and recovery for the shared signing, eligibility, fallback, and analytics contract.

Props reference

Required

Transfer

targetChain and targetToken are optional — they seed the form, and the user can pick any supported destination. Omit them to open on a same-chain, same-token withdrawal.

Account

Backend

Display

Recovery

Callbacks

Withdraw sessions send analytics to Rhinestone from the browser too, so the same content security policy applies. WithdrawLifecycleEvent has no balance-changed or smart-account-changed variants, and its payload types differ from the deposit union: txHash is Hex, sourceChain is always a number, sourceToken / targetToken are Address, and "submitted" carries an accountAddress.

Analytics