@unifold/ui-react 0.1.40 → 0.1.42
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 +332 -37
- package/dist/index.d.ts +332 -37
- package/dist/index.js +2253 -186
- package/dist/index.mjs +2273 -184
- package/dist/styles-base.css +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -74,22 +74,36 @@ __export(index_exports, {
|
|
|
74
74
|
TransferCryptoButton: () => TransferCryptoButton,
|
|
75
75
|
TransferCryptoDoubleInput: () => TransferCryptoDoubleInput,
|
|
76
76
|
TransferCryptoSingleInput: () => TransferCryptoSingleInput,
|
|
77
|
+
WithdrawConfirmingView: () => WithdrawConfirmingView,
|
|
78
|
+
WithdrawDoubleInput: () => WithdrawDoubleInput,
|
|
79
|
+
WithdrawExecutionItem: () => WithdrawExecutionItem,
|
|
80
|
+
WithdrawForm: () => WithdrawForm,
|
|
81
|
+
WithdrawModal: () => WithdrawModal,
|
|
82
|
+
WithdrawTokenSelector: () => WithdrawTokenSelector,
|
|
77
83
|
buttonVariants: () => buttonVariants,
|
|
78
84
|
cn: () => cn,
|
|
79
85
|
colors: () => colors,
|
|
80
86
|
defaultColors: () => defaultColors,
|
|
87
|
+
detectBrowserWallet: () => detectBrowserWallet,
|
|
81
88
|
getColors: () => getColors,
|
|
82
89
|
mergeColors: () => mergeColors,
|
|
83
90
|
resolveComponentTokens: () => resolveComponentTokens,
|
|
91
|
+
sendEvmWithdraw: () => sendEvmWithdraw,
|
|
92
|
+
sendSolanaWithdraw: () => sendSolanaWithdraw,
|
|
84
93
|
truncateAddress: () => truncateAddress,
|
|
94
|
+
useAddressBalance: () => useAddressBalance,
|
|
85
95
|
useAllowedCountry: () => useAllowedCountry,
|
|
86
96
|
useDepositPolling: () => useDepositPolling,
|
|
87
|
-
|
|
97
|
+
useSourceTokenValidation: () => useSourceTokenValidation,
|
|
98
|
+
useSupportedDestinationTokens: () => useSupportedDestinationTokens,
|
|
99
|
+
useTheme: () => useTheme,
|
|
100
|
+
useVerifyRecipientAddress: () => useVerifyRecipientAddress,
|
|
101
|
+
useWithdrawPolling: () => useWithdrawPolling
|
|
88
102
|
});
|
|
89
103
|
module.exports = __toCommonJS(index_exports);
|
|
90
104
|
|
|
91
105
|
// src/components/deposits/DepositModal.tsx
|
|
92
|
-
var
|
|
106
|
+
var import_react18 = require("react");
|
|
93
107
|
var import_lucide_react23 = require("lucide-react");
|
|
94
108
|
|
|
95
109
|
// src/components/shared/dialog.tsx
|
|
@@ -693,6 +707,7 @@ function useDepositAddress(params) {
|
|
|
693
707
|
destinationChainType,
|
|
694
708
|
destinationChainId,
|
|
695
709
|
destinationTokenAddress,
|
|
710
|
+
actionType,
|
|
696
711
|
enabled = true
|
|
697
712
|
} = params;
|
|
698
713
|
return (0, import_react_query.useQuery)({
|
|
@@ -704,6 +719,7 @@ function useDepositAddress(params) {
|
|
|
704
719
|
destinationChainType ?? null,
|
|
705
720
|
destinationChainId ?? null,
|
|
706
721
|
destinationTokenAddress ?? null,
|
|
722
|
+
actionType ?? null,
|
|
707
723
|
publishableKey
|
|
708
724
|
],
|
|
709
725
|
queryFn: () => (0, import_core.createDepositAddress)(
|
|
@@ -712,7 +728,8 @@ function useDepositAddress(params) {
|
|
|
712
728
|
recipient_address: recipientAddress,
|
|
713
729
|
destination_chain_type: destinationChainType,
|
|
714
730
|
destination_chain_id: destinationChainId,
|
|
715
|
-
destination_token_address: destinationTokenAddress
|
|
731
|
+
destination_token_address: destinationTokenAddress,
|
|
732
|
+
action_type: actionType
|
|
716
733
|
},
|
|
717
734
|
publishableKey
|
|
718
735
|
),
|
|
@@ -1426,6 +1443,30 @@ var en_default = {
|
|
|
1426
1443
|
youReceive: "You receive",
|
|
1427
1444
|
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."
|
|
1428
1445
|
}
|
|
1446
|
+
},
|
|
1447
|
+
withdrawModal: {
|
|
1448
|
+
title: "Withdraw",
|
|
1449
|
+
withdrawCrypto: {
|
|
1450
|
+
title: "Withdraw with Crypto",
|
|
1451
|
+
subtitle: "Send to any wallet address"
|
|
1452
|
+
},
|
|
1453
|
+
selectToken: "Select withdrawal token",
|
|
1454
|
+
receiveToken: "Receive token",
|
|
1455
|
+
receiveChain: "Receive chain",
|
|
1456
|
+
recipientAddress: "Recipient address",
|
|
1457
|
+
recipientAddressPlaceholder: "Enter wallet address",
|
|
1458
|
+
amount: "Amount",
|
|
1459
|
+
amountPlaceholder: "0.00",
|
|
1460
|
+
balance: "Balance",
|
|
1461
|
+
minimum: "min",
|
|
1462
|
+
withdraw: "Withdraw",
|
|
1463
|
+
invalidAddress: "Please enter a valid address",
|
|
1464
|
+
invalidAmount: "Please enter a valid amount",
|
|
1465
|
+
verifyingAddress: "Verifying address...",
|
|
1466
|
+
loading: "Loading...",
|
|
1467
|
+
noTokensAvailable: "No tokens available",
|
|
1468
|
+
review: "Review Withdrawal",
|
|
1469
|
+
back: "Back"
|
|
1429
1470
|
}
|
|
1430
1471
|
};
|
|
1431
1472
|
|
|
@@ -1510,7 +1551,7 @@ function useDepositPolling({
|
|
|
1510
1551
|
const modalOpenedAt = modalOpenedAtRef.current;
|
|
1511
1552
|
const poll = async () => {
|
|
1512
1553
|
try {
|
|
1513
|
-
const response = await (0, import_core6.queryExecutions)(userId, publishableKey);
|
|
1554
|
+
const response = await (0, import_core6.queryExecutions)(userId, publishableKey, import_core6.ActionType.Deposit);
|
|
1514
1555
|
const cutoff = new Date(modalOpenedAt.getTime() - CUTOFF_BUFFER_MS);
|
|
1515
1556
|
const sortedExecutions = [...response.data].sort((a, b) => {
|
|
1516
1557
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
@@ -1646,7 +1687,8 @@ function formatCurrency(currency) {
|
|
|
1646
1687
|
}
|
|
1647
1688
|
function DepositDetailContent({
|
|
1648
1689
|
execution,
|
|
1649
|
-
className
|
|
1690
|
+
className,
|
|
1691
|
+
variant = "deposit"
|
|
1650
1692
|
}) {
|
|
1651
1693
|
const { colors: colors2, fonts, components } = useTheme();
|
|
1652
1694
|
const [chains, setChains] = (0, import_react4.useState)([]);
|
|
@@ -2052,7 +2094,7 @@ function DepositDetailContent({
|
|
|
2052
2094
|
color: components.card.rowLeftLabel,
|
|
2053
2095
|
fontFamily: fonts.regular
|
|
2054
2096
|
},
|
|
2055
|
-
children: "Deposit Tx"
|
|
2097
|
+
children: variant === "withdraw" ? "Withdrawal Tx" : "Deposit Tx"
|
|
2056
2098
|
}
|
|
2057
2099
|
),
|
|
2058
2100
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
@@ -7095,7 +7137,7 @@ function useSupportedDepositTokens(publishableKey, options) {
|
|
|
7095
7137
|
}
|
|
7096
7138
|
|
|
7097
7139
|
// src/components/deposits/TransferCryptoSingleInput.tsx
|
|
7098
|
-
var
|
|
7140
|
+
var import_react15 = require("react");
|
|
7099
7141
|
var import_lucide_react16 = require("lucide-react");
|
|
7100
7142
|
|
|
7101
7143
|
// src/components/deposits/StyledQRCode.tsx
|
|
@@ -7338,7 +7380,7 @@ function DepositsModal({
|
|
|
7338
7380
|
if (!open || !userId) return;
|
|
7339
7381
|
const fetchExecutions = async () => {
|
|
7340
7382
|
try {
|
|
7341
|
-
const response = await (0, import_core19.queryExecutions)(userId, publishableKey);
|
|
7383
|
+
const response = await (0, import_core19.queryExecutions)(userId, publishableKey, import_core19.ActionType.Deposit);
|
|
7342
7384
|
const sorted = [...response.data].sort((a, b) => {
|
|
7343
7385
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
7344
7386
|
const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
@@ -7460,7 +7502,7 @@ function saveRecentToken(token) {
|
|
|
7460
7502
|
try {
|
|
7461
7503
|
const recent = getRecentTokens();
|
|
7462
7504
|
const filtered = recent.filter(
|
|
7463
|
-
(
|
|
7505
|
+
(t11) => !(t11.symbol === token.symbol && t11.chainType === token.chainType && t11.chainId === token.chainId)
|
|
7464
7506
|
);
|
|
7465
7507
|
filtered.unshift(token);
|
|
7466
7508
|
const trimmed = filtered.slice(0, MAX_RECENT_TOKENS);
|
|
@@ -7473,7 +7515,7 @@ function removeRecentToken(token) {
|
|
|
7473
7515
|
try {
|
|
7474
7516
|
const recent = getRecentTokens();
|
|
7475
7517
|
const filtered = recent.filter(
|
|
7476
|
-
(
|
|
7518
|
+
(t11) => !(t11.symbol === token.symbol && t11.chainType === token.chainType && t11.chainId === token.chainId)
|
|
7477
7519
|
);
|
|
7478
7520
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(filtered));
|
|
7479
7521
|
return filtered;
|
|
@@ -7512,7 +7554,7 @@ function TokenSelectorSheet({
|
|
|
7512
7554
|
const addOption = (symbol, chainType, chainId, isRecent) => {
|
|
7513
7555
|
const key = `${symbol}-${chainType}:${chainId}`;
|
|
7514
7556
|
if (seen.has(key)) return;
|
|
7515
|
-
const tokenData = tokens.find((
|
|
7557
|
+
const tokenData = tokens.find((t11) => t11.symbol === symbol);
|
|
7516
7558
|
if (!tokenData) return;
|
|
7517
7559
|
const chainData = tokenData.chains.find(
|
|
7518
7560
|
(c) => c.chain_type === chainType && c.chain_id === chainId
|
|
@@ -7972,6 +8014,107 @@ function DepositPollingUi({
|
|
|
7972
8014
|
return null;
|
|
7973
8015
|
}
|
|
7974
8016
|
|
|
8017
|
+
// src/hooks/use-default-source-token.ts
|
|
8018
|
+
var import_react13 = require("react");
|
|
8019
|
+
var getChainKey = (chainId, chainType) => {
|
|
8020
|
+
return `${chainType}:${chainId}`;
|
|
8021
|
+
};
|
|
8022
|
+
function resolveSourceToken(supportedTokens, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol) {
|
|
8023
|
+
if (!supportedTokens.length) return null;
|
|
8024
|
+
let selectedTokenData;
|
|
8025
|
+
let selectedChainData;
|
|
8026
|
+
const hasChainDefaults = defaultSourceChainType && defaultSourceChainId;
|
|
8027
|
+
if (defaultSourceTokenAddress && hasChainDefaults) {
|
|
8028
|
+
for (const t11 of supportedTokens) {
|
|
8029
|
+
const matchingChain = t11.chains.find(
|
|
8030
|
+
(c) => c.token_address.toLowerCase() === defaultSourceTokenAddress.toLowerCase() && c.chain_type === defaultSourceChainType && c.chain_id === defaultSourceChainId
|
|
8031
|
+
);
|
|
8032
|
+
if (matchingChain) {
|
|
8033
|
+
selectedTokenData = t11;
|
|
8034
|
+
selectedChainData = matchingChain;
|
|
8035
|
+
break;
|
|
8036
|
+
}
|
|
8037
|
+
}
|
|
8038
|
+
}
|
|
8039
|
+
if (!selectedTokenData && defaultSourceSymbol && hasChainDefaults) {
|
|
8040
|
+
for (const t11 of supportedTokens) {
|
|
8041
|
+
if (t11.symbol !== defaultSourceSymbol) continue;
|
|
8042
|
+
const matchedChain = t11.chains.find(
|
|
8043
|
+
(c) => c.chain_type === defaultSourceChainType && c.chain_id === defaultSourceChainId
|
|
8044
|
+
);
|
|
8045
|
+
if (matchedChain) {
|
|
8046
|
+
selectedTokenData = t11;
|
|
8047
|
+
selectedChainData = matchedChain;
|
|
8048
|
+
break;
|
|
8049
|
+
}
|
|
8050
|
+
}
|
|
8051
|
+
}
|
|
8052
|
+
if (!selectedTokenData) {
|
|
8053
|
+
for (const t11 of supportedTokens) {
|
|
8054
|
+
if (t11.chains.length > 0) {
|
|
8055
|
+
selectedTokenData = t11;
|
|
8056
|
+
selectedChainData = t11.chains[0];
|
|
8057
|
+
break;
|
|
8058
|
+
}
|
|
8059
|
+
}
|
|
8060
|
+
}
|
|
8061
|
+
if (selectedTokenData && selectedChainData) {
|
|
8062
|
+
return { token: selectedTokenData, chain: selectedChainData };
|
|
8063
|
+
}
|
|
8064
|
+
return null;
|
|
8065
|
+
}
|
|
8066
|
+
function useDefaultSourceToken({
|
|
8067
|
+
supportedTokens,
|
|
8068
|
+
defaultSourceChainType,
|
|
8069
|
+
defaultSourceChainId,
|
|
8070
|
+
defaultSourceTokenAddress,
|
|
8071
|
+
defaultSourceSymbol
|
|
8072
|
+
}) {
|
|
8073
|
+
const [token, setToken] = (0, import_react13.useState)(null);
|
|
8074
|
+
const [chain, setChain] = (0, import_react13.useState)(null);
|
|
8075
|
+
const [initialSelectionDone, setInitialSelectionDone] = (0, import_react13.useState)(false);
|
|
8076
|
+
const appliedDefaultsRef = (0, import_react13.useRef)("");
|
|
8077
|
+
(0, import_react13.useEffect)(() => {
|
|
8078
|
+
if (!supportedTokens.length) return;
|
|
8079
|
+
const defaultsKey = `${defaultSourceTokenAddress ?? ""}|${defaultSourceSymbol ?? ""}|${defaultSourceChainType ?? ""}|${defaultSourceChainId ?? ""}`;
|
|
8080
|
+
const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
|
|
8081
|
+
if (initialSelectionDone && !defaultsChanged) return;
|
|
8082
|
+
const result = resolveSourceToken(
|
|
8083
|
+
supportedTokens,
|
|
8084
|
+
defaultSourceChainType,
|
|
8085
|
+
defaultSourceChainId,
|
|
8086
|
+
defaultSourceTokenAddress,
|
|
8087
|
+
defaultSourceSymbol
|
|
8088
|
+
);
|
|
8089
|
+
if (result) {
|
|
8090
|
+
setToken(result.token.symbol);
|
|
8091
|
+
setChain(getChainKey(result.chain.chain_id, result.chain.chain_type));
|
|
8092
|
+
appliedDefaultsRef.current = defaultsKey;
|
|
8093
|
+
setInitialSelectionDone(true);
|
|
8094
|
+
}
|
|
8095
|
+
}, [
|
|
8096
|
+
supportedTokens,
|
|
8097
|
+
defaultSourceTokenAddress,
|
|
8098
|
+
defaultSourceSymbol,
|
|
8099
|
+
defaultSourceChainType,
|
|
8100
|
+
defaultSourceChainId,
|
|
8101
|
+
initialSelectionDone
|
|
8102
|
+
]);
|
|
8103
|
+
(0, import_react13.useEffect)(() => {
|
|
8104
|
+
if (!supportedTokens.length || !token) return;
|
|
8105
|
+
const currentToken = supportedTokens.find((t11) => t11.symbol === token);
|
|
8106
|
+
if (!currentToken || currentToken.chains.length === 0) return;
|
|
8107
|
+
const isChainAvailable = chain && currentToken.chains.some((c) => {
|
|
8108
|
+
return getChainKey(c.chain_id, c.chain_type) === chain;
|
|
8109
|
+
});
|
|
8110
|
+
if (!isChainAvailable) {
|
|
8111
|
+
const firstChain = currentToken.chains[0];
|
|
8112
|
+
setChain(getChainKey(firstChain.chain_id, firstChain.chain_type));
|
|
8113
|
+
}
|
|
8114
|
+
}, [token, supportedTokens, chain]);
|
|
8115
|
+
return { token, chain, setToken, setChain, initialSelectionDone };
|
|
8116
|
+
}
|
|
8117
|
+
|
|
7975
8118
|
// src/components/deposits/shared/DepositFooterLinks.tsx
|
|
7976
8119
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
7977
8120
|
function DepositFooterLinks({
|
|
@@ -8138,9 +8281,9 @@ function GlossaryModal({
|
|
|
8138
8281
|
}
|
|
8139
8282
|
|
|
8140
8283
|
// src/components/deposits/shared/useCopyAddress.ts
|
|
8141
|
-
var
|
|
8284
|
+
var import_react14 = require("react");
|
|
8142
8285
|
function useCopyAddress() {
|
|
8143
|
-
const [copied, setCopied] = (0,
|
|
8286
|
+
const [copied, setCopied] = (0, import_react14.useState)(false);
|
|
8144
8287
|
const handleCopy = (address) => {
|
|
8145
8288
|
if (!address) return;
|
|
8146
8289
|
navigator.clipboard.writeText(address);
|
|
@@ -8219,7 +8362,7 @@ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
|
|
|
8219
8362
|
var import_core20 = require("@unifold/core");
|
|
8220
8363
|
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
8221
8364
|
var t4 = i18n.transferCrypto;
|
|
8222
|
-
var
|
|
8365
|
+
var getChainKey2 = (chainId, chainType) => {
|
|
8223
8366
|
return `${chainType}:${chainId}`;
|
|
8224
8367
|
};
|
|
8225
8368
|
var parseChainKey = (chainKey) => {
|
|
@@ -8233,6 +8376,10 @@ function TransferCryptoSingleInput({
|
|
|
8233
8376
|
destinationChainType,
|
|
8234
8377
|
destinationChainId,
|
|
8235
8378
|
destinationTokenAddress,
|
|
8379
|
+
defaultSourceChainType,
|
|
8380
|
+
defaultSourceChainId,
|
|
8381
|
+
defaultSourceTokenAddress,
|
|
8382
|
+
defaultSourceSymbol,
|
|
8236
8383
|
depositConfirmationMode = "auto_ui",
|
|
8237
8384
|
onExecutionsChange,
|
|
8238
8385
|
onDepositSuccess,
|
|
@@ -8241,21 +8388,25 @@ function TransferCryptoSingleInput({
|
|
|
8241
8388
|
}) {
|
|
8242
8389
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
8243
8390
|
const isDarkMode = themeClass.includes("uf-dark");
|
|
8244
|
-
const [
|
|
8245
|
-
const [chain, setChain] = (0, import_react14.useState)("solana:mainnet");
|
|
8246
|
-
const [copied, setCopied] = (0, import_react14.useState)(false);
|
|
8391
|
+
const [copied, setCopied] = (0, import_react15.useState)(false);
|
|
8247
8392
|
const { copied: copiedRecipient, handleCopy: handleCopyRecipientAddress } = useCopyAddress();
|
|
8248
|
-
const [glossaryOpen, setGlossaryOpen] = (0,
|
|
8249
|
-
const [detailsExpanded, setDetailsExpanded] = (0,
|
|
8250
|
-
const [depositsModalOpen, setDepositsModalOpen] = (0,
|
|
8251
|
-
const [tokenSelectorOpen, setTokenSelectorOpen] = (0,
|
|
8252
|
-
const [initialSelectionDone, setInitialSelectionDone] = (0, import_react14.useState)(false);
|
|
8393
|
+
const [glossaryOpen, setGlossaryOpen] = (0, import_react15.useState)(false);
|
|
8394
|
+
const [detailsExpanded, setDetailsExpanded] = (0, import_react15.useState)(false);
|
|
8395
|
+
const [depositsModalOpen, setDepositsModalOpen] = (0, import_react15.useState)(false);
|
|
8396
|
+
const [tokenSelectorOpen, setTokenSelectorOpen] = (0, import_react15.useState)(false);
|
|
8253
8397
|
const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDepositTokens(publishableKey, {
|
|
8254
8398
|
destination_token_address: destinationTokenAddress,
|
|
8255
8399
|
destination_chain_id: destinationChainId,
|
|
8256
8400
|
destination_chain_type: destinationChainType
|
|
8257
8401
|
});
|
|
8258
8402
|
const supportedTokens = tokensResponse?.data ?? [];
|
|
8403
|
+
const { token, chain, setToken, setChain, initialSelectionDone } = useDefaultSourceToken({
|
|
8404
|
+
supportedTokens,
|
|
8405
|
+
defaultSourceChainType,
|
|
8406
|
+
defaultSourceChainId,
|
|
8407
|
+
defaultSourceTokenAddress,
|
|
8408
|
+
defaultSourceSymbol
|
|
8409
|
+
});
|
|
8259
8410
|
const {
|
|
8260
8411
|
data: depositAddressResponse,
|
|
8261
8412
|
isLoading: walletsLoading,
|
|
@@ -8273,10 +8424,10 @@ function TransferCryptoSingleInput({
|
|
|
8273
8424
|
const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
|
|
8274
8425
|
const loading = externalWallets?.length ? false : walletsLoading;
|
|
8275
8426
|
const error = walletsError?.message ?? null;
|
|
8276
|
-
const allAvailableChains = (0,
|
|
8427
|
+
const allAvailableChains = (0, import_react15.useMemo)(() => {
|
|
8277
8428
|
const chainsMap = /* @__PURE__ */ new Map();
|
|
8278
|
-
supportedTokens.forEach((
|
|
8279
|
-
|
|
8429
|
+
supportedTokens.forEach((t11) => {
|
|
8430
|
+
t11.chains.forEach((c) => {
|
|
8280
8431
|
const comboKey = `${c.chain_type}:${c.chain_id}`;
|
|
8281
8432
|
if (!chainsMap.has(comboKey)) {
|
|
8282
8433
|
chainsMap.set(comboKey, c);
|
|
@@ -8285,10 +8436,10 @@ function TransferCryptoSingleInput({
|
|
|
8285
8436
|
});
|
|
8286
8437
|
return Array.from(chainsMap.values());
|
|
8287
8438
|
}, [supportedTokens]);
|
|
8288
|
-
const currentChainCombo = parseChainKey(chain);
|
|
8289
|
-
const currentChainData = allAvailableChains.find(
|
|
8439
|
+
const currentChainCombo = chain ? parseChainKey(chain) : null;
|
|
8440
|
+
const currentChainData = currentChainCombo ? allAvailableChains.find(
|
|
8290
8441
|
(c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
|
|
8291
|
-
);
|
|
8442
|
+
) : void 0;
|
|
8292
8443
|
const currentChainType = currentChainData?.chain_type || "ethereum";
|
|
8293
8444
|
const currentWallet = (0, import_core20.getWalletByChainType)(wallets, currentChainType);
|
|
8294
8445
|
const depositAddress = currentWallet?.address || "";
|
|
@@ -8306,84 +8457,26 @@ function TransferCryptoSingleInput({
|
|
|
8306
8457
|
onDepositSuccess,
|
|
8307
8458
|
onDepositError
|
|
8308
8459
|
});
|
|
8309
|
-
(0,
|
|
8310
|
-
if (!supportedTokens.length || initialSelectionDone) return;
|
|
8311
|
-
let selectedTokenData;
|
|
8312
|
-
let selectedChainData;
|
|
8313
|
-
if (destinationTokenAddress) {
|
|
8314
|
-
for (const t7 of supportedTokens) {
|
|
8315
|
-
const matchingChain = t7.chains.find(
|
|
8316
|
-
(c) => c.token_address.toLowerCase() === destinationTokenAddress.toLowerCase()
|
|
8317
|
-
);
|
|
8318
|
-
if (matchingChain) {
|
|
8319
|
-
selectedTokenData = t7;
|
|
8320
|
-
selectedChainData = matchingChain;
|
|
8321
|
-
break;
|
|
8322
|
-
}
|
|
8323
|
-
}
|
|
8324
|
-
}
|
|
8325
|
-
if (!selectedTokenData) {
|
|
8326
|
-
selectedTokenData = supportedTokens.find((t7) => t7.symbol === "USDC");
|
|
8327
|
-
if (selectedTokenData && selectedTokenData.chains.length > 0) {
|
|
8328
|
-
selectedChainData = selectedTokenData.chains[0];
|
|
8329
|
-
}
|
|
8330
|
-
}
|
|
8331
|
-
if (!selectedTokenData) {
|
|
8332
|
-
selectedTokenData = supportedTokens.find((t7) => t7.symbol === "USDT");
|
|
8333
|
-
if (selectedTokenData && selectedTokenData.chains.length > 0) {
|
|
8334
|
-
selectedChainData = selectedTokenData.chains[0];
|
|
8335
|
-
}
|
|
8336
|
-
}
|
|
8337
|
-
if (!selectedTokenData) {
|
|
8338
|
-
selectedTokenData = supportedTokens[0];
|
|
8339
|
-
if (selectedTokenData.chains.length > 0) {
|
|
8340
|
-
selectedChainData = selectedTokenData.chains[0];
|
|
8341
|
-
}
|
|
8342
|
-
}
|
|
8343
|
-
if (selectedTokenData) {
|
|
8344
|
-
setToken(selectedTokenData.symbol);
|
|
8345
|
-
}
|
|
8346
|
-
if (selectedChainData) {
|
|
8347
|
-
setChain(
|
|
8348
|
-
getChainKey(selectedChainData.chain_id, selectedChainData.chain_type)
|
|
8349
|
-
);
|
|
8350
|
-
}
|
|
8351
|
-
setInitialSelectionDone(true);
|
|
8352
|
-
}, [supportedTokens, destinationTokenAddress, initialSelectionDone]);
|
|
8353
|
-
(0, import_react14.useEffect)(() => {
|
|
8460
|
+
(0, import_react15.useEffect)(() => {
|
|
8354
8461
|
if (onExecutionsChange) {
|
|
8355
8462
|
onExecutionsChange(depositExecutions);
|
|
8356
8463
|
}
|
|
8357
8464
|
}, [depositExecutions, onExecutionsChange]);
|
|
8358
|
-
|
|
8359
|
-
if (!supportedTokens.length) return;
|
|
8360
|
-
const currentToken = supportedTokens.find((t7) => t7.symbol === token);
|
|
8361
|
-
if (!currentToken || currentToken.chains.length === 0) return;
|
|
8362
|
-
const isChainAvailable = currentToken.chains.some((c) => {
|
|
8363
|
-
const key = getChainKey(c.chain_id, c.chain_type);
|
|
8364
|
-
return key === chain;
|
|
8365
|
-
});
|
|
8366
|
-
if (!isChainAvailable) {
|
|
8367
|
-
const firstChain = currentToken.chains[0];
|
|
8368
|
-
const newChain = getChainKey(firstChain.chain_id, firstChain.chain_type);
|
|
8369
|
-
setChain(newChain);
|
|
8370
|
-
}
|
|
8371
|
-
}, [token, supportedTokens, chain]);
|
|
8372
|
-
const selectedToken = supportedTokens.find((t7) => t7.symbol === token);
|
|
8465
|
+
const selectedToken = token ? supportedTokens.find((t11) => t11.symbol === token) : void 0;
|
|
8373
8466
|
const availableChainsForToken = selectedToken?.chains || [];
|
|
8374
|
-
const currentChainFromBackend = availableChainsForToken.find((c) => {
|
|
8375
|
-
const key =
|
|
8467
|
+
const currentChainFromBackend = chain ? availableChainsForToken.find((c) => {
|
|
8468
|
+
const key = getChainKey2(c.chain_id, c.chain_type);
|
|
8376
8469
|
return key === chain;
|
|
8377
8470
|
}) || allAvailableChains.find((c) => {
|
|
8378
|
-
const key =
|
|
8471
|
+
const key = getChainKey2(c.chain_id, c.chain_type);
|
|
8379
8472
|
return key === chain;
|
|
8380
|
-
});
|
|
8473
|
+
}) : void 0;
|
|
8381
8474
|
const handleCopyAddress = () => {
|
|
8382
8475
|
navigator.clipboard.writeText(depositAddress);
|
|
8383
8476
|
setCopied(true);
|
|
8384
8477
|
setTimeout(() => setCopied(false), 2e3);
|
|
8385
8478
|
};
|
|
8386
|
-
const
|
|
8479
|
+
const formatProcessingTime3 = (seconds) => {
|
|
8387
8480
|
if (seconds === null) {
|
|
8388
8481
|
return t4.processingTime.lessThanMinutes.replace("{{minutes}}", "1");
|
|
8389
8482
|
}
|
|
@@ -8412,10 +8505,10 @@ function TransferCryptoSingleInput({
|
|
|
8412
8505
|
"button",
|
|
8413
8506
|
{
|
|
8414
8507
|
onClick: () => setTokenSelectorOpen(true),
|
|
8415
|
-
disabled: tokensLoading || supportedTokens.length === 0,
|
|
8508
|
+
disabled: tokensLoading || !token || supportedTokens.length === 0,
|
|
8416
8509
|
className: "uf-w-full hover:uf-bg-accent uf-p-3 uf-flex uf-items-center uf-gap-3 uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
|
|
8417
8510
|
style: { backgroundColor: components.card.backgroundColor, borderRadius: components.card.borderRadius, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` },
|
|
8418
|
-
children: tokensLoading ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3 uf-animate-pulse", children: [
|
|
8511
|
+
children: tokensLoading || !token ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-3 uf-animate-pulse", children: [
|
|
8419
8512
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "uf-w-10 uf-h-10 uf-rounded-full uf-bg-muted" }),
|
|
8420
8513
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { className: "uf-flex-1", children: [
|
|
8421
8514
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "uf-h-4 uf-w-16 uf-bg-muted uf-rounded uf-mb-1" }),
|
|
@@ -8489,8 +8582,8 @@ function TransferCryptoSingleInput({
|
|
|
8489
8582
|
open: tokenSelectorOpen,
|
|
8490
8583
|
onOpenChange: setTokenSelectorOpen,
|
|
8491
8584
|
tokens: supportedTokens,
|
|
8492
|
-
selectedToken: token,
|
|
8493
|
-
selectedChainKey: chain,
|
|
8585
|
+
selectedToken: token ?? "",
|
|
8586
|
+
selectedChainKey: chain ?? "",
|
|
8494
8587
|
onSelect: (newToken, newChain) => {
|
|
8495
8588
|
setToken(newToken);
|
|
8496
8589
|
setChain(newChain);
|
|
@@ -8592,7 +8685,7 @@ function TransferCryptoSingleInput({
|
|
|
8592
8685
|
t4.processingTime.label,
|
|
8593
8686
|
":",
|
|
8594
8687
|
" ",
|
|
8595
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children:
|
|
8688
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: formatProcessingTime3(processingTime) })
|
|
8596
8689
|
] })
|
|
8597
8690
|
] }),
|
|
8598
8691
|
detailsExpanded ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react16.ChevronUp, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react16.ChevronDown, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } })
|
|
@@ -8702,7 +8795,7 @@ function TransferCryptoSingleInput({
|
|
|
8702
8795
|
}
|
|
8703
8796
|
|
|
8704
8797
|
// src/components/deposits/TransferCryptoDoubleInput.tsx
|
|
8705
|
-
var
|
|
8798
|
+
var import_react16 = require("react");
|
|
8706
8799
|
var import_lucide_react18 = require("lucide-react");
|
|
8707
8800
|
|
|
8708
8801
|
// src/components/shared/select.tsx
|
|
@@ -8843,7 +8936,7 @@ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
|
8843
8936
|
var import_core21 = require("@unifold/core");
|
|
8844
8937
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
8845
8938
|
var t5 = i18n.transferCrypto;
|
|
8846
|
-
var
|
|
8939
|
+
var getChainKey3 = (chainId, chainType) => {
|
|
8847
8940
|
return `${chainType}:${chainId}`;
|
|
8848
8941
|
};
|
|
8849
8942
|
var parseChainKey2 = (chainKey) => {
|
|
@@ -8857,6 +8950,10 @@ function TransferCryptoDoubleInput({
|
|
|
8857
8950
|
destinationChainType,
|
|
8858
8951
|
destinationChainId,
|
|
8859
8952
|
destinationTokenAddress,
|
|
8953
|
+
defaultSourceChainType,
|
|
8954
|
+
defaultSourceChainId,
|
|
8955
|
+
defaultSourceTokenAddress,
|
|
8956
|
+
defaultSourceSymbol,
|
|
8860
8957
|
depositConfirmationMode = "auto_ui",
|
|
8861
8958
|
onExecutionsChange,
|
|
8862
8959
|
onDepositSuccess,
|
|
@@ -8865,20 +8962,24 @@ function TransferCryptoDoubleInput({
|
|
|
8865
8962
|
}) {
|
|
8866
8963
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
8867
8964
|
const isDarkMode = themeClass.includes("uf-dark");
|
|
8868
|
-
const [
|
|
8869
|
-
const [chain, setChain] = (0, import_react15.useState)("solana:mainnet");
|
|
8870
|
-
const [copied, setCopied] = (0, import_react15.useState)(false);
|
|
8965
|
+
const [copied, setCopied] = (0, import_react16.useState)(false);
|
|
8871
8966
|
const { copied: copiedRecipient, handleCopy: handleCopyRecipientAddress } = useCopyAddress();
|
|
8872
|
-
const [glossaryOpen, setGlossaryOpen] = (0,
|
|
8873
|
-
const [detailsExpanded, setDetailsExpanded] = (0,
|
|
8874
|
-
const [depositsModalOpen, setDepositsModalOpen] = (0,
|
|
8875
|
-
const [initialSelectionDone, setInitialSelectionDone] = (0, import_react15.useState)(false);
|
|
8967
|
+
const [glossaryOpen, setGlossaryOpen] = (0, import_react16.useState)(false);
|
|
8968
|
+
const [detailsExpanded, setDetailsExpanded] = (0, import_react16.useState)(false);
|
|
8969
|
+
const [depositsModalOpen, setDepositsModalOpen] = (0, import_react16.useState)(false);
|
|
8876
8970
|
const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDepositTokens(publishableKey, {
|
|
8877
8971
|
destination_token_address: destinationTokenAddress,
|
|
8878
8972
|
destination_chain_id: destinationChainId,
|
|
8879
8973
|
destination_chain_type: destinationChainType
|
|
8880
8974
|
});
|
|
8881
8975
|
const supportedTokens = tokensResponse?.data ?? [];
|
|
8976
|
+
const { token, chain, setToken, setChain, initialSelectionDone } = useDefaultSourceToken({
|
|
8977
|
+
supportedTokens,
|
|
8978
|
+
defaultSourceChainType,
|
|
8979
|
+
defaultSourceChainId,
|
|
8980
|
+
defaultSourceTokenAddress,
|
|
8981
|
+
defaultSourceSymbol
|
|
8982
|
+
});
|
|
8882
8983
|
const {
|
|
8883
8984
|
data: depositAddressResponse,
|
|
8884
8985
|
isLoading: walletsLoading,
|
|
@@ -8896,10 +8997,10 @@ function TransferCryptoDoubleInput({
|
|
|
8896
8997
|
const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
|
|
8897
8998
|
const loading = externalWallets?.length ? false : walletsLoading;
|
|
8898
8999
|
const error = walletsError?.message ?? null;
|
|
8899
|
-
const allAvailableChains = (0,
|
|
9000
|
+
const allAvailableChains = (0, import_react16.useMemo)(() => {
|
|
8900
9001
|
const chainsMap = /* @__PURE__ */ new Map();
|
|
8901
|
-
supportedTokens.forEach((
|
|
8902
|
-
|
|
9002
|
+
supportedTokens.forEach((t11) => {
|
|
9003
|
+
t11.chains.forEach((c) => {
|
|
8903
9004
|
const comboKey = `${c.chain_type}:${c.chain_id}`;
|
|
8904
9005
|
if (!chainsMap.has(comboKey)) {
|
|
8905
9006
|
chainsMap.set(comboKey, c);
|
|
@@ -8908,10 +9009,10 @@ function TransferCryptoDoubleInput({
|
|
|
8908
9009
|
});
|
|
8909
9010
|
return Array.from(chainsMap.values());
|
|
8910
9011
|
}, [supportedTokens]);
|
|
8911
|
-
const currentChainCombo = parseChainKey2(chain);
|
|
8912
|
-
const currentChainData = allAvailableChains.find(
|
|
9012
|
+
const currentChainCombo = chain ? parseChainKey2(chain) : null;
|
|
9013
|
+
const currentChainData = currentChainCombo ? allAvailableChains.find(
|
|
8913
9014
|
(c) => c.chain_type === currentChainCombo.chainType && c.chain_id === currentChainCombo.chainId
|
|
8914
|
-
);
|
|
9015
|
+
) : void 0;
|
|
8915
9016
|
const currentChainType = currentChainData?.chain_type || "ethereum";
|
|
8916
9017
|
const currentWallet = (0, import_core21.getWalletByChainType)(wallets, currentChainType);
|
|
8917
9018
|
const depositAddress = currentWallet?.address || "";
|
|
@@ -8929,57 +9030,26 @@ function TransferCryptoDoubleInput({
|
|
|
8929
9030
|
onDepositSuccess,
|
|
8930
9031
|
onDepositError
|
|
8931
9032
|
});
|
|
8932
|
-
(0,
|
|
8933
|
-
if (!supportedTokens.length || initialSelectionDone) return;
|
|
8934
|
-
const allChains = /* @__PURE__ */ new Set();
|
|
8935
|
-
supportedTokens.forEach((t7) => {
|
|
8936
|
-
t7.chains.forEach((c) => {
|
|
8937
|
-
allChains.add(getChainKey2(c.chain_id, c.chain_type));
|
|
8938
|
-
});
|
|
8939
|
-
});
|
|
8940
|
-
if (!allChains.has(chain)) {
|
|
8941
|
-
const firstToken = supportedTokens[0];
|
|
8942
|
-
if (firstToken.chains.length > 0) {
|
|
8943
|
-
const firstChain = firstToken.chains[0];
|
|
8944
|
-
setChain(getChainKey2(firstChain.chain_id, firstChain.chain_type));
|
|
8945
|
-
}
|
|
8946
|
-
}
|
|
8947
|
-
setInitialSelectionDone(true);
|
|
8948
|
-
}, [supportedTokens, chain, initialSelectionDone]);
|
|
8949
|
-
(0, import_react15.useEffect)(() => {
|
|
9033
|
+
(0, import_react16.useEffect)(() => {
|
|
8950
9034
|
if (onExecutionsChange) {
|
|
8951
9035
|
onExecutionsChange(depositExecutions);
|
|
8952
9036
|
}
|
|
8953
9037
|
}, [depositExecutions, onExecutionsChange]);
|
|
8954
|
-
|
|
8955
|
-
if (!supportedTokens.length) return;
|
|
8956
|
-
const currentToken = supportedTokens.find((t7) => t7.symbol === token);
|
|
8957
|
-
if (!currentToken || currentToken.chains.length === 0) return;
|
|
8958
|
-
const isChainAvailable = currentToken.chains.some((c) => {
|
|
8959
|
-
const key = getChainKey2(c.chain_id, c.chain_type);
|
|
8960
|
-
return key === chain;
|
|
8961
|
-
});
|
|
8962
|
-
if (!isChainAvailable) {
|
|
8963
|
-
const firstChain = currentToken.chains[0];
|
|
8964
|
-
const newChain = getChainKey2(firstChain.chain_id, firstChain.chain_type);
|
|
8965
|
-
setChain(newChain);
|
|
8966
|
-
}
|
|
8967
|
-
}, [token, supportedTokens, chain]);
|
|
8968
|
-
const selectedToken = supportedTokens.find((t7) => t7.symbol === token);
|
|
9038
|
+
const selectedToken = token ? supportedTokens.find((t11) => t11.symbol === token) : void 0;
|
|
8969
9039
|
const availableChainsForToken = selectedToken?.chains || [];
|
|
8970
|
-
const currentChainFromBackend = availableChainsForToken.find((c) => {
|
|
8971
|
-
const key =
|
|
9040
|
+
const currentChainFromBackend = chain ? availableChainsForToken.find((c) => {
|
|
9041
|
+
const key = getChainKey3(c.chain_id, c.chain_type);
|
|
8972
9042
|
return key === chain;
|
|
8973
9043
|
}) || allAvailableChains.find((c) => {
|
|
8974
|
-
const key =
|
|
9044
|
+
const key = getChainKey3(c.chain_id, c.chain_type);
|
|
8975
9045
|
return key === chain;
|
|
8976
|
-
});
|
|
9046
|
+
}) : void 0;
|
|
8977
9047
|
const handleCopyAddress = () => {
|
|
8978
9048
|
navigator.clipboard.writeText(depositAddress);
|
|
8979
9049
|
setCopied(true);
|
|
8980
9050
|
setTimeout(() => setCopied(false), 2e3);
|
|
8981
9051
|
};
|
|
8982
|
-
const
|
|
9052
|
+
const formatProcessingTime3 = (seconds) => {
|
|
8983
9053
|
if (seconds === null) {
|
|
8984
9054
|
return t5.processingTime.lessThanMinutes.replace("{{minutes}}", "1");
|
|
8985
9055
|
}
|
|
@@ -9047,11 +9117,11 @@ function TransferCryptoDoubleInput({
|
|
|
9047
9117
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
9048
9118
|
Select,
|
|
9049
9119
|
{
|
|
9050
|
-
value: token,
|
|
9120
|
+
value: token ?? "",
|
|
9051
9121
|
onValueChange: setToken,
|
|
9052
|
-
disabled: tokensLoading || supportedTokens.length === 0,
|
|
9122
|
+
disabled: tokensLoading || !token || supportedTokens.length === 0,
|
|
9053
9123
|
children: [
|
|
9054
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectTrigger, { className: "uf-h-10 hover:uf-opacity-90 uf-text-foreground disabled:uf-opacity-50", style: { backgroundColor: components.card.backgroundColor, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` }, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectValue, { children: tokensLoading ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t5.loading }) }) : selectedToken ? renderTokenItem(selectedToken) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uf-text-xs uf-font-normal", children: token }) }) }) }),
|
|
9124
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectTrigger, { className: "uf-h-10 hover:uf-opacity-90 uf-text-foreground disabled:uf-opacity-50", style: { backgroundColor: components.card.backgroundColor, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` }, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectValue, { children: tokensLoading || !token ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t5.loading }) }) : selectedToken ? renderTokenItem(selectedToken) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uf-text-xs uf-font-normal", children: token }) }) }) }),
|
|
9055
9125
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectContent, { className: "uf-bg-secondary uf-border uf-text-foreground uf-max-h-[300px]", style: { border: `1px solid ${isDarkMode ? "rgba(255,255,255,0.15)" : "rgba(0,0,0,0.15)"}`, ...fonts.regular ? { "--uf-font-family": fonts.regular } : {} }, children: supportedTokens.map((tokenData) => /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
9056
9126
|
SelectItem,
|
|
9057
9127
|
{
|
|
@@ -9078,11 +9148,11 @@ function TransferCryptoDoubleInput({
|
|
|
9078
9148
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
9079
9149
|
Select,
|
|
9080
9150
|
{
|
|
9081
|
-
value: chain,
|
|
9151
|
+
value: chain ?? "",
|
|
9082
9152
|
onValueChange: setChain,
|
|
9083
|
-
disabled: tokensLoading || availableChainsForToken.length === 0,
|
|
9153
|
+
disabled: tokensLoading || !chain || availableChainsForToken.length === 0,
|
|
9084
9154
|
children: [
|
|
9085
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectTrigger, { className: "uf-h-10 hover:uf-opacity-90 uf-text-foreground disabled:uf-opacity-50", style: { backgroundColor: components.card.backgroundColor, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` }, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectValue, { children: tokensLoading ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t5.loading }) }) : currentChainFromBackend ? renderChainItem(currentChainFromBackend) : currentChainData ? renderChainItem(currentChainData) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uf-text-xs uf-font-normal", children: chain }) }) }) }),
|
|
9155
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectTrigger, { className: "uf-h-10 hover:uf-opacity-90 uf-text-foreground disabled:uf-opacity-50", style: { backgroundColor: components.card.backgroundColor, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` }, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(SelectValue, { children: tokensLoading || !chain ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t5.loading }) }) : currentChainFromBackend ? renderChainItem(currentChainFromBackend) : currentChainData ? renderChainItem(currentChainData) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "uf-text-xs uf-font-normal", children: chain }) }) }) }),
|
|
9086
9156
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
9087
9157
|
SelectContent,
|
|
9088
9158
|
{
|
|
@@ -9090,7 +9160,7 @@ function TransferCryptoDoubleInput({
|
|
|
9090
9160
|
className: "uf-bg-secondary uf-border uf-text-foreground uf-max-h-[300px] uf-min-w-[200px]",
|
|
9091
9161
|
style: { border: `1px solid ${isDarkMode ? "rgba(255,255,255,0.15)" : "rgba(0,0,0,0.15)"}`, ...fonts.regular ? { "--uf-font-family": fonts.regular } : {} },
|
|
9092
9162
|
children: availableChainsForToken.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "uf-px-2 uf-py-3 uf-text-xs uf-text-muted-foreground uf-text-center", children: t5.noChainsAvailable }) : availableChainsForToken.map((chainData) => {
|
|
9093
|
-
const chainKey =
|
|
9163
|
+
const chainKey = getChainKey3(
|
|
9094
9164
|
chainData.chain_id,
|
|
9095
9165
|
chainData.chain_type
|
|
9096
9166
|
);
|
|
@@ -9206,7 +9276,7 @@ function TransferCryptoDoubleInput({
|
|
|
9206
9276
|
t5.processingTime.label,
|
|
9207
9277
|
":",
|
|
9208
9278
|
" ",
|
|
9209
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children:
|
|
9279
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: formatProcessingTime3(processingTime) })
|
|
9210
9280
|
] })
|
|
9211
9281
|
] }),
|
|
9212
9282
|
detailsExpanded ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react18.ChevronUp, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react18.ChevronDown, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } })
|
|
@@ -10102,7 +10172,7 @@ function ReviewView({
|
|
|
10102
10172
|
}
|
|
10103
10173
|
|
|
10104
10174
|
// src/components/deposits/browser-wallets/ConfirmingView.tsx
|
|
10105
|
-
var
|
|
10175
|
+
var import_react17 = require("react");
|
|
10106
10176
|
var import_lucide_react21 = require("lucide-react");
|
|
10107
10177
|
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
10108
10178
|
function ConfirmingView({
|
|
@@ -10112,8 +10182,8 @@ function ConfirmingView({
|
|
|
10112
10182
|
isPolling = false
|
|
10113
10183
|
}) {
|
|
10114
10184
|
const { colors: colors2, fonts } = useTheme();
|
|
10115
|
-
const [containerEl, setContainerEl] = (0,
|
|
10116
|
-
const containerCallbackRef = (0,
|
|
10185
|
+
const [containerEl, setContainerEl] = (0, import_react17.useState)(null);
|
|
10186
|
+
const containerCallbackRef = (0, import_react17.useCallback)((el) => {
|
|
10117
10187
|
setContainerEl(el);
|
|
10118
10188
|
}, []);
|
|
10119
10189
|
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(PortalContainerProvider, { value: containerEl, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
@@ -10280,7 +10350,7 @@ function BrowserWalletModal({
|
|
|
10280
10350
|
);
|
|
10281
10351
|
if (cancelled) return;
|
|
10282
10352
|
const supportedToken = response.data.find(
|
|
10283
|
-
(
|
|
10353
|
+
(t11) => t11.symbol.toLowerCase() === token.symbol.toLowerCase()
|
|
10284
10354
|
);
|
|
10285
10355
|
if (supportedToken) {
|
|
10286
10356
|
const chainDetail = supportedToken.chains.find(
|
|
@@ -11496,6 +11566,10 @@ function DepositModal({
|
|
|
11496
11566
|
destinationChainType,
|
|
11497
11567
|
destinationChainId,
|
|
11498
11568
|
destinationTokenAddress,
|
|
11569
|
+
defaultSourceChainType,
|
|
11570
|
+
defaultSourceChainId,
|
|
11571
|
+
defaultSourceTokenAddress,
|
|
11572
|
+
defaultSourceSymbol,
|
|
11499
11573
|
hideDepositTracker = false,
|
|
11500
11574
|
showBalanceHeader = false,
|
|
11501
11575
|
transferInputVariant = "double_input",
|
|
@@ -11517,33 +11591,33 @@ function DepositModal({
|
|
|
11517
11591
|
depositTrackerSubTitle = t6.depositTracker.subtitle
|
|
11518
11592
|
}) {
|
|
11519
11593
|
const { colors: colors2, fonts, components } = useTheme();
|
|
11520
|
-
const effectiveInitialScreen = (0,
|
|
11594
|
+
const effectiveInitialScreen = (0, import_react18.useMemo)(() => {
|
|
11521
11595
|
const s = initialScreen ?? "main";
|
|
11522
11596
|
if (s === "tracker" && hideDepositTracker) return "main";
|
|
11523
11597
|
return s;
|
|
11524
11598
|
}, [initialScreen, hideDepositTracker]);
|
|
11525
|
-
const [containerEl, setContainerEl] = (0,
|
|
11526
|
-
const containerCallbackRef = (0,
|
|
11599
|
+
const [containerEl, setContainerEl] = (0, import_react18.useState)(null);
|
|
11600
|
+
const containerCallbackRef = (0, import_react18.useCallback)((el) => {
|
|
11527
11601
|
setContainerEl(el);
|
|
11528
11602
|
}, []);
|
|
11529
|
-
const [view, setView] = (0,
|
|
11603
|
+
const [view, setView] = (0, import_react18.useState)(
|
|
11530
11604
|
effectiveInitialScreen
|
|
11531
11605
|
);
|
|
11532
|
-
const resetViewTimeoutRef = (0,
|
|
11533
|
-
const [cardView, setCardView] = (0,
|
|
11606
|
+
const resetViewTimeoutRef = (0, import_react18.useRef)(null);
|
|
11607
|
+
const [cardView, setCardView] = (0, import_react18.useState)(
|
|
11534
11608
|
"amount"
|
|
11535
11609
|
);
|
|
11536
|
-
const [exchangeView, setExchangeView] = (0,
|
|
11610
|
+
const [exchangeView, setExchangeView] = (0, import_react18.useState)(
|
|
11537
11611
|
"providers"
|
|
11538
11612
|
);
|
|
11539
|
-
const [browserWalletModalOpen, setBrowserWalletModalOpen] = (0,
|
|
11540
|
-
const [browserWalletInfo, setBrowserWalletInfo] = (0,
|
|
11541
|
-
const [walletSelectionModalOpen, setWalletSelectionModalOpen] = (0,
|
|
11542
|
-
const [browserWalletChainType, setBrowserWalletChainType] = (0,
|
|
11543
|
-
const [quotesCount, setQuotesCount] = (0,
|
|
11544
|
-
const [allExecutions, setAllExecutions] = (0,
|
|
11545
|
-
const [selectedExecution, setSelectedExecution] = (0,
|
|
11546
|
-
const [depositExecutions, setDepositExecutions] = (0,
|
|
11613
|
+
const [browserWalletModalOpen, setBrowserWalletModalOpen] = (0, import_react18.useState)(false);
|
|
11614
|
+
const [browserWalletInfo, setBrowserWalletInfo] = (0, import_react18.useState)(null);
|
|
11615
|
+
const [walletSelectionModalOpen, setWalletSelectionModalOpen] = (0, import_react18.useState)(false);
|
|
11616
|
+
const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react18.useState)(() => getStoredWalletChainType());
|
|
11617
|
+
const [quotesCount, setQuotesCount] = (0, import_react18.useState)(0);
|
|
11618
|
+
const [allExecutions, setAllExecutions] = (0, import_react18.useState)([]);
|
|
11619
|
+
const [selectedExecution, setSelectedExecution] = (0, import_react18.useState)(null);
|
|
11620
|
+
const [depositExecutions, setDepositExecutions] = (0, import_react18.useState)([]);
|
|
11547
11621
|
const isMobileView = useIsMobileViewport();
|
|
11548
11622
|
const { data: depositAddressResponse, isLoading: walletsLoading } = useDepositAddress({
|
|
11549
11623
|
userId,
|
|
@@ -11556,10 +11630,10 @@ function DepositModal({
|
|
|
11556
11630
|
// Only fetch when modal is open
|
|
11557
11631
|
});
|
|
11558
11632
|
const wallets = depositAddressResponse?.data ?? [];
|
|
11559
|
-
const [resolvedTheme, setResolvedTheme] = (0,
|
|
11633
|
+
const [resolvedTheme, setResolvedTheme] = (0, import_react18.useState)(
|
|
11560
11634
|
theme === "auto" ? "dark" : theme
|
|
11561
11635
|
);
|
|
11562
|
-
(0,
|
|
11636
|
+
(0, import_react18.useEffect)(() => {
|
|
11563
11637
|
if (theme === "auto") {
|
|
11564
11638
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
11565
11639
|
setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
@@ -11588,11 +11662,11 @@ function DepositModal({
|
|
|
11588
11662
|
chainType: destinationChainType,
|
|
11589
11663
|
enabled: open
|
|
11590
11664
|
});
|
|
11591
|
-
(0,
|
|
11665
|
+
(0, import_react18.useEffect)(() => {
|
|
11592
11666
|
if (view !== "tracker" || !userId) return;
|
|
11593
11667
|
const fetchExecutions = async () => {
|
|
11594
11668
|
try {
|
|
11595
|
-
const response = await (0, import_core23.queryExecutions)(userId, publishableKey);
|
|
11669
|
+
const response = await (0, import_core23.queryExecutions)(userId, publishableKey, import_core23.ActionType.Deposit);
|
|
11596
11670
|
const sorted = [...response.data].sort((a, b) => {
|
|
11597
11671
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
11598
11672
|
const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
@@ -11609,7 +11683,7 @@ function DepositModal({
|
|
|
11609
11683
|
clearInterval(pollInterval);
|
|
11610
11684
|
};
|
|
11611
11685
|
}, [view, userId, publishableKey]);
|
|
11612
|
-
(0,
|
|
11686
|
+
(0, import_react18.useEffect)(() => {
|
|
11613
11687
|
if (view !== "tracker") {
|
|
11614
11688
|
setSelectedExecution(null);
|
|
11615
11689
|
}
|
|
@@ -11707,7 +11781,7 @@ function DepositModal({
|
|
|
11707
11781
|
resetViewTimeoutRef.current = null;
|
|
11708
11782
|
}, 200);
|
|
11709
11783
|
};
|
|
11710
|
-
(0,
|
|
11784
|
+
(0, import_react18.useLayoutEffect)(() => {
|
|
11711
11785
|
if (!open) return;
|
|
11712
11786
|
if (resetViewTimeoutRef.current) {
|
|
11713
11787
|
clearTimeout(resetViewTimeoutRef.current);
|
|
@@ -11719,7 +11793,7 @@ function DepositModal({
|
|
|
11719
11793
|
setBrowserWalletInfo(null);
|
|
11720
11794
|
setSelectedExecution(null);
|
|
11721
11795
|
}, [open, effectiveInitialScreen]);
|
|
11722
|
-
(0,
|
|
11796
|
+
(0, import_react18.useEffect)(
|
|
11723
11797
|
() => () => {
|
|
11724
11798
|
if (resetViewTimeoutRef.current) {
|
|
11725
11799
|
clearTimeout(resetViewTimeoutRef.current);
|
|
@@ -11928,6 +12002,10 @@ function DepositModal({
|
|
|
11928
12002
|
destinationChainType,
|
|
11929
12003
|
destinationChainId,
|
|
11930
12004
|
destinationTokenAddress,
|
|
12005
|
+
defaultSourceChainType,
|
|
12006
|
+
defaultSourceChainId,
|
|
12007
|
+
defaultSourceTokenAddress,
|
|
12008
|
+
defaultSourceSymbol,
|
|
11931
12009
|
depositConfirmationMode,
|
|
11932
12010
|
onExecutionsChange: setDepositExecutions,
|
|
11933
12011
|
onDepositSuccess,
|
|
@@ -11943,6 +12021,10 @@ function DepositModal({
|
|
|
11943
12021
|
destinationChainType,
|
|
11944
12022
|
destinationChainId,
|
|
11945
12023
|
destinationTokenAddress,
|
|
12024
|
+
defaultSourceChainType,
|
|
12025
|
+
defaultSourceChainId,
|
|
12026
|
+
defaultSourceTokenAddress,
|
|
12027
|
+
defaultSourceSymbol,
|
|
11946
12028
|
depositConfirmationMode,
|
|
11947
12029
|
onExecutionsChange: setDepositExecutions,
|
|
11948
12030
|
onDepositSuccess,
|
|
@@ -12103,6 +12185,1977 @@ function DepositModal({
|
|
|
12103
12185
|
}
|
|
12104
12186
|
) });
|
|
12105
12187
|
}
|
|
12188
|
+
|
|
12189
|
+
// src/components/withdrawals/WithdrawModal.tsx
|
|
12190
|
+
var import_react22 = require("react");
|
|
12191
|
+
var import_lucide_react26 = require("lucide-react");
|
|
12192
|
+
|
|
12193
|
+
// src/hooks/use-supported-destination-tokens.ts
|
|
12194
|
+
var import_react_query9 = require("@tanstack/react-query");
|
|
12195
|
+
var import_core24 = require("@unifold/core");
|
|
12196
|
+
function useSupportedDestinationTokens(publishableKey, enabled = true) {
|
|
12197
|
+
return (0, import_react_query9.useQuery)({
|
|
12198
|
+
queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
|
|
12199
|
+
queryFn: () => (0, import_core24.getSupportedDestinationTokens)(publishableKey),
|
|
12200
|
+
staleTime: 1e3 * 60 * 5,
|
|
12201
|
+
gcTime: 1e3 * 60 * 30,
|
|
12202
|
+
refetchOnMount: false,
|
|
12203
|
+
refetchOnWindowFocus: false,
|
|
12204
|
+
enabled
|
|
12205
|
+
});
|
|
12206
|
+
}
|
|
12207
|
+
|
|
12208
|
+
// src/hooks/use-source-token-validation.ts
|
|
12209
|
+
var import_react_query10 = require("@tanstack/react-query");
|
|
12210
|
+
var import_core25 = require("@unifold/core");
|
|
12211
|
+
function useSourceTokenValidation(params) {
|
|
12212
|
+
const {
|
|
12213
|
+
sourceChainType,
|
|
12214
|
+
sourceChainId,
|
|
12215
|
+
sourceTokenAddress,
|
|
12216
|
+
sourceTokenSymbol,
|
|
12217
|
+
publishableKey,
|
|
12218
|
+
enabled = true
|
|
12219
|
+
} = params;
|
|
12220
|
+
const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
|
|
12221
|
+
return (0, import_react_query10.useQuery)({
|
|
12222
|
+
queryKey: [
|
|
12223
|
+
"unifold",
|
|
12224
|
+
"sourceTokenValidation",
|
|
12225
|
+
sourceChainType ?? null,
|
|
12226
|
+
sourceChainId ?? null,
|
|
12227
|
+
sourceTokenAddress ?? null,
|
|
12228
|
+
publishableKey
|
|
12229
|
+
],
|
|
12230
|
+
queryFn: async () => {
|
|
12231
|
+
const res = await (0, import_core25.getSupportedDepositTokens)(publishableKey);
|
|
12232
|
+
let matchedMinUsd = null;
|
|
12233
|
+
let matchedProcessingTime = null;
|
|
12234
|
+
let matchedSlippage = null;
|
|
12235
|
+
let matchedPriceImpact = null;
|
|
12236
|
+
const found = res.data.some(
|
|
12237
|
+
(token) => token.chains.some((chain) => {
|
|
12238
|
+
const match = chain.chain_type === sourceChainType && chain.chain_id === sourceChainId && chain.token_address.toLowerCase() === sourceTokenAddress.toLowerCase();
|
|
12239
|
+
if (match) {
|
|
12240
|
+
matchedMinUsd = chain.minimum_deposit_amount_usd;
|
|
12241
|
+
matchedProcessingTime = chain.estimated_processing_time;
|
|
12242
|
+
matchedSlippage = chain.max_slippage_percent;
|
|
12243
|
+
matchedPriceImpact = chain.estimated_price_impact_percent;
|
|
12244
|
+
}
|
|
12245
|
+
return match;
|
|
12246
|
+
})
|
|
12247
|
+
);
|
|
12248
|
+
return {
|
|
12249
|
+
isSupported: found,
|
|
12250
|
+
minimumAmountUsd: matchedMinUsd,
|
|
12251
|
+
estimatedProcessingTime: matchedProcessingTime,
|
|
12252
|
+
maxSlippagePercent: matchedSlippage,
|
|
12253
|
+
priceImpactPercent: matchedPriceImpact,
|
|
12254
|
+
errorMessage: found ? null : `${sourceTokenSymbol || "Source token"} is not a supported withdrawal token. Supported tokens include USDC, USDT, and other stablecoins.`
|
|
12255
|
+
};
|
|
12256
|
+
},
|
|
12257
|
+
enabled: enabled && hasParams,
|
|
12258
|
+
staleTime: 1e3 * 60 * 5,
|
|
12259
|
+
gcTime: 1e3 * 60 * 30,
|
|
12260
|
+
refetchOnMount: false,
|
|
12261
|
+
refetchOnWindowFocus: false
|
|
12262
|
+
});
|
|
12263
|
+
}
|
|
12264
|
+
|
|
12265
|
+
// src/hooks/use-address-balance.ts
|
|
12266
|
+
var import_react_query11 = require("@tanstack/react-query");
|
|
12267
|
+
var import_core26 = require("@unifold/core");
|
|
12268
|
+
function useAddressBalance(params) {
|
|
12269
|
+
const {
|
|
12270
|
+
address,
|
|
12271
|
+
chainType,
|
|
12272
|
+
chainId,
|
|
12273
|
+
tokenAddress,
|
|
12274
|
+
publishableKey,
|
|
12275
|
+
enabled = true
|
|
12276
|
+
} = params;
|
|
12277
|
+
const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
|
|
12278
|
+
return (0, import_react_query11.useQuery)({
|
|
12279
|
+
queryKey: [
|
|
12280
|
+
"unifold",
|
|
12281
|
+
"addressBalance",
|
|
12282
|
+
address ?? null,
|
|
12283
|
+
chainType ?? null,
|
|
12284
|
+
chainId ?? null,
|
|
12285
|
+
tokenAddress ?? null,
|
|
12286
|
+
publishableKey
|
|
12287
|
+
],
|
|
12288
|
+
queryFn: async () => {
|
|
12289
|
+
const res = await (0, import_core26.getAddressBalance)(
|
|
12290
|
+
address,
|
|
12291
|
+
chainType,
|
|
12292
|
+
chainId,
|
|
12293
|
+
tokenAddress,
|
|
12294
|
+
publishableKey
|
|
12295
|
+
);
|
|
12296
|
+
if (res.balance) {
|
|
12297
|
+
const decimals = res.balance.token?.decimals ?? 6;
|
|
12298
|
+
const symbol = res.balance.token?.symbol ?? "";
|
|
12299
|
+
const baseUnit = res.balance.amount;
|
|
12300
|
+
const raw = BigInt(baseUnit);
|
|
12301
|
+
const divisor = BigInt(10 ** decimals);
|
|
12302
|
+
const whole = raw / divisor;
|
|
12303
|
+
const frac = raw % divisor;
|
|
12304
|
+
const fracStr = frac.toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
12305
|
+
const balanceHuman = fracStr ? `${whole}.${fracStr}` : whole.toString();
|
|
12306
|
+
return {
|
|
12307
|
+
balanceBaseUnit: baseUnit,
|
|
12308
|
+
balanceHuman,
|
|
12309
|
+
balanceUsd: res.balance.amount_usd,
|
|
12310
|
+
exchangeRate: res.balance.exchange_rate,
|
|
12311
|
+
decimals,
|
|
12312
|
+
symbol
|
|
12313
|
+
};
|
|
12314
|
+
}
|
|
12315
|
+
return { balanceBaseUnit: "0", balanceHuman: "0", balanceUsd: "0", exchangeRate: null, decimals: 6, symbol: "" };
|
|
12316
|
+
},
|
|
12317
|
+
enabled: enabled && hasParams,
|
|
12318
|
+
staleTime: 1e3 * 30,
|
|
12319
|
+
gcTime: 1e3 * 60 * 5,
|
|
12320
|
+
refetchInterval: 1e3 * 30,
|
|
12321
|
+
refetchOnMount: "always",
|
|
12322
|
+
refetchOnWindowFocus: false
|
|
12323
|
+
});
|
|
12324
|
+
}
|
|
12325
|
+
|
|
12326
|
+
// src/hooks/use-executions.ts
|
|
12327
|
+
var import_react_query12 = require("@tanstack/react-query");
|
|
12328
|
+
var import_core27 = require("@unifold/core");
|
|
12329
|
+
function useExecutions(userId, publishableKey, options) {
|
|
12330
|
+
const actionType = options?.actionType ?? import_core27.ActionType.Deposit;
|
|
12331
|
+
return (0, import_react_query12.useQuery)({
|
|
12332
|
+
queryKey: ["unifold", "executions", actionType, userId, publishableKey],
|
|
12333
|
+
queryFn: () => (0, import_core27.queryExecutions)(userId, publishableKey, actionType),
|
|
12334
|
+
enabled: (options?.enabled ?? true) && !!userId,
|
|
12335
|
+
refetchInterval: options?.refetchInterval ?? 3e3,
|
|
12336
|
+
staleTime: 0,
|
|
12337
|
+
gcTime: 1e3 * 60 * 5,
|
|
12338
|
+
refetchOnWindowFocus: false
|
|
12339
|
+
});
|
|
12340
|
+
}
|
|
12341
|
+
|
|
12342
|
+
// src/hooks/use-withdraw-polling.ts
|
|
12343
|
+
var import_react19 = require("react");
|
|
12344
|
+
var import_core28 = require("@unifold/core");
|
|
12345
|
+
var POLL_INTERVAL_MS2 = 2500;
|
|
12346
|
+
var POLL_ENDPOINT_INTERVAL_MS2 = 3e3;
|
|
12347
|
+
var CUTOFF_BUFFER_MS2 = 6e4;
|
|
12348
|
+
function useWithdrawPolling({
|
|
12349
|
+
userId,
|
|
12350
|
+
publishableKey,
|
|
12351
|
+
depositWalletId,
|
|
12352
|
+
enabled = false,
|
|
12353
|
+
onWithdrawSuccess,
|
|
12354
|
+
onWithdrawError
|
|
12355
|
+
}) {
|
|
12356
|
+
const [executions, setExecutions] = (0, import_react19.useState)([]);
|
|
12357
|
+
const [isPolling, setIsPolling] = (0, import_react19.useState)(false);
|
|
12358
|
+
const enabledAtRef = (0, import_react19.useRef)(/* @__PURE__ */ new Date());
|
|
12359
|
+
const trackedRef = (0, import_react19.useRef)(/* @__PURE__ */ new Map());
|
|
12360
|
+
const prevEnabledRef = (0, import_react19.useRef)(false);
|
|
12361
|
+
const onSuccessRef = (0, import_react19.useRef)(onWithdrawSuccess);
|
|
12362
|
+
const onErrorRef = (0, import_react19.useRef)(onWithdrawError);
|
|
12363
|
+
(0, import_react19.useEffect)(() => {
|
|
12364
|
+
onSuccessRef.current = onWithdrawSuccess;
|
|
12365
|
+
}, [onWithdrawSuccess]);
|
|
12366
|
+
(0, import_react19.useEffect)(() => {
|
|
12367
|
+
onErrorRef.current = onWithdrawError;
|
|
12368
|
+
}, [onWithdrawError]);
|
|
12369
|
+
(0, import_react19.useEffect)(() => {
|
|
12370
|
+
if (enabled && !prevEnabledRef.current) {
|
|
12371
|
+
enabledAtRef.current = /* @__PURE__ */ new Date();
|
|
12372
|
+
trackedRef.current.clear();
|
|
12373
|
+
}
|
|
12374
|
+
if (!enabled) {
|
|
12375
|
+
trackedRef.current.clear();
|
|
12376
|
+
}
|
|
12377
|
+
prevEnabledRef.current = enabled;
|
|
12378
|
+
}, [enabled]);
|
|
12379
|
+
(0, import_react19.useEffect)(() => {
|
|
12380
|
+
if (!userId || !enabled) return;
|
|
12381
|
+
const enabledAt = enabledAtRef.current;
|
|
12382
|
+
const poll = async () => {
|
|
12383
|
+
try {
|
|
12384
|
+
const response = await (0, import_core28.queryExecutions)(userId, publishableKey, import_core28.ActionType.Withdraw);
|
|
12385
|
+
const cutoff = new Date(enabledAt.getTime() - CUTOFF_BUFFER_MS2);
|
|
12386
|
+
const sorted = [...response.data].sort((a, b) => {
|
|
12387
|
+
const tA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
12388
|
+
const tB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
12389
|
+
return tB - tA;
|
|
12390
|
+
});
|
|
12391
|
+
const inProgress = [import_core28.ExecutionStatus.PENDING, import_core28.ExecutionStatus.WAITING, import_core28.ExecutionStatus.DELAYED];
|
|
12392
|
+
const terminal = [import_core28.ExecutionStatus.SUCCEEDED, import_core28.ExecutionStatus.FAILED];
|
|
12393
|
+
let target = null;
|
|
12394
|
+
for (const ex of sorted) {
|
|
12395
|
+
const t11 = ex.created_at ? new Date(ex.created_at) : null;
|
|
12396
|
+
if (!t11 || t11 < cutoff) continue;
|
|
12397
|
+
const prev = trackedRef.current.get(ex.id);
|
|
12398
|
+
if (!prev) {
|
|
12399
|
+
target = ex;
|
|
12400
|
+
break;
|
|
12401
|
+
}
|
|
12402
|
+
if (inProgress.includes(prev) && terminal.includes(ex.status)) {
|
|
12403
|
+
target = ex;
|
|
12404
|
+
break;
|
|
12405
|
+
}
|
|
12406
|
+
}
|
|
12407
|
+
if (target) {
|
|
12408
|
+
const ex = target;
|
|
12409
|
+
const exTime = ex.created_at ? new Date(ex.created_at) : null;
|
|
12410
|
+
if (!exTime || exTime < enabledAtRef.current) return;
|
|
12411
|
+
const prev = trackedRef.current.get(ex.id);
|
|
12412
|
+
trackedRef.current.set(ex.id, ex.status);
|
|
12413
|
+
setExecutions((list) => {
|
|
12414
|
+
const idx = list.findIndex((e) => e.id === ex.id);
|
|
12415
|
+
if (idx >= 0) {
|
|
12416
|
+
const u = [...list];
|
|
12417
|
+
u[idx] = ex;
|
|
12418
|
+
return u;
|
|
12419
|
+
}
|
|
12420
|
+
return [...list, ex];
|
|
12421
|
+
});
|
|
12422
|
+
if (ex.status === import_core28.ExecutionStatus.SUCCEEDED && (!prev || inProgress.includes(prev))) {
|
|
12423
|
+
onSuccessRef.current?.({ message: "Withdrawal completed successfully", executionId: ex.id, transaction: ex });
|
|
12424
|
+
} else if (ex.status === import_core28.ExecutionStatus.FAILED && prev !== import_core28.ExecutionStatus.FAILED) {
|
|
12425
|
+
onErrorRef.current?.({ message: "Withdrawal failed", code: "WITHDRAW_FAILED", error: ex });
|
|
12426
|
+
}
|
|
12427
|
+
}
|
|
12428
|
+
} catch (error) {
|
|
12429
|
+
console.error("Failed to fetch withdraw executions:", error);
|
|
12430
|
+
onErrorRef.current?.({ message: "Failed to fetch withdrawal status", code: "POLLING_ERROR", error });
|
|
12431
|
+
}
|
|
12432
|
+
};
|
|
12433
|
+
void poll();
|
|
12434
|
+
const interval = setInterval(poll, POLL_INTERVAL_MS2);
|
|
12435
|
+
setIsPolling(true);
|
|
12436
|
+
return () => {
|
|
12437
|
+
clearInterval(interval);
|
|
12438
|
+
setIsPolling(false);
|
|
12439
|
+
};
|
|
12440
|
+
}, [userId, publishableKey, enabled]);
|
|
12441
|
+
(0, import_react19.useEffect)(() => {
|
|
12442
|
+
if (!enabled || !depositWalletId) return;
|
|
12443
|
+
const trigger = async () => {
|
|
12444
|
+
try {
|
|
12445
|
+
await (0, import_core28.pollDirectExecutions)({ deposit_wallet_id: depositWalletId }, publishableKey);
|
|
12446
|
+
} catch {
|
|
12447
|
+
}
|
|
12448
|
+
};
|
|
12449
|
+
trigger();
|
|
12450
|
+
const interval = setInterval(trigger, POLL_ENDPOINT_INTERVAL_MS2);
|
|
12451
|
+
return () => clearInterval(interval);
|
|
12452
|
+
}, [enabled, depositWalletId, publishableKey]);
|
|
12453
|
+
return { executions, isPolling };
|
|
12454
|
+
}
|
|
12455
|
+
|
|
12456
|
+
// src/components/withdrawals/WithdrawDoubleInput.tsx
|
|
12457
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
12458
|
+
var t7 = i18n.withdrawModal;
|
|
12459
|
+
var getChainKey4 = (chainId, chainType) => `${chainType}:${chainId}`;
|
|
12460
|
+
function WithdrawDoubleInput({
|
|
12461
|
+
tokens,
|
|
12462
|
+
selectedTokenSymbol,
|
|
12463
|
+
selectedChainKey,
|
|
12464
|
+
onTokenChange,
|
|
12465
|
+
onChainChange,
|
|
12466
|
+
isLoading = false
|
|
12467
|
+
}) {
|
|
12468
|
+
const { fonts, components } = useTheme();
|
|
12469
|
+
const isDarkMode = useTheme().themeClass.includes("uf-dark");
|
|
12470
|
+
const selectedToken = selectedTokenSymbol ? tokens.find((t11) => t11.symbol === selectedTokenSymbol) : void 0;
|
|
12471
|
+
const availableChainsForToken = selectedToken?.chains || [];
|
|
12472
|
+
const renderTokenItem = (tokenData) => /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
12473
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12474
|
+
"img",
|
|
12475
|
+
{
|
|
12476
|
+
src: tokenData.icon_url,
|
|
12477
|
+
alt: tokenData.symbol,
|
|
12478
|
+
width: 20,
|
|
12479
|
+
height: 20,
|
|
12480
|
+
loading: "lazy",
|
|
12481
|
+
className: "uf-rounded-full uf-flex-shrink-0"
|
|
12482
|
+
}
|
|
12483
|
+
),
|
|
12484
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "uf-text-xs uf-font-normal", children: tokenData.symbol })
|
|
12485
|
+
] });
|
|
12486
|
+
const renderChainItem = (chainData) => /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
12487
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12488
|
+
"img",
|
|
12489
|
+
{
|
|
12490
|
+
src: chainData.icon_url,
|
|
12491
|
+
alt: chainData.chain_name,
|
|
12492
|
+
width: 20,
|
|
12493
|
+
height: 20,
|
|
12494
|
+
loading: "lazy",
|
|
12495
|
+
className: "uf-rounded-full uf-flex-shrink-0"
|
|
12496
|
+
}
|
|
12497
|
+
),
|
|
12498
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "uf-text-xs uf-font-normal", children: chainData.chain_name })
|
|
12499
|
+
] });
|
|
12500
|
+
const currentChainData = selectedChainKey ? availableChainsForToken.find(
|
|
12501
|
+
(c) => getChainKey4(c.chain_id, c.chain_type) === selectedChainKey
|
|
12502
|
+
) : void 0;
|
|
12503
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "uf-grid uf-grid-cols-2 uf-gap-2.5", children: [
|
|
12504
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { children: [
|
|
12505
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12506
|
+
"div",
|
|
12507
|
+
{
|
|
12508
|
+
className: "uf-text-xs uf-mb-2 uf-flex uf-items-center uf-gap-1",
|
|
12509
|
+
style: { color: components.card.labelColor },
|
|
12510
|
+
children: t7.receiveToken
|
|
12511
|
+
}
|
|
12512
|
+
),
|
|
12513
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
12514
|
+
Select,
|
|
12515
|
+
{
|
|
12516
|
+
value: selectedTokenSymbol ?? "",
|
|
12517
|
+
onValueChange: onTokenChange,
|
|
12518
|
+
disabled: isLoading || tokens.length === 0,
|
|
12519
|
+
children: [
|
|
12520
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12521
|
+
SelectTrigger,
|
|
12522
|
+
{
|
|
12523
|
+
className: "uf-h-10 hover:uf-opacity-90 uf-text-foreground disabled:uf-opacity-50",
|
|
12524
|
+
style: {
|
|
12525
|
+
backgroundColor: components.card.backgroundColor,
|
|
12526
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
12527
|
+
},
|
|
12528
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(SelectValue, { children: isLoading || !selectedTokenSymbol ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t7.loading }) : selectedToken ? renderTokenItem(selectedToken) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "uf-text-xs uf-font-normal", children: selectedTokenSymbol }) })
|
|
12529
|
+
}
|
|
12530
|
+
),
|
|
12531
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12532
|
+
SelectContent,
|
|
12533
|
+
{
|
|
12534
|
+
className: "uf-bg-secondary uf-border uf-text-foreground uf-max-h-[300px]",
|
|
12535
|
+
style: {
|
|
12536
|
+
border: `1px solid ${isDarkMode ? "rgba(255,255,255,0.15)" : "rgba(0,0,0,0.15)"}`,
|
|
12537
|
+
...fonts.regular ? { "--uf-font-family": fonts.regular } : {}
|
|
12538
|
+
},
|
|
12539
|
+
children: tokens.map((tokenData) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12540
|
+
SelectItem,
|
|
12541
|
+
{
|
|
12542
|
+
value: tokenData.symbol,
|
|
12543
|
+
className: "focus:uf-bg-accent focus:uf-text-foreground",
|
|
12544
|
+
children: renderTokenItem(tokenData)
|
|
12545
|
+
},
|
|
12546
|
+
tokenData.symbol
|
|
12547
|
+
))
|
|
12548
|
+
}
|
|
12549
|
+
)
|
|
12550
|
+
]
|
|
12551
|
+
}
|
|
12552
|
+
)
|
|
12553
|
+
] }),
|
|
12554
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { children: [
|
|
12555
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12556
|
+
"div",
|
|
12557
|
+
{
|
|
12558
|
+
className: "uf-text-xs uf-mb-2 uf-flex uf-items-center uf-gap-1",
|
|
12559
|
+
style: { color: components.card.labelColor },
|
|
12560
|
+
children: t7.receiveChain
|
|
12561
|
+
}
|
|
12562
|
+
),
|
|
12563
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
12564
|
+
Select,
|
|
12565
|
+
{
|
|
12566
|
+
value: selectedChainKey ?? "",
|
|
12567
|
+
onValueChange: onChainChange,
|
|
12568
|
+
disabled: isLoading || availableChainsForToken.length === 0,
|
|
12569
|
+
children: [
|
|
12570
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12571
|
+
SelectTrigger,
|
|
12572
|
+
{
|
|
12573
|
+
className: "uf-h-10 hover:uf-opacity-90 uf-text-foreground disabled:uf-opacity-50",
|
|
12574
|
+
style: {
|
|
12575
|
+
backgroundColor: components.card.backgroundColor,
|
|
12576
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
12577
|
+
},
|
|
12578
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(SelectValue, { children: isLoading || !selectedChainKey ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t7.loading }) : currentChainData ? renderChainItem(currentChainData) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "uf-text-xs uf-font-normal", children: selectedChainKey }) })
|
|
12579
|
+
}
|
|
12580
|
+
),
|
|
12581
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12582
|
+
SelectContent,
|
|
12583
|
+
{
|
|
12584
|
+
align: "end",
|
|
12585
|
+
className: "uf-bg-secondary uf-border uf-text-foreground uf-max-h-[300px] uf-min-w-[200px]",
|
|
12586
|
+
style: {
|
|
12587
|
+
border: `1px solid ${isDarkMode ? "rgba(255,255,255,0.15)" : "rgba(0,0,0,0.15)"}`,
|
|
12588
|
+
...fonts.regular ? { "--uf-font-family": fonts.regular } : {}
|
|
12589
|
+
},
|
|
12590
|
+
children: availableChainsForToken.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "uf-px-2 uf-py-3 uf-text-xs uf-text-muted-foreground uf-text-center", children: "No chains available" }) : availableChainsForToken.map((chainData) => {
|
|
12591
|
+
const chainKey = getChainKey4(chainData.chain_id, chainData.chain_type);
|
|
12592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
12593
|
+
SelectItem,
|
|
12594
|
+
{
|
|
12595
|
+
value: chainKey,
|
|
12596
|
+
className: "focus:uf-bg-accent focus:uf-text-foreground",
|
|
12597
|
+
children: renderChainItem(chainData)
|
|
12598
|
+
},
|
|
12599
|
+
chainKey
|
|
12600
|
+
);
|
|
12601
|
+
})
|
|
12602
|
+
}
|
|
12603
|
+
)
|
|
12604
|
+
]
|
|
12605
|
+
}
|
|
12606
|
+
)
|
|
12607
|
+
] })
|
|
12608
|
+
] });
|
|
12609
|
+
}
|
|
12610
|
+
|
|
12611
|
+
// src/components/withdrawals/WithdrawForm.tsx
|
|
12612
|
+
var import_react20 = require("react");
|
|
12613
|
+
var import_lucide_react24 = require("lucide-react");
|
|
12614
|
+
|
|
12615
|
+
// src/hooks/use-verify-recipient-address.ts
|
|
12616
|
+
var import_react_query13 = require("@tanstack/react-query");
|
|
12617
|
+
var import_core29 = require("@unifold/core");
|
|
12618
|
+
function useVerifyRecipientAddress(params) {
|
|
12619
|
+
const {
|
|
12620
|
+
chainType,
|
|
12621
|
+
chainId,
|
|
12622
|
+
tokenAddress,
|
|
12623
|
+
recipientAddress,
|
|
12624
|
+
publishableKey,
|
|
12625
|
+
enabled = true
|
|
12626
|
+
} = params;
|
|
12627
|
+
const trimmedAddress = recipientAddress?.trim() || "";
|
|
12628
|
+
const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
|
|
12629
|
+
return (0, import_react_query13.useQuery)({
|
|
12630
|
+
queryKey: [
|
|
12631
|
+
"unifold",
|
|
12632
|
+
"verifyRecipientAddress",
|
|
12633
|
+
chainType ?? null,
|
|
12634
|
+
chainId ?? null,
|
|
12635
|
+
tokenAddress ?? null,
|
|
12636
|
+
trimmedAddress,
|
|
12637
|
+
publishableKey
|
|
12638
|
+
],
|
|
12639
|
+
queryFn: () => (0, import_core29.verifyRecipientAddress)(
|
|
12640
|
+
{
|
|
12641
|
+
chain_type: chainType,
|
|
12642
|
+
chain_id: chainId,
|
|
12643
|
+
token_address: tokenAddress,
|
|
12644
|
+
recipient_address: trimmedAddress
|
|
12645
|
+
},
|
|
12646
|
+
publishableKey
|
|
12647
|
+
),
|
|
12648
|
+
enabled: enabled && hasAllParams,
|
|
12649
|
+
staleTime: 1e3 * 60 * 5,
|
|
12650
|
+
gcTime: 1e3 * 60 * 30,
|
|
12651
|
+
retry: 1,
|
|
12652
|
+
refetchOnMount: false,
|
|
12653
|
+
refetchOnWindowFocus: false
|
|
12654
|
+
});
|
|
12655
|
+
}
|
|
12656
|
+
|
|
12657
|
+
// src/components/withdrawals/send-withdraw.ts
|
|
12658
|
+
var import_core30 = require("@unifold/core");
|
|
12659
|
+
async function sendEvmWithdraw(params) {
|
|
12660
|
+
const {
|
|
12661
|
+
provider,
|
|
12662
|
+
fromAddress,
|
|
12663
|
+
depositWalletAddress,
|
|
12664
|
+
sourceTokenAddress,
|
|
12665
|
+
sourceChainId,
|
|
12666
|
+
amountBaseUnit
|
|
12667
|
+
} = params;
|
|
12668
|
+
const currentChainIdHex = await provider.request({
|
|
12669
|
+
method: "eth_chainId",
|
|
12670
|
+
params: []
|
|
12671
|
+
});
|
|
12672
|
+
const currentChainId = parseInt(currentChainIdHex, 16).toString();
|
|
12673
|
+
if (currentChainId !== sourceChainId) {
|
|
12674
|
+
const requiredHex = "0x" + parseInt(sourceChainId).toString(16);
|
|
12675
|
+
try {
|
|
12676
|
+
await provider.request({
|
|
12677
|
+
method: "wallet_switchEthereumChain",
|
|
12678
|
+
params: [{ chainId: requiredHex }]
|
|
12679
|
+
});
|
|
12680
|
+
const newHex = await provider.request({ method: "eth_chainId", params: [] });
|
|
12681
|
+
if (parseInt(newHex, 16).toString() !== sourceChainId) {
|
|
12682
|
+
throw new Error(`Failed to switch to chain ${sourceChainId}. Please switch manually.`);
|
|
12683
|
+
}
|
|
12684
|
+
} catch (err) {
|
|
12685
|
+
if (err && typeof err === "object" && "code" in err) {
|
|
12686
|
+
const e = err;
|
|
12687
|
+
if (e.code === 4902) throw new Error(`Chain ${sourceChainId} is not configured in your wallet.`);
|
|
12688
|
+
if (e.code === 4001) throw new Error("You must approve the network switch to withdraw.");
|
|
12689
|
+
}
|
|
12690
|
+
throw err;
|
|
12691
|
+
}
|
|
12692
|
+
}
|
|
12693
|
+
const isNative = sourceTokenAddress === "native" || sourceTokenAddress === "0x0000000000000000000000000000000000000000" || sourceTokenAddress === "";
|
|
12694
|
+
const amountBig = BigInt(amountBaseUnit);
|
|
12695
|
+
const txParams = isNative ? { from: fromAddress, to: depositWalletAddress, value: "0x" + amountBig.toString(16) } : {
|
|
12696
|
+
from: fromAddress,
|
|
12697
|
+
to: sourceTokenAddress,
|
|
12698
|
+
data: "0xa9059cbb" + depositWalletAddress.slice(2).padStart(64, "0") + amountBig.toString(16).padStart(64, "0")
|
|
12699
|
+
};
|
|
12700
|
+
let gasEstimate;
|
|
12701
|
+
try {
|
|
12702
|
+
const hex = await provider.request({ method: "eth_estimateGas", params: [txParams] });
|
|
12703
|
+
gasEstimate = BigInt(hex);
|
|
12704
|
+
} catch {
|
|
12705
|
+
gasEstimate = isNative ? BigInt(21e3) : BigInt(65e3);
|
|
12706
|
+
}
|
|
12707
|
+
const gasPrice = BigInt(await provider.request({ method: "eth_gasPrice", params: [] }));
|
|
12708
|
+
const gasWithBuffer = gasEstimate * BigInt(120) / BigInt(100);
|
|
12709
|
+
const gasCost = gasWithBuffer * gasPrice;
|
|
12710
|
+
const ethBalance = BigInt(
|
|
12711
|
+
await provider.request({ method: "eth_getBalance", params: [fromAddress, "latest"] })
|
|
12712
|
+
);
|
|
12713
|
+
const totalRequired = isNative ? gasCost + amountBig : gasCost;
|
|
12714
|
+
if (ethBalance < totalRequired) {
|
|
12715
|
+
const gasFmt = (Number(gasCost) / 1e18).toFixed(6);
|
|
12716
|
+
if (isNative) {
|
|
12717
|
+
throw new Error(`Insufficient balance. Need ${(Number(totalRequired) / 1e18).toFixed(6)} ETH (amount + ~${gasFmt} gas).`);
|
|
12718
|
+
}
|
|
12719
|
+
throw new Error(`Insufficient ETH for gas. Need ~${gasFmt} ETH for fees.`);
|
|
12720
|
+
}
|
|
12721
|
+
const txHash = await provider.request({ method: "eth_sendTransaction", params: [txParams] });
|
|
12722
|
+
return txHash;
|
|
12723
|
+
}
|
|
12724
|
+
async function sendSolanaWithdraw(params) {
|
|
12725
|
+
const {
|
|
12726
|
+
provider,
|
|
12727
|
+
fromAddress,
|
|
12728
|
+
depositWalletAddress,
|
|
12729
|
+
sourceTokenAddress,
|
|
12730
|
+
amountBaseUnit,
|
|
12731
|
+
publishableKey
|
|
12732
|
+
} = params;
|
|
12733
|
+
if (!provider.publicKey) {
|
|
12734
|
+
await provider.connect();
|
|
12735
|
+
}
|
|
12736
|
+
const buildResponse = await (0, import_core30.buildSolanaTransaction)(
|
|
12737
|
+
{
|
|
12738
|
+
chain_id: "mainnet",
|
|
12739
|
+
token_address: sourceTokenAddress === "" ? "native" : sourceTokenAddress,
|
|
12740
|
+
source_address: fromAddress,
|
|
12741
|
+
destination_address: depositWalletAddress,
|
|
12742
|
+
amount: amountBaseUnit
|
|
12743
|
+
},
|
|
12744
|
+
publishableKey
|
|
12745
|
+
);
|
|
12746
|
+
const { VersionedTransaction } = await import(
|
|
12747
|
+
/* @vite-ignore */
|
|
12748
|
+
"@solana/web3.js"
|
|
12749
|
+
);
|
|
12750
|
+
const binaryString = atob(buildResponse.transaction);
|
|
12751
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
12752
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
12753
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
12754
|
+
}
|
|
12755
|
+
const transaction = VersionedTransaction.deserialize(bytes);
|
|
12756
|
+
const signedTransaction = await provider.signTransaction(transaction);
|
|
12757
|
+
const serialized = signedTransaction.serialize();
|
|
12758
|
+
let binaryStr = "";
|
|
12759
|
+
for (let i = 0; i < serialized.length; i++) {
|
|
12760
|
+
binaryStr += String.fromCharCode(serialized[i]);
|
|
12761
|
+
}
|
|
12762
|
+
const sendResponse = await (0, import_core30.sendSolanaTransaction)(
|
|
12763
|
+
{ chain_id: "mainnet", signed_transaction: btoa(binaryStr) },
|
|
12764
|
+
publishableKey
|
|
12765
|
+
);
|
|
12766
|
+
return sendResponse.signature;
|
|
12767
|
+
}
|
|
12768
|
+
async function detectBrowserWallet(chainType, senderAddress) {
|
|
12769
|
+
const win = typeof window !== "undefined" ? window : null;
|
|
12770
|
+
if (!win || !senderAddress) return null;
|
|
12771
|
+
const anyWin = win;
|
|
12772
|
+
if (chainType === "solana") {
|
|
12773
|
+
const solProviders = [];
|
|
12774
|
+
if (win.phantom?.solana) solProviders.push({ provider: win.phantom.solana, name: "Phantom" });
|
|
12775
|
+
if (anyWin.solflare) solProviders.push({ provider: anyWin.solflare, name: "Solflare" });
|
|
12776
|
+
if (anyWin.backpack) solProviders.push({ provider: anyWin.backpack, name: "Backpack" });
|
|
12777
|
+
if (anyWin.trustwallet?.solana) solProviders.push({ provider: anyWin.trustwallet.solana, name: "Trust Wallet" });
|
|
12778
|
+
for (const { provider, name } of solProviders) {
|
|
12779
|
+
if (!provider) continue;
|
|
12780
|
+
try {
|
|
12781
|
+
let addr;
|
|
12782
|
+
if (provider.isConnected && provider.publicKey) {
|
|
12783
|
+
addr = provider.publicKey.toString();
|
|
12784
|
+
} else {
|
|
12785
|
+
const resp = await provider.connect({ onlyIfTrusted: true });
|
|
12786
|
+
if (resp?.publicKey) addr = resp.publicKey.toString();
|
|
12787
|
+
}
|
|
12788
|
+
if (addr && addr === senderAddress) {
|
|
12789
|
+
return { chainFamily: "solana", provider, name, address: addr };
|
|
12790
|
+
}
|
|
12791
|
+
} catch {
|
|
12792
|
+
}
|
|
12793
|
+
}
|
|
12794
|
+
}
|
|
12795
|
+
if (chainType === "ethereum") {
|
|
12796
|
+
const evmProviders = [];
|
|
12797
|
+
const seen = /* @__PURE__ */ new Set();
|
|
12798
|
+
const add = (p, name) => {
|
|
12799
|
+
if (p && typeof p.request === "function" && !seen.has(p)) {
|
|
12800
|
+
seen.add(p);
|
|
12801
|
+
evmProviders.push({ provider: p, name });
|
|
12802
|
+
}
|
|
12803
|
+
};
|
|
12804
|
+
add(anyWin.phantom?.ethereum, "Phantom");
|
|
12805
|
+
add(anyWin.coinbaseWalletExtension, "Coinbase");
|
|
12806
|
+
add(anyWin.trustwallet?.ethereum, "Trust Wallet");
|
|
12807
|
+
add(anyWin.okxwallet, "OKX Wallet");
|
|
12808
|
+
if (anyWin.__eip6963Providers) {
|
|
12809
|
+
for (const detail of anyWin.__eip6963Providers) {
|
|
12810
|
+
const rdns = detail.info?.rdns || "";
|
|
12811
|
+
let name = detail.info?.name || "Wallet";
|
|
12812
|
+
if (rdns.includes("metamask")) name = "MetaMask";
|
|
12813
|
+
else if (rdns.includes("rabby")) name = "Rabby";
|
|
12814
|
+
else if (rdns.includes("rainbow")) name = "Rainbow";
|
|
12815
|
+
add(detail.provider, name);
|
|
12816
|
+
}
|
|
12817
|
+
}
|
|
12818
|
+
if (win.ethereum) {
|
|
12819
|
+
const eth = win.ethereum;
|
|
12820
|
+
let name = "Wallet";
|
|
12821
|
+
if (eth.isMetaMask && !eth.isPhantom && !eth.isRabby) name = "MetaMask";
|
|
12822
|
+
else if (eth.isRabby) name = "Rabby";
|
|
12823
|
+
else if (eth.isRainbow) name = "Rainbow";
|
|
12824
|
+
else if (eth.isCoinbaseWallet) name = "Coinbase";
|
|
12825
|
+
add(eth, name);
|
|
12826
|
+
}
|
|
12827
|
+
for (const { provider, name } of evmProviders) {
|
|
12828
|
+
try {
|
|
12829
|
+
const accounts = await provider.request({ method: "eth_accounts" });
|
|
12830
|
+
if (accounts?.length > 0 && accounts[0].toLowerCase() === senderAddress.toLowerCase()) {
|
|
12831
|
+
return { chainFamily: "evm", provider, name, address: accounts[0] };
|
|
12832
|
+
}
|
|
12833
|
+
} catch {
|
|
12834
|
+
}
|
|
12835
|
+
}
|
|
12836
|
+
}
|
|
12837
|
+
return null;
|
|
12838
|
+
}
|
|
12839
|
+
|
|
12840
|
+
// src/components/withdrawals/WithdrawForm.tsx
|
|
12841
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
12842
|
+
var t8 = i18n.withdrawModal;
|
|
12843
|
+
var tCrypto = i18n.transferCrypto;
|
|
12844
|
+
function formatProcessingTime2(seconds) {
|
|
12845
|
+
if (seconds === null) {
|
|
12846
|
+
return tCrypto.processingTime.lessThanMinutes.replace("{{minutes}}", "1");
|
|
12847
|
+
}
|
|
12848
|
+
const minutes = Math.ceil(seconds / 60);
|
|
12849
|
+
if (minutes < 60) {
|
|
12850
|
+
return tCrypto.processingTime.lessThanMinutes.replace("{{minutes}}", String(minutes));
|
|
12851
|
+
}
|
|
12852
|
+
const hours = Math.ceil(minutes / 60);
|
|
12853
|
+
return tCrypto.processingTime.lessThanHours.replace("{{hours}}", String(hours));
|
|
12854
|
+
}
|
|
12855
|
+
function computeBaseUnit(balanceBaseUnit, inputAmount, balanceAmount) {
|
|
12856
|
+
if (balanceAmount <= 0 || inputAmount <= 0) return "0";
|
|
12857
|
+
if (inputAmount >= balanceAmount) return balanceBaseUnit;
|
|
12858
|
+
const PRECISION = 10n ** 18n;
|
|
12859
|
+
const ratioScaled = BigInt(Math.round(inputAmount / balanceAmount * Number(PRECISION)));
|
|
12860
|
+
const result = BigInt(balanceBaseUnit) * ratioScaled / PRECISION;
|
|
12861
|
+
return result.toString();
|
|
12862
|
+
}
|
|
12863
|
+
function toSafeDecimalString(n, maxDecimals) {
|
|
12864
|
+
if (n === 0) return "0";
|
|
12865
|
+
return n.toFixed(maxDecimals).replace(/\.?0+$/, "");
|
|
12866
|
+
}
|
|
12867
|
+
function WithdrawForm({
|
|
12868
|
+
publishableKey,
|
|
12869
|
+
externalUserId,
|
|
12870
|
+
sourceChainType,
|
|
12871
|
+
selectedToken,
|
|
12872
|
+
selectedChain,
|
|
12873
|
+
sourceTokenSymbol,
|
|
12874
|
+
recipientAddressProp,
|
|
12875
|
+
balanceData,
|
|
12876
|
+
isLoadingBalance,
|
|
12877
|
+
minimumWithdrawAmountUsd,
|
|
12878
|
+
estimatedProcessingTime,
|
|
12879
|
+
maxSlippagePercent,
|
|
12880
|
+
priceImpactPercent,
|
|
12881
|
+
detectedWallet,
|
|
12882
|
+
sourceChainId,
|
|
12883
|
+
sourceTokenAddress,
|
|
12884
|
+
isWalletMatch,
|
|
12885
|
+
connectedWalletName,
|
|
12886
|
+
canWithdraw,
|
|
12887
|
+
onWithdraw,
|
|
12888
|
+
onWithdrawError,
|
|
12889
|
+
onDepositWalletCreation,
|
|
12890
|
+
onWithdrawSubmitted,
|
|
12891
|
+
footerLeft
|
|
12892
|
+
}) {
|
|
12893
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
12894
|
+
const [recipientAddress, setRecipientAddress] = (0, import_react20.useState)(recipientAddressProp || "");
|
|
12895
|
+
const [amount, setAmount] = (0, import_react20.useState)("");
|
|
12896
|
+
const [inputUnit, setInputUnit] = (0, import_react20.useState)("crypto");
|
|
12897
|
+
const [isSubmitting, setIsSubmitting] = (0, import_react20.useState)(false);
|
|
12898
|
+
const [submitError, setSubmitError] = (0, import_react20.useState)(null);
|
|
12899
|
+
const [detailsExpanded, setDetailsExpanded] = (0, import_react20.useState)(false);
|
|
12900
|
+
const [glossaryOpen, setGlossaryOpen] = (0, import_react20.useState)(false);
|
|
12901
|
+
(0, import_react20.useEffect)(() => {
|
|
12902
|
+
setRecipientAddress(recipientAddressProp || "");
|
|
12903
|
+
setAmount("");
|
|
12904
|
+
setInputUnit("crypto");
|
|
12905
|
+
setSubmitError(null);
|
|
12906
|
+
}, [recipientAddressProp]);
|
|
12907
|
+
const trimmedAddress = recipientAddress.trim();
|
|
12908
|
+
const [debouncedAddress, setDebouncedAddress] = (0, import_react20.useState)(trimmedAddress);
|
|
12909
|
+
(0, import_react20.useEffect)(() => {
|
|
12910
|
+
const id = setTimeout(() => setDebouncedAddress(trimmedAddress), 500);
|
|
12911
|
+
return () => clearTimeout(id);
|
|
12912
|
+
}, [trimmedAddress]);
|
|
12913
|
+
const {
|
|
12914
|
+
data: addressVerification,
|
|
12915
|
+
isLoading: isVerifyingAddress,
|
|
12916
|
+
error: verifyError
|
|
12917
|
+
} = useVerifyRecipientAddress({
|
|
12918
|
+
chainType: selectedChain?.chain_type,
|
|
12919
|
+
chainId: selectedChain?.chain_id,
|
|
12920
|
+
tokenAddress: selectedChain?.token_address,
|
|
12921
|
+
recipientAddress: debouncedAddress,
|
|
12922
|
+
publishableKey,
|
|
12923
|
+
enabled: debouncedAddress.length > 5 && !!selectedChain
|
|
12924
|
+
});
|
|
12925
|
+
const isDebouncing = trimmedAddress !== debouncedAddress;
|
|
12926
|
+
const addressError = (0, import_react20.useMemo)(() => {
|
|
12927
|
+
if (!trimmedAddress || trimmedAddress.length <= 5) return null;
|
|
12928
|
+
if (isDebouncing || isVerifyingAddress) return null;
|
|
12929
|
+
if (verifyError) return t8.invalidAddress;
|
|
12930
|
+
if (addressVerification && !addressVerification.valid) {
|
|
12931
|
+
if (addressVerification.failure_code === "account_not_found")
|
|
12932
|
+
return `Account not found on ${selectedChain?.chain_name}`;
|
|
12933
|
+
if (addressVerification.failure_code === "not_opted_in")
|
|
12934
|
+
return `Recipient has not opted in to ${selectedToken?.symbol} on ${selectedChain?.chain_name}`;
|
|
12935
|
+
return t8.invalidAddress;
|
|
12936
|
+
}
|
|
12937
|
+
return null;
|
|
12938
|
+
}, [trimmedAddress, isDebouncing, isVerifyingAddress, verifyError, addressVerification, selectedChain, selectedToken]);
|
|
12939
|
+
const isAddressValid = !isDebouncing && !!addressVerification?.valid && !addressError;
|
|
12940
|
+
const exchangeRate = (0, import_react20.useMemo)(() => {
|
|
12941
|
+
if (!balanceData?.exchangeRate) return 0;
|
|
12942
|
+
return parseFloat(balanceData.exchangeRate);
|
|
12943
|
+
}, [balanceData]);
|
|
12944
|
+
const balanceCrypto = (0, import_react20.useMemo)(() => {
|
|
12945
|
+
if (!balanceData?.balanceHuman) return 0;
|
|
12946
|
+
return parseFloat(balanceData.balanceHuman);
|
|
12947
|
+
}, [balanceData]);
|
|
12948
|
+
const balanceUsdNum = (0, import_react20.useMemo)(() => {
|
|
12949
|
+
if (!balanceData?.balanceUsd) return 0;
|
|
12950
|
+
return parseFloat(balanceData.balanceUsd);
|
|
12951
|
+
}, [balanceData]);
|
|
12952
|
+
const tokenSymbol = sourceTokenSymbol || balanceData?.symbol || "TOKEN";
|
|
12953
|
+
const sourceDecimals = balanceData?.decimals ?? 6;
|
|
12954
|
+
const cryptoAmountFromInput = (0, import_react20.useMemo)(() => {
|
|
12955
|
+
const val = parseFloat(amount);
|
|
12956
|
+
if (!val || val <= 0) return 0;
|
|
12957
|
+
if (inputUnit === "crypto") return val;
|
|
12958
|
+
return exchangeRate > 0 ? val / exchangeRate : 0;
|
|
12959
|
+
}, [amount, inputUnit, exchangeRate]);
|
|
12960
|
+
const fiatAmountFromInput = (0, import_react20.useMemo)(() => {
|
|
12961
|
+
const val = parseFloat(amount);
|
|
12962
|
+
if (!val || val <= 0) return 0;
|
|
12963
|
+
if (inputUnit === "fiat") return val;
|
|
12964
|
+
return val * exchangeRate;
|
|
12965
|
+
}, [amount, inputUnit, exchangeRate]);
|
|
12966
|
+
const convertedDisplay = (0, import_react20.useMemo)(() => {
|
|
12967
|
+
if (!amount || parseFloat(amount) <= 0) return null;
|
|
12968
|
+
if (inputUnit === "crypto") {
|
|
12969
|
+
return `$${fiatAmountFromInput.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
12970
|
+
}
|
|
12971
|
+
return `${cryptoAmountFromInput.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 6 })} ${tokenSymbol}`;
|
|
12972
|
+
}, [amount, inputUnit, fiatAmountFromInput, cryptoAmountFromInput, tokenSymbol]);
|
|
12973
|
+
const balanceDisplay = (0, import_react20.useMemo)(() => {
|
|
12974
|
+
if (isLoadingBalance || !balanceData) return null;
|
|
12975
|
+
if (inputUnit === "crypto") {
|
|
12976
|
+
return `${balanceCrypto.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${tokenSymbol}`;
|
|
12977
|
+
}
|
|
12978
|
+
return `$${balanceUsdNum.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
12979
|
+
}, [isLoadingBalance, balanceData, inputUnit, balanceCrypto, balanceUsdNum, tokenSymbol]);
|
|
12980
|
+
const handleSwitchUnit = (0, import_react20.useCallback)(() => {
|
|
12981
|
+
const val = parseFloat(amount);
|
|
12982
|
+
if (!val || val <= 0 || exchangeRate <= 0) {
|
|
12983
|
+
setInputUnit((u) => u === "crypto" ? "fiat" : "crypto");
|
|
12984
|
+
setAmount("");
|
|
12985
|
+
return;
|
|
12986
|
+
}
|
|
12987
|
+
if (inputUnit === "crypto") {
|
|
12988
|
+
const fiat = val * exchangeRate;
|
|
12989
|
+
setAmount(fiat.toFixed(2));
|
|
12990
|
+
setInputUnit("fiat");
|
|
12991
|
+
} else {
|
|
12992
|
+
const crypto = val / exchangeRate;
|
|
12993
|
+
setAmount(crypto.toFixed(sourceDecimals > 6 ? 6 : sourceDecimals));
|
|
12994
|
+
setInputUnit("crypto");
|
|
12995
|
+
}
|
|
12996
|
+
}, [amount, inputUnit, exchangeRate, sourceDecimals]);
|
|
12997
|
+
const handleMaxClick = (0, import_react20.useCallback)(() => {
|
|
12998
|
+
if (inputUnit === "crypto") {
|
|
12999
|
+
if (balanceCrypto <= 0) return;
|
|
13000
|
+
setAmount(balanceData?.balanceHuman ?? "0");
|
|
13001
|
+
} else {
|
|
13002
|
+
if (balanceUsdNum <= 0) return;
|
|
13003
|
+
setAmount((Math.floor(balanceUsdNum * 100) / 100).toFixed(2));
|
|
13004
|
+
}
|
|
13005
|
+
}, [inputUnit, balanceCrypto, balanceUsdNum, balanceData]);
|
|
13006
|
+
const isBelowMinimum = minimumWithdrawAmountUsd !== null && fiatAmountFromInput > 0 && fiatAmountFromInput < minimumWithdrawAmountUsd;
|
|
13007
|
+
const isOverBalance = inputUnit === "crypto" ? cryptoAmountFromInput > 0 && balanceCrypto > 0 && cryptoAmountFromInput > balanceCrypto : fiatAmountFromInput > 0 && balanceUsdNum > 0 && fiatAmountFromInput > balanceUsdNum;
|
|
13008
|
+
const isFormValid = trimmedAddress.length > 0 && amount.trim().length > 0 && cryptoAmountFromInput > 0 && isAddressValid && !isBelowMinimum && !isOverBalance && !!balanceData;
|
|
13009
|
+
const handleWithdraw = (0, import_react20.useCallback)(async () => {
|
|
13010
|
+
if (!selectedToken || !selectedChain) return;
|
|
13011
|
+
if (!isFormValid) return;
|
|
13012
|
+
setIsSubmitting(true);
|
|
13013
|
+
setSubmitError(null);
|
|
13014
|
+
try {
|
|
13015
|
+
const depositWallet = await onDepositWalletCreation({
|
|
13016
|
+
destinationChainType: selectedChain.chain_type,
|
|
13017
|
+
destinationChainId: selectedChain.chain_id,
|
|
13018
|
+
destinationTokenAddress: selectedChain.token_address,
|
|
13019
|
+
recipientAddress: trimmedAddress
|
|
13020
|
+
});
|
|
13021
|
+
const amountBaseUnit = computeBaseUnit(
|
|
13022
|
+
balanceData.balanceBaseUnit,
|
|
13023
|
+
parseFloat(amount),
|
|
13024
|
+
inputUnit === "crypto" ? balanceCrypto : balanceUsdNum
|
|
13025
|
+
);
|
|
13026
|
+
const humanAmount = toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
|
|
13027
|
+
const txInfo = {
|
|
13028
|
+
sourceChainType,
|
|
13029
|
+
sourceChainId,
|
|
13030
|
+
sourceTokenAddress,
|
|
13031
|
+
sourceTokenSymbol: tokenSymbol,
|
|
13032
|
+
destinationChainType: selectedChain.chain_type,
|
|
13033
|
+
destinationChainId: selectedChain.chain_id,
|
|
13034
|
+
destinationTokenAddress: selectedChain.token_address,
|
|
13035
|
+
destinationTokenSymbol: selectedToken.symbol,
|
|
13036
|
+
amount: humanAmount,
|
|
13037
|
+
amountBaseUnit,
|
|
13038
|
+
withdrawIntentAddress: depositWallet.address,
|
|
13039
|
+
recipientAddress: trimmedAddress
|
|
13040
|
+
};
|
|
13041
|
+
if (detectedWallet) {
|
|
13042
|
+
if (detectedWallet.chainFamily === "evm") {
|
|
13043
|
+
await sendEvmWithdraw({
|
|
13044
|
+
provider: detectedWallet.provider,
|
|
13045
|
+
fromAddress: detectedWallet.address,
|
|
13046
|
+
depositWalletAddress: depositWallet.address,
|
|
13047
|
+
sourceTokenAddress,
|
|
13048
|
+
sourceChainId,
|
|
13049
|
+
amountBaseUnit
|
|
13050
|
+
});
|
|
13051
|
+
} else if (detectedWallet.chainFamily === "solana") {
|
|
13052
|
+
await sendSolanaWithdraw({
|
|
13053
|
+
provider: detectedWallet.provider,
|
|
13054
|
+
fromAddress: detectedWallet.address,
|
|
13055
|
+
depositWalletAddress: depositWallet.address,
|
|
13056
|
+
sourceTokenAddress,
|
|
13057
|
+
amountBaseUnit,
|
|
13058
|
+
publishableKey
|
|
13059
|
+
});
|
|
13060
|
+
}
|
|
13061
|
+
} else if (onWithdraw) {
|
|
13062
|
+
await onWithdraw(txInfo);
|
|
13063
|
+
} else {
|
|
13064
|
+
throw new Error("No withdrawal method available. Please connect a wallet.");
|
|
13065
|
+
}
|
|
13066
|
+
onWithdrawSubmitted?.(txInfo);
|
|
13067
|
+
} catch (err) {
|
|
13068
|
+
const raw = err instanceof Error ? err.message : "Withdrawal failed. Please try again.";
|
|
13069
|
+
setSubmitError(raw.length > 120 ? "Withdrawal failed. Please try again." : raw);
|
|
13070
|
+
onWithdrawError?.({
|
|
13071
|
+
message: raw,
|
|
13072
|
+
error: err,
|
|
13073
|
+
code: "WITHDRAW_FAILED"
|
|
13074
|
+
});
|
|
13075
|
+
} finally {
|
|
13076
|
+
setIsSubmitting(false);
|
|
13077
|
+
}
|
|
13078
|
+
}, [selectedToken, selectedChain, isFormValid, cryptoAmountFromInput, sourceDecimals, trimmedAddress, publishableKey, onWithdraw, detectedWallet, sourceTokenAddress, sourceChainId, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, amount, inputUnit, balanceCrypto, balanceUsdNum, balanceData]);
|
|
13079
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
|
|
13080
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { children: [
|
|
13081
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13082
|
+
"div",
|
|
13083
|
+
{
|
|
13084
|
+
className: "uf-text-xs uf-mb-1.5",
|
|
13085
|
+
style: { color: components.card.labelColor, fontFamily: fonts.medium },
|
|
13086
|
+
children: t8.recipientAddress
|
|
13087
|
+
}
|
|
13088
|
+
),
|
|
13089
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13090
|
+
"style",
|
|
13091
|
+
{
|
|
13092
|
+
dangerouslySetInnerHTML: {
|
|
13093
|
+
__html: `.uf-withdraw-addr::placeholder { color: ${components.search.placeholderColor}; }`
|
|
13094
|
+
}
|
|
13095
|
+
}
|
|
13096
|
+
),
|
|
13097
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
13098
|
+
"div",
|
|
13099
|
+
{
|
|
13100
|
+
className: "uf-flex uf-items-center uf-gap-1 uf-pr-2",
|
|
13101
|
+
style: {
|
|
13102
|
+
backgroundColor: components.search.backgroundColor,
|
|
13103
|
+
borderRadius: components.input.borderRadius,
|
|
13104
|
+
border: `${components.input.borderWidth}px solid ${addressError ? colors2.error : components.input.borderColor}`
|
|
13105
|
+
},
|
|
13106
|
+
children: [
|
|
13107
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13108
|
+
"input",
|
|
13109
|
+
{
|
|
13110
|
+
type: "text",
|
|
13111
|
+
placeholder: t8.recipientAddressPlaceholder,
|
|
13112
|
+
value: recipientAddress,
|
|
13113
|
+
onChange: (e) => {
|
|
13114
|
+
setRecipientAddress(e.target.value);
|
|
13115
|
+
setSubmitError(null);
|
|
13116
|
+
},
|
|
13117
|
+
className: "uf-withdraw-addr uf-flex-1 uf-min-w-0 uf-px-3 uf-py-2.5 uf-text-sm uf-bg-transparent uf-outline-none",
|
|
13118
|
+
style: {
|
|
13119
|
+
color: components.search.inputColor,
|
|
13120
|
+
fontFamily: fonts.regular
|
|
13121
|
+
}
|
|
13122
|
+
}
|
|
13123
|
+
),
|
|
13124
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13125
|
+
"button",
|
|
13126
|
+
{
|
|
13127
|
+
type: "button",
|
|
13128
|
+
onClick: async () => {
|
|
13129
|
+
try {
|
|
13130
|
+
const text = await navigator.clipboard.readText();
|
|
13131
|
+
if (text) {
|
|
13132
|
+
setRecipientAddress(text.trim());
|
|
13133
|
+
setSubmitError(null);
|
|
13134
|
+
}
|
|
13135
|
+
} catch {
|
|
13136
|
+
}
|
|
13137
|
+
},
|
|
13138
|
+
className: "uf-flex-shrink-0 uf-p-1 uf-rounded uf-transition-colors hover:uf-opacity-70",
|
|
13139
|
+
style: { color: colors2.foregroundMuted },
|
|
13140
|
+
title: "Paste from clipboard",
|
|
13141
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.ClipboardPaste, { className: "uf-w-4 uf-h-4" })
|
|
13142
|
+
}
|
|
13143
|
+
)
|
|
13144
|
+
]
|
|
13145
|
+
}
|
|
13146
|
+
),
|
|
13147
|
+
(isDebouncing || isVerifyingAddress) && trimmedAddress.length > 5 && /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-1.5", children: [
|
|
13148
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.Loader2, { className: "uf-w-3 uf-h-3 uf-animate-spin", style: { color: colors2.foregroundMuted } }),
|
|
13149
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: t8.verifyingAddress })
|
|
13150
|
+
] }),
|
|
13151
|
+
addressError && /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-1.5", children: [
|
|
13152
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.AlertTriangle, { className: "uf-w-3 uf-h-3", style: { color: colors2.error } }),
|
|
13153
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "uf-text-xs", style: { color: colors2.error, fontFamily: fonts.regular }, children: addressError })
|
|
13154
|
+
] })
|
|
13155
|
+
] }),
|
|
13156
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { children: [
|
|
13157
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-text-xs uf-mb-1.5", style: { color: components.card.labelColor, fontFamily: fonts.medium }, children: [
|
|
13158
|
+
t8.amount,
|
|
13159
|
+
minimumWithdrawAmountUsd != null && minimumWithdrawAmountUsd > 0 && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { color: colors2.warning, fontFamily: fonts.regular }, children: ` ($${minimumWithdrawAmountUsd.toFixed(2)} min)` })
|
|
13160
|
+
] }),
|
|
13161
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13162
|
+
"style",
|
|
13163
|
+
{
|
|
13164
|
+
dangerouslySetInnerHTML: {
|
|
13165
|
+
__html: `.uf-withdraw-amt::placeholder { color: ${components.search.placeholderColor}; }`
|
|
13166
|
+
}
|
|
13167
|
+
}
|
|
13168
|
+
),
|
|
13169
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
13170
|
+
"div",
|
|
13171
|
+
{
|
|
13172
|
+
className: "uf-flex uf-items-center uf-gap-2 uf-px-3 uf-py-2.5",
|
|
13173
|
+
style: {
|
|
13174
|
+
backgroundColor: components.search.backgroundColor,
|
|
13175
|
+
borderRadius: components.input.borderRadius,
|
|
13176
|
+
border: `${components.input.borderWidth}px solid ${components.input.borderColor}`
|
|
13177
|
+
},
|
|
13178
|
+
children: [
|
|
13179
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13180
|
+
"input",
|
|
13181
|
+
{
|
|
13182
|
+
type: "text",
|
|
13183
|
+
inputMode: "decimal",
|
|
13184
|
+
placeholder: "0.00",
|
|
13185
|
+
value: amount,
|
|
13186
|
+
onChange: (e) => {
|
|
13187
|
+
const val = e.target.value;
|
|
13188
|
+
if (val === "" || /^\d*\.?\d*$/.test(val)) {
|
|
13189
|
+
setAmount(val);
|
|
13190
|
+
setSubmitError(null);
|
|
13191
|
+
}
|
|
13192
|
+
},
|
|
13193
|
+
className: "uf-withdraw-amt uf-flex-1 uf-min-w-0 uf-bg-transparent uf-text-sm uf-outline-none",
|
|
13194
|
+
style: {
|
|
13195
|
+
color: components.search.inputColor,
|
|
13196
|
+
fontFamily: fonts.regular
|
|
13197
|
+
}
|
|
13198
|
+
}
|
|
13199
|
+
),
|
|
13200
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "uf-text-sm uf-shrink-0", style: { color: colors2.foregroundMuted, fontFamily: fonts.medium }, children: inputUnit === "crypto" ? tokenSymbol : "USD" }),
|
|
13201
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13202
|
+
"button",
|
|
13203
|
+
{
|
|
13204
|
+
type: "button",
|
|
13205
|
+
onClick: handleMaxClick,
|
|
13206
|
+
className: "uf-shrink-0 uf-px-2 uf-py-0.5 uf-rounded-md uf-text-xs uf-font-medium uf-transition-colors hover:uf-opacity-80",
|
|
13207
|
+
style: { backgroundColor: colors2.primary + "20", color: colors2.primary, fontFamily: fonts.medium },
|
|
13208
|
+
children: "Max"
|
|
13209
|
+
}
|
|
13210
|
+
)
|
|
13211
|
+
]
|
|
13212
|
+
}
|
|
13213
|
+
),
|
|
13214
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-mt-1.5 uf-px-3", children: [
|
|
13215
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
|
|
13216
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: convertedDisplay || (inputUnit === "crypto" ? "$0.00" : `0.00 ${tokenSymbol}`) }),
|
|
13217
|
+
exchangeRate > 0 && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13218
|
+
"button",
|
|
13219
|
+
{
|
|
13220
|
+
type: "button",
|
|
13221
|
+
onClick: handleSwitchUnit,
|
|
13222
|
+
className: "uf-p-0.5 uf-rounded uf-transition-colors hover:uf-opacity-70",
|
|
13223
|
+
style: { color: colors2.foregroundMuted },
|
|
13224
|
+
title: "Switch unit",
|
|
13225
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.ArrowUpDown, { className: "uf-w-3 uf-h-3" })
|
|
13226
|
+
}
|
|
13227
|
+
)
|
|
13228
|
+
] }),
|
|
13229
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { children: [
|
|
13230
|
+
balanceDisplay && /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: [
|
|
13231
|
+
t8.balance,
|
|
13232
|
+
": ",
|
|
13233
|
+
balanceDisplay
|
|
13234
|
+
] }),
|
|
13235
|
+
isLoadingBalance && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uf-h-3 uf-w-16 uf-bg-muted uf-rounded uf-animate-pulse" })
|
|
13236
|
+
] })
|
|
13237
|
+
] })
|
|
13238
|
+
] }),
|
|
13239
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-px-2.5", style: { backgroundColor: components.card.backgroundColor, borderRadius: components.card.borderRadius, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` }, children: [
|
|
13240
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
13241
|
+
"button",
|
|
13242
|
+
{
|
|
13243
|
+
type: "button",
|
|
13244
|
+
onClick: () => setDetailsExpanded(!detailsExpanded),
|
|
13245
|
+
className: "uf-w-full uf-flex uf-items-center uf-justify-between uf-py-2.5",
|
|
13246
|
+
children: [
|
|
13247
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
13248
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uf-rounded-full uf-p-1", style: { backgroundColor: components.card.iconBackgroundColor }, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.Clock, { className: "uf-w-3 uf-h-3", style: { color: components.card.iconColor } }) }),
|
|
13249
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "uf-text-xs", style: { color: components.card.labelColor, fontFamily: fonts.regular }, children: [
|
|
13250
|
+
tCrypto.processingTime.label,
|
|
13251
|
+
":",
|
|
13252
|
+
" ",
|
|
13253
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: formatProcessingTime2(estimatedProcessingTime) })
|
|
13254
|
+
] })
|
|
13255
|
+
] }),
|
|
13256
|
+
detailsExpanded ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.ChevronUp, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.ChevronDown, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } })
|
|
13257
|
+
]
|
|
13258
|
+
}
|
|
13259
|
+
),
|
|
13260
|
+
detailsExpanded && /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-pb-3 uf-space-y-2.5", children: [
|
|
13261
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
13262
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uf-rounded-full uf-p-1", style: { backgroundColor: components.card.iconBackgroundColor }, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.ShieldCheck, { className: "uf-w-3 uf-h-3", style: { color: components.card.iconColor } }) }),
|
|
13263
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "uf-text-xs", style: { color: components.card.labelColor, fontFamily: fonts.regular }, children: [
|
|
13264
|
+
tCrypto.slippage.label,
|
|
13265
|
+
":",
|
|
13266
|
+
" ",
|
|
13267
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: [
|
|
13268
|
+
tCrypto.slippage.auto,
|
|
13269
|
+
" \u2022 ",
|
|
13270
|
+
(maxSlippagePercent ?? 0.25).toFixed(2),
|
|
13271
|
+
"%"
|
|
13272
|
+
] })
|
|
13273
|
+
] })
|
|
13274
|
+
] }),
|
|
13275
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
13276
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uf-rounded-full uf-p-1", style: { backgroundColor: components.card.iconBackgroundColor }, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.DollarSign, { className: "uf-w-3 uf-h-3", style: { color: components.card.iconColor } }) }),
|
|
13277
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "uf-text-xs", style: { color: components.card.labelColor, fontFamily: fonts.regular }, children: [
|
|
13278
|
+
tCrypto.priceImpact.label,
|
|
13279
|
+
":",
|
|
13280
|
+
" ",
|
|
13281
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: [
|
|
13282
|
+
(priceImpactPercent ?? 0).toFixed(2),
|
|
13283
|
+
"%"
|
|
13284
|
+
] })
|
|
13285
|
+
] })
|
|
13286
|
+
] })
|
|
13287
|
+
] })
|
|
13288
|
+
] }),
|
|
13289
|
+
!canWithdraw && !submitError && /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
13290
|
+
"div",
|
|
13291
|
+
{
|
|
13292
|
+
className: "uf-flex uf-items-start uf-gap-2.5 uf-p-3 uf-rounded-xl",
|
|
13293
|
+
style: { backgroundColor: colors2.card, border: `1px solid ${colors2.border}` },
|
|
13294
|
+
children: [
|
|
13295
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.Wallet, { className: "uf-w-4 uf-h-4 uf-flex-shrink-0 uf-mt-0.5", style: { color: colors2.warning } }),
|
|
13296
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No connected wallet detected. Please connect a wallet that matches your account to withdraw." })
|
|
13297
|
+
]
|
|
13298
|
+
}
|
|
13299
|
+
),
|
|
13300
|
+
isWalletMatch && connectedWalletName ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13301
|
+
"button",
|
|
13302
|
+
{
|
|
13303
|
+
type: "button",
|
|
13304
|
+
onClick: handleWithdraw,
|
|
13305
|
+
disabled: !isFormValid || !canWithdraw || isSubmitting || !selectedToken || !selectedChain,
|
|
13306
|
+
className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed uf-flex uf-items-center uf-justify-center uf-gap-2",
|
|
13307
|
+
style: {
|
|
13308
|
+
backgroundColor: colors2.primary,
|
|
13309
|
+
color: colors2.primaryForeground,
|
|
13310
|
+
fontFamily: fonts.medium,
|
|
13311
|
+
borderRadius: components.button.borderRadius,
|
|
13312
|
+
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
|
|
13313
|
+
},
|
|
13314
|
+
children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
|
|
13315
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.Loader2, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
|
|
13316
|
+
"Processing..."
|
|
13317
|
+
] }) : isOverBalance ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_jsx_runtime53.Fragment, { children: "Insufficient balance" }) : isBelowMinimum ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_jsx_runtime53.Fragment, { children: "Minimum amount not met" }) : submitError ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_jsx_runtime53.Fragment, { children: "Withdrawal failed. Try again" }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(import_jsx_runtime53.Fragment, { children: [
|
|
13318
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.Wallet, { className: "uf-w-4 uf-h-4" }),
|
|
13319
|
+
"Withdraw from ",
|
|
13320
|
+
connectedWalletName
|
|
13321
|
+
] })
|
|
13322
|
+
}
|
|
13323
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13324
|
+
"button",
|
|
13325
|
+
{
|
|
13326
|
+
type: "button",
|
|
13327
|
+
onClick: handleWithdraw,
|
|
13328
|
+
disabled: !isFormValid || !canWithdraw || isSubmitting || !selectedToken || !selectedChain,
|
|
13329
|
+
className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
|
|
13330
|
+
style: {
|
|
13331
|
+
backgroundColor: colors2.primary,
|
|
13332
|
+
color: colors2.primaryForeground,
|
|
13333
|
+
fontFamily: fonts.medium,
|
|
13334
|
+
borderRadius: components.button.borderRadius,
|
|
13335
|
+
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
|
|
13336
|
+
},
|
|
13337
|
+
children: isSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2", children: [
|
|
13338
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react24.Loader2, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
|
|
13339
|
+
"Processing..."
|
|
13340
|
+
] }) : isOverBalance ? "Insufficient balance" : isBelowMinimum ? "Minimum amount not met" : submitError ? "Withdrawal failed. Try again" : t8.withdraw
|
|
13341
|
+
}
|
|
13342
|
+
),
|
|
13343
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "uf-flex uf-items-center uf-justify-between uf-text-xs uf-pt-1", children: [
|
|
13344
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { children: footerLeft }),
|
|
13345
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(DepositFooterLinks, { onGlossaryClick: () => setGlossaryOpen(true) })
|
|
13346
|
+
] }),
|
|
13347
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
13348
|
+
GlossaryModal,
|
|
13349
|
+
{
|
|
13350
|
+
open: glossaryOpen,
|
|
13351
|
+
onOpenChange: setGlossaryOpen
|
|
13352
|
+
}
|
|
13353
|
+
)
|
|
13354
|
+
] });
|
|
13355
|
+
}
|
|
13356
|
+
|
|
13357
|
+
// src/components/withdrawals/WithdrawExecutionItem.tsx
|
|
13358
|
+
var import_lucide_react25 = require("lucide-react");
|
|
13359
|
+
var import_core31 = require("@unifold/core");
|
|
13360
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
13361
|
+
function WithdrawExecutionItem({
|
|
13362
|
+
execution,
|
|
13363
|
+
onClick
|
|
13364
|
+
}) {
|
|
13365
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
13366
|
+
const isPending = execution.status === import_core31.ExecutionStatus.PENDING || execution.status === import_core31.ExecutionStatus.WAITING || execution.status === import_core31.ExecutionStatus.DELAYED;
|
|
13367
|
+
const formatDateTime = (timestamp) => {
|
|
13368
|
+
try {
|
|
13369
|
+
const date = new Date(timestamp);
|
|
13370
|
+
const monthDay = date.toLocaleDateString("en-US", {
|
|
13371
|
+
month: "short",
|
|
13372
|
+
day: "numeric",
|
|
13373
|
+
year: "numeric"
|
|
13374
|
+
});
|
|
13375
|
+
const time = date.toLocaleTimeString("en-US", {
|
|
13376
|
+
hour: "numeric",
|
|
13377
|
+
minute: "2-digit",
|
|
13378
|
+
hour12: true
|
|
13379
|
+
}).toLowerCase();
|
|
13380
|
+
return `${monthDay} at ${time}`;
|
|
13381
|
+
} catch {
|
|
13382
|
+
return timestamp;
|
|
13383
|
+
}
|
|
13384
|
+
};
|
|
13385
|
+
const formatUsdAmount2 = (sourceAmountUsd) => {
|
|
13386
|
+
try {
|
|
13387
|
+
const amount = Number(sourceAmountUsd);
|
|
13388
|
+
return new Intl.NumberFormat("en-US", {
|
|
13389
|
+
style: "currency",
|
|
13390
|
+
currency: "USD",
|
|
13391
|
+
minimumFractionDigits: 2,
|
|
13392
|
+
maximumFractionDigits: 2
|
|
13393
|
+
}).format(amount);
|
|
13394
|
+
} catch {
|
|
13395
|
+
return "$0.00";
|
|
13396
|
+
}
|
|
13397
|
+
};
|
|
13398
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
13399
|
+
"button",
|
|
13400
|
+
{
|
|
13401
|
+
onClick,
|
|
13402
|
+
className: "uf-w-full uf-p-3 uf-flex uf-items-center uf-gap-3 hover:uf-bg-secondary/80 uf-transition-colors uf-text-left",
|
|
13403
|
+
style: {
|
|
13404
|
+
backgroundColor: components.card.backgroundColor,
|
|
13405
|
+
borderRadius: components.list.rowBorderRadius,
|
|
13406
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
13407
|
+
},
|
|
13408
|
+
children: [
|
|
13409
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "uf-relative uf-flex-shrink-0 uf-w-9 uf-h-9", children: [
|
|
13410
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13411
|
+
"img",
|
|
13412
|
+
{
|
|
13413
|
+
src: execution.destination_token_metadata?.icon_url || (0, import_core31.getIconUrl)("/icons/tokens/svg/usdc.svg"),
|
|
13414
|
+
alt: "Token",
|
|
13415
|
+
width: 36,
|
|
13416
|
+
height: 36,
|
|
13417
|
+
loading: "lazy",
|
|
13418
|
+
className: "uf-rounded-full uf-w-9 uf-h-9"
|
|
13419
|
+
}
|
|
13420
|
+
),
|
|
13421
|
+
isPending ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13422
|
+
"div",
|
|
13423
|
+
{
|
|
13424
|
+
className: "uf-absolute -uf-bottom-0.5 -uf-right-0.5 uf-rounded-full uf-p-0.5",
|
|
13425
|
+
style: { backgroundColor: colors2.warning },
|
|
13426
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13427
|
+
"svg",
|
|
13428
|
+
{
|
|
13429
|
+
width: "10",
|
|
13430
|
+
height: "10",
|
|
13431
|
+
viewBox: "0 0 12 12",
|
|
13432
|
+
fill: "none",
|
|
13433
|
+
className: "uf-animate-spin uf-block",
|
|
13434
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13435
|
+
"path",
|
|
13436
|
+
{
|
|
13437
|
+
d: "M6 1V3M6 9V11M1 6H3M9 6H11M2.5 2.5L4 4M8 8L9.5 9.5M2.5 9.5L4 8M8 4L9.5 2.5",
|
|
13438
|
+
stroke: "white",
|
|
13439
|
+
strokeWidth: "2",
|
|
13440
|
+
strokeLinecap: "round"
|
|
13441
|
+
}
|
|
13442
|
+
)
|
|
13443
|
+
}
|
|
13444
|
+
)
|
|
13445
|
+
}
|
|
13446
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13447
|
+
"div",
|
|
13448
|
+
{
|
|
13449
|
+
className: "uf-absolute -uf-bottom-0.5 -uf-right-0.5 uf-rounded-full uf-p-0.5",
|
|
13450
|
+
style: { backgroundColor: colors2.success },
|
|
13451
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13452
|
+
"svg",
|
|
13453
|
+
{
|
|
13454
|
+
width: "10",
|
|
13455
|
+
height: "10",
|
|
13456
|
+
viewBox: "0 0 12 12",
|
|
13457
|
+
fill: "none",
|
|
13458
|
+
className: "uf-block",
|
|
13459
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13460
|
+
"path",
|
|
13461
|
+
{
|
|
13462
|
+
d: "M10 3L4.5 8.5L2 6",
|
|
13463
|
+
stroke: "white",
|
|
13464
|
+
strokeWidth: "2",
|
|
13465
|
+
strokeLinecap: "round",
|
|
13466
|
+
strokeLinejoin: "round"
|
|
13467
|
+
}
|
|
13468
|
+
)
|
|
13469
|
+
}
|
|
13470
|
+
)
|
|
13471
|
+
}
|
|
13472
|
+
)
|
|
13473
|
+
] }),
|
|
13474
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "uf-flex-1 uf-min-w-0", children: [
|
|
13475
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13476
|
+
"h3",
|
|
13477
|
+
{
|
|
13478
|
+
className: "uf-font-medium uf-text-sm uf-leading-tight",
|
|
13479
|
+
style: {
|
|
13480
|
+
color: components.card.titleColor,
|
|
13481
|
+
fontFamily: fonts.medium
|
|
13482
|
+
},
|
|
13483
|
+
children: isPending ? "Withdrawal processing" : "Withdrawal completed"
|
|
13484
|
+
}
|
|
13485
|
+
),
|
|
13486
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13487
|
+
"p",
|
|
13488
|
+
{
|
|
13489
|
+
className: "uf-text-xs uf-leading-tight",
|
|
13490
|
+
style: {
|
|
13491
|
+
color: components.card.subtitleColor,
|
|
13492
|
+
fontFamily: fonts.regular
|
|
13493
|
+
},
|
|
13494
|
+
children: formatDateTime(execution.created_at || (/* @__PURE__ */ new Date()).toISOString())
|
|
13495
|
+
}
|
|
13496
|
+
)
|
|
13497
|
+
] }),
|
|
13498
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13499
|
+
"span",
|
|
13500
|
+
{
|
|
13501
|
+
className: "uf-font-medium uf-text-sm uf-flex-shrink-0",
|
|
13502
|
+
style: {
|
|
13503
|
+
color: components.card.textRightColor,
|
|
13504
|
+
fontFamily: fonts.medium
|
|
13505
|
+
},
|
|
13506
|
+
children: formatUsdAmount2(execution.source_amount_usd || "0")
|
|
13507
|
+
}
|
|
13508
|
+
),
|
|
13509
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
13510
|
+
import_lucide_react25.ChevronRight,
|
|
13511
|
+
{
|
|
13512
|
+
className: "uf-w-4 uf-h-4 uf-flex-shrink-0",
|
|
13513
|
+
style: { color: components.card.actionColor }
|
|
13514
|
+
}
|
|
13515
|
+
)
|
|
13516
|
+
]
|
|
13517
|
+
}
|
|
13518
|
+
);
|
|
13519
|
+
}
|
|
13520
|
+
|
|
13521
|
+
// src/components/withdrawals/WithdrawConfirmingView.tsx
|
|
13522
|
+
var import_react21 = require("react");
|
|
13523
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
13524
|
+
function truncateAddress4(addr) {
|
|
13525
|
+
if (addr.length <= 12) return addr;
|
|
13526
|
+
return `${addr.slice(0, 6)}...${addr.slice(-4)}`;
|
|
13527
|
+
}
|
|
13528
|
+
var SHOW_BUTTON_DELAY_MS = 5e3;
|
|
13529
|
+
function WithdrawConfirmingView({
|
|
13530
|
+
txInfo,
|
|
13531
|
+
executions,
|
|
13532
|
+
onClose,
|
|
13533
|
+
onViewTracker
|
|
13534
|
+
}) {
|
|
13535
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
13536
|
+
const [showButton, setShowButton] = (0, import_react21.useState)(false);
|
|
13537
|
+
const latestExecution = executions.length > 0 ? executions[executions.length - 1] : null;
|
|
13538
|
+
(0, import_react21.useEffect)(() => {
|
|
13539
|
+
if (latestExecution) return;
|
|
13540
|
+
const timer = setTimeout(() => setShowButton(true), SHOW_BUTTON_DELAY_MS);
|
|
13541
|
+
return () => clearTimeout(timer);
|
|
13542
|
+
}, [latestExecution]);
|
|
13543
|
+
const btnRadius = components.button.borderRadius;
|
|
13544
|
+
const btnBorder = `${components.button.borderWidth}px solid ${components.button.borderColor}`;
|
|
13545
|
+
if (latestExecution) {
|
|
13546
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
|
|
13547
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(DepositHeader, { title: "Withdrawal Details", showClose: true, onClose }),
|
|
13548
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(DepositDetailContent, { execution: latestExecution, variant: "withdraw" }),
|
|
13549
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uf-flex uf-gap-2 uf-px-2 uf-pt-2", children: [
|
|
13550
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13551
|
+
"button",
|
|
13552
|
+
{
|
|
13553
|
+
type: "button",
|
|
13554
|
+
onClick: onViewTracker,
|
|
13555
|
+
className: "uf-flex-1 uf-py-2.5 uf-text-sm uf-transition-colors hover:uf-opacity-90",
|
|
13556
|
+
style: {
|
|
13557
|
+
backgroundColor: components.button.secondaryBackground,
|
|
13558
|
+
color: components.button.secondaryText,
|
|
13559
|
+
fontFamily: fonts.medium,
|
|
13560
|
+
borderRadius: btnRadius,
|
|
13561
|
+
border: btnBorder
|
|
13562
|
+
},
|
|
13563
|
+
children: "Withdrawal History"
|
|
13564
|
+
}
|
|
13565
|
+
),
|
|
13566
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13567
|
+
"button",
|
|
13568
|
+
{
|
|
13569
|
+
type: "button",
|
|
13570
|
+
onClick: onClose,
|
|
13571
|
+
className: "uf-flex-1 uf-py-2.5 uf-text-sm uf-transition-colors hover:uf-opacity-90",
|
|
13572
|
+
style: {
|
|
13573
|
+
backgroundColor: components.button.primaryBackground,
|
|
13574
|
+
color: components.button.primaryText,
|
|
13575
|
+
fontFamily: fonts.medium,
|
|
13576
|
+
borderRadius: btnRadius,
|
|
13577
|
+
border: btnBorder
|
|
13578
|
+
},
|
|
13579
|
+
children: "Close"
|
|
13580
|
+
}
|
|
13581
|
+
)
|
|
13582
|
+
] }),
|
|
13583
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uf-pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13584
|
+
PoweredByUnifold,
|
|
13585
|
+
{
|
|
13586
|
+
color: colors2.foregroundMuted,
|
|
13587
|
+
className: "uf-flex uf-justify-center uf-shrink-0"
|
|
13588
|
+
}
|
|
13589
|
+
) })
|
|
13590
|
+
] });
|
|
13591
|
+
}
|
|
13592
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
|
|
13593
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(DepositHeader, { title: "Withdrawal Status", showClose: true, onClose }),
|
|
13594
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-16 uf-px-4", children: [
|
|
13595
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13596
|
+
"div",
|
|
13597
|
+
{
|
|
13598
|
+
className: "uf-w-20 uf-h-20 uf-rounded-full uf-flex uf-items-center uf-justify-center uf-mb-6",
|
|
13599
|
+
style: { backgroundColor: `${colors2.primary}20` },
|
|
13600
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13601
|
+
"svg",
|
|
13602
|
+
{
|
|
13603
|
+
width: "40",
|
|
13604
|
+
height: "40",
|
|
13605
|
+
viewBox: "0 0 24 24",
|
|
13606
|
+
fill: "none",
|
|
13607
|
+
className: "uf-animate-spin",
|
|
13608
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13609
|
+
"path",
|
|
13610
|
+
{
|
|
13611
|
+
d: "M21 12a9 9 0 1 1-6.22-8.56",
|
|
13612
|
+
stroke: colors2.primary,
|
|
13613
|
+
strokeWidth: "2.5",
|
|
13614
|
+
strokeLinecap: "round"
|
|
13615
|
+
}
|
|
13616
|
+
)
|
|
13617
|
+
}
|
|
13618
|
+
)
|
|
13619
|
+
}
|
|
13620
|
+
),
|
|
13621
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13622
|
+
"h3",
|
|
13623
|
+
{
|
|
13624
|
+
className: "uf-text-xl uf-mb-2",
|
|
13625
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
13626
|
+
children: "Checking Withdrawal"
|
|
13627
|
+
}
|
|
13628
|
+
),
|
|
13629
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
13630
|
+
"p",
|
|
13631
|
+
{
|
|
13632
|
+
className: "uf-text-sm uf-text-center",
|
|
13633
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
13634
|
+
children: [
|
|
13635
|
+
txInfo.amount,
|
|
13636
|
+
" ",
|
|
13637
|
+
txInfo.sourceTokenSymbol,
|
|
13638
|
+
" to",
|
|
13639
|
+
" ",
|
|
13640
|
+
truncateAddress4(txInfo.recipientAddress)
|
|
13641
|
+
]
|
|
13642
|
+
}
|
|
13643
|
+
)
|
|
13644
|
+
] }),
|
|
13645
|
+
showButton && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uf-px-1 uf-pb-1", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13646
|
+
"button",
|
|
13647
|
+
{
|
|
13648
|
+
type: "button",
|
|
13649
|
+
onClick: onViewTracker,
|
|
13650
|
+
className: "uf-w-full uf-py-2.5 uf-text-sm uf-transition-colors hover:uf-opacity-90",
|
|
13651
|
+
style: {
|
|
13652
|
+
backgroundColor: components.button.secondaryBackground,
|
|
13653
|
+
color: components.button.secondaryText,
|
|
13654
|
+
fontFamily: fonts.medium,
|
|
13655
|
+
borderRadius: btnRadius,
|
|
13656
|
+
border: btnBorder
|
|
13657
|
+
},
|
|
13658
|
+
children: "Withdrawal History"
|
|
13659
|
+
}
|
|
13660
|
+
) }),
|
|
13661
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "uf-pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
13662
|
+
PoweredByUnifold,
|
|
13663
|
+
{
|
|
13664
|
+
color: colors2.foregroundMuted,
|
|
13665
|
+
className: "uf-flex uf-justify-center uf-shrink-0"
|
|
13666
|
+
}
|
|
13667
|
+
) })
|
|
13668
|
+
] });
|
|
13669
|
+
}
|
|
13670
|
+
|
|
13671
|
+
// src/components/withdrawals/WithdrawModal.tsx
|
|
13672
|
+
var import_core32 = require("@unifold/core");
|
|
13673
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
13674
|
+
var t9 = i18n.withdrawModal;
|
|
13675
|
+
var getChainKey5 = (chainId, chainType) => `${chainType}:${chainId}`;
|
|
13676
|
+
function WithdrawModal({
|
|
13677
|
+
open,
|
|
13678
|
+
onOpenChange,
|
|
13679
|
+
publishableKey,
|
|
13680
|
+
modalTitle,
|
|
13681
|
+
externalUserId,
|
|
13682
|
+
sourceChainType,
|
|
13683
|
+
sourceChainId,
|
|
13684
|
+
sourceTokenAddress,
|
|
13685
|
+
sourceTokenSymbol,
|
|
13686
|
+
recipientAddress: recipientAddressProp,
|
|
13687
|
+
senderAddress,
|
|
13688
|
+
onWithdraw,
|
|
13689
|
+
onWithdrawSuccess,
|
|
13690
|
+
onWithdrawError,
|
|
13691
|
+
theme = "dark",
|
|
13692
|
+
hideOverlay = false
|
|
13693
|
+
}) {
|
|
13694
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
13695
|
+
const [containerEl, setContainerEl] = (0, import_react22.useState)(null);
|
|
13696
|
+
const containerCallbackRef = (0, import_react22.useCallback)((el) => {
|
|
13697
|
+
setContainerEl(el);
|
|
13698
|
+
}, []);
|
|
13699
|
+
const [resolvedTheme, setResolvedTheme] = (0, import_react22.useState)(
|
|
13700
|
+
theme === "auto" ? "dark" : theme
|
|
13701
|
+
);
|
|
13702
|
+
(0, import_react22.useEffect)(() => {
|
|
13703
|
+
if (theme === "auto") {
|
|
13704
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
13705
|
+
setResolvedTheme(mq.matches ? "dark" : "light");
|
|
13706
|
+
const h = (e) => setResolvedTheme(e.matches ? "dark" : "light");
|
|
13707
|
+
mq.addEventListener("change", h);
|
|
13708
|
+
return () => mq.removeEventListener("change", h);
|
|
13709
|
+
}
|
|
13710
|
+
setResolvedTheme(theme);
|
|
13711
|
+
}, [theme]);
|
|
13712
|
+
const themeClass = resolvedTheme === "dark" ? "uf-dark" : "";
|
|
13713
|
+
const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDestinationTokens(publishableKey, open);
|
|
13714
|
+
const destinationTokens = tokensResponse?.data ?? [];
|
|
13715
|
+
const { data: sourceValidation, isLoading: isCheckingSourceToken } = useSourceTokenValidation({
|
|
13716
|
+
sourceChainType,
|
|
13717
|
+
sourceChainId,
|
|
13718
|
+
sourceTokenAddress,
|
|
13719
|
+
sourceTokenSymbol,
|
|
13720
|
+
publishableKey,
|
|
13721
|
+
enabled: open
|
|
13722
|
+
});
|
|
13723
|
+
const { data: balanceData, isLoading: isLoadingBalance } = useAddressBalance({
|
|
13724
|
+
address: senderAddress,
|
|
13725
|
+
chainType: sourceChainType,
|
|
13726
|
+
chainId: sourceChainId,
|
|
13727
|
+
tokenAddress: sourceTokenAddress,
|
|
13728
|
+
publishableKey,
|
|
13729
|
+
enabled: open
|
|
13730
|
+
});
|
|
13731
|
+
const [selectedToken, setSelectedToken] = (0, import_react22.useState)(null);
|
|
13732
|
+
const [selectedChain, setSelectedChain] = (0, import_react22.useState)(null);
|
|
13733
|
+
const [detectedWallet, setDetectedWallet] = (0, import_react22.useState)(null);
|
|
13734
|
+
const connectedWalletName = detectedWallet?.name ?? null;
|
|
13735
|
+
const isWalletMatch = !!detectedWallet;
|
|
13736
|
+
(0, import_react22.useEffect)(() => {
|
|
13737
|
+
if (!senderAddress || !open) {
|
|
13738
|
+
setDetectedWallet(null);
|
|
13739
|
+
return;
|
|
13740
|
+
}
|
|
13741
|
+
let cancelled = false;
|
|
13742
|
+
detectBrowserWallet(sourceChainType, senderAddress).then((wallet) => {
|
|
13743
|
+
if (!cancelled) setDetectedWallet(wallet);
|
|
13744
|
+
});
|
|
13745
|
+
return () => {
|
|
13746
|
+
cancelled = true;
|
|
13747
|
+
};
|
|
13748
|
+
}, [senderAddress, sourceChainType, open]);
|
|
13749
|
+
const [view, setView] = (0, import_react22.useState)("form");
|
|
13750
|
+
const [withdrawDepositWalletId, setWithdrawDepositWalletId] = (0, import_react22.useState)();
|
|
13751
|
+
const [selectedExecution, setSelectedExecution] = (0, import_react22.useState)(null);
|
|
13752
|
+
const [submittedTxInfo, setSubmittedTxInfo] = (0, import_react22.useState)(null);
|
|
13753
|
+
const { executions: realtimeExecutions } = useWithdrawPolling({
|
|
13754
|
+
userId: externalUserId,
|
|
13755
|
+
publishableKey,
|
|
13756
|
+
depositWalletId: withdrawDepositWalletId,
|
|
13757
|
+
enabled: !!withdrawDepositWalletId && open,
|
|
13758
|
+
onWithdrawSuccess: onWithdrawSuccess ? (d) => onWithdrawSuccess({ message: d.message, transaction: d.transaction }) : void 0,
|
|
13759
|
+
onWithdrawError
|
|
13760
|
+
});
|
|
13761
|
+
const { data: allWithdrawalsData } = useExecutions(externalUserId, publishableKey, {
|
|
13762
|
+
actionType: import_core32.ActionType.Withdraw,
|
|
13763
|
+
enabled: open,
|
|
13764
|
+
refetchInterval: view === "tracker" || view === "detail" ? 5e3 : 15e3
|
|
13765
|
+
});
|
|
13766
|
+
const allWithdrawals = allWithdrawalsData?.data ?? [];
|
|
13767
|
+
const handleDepositWalletCreation = (0, import_react22.useCallback)(async (params) => {
|
|
13768
|
+
const { data: wallets } = await (0, import_core32.createDepositAddress)(
|
|
13769
|
+
{
|
|
13770
|
+
external_user_id: externalUserId,
|
|
13771
|
+
destination_chain_type: params.destinationChainType,
|
|
13772
|
+
destination_chain_id: params.destinationChainId,
|
|
13773
|
+
destination_token_address: params.destinationTokenAddress,
|
|
13774
|
+
recipient_address: params.recipientAddress,
|
|
13775
|
+
action_type: import_core32.ActionType.Withdraw
|
|
13776
|
+
},
|
|
13777
|
+
publishableKey
|
|
13778
|
+
);
|
|
13779
|
+
const depositWallet = (0, import_core32.getWalletByChainType)(wallets, sourceChainType);
|
|
13780
|
+
if (!depositWallet) {
|
|
13781
|
+
throw new Error(`No deposit wallet available for ${sourceChainType}`);
|
|
13782
|
+
}
|
|
13783
|
+
setWithdrawDepositWalletId(depositWallet.id);
|
|
13784
|
+
return depositWallet;
|
|
13785
|
+
}, [externalUserId, publishableKey, sourceChainType]);
|
|
13786
|
+
const handleWithdrawSubmitted = (0, import_react22.useCallback)((txInfo) => {
|
|
13787
|
+
setSubmittedTxInfo(txInfo);
|
|
13788
|
+
setView("confirming");
|
|
13789
|
+
}, []);
|
|
13790
|
+
(0, import_react22.useEffect)(() => {
|
|
13791
|
+
if (!destinationTokens.length || selectedToken) return;
|
|
13792
|
+
const first = destinationTokens[0];
|
|
13793
|
+
if (first?.chains.length > 0) {
|
|
13794
|
+
setSelectedToken(first);
|
|
13795
|
+
setSelectedChain(first.chains[0]);
|
|
13796
|
+
}
|
|
13797
|
+
}, [destinationTokens, selectedToken]);
|
|
13798
|
+
const resetViewTimeoutRef = (0, import_react22.useRef)(null);
|
|
13799
|
+
const handleClose = (0, import_react22.useCallback)(() => {
|
|
13800
|
+
onOpenChange(false);
|
|
13801
|
+
if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
|
|
13802
|
+
resetViewTimeoutRef.current = setTimeout(() => {
|
|
13803
|
+
setSelectedToken(null);
|
|
13804
|
+
setSelectedChain(null);
|
|
13805
|
+
setView("form");
|
|
13806
|
+
setSelectedExecution(null);
|
|
13807
|
+
setSubmittedTxInfo(null);
|
|
13808
|
+
setWithdrawDepositWalletId(void 0);
|
|
13809
|
+
resetViewTimeoutRef.current = null;
|
|
13810
|
+
}, 200);
|
|
13811
|
+
}, [onOpenChange]);
|
|
13812
|
+
(0, import_react22.useLayoutEffect)(() => {
|
|
13813
|
+
if (!open) return;
|
|
13814
|
+
if (resetViewTimeoutRef.current) {
|
|
13815
|
+
clearTimeout(resetViewTimeoutRef.current);
|
|
13816
|
+
resetViewTimeoutRef.current = null;
|
|
13817
|
+
}
|
|
13818
|
+
setSelectedToken(null);
|
|
13819
|
+
setSelectedChain(null);
|
|
13820
|
+
setView("form");
|
|
13821
|
+
setSelectedExecution(null);
|
|
13822
|
+
setSubmittedTxInfo(null);
|
|
13823
|
+
setWithdrawDepositWalletId(void 0);
|
|
13824
|
+
}, [open]);
|
|
13825
|
+
(0, import_react22.useEffect)(() => () => {
|
|
13826
|
+
if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
|
|
13827
|
+
}, []);
|
|
13828
|
+
const handleTokenSymbolChange = (0, import_react22.useCallback)((symbol) => {
|
|
13829
|
+
const tok = destinationTokens.find((t11) => t11.symbol === symbol);
|
|
13830
|
+
if (tok) {
|
|
13831
|
+
setSelectedToken(tok);
|
|
13832
|
+
if (tok.chains.length > 0) setSelectedChain(tok.chains[0]);
|
|
13833
|
+
}
|
|
13834
|
+
}, [destinationTokens]);
|
|
13835
|
+
const handleChainKeyChange = (0, import_react22.useCallback)((chainKey) => {
|
|
13836
|
+
if (!selectedToken) return;
|
|
13837
|
+
const chain = selectedToken.chains.find((c) => getChainKey5(c.chain_id, c.chain_type) === chainKey);
|
|
13838
|
+
if (chain) setSelectedChain(chain);
|
|
13839
|
+
}, [selectedToken]);
|
|
13840
|
+
const isSourceSupported = sourceValidation?.isSupported ?? null;
|
|
13841
|
+
const canWithdraw = !!onWithdraw || isWalletMatch;
|
|
13842
|
+
const isAnyLoading = tokensLoading || isCheckingSourceToken;
|
|
13843
|
+
const withdrawPoweredByFooter = /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uf-pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(PoweredByUnifold, { color: colors2.foregroundMuted, className: "uf-flex uf-justify-center uf-shrink-0" }) });
|
|
13844
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(PortalContainerProvider, { value: hideOverlay ? containerEl : null, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Dialog, { open: hideOverlay || open, onOpenChange: hideOverlay ? void 0 : handleClose, modal: !hideOverlay, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
13845
|
+
DialogContent,
|
|
13846
|
+
{
|
|
13847
|
+
ref: hideOverlay ? containerCallbackRef : void 0,
|
|
13848
|
+
hideOverlay,
|
|
13849
|
+
className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden ${hideOverlay ? `uf-p-6 uf-overflow-hidden ${themeClass}` : `uf-p-0 uf-overflow-visible !uf-top-auto !uf-h-auto !uf-max-h-[90vh] sm:!uf-max-h-none sm:!uf-top-[50%] ${themeClass}`}`,
|
|
13850
|
+
style: { backgroundColor: colors2.background },
|
|
13851
|
+
onPointerDownOutside: (e) => e.preventDefault(),
|
|
13852
|
+
onInteractOutside: (e) => e.preventDefault(),
|
|
13853
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(ThemeStyleInjector, { children: view === "confirming" && submittedTxInfo ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
13854
|
+
WithdrawConfirmingView,
|
|
13855
|
+
{
|
|
13856
|
+
txInfo: submittedTxInfo,
|
|
13857
|
+
executions: realtimeExecutions,
|
|
13858
|
+
onClose: handleClose,
|
|
13859
|
+
onViewTracker: () => setView("tracker")
|
|
13860
|
+
}
|
|
13861
|
+
) : view === "detail" && selectedExecution ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
13862
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(DepositHeader, { title: "Withdrawal Details", showBack: true, showClose: !hideOverlay, onBack: () => {
|
|
13863
|
+
setSelectedExecution(null);
|
|
13864
|
+
setView("tracker");
|
|
13865
|
+
}, onClose: handleClose }),
|
|
13866
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(DepositDetailContent, { execution: selectedExecution, variant: "withdraw" }),
|
|
13867
|
+
withdrawPoweredByFooter
|
|
13868
|
+
] }) : view === "tracker" ? (
|
|
13869
|
+
/* ---------- Tracker view: execution list ---------- */
|
|
13870
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
13871
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(DepositHeader, { title: "Withdrawal History", showBack: true, showClose: !hideOverlay, onBack: () => setView("form"), onClose: handleClose }),
|
|
13872
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uf-flex uf-flex-col uf-gap-2", style: { minHeight: 200 }, children: allWithdrawals.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "uf-text-sm", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No withdrawals to track yet" }) }) : allWithdrawals.map((ex) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
13873
|
+
WithdrawExecutionItem,
|
|
13874
|
+
{
|
|
13875
|
+
execution: ex,
|
|
13876
|
+
onClick: () => {
|
|
13877
|
+
setSelectedExecution(ex);
|
|
13878
|
+
setView("detail");
|
|
13879
|
+
}
|
|
13880
|
+
},
|
|
13881
|
+
ex.id
|
|
13882
|
+
)) }),
|
|
13883
|
+
withdrawPoweredByFooter
|
|
13884
|
+
] })
|
|
13885
|
+
) : (
|
|
13886
|
+
/* ---------- Form view (default) ---------- */
|
|
13887
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
13888
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(DepositHeader, { title: modalTitle || t9.title, showClose: !hideOverlay, onClose: handleClose }),
|
|
13889
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "uf-flex uf-flex-col uf-gap-3", children: [
|
|
13890
|
+
isAnyLoading ? /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uf-space-y-3", children: [1, 2, 3].map((i) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uf-w-full uf-bg-secondary uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-animate-pulse", children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "uf-bg-muted uf-rounded-lg uf-w-full uf-h-10" }) }, i)) }) : isSourceSupported === false ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
|
|
13891
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("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__ */ (0, import_jsx_runtime56.jsx)(import_lucide_react26.AlertTriangle, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
|
|
13892
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("h3", { className: "uf-text-lg uf-font-semibold uf-mb-2", style: { color: colors2.foreground, fontFamily: fonts.medium }, children: "Unsupported Source Token" }),
|
|
13893
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("p", { className: "uf-text-sm uf-max-w-[280px]", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: sourceValidation?.errorMessage })
|
|
13894
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
13895
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
13896
|
+
WithdrawDoubleInput,
|
|
13897
|
+
{
|
|
13898
|
+
tokens: destinationTokens,
|
|
13899
|
+
selectedTokenSymbol: selectedToken?.symbol ?? null,
|
|
13900
|
+
selectedChainKey: selectedChain ? getChainKey5(selectedChain.chain_id, selectedChain.chain_type) : null,
|
|
13901
|
+
onTokenChange: handleTokenSymbolChange,
|
|
13902
|
+
onChainChange: handleChainKeyChange,
|
|
13903
|
+
isLoading: tokensLoading
|
|
13904
|
+
}
|
|
13905
|
+
),
|
|
13906
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
13907
|
+
WithdrawForm,
|
|
13908
|
+
{
|
|
13909
|
+
publishableKey,
|
|
13910
|
+
externalUserId,
|
|
13911
|
+
sourceChainType,
|
|
13912
|
+
selectedToken,
|
|
13913
|
+
selectedChain,
|
|
13914
|
+
sourceTokenSymbol,
|
|
13915
|
+
recipientAddressProp,
|
|
13916
|
+
balanceData: balanceData ?? null,
|
|
13917
|
+
isLoadingBalance,
|
|
13918
|
+
minimumWithdrawAmountUsd: sourceValidation?.minimumAmountUsd ?? null,
|
|
13919
|
+
estimatedProcessingTime: sourceValidation?.estimatedProcessingTime ?? null,
|
|
13920
|
+
maxSlippagePercent: sourceValidation?.maxSlippagePercent ?? null,
|
|
13921
|
+
priceImpactPercent: sourceValidation?.priceImpactPercent ?? null,
|
|
13922
|
+
detectedWallet,
|
|
13923
|
+
sourceChainId,
|
|
13924
|
+
sourceTokenAddress,
|
|
13925
|
+
isWalletMatch,
|
|
13926
|
+
connectedWalletName,
|
|
13927
|
+
canWithdraw,
|
|
13928
|
+
onWithdraw,
|
|
13929
|
+
onWithdrawError,
|
|
13930
|
+
onDepositWalletCreation: handleDepositWalletCreation,
|
|
13931
|
+
onWithdrawSubmitted: handleWithdrawSubmitted,
|
|
13932
|
+
footerLeft: /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
|
|
13933
|
+
"button",
|
|
13934
|
+
{
|
|
13935
|
+
onClick: () => setView("tracker"),
|
|
13936
|
+
className: "uf-flex uf-items-center uf-gap-1 uf-transition-colors hover:uf-opacity-70",
|
|
13937
|
+
style: { color: colors2.foregroundMuted },
|
|
13938
|
+
children: [
|
|
13939
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_lucide_react26.Clock, { className: "uf-w-3.5 uf-h-3.5" }),
|
|
13940
|
+
"Withdrawal History",
|
|
13941
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(import_lucide_react26.ChevronRight, { className: "uf-w-3 uf-h-3" })
|
|
13942
|
+
]
|
|
13943
|
+
}
|
|
13944
|
+
)
|
|
13945
|
+
}
|
|
13946
|
+
)
|
|
13947
|
+
] }),
|
|
13948
|
+
withdrawPoweredByFooter
|
|
13949
|
+
] })
|
|
13950
|
+
] })
|
|
13951
|
+
) })
|
|
13952
|
+
}
|
|
13953
|
+
) }) });
|
|
13954
|
+
}
|
|
13955
|
+
|
|
13956
|
+
// src/components/withdrawals/WithdrawTokenSelector.tsx
|
|
13957
|
+
var import_react23 = require("react");
|
|
13958
|
+
var import_lucide_react27 = require("lucide-react");
|
|
13959
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
13960
|
+
var t10 = i18n.withdrawModal;
|
|
13961
|
+
function WithdrawTokenSelector({
|
|
13962
|
+
tokens,
|
|
13963
|
+
onSelect,
|
|
13964
|
+
onBack
|
|
13965
|
+
}) {
|
|
13966
|
+
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
13967
|
+
const [searchQuery, setSearchQuery] = (0, import_react23.useState)("");
|
|
13968
|
+
const [hoveredKey, setHoveredKey] = (0, import_react23.useState)(null);
|
|
13969
|
+
const allOptions = (0, import_react23.useMemo)(() => {
|
|
13970
|
+
const options = [];
|
|
13971
|
+
tokens.forEach((token) => {
|
|
13972
|
+
token.chains.forEach((chain) => {
|
|
13973
|
+
options.push({ token, chain });
|
|
13974
|
+
});
|
|
13975
|
+
});
|
|
13976
|
+
return options;
|
|
13977
|
+
}, [tokens]);
|
|
13978
|
+
const filteredOptions = (0, import_react23.useMemo)(() => {
|
|
13979
|
+
if (!searchQuery.trim()) return allOptions;
|
|
13980
|
+
const query = searchQuery.toLowerCase();
|
|
13981
|
+
return allOptions.filter(
|
|
13982
|
+
({ token, chain }) => token.symbol.toLowerCase().includes(query) || token.name.toLowerCase().includes(query) || chain.chain_name.toLowerCase().includes(query)
|
|
13983
|
+
);
|
|
13984
|
+
}, [allOptions, searchQuery]);
|
|
13985
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
|
|
13986
|
+
"div",
|
|
13987
|
+
{
|
|
13988
|
+
className: "uf-flex uf-flex-col",
|
|
13989
|
+
style: { minHeight: 0, flex: 1 },
|
|
13990
|
+
children: [
|
|
13991
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { className: "uf-pb-3", children: [
|
|
13992
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
13993
|
+
"style",
|
|
13994
|
+
{
|
|
13995
|
+
dangerouslySetInnerHTML: {
|
|
13996
|
+
__html: `.uf-withdraw-token-search::placeholder { color: ${components.search.placeholderColor}; }`
|
|
13997
|
+
}
|
|
13998
|
+
}
|
|
13999
|
+
),
|
|
14000
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { style: { position: "relative" }, children: [
|
|
14001
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14002
|
+
import_lucide_react27.Search,
|
|
14003
|
+
{
|
|
14004
|
+
className: "uf-absolute uf-left-3 uf-top-1/2 uf--translate-y-1/2 uf-w-4 uf-h-4",
|
|
14005
|
+
style: { color: components.search.placeholderColor }
|
|
14006
|
+
}
|
|
14007
|
+
),
|
|
14008
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14009
|
+
"input",
|
|
14010
|
+
{
|
|
14011
|
+
type: "text",
|
|
14012
|
+
placeholder: "Search token or network",
|
|
14013
|
+
value: searchQuery,
|
|
14014
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
14015
|
+
className: "uf-withdraw-token-search uf-w-full uf-pl-10 uf-pr-4 uf-py-2.5 uf-text-sm uf-outline-none focus:uf-ring-2 focus:uf-ring-ring/30",
|
|
14016
|
+
style: {
|
|
14017
|
+
backgroundColor: components.search.backgroundColor,
|
|
14018
|
+
color: components.search.inputColor,
|
|
14019
|
+
fontFamily: fonts.regular,
|
|
14020
|
+
borderRadius: components.input.borderRadius,
|
|
14021
|
+
border: `${components.input.borderWidth}px solid ${components.input.borderColor}`
|
|
14022
|
+
}
|
|
14023
|
+
}
|
|
14024
|
+
)
|
|
14025
|
+
] })
|
|
14026
|
+
] }),
|
|
14027
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14028
|
+
"div",
|
|
14029
|
+
{
|
|
14030
|
+
className: "uf-text-xs uf-mb-2",
|
|
14031
|
+
style: {
|
|
14032
|
+
color: components.list.titleSectionColor,
|
|
14033
|
+
fontFamily: fonts.medium
|
|
14034
|
+
},
|
|
14035
|
+
children: t10.selectToken
|
|
14036
|
+
}
|
|
14037
|
+
),
|
|
14038
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14039
|
+
"div",
|
|
14040
|
+
{
|
|
14041
|
+
className: "uf-flex-1 uf-overflow-y-auto uf-min-h-0 uf--mx-6 uf-px-6 uf-pb-3",
|
|
14042
|
+
style: { scrollbarWidth: "none" },
|
|
14043
|
+
children: filteredOptions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14044
|
+
"div",
|
|
14045
|
+
{
|
|
14046
|
+
style: {
|
|
14047
|
+
textAlign: "center",
|
|
14048
|
+
padding: "2rem 0",
|
|
14049
|
+
fontSize: 14,
|
|
14050
|
+
color: components.container.subtitleColor,
|
|
14051
|
+
fontFamily: fonts.regular
|
|
14052
|
+
},
|
|
14053
|
+
children: t10.noTokensAvailable
|
|
14054
|
+
}
|
|
14055
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: filteredOptions.map(({ token, chain }) => {
|
|
14056
|
+
const key = `${token.symbol}-${chain.chain_type}:${chain.chain_id}`;
|
|
14057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
|
|
14058
|
+
"button",
|
|
14059
|
+
{
|
|
14060
|
+
type: "button",
|
|
14061
|
+
onClick: () => onSelect(token, chain),
|
|
14062
|
+
onMouseEnter: () => setHoveredKey(key),
|
|
14063
|
+
onMouseLeave: () => setHoveredKey(null),
|
|
14064
|
+
className: "uf-transition-colors",
|
|
14065
|
+
style: {
|
|
14066
|
+
width: "100%",
|
|
14067
|
+
display: "flex",
|
|
14068
|
+
alignItems: "center",
|
|
14069
|
+
gap: 12,
|
|
14070
|
+
padding: 12,
|
|
14071
|
+
borderRadius: 12,
|
|
14072
|
+
border: "none",
|
|
14073
|
+
cursor: "pointer",
|
|
14074
|
+
textAlign: "left",
|
|
14075
|
+
backgroundColor: hoveredKey === key ? colors2.cardHover : "transparent"
|
|
14076
|
+
},
|
|
14077
|
+
children: [
|
|
14078
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
14079
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14080
|
+
"img",
|
|
14081
|
+
{
|
|
14082
|
+
src: token.icon_url,
|
|
14083
|
+
alt: token.symbol,
|
|
14084
|
+
width: 40,
|
|
14085
|
+
height: 40,
|
|
14086
|
+
loading: "lazy",
|
|
14087
|
+
className: "uf-rounded-full"
|
|
14088
|
+
}
|
|
14089
|
+
),
|
|
14090
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14091
|
+
"div",
|
|
14092
|
+
{
|
|
14093
|
+
style: {
|
|
14094
|
+
position: "absolute",
|
|
14095
|
+
bottom: -4,
|
|
14096
|
+
right: -4
|
|
14097
|
+
},
|
|
14098
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14099
|
+
"img",
|
|
14100
|
+
{
|
|
14101
|
+
src: chain.icon_url,
|
|
14102
|
+
alt: chain.chain_name,
|
|
14103
|
+
width: 20,
|
|
14104
|
+
height: 20,
|
|
14105
|
+
loading: "lazy",
|
|
14106
|
+
className: "uf-rounded-full uf-border-2"
|
|
14107
|
+
}
|
|
14108
|
+
)
|
|
14109
|
+
}
|
|
14110
|
+
)
|
|
14111
|
+
] }),
|
|
14112
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
14113
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14114
|
+
"div",
|
|
14115
|
+
{
|
|
14116
|
+
style: {
|
|
14117
|
+
fontSize: 14,
|
|
14118
|
+
fontWeight: 500,
|
|
14119
|
+
color: components.card.titleColor,
|
|
14120
|
+
fontFamily: fonts.medium
|
|
14121
|
+
},
|
|
14122
|
+
children: token.symbol
|
|
14123
|
+
}
|
|
14124
|
+
),
|
|
14125
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(
|
|
14126
|
+
"div",
|
|
14127
|
+
{
|
|
14128
|
+
style: {
|
|
14129
|
+
fontSize: 12,
|
|
14130
|
+
color: components.card.subtitleColor,
|
|
14131
|
+
fontFamily: fonts.regular
|
|
14132
|
+
},
|
|
14133
|
+
children: [
|
|
14134
|
+
token.name,
|
|
14135
|
+
" \u2022 ",
|
|
14136
|
+
chain.chain_name
|
|
14137
|
+
]
|
|
14138
|
+
}
|
|
14139
|
+
)
|
|
14140
|
+
] })
|
|
14141
|
+
]
|
|
14142
|
+
},
|
|
14143
|
+
key
|
|
14144
|
+
);
|
|
14145
|
+
}) })
|
|
14146
|
+
}
|
|
14147
|
+
),
|
|
14148
|
+
/* @__PURE__ */ (0, import_jsx_runtime57.jsx)("div", { className: "uf-pt-3 uf-pb-2 uf-shrink-0", children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
14149
|
+
PoweredByUnifold,
|
|
14150
|
+
{
|
|
14151
|
+
color: colors2.foregroundMuted,
|
|
14152
|
+
className: "uf-flex uf-justify-center uf-shrink-0"
|
|
14153
|
+
}
|
|
14154
|
+
) })
|
|
14155
|
+
]
|
|
14156
|
+
}
|
|
14157
|
+
);
|
|
14158
|
+
}
|
|
12106
14159
|
// Annotate the CommonJS export names for ESM import in node:
|
|
12107
14160
|
0 && (module.exports = {
|
|
12108
14161
|
Button,
|
|
@@ -12149,15 +14202,29 @@ function DepositModal({
|
|
|
12149
14202
|
TransferCryptoButton,
|
|
12150
14203
|
TransferCryptoDoubleInput,
|
|
12151
14204
|
TransferCryptoSingleInput,
|
|
14205
|
+
WithdrawConfirmingView,
|
|
14206
|
+
WithdrawDoubleInput,
|
|
14207
|
+
WithdrawExecutionItem,
|
|
14208
|
+
WithdrawForm,
|
|
14209
|
+
WithdrawModal,
|
|
14210
|
+
WithdrawTokenSelector,
|
|
12152
14211
|
buttonVariants,
|
|
12153
14212
|
cn,
|
|
12154
14213
|
colors,
|
|
12155
14214
|
defaultColors,
|
|
14215
|
+
detectBrowserWallet,
|
|
12156
14216
|
getColors,
|
|
12157
14217
|
mergeColors,
|
|
12158
14218
|
resolveComponentTokens,
|
|
14219
|
+
sendEvmWithdraw,
|
|
14220
|
+
sendSolanaWithdraw,
|
|
12159
14221
|
truncateAddress,
|
|
14222
|
+
useAddressBalance,
|
|
12160
14223
|
useAllowedCountry,
|
|
12161
14224
|
useDepositPolling,
|
|
12162
|
-
|
|
14225
|
+
useSourceTokenValidation,
|
|
14226
|
+
useSupportedDestinationTokens,
|
|
14227
|
+
useTheme,
|
|
14228
|
+
useVerifyRecipientAddress,
|
|
14229
|
+
useWithdrawPolling
|
|
12163
14230
|
});
|