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
- The modal initializes and fires
onReady - If the user funds from a wallet,
"connected"fires with the EOAaddressand thesmartAccountthe deposit lands on - The user selects a source chain, token, and amount, then confirms
- The modal submits the transaction on the source chain and emits
"submitted" - The bridge routes funds to the target chain. Once they arrive, the modal
emits
"complete"
"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.
Deposit events
amount is in the source token’s base units — divide by sourceDecimals to display
it. sourceDecimals is omitted when the token isn’t recognised, which happens for a
QR deposit of an unlisted token.
amountUsd is the USD value as entered in the modal. It is omitted for flows with no
amount input: QR transfer, fiat on-ramp, and exchange connect.
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 an
accountAddress: Address field. "connected" means the deposit account for the
chosen target is registered and fundable, not that a wallet connected.
Claim events
ClaimLifecycleEvent is a separate union — lookup, refund_requested, complete,
failed. See claim modal.
onReady
Fires once when the modal is initialized and ready for interaction. No payload.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.
Codes
Errors without a code carry only
message. For bridge-level codes, see deposit processing error codes.
Error handling
After the source chain transaction confirms, the deposit service may
retry automatically before the
"failed" event fires.
Analytics
TheonEvent callback delivers modal funnel events and analytics delivery diagnostics. Funnel events use DepositAnalyticsEvent, WithdrawAnalyticsEvent, or ClaimAnalyticsEvent; diagnostics use AnalyticsIngestFailureEvent.
step. Abandonment carries the latest reached step. Close carries that step, or step: null only when the session closes before entering the funnel. A UI outcome reports what the widget observed, not backend or on-chain fulfillment truth.
The session envelope
Every funnel event carries these fields in addition to its event-specific payload:
Deposit funnel events also carry top-level
funding_method, which is null before method selection. AnalyticsIngestFailureEvent is a delivery diagnostic, not a funnel event, so it has no session_properties.
Session properties stay fixed for the session even if props change while the modal is open.
Deposit session properties
The target is the configured deposit destination.
Withdraw session properties
The target is the destination on which the form opened, including the source-chain and source-token fallback when no target was supplied. The prefill flags separately record whether your app supplied each value.
Claim session properties
overlay_close_enabled reports the effective configuration. Backdrop closing is opt-in because closeOnOverlayClick defaults to false.
Target identities
target_chain uses CAIP-2: eip155:<id>, solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp, or hypercore:spot. target_token is the on-chain token identity. EVM addresses and HyperCore hex token IDs are normalized to lowercase, Solana mints preserve case, and the literal native is allowed. Invalid chain and token values are omitted independently, so one invalid value does not remove the other or invalidate the session.
Friction, failure, and retry
- Friction means progress is blocked without an attempted operation failing. Its payload carries
stepandreason. - Failure means an attempted operation failed or the flow reached a terminal condition. Its payload carries
step,reason, andretryable. - Retry is a subsequent explicit attempt after a reported reason. Its payload carries
stepandreason.
retryable means the widget judged another attempt safe or offered that affordance. It appears only on failure events.
Reasons used by friction, failure, and retry form bounded vocabularies. Each starts with one declared AnalyticsReasonFamily: account_setup, amount, exchange, lookup, migration, modal, processor, provider, quote, recipient, recovery, refund, regional_methods, registration, route, signature, submission, swapped, transfer, or wallet.
Route reasons by matching this declared list longest-prefix first. Do not split at the first underscore: account_setup_* and regional_methods_* are multiword families. Abandonment reasons, close sources, and ingest-delivery reasons are separate vocabularies and do not follow this convention.
Deposit analytics
Funding methods arewallet, transfer, fiat_onramp, exchange_connect, and asset_migration.
Deposit steps
Deposit events
All payloads below also carry the envelope and top-levelfunding_method.
entry_source is user or initial_config. Method-selection identifiers are discriminated by funding_method:
A transfer handoff requires
correlator: { type: "deposit_address", value } and identifiers: { source_chain, source_token }. Those identities describe the payment source, not the session target. Non-transfer handoffs cannot use deposit_address and have no identifier bag.
The transfer picker can show a temporary default while its source options load. The modal waits until the picker settles on the source presented to the user before emitting a handoff, so it never publishes that temporary source. If no source identity resolves, the step events remain but no transfer handoff is emitted. A later selection of a distinct source can emit another handoff.
For same-route deposits, the processing step opens before the completed outcome. A transfer emits deposit_modal_step_open at transfer_tracking, followed by deposit_modal_ui_outcome with outcome: "completed" and step: "transfer_tracking". A wallet deposit emits the same events in that order at wallet_processing. These outcomes report what the widget observed, not backend or on-chain fulfillment.
Correlator types are deposit_address, transaction_hash, deposit_id, and swapped_external_customer_id.
Abandonment reasons are back, modal_close, provider_back, wallet_disconnect, method_replacement, and initial_migration_fallback. Close sources are header_button, escape, overlay, host_controlled, provider_back, native_dismiss_request, success_done, failure_cancel, and new_deposit_reset.
Deposit reasons
Withdraw analytics
Steps areform, review, submit, and processing. submit is the asynchronous boundary opened by the review CTA, not a separate screen.
same_route is unknown before submit, pinned on handoff, and repeated on later events. A same-route withdrawal creates no backend bridge row, so its UI outcome remains a client observation. Close sources are header_button, escape, overlay, host_controlled, success_done, and failure_cancel.
Withdraw reasons
Claim analytics
Steps arelookup, select, review, and submit. submit is the asynchronous boundary opened by the review CTA, not a separate screen.
Most events arrive at most once per attempt.
claim_modal_lookup_result arrives once per submitted search. The searched hash, refund destination, and deposit amount are not sent. Identities enter the stream only after a lookup matches a backend deposit row.
transaction_hash is the deposit’s source transaction hash; refund_transaction_hash is the submitted refund transaction. A missing source hash is null, never an empty string, and deposit_id is the authoritative join key.
A claim UI outcome is what the widget observed at submit, not on-chain settlement. Close sources are header_button, escape, overlay, host_controlled, success_done, and failure_cancel.
Claim reasons
These are not the claim lifecycle events.
onLifecycle reports where the claim itself got to; onEvent reports funnel behavior.Opting out
enableAnalyticsIngest={false} on any modal turns Rhinestone collection off entirely. onEvent receives the same events either way, so your own pipeline is unaffected.
Collection and attribution are separate: leaving the POST /analytics/ingest-token route off your proxy leaves sessions unattributed but does not stop collection.
Ingest failures
When delivery to Rhinestone fails,onEvent receives an AnalyticsIngestFailureEvent. It carries type, session_id, modal, widget_version, timestamp, reason, dropped_events, and status when an HTTP response exists. It has no session_properties and is never sent to Rhinestone.
It fires at most once per distinct reason per session, with a running
dropped_events count.
Analytics never blocks or interrupts a deposit, withdrawal, or claim. Ignoring a delivery diagnostic costs analytics only.