@rhinestone/deposit-modal 0.14.1 → 0.15.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 +6 -0
  2. package/bridge-transcript.json +14 -0
  3. package/dist/ClaimModal-GFDBVCN5.cjs +11 -0
  4. package/dist/ClaimModal-VQS3AKEL.mjs +11 -0
  5. package/dist/{DepositModalReown-2EVV64OA.mjs → DepositModalReown-KOJ7VEY7.mjs} +6 -7
  6. package/dist/{DepositModalReown-GAD45GIC.cjs → DepositModalReown-R37SSHUF.cjs} +21 -22
  7. package/dist/WithdrawModal-QVXHMH43.mjs +12 -0
  8. package/dist/WithdrawModal-RY2NMFLE.cjs +12 -0
  9. package/dist/{caip-D8aRWdEY.d.cts → caip-BMi-9t09.d.cts} +27 -3
  10. package/dist/{caip-D8aRWdEY.d.ts → caip-BMi-9t09.d.ts} +27 -3
  11. package/dist/{chunk-HAQOFI3D.cjs → chunk-3OOY67VJ.cjs} +1046 -226
  12. package/dist/{chunk-AQVJUXSG.cjs → chunk-5P2PVLS4.cjs} +1 -1
  13. package/dist/{chunk-UX35GYLM.mjs → chunk-5VONFVQN.mjs} +918 -98
  14. package/dist/chunk-6HUHVXCY.cjs +704 -0
  15. package/dist/{chunk-GZ4GQ5MC.mjs → chunk-7UQ6OUEE.mjs} +166 -45
  16. package/dist/{chunk-LMG46EP2.mjs → chunk-CXBMIZUF.mjs} +1 -1
  17. package/dist/{chunk-A6JPBMYY.cjs → chunk-DTVZUBHI.cjs} +236 -115
  18. package/dist/{chunk-VUATPOWJ.mjs → chunk-EAGMY3QE.mjs} +74 -17
  19. package/dist/{chunk-RN5VKWI6.mjs → chunk-FTWKAJGN.mjs} +1 -1
  20. package/dist/{chunk-5Q5CSVKF.mjs → chunk-IKUYZA7A.mjs} +195 -495
  21. package/dist/{chunk-DW2EQA2U.cjs → chunk-LVCD6RHF.cjs} +2 -2
  22. package/dist/{chunk-4KCSH4T3.cjs → chunk-OY5N3E6L.cjs} +86 -29
  23. package/dist/chunk-QJ7RCCU7.mjs +704 -0
  24. package/dist/{chunk-XCTRKCNM.mjs → chunk-UCBUCX2W.mjs} +1515 -194
  25. package/dist/{chunk-NQMC5VKQ.cjs → chunk-VPDCGD2D.cjs} +552 -852
  26. package/dist/{chunk-4J5ADVIN.cjs → chunk-X4D52IZK.cjs} +1496 -175
  27. package/dist/claim.cjs +5 -7
  28. package/dist/claim.d.cts +3 -3
  29. package/dist/claim.d.ts +3 -3
  30. package/dist/claim.mjs +4 -6
  31. package/dist/{constants-DBrWhJWE.d.cts → constants-BT4ctuHo.d.cts} +7 -6
  32. package/dist/{constants-DBrWhJWE.d.ts → constants-D21ZdNOP.d.ts} +7 -6
  33. package/dist/constants.cjs +3 -3
  34. package/dist/constants.d.cts +3 -3
  35. package/dist/constants.d.ts +3 -3
  36. package/dist/constants.mjs +2 -2
  37. package/dist/deposit.cjs +7 -8
  38. package/dist/deposit.d.cts +3 -3
  39. package/dist/deposit.d.ts +3 -3
  40. package/dist/deposit.mjs +6 -7
  41. package/dist/embed.cjs +135 -44
  42. package/dist/embed.d.cts +2 -2
  43. package/dist/embed.d.ts +2 -2
  44. package/dist/embed.mjs +116 -25
  45. package/dist/index.cjs +13 -11
  46. package/dist/index.d.cts +3 -3
  47. package/dist/index.d.ts +3 -3
  48. package/dist/index.mjs +12 -10
  49. package/dist/polymarket.cjs +6 -6
  50. package/dist/polymarket.mjs +2 -2
  51. package/dist/styles.css +132 -100
  52. package/dist/{types-DP_3KwlD.d.cts → types-CQ0NHqCy.d.ts} +146 -11
  53. package/dist/{types-Bho4OA03.d.ts → types-CxiLX5sv.d.cts} +146 -11
  54. package/dist/withdraw.cjs +6 -6
  55. package/dist/withdraw.d.cts +4 -4
  56. package/dist/withdraw.d.ts +4 -4
  57. package/dist/withdraw.mjs +5 -5
  58. package/package.json +6 -6
  59. package/dist/ClaimModal-GDFENSLV.mjs +0 -13
  60. package/dist/ClaimModal-L3FUBI5U.cjs +0 -13
  61. package/dist/WithdrawModal-FAQH35NG.cjs +0 -12
  62. package/dist/WithdrawModal-IKUHF5CF.mjs +0 -12
  63. package/dist/chunk-62UCV2LG.cjs +0 -81
  64. package/dist/chunk-7AZFT2MV.cjs +0 -163
  65. package/dist/chunk-QACOOLOE.mjs +0 -1062
  66. package/dist/chunk-R5UQ3TN4.mjs +0 -81
  67. package/dist/chunk-VALXN5IO.mjs +0 -163
  68. package/dist/chunk-YP7QVKQ6.cjs +0 -1062
