@rhinestone/deposit-modal 0.1.21 → 0.1.22

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.
@@ -0,0 +1,1648 @@
1
+ import {
2
+ CHAIN_BY_ID,
3
+ NATIVE_TOKEN_ADDRESS,
4
+ SUPPORTED_CHAINS,
5
+ getChainIcon,
6
+ getChainName,
7
+ getExplorerTxUrl,
8
+ getSupportedTokenSymbolsForChain,
9
+ getTokenAddress,
10
+ getTokenDecimalsByAddress,
11
+ getTokenSymbol,
12
+ isSupportedTokenAddressForChain
13
+ } from "./chunk-A6QLADED.mjs";
14
+
15
+ // src/components/ui/Modal.tsx
16
+ import {
17
+ useEffect,
18
+ useRef,
19
+ useCallback
20
+ } from "react";
21
+ import { createPortal } from "react-dom";
22
+ import { jsx } from "react/jsx-runtime";
23
+ function getFocusableElements(container) {
24
+ const elements = container.querySelectorAll(
25
+ 'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'
26
+ );
27
+ return Array.from(elements).filter(
28
+ (el) => !el.hasAttribute("disabled") && el.offsetParent !== null
29
+ );
30
+ }
31
+ function Modal({
32
+ isOpen,
33
+ onClose,
34
+ children,
35
+ className = "",
36
+ inline = false
37
+ }) {
38
+ const overlayRef = useRef(null);
39
+ const contentRef = useRef(null);
40
+ const previousActiveElement = useRef(null);
41
+ useEffect(() => {
42
+ if (isOpen) {
43
+ previousActiveElement.current = document.activeElement;
44
+ }
45
+ }, [isOpen]);
46
+ useEffect(() => {
47
+ if (!isOpen && previousActiveElement.current) {
48
+ previousActiveElement.current.focus();
49
+ previousActiveElement.current = null;
50
+ }
51
+ }, [isOpen]);
52
+ useEffect(() => {
53
+ if (isOpen && contentRef.current) {
54
+ const focusable = getFocusableElements(contentRef.current);
55
+ if (focusable.length > 0) {
56
+ focusable[0].focus();
57
+ } else {
58
+ contentRef.current.focus();
59
+ }
60
+ }
61
+ }, [isOpen]);
62
+ useEffect(() => {
63
+ if (isOpen) {
64
+ const originalOverflow = document.body.style.overflow;
65
+ document.body.style.overflow = "hidden";
66
+ return () => {
67
+ document.body.style.overflow = originalOverflow;
68
+ };
69
+ }
70
+ }, [isOpen]);
71
+ const handleKeyDown = useCallback(
72
+ (event) => {
73
+ if (event.key === "Escape") {
74
+ event.preventDefault();
75
+ onClose();
76
+ return;
77
+ }
78
+ if (event.key === "Tab" && contentRef.current) {
79
+ const focusable = getFocusableElements(contentRef.current);
80
+ if (focusable.length === 0) return;
81
+ const firstElement = focusable[0];
82
+ const lastElement = focusable[focusable.length - 1];
83
+ if (event.shiftKey) {
84
+ if (document.activeElement === firstElement) {
85
+ event.preventDefault();
86
+ lastElement.focus();
87
+ }
88
+ } else {
89
+ if (document.activeElement === lastElement) {
90
+ event.preventDefault();
91
+ firstElement.focus();
92
+ }
93
+ }
94
+ }
95
+ },
96
+ [onClose]
97
+ );
98
+ const handleOverlayClick = useCallback(
99
+ (event) => {
100
+ if (event.target === overlayRef.current) {
101
+ onClose();
102
+ }
103
+ },
104
+ [onClose]
105
+ );
106
+ if (!isOpen) return null;
107
+ if (inline) {
108
+ return /* @__PURE__ */ jsx(
109
+ "div",
110
+ {
111
+ ref: contentRef,
112
+ className: `rs-modal-content rs-modal-content--inline ${className}`,
113
+ tabIndex: -1,
114
+ children
115
+ }
116
+ );
117
+ }
118
+ return createPortal(
119
+ /* @__PURE__ */ jsx(
120
+ "div",
121
+ {
122
+ ref: overlayRef,
123
+ className: `rs-modal-overlay ${isOpen ? "rs-modal-overlay--open" : ""}`,
124
+ onClick: handleOverlayClick,
125
+ onKeyDown: handleKeyDown,
126
+ role: "dialog",
127
+ "aria-modal": "true",
128
+ "aria-labelledby": "rs-modal-title",
129
+ children: /* @__PURE__ */ jsx(
130
+ "div",
131
+ {
132
+ ref: contentRef,
133
+ className: `rs-modal-content ${className}`,
134
+ tabIndex: -1,
135
+ children
136
+ }
137
+ )
138
+ }
139
+ ),
140
+ document.body
141
+ );
142
+ }
143
+ Modal.displayName = "Modal";
144
+
145
+ // src/core/deposit-service.ts
146
+ function jsonReplacer(_key, value) {
147
+ return typeof value === "bigint" ? value.toString() : value;
148
+ }
149
+ function createDepositService(baseUrl) {
150
+ const normalizedBaseUrl = baseUrl.replace(/\/$/, "");
151
+ function apiUrl(path) {
152
+ const normalizedPath = path.startsWith("/") ? path : `/${path}`;
153
+ return `${normalizedBaseUrl}${normalizedPath}`;
154
+ }
155
+ return {
156
+ async registerAccount(params) {
157
+ const { eoaAddress, sessionOwner, ...account } = params;
158
+ const response = await fetch(apiUrl("/register"), {
159
+ method: "POST",
160
+ headers: { "Content-Type": "application/json" },
161
+ body: JSON.stringify(
162
+ {
163
+ account,
164
+ eoaAddress,
165
+ sessionOwner
166
+ },
167
+ jsonReplacer
168
+ )
169
+ });
170
+ if (!response.ok) {
171
+ const error = await response.json().catch(() => ({ error: "Unknown error" }));
172
+ throw new Error(
173
+ error.error || `Registration failed: ${response.status}`
174
+ );
175
+ }
176
+ return response.json();
177
+ },
178
+ async checkAccount(address) {
179
+ const response = await fetch(apiUrl(`/check/${address}`), {
180
+ method: "GET",
181
+ headers: { "Content-Type": "application/json" }
182
+ });
183
+ if (!response.ok) {
184
+ const error = await response.json().catch(() => ({ error: "Unknown error" }));
185
+ throw new Error(error.error || `Check failed: ${response.status}`);
186
+ }
187
+ return response.json();
188
+ },
189
+ async fetchPortfolio(address) {
190
+ const response = await fetch(apiUrl(`/portfolio/${address}`), {
191
+ method: "GET",
192
+ headers: { "Content-Type": "application/json" }
193
+ });
194
+ if (!response.ok) {
195
+ const error = await response.json().catch(() => ({ error: "Unknown error" }));
196
+ throw new Error(
197
+ error.error || `Portfolio fetch failed: ${response.status}`
198
+ );
199
+ }
200
+ const data = await response.json();
201
+ const direct = normalizeDirectPortfolio(data);
202
+ if (direct.tokens.length > 0) {
203
+ return direct;
204
+ }
205
+ const portfolioData = extractOrchestratorPortfolio(data);
206
+ if (portfolioData) {
207
+ return normalizeOrchestratorPortfolio(portfolioData);
208
+ }
209
+ return { tokens: [], totalUsd: 0 };
210
+ },
211
+ async fetchStatus(address, txHash) {
212
+ const txHashParam = encodeURIComponent(txHash.toLowerCase());
213
+ const response = await fetch(
214
+ apiUrl(`/status/${address}?txHash=${txHashParam}`),
215
+ {
216
+ method: "GET",
217
+ headers: { "Content-Type": "application/json" },
218
+ cache: "no-store"
219
+ }
220
+ );
221
+ if (!response.ok) {
222
+ return { lastEvent: void 0 };
223
+ }
224
+ return response.json();
225
+ },
226
+ async fetchLatestStatus(address) {
227
+ const response = await fetch(apiUrl(`/status/${address}`), {
228
+ method: "GET",
229
+ headers: { "Content-Type": "application/json" },
230
+ cache: "no-store"
231
+ });
232
+ if (!response.ok) {
233
+ return { lastEvent: void 0 };
234
+ }
235
+ return response.json();
236
+ }
237
+ };
238
+ }
239
+ function normalizeDirectPortfolio(data) {
240
+ const rawTokens = extractArray(data, "tokens") ?? extractArray(
241
+ data?.data,
242
+ "tokens"
243
+ ) ?? [];
244
+ const totalUsd = extractNumber(data, "totalUsd") ?? extractNumber(data?.data, "totalUsd") ?? 0;
245
+ const tokens = rawTokens.map((token) => normalizeDirectToken(token)).filter((token) => Boolean(token));
246
+ return { tokens, totalUsd };
247
+ }
248
+ function extractOrchestratorPortfolio(data) {
249
+ const portfolio = extractArray(data, "portfolio") ?? extractArray(
250
+ data?.data,
251
+ "portfolio"
252
+ );
253
+ if (!portfolio || !Array.isArray(portfolio)) return null;
254
+ return { portfolio };
255
+ }
256
+ function normalizeOrchestratorPortfolio(data) {
257
+ const tokens = [];
258
+ for (const tokenData of data.portfolio || []) {
259
+ const chainBalances = tokenData.tokenChainBalance ?? tokenData.chainBalances ?? [];
260
+ for (const chainBalance of chainBalances) {
261
+ const unlocked = chainBalance.balance?.unlocked ?? "0";
262
+ const normalizedName = tokenData.tokenName.trim();
263
+ const isNativeSymbol = normalizedName.toUpperCase() === "ETH" || normalizedName.toUpperCase() === "ETHER";
264
+ const tokenAddress = chainBalance.tokenAddress ?? extractTokenAddress(tokenData, chainBalance.chainId) ?? getTokenAddress(tokenData.tokenName, chainBalance.chainId);
265
+ const resolvedTokenAddress = isNativeSymbol ? NATIVE_TOKEN_ADDRESS : tokenAddress;
266
+ if (!resolvedTokenAddress) {
267
+ continue;
268
+ }
269
+ if (!isSupportedTokenAddressForChain(
270
+ resolvedTokenAddress,
271
+ chainBalance.chainId
272
+ )) {
273
+ continue;
274
+ }
275
+ const symbol = getTokenSymbol(resolvedTokenAddress, chainBalance.chainId);
276
+ tokens.push({
277
+ chainId: chainBalance.chainId,
278
+ address: resolvedTokenAddress,
279
+ symbol,
280
+ name: symbol,
281
+ decimals: getTokenDecimalsByAddress(
282
+ resolvedTokenAddress,
283
+ chainBalance.chainId
284
+ ),
285
+ balance: unlocked,
286
+ balanceUsd: 0
287
+ });
288
+ }
289
+ }
290
+ return {
291
+ tokens,
292
+ totalUsd: 0
293
+ };
294
+ }
295
+ function normalizeDirectToken(token) {
296
+ const chainId = extractNumber(token, "chainId") ?? extractNumber(token.chain, "id");
297
+ if (!chainId) return null;
298
+ const symbol = extractString(token, "symbol") ?? extractString(token, "tokenSymbol") ?? extractString(token, "tokenName") ?? extractString(token, "name");
299
+ if (!symbol) return null;
300
+ const balanceValue = extractString(token, "balance") ?? extractString(token, "amount") ?? extractString(token, "value") ?? extractString(token, "rawBalance") ?? extractNumber(token, "balance")?.toString() ?? extractNumber(token, "amount")?.toString() ?? extractNumber(token, "value")?.toString() ?? extractNumber(token, "rawBalance")?.toString();
301
+ if (!balanceValue) return null;
302
+ const address = extractString(token, "address") ?? extractString(token, "tokenAddress") ?? extractString(
303
+ token.token,
304
+ "address"
305
+ ) ?? getTokenAddress(symbol, chainId);
306
+ if (!address) return null;
307
+ const addressAsToken = address;
308
+ if (!isSupportedTokenAddressForChain(addressAsToken, chainId)) return null;
309
+ const balanceUsd = extractNumber(token, "balanceUsd") ?? extractNumber(token, "usdValue") ?? extractNumber(token, "valueUsd") ?? extractNumericString(token, "balanceUsd") ?? extractNumericString(token, "usdValue") ?? extractNumericString(token, "valueUsd") ?? 0;
310
+ return {
311
+ chainId,
312
+ address: addressAsToken,
313
+ symbol: getTokenSymbol(addressAsToken, chainId),
314
+ name: getTokenSymbol(addressAsToken, chainId),
315
+ decimals: getTokenDecimalsByAddress(addressAsToken, chainId),
316
+ balance: balanceValue,
317
+ balanceUsd
318
+ };
319
+ }
320
+ function extractTokenAddress(tokenData, chainId) {
321
+ const token = tokenData;
322
+ return token.tokenAddress ?? token.address ?? token.addresses?.[chainId] ?? token.token?.address ?? token.token?.addresses?.[chainId];
323
+ }
324
+ function extractArray(data, key) {
325
+ if (!data || typeof data !== "object") return null;
326
+ const record = data;
327
+ const value = record[key];
328
+ return Array.isArray(value) ? value : null;
329
+ }
330
+ function extractNumber(data, key) {
331
+ if (!data || typeof data !== "object") return null;
332
+ const record = data;
333
+ const value = record[key];
334
+ return typeof value === "number" ? value : null;
335
+ }
336
+ function extractString(data, key) {
337
+ if (!data || typeof data !== "object") return null;
338
+ const record = data;
339
+ const value = record[key];
340
+ return typeof value === "string" ? value : null;
341
+ }
342
+ function extractNumericString(data, key) {
343
+ const value = extractString(data, key);
344
+ if (!value) return null;
345
+ const parsed = Number(value);
346
+ return Number.isFinite(parsed) ? parsed : null;
347
+ }
348
+ function getAssetId(asset) {
349
+ return `${asset.chainId}:${asset.token.toLowerCase()}`;
350
+ }
351
+ function portfolioTokenToAsset(token) {
352
+ return {
353
+ id: getAssetId({ chainId: token.chainId, token: token.address }),
354
+ chainId: token.chainId,
355
+ token: token.address,
356
+ symbol: token.symbol,
357
+ name: token.name,
358
+ decimals: token.decimals,
359
+ balance: token.balance,
360
+ balanceUsd: token.balanceUsd
361
+ };
362
+ }
363
+ function portfolioToAssets(tokens) {
364
+ return tokens.map(portfolioTokenToAsset).sort((a, b) => {
365
+ const balanceA = safeBigInt(a.balance);
366
+ const balanceB = safeBigInt(b.balance);
367
+ if (balanceB > balanceA) return 1;
368
+ if (balanceB < balanceA) return -1;
369
+ return 0;
370
+ });
371
+ }
372
+ function safeBigInt(value) {
373
+ if (!value) return BigInt(0);
374
+ try {
375
+ return BigInt(value);
376
+ } catch {
377
+ return BigInt(0);
378
+ }
379
+ }
380
+ function isNativeAsset(asset) {
381
+ return asset.token.toLowerCase() === "0x0000000000000000000000000000000000000000";
382
+ }
383
+
384
+ // src/core/formatters.ts
385
+ var currencyFormatter = new Intl.NumberFormat("en-US", {
386
+ style: "currency",
387
+ currency: "USD",
388
+ maximumFractionDigits: 2
389
+ });
390
+ var tokenFormatter = new Intl.NumberFormat("en-US", {
391
+ maximumFractionDigits: 6
392
+ });
393
+ function formatUserError(raw) {
394
+ const lower = raw.toLowerCase();
395
+ if (lower.includes("user rejected") || lower.includes("user denied")) {
396
+ return "Transaction cancelled";
397
+ }
398
+ if (lower.includes("insufficient funds")) {
399
+ return "Insufficient funds for this transaction";
400
+ }
401
+ if (lower.includes("nonce too low") || lower.includes("nonce too high")) {
402
+ return "Transaction conflict \u2014 please try again";
403
+ }
404
+ if (lower.includes("execution reverted")) {
405
+ return "Transaction would fail on-chain";
406
+ }
407
+ if (lower.includes("network") || lower.includes("disconnected")) {
408
+ return "Network error \u2014 check your connection";
409
+ }
410
+ const detailsCut = raw.indexOf("\n\nRequest Arguments:");
411
+ if (detailsCut !== -1) {
412
+ const short = raw.slice(0, detailsCut).trim();
413
+ return short.length > 80 ? short.slice(0, 80) + "..." : short;
414
+ }
415
+ if (raw.length > 80) {
416
+ return raw.slice(0, 80) + "...";
417
+ }
418
+ return raw;
419
+ }
420
+
421
+ // src/core/theme.ts
422
+ var RADIUS_VALUES = {
423
+ none: "0",
424
+ sm: "8px",
425
+ md: "10px",
426
+ lg: "14px",
427
+ full: "9999px"
428
+ };
429
+ function applyTheme(element, theme) {
430
+ if (!element) return;
431
+ if (theme?.mode) {
432
+ element.setAttribute("data-theme", theme.mode);
433
+ } else {
434
+ element.removeAttribute("data-theme");
435
+ }
436
+ if (theme?.fontColor) {
437
+ element.style.setProperty("--rs-foreground", theme.fontColor);
438
+ }
439
+ if (theme?.iconColor) {
440
+ element.style.setProperty("--rs-icon", theme.iconColor);
441
+ }
442
+ if (theme?.ctaColor) {
443
+ element.style.setProperty("--rs-primary", theme.ctaColor);
444
+ element.style.setProperty("--rs-border-accent", theme.ctaColor);
445
+ element.style.setProperty(
446
+ "--rs-primary-hover",
447
+ theme.ctaHoverColor ?? theme.ctaColor
448
+ );
449
+ } else if (theme?.ctaHoverColor) {
450
+ element.style.setProperty("--rs-primary-hover", theme.ctaHoverColor);
451
+ }
452
+ if (theme?.borderColor) {
453
+ element.style.setProperty("--rs-border", theme.borderColor);
454
+ element.style.setProperty("--rs-border-surface", theme.borderColor);
455
+ }
456
+ if (theme?.backgroundColor) {
457
+ element.style.setProperty("--rs-background", theme.backgroundColor);
458
+ }
459
+ if (theme?.radius) {
460
+ element.style.setProperty("--rs-radius", RADIUS_VALUES[theme.radius]);
461
+ }
462
+ }
463
+
464
+ // src/components/ui/Spinner.tsx
465
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
466
+ function Spinner({ className }) {
467
+ return /* @__PURE__ */ jsxs(
468
+ "svg",
469
+ {
470
+ className: `rs-spinner ${className || ""}`,
471
+ fill: "none",
472
+ viewBox: "0 0 20 21",
473
+ children: [
474
+ /* @__PURE__ */ jsx2(
475
+ "path",
476
+ {
477
+ d: "M10 0.5C8.02219 0.5 6.08879 1.08649 4.4443 2.1853C2.79981 3.28412 1.51809 4.8459 0.761209 6.67316C0.00433288 8.50043 -0.1937 10.5111 0.192152 12.4509C0.578004 14.3907 1.53041 16.1725 2.92894 17.5711C4.32746 18.9696 6.10929 19.922 8.0491 20.3078C9.98891 20.6937 11.9996 20.4957 13.8268 19.7388C15.6541 18.9819 17.2159 17.7002 18.3147 16.0557C19.4135 14.4112 20 12.4778 20 10.5C20 7.84783 18.9464 5.3043 17.0711 3.42893C15.1957 1.55357 12.6522 0.5 10 0.5ZM10 17.7727C8.56159 17.7727 7.15549 17.3462 5.95949 16.547C4.7635 15.7479 3.83134 14.6121 3.28088 13.2831C2.73042 11.9542 2.5864 10.4919 2.86702 9.08116C3.14764 7.67039 3.8403 6.37451 4.85741 5.3574C5.87452 4.3403 7.17039 3.64764 8.58116 3.36702C9.99193 3.0864 11.4542 3.23042 12.7832 3.78088C14.1121 4.33133 15.2479 5.26349 16.0471 6.45949C16.8462 7.65548 17.2727 9.06159 17.2727 10.5C17.2727 12.4288 16.5065 14.2787 15.1426 15.6426C13.7787 17.0065 11.9288 17.7727 10 17.7727Z",
478
+ fill: "currentColor",
479
+ opacity: 0.3
480
+ }
481
+ ),
482
+ /* @__PURE__ */ jsx2(
483
+ "path",
484
+ {
485
+ d: "M10 3.22767C11.7423 3.22846 13.4276 3.8412 14.7556 4.95667C16.0837 6.07214 16.9681 7.61784 17.2512 9.31825C17.3012 9.64364 17.4662 9.94096 17.7169 10.1573C17.9677 10.3737 18.2878 10.4951 18.6205 10.5C18.8211 10.5001 19.0193 10.457 19.2012 10.3735C19.3832 10.2901 19.5445 10.1684 19.674 10.017C19.8036 9.86549 19.8981 9.68789 19.9511 9.49656C20.004 9.30523 20.0141 9.10478 19.9807 8.90918C19.5986 6.56305 18.3843 4.42821 16.5554 2.88726C14.7265 1.34631 12.4025 0.5 10 0.5C7.59751 0.5 5.27354 1.34631 3.44461 2.88726C1.61569 4.42821 0.401366 6.56305 0.0192815 8.90918C-0.0141442 9.10478 -0.00402016 9.30523 0.0489472 9.49656C0.101914 9.68789 0.196449 9.86549 0.325956 10.017C0.455463 10.1684 0.616823 10.2901 0.798778 10.3735C0.980732 10.457 1.1789 10.5001 1.37945 10.5C1.71216 10.4951 2.03235 10.3737 2.28307 10.1573C2.5338 9.94096 2.69883 9.64364 2.74882 9.31825C3.03193 7.61784 3.91633 6.07214 5.24436 4.95667C6.57239 3.8412 8.25775 3.22846 10 3.22767Z",
486
+ fill: "currentColor"
487
+ }
488
+ )
489
+ ]
490
+ }
491
+ );
492
+ }
493
+
494
+ // src/components/ui/Button.tsx
495
+ import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
496
+ function Button({
497
+ children,
498
+ variant = "accent",
499
+ size = "default",
500
+ loading = false,
501
+ fullWidth = false,
502
+ disabled,
503
+ className = "",
504
+ ...props
505
+ }) {
506
+ const classes = [
507
+ "rs-button",
508
+ `rs-button--${variant}`,
509
+ `rs-button--size-${size}`,
510
+ fullWidth ? "rs-button--full-width" : "",
511
+ className
512
+ ].filter(Boolean).join(" ");
513
+ return /* @__PURE__ */ jsxs2(
514
+ "button",
515
+ {
516
+ className: classes,
517
+ disabled: disabled || loading,
518
+ "aria-busy": loading || void 0,
519
+ ...props,
520
+ children: [
521
+ /* @__PURE__ */ jsx3("span", { className: loading ? "rs-button__content--hidden" : "", children }),
522
+ loading && /* @__PURE__ */ jsx3("span", { className: "rs-button__spinner", children: /* @__PURE__ */ jsx3(Spinner, { className: "rs-spinner--sm" }) })
523
+ ]
524
+ }
525
+ );
526
+ }
527
+ Button.displayName = "Button";
528
+
529
+ // src/components/ui/Icons.tsx
530
+ import { jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
531
+ function WalletIcon() {
532
+ return /* @__PURE__ */ jsxs3("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
533
+ /* @__PURE__ */ jsx4(
534
+ "rect",
535
+ {
536
+ x: "3",
537
+ y: "6",
538
+ width: "18",
539
+ height: "13",
540
+ rx: "2",
541
+ strokeLinecap: "round",
542
+ strokeLinejoin: "round"
543
+ }
544
+ ),
545
+ /* @__PURE__ */ jsx4(
546
+ "path",
547
+ {
548
+ d: "M16 12.5a1 1 0 100-2 1 1 0 000 2z",
549
+ fill: "currentColor",
550
+ stroke: "none"
551
+ }
552
+ ),
553
+ /* @__PURE__ */ jsx4("path", { d: "M3 10h18", strokeLinecap: "round" })
554
+ ] });
555
+ }
556
+ function ExternalLinkIcon() {
557
+ return /* @__PURE__ */ jsxs3("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
558
+ /* @__PURE__ */ jsx4(
559
+ "path",
560
+ {
561
+ d: "M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5",
562
+ strokeLinecap: "round",
563
+ strokeLinejoin: "round"
564
+ }
565
+ ),
566
+ /* @__PURE__ */ jsx4("path", { d: "M15 3h6v6", strokeLinecap: "round", strokeLinejoin: "round" }),
567
+ /* @__PURE__ */ jsx4("path", { d: "M10 14L21 3", strokeLinecap: "round", strokeLinejoin: "round" })
568
+ ] });
569
+ }
570
+ function TransferIcon() {
571
+ return /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: /* @__PURE__ */ jsx4(
572
+ "path",
573
+ {
574
+ d: "M7.5 21L3 16.5m0 0L7.5 12M3 16.5h13.5m0-9L21 12m0 0l-4.5 4.5M21 12H7.5",
575
+ strokeLinecap: "round",
576
+ strokeLinejoin: "round"
577
+ }
578
+ ) });
579
+ }
580
+ function CheckIcon() {
581
+ return /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", children: /* @__PURE__ */ jsx4(
582
+ "path",
583
+ {
584
+ d: "M5 13l4 4L19 7",
585
+ strokeLinecap: "round",
586
+ strokeLinejoin: "round"
587
+ }
588
+ ) });
589
+ }
590
+ function ChevronRightIcon() {
591
+ return /* @__PURE__ */ jsx4("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", children: /* @__PURE__ */ jsx4(
592
+ "path",
593
+ {
594
+ d: "M9 5l7 7-7 7",
595
+ strokeLinecap: "round",
596
+ strokeLinejoin: "round"
597
+ }
598
+ ) });
599
+ }
600
+
601
+ // src/components/steps/ConnectStep.tsx
602
+ import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
603
+ function rowIcon(kind) {
604
+ if (kind === "connected") return /* @__PURE__ */ jsx5(WalletIcon, {});
605
+ return /* @__PURE__ */ jsx5(ExternalLinkIcon, {});
606
+ }
607
+ function ConnectStep({
608
+ walletOptions,
609
+ selectedAddress,
610
+ onSelectAddress,
611
+ onSelectTransferCrypto,
612
+ onRequestConnect,
613
+ onConnect,
614
+ onContinue,
615
+ continueButtonLabel = "Continue",
616
+ connectButtonLabel = "Connect external wallet"
617
+ }) {
618
+ const hasWalletOptions = (walletOptions?.length ?? 0) > 0;
619
+ if (hasWalletOptions) {
620
+ const hasExternalWallet = walletOptions?.some((option) => option.kind === "external") ?? false;
621
+ const showConnectDifferentWalletOption = Boolean(onConnect) && !hasExternalWallet;
622
+ return /* @__PURE__ */ jsxs4("div", { className: "rs-step", children: [
623
+ /* @__PURE__ */ jsxs4("div", { className: "rs-connect-centered rs-connect-centered--wallets", children: [
624
+ /* @__PURE__ */ jsxs4("div", { className: "rs-connect-wallet-list", children: [
625
+ walletOptions?.map((option) => {
626
+ const isSelected = option.address.toLowerCase() === (selectedAddress ?? "").toLowerCase();
627
+ const shortAddress = `${option.address.slice(0, 6)}...${option.address.slice(-4)}`;
628
+ return /* @__PURE__ */ jsxs4(
629
+ "button",
630
+ {
631
+ type: "button",
632
+ className: `rs-connect-wallet-row ${isSelected ? "rs-connect-wallet-row--selected" : ""}`,
633
+ onClick: () => onSelectAddress?.(option.address),
634
+ children: [
635
+ /* @__PURE__ */ jsx5(
636
+ "div",
637
+ {
638
+ className: `rs-connect-wallet-icon ${isSelected ? "rs-connect-wallet-icon--selected" : ""}`,
639
+ children: rowIcon(option.kind)
640
+ }
641
+ ),
642
+ /* @__PURE__ */ jsxs4("div", { className: "rs-connect-wallet-meta", children: [
643
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-label", children: option.label }),
644
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-address", children: shortAddress })
645
+ ] }),
646
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-indicator", children: isSelected ? /* @__PURE__ */ jsx5(CheckIcon, {}) : /* @__PURE__ */ jsx5(ChevronRightIcon, {}) })
647
+ ]
648
+ },
649
+ `${option.label}-${option.address}`
650
+ );
651
+ }),
652
+ showConnectDifferentWalletOption && /* @__PURE__ */ jsxs4(
653
+ "button",
654
+ {
655
+ type: "button",
656
+ className: "rs-connect-wallet-row rs-connect-wallet-row--action",
657
+ onClick: onConnect,
658
+ children: [
659
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-icon rs-connect-wallet-icon--action", children: /* @__PURE__ */ jsx5(ExternalLinkIcon, {}) }),
660
+ /* @__PURE__ */ jsxs4("div", { className: "rs-connect-wallet-meta", children: [
661
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-label", children: "External Wallet" }),
662
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-address", children: "Connect different wallet" })
663
+ ] }),
664
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-indicator", children: /* @__PURE__ */ jsx5(ChevronRightIcon, {}) })
665
+ ]
666
+ }
667
+ ),
668
+ onSelectTransferCrypto && /* @__PURE__ */ jsxs4(
669
+ "button",
670
+ {
671
+ type: "button",
672
+ className: "rs-connect-wallet-row rs-connect-wallet-row--action",
673
+ onClick: onSelectTransferCrypto,
674
+ children: [
675
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-icon rs-connect-wallet-icon--action", children: /* @__PURE__ */ jsx5(TransferIcon, {}) }),
676
+ /* @__PURE__ */ jsxs4("div", { className: "rs-connect-wallet-meta", children: [
677
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-label", children: "Transfer Crypto" }),
678
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-address", children: "Deposit via QR code" })
679
+ ] }),
680
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-wallet-indicator", children: /* @__PURE__ */ jsx5(ChevronRightIcon, {}) })
681
+ ]
682
+ }
683
+ )
684
+ ] }),
685
+ onConnect && walletOptions?.some((option) => option.kind === "external") && /* @__PURE__ */ jsx5(
686
+ "button",
687
+ {
688
+ type: "button",
689
+ className: "rs-connect-wallet-manage",
690
+ onClick: onConnect,
691
+ children: "Disconnect Wallet"
692
+ }
693
+ )
694
+ ] }),
695
+ /* @__PURE__ */ jsx5("div", { className: "rs-step-footer rs-step-footer--connect-empty", children: /* @__PURE__ */ jsx5(
696
+ Button,
697
+ {
698
+ onClick: onContinue,
699
+ variant: "accent",
700
+ fullWidth: true,
701
+ disabled: !selectedAddress || !onContinue,
702
+ children: continueButtonLabel
703
+ }
704
+ ) })
705
+ ] });
706
+ }
707
+ const handleConnect = onConnect ?? onRequestConnect;
708
+ return /* @__PURE__ */ jsxs4("div", { className: "rs-step", children: [
709
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-centered rs-connect-centered--minimal", children: /* @__PURE__ */ jsxs4("div", { className: "rs-connect-empty", children: [
710
+ /* @__PURE__ */ jsxs4("div", { className: "rs-connect-empty-graphic", "aria-hidden": "true", children: [
711
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-empty-orbit rs-connect-empty-orbit--outer" }),
712
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-empty-orbit rs-connect-empty-orbit--inner" }),
713
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-empty-core", children: /* @__PURE__ */ jsxs4(
714
+ "svg",
715
+ {
716
+ viewBox: "0 0 24 24",
717
+ fill: "none",
718
+ stroke: "currentColor",
719
+ strokeWidth: "1.6",
720
+ children: [
721
+ /* @__PURE__ */ jsx5(
722
+ "path",
723
+ {
724
+ strokeLinecap: "round",
725
+ strokeLinejoin: "round",
726
+ d: "M4 8.25A2.25 2.25 0 016.25 6h11.5A2.25 2.25 0 0120 8.25v7.5A2.25 2.25 0 0117.75 18H6.25A2.25 2.25 0 014 15.75v-7.5z"
727
+ }
728
+ ),
729
+ /* @__PURE__ */ jsx5(
730
+ "path",
731
+ {
732
+ strokeLinecap: "round",
733
+ strokeLinejoin: "round",
734
+ d: "M20 10.5h-3.75a2.25 2.25 0 100 4.5H20"
735
+ }
736
+ ),
737
+ /* @__PURE__ */ jsx5("circle", { cx: "16.25", cy: "12.75", r: "0.85", fill: "currentColor" })
738
+ ]
739
+ }
740
+ ) }),
741
+ /* @__PURE__ */ jsx5("span", { className: "rs-connect-empty-dot rs-connect-empty-dot--left" }),
742
+ /* @__PURE__ */ jsx5("span", { className: "rs-connect-empty-dot rs-connect-empty-dot--right" })
743
+ ] }),
744
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-empty-title", children: "No wallet connected" }),
745
+ /* @__PURE__ */ jsx5("div", { className: "rs-connect-empty-subtitle", children: "Connect an external wallet to continue." })
746
+ ] }) }),
747
+ /* @__PURE__ */ jsxs4("div", { className: "rs-step-footer rs-step-footer--connect-empty", children: [
748
+ /* @__PURE__ */ jsx5(
749
+ Button,
750
+ {
751
+ onClick: handleConnect,
752
+ variant: "accent",
753
+ fullWidth: true,
754
+ disabled: !handleConnect,
755
+ children: connectButtonLabel
756
+ }
757
+ ),
758
+ onSelectTransferCrypto && /* @__PURE__ */ jsx5(
759
+ "button",
760
+ {
761
+ type: "button",
762
+ className: "rs-connect-transfer-link",
763
+ onClick: onSelectTransferCrypto,
764
+ children: "Or deposit via QR code"
765
+ }
766
+ )
767
+ ] })
768
+ ] });
769
+ }
770
+ ConnectStep.displayName = "ConnectStep";
771
+
772
+ // src/core/account.ts
773
+ import {
774
+ RhinestoneSDK
775
+ } from "@rhinestone/sdk";
776
+ import { zeroAddress } from "viem";
777
+ import { toAccount } from "viem/accounts";
778
+ function createViewOnlyAccount(address) {
779
+ if (!address || address === zeroAddress) {
780
+ throw new Error("Address is required");
781
+ }
782
+ return toAccount({
783
+ address,
784
+ signMessage: async () => {
785
+ throw new Error("Account is view-only");
786
+ },
787
+ signTransaction: async () => {
788
+ throw new Error("Account is view-only");
789
+ },
790
+ signTypedData: async () => {
791
+ throw new Error("Account is view-only");
792
+ }
793
+ });
794
+ }
795
+ function getSessionSignerAccount(signerAddress) {
796
+ if (!signerAddress || signerAddress === zeroAddress) {
797
+ throw new Error("Signer address is required");
798
+ }
799
+ return toAccount({
800
+ address: signerAddress,
801
+ signMessage: async () => {
802
+ throw new Error("Session signer is view-only");
803
+ },
804
+ signTransaction: async () => {
805
+ throw new Error("Session signer is view-only");
806
+ },
807
+ signTypedData: async () => {
808
+ throw new Error("Session signer is view-only");
809
+ }
810
+ });
811
+ }
812
+ function buildSession(chain, signerAddress) {
813
+ const sessionSignerAccount = getSessionSignerAccount(signerAddress);
814
+ return {
815
+ owners: {
816
+ type: "ecdsa",
817
+ accounts: [sessionSignerAccount]
818
+ },
819
+ chain
820
+ };
821
+ }
822
+ async function createSmartAccount(userSigner, sessionSigner, sdkApiKey) {
823
+ const rhinestone = new RhinestoneSDK({
824
+ apiKey: sdkApiKey ?? ""
825
+ });
826
+ const ownerAccounts = sessionSigner ? [userSigner, sessionSigner] : [userSigner];
827
+ const config = {
828
+ account: {
829
+ type: "nexus"
830
+ },
831
+ owners: {
832
+ type: "ecdsa",
833
+ accounts: ownerAccounts,
834
+ ...sessionSigner ? { threshold: 1 } : {}
835
+ },
836
+ experimental_sessions: {
837
+ enabled: true
838
+ }
839
+ };
840
+ const account = await rhinestone.createAccount(config);
841
+ return account;
842
+ }
843
+ function getAccountAddress(account) {
844
+ return account.getAddress();
845
+ }
846
+ function getAccountInitData(account) {
847
+ const { factory, factoryData } = account.getInitData();
848
+ if (!factory) {
849
+ throw new Error("Account init data is not available");
850
+ }
851
+ return {
852
+ factory,
853
+ factoryData
854
+ };
855
+ }
856
+ async function signEnableSessionWithOwner(rhinestoneAccount, sessionDetails, signer) {
857
+ const originalOwners = rhinestoneAccount.config.owners;
858
+ rhinestoneAccount.config.owners = {
859
+ type: "ecdsa",
860
+ accounts: [signer],
861
+ threshold: 1,
862
+ ...originalOwners?.type === "ecdsa" && originalOwners.module ? { module: originalOwners.module } : {}
863
+ };
864
+ try {
865
+ return await rhinestoneAccount.experimental_signEnableSession(
866
+ sessionDetails
867
+ );
868
+ } finally {
869
+ rhinestoneAccount.config.owners = originalOwners;
870
+ }
871
+ }
872
+ async function getSessionDetails(rhinestoneAccount, targetChain, signerAddress, sessionSigner, targetToken, sessionChainIds) {
873
+ const isTargetTestnet = Boolean(targetChain.testnet);
874
+ const chainsByNetworkType = SUPPORTED_CHAINS.filter(
875
+ (chain) => Boolean(chain.testnet) === isTargetTestnet
876
+ );
877
+ const chainsById = new Map(
878
+ chainsByNetworkType.map((chain) => [chain.id, chain])
879
+ );
880
+ let selectedChains = [...chainsByNetworkType];
881
+ if (sessionChainIds && sessionChainIds.length > 0) {
882
+ const selectedByCaller = [];
883
+ for (const chainId of sessionChainIds) {
884
+ const chain = chainsById.get(chainId);
885
+ if (chain) {
886
+ selectedByCaller.push(chain);
887
+ }
888
+ }
889
+ if (selectedByCaller.length > 0) {
890
+ selectedChains = selectedByCaller;
891
+ }
892
+ }
893
+ if (targetToken) {
894
+ const targetSymbol = getTokenSymbol(
895
+ targetToken,
896
+ targetChain.id
897
+ ).toUpperCase();
898
+ if (targetSymbol && targetSymbol !== "TOKEN") {
899
+ const chainsForToken = selectedChains.filter(
900
+ (chain) => getSupportedTokenSymbolsForChain(chain.id).includes(targetSymbol)
901
+ );
902
+ if (chainsForToken.length > 0) {
903
+ selectedChains = chainsForToken;
904
+ }
905
+ }
906
+ }
907
+ if (!selectedChains.some((c) => c.id === targetChain.id)) {
908
+ selectedChains.push(targetChain);
909
+ }
910
+ const uniqueChains = Array.from(
911
+ new Map(selectedChains.map((chain) => [chain.id, chain])).values()
912
+ );
913
+ const sessions = uniqueChains.map(
914
+ (chain) => buildSession(chain, signerAddress)
915
+ );
916
+ const sessionDetails = await rhinestoneAccount.experimental_getSessionDetails(sessions);
917
+ const enableSignature = sessionSigner ? await signEnableSessionWithOwner(
918
+ rhinestoneAccount,
919
+ sessionDetails,
920
+ sessionSigner
921
+ ) : await rhinestoneAccount.experimental_signEnableSession(sessionDetails);
922
+ if (!sessionDetails.hashesAndChainIds?.length) {
923
+ throw new Error("Session details missing chain digests");
924
+ }
925
+ return {
926
+ hashesAndChainIds: sessionDetails.hashesAndChainIds,
927
+ signature: enableSignature
928
+ };
929
+ }
930
+
931
+ // src/core/session-owner.ts
932
+ import { isAddress } from "viem";
933
+ import {
934
+ generatePrivateKey,
935
+ privateKeyToAccount
936
+ } from "viem/accounts";
937
+ var STORAGE_PREFIX = "rhinestone:session-owner";
938
+ function storageKey(eoaAddress) {
939
+ return `${STORAGE_PREFIX}:${eoaAddress.toLowerCase()}`;
940
+ }
941
+ function loadSessionOwnerFromStorage(eoaAddress) {
942
+ if (typeof window === "undefined") return null;
943
+ const raw = window.localStorage.getItem(storageKey(eoaAddress));
944
+ if (!raw) return null;
945
+ try {
946
+ const parsed = JSON.parse(raw);
947
+ if (!parsed.privateKey) return null;
948
+ const account = privateKeyToAccount(parsed.privateKey);
949
+ return {
950
+ privateKey: parsed.privateKey,
951
+ address: account.address
952
+ };
953
+ } catch {
954
+ return null;
955
+ }
956
+ }
957
+ function saveSessionOwnerToStorage(eoaAddress, privateKey, address) {
958
+ if (typeof window === "undefined") return;
959
+ if (!isAddress(address)) return;
960
+ const payload = {
961
+ privateKey,
962
+ address,
963
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
964
+ };
965
+ window.localStorage.setItem(storageKey(eoaAddress), JSON.stringify(payload));
966
+ }
967
+ function createSessionOwnerKey() {
968
+ const privateKey = generatePrivateKey();
969
+ const account = privateKeyToAccount(privateKey);
970
+ return {
971
+ privateKey,
972
+ account,
973
+ address: account.address
974
+ };
975
+ }
976
+ function accountFromPrivateKey(privateKey) {
977
+ return privateKeyToAccount(privateKey);
978
+ }
979
+
980
+ // src/components/steps/ProcessingStep.tsx
981
+ import { useState, useEffect as useEffect2, useRef as useRef2 } from "react";
982
+ import { formatUnits } from "viem";
983
+
984
+ // src/components/ui/PoweredBy.tsx
985
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
986
+ function PoweredBy() {
987
+ return /* @__PURE__ */ jsxs5("div", { className: "rs-powered-by", children: [
988
+ /* @__PURE__ */ jsx6(
989
+ "svg",
990
+ {
991
+ viewBox: "0 0 24 24",
992
+ fill: "none",
993
+ stroke: "currentColor",
994
+ strokeWidth: "2",
995
+ children: /* @__PURE__ */ jsx6(
996
+ "path",
997
+ {
998
+ strokeLinecap: "round",
999
+ strokeLinejoin: "round",
1000
+ d: "M9 12.75L11.25 15 15 9.75m-3-7.036A11.959 11.959 0 013.598 6 11.99 11.99 0 003 9.749c0 5.592 3.824 10.29 9 11.623 5.176-1.332 9-6.03 9-11.622 0-1.31-.21-2.571-.598-3.751h-.152c-3.196 0-6.1-1.248-8.25-3.285z"
1001
+ }
1002
+ )
1003
+ }
1004
+ ),
1005
+ /* @__PURE__ */ jsxs5("span", { children: [
1006
+ "Powered by",
1007
+ " ",
1008
+ /* @__PURE__ */ jsx6(
1009
+ "a",
1010
+ {
1011
+ href: "https://www.rhinestone.dev",
1012
+ target: "_blank",
1013
+ rel: "noopener noreferrer",
1014
+ children: "Rhinestone"
1015
+ }
1016
+ )
1017
+ ] })
1018
+ ] });
1019
+ }
1020
+
1021
+ // src/core/webhook.ts
1022
+ function isRecord(value) {
1023
+ return typeof value === "object" && value !== null;
1024
+ }
1025
+ function asString(value) {
1026
+ return typeof value === "string" ? value : void 0;
1027
+ }
1028
+ function getEventTxHash(event) {
1029
+ if (!event?.type) return void 0;
1030
+ if (event.type === "deposit-received") {
1031
+ return asString(event.data?.transactionHash);
1032
+ }
1033
+ if (event.type === "bridge-started" || event.type === "bridge-complete") {
1034
+ const deposit = isRecord(event.data?.deposit) ? event.data.deposit : void 0;
1035
+ return asString(deposit?.transactionHash);
1036
+ }
1037
+ if (event.type === "bridge-failed" || event.type === "error") {
1038
+ const deposit = isRecord(event.data?.deposit) ? event.data.deposit : void 0;
1039
+ return asString(deposit?.transactionHash);
1040
+ }
1041
+ return void 0;
1042
+ }
1043
+ function isDepositEvent(event) {
1044
+ return event?.type === "deposit-received" || event?.type === "bridge-started";
1045
+ }
1046
+
1047
+ // src/components/steps/ProcessingStep.tsx
1048
+ import { Fragment, jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1049
+ var INITIAL_POLL_INTERVAL = 3e3;
1050
+ var MAX_POLL_INTERVAL = 3e4;
1051
+ var BACKOFF_MULTIPLIER = 1.5;
1052
+ var PROCESS_TIMEOUT_MS = 10 * 60 * 1e3;
1053
+ function isEventForTx(event, txHash) {
1054
+ const eventTxHash = getEventTxHash(event);
1055
+ if (!eventTxHash) return false;
1056
+ return eventTxHash.toLowerCase() === txHash.toLowerCase();
1057
+ }
1058
+ function formatBridgeFailedMessage(event) {
1059
+ const eventData = event?.data ?? {};
1060
+ const code = typeof eventData.errorCode === "string" ? eventData.errorCode : void 0;
1061
+ const backendMessage = typeof eventData.message === "string" ? eventData.message.trim() : "";
1062
+ if (backendMessage.length > 0) {
1063
+ return {
1064
+ message: backendMessage,
1065
+ code
1066
+ };
1067
+ }
1068
+ if (code) {
1069
+ return { message: `Bridge failed (${code})`, code };
1070
+ }
1071
+ return { message: "Bridge failed" };
1072
+ }
1073
+ function ProcessingStep({
1074
+ smartAccount,
1075
+ txHash,
1076
+ sourceChain,
1077
+ sourceToken,
1078
+ targetChain,
1079
+ targetToken,
1080
+ amount,
1081
+ waitForFinalTx,
1082
+ service,
1083
+ directTransfer,
1084
+ flowLabel = "deposit",
1085
+ debug,
1086
+ onClose,
1087
+ onNewDeposit,
1088
+ onDepositComplete,
1089
+ onDepositFailed,
1090
+ onError
1091
+ }) {
1092
+ const [state, setState] = useState(
1093
+ directTransfer ? { type: "complete" } : { type: "processing" }
1094
+ );
1095
+ const [elapsedSeconds, setElapsedSeconds] = useState(0);
1096
+ const startTimeRef = useRef2(Date.now());
1097
+ const intervalRef = useRef2(null);
1098
+ useEffect2(() => {
1099
+ if (directTransfer) {
1100
+ onDepositComplete?.(txHash);
1101
+ return;
1102
+ }
1103
+ }, [directTransfer, txHash, onDepositComplete]);
1104
+ useEffect2(() => {
1105
+ if (directTransfer) return;
1106
+ startTimeRef.current = Date.now();
1107
+ intervalRef.current = setInterval(() => {
1108
+ setElapsedSeconds(Math.floor((Date.now() - startTimeRef.current) / 1e3));
1109
+ }, 1e3);
1110
+ return () => {
1111
+ if (intervalRef.current) clearInterval(intervalRef.current);
1112
+ };
1113
+ }, [directTransfer]);
1114
+ useEffect2(() => {
1115
+ if (state.type === "complete" || state.type === "failed" || state.type === "error") {
1116
+ if (intervalRef.current) {
1117
+ clearInterval(intervalRef.current);
1118
+ intervalRef.current = null;
1119
+ }
1120
+ }
1121
+ }, [state.type]);
1122
+ const pollIntervalRef = useRef2(INITIAL_POLL_INTERVAL);
1123
+ const pollTimeoutRef = useRef2(null);
1124
+ const processTimeoutRef = useRef2(null);
1125
+ useEffect2(() => {
1126
+ if (directTransfer) return;
1127
+ if (state.type !== "processing") {
1128
+ pollIntervalRef.current = INITIAL_POLL_INTERVAL;
1129
+ return;
1130
+ }
1131
+ let isMounted = true;
1132
+ async function pollStatus() {
1133
+ try {
1134
+ const data = await service.fetchStatus(smartAccount, txHash);
1135
+ const lastEvent2 = data.lastEvent;
1136
+ const eventMatchesTx = isEventForTx(lastEvent2, txHash);
1137
+ const eventForCurrentTx = eventMatchesTx ? lastEvent2 : void 0;
1138
+ if (debug && lastEvent2) {
1139
+ const eventData = lastEvent2.data;
1140
+ console.log("[deposit-modal] status poll", {
1141
+ type: lastEvent2.type,
1142
+ matchesTx: eventMatchesTx,
1143
+ intentId: eventData?.intentId,
1144
+ data: eventData
1145
+ });
1146
+ }
1147
+ if (!isMounted) return;
1148
+ if (eventForCurrentTx?.type === "bridge-complete") {
1149
+ setState({ type: "complete", lastEvent: eventForCurrentTx });
1150
+ const destinationTxHash2 = eventForCurrentTx.data?.destination?.transactionHash;
1151
+ onDepositComplete?.(txHash, destinationTxHash2);
1152
+ return;
1153
+ }
1154
+ if (!waitForFinalTx && eventForCurrentTx?.type === "bridge-started") {
1155
+ setState({ type: "complete", lastEvent: eventForCurrentTx });
1156
+ onDepositComplete?.(txHash);
1157
+ return;
1158
+ }
1159
+ if (eventForCurrentTx?.type === "bridge-failed") {
1160
+ const formatted = formatBridgeFailedMessage(eventForCurrentTx);
1161
+ setState({
1162
+ type: "failed",
1163
+ message: formatted.message,
1164
+ lastEvent: eventForCurrentTx
1165
+ });
1166
+ onDepositFailed?.(txHash, formatted.message);
1167
+ return;
1168
+ }
1169
+ if (eventForCurrentTx?.type === "error") {
1170
+ const errorMessage = eventForCurrentTx.data?.message ?? "Unknown error";
1171
+ setState({
1172
+ type: "failed",
1173
+ message: errorMessage,
1174
+ lastEvent: eventForCurrentTx
1175
+ });
1176
+ onDepositFailed?.(txHash, errorMessage);
1177
+ return;
1178
+ }
1179
+ setState({ type: "processing", lastEvent: eventForCurrentTx });
1180
+ scheduleNextPoll();
1181
+ } catch {
1182
+ scheduleNextPoll();
1183
+ }
1184
+ }
1185
+ function scheduleNextPoll() {
1186
+ if (!isMounted) return;
1187
+ pollTimeoutRef.current = setTimeout(() => {
1188
+ pollIntervalRef.current = Math.min(
1189
+ pollIntervalRef.current * BACKOFF_MULTIPLIER,
1190
+ MAX_POLL_INTERVAL
1191
+ );
1192
+ pollStatus();
1193
+ }, pollIntervalRef.current);
1194
+ }
1195
+ pollStatus();
1196
+ return () => {
1197
+ isMounted = false;
1198
+ if (pollTimeoutRef.current) {
1199
+ clearTimeout(pollTimeoutRef.current);
1200
+ }
1201
+ };
1202
+ }, [
1203
+ directTransfer,
1204
+ state.type,
1205
+ smartAccount,
1206
+ txHash,
1207
+ service,
1208
+ waitForFinalTx,
1209
+ onDepositComplete,
1210
+ onDepositFailed
1211
+ ]);
1212
+ useEffect2(() => {
1213
+ if (directTransfer) return;
1214
+ if (state.type !== "processing") {
1215
+ if (processTimeoutRef.current) {
1216
+ clearTimeout(processTimeoutRef.current);
1217
+ processTimeoutRef.current = null;
1218
+ }
1219
+ return;
1220
+ }
1221
+ processTimeoutRef.current = setTimeout(() => {
1222
+ const message = "We couldn't confirm your transfer. Please contact support if funds do not arrive.";
1223
+ setState({ type: "error", message });
1224
+ onError?.(message, "PROCESS_TIMEOUT");
1225
+ }, PROCESS_TIMEOUT_MS);
1226
+ return () => {
1227
+ if (processTimeoutRef.current) {
1228
+ clearTimeout(processTimeoutRef.current);
1229
+ processTimeoutRef.current = null;
1230
+ }
1231
+ };
1232
+ }, [directTransfer, state.type, onError]);
1233
+ const isError = state.type === "error" || state.type === "failed";
1234
+ const isComplete = state.type === "complete";
1235
+ const isProcessing = state.type === "processing";
1236
+ const lastEvent = state.type === "processing" || state.type === "complete" || state.type === "failed" ? state.lastEvent : void 0;
1237
+ const isEarlyComplete = !waitForFinalTx && lastEvent?.type === "bridge-started";
1238
+ const flowNoun = flowLabel === "withdraw" ? "withdrawal" : "deposit";
1239
+ const flowCapitalized = flowLabel === "withdraw" ? "Withdrawal" : "Deposit";
1240
+ const destinationTxHash = lastEvent?.data?.destination?.transactionHash || null;
1241
+ const sourceExplorerUrl = getExplorerTxUrl(sourceChain, txHash);
1242
+ const destExplorerUrl = destinationTxHash ? getExplorerTxUrl(targetChain, destinationTxHash) : null;
1243
+ const truncateHash = (hash) => `${hash.slice(0, 10)}...${hash.slice(-8)}`;
1244
+ const formatElapsedTime = (seconds) => {
1245
+ if (seconds < 60) return `${seconds} second${seconds !== 1 ? "s" : ""}`;
1246
+ const mins = Math.floor(seconds / 60);
1247
+ const secs = seconds % 60;
1248
+ return `${mins}m ${secs}s`;
1249
+ };
1250
+ const targetSymbol = getTokenSymbol(targetToken, targetChain);
1251
+ const sourceDecimals = getTokenDecimalsByAddress(sourceToken, sourceChain);
1252
+ const formattedReceivedAmount = (() => {
1253
+ try {
1254
+ const raw = formatUnits(BigInt(amount), sourceDecimals);
1255
+ const numeric = Number(raw);
1256
+ if (!Number.isFinite(numeric)) return raw;
1257
+ return numeric.toLocaleString("en-US", { maximumFractionDigits: 6 });
1258
+ } catch {
1259
+ return Number(amount).toLocaleString("en-US", {
1260
+ maximumFractionDigits: 6
1261
+ });
1262
+ }
1263
+ })();
1264
+ if (isComplete) {
1265
+ return /* @__PURE__ */ jsxs6("div", { className: "rs-step", children: [
1266
+ /* @__PURE__ */ jsxs6("div", { className: "rs-step-body rs-space-y-3", children: [
1267
+ /* @__PURE__ */ jsxs6("div", { className: "rs-success-state", children: [
1268
+ /* @__PURE__ */ jsx7("div", { className: "rs-success-checkmark", children: /* @__PURE__ */ jsx7(
1269
+ "svg",
1270
+ {
1271
+ viewBox: "0 0 24 24",
1272
+ fill: "none",
1273
+ stroke: "currentColor",
1274
+ strokeWidth: "2.5",
1275
+ children: /* @__PURE__ */ jsx7(
1276
+ "path",
1277
+ {
1278
+ strokeLinecap: "round",
1279
+ strokeLinejoin: "round",
1280
+ d: "M5 12l5 5L20 7"
1281
+ }
1282
+ )
1283
+ }
1284
+ ) }),
1285
+ /* @__PURE__ */ jsx7("div", { className: "rs-success-title", children: isEarlyComplete ? `${flowCapitalized} confirmed` : `${flowCapitalized} successful` }),
1286
+ /* @__PURE__ */ jsx7("div", { className: "rs-success-subtitle", children: directTransfer ? "Your transfer is complete." : isEarlyComplete ? "Your transfer has been confirmed and funds will arrive shortly." : "Your funds have been successfully bridged." })
1287
+ ] }),
1288
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card", children: [
1289
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1290
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Status" }),
1291
+ /* @__PURE__ */ jsx7(
1292
+ "span",
1293
+ {
1294
+ className: "rs-card-value",
1295
+ style: { color: "var(--rs-success)" },
1296
+ children: isEarlyComplete ? "Confirmed" : "Successful"
1297
+ }
1298
+ )
1299
+ ] }),
1300
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1301
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Total time" }),
1302
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-value", children: formatElapsedTime(elapsedSeconds) })
1303
+ ] }),
1304
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1305
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "You received" }),
1306
+ /* @__PURE__ */ jsxs6("span", { className: "rs-card-value", children: [
1307
+ formattedReceivedAmount,
1308
+ " ",
1309
+ targetSymbol
1310
+ ] })
1311
+ ] })
1312
+ ] }),
1313
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card", children: [
1314
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1315
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Source" }),
1316
+ /* @__PURE__ */ jsxs6(
1317
+ "span",
1318
+ {
1319
+ className: "rs-card-value",
1320
+ style: { display: "flex", alignItems: "center", gap: 6 },
1321
+ children: [
1322
+ getChainIcon(sourceChain) && /* @__PURE__ */ jsx7(
1323
+ "img",
1324
+ {
1325
+ src: getChainIcon(sourceChain),
1326
+ alt: "",
1327
+ style: { width: 14, height: 14, borderRadius: "50%" }
1328
+ }
1329
+ ),
1330
+ getChainName(sourceChain)
1331
+ ]
1332
+ }
1333
+ )
1334
+ ] }),
1335
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1336
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Destination" }),
1337
+ /* @__PURE__ */ jsxs6(
1338
+ "span",
1339
+ {
1340
+ className: "rs-card-value",
1341
+ style: { display: "flex", alignItems: "center", gap: 6 },
1342
+ children: [
1343
+ getChainIcon(targetChain) && /* @__PURE__ */ jsx7(
1344
+ "img",
1345
+ {
1346
+ src: getChainIcon(targetChain),
1347
+ alt: "",
1348
+ style: { width: 14, height: 14, borderRadius: "50%" }
1349
+ }
1350
+ ),
1351
+ getChainName(targetChain)
1352
+ ]
1353
+ }
1354
+ )
1355
+ ] }),
1356
+ sourceExplorerUrl && /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1357
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Transaction" }),
1358
+ /* @__PURE__ */ jsxs6(
1359
+ "a",
1360
+ {
1361
+ href: sourceExplorerUrl,
1362
+ target: "_blank",
1363
+ rel: "noopener noreferrer",
1364
+ className: "rs-link rs-link-external rs-font-mono rs-text-xs",
1365
+ children: [
1366
+ truncateHash(txHash),
1367
+ /* @__PURE__ */ jsx7(
1368
+ "svg",
1369
+ {
1370
+ viewBox: "0 0 24 24",
1371
+ fill: "none",
1372
+ stroke: "currentColor",
1373
+ strokeWidth: "2.5",
1374
+ style: { width: 12, height: 12 },
1375
+ children: /* @__PURE__ */ jsx7(
1376
+ "path",
1377
+ {
1378
+ strokeLinecap: "round",
1379
+ strokeLinejoin: "round",
1380
+ d: "M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"
1381
+ }
1382
+ )
1383
+ }
1384
+ )
1385
+ ]
1386
+ }
1387
+ )
1388
+ ] }),
1389
+ destinationTxHash && destExplorerUrl && /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1390
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Destination tx" }),
1391
+ /* @__PURE__ */ jsxs6(
1392
+ "a",
1393
+ {
1394
+ href: destExplorerUrl,
1395
+ target: "_blank",
1396
+ rel: "noopener noreferrer",
1397
+ className: "rs-link rs-link-external rs-font-mono rs-text-xs",
1398
+ children: [
1399
+ truncateHash(destinationTxHash),
1400
+ /* @__PURE__ */ jsx7(
1401
+ "svg",
1402
+ {
1403
+ viewBox: "0 0 24 24",
1404
+ fill: "none",
1405
+ stroke: "currentColor",
1406
+ strokeWidth: "2.5",
1407
+ style: { width: 12, height: 12 },
1408
+ children: /* @__PURE__ */ jsx7(
1409
+ "path",
1410
+ {
1411
+ strokeLinecap: "round",
1412
+ strokeLinejoin: "round",
1413
+ d: "M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"
1414
+ }
1415
+ )
1416
+ }
1417
+ )
1418
+ ]
1419
+ }
1420
+ )
1421
+ ] })
1422
+ ] })
1423
+ ] }),
1424
+ /* @__PURE__ */ jsxs6("div", { className: "rs-step-footer", style: { gap: 8, display: "flex" }, children: [
1425
+ /* @__PURE__ */ jsx7(Button, { variant: "outline", onClick: onClose, fullWidth: true, children: "Close" }),
1426
+ /* @__PURE__ */ jsxs6(Button, { onClick: onNewDeposit, fullWidth: true, children: [
1427
+ "New ",
1428
+ flowNoun
1429
+ ] })
1430
+ ] }),
1431
+ /* @__PURE__ */ jsx7(PoweredBy, {})
1432
+ ] });
1433
+ }
1434
+ return /* @__PURE__ */ jsxs6("div", { className: "rs-step", children: [
1435
+ /* @__PURE__ */ jsxs6("div", { className: "rs-step-header", children: [
1436
+ /* @__PURE__ */ jsxs6("div", { className: "rs-step-header-row", children: [
1437
+ /* @__PURE__ */ jsx7(
1438
+ "div",
1439
+ {
1440
+ className: `rs-step-icon ${isError ? "rs-step-icon--error" : "rs-step-icon--accent"}`,
1441
+ children: isError ? /* @__PURE__ */ jsx7(
1442
+ "svg",
1443
+ {
1444
+ viewBox: "0 0 24 24",
1445
+ fill: "none",
1446
+ stroke: "currentColor",
1447
+ strokeWidth: "2",
1448
+ children: /* @__PURE__ */ jsx7(
1449
+ "path",
1450
+ {
1451
+ strokeLinecap: "round",
1452
+ strokeLinejoin: "round",
1453
+ d: "M12 9v3.75m9-.75a9 9 0 11-18 0 9 9 0 0118 0zm-9 3.75h.008v.008H12v-.008z"
1454
+ }
1455
+ )
1456
+ }
1457
+ ) : /* @__PURE__ */ jsx7(Spinner, {})
1458
+ }
1459
+ ),
1460
+ /* @__PURE__ */ jsx7(
1461
+ "div",
1462
+ {
1463
+ className: `rs-step-title ${isError ? "rs-step-title--error" : ""}`,
1464
+ children: isError ? `${flowCapitalized} Failed` : `Bridging ${flowCapitalized}`
1465
+ }
1466
+ )
1467
+ ] }),
1468
+ /* @__PURE__ */ jsxs6(
1469
+ "div",
1470
+ {
1471
+ className: `rs-step-description ${isError ? "rs-text-error" : "rs-text-secondary"}`,
1472
+ children: [
1473
+ state.type === "processing" && (lastEvent?.type === "deposit-received" ? "Transfer received. Preparing bridge..." : lastEvent?.type === "bridge-started" ? "Transfer confirmed. Funds arriving shortly..." : `Bridging your ${flowNoun} to ${getChainName(targetChain)}.`),
1474
+ state.type === "failed" && state.message,
1475
+ state.type === "error" && state.message
1476
+ ]
1477
+ }
1478
+ )
1479
+ ] }),
1480
+ /* @__PURE__ */ jsxs6("div", { className: "rs-step-body rs-space-y-3", children: [
1481
+ isProcessing && /* @__PURE__ */ jsxs6(Fragment, { children: [
1482
+ /* @__PURE__ */ jsx7("div", { className: "rs-progress-bar", children: /* @__PURE__ */ jsx7("div", { className: "rs-progress-bar-fill rs-progress-bar-fill--indeterminate" }) }),
1483
+ /* @__PURE__ */ jsxs6("div", { className: "rs-alert rs-alert--info", children: [
1484
+ /* @__PURE__ */ jsx7(
1485
+ "svg",
1486
+ {
1487
+ className: "rs-alert-icon",
1488
+ viewBox: "0 0 24 24",
1489
+ fill: "none",
1490
+ stroke: "currentColor",
1491
+ strokeWidth: "2",
1492
+ children: /* @__PURE__ */ jsx7(
1493
+ "path",
1494
+ {
1495
+ strokeLinecap: "round",
1496
+ strokeLinejoin: "round",
1497
+ d: "M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"
1498
+ }
1499
+ )
1500
+ }
1501
+ ),
1502
+ /* @__PURE__ */ jsxs6("p", { className: "rs-alert-text", children: [
1503
+ "You can safely close this window. Your ",
1504
+ flowNoun,
1505
+ " will complete in the background."
1506
+ ] })
1507
+ ] }),
1508
+ /* @__PURE__ */ jsxs6(
1509
+ "div",
1510
+ {
1511
+ className: "rs-text-sm rs-text-tertiary",
1512
+ style: { textAlign: "center" },
1513
+ children: [
1514
+ "Elapsed: ",
1515
+ formatElapsedTime(elapsedSeconds)
1516
+ ]
1517
+ }
1518
+ )
1519
+ ] }),
1520
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card", children: [
1521
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1522
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Source" }),
1523
+ /* @__PURE__ */ jsxs6(
1524
+ "span",
1525
+ {
1526
+ className: "rs-card-value",
1527
+ style: { display: "flex", alignItems: "center", gap: 8 },
1528
+ children: [
1529
+ getChainIcon(sourceChain) && /* @__PURE__ */ jsx7(
1530
+ "img",
1531
+ {
1532
+ src: getChainIcon(sourceChain),
1533
+ alt: "",
1534
+ style: { width: 16, height: 16, borderRadius: "50%" }
1535
+ }
1536
+ ),
1537
+ getChainName(sourceChain)
1538
+ ]
1539
+ }
1540
+ )
1541
+ ] }),
1542
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1543
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Destination" }),
1544
+ /* @__PURE__ */ jsxs6(
1545
+ "span",
1546
+ {
1547
+ className: "rs-card-value",
1548
+ style: { display: "flex", alignItems: "center", gap: 8 },
1549
+ children: [
1550
+ getChainIcon(targetChain) && /* @__PURE__ */ jsx7(
1551
+ "img",
1552
+ {
1553
+ src: getChainIcon(targetChain),
1554
+ alt: "",
1555
+ style: { width: 16, height: 16, borderRadius: "50%" }
1556
+ }
1557
+ ),
1558
+ getChainName(targetChain)
1559
+ ]
1560
+ }
1561
+ )
1562
+ ] }),
1563
+ /* @__PURE__ */ jsxs6("div", { className: "rs-card-row", children: [
1564
+ /* @__PURE__ */ jsx7("span", { className: "rs-card-label", children: "Transaction" }),
1565
+ sourceExplorerUrl ? /* @__PURE__ */ jsxs6(
1566
+ "a",
1567
+ {
1568
+ href: sourceExplorerUrl,
1569
+ target: "_blank",
1570
+ rel: "noopener noreferrer",
1571
+ className: "rs-link rs-link-external rs-font-mono rs-text-xs",
1572
+ children: [
1573
+ truncateHash(txHash),
1574
+ /* @__PURE__ */ jsx7(
1575
+ "svg",
1576
+ {
1577
+ viewBox: "0 0 24 24",
1578
+ fill: "none",
1579
+ stroke: "currentColor",
1580
+ strokeWidth: "2.5",
1581
+ children: /* @__PURE__ */ jsx7(
1582
+ "path",
1583
+ {
1584
+ strokeLinecap: "round",
1585
+ strokeLinejoin: "round",
1586
+ d: "M13.5 6H5.25A2.25 2.25 0 003 8.25v10.5A2.25 2.25 0 005.25 21h10.5A2.25 2.25 0 0018 18.75V10.5m-10.5 6L21 3m0 0h-5.25M21 3v5.25"
1587
+ }
1588
+ )
1589
+ }
1590
+ )
1591
+ ]
1592
+ }
1593
+ ) : /* @__PURE__ */ jsx7("span", { className: "rs-card-value rs-card-value--mono", children: truncateHash(txHash) })
1594
+ ] })
1595
+ ] })
1596
+ ] }),
1597
+ isError && /* @__PURE__ */ jsxs6("div", { className: "rs-step-footer", style: { gap: 8, display: "flex" }, children: [
1598
+ /* @__PURE__ */ jsx7(Button, { variant: "outline", onClick: onClose, fullWidth: true, children: "Close" }),
1599
+ /* @__PURE__ */ jsx7(Button, { onClick: onNewDeposit, fullWidth: true, children: "Try Again" })
1600
+ ] }),
1601
+ /* @__PURE__ */ jsx7(PoweredBy, {})
1602
+ ] });
1603
+ }
1604
+
1605
+ // src/core/public-client.ts
1606
+ import { createPublicClient, http } from "viem";
1607
+ var clientCache = /* @__PURE__ */ new Map();
1608
+ function getPublicClient(chainId) {
1609
+ let client = clientCache.get(chainId);
1610
+ if (!client) {
1611
+ const chain = CHAIN_BY_ID[chainId];
1612
+ client = createPublicClient({
1613
+ chain,
1614
+ transport: http()
1615
+ });
1616
+ clientCache.set(chainId, client);
1617
+ }
1618
+ return client;
1619
+ }
1620
+
1621
+ export {
1622
+ Modal,
1623
+ Spinner,
1624
+ Button,
1625
+ ConnectStep,
1626
+ createViewOnlyAccount,
1627
+ createSmartAccount,
1628
+ getAccountAddress,
1629
+ getAccountInitData,
1630
+ getSessionDetails,
1631
+ loadSessionOwnerFromStorage,
1632
+ saveSessionOwnerToStorage,
1633
+ createSessionOwnerKey,
1634
+ accountFromPrivateKey,
1635
+ PoweredBy,
1636
+ createDepositService,
1637
+ getAssetId,
1638
+ portfolioToAssets,
1639
+ isNativeAsset,
1640
+ currencyFormatter,
1641
+ tokenFormatter,
1642
+ formatUserError,
1643
+ getEventTxHash,
1644
+ isDepositEvent,
1645
+ ProcessingStep,
1646
+ getPublicClient,
1647
+ applyTheme
1648
+ };