@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/README.md +121 -0
- package/dist/assets/fonts/Sons-Black.ttf +0 -0
- package/dist/assets/fonts/Sons-BlackItalic.ttf +0 -0
- package/dist/assets/fonts/Sons-Bold.ttf +0 -0
- package/dist/assets/fonts/Sons-BoldItalic.ttf +0 -0
- package/dist/assets/fonts/Sons-Extrabold.ttf +0 -0
- package/dist/assets/fonts/Sons-ExtraboldItalic.ttf +0 -0
- package/dist/assets/fonts/Sons-Light.ttf +0 -0
- package/dist/assets/fonts/Sons-LightItalic.ttf +0 -0
- package/dist/assets/fonts/Sons-Medium.ttf +0 -0
- package/dist/assets/fonts/Sons-MediumItalic.ttf +0 -0
- package/dist/assets/fonts/Sons-Regular.ttf +0 -0
- package/dist/assets/fonts/Sons-RegularItalic.ttf +0 -0
- package/dist/assets/fonts/Sons-Semibold.ttf +0 -0
- package/dist/assets/fonts/Sons-SemiboldItalic.ttf +0 -0
- package/dist/assets/fonts/Sons-Thin.ttf +0 -0
- package/dist/assets/fonts/Sons-ThinItalic.ttf +0 -0
- package/dist/index.d.mts +565 -0
- package/dist/index.d.ts +565 -0
- package/dist/index.js +2847 -0
- package/dist/index.mjs +2763 -0
- package/dist/styles.css +1 -0
- package/package.json +70 -0
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
|
+
};
|