@@ -1,40 +1,1246 @@
1
1
  import {
2
+ AlertTriangleIcon,
3
+ AnalyticsSession,
4
+ ArrowUpRightIcon,
2
5
  BodyHeader,
3
6
  Button,
4
7
  Callout,
5
8
  CdnIcon,
6
9
  CheckIcon,
7
10
  ChevronDownIcon,
11
+ ChevronLeftIcon,
12
+ ChevronRightIcon,
13
+ ClaimAnalyticsControllerProvider,
14
+ CloseIcon,
15
+ CoinsIcon,
8
16
  ExternalLinkIcon,
17
+ HistoryIcon,
9
18
  InfoIcon,
19
+ ListRow,
10
20
  PoweredBy,
21
+ RECOVERY_LOOKUP_MISS_COPY,
22
+ RecoveryError,
23
+ RecoveryLookupScreen,
24
+ RecoveryOutcomeScreen,
25
+ RecoveryReviewScreen,
26
+ RegistrationError,
27
+ Spinner,
11
28
  TokenIcon,
12
29
  WalletIcon,
30
+ claimFailureReasonForError,
31
+ classifyRecoveryLookup,
13
32
  debugError,
14
33
  debugLog,
34
+ describeRecoveryDeposit,
15
35
  estimateReceiveAmount,
16
36
  formatFeeUsd,
17
37
  formatQuotedReceive,
18
38
  formatRawTokenAmount,
39
+ formatRecoveryAmount,
19
40
  formatTokenAmount,
41
+ formatUserError,
20
42
  isRecognizedToken,
21
43
  quoteFeeGroups,
22
44
  quoteFeeRow,
45
+ randomUuid,
46
+ recoveryFailureCause,
23
47
  resolveTokenDisplay,
48
+ submitSignedRecovery,
49
+ toRecoverableDeposit,
24
50
  tokenAmountToNumber,
51
+ useClaimAnalyticsController,
25
52
  useExplorerTxUrl,
26
53
  useLatestRef
27
- } from "./chunk-UX35GYLM.mjs";
54
+ } from "./chunk-5VONFVQN.mjs";
28
55
  import {
56
+ HYPERCORE_CHAIN_ID,
29
57
  NATIVE_TOKEN_ADDRESS,
30
58
  SOLANA_MAINNET_CAIP2,
59
+ SOLANA_TOKENS,
31
60
  cdnIconUrl,
61
+ displayChainIdForCaip2,
32
62
  getChainIcon,
33
63
  getChainName,
64
+ getTokenDecimalsByAddress,
65
+ getTokenSymbol,
34
66
  targetChainToCaip2,
35
67
  targetChainToChainId,
36
- toEvmCaip2
37
- } from "./chunk-VUATPOWJ.mjs";
68
+ toEvmCaip2,
69
+ tokenIconUrl
70
+ } from "./chunk-EAGMY3QE.mjs";
71
+
72
+ // src/core/history-status.ts
73
+ function normalizeStatus(raw, isSpam) {
74
+ const lower = raw.toLowerCase();
75
+ if (lower === "completed" || lower === "complete" || lower === "bridge-complete" || lower === "processed")
76
+ return "completed";
77
+ if (lower === "failed" || lower === "error" || lower === "bridge-failed" || lower === "rejected") {
78
+ return isSpam ? "spam" : "failed";
79
+ }
80
+ if (lower === "refunded") return "refunded";
81
+ if (lower === "processing" || lower === "submitted" || lower === "bridging")
82
+ return "processing";
83
+ return "pending";
84
+ }
85
+ var STATUS_LABEL = {
86
+ pending: "Pending",
87
+ processing: "Processing",
88
+ completed: "Completed",
89
+ failed: "Failed",
90
+ refunded: "Refunded",
91
+ spam: "Spam token"
92
+ };
93
+ function filterVisibleDeposits(deposits) {
94
+ const sourceHashes = new Set(
95
+ deposits.map((d) => d.sourceTxHash?.toLowerCase()).filter((h) => Boolean(h))
96
+ );
97
+ return deposits.filter(
98
+ (d) => !(d.txHash && sourceHashes.has(d.txHash.toLowerCase()))
99
+ );
100
+ }
101
+
102
+ // src/core/history-badge.ts
103
+ function deriveHistoryBadge(deposits, { recipient, canRecover }) {
104
+ const visible = filterVisibleDeposits(deposits);
105
+ if (canRecover) {
106
+ const needsYou = visible.filter(
107
+ (row) => toRecoverableDeposit(row, { recipient }) !== null
108
+ ).length;
109
+ if (needsYou > 0) return { state: "needs-you", count: needsYou };
110
+ }
111
+ const inProgress = visible.filter((row) => {
112
+ const status = normalizeStatus(row.status, row.isSpam);
113
+ return status === "pending" || status === "processing";
114
+ }).length;
115
+ if (inProgress > 0) return { state: "progress", count: inProgress };
116
+ return null;
117
+ }
118
+ function historyBadgeAriaLabel(badge) {
119
+ if (!badge) return "Deposit history";
120
+ const single = badge.count === 1;
121
+ const noun = single ? "deposit" : "deposits";
122
+ const state = badge.state === "needs-you" ? single ? "needs you" : "need you" : "in progress";
123
+ return `Deposit history \u2014 ${badge.count} ${noun} ${state}`;
124
+ }
125
+
126
+ // src/components/history/HistoryEntryButton.tsx
127
+ import { jsx, jsxs } from "react/jsx-runtime";
128
+ function HistoryEntryButton({
129
+ badge,
130
+ onClick,
131
+ disabled
132
+ }) {
133
+ return /* @__PURE__ */ jsxs(
134
+ "button",
135
+ {
136
+ type: "button",
137
+ className: "rs-modal-header-history",
138
+ "aria-label": historyBadgeAriaLabel(badge),
139
+ onClick,
140
+ disabled,
141
+ children: [
142
+ /* @__PURE__ */ jsx(HistoryIcon, {}),
143
+ badge && /* @__PURE__ */ jsx(
144
+ "span",
145
+ {
146
+ className: `rs-history-dot rs-history-dot--${badge.state}`,
147
+ "aria-hidden": "true"
148
+ }
149
+ )
150
+ ]
151
+ }
152
+ );
153
+ }
154
+
155
+ // src/components/history/HistoryOverlay.tsx
156
+ import { useCallback as useCallback4, useEffect as useEffect4, useMemo as useMemo2, useRef as useRef4, useState as useState4 } from "react";
157
+
158
+ // src/components/history/DepositHistoryPanel.tsx
159
+ import {
160
+ useCallback,
161
+ useEffect,
162
+ useId,
163
+ useMemo,
164
+ useRef,
165
+ useState
166
+ } from "react";
167
+ import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
168
+ function shortenHash(hash) {
169
+ if (hash.length <= 14) return hash;
170
+ return `${hash.slice(0, 6)}\u2026${hash.slice(-4)}`;
171
+ }
172
+ function formatDate(iso) {
173
+ try {
174
+ const date = new Date(iso);
175
+ if (Number.isNaN(date.getTime())) return iso;
176
+ return date.toLocaleDateString("en-US", {
177
+ day: "numeric",
178
+ month: "short",
179
+ year: "numeric"
180
+ });
181
+ } catch {
182
+ return iso;
183
+ }
184
+ }
185
+ function resolveChainId(value) {
186
+ if (value === void 0 || value === null) return null;
187
+ if (typeof value === "number") return value;
188
+ const display = displayChainIdForCaip2(value);
189
+ if (display !== null) return display;
190
+ if (value === "solana" || value === "hypercore") return value;
191
+ const num = Number(value);
192
+ return Number.isFinite(num) ? num : null;
193
+ }
194
+ function resolveTokenSymbol(token, chainId) {
195
+ if (!token) return "";
196
+ if (chainId === "solana") {
197
+ const normalized = token.toLowerCase();
198
+ const matched = SOLANA_TOKENS.find(
199
+ (entry) => entry.mint.toLowerCase() === normalized
200
+ );
201
+ if (matched) return matched.symbol;
202
+ if (normalized === "native" || normalized === "11111111111111111111111111111111" || normalized === "so11111111111111111111111111111111111111112") {
203
+ return "SOL";
204
+ }
205
+ }
206
+ if (chainId !== null && chainId !== void 0 && chainId !== "solana" && // Both callers pass the SOURCE chain, and `/chains` reports
207
+ // `deposit: false` for Tron and Stellar — so neither can appear here, and
208
+ // neither has an EVM token table to look one up in if it did.
209
+ chainId !== "tron" && chainId !== "stellar" && /^0x[a-fA-F0-9]{40}$/.test(token)) {
210
+ const evmChainId = chainId === "hypercore" ? HYPERCORE_CHAIN_ID : chainId;
211
+ const sym = getTokenSymbol(token, evmChainId);
212
+ if (sym !== "Token") return sym;
213
+ }
214
+ return shortenHash(token);
215
+ }
216
+ function formatAmount(rawAmount, token, chainId) {
217
+ if (!rawAmount) return "";
218
+ let decimals = 18;
219
+ if (token && chainId !== null && chainId !== void 0) {
220
+ if (chainId === "solana") {
221
+ const normalized = token.toLowerCase();
222
+ const matched = SOLANA_TOKENS.find(
223
+ (entry) => entry.mint.toLowerCase() === normalized
224
+ );
225
+ if (matched) {
226
+ decimals = matched.decimals;
227
+ } else if (normalized === "native" || normalized === "11111111111111111111111111111111" || normalized === "so11111111111111111111111111111111111111112") {
228
+ decimals = 9;
229
+ }
230
+ } else if (
231
+ // See `resolveTokenSymbol`: this reads the source chain, which Tron and
232
+ // Stellar cannot be.
233
+ chainId !== "tron" && chainId !== "stellar" && /^0x[a-fA-F0-9]{40}$/.test(token)
234
+ ) {
235
+ const evmChainId = chainId === "hypercore" ? HYPERCORE_CHAIN_ID : chainId;
236
+ decimals = getTokenDecimalsByAddress(token, evmChainId);
237
+ }
238
+ }
239
+ try {
240
+ const raw = BigInt(rawAmount);
241
+ const divisor = 10n ** BigInt(decimals);
242
+ const whole = raw / divisor;
243
+ const remainder = raw % divisor;
244
+ const fracStr = remainder.toString().padStart(decimals, "0");
245
+ let frac = fracStr.slice(0, 5).replace(/0+$/, "");
246
+ if (frac.length < 2) frac = frac.padEnd(2, "0");
247
+ return `${whole}.${frac}`;
248
+ } catch {
249
+ return rawAmount;
250
+ }
251
+ }
252
+ function DepositHistoryPanel({
253
+ deposits,
254
+ isLoading,
255
+ error,
256
+ hasMore,
257
+ isLoadingMore,
258
+ onLoadMore,
259
+ onClose,
260
+ onCloseModal,
261
+ backLabel,
262
+ title = "History",
263
+ recipient,
264
+ onRecover,
265
+ onFindByTxHash,
266
+ onRowView,
267
+ obscured
268
+ }) {
269
+ const rootRef = useRef(null);
270
+ useEffect(() => {
271
+ rootRef.current?.toggleAttribute("inert", Boolean(obscured));
272
+ }, [obscured]);
273
+ const handleKeyDown = useCallback(
274
+ (e) => {
275
+ if (obscured) return;
276
+ if (e.key === "Escape") {
277
+ e.stopPropagation();
278
+ onClose();
279
+ }
280
+ },
281
+ [onClose, obscured]
282
+ );
283
+ const visibleDeposits = useMemo(
284
+ () => filterVisibleDeposits(deposits),
285
+ [deposits]
286
+ );
287
+ return /* @__PURE__ */ jsxs2(
288
+ "div",
289
+ {
290
+ ref: rootRef,
291
+ className: "rs-history-panel",
292
+ role: "dialog",
293
+ "aria-label": "Deposit history",
294
+ "aria-hidden": obscured || void 0,
295
+ onKeyDown: handleKeyDown,
296
+ children: [
297
+ /* @__PURE__ */ jsxs2("div", { className: "rs-modal-header--redesigned", children: [
298
+ /* @__PURE__ */ jsx2("div", { className: "rs-modal-header-nav-left", children: /* @__PURE__ */ jsxs2(
299
+ "button",
300
+ {
301
+ type: "button",
302
+ className: `rs-modal-header-back${backLabel ? " rs-modal-header-back--labelled" : ""}`,
303
+ "aria-label": backLabel ? `Back to ${backLabel.toLowerCase()}` : "Back",
304
+ onClick: onClose,
305
+ children: [
306
+ /* @__PURE__ */ jsx2(ChevronLeftIcon, {}),
307
+ backLabel && /* @__PURE__ */ jsx2("span", { children: backLabel })
308
+ ]
309
+ }
310
+ ) }),
311
+ /* @__PURE__ */ jsx2("div", { className: "rs-modal-header-nav-right", children: onCloseModal && /* @__PURE__ */ jsx2(
312
+ "button",
313
+ {
314
+ type: "button",
315
+ className: "rs-modal-close",
316
+ "aria-label": "Close",
317
+ onClick: onCloseModal,
318
+ children: /* @__PURE__ */ jsx2(CloseIcon, {})
319
+ }
320
+ ) })
321
+ ] }),
322
+ /* @__PURE__ */ jsxs2("div", { className: "rs-history-screen", children: [
323
+ /* @__PURE__ */ jsxs2("div", { className: "rs-history-screen-body", children: [
324
+ /* @__PURE__ */ jsx2(BodyHeader, { icon: /* @__PURE__ */ jsx2(HistoryIcon, {}), title }),
325
+ onFindByTxHash && /* @__PURE__ */ jsxs2(
326
+ "button",
327
+ {
328
+ type: "button",
329
+ className: "rs-history-hint",
330
+ onClick: onFindByTxHash,
331
+ children: [
332
+ /* @__PURE__ */ jsx2("span", { children: "Deposit missing?" }),
333
+ /* @__PURE__ */ jsx2("strong", { children: "Find it by transaction hash" })
334
+ ]
335
+ }
336
+ ),
337
+ isLoading && deposits.length === 0 && /* @__PURE__ */ jsxs2("div", { className: "rs-history-empty", children: [
338
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-empty-glyph", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(HistoryIcon, {}) }),
339
+ /* @__PURE__ */ jsxs2("div", { className: "rs-history-empty-text", children: [
340
+ /* @__PURE__ */ jsx2(Spinner, { className: "rs-spinner--sm" }),
341
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-empty-hint", children: "Loading history\u2026" })
342
+ ] })
343
+ ] }),
344
+ error && !isLoading && /* @__PURE__ */ jsxs2("div", { className: "rs-history-empty", children: [
345
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-empty-glyph", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(AlertTriangleIcon, {}) }),
346
+ /* @__PURE__ */ jsxs2("div", { className: "rs-history-empty-text", children: [
347
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-empty-title", children: "Couldn't load history" }),
348
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-empty-hint", children: error })
349
+ ] })
350
+ ] }),
351
+ !isLoading && !error && visibleDeposits.length === 0 && /* @__PURE__ */ jsxs2("div", { className: "rs-history-empty", children: [
352
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-empty-glyph", "aria-hidden": "true", children: /* @__PURE__ */ jsx2(HistoryIcon, {}) }),
353
+ /* @__PURE__ */ jsxs2("div", { className: "rs-history-empty-text", children: [
354
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-empty-title", children: "No deposits yet" }),
355
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-empty-hint", children: "Your deposit history will appear here" })
356
+ ] })
357
+ ] }),
358
+ visibleDeposits.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "rs-history-list", children: [
359
+ visibleDeposits.map((deposit, i) => /* @__PURE__ */ jsx2(
360
+ HistoryCard,
361
+ {
362
+ deposit,
363
+ position: i,
364
+ recipient,
365
+ onRecover,
366
+ onRowView
367
+ },
368
+ deposit.txHash || i
369
+ )),
370
+ hasMore && /* @__PURE__ */ jsx2(
371
+ "button",
372
+ {
373
+ type: "button",
374
+ className: "rs-history-load-more",
375
+ onClick: onLoadMore,
376
+ disabled: isLoadingMore,
377
+ children: isLoadingMore ? "Loading\u2026" : "Load more"
378
+ }
379
+ )
380
+ ] })
381
+ ] }),
382
+ /* @__PURE__ */ jsx2(PoweredBy, {})
383
+ ] })
384
+ ]
385
+ }
386
+ );
387
+ }
388
+ function HistoryCard({
389
+ deposit,
390
+ position,
391
+ recipient,
392
+ onRecover,
393
+ onRowView
394
+ }) {
395
+ const explorerTxUrl = useExplorerTxUrl();
396
+ const [expanded, setExpanded] = useState(false);
397
+ const panelId = useId();
398
+ const status = normalizeStatus(deposit.status, deposit.isSpam);
399
+ const sourceChainId = resolveChainId(deposit.chain);
400
+ const targetChainId = resolveChainId(deposit.targetChain);
401
+ const sourceChainName = sourceChainId ? getChainName(sourceChainId) : null;
402
+ const targetChainName = targetChainId ? getChainName(targetChainId) : null;
403
+ const sourceChainIcon = sourceChainId ? getChainIcon(sourceChainId) : void 0;
404
+ const targetChainIcon = targetChainId ? getChainIcon(targetChainId) : void 0;
405
+ const sourceSymbol = resolveTokenSymbol(deposit.token, sourceChainId);
406
+ const rawAmount = deposit.sourceAmount && deposit.sourceAmount !== "0" ? deposit.sourceAmount : deposit.amount;
407
+ const formattedAmount = rawAmount ? formatAmount(rawAmount, deposit.token, sourceChainId) : null;
408
+ const displayAmount = formattedAmount ? sourceSymbol && /^USD/.test(sourceSymbol) ? `$${Number(formattedAmount).toLocaleString("en-US", {
409
+ minimumFractionDigits: 2,
410
+ maximumFractionDigits: 2
411
+ })}` : `${formattedAmount} ${sourceSymbol}` : "\u2014";
412
+ const date = deposit.createdAt ? formatDate(deposit.createdAt) : null;
413
+ const txTypeLabel = `Deposit${sourceSymbol ? ` ${sourceSymbol}` : ""}`;
414
+ const srcTxHash = sourceChainId === "hypercore" ? deposit.txHash : deposit.sourceTxHash;
415
+ const srcTxUrl = srcTxHash && sourceChainId ? explorerTxUrl(sourceChainId, srcTxHash) : null;
416
+ const eligible = toRecoverableDeposit(deposit, { recipient });
417
+ const recoverable = onRecover ? eligible : null;
418
+ const toggleExpanded = () => {
419
+ const next = !expanded;
420
+ setExpanded(next);
421
+ const depositId = deposit.id ?? deposit.txHash;
422
+ if (!next || !depositId) return;
423
+ onRowView?.({
424
+ depositId,
425
+ status,
426
+ recoverable: eligible !== null,
427
+ position
428
+ });
429
+ };
430
+ return /* @__PURE__ */ jsxs2(
431
+ "div",
432
+ {
433
+ className: `rs-history-card ${expanded ? "rs-history-card--expanded" : ""}`,
434
+ children: [
435
+ /* @__PURE__ */ jsx2(
436
+ "button",
437
+ {
438
+ type: "button",
439
+ className: "rs-history-card-trigger",
440
+ onClick: toggleExpanded,
441
+ "aria-expanded": expanded,
442
+ "aria-controls": panelId,
443
+ children: /* @__PURE__ */ jsxs2("div", { className: "rs-history-card-row", children: [
444
+ /* @__PURE__ */ jsxs2("div", { className: "rs-history-card-icons", children: [
445
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-card-token", children: /* @__PURE__ */ jsx2(
446
+ TokenIcon,
447
+ {
448
+ symbol: sourceSymbol,
449
+ fallback: sourceSymbol.slice(0, 2)
450
+ }
451
+ ) }),
452
+ sourceChainIcon && /* @__PURE__ */ jsx2("span", { className: "rs-history-card-chain", children: /* @__PURE__ */ jsx2(CdnIcon, { src: sourceChainIcon }) })
453
+ ] }),
454
+ /* @__PURE__ */ jsxs2("div", { className: "rs-history-card-text", children: [
455
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-card-title", children: txTypeLabel }),
456
+ date && /* @__PURE__ */ jsx2("span", { className: "rs-history-card-date", children: date })
457
+ ] }),
458
+ /* @__PURE__ */ jsxs2("div", { className: "rs-history-card-side", children: [
459
+ /* @__PURE__ */ jsx2("span", { className: "rs-history-card-amount", children: displayAmount }),
460
+ /* @__PURE__ */ jsx2("span", { className: `rs-history-badge rs-history-badge--${status}`, children: STATUS_LABEL[status] })
461
+ ] })
462
+ ] })
463
+ }
464
+ ),
465
+ /* @__PURE__ */ jsx2("div", { className: "rs-history-card-panel", id: panelId, children: /* @__PURE__ */ jsx2("div", { className: "rs-history-card-panel-inner", children: /* @__PURE__ */ jsxs2("div", { className: "rs-history-card-details", children: [
466
+ (status === "failed" || recoverable) && /* @__PURE__ */ jsx2(Callout, { variant: "error", children: recoveryFailureCause(sourceChainName) }),
467
+ sourceChainName && /* @__PURE__ */ jsxs2("div", { className: "rs-amount-detail-row", children: [
468
+ /* @__PURE__ */ jsx2("span", { children: "Source chain" }),
469
+ /* @__PURE__ */ jsxs2("span", { className: "rs-amount-detail-value", children: [
470
+ /* @__PURE__ */ jsx2("span", { children: sourceChainName }),
471
+ sourceChainIcon && /* @__PURE__ */ jsx2("span", { className: "rs-amount-detail-icon", children: /* @__PURE__ */ jsx2(CdnIcon, { src: sourceChainIcon }) })
472
+ ] })
473
+ ] }),
474
+ targetChainName && /* @__PURE__ */ jsxs2("div", { className: "rs-amount-detail-row", children: [
475
+ /* @__PURE__ */ jsx2("span", { children: "Destination chain" }),
476
+ /* @__PURE__ */ jsxs2("span", { className: "rs-amount-detail-value", children: [
477
+ /* @__PURE__ */ jsx2("span", { children: targetChainName }),
478
+ targetChainIcon && /* @__PURE__ */ jsx2("span", { className: "rs-amount-detail-icon", children: /* @__PURE__ */ jsx2(CdnIcon, { src: targetChainIcon }) })
479
+ ] })
480
+ ] }),
481
+ srcTxUrl && srcTxHash && /* @__PURE__ */ jsxs2("div", { className: "rs-amount-detail-row", children: [
482
+ /* @__PURE__ */ jsx2("span", { children: "Transaction details" }),
483
+ /* @__PURE__ */ jsxs2(
484
+ "a",
485
+ {
486
+ href: srcTxUrl,
487
+ target: "_blank",
488
+ rel: "noopener noreferrer",
489
+ className: "rs-history-card-link",
490
+ children: [
491
+ /* @__PURE__ */ jsx2("span", { children: shortenHash(srcTxHash) }),
492
+ /* @__PURE__ */ jsx2(ArrowUpRightIcon, {})
493
+ ]
494
+ }
495
+ )
496
+ ] }),
497
+ recoverable && /* @__PURE__ */ jsxs2(
498
+ Button,
499
+ {
500
+ onClick: () => onRecover?.(recoverable),
501
+ fullWidth: true,
502
+ className: "rs-history-card-recover",
503
+ children: [
504
+ /* @__PURE__ */ jsxs2("span", { children: [
505
+ "Recover ",
506
+ displayAmount
507
+ ] }),
508
+ /* @__PURE__ */ jsx2(ChevronRightIcon, {})
509
+ ]
510
+ }
511
+ )
512
+ ] }) }) })
513
+ ]
514
+ }
515
+ );
516
+ }
517
+ DepositHistoryPanel.displayName = "DepositHistoryPanel";
518
+
519
+ // src/components/history/HistoryFallbackFlow.tsx
520
+ import { useCallback as useCallback2, useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
521
+ import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
522
+ function HistoryFallbackFlow({
523
+ service,
524
+ recipient,
525
+ onBack,
526
+ onCloseModal,
527
+ onFound
528
+ }) {
529
+ const analytics = useClaimAnalyticsController();
530
+ const [loading, setLoading] = useState2(false);
531
+ const [error, setError] = useState2(null);
532
+ const [matches, setMatches] = useState2(null);
533
+ useEffect2(() => {
534
+ analytics.openStep("lookup");
535
+ }, [analytics]);
536
+ const epochRef = useRef2(0);
537
+ useEffect2(() => {
538
+ setMatches(null);
539
+ setError(null);
540
+ setLoading(false);
541
+ return () => {
542
+ epochRef.current += 1;
543
+ };
544
+ }, [recipient]);
545
+ const reportSelection = useCallback2(
546
+ (match, autoSelected) => {
547
+ analytics.selectDeposit({
548
+ depositId: match.depositId,
549
+ transactionHash: match.sourceTxHash ?? null,
550
+ autoSelected
551
+ });
552
+ },
553
+ [analytics]
554
+ );
555
+ const lookup = useCallback2(
556
+ async (txHash) => {
557
+ const epoch = epochRef.current;
558
+ const isCurrentLookup = () => epochRef.current === epoch;
559
+ setError(null);
560
+ setLoading(true);
561
+ analytics.rearmStep("lookup");
562
+ try {
563
+ const rows = await service.lookupRecoverableDeposits({ txHash });
564
+ if (!isCurrentLookup()) return;
565
+ const outcome = classifyRecoveryLookup(newestFirst(rows), {
566
+ recipient
567
+ });
568
+ const { eligible, miss } = outcome;
569
+ analytics.lookupResult(outcome.rows.length, eligible.length);
570
+ if (miss) {
571
+ analytics.friction(
572
+ miss === "not_found" ? "lookup_no_deposits_found" : "lookup_no_eligible_deposits",
573
+ "lookup"
574
+ );
575
+ setError(RECOVERY_LOOKUP_MISS_COPY[miss]);
576
+ return;
577
+ }
578
+ analytics.completeStep("lookup");
579
+ if (eligible.length === 1) {
580
+ reportSelection(eligible[0], true);
581
+ onFound(eligible[0]);
582
+ return;
583
+ }
584
+ analytics.openStep("select");
585
+ setMatches(eligible);
586
+ } catch (err) {
587
+ if (!isCurrentLookup()) return;
588
+ analytics.failure("lookup_failed", true, "lookup");
589
+ setError(
590
+ formatUserError(err instanceof Error ? err.message : "Lookup failed")
591
+ );
592
+ } finally {
593
+ if (isCurrentLookup()) setLoading(false);
594
+ }
595
+ },
596
+ [analytics, service, recipient, onFound, reportSelection]
597
+ );
598
+ const selectMatch = useCallback2(
599
+ (match) => {
600
+ analytics.completeStep("select");
601
+ reportSelection(match, false);
602
+ onFound(match);
603
+ },
604
+ [analytics, onFound, reportSelection]
605
+ );
606
+ const handleKeyDown = useCallback2(
607
+ (e) => {
608
+ if (e.key === "Escape") {
609
+ e.stopPropagation();
610
+ onBack("escape");
611
+ }
612
+ },
613
+ [onBack]
614
+ );
615
+ return /* @__PURE__ */ jsxs3(
616
+ "div",
617
+ {
618
+ className: "rs-history-lookup",
619
+ role: "dialog",
620
+ "aria-label": "Find a deposit",
621
+ onKeyDown: handleKeyDown,
622
+ children: [
623
+ /* @__PURE__ */ jsxs3("div", { className: "rs-modal-header--redesigned", children: [
624
+ /* @__PURE__ */ jsx3("div", { className: "rs-modal-header-nav-left", children: /* @__PURE__ */ jsxs3(
625
+ "button",
626
+ {
627
+ type: "button",
628
+ className: "rs-modal-header-back rs-modal-header-back--labelled",
629
+ "aria-label": "Back to history",
630
+ onClick: () => onBack(),
631
+ children: [
632
+ /* @__PURE__ */ jsx3(ChevronLeftIcon, {}),
633
+ /* @__PURE__ */ jsx3("span", { children: "History" })
634
+ ]
635
+ }
636
+ ) }),
637
+ /* @__PURE__ */ jsx3("div", { className: "rs-modal-header-nav-right", children: /* @__PURE__ */ jsx3(
638
+ "button",
639
+ {
640
+ type: "button",
641
+ className: "rs-modal-close",
642
+ "aria-label": "Close",
643
+ onClick: onCloseModal,
644
+ children: /* @__PURE__ */ jsx3(CloseIcon, {})
645
+ }
646
+ ) })
647
+ ] }),
648
+ matches ? /* @__PURE__ */ jsxs3("div", { className: "rs-screen", children: [
649
+ /* @__PURE__ */ jsxs3("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
650
+ /* @__PURE__ */ jsx3(
651
+ BodyHeader,
652
+ {
653
+ icon: /* @__PURE__ */ jsx3(CoinsIcon, {}),
654
+ title: "Select a deposit",
655
+ subtitle: "This transaction produced multiple deposits. Choose the one to recover."
656
+ }
657
+ ),
658
+ /* @__PURE__ */ jsx3("div", { className: "rs-list", children: matches.map((match) => {
659
+ const { symbol, amount, chainName } = describeRecoveryDeposit({
660
+ chainId: match.sourceChainId,
661
+ token: match.token,
662
+ amountRaw: match.amountRaw
663
+ });
664
+ return /* @__PURE__ */ jsx3(
665
+ ListRow,
666
+ {
667
+ leadingMedia: tokenIconUrl(symbol),
668
+ title: `${amount} ${symbol}`,
669
+ subtitle: chainName,
670
+ onClick: () => selectMatch(match)
671
+ },
672
+ match.depositId
673
+ );
674
+ }) })
675
+ ] }),
676
+ /* @__PURE__ */ jsx3(PoweredBy, {})
677
+ ] }) : /* @__PURE__ */ jsx3(
678
+ RecoveryLookupScreen,
679
+ {
680
+ title: "Find a deposit",
681
+ subtitle: "Some deposits don't appear in your history. Look one up by the transaction that sent the funds.",
682
+ hint: "The transaction hash from the wallet or exchange you sent from.",
683
+ loading,
684
+ error,
685
+ onSubmit: lookup,
686
+ onInvalid: () => analytics.friction("lookup_transaction_hash_invalid", "lookup")
687
+ }
688
+ )
689
+ ]
690
+ }
691
+ );
692
+ }
693
+ function newestFirst(rows) {
694
+ return [...rows].sort(
695
+ (a, b) => (b.createdAt ? Date.parse(b.createdAt) : 0) - (a.createdAt ? Date.parse(a.createdAt) : 0)
696
+ );
697
+ }
698
+ HistoryFallbackFlow.displayName = "HistoryFallbackFlow";
699
+
700
+ // src/components/history/HistoryRecoveryFlow.tsx
701
+ import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef3, useState as useState3 } from "react";
702
+ import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
703
+ function HistoryRecoveryFlow({
704
+ deposit,
705
+ entrySource,
706
+ backendUrl,
707
+ signRecovery,
708
+ debug,
709
+ onBack,
710
+ onCloseModal,
711
+ onSubmittingChange,
712
+ onRecovered
713
+ }) {
714
+ const analytics = useClaimAnalyticsController();
715
+ const [phase, setPhase] = useState3("review");
716
+ const [outcome, setOutcome] = useState3(null);
717
+ const [error, setError] = useState3(null);
718
+ const [retryable, setRetryable] = useState3(false);
719
+ const lastFailureRef = useRef3(null);
720
+ useEffect3(() => {
721
+ if (entrySource === "history_row") {
722
+ analytics.selectDeposit({
723
+ depositId: deposit.depositId,
724
+ transactionHash: deposit.sourceTxHash ?? null,
725
+ autoSelected: true
726
+ });
727
+ }
728
+ analytics.openStep("review");
729
+ }, [analytics, deposit, entrySource]);
730
+ const { symbol, decimals } = describeRecoveryDeposit({
731
+ chainId: deposit.sourceChainId,
732
+ token: deposit.token,
733
+ amountRaw: deposit.amountRaw
734
+ });
735
+ const submit = useCallback3(
736
+ async (destination) => {
737
+ setPhase("submitting");
738
+ onSubmittingChange(true);
739
+ analytics.completeStep("review");
740
+ analytics.openStep("submit");
741
+ try {
742
+ const result = await submitSignedRecovery({
743
+ backendUrl,
744
+ // The target chain: the processor verifies where the recipient wallet
745
+ // lives, not where the refund pays out.
746
+ chainId: deposit.targetChainId,
747
+ depositId: deposit.depositId,
748
+ signer: deposit.signer,
749
+ destination,
750
+ signRecovery,
751
+ debug
752
+ });
753
+ setOutcome({
754
+ // No destination to reconcile: it is inside the signed struct, so the
755
+ // processor cannot have paid anywhere else.
756
+ destination,
757
+ txHash: result.transactionHash,
758
+ symbol,
759
+ amountDisplay: formatRecoveryAmount(
760
+ result.amount ?? deposit.amountRaw,
761
+ decimals,
762
+ symbol
763
+ )
764
+ });
765
+ setPhase("success");
766
+ analytics.handoff(
767
+ {
768
+ depositId: deposit.depositId,
769
+ transactionHash: deposit.sourceTxHash ?? null,
770
+ refundTransactionHash: result.transactionHash
771
+ },
772
+ "submit"
773
+ );
774
+ analytics.completeStep("submit");
775
+ analytics.outcome("completed");
776
+ onRecovered();
777
+ } catch (err) {
778
+ const recoveryError = err instanceof RecoveryError ? err : void 0;
779
+ setError(
780
+ recoveryError?.message ?? formatUserError(
781
+ err instanceof Error ? err.message : "Recovery failed"
782
+ )
783
+ );
784
+ const canRetry = recoveryError?.retryable ?? true;
785
+ setRetryable(canRetry);
786
+ setPhase("failed");
787
+ const reason = claimFailureReasonForError(err);
788
+ lastFailureRef.current = canRetry ? reason : null;
789
+ analytics.failure(reason, canRetry, "submit");
790
+ analytics.outcome("failed");
791
+ } finally {
792
+ onSubmittingChange(false);
793
+ }
794
+ },
795
+ [
796
+ analytics,
797
+ backendUrl,
798
+ debug,
799
+ decimals,
800
+ deposit,
801
+ onRecovered,
802
+ onSubmittingChange,
803
+ signRecovery,
804
+ symbol
805
+ ]
806
+ );
807
+ const retry = useCallback3(() => {
808
+ const reason = lastFailureRef.current;
809
+ if (reason) {
810
+ lastFailureRef.current = null;
811
+ analytics.retry(reason, "submit");
812
+ }
813
+ setError(null);
814
+ setPhase("review");
815
+ }, [analytics]);
816
+ const submitting = phase === "submitting";
817
+ return /* @__PURE__ */ jsxs4(
818
+ "div",
819
+ {
820
+ className: "rs-history-recovery",
821
+ role: "dialog",
822
+ "aria-label": "Recover deposit",
823
+ children: [
824
+ /* @__PURE__ */ jsxs4("div", { className: "rs-modal-header--redesigned", children: [
825
+ /* @__PURE__ */ jsx4("div", { className: "rs-modal-header-nav-left", children: !submitting && /* @__PURE__ */ jsxs4(
826
+ "button",
827
+ {
828
+ type: "button",
829
+ className: "rs-modal-header-back rs-modal-header-back--labelled",
830
+ "aria-label": "Back to history",
831
+ onClick: onBack,
832
+ children: [
833
+ /* @__PURE__ */ jsx4(ChevronLeftIcon, {}),
834
+ /* @__PURE__ */ jsx4("span", { children: "History" })
835
+ ]
836
+ }
837
+ ) }),
838
+ /* @__PURE__ */ jsx4("div", { className: "rs-modal-header-nav-right", children: /* @__PURE__ */ jsx4(
839
+ "button",
840
+ {
841
+ type: "button",
842
+ className: "rs-modal-close",
843
+ "aria-label": "Close",
844
+ onClick: onCloseModal,
845
+ disabled: submitting,
846
+ children: /* @__PURE__ */ jsx4(CloseIcon, {})
847
+ }
848
+ ) })
849
+ ] }),
850
+ (phase === "review" || submitting) && /* @__PURE__ */ jsx4(
851
+ RecoveryReviewScreen,
852
+ {
853
+ chainId: deposit.sourceChainId,
854
+ token: deposit.token,
855
+ amountRaw: deposit.amountRaw,
856
+ txHash: deposit.sourceTxHash,
857
+ defaultDestination: deposit.destinationPrefill,
858
+ destinationHint: "Prefilled with the account this deposit was for. Editable.",
859
+ submitting,
860
+ onSubmit: submit,
861
+ onDestinationInvalid: () => analytics.friction("refund_destination_invalid", "review")
862
+ }
863
+ ),
864
+ phase === "success" && outcome && /* @__PURE__ */ jsx4(
865
+ RecoveryOutcomeScreen,
866
+ {
867
+ result: { ...outcome, chainId: deposit.sourceChainId },
868
+ children: /* @__PURE__ */ jsx4(Button, { variant: "outline", onClick: onBack, fullWidth: true, children: "Back to history" })
869
+ }
870
+ ),
871
+ phase === "failed" && /* @__PURE__ */ jsxs4(RecoveryOutcomeScreen, { error, children: [
872
+ /* @__PURE__ */ jsx4(Button, { variant: "outline", onClick: onBack, fullWidth: true, children: "Back to history" }),
873
+ retryable && /* @__PURE__ */ jsx4(Button, { onClick: retry, fullWidth: true, children: "Try again" })
874
+ ] })
875
+ ]
876
+ }
877
+ );
878
+ }
879
+ HistoryRecoveryFlow.displayName = "HistoryRecoveryFlow";
880
+
881
+ // src/components/history/HistoryOverlay.tsx
882
+ import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
883
+ function HistoryOverlay({
884
+ controller,
885
+ backLabel,
886
+ title,
887
+ recipient,
888
+ backendUrl,
889
+ service,
890
+ signRecovery,
891
+ debug,
892
+ onCloseModal,
893
+ analytics,
894
+ inline,
895
+ closeOnOverlayClick,
896
+ enableAnalyticsIngest,
897
+ analyticsIngestUrl,
898
+ onEvent
899
+ }) {
900
+ const recovering = signRecovery ? controller.recovering : null;
901
+ const [fallbackOpen, setFallbackOpen] = useState4(false);
902
+ const [attempt, setAttempt] = useState4(null);
903
+ const claimControllerRef = useRef4(null);
904
+ const beginAttempt = useCallback4(
905
+ (entrySource) => {
906
+ const id = randomUuid();
907
+ const started = {
908
+ id,
909
+ entrySource,
910
+ correlation: {
911
+ entry_source: entrySource,
912
+ ...analytics.sourceSessionId ? { source_session_id: analytics.sourceSessionId } : {},
913
+ ...analytics.visitId ? { history_visit_id: analytics.visitId } : {},
914
+ claim_attempt_id: id
915
+ }
916
+ };
917
+ setAttempt(started);
918
+ return started;
919
+ },
920
+ [analytics]
921
+ );
922
+ const endAttempt = useCallback4(
923
+ (source, reason) => {
924
+ const claim = claimControllerRef.current;
925
+ claim?.abandon(reason);
926
+ claim?.close(source);
927
+ claimControllerRef.current = null;
928
+ setAttempt(null);
929
+ },
930
+ []
931
+ );
932
+ const openFallback = useCallback4(() => {
933
+ const started = beginAttempt("history_fallback");
934
+ analytics.fallbackOpened(started.id);
935
+ setFallbackOpen(true);
936
+ }, [analytics, beginAttempt]);
937
+ const closeFallback = useCallback4(
938
+ (via) => {
939
+ endAttempt(via === "escape" ? "escape" : "history_back", "back");
940
+ setFallbackOpen(false);
941
+ },
942
+ [endAttempt]
943
+ );
944
+ const canLookup = Boolean(signRecovery) && Boolean(recipient);
945
+ useEffect4(() => {
946
+ if (canLookup) return;
947
+ setFallbackOpen(false);
948
+ if (fallbackOpen && !recovering) endAttempt("host_controlled", "back");
949
+ }, [canLookup, fallbackOpen, recovering, endAttempt]);
950
+ const startRecoveryFromRow = useCallback4(
951
+ (deposit) => {
952
+ const started = beginAttempt("history_row");
953
+ analytics.recoveryStarted(started.id, "history_row", deposit.depositId);
954
+ controller.startRecovery(deposit);
955
+ },
956
+ [analytics, beginAttempt, controller]
957
+ );
958
+ const startRecoveryFromLookup = useCallback4(
959
+ (deposit) => {
960
+ if (attempt) {
961
+ analytics.recoveryStarted(
962
+ attempt.id,
963
+ attempt.entrySource,
964
+ deposit.depositId
965
+ );
966
+ }
967
+ setFallbackOpen(false);
968
+ controller.startRecovery(deposit);
969
+ },
970
+ [analytics, attempt, controller]
971
+ );
972
+ const cancelRecovery = useCallback4(() => {
973
+ endAttempt("history_back", "back");
974
+ controller.cancelRecovery();
975
+ }, [controller, endAttempt]);
976
+ const closeModal = useCallback4(() => {
977
+ endAttempt("header_button", "modal_close");
978
+ onCloseModal();
979
+ }, [endAttempt, onCloseModal]);
980
+ useEffect4(() => {
981
+ if (!attempt) return;
982
+ return () => {
983
+ const claim = claimControllerRef.current;
984
+ claim?.abandon("modal_close");
985
+ claim?.close("host_controlled");
986
+ };
987
+ }, [attempt]);
988
+ const claimSessionProperties = useMemo2(
989
+ () => ({
990
+ presentation: inline ? "inline" : "overlay",
991
+ overlay_close_enabled: !inline && Boolean(closeOnOverlayClick),
992
+ prefills: { transaction_hash: false, refund_destination: true }
993
+ }),
994
+ [inline, closeOnOverlayClick]
995
+ );
996
+ const layers = /* @__PURE__ */ jsxs5(Fragment, { children: [
997
+ fallbackOpen && recipient && !recovering && /* @__PURE__ */ jsx5(
998
+ HistoryFallbackFlow,
999
+ {
1000
+ service,
1001
+ recipient,
1002
+ onBack: closeFallback,
1003
+ onCloseModal: closeModal,
1004
+ onFound: startRecoveryFromLookup
1005
+ }
1006
+ ),
1007
+ recovering && signRecovery && /* @__PURE__ */ jsx5(
1008
+ HistoryRecoveryFlow,
1009
+ {
1010
+ deposit: recovering,
1011
+ entrySource: attempt?.entrySource ?? "history_row",
1012
+ backendUrl,
1013
+ signRecovery,
1014
+ debug,
1015
+ onBack: cancelRecovery,
1016
+ onCloseModal: closeModal,
1017
+ onSubmittingChange: controller.setRecoverySubmitting,
1018
+ onRecovered: controller.markStale
1019
+ }
1020
+ )
1021
+ ] });
1022
+ return /* @__PURE__ */ jsxs5(Fragment, { children: [
1023
+ /* @__PURE__ */ jsx5(
1024
+ DepositHistoryPanel,
1025
+ {
1026
+ deposits: controller.deposits,
1027
+ isLoading: controller.isLoading,
1028
+ error: controller.error,
1029
+ hasMore: controller.hasMore,
1030
+ isLoadingMore: controller.isLoadingMore,
1031
+ onLoadMore: controller.loadMore,
1032
+ onClose: controller.closePanel,
1033
+ onCloseModal: closeModal,
1034
+ backLabel,
1035
+ title,
1036
+ recipient,
1037
+ onRecover: signRecovery ? startRecoveryFromRow : void 0,
1038
+ onFindByTxHash: canLookup ? openFallback : void 0,
1039
+ onRowView: analytics.rowViewed,
1040
+ obscured: Boolean(recovering) || fallbackOpen
1041
+ }
1042
+ ),
1043
+ attempt ? /* @__PURE__ */ jsx5(
1044
+ AnalyticsSession,
1045
+ {
1046
+ modal: "claim",
1047
+ sessionProperties: claimSessionProperties,
1048
+ onEvent,
1049
+ backendUrl,
1050
+ enableIngest: enableAnalyticsIngest,
1051
+ ingestUrl: analyticsIngestUrl,
1052
+ children: /* @__PURE__ */ jsx5(
1053
+ ClaimAnalyticsControllerProvider,
1054
+ {
1055
+ controllerRef: claimControllerRef,
1056
+ correlation: attempt.correlation,
1057
+ children: layers
1058
+ }
1059
+ )
1060
+ },
1061
+ attempt.id
1062
+ ) : layers
1063
+ ] });
1064
+ }
1065
+
1066
+ // src/components/history/useHistoryPanel.ts
1067
+ import { useCallback as useCallback5, useEffect as useEffect5, useMemo as useMemo3, useRef as useRef5, useState as useState5 } from "react";
1068
+ function sortByCreatedAtDesc(items) {
1069
+ return [...items].sort((a, b) => {
1070
+ const at = a.createdAt ? Date.parse(a.createdAt) : 0;
1071
+ const bt = b.createdAt ? Date.parse(b.createdAt) : 0;
1072
+ return bt - at;
1073
+ });
1074
+ }
1075
+ function useHistoryPanel({
1076
+ isOpen,
1077
+ recipient,
1078
+ service,
1079
+ canRecover,
1080
+ analytics
1081
+ }) {
1082
+ const [isPanelOpen, setIsPanelOpen] = useState5(false);
1083
+ const [deposits, setDeposits] = useState5([]);
1084
+ const [hasMore, setHasMore] = useState5(false);
1085
+ const [isLoading, setIsLoading] = useState5(false);
1086
+ const [isLoadingMore, setIsLoadingMore] = useState5(false);
1087
+ const [error, setError] = useState5(null);
1088
+ const cursorRef = useRef5(null);
1089
+ const staleRef = useRef5(false);
1090
+ const loadedRef = useRef5(false);
1091
+ const recipientRef = useRef5(recipient);
1092
+ const requestRef = useRef5(0);
1093
+ const [recovering, setRecovering] = useState5(null);
1094
+ const [recoverySubmitting, setRecoverySubmitting] = useState5(false);
1095
+ const fetchHistory = useCallback5(
1096
+ async (mode = "initial") => {
1097
+ if (!recipient) return;
1098
+ const isInitial = mode === "initial";
1099
+ const requestId = isInitial ? ++requestRef.current : requestRef.current;
1100
+ const isCurrent = () => recipientRef.current === recipient && requestId === requestRef.current;
1101
+ if (isInitial) {
1102
+ setIsLoading(true);
1103
+ } else {
1104
+ setIsLoadingMore(true);
1105
+ }
1106
+ setError(null);
1107
+ try {
1108
+ const cursor = isInitial ? null : cursorRef.current;
1109
+ if (!isInitial && !cursor) {
1110
+ setHasMore(false);
1111
+ return;
1112
+ }
1113
+ const result = await service.fetchDepositHistory({
1114
+ recipient,
1115
+ limit: 20,
1116
+ cursor: cursor ?? void 0
1117
+ });
1118
+ if (!isCurrent()) return;
1119
+ const incoming = result.deposits;
1120
+ const nextCursor = result.nextCursor ?? null;
1121
+ if (isInitial) {
1122
+ setDeposits(sortByCreatedAtDesc(incoming));
1123
+ } else {
1124
+ setDeposits((prev) => sortByCreatedAtDesc([...prev, ...incoming]));
1125
+ }
1126
+ cursorRef.current = nextCursor;
1127
+ setHasMore(Boolean(nextCursor));
1128
+ staleRef.current = false;
1129
+ loadedRef.current = true;
1130
+ } catch (err) {
1131
+ if (!isCurrent()) return;
1132
+ setError(err instanceof Error ? err.message : "Failed to load history");
1133
+ } finally {
1134
+ if (isCurrent()) {
1135
+ if (isInitial) {
1136
+ setIsLoading(false);
1137
+ } else {
1138
+ setIsLoadingMore(false);
1139
+ }
1140
+ }
1141
+ }
1142
+ },
1143
+ [recipient, service]
1144
+ );
1145
+ const badge = useMemo3(
1146
+ () => deriveHistoryBadge(deposits, { recipient, canRecover }),
1147
+ [deposits, recipient, canRecover]
1148
+ );
1149
+ const openPanel = useCallback5(() => {
1150
+ setIsPanelOpen(true);
1151
+ analytics?.visitOpened(badge);
1152
+ if (!loadedRef.current || staleRef.current) {
1153
+ fetchHistory("initial");
1154
+ }
1155
+ }, [analytics, badge, fetchHistory]);
1156
+ const closePanel = useCallback5(() => {
1157
+ if (recovering) return;
1158
+ setIsPanelOpen(false);
1159
+ analytics?.visitEnded();
1160
+ }, [analytics, recovering]);
1161
+ const loadMore = useCallback5(() => {
1162
+ analytics?.loadMore(filterVisibleDeposits(deposits).length);
1163
+ fetchHistory("more");
1164
+ }, [analytics, deposits, fetchHistory]);
1165
+ const markStale = useCallback5(() => {
1166
+ staleRef.current = true;
1167
+ if (isOpen) {
1168
+ fetchHistory("initial");
1169
+ }
1170
+ }, [isOpen, fetchHistory]);
1171
+ useEffect5(() => {
1172
+ if (recipientRef.current === recipient) return;
1173
+ recipientRef.current = recipient;
1174
+ setDeposits([]);
1175
+ setHasMore(false);
1176
+ setError(null);
1177
+ cursorRef.current = null;
1178
+ staleRef.current = false;
1179
+ loadedRef.current = false;
1180
+ }, [recipient]);
1181
+ useEffect5(() => {
1182
+ if (!isOpen || !recipient) return;
1183
+ if (!loadedRef.current || staleRef.current) {
1184
+ fetchHistory("initial");
1185
+ }
1186
+ }, [isOpen, recipient, fetchHistory]);
1187
+ useEffect5(() => {
1188
+ if (isOpen) return;
1189
+ setIsPanelOpen(false);
1190
+ analytics?.visitEnded();
1191
+ setDeposits([]);
1192
+ setHasMore(false);
1193
+ setError(null);
1194
+ cursorRef.current = null;
1195
+ staleRef.current = false;
1196
+ loadedRef.current = false;
1197
+ requestRef.current += 1;
1198
+ setRecovering(null);
1199
+ setRecoverySubmitting(false);
1200
+ }, [isOpen, analytics]);
1201
+ const invalidate = useCallback5(() => {
1202
+ staleRef.current = true;
1203
+ }, []);
1204
+ const cancelRecovery = useCallback5(() => setRecovering(null), []);
1205
+ return useMemo3(
1206
+ () => ({
1207
+ deposits,
1208
+ isLoading,
1209
+ isLoadingMore,
1210
+ error,
1211
+ hasMore,
1212
+ badge,
1213
+ isPanelOpen,
1214
+ openPanel,
1215
+ closePanel,
1216
+ loadMore,
1217
+ markStale,
1218
+ invalidate,
1219
+ recovering,
1220
+ startRecovery: setRecovering,
1221
+ cancelRecovery,
1222
+ recoverySubmitting,
1223
+ setRecoverySubmitting
1224
+ }),
1225
+ [
1226
+ deposits,
1227
+ isLoading,
1228
+ isLoadingMore,
1229
+ error,
1230
+ hasMore,
1231
+ badge,
1232
+ isPanelOpen,
1233
+ openPanel,
1234
+ closePanel,
1235
+ loadMore,
1236
+ markStale,
1237
+ invalidate,
1238
+ recovering,
1239
+ cancelRecovery,
1240
+ recoverySubmitting
1241
+ ]
1242
+ );
1243
+ }
38
1244
 
