@unifold/ui-react 0.1.21 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +11 -3
- package/dist/index.d.ts +11 -3
- package/dist/index.js +500 -214
- package/dist/index.mjs +437 -149
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/components/deposits/DepositModal.tsx
|
|
2
|
-
import { useState as
|
|
2
|
+
import { useState as useState17, useEffect as useEffect14 } from "react";
|
|
3
3
|
import { ChevronRight as ChevronRight8, MapPinOff, AlertTriangle } from "lucide-react";
|
|
4
4
|
|
|
5
5
|
// src/components/shared/dialog.tsx
|
|
@@ -13,6 +13,29 @@ import { twMerge } from "tailwind-merge";
|
|
|
13
13
|
function cn(...inputs) {
|
|
14
14
|
return twMerge(clsx(inputs));
|
|
15
15
|
}
|
|
16
|
+
function formatEstimatedTime(seconds) {
|
|
17
|
+
if (seconds == null) {
|
|
18
|
+
return "< 1 min";
|
|
19
|
+
}
|
|
20
|
+
if (seconds < 60) {
|
|
21
|
+
return `< ${seconds} sec${seconds > 1 ? "s" : ""}`;
|
|
22
|
+
} else if (seconds < 3600) {
|
|
23
|
+
const mins = Math.ceil(seconds / 60);
|
|
24
|
+
return `< ${mins} min${mins > 1 ? "s" : ""}`;
|
|
25
|
+
} else {
|
|
26
|
+
let hrs = Math.floor(seconds / 3600);
|
|
27
|
+
let mins = Math.ceil(seconds % 3600 / 60);
|
|
28
|
+
if (mins === 60) {
|
|
29
|
+
hrs += 1;
|
|
30
|
+
mins = 0;
|
|
31
|
+
}
|
|
32
|
+
const hrLabel = hrs > 1 ? "hrs" : "hr";
|
|
33
|
+
if (mins === 0) {
|
|
34
|
+
return `< ${hrs} ${hrLabel}`;
|
|
35
|
+
}
|
|
36
|
+
return `< ${hrs} ${hrLabel} ${mins} min${mins > 1 ? "s" : ""}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
16
39
|
|
|
17
40
|
// src/context/ThemeContext.tsx
|
|
18
41
|
import * as React from "react";
|
|
@@ -466,7 +489,7 @@ var DialogDescription = React2.forwardRef(({ className, ...props }, ref) => /* @
|
|
|
466
489
|
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
467
490
|
|
|
468
491
|
// src/components/deposits/BuyWithCard.tsx
|
|
469
|
-
import { useState as
|
|
492
|
+
import { useState as useState9, useEffect as useEffect5, useRef as useRef2 } from "react";
|
|
470
493
|
import { ChevronDown as ChevronDown2, ChevronRight } from "lucide-react";
|
|
471
494
|
import {
|
|
472
495
|
getOnrampQuotes,
|
|
@@ -481,10 +504,12 @@ import {
|
|
|
481
504
|
} from "@unifold/core";
|
|
482
505
|
|
|
483
506
|
// src/components/deposits/CurrencyModal.tsx
|
|
484
|
-
import { useState as
|
|
507
|
+
import { useState as useState4 } from "react";
|
|
485
508
|
|
|
486
509
|
// src/components/deposits/DepositHeader.tsx
|
|
487
510
|
import { ArrowLeft, X as X2 } from "lucide-react";
|
|
511
|
+
import { useEffect as useEffect2, useState as useState2 } from "react";
|
|
512
|
+
import { getAddressBalance } from "@unifold/core";
|
|
488
513
|
import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
489
514
|
function DepositHeader({
|
|
490
515
|
title,
|
|
@@ -492,10 +517,83 @@ function DepositHeader({
|
|
|
492
517
|
showClose = true,
|
|
493
518
|
onBack,
|
|
494
519
|
onClose,
|
|
495
|
-
badge
|
|
520
|
+
badge,
|
|
521
|
+
showBalance = false,
|
|
522
|
+
balanceAddress,
|
|
523
|
+
balanceChainType,
|
|
524
|
+
balanceChainId,
|
|
525
|
+
balanceTokenAddress,
|
|
526
|
+
publishableKey
|
|
496
527
|
}) {
|
|
497
528
|
const { colors: colors2, fonts, components } = useTheme();
|
|
498
|
-
|
|
529
|
+
const [balance, setBalance] = useState2(null);
|
|
530
|
+
const [isLoadingBalance, setIsLoadingBalance] = useState2(false);
|
|
531
|
+
useEffect2(() => {
|
|
532
|
+
if (!showBalance || !balanceAddress || !balanceChainType || !balanceChainId || !balanceTokenAddress || !publishableKey) {
|
|
533
|
+
setBalance(null);
|
|
534
|
+
setIsLoadingBalance(false);
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
537
|
+
let cancelled = false;
|
|
538
|
+
setIsLoadingBalance(true);
|
|
539
|
+
getAddressBalance(
|
|
540
|
+
balanceAddress,
|
|
541
|
+
balanceChainType,
|
|
542
|
+
balanceChainId,
|
|
543
|
+
balanceTokenAddress,
|
|
544
|
+
publishableKey
|
|
545
|
+
).then((response) => {
|
|
546
|
+
if (cancelled) return;
|
|
547
|
+
if (response.balance && response.balance.amount !== "0") {
|
|
548
|
+
const value = Number(response.balance.amount) / 10 ** response.balance.token.decimals;
|
|
549
|
+
let formatted;
|
|
550
|
+
let maxDecimals = 4;
|
|
551
|
+
const symbol = response.balance.token.symbol?.toUpperCase() || "";
|
|
552
|
+
if (symbol === "BTC" || symbol === "WBTC") {
|
|
553
|
+
maxDecimals = 8;
|
|
554
|
+
} else if (symbol === "ETH" || symbol === "WETH") {
|
|
555
|
+
maxDecimals = 6;
|
|
556
|
+
}
|
|
557
|
+
if (value >= 1) {
|
|
558
|
+
formatted = value.toLocaleString(void 0, {
|
|
559
|
+
minimumFractionDigits: 2,
|
|
560
|
+
maximumFractionDigits: maxDecimals
|
|
561
|
+
});
|
|
562
|
+
} else if (value > 0) {
|
|
563
|
+
formatted = value.toLocaleString(void 0, {
|
|
564
|
+
minimumFractionDigits: 2,
|
|
565
|
+
maximumFractionDigits: maxDecimals,
|
|
566
|
+
minimumSignificantDigits: 2,
|
|
567
|
+
maximumSignificantDigits: 6
|
|
568
|
+
});
|
|
569
|
+
} else {
|
|
570
|
+
formatted = value.toExponential(2);
|
|
571
|
+
}
|
|
572
|
+
const balanceText = response.balance.amount_usd ? `Balance: $${response.balance.amount_usd} (${formatted} ${response.balance.token.symbol})` : `Balance: ${formatted} ${response.balance.token.symbol}`;
|
|
573
|
+
setBalance(balanceText);
|
|
574
|
+
} else {
|
|
575
|
+
setBalance(null);
|
|
576
|
+
}
|
|
577
|
+
}).catch((error) => {
|
|
578
|
+
if (cancelled) return;
|
|
579
|
+
console.error("Error fetching balance:", error);
|
|
580
|
+
setBalance(null);
|
|
581
|
+
}).finally(() => {
|
|
582
|
+
if (cancelled) return;
|
|
583
|
+
setIsLoadingBalance(false);
|
|
584
|
+
});
|
|
585
|
+
return () => {
|
|
586
|
+
cancelled = true;
|
|
587
|
+
};
|
|
588
|
+
}, [
|
|
589
|
+
showBalance,
|
|
590
|
+
balanceAddress,
|
|
591
|
+
balanceChainType,
|
|
592
|
+
balanceChainId,
|
|
593
|
+
balanceTokenAddress,
|
|
594
|
+
publishableKey
|
|
595
|
+
]);
|
|
596
|
+
return /* @__PURE__ */ jsx3("div", { children: /* @__PURE__ */ jsxs2("div", { className: "uf-flex uf-items-center uf-justify-between uf-pb-6", children: [
|
|
499
597
|
showBack ? /* @__PURE__ */ jsx3(
|
|
500
598
|
"button",
|
|
501
599
|
{
|
|
@@ -505,8 +603,32 @@ function DepositHeader({
|
|
|
505
603
|
children: /* @__PURE__ */ jsx3(ArrowLeft, { className: "uf-w-5 uf-h-5" })
|
|
506
604
|
}
|
|
507
605
|
) : /* @__PURE__ */ jsx3("div", { className: "uf-w-5 uf-h-5 uf-invisible" }),
|
|
508
|
-
|
|
509
|
-
/* @__PURE__ */
|
|
606
|
+
/* @__PURE__ */ jsxs2("div", { className: "uf-flex uf-flex-col uf-items-center", children: [
|
|
607
|
+
badge ? /* @__PURE__ */ jsxs2("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
608
|
+
/* @__PURE__ */ jsx3(
|
|
609
|
+
DialogTitle,
|
|
610
|
+
{
|
|
611
|
+
className: "uf-text-center uf-text-base",
|
|
612
|
+
style: {
|
|
613
|
+
color: components.header.titleColor,
|
|
614
|
+
fontFamily: fonts.medium
|
|
615
|
+
},
|
|
616
|
+
children: title
|
|
617
|
+
}
|
|
618
|
+
),
|
|
619
|
+
/* @__PURE__ */ jsx3(
|
|
620
|
+
"div",
|
|
621
|
+
{
|
|
622
|
+
className: "uf-px-2 uf-py-0.5 uf-rounded-full uf-text-[10px]",
|
|
623
|
+
style: {
|
|
624
|
+
backgroundColor: colors2.card,
|
|
625
|
+
color: colors2.foregroundMuted,
|
|
626
|
+
fontFamily: fonts.regular
|
|
627
|
+
},
|
|
628
|
+
children: badge.count
|
|
629
|
+
}
|
|
630
|
+
)
|
|
631
|
+
] }) : /* @__PURE__ */ jsx3(
|
|
510
632
|
DialogTitle,
|
|
511
633
|
{
|
|
512
634
|
className: "uf-text-center uf-text-base",
|
|
@@ -517,29 +639,19 @@ function DepositHeader({
|
|
|
517
639
|
children: title
|
|
518
640
|
}
|
|
519
641
|
),
|
|
520
|
-
/* @__PURE__ */ jsx3(
|
|
642
|
+
showBalance && (isLoadingBalance ? /* @__PURE__ */ jsx3("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded uf-animate-pulse uf-mt-2" }) : balance ? /* @__PURE__ */ jsx3(
|
|
521
643
|
"div",
|
|
522
644
|
{
|
|
523
|
-
className: "uf-
|
|
645
|
+
className: "uf-text-xs uf-mt-2",
|
|
524
646
|
style: {
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
647
|
+
color: colors2.foreground,
|
|
648
|
+
fontFamily: fonts.regular,
|
|
649
|
+
opacity: 0.7
|
|
528
650
|
},
|
|
529
|
-
children:
|
|
651
|
+
children: balance
|
|
530
652
|
}
|
|
531
|
-
)
|
|
532
|
-
] })
|
|
533
|
-
DialogTitle,
|
|
534
|
-
{
|
|
535
|
-
className: "uf-text-center uf-text-base",
|
|
536
|
-
style: {
|
|
537
|
-
color: components.header.titleColor,
|
|
538
|
-
fontFamily: fonts.medium
|
|
539
|
-
},
|
|
540
|
-
children: title
|
|
541
|
-
}
|
|
542
|
-
),
|
|
653
|
+
) : null)
|
|
654
|
+
] }),
|
|
543
655
|
showClose ? /* @__PURE__ */ jsx3(
|
|
544
656
|
"button",
|
|
545
657
|
{
|
|
@@ -549,7 +661,7 @@ function DepositHeader({
|
|
|
549
661
|
children: /* @__PURE__ */ jsx3(X2, { className: "uf-w-5 uf-h-5" })
|
|
550
662
|
}
|
|
551
663
|
) : /* @__PURE__ */ jsx3("div", { className: "uf-w-5 uf-h-5 uf-invisible" })
|
|
552
|
-
] });
|
|
664
|
+
] }) });
|
|
553
665
|
}
|
|
554
666
|
|
|
555
667
|
// src/components/currency/CurrencyListItem.tsx
|
|
@@ -662,7 +774,7 @@ function CurrencyModal({
|
|
|
662
774
|
themeClass = ""
|
|
663
775
|
}) {
|
|
664
776
|
const { colors: colors2, fonts, components } = useTheme();
|
|
665
|
-
const [searchQuery, setSearchQuery] =
|
|
777
|
+
const [searchQuery, setSearchQuery] = useState4("");
|
|
666
778
|
const preferredCurrencies = preferredCurrencyCodes.map(
|
|
667
779
|
(code) => currencies.find(
|
|
668
780
|
(currency) => currency.currency_code.toLowerCase() === code.toLowerCase()
|
|
@@ -838,7 +950,19 @@ var en_default = {
|
|
|
838
950
|
minimumDeposit: "Minimum: {{amount}}",
|
|
839
951
|
minimumDepositTooltip: "The minimum amount you can deposit on the selected network.",
|
|
840
952
|
selectTokenDeposit: "Your deposit token",
|
|
841
|
-
selectTokenDepositTooltip: "Select the token you want to deposit with in order to begin the deposit process."
|
|
953
|
+
selectTokenDepositTooltip: "Select the token you want to deposit with in order to begin the deposit process.",
|
|
954
|
+
addressValidation: {
|
|
955
|
+
validating: "Verifying recipient address...",
|
|
956
|
+
unableToReceiveFunds: "Unable to Receive Funds",
|
|
957
|
+
errors: {
|
|
958
|
+
token_not_supported: "The destination token is not supported",
|
|
959
|
+
not_opted_in: "Please make sure you opt-in {{token_symbol}}({{chain_name}}) before receiving funds",
|
|
960
|
+
insufficient_balance: "Recipient account does not meet the minimum balance requirement",
|
|
961
|
+
account_not_found: "Recipient account does not exist on {{chain_name}}",
|
|
962
|
+
validation_error: "Unable to verify recipient address on {{chain_name}}"
|
|
963
|
+
},
|
|
964
|
+
defaultError: "The recipient address cannot receive funds for the selected token"
|
|
965
|
+
}
|
|
842
966
|
},
|
|
843
967
|
depositModal: {
|
|
844
968
|
transferCrypto: {
|
|
@@ -847,7 +971,7 @@ var en_default = {
|
|
|
847
971
|
},
|
|
848
972
|
depositWithCard: {
|
|
849
973
|
title: "Deposit with Card",
|
|
850
|
-
subtitle: "$50,000 limit
|
|
974
|
+
subtitle: "$50,000 limit"
|
|
851
975
|
},
|
|
852
976
|
quotes: "Quotes"
|
|
853
977
|
},
|
|
@@ -865,9 +989,16 @@ var en_default = {
|
|
|
865
989
|
|
|
866
990
|
// src/lib/i18n.ts
|
|
867
991
|
var i18n = en_default;
|
|
992
|
+
function interpolate(template, params) {
|
|
993
|
+
if (!params) return template;
|
|
994
|
+
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => {
|
|
995
|
+
const value = params[key];
|
|
996
|
+
return value !== void 0 ? String(value) : `{{${key}}}`;
|
|
997
|
+
});
|
|
998
|
+
}
|
|
868
999
|
|
|
869
1000
|
// src/hooks/use-deposit-polling.ts
|
|
870
|
-
import { useState as
|
|
1001
|
+
import { useState as useState5, useEffect as useEffect3, useRef } from "react";
|
|
871
1002
|
import {
|
|
872
1003
|
queryExecutions,
|
|
873
1004
|
ExecutionStatus
|
|
@@ -879,14 +1010,14 @@ function useDepositPolling({
|
|
|
879
1010
|
onDepositSuccess,
|
|
880
1011
|
onDepositError
|
|
881
1012
|
}) {
|
|
882
|
-
const [executions, setExecutions] =
|
|
883
|
-
const [isPolling, setIsPolling] =
|
|
1013
|
+
const [executions, setExecutions] = useState5([]);
|
|
1014
|
+
const [isPolling, setIsPolling] = useState5(false);
|
|
884
1015
|
const pollingIntervalRef = useRef(
|
|
885
1016
|
null
|
|
886
1017
|
);
|
|
887
|
-
const [modalOpenedAt] =
|
|
888
|
-
const [trackedExecutions, setTrackedExecutions] =
|
|
889
|
-
|
|
1018
|
+
const [modalOpenedAt] = useState5(/* @__PURE__ */ new Date());
|
|
1019
|
+
const [trackedExecutions, setTrackedExecutions] = useState5(/* @__PURE__ */ new Map());
|
|
1020
|
+
useEffect3(() => {
|
|
890
1021
|
if (!userId || !modalOpenedAt || !enabled) return;
|
|
891
1022
|
const pollInterval = setInterval(async () => {
|
|
892
1023
|
try {
|
|
@@ -989,10 +1120,10 @@ function useDepositPolling({
|
|
|
989
1120
|
}
|
|
990
1121
|
|
|
991
1122
|
// src/components/deposits/DepositPollingToasts.tsx
|
|
992
|
-
import { useState as
|
|
1123
|
+
import { useState as useState8 } from "react";
|
|
993
1124
|
|
|
994
1125
|
// src/components/deposits/DepositSuccessToast.tsx
|
|
995
|
-
import { useState as
|
|
1126
|
+
import { useState as useState7 } from "react";
|
|
996
1127
|
import { X as X3 } from "lucide-react";
|
|
997
1128
|
import {
|
|
998
1129
|
ExecutionStatus as ExecutionStatus3,
|
|
@@ -1000,7 +1131,7 @@ import {
|
|
|
1000
1131
|
} from "@unifold/core";
|
|
1001
1132
|
|
|
1002
1133
|
// src/components/deposits/DepositDetailContent.tsx
|
|
1003
|
-
import { useEffect as
|
|
1134
|
+
import { useEffect as useEffect4, useState as useState6 } from "react";
|
|
1004
1135
|
import { ExternalLink, ChevronDown, ChevronUp } from "lucide-react";
|
|
1005
1136
|
import {
|
|
1006
1137
|
ExecutionStatus as ExecutionStatus2,
|
|
@@ -1019,12 +1150,12 @@ function formatCurrency(currency) {
|
|
|
1019
1150
|
}
|
|
1020
1151
|
function DepositDetailContent({ execution }) {
|
|
1021
1152
|
const { colors: colors2, fonts, components } = useTheme();
|
|
1022
|
-
const [chains, setChains] =
|
|
1023
|
-
const [showNetworkDetails, setShowNetworkDetails] =
|
|
1024
|
-
|
|
1153
|
+
const [chains, setChains] = useState6([]);
|
|
1154
|
+
const [showNetworkDetails, setShowNetworkDetails] = useState6(false);
|
|
1155
|
+
useEffect4(() => {
|
|
1025
1156
|
getTokenChains().then((response) => setChains(response.data)).catch((err) => console.error("Failed to fetch chains:", err));
|
|
1026
1157
|
}, []);
|
|
1027
|
-
|
|
1158
|
+
useEffect4(() => {
|
|
1028
1159
|
setShowNetworkDetails(false);
|
|
1029
1160
|
}, [execution?.id]);
|
|
1030
1161
|
const isPending = execution.status === ExecutionStatus2.PENDING || execution.status === ExecutionStatus2.WAITING || execution.status === ExecutionStatus2.DELAYED;
|
|
@@ -1319,6 +1450,37 @@ function DepositDetailContent({ execution }) {
|
|
|
1319
1450
|
]
|
|
1320
1451
|
}
|
|
1321
1452
|
),
|
|
1453
|
+
isPending && /* @__PURE__ */ jsxs6(
|
|
1454
|
+
"div",
|
|
1455
|
+
{
|
|
1456
|
+
className: "uf-flex uf-justify-between uf-items-center uf-px-4 uf-py-3 uf-border-b",
|
|
1457
|
+
style: { borderColor: colors2.border },
|
|
1458
|
+
children: [
|
|
1459
|
+
/* @__PURE__ */ jsx7(
|
|
1460
|
+
"span",
|
|
1461
|
+
{
|
|
1462
|
+
className: "uf-text-sm",
|
|
1463
|
+
style: {
|
|
1464
|
+
color: components.card.labelColor,
|
|
1465
|
+
fontFamily: fonts.regular
|
|
1466
|
+
},
|
|
1467
|
+
children: "Estimated delivery time"
|
|
1468
|
+
}
|
|
1469
|
+
),
|
|
1470
|
+
/* @__PURE__ */ jsx7(
|
|
1471
|
+
"span",
|
|
1472
|
+
{
|
|
1473
|
+
style: {
|
|
1474
|
+
color: components.card.titleColor,
|
|
1475
|
+
fontFamily: fonts.regular,
|
|
1476
|
+
fontSize: "14px"
|
|
1477
|
+
},
|
|
1478
|
+
children: formatEstimatedTime(execution?.estimated_processing_time)
|
|
1479
|
+
}
|
|
1480
|
+
)
|
|
1481
|
+
]
|
|
1482
|
+
}
|
|
1483
|
+
),
|
|
1322
1484
|
/* @__PURE__ */ jsxs6(
|
|
1323
1485
|
"div",
|
|
1324
1486
|
{
|
|
@@ -1505,7 +1667,7 @@ function DepositSuccessToast({
|
|
|
1505
1667
|
onClose,
|
|
1506
1668
|
execution
|
|
1507
1669
|
}) {
|
|
1508
|
-
const [detailModalOpen, setDetailModalOpen] =
|
|
1670
|
+
const [detailModalOpen, setDetailModalOpen] = useState7(false);
|
|
1509
1671
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
1510
1672
|
const isPending = status === ExecutionStatus3.PENDING || status === ExecutionStatus3.WAITING || status === ExecutionStatus3.DELAYED;
|
|
1511
1673
|
const formatDateTime = (timestamp) => {
|
|
@@ -1639,14 +1801,27 @@ function DepositSuccessToast({
|
|
|
1639
1801
|
}
|
|
1640
1802
|
)
|
|
1641
1803
|
] }),
|
|
1642
|
-
/* @__PURE__ */
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1804
|
+
/* @__PURE__ */ jsxs7("div", { className: "uf-flex-shrink-0 uf-text-right", children: [
|
|
1805
|
+
/* @__PURE__ */ jsx8(
|
|
1806
|
+
"div",
|
|
1807
|
+
{
|
|
1808
|
+
className: "uf-font-medium uf-text-sm",
|
|
1809
|
+
style: { color: colors2.background },
|
|
1810
|
+
children: formatUsdAmount(sourceAmountUsd)
|
|
1811
|
+
}
|
|
1812
|
+
),
|
|
1813
|
+
isPending && execution?.estimated_processing_time && /* @__PURE__ */ jsxs7(
|
|
1814
|
+
"p",
|
|
1815
|
+
{
|
|
1816
|
+
className: "uf-text-xs",
|
|
1817
|
+
style: { color: colors2.foregroundMuted },
|
|
1818
|
+
children: [
|
|
1819
|
+
"Est. ",
|
|
1820
|
+
formatEstimatedTime(execution.estimated_processing_time)
|
|
1821
|
+
]
|
|
1822
|
+
}
|
|
1823
|
+
)
|
|
1824
|
+
] }),
|
|
1650
1825
|
/* @__PURE__ */ jsx8(
|
|
1651
1826
|
"button",
|
|
1652
1827
|
{
|
|
@@ -1695,7 +1870,7 @@ function DepositPollingToasts({
|
|
|
1695
1870
|
executions,
|
|
1696
1871
|
horizontalPadding = "24px"
|
|
1697
1872
|
}) {
|
|
1698
|
-
const [closedExecutionIds, setClosedExecutionIds] =
|
|
1873
|
+
const [closedExecutionIds, setClosedExecutionIds] = useState8(
|
|
1699
1874
|
/* @__PURE__ */ new Set()
|
|
1700
1875
|
);
|
|
1701
1876
|
const handleClose = (executionId) => {
|
|
@@ -1776,28 +1951,28 @@ function BuyWithCard({
|
|
|
1776
1951
|
assetCdnUrl
|
|
1777
1952
|
}) {
|
|
1778
1953
|
const { colors: colors2, fonts, components } = useTheme();
|
|
1779
|
-
const [amount, setAmount] =
|
|
1780
|
-
const [currency, setCurrency] =
|
|
1781
|
-
const [hasManualCurrencySelection, setHasManualCurrencySelection] =
|
|
1782
|
-
const [hasManualAmountEntry, setHasManualAmountEntry] =
|
|
1783
|
-
const [showCurrencyModal, setShowCurrencyModal] =
|
|
1784
|
-
const [quotes, setQuotes] =
|
|
1785
|
-
const [quotesLoading, setQuotesLoading] =
|
|
1786
|
-
const [quotesError, setQuotesError] =
|
|
1787
|
-
const [amountValidationError, setAmountValidationError] =
|
|
1788
|
-
const [internalView, setInternalView] =
|
|
1789
|
-
const [defaultToken, setDefaultToken] =
|
|
1954
|
+
const [amount, setAmount] = useState9("");
|
|
1955
|
+
const [currency, setCurrency] = useState9("usd");
|
|
1956
|
+
const [hasManualCurrencySelection, setHasManualCurrencySelection] = useState9(false);
|
|
1957
|
+
const [hasManualAmountEntry, setHasManualAmountEntry] = useState9(false);
|
|
1958
|
+
const [showCurrencyModal, setShowCurrencyModal] = useState9(false);
|
|
1959
|
+
const [quotes, setQuotes] = useState9([]);
|
|
1960
|
+
const [quotesLoading, setQuotesLoading] = useState9(false);
|
|
1961
|
+
const [quotesError, setQuotesError] = useState9(null);
|
|
1962
|
+
const [amountValidationError, setAmountValidationError] = useState9(null);
|
|
1963
|
+
const [internalView, setInternalView] = useState9("amount");
|
|
1964
|
+
const [defaultToken, setDefaultToken] = useState9(
|
|
1790
1965
|
null
|
|
1791
1966
|
);
|
|
1792
|
-
const [defaultTokenLoading, setDefaultTokenLoading] =
|
|
1967
|
+
const [defaultTokenLoading, setDefaultTokenLoading] = useState9(false);
|
|
1793
1968
|
const { userIpInfo, isLoading: isLoadingIp } = useUserIp();
|
|
1794
|
-
const [onrampSession, setOnrampSession] =
|
|
1969
|
+
const [onrampSession, setOnrampSession] = useState9(
|
|
1795
1970
|
null
|
|
1796
1971
|
);
|
|
1797
1972
|
const currentView = externalView ?? internalView;
|
|
1798
1973
|
const showQuotesView = currentView === "quotes";
|
|
1799
1974
|
const showOnrampView = currentView === "onramp";
|
|
1800
|
-
|
|
1975
|
+
useEffect5(() => {
|
|
1801
1976
|
if (externalView) {
|
|
1802
1977
|
setInternalView(externalView);
|
|
1803
1978
|
}
|
|
@@ -1810,31 +1985,31 @@ function BuyWithCard({
|
|
|
1810
1985
|
onViewChange?.(newView);
|
|
1811
1986
|
}
|
|
1812
1987
|
};
|
|
1813
|
-
const [selectedProvider, setSelectedProvider] =
|
|
1988
|
+
const [selectedProvider, setSelectedProvider] = useState9(
|
|
1814
1989
|
null
|
|
1815
1990
|
);
|
|
1816
|
-
const [isAutoSelected, setIsAutoSelected] =
|
|
1817
|
-
const [autoSelectedProvider, setAutoSelectedProvider] =
|
|
1818
|
-
const [hoveredProviderIndex, setHoveredProviderIndex] =
|
|
1819
|
-
const [hasManualSelection, setHasManualSelection] =
|
|
1991
|
+
const [isAutoSelected, setIsAutoSelected] = useState9(true);
|
|
1992
|
+
const [autoSelectedProvider, setAutoSelectedProvider] = useState9(null);
|
|
1993
|
+
const [hoveredProviderIndex, setHoveredProviderIndex] = useState9(null);
|
|
1994
|
+
const [hasManualSelection, setHasManualSelection] = useState9(false);
|
|
1820
1995
|
const selectedProviderRef = useRef2(null);
|
|
1821
1996
|
const hasManualSelectionRef = useRef2(false);
|
|
1822
|
-
|
|
1997
|
+
useEffect5(() => {
|
|
1823
1998
|
selectedProviderRef.current = selectedProvider;
|
|
1824
1999
|
}, [selectedProvider]);
|
|
1825
|
-
|
|
2000
|
+
useEffect5(() => {
|
|
1826
2001
|
hasManualSelectionRef.current = hasManualSelection;
|
|
1827
2002
|
}, [hasManualSelection]);
|
|
1828
|
-
const [internalWallets, setInternalWallets] =
|
|
1829
|
-
const [walletsLoading, setWalletsLoading] =
|
|
2003
|
+
const [internalWallets, setInternalWallets] = useState9([]);
|
|
2004
|
+
const [walletsLoading, setWalletsLoading] = useState9(
|
|
1830
2005
|
!externalWallets?.length
|
|
1831
2006
|
);
|
|
1832
2007
|
const wallets = externalWallets?.length ? externalWallets : internalWallets;
|
|
1833
|
-
const [countdown, setCountdown] =
|
|
1834
|
-
const [fiatCurrencies, setFiatCurrencies] =
|
|
1835
|
-
const [preferredCurrencyCodes, setPreferredCurrencyCodes] =
|
|
1836
|
-
const [currenciesLoading, setCurrenciesLoading] =
|
|
1837
|
-
const [destinationToken, setDestinationToken] =
|
|
2008
|
+
const [countdown, setCountdown] = useState9(60);
|
|
2009
|
+
const [fiatCurrencies, setFiatCurrencies] = useState9([]);
|
|
2010
|
+
const [preferredCurrencyCodes, setPreferredCurrencyCodes] = useState9([]);
|
|
2011
|
+
const [currenciesLoading, setCurrenciesLoading] = useState9(true);
|
|
2012
|
+
const [destinationToken, setDestinationToken] = useState9(null);
|
|
1838
2013
|
const { executions, isPolling } = useDepositPolling({
|
|
1839
2014
|
userId,
|
|
1840
2015
|
publishableKey,
|
|
@@ -1846,7 +2021,7 @@ function BuyWithCard({
|
|
|
1846
2021
|
const destinationTokenIcon = destinationToken?.icon_url;
|
|
1847
2022
|
const destinationChainIcon = destinationToken?.chain_icon_url;
|
|
1848
2023
|
const destinationChainName = destinationToken?.chain_name;
|
|
1849
|
-
|
|
2024
|
+
useEffect5(() => {
|
|
1850
2025
|
async function fetchFiatCurrencies() {
|
|
1851
2026
|
try {
|
|
1852
2027
|
const response = await getFiatCurrencies(publishableKey);
|
|
@@ -1860,7 +2035,7 @@ function BuyWithCard({
|
|
|
1860
2035
|
}
|
|
1861
2036
|
fetchFiatCurrencies();
|
|
1862
2037
|
}, [publishableKey]);
|
|
1863
|
-
|
|
2038
|
+
useEffect5(() => {
|
|
1864
2039
|
if (hasManualCurrencySelection) return;
|
|
1865
2040
|
if (fiatCurrencies.length === 0 || !userIpInfo?.alpha2) return;
|
|
1866
2041
|
const userCountryCode = userIpInfo.alpha2.toUpperCase();
|
|
@@ -1888,7 +2063,7 @@ function BuyWithCard({
|
|
|
1888
2063
|
hasManualAmountEntry
|
|
1889
2064
|
]);
|
|
1890
2065
|
const prevCurrencyRef = useRef2(null);
|
|
1891
|
-
|
|
2066
|
+
useEffect5(() => {
|
|
1892
2067
|
if (fiatCurrencies.length === 0) return;
|
|
1893
2068
|
if (prevCurrencyRef.current !== null && prevCurrencyRef.current !== currency) {
|
|
1894
2069
|
const currentCurrency = fiatCurrencies.find(
|
|
@@ -1900,7 +2075,7 @@ function BuyWithCard({
|
|
|
1900
2075
|
}
|
|
1901
2076
|
prevCurrencyRef.current = currency;
|
|
1902
2077
|
}, [currency]);
|
|
1903
|
-
|
|
2078
|
+
useEffect5(() => {
|
|
1904
2079
|
if (externalWallets?.length) {
|
|
1905
2080
|
setWalletsLoading(false);
|
|
1906
2081
|
return;
|
|
@@ -1953,7 +2128,7 @@ function BuyWithCard({
|
|
|
1953
2128
|
publishableKey,
|
|
1954
2129
|
externalWallets
|
|
1955
2130
|
]);
|
|
1956
|
-
|
|
2131
|
+
useEffect5(() => {
|
|
1957
2132
|
async function fetchDestinationToken() {
|
|
1958
2133
|
try {
|
|
1959
2134
|
const response = await getTokenMetadata(
|
|
@@ -1971,7 +2146,7 @@ function BuyWithCard({
|
|
|
1971
2146
|
}
|
|
1972
2147
|
fetchDestinationToken();
|
|
1973
2148
|
}, [publishableKey]);
|
|
1974
|
-
|
|
2149
|
+
useEffect5(() => {
|
|
1975
2150
|
async function fetchDefaultToken() {
|
|
1976
2151
|
if (!destinationTokenAddress || !destinationChainId || !destinationChainType) {
|
|
1977
2152
|
return;
|
|
@@ -2007,7 +2182,7 @@ function BuyWithCard({
|
|
|
2007
2182
|
isLoadingIp,
|
|
2008
2183
|
publishableKey
|
|
2009
2184
|
]);
|
|
2010
|
-
|
|
2185
|
+
useEffect5(() => {
|
|
2011
2186
|
const amountNum = parseFloat(amount);
|
|
2012
2187
|
if (isNaN(amountNum) || amountNum <= 0) {
|
|
2013
2188
|
setQuotes([]);
|
|
@@ -2116,7 +2291,7 @@ function BuyWithCard({
|
|
|
2116
2291
|
setQuotesLoading(false);
|
|
2117
2292
|
}
|
|
2118
2293
|
};
|
|
2119
|
-
|
|
2294
|
+
useEffect5(() => {
|
|
2120
2295
|
if (quotes.length === 0) return;
|
|
2121
2296
|
const timer = setInterval(() => {
|
|
2122
2297
|
setCountdown((prev) => {
|
|
@@ -2451,6 +2626,20 @@ function BuyWithCard({
|
|
|
2451
2626
|
},
|
|
2452
2627
|
children: quotesError
|
|
2453
2628
|
}
|
|
2629
|
+
),
|
|
2630
|
+
defaultToken?.estimated_processing_time && !quotesLoading && selectedProvider && /* @__PURE__ */ jsxs8(
|
|
2631
|
+
"div",
|
|
2632
|
+
{
|
|
2633
|
+
className: "uf-text-xs uf-mt-2 uf-px-1",
|
|
2634
|
+
style: {
|
|
2635
|
+
color: components.card.subtitleColor,
|
|
2636
|
+
fontFamily: fonts.regular
|
|
2637
|
+
},
|
|
2638
|
+
children: [
|
|
2639
|
+
"Estimated delivery time: ",
|
|
2640
|
+
formatEstimatedTime(defaultToken.estimated_processing_time)
|
|
2641
|
+
]
|
|
2642
|
+
}
|
|
2454
2643
|
)
|
|
2455
2644
|
] }),
|
|
2456
2645
|
/* @__PURE__ */ jsx10(
|
|
@@ -2668,7 +2857,7 @@ function BuyWithCard({
|
|
|
2668
2857
|
}
|
|
2669
2858
|
|
|
2670
2859
|
// src/components/deposits/DepositsModal.tsx
|
|
2671
|
-
import { useEffect as
|
|
2860
|
+
import { useEffect as useEffect6, useState as useState10 } from "react";
|
|
2672
2861
|
|
|
2673
2862
|
// src/components/deposits/DepositExecutionItem.tsx
|
|
2674
2863
|
import { ChevronRight as ChevronRight2 } from "lucide-react";
|
|
@@ -2913,9 +3102,9 @@ function DepositsModal({
|
|
|
2913
3102
|
themeClass = ""
|
|
2914
3103
|
}) {
|
|
2915
3104
|
const { colors: colors2 } = useTheme();
|
|
2916
|
-
const [allExecutions, setAllExecutions] =
|
|
2917
|
-
const [selectedExecution, setSelectedExecution] =
|
|
2918
|
-
|
|
3105
|
+
const [allExecutions, setAllExecutions] = useState10(sessionExecutions);
|
|
3106
|
+
const [selectedExecution, setSelectedExecution] = useState10(null);
|
|
3107
|
+
useEffect6(() => {
|
|
2919
3108
|
if (!open || !userId) return;
|
|
2920
3109
|
const fetchExecutions = async () => {
|
|
2921
3110
|
try {
|
|
@@ -2937,7 +3126,7 @@ function DepositsModal({
|
|
|
2937
3126
|
clearInterval(pollInterval);
|
|
2938
3127
|
};
|
|
2939
3128
|
}, [open, userId, publishableKey, sessionExecutions]);
|
|
2940
|
-
|
|
3129
|
+
useEffect6(() => {
|
|
2941
3130
|
if (!open) {
|
|
2942
3131
|
setSelectedExecution(null);
|
|
2943
3132
|
}
|
|
@@ -3325,8 +3514,68 @@ function useAllowedCountry(publishableKey) {
|
|
|
3325
3514
|
};
|
|
3326
3515
|
}
|
|
3327
3516
|
|
|
3517
|
+
// src/hooks/use-address-validation.ts
|
|
3518
|
+
import { useQuery as useQuery3 } from "@tanstack/react-query";
|
|
3519
|
+
import {
|
|
3520
|
+
verifyRecipientAddress
|
|
3521
|
+
} from "@unifold/core";
|
|
3522
|
+
function useAddressValidation({
|
|
3523
|
+
recipientAddress,
|
|
3524
|
+
destinationChainType,
|
|
3525
|
+
destinationChainId,
|
|
3526
|
+
destinationTokenAddress,
|
|
3527
|
+
publishableKey,
|
|
3528
|
+
enabled = true,
|
|
3529
|
+
refetchOnMount = false
|
|
3530
|
+
}) {
|
|
3531
|
+
const shouldValidate = enabled && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
|
|
3532
|
+
const { data, isLoading, error } = useQuery3({
|
|
3533
|
+
queryKey: [
|
|
3534
|
+
"unifold",
|
|
3535
|
+
"addressValidation",
|
|
3536
|
+
recipientAddress,
|
|
3537
|
+
destinationChainType,
|
|
3538
|
+
destinationChainId,
|
|
3539
|
+
destinationTokenAddress
|
|
3540
|
+
],
|
|
3541
|
+
queryFn: () => verifyRecipientAddress(
|
|
3542
|
+
{
|
|
3543
|
+
chain_type: destinationChainType,
|
|
3544
|
+
chain_id: destinationChainId,
|
|
3545
|
+
token_address: destinationTokenAddress,
|
|
3546
|
+
recipient_address: recipientAddress
|
|
3547
|
+
},
|
|
3548
|
+
publishableKey
|
|
3549
|
+
),
|
|
3550
|
+
enabled: shouldValidate,
|
|
3551
|
+
refetchOnMount,
|
|
3552
|
+
refetchOnReconnect: false,
|
|
3553
|
+
refetchOnWindowFocus: false,
|
|
3554
|
+
staleTime: 1e3 * 60 * 5,
|
|
3555
|
+
// 5 minutes - address state can change
|
|
3556
|
+
gcTime: 1e3 * 60 * 30
|
|
3557
|
+
// 30 minutes
|
|
3558
|
+
});
|
|
3559
|
+
if (!shouldValidate) {
|
|
3560
|
+
return {
|
|
3561
|
+
isValid: null,
|
|
3562
|
+
failureCode: null,
|
|
3563
|
+
metadata: null,
|
|
3564
|
+
isLoading: false,
|
|
3565
|
+
error: null
|
|
3566
|
+
};
|
|
3567
|
+
}
|
|
3568
|
+
return {
|
|
3569
|
+
isValid: data?.valid ?? null,
|
|
3570
|
+
failureCode: data?.failure_code ?? null,
|
|
3571
|
+
metadata: data?.metadata ?? null,
|
|
3572
|
+
isLoading,
|
|
3573
|
+
error: error ?? null
|
|
3574
|
+
};
|
|
3575
|
+
}
|
|
3576
|
+
|
|
3328
3577
|
// src/components/deposits/TransferCryptoSingleInput.tsx
|
|
3329
|
-
import { useState as
|
|
3578
|
+
import { useState as useState15, useEffect as useEffect12 } from "react";
|
|
3330
3579
|
import {
|
|
3331
3580
|
ChevronDown as ChevronDown3,
|
|
3332
3581
|
ChevronUp as ChevronUp2,
|
|
@@ -3342,7 +3591,7 @@ import {
|
|
|
3342
3591
|
} from "lucide-react";
|
|
3343
3592
|
|
|
3344
3593
|
// src/components/deposits/StyledQRCode.tsx
|
|
3345
|
-
import { useEffect as
|
|
3594
|
+
import { useEffect as useEffect10, useRef as useRef3 } from "react";
|
|
3346
3595
|
import QRCodeStyling from "qr-code-styling";
|
|
3347
3596
|
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
3348
3597
|
function StyledQRCode({
|
|
@@ -3354,7 +3603,7 @@ function StyledQRCode({
|
|
|
3354
3603
|
}) {
|
|
3355
3604
|
const ref = useRef3(null);
|
|
3356
3605
|
const qrCodeRef = useRef3(null);
|
|
3357
|
-
|
|
3606
|
+
useEffect10(() => {
|
|
3358
3607
|
if (!ref.current) return;
|
|
3359
3608
|
if (!qrCodeRef.current) {
|
|
3360
3609
|
qrCodeRef.current = new QRCodeStyling({
|
|
@@ -3394,7 +3643,7 @@ function StyledQRCode({
|
|
|
3394
3643
|
qrCodeRef.current.append(ref.current);
|
|
3395
3644
|
}
|
|
3396
3645
|
}, []);
|
|
3397
|
-
|
|
3646
|
+
useEffect10(() => {
|
|
3398
3647
|
if (qrCodeRef.current) {
|
|
3399
3648
|
qrCodeRef.current.update({
|
|
3400
3649
|
data: value,
|
|
@@ -3435,7 +3684,7 @@ function StyledQRCode({
|
|
|
3435
3684
|
}
|
|
3436
3685
|
|
|
3437
3686
|
// src/components/deposits/TokenSelectorSheet.tsx
|
|
3438
|
-
import { useState as
|
|
3687
|
+
import { useState as useState14, useMemo as useMemo3, useEffect as useEffect11 } from "react";
|
|
3439
3688
|
import { ArrowLeft as ArrowLeft2, X as X4 } from "lucide-react";
|
|
3440
3689
|
import { jsx as jsx18, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3441
3690
|
var STORAGE_KEY = "unifold_recent_tokens";
|
|
@@ -3493,10 +3742,10 @@ function TokenSelectorSheet({
|
|
|
3493
3742
|
}) {
|
|
3494
3743
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
3495
3744
|
const isDarkMode = themeClass.includes("uf-dark");
|
|
3496
|
-
const [searchQuery, setSearchQuery] =
|
|
3497
|
-
const [recentTokens, setRecentTokens] =
|
|
3498
|
-
const [hoveredTokenKey, setHoveredTokenKey] =
|
|
3499
|
-
|
|
3745
|
+
const [searchQuery, setSearchQuery] = useState14("");
|
|
3746
|
+
const [recentTokens, setRecentTokens] = useState14([]);
|
|
3747
|
+
const [hoveredTokenKey, setHoveredTokenKey] = useState14(null);
|
|
3748
|
+
useEffect11(() => {
|
|
3500
3749
|
setRecentTokens(getRecentTokens());
|
|
3501
3750
|
}, []);
|
|
3502
3751
|
const allOptions = useMemo3(() => {
|
|
@@ -3938,13 +4187,13 @@ function TransferCryptoSingleInput({
|
|
|
3938
4187
|
}) {
|
|
3939
4188
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
3940
4189
|
const isDarkMode = themeClass.includes("uf-dark");
|
|
3941
|
-
const [token, setToken] =
|
|
3942
|
-
const [chain, setChain] =
|
|
3943
|
-
const [copied, setCopied] =
|
|
3944
|
-
const [internalWallets, setInternalWallets] =
|
|
3945
|
-
const [loading, setLoading] =
|
|
4190
|
+
const [token, setToken] = useState15("USDC");
|
|
4191
|
+
const [chain, setChain] = useState15("solana:mainnet");
|
|
4192
|
+
const [copied, setCopied] = useState15(false);
|
|
4193
|
+
const [internalWallets, setInternalWallets] = useState15([]);
|
|
4194
|
+
const [loading, setLoading] = useState15(!externalWallets?.length);
|
|
3946
4195
|
const wallets = externalWallets?.length ? externalWallets : internalWallets;
|
|
3947
|
-
const [error, setError] =
|
|
4196
|
+
const [error, setError] = useState15(null);
|
|
3948
4197
|
const { executions: depositExecutions, isPolling } = useDepositPolling({
|
|
3949
4198
|
userId,
|
|
3950
4199
|
publishableKey,
|
|
@@ -3952,11 +4201,11 @@ function TransferCryptoSingleInput({
|
|
|
3952
4201
|
onDepositSuccess,
|
|
3953
4202
|
onDepositError
|
|
3954
4203
|
});
|
|
3955
|
-
const [supportedTokens, setSupportedTokens] =
|
|
3956
|
-
const [tokensLoading, setTokensLoading] =
|
|
3957
|
-
const [detailsExpanded, setDetailsExpanded] =
|
|
3958
|
-
const [depositsModalOpen, setDepositsModalOpen] =
|
|
3959
|
-
const [tokenSelectorOpen, setTokenSelectorOpen] =
|
|
4204
|
+
const [supportedTokens, setSupportedTokens] = useState15([]);
|
|
4205
|
+
const [tokensLoading, setTokensLoading] = useState15(true);
|
|
4206
|
+
const [detailsExpanded, setDetailsExpanded] = useState15(false);
|
|
4207
|
+
const [depositsModalOpen, setDepositsModalOpen] = useState15(false);
|
|
4208
|
+
const [tokenSelectorOpen, setTokenSelectorOpen] = useState15(false);
|
|
3960
4209
|
const allChainsMap = /* @__PURE__ */ new Map();
|
|
3961
4210
|
supportedTokens.forEach((t5) => {
|
|
3962
4211
|
t5.chains.forEach((c) => {
|
|
@@ -3974,7 +4223,7 @@ function TransferCryptoSingleInput({
|
|
|
3974
4223
|
const currentChainType = currentChainData?.chain_type || "ethereum";
|
|
3975
4224
|
const currentWallet = getWalletByChainType2(wallets, currentChainType);
|
|
3976
4225
|
const depositAddress = currentWallet?.address || "";
|
|
3977
|
-
|
|
4226
|
+
useEffect12(() => {
|
|
3978
4227
|
async function fetchSupportedTokens() {
|
|
3979
4228
|
try {
|
|
3980
4229
|
setTokensLoading(true);
|
|
@@ -4046,12 +4295,12 @@ function TransferCryptoSingleInput({
|
|
|
4046
4295
|
destinationChainId,
|
|
4047
4296
|
destinationChainType
|
|
4048
4297
|
]);
|
|
4049
|
-
|
|
4298
|
+
useEffect12(() => {
|
|
4050
4299
|
if (onExecutionsChange) {
|
|
4051
4300
|
onExecutionsChange(depositExecutions);
|
|
4052
4301
|
}
|
|
4053
4302
|
}, [depositExecutions, onExecutionsChange]);
|
|
4054
|
-
|
|
4303
|
+
useEffect12(() => {
|
|
4055
4304
|
if (externalWallets?.length) {
|
|
4056
4305
|
setLoading(false);
|
|
4057
4306
|
return;
|
|
@@ -4108,7 +4357,7 @@ function TransferCryptoSingleInput({
|
|
|
4108
4357
|
publishableKey,
|
|
4109
4358
|
externalWallets
|
|
4110
4359
|
]);
|
|
4111
|
-
|
|
4360
|
+
useEffect12(() => {
|
|
4112
4361
|
if (!supportedTokens.length) return;
|
|
4113
4362
|
const currentToken = supportedTokens.find((t5) => t5.symbol === token);
|
|
4114
4363
|
if (!currentToken || currentToken.chains.length === 0) return;
|
|
@@ -4486,7 +4735,7 @@ function TransferCryptoSingleInput({
|
|
|
4486
4735
|
}
|
|
4487
4736
|
|
|
4488
4737
|
// src/components/deposits/TransferCryptoDoubleInput.tsx
|
|
4489
|
-
import { useState as
|
|
4738
|
+
import { useState as useState16, useEffect as useEffect13 } from "react";
|
|
4490
4739
|
import {
|
|
4491
4740
|
ChevronDown as ChevronDown5,
|
|
4492
4741
|
ChevronUp as ChevronUp4,
|
|
@@ -4651,13 +4900,13 @@ function TransferCryptoDoubleInput({
|
|
|
4651
4900
|
}) {
|
|
4652
4901
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
4653
4902
|
const isDarkMode = themeClass.includes("uf-dark");
|
|
4654
|
-
const [token, setToken] =
|
|
4655
|
-
const [chain, setChain] =
|
|
4656
|
-
const [copied, setCopied] =
|
|
4657
|
-
const [internalWallets, setInternalWallets] =
|
|
4658
|
-
const [loading, setLoading] =
|
|
4903
|
+
const [token, setToken] = useState16("USDC");
|
|
4904
|
+
const [chain, setChain] = useState16("solana:mainnet");
|
|
4905
|
+
const [copied, setCopied] = useState16(false);
|
|
4906
|
+
const [internalWallets, setInternalWallets] = useState16([]);
|
|
4907
|
+
const [loading, setLoading] = useState16(!externalWallets?.length);
|
|
4659
4908
|
const wallets = externalWallets?.length ? externalWallets : internalWallets;
|
|
4660
|
-
const [error, setError] =
|
|
4909
|
+
const [error, setError] = useState16(null);
|
|
4661
4910
|
const { executions: depositExecutions, isPolling } = useDepositPolling({
|
|
4662
4911
|
userId,
|
|
4663
4912
|
publishableKey,
|
|
@@ -4665,10 +4914,10 @@ function TransferCryptoDoubleInput({
|
|
|
4665
4914
|
onDepositSuccess,
|
|
4666
4915
|
onDepositError
|
|
4667
4916
|
});
|
|
4668
|
-
const [supportedTokens, setSupportedTokens] =
|
|
4669
|
-
const [tokensLoading, setTokensLoading] =
|
|
4670
|
-
const [detailsExpanded, setDetailsExpanded] =
|
|
4671
|
-
const [depositsModalOpen, setDepositsModalOpen] =
|
|
4917
|
+
const [supportedTokens, setSupportedTokens] = useState16([]);
|
|
4918
|
+
const [tokensLoading, setTokensLoading] = useState16(true);
|
|
4919
|
+
const [detailsExpanded, setDetailsExpanded] = useState16(false);
|
|
4920
|
+
const [depositsModalOpen, setDepositsModalOpen] = useState16(false);
|
|
4672
4921
|
const allChainsMap = /* @__PURE__ */ new Map();
|
|
4673
4922
|
supportedTokens.forEach((t5) => {
|
|
4674
4923
|
t5.chains.forEach((c) => {
|
|
@@ -4686,7 +4935,7 @@ function TransferCryptoDoubleInput({
|
|
|
4686
4935
|
const currentChainType = currentChainData?.chain_type || "ethereum";
|
|
4687
4936
|
const currentWallet = getWalletByChainType3(wallets, currentChainType);
|
|
4688
4937
|
const depositAddress = currentWallet?.address || "";
|
|
4689
|
-
|
|
4938
|
+
useEffect13(() => {
|
|
4690
4939
|
async function fetchSupportedTokens() {
|
|
4691
4940
|
try {
|
|
4692
4941
|
setTokensLoading(true);
|
|
@@ -4729,12 +4978,12 @@ function TransferCryptoDoubleInput({
|
|
|
4729
4978
|
destinationChainId,
|
|
4730
4979
|
destinationChainType
|
|
4731
4980
|
]);
|
|
4732
|
-
|
|
4981
|
+
useEffect13(() => {
|
|
4733
4982
|
if (onExecutionsChange) {
|
|
4734
4983
|
onExecutionsChange(depositExecutions);
|
|
4735
4984
|
}
|
|
4736
4985
|
}, [depositExecutions, onExecutionsChange]);
|
|
4737
|
-
|
|
4986
|
+
useEffect13(() => {
|
|
4738
4987
|
if (externalWallets?.length) {
|
|
4739
4988
|
setLoading(false);
|
|
4740
4989
|
return;
|
|
@@ -4791,7 +5040,7 @@ function TransferCryptoDoubleInput({
|
|
|
4791
5040
|
publishableKey,
|
|
4792
5041
|
externalWallets
|
|
4793
5042
|
]);
|
|
4794
|
-
|
|
5043
|
+
useEffect13(() => {
|
|
4795
5044
|
if (!supportedTokens.length) return;
|
|
4796
5045
|
const currentToken = supportedTokens.find((t5) => t5.symbol === token);
|
|
4797
5046
|
if (!currentToken || currentToken.chains.length === 0) return;
|
|
@@ -5242,26 +5491,27 @@ function DepositModal({
|
|
|
5242
5491
|
destinationChainId,
|
|
5243
5492
|
destinationTokenAddress,
|
|
5244
5493
|
hideDepositTracker = false,
|
|
5494
|
+
showBalanceHeader = false,
|
|
5245
5495
|
transferInputVariant = "double_input",
|
|
5246
5496
|
onDepositSuccess,
|
|
5247
5497
|
onDepositError,
|
|
5248
5498
|
theme = "dark"
|
|
5249
5499
|
}) {
|
|
5250
|
-
const { colors: colors2 } = useTheme();
|
|
5251
|
-
const [view, setView] =
|
|
5252
|
-
const [cardView, setCardView] =
|
|
5500
|
+
const { colors: colors2, fonts } = useTheme();
|
|
5501
|
+
const [view, setView] = useState17("main");
|
|
5502
|
+
const [cardView, setCardView] = useState17(
|
|
5253
5503
|
"amount"
|
|
5254
5504
|
);
|
|
5255
|
-
const [quotesCount, setQuotesCount] =
|
|
5256
|
-
const [depositsModalOpen, setDepositsModalOpen] =
|
|
5257
|
-
const [depositExecutions, setDepositExecutions] =
|
|
5258
|
-
const [projectConfig, setProjectConfig] =
|
|
5259
|
-
const [wallets, setWallets] =
|
|
5260
|
-
const [walletsLoading, setWalletsLoading] =
|
|
5261
|
-
|
|
5505
|
+
const [quotesCount, setQuotesCount] = useState17(0);
|
|
5506
|
+
const [depositsModalOpen, setDepositsModalOpen] = useState17(false);
|
|
5507
|
+
const [depositExecutions, setDepositExecutions] = useState17([]);
|
|
5508
|
+
const [projectConfig, setProjectConfig] = useState17(null);
|
|
5509
|
+
const [wallets, setWallets] = useState17([]);
|
|
5510
|
+
const [walletsLoading, setWalletsLoading] = useState17(false);
|
|
5511
|
+
useEffect14(() => {
|
|
5262
5512
|
setProjectConfig(null);
|
|
5263
5513
|
}, [publishableKey]);
|
|
5264
|
-
|
|
5514
|
+
useEffect14(() => {
|
|
5265
5515
|
setWallets([]);
|
|
5266
5516
|
}, [
|
|
5267
5517
|
userId,
|
|
@@ -5271,10 +5521,10 @@ function DepositModal({
|
|
|
5271
5521
|
destinationTokenAddress,
|
|
5272
5522
|
publishableKey
|
|
5273
5523
|
]);
|
|
5274
|
-
const [resolvedTheme, setResolvedTheme] =
|
|
5524
|
+
const [resolvedTheme, setResolvedTheme] = useState17(
|
|
5275
5525
|
theme === "auto" ? "dark" : theme
|
|
5276
5526
|
);
|
|
5277
|
-
|
|
5527
|
+
useEffect14(() => {
|
|
5278
5528
|
if (theme === "auto") {
|
|
5279
5529
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
5280
5530
|
setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
@@ -5287,7 +5537,7 @@ function DepositModal({
|
|
|
5287
5537
|
setResolvedTheme(theme);
|
|
5288
5538
|
}
|
|
5289
5539
|
}, [theme]);
|
|
5290
|
-
|
|
5540
|
+
useEffect14(() => {
|
|
5291
5541
|
if (open && !projectConfig) {
|
|
5292
5542
|
getProjectConfig2(publishableKey).then(setProjectConfig).catch(console.error);
|
|
5293
5543
|
}
|
|
@@ -5297,7 +5547,29 @@ function DepositModal({
|
|
|
5297
5547
|
isLoading: isCountryLoading,
|
|
5298
5548
|
error: countryError
|
|
5299
5549
|
} = useAllowedCountry(publishableKey);
|
|
5300
|
-
|
|
5550
|
+
const {
|
|
5551
|
+
isValid: isAddressValid,
|
|
5552
|
+
failureCode: addressFailureCode,
|
|
5553
|
+
metadata: addressFailureMetadata,
|
|
5554
|
+
isLoading: isAddressValidationLoading
|
|
5555
|
+
} = useAddressValidation({
|
|
5556
|
+
recipientAddress,
|
|
5557
|
+
destinationChainType,
|
|
5558
|
+
destinationChainId,
|
|
5559
|
+
destinationTokenAddress,
|
|
5560
|
+
publishableKey,
|
|
5561
|
+
enabled: open,
|
|
5562
|
+
// Only validate when modal is open
|
|
5563
|
+
refetchOnMount: "always"
|
|
5564
|
+
});
|
|
5565
|
+
const addressValidationMessages = i18n.transferCrypto.addressValidation;
|
|
5566
|
+
const getAddressValidationErrorMessage = (code, metadata) => {
|
|
5567
|
+
if (!code) return addressValidationMessages.defaultError;
|
|
5568
|
+
const errors = addressValidationMessages.errors;
|
|
5569
|
+
const template = errors[code] ?? addressValidationMessages.defaultError;
|
|
5570
|
+
return interpolate(template, metadata);
|
|
5571
|
+
};
|
|
5572
|
+
useEffect14(() => {
|
|
5301
5573
|
if (!open || wallets.length > 0) return;
|
|
5302
5574
|
let retryTimeout = null;
|
|
5303
5575
|
let isCancelled = false;
|
|
@@ -5381,10 +5653,16 @@ function DepositModal({
|
|
|
5381
5653
|
DepositHeader,
|
|
5382
5654
|
{
|
|
5383
5655
|
title: modalTitle || "Deposit",
|
|
5384
|
-
onClose: handleClose
|
|
5656
|
+
onClose: handleClose,
|
|
5657
|
+
showBalance: showBalanceHeader,
|
|
5658
|
+
balanceAddress: recipientAddress,
|
|
5659
|
+
balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" ? destinationChainType : void 0,
|
|
5660
|
+
balanceChainId: destinationChainId,
|
|
5661
|
+
balanceTokenAddress: destinationTokenAddress,
|
|
5662
|
+
publishableKey
|
|
5385
5663
|
}
|
|
5386
5664
|
),
|
|
5387
|
-
/* @__PURE__ */ jsx23("div", { className: "uf-pb-4 uf-space-y-3", children: isCountryLoading || !projectConfig ? /* @__PURE__ */ jsxs18(Fragment5, { children: [
|
|
5665
|
+
/* @__PURE__ */ jsx23("div", { className: "uf-pb-4 uf-space-y-3", children: isCountryLoading || isAddressValidationLoading || !projectConfig ? /* @__PURE__ */ jsxs18(Fragment5, { children: [
|
|
5388
5666
|
/* @__PURE__ */ jsx23(SkeletonButton, { variant: "with-icons" }),
|
|
5389
5667
|
/* @__PURE__ */ jsx23(SkeletonButton, { variant: "with-icons" }),
|
|
5390
5668
|
!hideDepositTracker && /* @__PURE__ */ jsx23(SkeletonButton, {})
|
|
@@ -5402,6 +5680,16 @@ function DepositModal({
|
|
|
5402
5680
|
/* @__PURE__ */ jsx23("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: "No Tokens Available" }),
|
|
5403
5681
|
/* @__PURE__ */ jsx23("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: "There are no supported tokens available from your current location." })
|
|
5404
5682
|
] })
|
|
5683
|
+
) : isAddressValid === false ? (
|
|
5684
|
+
/* Invalid recipient address state (e.g., Algorand not opted in) */
|
|
5685
|
+
/* @__PURE__ */ jsxs18("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
|
|
5686
|
+
/* @__PURE__ */ jsx23("div", { className: "uf-w-16 uf-h-16 uf-rounded-full uf-bg-muted uf-flex uf-items-center uf-justify-center uf-mb-4", children: /* @__PURE__ */ jsx23(AlertTriangle, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
|
|
5687
|
+
/* @__PURE__ */ jsx23("h3", { className: "uf-text-lg uf-font-semibold uf-text-foreground uf-mb-2", children: addressValidationMessages.unableToReceiveFunds }),
|
|
5688
|
+
/* @__PURE__ */ jsx23("p", { className: "uf-text-sm uf-text-muted-foreground uf-max-w-[280px]", children: getAddressValidationErrorMessage(
|
|
5689
|
+
addressFailureCode,
|
|
5690
|
+
addressFailureMetadata
|
|
5691
|
+
) })
|
|
5692
|
+
] })
|
|
5405
5693
|
) : (
|
|
5406
5694
|
/* Normal deposit options */
|
|
5407
5695
|
/* @__PURE__ */ jsxs18(Fragment5, { children: [
|