@rhinestone/deposit-modal 0.12.2 → 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.
Files changed (68) hide show
  1. package/README.md +73 -18
  2. package/bridge-transcript.json +653 -0
  3. package/dist/ClaimModal-IKTJU43Y.cjs +13 -0
  4. package/dist/ClaimModal-SEKNWRMA.mjs +13 -0
  5. package/dist/{DepositModalReown-VG66OTIU.cjs → DepositModalReown-46LPVFB6.cjs} +58 -35
  6. package/dist/{DepositModalReown-TEC3MEZ4.mjs → DepositModalReown-Q2JMLT47.mjs} +45 -22
  7. package/dist/{QRCode-WUC652SH.mjs → QRCode-5RGIZZHL.mjs} +1 -1
  8. package/dist/{QRCode-5DXFNKI2.cjs → QRCode-JKXG4RHN.cjs} +2 -2
  9. package/dist/WithdrawModal-5ICGD4HJ.mjs +12 -0
  10. package/dist/WithdrawModal-VP6PMIRO.cjs +12 -0
  11. package/dist/{chunk-O7BCVQ6L.cjs → chunk-4KCSH4T3.cjs} +157 -199
  12. package/dist/chunk-6KG642KH.cjs +31 -0
  13. package/dist/{chunk-PWLEBV5V.cjs → chunk-7ICSHJFE.cjs} +296 -220
  14. package/dist/{chunk-J46WDSRD.mjs → chunk-7SR7ENVJ.mjs} +165 -89
  15. package/dist/{chunk-2TPSF77V.mjs → chunk-CFKC77SV.mjs} +455 -261
  16. package/dist/{chunk-75DVGSAX.cjs → chunk-DW2EQA2U.cjs} +6 -3
  17. package/dist/{chunk-FXXUIK4E.mjs → chunk-IN77XSWO.mjs} +899 -153
  18. package/dist/chunk-K4H6TGBE.mjs +31 -0
  19. package/dist/{chunk-SDSKIJC7.mjs → chunk-KTUVSKR4.mjs} +2410 -1177
  20. package/dist/{chunk-HL5NUKZW.cjs → chunk-LZFRL2AL.cjs} +3 -3
  21. package/dist/{chunk-UQIJU6HV.cjs → chunk-MTFJSE52.cjs} +499 -191
  22. package/dist/{chunk-FLVLYO64.mjs → chunk-PKML3XVS.mjs} +430 -122
  23. package/dist/{chunk-4ZXQPFNU.mjs → chunk-RN5VKWI6.mjs} +4 -1
  24. package/dist/{chunk-BRYNGLDM.cjs → chunk-V2OBGLJD.cjs} +961 -215
  25. package/dist/{chunk-3STTWRAN.mjs → chunk-VUATPOWJ.mjs} +147 -189
  26. package/dist/{chunk-JE4R5VA3.mjs → chunk-WUJIKCFU.mjs} +1 -1
  27. package/dist/chunk-X2IPAPXU.cjs +163 -0
  28. package/dist/{chunk-OIN4CXCP.cjs → chunk-YCQZJQO6.cjs} +2343 -1110
  29. package/dist/{chunk-TM7VGHAG.cjs → chunk-YWMWI7PZ.cjs} +462 -268
  30. package/dist/chunk-ZEO6ADM3.mjs +163 -0
  31. package/dist/claim.cjs +7 -6
  32. package/dist/claim.d.cts +11 -3
  33. package/dist/claim.d.ts +11 -3
  34. package/dist/claim.mjs +6 -5
  35. package/dist/{constants-FuzG3h4m.d.cts → constants-DBrWhJWE.d.cts} +12 -7
  36. package/dist/{constants-FuzG3h4m.d.ts → constants-DBrWhJWE.d.ts} +12 -7
  37. package/dist/constants.cjs +3 -9
  38. package/dist/constants.d.cts +2 -3
  39. package/dist/constants.d.ts +2 -3
  40. package/dist/constants.mjs +4 -10
  41. package/dist/deposit.cjs +8 -8
  42. package/dist/deposit.d.cts +2 -2
  43. package/dist/deposit.d.ts +2 -2
  44. package/dist/deposit.mjs +7 -7
  45. package/dist/embed.cjs +1476 -0
  46. package/dist/embed.d.cts +183 -0
  47. package/dist/embed.d.ts +183 -0
  48. package/dist/embed.mjs +1476 -0
  49. package/dist/index.cjs +11 -16
  50. package/dist/index.d.cts +3 -3
  51. package/dist/index.d.ts +3 -3
  52. package/dist/index.mjs +14 -19
  53. package/dist/modal-ui-state-OD1RmKkK.d.cts +30 -0
  54. package/dist/modal-ui-state-OD1RmKkK.d.ts +30 -0
  55. package/dist/polymarket.cjs +17 -7
  56. package/dist/polymarket.mjs +13 -3
  57. package/dist/styles.css +124 -98
  58. package/dist/types-Bho4OA03.d.ts +982 -0
  59. package/dist/types-DP_3KwlD.d.cts +982 -0
  60. package/dist/withdraw.cjs +6 -6
  61. package/dist/withdraw.d.cts +11 -3
  62. package/dist/withdraw.d.ts +11 -3
  63. package/dist/withdraw.mjs +5 -5
  64. package/package.json +59 -6
  65. package/dist/chunk-IAGFDSNC.mjs +0 -11
  66. package/dist/chunk-L32UI7LA.cjs +0 -11
  67. package/dist/types-BO4iP6fG.d.cts +0 -612
  68. package/dist/types-oFblf65g.d.ts +0 -612
@@ -1,8 +1,13 @@
1
+ import {
2
+ RecoveryError,
3
+ submitSignedRecovery
4
+ } from "./chunk-ZEO6ADM3.mjs";
1
5
  import {
2
6
  ListRow
3
- } from "./chunk-JE4R5VA3.mjs";
7
+ } from "./chunk-WUJIKCFU.mjs";
4
8
  import {
5
9
  AlertTriangleIcon,
10
+ AnalyticsSession,
6
11
  BodyHeader,
7
12
  Button,
8
13
  Callout,
@@ -21,30 +26,26 @@ import {
21
26
  applyTheme,
22
27
  checkBackendUrl,
23
28
  createDepositService,
24
- debugError,
25
- debugLog,
26
29
  formatTokenAmount,
27
30
  formatUserError,
31
+ useClaimAnalyticsEmitter,
28
32
  useExplorerTxUrl,
29
33
  useLatestRef,
30
34
  useStableRpcUrls
31
- } from "./chunk-FXXUIK4E.mjs";
32
- import {
33
- SERVICE_HEADERS
34
- } from "./chunk-IAGFDSNC.mjs";
35
+ } from "./chunk-IN77XSWO.mjs";
35
36
  import {
36
37
  getChainIcon,
37
38
  getChainName,
38
39
  getTokenDecimalsByAddress,
39
40
  getTokenSymbol,
40
41
  tokenIconUrl
41
- } from "./chunk-3STTWRAN.mjs";
42
+ } from "./chunk-VUATPOWJ.mjs";
42
43
 