39
1245
  // src/core/removed-props.ts
40
1246
  var MANAGED_ACCOUNT_REMOVALS = {
@@ -97,6 +1303,104 @@ function warnRemovedProps(component, props) {
97
1303
  }
98
1304
  }
99
1305
 
1306
+ // src/core/history-entry.ts
1307
+ var PROVIDER_SCREENS = /* @__PURE__ */ new Set(["fiat-onramp", "exchange-connect"]);
1308
+ function isHistoryEntryVisible(input) {
1309
+ if (input.submitting) return false;
1310
+ if (input.screen === "processing") return input.settled;
1311
+ if (PROVIDER_SCREENS.has(input.screen)) return false;
1312
+ return true;
1313
+ }
1314
+
1315
+ // src/core/history-analytics.ts
1316
+ function sinkFor(source) {
1317
+ if (source.modal === "deposit") {
1318
+ const at2 = () => source.controllerRef.current;
1319
+ return {
1320
+ opened: (detail) => at2()?.historyOpened({ ...detail, step: at2()?.step ?? null }),
1321
+ rowViewed: (detail) => at2()?.historyRowViewed(detail),
1322
+ loadMore: (detail) => at2()?.historyLoadMore(detail),
1323
+ fallbackOpened: (detail) => at2()?.historyFallbackOpened(detail),
1324
+ recoveryStarted: (detail) => at2()?.historyRecoveryStarted(detail)
1325
+ };
1326
+ }
1327
+ const at = () => source.controllerRef.current;
1328
+ return {
1329
+ opened: (detail) => at()?.historyOpened({ ...detail, step: at()?.step ?? null }),
1330
+ rowViewed: (detail) => at()?.historyRowViewed(detail),
1331
+ loadMore: (detail) => at()?.historyLoadMore(detail),
1332
+ fallbackOpened: (detail) => at()?.historyFallbackOpened(detail),
1333
+ recoveryStarted: (detail) => at()?.historyRecoveryStarted(detail)
1334
+ };
1335
+ }
1336
+ function badgeState(badge) {
1337
+ if (!badge) return "none";
1338
+ return badge.state === "needs-you" ? "needs_you" : "progress";
1339
+ }
1340
+ function createHistoryAnalytics(source) {
1341
+ const sink = sinkFor(source);
1342
+ let visitId = null;
1343
+ let loadMorePresses = 0;
1344
+ let viewedRows = /* @__PURE__ */ new Set();
1345
+ return {
1346
+ get sourceSessionId() {
1347
+ return source.sessionIdRef.current;
1348
+ },
1349
+ get visitId() {
1350
+ return visitId;
1351
+ },
1352
+ visitOpened(badge) {
1353
+ visitId = randomUuid();
1354
+ loadMorePresses = 0;
1355
+ viewedRows = /* @__PURE__ */ new Set();
1356
+ sink.opened({
1357
+ history_visit_id: visitId,
1358
+ badge: badgeState(badge),
1359
+ badge_count: badge?.count ?? 0
1360
+ });
1361
+ },
1362
+ visitEnded() {
1363
+ visitId = null;
1364
+ },
1365
+ rowViewed({ depositId, status, recoverable, position }) {
1366
+ if (!visitId || viewedRows.has(depositId)) return;
1367
+ viewedRows.add(depositId);
1368
+ sink.rowViewed({
1369
+ history_visit_id: visitId,
1370
+ deposit_id: depositId,
1371
+ status,
1372
+ recoverable,
1373
+ position
1374
+ });
1375
+ },
1376
+ loadMore(loadedRows) {
1377
+ if (!visitId) return;
1378
+ loadMorePresses += 1;
1379
+ sink.loadMore({
1380
+ history_visit_id: visitId,
1381
+ page: loadMorePresses,
1382
+ loaded_rows: loadedRows
1383
+ });
1384
+ },
1385
+ fallbackOpened(claimAttemptId) {
1386
+ if (!visitId) return;
1387
+ sink.fallbackOpened({
1388
+ history_visit_id: visitId,
1389
+ claim_attempt_id: claimAttemptId
1390
+ });
1391
+ },
1392
+ recoveryStarted(claimAttemptId, entrySource, depositId) {
1393
+ if (!visitId) return;
1394
+ sink.recoveryStarted({
1395
+ history_visit_id: visitId,
1396
+ claim_attempt_id: claimAttemptId,
1397
+ entry_source: entrySource,
1398
+ deposit_id: depositId
1399
+ });
1400
+ }
1401
+ };
1402
+ }
1403
+
100
1404
  // src/core/analytics-target.ts
