@rhinestone/deposit-modal 0.13.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +43 -2
- package/bridge-transcript.json +653 -0
- package/dist/ClaimModal-IKTJU43Y.cjs +13 -0
- package/dist/ClaimModal-SEKNWRMA.mjs +13 -0
- package/dist/{DepositModalReown-YNNHLAV2.cjs → DepositModalReown-46LPVFB6.cjs} +16 -15
- package/dist/{DepositModalReown-3H75G3XQ.mjs → DepositModalReown-Q2JMLT47.mjs} +6 -5
- package/dist/WithdrawModal-5ICGD4HJ.mjs +12 -0
- package/dist/WithdrawModal-VP6PMIRO.cjs +12 -0
- package/dist/{chunk-GACIGCSN.cjs → chunk-6KG642KH.cjs} +1 -1
- package/dist/{chunk-RAADLTSW.cjs → chunk-7ICSHJFE.cjs} +179 -138
- package/dist/{chunk-COCBCQQC.mjs → chunk-7SR7ENVJ.mjs} +46 -5
- package/dist/{chunk-OLCD75JK.mjs → chunk-CFKC77SV.mjs} +451 -131
- package/dist/{chunk-EOMT5LKX.mjs → chunk-IN77XSWO.mjs} +526 -3
- package/dist/{chunk-FZ5FZFIG.mjs → chunk-K4H6TGBE.mjs} +1 -1
- package/dist/{chunk-DSIZNRWA.mjs → chunk-KTUVSKR4.mjs} +979 -360
- package/dist/{chunk-HOGZKHHY.cjs → chunk-LZFRL2AL.cjs} +3 -3
- package/dist/{chunk-7N77GIP4.cjs → chunk-MTFJSE52.cjs} +465 -171
- package/dist/{chunk-LTMMETAB.mjs → chunk-PKML3XVS.mjs} +404 -110
- package/dist/{chunk-ZMT4ATHR.cjs → chunk-V2OBGLJD.cjs} +564 -41
- package/dist/{chunk-XYJFEN5D.mjs → chunk-WUJIKCFU.mjs} +1 -1
- package/dist/{chunk-CVGNCUVU.cjs → chunk-X2IPAPXU.cjs} +22 -13
- package/dist/{chunk-2G2EIN4A.cjs → chunk-YCQZJQO6.cjs} +1272 -653
- package/dist/{chunk-5NUIKYSF.cjs → chunk-YWMWI7PZ.cjs} +458 -138
- package/dist/{chunk-YREVFB64.mjs → chunk-ZEO6ADM3.mjs} +16 -7
- package/dist/claim.cjs +6 -6
- package/dist/claim.d.cts +3 -3
- package/dist/claim.d.ts +3 -3
- package/dist/claim.mjs +5 -5
- package/dist/constants.cjs +2 -2
- package/dist/constants.d.cts +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.mjs +1 -1
- package/dist/deposit.cjs +6 -6
- package/dist/deposit.d.cts +2 -2
- package/dist/deposit.d.ts +2 -2
- package/dist/deposit.mjs +5 -5
- package/dist/embed.cjs +310 -102
- package/dist/embed.d.cts +7 -1
- package/dist/embed.d.ts +7 -1
- package/dist/embed.mjs +285 -77
- package/dist/index.cjs +9 -9
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.mjs +8 -8
- package/dist/types-Bho4OA03.d.ts +982 -0
- package/dist/types-DP_3KwlD.d.cts +982 -0
- package/dist/withdraw.cjs +5 -5
- package/dist/withdraw.d.cts +3 -3
- package/dist/withdraw.d.ts +3 -3
- package/dist/withdraw.mjs +4 -4
- package/package.json +28 -7
- package/dist/ClaimModal-CREZO27I.mjs +0 -11
- package/dist/ClaimModal-JRIA32U2.cjs +0 -11
- package/dist/WithdrawModal-NVRX44IZ.mjs +0 -10
- package/dist/WithdrawModal-YYSBPCJJ.cjs +0 -10
- package/dist/types-B89I8_8H.d.ts +0 -638
- package/dist/types-nnDR4tqA.d.cts +0 -638
|
@@ -0,0 +1,982 @@
|
|
|
1
|
+
import { TypedDataDefinition, Address, Hex, WalletClient, PublicClient, Chain } from 'viem';
|
|
2
|
+
import { T as TargetChain } from './caip-D8aRWdEY.cjs';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Public config shape exposed on DepositModalProps. Each provider defaults to
|
|
6
|
+
* off — clients must explicitly opt in.
|
|
7
|
+
*
|
|
8
|
+
* A key controls VISIBILITY only. A provider that is enabled but has no
|
|
9
|
+
* implementation yet renders as a disabled "Coming soon" row; one that is not
|
|
10
|
+
* enabled is not shown at all.
|
|
11
|
+
*/
|
|
12
|
+
interface AssetMigrationsConfig {
|
|
13
|
+
polymarket?: boolean;
|
|
14
|
+
hyperliquid?: boolean;
|
|
15
|
+
aave?: boolean;
|
|
16
|
+
morpho?: boolean;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare const RECOVER_TYPES: {
|
|
20
|
+
readonly RecoverDeposit: readonly [{
|
|
21
|
+
readonly name: "depositId";
|
|
22
|
+
readonly type: "uint256";
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "destination";
|
|
25
|
+
readonly type: "address";
|
|
26
|
+
}];
|
|
27
|
+
};
|
|
28
|
+
/** What `signRecovery` is handed. */
|
|
29
|
+
interface SignRecoveryPayload {
|
|
30
|
+
/**
|
|
31
|
+
* Sign this exactly. Pass it to `signTypedData` on the wallet that owns
|
|
32
|
+
* `signer` — or to your account SDK, if `signer` is a smart account.
|
|
33
|
+
*/
|
|
34
|
+
typedData: TypedDataDefinition<typeof RECOVER_TYPES, "RecoverDeposit">;
|
|
35
|
+
/**
|
|
36
|
+
* The address whose signature the processor will verify: the deposit's
|
|
37
|
+
* `recipient`. Whatever you return must be a signature this address's own
|
|
38
|
+
* verifier accepts.
|
|
39
|
+
*/
|
|
40
|
+
signer: Address;
|
|
41
|
+
/**
|
|
42
|
+
* The chain the deposit is on, and therefore the chain the signature is
|
|
43
|
+
* verified against.
|
|
44
|
+
*
|
|
45
|
+
* Load-bearing for a smart account: ERC-1271 and ERC-6492 verification are
|
|
46
|
+
* per-chain, so a signature produced against the wrong one is well formed,
|
|
47
|
+
* rejected remotely, and reported to the user as a signature their wallet
|
|
48
|
+
* cannot make. An EOA signature does not depend on it.
|
|
49
|
+
*/
|
|
50
|
+
chainId: number;
|
|
51
|
+
/** Deposit being recovered, for your own logging or confirmation UI. */
|
|
52
|
+
depositId: string;
|
|
53
|
+
/** Where the funds will go. Covered by the signature. */
|
|
54
|
+
destination: Address;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Produces a signature the recipient's verifier accepts.
|
|
58
|
+
*
|
|
59
|
+
* - **embedded EOA** (Privy, Turnkey, Dynamic): `signTypedData` and return the raw
|
|
60
|
+
* 65-byte result.
|
|
61
|
+
* - **deployed smart account**: return a signature valid under its ERC-1271
|
|
62
|
+
* `isValidSignature`. A raw owner signature is usually *not* enough — a Safe, for
|
|
63
|
+
* instance, expects its own message wrapping — so go through your account SDK.
|
|
64
|
+
* - **undeployed smart account**: wrap it per ERC-6492 so the processor can verify
|
|
65
|
+
* counterfactually. `ox/erc6492`'s `SignatureErc6492.wrap` does this, and ships
|
|
66
|
+
* with viem already.
|
|
67
|
+
*/
|
|
68
|
+
type SignRecovery = (payload: SignRecoveryPayload) => Promise<Hex>;
|
|
69
|
+
/** Structured code from the processor; drives copy and whether a retry helps. */
|
|
70
|
+
type RecoveryErrorCode = "DEPOSIT_NOT_RECOVERABLE" | "RECOVERY_UNSUPPORTED" | "SIGNATURE_INVALID" | "VERIFICATION_UNAVAILABLE" | "REFUND_RECONCILIATION_REQUIRED" | "REFUND_FAILED";
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Consumer-supplied RPC URL overrides, scoped to a single modal instance (see
|
|
74
|
+
* {@link RpcUrlsProvider}). Threaded into every client the modal builds — EVM
|
|
75
|
+
* public clients (`public-client.ts`), the wallet adapter's transports
|
|
76
|
+
* (`reown.tsx`), and the Solana connection (`solana.ts`).
|
|
77
|
+
*
|
|
78
|
+
* Keyed by the same `number | "solana"` chain identifier the rest of the modal
|
|
79
|
+
* uses (see `core/constants.ts`), so a single `rpcUrls` prop covers every
|
|
80
|
+
* chain — EVM mainnets, Polygon (137, also feeds Polymarket reads), HyperEVM
|
|
81
|
+
* (999), and Solana.
|
|
82
|
+
*/
|
|
83
|
+
type ChainKey = number | "solana";
|
|
84
|
+
type RpcUrlMap = Partial<Record<ChainKey, string>>;
|
|
85
|
+
|
|
86
|
+
type Caip2ChainId = `eip155:${number}` | `solana:${string}`;
|
|
87
|
+
type ChainId = number | "solana" | "hypercore" | Caip2ChainId;
|
|
88
|
+
interface DepositModalTheme {
|
|
89
|
+
/**
|
|
90
|
+
* Absent means light, unconditionally — never "follow the OS". `"system"` is
|
|
91
|
+
* opt-in because an app that is single-appearance by design would otherwise
|
|
92
|
+
* get a dark funding sheet inside a light app the moment the user flips
|
|
93
|
+
* their phone.
|
|
94
|
+
*/
|
|
95
|
+
mode?: "light" | "dark" | "system";
|
|
96
|
+
radius?: "none" | "sm" | "md" | "lg" | "full";
|
|
97
|
+
fontColor?: string;
|
|
98
|
+
iconColor?: string;
|
|
99
|
+
ctaColor?: string;
|
|
100
|
+
ctaHoverColor?: string;
|
|
101
|
+
borderColor?: string;
|
|
102
|
+
backgroundColor?: string;
|
|
103
|
+
}
|
|
104
|
+
interface DepositModalUIConfig {
|
|
105
|
+
showBackButton?: boolean;
|
|
106
|
+
maxDepositUsd?: number;
|
|
107
|
+
minDepositUsd?: number;
|
|
108
|
+
/**
|
|
109
|
+
* When true the network/protocol fee is sponsored — the Review / Processing /
|
|
110
|
+
* Success / Failure screens render the fee line-through and surface a
|
|
111
|
+
* tooltip on the info icon explaining the sponsorship.
|
|
112
|
+
*/
|
|
113
|
+
feeSponsored?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Custom tooltip copy for the fee info icon. Defaults to a generic
|
|
116
|
+
* "Fees are sponsored" / "Fees apply" message based on `feeSponsored`.
|
|
117
|
+
*/
|
|
118
|
+
feeTooltip?: string;
|
|
119
|
+
}
|
|
120
|
+
interface ConnectedEventData {
|
|
121
|
+
address: Address;
|
|
122
|
+
smartAccount: Address;
|
|
123
|
+
}
|
|
124
|
+
interface DepositSubmittedEventData {
|
|
125
|
+
txHash: string;
|
|
126
|
+
sourceChain: ChainId | "unknown";
|
|
127
|
+
amount: string;
|
|
128
|
+
}
|
|
129
|
+
interface DepositCompleteEventData {
|
|
130
|
+
txHash: string;
|
|
131
|
+
destinationTxHash?: string;
|
|
132
|
+
amount: string;
|
|
133
|
+
sourceChain: ChainId | "unknown";
|
|
134
|
+
sourceToken?: string;
|
|
135
|
+
targetChain: TargetChain;
|
|
136
|
+
targetToken: string;
|
|
137
|
+
}
|
|
138
|
+
interface DepositFailedEventData {
|
|
139
|
+
txHash: string;
|
|
140
|
+
error?: string;
|
|
141
|
+
}
|
|
142
|
+
interface WithdrawSubmittedEventData {
|
|
143
|
+
txHash: Hex;
|
|
144
|
+
sourceChain: number;
|
|
145
|
+
amount: string;
|
|
146
|
+
accountAddress: Address;
|
|
147
|
+
}
|
|
148
|
+
interface WithdrawCompleteEventData {
|
|
149
|
+
txHash: Hex;
|
|
150
|
+
destinationTxHash?: Hex;
|
|
151
|
+
amount: string;
|
|
152
|
+
sourceChain: number;
|
|
153
|
+
sourceToken: Address;
|
|
154
|
+
targetChain: number;
|
|
155
|
+
targetToken: Address;
|
|
156
|
+
}
|
|
157
|
+
interface WithdrawFailedEventData {
|
|
158
|
+
txHash: Hex;
|
|
159
|
+
error?: string;
|
|
160
|
+
}
|
|
161
|
+
interface ErrorEventData {
|
|
162
|
+
message: string;
|
|
163
|
+
code?: string;
|
|
164
|
+
/**
|
|
165
|
+
* The underlying wallet/RPC error, verbatim. `message` is written for the
|
|
166
|
+
* end user and drops the detail a bug report needs — log this instead. Never
|
|
167
|
+
* render it: it is unsanitized and can carry RPC URLs.
|
|
168
|
+
*/
|
|
169
|
+
cause?: string;
|
|
170
|
+
}
|
|
171
|
+
interface OutputTokenRule {
|
|
172
|
+
match: {
|
|
173
|
+
chain?: string;
|
|
174
|
+
token?: string;
|
|
175
|
+
symbol?: string;
|
|
176
|
+
};
|
|
177
|
+
outputToken: string;
|
|
178
|
+
}
|
|
179
|
+
/**
|
|
180
|
+
* Which Swapped payment groups the fiat on-ramp offers. Keys are Swapped
|
|
181
|
+
* `payment_group` values; omit the object to offer all of them.
|
|
182
|
+
*
|
|
183
|
+
* Deliberately booleans rather than a list of row descriptors: the label,
|
|
184
|
+
* sublabel and icon belong to the modal, so subsetting cannot drift from — or
|
|
185
|
+
* freeze a stale copy of — Swapped's own limits and naming.
|
|
186
|
+
*/
|
|
187
|
+
interface FiatMethodsConfig {
|
|
188
|
+
creditcard?: boolean;
|
|
189
|
+
"bank-transfer"?: boolean;
|
|
190
|
+
"apple-pay"?: boolean;
|
|
191
|
+
}
|
|
192
|
+
interface DepositModalProps {
|
|
193
|
+
/**
|
|
194
|
+
* A wallet the host app already has connected. Pass this to reuse the user's
|
|
195
|
+
* existing session — the modal reads the address off `.account`, so it cannot
|
|
196
|
+
* disagree with what your app thinks the user is. Also what lets the modal
|
|
197
|
+
* skip its own connect step when the wallet is the only funding feature.
|
|
198
|
+
*
|
|
199
|
+
* Omit it and pass `reownAppId` instead to have the modal connect a wallet
|
|
200
|
+
* itself.
|
|
201
|
+
*/
|
|
202
|
+
walletClient?: WalletClient | null;
|
|
203
|
+
/** Read client paired with `walletClient`. Defaults to the modal's own. */
|
|
204
|
+
publicClient?: PublicClient | null;
|
|
205
|
+
targetChain: Chain | TargetChain;
|
|
206
|
+
targetToken: Address | string;
|
|
207
|
+
isOpen: boolean;
|
|
208
|
+
onClose: () => void;
|
|
209
|
+
inline?: boolean;
|
|
210
|
+
closeOnOverlayClick?: boolean;
|
|
211
|
+
sourceChain?: Chain | number;
|
|
212
|
+
sourceToken?: Address;
|
|
213
|
+
/**
|
|
214
|
+
* Pre-fills the deposit amount. Either a USD-denominated number string
|
|
215
|
+
* (e.g. "25") or the case-insensitive sentinel `"max"`, which fills the
|
|
216
|
+
* full available balance once it loads (same as the Max preset).
|
|
217
|
+
*/
|
|
218
|
+
defaultAmount?: string;
|
|
219
|
+
recipient: Address | string;
|
|
220
|
+
/**
|
|
221
|
+
* The user's current in-app balance, in USD, as the consuming app displays
|
|
222
|
+
* it. When provided, the amount screen shows a "Balance after deposit" row
|
|
223
|
+
* (`appBalanceUsd + amount`) so the user sees their post-deposit app
|
|
224
|
+
* balance. The row is hidden when this is omitted.
|
|
225
|
+
*/
|
|
226
|
+
appBalanceUsd?: number;
|
|
227
|
+
outputTokenRules?: OutputTokenRule[];
|
|
228
|
+
rejectUnmapped?: boolean;
|
|
229
|
+
backendUrl: string;
|
|
230
|
+
/**
|
|
231
|
+
* Per-chain RPC URL overrides, keyed by EVM chain id plus the literal
|
|
232
|
+
* `"solana"` key. Applied everywhere the modal reads chain state — EVM
|
|
233
|
+
* public clients, the connected wallet's transports (avoiding the
|
|
234
|
+
* rate-limited public defaults), Polygon/Polymarket reads, HyperEVM (999),
|
|
235
|
+
* and the Solana connection. Chains left unset use their default RPC.
|
|
236
|
+
*/
|
|
237
|
+
rpcUrls?: RpcUrlMap;
|
|
238
|
+
forceRegister?: boolean;
|
|
239
|
+
reownAppId?: string;
|
|
240
|
+
/**
|
|
241
|
+
* Enable importing balances from third-party dapps. Each dapp defaults to
|
|
242
|
+
* off — clients must explicitly opt in. When a dapp is enabled and the
|
|
243
|
+
* connected wallet has a balance there, a new row appears on the deposit
|
|
244
|
+
* entry screen.
|
|
245
|
+
*/
|
|
246
|
+
assetMigrations?: AssetMigrationsConfig;
|
|
247
|
+
/**
|
|
248
|
+
* Open the modal pre-routed into a dapp-import provider, skipping the
|
|
249
|
+
* deposit-method home screen. Must name an enabled `assetMigrations` key
|
|
250
|
+
* (e.g. "polymarket"); disabled/unknown values are a no-op. While the
|
|
251
|
+
* provider's balances are checked the modal shows a loading skeleton;
|
|
252
|
+
* if the flow turns out to be unreachable (no account, no balance, no
|
|
253
|
+
* wallet) it falls back to the home screen.
|
|
254
|
+
*/
|
|
255
|
+
initialAssetMigration?: keyof AssetMigrationsConfig;
|
|
256
|
+
/** Show fiat on-ramp option(s) that embed Swapped's iframe. Default: false. */
|
|
257
|
+
/**
|
|
258
|
+
* Offer the connected wallet as a funding source. Default: true. Turn off to
|
|
259
|
+
* present a wallet-free flow (QR / fiat / exchange only) even when a wallet
|
|
260
|
+
* client or `reownAppId` is supplied.
|
|
261
|
+
*/
|
|
262
|
+
enableWallet?: boolean;
|
|
263
|
+
enableFiatOnramp?: boolean;
|
|
264
|
+
/** Show the Transfer Crypto / QR row. Default: true. */
|
|
265
|
+
enableQrTransfer?: boolean;
|
|
266
|
+
/**
|
|
267
|
+
* Offer gasless ERC-20 deposits from the connected wallet: instead of an
|
|
268
|
+
* on-chain transfer, the user signs the highest-priority token authorization
|
|
269
|
+
* supported by the backend (ERC-3009, ERC-2612, then Permit2). Opt-in and
|
|
270
|
+
* purely additive — the plain transfer stays the default and the automatic
|
|
271
|
+
* fallback whenever the gasless path is unavailable (older proxy, feature
|
|
272
|
+
* disabled, missing Permit2 allowance, rejected signature). Default: false.
|
|
273
|
+
*/
|
|
274
|
+
enableGaslessDeposit?: boolean;
|
|
275
|
+
/**
|
|
276
|
+
* Restrict Cash to an exact subset of the standard payment groups. Providing
|
|
277
|
+
* the map opts this modal instance out of regional personalization; omit it
|
|
278
|
+
* to use backend-resolved methods with the built-in global fallback.
|
|
279
|
+
* An empty or all-false map disables Cash.
|
|
280
|
+
*/
|
|
281
|
+
fiatMethods?: FiatMethodsConfig;
|
|
282
|
+
/**
|
|
283
|
+
* Show a "Connect exchange" row that opens Swapped Connect — the user
|
|
284
|
+
* picks their CEX (Coinbase, Binance, Kraken…) or wallet inside the iframe
|
|
285
|
+
* and Swapped pulls the crypto on-chain to the smart account. Default: false.
|
|
286
|
+
*/
|
|
287
|
+
enableExchangeConnect?: boolean;
|
|
288
|
+
onRequestConnect?: () => void;
|
|
289
|
+
theme?: DepositModalTheme;
|
|
290
|
+
uiConfig?: DepositModalUIConfig;
|
|
291
|
+
className?: string;
|
|
292
|
+
onReady?: () => void;
|
|
293
|
+
/** Discriminated stream of deposit lifecycle transitions. */
|
|
294
|
+
onLifecycle?: (event: DepositLifecycleEvent) => void;
|
|
295
|
+
onEvent?: (event: DepositAnalyticsEvent | AnalyticsIngestFailureEvent) => void;
|
|
296
|
+
onError?: (data: ErrorEventData) => void;
|
|
297
|
+
/**
|
|
298
|
+
* Send session analytics to Rhinestone in addition to `onEvent`. Default:
|
|
299
|
+
* true. Turning it off changes nothing about what `onEvent` receives.
|
|
300
|
+
*/
|
|
301
|
+
enableAnalyticsIngest?: boolean;
|
|
302
|
+
/** @internal Rhinestone's own dev verification. Not a supported prop. */
|
|
303
|
+
analyticsIngestUrl?: string;
|
|
304
|
+
debug?: boolean;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* One transfer the host app must execute to fund a withdrawal.
|
|
308
|
+
*
|
|
309
|
+
* `to` is authoritative: it is the Rhinestone deposit account the processor
|
|
310
|
+
* watches, except on a same-route withdrawal (source chain+token identical to
|
|
311
|
+
* the target) where the modal skips the bridge and `to` is the end recipient.
|
|
312
|
+
* Either way the app's job is identical — move `amount` of `token` to `to` on
|
|
313
|
+
* `chainId` — so it must never substitute an address of its own.
|
|
314
|
+
*/
|
|
315
|
+
interface WithdrawTransferRequest {
|
|
316
|
+
/** Source chain to send from. */
|
|
317
|
+
chainId: number;
|
|
318
|
+
/** Source token; `NATIVE_TOKEN_ADDRESS` for the chain's native asset. */
|
|
319
|
+
token: Address;
|
|
320
|
+
/** Amount in the token's base units. */
|
|
321
|
+
amount: bigint;
|
|
322
|
+
/** Destination for this transfer. Send here. */
|
|
323
|
+
to: Address;
|
|
324
|
+
}
|
|
325
|
+
interface WithdrawModalProps {
|
|
326
|
+
/**
|
|
327
|
+
* Account holding the funds being withdrawn. Used to read the withdrawable
|
|
328
|
+
* balance and to keep the user from sending to themselves; the modal never
|
|
329
|
+
* transacts from it — `onSendTransaction` does.
|
|
330
|
+
*/
|
|
331
|
+
accountAddress: Address;
|
|
332
|
+
sourceChain: Chain | number;
|
|
333
|
+
sourceToken: Address;
|
|
334
|
+
/**
|
|
335
|
+
* Initial destination, not a constraint. The withdraw form lets the user pick
|
|
336
|
+
* any supported chain/token/recipient, so these only seed the fields — pass
|
|
337
|
+
* them to open on a particular destination, omit them to let the user choose.
|
|
338
|
+
*/
|
|
339
|
+
targetChain?: Chain | number;
|
|
340
|
+
targetToken?: Address;
|
|
341
|
+
recipient?: Address;
|
|
342
|
+
defaultAmount?: string;
|
|
343
|
+
isOpen: boolean;
|
|
344
|
+
onClose: () => void;
|
|
345
|
+
inline?: boolean;
|
|
346
|
+
closeOnOverlayClick?: boolean;
|
|
347
|
+
backendUrl: string;
|
|
348
|
+
/**
|
|
349
|
+
* Per-chain RPC URL overrides, keyed by EVM chain id plus the literal
|
|
350
|
+
* `"solana"` key. Applied to every chain read (EVM public clients and the
|
|
351
|
+
* connected wallet's transports). Chains left unset use their default RPC.
|
|
352
|
+
*/
|
|
353
|
+
rpcUrls?: RpcUrlMap;
|
|
354
|
+
forceRegister?: boolean;
|
|
355
|
+
/**
|
|
356
|
+
* Executes the transfer that funds the withdrawal, using whatever account
|
|
357
|
+
* model the host app has (EOA, smart account, in-app wallet, relayer).
|
|
358
|
+
*
|
|
359
|
+
* Must resolve with the **on-chain transaction hash** — not a userOp hash or
|
|
360
|
+
* bundler id. Progress is tracked by looking the deposit up by that hash, so
|
|
361
|
+
* anything else leaves the modal waiting on a withdrawal that already
|
|
362
|
+
* succeeded. Reject to surface a failure in the modal.
|
|
363
|
+
*/
|
|
364
|
+
onSendTransaction: (request: WithdrawTransferRequest) => Promise<{
|
|
365
|
+
txHash: Hex;
|
|
366
|
+
}>;
|
|
367
|
+
theme?: DepositModalTheme;
|
|
368
|
+
uiConfig?: DepositModalUIConfig;
|
|
369
|
+
className?: string;
|
|
370
|
+
onReady?: () => void;
|
|
371
|
+
/** Discriminated stream of withdraw lifecycle transitions. */
|
|
372
|
+
onLifecycle?: (event: WithdrawLifecycleEvent) => void;
|
|
373
|
+
onEvent?: (event: WithdrawAnalyticsEvent | AnalyticsIngestFailureEvent) => void;
|
|
374
|
+
onError?: (data: ErrorEventData) => void;
|
|
375
|
+
/**
|
|
376
|
+
* Send session analytics to Rhinestone in addition to `onEvent`. Default:
|
|
377
|
+
* true. Turning it off changes nothing about what `onEvent` receives.
|
|
378
|
+
*/
|
|
379
|
+
enableAnalyticsIngest?: boolean;
|
|
380
|
+
/** @internal Rhinestone's own dev verification. Not a supported prop. */
|
|
381
|
+
analyticsIngestUrl?: string;
|
|
382
|
+
debug?: boolean;
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Self-service recovery modal. Returns a failed or rejected deposit's
|
|
386
|
+
* source-chain funds to an address the user names. The deposit is looked up by
|
|
387
|
+
* transaction hash.
|
|
388
|
+
*
|
|
389
|
+
* The user's own wallet authorizes it: the deposit's `recipient` — the in-app
|
|
390
|
+
* wallet the funds were headed to — signs an EIP-712 struct naming the deposit and
|
|
391
|
+
* the destination, and the processor verifies that signature against the same
|
|
392
|
+
* `recipient` before moving anything. Your app needs no backend and no shared
|
|
393
|
+
* secret; the request goes from the browser through your `deposit-widget-proxy`,
|
|
394
|
+
* which adds only the project API key.
|
|
395
|
+
*
|
|
396
|
+
* Note the signer is the recipient, not the deposit account — deposit accounts are
|
|
397
|
+
* service-owned and cannot sign for themselves.
|
|
398
|
+
*/
|
|
399
|
+
interface ClaimModalProps {
|
|
400
|
+
/**
|
|
401
|
+
* Signs the recovery authorization. Called with the exact typed data to sign and
|
|
402
|
+
* the `signer` address whose signature the processor will verify — the deposit's
|
|
403
|
+
* `recipient`.
|
|
404
|
+
*
|
|
405
|
+
* Return whatever that address's own verifier accepts:
|
|
406
|
+
* - **embedded EOA** (Privy, Turnkey, Dynamic) — `signTypedData`, raw 65-byte
|
|
407
|
+
* result.
|
|
408
|
+
* - **deployed smart account** — a signature valid under its ERC-1271
|
|
409
|
+
* `isValidSignature`. A raw owner signature is usually not enough; a Safe, for
|
|
410
|
+
* one, expects its own message wrapping, so go through your account SDK.
|
|
411
|
+
* - **undeployed smart account** — wrap per ERC-6492 so it can be verified
|
|
412
|
+
* counterfactually. `SignatureErc6492.wrap` from `ox/erc6492` does this and
|
|
413
|
+
* ships with viem already.
|
|
414
|
+
*
|
|
415
|
+
* Throwing (or returning nothing) is treated as the user declining, which is
|
|
416
|
+
* retryable.
|
|
417
|
+
*
|
|
418
|
+
* If your users can't sign — a lost embedded wallet, or a recipient your app
|
|
419
|
+
* controls rather than the user — use `createRefundHandler` from
|
|
420
|
+
* `@rhinestone/deposit-modal/server` against your own backend instead, and drive
|
|
421
|
+
* your own UI. That path authorizes on your say-so rather than a signature.
|
|
422
|
+
*/
|
|
423
|
+
signRecovery: SignRecovery;
|
|
424
|
+
isOpen: boolean;
|
|
425
|
+
onClose: () => void;
|
|
426
|
+
inline?: boolean;
|
|
427
|
+
closeOnOverlayClick?: boolean;
|
|
428
|
+
backendUrl: string;
|
|
429
|
+
rpcUrls?: RpcUrlMap;
|
|
430
|
+
/** Optional prefills for the lookup form and destination. */
|
|
431
|
+
defaultTxHash?: string;
|
|
432
|
+
/**
|
|
433
|
+
* Prefills the refund destination. Left empty otherwise — the modal
|
|
434
|
+
* deliberately does NOT default to the deposit's sender, because returning
|
|
435
|
+
* funds to an exchange's hot wallet can lose them.
|
|
436
|
+
*
|
|
437
|
+
* Matches `refundDestination` on `RefundAuthorization` in `./server`, which
|
|
438
|
+
* is the authoritative version: this one only seeds the field and the user can
|
|
439
|
+
* edit it. Not related to the deposit's `recipient`.
|
|
440
|
+
*/
|
|
441
|
+
defaultRefundDestination?: Address;
|
|
442
|
+
theme?: DepositModalTheme;
|
|
443
|
+
uiConfig?: DepositModalUIConfig;
|
|
444
|
+
className?: string;
|
|
445
|
+
onReady?: () => void;
|
|
446
|
+
onLifecycle?: (event: ClaimLifecycleEvent) => void;
|
|
447
|
+
onEvent?: (event: ClaimAnalyticsEvent | AnalyticsIngestFailureEvent) => void;
|
|
448
|
+
onError?: (data: ErrorEventData) => void;
|
|
449
|
+
/**
|
|
450
|
+
* Sends claim session analytics to Rhinestone in addition to `onEvent`.
|
|
451
|
+
* Defaults to on; `false` turns collection off entirely.
|
|
452
|
+
*/
|
|
453
|
+
enableAnalyticsIngest?: boolean;
|
|
454
|
+
/** @internal Rhinestone's own dev verification. Not a supported prop. */
|
|
455
|
+
analyticsIngestUrl?: string;
|
|
456
|
+
debug?: boolean;
|
|
457
|
+
}
|
|
458
|
+
interface AssetOption {
|
|
459
|
+
id: string;
|
|
460
|
+
chainId: number;
|
|
461
|
+
token: Address;
|
|
462
|
+
symbol: string;
|
|
463
|
+
name: string;
|
|
464
|
+
decimals: number;
|
|
465
|
+
balance?: string;
|
|
466
|
+
balanceUsd?: number;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* Discriminated union covering every deposit flow state transition the
|
|
470
|
+
* consumer can observe. Consumers handle additions in a single switch; the
|
|
471
|
+
* modal can add new event variants without changing the prop surface.
|
|
472
|
+
*/
|
|
473
|
+
type DepositLifecycleEvent = {
|
|
474
|
+
type: "connected";
|
|
475
|
+
address: Address;
|
|
476
|
+
smartAccount: Address;
|
|
477
|
+
} | {
|
|
478
|
+
type: "submitted";
|
|
479
|
+
/** Real source-chain transaction hash; not emitted for permit deposits before settlement. */
|
|
480
|
+
txHash: string;
|
|
481
|
+
sourceChain: ChainId | "unknown";
|
|
482
|
+
/** Source-token base units (e.g. "1100000" for 1.10 USDC). */
|
|
483
|
+
amount: string;
|
|
484
|
+
/**
|
|
485
|
+
* Decimals of the source token, for converting `amount` to a
|
|
486
|
+
* human-readable value. Omitted when the token is not recognised
|
|
487
|
+
* (e.g. a QR deposit of an unlisted token).
|
|
488
|
+
*/
|
|
489
|
+
sourceDecimals?: number;
|
|
490
|
+
/**
|
|
491
|
+
* USD equivalent of the deposit as entered in the modal (token units
|
|
492
|
+
* for unpriced non-stablecoins). Omitted for flows without an amount
|
|
493
|
+
* input (QR transfer, fiat onramp, exchange connect).
|
|
494
|
+
*/
|
|
495
|
+
amountUsd?: string;
|
|
496
|
+
} | {
|
|
497
|
+
type: "complete";
|
|
498
|
+
txHash: string;
|
|
499
|
+
destinationTxHash?: string;
|
|
500
|
+
/** Source-token base units (e.g. "1100000" for 1.10 USDC). */
|
|
501
|
+
amount: string;
|
|
502
|
+
sourceChain: ChainId | "unknown";
|
|
503
|
+
sourceToken?: string;
|
|
504
|
+
/**
|
|
505
|
+
* Decimals of the source token, for converting `amount` to a
|
|
506
|
+
* human-readable value. Omitted when the token is not recognised
|
|
507
|
+
* (e.g. a QR deposit of an unlisted token).
|
|
508
|
+
*/
|
|
509
|
+
sourceDecimals?: number;
|
|
510
|
+
/**
|
|
511
|
+
* USD equivalent of the deposit as entered in the modal (token units
|
|
512
|
+
* for unpriced non-stablecoins). Omitted for flows without an amount
|
|
513
|
+
* input (QR transfer, fiat onramp, exchange connect).
|
|
514
|
+
*/
|
|
515
|
+
amountUsd?: string;
|
|
516
|
+
targetChain: TargetChain;
|
|
517
|
+
targetToken: string;
|
|
518
|
+
} | {
|
|
519
|
+
type: "failed";
|
|
520
|
+
txHash: string;
|
|
521
|
+
error?: string;
|
|
522
|
+
} | {
|
|
523
|
+
type: "balance-changed";
|
|
524
|
+
totalUsd: number;
|
|
525
|
+
} | {
|
|
526
|
+
type: "smart-account-changed";
|
|
527
|
+
evm: Address | null;
|
|
528
|
+
solana: string | null;
|
|
529
|
+
};
|
|
530
|
+
type WithdrawLifecycleEvent =
|
|
531
|
+
/** The deposit account for the chosen target is registered and fundable. */
|
|
532
|
+
{
|
|
533
|
+
type: "connected";
|
|
534
|
+
address: Address;
|
|
535
|
+
smartAccount: Address;
|
|
536
|
+
} | {
|
|
537
|
+
type: "submitted";
|
|
538
|
+
txHash: Hex;
|
|
539
|
+
sourceChain: number;
|
|
540
|
+
amount: string;
|
|
541
|
+
accountAddress: Address;
|
|
542
|
+
} | {
|
|
543
|
+
type: "complete";
|
|
544
|
+
txHash: Hex;
|
|
545
|
+
destinationTxHash?: Hex;
|
|
546
|
+
amount: string;
|
|
547
|
+
sourceChain: number;
|
|
548
|
+
sourceToken: Address;
|
|
549
|
+
targetChain: number;
|
|
550
|
+
targetToken: Address;
|
|
551
|
+
} | {
|
|
552
|
+
type: "failed";
|
|
553
|
+
txHash: Hex;
|
|
554
|
+
error?: string;
|
|
555
|
+
};
|
|
556
|
+
type ClaimLifecycleEvent = {
|
|
557
|
+
type: "lookup";
|
|
558
|
+
txHash: string;
|
|
559
|
+
matches: number;
|
|
560
|
+
} | {
|
|
561
|
+
type: "refund_requested";
|
|
562
|
+
account: Address;
|
|
563
|
+
/** Where the funds were asked to go, on the source chain. */
|
|
564
|
+
destination: Address;
|
|
565
|
+
chain: number;
|
|
566
|
+
} | {
|
|
567
|
+
type: "complete";
|
|
568
|
+
txHash: string;
|
|
569
|
+
account: Address;
|
|
570
|
+
destination: Address;
|
|
571
|
+
chain: number;
|
|
572
|
+
token: string;
|
|
573
|
+
amount: string;
|
|
574
|
+
} | {
|
|
575
|
+
type: "failed";
|
|
576
|
+
/** HTTP status from the refund endpoint; 0 if it was unreachable. */
|
|
577
|
+
status?: number;
|
|
578
|
+
error?: string;
|
|
579
|
+
};
|
|
580
|
+
type DepositFundingMethod = "wallet" | "transfer" | "fiat_onramp" | "exchange_connect" | "asset_migration";
|
|
581
|
+
type DepositWalletIntegration = "modal_connected" | "host_supplied" | "none";
|
|
582
|
+
interface DepositAnalyticsSessionProperties {
|
|
583
|
+
readonly enabled_funding_methods: readonly DepositFundingMethod[];
|
|
584
|
+
readonly wallet_integration: DepositWalletIntegration;
|
|
585
|
+
readonly fiat_methods: {
|
|
586
|
+
readonly source: "backend_resolved";
|
|
587
|
+
} | {
|
|
588
|
+
readonly source: "configured";
|
|
589
|
+
readonly identifiers: readonly string[];
|
|
590
|
+
};
|
|
591
|
+
readonly asset_migration_providers: readonly string[];
|
|
592
|
+
readonly initial_asset_migration: string | null;
|
|
593
|
+
readonly gasless_wallet_flow_enabled: boolean;
|
|
594
|
+
readonly presentation: "inline" | "overlay";
|
|
595
|
+
readonly overlay_close_enabled: boolean;
|
|
596
|
+
readonly prefills: {
|
|
597
|
+
readonly source_chain: boolean;
|
|
598
|
+
readonly source_token: boolean;
|
|
599
|
+
readonly amount: boolean;
|
|
600
|
+
readonly initial_asset_migration: boolean;
|
|
601
|
+
};
|
|
602
|
+
/**
|
|
603
|
+
* The target the session opened with, as CAIP-2 and on-chain token identity.
|
|
604
|
+
* Optional because a value the ingest contract would refuse is omitted
|
|
605
|
+
* rather than sent — a refused envelope would cost the whole session.
|
|
606
|
+
*/
|
|
607
|
+
readonly target_chain?: string;
|
|
608
|
+
readonly target_token?: string;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Fixed by the ingest contract: it is validated strictly and compared for
|
|
612
|
+
* equality across every event in a session, so anything added here that can
|
|
613
|
+
* vary mid-session rejects the whole batch. Route classification therefore
|
|
614
|
+
* lives on the event payload, not in this envelope.
|
|
615
|
+
*/
|
|
616
|
+
interface WithdrawAnalyticsSessionProperties {
|
|
617
|
+
readonly presentation: "inline" | "overlay";
|
|
618
|
+
readonly overlay_close_enabled: boolean;
|
|
619
|
+
readonly prefills: {
|
|
620
|
+
readonly target_chain: boolean;
|
|
621
|
+
readonly target_token: boolean;
|
|
622
|
+
readonly recipient: boolean;
|
|
623
|
+
readonly amount: boolean;
|
|
624
|
+
};
|
|
625
|
+
/**
|
|
626
|
+
* The destination the form opened on — the configured target, or the source
|
|
627
|
+
* it falls back to. `prefills.target_*` stay the record of which of the two
|
|
628
|
+
* it was. Optional on the same terms as the deposit envelope's.
|
|
629
|
+
*/
|
|
630
|
+
readonly target_chain?: string;
|
|
631
|
+
readonly target_token?: string;
|
|
632
|
+
}
|
|
633
|
+
/**
|
|
634
|
+
* Fixed by the ingest contract, exactly as the withdraw one is: strictly
|
|
635
|
+
* validated and compared for equality across every event in a session.
|
|
636
|
+
*/
|
|
637
|
+
interface ClaimAnalyticsSessionProperties {
|
|
638
|
+
readonly presentation: "inline" | "overlay";
|
|
639
|
+
readonly overlay_close_enabled: boolean;
|
|
640
|
+
readonly prefills: {
|
|
641
|
+
readonly transaction_hash: boolean;
|
|
642
|
+
readonly refund_destination: boolean;
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
interface AnalyticsEventEnvelope<Modal extends "deposit" | "withdraw" | "claim", SessionProperties> {
|
|
646
|
+
session_id: string;
|
|
647
|
+
modal: Modal;
|
|
648
|
+
widget_version: string;
|
|
649
|
+
timestamp: string;
|
|
650
|
+
session_properties: SessionProperties;
|
|
651
|
+
}
|
|
652
|
+
type DepositAnalyticsSharedStep = "account_setup" | "funding_method_home";
|
|
653
|
+
type DepositAnalyticsWalletStep = "wallet_connect" | "wallet_source_asset" | "wallet_source_token" | "wallet_amount" | "wallet_review" | "wallet_submit" | "wallet_processing";
|
|
654
|
+
type DepositAnalyticsTransferStep = "transfer_source_selection" | "transfer_address_shown" | "transfer_copy" | "transfer_fee_amount" | "transfer_fee_review" | "transfer_tracking";
|
|
655
|
+
type DepositAnalyticsFiatStep = "fiat_regional_payment_method" | "fiat_provider_mint" | "fiat_provider_handoff" | "fiat_tracking" | "fiat_receipt";
|
|
656
|
+
type DepositAnalyticsExchangeStep = "exchange_selection" | "exchange_fee_acknowledgement" | "exchange_provider_mint" | "exchange_provider_handoff" | "exchange_tracking" | "exchange_finalising" | "exchange_receipt";
|
|
657
|
+
type DepositAnalyticsMigrationStep = "migration_boot_resolve" | "migration_provider_selection" | "migration_asset_selection" | "migration_amount" | "migration_review" | "migration_submit" | "migration_processing";
|
|
658
|
+
type DepositAnalyticsStep = DepositAnalyticsSharedStep | DepositAnalyticsWalletStep | DepositAnalyticsTransferStep | DepositAnalyticsFiatStep | DepositAnalyticsExchangeStep | DepositAnalyticsMigrationStep;
|
|
659
|
+
type AnalyticsReasonFamily = "account_setup" | "amount" | "exchange" | "lookup" | "migration" | "modal" | "processor" | "provider" | "quote" | "recipient" | "recovery" | "refund" | "regional_methods" | "registration" | "route" | "signature" | "submission" | "swapped" | "transfer" | "wallet";
|
|
660
|
+
/**
|
|
661
|
+
* Reason prefixes are stable downstream routing keys. Multiword families are
|
|
662
|
+
* matched from this declared list, not by splitting at the first underscore.
|
|
663
|
+
*/
|
|
664
|
+
type RoutableAnalyticsReason<Reason extends `${AnalyticsReasonFamily}_${string}`> = Reason;
|
|
665
|
+
type DepositAnalyticsFailureReason = RoutableAnalyticsReason<"account_setup_pending" | "account_setup_stale_response" | "account_setup_failed" | "wallet_connection_requested" | "wallet_connection_rejected" | "wallet_connection_failed" | "wallet_disconnected" | "wallet_portfolio_load_failed" | "wallet_no_supported_assets" | "wallet_no_funded_assets" | "amount_invalid" | "amount_insufficient_balance" | "amount_below_minimum" | "amount_above_maximum" | "quote_source_price_unavailable" | "quote_target_price_unavailable" | "quote_unavailable" | "wallet_chain_switch_rejected" | "wallet_chain_switch_failed" | "wallet_permit_preparation_unavailable" | "wallet_signature_rejected" | "submission_rejected" | "submission_failed" | "submission_missing_hash" | "submission_uncertain" | "transfer_source_unavailable" | "transfer_address_unavailable" | "transfer_clipboard_failed" | "processor_status_poll_failed" | "regional_methods_timeout" | "regional_methods_failed" | "regional_methods_fallback" | "regional_methods_empty" | "exchange_list_failed" | "exchange_list_empty" | "exchange_setup_unavailable" | "exchange_fee_changed" | "exchange_fee_not_acknowledged" | "swapped_mint_failed" | "swapped_url_untrusted" | "swapped_iframe_timeout" | "swapped_browser_open_failed" | "provider_cancelled" | "provider_failed" | "processor_failed" | "migration_wallet_required" | "migration_availability_loading" | "migration_availability_failed" | "migration_unavailable" | "migration_no_balance" | "migration_partial_availability" | "migration_coming_soon">;
|
|
666
|
+
type DepositAnalyticsAbandonmentReason = "back" | "modal_close" | "provider_back" | "wallet_disconnect" | "method_replacement" | "initial_migration_fallback";
|
|
667
|
+
type DepositAnalyticsCloseSource = "header_button" | "escape" | "overlay" | "host_controlled" | "provider_back" | "native_dismiss_request" | "success_done" | "failure_cancel" | "new_deposit_reset";
|
|
668
|
+
type DepositAnalyticsUiOutcome = "completed" | "failed" | "cancelled";
|
|
669
|
+
type DepositAnalyticsCorrelator = {
|
|
670
|
+
type: "deposit_address";
|
|
671
|
+
value: string;
|
|
672
|
+
} | {
|
|
673
|
+
type: "transaction_hash";
|
|
674
|
+
value: string;
|
|
675
|
+
} | {
|
|
676
|
+
type: "deposit_id";
|
|
677
|
+
value: string;
|
|
678
|
+
} | {
|
|
679
|
+
type: "swapped_external_customer_id";
|
|
680
|
+
value: string;
|
|
681
|
+
};
|
|
682
|
+
interface DepositWalletMethodIdentifiers {
|
|
683
|
+
readonly network: "evm" | "solana";
|
|
684
|
+
readonly integration: DepositWalletIntegration;
|
|
685
|
+
}
|
|
686
|
+
interface DepositFiatOnrampMethodIdentifiers {
|
|
687
|
+
readonly payment_method: string;
|
|
688
|
+
readonly source: "personalized" | "fallback" | "configured";
|
|
689
|
+
}
|
|
690
|
+
interface DepositExchangeConnectMethodIdentifiers {
|
|
691
|
+
readonly exchange: string;
|
|
692
|
+
}
|
|
693
|
+
interface DepositAssetMigrationMethodIdentifiers {
|
|
694
|
+
readonly provider: string;
|
|
695
|
+
}
|
|
696
|
+
interface DepositTransferHandoffIdentifiers {
|
|
697
|
+
readonly source_chain: string;
|
|
698
|
+
readonly source_token: string;
|
|
699
|
+
}
|
|
700
|
+
type DepositAnalyticsMethodSelectedPayload = {
|
|
701
|
+
type: "deposit_modal_method_selected";
|
|
702
|
+
funding_method: "wallet";
|
|
703
|
+
entry_source: "user" | "initial_config";
|
|
704
|
+
identifiers: DepositWalletMethodIdentifiers;
|
|
705
|
+
} | {
|
|
706
|
+
type: "deposit_modal_method_selected";
|
|
707
|
+
funding_method: "transfer";
|
|
708
|
+
entry_source: "user" | "initial_config";
|
|
709
|
+
identifiers?: never;
|
|
710
|
+
} | {
|
|
711
|
+
type: "deposit_modal_method_selected";
|
|
712
|
+
funding_method: "fiat_onramp";
|
|
713
|
+
entry_source: "user" | "initial_config";
|
|
714
|
+
identifiers: DepositFiatOnrampMethodIdentifiers;
|
|
715
|
+
} | {
|
|
716
|
+
type: "deposit_modal_method_selected";
|
|
717
|
+
funding_method: "exchange_connect";
|
|
718
|
+
entry_source: "user" | "initial_config";
|
|
719
|
+
identifiers?: DepositExchangeConnectMethodIdentifiers;
|
|
720
|
+
} | {
|
|
721
|
+
type: "deposit_modal_method_selected";
|
|
722
|
+
funding_method: "asset_migration";
|
|
723
|
+
entry_source: "user" | "initial_config";
|
|
724
|
+
identifiers?: DepositAssetMigrationMethodIdentifiers;
|
|
725
|
+
};
|
|
726
|
+
type DepositAnalyticsNonTransferHandoffPayload = {
|
|
727
|
+
[Method in Exclude<DepositFundingMethod, "transfer">]: {
|
|
728
|
+
type: "deposit_modal_handoff";
|
|
729
|
+
funding_method: Method;
|
|
730
|
+
step: DepositAnalyticsStep;
|
|
731
|
+
correlator: Exclude<DepositAnalyticsCorrelator, {
|
|
732
|
+
type: "deposit_address";
|
|
733
|
+
}>;
|
|
734
|
+
identifiers?: never;
|
|
735
|
+
};
|
|
736
|
+
}[Exclude<DepositFundingMethod, "transfer">];
|
|
737
|
+
type DepositAnalyticsHandoffPayload = {
|
|
738
|
+
type: "deposit_modal_handoff";
|
|
739
|
+
funding_method: "transfer";
|
|
740
|
+
step: DepositAnalyticsStep;
|
|
741
|
+
correlator: Extract<DepositAnalyticsCorrelator, {
|
|
742
|
+
type: "deposit_address";
|
|
743
|
+
}>;
|
|
744
|
+
identifiers: DepositTransferHandoffIdentifiers;
|
|
745
|
+
} | DepositAnalyticsNonTransferHandoffPayload;
|
|
746
|
+
type DepositAnalyticsCommonEventPayload = {
|
|
747
|
+
type: "deposit_modal_open";
|
|
748
|
+
} | {
|
|
749
|
+
type: "deposit_modal_step_open";
|
|
750
|
+
step: DepositAnalyticsStep;
|
|
751
|
+
} | {
|
|
752
|
+
type: "deposit_modal_step_complete";
|
|
753
|
+
step: DepositAnalyticsStep;
|
|
754
|
+
}
|
|
755
|
+
/** Progress is blocked, but no attempted operation failed. */
|
|
756
|
+
| {
|
|
757
|
+
type: "deposit_modal_friction";
|
|
758
|
+
step: DepositAnalyticsStep;
|
|
759
|
+
reason: DepositAnalyticsFailureReason;
|
|
760
|
+
}
|
|
761
|
+
/** An attempted operation failed or the flow reached a terminal condition. */
|
|
762
|
+
| {
|
|
763
|
+
type: "deposit_modal_failure";
|
|
764
|
+
step: DepositAnalyticsStep;
|
|
765
|
+
reason: DepositAnalyticsFailureReason;
|
|
766
|
+
retryable: boolean;
|
|
767
|
+
} | {
|
|
768
|
+
type: "deposit_modal_retry";
|
|
769
|
+
step: DepositAnalyticsStep;
|
|
770
|
+
reason: DepositAnalyticsFailureReason;
|
|
771
|
+
} | {
|
|
772
|
+
type: "deposit_modal_correlator_observed";
|
|
773
|
+
step: DepositAnalyticsStep;
|
|
774
|
+
correlator: DepositAnalyticsCorrelator;
|
|
775
|
+
} | {
|
|
776
|
+
type: "deposit_modal_ui_outcome";
|
|
777
|
+
step: DepositAnalyticsStep;
|
|
778
|
+
outcome: DepositAnalyticsUiOutcome;
|
|
779
|
+
} | {
|
|
780
|
+
type: "deposit_modal_method_abandoned";
|
|
781
|
+
step: DepositAnalyticsStep;
|
|
782
|
+
reason: DepositAnalyticsAbandonmentReason;
|
|
783
|
+
} | {
|
|
784
|
+
type: "deposit_modal_close";
|
|
785
|
+
source: DepositAnalyticsCloseSource;
|
|
786
|
+
step: DepositAnalyticsStep | null;
|
|
787
|
+
after_handoff: boolean;
|
|
788
|
+
};
|
|
789
|
+
/**
|
|
790
|
+
* Method-aware deposit telemetry. UI outcomes describe only what the widget
|
|
791
|
+
* observed and must not be treated as backend fulfilment truth.
|
|
792
|
+
*/
|
|
793
|
+
type DepositAnalyticsEventPayload = DepositAnalyticsMethodSelectedPayload | DepositAnalyticsHandoffPayload | (DepositAnalyticsCommonEventPayload & {
|
|
794
|
+
funding_method: DepositFundingMethod | null;
|
|
795
|
+
});
|
|
796
|
+
/** Deposit funnel telemetry, as delivered to `onEvent`. */
|
|
797
|
+
type DepositAnalyticsEvent = DepositAnalyticsEventPayload & AnalyticsEventEnvelope<"deposit", DepositAnalyticsSessionProperties>;
|
|
798
|
+
/**
|
|
799
|
+
* `submit` is the async boundary the review CTA opens rather than a screen of
|
|
800
|
+
* its own, so submit-time failures and the handoff have somewhere to attach.
|
|
801
|
+
*/
|
|
802
|
+
type WithdrawAnalyticsStep = "form" | "review" | "submit" | "processing";
|
|
803
|
+
/** Every reason has a call site in the withdraw flow; none is aspirational. */
|
|
804
|
+
type WithdrawAnalyticsFailureReason = RoutableAnalyticsReason<"submission_handler_missing" | "wallet_balance_unavailable" | "route_target_tokens_unavailable" | "recipient_invalid" | "recipient_not_allowed" | "amount_invalid" | "amount_insufficient_balance" | "registration_pending" | "registration_stale" | "registration_failed" | "registration_target_changed" | "submission_rejected" | "submission_failed" | "submission_missing_hash" | "submission_uncertain" | "processor_status_poll_failed" | "processor_failed">;
|
|
805
|
+
type WithdrawAnalyticsAbandonmentReason = "back" | "modal_close";
|
|
806
|
+
type WithdrawAnalyticsCloseSource = "header_button" | "escape" | "overlay" | "host_controlled" | "success_done" | "failure_cancel";
|
|
807
|
+
type WithdrawAnalyticsUiOutcome = "completed" | "failed";
|
|
808
|
+
/**
|
|
809
|
+
* Withdraw funnel telemetry. `same_route` is pinned at submit and stamped onto
|
|
810
|
+
* every later event, so a target prop change mid-flight still reports the route
|
|
811
|
+
* the withdrawal actually took. UI outcomes describe only what the widget
|
|
812
|
+
* observed — a same-route withdrawal has no backend record at all.
|
|
813
|
+
*/
|
|
814
|
+
type WithdrawAnalyticsEventPayload = {
|
|
815
|
+
type: "withdraw_modal_open";
|
|
816
|
+
} | {
|
|
817
|
+
type: "withdraw_modal_step_open";
|
|
818
|
+
step: WithdrawAnalyticsStep;
|
|
819
|
+
same_route?: boolean;
|
|
820
|
+
} | {
|
|
821
|
+
type: "withdraw_modal_step_complete";
|
|
822
|
+
step: WithdrawAnalyticsStep;
|
|
823
|
+
same_route?: boolean;
|
|
824
|
+
}
|
|
825
|
+
/** Progress is blocked, but no attempted operation failed. */
|
|
826
|
+
| {
|
|
827
|
+
type: "withdraw_modal_friction";
|
|
828
|
+
step: WithdrawAnalyticsStep;
|
|
829
|
+
reason: WithdrawAnalyticsFailureReason;
|
|
830
|
+
same_route?: boolean;
|
|
831
|
+
}
|
|
832
|
+
/** An attempted operation failed or the flow reached a terminal condition. */
|
|
833
|
+
| {
|
|
834
|
+
type: "withdraw_modal_failure";
|
|
835
|
+
step: WithdrawAnalyticsStep;
|
|
836
|
+
reason: WithdrawAnalyticsFailureReason;
|
|
837
|
+
retryable: boolean;
|
|
838
|
+
same_route?: boolean;
|
|
839
|
+
} | {
|
|
840
|
+
type: "withdraw_modal_retry";
|
|
841
|
+
step: WithdrawAnalyticsStep;
|
|
842
|
+
reason: WithdrawAnalyticsFailureReason;
|
|
843
|
+
same_route?: boolean;
|
|
844
|
+
}
|
|
845
|
+
/**
|
|
846
|
+
* The submitted withdrawal, once. Flat by contract: these are the field
|
|
847
|
+
* names the warehouse join reads to match a widget session against its
|
|
848
|
+
* backend record.
|
|
849
|
+
*/
|
|
850
|
+
| {
|
|
851
|
+
type: "withdraw_modal_handoff";
|
|
852
|
+
step: WithdrawAnalyticsStep;
|
|
853
|
+
transaction_hash: string;
|
|
854
|
+
managed_account: string;
|
|
855
|
+
same_route: boolean;
|
|
856
|
+
} | {
|
|
857
|
+
type: "withdraw_modal_ui_outcome";
|
|
858
|
+
step: WithdrawAnalyticsStep;
|
|
859
|
+
outcome: WithdrawAnalyticsUiOutcome;
|
|
860
|
+
same_route?: boolean;
|
|
861
|
+
} | {
|
|
862
|
+
type: "withdraw_modal_abandoned";
|
|
863
|
+
step: WithdrawAnalyticsStep;
|
|
864
|
+
reason: WithdrawAnalyticsAbandonmentReason;
|
|
865
|
+
same_route?: boolean;
|
|
866
|
+
} | {
|
|
867
|
+
type: "withdraw_modal_close";
|
|
868
|
+
source: WithdrawAnalyticsCloseSource;
|
|
869
|
+
step: WithdrawAnalyticsStep | null;
|
|
870
|
+
after_handoff: boolean;
|
|
871
|
+
same_route?: boolean;
|
|
872
|
+
};
|
|
873
|
+
type WithdrawAnalyticsEvent = WithdrawAnalyticsEventPayload & AnalyticsEventEnvelope<"withdraw", WithdrawAnalyticsSessionProperties>;
|
|
874
|
+
/**
|
|
875
|
+
* `submit` is the async boundary the review CTA opens rather than a screen of
|
|
876
|
+
* its own, so submit-time failures and the handoff have somewhere to attach.
|
|
877
|
+
*/
|
|
878
|
+
type ClaimAnalyticsStep = "lookup" | "select" | "review" | "submit";
|
|
879
|
+
/** Every reason has a call site in the claim flow; none is aspirational. */
|
|
880
|
+
type ClaimAnalyticsFailureReason = RoutableAnalyticsReason<"lookup_transaction_hash_invalid" | "lookup_failed" | "lookup_no_deposits_found" | "lookup_no_eligible_deposits" | "refund_destination_invalid" | "recovery_deposit_data_incomplete" | "signature_rejected" | "signature_invalid" | "recovery_deposit_not_recoverable" | "recovery_unsupported" | "signature_verification_unavailable" | "refund_reconciliation_required" | "refund_failed" | "refund_service_unreachable" | "modal_close_refused_in_flight">;
|
|
881
|
+
type ClaimAnalyticsAbandonmentReason = "back" | "modal_close";
|
|
882
|
+
type ClaimAnalyticsCloseSource = "header_button" | "escape" | "overlay" | "host_controlled" | "success_done" | "failure_cancel";
|
|
883
|
+
type ClaimAnalyticsUiOutcome = "completed" | "failed";
|
|
884
|
+
/**
|
|
885
|
+
* Claim funnel telemetry. Identities enter the stream only once a lookup has
|
|
886
|
+
* matched a backend deposit row: the hash the user searched for, the refund
|
|
887
|
+
* destination they typed and the amount are never sent.
|
|
888
|
+
*
|
|
889
|
+
* `transaction_hash` is always the *deposit's* source transaction hash — the
|
|
890
|
+
* same meaning it has on the deposit and withdraw handoffs. The refund's own
|
|
891
|
+
* hash is `refund_transaction_hash`. It is `null` when the backend row carried
|
|
892
|
+
* no hash, never an empty string: `deposit_id` is the join key, and a blank
|
|
893
|
+
* identity would join to nothing while looking like one that does.
|
|
894
|
+
*/
|
|
895
|
+
type ClaimAnalyticsEventPayload = {
|
|
896
|
+
type: "claim_modal_open";
|
|
897
|
+
} | {
|
|
898
|
+
type: "claim_modal_step_open";
|
|
899
|
+
step: ClaimAnalyticsStep;
|
|
900
|
+
} | {
|
|
901
|
+
type: "claim_modal_step_complete";
|
|
902
|
+
step: ClaimAnalyticsStep;
|
|
903
|
+
}
|
|
904
|
+
/** How many deposits the hash resolved to, and how many were recoverable. */
|
|
905
|
+
| {
|
|
906
|
+
type: "claim_modal_lookup_result";
|
|
907
|
+
matches: number;
|
|
908
|
+
eligible: number;
|
|
909
|
+
} | {
|
|
910
|
+
type: "claim_modal_deposit_selected";
|
|
911
|
+
deposit_id: string;
|
|
912
|
+
transaction_hash: string | null;
|
|
913
|
+
auto_selected: boolean;
|
|
914
|
+
}
|
|
915
|
+
/** Progress is blocked, but no attempted operation failed. */
|
|
916
|
+
| {
|
|
917
|
+
type: "claim_modal_friction";
|
|
918
|
+
step: ClaimAnalyticsStep;
|
|
919
|
+
reason: ClaimAnalyticsFailureReason;
|
|
920
|
+
}
|
|
921
|
+
/** An attempted operation failed or the flow reached a terminal condition. */
|
|
922
|
+
| {
|
|
923
|
+
type: "claim_modal_failure";
|
|
924
|
+
step: ClaimAnalyticsStep;
|
|
925
|
+
reason: ClaimAnalyticsFailureReason;
|
|
926
|
+
retryable: boolean;
|
|
927
|
+
} | {
|
|
928
|
+
type: "claim_modal_retry";
|
|
929
|
+
step: ClaimAnalyticsStep;
|
|
930
|
+
reason: ClaimAnalyticsFailureReason;
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* The submitted refund, once. Flat by contract: these are the field names the
|
|
934
|
+
* warehouse join reads to match a widget session against its backend record.
|
|
935
|
+
*/
|
|
936
|
+
| {
|
|
937
|
+
type: "claim_modal_handoff";
|
|
938
|
+
step: ClaimAnalyticsStep;
|
|
939
|
+
deposit_id: string;
|
|
940
|
+
transaction_hash: string | null;
|
|
941
|
+
refund_transaction_hash: string;
|
|
942
|
+
} | {
|
|
943
|
+
type: "claim_modal_ui_outcome";
|
|
944
|
+
step: ClaimAnalyticsStep;
|
|
945
|
+
outcome: ClaimAnalyticsUiOutcome;
|
|
946
|
+
} | {
|
|
947
|
+
type: "claim_modal_abandoned";
|
|
948
|
+
step: ClaimAnalyticsStep;
|
|
949
|
+
reason: ClaimAnalyticsAbandonmentReason;
|
|
950
|
+
} | {
|
|
951
|
+
type: "claim_modal_close";
|
|
952
|
+
source: ClaimAnalyticsCloseSource;
|
|
953
|
+
step: ClaimAnalyticsStep | null;
|
|
954
|
+
after_handoff: boolean;
|
|
955
|
+
};
|
|
956
|
+
type ClaimAnalyticsEvent = ClaimAnalyticsEventPayload & AnalyticsEventEnvelope<"claim", ClaimAnalyticsSessionProperties>;
|
|
957
|
+
/**
|
|
958
|
+
* Why a batch of analytics events could not be delivered to Rhinestone.
|
|
959
|
+
* `network` also covers a Content-Security-Policy `connect-src` block, which a
|
|
960
|
+
* browser reports to JavaScript as an ordinary fetch failure.
|
|
961
|
+
*/
|
|
962
|
+
type AnalyticsIngestFailureReason = "network" | "rejected" | "conflict" | "unauthorized" | "throttled" | "unavailable" | "token_unavailable" | "unsupported";
|
|
963
|
+
/**
|
|
964
|
+
* Delivery diagnostic, not a funnel event: it reports that analytics could not
|
|
965
|
+
* be sent, and is never itself sent. Emitted at most once per distinct reason
|
|
966
|
+
* per session — a blocked origin reports once, not once per attempt.
|
|
967
|
+
*/
|
|
968
|
+
interface AnalyticsIngestFailureEvent {
|
|
969
|
+
type: "analytics_ingest_failure";
|
|
970
|
+
session_id: string;
|
|
971
|
+
modal: "deposit" | "withdraw" | "claim";
|
|
972
|
+
widget_version: string;
|
|
973
|
+
timestamp: string;
|
|
974
|
+
reason: AnalyticsIngestFailureReason;
|
|
975
|
+
/** HTTP status when there was a response; absent when the request failed. */
|
|
976
|
+
status?: number;
|
|
977
|
+
/** Events lost in this session so far, at the time of emission. */
|
|
978
|
+
dropped_events: number;
|
|
979
|
+
}
|
|
980
|
+
type ModalAnalyticsEvent = DepositAnalyticsEvent | WithdrawAnalyticsEvent | ClaimAnalyticsEvent | AnalyticsIngestFailureEvent;
|
|
981
|
+
|
|
982
|
+
export type { WithdrawAnalyticsCloseSource as $, AnalyticsEventEnvelope as A, DepositAnalyticsStep as B, ChainId as C, DepositAnalyticsAbandonmentReason as D, DepositAnalyticsTransferStep as E, DepositAnalyticsUiOutcome as F, DepositAnalyticsWalletStep as G, DepositAssetMigrationMethodIdentifiers as H, DepositCompleteEventData as I, DepositExchangeConnectMethodIdentifiers as J, DepositFailedEventData as K, DepositFiatOnrampMethodIdentifiers as L, DepositFundingMethod as M, DepositLifecycleEvent as N, DepositModalProps as O, DepositModalTheme as P, DepositModalUIConfig as Q, DepositSubmittedEventData as R, DepositTransferHandoffIdentifiers as S, DepositWalletIntegration as T, DepositWalletMethodIdentifiers as U, ErrorEventData as V, FiatMethodsConfig as W, ModalAnalyticsEvent as X, OutputTokenRule as Y, RpcUrlMap as Z, WithdrawAnalyticsAbandonmentReason as _, AnalyticsIngestFailureEvent as a, WithdrawAnalyticsEvent as a0, WithdrawAnalyticsEventPayload as a1, WithdrawAnalyticsFailureReason as a2, WithdrawAnalyticsSessionProperties as a3, WithdrawAnalyticsStep as a4, WithdrawAnalyticsUiOutcome as a5, WithdrawCompleteEventData as a6, WithdrawFailedEventData as a7, WithdrawLifecycleEvent as a8, WithdrawModalProps as a9, WithdrawSubmittedEventData as aa, WithdrawTransferRequest as ab, RecoveryErrorCode as ac, SignRecovery as ad, SignRecoveryPayload as ae, AnalyticsIngestFailureReason as b, AnalyticsReasonFamily as c, AssetMigrationsConfig as d, AssetOption as e, ClaimAnalyticsAbandonmentReason as f, ClaimAnalyticsCloseSource as g, ClaimAnalyticsEvent as h, ClaimAnalyticsEventPayload as i, ClaimAnalyticsFailureReason as j, ClaimAnalyticsSessionProperties as k, ClaimAnalyticsStep as l, ClaimAnalyticsUiOutcome as m, ClaimLifecycleEvent as n, ClaimModalProps as o, ConnectedEventData as p, DepositAnalyticsCloseSource as q, DepositAnalyticsCorrelator as r, DepositAnalyticsEvent as s, DepositAnalyticsEventPayload as t, DepositAnalyticsExchangeStep as u, DepositAnalyticsFailureReason as v, DepositAnalyticsFiatStep as w, DepositAnalyticsMigrationStep as x, DepositAnalyticsSessionProperties as y, DepositAnalyticsSharedStep as z };
|