Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.rhinestone.dev/llms.txt

Use this file to discover all available pages before exploring further.

The modal emits every state transition through a single onLifecycle callback. You switch on event.type to update your UI, trigger backend processes, or log analytics. New event variants can be added without changing the prop surface.

Deposit lifecycle

  1. The modal initializes and fires onReady
  2. The user connects a wallet (or is connected via an embedded wallet). The modal creates a smart account and emits "connected" with the EOA address and smartAccount address.
  3. The user selects a source chain, token, and amount, then confirms
  4. The modal submits the transaction on the source chain and emits "submitted"
  5. The bridge routes funds to the target chain. Once they arrive, the modal emits "complete"
If the bridge fails after submission, "failed" is emitted instead of "complete".

onLifecycle

onLifecycle receives a discriminated union — DepositLifecycleEvent on <DepositModal>, WithdrawLifecycleEvent on <WithdrawModal>. The two are similar but not identical; see withdraw events for the differences.
import type { DepositLifecycleEvent } from "@rhinestone/deposit-modal";

<DepositModal
  // ...required props
  onLifecycle={(event: DepositLifecycleEvent) => {
    switch (event.type) {
      case "connected":
        console.log("smart account", event.smartAccount);
        break;
      case "submitted":
        console.log("source tx", event.txHash, "on", event.sourceChain);
        break;
      case "complete":
        console.log("done", event.destinationTxHash, event.amount);
        break;
      case "failed":
        console.error("failed", event.txHash, event.error);
        break;
      case "balance-changed":
        setBalance(event.totalUsd);
        break;
      case "smart-account-changed":
        setSmartAccount({ evm: event.evm, solana: event.solana });
        break;
    }
  }}
/>

Deposit events

event.typeFieldsDescription
"connected"address: Address, smartAccount: AddressSmart account created for the deposit
"submitted"txHash: string, sourceChain: ChainId | "unknown", amount: stringDeposit transaction submitted on the source chain
"complete"txHash: string, destinationTxHash?: string, amount: string, sourceChain: ChainId | "unknown", sourceToken?: string, targetChain: number | "solana", targetToken: stringTokens arrived on the target chain
"failed"txHash: string, error?: stringBridge or transfer failed after submission
"balance-changed"totalUsd: numberThe user’s total portfolio balance (USD) changed
"smart-account-changed"evm: Address | null, solana: string | nullThe resolved smart account addresses changed
amount is the deposit amount in the token’s smallest unit.
sourceChain: "unknown" is deposit-only. When a webhook-detected deposit arrives without chain or token information, sourceChain is "unknown" and sourceToken is undefined — handle this branch so you don’t pick the wrong explorer URL.

Withdraw events

WithdrawLifecycleEvent carries the same type values minus "balance-changed" and "smart-account-changed". Its txHash is Hex, sourceChain is always a number, sourceToken / targetToken are Address, and "submitted" adds a safeAddress: Address field.

onReady

Fires once when the modal is initialized and ready for interaction. No payload.
onReady={() => console.log("modal ready")}

onError

Fires on errors at any stage — wallet connection, transaction signing, bridge setup — that prevent the deposit from being submitted. Distinct from the "failed" lifecycle event, which covers failures after the source transaction confirms.
onError={(data) => console.error(`[${data.code}] ${data.message}`)}
FieldTypeDescription
messagestringError description
codestring | undefinedError code, if available
For bridge-level error codes, see deposit processing error codes.

Error handling

StageSignalTypical causes
Wallet connectiononErrorUser rejected connection, network error
Transaction signingonErrorUser rejected transaction, insufficient gas
After submissiononLifecycle "failed"Bridge failure, timeout, price deviation
Any stageonErrorUnexpected errors
After the source chain transaction confirms, the deposit service may retry automatically before the "failed" event fires.

Analytics

The onEvent callback fires on granular user interactions for your analytics pipeline. Its payload type is DepositAnalyticsEvent (or WithdrawAnalyticsEvent).
import type { DepositAnalyticsEvent } from "@rhinestone/deposit-modal";

onEvent={(event: DepositAnalyticsEvent) => {
  analytics.track(event.type, event);
}}
Events include modal views (*_open) and CTA clicks (*_cta_click) at each step of the flow, with contextual properties like selected token, chain, and amount.