101
1405
  var HEX_TOKEN = /^0x(?:[0-9a-f]{32}|[0-9a-f]{40})$/i;
102
1406
  var BASE58_TOKEN = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
@@ -143,23 +1447,23 @@ function isSubmissionUncertain(error) {
143
1447
  }
144
1448
 
145
1449
  // src/components/steps/ProcessingStep.tsx
146
- import { useCallback as useCallback2, useEffect as useEffect3, useRef as useRef2, useState as useState4 } from "react";
1450
+ import { useCallback as useCallback7, useEffect as useEffect8, useRef as useRef7, useState as useState9 } from "react";
147
1451
 
148
1452
  // src/components/ui/Tooltip.tsx
149
1453
  import {
150
- useState,
151
- useRef,
152
- useEffect,
153
- useCallback
1454
+ useState as useState6,
1455
+ useRef as useRef6,
1456
+ useEffect as useEffect6,
1457
+ useCallback as useCallback6
154
1458
  } from "react";
155
1459
  import { createPortal } from "react-dom";
156
- import { jsx, jsxs } from "react/jsx-runtime";
1460
+ import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
157
1461
  function Tooltip({ content, children, className }) {
158
- const [open, setOpen] = useState(false);
159
- const [position, setPosition] = useState(null);
160
- const triggerRef = useRef(null);
161
- const bubbleRef = useRef(null);
162
- const updatePosition = useCallback(() => {
1462
+ const [open, setOpen] = useState6(false);
1463
+ const [position, setPosition] = useState6(null);
1464
+ const triggerRef = useRef6(null);
1465
+ const bubbleRef = useRef6(null);
1466
+ const updatePosition = useCallback6(() => {
163
1467
  const trigger = triggerRef.current;
164
1468
  if (!trigger) return;
165
1469
  const rect = trigger.getBoundingClientRect();
@@ -168,7 +1472,7 @@ function Tooltip({ content, children, className }) {
168
1472
  left: rect.left + rect.width / 2
169
1473
  });
170
1474
  }, []);
171
- useEffect(() => {
1475
+ useEffect6(() => {
172
1476
  if (!open) return;
173
1477
  updatePosition();
174
1478
  function handleOutside(event) {
@@ -194,7 +1498,7 @@ function Tooltip({ content, children, className }) {
194
1498
  window.removeEventListener("resize", updatePosition);
195
1499
  };
196
1500
  }, [open, updatePosition]);
197
- return /* @__PURE__ */ jsxs(
1501
+ return /* @__PURE__ */ jsxs6(
198
1502
  "span",
199
1503
  {
200
1504
  ref: triggerRef,
@@ -202,7 +1506,7 @@ function Tooltip({ content, children, className }) {
202
1506
  onMouseEnter: () => setOpen(true),
203
1507
  onMouseLeave: () => setOpen(false),
204
1508
  children: [
205
- /* @__PURE__ */ jsx(
1509
+ /* @__PURE__ */ jsx6(
206
1510
  "span",
207
1511
  {
208
1512
  className: "rs-tooltip-trigger",
@@ -224,7 +1528,7 @@ function Tooltip({ content, children, className }) {
224
1528
  }
225
1529
  ),
226
1530
  open && position && typeof document !== "undefined" && createPortal(
227
- /* @__PURE__ */ jsx(
1531
+ /* @__PURE__ */ jsx6(
228
1532
  "span",
229
1533
  {
230
1534
  ref: bubbleRef,
@@ -243,18 +1547,18 @@ function Tooltip({ content, children, className }) {
243
1547
  Tooltip.displayName = "Tooltip";
244
1548
 
245
1549
  // src/components/ui/FeesAccordion.tsx
246
- import { useState as useState2 } from "react";
247
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
1550
+ import { useState as useState7 } from "react";
1551
+ import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
248
1552
  function FeesAccordion({ total, rows, tooltip }) {
249
- const [open, setOpen] = useState2(false);
1553
+ const [open, setOpen] = useState7(false);
250
1554
  const expandable = rows.length > 0;
251
- return /* @__PURE__ */ jsxs2("div", { className: "rs-fees-accordion", children: [
252
- /* @__PURE__ */ jsxs2("div", { className: "rs-fees-accordion-summary", children: [
253
- /* @__PURE__ */ jsxs2("span", { className: "rs-fees-accordion-label", children: [
254
- /* @__PURE__ */ jsx2("span", { children: "Fees" }),
255
- tooltip && /* @__PURE__ */ jsx2(Tooltip, { content: tooltip, children: /* @__PURE__ */ jsx2("span", { className: "rs-review-detail-info", "aria-label": "Fees info", children: /* @__PURE__ */ jsx2(InfoIcon, {}) }) })
1555
+ return /* @__PURE__ */ jsxs7("div", { className: "rs-fees-accordion", children: [
1556
+ /* @__PURE__ */ jsxs7("div", { className: "rs-fees-accordion-summary", children: [
1557
+ /* @__PURE__ */ jsxs7("span", { className: "rs-fees-accordion-label", children: [
1558
+ /* @__PURE__ */ jsx7("span", { children: "Fees" }),
1559
+ tooltip && /* @__PURE__ */ jsx7(Tooltip, { content: tooltip, children: /* @__PURE__ */ jsx7("span", { className: "rs-review-detail-info", "aria-label": "Fees info", children: /* @__PURE__ */ jsx7(InfoIcon, {}) }) })
256
1560
  ] }),
257
- /* @__PURE__ */ jsxs2(
1561
+ /* @__PURE__ */ jsxs7(
258
1562
  "button",
259
1563
  {
260
1564
  type: "button",
@@ -264,35 +1568,35 @@ function FeesAccordion({ total, rows, tooltip }) {
264
1568
  disabled: !expandable,
265
1569
  onClick: () => expandable && setOpen((o) => !o),
266
1570
  children: [
267
- /* @__PURE__ */ jsx2("span", { children: total }),
268
- expandable && /* @__PURE__ */ jsx2(
1571
+ /* @__PURE__ */ jsx7("span", { children: total }),
1572
+ expandable && /* @__PURE__ */ jsx7(
269
1573
  "span",
270
1574
  {
271
1575
  className: `rs-fees-accordion-chevron${open ? " rs-fees-accordion-chevron--open" : ""}`,
272
1576
  "aria-hidden": "true",
273
- children: /* @__PURE__ */ jsx2(ChevronDownIcon, {})
1577
+ children: /* @__PURE__ */ jsx7(ChevronDownIcon, {})
274
1578
  }
275
1579
  )
276
1580
  ]
277
1581
  }
278
1582
  )
279
1583
  ] }),
280
- expandable && open && /* @__PURE__ */ jsx2("div", { className: "rs-fees-accordion-rows", children: rows.map((row, i) => /* @__PURE__ */ jsxs2("div", { className: "rs-fees-accordion-row", children: [
281
- /* @__PURE__ */ jsx2("span", { children: row.label }),
282
- /* @__PURE__ */ jsxs2("span", { className: "rs-review-detail-value", children: [
283
- /* @__PURE__ */ jsx2(
1584
+ expandable && open && /* @__PURE__ */ jsx7("div", { className: "rs-fees-accordion-rows", children: rows.map((row, i) => /* @__PURE__ */ jsxs7("div", { className: "rs-fees-accordion-row", children: [
1585
+ /* @__PURE__ */ jsx7("span", { children: row.label }),
1586
+ /* @__PURE__ */ jsxs7("span", { className: "rs-review-detail-value", children: [
1587
+ /* @__PURE__ */ jsx7(
284
1588
  "span",
285
1589
  {
286
1590
  className: row.strike ? "rs-review-detail-value--strike" : void 0,
287
1591
  children: row.value
288
1592
  }
289
1593
  ),
290
- row.tooltip && /* @__PURE__ */ jsx2(Tooltip, { content: row.tooltip, children: /* @__PURE__ */ jsx2(
1594
+ row.tooltip && /* @__PURE__ */ jsx7(Tooltip, { content: row.tooltip, children: /* @__PURE__ */ jsx7(
291
1595
  "span",
292
1596
  {
293
1597
  className: "rs-review-detail-info",
294
1598
  "aria-label": `${row.label} info`,
295
- children: /* @__PURE__ */ jsx2(InfoIcon, {})
1599
+ children: /* @__PURE__ */ jsx7(InfoIcon, {})
296
1600
  }
297
1601
  ) })
298
1602
  ] })
@@ -302,7 +1606,7 @@ function FeesAccordion({ total, rows, tooltip }) {
302
1606
  FeesAccordion.displayName = "FeesAccordion";
303
1607
 
304
1608
  // src/components/steps/SwappedReceipt.tsx
305
- import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
1609
+ import { jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
306
1610
  function SwappedReceipt({
307
1611
  onrampMethod,
308
1612
  onrampMethodIcon,
@@ -316,29 +1620,29 @@ function SwappedReceipt({
316
1620
  onNewDeposit,
317
1621
  onClose
318
1622
  }) {
319
- return /* @__PURE__ */ jsxs3("div", { className: "rs-screen", children: [
320
- /* @__PURE__ */ jsxs3("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
321
- /* @__PURE__ */ jsx3(BodyHeader, { icon: /* @__PURE__ */ jsx3(CheckIcon, {}), title: "Deposit successful" }),
322
- /* @__PURE__ */ jsxs3("div", { className: "rs-review-details", children: [
323
- onrampMethod && /* @__PURE__ */ jsxs3("div", { className: "rs-review-detail-row", children: [
324
- /* @__PURE__ */ jsx3("span", { children: "Onramp method" }),
325
- /* @__PURE__ */ jsxs3("span", { className: "rs-review-detail-value", children: [
326
- /* @__PURE__ */ jsx3("span", { children: onrampMethod }),
327
- onrampMethodIcon && /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-icon rs-review-detail-icon--square", children: /* @__PURE__ */ jsx3(CdnIcon, { src: onrampMethodIcon }) })
1623
+ return /* @__PURE__ */ jsxs8("div", { className: "rs-screen", children: [
1624
+ /* @__PURE__ */ jsxs8("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
1625
+ /* @__PURE__ */ jsx8(BodyHeader, { icon: /* @__PURE__ */ jsx8(CheckIcon, {}), title: "Deposit successful" }),
1626
+ /* @__PURE__ */ jsxs8("div", { className: "rs-review-details", children: [
1627
+ onrampMethod && /* @__PURE__ */ jsxs8("div", { className: "rs-review-detail-row", children: [
1628
+ /* @__PURE__ */ jsx8("span", { children: "Onramp method" }),
1629
+ /* @__PURE__ */ jsxs8("span", { className: "rs-review-detail-value", children: [
1630
+ /* @__PURE__ */ jsx8("span", { children: onrampMethod }),
1631
+ onrampMethodIcon && /* @__PURE__ */ jsx8("span", { className: "rs-review-detail-icon rs-review-detail-icon--square", children: /* @__PURE__ */ jsx8(CdnIcon, { src: onrampMethodIcon }) })
328
1632
  ] })
329
1633
  ] }),
330
- amountPaid && /* @__PURE__ */ jsxs3("div", { className: "rs-review-detail-row", children: [
331
- /* @__PURE__ */ jsx3("span", { children: "Amount paid" }),
332
- /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-value", children: amountPaid })
1634
+ amountPaid && /* @__PURE__ */ jsxs8("div", { className: "rs-review-detail-row", children: [
1635
+ /* @__PURE__ */ jsx8("span", { children: "Amount paid" }),
1636
+ /* @__PURE__ */ jsx8("span", { className: "rs-review-detail-value", children: amountPaid })
333
1637
  ] }),
334
- /* @__PURE__ */ jsxs3("div", { className: "rs-review-detail-row", children: [
335
- /* @__PURE__ */ jsx3("span", { children: "Deposited amount" }),
336
- /* @__PURE__ */ jsxs3("span", { className: "rs-review-detail-value", children: [
337
- /* @__PURE__ */ jsx3("span", { children: depositedAmount }),
338
- depositedSymbol && /* @__PURE__ */ jsx3("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx3(TokenIcon, { symbol: depositedSymbol }) })
1638
+ /* @__PURE__ */ jsxs8("div", { className: "rs-review-detail-row", children: [
1639
+ /* @__PURE__ */ jsx8("span", { children: "Deposited amount" }),
1640
+ /* @__PURE__ */ jsxs8("span", { className: "rs-review-detail-value", children: [
1641
+ /* @__PURE__ */ jsx8("span", { children: depositedAmount }),
1642
+ depositedSymbol && /* @__PURE__ */ jsx8("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx8(TokenIcon, { symbol: depositedSymbol }) })
339
1643
  ] })
340
1644
  ] }),
341
- feesTotal != null && /* @__PURE__ */ jsx3(
1645
+ feesTotal != null && /* @__PURE__ */ jsx8(
342
1646
  FeesAccordion,
343
1647
  {
344
1648
  total: feesTotal,
@@ -347,18 +1651,18 @@ function SwappedReceipt({
347
1651
  }
348
1652
  )
349
1653
  ] }),
350
- /* @__PURE__ */ jsxs3("div", { className: "rs-screen-button-row", children: [
351
- onNewDeposit && /* @__PURE__ */ jsx3(Button, { variant: "outline", onClick: onNewDeposit, fullWidth: true, children: newLabel }),
352
- onClose && /* @__PURE__ */ jsx3(Button, { onClick: onClose, fullWidth: true, children: "Done" })
1654
+ /* @__PURE__ */ jsxs8("div", { className: "rs-screen-button-row", children: [
1655
+ onNewDeposit && /* @__PURE__ */ jsx8(Button, { variant: "outline", onClick: onNewDeposit, fullWidth: true, children: newLabel }),
1656
+ onClose && /* @__PURE__ */ jsx8(Button, { onClick: onClose, fullWidth: true, children: "Done" })
353
1657
  ] })
354
1658
  ] }),
355
- /* @__PURE__ */ jsx3(PoweredBy, {})
1659
+ /* @__PURE__ */ jsx8(PoweredBy, {})
356
1660
  ] });
357
1661
  }
358
1662
  SwappedReceipt.displayName = "SwappedReceipt";
359
1663
 
360
1664
  // src/components/ui/ExchangeLogos.tsx
361
- import { jsx as jsx4 } from "react/jsx-runtime";
1665
+ import { jsx as jsx9 } from "react/jsx-runtime";
362
1666
  var EXCHANGE_SLUGS = [
363
1667
  "binance",
364
1668
  "bitfinex",
@@ -388,7 +1692,7 @@ function getExchangeLogoSrc(name, connection) {
388
1692
  }
389
1693
  function getExchangeLogo(name, connection) {
390
1694
  const src = getExchangeLogoSrc(name, connection);
391
- return src ? /* @__PURE__ */ jsx4(CdnIcon, { src }) : null;
1695
+ return src ? /* @__PURE__ */ jsx9(CdnIcon, { src }) : null;
392
1696
  }
393
1697
 
394
1698
  // src/core/webhook.ts
@@ -533,7 +1837,7 @@ function failureMessageForEvent(event) {
533
1837
  }
534
1838
 
535
1839
  // src/core/useTokenPrices.ts
536
- import { useEffect as useEffect2, useState as useState3 } from "react";
1840
+ import { useEffect as useEffect7, useState as useState8 } from "react";
537
1841
  var PRICE_SERVICE_NATIVE = "0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee";
538
1842
  var WRAPPED_SOL_MINT = "So11111111111111111111111111111111111111112";
539
1843
  var SOL_SYSTEM_PROGRAM = "11111111111111111111111111111111";
@@ -563,7 +1867,7 @@ async function fetchTokenPriceUsd(service, token) {
563
1867
  return typeof price === "number" && price > 0 ? price : null;
564
1868
  }
565
1869
  function useTokenPrices(service, tokens) {
566
- const [prices, setPrices] = useState3({});
1870
+ const [prices, setPrices] = useState8({});
567
1871
  const defined = tokens.filter((t) => Boolean(t?.symbol));
568
1872
  const entries = [
569
1873
  ...new Map(
@@ -574,7 +1878,7 @@ function useTokenPrices(service, tokens) {
574
1878
  ).values()
575
1879
  ].sort((a, b) => a.caip2.localeCompare(b.caip2));
576
1880
  const key = JSON.stringify(entries);
577
- useEffect2(() => {
1881
+ useEffect7(() => {
578
1882
  if (key === "[]") return;
579
1883
  let cancelled = false;
580
1884
  const parsed = JSON.parse(key);
@@ -597,9 +1901,9 @@ function useTokenPrices(service, tokens) {
597
1901
  }
598
1902
 
599
1903
  // src/components/steps/ProcessingStep.tsx
600
- import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1904
+ import { Fragment as Fragment2, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
601
1905
  function SuccessBadge() {
602
- return /* @__PURE__ */ jsxs4(
1906
+ return /* @__PURE__ */ jsxs9(
603
1907
  "svg",
604
1908
  {
605
1909
  width: "40",
@@ -609,7 +1913,7 @@ function SuccessBadge() {
609
1913
  xmlns: "http://www.w3.org/2000/svg",
610
1914
  "aria-hidden": "true",
611
1915
  children: [
612
- /* @__PURE__ */ jsx5(
1916
+ /* @__PURE__ */ jsx10(
613
1917
  "rect",
614
1918
  {
615
1919
  width: "40",
@@ -618,7 +1922,7 @@ function SuccessBadge() {
618
1922
  fill: "var(--rs-icon-wrapper-bg)"
619
1923
  }
620
1924
  ),
621
- /* @__PURE__ */ jsx5(
1925
+ /* @__PURE__ */ jsx10(
622
1926
  "path",
623
1927
  {
624
1928
  d: "M28 14L17 25L12 20",
@@ -633,7 +1937,7 @@ function SuccessBadge() {
633
1937
  );
634
1938
  }
635
1939
  function FailedBadge() {
636
- return /* @__PURE__ */ jsxs4(
1940
+ return /* @__PURE__ */ jsxs9(
637
1941
  "svg",
638
1942
  {
639
1943
  width: "40",
@@ -643,8 +1947,8 @@ function FailedBadge() {
643
1947
  xmlns: "http://www.w3.org/2000/svg",
644
1948
  "aria-hidden": "true",
645
1949
  children: [
646
- /* @__PURE__ */ jsx5("rect", { width: "40", height: "40", rx: "8", fill: "#FB2C36" }),
647
- /* @__PURE__ */ jsx5(
1950
+ /* @__PURE__ */ jsx10("rect", { width: "40", height: "40", rx: "8", fill: "#FB2C36" }),
1951
+ /* @__PURE__ */ jsx10(
648
1952
  "path",
649
1953
  {
650
1954
  d: "M26 14L14 26M14 14L26 26",
@@ -778,10 +2082,10 @@ function formatTimer(seconds) {
778
2082
  return `${mins}:${String(secs).padStart(2, "0")}`;
779
2083
  }
780
2084
  function TickerChar({ value }) {
781
- const [current, setCurrent] = useState4(value);
782
- const [previous, setPrevious] = useState4(null);
783
- const [animKey, setAnimKey] = useState4(0);
784
- useEffect3(() => {
2085
+ const [current, setCurrent] = useState9(value);
2086
+ const [previous, setPrevious] = useState9(null);
2087
+ const [animKey, setAnimKey] = useState9(0);
2088
+ useEffect8(() => {
785
2089
  if (value === current) return;
786
2090
  setPrevious(current);
787
2091
  setCurrent(value);
@@ -789,16 +2093,16 @@ function TickerChar({ value }) {
789
2093
  const timeout = setTimeout(() => setPrevious(null), 360);
790
2094
  return () => clearTimeout(timeout);
791
2095
  }, [value, current]);
792
- return /* @__PURE__ */ jsxs4("span", { className: "rs-ticker-slot", children: [
793
- previous !== null && /* @__PURE__ */ jsx5("span", { className: "rs-ticker-out", children: previous }, `out-${animKey}`),
794
- /* @__PURE__ */ jsx5("span", { className: "rs-ticker-in", children: current }, `in-${animKey}`)
2096
+ return /* @__PURE__ */ jsxs9("span", { className: "rs-ticker-slot", children: [
2097
+ previous !== null && /* @__PURE__ */ jsx10("span", { className: "rs-ticker-out", children: previous }, `out-${animKey}`),
2098
+ /* @__PURE__ */ jsx10("span", { className: "rs-ticker-in", children: current }, `in-${animKey}`)
795
2099
  ] });
796
2100
  }
797
2101
  function Ticker({ value }) {
798
- return /* @__PURE__ */ jsx5("span", { className: "rs-ticker", "aria-label": value, children: value.split("").map((char, index) => (
2102
+ return /* @__PURE__ */ jsx10("span", { className: "rs-ticker", "aria-label": value, children: value.split("").map((char, index) => (
799
2103
  // Position-stable key so each slot keeps its own animation state.
800
2104
  // eslint-disable-next-line react/no-array-index-key
801
- /* @__PURE__ */ jsx5(TickerChar, { value: char }, index)
2105
+ /* @__PURE__ */ jsx10(TickerChar, { value: char }, index)
802
2106
  )) });
803
2107
  }
804
2108
  function getPhaseStartTime(phaseId, phaseTimings) {
@@ -912,12 +2216,13 @@ function ProcessingStep({
912
2216
  onDepositComplete,
913
2217
  onDepositFailed,
914
2218
  onSourceTransactionObserved,
2219
+ onSettledChange,
915
2220
  onError
916
2221
  }) {
917
- const startTimeRef = useRef2(Date.now());
918
- const pollIntervalRef = useRef2(INITIAL_POLL_INTERVAL);
919
- const pollTimeoutRef = useRef2(null);
920
- const escalatedDelayRef = useRef2(false);
2222
+ const startTimeRef = useRef7(Date.now());
2223
+ const pollIntervalRef = useRef7(INITIAL_POLL_INTERVAL);
2224
+ const pollTimeoutRef = useRef7(null);
2225
+ const escalatedDelayRef = useRef7(false);
921
2226
  const processingContextRef = useLatestRef({
922
2227
  amount,
923
2228
  sourceChain,
@@ -931,9 +2236,9 @@ function ProcessingStep({
931
2236
  const onDepositFailedRef = useLatestRef(onDepositFailed);
932
2237
  const onErrorRef = useLatestRef(onError);
933
2238
  const explorerTxUrl = useExplorerTxUrl();
934
- const initialTerminalEventRef = useRef2(null);
935
- const completedDirectTransferTxHashRef = useRef2(null);
936
- const [state, setState] = useState4(() => {
2239
+ const initialTerminalEventRef = useRef7(null);
2240
+ const completedDirectTransferTxHashRef = useRef7(null);
2241
+ const [state, setState] = useState9(() => {
937
2242
  if (directTransfer) return { type: "complete" };
938
2243
  const initial = getInitialProcessingState(
939
2244
  initialEvent,
@@ -947,8 +2252,8 @@ function ProcessingStep({
947
2252
  }
948
2253
  return { type: "processing" };
949
2254
  });
950
- const [elapsedSeconds, setElapsedSeconds] = useState4(0);
951
- const [phaseTimings, setPhaseTimings] = useState4(() => {
2255
+ const [elapsedSeconds, setElapsedSeconds] = useState9(0);
2256
+ const [phaseTimings, setPhaseTimings] = useState9(() => {
952
2257
  const saved = loadPhaseTimings(txHash);
953
2258
  if (saved) {
954
2259
  startTimeRef.current = saved.startedAt;
@@ -956,8 +2261,8 @@ function ProcessingStep({
956
2261
  }
957
2262
  return { startedAt: startTimeRef.current };
958
2263
  });
959
- const [hasEscalatedDelay, setHasEscalatedDelay] = useState4(false);
960
- const updatePhaseTimings = useCallback2(
2264
+ const [hasEscalatedDelay, setHasEscalatedDelay] = useState9(false);
2265
+ const updatePhaseTimings = useCallback7(
961
2266
  (updater) => {
962
2267
  setPhaseTimings((previous) => {
963
2268
  const next = updater(previous);
@@ -967,7 +2272,7 @@ function ProcessingStep({
967
2272
  },
968
2273
  [txHash]
969
2274
  );
970
- useEffect3(() => {
2275
+ useEffect8(() => {
971
2276
  if (!directTransfer || completedDirectTransferTxHashRef.current === txHash) {
972
2277
  return;
973
2278
  }
@@ -1001,7 +2306,7 @@ function ProcessingStep({
1001
2306
  txHash,
1002
2307
  updatePhaseTimings
1003
2308
  ]);
1004
- useEffect3(() => {
2309
+ useEffect8(() => {
1005
2310
  const event = initialTerminalEventRef.current;
1006
2311
  if (!event) return;
1007
2312
  initialTerminalEventRef.current = null;
@@ -1044,7 +2349,13 @@ function ProcessingStep({
1044
2349
  processingContextRef,
1045
2350
  txHash
1046
2351
  ]);
1047
- useEffect3(() => {
2352
+ const onSettledChangeRef = useRef7(onSettledChange);
2353
+ onSettledChangeRef.current = onSettledChange;
2354
+ useEffect8(() => {
2355
+ onSettledChangeRef.current?.(state.type !== "processing");
2356
+ return () => onSettledChangeRef.current?.(false);
2357
+ }, [state.type]);
2358
+ useEffect8(() => {
1048
2359
  if (directTransfer || state.type !== "processing") return;
1049
2360
  const updateElapsed = () => {
1050
2361
  setElapsedSeconds(
@@ -1055,7 +2366,7 @@ function ProcessingStep({
1055
2366
  const intervalId = setInterval(updateElapsed, 1e3);
1056
2367
  return () => clearInterval(intervalId);
1057
2368
  }, [directTransfer, state.type]);
1058
- useEffect3(() => {
2369
+ useEffect8(() => {
1059
2370
  if (state.type === "processing") return;
1060
2371
  const endedAt = state.type === "complete" ? phaseTimings.completedAt ?? Date.now() : Date.now();
1061
2372
  setElapsedSeconds(Math.floor((endedAt - startTimeRef.current) / 1e3));
@@ -1063,14 +2374,14 @@ function ProcessingStep({
1063
2374
  (previous) => previous.endedAt !== void 0 ? previous : { ...previous, endedAt }
1064
2375
  );
1065
2376
  }, [phaseTimings.completedAt, state.type, updatePhaseTimings]);
1066
- useEffect3(() => {
2377
+ useEffect8(() => {
1067
2378
  if (!state.lastEvent) return;
1068
2379
  updatePhaseTimings(
1069
2380
  (previous) => syncPhaseTimings(previous, state.lastEvent)
1070
2381
  );
1071
2382
  }, [state.lastEvent?.time, state.lastEvent?.type, updatePhaseTimings]);
1072
- const [swappedFiatContext, setSwappedFiatContext] = useState4(null);
1073
- useEffect3(() => {
2383
+ const [swappedFiatContext, setSwappedFiatContext] = useState9(null);
2384
+ useEffect8(() => {
1074
2385
  let cancelled = false;
1075
2386
  let timeoutId;
1076
2387
  const isFiatSwappedOrder = isSwappedOrder && swappedContext?.variant === "fiat";
@@ -1127,7 +2438,7 @@ function ProcessingStep({
1127
2438
  swappedContext?.variant,
1128
2439
  swappedContext?.expectedOrderUuid
1129
2440
  ]);
1130
- useEffect3(() => {
2441
+ useEffect8(() => {
1131
2442
  if (directTransfer) return;
1132
2443
  if (state.type !== "processing") {
1133
2444
  pollIntervalRef.current = INITIAL_POLL_INTERVAL;
@@ -1256,7 +2567,7 @@ function ProcessingStep({
1256
2567
  state.type,
1257
2568
  txHash
1258
2569
  ]);
1259
- useEffect3(() => {
2570
+ useEffect8(() => {
1260
2571
  if (directTransfer || state.type !== "processing") return;
1261
2572
  const timeoutId = setTimeout(() => {
1262
2573
  if (escalatedDelayRef.current) return;
@@ -1288,7 +2599,7 @@ function ProcessingStep({
1288
2599
  const targetChainId = targetChainToChainId(targetChain);
1289
2600
  const settledSourceTxHash = lastEvent?.data?.source?.transactionHash;
1290
2601
  const sourceExplorerHash = settledSourceTxHash ?? (sourceTxHashPending ? null : sourceTxHash);
1291
- useEffect3(() => {
2602
+ useEffect8(() => {
1292
2603
  if (sourceTxHashPending && settledSourceTxHash) {
1293
2604
  onSourceTransactionObserved?.(settledSourceTxHash);
1294
2605
  }
@@ -1382,13 +2693,13 @@ function ProcessingStep({
1382
2693
  const feeTooltip = uiConfig?.feeTooltip ?? (feeSponsored ? "Network fees are sponsored for this deposit." : "Network fees apply.");
1383
2694
  const stateTitle = isComplete ? `${flowCapitalized} successful` : isFailed ? `${flowCapitalized} failed` : "Processing...";
1384
2695
  const handleRetry = onRetry ?? onNewDeposit;
1385
- const headerContent = isComplete ? /* @__PURE__ */ jsxs4("div", { className: "rs-body-header", children: [
1386
- /* @__PURE__ */ jsx5(SuccessBadge, {}),
1387
- /* @__PURE__ */ jsx5("div", { className: "rs-body-header-text", children: /* @__PURE__ */ jsx5("h2", { className: "rs-body-header-title", children: stateTitle }) })
1388
- ] }) : isFailed ? /* @__PURE__ */ jsxs4("div", { className: "rs-body-header", children: [
1389
- /* @__PURE__ */ jsx5(FailedBadge, {}),
1390
- /* @__PURE__ */ jsx5("div", { className: "rs-body-header-text", children: /* @__PURE__ */ jsx5("h2", { className: "rs-body-header-title", children: stateTitle }) })
1391
- ] }) : /* @__PURE__ */ jsx5(BodyHeader, { icon: /* @__PURE__ */ jsx5(WalletIcon, {}), title: stateTitle });
2696
+ const headerContent = isComplete ? /* @__PURE__ */ jsxs9("div", { className: "rs-body-header", children: [
2697
+ /* @__PURE__ */ jsx10(SuccessBadge, {}),
2698
+ /* @__PURE__ */ jsx10("div", { className: "rs-body-header-text", children: /* @__PURE__ */ jsx10("h2", { className: "rs-body-header-title", children: stateTitle }) })
2699
+ ] }) : isFailed ? /* @__PURE__ */ jsxs9("div", { className: "rs-body-header", children: [
2700
+ /* @__PURE__ */ jsx10(FailedBadge, {}),
2701
+ /* @__PURE__ */ jsx10("div", { className: "rs-body-header-text", children: /* @__PURE__ */ jsx10("h2", { className: "rs-body-header-title", children: stateTitle }) })
2702
+ ] }) : /* @__PURE__ */ jsx10(BodyHeader, { icon: /* @__PURE__ */ jsx10(WalletIcon, {}), title: stateTitle });
1392
2703
  if (isComplete && isSwappedOrder) {
1393
2704
  const effectivePaymentMethod = swappedContext?.method ?? swappedFiatContext?.paymentMethod ?? null;
1394
2705
  const onrampMethod = effectivePaymentMethod ? formatPaymentMethod(effectivePaymentMethod) : null;
@@ -1428,7 +2739,7 @@ function ProcessingStep({
1428
2739
  const feesTotal = feeRows.length > 0 ? formatFeeUsd(
1429
2740
  (onrampFeeUsd ?? 0) + chargeableUsd + fallbackChargeableUsd
1430
2741
  ) : null;
1431
- return /* @__PURE__ */ jsx5(
2742
+ return /* @__PURE__ */ jsx10(
1432
2743
  SwappedReceipt,
1433
2744
  {
1434
2745
  onrampMethod,
@@ -1445,16 +2756,16 @@ function ProcessingStep({
1445
2756
  }
1446
2757
  );
1447
2758
  }
1448
- return /* @__PURE__ */ jsxs4("div", { className: "rs-screen", children: [
1449
- /* @__PURE__ */ jsxs4("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
2759
+ return /* @__PURE__ */ jsxs9("div", { className: "rs-screen", children: [
2760
+ /* @__PURE__ */ jsxs9("div", { className: "rs-screen-body rs-screen-body--gap-32", children: [
1450
2761
  headerContent,
1451
- /* @__PURE__ */ jsxs4("div", { className: "rs-review-details", children: [
1452
- /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1453
- /* @__PURE__ */ jsx5("span", { children: "Source chain" }),
1454
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
1455
- /* @__PURE__ */ jsx5("span", { children: sourceChainName }),
1456
- sourceChainIcon && /* @__PURE__ */ jsx5("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx5(CdnIcon, { src: sourceChainIcon }) }),
1457
- sourceExplorerUrl && /* @__PURE__ */ jsx5(
2762
+ /* @__PURE__ */ jsxs9("div", { className: "rs-review-details", children: [
2763
+ /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2764
+ /* @__PURE__ */ jsx10("span", { children: "Source chain" }),
2765
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
2766
+ /* @__PURE__ */ jsx10("span", { children: sourceChainName }),
2767
+ sourceChainIcon && /* @__PURE__ */ jsx10("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx10(CdnIcon, { src: sourceChainIcon }) }),
2768
+ sourceExplorerUrl && /* @__PURE__ */ jsx10(
1458
2769
  "a",
1459
2770
  {
1460
2771
  href: sourceExplorerUrl,
@@ -1462,17 +2773,17 @@ function ProcessingStep({
1462
2773
  rel: "noopener noreferrer",
1463
2774
  className: "rs-review-detail-link",
1464
2775
  "aria-label": "View source transaction",
1465
- children: /* @__PURE__ */ jsx5(ExternalLinkIcon, {})
2776
+ children: /* @__PURE__ */ jsx10(ExternalLinkIcon, {})
1466
2777
  }
1467
2778
  )
1468
2779
  ] })
1469
2780
  ] }),
1470
- /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1471
- /* @__PURE__ */ jsx5("span", { children: "Destination chain" }),
1472
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
1473
- /* @__PURE__ */ jsx5("span", { children: targetChainName }),
1474
- targetChainIcon && /* @__PURE__ */ jsx5("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx5(CdnIcon, { src: targetChainIcon }) }),
1475
- destExplorerUrl && /* @__PURE__ */ jsx5(
2781
+ /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2782
+ /* @__PURE__ */ jsx10("span", { children: "Destination chain" }),
2783
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
2784
+ /* @__PURE__ */ jsx10("span", { children: targetChainName }),
2785
+ targetChainIcon && /* @__PURE__ */ jsx10("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx10(CdnIcon, { src: targetChainIcon }) }),
2786
+ destExplorerUrl && /* @__PURE__ */ jsx10(
1476
2787
  "a",
1477
2788
  {
1478
2789
  href: destExplorerUrl,
@@ -1480,75 +2791,75 @@ function ProcessingStep({
1480
2791
  rel: "noopener noreferrer",
1481
2792
  className: "rs-review-detail-link",
1482
2793
  "aria-label": "View destination transaction",
1483
- children: /* @__PURE__ */ jsx5(ExternalLinkIcon, {})
2794
+ children: /* @__PURE__ */ jsx10(ExternalLinkIcon, {})
1484
2795
  }
1485
2796
  )
1486
2797
  ] })
1487
2798
  ] }),
1488
- /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1489
- /* @__PURE__ */ jsx5("span", { children: isProcessing ? "Time elapsed" : "Total time" }),
1490
- /* @__PURE__ */ jsx5("span", { className: "rs-review-detail-value", children: /* @__PURE__ */ jsx5(Ticker, { value: timerText }) })
2799
+ /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2800
+ /* @__PURE__ */ jsx10("span", { children: isProcessing ? "Time elapsed" : "Total time" }),
2801
+ /* @__PURE__ */ jsx10("span", { className: "rs-review-detail-value", children: /* @__PURE__ */ jsx10(Ticker, { value: timerText }) })
1491
2802
  ] }),
1492
- isSwappedOrder ? /* @__PURE__ */ jsxs4(Fragment, { children: [
1493
- swappedFiatContext?.paidAmountUsd != null && /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1494
- /* @__PURE__ */ jsx5("span", { children: "You pay" }),
1495
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
2803
+ isSwappedOrder ? /* @__PURE__ */ jsxs9(Fragment2, { children: [
2804
+ swappedFiatContext?.paidAmountUsd != null && /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2805
+ /* @__PURE__ */ jsx10("span", { children: "You pay" }),
2806
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
1496
2807
  "$",
1497
2808
  swappedFiatContext.paidAmountUsd.toFixed(2),
1498
- swappedFiatContext.paymentMethod && /* @__PURE__ */ jsxs4("span", { style: { color: "#71717b", marginLeft: 6 }, children: [
2809
+ swappedFiatContext.paymentMethod && /* @__PURE__ */ jsxs9("span", { style: { color: "#71717b", marginLeft: 6 }, children: [
1499
2810
  "via",
1500
2811
  " ",
1501
2812
  formatPaymentMethod(swappedFiatContext.paymentMethod)
1502
2813
  ] })
1503
2814
  ] })
1504
2815
  ] }),
1505
- swappedFiatContext?.onrampFeeUsd != null && /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1506
- /* @__PURE__ */ jsx5("span", { children: "On-ramp fee" }),
1507
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
2816
+ swappedFiatContext?.onrampFeeUsd != null && /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2817
+ /* @__PURE__ */ jsx10("span", { children: "On-ramp fee" }),
2818
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
1508
2819
  "$",
1509
2820
  swappedFiatContext.onrampFeeUsd.toFixed(2)
1510
2821
  ] })
1511
2822
  ] }),
1512
- formattedBridgingCost && /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1513
- /* @__PURE__ */ jsx5("span", { children: "Bridging cost" }),
1514
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
1515
- /* @__PURE__ */ jsxs4("span", { children: [
2823
+ formattedBridgingCost && /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2824
+ /* @__PURE__ */ jsx10("span", { children: "Bridging cost" }),
2825
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
2826
+ /* @__PURE__ */ jsxs9("span", { children: [
1516
2827
  formattedBridgingCost,
1517
2828
  " ",
1518
2829
  sourceSymbol
1519
2830
  ] }),
1520
- /* @__PURE__ */ jsx5("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx5(TokenIcon, { symbol: sourceSymbol }) })
2831
+ /* @__PURE__ */ jsx10("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx10(TokenIcon, { symbol: sourceSymbol }) })
1521
2832
  ] })
1522
2833
  ] })
1523
- ] }) : /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1524
- /* @__PURE__ */ jsx5("span", { children: isProcessing ? "You send" : "You sent" }),
1525
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
1526
- /* @__PURE__ */ jsxs4("span", { children: [
2834
+ ] }) : /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2835
+ /* @__PURE__ */ jsx10("span", { children: isProcessing ? "You send" : "You sent" }),
2836
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
2837
+ /* @__PURE__ */ jsxs9("span", { children: [
1527
2838
  formattedSentAmount,
1528
2839
  " ",
1529
2840
  sourceSymbol
1530
2841
  ] }),
1531
- /* @__PURE__ */ jsx5("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx5(TokenIcon, { symbol: sourceSymbol }) })
2842
+ /* @__PURE__ */ jsx10("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx10(TokenIcon, { symbol: sourceSymbol }) })
1532
2843
  ] })
1533
2844
  ] }),
1534
- /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1535
- /* @__PURE__ */ jsx5("span", { children: isProcessing ? "Receive" : "Received" }),
1536
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
1537
- /* @__PURE__ */ jsx5("span", { children: receiveDisplay }),
1538
- /* @__PURE__ */ jsx5("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx5(TokenIcon, { symbol: targetSymbol }) })
2845
+ /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2846
+ /* @__PURE__ */ jsx10("span", { children: isProcessing ? "Receive" : "Received" }),
2847
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
2848
+ /* @__PURE__ */ jsx10("span", { children: receiveDisplay }),
2849
+ /* @__PURE__ */ jsx10("span", { className: "rs-review-detail-icon", children: /* @__PURE__ */ jsx10(TokenIcon, { symbol: targetSymbol }) })
1539
2850
  ] })
1540
2851
  ] }),
1541
- isFailed && balanceAfterUsd !== void 0 && /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1542
- /* @__PURE__ */ jsx5("span", { children: "Balance" }),
1543
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
2852
+ isFailed && balanceAfterUsd !== void 0 && /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2853
+ /* @__PURE__ */ jsx10("span", { children: "Balance" }),
2854
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
1544
2855
  "$",
1545
2856
  balanceAfterUsd.toFixed(2)
1546
2857
  ] })
1547
2858
  ] }),
1548
- isSwappedOrder ? quotedFeeAmount !== void 0 && /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1549
- /* @__PURE__ */ jsx5("span", { children: "Fees" }),
1550
- /* @__PURE__ */ jsxs4("span", { className: "rs-review-detail-value", children: [
1551
- /* @__PURE__ */ jsxs4(
2859
+ isSwappedOrder ? quotedFeeAmount !== void 0 && /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2860
+ /* @__PURE__ */ jsx10("span", { children: "Fees" }),
2861
+ /* @__PURE__ */ jsxs9("span", { className: "rs-review-detail-value", children: [
2862
+ /* @__PURE__ */ jsxs9(
1552
2863
  "span",
1553
2864
  {
1554
2865
  style: feeSponsored ? { textDecoration: "line-through" } : void 0,
@@ -1559,21 +2870,21 @@ function ProcessingStep({
1559
2870
  ]
1560
2871
  }
1561
2872
  ),
1562
- /* @__PURE__ */ jsx5(Tooltip, { content: feeTooltip, children: /* @__PURE__ */ jsx5(
2873
+ /* @__PURE__ */ jsx10(Tooltip, { content: feeTooltip, children: /* @__PURE__ */ jsx10(
1563
2874
  "span",
1564
2875
  {
1565
2876
  className: "rs-review-detail-info",
1566
2877
  "aria-label": "Fee info",
1567
- children: /* @__PURE__ */ jsx5(InfoIcon, {})
2878
+ children: /* @__PURE__ */ jsx10(InfoIcon, {})
1568
2879
  }
1569
2880
  ) })
1570
2881
  ] })
1571
2882
  ] }) : (() => {
1572
2883
  const { display, struck } = quoteFeeRow(quote?.fees);
1573
2884
  if (display !== null) {
1574
- return /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1575
- /* @__PURE__ */ jsx5("span", { children: "Fees" }),
1576
- /* @__PURE__ */ jsx5("span", { className: "rs-review-detail-value", children: /* @__PURE__ */ jsx5(
2885
+ return /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2886
+ /* @__PURE__ */ jsx10("span", { children: "Fees" }),
2887
+ /* @__PURE__ */ jsx10("span", { className: "rs-review-detail-value", children: /* @__PURE__ */ jsx10(
1577
2888
  "span",
1578
2889
  {
1579
2890
  style: struck ? { textDecoration: "line-through" } : void 0,
@@ -1584,9 +2895,9 @@ function ProcessingStep({
1584
2895
  }
1585
2896
  const feeValue = quotedFeeAmount ?? formattedBridgingCost;
1586
2897
  if (feeValue === void 0) return null;
1587
- return /* @__PURE__ */ jsxs4("div", { className: "rs-review-detail-row", children: [
1588
- /* @__PURE__ */ jsx5("span", { children: "Fees" }),
1589
- /* @__PURE__ */ jsx5("span", { className: "rs-review-detail-value", children: /* @__PURE__ */ jsxs4(
2898
+ return /* @__PURE__ */ jsxs9("div", { className: "rs-review-detail-row", children: [
2899
+ /* @__PURE__ */ jsx10("span", { children: "Fees" }),
2900
+ /* @__PURE__ */ jsx10("span", { className: "rs-review-detail-value", children: /* @__PURE__ */ jsxs9(
1590
2901
  "span",
1591
2902
  {
1592
2903
  style: feeSponsored ? { textDecoration: "line-through" } : void 0,
@@ -1600,8 +2911,8 @@ function ProcessingStep({
1600
2911
  ] });
1601
2912
  })()
1602
2913
  ] }),
1603
- isFailed && failureMessage && /* @__PURE__ */ jsx5(Callout, { variant: "error", children: failureMessage }),
1604
- isProcessing && /* @__PURE__ */ jsx5(
2914
+ isFailed && failureMessage && /* @__PURE__ */ jsx10(Callout, { variant: "error", children: failureMessage }),
2915
+ isProcessing && /* @__PURE__ */ jsx10(
1605
2916
  Button,
1606
2917
  {
1607
2918
  fullWidth: true,
@@ -1611,15 +2922,15 @@ function ProcessingStep({
1611
2922
  children: "Submitting transaction\u2026"
1612
2923
  }
1613
2924
  ),
1614
- isComplete && /* @__PURE__ */ jsxs4("div", { className: "rs-screen-button-row", children: [
1615
- onNewDeposit && /* @__PURE__ */ jsxs4(Button, { variant: "outline", onClick: onNewDeposit, fullWidth: true, children: [
2925
+ isComplete && /* @__PURE__ */ jsxs9("div", { className: "rs-screen-button-row", children: [
2926
+ onNewDeposit && /* @__PURE__ */ jsxs9(Button, { variant: "outline", onClick: onNewDeposit, fullWidth: true, children: [
1616
2927
  "New ",
1617
2928
  flowNoun
1618
2929
  ] }),
1619
- onClose && /* @__PURE__ */ jsx5(Button, { onClick: () => onClose("success_done"), fullWidth: true, children: "Done" })
2930
+ onClose && /* @__PURE__ */ jsx10(Button, { onClick: () => onClose("success_done"), fullWidth: true, children: "Done" })
1620
2931
  ] }),
1621
- isFailed && /* @__PURE__ */ jsxs4("div", { className: "rs-screen-button-row", children: [
1622
- onClose && /* @__PURE__ */ jsx5(
2932
+ isFailed && /* @__PURE__ */ jsxs9("div", { className: "rs-screen-button-row", children: [
2933
+ onClose && /* @__PURE__ */ jsx10(
1623
2934
  Button,
1624
2935
  {
1625
2936
  variant: "outline",
@@ -1628,10 +2939,10 @@ function ProcessingStep({
1628
2939
  children: "Cancel"
1629
2940
  }
1630
2941
  ),
1631
- handleRetry && /* @__PURE__ */ jsx5(Button, { onClick: handleRetry, fullWidth: true, children: "Try again" })
2942
+ handleRetry && /* @__PURE__ */ jsx10(Button, { onClick: handleRetry, fullWidth: true, children: "Try again" })
1632
2943
  ] })
1633
2944
  ] }),
1634
- /* @__PURE__ */ jsx5(PoweredBy, {})
2945
+ /* @__PURE__ */ jsx10(PoweredBy, {})
1635
2946
  ] });
1636
2947
  }
1637
2948
 
@@ -1660,9 +2971,22 @@ function normalizeKeyToken(value) {
1660
2971
  if (value === void 0) return void 0;
1661
2972
  return value.startsWith("0x") ? value.toLowerCase() : value;
1662
2973
  }
1663
- var SOLANA_ADDRESS_PATTERN = /^[1-9A-HJ-NP-Za-km-z]{32,44}$/;
2974
+ var RECIPIENT_PATTERNS = {
2975
+ solana: /^[1-9A-HJ-NP-Za-km-z]{32,44}$/,
2976
+ tron: /^T[1-9A-HJ-NP-Za-km-z]{33}$/,
2977
+ stellar: /^G[A-Z2-7]{55}$/
2978
+ };
2979
+ var RECIPIENT_HINTS = {
2980
+ solana: "A Solana destination needs a base58 recipient address.",
2981
+ tron: "A Tron destination needs a base58 recipient address starting with T.",
2982
+ stellar: "A Stellar destination needs a recipient account ID starting with G."
2983
+ };
2984
+ function recipientNamespace(targetChain) {
2985
+ return targetChainToCaip2(targetChain).split(":")[0] ?? "";
2986
+ }
1664
2987
  function recipientMatchesTarget(recipient, targetChain) {
1665
- return targetChainToCaip2(targetChain).startsWith("solana:") ? SOLANA_ADDRESS_PATTERN.test(recipient) : isAddress(recipient);
2988
+ const pattern = RECIPIENT_PATTERNS[recipientNamespace(targetChain)];
2989
+ return pattern ? pattern.test(recipient) : isAddress(recipient);
1666
2990
  }
1667
2991
  function deriveAccountSalt(input) {
1668
2992
  return keccak256(
@@ -1716,7 +3040,7 @@ async function runAccountSetup(input, deps) {
1716
3040
  }
1717
3041
  if (!recipientMatchesTarget(input.recipient, input.targetChain)) {
1718
3042
  throw new SetupError(
1719
- input.targetChain === "solana" ? "A Solana destination needs a base58 recipient address." : "An EVM destination needs a 0x recipient address.",
3043
+ RECIPIENT_HINTS[recipientNamespace(input.targetChain)] ?? "An EVM destination needs a 0x recipient address.",
1720
3044
  "client"
1721
3045
  );
1722
3046
  }
@@ -1798,22 +3122,14 @@ function mapError(error) {
1798
3122
  "network"
1799
3123
  );
1800
3124
  }
1801
- if (error instanceof Error) {
1802
- const statusMatch = error.message.match(/\b(4\d{2}|5\d{2})\b/);
1803
- if (statusMatch) {
1804
- const status = Number(statusMatch[1]);
1805
- if (status >= 500) {
1806
- return new SetupError(
1807
- "Deposit service is temporarily unavailable. Please try again shortly.",
1808
- "server"
1809
- );
1810
- }
1811
- return new SetupError(error.message, "client");
3125
+ if (error instanceof RegistrationError) {
3126
+ if (error.status >= 500) {
3127
+ return new SetupError(
3128
+ "Deposit service is temporarily unavailable. Please try again shortly.",
3129
+ "server"
3130
+ );
1812
3131
  }
1813
- return new SetupError(
1814
- "Deposit service is temporarily unavailable. Please try again shortly.",
1815
- "unknown"
1816
- );
3132
+ return new SetupError(error.message, "client");
1817
3133
  }
1818
3134
  return new SetupError(
1819
3135
  "Deposit service is temporarily unavailable. Please try again shortly.",
@@ -1843,6 +3159,11 @@ export {
1843
3159
  computeIsCacheable,
1844
3160
  readDedupedAccountSetupResult,
1845
3161
  runAccountSetupDeduped,
3162
+ HistoryEntryButton,
3163
+ HistoryOverlay,
3164
+ useHistoryPanel,
1846
3165
  warnRemovedProps,
3166
+ isHistoryEntryVisible,
3167
+ createHistoryAnalytics,
1847
3168
  analyticsTargetProperties
1848
3169
  };