43
44
  // src/ClaimModal.tsx
44
45
  import {
45
46
  useCallback,
46
47
  useEffect,
47
- useMemo,
48
+ useMemo as useMemo2,
48
49
  useReducer,
49
50
  useRef,
50
51
  useState
@@ -76,144 +77,193 @@ var Input = forwardRef(
76
77
  );
77
78
  Input.displayName = "Input";
78
79
 
79
- // src/core/recovery.ts
80
- var RECOVER_DOMAIN = {
81
- name: "Rhinestone Deposit Recovery",
82
- version: "1"
83
- };
84
- var RECOVER_TYPES = {
85
- RecoverDeposit: [
86
- { name: "depositId", type: "uint256" },
87
- { name: "destination", type: "address" }
88
- ]
89
- };
90
- var RecoveryError = class extends Error {
91
- constructor(message, status, code, retryable = false) {
92
- super(message);
93
- this.name = "RecoveryError";
94
- this.status = status;
95
- this.code = code;
96
- this.retryable = retryable;
97
- }
98
- };
99
- function formatRecoveryError(status, code, serverMessage) {
100
- switch (code) {
80
+ // src/core/claim-analytics.tsx
81
+ import {
82
+ createContext,
83
+ useContext,
84
+ useMemo
85
+ } from "react";
86
+ import { jsx as jsx2 } from "react/jsx-runtime";
87
+ function claimFailureReasonForError(error) {
88
+ if (!(error instanceof RecoveryError)) return "refund_failed";
89
+ switch (error.code) {
90
+ case "SIGNATURE_INVALID":
91
+ return "signature_invalid";
101
92
  case "DEPOSIT_NOT_RECOVERABLE":
102
- return {
103
- message: "This deposit can't be recovered \u2014 it may already have been claimed.",
104
- retryable: false
105
- };
93
+ return "recovery_deposit_not_recoverable";
106
94
  case "RECOVERY_UNSUPPORTED":
107
- return {
108
- message: "This deposit can't be recovered automatically. Contact support to get your funds back.",
109
- retryable: false
110
- };
111
- case "SIGNATURE_INVALID":
112
- return {
113
- message: "That signature wasn't accepted for this wallet. Contact support to recover this deposit.",
114
- retryable: false
115
- };
95
+ return "recovery_unsupported";
116
96
  case "VERIFICATION_UNAVAILABLE":
117
- return {
118
- message: "Couldn't verify your signature just now. Try again shortly.",
119
- retryable: true
120
- };
97
+ return "signature_verification_unavailable";
121
98
  case "REFUND_RECONCILIATION_REQUIRED":
122
- return {
123
- message: "Your recovery is being reviewed. Contact support with this deposit if it doesn't arrive.",
124
- retryable: false
125
- };
99
+ return "refund_reconciliation_required";
126
100
  case "REFUND_FAILED":
127
- return {
128
- message: serverMessage ?? "The recovery couldn't be completed. Please try again or contact support.",
129
- retryable: true
130
- };
101
+ return "refund_failed";
131
102
  default:
132
- if (status === 0) {
133
- return {
134
- message: "Couldn't reach the recovery service. Check your connection and try again.",
135
- retryable: true
136
- };
137
- }
138
- return {
139
- message: serverMessage ?? "The recovery couldn't be completed. Please try again or contact support.",
140
- retryable: true
141
- };
103
+ if (error.phase === "signature") return "signature_rejected";
104
+ if (error.phase === "request") return "refund_service_unreachable";
105
+ return "refund_failed";
142
106
  }
143
107
  }
144
- async function submitSignedRecovery(params) {
145
- const { backendUrl, depositId, signer, destination, signRecovery, debug } = params;
146
- const scope = "service:recovery";
147
- const typedData = {
148
- domain: RECOVER_DOMAIN,
149
- types: RECOVER_TYPES,
150
- primaryType: "RecoverDeposit",
151
- message: { depositId: BigInt(depositId), destination }
108
+ function createClaimAnalyticsController(emit) {
109
+ let step = null;
110
+ let afterHandoff = false;
111
+ let opened = false;
112
+ let closed = false;
113
+ const dedupe = /* @__PURE__ */ new Set();
114
+ const send = (payload) => {
115
+ controller.openSession();
116
+ emit(payload);
152
117
  };
153
- let signature;
154
- try {
155
- signature = await signRecovery({ typedData, signer, depositId, destination });
156
- } catch (error) {
157
- debugError(debug, scope, "signRecovery:failed", error);
158
- throw new RecoveryError(
159
- "Signature request was declined. Approve it in your wallet to recover this deposit.",
160
- 0,
161
- void 0,
162
- true
163
- );
164
- }
165
- if (!signature) {
166
- throw new RecoveryError(
167
- "Signature request was declined. Approve it in your wallet to recover this deposit.",
168
- 0,
169
- void 0,
170
- true
171
- );
172
- }
173
- const url = `${backendUrl.replace(/\/$/, "")}/deposits/recover`;
174
- debugLog(debug, scope, "submitSignedRecovery:request", {
175
- url,
176
- depositId,
177
- signer
178
- });
179
- let response;
180
- try {
181
- response = await fetch(url, {
182
- method: "POST",
183
- // The shared const, so recovery carries `x-deposit-modal-version` like
184
- // every other backend call. Without it this path would be invisible in the
185
- // per-client version telemetry the processor records.
186
- headers: SERVICE_HEADERS,
187
- // `depositId` as a string: it is a uint256 upstream and JSON numbers lose
188
- // precision well before that range.
189
- body: JSON.stringify({ depositId, destination, signature })
190
- });
191
- } catch (error) {
192
- debugError(debug, scope, "submitSignedRecovery:network", error);
193
- const { message, retryable } = formatRecoveryError(0);
194
- throw new RecoveryError(message, 0, void 0, retryable);
195
- }
196
- if (!response.ok) {
197
- const body = await response.json().catch(() => ({}));
198
- debugError(debug, scope, "submitSignedRecovery:failed", body, {
199
- status: response.status
200
- });
201
- const { message, retryable } = formatRecoveryError(
202
- response.status,
203
- body.code,
204
- body.error
205
- );
206
- throw new RecoveryError(message, response.status, body.code, retryable);
207
- }
208
- const result = await response.json();
209
- debugLog(debug, scope, "submitSignedRecovery:success", {
210
- transactionHash: result.transactionHash
211
- });
212
- return result;
118
+ const emitOnce = (key, payload) => {
119
+ if (dedupe.has(key)) return;
120
+ dedupe.add(key);
121
+ send(payload);
122
+ };
123
+ const rearmStep = (rearmed) => {
124
+ for (const key of [...dedupe]) {
125
+ if (key.includes(`:${rearmed}:`)) dedupe.delete(key);
126
+ }
127
+ };
128
+ const controller = {
129
+ openSession() {
130
+ if (opened) return;
131
+ opened = true;
132
+ emit({ type: "claim_modal_open" });
133
+ },
134
+ openStep(nextStep) {
135
+ controller.openSession();
136
+ if (step === nextStep) return;
137
+ step = nextStep;
138
+ emitOnce(`step-open:${nextStep}`, {
139
+ type: "claim_modal_step_open",
140
+ step: nextStep
141
+ });
142
+ },
143
+ completeStep(completedStep = step ?? void 0) {
144
+ if (!completedStep) return;
145
+ emitOnce(`step-complete:${completedStep}`, {
146
+ type: "claim_modal_step_complete",
147
+ step: completedStep
148
+ });
149
+ },
150
+ rearmStep(rearmed) {
151
+ rearmStep(rearmed);
152
+ },
153
+ // One per submitted search, never deduplicated: the searched hash is
154
+ // deliberately not in the stream, so collapsing two searches that returned
155
+ // the same counts would make the second one unrecoverable.
156
+ lookupResult(matches, eligible) {
157
+ send({
158
+ type: "claim_modal_lookup_result",
159
+ matches,
160
+ eligible
161
+ });
162
+ },
163
+ selectDeposit({ depositId, transactionHash, autoSelected }) {
164
+ emitOnce(`deposit-selected:${depositId}`, {
165
+ type: "claim_modal_deposit_selected",
166
+ deposit_id: depositId,
167
+ transaction_hash: transactionHash,
168
+ auto_selected: autoSelected
169
+ });
170
+ },
171
+ friction(reason, eventStep = step ?? void 0) {
172
+ if (!eventStep) return;
173
+ emitOnce(`friction:${eventStep}:${reason}`, {
174
+ type: "claim_modal_friction",
175
+ step: eventStep,
176
+ reason
177
+ });
178
+ },
179
+ failure(reason, retryable, eventStep = step ?? void 0) {
180
+ if (!eventStep) return;
181
+ emitOnce(`failure:${eventStep}:${reason}`, {
182
+ type: "claim_modal_failure",
183
+ step: eventStep,
184
+ reason,
185
+ retryable
186
+ });
187
+ },
188
+ retry(reason, eventStep = step ?? void 0) {
189
+ if (!eventStep) return;
190
+ send({ type: "claim_modal_retry", step: eventStep, reason });
191
+ rearmStep(eventStep);
192
+ },
193
+ handoff({ depositId, transactionHash, refundTransactionHash }, eventStep) {
194
+ const handoffStep = eventStep ?? step ?? "submit";
195
+ if (step !== handoffStep) controller.openStep(handoffStep);
196
+ afterHandoff = true;
197
+ emitOnce(`handoff:${refundTransactionHash}`, {
198
+ type: "claim_modal_handoff",
199
+ step: handoffStep,
200
+ deposit_id: depositId,
201
+ transaction_hash: transactionHash,
202
+ refund_transaction_hash: refundTransactionHash
203
+ });
204
+ },
205
+ // Keyed by step so a retry re-arms it: a second failed submit is a second
206
+ // terminal outcome, not a duplicate of the first.
207
+ outcome(outcome) {
208
+ if (!step) return;
209
+ emitOnce(`outcome:${step}:${outcome}`, {
210
+ type: "claim_modal_ui_outcome",
211
+ step,
212
+ outcome
213
+ });
214
+ },
215
+ abandon(reason) {
216
+ if (!step || afterHandoff) return;
217
+ emitOnce(`abandon:${step}:${reason}`, {
218
+ type: "claim_modal_abandoned",
219
+ step,
220
+ reason
221
+ });
222
+ },
223
+ close(source) {
224
+ if (closed) return;
225
+ closed = true;
226
+ send({
227
+ type: "claim_modal_close",
228
+ source,
229
+ step,
230
+ after_handoff: afterHandoff
231
+ });
232
+ },
233
+ /** "Claim another deposit" on the success screen: a fresh attempt in the
234
+ * same session, so the envelope and its session id stay. */
235
+ resetAttempt() {
236
+ step = null;
237
+ afterHandoff = false;
238
+ dedupe.clear();
239
+ },
240
+ get step() {
241
+ return step;
242
+ },
243
+ get afterHandoff() {
244
+ return afterHandoff;
245
+ }
246
+ };
247
+ return controller;
248
+ }
249
+ var ClaimAnalyticsControllerContext = createContext(null);
250
+ var noopController = createClaimAnalyticsController(() => {
251
+ });
252
+ function ClaimAnalyticsControllerProvider({
253
+ children,
254
+ controllerRef
255
+ }) {
256
+ const emit = useClaimAnalyticsEmitter();
257
+ const controller = useMemo(() => createClaimAnalyticsController(emit), [emit]);
258
+ if (controllerRef) controllerRef.current = controller;
259
+ return /* @__PURE__ */ jsx2(ClaimAnalyticsControllerContext.Provider, { value: controller, children });
260
+ }
261
+ function useClaimAnalyticsController() {
262
+ return useContext(ClaimAnalyticsControllerContext) ?? noopController;
213
263
  }
214
264
 
215
265
  // src/ClaimModal.tsx
216
- import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
266
+ import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
217
267
  function evmChainIdFromCaip2(chain) {
218
268
  if (!chain?.startsWith("eip155:")) return null;
219
269
  const id = Number.parseInt(chain.slice("eip155:".length), 10);
@@ -306,6 +356,27 @@ function claimReducer(state, action) {
306
356
  return state;
307
357
  }
308
358
  }
359
+ function buildClaimAnalyticsSessionProperties({
360
+ inline = false,
361
+ closeOnOverlayClick = false,
362
+ defaultTxHash,
363
+ defaultRefundDestination
364
+ }) {
365
+ return {
366
+ presentation: inline ? "inline" : "overlay",
367
+ overlay_close_enabled: !inline && closeOnOverlayClick,
368
+ prefills: {
369
+ transaction_hash: defaultTxHash !== void 0,
370
+ refund_destination: defaultRefundDestination !== void 0
371
+ }
372
+ };
373
+ }
374
+ function analyticsStepForClaimStep(step) {
375
+ if (step === "lookup") return "lookup";
376
+ if (step === "select") return "select";
377
+ if (step === "review") return "review";
378
+ return "submit";
379
+ }
309
380
  function ClaimModal({
310
381
  signRecovery,
311
382
  isOpen,
@@ -323,16 +394,21 @@ function ClaimModal({
323
394
  onLifecycle,
324
395
  onEvent,
325
396
  onError,
326
- debug
397
+ enableAnalyticsIngest,
398
+ analyticsIngestUrl,
399
+ debug,
400
+ onUiState
327
401
  }) {
328
402
  checkBackendUrl("ClaimModal", backendUrl);
329
403
  const modalRef = useRef(null);
330
404
  const onReadyRef = useLatestRef(onReady);
331
405
  const onLifecycleRef = useLatestRef(onLifecycle);
332
- const onEventRef = useLatestRef(onEvent);
333
406
  const onErrorRef = useLatestRef(onError);
407
+ const analyticsControllerRef = useRef(null);
408
+ const lastSubmitFailureRef = useRef(null);
409
+ const previousOpenRef = useRef(isOpen);
334
410
  const rpcUrls = useStableRpcUrls(rpcUrlsProp);
335
- const service = useMemo(
411
+ const service = useMemo2(
336
412
  () => createDepositService(backendUrl, { debug, debugScope: "service:claim" }),
337
413
  [backendUrl, debug]
338
414
  );
@@ -341,80 +417,144 @@ function ClaimModal({
341
417
  const isOpenRef = useRef(isOpen);
342
418
  isOpenRef.current = isOpen;
343
419
  useEffect(() => {
344
- if (isOpen && modalRef.current) applyTheme(modalRef.current, theme);
420
+ if (!isOpen || !modalRef.current) return;
421
+ return applyTheme(modalRef.current, theme);
345
422
  }, [isOpen, theme]);
346
423
  useEffect(() => {
347
424
  if (isOpen) {
348
425
  onReadyRef.current?.();
349
- onEventRef.current?.({ type: "claim_modal_open" });
350
426
  }
351
- }, [isOpen, onReadyRef, onEventRef]);
427
+ }, [isOpen, onReadyRef]);
428
+ useEffect(() => {
429
+ if (previousOpenRef.current && !isOpen) {
430
+ const analytics = analyticsControllerRef.current;
431
+ analytics?.abandon("modal_close");
432
+ analytics?.close("host_controlled");
433
+ }
434
+ previousOpenRef.current = isOpen;
435
+ }, [isOpen]);
352
436
  useEffect(() => {
353
437
  if (!isOpen) {
354
438
  operationEpochRef.current += 1;
355
439
  dispatch({ type: "reset" });
356
440
  }
357
441
  }, [isOpen]);
358
- const handleClose = useCallback(() => {
359
- if (state.step !== "processing") {
442
+ const closeWithSource = useCallback(
443
+ (source) => {
444
+ const analytics = analyticsControllerRef.current;
445
+ if (state.step === "processing") {
446
+ analytics?.friction("modal_close_refused_in_flight", "submit");
447
+ return;
448
+ }
449
+ analytics?.abandon("modal_close");
450
+ analytics?.close(source);
360
451
  operationEpochRef.current += 1;
361
452
  onClose();
453
+ },
454
+ [state.step, onClose]
455
+ );
456
+ const handleModalDismiss = useCallback(
457
+ (reason) => {
458
+ closeWithSource(
459
+ reason === "escape" ? "escape" : reason === "overlay" ? "overlay" : "header_button"
460
+ );
461
+ },
462
+ [closeWithSource]
463
+ );
464
+ const goBack = useCallback(() => {
465
+ const analytics = analyticsControllerRef.current;
466
+ const previousFailure = lastSubmitFailureRef.current;
467
+ if (state.step === "failed" && previousFailure?.retryable) {
468
+ lastSubmitFailureRef.current = null;
469
+ analytics?.retry(previousFailure.reason, "submit");
470
+ } else {
471
+ if (state.step === "failed") {
472
+ lastSubmitFailureRef.current = null;
473
+ analytics?.rearmStep("submit");
474
+ }
475
+ analytics?.abandon("back");
362
476
  }
363
- }, [state.step, onClose]);
477
+ dispatch({ type: "back" });
478
+ }, [state.step]);
364
479
  const canGoBack = state.step === "select" || state.step === "review" || state.step === "failed";
480
+ const onUiStateRef = useLatestRef(onUiState);
481
+ useEffect(() => {
482
+ onUiStateRef.current?.({
483
+ screen: state.step,
484
+ back: canGoBack ? goBack : void 0,
485
+ submitting: state.step === "processing"
486
+ });
487
+ }, [state.step, canGoBack, goBack, onUiStateRef]);
365
488
  const showBackButton = uiConfig?.showBackButton ?? true;
366
- return /* @__PURE__ */ jsx2(RpcUrlsProvider, { value: rpcUrls, children: /* @__PURE__ */ jsx2(ChainCatalogProvider, { service, rpcUrls, children: /* @__PURE__ */ jsx2(
489
+ return /* @__PURE__ */ jsx3(RpcUrlsProvider, { value: rpcUrls, children: /* @__PURE__ */ jsx3(ChainCatalogProvider, { service, rpcUrls, children: /* @__PURE__ */ jsx3(
367
490
  Modal,
368
491
  {
369
492
  isOpen,
370
- onClose: handleClose,
493
+ onClose: handleModalDismiss,
371
494
  className,
372
495
  inline,
373
496
  closeOnOverlayClick,
374
- children: /* @__PURE__ */ jsxs2("div", { ref: modalRef, className: "rs-modal", children: [
375
- /* @__PURE__ */ jsxs2("div", { className: "rs-modal-header--redesigned", children: [
376
- /* @__PURE__ */ jsx2("div", { className: "rs-modal-header-nav-left", children: showBackButton && canGoBack && /* @__PURE__ */ jsx2(
377
- "button",
378
- {
379
- type: "button",
380
- className: "rs-modal-header-back",
381
- "aria-label": "Go back",
382
- onClick: () => dispatch({ type: "back" }),
383
- children: /* @__PURE__ */ jsx2(ChevronLeftIcon, {})
384
- }
385
- ) }),
386
- /* @__PURE__ */ jsx2("div", { className: "rs-modal-header-nav-right", children: /* @__PURE__ */ jsx2(
387
- "button",
388
- {
389
- type: "button",
390
- onClick: handleClose,
391
- disabled: state.step === "processing",
392
- className: "rs-modal-close",
393
- "aria-label": "Close",
394
- children: /* @__PURE__ */ jsx2(CloseIcon, {})
395
- }
396
- ) })
397
- ] }),
398
- /* @__PURE__ */ jsx2("div", { className: "rs-modal-body", children: /* @__PURE__ */ jsx2(
399
- ClaimBody,
400
- {
401
- state,
402
- dispatch,
403
- service,
404
- signRecovery,
405
- backendUrl,
406
- debug,
497
+ children: /* @__PURE__ */ jsx3(
498
+ AnalyticsSession,
499
+ {
500
+ modal: "claim",
501
+ sessionProperties: buildClaimAnalyticsSessionProperties({
502
+ inline,
503
+ closeOnOverlayClick,
407
504
  defaultTxHash,
408
- defaultRefundDestination,
409
- onClose: handleClose,
410
- operationEpochRef,
411
- isOpenRef,
412
- onLifecycleRef,
413
- onEventRef,
414
- onErrorRef
415
- }
416
- ) })
417
- ] })
505
+ defaultRefundDestination
506
+ }),
507
+ onEvent,
508
+ backendUrl,
509
+ enableIngest: enableAnalyticsIngest,
510
+ ingestUrl: analyticsIngestUrl,
511
+ children: /* @__PURE__ */ jsx3(ClaimAnalyticsControllerProvider, { controllerRef: analyticsControllerRef, children: /* @__PURE__ */ jsxs2("div", { ref: modalRef, className: "rs-modal", children: [
512
+ /* @__PURE__ */ jsxs2("div", { className: "rs-modal-header--redesigned", children: [
513
+ /* @__PURE__ */ jsx3("div", { className: "rs-modal-header-nav-left", children: showBackButton && canGoBack && /* @__PURE__ */ jsx3(
514
+ "button",
515
+ {
516
+ type: "button",
517
+ className: "rs-modal-header-back",
518
+ "aria-label": "Go back",
519
+ onClick: goBack,
520
+ children: /* @__PURE__ */ jsx3(ChevronLeftIcon, {})
521
+ }
522
+ ) }),
523
+ /* @__PURE__ */ jsx3("div", { className: "rs-modal-header-nav-right", children: /* @__PURE__ */ jsx3(
524
+ "button",
525
+ {
526
+ type: "button",
527
+ onClick: () => closeWithSource("header_button"),
528
+ disabled: state.step === "processing",
529
+ className: "rs-modal-close",
530
+ "aria-label": "Close",
531
+ children: /* @__PURE__ */ jsx3(CloseIcon, {})
532
+ }
533
+ ) })
534
+ ] }),
535
+ /* @__PURE__ */ jsx3("div", { className: "rs-modal-body", children: /* @__PURE__ */ jsx3(
536
+ ClaimBody,
537
+ {
538
+ state,
539
+ dispatch,
540
+ service,
541
+ signRecovery,
542
+ backendUrl,
543
+ debug,
544
+ defaultTxHash,
545
+ defaultRefundDestination,
546
+ onClose: closeWithSource,
547
+ onBack: goBack,
548
+ operationEpochRef,
549
+ isOpenRef,
550
+ lastSubmitFailureRef,
551
+ onLifecycleRef,
552
+ onErrorRef
553
+ }
554
+ ) })
555
+ ] }) })
556
+ }
557
+ )
418
558
  }
419
559
  ) }) });
420
560
  }
@@ -428,15 +568,21 @@ function ClaimBody({
428
568
  defaultTxHash,
429
569
  defaultRefundDestination,
430
570
  onClose,
571
+ onBack,
431
572
  operationEpochRef,
432
573
  isOpenRef,
574
+ lastSubmitFailureRef,
433
575
  onLifecycleRef,
434
- onEventRef,
435
576
  onErrorRef
436
577
  }) {
578
+ const analytics = useClaimAnalyticsController();
579
+ useEffect(() => {
580
+ analytics.openSession();
581
+ analytics.openStep(analyticsStepForClaimStep(state.step));
582
+ }, [analytics, state.step]);
437
583
  switch (state.step) {
438
584
  case "lookup":
439
- return /* @__PURE__ */ jsx2(
585
+ return /* @__PURE__ */ jsx3(
440
586
  LookupStep,
441
587
  {
442
588
  service,
@@ -446,24 +592,29 @@ function ClaimBody({
446
592
  onResults: (deposits) => {
447
593
  const eligible = deposits.filter(isEligible);
448
594
  const autoSelect = deposits.length === 1 && eligible.length === 1 ? deposits[0] : null;
595
+ analytics.completeStep("lookup");
596
+ if (autoSelect) reportSelection(autoSelect, true);
449
597
  dispatch({ type: "lookup/results", deposits, autoSelect });
450
598
  },
451
599
  onLifecycleRef,
452
- onEventRef,
453
600
  onErrorRef
454
601
  }
455
602
  );
456
603
  case "select":
457
- return /* @__PURE__ */ jsx2(
604
+ return /* @__PURE__ */ jsx3(
458
605
  SelectStep,
459
606
  {
460
607
  deposits: state.deposits,
461
- onSelect: (deposit) => dispatch({ type: "select", deposit })
608
+ onSelect: (deposit) => {
609
+ analytics.completeStep("select");
610
+ reportSelection(deposit, false);
611
+ dispatch({ type: "select", deposit });
612
+ }
462
613
  }
463
614
  );
464
615
  case "review":
465
616
  case "processing":
466
- return /* @__PURE__ */ jsx2(
617
+ return /* @__PURE__ */ jsx3(
467
618
  ReviewStep,
468
619
  {
469
620
  deposit: state.selected,
@@ -473,27 +624,51 @@ function ClaimBody({
473
624
  }
474
625
  );
475
626
  case "complete":
476
- return /* @__PURE__ */ jsx2(ResultStep, { result: state.result, onClose, onReset: () => dispatch({ type: "reset" }) });
627
+ return /* @__PURE__ */ jsx3(
628
+ ResultStep,
629
+ {
630
+ result: state.result,
631
+ onClose: () => onClose("success_done"),
632
+ onReset: () => {
633
+ analytics.resetAttempt();
634
+ dispatch({ type: "reset" });
635
+ }
636
+ }
637
+ );
477
638
  case "failed":
478
- return /* @__PURE__ */ jsx2(
639
+ return /* @__PURE__ */ jsx3(
479
640
  ResultStep,
480
641
  {
481
642
  error: state.error,
482
- onClose,
483
- onRetry: state.retryable ? () => dispatch({ type: "back" }) : void 0
643
+ onClose: () => onClose("failure_cancel"),
644
+ onRetry: state.retryable ? onBack : void 0
484
645
  }
485
646
  );
486
647
  default:
487
648
  return null;
488
649
  }
650
+ function reportSelection(deposit, autoSelected) {
651
+ if (!deposit.id) return;
652
+ analytics.selectDeposit({
653
+ depositId: deposit.id,
654
+ transactionHash: deposit.txHash ?? null,
655
+ autoSelected
656
+ });
657
+ }
489
658
  async function submitRecoveryRequest(destination) {
490
659
  const deposit = state.selected;
491
660
  if (!deposit) return;
492
661
  const sourceChainId = evmChainIdFromCaip2(deposit.chain);
493
662
  if (sourceChainId == null || !deposit.id || !deposit.recipient || !deposit.depositAddress || !deposit.token || !deposit.chain) {
663
+ analytics.failure("recovery_deposit_data_incomplete", false, "review");
664
+ analytics.outcome("failed");
494
665
  dispatch({
495
666
  type: "failed",
496
- error: "Deposit is missing data required to recover it."
667
+ error: "Deposit is missing data required to recover it.",
668
+ // The missing fields come off the backend row already in memory, so a
669
+ // retry re-reads nothing and fails identically. Offering one would be a
670
+ // dead end, and would also contradict the `retryable` reported above.
671
+ retryable: false
497
672
  });
498
673
  return;
499
674
  }
@@ -502,11 +677,9 @@ function ClaimBody({
502
677
  const token = deposit.token;
503
678
  const operationEpoch = operationEpochRef.current;
504
679
  const isCurrentOperation = () => isOpenRef.current && operationEpochRef.current === operationEpoch;
680
+ analytics.completeStep("review");
681
+ analytics.openStep("submit");
505
682
  dispatch({ type: "submit" });
506
- onEventRef.current?.({
507
- type: "claim_modal_refund_click",
508
- chain: `eip155:${sourceChainId}`
509
- });
510
683
  onLifecycleRef.current?.({
511
684
  type: "refund_requested",
512
685
  account,
@@ -516,6 +689,7 @@ function ClaimBody({
516
689
  try {
517
690
  const result = await submitSignedRecovery({
518
691
  backendUrl,
692
+ chainId: sourceChainId,
519
693
  depositId: deposit.id,
520
694
  signer,
521
695
  destination,
@@ -539,10 +713,16 @@ function ClaimBody({
539
713
  destination: paidTo,
540
714
  chain: sourceChainId
541
715
  });
542
- onEventRef.current?.({
543
- type: "claim_modal_complete",
544
- chain: `eip155:${sourceChainId}`
545
- });
716
+ analytics.handoff(
717
+ {
718
+ depositId: deposit.id,
719
+ transactionHash: deposit.txHash ?? null,
720
+ refundTransactionHash: result.transactionHash
721
+ },
722
+ "submit"
723
+ );
724
+ analytics.completeStep("submit");
725
+ analytics.outcome("completed");
546
726
  onLifecycleRef.current?.({
547
727
  type: "complete",
548
728
  txHash: result.transactionHash,
@@ -559,16 +739,16 @@ function ClaimBody({
559
739
  const message = recoveryError?.message ?? formatUserError(
560
740
  err instanceof Error ? err.message : "Recovery failed"
561
741
  );
742
+ const retryable = recoveryError?.retryable ?? true;
562
743
  dispatch({
563
744
  type: "failed",
564
745
  error: message,
565
- retryable: recoveryError?.retryable ?? true
566
- });
567
- onEventRef.current?.({
568
- type: "claim_modal_failed",
569
- chain: `eip155:${sourceChainId}`,
570
- status
746
+ retryable
571
747
  });
748
+ const reason = claimFailureReasonForError(err);
749
+ lastSubmitFailureRef.current = { reason, retryable };
750
+ analytics.failure(reason, retryable, "submit");
751
+ analytics.outcome("failed");
572
752
  onLifecycleRef.current?.({ type: "failed", status, error: message });
573
753
  onErrorRef.current?.({ message, code: "CLAIM_FAILED" });
574
754
  }
@@ -581,19 +761,25 @@ function LookupStep({
581
761
  isOpenRef,
582
762
  onResults,
583
763
  onLifecycleRef,
584
- onEventRef,
585
764
  onErrorRef
586
765
  }) {
766
+ const analytics = useClaimAnalyticsController();
587
767
  const [txHash, setTxHash] = useState(defaultTxHash ?? "");
588
768
  const [loading, setLoading] = useState(false);
589
769
  const [error, setError] = useState(null);
590
770
  const trimmed = txHash.trim();
591
771
  const validTxHash = /^0x[a-fA-F0-9]{64}$/.test(trimmed);
772
+ useEffect(() => {
773
+ if (trimmed.length > 0 && !validTxHash) {
774
+ analytics.friction("lookup_transaction_hash_invalid", "lookup");
775
+ }
776
+ }, [analytics, trimmed, validTxHash]);
592
777
  const handleLookup = useCallback(async () => {
593
778
  const operationEpoch = operationEpochRef.current;
594
779
  const isCurrentOperation = () => isOpenRef.current && operationEpochRef.current === operationEpoch;
595
780
  setError(null);
596
781
  setLoading(true);
782
+ analytics.rearmStep("lookup");
597
783
  try {
598
784
  const deposits = await service.lookupRecoverableDeposits({
599
785
  txHash: trimmed
@@ -604,15 +790,15 @@ function LookupStep({
604
790
  txHash: trimmed,
605
791
  matches: deposits.length
606
792
  });
607
- onEventRef.current?.({
608
- type: "claim_modal_lookup",
609
- matches: deposits.length
610
- });
793
+ const eligible = deposits.filter(isEligible);
794
+ analytics.lookupResult(deposits.length, eligible.length);
611
795
  if (deposits.length === 0) {
796
+ analytics.friction("lookup_no_deposits_found", "lookup");
612
797
  setError("No deposits found for this transaction.");
613
798
  return;
614
799
  }
615
- if (!deposits.some(isEligible)) {
800
+ if (eligible.length === 0) {
801
+ analytics.friction("lookup_no_eligible_deposits", "lookup");
616
802
  setError(
617
803
  "This transaction has no failed or rejected deposits available to recover."
618
804
  );
@@ -624,32 +810,33 @@ function LookupStep({
624
810
  const message = formatUserError(
625
811
  err instanceof Error ? err.message : "Lookup failed"
626
812
  );
813
+ analytics.failure("lookup_failed", true, "lookup");
627
814
  setError(message);
628
815
  onErrorRef.current?.({ message, code: "CLAIM_LOOKUP_FAILED" });
629
816
  } finally {
630
817
  if (isCurrentOperation()) setLoading(false);
631
818
  }
632
819
  }, [
820
+ analytics,
633
821
  trimmed,
634
822
  service,
635
823
  operationEpochRef,
636
824
  isOpenRef,
637
825
  onResults,
638
826
  onLifecycleRef,
639
- onEventRef,
640
827
  onErrorRef
641
828
  ]);
642
829
  return /* @__PURE__ */ jsxs2("div", { className: "rs-screen", children: [
643
830
  /* @__PURE__ */ jsxs2("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
644
- /* @__PURE__ */ jsx2(
831
+ /* @__PURE__ */ jsx3(
645
832
  BodyHeader,
646
833
  {
647
- icon: /* @__PURE__ */ jsx2(HandCoinsIcon, {}),
834
+ icon: /* @__PURE__ */ jsx3(HandCoinsIcon, {}),
648
835
  title: "Claim a deposit",
649
836
  subtitle: "Get funds from a failed deposit sent back to you on the source chain."
650
837
  }
651
838
  ),
652
- /* @__PURE__ */ jsx2(
839
+ /* @__PURE__ */ jsx3(
653
840
  Input,
654
841
  {
655
842
  label: "Transaction hash",
@@ -659,8 +846,8 @@ function LookupStep({
659
846
  error: trimmed.length > 0 && !validTxHash ? "Enter a valid transaction hash" : void 0
660
847
  }
661
848
  ),
662
- error && /* @__PURE__ */ jsx2(Callout, { variant: "error", children: error }),
663
- /* @__PURE__ */ jsx2(
849
+ error && /* @__PURE__ */ jsx3(Callout, { variant: "error", children: error }),
850
+ /* @__PURE__ */ jsx3(
664
851
  Button,
665
852
  {
666
853
  onClick: handleLookup,
@@ -672,7 +859,7 @@ function LookupStep({
672
859
  }
673
860
  )
674
861
  ] }),
675
- /* @__PURE__ */ jsx2(PoweredBy, {})
862
+ /* @__PURE__ */ jsx3(PoweredBy, {})
676
863
  ] });
677
864
  }
678
865
  function SelectStep({
@@ -681,18 +868,18 @@ function SelectStep({
681
868
  }) {
682
869
  return /* @__PURE__ */ jsxs2("div", { className: "rs-screen", children: [
683
870
  /* @__PURE__ */ jsxs2("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
684
- /* @__PURE__ */ jsx2(
871
+ /* @__PURE__ */ jsx3(
685
872
  BodyHeader,
686
873
  {
687
- icon: /* @__PURE__ */ jsx2(CoinsIcon, {}),
874
+ icon: /* @__PURE__ */ jsx3(CoinsIcon, {}),
688
875
  title: "Select a deposit",
689
876
  subtitle: "This transaction produced multiple deposits. Choose the one to claim."
690
877
  }
691
878
  ),
692
- /* @__PURE__ */ jsx2("div", { className: "rs-list", children: deposits.map((row) => {
879
+ /* @__PURE__ */ jsx3("div", { className: "rs-list", children: deposits.map((row) => {
693
880
  const { symbol, amount, chainName } = describeDeposit(row);
694
881
  const eligible = isEligible(row);
695
- return /* @__PURE__ */ jsx2(
882
+ return /* @__PURE__ */ jsx3(
696
883
  ListRow,
697
884
  {
698
885
  leadingMedia: tokenIconUrl(symbol),
@@ -706,7 +893,7 @@ function SelectStep({
706
893
  );
707
894
  }) })
708
895
  ] }),
709
- /* @__PURE__ */ jsx2(PoweredBy, {})
896
+ /* @__PURE__ */ jsx3(PoweredBy, {})
710
897
  ] });
711
898
  }
712
899
  function ReviewStep({
@@ -715,41 +902,47 @@ function ReviewStep({
715
902
  defaultRefundDestination,
716
903
  onSubmit
717
904
  }) {
905
+ const analytics = useClaimAnalyticsController();
718
906
  const { chainId, symbol, amount, chainName, chainIcon } = describeDeposit(deposit);
719
907
  const explorerTxUrl = useExplorerTxUrl();
720
908
  const [destination, setDestination] = useState(defaultRefundDestination ?? "");
721
909
  const destinationValid = isAddress(destination);
910
+ useEffect(() => {
911
+ if (destination.length > 0 && !destinationValid) {
912
+ analytics.friction("refund_destination_invalid", "review");
913
+ }
914
+ }, [analytics, destination, destinationValid]);
722
915
  return /* @__PURE__ */ jsxs2("div", { className: "rs-screen", children: [
723
916
  /* @__PURE__ */ jsxs2("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
724
- /* @__PURE__ */ jsx2(
917
+ /* @__PURE__ */ jsx3(
725
918
  BodyHeader,
726
919
  {
727
- icon: /* @__PURE__ */ jsx2(HandCoinsIcon, {}),
920
+ icon: /* @__PURE__ */ jsx3(HandCoinsIcon, {}),
728
921
  title: "Review refund",
729
922
  subtitle: "This returns the funds on the source chain. It does not retry the original bridge."
730
923
  }
731
924
  ),
732
925
  /* @__PURE__ */ jsxs2("div", { className: "rs-review-details", children: [
733
926
  /* @__PURE__ */ jsxs2("div", { className: "rs-review-detail-row", children: [
734
- /* @__PURE__ */ jsx2("span", { children: "Amount" }),
927
+ /* @__PURE__ */ jsx3("span", { children: "Amount" }),
735
928
  /* @__PURE__ */ jsxs2("span", { className: "rs-review-detail-value", children: [
736
929
  /* @__PURE__ */ jsxs2("span", { children: [
737
930
  amount,
738
931
  " ",
739
932
  symbol
740
933
  ] }),
741
- /* @__PURE__ */ jsx2("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx2(TokenIcon, { symbol }) })
934
+ /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx3(TokenIcon, { symbol }) })
742
935
  ] })
743
936
  ] }),
744
937
  /* @__PURE__ */ jsxs2("div", { className: "rs-review-detail-row", children: [
745
- /* @__PURE__ */ jsx2("span", { children: "Source chain" }),
938
+ /* @__PURE__ */ jsx3("span", { children: "Source chain" }),
746
939
  /* @__PURE__ */ jsxs2("span", { className: "rs-review-detail-value", children: [
747
- /* @__PURE__ */ jsx2("span", { children: chainName }),
748
- chainIcon && /* @__PURE__ */ jsx2("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx2(CdnIcon, { src: chainIcon }) })
940
+ /* @__PURE__ */ jsx3("span", { children: chainName }),
941
+ chainIcon && /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx3(CdnIcon, { src: chainIcon }) })
749
942
  ] })
750
943
  ] }),
751
944
  /* @__PURE__ */ jsxs2("div", { className: "rs-review-detail-row", children: [
752
- /* @__PURE__ */ jsx2("span", { children: "Deposit transaction" }),
945
+ /* @__PURE__ */ jsx3("span", { children: "Deposit transaction" }),
753
946
  (() => {
754
947
  const url = deposit.txHash ? explorerTxUrl(chainId, deposit.txHash) : null;
755
948
  const short = deposit.txHash ? shortenHash(deposit.txHash) : "\u2014";
@@ -762,14 +955,14 @@ function ReviewStep({
762
955
  rel: "noreferrer",
763
956
  children: [
764
957
  short,
765
- /* @__PURE__ */ jsx2(ExternalLinkIcon, {})
958
+ /* @__PURE__ */ jsx3(ExternalLinkIcon, {})
766
959
  ]
767
960
  }
768
- ) : /* @__PURE__ */ jsx2("span", { className: "rs-review-detail-value", children: short });
961
+ ) : /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-value", children: short });
769
962
  })()
770
963
  ] })
771
964
  ] }),
772
- /* @__PURE__ */ jsx2(
965
+ /* @__PURE__ */ jsx3(
773
966
  Input,
774
967
  {
775
968
  label: "Send to",
@@ -779,7 +972,7 @@ function ReviewStep({
779
972
  error: destination.length > 0 && !destinationValid ? "Enter a valid address" : void 0
780
973
  }
781
974
  ),
782
- /* @__PURE__ */ jsx2(
975
+ /* @__PURE__ */ jsx3(
783
976
  Button,
784
977
  {
785
978
  onClick: () => destinationValid && onSubmit(destination),
@@ -791,7 +984,7 @@ function ReviewStep({
791
984
  }
792
985
  )
793
986
  ] }),
794
- /* @__PURE__ */ jsx2(PoweredBy, {})
987
+ /* @__PURE__ */ jsx3(PoweredBy, {})
795
988
  ] });
796
989
  }
797
990
  function ResultStep({
@@ -805,10 +998,10 @@ function ResultStep({
805
998
  const explorerTxUrl = useExplorerTxUrl();
806
999
  return /* @__PURE__ */ jsxs2("div", { className: "rs-screen", children: [
807
1000
  /* @__PURE__ */ jsxs2("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
808
- /* @__PURE__ */ jsx2(
1001
+ /* @__PURE__ */ jsx3(
809
1002
  BodyHeader,
810
1003
  {
811
- icon: success ? /* @__PURE__ */ jsx2(CheckIcon, {}) : /* @__PURE__ */ jsx2(AlertTriangleIcon, {}),
1004
+ icon: success ? /* @__PURE__ */ jsx3(CheckIcon, {}) : /* @__PURE__ */ jsx3(AlertTriangleIcon, {}),
812
1005
  variant: success ? "success" : "error",
813
1006
  title: success ? "Refund submitted" : "Refund failed",
814
1007
  subtitle: success ? "Your funds are being returned on the source chain." : void 0
@@ -816,22 +1009,22 @@ function ResultStep({
816
1009
  ),
817
1010
  success ? /* @__PURE__ */ jsxs2("div", { className: "rs-review-details", children: [
818
1011
  /* @__PURE__ */ jsxs2("div", { className: "rs-review-detail-row", children: [
819
- /* @__PURE__ */ jsx2("span", { children: "Amount" }),
1012
+ /* @__PURE__ */ jsx3("span", { children: "Amount" }),
820
1013
  /* @__PURE__ */ jsxs2("span", { className: "rs-review-detail-value", children: [
821
1014
  /* @__PURE__ */ jsxs2("span", { children: [
822
1015
  result.amountDisplay,
823
1016
  " ",
824
1017
  result.symbol
825
1018
  ] }),
826
- /* @__PURE__ */ jsx2("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx2(TokenIcon, { symbol: result.symbol }) })
1019
+ /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx3(TokenIcon, { symbol: result.symbol }) })
827
1020
  ] })
828
1021
  ] }),
829
1022
  /* @__PURE__ */ jsxs2("div", { className: "rs-review-detail-row", children: [
830
- /* @__PURE__ */ jsx2("span", { children: "Sent to" }),
831
- /* @__PURE__ */ jsx2("span", { className: "rs-review-detail-value", children: shortenAddress(result.destination) })
1023
+ /* @__PURE__ */ jsx3("span", { children: "Sent to" }),
1024
+ /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-value", children: shortenAddress(result.destination) })
832
1025
  ] }),
833
1026
  /* @__PURE__ */ jsxs2("div", { className: "rs-review-detail-row", children: [
834
- /* @__PURE__ */ jsx2("span", { children: "Transaction" }),
1027
+ /* @__PURE__ */ jsx3("span", { children: "Transaction" }),
835
1028
  (() => {
836
1029
  const url = explorerTxUrl(result.chain, result.txHash);
837
1030
  const short = shortenHash(result.txHash);
@@ -844,25 +1037,26 @@ function ResultStep({
844
1037
  rel: "noreferrer",
845
1038
  children: [
846
1039
  short,
847
- /* @__PURE__ */ jsx2(ExternalLinkIcon, {})
1040
+ /* @__PURE__ */ jsx3(ExternalLinkIcon, {})
848
1041
  ]
849
1042
  }
850
- ) : /* @__PURE__ */ jsx2("span", { className: "rs-review-detail-value", children: short });
1043
+ ) : /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-value", children: short });
851
1044
  })()
852
1045
  ] })
853
- ] }) : /* @__PURE__ */ jsx2(Callout, { variant: "error", children: error }),
854
- /* @__PURE__ */ jsx2("div", { className: "rs-screen-button-row", children: success ? /* @__PURE__ */ jsxs2(Fragment, { children: [
855
- onReset && /* @__PURE__ */ jsx2(Button, { variant: "outline", onClick: onReset, fullWidth: true, children: "Claim another deposit" }),
856
- /* @__PURE__ */ jsx2(Button, { onClick: onClose, fullWidth: true, children: "Done" })
1046
+ ] }) : /* @__PURE__ */ jsx3(Callout, { variant: "error", children: error }),
1047
+ /* @__PURE__ */ jsx3("div", { className: "rs-screen-button-row", children: success ? /* @__PURE__ */ jsxs2(Fragment, { children: [
1048
+ onReset && /* @__PURE__ */ jsx3(Button, { variant: "outline", onClick: onReset, fullWidth: true, children: "Claim another deposit" }),
1049
+ /* @__PURE__ */ jsx3(Button, { onClick: onClose, fullWidth: true, children: "Done" })
857
1050
  ] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
858
- /* @__PURE__ */ jsx2(Button, { variant: "outline", onClick: onClose, fullWidth: true, children: "Cancel" }),
859
- onRetry && /* @__PURE__ */ jsx2(Button, { onClick: onRetry, fullWidth: true, children: "Try again" })
1051
+ /* @__PURE__ */ jsx3(Button, { variant: "outline", onClick: onClose, fullWidth: true, children: "Cancel" }),
1052
+ onRetry && /* @__PURE__ */ jsx3(Button, { onClick: onRetry, fullWidth: true, children: "Try again" })
860
1053
  ] }) })
861
1054
  ] }),
862
- /* @__PURE__ */ jsx2(PoweredBy, {})
1055
+ /* @__PURE__ */ jsx3(PoweredBy, {})
863
1056
  ] });
864
1057
  }
865
1058
 
866
1059
  export {
1060
+ buildClaimAnalyticsSessionProperties,
867
1061
  ClaimModal
868
1062
  };