@unifold/ui-react 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs ADDED
@@ -0,0 +1,2763 @@
1
+ // src/components/deposits/DepositModal.tsx
2
+ import { useState as useState5, useEffect as useEffect5 } from "react";
3
+
4
+ // src/components/shared/dialog.tsx
5
+ import * as React2 from "react";
6
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
7
+ import { X } from "lucide-react";
8
+
9
+ // src/lib/utils.ts
10
+ import { clsx } from "clsx";
11
+ import { twMerge } from "tailwind-merge";
12
+ function cn(...inputs) {
13
+ return twMerge(clsx(inputs));
14
+ }
15
+
16
+ // src/context/ThemeContext.tsx
17
+ import * as React from "react";
18
+ import { jsx } from "react/jsx-runtime";
19
+ var ThemeContext = React.createContext({ themeClass: "" });
20
+ function ThemeProvider({
21
+ children,
22
+ themeClass
23
+ }) {
24
+ return /* @__PURE__ */ jsx(ThemeContext.Provider, { value: { themeClass }, children });
25
+ }
26
+ function useTheme() {
27
+ return React.useContext(ThemeContext);
28
+ }
29
+
30
+ // src/components/shared/dialog.tsx
31
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
32
+ var Dialog = DialogPrimitive.Root;
33
+ var DialogTrigger = DialogPrimitive.Trigger;
34
+ var DialogPortal = DialogPrimitive.Portal;
35
+ var DialogClose = DialogPrimitive.Close;
36
+ var DialogOverlay = React2.forwardRef(({ className, ...props }, ref) => {
37
+ const { themeClass } = useTheme();
38
+ return /* @__PURE__ */ jsx2(
39
+ DialogPrimitive.Overlay,
40
+ {
41
+ ref,
42
+ className: cn(
43
+ themeClass,
44
+ "uf-fixed uf-inset-0 uf-z-50 uf-bg-black/40 data-[state=open]:uf-animate-in data-[state=closed]:uf-animate-out data-[state=closed]:uf-fade-out-0 data-[state=open]:uf-fade-in-0",
45
+ className
46
+ ),
47
+ ...props
48
+ }
49
+ );
50
+ });
51
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
52
+ var DialogContent = React2.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
53
+ /* @__PURE__ */ jsx2(DialogOverlay, {}),
54
+ /* @__PURE__ */ jsxs(
55
+ DialogPrimitive.Content,
56
+ {
57
+ ref,
58
+ className: cn(
59
+ // Mobile: bottom-aligned, full-width
60
+ "uf-fixed uf-bottom-0 uf-left-0 uf-right-0 uf-z-50 uf-grid uf-w-full uf-max-w-full",
61
+ // Mobile: rounded top corners only
62
+ "uf-rounded-t-3xl",
63
+ // Desktop: centered modal (no default max-width, let parent specify)
64
+ "sm:uf-left-[50%] sm:uf-top-[50%] sm:uf-bottom-auto sm:uf-right-auto sm:uf-translate-x-[-50%] sm:uf-translate-y-[-50%]",
65
+ // Desktop: rounded all corners
66
+ "sm:uf-rounded-3xl",
67
+ // Common styles
68
+ "uf-gap-4 uf-border uf-bg-background uf-p-6 uf-shadow-lg uf-duration-200",
69
+ // Animations - mobile slides from bottom
70
+ "data-[state=open]:uf-animate-in data-[state=closed]:uf-animate-out",
71
+ "data-[state=closed]:uf-fade-out-0 data-[state=open]:uf-fade-in-0",
72
+ "data-[state=closed]:uf-slide-out-to-bottom data-[state=open]:uf-slide-in-from-bottom",
73
+ // Desktop animations - center zoom
74
+ "sm:data-[state=closed]:uf-zoom-out-95 sm:data-[state=open]:uf-zoom-in-95",
75
+ "sm:data-[state=closed]:uf-slide-out-to-left-1/2 sm:data-[state=closed]:uf-slide-out-to-top-[48%]",
76
+ "sm:data-[state=open]:uf-slide-in-from-left-1/2 sm:data-[state=open]:uf-slide-in-from-top-[48%]",
77
+ className
78
+ ),
79
+ ...props,
80
+ children: [
81
+ children,
82
+ /* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "uf-absolute uf-right-6 uf-top-6 uf-rounded-sm uf-opacity-70 uf-ring-offset-background uf-transition-opacity hover:uf-opacity-100 focus:uf-outline-none focus:uf-ring-2 focus:uf-ring-ring focus:uf-ring-offset-2 disabled:uf-pointer-events-none data-[state=open]:uf-bg-accent data-[state=open]:uf-text-muted-foreground", children: [
83
+ /* @__PURE__ */ jsx2(X, { className: "uf-h-6 uf-w-6" }),
84
+ /* @__PURE__ */ jsx2("span", { className: "uf-sr-only", children: "Close" })
85
+ ] })
86
+ ]
87
+ }
88
+ )
89
+ ] }));
90
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
91
+ var DialogHeader = ({
92
+ className,
93
+ ...props
94
+ }) => /* @__PURE__ */ jsx2(
95
+ "div",
96
+ {
97
+ className: cn(
98
+ "uf-flex uf-flex-col uf-space-y-1.5 uf-text-center sm:uf-text-left",
99
+ className
100
+ ),
101
+ ...props
102
+ }
103
+ );
104
+ DialogHeader.displayName = "DialogHeader";
105
+ var DialogFooter = ({
106
+ className,
107
+ ...props
108
+ }) => /* @__PURE__ */ jsx2(
109
+ "div",
110
+ {
111
+ className: cn(
112
+ "uf-flex uf-flex-col-reverse sm:uf-flex-row sm:uf-justify-end sm:uf-space-x-2",
113
+ className
114
+ ),
115
+ ...props
116
+ }
117
+ );
118
+ DialogFooter.displayName = "DialogFooter";
119
+ var DialogTitle = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
120
+ DialogPrimitive.Title,
121
+ {
122
+ ref,
123
+ className: cn(
124
+ "uf-text-lg uf-font-semibold uf-leading-none uf-tracking-tight",
125
+ className
126
+ ),
127
+ ...props
128
+ }
129
+ ));
130
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
131
+ var DialogDescription = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx2(
132
+ DialogPrimitive.Description,
133
+ {
134
+ ref,
135
+ className: cn("uf-text-sm uf-text-muted-foreground", className),
136
+ ...props
137
+ }
138
+ ));
139
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
140
+
141
+ // src/components/deposits/TransferCryptoBase.tsx
142
+ import { useState as useState2, useEffect as useEffect3 } from "react";
143
+ import {
144
+ ChevronDown as ChevronDown2,
145
+ ChevronUp as ChevronUp2,
146
+ Info,
147
+ Copy,
148
+ Check as Check2,
149
+ DollarSign,
150
+ ShieldCheck,
151
+ Clock,
152
+ FileText,
153
+ ChevronRight
154
+ } from "lucide-react";
155
+
156
+ // src/components/deposits/StyledQRCode.tsx
157
+ import { useEffect, useRef } from "react";
158
+ import QRCodeStyling from "qr-code-styling";
159
+ import { jsx as jsx3 } from "react/jsx-runtime";
160
+ function StyledQRCode({
161
+ value,
162
+ size = 200,
163
+ imageUrl,
164
+ imageSize = 50,
165
+ darkMode = false
166
+ }) {
167
+ const ref = useRef(null);
168
+ const qrCodeRef = useRef(null);
169
+ useEffect(() => {
170
+ if (!ref.current) return;
171
+ if (!qrCodeRef.current) {
172
+ qrCodeRef.current = new QRCodeStyling({
173
+ type: "svg",
174
+ width: size,
175
+ height: size,
176
+ data: value,
177
+ margin: 0,
178
+ qrOptions: {
179
+ typeNumber: 0,
180
+ mode: "Byte",
181
+ errorCorrectionLevel: "H"
182
+ },
183
+ imageOptions: {
184
+ hideBackgroundDots: true,
185
+ imageSize: imageSize / size,
186
+ margin: 4,
187
+ crossOrigin: "anonymous"
188
+ },
189
+ dotsOptions: {
190
+ type: "dots",
191
+ color: darkMode ? "#ffffff" : "#000000"
192
+ },
193
+ backgroundOptions: {
194
+ color: darkMode ? "#1a1a1a" : "#ffffff"
195
+ },
196
+ image: imageUrl,
197
+ cornersSquareOptions: {
198
+ type: "extra-rounded",
199
+ color: darkMode ? "#ffffff" : "#000000"
200
+ },
201
+ cornersDotOptions: {
202
+ type: "dot",
203
+ color: darkMode ? "#ffffff" : "#000000"
204
+ }
205
+ });
206
+ qrCodeRef.current.append(ref.current);
207
+ }
208
+ }, []);
209
+ useEffect(() => {
210
+ if (qrCodeRef.current) {
211
+ qrCodeRef.current.update({
212
+ data: value,
213
+ image: imageUrl,
214
+ width: size,
215
+ height: size,
216
+ dotsOptions: {
217
+ type: "dots",
218
+ color: darkMode ? "#ffffff" : "#000000"
219
+ },
220
+ backgroundOptions: {
221
+ color: darkMode ? "#1a1a1a" : "#ffffff"
222
+ },
223
+ cornersSquareOptions: {
224
+ type: "extra-rounded",
225
+ color: darkMode ? "#ffffff" : "#000000"
226
+ },
227
+ cornersDotOptions: {
228
+ type: "dot",
229
+ color: darkMode ? "#ffffff" : "#000000"
230
+ }
231
+ });
232
+ }
233
+ }, [value, size, imageUrl, imageSize, darkMode]);
234
+ return /* @__PURE__ */ jsx3(
235
+ "div",
236
+ {
237
+ ref,
238
+ style: {
239
+ width: size,
240
+ height: size,
241
+ display: "flex",
242
+ alignItems: "center",
243
+ justifyContent: "center"
244
+ }
245
+ }
246
+ );
247
+ }
248
+
249
+ // src/components/deposits/DepositsModal.tsx
250
+ import { useEffect as useEffect2, useState } from "react";
251
+
252
+ // src/components/deposits/DepositHeader.tsx
253
+ import { ArrowLeft, X as X2 } from "lucide-react";
254
+ import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
255
+ function DepositHeader({
256
+ title,
257
+ showBack = false,
258
+ showClose = true,
259
+ onBack,
260
+ onClose,
261
+ badge
262
+ }) {
263
+ return /* @__PURE__ */ jsxs2("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-2", children: [
264
+ showBack ? /* @__PURE__ */ jsx4(
265
+ "button",
266
+ {
267
+ onClick: onBack,
268
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
269
+ children: /* @__PURE__ */ jsx4(ArrowLeft, { className: "uf-w-5 uf-h-5" })
270
+ }
271
+ ) : /* @__PURE__ */ jsx4("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
272
+ badge ? /* @__PURE__ */ jsxs2("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
273
+ /* @__PURE__ */ jsx4(DialogTitle, { className: "uf-text-center uf-text-base uf-font-light uf-text-foreground", children: title }),
274
+ /* @__PURE__ */ jsx4("div", { className: "uf-bg-secondary uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px] uf-text-muted-foreground", children: badge.count })
275
+ ] }) : /* @__PURE__ */ jsx4(DialogTitle, { className: "uf-text-center uf-text-base uf-font-light uf-text-foreground", children: title }),
276
+ showClose ? /* @__PURE__ */ jsx4(
277
+ "button",
278
+ {
279
+ onClick: onClose,
280
+ className: "hover:uf-bg-secondary uf-rounded-lg uf-p-1 uf-transition-colors",
281
+ children: /* @__PURE__ */ jsx4(X2, { className: "uf-w-5 uf-h-5" })
282
+ }
283
+ ) : /* @__PURE__ */ jsx4("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
284
+ ] });
285
+ }
286
+
287
+ // src/components/deposits/DepositExecutionItem.tsx
288
+ import { X as X3, ExternalLink } from "lucide-react";
289
+
290
+ // src/lib/api.ts
291
+ var API_BASE_URL = "http://localhost:3002";
292
+ var DEFAULT_PUBLISHABLE_KEY = "pk_test_123";
293
+ var DEFAULT_CONFIG = {};
294
+ function setApiConfig(config) {
295
+ if (config.baseUrl) {
296
+ API_BASE_URL = config.baseUrl;
297
+ }
298
+ if (config.publishableKey) {
299
+ DEFAULT_PUBLISHABLE_KEY = config.publishableKey;
300
+ }
301
+ if (config.defaultConfig) {
302
+ DEFAULT_CONFIG = config.defaultConfig;
303
+ }
304
+ }
305
+ function getApiBaseUrl() {
306
+ return API_BASE_URL;
307
+ }
308
+ function getIconUrl(iconPath) {
309
+ const normalizedPath = iconPath.startsWith("/") ? iconPath : `/${iconPath}`;
310
+ return `${API_BASE_URL}/api/public${normalizedPath}`;
311
+ }
312
+ async function createEOA(overrides, publishableKey) {
313
+ if (!overrides?.user_id) {
314
+ throw new Error("user_id is required");
315
+ }
316
+ const payload = {
317
+ user_id: overrides.user_id,
318
+ destination_chain_type: overrides?.destination_chain_type || "ethereum",
319
+ destination_chain_id: overrides?.destination_chain_id || DEFAULT_CONFIG.destinationChainId || "8453",
320
+ destination_token_address: overrides?.destination_token_address || DEFAULT_CONFIG.destinationTokenAddress || "0x833589fcd6edb6e08f4c7c32d4f71b54bda02913",
321
+ recipient_address: overrides?.recipient_address || DEFAULT_CONFIG.recipientAddress || "0x309a4154a2CD4153Da886E780890C9cb5161553C",
322
+ client_metadata: overrides?.client_metadata || {}
323
+ };
324
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
325
+ const response = await fetch(`${API_BASE_URL}/v1/public/deposit_addresses`, {
326
+ method: "POST",
327
+ headers: {
328
+ accept: "application/json",
329
+ "x-publishable-key": pk,
330
+ "Content-Type": "application/json"
331
+ },
332
+ body: JSON.stringify(payload)
333
+ });
334
+ if (!response.ok) {
335
+ throw new Error(`Failed to create EOA: ${response.statusText}`);
336
+ }
337
+ return response.json();
338
+ }
339
+ function getWalletByChainType(wallets, chainType) {
340
+ return wallets.find((wallet) => wallet.chain_type === chainType);
341
+ }
342
+ var ExecutionStatus = /* @__PURE__ */ ((ExecutionStatus2) => {
343
+ ExecutionStatus2["DELAYED"] = "delayed";
344
+ ExecutionStatus2["FAILED"] = "failed";
345
+ ExecutionStatus2["PENDING"] = "pending";
346
+ ExecutionStatus2["REFUNDED"] = "refunded";
347
+ ExecutionStatus2["SUCCEEDED"] = "succeeded";
348
+ ExecutionStatus2["WAITING"] = "waiting";
349
+ return ExecutionStatus2;
350
+ })(ExecutionStatus || {});
351
+ var SOLANA_USDC_ADDRESS = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v";
352
+ async function queryExecutions(externalUserId, publishableKey) {
353
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
354
+ const response = await fetch(
355
+ `${API_BASE_URL}/v1/public/direct_executions/query`,
356
+ {
357
+ method: "POST",
358
+ headers: {
359
+ accept: "application/json",
360
+ "x-publishable-key": pk,
361
+ "Content-Type": "application/json"
362
+ },
363
+ body: JSON.stringify({
364
+ external_user_id: externalUserId
365
+ })
366
+ }
367
+ );
368
+ if (!response.ok) {
369
+ throw new Error(`Failed to query executions: ${response.statusText}`);
370
+ }
371
+ return response.json();
372
+ }
373
+ async function getSupportedDepositTokens(publishableKey) {
374
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
375
+ const response = await fetch(
376
+ `${API_BASE_URL}/v1/public/tokens/supported_deposit_tokens`,
377
+ {
378
+ method: "GET",
379
+ headers: {
380
+ accept: "application/json",
381
+ "x-publishable-key": pk
382
+ }
383
+ }
384
+ );
385
+ if (!response.ok) {
386
+ throw new Error(
387
+ `Failed to fetch supported deposit tokens: ${response.statusText}`
388
+ );
389
+ }
390
+ return response.json();
391
+ }
392
+ async function getMeldQuotes(request, publishableKey) {
393
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
394
+ const response = await fetch(
395
+ `${API_BASE_URL}/v1/public/onramps/meld/quotes`,
396
+ {
397
+ method: "POST",
398
+ headers: {
399
+ accept: "application/json",
400
+ "x-publishable-key": pk,
401
+ "Content-Type": "application/json"
402
+ },
403
+ body: JSON.stringify(request)
404
+ }
405
+ );
406
+ if (!response.ok) {
407
+ throw new Error(`Failed to fetch Meld quotes: ${response.statusText}`);
408
+ }
409
+ return response.json();
410
+ }
411
+ async function createMeldSession(request, publishableKey) {
412
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
413
+ const response = await fetch(
414
+ `${API_BASE_URL}/v1/public/onramps/meld/sessions`,
415
+ {
416
+ method: "POST",
417
+ headers: {
418
+ accept: "application/json",
419
+ "x-publishable-key": pk,
420
+ "Content-Type": "application/json"
421
+ },
422
+ body: JSON.stringify(request)
423
+ }
424
+ );
425
+ if (!response.ok) {
426
+ throw new Error(`Failed to create Meld session: ${response.statusText}`);
427
+ }
428
+ return response.json();
429
+ }
430
+ async function getFiatCurrencies(publishableKey) {
431
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
432
+ const response = await fetch(
433
+ `${API_BASE_URL}/v1/public/onramps/fiat_currencies`,
434
+ {
435
+ method: "GET",
436
+ headers: {
437
+ accept: "application/json",
438
+ "x-publishable-key": pk
439
+ }
440
+ }
441
+ );
442
+ if (!response.ok) {
443
+ throw new Error(`Failed to fetch fiat currencies: ${response.statusText}`);
444
+ }
445
+ return response.json();
446
+ }
447
+
448
+ // src/components/deposits/DepositExecutionItem.tsx
449
+ import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
450
+ function DepositExecutionItem({
451
+ execution,
452
+ showCloseButton = false,
453
+ onClose
454
+ }) {
455
+ const isPending = execution.status === "pending" /* PENDING */ || execution.status === "waiting" /* WAITING */ || execution.status === "delayed" /* DELAYED */;
456
+ const formatTxHash = (hash) => {
457
+ if (hash.length <= 12) return hash;
458
+ return `${hash.slice(0, 16)}...${hash.slice(-8)}`;
459
+ };
460
+ const formatDateTime = (timestamp) => {
461
+ try {
462
+ const date = new Date(timestamp);
463
+ return date.toLocaleDateString("en-US", { month: "short", day: "numeric" }) + " \xB7 " + date.toLocaleTimeString("en-US", {
464
+ hour: "numeric",
465
+ minute: "2-digit",
466
+ second: "2-digit",
467
+ hour12: false
468
+ });
469
+ } catch {
470
+ return timestamp;
471
+ }
472
+ };
473
+ return /* @__PURE__ */ jsxs3("div", { className: "uf-bg-card uf-border uf-border-border uf-rounded-xl uf-overflow-hidden uf-p-3", children: [
474
+ /* @__PURE__ */ jsxs3("div", { className: "uf-flex uf-items-start uf-justify-between", children: [
475
+ /* @__PURE__ */ jsxs3("div", { className: "uf-flex uf-items-center uf-gap-2.5 uf-flex-1", children: [
476
+ /* @__PURE__ */ jsxs3("div", { className: "uf-relative uf-flex-shrink-0", children: [
477
+ /* @__PURE__ */ jsx5(
478
+ "img",
479
+ {
480
+ src: execution.source_token_metadata?.icon_url || getIconUrl("/icons/tokens/usdc.svg"),
481
+ alt: "Token",
482
+ width: 32,
483
+ height: 32,
484
+ className: "uf-rounded-full"
485
+ }
486
+ ),
487
+ isPending ? /* @__PURE__ */ jsx5("div", { className: "uf-absolute uf--bottom-0.5 uf--right-0.5 uf-bg-yellow-500 uf-rounded-full uf-p-0.5", children: /* @__PURE__ */ jsx5(
488
+ "svg",
489
+ {
490
+ width: "10",
491
+ height: "10",
492
+ viewBox: "0 0 12 12",
493
+ fill: "none",
494
+ className: "uf-animate-spin",
495
+ children: /* @__PURE__ */ jsx5(
496
+ "path",
497
+ {
498
+ d: "M6 1V3M6 9V11M1 6H3M9 6H11M2.5 2.5L4 4M8 8L9.5 9.5M2.5 9.5L4 8M8 4L9.5 2.5",
499
+ stroke: "white",
500
+ strokeWidth: "2",
501
+ strokeLinecap: "round"
502
+ }
503
+ )
504
+ }
505
+ ) }) : /* @__PURE__ */ jsx5("div", { className: "uf-absolute uf--bottom-0.5 uf--right-0.5 uf-bg-green-500 uf-rounded-full uf-p-0.5", children: /* @__PURE__ */ jsx5("svg", { width: "10", height: "10", viewBox: "0 0 12 12", fill: "none", children: /* @__PURE__ */ jsx5(
506
+ "path",
507
+ {
508
+ d: "M10 3L4.5 8.5L2 6",
509
+ stroke: "white",
510
+ strokeWidth: "2",
511
+ strokeLinecap: "round",
512
+ strokeLinejoin: "round"
513
+ }
514
+ ) }) })
515
+ ] }),
516
+ /* @__PURE__ */ jsxs3("div", { className: "uf-flex-1 uf-min-w-0", children: [
517
+ /* @__PURE__ */ jsxs3("div", { className: "uf-flex uf-items-center uf-justify-between uf-mb-0.5", children: [
518
+ /* @__PURE__ */ jsx5("h3", { className: "uf-text-foreground uf-font-medium uf-text-sm", children: isPending ? "Deposit received" : "Deposit completed" }),
519
+ /* @__PURE__ */ jsx5("span", { className: "uf-text-muted-foreground uf-text-xs uf-whitespace-nowrap uf-ml-2", children: formatDateTime(execution.created_at || (/* @__PURE__ */ new Date()).toISOString()) })
520
+ ] }),
521
+ /* @__PURE__ */ jsx5("p", { className: "uf-text-muted-foreground uf-text-xs", children: isPending ? "Your account will be credited shortly." : "Your account has been credited successfully." })
522
+ ] })
523
+ ] }),
524
+ showCloseButton && onClose && /* @__PURE__ */ jsx5(
525
+ "button",
526
+ {
527
+ onClick: onClose,
528
+ className: "uf-text-muted-foreground hover:uf-text-foreground uf-transition-colors uf-p-0.5 uf-flex-shrink-0 uf-ml-2",
529
+ children: /* @__PURE__ */ jsx5(X3, { className: "uf-w-4 uf-h-4" })
530
+ }
531
+ )
532
+ ] }),
533
+ !isPending && execution.explorer_url && /* @__PURE__ */ jsxs3("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-2 uf-pt-2 uf-border-t uf-border-secondary uf-text-xs uf-ml-[42px]", children: [
534
+ /* @__PURE__ */ jsx5("span", { className: "uf-text-muted-foreground", children: "Deposit tx:" }),
535
+ /* @__PURE__ */ jsxs3(
536
+ "a",
537
+ {
538
+ href: execution.explorer_url,
539
+ target: "_blank",
540
+ rel: "noopener noreferrer",
541
+ className: "uf-flex uf-items-center uf-gap-1 uf-text-blue-400 hover:uf-text-blue-300 uf-transition-colors uf-font-mono",
542
+ children: [
543
+ formatTxHash(execution.transaction_hash),
544
+ /* @__PURE__ */ jsx5(ExternalLink, { className: "uf-w-3 uf-h-3" })
545
+ ]
546
+ }
547
+ )
548
+ ] })
549
+ ] });
550
+ }
551
+
552
+ // src/components/deposits/DepositsModal.tsx
553
+ import { Fragment, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
554
+ function DepositsModal({
555
+ open,
556
+ onOpenChange,
557
+ executions: sessionExecutions,
558
+ userId,
559
+ publishableKey,
560
+ themeClass = ""
561
+ }) {
562
+ const [allExecutions, setAllExecutions] = useState(sessionExecutions);
563
+ useEffect2(() => {
564
+ if (!open || !userId) return;
565
+ const fetchExecutions = async () => {
566
+ try {
567
+ const response = await queryExecutions(userId, publishableKey);
568
+ const sorted = [...response.data].sort((a, b) => {
569
+ const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
570
+ const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
571
+ return timeB - timeA;
572
+ });
573
+ setAllExecutions(sorted);
574
+ } catch (error) {
575
+ console.error("Failed to fetch executions:", error);
576
+ setAllExecutions(sessionExecutions);
577
+ }
578
+ };
579
+ fetchExecutions();
580
+ const pollInterval = setInterval(fetchExecutions, 1e4);
581
+ return () => {
582
+ clearInterval(pollInterval);
583
+ };
584
+ }, [open, userId, publishableKey, sessionExecutions]);
585
+ const handleClose = () => {
586
+ onOpenChange(false);
587
+ };
588
+ return /* @__PURE__ */ jsx6(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs4(DialogContent, { className: `sm:uf-max-w-[400px] !uf-bg-card uf-border-secondary uf-text-foreground uf-p-0 uf-gap-0 [&>button]:uf-hidden ${themeClass}`, children: [
589
+ /* @__PURE__ */ jsx6(DepositHeader, { title: "Deposit Tracker", onClose: handleClose }),
590
+ /* @__PURE__ */ jsx6("div", { className: "uf-max-h-[500px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: /* @__PURE__ */ jsx6("div", { className: "uf-space-y-3", children: allExecutions.length === 0 ? /* @__PURE__ */ jsx6("div", { className: "uf-py-8 uf-px-4 uf-text-center", children: /* @__PURE__ */ jsx6("div", { className: "uf-text-muted-foreground uf-text-sm", children: "No deposits yet" }) }) : /* @__PURE__ */ jsx6(Fragment, { children: allExecutions.map((execution) => /* @__PURE__ */ jsx6(DepositExecutionItem, { execution }, execution.id)) }) }) })
591
+ ] }) });
592
+ }
593
+
594
+ // src/components/deposits/DepositSuccessToast.tsx
595
+ import { jsx as jsx7 } from "react/jsx-runtime";
596
+ function DepositSuccessToast({
597
+ depositTx,
598
+ completionTx,
599
+ orderSubmittedAt,
600
+ orderFilledAt,
601
+ explorerUrl,
602
+ completionExplorerUrl,
603
+ status,
604
+ tokenIconUrl,
605
+ onClose
606
+ }) {
607
+ const execution = {
608
+ id: depositTx,
609
+ transaction_hash: depositTx,
610
+ explorer_url: explorerUrl,
611
+ destination_transaction_hashes: completionTx ? [completionTx] : void 0,
612
+ status,
613
+ created_at: orderSubmittedAt,
614
+ updated_at: orderFilledAt,
615
+ source_token_metadata: tokenIconUrl ? { icon_url: tokenIconUrl } : void 0
616
+ };
617
+ return /* @__PURE__ */ jsx7("div", { className: "uf-w-full uf-animate-in uf-slide-in-from-bottom-2 uf-duration-300", children: /* @__PURE__ */ jsx7(
618
+ DepositExecutionItem,
619
+ {
620
+ execution,
621
+ showCloseButton: true,
622
+ onClose
623
+ }
624
+ ) });
625
+ }
626
+
627
+ // src/components/shared/select.tsx
628
+ import * as React3 from "react";
629
+ import * as SelectPrimitive from "@radix-ui/react-select";
630
+ import { Check, ChevronDown, ChevronUp } from "lucide-react";
631
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
632
+ var Select = SelectPrimitive.Root;
633
+ var SelectGroup = SelectPrimitive.Group;
634
+ var SelectValue = SelectPrimitive.Value;
635
+ var SelectTrigger = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs5(
636
+ SelectPrimitive.Trigger,
637
+ {
638
+ ref,
639
+ className: cn(
640
+ "uf-flex uf-h-10 uf-w-full uf-items-center uf-justify-between uf-rounded-md uf-border uf-border-border !uf-bg-secondary uf-px-3 uf-py-2 uf-text-sm uf-text-foreground uf-ring-offset-background placeholder:uf-text-muted-foreground focus:uf-outline-none focus:uf-ring-2 focus:uf-ring-ring focus:uf-ring-offset-2 disabled:uf-cursor-not-allowed disabled:uf-opacity-50 [&>span]:uf-line-clamp-1",
641
+ className
642
+ ),
643
+ ...props,
644
+ children: [
645
+ children,
646
+ /* @__PURE__ */ jsx8(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx8(ChevronDown, { className: "uf-h-4 uf-w-4 uf-opacity-50" }) })
647
+ ]
648
+ }
649
+ ));
650
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
651
+ var SelectScrollUpButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
652
+ SelectPrimitive.ScrollUpButton,
653
+ {
654
+ ref,
655
+ className: cn(
656
+ "uf-flex uf-cursor-default uf-items-center uf-justify-center uf-py-1",
657
+ className
658
+ ),
659
+ ...props,
660
+ children: /* @__PURE__ */ jsx8(ChevronUp, { className: "uf-h-4 uf-w-4" })
661
+ }
662
+ ));
663
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
664
+ var SelectScrollDownButton = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
665
+ SelectPrimitive.ScrollDownButton,
666
+ {
667
+ ref,
668
+ className: cn(
669
+ "uf-flex uf-cursor-default uf-items-center uf-justify-center uf-py-1",
670
+ className
671
+ ),
672
+ ...props,
673
+ children: /* @__PURE__ */ jsx8(ChevronDown, { className: "uf-h-4 uf-w-4" })
674
+ }
675
+ ));
676
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
677
+ var SelectContent = React3.forwardRef(({ className, children, position = "popper", ...props }, ref) => {
678
+ const { themeClass } = useTheme();
679
+ return /* @__PURE__ */ jsx8(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs5(
680
+ SelectPrimitive.Content,
681
+ {
682
+ ref,
683
+ className: cn(
684
+ themeClass,
685
+ "uf-relative uf-z-50 uf-max-h-96 uf-min-w-[8rem] uf-overflow-hidden uf-rounded-lg uf-border uf-border-border !uf-bg-popover uf-text-popover-foreground uf-shadow-lg data-[state=open]:uf-animate-in data-[state=closed]:uf-animate-out data-[state=closed]:uf-fade-out-0 data-[state=open]:uf-fade-in-0 data-[state=closed]:uf-zoom-out-95 data-[state=open]:uf-zoom-in-95 data-[side=bottom]:uf-slide-in-from-top-2 data-[side=left]:uf-slide-in-from-right-2 data-[side=right]:uf-slide-in-from-left-2 data-[side=top]:uf-slide-in-from-bottom-2",
686
+ position === "popper" && "data-[side=bottom]:uf-translate-y-1 data-[side=left]:uf--translate-x-1 data-[side=right]:uf-translate-x-1 data-[side=top]:uf--translate-y-1",
687
+ className
688
+ ),
689
+ position,
690
+ ...props,
691
+ children: [
692
+ /* @__PURE__ */ jsx8(SelectScrollUpButton, {}),
693
+ /* @__PURE__ */ jsx8(
694
+ SelectPrimitive.Viewport,
695
+ {
696
+ className: cn(
697
+ "uf-p-1",
698
+ position === "popper" && "uf-h-[var(--radix-select-trigger-height)] uf-w-full uf-min-w-[var(--radix-select-trigger-width)]"
699
+ ),
700
+ children
701
+ }
702
+ ),
703
+ /* @__PURE__ */ jsx8(SelectScrollDownButton, {})
704
+ ]
705
+ }
706
+ ) });
707
+ });
708
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
709
+ var SelectLabel = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
710
+ SelectPrimitive.Label,
711
+ {
712
+ ref,
713
+ className: cn("uf-py-1.5 uf-pl-8 uf-pr-2 uf-text-sm uf-font-semibold", className),
714
+ ...props
715
+ }
716
+ ));
717
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
718
+ var SelectItem = React3.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs5(
719
+ SelectPrimitive.Item,
720
+ {
721
+ ref,
722
+ className: cn(
723
+ "uf-relative uf-flex uf-w-full uf-cursor-default uf-select-none uf-items-center uf-rounded-sm uf-py-1.5 uf-pl-8 uf-pr-2 uf-text-sm uf-text-foreground uf-outline-none focus:uf-bg-accent focus:uf-text-accent-foreground data-[disabled]:uf-pointer-events-none data-[disabled]:uf-opacity-50 hover:uf-bg-accent",
724
+ className
725
+ ),
726
+ ...props,
727
+ children: [
728
+ /* @__PURE__ */ jsx8("span", { className: "uf-absolute uf-left-2 uf-flex uf-h-3.5 uf-w-3.5 uf-items-center uf-justify-center", children: /* @__PURE__ */ jsx8(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx8(Check, { className: "uf-h-4 uf-w-4" }) }) }),
729
+ /* @__PURE__ */ jsx8(SelectPrimitive.ItemText, { children })
730
+ ]
731
+ }
732
+ ));
733
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
734
+ var SelectSeparator = React3.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx8(
735
+ SelectPrimitive.Separator,
736
+ {
737
+ ref,
738
+ className: cn("uf--mx-1 uf-my-1 uf-h-px uf-bg-muted", className),
739
+ ...props
740
+ }
741
+ ));
742
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
743
+
744
+ // src/components/shared/button.tsx
745
+ import * as React4 from "react";
746
+ import { Slot } from "@radix-ui/react-slot";
747
+ import { cva } from "class-variance-authority";
748
+ import { jsx as jsx9 } from "react/jsx-runtime";
749
+ var buttonVariants = cva(
750
+ "uf-inline-flex uf-items-center uf-justify-center uf-whitespace-nowrap uf-rounded-md uf-text-sm uf-font-medium uf-ring-offset-background uf-transition-colors focus-visible:uf-outline-none focus-visible:uf-ring-2 focus-visible:uf-ring-ring focus-visible:uf-ring-offset-2 disabled:uf-pointer-events-none disabled:uf-opacity-50",
751
+ {
752
+ variants: {
753
+ variant: {
754
+ default: "uf-bg-primary uf-text-primary-foreground hover:uf-bg-primary/90",
755
+ destructive: "uf-bg-destructive uf-text-destructive-foreground hover:uf-bg-destructive/90",
756
+ outline: "uf-border uf-border-input uf-bg-background hover:uf-bg-accent hover:uf-text-accent-foreground",
757
+ secondary: "uf-bg-secondary uf-text-secondary-foreground hover:uf-bg-secondary/80",
758
+ ghost: "hover:uf-bg-accent hover:uf-text-accent-foreground",
759
+ link: "uf-text-primary uf-underline-offset-4 hover:uf-underline"
760
+ },
761
+ size: {
762
+ default: "uf-h-10 uf-px-4 uf-py-2",
763
+ sm: "uf-h-9 uf-rounded-md uf-px-3",
764
+ lg: "uf-h-11 uf-rounded-md uf-px-8",
765
+ icon: "uf-h-10 uf-w-10"
766
+ }
767
+ },
768
+ defaultVariants: {
769
+ variant: "default",
770
+ size: "default"
771
+ }
772
+ }
773
+ );
774
+ var Button = React4.forwardRef(
775
+ ({ className, variant, size, asChild = false, ...props }, ref) => {
776
+ const Comp = asChild ? Slot : "button";
777
+ return /* @__PURE__ */ jsx9(
778
+ Comp,
779
+ {
780
+ className: cn(buttonVariants({ variant, size, className })),
781
+ ref,
782
+ ...props
783
+ }
784
+ );
785
+ }
786
+ );
787
+ Button.displayName = "Button";
788
+
789
+ // src/components/shared/tooltip.tsx
790
+ import * as React5 from "react";
791
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
792
+ import { jsx as jsx10 } from "react/jsx-runtime";
793
+ var TooltipProvider = TooltipPrimitive.Provider;
794
+ var Tooltip = TooltipPrimitive.Root;
795
+ var TooltipTrigger = TooltipPrimitive.Trigger;
796
+ var TooltipContent = React5.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
797
+ const { themeClass } = useTheme();
798
+ return /* @__PURE__ */ jsx10(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx10(
799
+ TooltipPrimitive.Content,
800
+ {
801
+ ref,
802
+ sideOffset,
803
+ className: cn(
804
+ themeClass,
805
+ "uf-z-[9999] uf-w-[calc(100vw-2rem)] uf-max-w-[280px] uf-overflow-hidden uf-rounded-lg uf-bg-popover uf-px-3 uf-py-2 uf-text-xs uf-text-popover-foreground uf-shadow-lg uf-border uf-border-border uf-animate-in uf-fade-in-0 uf-zoom-in-95 data-[state=closed]:uf-animate-out data-[state=closed]:uf-fade-out-0 data-[state=closed]:uf-zoom-out-95 data-[side=bottom]:uf-slide-in-from-top-2 data-[side=left]:uf-slide-in-from-right-2 data-[side=right]:uf-slide-in-from-left-2 data-[side=top]:uf-slide-in-from-bottom-2",
806
+ className
807
+ ),
808
+ ...props
809
+ }
810
+ ) });
811
+ });
812
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
813
+
814
+ // src/lib/i18n/en.json
815
+ var en_default = {
816
+ transferCrypto: {
817
+ priceImpact: {
818
+ label: "Price impact",
819
+ tooltip: "Price impact reflects the difference between the expected price and the final execution price, influenced by trade size and available liquidity. Larger trades may move the market price during execution.",
820
+ finalCost: "The final cost reflects price impact and may vary depending on market and network conditions. Larger trade sizes typically benefit from lower relative costs."
821
+ },
822
+ slippage: {
823
+ label: "Max slippage",
824
+ auto: "Auto",
825
+ tooltip: "Slippage represents price changes that can occur while a transaction is being processed. Slippage is dynamically adjusted per trading pair to support reliable execution during market movements.",
826
+ finalCost: "The final cost includes any slippage and may change based on real-time network conditions. Costs are generally reduced for larger transaction amounts."
827
+ },
828
+ processingTime: {
829
+ label: "Processing time",
830
+ lessThanMinutes: "< {{minutes}} min",
831
+ lessThanHours: "< {{hours}} hr"
832
+ },
833
+ minDeposit: {
834
+ label: "min",
835
+ tooltip: "The minimum amount you can deposit on the selected network."
836
+ },
837
+ help: {
838
+ needHelp: "Need help?",
839
+ contactSupport: "Contact support"
840
+ },
841
+ terms: {
842
+ termsApply: "Terms apply"
843
+ },
844
+ supportedToken: "Supported token",
845
+ supportedChain: "Supported chain",
846
+ depositAddress: {
847
+ label: "Your deposit address",
848
+ tooltip: "Send any supported token to this address, and it will be automatically converted to {{token}} in your account."
849
+ },
850
+ copyAddress: "Copy address",
851
+ copied: "Copied!",
852
+ loading: "Loading...",
853
+ loadingQRCode: "Loading QR Code...",
854
+ noAddressAvailable: "No address available",
855
+ noChainsAvailable: "No chains available for this token"
856
+ },
857
+ depositModal: {
858
+ transferCrypto: {
859
+ title: "Transfer Crypto",
860
+ subtitle: "No limit \u2022 Instant"
861
+ },
862
+ depositWithCard: {
863
+ title: "Deposit with Card",
864
+ subtitle: "$50,000 limit \u2022 2 min"
865
+ },
866
+ quotes: "Quotes"
867
+ },
868
+ buyWithCard: {
869
+ onramp: {
870
+ completeTransaction: "Complete transaction with {{provider}}",
871
+ canCloseModal: "You can close this modal.",
872
+ youUse: "You use",
873
+ youBuy: "You buy",
874
+ youReceive: "You receive",
875
+ intentAddressNote: "The wallet address displayed in the payment provider is a temporary deposit address. Your funds will be automatically converted and deposited into your account."
876
+ }
877
+ }
878
+ };
879
+
880
+ // src/lib/i18n.ts
881
+ var i18n = en_default;
882
+
883
+ // src/components/deposits/TransferCryptoBase.tsx
884
+ import { Fragment as Fragment2, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
885
+ var t = i18n.transferCrypto;
886
+ var getChainKey = (chainId, chainType) => {
887
+ return `${chainType}:${chainId}`;
888
+ };
889
+ var parseChainKey = (chainKey) => {
890
+ const [chainType, chainId] = chainKey.split(":");
891
+ return { chainType, chainId };
892
+ };
893
+ function TransferCryptoBase({
894
+ userId,
895
+ publishableKey,
896
+ recipientAddress,
897
+ destinationChainId,
898
+ destinationTokenAddress,
899
+ copyButtonMode = "compact",
900
+ layoutVariant = "horizontal",
901
+ showDetailedDropdowns = false,
902
+ onExecutionsChange,
903
+ onDepositSuccess,
904
+ onDepositError
905
+ }) {
906
+ const { themeClass } = useTheme();
907
+ const isDarkMode = themeClass.includes("uf-dark");
908
+ const [token, setToken] = useState2("USDC");
909
+ const [chain, setChain] = useState2("solana:mainnet");
910
+ const [copied, setCopied] = useState2(false);
911
+ const [wallets, setWallets] = useState2([]);
912
+ const [loading, setLoading] = useState2(true);
913
+ const [error, setError] = useState2(null);
914
+ const [depositExecutions, setDepositExecutions] = useState2([]);
915
+ const [trackedExecutions, setTrackedExecutions] = useState2(/* @__PURE__ */ new Map());
916
+ const [modalOpenedAt, setModalOpenedAt] = useState2(null);
917
+ const [supportedTokens, setSupportedTokens] = useState2([]);
918
+ const [tokensLoading, setTokensLoading] = useState2(true);
919
+ const [detailsExpanded, setDetailsExpanded] = useState2(false);
920
+ const [depositsModalOpen, setDepositsModalOpen] = useState2(false);
921
+ const allChainsMap = /* @__PURE__ */ new Map();
922
+ supportedTokens.forEach((t4) => {
923
+ t4.chains.forEach((c) => {
924
+ const comboKey = `${c.chain_type}:${c.chain_id}`;
925
+ if (!allChainsMap.has(comboKey)) {
926
+ allChainsMap.set(comboKey, c);
927
+ }
928
+ });
929
+ });
930
+ const allAvailableChains = Array.from(allChainsMap.values());
931
+ const currentChainCombo = parseChainKey(chain);
932
+ const currentChainData = allAvailableChains.find(
933
+ (c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
934
+ );
935
+ const currentChainType = currentChainData?.chain_type || "ethereum";
936
+ const currentWallet = getWalletByChainType(wallets, currentChainType);
937
+ const depositAddress = currentWallet?.address || "";
938
+ useEffect3(() => {
939
+ setModalOpenedAt(/* @__PURE__ */ new Date());
940
+ }, []);
941
+ useEffect3(() => {
942
+ async function fetchSupportedTokens() {
943
+ try {
944
+ setTokensLoading(true);
945
+ const response = await getSupportedDepositTokens(publishableKey);
946
+ setSupportedTokens(response.data);
947
+ if (response.data.length > 0) {
948
+ const allChains = /* @__PURE__ */ new Set();
949
+ response.data.forEach((t4) => {
950
+ t4.chains.forEach((c) => {
951
+ allChains.add(getChainKey(c.chain_id, c.chain_type));
952
+ });
953
+ });
954
+ if (!allChains.has(chain)) {
955
+ const firstToken = response.data[0];
956
+ if (firstToken.chains.length > 0) {
957
+ const firstChain = firstToken.chains[0];
958
+ setChain(getChainKey(firstChain.chain_id, firstChain.chain_type));
959
+ }
960
+ }
961
+ }
962
+ } catch (err) {
963
+ console.error("Error fetching supported tokens:", err);
964
+ } finally {
965
+ setTokensLoading(false);
966
+ }
967
+ }
968
+ fetchSupportedTokens();
969
+ }, [publishableKey, chain]);
970
+ useEffect3(() => {
971
+ if (onExecutionsChange) {
972
+ onExecutionsChange(depositExecutions);
973
+ }
974
+ }, [depositExecutions, onExecutionsChange]);
975
+ useEffect3(() => {
976
+ async function fetchWallets() {
977
+ try {
978
+ setLoading(true);
979
+ const response = await createEOA(
980
+ {
981
+ user_id: userId,
982
+ recipient_address: recipientAddress,
983
+ destination_chain_id: destinationChainId,
984
+ destination_token_address: destinationTokenAddress
985
+ },
986
+ publishableKey
987
+ );
988
+ setWallets(response.data);
989
+ setError(null);
990
+ } catch (err) {
991
+ setError(err instanceof Error ? err.message : "Failed to load wallets");
992
+ console.error("Error fetching wallets:", err);
993
+ } finally {
994
+ setLoading(false);
995
+ }
996
+ }
997
+ fetchWallets();
998
+ }, [
999
+ userId,
1000
+ recipientAddress,
1001
+ destinationChainId,
1002
+ destinationTokenAddress,
1003
+ publishableKey
1004
+ ]);
1005
+ useEffect3(() => {
1006
+ if (!supportedTokens.length) return;
1007
+ const currentToken = supportedTokens.find((t4) => t4.symbol === token);
1008
+ if (!currentToken || currentToken.chains.length === 0) return;
1009
+ const isChainAvailable = currentToken.chains.some((c) => {
1010
+ const key = getChainKey(c.chain_id, c.chain_type);
1011
+ return key === chain;
1012
+ });
1013
+ if (!isChainAvailable) {
1014
+ const firstChain = currentToken.chains[0];
1015
+ const newChain = getChainKey(firstChain.chain_id, firstChain.chain_type);
1016
+ setChain(newChain);
1017
+ }
1018
+ }, [token, supportedTokens, chain]);
1019
+ useEffect3(() => {
1020
+ if (!userId || !modalOpenedAt) return;
1021
+ const pollInterval = setInterval(async () => {
1022
+ try {
1023
+ const response = await queryExecutions(userId, publishableKey);
1024
+ let executionToShow = null;
1025
+ for (const execution of response.data) {
1026
+ const executionTime = execution.created_at ? new Date(execution.created_at) : null;
1027
+ if (!executionTime || executionTime <= modalOpenedAt) {
1028
+ continue;
1029
+ }
1030
+ const trackedStatus = trackedExecutions.get(execution.id);
1031
+ if (!trackedStatus) {
1032
+ executionToShow = execution;
1033
+ break;
1034
+ }
1035
+ const inProgressStatuses = [
1036
+ "pending" /* PENDING */,
1037
+ "waiting" /* WAITING */,
1038
+ "delayed" /* DELAYED */
1039
+ ];
1040
+ if (inProgressStatuses.includes(trackedStatus) && execution.status === "succeeded" /* SUCCEEDED */) {
1041
+ executionToShow = execution;
1042
+ break;
1043
+ }
1044
+ }
1045
+ if (executionToShow) {
1046
+ const execution = executionToShow;
1047
+ setDepositExecutions((prev) => {
1048
+ const existingIndex = prev.findIndex((e) => e.id === execution.id);
1049
+ if (existingIndex >= 0) {
1050
+ const updated = [...prev];
1051
+ updated[existingIndex] = execution;
1052
+ return updated;
1053
+ } else {
1054
+ return [...prev, execution];
1055
+ }
1056
+ });
1057
+ setTrackedExecutions((prev) => {
1058
+ const updated = new Map(prev);
1059
+ updated.set(execution.id, execution.status);
1060
+ return updated;
1061
+ });
1062
+ if (onDepositSuccess) {
1063
+ const isCompleted = execution.status === "succeeded" /* SUCCEEDED */;
1064
+ if (isCompleted) {
1065
+ onDepositSuccess({
1066
+ message: "Deposit completed successfully",
1067
+ transaction: execution,
1068
+ executionId: execution.id
1069
+ });
1070
+ }
1071
+ }
1072
+ }
1073
+ } catch (err) {
1074
+ console.error("Error polling executions:", err);
1075
+ if (onDepositError) {
1076
+ onDepositError({
1077
+ message: "Failed to check deposit status",
1078
+ error: err,
1079
+ code: "POLLING_ERROR"
1080
+ });
1081
+ }
1082
+ }
1083
+ }, 5e3);
1084
+ return () => clearInterval(pollInterval);
1085
+ }, [
1086
+ userId,
1087
+ trackedExecutions,
1088
+ modalOpenedAt,
1089
+ publishableKey,
1090
+ onDepositSuccess,
1091
+ onDepositError
1092
+ ]);
1093
+ const selectedToken = supportedTokens.find((t4) => t4.symbol === token);
1094
+ const availableChainsForToken = selectedToken?.chains || [];
1095
+ const currentChainFromBackend = availableChainsForToken.find((c) => {
1096
+ const key = getChainKey(c.chain_id, c.chain_type);
1097
+ return key === chain;
1098
+ }) || allAvailableChains.find((c) => {
1099
+ const key = getChainKey(c.chain_id, c.chain_type);
1100
+ return key === chain;
1101
+ });
1102
+ const handleCopyAddress = () => {
1103
+ navigator.clipboard.writeText(depositAddress);
1104
+ setCopied(true);
1105
+ setTimeout(() => setCopied(false), 2e3);
1106
+ };
1107
+ const formatProcessingTime = (seconds) => {
1108
+ if (seconds === null) {
1109
+ return t.processingTime.lessThanMinutes.replace("{{minutes}}", "1");
1110
+ }
1111
+ const minutes = Math.ceil(seconds / 60);
1112
+ if (minutes < 60) {
1113
+ return t.processingTime.lessThanMinutes.replace(
1114
+ "{{minutes}}",
1115
+ String(minutes)
1116
+ );
1117
+ }
1118
+ const hours = Math.ceil(minutes / 60);
1119
+ return t.processingTime.lessThanHours.replace("{{hours}}", String(hours));
1120
+ };
1121
+ const priceImpact = currentChainFromBackend?.estimated_price_impact_percent ?? 0;
1122
+ const maxSlippage = currentChainFromBackend?.max_slippage_percent ?? 0.25;
1123
+ const processingTime = currentChainFromBackend?.estimated_processing_time ?? null;
1124
+ const minDepositUsd = currentChainFromBackend?.minimum_deposit_amount_usd ?? 3;
1125
+ const renderTokenItem = (tokenData) => {
1126
+ return /* @__PURE__ */ jsxs6("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
1127
+ /* @__PURE__ */ jsx11(
1128
+ "img",
1129
+ {
1130
+ src: tokenData.icon_url,
1131
+ alt: tokenData.symbol,
1132
+ width: 20,
1133
+ height: 20,
1134
+ className: "uf-rounded-full uf-flex-shrink-0"
1135
+ }
1136
+ ),
1137
+ /* @__PURE__ */ jsx11("span", { className: "uf-text-xs uf-font-normal", children: tokenData.symbol }),
1138
+ showDetailedDropdowns && /* @__PURE__ */ jsx11("span", { className: "uf-text-xs uf-text-muted-foreground", children: tokenData.name })
1139
+ ] });
1140
+ };
1141
+ const renderChainItem = (chainData) => {
1142
+ return /* @__PURE__ */ jsxs6("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
1143
+ /* @__PURE__ */ jsx11(
1144
+ "img",
1145
+ {
1146
+ src: chainData.icon_url,
1147
+ alt: chainData.chain_name,
1148
+ width: 20,
1149
+ height: 20,
1150
+ className: "uf-rounded-full uf-flex-shrink-0"
1151
+ }
1152
+ ),
1153
+ /* @__PURE__ */ jsx11("span", { className: "uf-text-xs uf-font-normal", children: chainData.chain_name }),
1154
+ showDetailedDropdowns && /* @__PURE__ */ jsx11("span", { className: "uf-text-xs uf-text-muted-foreground uf-capitalize", children: chainData.chain_type })
1155
+ ] });
1156
+ };
1157
+ const selectContainerClass = layoutVariant === "horizontal" ? "uf-grid uf-grid-cols-2 uf-gap-2.5" : "uf-space-y-3";
1158
+ return /* @__PURE__ */ jsx11(TooltipProvider, { delayDuration: 0, skipDelayDuration: 0, children: /* @__PURE__ */ jsxs6("div", { className: "uf-space-y-3", children: [
1159
+ /* @__PURE__ */ jsxs6("div", { className: selectContainerClass, children: [
1160
+ /* @__PURE__ */ jsxs6("div", { children: [
1161
+ /* @__PURE__ */ jsx11("div", { className: "uf-text-xs uf-text-muted-foreground uf-mb-2 uf-flex uf-items-center uf-gap-1", children: t.supportedToken }),
1162
+ /* @__PURE__ */ jsxs6(
1163
+ Select,
1164
+ {
1165
+ value: token,
1166
+ onValueChange: setToken,
1167
+ disabled: tokensLoading || supportedTokens.length === 0,
1168
+ children: [
1169
+ /* @__PURE__ */ jsx11(SelectTrigger, { className: "uf-bg-secondary uf-border-none uf-rounded-lg uf-h-10 hover:uf-bg-accent uf-text-foreground focus:uf-ring-1 focus:uf-ring-ring disabled:uf-opacity-50", children: /* @__PURE__ */ jsx11(SelectValue, { children: tokensLoading ? /* @__PURE__ */ jsx11("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ jsx11("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t.loading }) }) : selectedToken ? renderTokenItem(selectedToken) : /* @__PURE__ */ jsx11("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ jsx11("span", { className: "uf-text-xs uf-font-normal", children: token }) }) }) }),
1170
+ /* @__PURE__ */ jsx11(SelectContent, { className: "uf-bg-secondary uf-border uf-text-foreground uf-max-h-[300px]", children: supportedTokens.map((tokenData) => /* @__PURE__ */ jsx11(
1171
+ SelectItem,
1172
+ {
1173
+ value: tokenData.symbol,
1174
+ className: "focus:uf-bg-accent focus:uf-text-foreground",
1175
+ children: renderTokenItem(tokenData)
1176
+ },
1177
+ tokenData.symbol
1178
+ )) })
1179
+ ]
1180
+ }
1181
+ )
1182
+ ] }),
1183
+ /* @__PURE__ */ jsxs6("div", { children: [
1184
+ /* @__PURE__ */ jsxs6("div", { className: "uf-text-xs uf-text-muted-foreground uf-mb-2 uf-flex uf-items-center uf-gap-1", children: [
1185
+ t.supportedChain,
1186
+ /* @__PURE__ */ jsxs6("span", { className: "uf-text-[10px]", children: [
1187
+ "$",
1188
+ minDepositUsd,
1189
+ " ",
1190
+ t.minDeposit.label
1191
+ ] }),
1192
+ /* @__PURE__ */ jsxs6(Tooltip, { children: [
1193
+ /* @__PURE__ */ jsx11(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx11(
1194
+ "span",
1195
+ {
1196
+ className: "uf-inline-flex uf-cursor-pointer uf-transition-colors hover:uf-text-foreground",
1197
+ tabIndex: 0,
1198
+ role: "button",
1199
+ "aria-label": "Minimum deposit information",
1200
+ children: /* @__PURE__ */ jsx11(Info, { className: "uf-w-3 uf-h-3" })
1201
+ }
1202
+ ) }),
1203
+ /* @__PURE__ */ jsx11(
1204
+ TooltipContent,
1205
+ {
1206
+ side: "left",
1207
+ align: "center",
1208
+ className: "uf-max-w-[200px]",
1209
+ children: /* @__PURE__ */ jsx11("p", { children: t.minDeposit.tooltip })
1210
+ }
1211
+ )
1212
+ ] })
1213
+ ] }),
1214
+ /* @__PURE__ */ jsxs6(
1215
+ Select,
1216
+ {
1217
+ value: chain,
1218
+ onValueChange: setChain,
1219
+ disabled: tokensLoading || availableChainsForToken.length === 0,
1220
+ children: [
1221
+ /* @__PURE__ */ jsx11(SelectTrigger, { className: "uf-bg-secondary uf-border-none uf-rounded-lg uf-h-10 hover:uf-bg-accent uf-text-foreground focus:uf-ring-1 focus:uf-ring-ring disabled:uf-opacity-50", children: /* @__PURE__ */ jsx11(SelectValue, { children: tokensLoading ? /* @__PURE__ */ jsx11("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ jsx11("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t.loading }) }) : currentChainFromBackend ? renderChainItem(currentChainFromBackend) : currentChainData ? renderChainItem(currentChainData) : /* @__PURE__ */ jsx11("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ jsx11("span", { className: "uf-text-xs uf-font-normal", children: chain }) }) }) }),
1222
+ /* @__PURE__ */ jsx11(SelectContent, { className: "uf-bg-secondary uf-border uf-text-foreground uf-max-h-[300px]", children: availableChainsForToken.length === 0 ? /* @__PURE__ */ jsx11("div", { className: "uf-px-2 uf-py-3 uf-text-xs uf-text-muted-foreground uf-text-center", children: t.noChainsAvailable }) : availableChainsForToken.map((chainData) => {
1223
+ const chainKey = getChainKey(
1224
+ chainData.chain_id,
1225
+ chainData.chain_type
1226
+ );
1227
+ return /* @__PURE__ */ jsx11(
1228
+ SelectItem,
1229
+ {
1230
+ value: chainKey,
1231
+ className: "focus:uf-bg-accent focus:uf-text-foreground",
1232
+ children: renderChainItem(chainData)
1233
+ },
1234
+ `${chainData.chain_id}-${chainData.chain_type}`
1235
+ );
1236
+ }) })
1237
+ ]
1238
+ }
1239
+ )
1240
+ ] })
1241
+ ] }),
1242
+ /* @__PURE__ */ jsx11("div", { className: "uf-flex uf-justify-center uf-py-2", children: /* @__PURE__ */ jsx11("div", { className: "uf-bg-card uf-p-4 uf-rounded-2xl uf-shadow-lg uf-border uf-border-border", children: loading ? /* @__PURE__ */ jsx11(
1243
+ "div",
1244
+ {
1245
+ className: "uf-flex uf-items-center uf-justify-center",
1246
+ style: { width: 180, height: 180 },
1247
+ children: /* @__PURE__ */ jsx11("div", { className: "uf-text-foreground uf-text-sm", children: t.loadingQRCode })
1248
+ }
1249
+ ) : depositAddress ? /* @__PURE__ */ jsx11(
1250
+ StyledQRCode,
1251
+ {
1252
+ value: depositAddress,
1253
+ size: 180,
1254
+ imageUrl: currentChainData?.icon_url || currentChainFromBackend?.icon_url || getIconUrl("/icons/networks/ethereum.svg"),
1255
+ imageSize: 45,
1256
+ darkMode: isDarkMode
1257
+ },
1258
+ `qr-${depositAddress}-${chain}`
1259
+ ) : /* @__PURE__ */ jsx11(
1260
+ "div",
1261
+ {
1262
+ className: "uf-flex uf-items-center uf-justify-center",
1263
+ style: { width: 180, height: 180 },
1264
+ children: /* @__PURE__ */ jsx11("div", { className: "uf-text-red-400 uf-text-sm", children: t.noAddressAvailable })
1265
+ }
1266
+ ) }) }),
1267
+ /* @__PURE__ */ jsxs6("div", { children: [
1268
+ /* @__PURE__ */ jsxs6("div", { className: "uf-text-xs uf-text-muted-foreground uf-mb-2 uf-flex uf-items-center uf-justify-between", children: [
1269
+ /* @__PURE__ */ jsxs6("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
1270
+ t.depositAddress.label,
1271
+ /* @__PURE__ */ jsxs6(Tooltip, { children: [
1272
+ /* @__PURE__ */ jsx11(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx11(
1273
+ "span",
1274
+ {
1275
+ className: "uf-inline-flex uf-cursor-pointer uf-transition-colors hover:uf-text-foreground",
1276
+ tabIndex: 0,
1277
+ role: "button",
1278
+ "aria-label": "Deposit address information",
1279
+ children: /* @__PURE__ */ jsx11(Info, { className: "uf-w-3 uf-h-3" })
1280
+ }
1281
+ ) }),
1282
+ /* @__PURE__ */ jsx11(
1283
+ TooltipContent,
1284
+ {
1285
+ side: "top",
1286
+ align: "center",
1287
+ className: "uf-max-w-[240px]",
1288
+ children: /* @__PURE__ */ jsx11("p", { children: t.depositAddress.tooltip.replace("{{token}}", token) })
1289
+ }
1290
+ )
1291
+ ] })
1292
+ ] }),
1293
+ copyButtonMode === "compact" && /* @__PURE__ */ jsx11(
1294
+ "button",
1295
+ {
1296
+ onClick: handleCopyAddress,
1297
+ disabled: loading || !depositAddress,
1298
+ className: "uf-flex uf-items-center uf-gap-1 uf-text-xs uf-text-muted-foreground hover:uf-text-foreground uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
1299
+ children: copied ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
1300
+ /* @__PURE__ */ jsx11(Check2, { className: "uf-w-3 uf-h-3" }),
1301
+ /* @__PURE__ */ jsx11("span", { children: t.copied })
1302
+ ] }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
1303
+ /* @__PURE__ */ jsx11(Copy, { className: "uf-w-3 uf-h-3" }),
1304
+ /* @__PURE__ */ jsx11("span", { children: t.copyAddress })
1305
+ ] })
1306
+ }
1307
+ )
1308
+ ] }),
1309
+ loading ? /* @__PURE__ */ jsx11("div", { className: "uf-bg-secondary uf-rounded-lg uf-px-3 uf-py-2.5 uf-text-xs uf-text-muted-foreground uf-animate-pulse", children: t.loading }) : error ? /* @__PURE__ */ jsx11("div", { className: "uf-bg-secondary uf-rounded-lg uf-px-3 uf-py-2.5 uf-text-xs uf-text-red-400", children: error }) : /* @__PURE__ */ jsx11("div", { className: "uf-bg-secondary uf-rounded-lg uf-px-3 uf-py-2.5 uf-text-xs uf-font-mono uf-break-all", children: depositAddress || t.noAddressAvailable })
1310
+ ] }),
1311
+ copyButtonMode === "fullWidth" && /* @__PURE__ */ jsx11(
1312
+ Button,
1313
+ {
1314
+ onClick: handleCopyAddress,
1315
+ disabled: loading || !depositAddress,
1316
+ className: "uf-w-full uf-bg-secondary hover:uf-bg-accent uf-text-foreground uf-rounded-lg uf-h-9 uf-text-sm uf-font-medium disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
1317
+ children: copied ? /* @__PURE__ */ jsxs6(Fragment2, { children: [
1318
+ /* @__PURE__ */ jsx11(Check2, { className: "uf-w-4 uf-h-4 uf-mr-2" }),
1319
+ t.copied
1320
+ ] }) : /* @__PURE__ */ jsxs6(Fragment2, { children: [
1321
+ /* @__PURE__ */ jsx11(Copy, { className: "uf-w-4 uf-h-4 uf-mr-2" }),
1322
+ t.copyAddress
1323
+ ] })
1324
+ }
1325
+ ),
1326
+ /* @__PURE__ */ jsxs6("div", { className: "uf-border-t uf-border-border", children: [
1327
+ /* @__PURE__ */ jsxs6(
1328
+ "button",
1329
+ {
1330
+ onClick: () => setDetailsExpanded(!detailsExpanded),
1331
+ className: "uf-w-full uf-flex uf-items-center uf-justify-between uf-py-2.5",
1332
+ children: [
1333
+ /* @__PURE__ */ jsxs6("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
1334
+ /* @__PURE__ */ jsx11("div", { className: "uf-bg-secondary uf-rounded-full uf-p-1", children: /* @__PURE__ */ jsx11(DollarSign, { className: "uf-w-3 uf-h-3" }) }),
1335
+ /* @__PURE__ */ jsxs6("span", { className: "uf-text-xs", children: [
1336
+ t.priceImpact.label,
1337
+ ":",
1338
+ " ",
1339
+ /* @__PURE__ */ jsxs6("span", { className: "uf-text-foreground", children: [
1340
+ priceImpact.toFixed(2),
1341
+ "%"
1342
+ ] })
1343
+ ] }),
1344
+ /* @__PURE__ */ jsxs6(Tooltip, { children: [
1345
+ /* @__PURE__ */ jsx11(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx11(
1346
+ "span",
1347
+ {
1348
+ className: "uf-inline-flex uf-cursor-pointer uf-text-muted-foreground uf-transition-colors hover:uf-text-foreground",
1349
+ onClick: (e) => e.stopPropagation(),
1350
+ onKeyDown: (e) => {
1351
+ if (e.key === "Enter" || e.key === " ") {
1352
+ e.stopPropagation();
1353
+ }
1354
+ },
1355
+ tabIndex: 0,
1356
+ role: "button",
1357
+ "aria-label": "Price impact information",
1358
+ children: /* @__PURE__ */ jsx11(Info, { className: "uf-w-3 uf-h-3" })
1359
+ }
1360
+ ) }),
1361
+ /* @__PURE__ */ jsx11(
1362
+ TooltipContent,
1363
+ {
1364
+ side: "top",
1365
+ align: "center",
1366
+ className: "uf-max-w-[240px]",
1367
+ children: /* @__PURE__ */ jsx11("p", { children: t.priceImpact.tooltip })
1368
+ }
1369
+ )
1370
+ ] })
1371
+ ] }),
1372
+ detailsExpanded ? /* @__PURE__ */ jsx11(ChevronUp2, { className: "uf-w-4 uf-h-4 uf-text-muted-foreground" }) : /* @__PURE__ */ jsx11(ChevronDown2, { className: "uf-w-4 uf-h-4 uf-text-muted-foreground" })
1373
+ ]
1374
+ }
1375
+ ),
1376
+ detailsExpanded && /* @__PURE__ */ jsxs6("div", { className: "uf-pb-3 uf-space-y-2.5", children: [
1377
+ /* @__PURE__ */ jsxs6("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
1378
+ /* @__PURE__ */ jsx11("div", { className: "uf-bg-secondary uf-rounded-full uf-p-1", children: /* @__PURE__ */ jsx11(ShieldCheck, { className: "uf-w-3 uf-h-3" }) }),
1379
+ /* @__PURE__ */ jsxs6("span", { className: "uf-text-xs", children: [
1380
+ t.slippage.label,
1381
+ ":",
1382
+ " ",
1383
+ /* @__PURE__ */ jsxs6("span", { className: "uf-text-foreground", children: [
1384
+ t.slippage.auto,
1385
+ " \u2022 ",
1386
+ maxSlippage.toFixed(2),
1387
+ "%"
1388
+ ] })
1389
+ ] }),
1390
+ /* @__PURE__ */ jsxs6(Tooltip, { children: [
1391
+ /* @__PURE__ */ jsx11(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx11(
1392
+ "span",
1393
+ {
1394
+ className: "uf-inline-flex uf-cursor-pointer uf-text-muted-foreground uf-transition-colors hover:uf-text-foreground",
1395
+ tabIndex: 0,
1396
+ role: "button",
1397
+ "aria-label": "Slippage information",
1398
+ children: /* @__PURE__ */ jsx11(Info, { className: "uf-w-3 uf-h-3" })
1399
+ }
1400
+ ) }),
1401
+ /* @__PURE__ */ jsx11(
1402
+ TooltipContent,
1403
+ {
1404
+ side: "top",
1405
+ align: "center",
1406
+ className: "uf-max-w-[240px]",
1407
+ children: /* @__PURE__ */ jsx11("p", { children: t.slippage.tooltip })
1408
+ }
1409
+ )
1410
+ ] })
1411
+ ] }),
1412
+ /* @__PURE__ */ jsxs6("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
1413
+ /* @__PURE__ */ jsx11("div", { className: "uf-bg-secondary uf-rounded-full uf-p-1", children: /* @__PURE__ */ jsx11(Clock, { className: "uf-w-3 uf-h-3" }) }),
1414
+ /* @__PURE__ */ jsxs6("span", { className: "uf-text-xs", children: [
1415
+ t.processingTime.label,
1416
+ ":",
1417
+ " ",
1418
+ /* @__PURE__ */ jsx11("span", { className: "uf-text-foreground", children: formatProcessingTime(processingTime) })
1419
+ ] })
1420
+ ] }),
1421
+ /* @__PURE__ */ jsxs6("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
1422
+ /* @__PURE__ */ jsx11("div", { className: "uf-bg-secondary uf-rounded-full uf-p-1", children: /* @__PURE__ */ jsx11(FileText, { className: "uf-w-3 uf-h-3" }) }),
1423
+ /* @__PURE__ */ jsxs6("span", { className: "uf-text-xs", children: [
1424
+ t.help.needHelp,
1425
+ " ",
1426
+ /* @__PURE__ */ jsx11(
1427
+ "a",
1428
+ {
1429
+ href: "#",
1430
+ className: "uf-text-foreground uf-underline hover:uf-text-muted-foreground uf-transition-colors",
1431
+ children: t.help.contactSupport
1432
+ }
1433
+ )
1434
+ ] })
1435
+ ] })
1436
+ ] }),
1437
+ /* @__PURE__ */ jsxs6("div", { className: "uf-flex uf-items-center uf-justify-between uf-text-xs uf-pt-2", children: [
1438
+ /* @__PURE__ */ jsx11(
1439
+ "a",
1440
+ {
1441
+ href: "#",
1442
+ className: "uf-text-muted-foreground uf-underline hover:uf-text-foreground uf-transition-colors",
1443
+ children: t.terms.termsApply
1444
+ }
1445
+ ),
1446
+ depositExecutions.length > 1 && /* @__PURE__ */ jsxs6(
1447
+ "button",
1448
+ {
1449
+ onClick: () => setDepositsModalOpen(true),
1450
+ className: "uf-flex uf-items-center uf-gap-1 uf-text-muted-foreground hover:uf-text-foreground uf-transition-colors uf-animate-in uf-fade-in uf-slide-in-from-right-8 uf-duration-1000",
1451
+ children: [
1452
+ /* @__PURE__ */ jsx11(Clock, { className: "uf-w-3.5 uf-h-3.5" }),
1453
+ "Track deposits (",
1454
+ depositExecutions.length,
1455
+ ")",
1456
+ /* @__PURE__ */ jsx11(ChevronRight, { className: "uf-w-3 uf-h-3" })
1457
+ ]
1458
+ }
1459
+ )
1460
+ ] })
1461
+ ] }),
1462
+ depositExecutions.length === 1 && /* @__PURE__ */ jsx11("div", { className: "uf-fixed uf-bottom-4 uf-left-1/2 uf--translate-x-1/2 uf-w-[360px] uf-max-w-[calc(100vw-2rem)] uf-z-[100]", children: /* @__PURE__ */ jsx11(
1463
+ DepositSuccessToast,
1464
+ {
1465
+ depositTx: depositExecutions[0].transaction_hash,
1466
+ completionTx: depositExecutions[0].destination_transaction_hashes?.[0] || (depositExecutions[0].status === "succeeded" /* SUCCEEDED */ ? depositExecutions[0].transaction_hash : void 0),
1467
+ orderSubmittedAt: depositExecutions[0].created_at || (/* @__PURE__ */ new Date()).toISOString(),
1468
+ orderFilledAt: depositExecutions[0].updated_at || (/* @__PURE__ */ new Date()).toISOString(),
1469
+ explorerUrl: depositExecutions[0].explorer_url,
1470
+ completionExplorerUrl: depositExecutions[0].destination_transaction_hashes?.[0] ? `https://polygonscan.com/tx/${depositExecutions[0].destination_transaction_hashes[0]}` : depositExecutions[0].status === "succeeded" /* SUCCEEDED */ ? depositExecutions[0].explorer_url : void 0,
1471
+ status: depositExecutions[0].status,
1472
+ tokenIconUrl: depositExecutions[0].source_token_metadata?.icon_url,
1473
+ onClose: () => setDepositExecutions([])
1474
+ },
1475
+ depositExecutions[0].id
1476
+ ) }),
1477
+ /* @__PURE__ */ jsx11(
1478
+ DepositsModal,
1479
+ {
1480
+ open: depositsModalOpen,
1481
+ onOpenChange: setDepositsModalOpen,
1482
+ executions: depositExecutions,
1483
+ userId,
1484
+ publishableKey,
1485
+ themeClass
1486
+ }
1487
+ )
1488
+ ] }) });
1489
+ }
1490
+
1491
+ // src/components/deposits/TransferCrypto.tsx
1492
+ import { jsx as jsx12 } from "react/jsx-runtime";
1493
+ function TransferCrypto(props) {
1494
+ return /* @__PURE__ */ jsx12(
1495
+ TransferCryptoBase,
1496
+ {
1497
+ ...props,
1498
+ layoutVariant: "horizontal",
1499
+ showDetailedDropdowns: false
1500
+ }
1501
+ );
1502
+ }
1503
+
1504
+ // src/components/deposits/BuyWithCard.tsx
1505
+ import { useState as useState4, useEffect as useEffect4 } from "react";
1506
+ import { ChevronDown as ChevronDown3, ChevronRight as ChevronRight2 } from "lucide-react";
1507
+
1508
+ // src/components/deposits/CurrencyModal.tsx
1509
+ import { useState as useState3 } from "react";
1510
+ import { Search } from "lucide-react";
1511
+
1512
+ // src/components/currency/CurrencyListItem.tsx
1513
+ import { Check as Check3 } from "lucide-react";
1514
+ import { jsx as jsx13, jsxs as jsxs7 } from "react/jsx-runtime";
1515
+ function CurrencyListItem({
1516
+ currency,
1517
+ isSelected,
1518
+ onSelect
1519
+ }) {
1520
+ return /* @__PURE__ */ jsxs7(
1521
+ "button",
1522
+ {
1523
+ onClick: () => onSelect(currency.currency_code),
1524
+ className: "uf-w-full uf-bg-secondary hover:uf-bg-accent uf-transition-colors uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-justify-between uf-group",
1525
+ children: [
1526
+ /* @__PURE__ */ jsxs7("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
1527
+ /* @__PURE__ */ jsx13("div", { className: "uf-w-10 uf-h-10 uf-flex uf-items-center uf-justify-center uf-flex-shrink-0 uf-rounded-full uf-overflow-hidden uf-bg-card", children: /* @__PURE__ */ jsx13(
1528
+ "img",
1529
+ {
1530
+ src: currency.icon_url,
1531
+ alt: currency.name,
1532
+ width: 40,
1533
+ height: 40,
1534
+ className: "uf-w-full uf-h-full uf-object-cover uf-rounded-full"
1535
+ }
1536
+ ) }),
1537
+ /* @__PURE__ */ jsxs7("div", { className: "uf-text-left", children: [
1538
+ /* @__PURE__ */ jsx13("div", { className: "uf-text-sm uf-font-normal uf-text-foreground", children: currency.name }),
1539
+ /* @__PURE__ */ jsx13("div", { className: "uf-text-xs uf-text-muted-foreground uf-font-light", children: currency.currency_code.toUpperCase() })
1540
+ ] })
1541
+ ] }),
1542
+ isSelected && /* @__PURE__ */ jsx13(Check3, { className: "uf-w-4 uf-h-4 uf-text-foreground" })
1543
+ ]
1544
+ }
1545
+ );
1546
+ }
1547
+
1548
+ // src/components/currency/CurrencyListSection.tsx
1549
+ import { Fragment as Fragment3, jsx as jsx14, jsxs as jsxs8 } from "react/jsx-runtime";
1550
+ function CurrencyListSection({
1551
+ title,
1552
+ currencies,
1553
+ selectedCurrency,
1554
+ onSelect
1555
+ }) {
1556
+ if (currencies.length === 0) return null;
1557
+ return /* @__PURE__ */ jsxs8(Fragment3, { children: [
1558
+ /* @__PURE__ */ jsx14("div", { className: "uf-px-1 uf-pb-2", children: /* @__PURE__ */ jsx14("h3", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: title }) }),
1559
+ currencies.map((currency) => /* @__PURE__ */ jsx14(
1560
+ CurrencyListItem,
1561
+ {
1562
+ currency,
1563
+ isSelected: selectedCurrency.toLowerCase() === currency.currency_code.toLowerCase(),
1564
+ onSelect
1565
+ },
1566
+ currency.currency_code
1567
+ ))
1568
+ ] });
1569
+ }
1570
+
1571
+ // src/components/deposits/CurrencyModal.tsx
1572
+ import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
1573
+ function CurrencyModal({
1574
+ open,
1575
+ onOpenChange,
1576
+ currencies,
1577
+ preferredCurrencyCodes,
1578
+ selectedCurrency,
1579
+ onSelectCurrency,
1580
+ themeClass = ""
1581
+ }) {
1582
+ const [searchQuery, setSearchQuery] = useState3("");
1583
+ const preferredCurrencies = preferredCurrencyCodes.map(
1584
+ (code) => currencies.find(
1585
+ (currency) => currency.currency_code.toLowerCase() === code.toLowerCase()
1586
+ )
1587
+ ).filter((currency) => currency !== void 0);
1588
+ const otherCurrencies = currencies.filter(
1589
+ (currency) => !preferredCurrencyCodes.includes(currency.currency_code.toLowerCase())
1590
+ );
1591
+ const filterCurrencies = (currencyList) => {
1592
+ if (!searchQuery) return currencyList;
1593
+ const query = searchQuery.toLowerCase();
1594
+ return currencyList.filter(
1595
+ (currency) => currency.name.toLowerCase().includes(query) || currency.currency_code.toLowerCase().includes(query)
1596
+ );
1597
+ };
1598
+ const filteredPreferred = filterCurrencies(preferredCurrencies);
1599
+ const filteredOther = filterCurrencies(otherCurrencies);
1600
+ const handleSelect = (currencyCode) => {
1601
+ onSelectCurrency(currencyCode);
1602
+ onOpenChange(false);
1603
+ setSearchQuery("");
1604
+ };
1605
+ const handleClose = () => {
1606
+ onOpenChange(false);
1607
+ setSearchQuery("");
1608
+ };
1609
+ return /* @__PURE__ */ jsx15(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs9(DialogContent, { className: `sm:uf-max-w-[400px] !uf-bg-card uf-border-secondary uf-text-foreground uf-p-0 uf-gap-0 [&>button]:uf-hidden ${themeClass}`, children: [
1610
+ /* @__PURE__ */ jsx15(
1611
+ DepositHeader,
1612
+ {
1613
+ title: "Currency",
1614
+ showBack: true,
1615
+ onBack: handleClose,
1616
+ onClose: handleClose
1617
+ }
1618
+ ),
1619
+ /* @__PURE__ */ jsx15("div", { children: /* @__PURE__ */ jsxs9("div", { className: "uf-relative", children: [
1620
+ /* @__PURE__ */ jsx15(Search, { className: "uf-absolute uf-left-4 uf-top-1/2 uf--translate-y-1/2 uf-w-4 uf-h-4 uf-text-muted-foreground" }),
1621
+ /* @__PURE__ */ jsx15(
1622
+ "input",
1623
+ {
1624
+ type: "text",
1625
+ value: searchQuery,
1626
+ onChange: (e) => setSearchQuery(e.target.value),
1627
+ placeholder: "Search",
1628
+ className: "uf-w-full uf-bg-secondary uf-rounded-xl uf-pl-11 uf-pr-4 uf-py-2.5 uf-text-sm uf-text-foreground uf-placeholder-muted-foreground uf-outline-none focus:uf-ring-2 focus:uf-ring-ring/30"
1629
+ }
1630
+ )
1631
+ ] }) }),
1632
+ /* @__PURE__ */ jsx15("div", { className: "uf-max-h-[500px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: /* @__PURE__ */ jsxs9("div", { className: "uf-space-y-2", children: [
1633
+ /* @__PURE__ */ jsx15(
1634
+ CurrencyListSection,
1635
+ {
1636
+ title: "Popular currencies",
1637
+ currencies: filteredPreferred,
1638
+ selectedCurrency,
1639
+ onSelect: handleSelect
1640
+ }
1641
+ ),
1642
+ filteredPreferred.length > 0 && filteredOther.length > 0 && /* @__PURE__ */ jsx15("div", { className: "uf-h-2" }),
1643
+ /* @__PURE__ */ jsx15(
1644
+ CurrencyListSection,
1645
+ {
1646
+ title: "All currencies",
1647
+ currencies: filteredOther,
1648
+ selectedCurrency,
1649
+ onSelect: handleSelect
1650
+ }
1651
+ ),
1652
+ filteredPreferred.length === 0 && filteredOther.length === 0 && /* @__PURE__ */ jsx15("div", { className: "uf-text-center uf-py-8 uf-text-muted-foreground uf-text-sm", children: "No currencies found" })
1653
+ ] }) })
1654
+ ] }) });
1655
+ }
1656
+
1657
+ // src/hooks/use-user-ip.ts
1658
+ import { useQuery } from "@tanstack/react-query";
1659
+ async function getIpViaMoonpay(moonpayApiKey) {
1660
+ const url = `https://api.moonpay.com/v3/ip_address?apiKey=${moonpayApiKey}`;
1661
+ const response = await fetch(url);
1662
+ if (!response.ok) {
1663
+ throw new Error(`Moonpay IP API failed: ${response.statusText}`);
1664
+ }
1665
+ const data = await response.json();
1666
+ return {
1667
+ alpha2: data.alpha2.toLowerCase(),
1668
+ state: data.state?.toLowerCase()
1669
+ };
1670
+ }
1671
+ async function getIpViaIpApi() {
1672
+ const url = "https://ipapi.co/json";
1673
+ const response = await fetch(url);
1674
+ if (!response.ok) {
1675
+ throw new Error(`ipapi.co failed: ${response.statusText}`);
1676
+ }
1677
+ const data = await response.json();
1678
+ return {
1679
+ alpha2: data.country_code.toLowerCase(),
1680
+ state: data.region_code?.toLowerCase()
1681
+ };
1682
+ }
1683
+ function useUserIp(moonpayApiKey) {
1684
+ const {
1685
+ data: userIpInfo,
1686
+ isLoading,
1687
+ error
1688
+ } = useQuery({
1689
+ queryKey: ["getUserIpInfo"],
1690
+ queryFn: async () => {
1691
+ if (moonpayApiKey) {
1692
+ try {
1693
+ const moonpayIpData = await getIpViaMoonpay(moonpayApiKey);
1694
+ console.log("IP detected via Moonpay:", moonpayIpData);
1695
+ return moonpayIpData;
1696
+ } catch (error2) {
1697
+ console.warn("Moonpay IP API failed, trying fallback:", error2);
1698
+ }
1699
+ }
1700
+ try {
1701
+ const ipApiData = await getIpViaIpApi();
1702
+ console.log("IP detected via ipapi.co:", ipApiData);
1703
+ return ipApiData;
1704
+ } catch (ipApiError) {
1705
+ console.error("All IP detection methods failed:", ipApiError);
1706
+ throw ipApiError;
1707
+ }
1708
+ },
1709
+ // Cache configuration to reduce API calls
1710
+ refetchOnMount: false,
1711
+ refetchOnReconnect: true,
1712
+ refetchOnWindowFocus: false,
1713
+ // Optional: Increase cache duration to 1 hour for even better rate limit protection
1714
+ staleTime: 1e3 * 60 * 60,
1715
+ // 1 hour - data considered fresh for 1 hour
1716
+ gcTime: 1e3 * 60 * 60 * 24
1717
+ // 24 hours - keep in cache for 24 hours
1718
+ });
1719
+ return {
1720
+ userIpInfo,
1721
+ isLoading,
1722
+ error
1723
+ };
1724
+ }
1725
+
1726
+ // src/components/deposits/BuyWithCard.tsx
1727
+ import { jsx as jsx16, jsxs as jsxs10 } from "react/jsx-runtime";
1728
+ var t2 = i18n.buyWithCard;
1729
+ var QUICK_AMOUNTS = [100, 500, 1e3];
1730
+ function getCurrencySymbol(currencyCode) {
1731
+ try {
1732
+ return new Intl.NumberFormat("en", {
1733
+ style: "currency",
1734
+ currency: currencyCode.toUpperCase(),
1735
+ minimumFractionDigits: 0,
1736
+ maximumFractionDigits: 0
1737
+ }).format(0).replace(/\d/g, "").trim();
1738
+ } catch {
1739
+ return currencyCode.toUpperCase();
1740
+ }
1741
+ }
1742
+ function BuyWithCard({
1743
+ userId,
1744
+ publishableKey,
1745
+ view: externalView,
1746
+ onViewChange,
1747
+ maxAmountUsd = 5e4,
1748
+ accentColor = "#0052FF",
1749
+ destinationTokenSymbol,
1750
+ recipientAddress,
1751
+ destinationChainId,
1752
+ destinationTokenAddress,
1753
+ themeClass = ""
1754
+ }) {
1755
+ const [amount, setAmount] = useState4("500.00");
1756
+ const [currency, setCurrency] = useState4("usd");
1757
+ const [showCurrencyModal, setShowCurrencyModal] = useState4(false);
1758
+ const [quotes, setQuotes] = useState4([]);
1759
+ const [quotesLoading, setQuotesLoading] = useState4(false);
1760
+ const [quotesError, setQuotesError] = useState4(null);
1761
+ const [internalView, setInternalView] = useState4("amount");
1762
+ const { userIpInfo, isLoading: isLoadingIp } = useUserIp();
1763
+ const [onrampSession, setOnrampSession] = useState4(
1764
+ null
1765
+ );
1766
+ const currentView = externalView ?? internalView;
1767
+ const showQuotesView = currentView === "quotes";
1768
+ const showOnrampView = currentView === "onramp";
1769
+ useEffect4(() => {
1770
+ if (externalView) {
1771
+ setInternalView(externalView);
1772
+ }
1773
+ }, [externalView]);
1774
+ const handleViewChange = (newView) => {
1775
+ setInternalView(newView);
1776
+ if (newView === "quotes") {
1777
+ onViewChange?.(newView, quotes.length);
1778
+ } else {
1779
+ onViewChange?.(newView);
1780
+ }
1781
+ };
1782
+ const [selectedProvider, setSelectedProvider] = useState4(
1783
+ null
1784
+ );
1785
+ const [isAutoSelected, setIsAutoSelected] = useState4(true);
1786
+ const [autoSelectedProvider, setAutoSelectedProvider] = useState4(null);
1787
+ const [hasManualSelection, setHasManualSelection] = useState4(false);
1788
+ const [wallets, setWallets] = useState4([]);
1789
+ const [walletsLoading, setWalletsLoading] = useState4(true);
1790
+ const [countdown, setCountdown] = useState4(60);
1791
+ const [fiatCurrencies, setFiatCurrencies] = useState4([]);
1792
+ const [preferredCurrencyCodes, setPreferredCurrencyCodes] = useState4([]);
1793
+ const [currenciesLoading, setCurrenciesLoading] = useState4(true);
1794
+ const [supportedTokens, setSupportedTokens] = useState4([]);
1795
+ const destinationWallet = getWalletByChainType(wallets, "ethereum");
1796
+ const walletDestinationChainId = destinationWallet?.destination_chain_id;
1797
+ const resolvedDestinationChainId = destinationChainId || walletDestinationChainId;
1798
+ const displayTokenSymbol = destinationTokenSymbol || supportedTokens[0]?.symbol || "USDC";
1799
+ const destinationToken = supportedTokens[0];
1800
+ const destinationChain = destinationToken?.chains.find(
1801
+ (c) => c.chain_id === resolvedDestinationChainId
1802
+ );
1803
+ useEffect4(() => {
1804
+ async function fetchFiatCurrencies() {
1805
+ try {
1806
+ const response = await getFiatCurrencies(publishableKey);
1807
+ setFiatCurrencies(response.data);
1808
+ setPreferredCurrencyCodes(response.preferred || []);
1809
+ } catch (err) {
1810
+ console.error("Error fetching fiat currencies:", err);
1811
+ } finally {
1812
+ setCurrenciesLoading(false);
1813
+ }
1814
+ }
1815
+ fetchFiatCurrencies();
1816
+ }, [publishableKey]);
1817
+ useEffect4(() => {
1818
+ async function fetchWallets() {
1819
+ try {
1820
+ const response = await createEOA(
1821
+ {
1822
+ user_id: userId,
1823
+ recipient_address: recipientAddress,
1824
+ destination_chain_id: destinationChainId,
1825
+ destination_token_address: destinationTokenAddress
1826
+ },
1827
+ publishableKey
1828
+ );
1829
+ setWallets(response.data);
1830
+ } catch (err) {
1831
+ console.error("Error fetching wallets:", err);
1832
+ setQuotesError("Failed to load wallet addresses");
1833
+ } finally {
1834
+ setWalletsLoading(false);
1835
+ }
1836
+ }
1837
+ fetchWallets();
1838
+ }, [userId, recipientAddress, destinationChainId, destinationTokenAddress, publishableKey]);
1839
+ useEffect4(() => {
1840
+ async function fetchSupportedTokens() {
1841
+ try {
1842
+ const response = await getSupportedDepositTokens(publishableKey);
1843
+ setSupportedTokens(response.data);
1844
+ } catch (err) {
1845
+ console.error("Error fetching supported tokens:", err);
1846
+ }
1847
+ }
1848
+ fetchSupportedTokens();
1849
+ }, [publishableKey]);
1850
+ useEffect4(() => {
1851
+ const amountNum = parseFloat(amount);
1852
+ if (isNaN(amountNum) || amountNum <= 0) {
1853
+ setQuotes([]);
1854
+ return;
1855
+ }
1856
+ if (isLoadingIp || !userIpInfo) {
1857
+ return;
1858
+ }
1859
+ if (currency.toLowerCase() === "usd" && amountNum > maxAmountUsd) {
1860
+ setQuotes([]);
1861
+ setQuotesError(
1862
+ `Maximum amount is ${getCurrencySymbol("usd")}${maxAmountUsd.toLocaleString()}`
1863
+ );
1864
+ return;
1865
+ }
1866
+ const timer = setTimeout(() => {
1867
+ fetchQuotes(amountNum);
1868
+ }, 500);
1869
+ return () => clearTimeout(timer);
1870
+ }, [amount, currency, maxAmountUsd, userIpInfo, isLoadingIp, publishableKey]);
1871
+ const fetchQuotes = async (sourceAmount) => {
1872
+ if (!userIpInfo?.alpha2) {
1873
+ setQuotesError("Detecting your location...");
1874
+ return;
1875
+ }
1876
+ setQuotesLoading(true);
1877
+ setQuotesError(null);
1878
+ try {
1879
+ const request = {
1880
+ country_code: userIpInfo.alpha2.toUpperCase(),
1881
+ destination_currency_code: "usdc_polygon",
1882
+ source_amount: sourceAmount.toString(),
1883
+ source_currency_code: currency.toLowerCase()
1884
+ };
1885
+ const response = await getMeldQuotes(request, publishableKey);
1886
+ setQuotes(response.data);
1887
+ if (hasManualSelection && selectedProvider) {
1888
+ const manualProviderStillExists = response.data.find(
1889
+ (q) => q.service_provider === selectedProvider.service_provider
1890
+ );
1891
+ if (manualProviderStillExists) {
1892
+ setSelectedProvider(manualProviderStillExists);
1893
+ const bestProvider = response.data.reduce(
1894
+ (best, current) => current.destination_amount > best.destination_amount ? current : best
1895
+ );
1896
+ if (!autoSelectedProvider) {
1897
+ setAutoSelectedProvider(bestProvider.service_provider);
1898
+ }
1899
+ setIsAutoSelected(
1900
+ manualProviderStillExists.service_provider === autoSelectedProvider
1901
+ );
1902
+ } else {
1903
+ const bestProvider = response.data.reduce(
1904
+ (best, current) => current.destination_amount > best.destination_amount ? current : best
1905
+ );
1906
+ setSelectedProvider(bestProvider);
1907
+ setAutoSelectedProvider(bestProvider.service_provider);
1908
+ setIsAutoSelected(true);
1909
+ setHasManualSelection(false);
1910
+ }
1911
+ } else {
1912
+ if (response.data.length > 0) {
1913
+ const bestProvider = response.data.reduce(
1914
+ (best, current) => current.destination_amount > best.destination_amount ? current : best
1915
+ );
1916
+ setSelectedProvider(bestProvider);
1917
+ setAutoSelectedProvider(bestProvider.service_provider);
1918
+ setIsAutoSelected(true);
1919
+ }
1920
+ }
1921
+ setCountdown(60);
1922
+ } catch (error) {
1923
+ console.error("Failed to fetch quotes:", error);
1924
+ setQuotesError("Failed to fetch quotes");
1925
+ setQuotes([]);
1926
+ } finally {
1927
+ setQuotesLoading(false);
1928
+ }
1929
+ };
1930
+ useEffect4(() => {
1931
+ if (quotes.length === 0) return;
1932
+ const timer = setInterval(() => {
1933
+ setCountdown((prev) => {
1934
+ if (prev <= 1) {
1935
+ const amountNum = parseFloat(amount);
1936
+ if (!isNaN(amountNum) && amountNum > 0) {
1937
+ fetchQuotes(amountNum);
1938
+ }
1939
+ return 60;
1940
+ }
1941
+ return prev - 1;
1942
+ });
1943
+ }, 1e3);
1944
+ return () => clearInterval(timer);
1945
+ }, [quotes.length, amount]);
1946
+ const handleAmountChange = (value) => {
1947
+ const regex = /^\d*\.?\d{0,2}$/;
1948
+ if (regex.test(value) || value === "") {
1949
+ setAmount(value);
1950
+ }
1951
+ };
1952
+ const handleQuickAmount = (quickAmount) => {
1953
+ setAmount(quickAmount.toFixed(2));
1954
+ };
1955
+ const calculateUSDC = () => {
1956
+ if (!selectedProvider) return "0.000000";
1957
+ return selectedProvider.destination_amount.toFixed(6);
1958
+ };
1959
+ const selectedCurrencyData = fiatCurrencies.find(
1960
+ (c) => c.currency_code.toLowerCase() === currency.toLowerCase()
1961
+ );
1962
+ const handleContinue = async () => {
1963
+ if (!selectedProvider) return;
1964
+ try {
1965
+ const wallet = getWalletByChainType(wallets, "ethereum");
1966
+ if (!wallet?.address) {
1967
+ setQuotesError("Wallet address not available");
1968
+ return;
1969
+ }
1970
+ const sessionRequest = {
1971
+ service_provider: selectedProvider.service_provider,
1972
+ country_code: selectedProvider.country_code.toUpperCase(),
1973
+ destination_currency_code: selectedProvider.destination_currency_code,
1974
+ source_currency_code: selectedProvider.source_currency_code,
1975
+ wallet_address: wallet.address,
1976
+ source_amount: amount
1977
+ };
1978
+ const session = await createMeldSession(sessionRequest, publishableKey);
1979
+ setOnrampSession({
1980
+ provider: selectedProvider,
1981
+ sourceCurrency: currency,
1982
+ sourceAmount: amount
1983
+ });
1984
+ window.open(session.widget_url, "_blank");
1985
+ handleViewChange("onramp");
1986
+ } catch (error) {
1987
+ console.error("Failed to create session:", error);
1988
+ setQuotesError("Failed to start payment flow");
1989
+ }
1990
+ };
1991
+ const getProviderBadges = (quote, allQuotes) => {
1992
+ const badges = [];
1993
+ const maxDestination = Math.max(
1994
+ ...allQuotes.map((q) => q.destination_amount)
1995
+ );
1996
+ if (quote.destination_amount === maxDestination) {
1997
+ badges.push("Best price");
1998
+ }
1999
+ return badges;
2000
+ };
2001
+ const sortedQuotes = [...quotes].sort(
2002
+ (a, b) => b.destination_amount - a.destination_amount
2003
+ );
2004
+ const currencySymbol = getCurrencySymbol(currency);
2005
+ return /* @__PURE__ */ jsxs10("div", { className: "uf-pb-1 uf-relative uf-overflow-hidden", children: [
2006
+ /* @__PURE__ */ jsxs10(
2007
+ "div",
2008
+ {
2009
+ className: `uf-transition-all uf-duration-300 ${showQuotesView || showOnrampView ? "uf-opacity-0 uf-pointer-events-none uf-absolute uf-inset-0" : "uf-opacity-100"}`,
2010
+ children: [
2011
+ /* @__PURE__ */ jsxs10("div", { className: "uf-mb-6 uf-pt-4", children: [
2012
+ /* @__PURE__ */ jsx16("div", { className: "uf-flex uf-justify-center uf-mb-4", children: /* @__PURE__ */ jsxs10(
2013
+ "button",
2014
+ {
2015
+ onClick: () => setShowCurrencyModal(true),
2016
+ disabled: currenciesLoading,
2017
+ className: "uf-flex uf-items-center uf-gap-1.5 uf-px-3 uf-py-1.5 uf-rounded-lg uf-bg-secondary hover:uf-bg-accent uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
2018
+ children: [
2019
+ selectedCurrencyData && /* @__PURE__ */ jsx16("div", { className: "uf-w-4 uf-h-4 uf-rounded-full uf-overflow-hidden uf-flex uf-items-center uf-justify-center", children: /* @__PURE__ */ jsx16(
2020
+ "img",
2021
+ {
2022
+ src: selectedCurrencyData.icon_url,
2023
+ alt: selectedCurrencyData.name,
2024
+ width: 16,
2025
+ height: 16,
2026
+ className: "uf-w-full uf-h-full uf-object-cover uf-rounded-full"
2027
+ }
2028
+ ) }),
2029
+ /* @__PURE__ */ jsx16("span", { className: "uf-text-sm uf-text-foreground uf-font-medium", children: currency.toUpperCase() }),
2030
+ /* @__PURE__ */ jsx16(ChevronDown3, { className: "uf-w-3.5 uf-h-3.5 uf-text-muted-foreground" })
2031
+ ]
2032
+ }
2033
+ ) }),
2034
+ /* @__PURE__ */ jsxs10("div", { className: "uf-text-center uf-mb-4", children: [
2035
+ /* @__PURE__ */ jsx16("div", { className: "uf-flex uf-items-center uf-justify-center uf-mb-2 uf-px-8", children: /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-items-center uf-max-w-full", children: [
2036
+ /* @__PURE__ */ jsx16(
2037
+ "span",
2038
+ {
2039
+ className: "uf-font-normal uf-text-foreground uf-flex-shrink-0 uf-mr-1",
2040
+ style: {
2041
+ fontSize: `${Math.max(3.75 - amount.length * 0.15, 2)}rem`
2042
+ },
2043
+ children: currencySymbol
2044
+ }
2045
+ ),
2046
+ /* @__PURE__ */ jsx16(
2047
+ "input",
2048
+ {
2049
+ type: "text",
2050
+ value: amount,
2051
+ onChange: (e) => handleAmountChange(e.target.value),
2052
+ className: "uf-font-normal uf-text-foreground uf-bg-transparent uf-text-left uf-outline-none uf-min-w-[1ch]",
2053
+ placeholder: "0",
2054
+ style: {
2055
+ caretColor: "currentColor",
2056
+ fontSize: `${Math.max(3.75 - amount.length * 0.15, 2)}rem`,
2057
+ width: `${Math.max(amount.length || 1, 1)}ch`
2058
+ }
2059
+ }
2060
+ )
2061
+ ] }) }),
2062
+ quotesLoading ? /* @__PURE__ */ jsx16("div", { className: "uf-flex uf-justify-center", children: /* @__PURE__ */ jsx16("div", { className: "uf-h-4 uf-bg-muted uf-rounded uf-w-40 uf-animate-pulse" }) }) : /* @__PURE__ */ jsxs10("div", { className: "uf-text-sm uf-text-muted-foreground uf-font-normal", children: [
2063
+ calculateUSDC(),
2064
+ " USDC (Perps)"
2065
+ ] })
2066
+ ] }),
2067
+ /* @__PURE__ */ jsx16("div", { className: "uf-flex uf-gap-3 uf-justify-center", children: QUICK_AMOUNTS.map((quickAmount) => /* @__PURE__ */ jsxs10(
2068
+ "button",
2069
+ {
2070
+ onClick: () => handleQuickAmount(quickAmount),
2071
+ className: "uf-w-24 uf-py-2 uf-rounded-lg uf-bg-secondary hover:uf-bg-accent uf-transition-colors uf-text-sm uf-text-foreground uf-font-medium",
2072
+ children: [
2073
+ getCurrencySymbol(currency),
2074
+ quickAmount.toLocaleString()
2075
+ ]
2076
+ },
2077
+ quickAmount
2078
+ )) })
2079
+ ] }),
2080
+ /* @__PURE__ */ jsxs10("div", { className: "uf-mb-6", children: [
2081
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-items-center uf-justify-between uf-text-xs uf-font-medium uf-mb-2 uf-px-1", children: [
2082
+ /* @__PURE__ */ jsx16("span", { className: "uf-text-foreground", children: "Provider" }),
2083
+ quotes.length > 0 && !quotesLoading && /* @__PURE__ */ jsxs10("span", { className: "uf-text-[10px] uf-text-foreground uf-font-normal", children: [
2084
+ "Refreshing in ",
2085
+ countdown,
2086
+ "s"
2087
+ ] })
2088
+ ] }),
2089
+ /* @__PURE__ */ jsx16(
2090
+ "button",
2091
+ {
2092
+ onClick: () => handleViewChange("quotes"),
2093
+ disabled: quotesLoading || quotes.length === 0,
2094
+ className: "uf-w-full uf-bg-secondary hover:uf-bg-accent uf-transition-colors uf-rounded-xl uf-p-4 uf-group disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
2095
+ children: quotesLoading ? /* @__PURE__ */ jsxs10("div", { className: "uf-text-left uf-w-full uf-animate-pulse", children: [
2096
+ /* @__PURE__ */ jsx16("div", { className: "uf-h-3 uf-bg-muted uf-rounded uf-w-28 uf-mb-3" }),
2097
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
2098
+ /* @__PURE__ */ jsx16("div", { className: "uf-w-8 uf-h-8 uf-bg-muted uf-rounded-full" }),
2099
+ /* @__PURE__ */ jsx16("div", { className: "uf-h-4 uf-bg-muted uf-rounded uf-w-32" })
2100
+ ] })
2101
+ ] }) : /* @__PURE__ */ jsxs10("div", { className: "uf-w-full uf-text-left", children: [
2102
+ isAutoSelected && /* @__PURE__ */ jsx16("div", { className: "uf-text-xs uf-text-muted-foreground uf-font-normal uf-mb-2", children: "Auto-picked for you" }),
2103
+ selectedProvider && /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
2104
+ /* @__PURE__ */ jsx16(
2105
+ "img",
2106
+ {
2107
+ src: selectedProvider.icon_url,
2108
+ alt: selectedProvider.service_provider,
2109
+ width: 32,
2110
+ height: 32,
2111
+ className: "uf-rounded-full uf-flex-shrink-0"
2112
+ }
2113
+ ),
2114
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex-1 uf-min-w-0", children: [
2115
+ /* @__PURE__ */ jsx16("div", { className: "uf-text-sm uf-text-foreground uf-font-medium", children: selectedProvider.service_provider_display_name }),
2116
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: [
2117
+ isAutoSelected && /* @__PURE__ */ jsx16("span", { className: "uf-text-[10px] uf-text-green-400 uf-font-normal", children: "Best price" }),
2118
+ isAutoSelected && selectedProvider.low_kyc === false && /* @__PURE__ */ jsx16("span", { className: "uf-text-[10px] uf-text-muted-foreground", children: "\u2022" }),
2119
+ selectedProvider.low_kyc === false && /* @__PURE__ */ jsx16("span", { className: "uf-text-[10px] uf-text-muted-foreground uf-font-normal", children: "No document upload" })
2120
+ ] })
2121
+ ] }),
2122
+ quotes.length > 0 && /* @__PURE__ */ jsx16(ChevronRight2, { className: "uf-w-4 uf-h-4 uf-text-muted-foreground group-hover:uf-text-foreground uf-transition-colors uf-flex-shrink-0" })
2123
+ ] })
2124
+ ] })
2125
+ }
2126
+ ),
2127
+ quotesError && /* @__PURE__ */ jsx16("div", { className: "uf-text-xs uf-text-red-400 uf-mt-2 uf-px-1", children: quotesError })
2128
+ ] }),
2129
+ /* @__PURE__ */ jsx16(
2130
+ "button",
2131
+ {
2132
+ onClick: handleContinue,
2133
+ disabled: quotesLoading || walletsLoading || isLoadingIp || !selectedProvider || parseFloat(amount) <= 0 || currency.toLowerCase() === "usd" && parseFloat(amount) > maxAmountUsd,
2134
+ style: {
2135
+ backgroundColor: accentColor
2136
+ },
2137
+ className: "uf-w-full disabled:uf-cursor-not-allowed disabled:!uf-bg-muted uf-text-white uf-rounded-xl uf-py-4 uf-font-medium uf-text-base uf-transition-all hover:uf-opacity-90 disabled:uf-opacity-50 disabled:uf-text-muted-foreground",
2138
+ children: isLoadingIp ? "Detecting location..." : walletsLoading ? "Loading..." : "Continue"
2139
+ }
2140
+ )
2141
+ ]
2142
+ }
2143
+ ),
2144
+ /* @__PURE__ */ jsx16(
2145
+ "div",
2146
+ {
2147
+ className: `uf-transition-all uf-duration-300 ${showQuotesView && !showOnrampView ? "uf-opacity-100" : "uf-opacity-0 uf-pointer-events-none uf-absolute uf-inset-0"}`,
2148
+ children: /* @__PURE__ */ jsx16("div", { className: "uf-space-y-2 uf-pt-2", children: sortedQuotes.map((quote, index) => {
2149
+ const badges = getProviderBadges(quote, sortedQuotes);
2150
+ const displayName = quote.service_provider_display_name;
2151
+ const isSelected = selectedProvider?.service_provider === quote.service_provider;
2152
+ return /* @__PURE__ */ jsxs10(
2153
+ "button",
2154
+ {
2155
+ onClick: () => {
2156
+ setSelectedProvider(quote);
2157
+ setHasManualSelection(true);
2158
+ setIsAutoSelected(
2159
+ quote.service_provider === autoSelectedProvider
2160
+ );
2161
+ handleViewChange("amount");
2162
+ },
2163
+ className: `uf-w-full uf-bg-secondary hover:uf-bg-accent uf-transition-colors uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-justify-between uf-group ${isSelected ? "uf-ring-2 uf-ring-inset uf-ring-primary" : ""}`,
2164
+ children: [
2165
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
2166
+ /* @__PURE__ */ jsx16("div", { className: "uf-w-10 uf-h-10 uf-flex uf-items-center uf-justify-center uf-flex-shrink-0", children: /* @__PURE__ */ jsx16(
2167
+ "img",
2168
+ {
2169
+ src: quote.icon_url,
2170
+ alt: displayName,
2171
+ width: 40,
2172
+ height: 40,
2173
+ className: "uf-rounded-full"
2174
+ }
2175
+ ) }),
2176
+ /* @__PURE__ */ jsxs10("div", { className: "uf-text-left", children: [
2177
+ /* @__PURE__ */ jsx16("div", { className: "uf-text-sm uf-font-medium uf-text-foreground", children: displayName }),
2178
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-0.5", children: [
2179
+ badges.map((badge, i) => /* @__PURE__ */ jsxs10(
2180
+ "span",
2181
+ {
2182
+ className: "uf-text-[10px] uf-text-green-400 uf-font-normal",
2183
+ children: [
2184
+ badge,
2185
+ i < badges.length - 1 && ","
2186
+ ]
2187
+ },
2188
+ i
2189
+ )),
2190
+ quote.low_kyc === false && badges.length > 0 && /* @__PURE__ */ jsx16("span", { className: "uf-text-[10px] uf-text-muted-foreground", children: "\u2022" }),
2191
+ quote.low_kyc === false && /* @__PURE__ */ jsx16("span", { className: "uf-text-[10px] uf-text-muted-foreground uf-font-normal", children: "No document upload" })
2192
+ ] })
2193
+ ] })
2194
+ ] }),
2195
+ /* @__PURE__ */ jsxs10("div", { className: "uf-text-right", children: [
2196
+ /* @__PURE__ */ jsxs10("div", { className: "uf-text-sm uf-font-medium uf-text-foreground", children: [
2197
+ quote.destination_amount.toFixed(2),
2198
+ " USDC"
2199
+ ] }),
2200
+ /* @__PURE__ */ jsxs10("div", { className: "uf-text-xs uf-text-muted-foreground uf-font-normal", children: [
2201
+ currencySymbol,
2202
+ " ",
2203
+ amount
2204
+ ] })
2205
+ ] })
2206
+ ]
2207
+ },
2208
+ index
2209
+ );
2210
+ }) })
2211
+ }
2212
+ ),
2213
+ /* @__PURE__ */ jsx16(
2214
+ "div",
2215
+ {
2216
+ className: `uf-transition-all uf-duration-300 ${showOnrampView ? "uf-opacity-100" : "uf-opacity-0 uf-pointer-events-none uf-absolute uf-inset-0"}`,
2217
+ children: onrampSession && /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-flex-col uf-items-center uf-pt-6 uf-pb-4 uf-px-2", children: [
2218
+ /* @__PURE__ */ jsx16("div", { className: "uf-mb-6", children: /* @__PURE__ */ jsx16(
2219
+ "img",
2220
+ {
2221
+ src: onrampSession.provider.icon_url,
2222
+ alt: onrampSession.provider.service_provider_display_name,
2223
+ width: 64,
2224
+ height: 64,
2225
+ className: "uf-rounded-2xl"
2226
+ }
2227
+ ) }),
2228
+ /* @__PURE__ */ jsx16("h2", { className: "uf-text-xl uf-font-medium uf-text-foreground uf-mb-2", children: t2.onramp.completeTransaction.replace(
2229
+ "{{provider}}",
2230
+ onrampSession.provider.service_provider_display_name
2231
+ ) }),
2232
+ /* @__PURE__ */ jsx16("p", { className: "uf-text-sm uf-text-muted-foreground uf-mb-8", children: t2.onramp.canCloseModal }),
2233
+ /* @__PURE__ */ jsx16("div", { className: "uf-w-full uf-bg-secondary uf-rounded-xl uf-p-4 uf-mb-4", children: /* @__PURE__ */ jsxs10("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
2234
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex-1 uf-flex uf-flex-col uf-items-center", children: [
2235
+ /* @__PURE__ */ jsx16("div", { className: "uf-flex uf-items-center uf-gap-2 uf-mb-1", children: /* @__PURE__ */ jsx16(
2236
+ "img",
2237
+ {
2238
+ src: getIconUrl(
2239
+ `/icons/currencies/${onrampSession.sourceCurrency.toLowerCase()}.svg`
2240
+ ),
2241
+ alt: onrampSession.sourceCurrency.toUpperCase(),
2242
+ width: 28,
2243
+ height: 28,
2244
+ className: "uf-rounded-full"
2245
+ }
2246
+ ) }),
2247
+ /* @__PURE__ */ jsx16("span", { className: "uf-text-[10px] uf-text-muted-foreground", children: t2.onramp.youUse }),
2248
+ /* @__PURE__ */ jsx16("span", { className: "uf-text-sm uf-font-medium uf-text-foreground", children: onrampSession.sourceCurrency.toUpperCase() })
2249
+ ] }),
2250
+ /* @__PURE__ */ jsx16("div", { className: "uf-text-muted-foreground uf-flex-shrink-0", children: /* @__PURE__ */ jsx16(ChevronRight2, { className: "uf-w-5 uf-h-5" }) }),
2251
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex-1 uf-flex uf-flex-col uf-items-center", children: [
2252
+ /* @__PURE__ */ jsx16("div", { className: "uf-flex uf-items-center uf-gap-2 uf-mb-1", children: /* @__PURE__ */ jsxs10("div", { className: "uf-relative", children: [
2253
+ /* @__PURE__ */ jsx16(
2254
+ "img",
2255
+ {
2256
+ src: getIconUrl("/icons/tokens/usdc.svg"),
2257
+ alt: "USDC",
2258
+ width: 28,
2259
+ height: 28,
2260
+ className: "uf-rounded-full"
2261
+ }
2262
+ ),
2263
+ /* @__PURE__ */ jsx16(
2264
+ "img",
2265
+ {
2266
+ src: getIconUrl("/icons/networks/polygon.svg"),
2267
+ alt: "Polygon",
2268
+ width: 14,
2269
+ height: 14,
2270
+ className: "uf-absolute uf--bottom-0.5 uf--right-0.5 uf-rounded-full"
2271
+ }
2272
+ )
2273
+ ] }) }),
2274
+ /* @__PURE__ */ jsx16("span", { className: "uf-text-[10px] uf-text-muted-foreground", children: t2.onramp.youBuy }),
2275
+ /* @__PURE__ */ jsx16("span", { className: "uf-text-sm uf-font-medium uf-text-foreground", children: "USDC" })
2276
+ ] }),
2277
+ /* @__PURE__ */ jsx16("div", { className: "uf-text-muted-foreground uf-flex-shrink-0", children: /* @__PURE__ */ jsx16(ChevronRight2, { className: "uf-w-5 uf-h-5" }) }),
2278
+ /* @__PURE__ */ jsxs10("div", { className: "uf-flex-1 uf-flex uf-flex-col uf-items-center", children: [
2279
+ /* @__PURE__ */ jsx16("div", { className: "uf-flex uf-items-center uf-gap-2 uf-mb-1", children: /* @__PURE__ */ jsxs10("div", { className: "uf-relative", children: [
2280
+ /* @__PURE__ */ jsx16(
2281
+ "img",
2282
+ {
2283
+ src: destinationToken?.icon_url || getIconUrl("/icons/tokens/usdc.svg"),
2284
+ alt: displayTokenSymbol,
2285
+ width: 28,
2286
+ height: 28,
2287
+ className: "uf-rounded-full"
2288
+ }
2289
+ ),
2290
+ destinationChain?.icon_url && /* @__PURE__ */ jsx16(
2291
+ "img",
2292
+ {
2293
+ src: destinationChain.icon_url,
2294
+ alt: destinationChain.chain_name,
2295
+ width: 14,
2296
+ height: 14,
2297
+ className: "uf-absolute uf--bottom-0.5 uf--right-0.5 uf-rounded-full"
2298
+ }
2299
+ )
2300
+ ] }) }),
2301
+ /* @__PURE__ */ jsx16("span", { className: "uf-text-[10px] uf-text-muted-foreground", children: t2.onramp.youReceive }),
2302
+ /* @__PURE__ */ jsx16("span", { className: "uf-text-sm uf-font-medium uf-text-foreground", children: displayTokenSymbol })
2303
+ ] })
2304
+ ] }) }),
2305
+ /* @__PURE__ */ jsx16("div", { className: "uf-w-full uf-bg-secondary uf-rounded-xl uf-p-4", children: /* @__PURE__ */ jsx16("p", { className: "uf-text-xs uf-text-muted-foreground uf-leading-relaxed", children: t2.onramp.intentAddressNote }) })
2306
+ ] })
2307
+ }
2308
+ ),
2309
+ /* @__PURE__ */ jsx16(
2310
+ CurrencyModal,
2311
+ {
2312
+ open: showCurrencyModal,
2313
+ onOpenChange: setShowCurrencyModal,
2314
+ currencies: fiatCurrencies,
2315
+ preferredCurrencyCodes,
2316
+ selectedCurrency: currency,
2317
+ onSelectCurrency: (currencyCode) => {
2318
+ setCurrency(currencyCode.toLowerCase());
2319
+ },
2320
+ themeClass
2321
+ }
2322
+ )
2323
+ ] });
2324
+ }
2325
+
2326
+ // src/components/deposits/buttons/TransferCryptoButton.tsx
2327
+ import { Zap, ChevronRight as ChevronRight3 } from "lucide-react";
2328
+ import { jsx as jsx17, jsxs as jsxs11 } from "react/jsx-runtime";
2329
+ function TransferCryptoButton({
2330
+ onClick,
2331
+ title,
2332
+ subtitle
2333
+ }) {
2334
+ return /* @__PURE__ */ jsxs11(
2335
+ "button",
2336
+ {
2337
+ onClick,
2338
+ className: "uf-w-full uf-bg-secondary hover:uf-bg-accent uf-transition-colors uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-justify-between uf-group",
2339
+ children: [
2340
+ /* @__PURE__ */ jsxs11("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
2341
+ /* @__PURE__ */ jsx17("div", { className: "uf-bg-muted uf-rounded-lg uf-p-2", children: /* @__PURE__ */ jsx17(Zap, { className: "uf-w-5 uf-h-5" }) }),
2342
+ /* @__PURE__ */ jsxs11("div", { className: "uf-text-left", children: [
2343
+ /* @__PURE__ */ jsx17("div", { className: "uf-text-sm uf-font-normal uf-mb-0.5 uf-text-foreground", children: title }),
2344
+ /* @__PURE__ */ jsx17("div", { className: "uf-text-muted-foreground uf-text-xs uf-font-light", children: subtitle })
2345
+ ] })
2346
+ ] }),
2347
+ /* @__PURE__ */ jsxs11("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
2348
+ /* @__PURE__ */ jsxs11("div", { className: "uf-flex uf--space-x-1", children: [
2349
+ /* @__PURE__ */ jsx17(
2350
+ "img",
2351
+ {
2352
+ src: getIconUrl("/icons/networks/ethereum.svg"),
2353
+ alt: "ETH",
2354
+ width: 20,
2355
+ height: 20,
2356
+ className: "uf-rounded-full uf-border-2 uf-border-secondary"
2357
+ }
2358
+ ),
2359
+ /* @__PURE__ */ jsx17(
2360
+ "img",
2361
+ {
2362
+ src: getIconUrl("/icons/networks/optimism.svg"),
2363
+ alt: "OP",
2364
+ width: 20,
2365
+ height: 20,
2366
+ className: "uf-rounded-full uf-border-2 uf-border-secondary"
2367
+ }
2368
+ ),
2369
+ /* @__PURE__ */ jsx17(
2370
+ "img",
2371
+ {
2372
+ src: getIconUrl("/icons/networks/polygon.svg"),
2373
+ alt: "MATIC",
2374
+ width: 20,
2375
+ height: 20,
2376
+ className: "uf-rounded-full uf-border-2 uf-border-secondary"
2377
+ }
2378
+ ),
2379
+ /* @__PURE__ */ jsx17(
2380
+ "img",
2381
+ {
2382
+ src: getIconUrl("/icons/networks/arbitrum.svg"),
2383
+ alt: "ARB",
2384
+ width: 20,
2385
+ height: 20,
2386
+ className: "uf-rounded-full uf-border-2 uf-border-secondary"
2387
+ }
2388
+ ),
2389
+ /* @__PURE__ */ jsx17(
2390
+ "img",
2391
+ {
2392
+ src: getIconUrl("/icons/tokens/usdc.svg"),
2393
+ alt: "USDC",
2394
+ width: 20,
2395
+ height: 20,
2396
+ className: "uf-rounded-full uf-border-2 uf-border-secondary"
2397
+ }
2398
+ ),
2399
+ /* @__PURE__ */ jsx17(
2400
+ "img",
2401
+ {
2402
+ src: getIconUrl("/icons/networks/solana.svg"),
2403
+ alt: "SOL",
2404
+ width: 20,
2405
+ height: 20,
2406
+ className: "uf-rounded-full uf-border-2 uf-border-secondary"
2407
+ }
2408
+ ),
2409
+ /* @__PURE__ */ jsx17(
2410
+ "img",
2411
+ {
2412
+ src: getIconUrl("/icons/tokens/avax.svg"),
2413
+ alt: "AVAX",
2414
+ width: 20,
2415
+ height: 20,
2416
+ className: "uf-rounded-full uf-border-2 uf-border-secondary"
2417
+ }
2418
+ ),
2419
+ /* @__PURE__ */ jsx17(
2420
+ "img",
2421
+ {
2422
+ src: getIconUrl("/icons/networks/bitcoin.svg"),
2423
+ alt: "BTC",
2424
+ width: 20,
2425
+ height: 20,
2426
+ className: "uf-rounded-full uf-border-2 uf-border-secondary"
2427
+ }
2428
+ )
2429
+ ] }),
2430
+ /* @__PURE__ */ jsx17(ChevronRight3, { className: "uf-w-4 uf-h-4 uf-text-muted-foreground group-hover:uf-text-foreground uf-transition-colors" })
2431
+ ] })
2432
+ ]
2433
+ }
2434
+ );
2435
+ }
2436
+
2437
+ // src/components/deposits/buttons/DepositWithCardButton.tsx
2438
+ import { CreditCard, ChevronRight as ChevronRight4 } from "lucide-react";
2439
+ import { jsx as jsx18, jsxs as jsxs12 } from "react/jsx-runtime";
2440
+ function DepositWithCardButton({
2441
+ onClick,
2442
+ title,
2443
+ subtitle
2444
+ }) {
2445
+ return /* @__PURE__ */ jsxs12(
2446
+ "button",
2447
+ {
2448
+ onClick,
2449
+ className: "uf-w-full uf-bg-secondary hover:uf-bg-accent uf-transition-colors uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-justify-between uf-group",
2450
+ children: [
2451
+ /* @__PURE__ */ jsxs12("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
2452
+ /* @__PURE__ */ jsx18("div", { className: "uf-bg-muted uf-rounded-lg uf-p-2", children: /* @__PURE__ */ jsx18(CreditCard, { className: "uf-w-5 uf-h-5" }) }),
2453
+ /* @__PURE__ */ jsxs12("div", { className: "uf-text-left", children: [
2454
+ /* @__PURE__ */ jsx18("div", { className: "uf-text-sm uf-font-normal uf-mb-0.5 uf-text-foreground", children: title }),
2455
+ /* @__PURE__ */ jsx18("div", { className: "uf-text-muted-foreground uf-text-xs uf-font-light", children: subtitle })
2456
+ ] })
2457
+ ] }),
2458
+ /* @__PURE__ */ jsxs12("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
2459
+ /* @__PURE__ */ jsxs12("div", { className: "uf-flex uf-items-center uf-gap-1.5", children: [
2460
+ /* @__PURE__ */ jsx18(
2461
+ "img",
2462
+ {
2463
+ src: getIconUrl("/icons/networks/mastercard.svg"),
2464
+ alt: "Mastercard",
2465
+ width: 32,
2466
+ height: 32,
2467
+ className: "uf-rounded"
2468
+ }
2469
+ ),
2470
+ /* @__PURE__ */ jsx18(
2471
+ "img",
2472
+ {
2473
+ src: getIconUrl("/icons/networks/visa.svg"),
2474
+ alt: "Visa",
2475
+ width: 32,
2476
+ height: 32,
2477
+ className: "uf-rounded"
2478
+ }
2479
+ )
2480
+ ] }),
2481
+ /* @__PURE__ */ jsx18(ChevronRight4, { className: "uf-w-4 uf-h-4 uf-text-muted-foreground group-hover:uf-text-foreground uf-transition-colors" })
2482
+ ] })
2483
+ ]
2484
+ }
2485
+ );
2486
+ }
2487
+
2488
+ // src/components/deposits/buttons/DepositTrackerButton.tsx
2489
+ import { Clock as Clock2, ChevronRight as ChevronRight5 } from "lucide-react";
2490
+ import { jsx as jsx19, jsxs as jsxs13 } from "react/jsx-runtime";
2491
+ function DepositTrackerButton({
2492
+ onClick,
2493
+ title,
2494
+ subtitle,
2495
+ badge
2496
+ }) {
2497
+ return /* @__PURE__ */ jsxs13(
2498
+ "button",
2499
+ {
2500
+ onClick,
2501
+ className: "uf-w-full uf-bg-secondary hover:uf-bg-accent uf-transition-colors uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-justify-between uf-group",
2502
+ children: [
2503
+ /* @__PURE__ */ jsxs13("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
2504
+ /* @__PURE__ */ jsxs13("div", { className: "uf-bg-muted uf-rounded-lg uf-p-2 uf-relative", children: [
2505
+ /* @__PURE__ */ jsx19(Clock2, { className: "uf-w-5 uf-h-5" }),
2506
+ badge !== void 0 && badge > 0 && /* @__PURE__ */ jsx19("div", { className: "uf-absolute -uf-top-1 -uf-right-1 uf-bg-blue-500 uf-text-primary-foreground uf-text-[10px] uf-font-semibold uf-rounded-full uf-min-w-[18px] uf-h-[18px] uf-flex uf-items-center uf-justify-center uf-px-1", children: badge > 99 ? "99+" : badge })
2507
+ ] }),
2508
+ /* @__PURE__ */ jsxs13("div", { className: "uf-text-left", children: [
2509
+ /* @__PURE__ */ jsx19("div", { className: "uf-text-sm uf-font-normal uf-mb-0.5 uf-text-foreground", children: title }),
2510
+ /* @__PURE__ */ jsx19("div", { className: "uf-text-muted-foreground uf-text-xs uf-font-light", children: subtitle })
2511
+ ] })
2512
+ ] }),
2513
+ /* @__PURE__ */ jsx19(ChevronRight5, { className: "uf-w-4 uf-h-4 uf-text-muted-foreground group-hover:uf-text-foreground uf-transition-colors" })
2514
+ ]
2515
+ }
2516
+ );
2517
+ }
2518
+
2519
+ // src/components/deposits/DepositModal.tsx
2520
+ import { Fragment as Fragment4, jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
2521
+ var t3 = i18n.depositModal;
2522
+ function DepositModal({
2523
+ open,
2524
+ onOpenChange,
2525
+ userId,
2526
+ publishableKey,
2527
+ modalTitle,
2528
+ destinationTokenSymbol,
2529
+ recipientAddress,
2530
+ destinationChainId,
2531
+ destinationTokenAddress,
2532
+ hideDepositTracker = false,
2533
+ onDepositSuccess,
2534
+ onDepositError,
2535
+ theme = "dark"
2536
+ }) {
2537
+ const [view, setView] = useState5("main");
2538
+ const [cardView, setCardView] = useState5(
2539
+ "amount"
2540
+ );
2541
+ const [quotesCount, setQuotesCount] = useState5(0);
2542
+ const [depositsModalOpen, setDepositsModalOpen] = useState5(false);
2543
+ const [depositExecutions, setDepositExecutions] = useState5([]);
2544
+ const [resolvedTheme, setResolvedTheme] = useState5(theme === "auto" ? "dark" : theme);
2545
+ useEffect5(() => {
2546
+ if (theme === "auto") {
2547
+ const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
2548
+ setResolvedTheme(mediaQuery.matches ? "dark" : "light");
2549
+ const handler = (e) => {
2550
+ setResolvedTheme(e.matches ? "dark" : "light");
2551
+ };
2552
+ mediaQuery.addEventListener("change", handler);
2553
+ return () => mediaQuery.removeEventListener("change", handler);
2554
+ } else {
2555
+ setResolvedTheme(theme);
2556
+ }
2557
+ }, [theme]);
2558
+ const themeClass = resolvedTheme === "dark" ? "uf-dark" : "";
2559
+ const handleClose = () => {
2560
+ onOpenChange(false);
2561
+ setTimeout(() => {
2562
+ setView("main");
2563
+ setCardView("amount");
2564
+ }, 200);
2565
+ };
2566
+ const handleBack = () => {
2567
+ if (view === "card" && cardView === "quotes") {
2568
+ setCardView("amount");
2569
+ } else if (view === "card" && cardView === "onramp") {
2570
+ setCardView("amount");
2571
+ } else {
2572
+ setView("main");
2573
+ setCardView("amount");
2574
+ }
2575
+ };
2576
+ const handleCardViewChange = (newView, count) => {
2577
+ setCardView(newView);
2578
+ if (count !== void 0) {
2579
+ setQuotesCount(count);
2580
+ }
2581
+ };
2582
+ return /* @__PURE__ */ jsx20(ThemeProvider, { themeClass, children: /* @__PURE__ */ jsxs14(Dialog, { open, onOpenChange: handleClose, children: [
2583
+ /* @__PURE__ */ jsx20(
2584
+ DialogContent,
2585
+ {
2586
+ className: `sm:uf-max-w-[400px] !uf-bg-card uf-border-secondary uf-text-foreground uf-p-0 uf-gap-0 uf-overflow-visible [&>button]:uf-hidden ${themeClass}`,
2587
+ onPointerDownOutside: (e) => e.preventDefault(),
2588
+ onInteractOutside: (e) => e.preventDefault(),
2589
+ children: view === "main" ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
2590
+ /* @__PURE__ */ jsx20(
2591
+ DepositHeader,
2592
+ {
2593
+ title: modalTitle || "Deposit",
2594
+ onClose: handleClose
2595
+ }
2596
+ ),
2597
+ /* @__PURE__ */ jsxs14("div", { className: "uf-pb-4 uf-space-y-3", children: [
2598
+ /* @__PURE__ */ jsx20(
2599
+ TransferCryptoButton,
2600
+ {
2601
+ onClick: () => setView("transfer"),
2602
+ title: t3.transferCrypto.title,
2603
+ subtitle: t3.transferCrypto.subtitle
2604
+ }
2605
+ ),
2606
+ /* @__PURE__ */ jsx20(
2607
+ DepositWithCardButton,
2608
+ {
2609
+ onClick: () => setView("card"),
2610
+ title: t3.depositWithCard.title,
2611
+ subtitle: t3.depositWithCard.subtitle
2612
+ }
2613
+ ),
2614
+ !hideDepositTracker && /* @__PURE__ */ jsx20(
2615
+ DepositTrackerButton,
2616
+ {
2617
+ onClick: () => setDepositsModalOpen(true),
2618
+ title: "Deposit Tracker",
2619
+ subtitle: "Track your deposit progress",
2620
+ badge: depositExecutions.length > 0 ? depositExecutions.length : void 0
2621
+ }
2622
+ )
2623
+ ] })
2624
+ ] }) : view === "transfer" ? /* @__PURE__ */ jsxs14(Fragment4, { children: [
2625
+ /* @__PURE__ */ jsx20(
2626
+ DepositHeader,
2627
+ {
2628
+ title: t3.transferCrypto.title,
2629
+ showBack: true,
2630
+ onBack: handleBack,
2631
+ onClose: handleClose
2632
+ }
2633
+ ),
2634
+ /* @__PURE__ */ jsx20(
2635
+ TransferCrypto,
2636
+ {
2637
+ userId,
2638
+ publishableKey,
2639
+ recipientAddress,
2640
+ destinationChainId,
2641
+ destinationTokenAddress,
2642
+ onExecutionsChange: setDepositExecutions,
2643
+ onDepositSuccess,
2644
+ onDepositError
2645
+ }
2646
+ )
2647
+ ] }) : /* @__PURE__ */ jsxs14(Fragment4, { children: [
2648
+ /* @__PURE__ */ jsx20(
2649
+ DepositHeader,
2650
+ {
2651
+ title: cardView === "quotes" ? t3.quotes : modalTitle || "Deposit",
2652
+ showBack: true,
2653
+ onBack: handleBack,
2654
+ onClose: handleClose,
2655
+ badge: cardView === "quotes" ? { count: quotesCount } : void 0
2656
+ }
2657
+ ),
2658
+ /* @__PURE__ */ jsx20(
2659
+ BuyWithCard,
2660
+ {
2661
+ userId,
2662
+ publishableKey,
2663
+ view: cardView,
2664
+ onViewChange: handleCardViewChange,
2665
+ destinationTokenSymbol,
2666
+ recipientAddress,
2667
+ destinationChainId,
2668
+ destinationTokenAddress,
2669
+ onDepositSuccess,
2670
+ onDepositError,
2671
+ themeClass
2672
+ }
2673
+ )
2674
+ ] })
2675
+ }
2676
+ ),
2677
+ /* @__PURE__ */ jsx20(
2678
+ DepositsModal,
2679
+ {
2680
+ open: depositsModalOpen,
2681
+ onOpenChange: setDepositsModalOpen,
2682
+ executions: depositExecutions,
2683
+ userId,
2684
+ publishableKey,
2685
+ themeClass
2686
+ }
2687
+ )
2688
+ ] }) });
2689
+ }
2690
+
2691
+ // src/components/deposits/TransferCrypto2.tsx
2692
+ import { jsx as jsx21 } from "react/jsx-runtime";
2693
+ function TransferCrypto2(props) {
2694
+ return /* @__PURE__ */ jsx21(
2695
+ TransferCryptoBase,
2696
+ {
2697
+ ...props,
2698
+ layoutVariant: "vertical",
2699
+ showDetailedDropdowns: true
2700
+ }
2701
+ );
2702
+ }
2703
+ export {
2704
+ Button,
2705
+ BuyWithCard,
2706
+ CurrencyListItem,
2707
+ CurrencyListSection,
2708
+ CurrencyModal,
2709
+ DepositExecutionItem,
2710
+ DepositHeader,
2711
+ DepositModal,
2712
+ DepositSuccessToast,
2713
+ DepositTrackerButton,
2714
+ DepositWithCardButton,
2715
+ DepositsModal,
2716
+ Dialog,
2717
+ DialogClose,
2718
+ DialogContent,
2719
+ DialogDescription,
2720
+ DialogFooter,
2721
+ DialogHeader,
2722
+ DialogOverlay,
2723
+ DialogPortal,
2724
+ DialogTitle,
2725
+ DialogTrigger,
2726
+ ExecutionStatus,
2727
+ SOLANA_USDC_ADDRESS,
2728
+ Select,
2729
+ SelectContent,
2730
+ SelectGroup,
2731
+ SelectItem,
2732
+ SelectLabel,
2733
+ SelectScrollDownButton,
2734
+ SelectScrollUpButton,
2735
+ SelectSeparator,
2736
+ SelectTrigger,
2737
+ SelectValue,
2738
+ StyledQRCode,
2739
+ ThemeProvider,
2740
+ Tooltip,
2741
+ TooltipContent,
2742
+ TooltipProvider,
2743
+ TooltipTrigger,
2744
+ TransferCrypto,
2745
+ TransferCrypto2,
2746
+ TransferCryptoBase,
2747
+ TransferCryptoButton,
2748
+ buttonVariants,
2749
+ cn,
2750
+ createEOA,
2751
+ createMeldSession,
2752
+ getApiBaseUrl,
2753
+ getFiatCurrencies,
2754
+ getIconUrl,
2755
+ getMeldQuotes,
2756
+ getSupportedDepositTokens,
2757
+ getWalletByChainType,
2758
+ i18n,
2759
+ queryExecutions,
2760
+ setApiConfig,
2761
+ useTheme,
2762
+ useUserIp
2763
+ };