@unifold/ui-react 0.1.41 → 0.1.43
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 +410 -37
- package/dist/index.d.ts +410 -37
- package/dist/index.js +3174 -107
- package/dist/index.mjs +3218 -123
- package/dist/styles-base.css +1 -1
- package/dist/styles.css +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// src/components/deposits/DepositModal.tsx
|
|
2
2
|
import {
|
|
3
3
|
useState as useState27,
|
|
4
|
-
useEffect as
|
|
4
|
+
useEffect as useEffect22,
|
|
5
5
|
useLayoutEffect as useLayoutEffect2,
|
|
6
6
|
useCallback as useCallback4,
|
|
7
|
-
useRef as
|
|
7
|
+
useRef as useRef7,
|
|
8
8
|
useMemo as useMemo9
|
|
9
9
|
} from "react";
|
|
10
10
|
import { ChevronRight as ChevronRight11, MapPinOff, AlertTriangle } from "lucide-react";
|
|
@@ -621,6 +621,7 @@ function useDepositAddress(params) {
|
|
|
621
621
|
destinationChainType,
|
|
622
622
|
destinationChainId,
|
|
623
623
|
destinationTokenAddress,
|
|
624
|
+
actionType,
|
|
624
625
|
enabled = true
|
|
625
626
|
} = params;
|
|
626
627
|
return useQuery({
|
|
@@ -632,6 +633,7 @@ function useDepositAddress(params) {
|
|
|
632
633
|
destinationChainType ?? null,
|
|
633
634
|
destinationChainId ?? null,
|
|
634
635
|
destinationTokenAddress ?? null,
|
|
636
|
+
actionType ?? null,
|
|
635
637
|
publishableKey
|
|
636
638
|
],
|
|
637
639
|
queryFn: () => createDepositAddress(
|
|
@@ -640,7 +642,8 @@ function useDepositAddress(params) {
|
|
|
640
642
|
recipient_address: recipientAddress,
|
|
641
643
|
destination_chain_type: destinationChainType,
|
|
642
644
|
destination_chain_id: destinationChainId,
|
|
643
|
-
destination_token_address: destinationTokenAddress
|
|
645
|
+
destination_token_address: destinationTokenAddress,
|
|
646
|
+
action_type: actionType
|
|
644
647
|
},
|
|
645
648
|
publishableKey
|
|
646
649
|
),
|
|
@@ -1354,6 +1357,30 @@ var en_default = {
|
|
|
1354
1357
|
youReceive: "You receive",
|
|
1355
1358
|
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."
|
|
1356
1359
|
}
|
|
1360
|
+
},
|
|
1361
|
+
withdrawModal: {
|
|
1362
|
+
title: "Withdraw",
|
|
1363
|
+
withdrawCrypto: {
|
|
1364
|
+
title: "Withdraw with Crypto",
|
|
1365
|
+
subtitle: "Send to any wallet address"
|
|
1366
|
+
},
|
|
1367
|
+
selectToken: "Select withdrawal token",
|
|
1368
|
+
receiveToken: "Receive token",
|
|
1369
|
+
receiveChain: "Receive chain",
|
|
1370
|
+
recipientAddress: "Recipient address",
|
|
1371
|
+
recipientAddressPlaceholder: "Enter wallet address",
|
|
1372
|
+
amount: "Amount",
|
|
1373
|
+
amountPlaceholder: "0.00",
|
|
1374
|
+
balance: "Balance",
|
|
1375
|
+
minimum: "min",
|
|
1376
|
+
withdraw: "Withdraw",
|
|
1377
|
+
invalidAddress: "Please enter a valid address",
|
|
1378
|
+
invalidAmount: "Please enter a valid amount",
|
|
1379
|
+
verifyingAddress: "Verifying address...",
|
|
1380
|
+
loading: "Loading...",
|
|
1381
|
+
noTokensAvailable: "No tokens available",
|
|
1382
|
+
review: "Review Withdrawal",
|
|
1383
|
+
back: "Back"
|
|
1357
1384
|
}
|
|
1358
1385
|
};
|
|
1359
1386
|
|
|
@@ -1371,8 +1398,10 @@ function interpolate(template, params) {
|
|
|
1371
1398
|
import { useState as useState5, useEffect as useEffect3, useRef } from "react";
|
|
1372
1399
|
import {
|
|
1373
1400
|
queryExecutions,
|
|
1401
|
+
listPaymentIntentExecutions,
|
|
1374
1402
|
pollDirectExecutions,
|
|
1375
|
-
ExecutionStatus
|
|
1403
|
+
ExecutionStatus,
|
|
1404
|
+
ActionType
|
|
1376
1405
|
} from "@unifold/core";
|
|
1377
1406
|
var DEPOSIT_CONFIRM_DELAY_MS = 1e4;
|
|
1378
1407
|
var POLL_INTERVAL_MS = 2500;
|
|
@@ -1381,6 +1410,7 @@ var CUTOFF_BUFFER_MS = 6e4;
|
|
|
1381
1410
|
function useDepositPolling({
|
|
1382
1411
|
userId,
|
|
1383
1412
|
publishableKey,
|
|
1413
|
+
clientSecret,
|
|
1384
1414
|
depositConfirmationMode = "auto_ui",
|
|
1385
1415
|
depositWalletId,
|
|
1386
1416
|
enabled = true,
|
|
@@ -1438,11 +1468,12 @@ function useDepositPolling({
|
|
|
1438
1468
|
depositWalletId
|
|
1439
1469
|
]);
|
|
1440
1470
|
useEffect3(() => {
|
|
1441
|
-
if (!
|
|
1471
|
+
if (!enabled) return;
|
|
1472
|
+
if (!clientSecret && !userId) return;
|
|
1442
1473
|
const modalOpenedAt = modalOpenedAtRef.current;
|
|
1443
1474
|
const poll = async () => {
|
|
1444
1475
|
try {
|
|
1445
|
-
const response = await queryExecutions(userId, publishableKey);
|
|
1476
|
+
const response = clientSecret ? await listPaymentIntentExecutions(clientSecret, publishableKey) : await queryExecutions(userId, publishableKey, ActionType.Deposit);
|
|
1446
1477
|
const cutoff = new Date(modalOpenedAt.getTime() - CUTOFF_BUFFER_MS);
|
|
1447
1478
|
const sortedExecutions = [...response.data].sort((a, b) => {
|
|
1448
1479
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
@@ -1526,7 +1557,7 @@ function useDepositPolling({
|
|
|
1526
1557
|
clearInterval(pollInterval);
|
|
1527
1558
|
setIsPolling(false);
|
|
1528
1559
|
};
|
|
1529
|
-
}, [userId, publishableKey, enabled]);
|
|
1560
|
+
}, [userId, publishableKey, clientSecret, enabled]);
|
|
1530
1561
|
useEffect3(() => {
|
|
1531
1562
|
if (!pollingEnabled || !depositWalletId) return;
|
|
1532
1563
|
const triggerPoll = async () => {
|
|
@@ -1586,7 +1617,8 @@ function formatCurrency(currency) {
|
|
|
1586
1617
|
}
|
|
1587
1618
|
function DepositDetailContent({
|
|
1588
1619
|
execution,
|
|
1589
|
-
className
|
|
1620
|
+
className,
|
|
1621
|
+
variant = "deposit"
|
|
1590
1622
|
}) {
|
|
1591
1623
|
const { colors: colors2, fonts, components } = useTheme();
|
|
1592
1624
|
const [chains, setChains] = useState6([]);
|
|
@@ -1992,7 +2024,7 @@ function DepositDetailContent({
|
|
|
1992
2024
|
color: components.card.rowLeftLabel,
|
|
1993
2025
|
fontFamily: fonts.regular
|
|
1994
2026
|
},
|
|
1995
|
-
children: "Deposit Tx"
|
|
2027
|
+
children: variant === "withdraw" ? "Withdrawal Tx" : "Deposit Tx"
|
|
1996
2028
|
}
|
|
1997
2029
|
),
|
|
1998
2030
|
/* @__PURE__ */ jsx7(
|
|
@@ -6900,7 +6932,8 @@ function useProjectConfig({
|
|
|
6900
6932
|
|
|
6901
6933
|
// src/components/deposits/DepositModal.tsx
|
|
6902
6934
|
import {
|
|
6903
|
-
queryExecutions as queryExecutions3
|
|
6935
|
+
queryExecutions as queryExecutions3,
|
|
6936
|
+
ActionType as ActionType3
|
|
6904
6937
|
} from "@unifold/core";
|
|
6905
6938
|
|
|
6906
6939
|
// src/hooks/use-allowed-country.ts
|
|
@@ -7287,7 +7320,7 @@ function PoweredByUnifold({
|
|
|
7287
7320
|
}
|
|
7288
7321
|
|
|
7289
7322
|
// src/components/deposits/DepositsModal.tsx
|
|
7290
|
-
import { queryExecutions as queryExecutions2 } from "@unifold/core";
|
|
7323
|
+
import { queryExecutions as queryExecutions2, ActionType as ActionType2 } from "@unifold/core";
|
|
7291
7324
|
import { Fragment as Fragment3, jsx as jsx35, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
7292
7325
|
function DepositsModal({
|
|
7293
7326
|
open,
|
|
@@ -7305,7 +7338,7 @@ function DepositsModal({
|
|
|
7305
7338
|
if (!open || !userId) return;
|
|
7306
7339
|
const fetchExecutions = async () => {
|
|
7307
7340
|
try {
|
|
7308
|
-
const response = await queryExecutions2(userId, publishableKey);
|
|
7341
|
+
const response = await queryExecutions2(userId, publishableKey, ActionType2.Deposit);
|
|
7309
7342
|
const sorted = [...response.data].sort((a, b) => {
|
|
7310
7343
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
7311
7344
|
const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
@@ -7427,7 +7460,7 @@ function saveRecentToken(token) {
|
|
|
7427
7460
|
try {
|
|
7428
7461
|
const recent = getRecentTokens();
|
|
7429
7462
|
const filtered = recent.filter(
|
|
7430
|
-
(
|
|
7463
|
+
(t11) => !(t11.symbol === token.symbol && t11.chainType === token.chainType && t11.chainId === token.chainId)
|
|
7431
7464
|
);
|
|
7432
7465
|
filtered.unshift(token);
|
|
7433
7466
|
const trimmed = filtered.slice(0, MAX_RECENT_TOKENS);
|
|
@@ -7440,7 +7473,7 @@ function removeRecentToken(token) {
|
|
|
7440
7473
|
try {
|
|
7441
7474
|
const recent = getRecentTokens();
|
|
7442
7475
|
const filtered = recent.filter(
|
|
7443
|
-
(
|
|
7476
|
+
(t11) => !(t11.symbol === token.symbol && t11.chainType === token.chainType && t11.chainId === token.chainId)
|
|
7444
7477
|
);
|
|
7445
7478
|
localStorage.setItem(STORAGE_KEY, JSON.stringify(filtered));
|
|
7446
7479
|
return filtered;
|
|
@@ -7479,7 +7512,7 @@ function TokenSelectorSheet({
|
|
|
7479
7512
|
const addOption = (symbol, chainType, chainId, isRecent) => {
|
|
7480
7513
|
const key = `${symbol}-${chainType}:${chainId}`;
|
|
7481
7514
|
if (seen.has(key)) return;
|
|
7482
|
-
const tokenData = tokens.find((
|
|
7515
|
+
const tokenData = tokens.find((t11) => t11.symbol === symbol);
|
|
7483
7516
|
if (!tokenData) return;
|
|
7484
7517
|
const chainData = tokenData.chains.find(
|
|
7485
7518
|
(c) => c.chain_type === chainType && c.chain_id === chainId
|
|
@@ -7950,35 +7983,35 @@ function resolveSourceToken(supportedTokens, defaultSourceChainType, defaultSour
|
|
|
7950
7983
|
let selectedChainData;
|
|
7951
7984
|
const hasChainDefaults = defaultSourceChainType && defaultSourceChainId;
|
|
7952
7985
|
if (defaultSourceTokenAddress && hasChainDefaults) {
|
|
7953
|
-
for (const
|
|
7954
|
-
const matchingChain =
|
|
7986
|
+
for (const t11 of supportedTokens) {
|
|
7987
|
+
const matchingChain = t11.chains.find(
|
|
7955
7988
|
(c) => c.token_address.toLowerCase() === defaultSourceTokenAddress.toLowerCase() && c.chain_type === defaultSourceChainType && c.chain_id === defaultSourceChainId
|
|
7956
7989
|
);
|
|
7957
7990
|
if (matchingChain) {
|
|
7958
|
-
selectedTokenData =
|
|
7991
|
+
selectedTokenData = t11;
|
|
7959
7992
|
selectedChainData = matchingChain;
|
|
7960
7993
|
break;
|
|
7961
7994
|
}
|
|
7962
7995
|
}
|
|
7963
7996
|
}
|
|
7964
7997
|
if (!selectedTokenData && defaultSourceSymbol && hasChainDefaults) {
|
|
7965
|
-
for (const
|
|
7966
|
-
if (
|
|
7967
|
-
const matchedChain =
|
|
7998
|
+
for (const t11 of supportedTokens) {
|
|
7999
|
+
if (t11.symbol !== defaultSourceSymbol) continue;
|
|
8000
|
+
const matchedChain = t11.chains.find(
|
|
7968
8001
|
(c) => c.chain_type === defaultSourceChainType && c.chain_id === defaultSourceChainId
|
|
7969
8002
|
);
|
|
7970
8003
|
if (matchedChain) {
|
|
7971
|
-
selectedTokenData =
|
|
8004
|
+
selectedTokenData = t11;
|
|
7972
8005
|
selectedChainData = matchedChain;
|
|
7973
8006
|
break;
|
|
7974
8007
|
}
|
|
7975
8008
|
}
|
|
7976
8009
|
}
|
|
7977
8010
|
if (!selectedTokenData) {
|
|
7978
|
-
for (const
|
|
7979
|
-
if (
|
|
7980
|
-
selectedTokenData =
|
|
7981
|
-
selectedChainData =
|
|
8011
|
+
for (const t11 of supportedTokens) {
|
|
8012
|
+
if (t11.chains.length > 0) {
|
|
8013
|
+
selectedTokenData = t11;
|
|
8014
|
+
selectedChainData = t11.chains[0];
|
|
7982
8015
|
break;
|
|
7983
8016
|
}
|
|
7984
8017
|
}
|
|
@@ -8027,7 +8060,7 @@ function useDefaultSourceToken({
|
|
|
8027
8060
|
]);
|
|
8028
8061
|
useEffect16(() => {
|
|
8029
8062
|
if (!supportedTokens.length || !token) return;
|
|
8030
|
-
const currentToken = supportedTokens.find((
|
|
8063
|
+
const currentToken = supportedTokens.find((t11) => t11.symbol === token);
|
|
8031
8064
|
if (!currentToken || currentToken.chains.length === 0) return;
|
|
8032
8065
|
const isChainAvailable = chain && currentToken.chains.some((c) => {
|
|
8033
8066
|
return getChainKey(c.chain_id, c.chain_type) === chain;
|
|
@@ -8299,6 +8332,7 @@ var parseChainKey = (chainKey) => {
|
|
|
8299
8332
|
function TransferCryptoSingleInput({
|
|
8300
8333
|
userId,
|
|
8301
8334
|
publishableKey,
|
|
8335
|
+
clientSecret,
|
|
8302
8336
|
recipientAddress,
|
|
8303
8337
|
destinationChainType,
|
|
8304
8338
|
destinationChainId,
|
|
@@ -8311,7 +8345,9 @@ function TransferCryptoSingleInput({
|
|
|
8311
8345
|
onExecutionsChange,
|
|
8312
8346
|
onDepositSuccess,
|
|
8313
8347
|
onDepositError,
|
|
8314
|
-
wallets: externalWallets
|
|
8348
|
+
wallets: externalWallets,
|
|
8349
|
+
onSourceTokenChange,
|
|
8350
|
+
checkoutQuote
|
|
8315
8351
|
}) {
|
|
8316
8352
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
8317
8353
|
const isDarkMode = themeClass.includes("uf-dark");
|
|
@@ -8353,8 +8389,8 @@ function TransferCryptoSingleInput({
|
|
|
8353
8389
|
const error = walletsError?.message ?? null;
|
|
8354
8390
|
const allAvailableChains = useMemo5(() => {
|
|
8355
8391
|
const chainsMap = /* @__PURE__ */ new Map();
|
|
8356
|
-
supportedTokens.forEach((
|
|
8357
|
-
|
|
8392
|
+
supportedTokens.forEach((t11) => {
|
|
8393
|
+
t11.chains.forEach((c) => {
|
|
8358
8394
|
const comboKey = `${c.chain_type}:${c.chain_id}`;
|
|
8359
8395
|
if (!chainsMap.has(comboKey)) {
|
|
8360
8396
|
chainsMap.set(comboKey, c);
|
|
@@ -8378,18 +8414,34 @@ function TransferCryptoSingleInput({
|
|
|
8378
8414
|
} = useDepositPolling({
|
|
8379
8415
|
userId,
|
|
8380
8416
|
publishableKey,
|
|
8417
|
+
clientSecret,
|
|
8381
8418
|
depositConfirmationMode,
|
|
8382
8419
|
depositWalletId: currentWallet?.id,
|
|
8383
8420
|
enabled: true,
|
|
8384
8421
|
onDepositSuccess,
|
|
8385
8422
|
onDepositError
|
|
8386
8423
|
});
|
|
8424
|
+
useEffect17(() => {
|
|
8425
|
+
if (!onSourceTokenChange || !token || !chain || !initialSelectionDone) return;
|
|
8426
|
+
const { chainType, chainId } = parseChainKey(chain);
|
|
8427
|
+
const matchedToken = supportedTokens.find((t11) => t11.symbol === token);
|
|
8428
|
+
const matchedChain = matchedToken?.chains.find(
|
|
8429
|
+
(c) => c.chain_type === chainType && c.chain_id === chainId
|
|
8430
|
+
);
|
|
8431
|
+
onSourceTokenChange({
|
|
8432
|
+
symbol: token,
|
|
8433
|
+
chainType,
|
|
8434
|
+
chainId,
|
|
8435
|
+
tokenAddress: matchedChain?.token_address ?? "",
|
|
8436
|
+
minimumDepositAmountUsd: matchedChain?.minimum_deposit_amount_usd ?? 0
|
|
8437
|
+
});
|
|
8438
|
+
}, [token, chain, initialSelectionDone, onSourceTokenChange, supportedTokens]);
|
|
8387
8439
|
useEffect17(() => {
|
|
8388
8440
|
if (onExecutionsChange) {
|
|
8389
8441
|
onExecutionsChange(depositExecutions);
|
|
8390
8442
|
}
|
|
8391
8443
|
}, [depositExecutions, onExecutionsChange]);
|
|
8392
|
-
const selectedToken = token ? supportedTokens.find((
|
|
8444
|
+
const selectedToken = token ? supportedTokens.find((t11) => t11.symbol === token) : void 0;
|
|
8393
8445
|
const availableChainsForToken = selectedToken?.chains || [];
|
|
8394
8446
|
const currentChainFromBackend = chain ? availableChainsForToken.find((c) => {
|
|
8395
8447
|
const key = getChainKey2(c.chain_id, c.chain_type);
|
|
@@ -8403,7 +8455,7 @@ function TransferCryptoSingleInput({
|
|
|
8403
8455
|
setCopied(true);
|
|
8404
8456
|
setTimeout(() => setCopied(false), 2e3);
|
|
8405
8457
|
};
|
|
8406
|
-
const
|
|
8458
|
+
const formatProcessingTime3 = (seconds) => {
|
|
8407
8459
|
if (seconds === null) {
|
|
8408
8460
|
return t4.processingTime.lessThanMinutes.replace("{{minutes}}", "1");
|
|
8409
8461
|
}
|
|
@@ -8530,6 +8582,53 @@ function TransferCryptoSingleInput({
|
|
|
8530
8582
|
/* @__PURE__ */ jsx41("span", { children: "Retrying automatically every 5 seconds..." })
|
|
8531
8583
|
] })
|
|
8532
8584
|
] }),
|
|
8585
|
+
checkoutQuote && /* @__PURE__ */ jsxs35(
|
|
8586
|
+
"div",
|
|
8587
|
+
{
|
|
8588
|
+
className: "uf-rounded-xl uf-px-3 uf-py-2 uf-flex uf-items-center uf-justify-between",
|
|
8589
|
+
style: {
|
|
8590
|
+
backgroundColor: components.card.backgroundColor,
|
|
8591
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`,
|
|
8592
|
+
borderRadius: components.card.borderRadius
|
|
8593
|
+
},
|
|
8594
|
+
children: [
|
|
8595
|
+
/* @__PURE__ */ jsx41(
|
|
8596
|
+
"span",
|
|
8597
|
+
{
|
|
8598
|
+
className: "uf-text-xs",
|
|
8599
|
+
style: { color: components.card.subtitleColor, fontFamily: fonts.regular },
|
|
8600
|
+
children: "You send"
|
|
8601
|
+
}
|
|
8602
|
+
),
|
|
8603
|
+
/* @__PURE__ */ jsxs35(
|
|
8604
|
+
"span",
|
|
8605
|
+
{
|
|
8606
|
+
className: "uf-text-sm uf-font-semibold",
|
|
8607
|
+
style: { color: components.card.titleColor, fontFamily: fonts.semibold },
|
|
8608
|
+
children: [
|
|
8609
|
+
(Number(checkoutQuote.sourceAmount) / 10 ** checkoutQuote.sourceTokenDecimals).toFixed(
|
|
8610
|
+
Math.min(checkoutQuote.sourceTokenDecimals, 6)
|
|
8611
|
+
),
|
|
8612
|
+
" ",
|
|
8613
|
+
checkoutQuote.sourceTokenSymbol,
|
|
8614
|
+
checkoutQuote.sourceAmountUsd && /* @__PURE__ */ jsxs35(
|
|
8615
|
+
"span",
|
|
8616
|
+
{
|
|
8617
|
+
className: "uf-text-xs uf-font-normal uf-ml-1.5",
|
|
8618
|
+
style: { color: components.card.subtitleColor },
|
|
8619
|
+
children: [
|
|
8620
|
+
"($",
|
|
8621
|
+
checkoutQuote.sourceAmountUsd,
|
|
8622
|
+
")"
|
|
8623
|
+
]
|
|
8624
|
+
}
|
|
8625
|
+
)
|
|
8626
|
+
]
|
|
8627
|
+
}
|
|
8628
|
+
)
|
|
8629
|
+
]
|
|
8630
|
+
}
|
|
8631
|
+
),
|
|
8533
8632
|
/* @__PURE__ */ jsxs35("div", { className: "uf-flex uf-flex-col uf-items-center uf-pt-2", children: [
|
|
8534
8633
|
/* @__PURE__ */ jsx41("div", { className: "uf-text-xs uf-mb-2 uf-flex uf-items-center uf-gap-1", style: { color: components.card.labelColor }, children: "Intent address" }),
|
|
8535
8634
|
/* @__PURE__ */ jsx41("div", { className: "uf-shadow-lg", style: { borderRadius: components.card.borderRadius, border: `${components.card.borderWidth}px solid ${components.card.borderColor}` }, children: loading || tokensLoading || !initialSelectionDone ? (
|
|
@@ -8612,7 +8711,7 @@ function TransferCryptoSingleInput({
|
|
|
8612
8711
|
t4.processingTime.label,
|
|
8613
8712
|
":",
|
|
8614
8713
|
" ",
|
|
8615
|
-
/* @__PURE__ */ jsx41("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children:
|
|
8714
|
+
/* @__PURE__ */ jsx41("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: formatProcessingTime3(processingTime) })
|
|
8616
8715
|
] })
|
|
8617
8716
|
] }),
|
|
8618
8717
|
detailsExpanded ? /* @__PURE__ */ jsx41(ChevronUp2, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } }) : /* @__PURE__ */ jsx41(ChevronDown3, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } })
|
|
@@ -8939,8 +9038,8 @@ function TransferCryptoDoubleInput({
|
|
|
8939
9038
|
const error = walletsError?.message ?? null;
|
|
8940
9039
|
const allAvailableChains = useMemo6(() => {
|
|
8941
9040
|
const chainsMap = /* @__PURE__ */ new Map();
|
|
8942
|
-
supportedTokens.forEach((
|
|
8943
|
-
|
|
9041
|
+
supportedTokens.forEach((t11) => {
|
|
9042
|
+
t11.chains.forEach((c) => {
|
|
8944
9043
|
const comboKey = `${c.chain_type}:${c.chain_id}`;
|
|
8945
9044
|
if (!chainsMap.has(comboKey)) {
|
|
8946
9045
|
chainsMap.set(comboKey, c);
|
|
@@ -8975,7 +9074,7 @@ function TransferCryptoDoubleInput({
|
|
|
8975
9074
|
onExecutionsChange(depositExecutions);
|
|
8976
9075
|
}
|
|
8977
9076
|
}, [depositExecutions, onExecutionsChange]);
|
|
8978
|
-
const selectedToken = token ? supportedTokens.find((
|
|
9077
|
+
const selectedToken = token ? supportedTokens.find((t11) => t11.symbol === token) : void 0;
|
|
8979
9078
|
const availableChainsForToken = selectedToken?.chains || [];
|
|
8980
9079
|
const currentChainFromBackend = chain ? availableChainsForToken.find((c) => {
|
|
8981
9080
|
const key = getChainKey3(c.chain_id, c.chain_type);
|
|
@@ -8989,7 +9088,7 @@ function TransferCryptoDoubleInput({
|
|
|
8989
9088
|
setCopied(true);
|
|
8990
9089
|
setTimeout(() => setCopied(false), 2e3);
|
|
8991
9090
|
};
|
|
8992
|
-
const
|
|
9091
|
+
const formatProcessingTime3 = (seconds) => {
|
|
8993
9092
|
if (seconds === null) {
|
|
8994
9093
|
return t5.processingTime.lessThanMinutes.replace("{{minutes}}", "1");
|
|
8995
9094
|
}
|
|
@@ -9216,7 +9315,7 @@ function TransferCryptoDoubleInput({
|
|
|
9216
9315
|
t5.processingTime.label,
|
|
9217
9316
|
":",
|
|
9218
9317
|
" ",
|
|
9219
|
-
/* @__PURE__ */ jsx43("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children:
|
|
9318
|
+
/* @__PURE__ */ jsx43("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: formatProcessingTime3(processingTime) })
|
|
9220
9319
|
] })
|
|
9221
9320
|
] }),
|
|
9222
9321
|
detailsExpanded ? /* @__PURE__ */ jsx43(ChevronUp4, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } }) : /* @__PURE__ */ jsx43(ChevronDown5, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } })
|
|
@@ -9399,9 +9498,16 @@ function SelectTokenView({
|
|
|
9399
9498
|
onBack,
|
|
9400
9499
|
onClose,
|
|
9401
9500
|
onDisconnectWallet,
|
|
9402
|
-
isDisconnectingWallet = false
|
|
9501
|
+
isDisconnectingWallet = false,
|
|
9502
|
+
checkoutAmountUsd,
|
|
9503
|
+
checkoutReceivedUsd
|
|
9403
9504
|
}) {
|
|
9404
9505
|
const { colors: colors2, fonts, components } = useTheme();
|
|
9506
|
+
const isCheckout = !!checkoutAmountUsd;
|
|
9507
|
+
const headerSubtitle = isCheckout ? parseFloat(checkoutReceivedUsd || "0") > 0 ? `$${checkoutReceivedUsd} / $${checkoutAmountUsd} received` : `Amount due: $${checkoutAmountUsd}` : formatBalanceDisplay(
|
|
9508
|
+
`$${totalBalanceUsd || "0.00"}`,
|
|
9509
|
+
projectName
|
|
9510
|
+
);
|
|
9405
9511
|
return /* @__PURE__ */ jsxs38(
|
|
9406
9512
|
"div",
|
|
9407
9513
|
{
|
|
@@ -9410,11 +9516,8 @@ function SelectTokenView({
|
|
|
9410
9516
|
/* @__PURE__ */ jsx45(
|
|
9411
9517
|
DepositHeader,
|
|
9412
9518
|
{
|
|
9413
|
-
title: "Select Token",
|
|
9414
|
-
subtitle:
|
|
9415
|
-
`$${totalBalanceUsd || "0.00"}`,
|
|
9416
|
-
projectName
|
|
9417
|
-
),
|
|
9519
|
+
title: isCheckout ? "Select Token" : "Select Token",
|
|
9520
|
+
subtitle: headerSubtitle,
|
|
9418
9521
|
showBack: true,
|
|
9419
9522
|
onBack,
|
|
9420
9523
|
onClose
|
|
@@ -9645,10 +9748,19 @@ function EnterAmountView({
|
|
|
9645
9748
|
onReview,
|
|
9646
9749
|
onBack,
|
|
9647
9750
|
onClose,
|
|
9648
|
-
quickSelectMode
|
|
9751
|
+
quickSelectMode,
|
|
9752
|
+
checkoutAmountUsd,
|
|
9753
|
+
checkoutReceivedUsd
|
|
9649
9754
|
}) {
|
|
9650
9755
|
const { colors: colors2, fonts, components } = useTheme();
|
|
9756
|
+
const isCheckout = !!checkoutAmountUsd;
|
|
9651
9757
|
const balanceSubtitle = selectedBalance?.amount_usd ? `Balance: $${parseFloat(selectedBalance.amount_usd).toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} (${formatTokenAmount(selectedBalance.amount, selectedToken.decimals, selectedToken.symbol)} ${selectedToken.symbol})` : `Balance: ${formatTokenAmount(selectedBalance.amount, selectedToken.decimals, selectedToken.symbol)} ${selectedToken.symbol}`;
|
|
9758
|
+
const checkoutRemainingUsd = isCheckout ? Math.max(
|
|
9759
|
+
parseFloat(checkoutAmountUsd) - parseFloat(checkoutReceivedUsd || "0"),
|
|
9760
|
+
0
|
|
9761
|
+
).toFixed(2) : null;
|
|
9762
|
+
const headerTitle = isCheckout ? `Pay $${checkoutRemainingUsd}` : "Enter Amount";
|
|
9763
|
+
const headerSubtitle = isCheckout ? parseFloat(checkoutReceivedUsd || "0") > 0 ? `$${checkoutReceivedUsd} / $${checkoutAmountUsd} received` : null : balanceSubtitle;
|
|
9652
9764
|
const usePercentageChips = quickSelectMode === "percentage" && maxUsdAmount > 0;
|
|
9653
9765
|
const chipButtonClass = "uf-flex-1 uf-min-w-0 uf-basis-0 uf-py-2 uf-px-1 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-colors hover:uf-opacity-80 uf-whitespace-nowrap";
|
|
9654
9766
|
return /* @__PURE__ */ jsxs39(
|
|
@@ -9662,14 +9774,27 @@ function EnterAmountView({
|
|
|
9662
9774
|
/* @__PURE__ */ jsx46(
|
|
9663
9775
|
DepositHeader,
|
|
9664
9776
|
{
|
|
9665
|
-
title:
|
|
9666
|
-
subtitle:
|
|
9777
|
+
title: headerTitle,
|
|
9778
|
+
subtitle: headerSubtitle ?? void 0,
|
|
9667
9779
|
showBack: true,
|
|
9668
9780
|
onBack,
|
|
9669
9781
|
onClose
|
|
9670
9782
|
}
|
|
9671
9783
|
),
|
|
9672
|
-
walletInfoProp ? /* @__PURE__ */ jsx46("div", { className: "uf-flex uf-w-full uf-justify-center uf-mb-3", children: /* @__PURE__ */
|
|
9784
|
+
walletInfoProp ? /* @__PURE__ */ jsx46("div", { className: "uf-flex uf-w-full uf-justify-center uf-mb-3", children: /* @__PURE__ */ jsxs39("div", { className: "uf-flex uf-flex-col uf-items-center uf-gap-1", children: [
|
|
9785
|
+
/* @__PURE__ */ jsx46(WalletWithNetworkBadge, { walletInfo: walletInfoProp }),
|
|
9786
|
+
isCheckout && /* @__PURE__ */ jsx46(
|
|
9787
|
+
"span",
|
|
9788
|
+
{
|
|
9789
|
+
className: "uf-text-xs",
|
|
9790
|
+
style: {
|
|
9791
|
+
color: colors2.foregroundMuted,
|
|
9792
|
+
fontFamily: fonts.regular
|
|
9793
|
+
},
|
|
9794
|
+
children: balanceSubtitle
|
|
9795
|
+
}
|
|
9796
|
+
)
|
|
9797
|
+
] }) }) : null,
|
|
9673
9798
|
/* @__PURE__ */ jsxs39("div", { className: "uf-flex uf-min-h-0 uf-flex-1 uf-flex-col", children: [
|
|
9674
9799
|
/* @__PURE__ */ jsxs39("div", { className: "uf-min-h-0 uf-flex-1", children: [
|
|
9675
9800
|
/* @__PURE__ */ jsxs39("div", { className: "uf-text-center uf-py-8", children: [
|
|
@@ -9692,7 +9817,9 @@ function EnterAmountView({
|
|
|
9692
9817
|
inputMode: "decimal",
|
|
9693
9818
|
placeholder: "0",
|
|
9694
9819
|
value: amountUsd,
|
|
9820
|
+
readOnly: isCheckout,
|
|
9695
9821
|
onChange: (e) => {
|
|
9822
|
+
if (isCheckout) return;
|
|
9696
9823
|
const value = e.target.value;
|
|
9697
9824
|
if (value === "" || /^\d*\.?\d*$/.test(value)) {
|
|
9698
9825
|
const decimalIndex = value.indexOf(".");
|
|
@@ -9703,7 +9830,7 @@ function EnterAmountView({
|
|
|
9703
9830
|
onAmountChange(value);
|
|
9704
9831
|
}
|
|
9705
9832
|
},
|
|
9706
|
-
className:
|
|
9833
|
+
className: `uf-bg-transparent uf-outline-none uf-text-center uf-font-normal uf-w-auto uf-min-w-[60px] ${isCheckout ? "uf-cursor-default" : ""}`,
|
|
9707
9834
|
style: {
|
|
9708
9835
|
fontSize: `${Math.max(3.75 - (amountUsd || "0").length * 0.15, 2)}rem`,
|
|
9709
9836
|
color: components.input.textColor,
|
|
@@ -9725,7 +9852,7 @@ function EnterAmountView({
|
|
|
9725
9852
|
}
|
|
9726
9853
|
)
|
|
9727
9854
|
] }),
|
|
9728
|
-
/* @__PURE__ */ jsx46("div", { className: "uf-mb-4 uf-flex uf-w-full uf-min-w-0 uf-flex-nowrap uf-gap-1.5 uf-overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: usePercentageChips ? /* @__PURE__ */ jsxs39(Fragment5, { children: [
|
|
9855
|
+
!isCheckout && /* @__PURE__ */ jsx46("div", { className: "uf-mb-4 uf-flex uf-w-full uf-min-w-0 uf-flex-nowrap uf-gap-1.5 uf-overflow-x-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: usePercentageChips ? /* @__PURE__ */ jsxs39(Fragment5, { children: [
|
|
9729
9856
|
PERCENT_QUICK_AMOUNTS.map((pct) => /* @__PURE__ */ jsxs39(
|
|
9730
9857
|
"button",
|
|
9731
9858
|
{
|
|
@@ -9794,7 +9921,46 @@ function EnterAmountView({
|
|
|
9794
9921
|
}
|
|
9795
9922
|
)
|
|
9796
9923
|
] }) }),
|
|
9797
|
-
tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && /* @__PURE__ */ jsxs39(
|
|
9924
|
+
tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && (isCheckout && checkoutAmountUsd && inputUsdNum > parseFloat(checkoutAmountUsd) - parseFloat(checkoutReceivedUsd || "0") + 5e-3 ? /* @__PURE__ */ jsxs39(
|
|
9925
|
+
"div",
|
|
9926
|
+
{
|
|
9927
|
+
className: "uf-rounded-lg uf-px-3 uf-py-2 uf-mb-3 uf-text-center",
|
|
9928
|
+
style: {
|
|
9929
|
+
backgroundColor: colors2.warning + "15",
|
|
9930
|
+
border: `1px solid ${colors2.warning}30`,
|
|
9931
|
+
borderRadius: components.card.borderRadius,
|
|
9932
|
+
animation: "uf-fadeSlideIn 0.4s ease-out"
|
|
9933
|
+
},
|
|
9934
|
+
children: [
|
|
9935
|
+
/* @__PURE__ */ jsxs39(
|
|
9936
|
+
"div",
|
|
9937
|
+
{
|
|
9938
|
+
className: "uf-text-xs uf-font-medium",
|
|
9939
|
+
style: { color: colors2.warning, fontFamily: fonts.medium },
|
|
9940
|
+
children: [
|
|
9941
|
+
"Minimum for ",
|
|
9942
|
+
selectedToken.symbol,
|
|
9943
|
+
" on ",
|
|
9944
|
+
selectedToken.chain_name,
|
|
9945
|
+
" is $",
|
|
9946
|
+
tokenChainDetails.minimum_deposit_amount_usd.toFixed(2)
|
|
9947
|
+
]
|
|
9948
|
+
}
|
|
9949
|
+
),
|
|
9950
|
+
/* @__PURE__ */ jsxs39(
|
|
9951
|
+
"div",
|
|
9952
|
+
{
|
|
9953
|
+
className: "uf-text-xs uf-mt-0.5",
|
|
9954
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
9955
|
+
children: [
|
|
9956
|
+
"Amount adjusted from remaining $",
|
|
9957
|
+
(parseFloat(checkoutAmountUsd) - parseFloat(checkoutReceivedUsd || "0")).toFixed(2)
|
|
9958
|
+
]
|
|
9959
|
+
}
|
|
9960
|
+
)
|
|
9961
|
+
]
|
|
9962
|
+
}
|
|
9963
|
+
) : /* @__PURE__ */ jsxs39(
|
|
9798
9964
|
"div",
|
|
9799
9965
|
{
|
|
9800
9966
|
className: "uf-text-center uf-text-xs uf-mb-3",
|
|
@@ -9804,7 +9970,7 @@ function EnterAmountView({
|
|
|
9804
9970
|
tokenChainDetails.minimum_deposit_amount_usd.toFixed(2)
|
|
9805
9971
|
]
|
|
9806
9972
|
}
|
|
9807
|
-
),
|
|
9973
|
+
)),
|
|
9808
9974
|
inputUsdNum > 0 && /* @__PURE__ */ jsx46(Fragment5, { children: inputUsdNum > maxUsdAmount ? /* @__PURE__ */ jsx46(
|
|
9809
9975
|
"div",
|
|
9810
9976
|
{
|
|
@@ -9819,7 +9985,44 @@ function EnterAmountView({
|
|
|
9819
9985
|
style: { color: colors2.error },
|
|
9820
9986
|
children: error
|
|
9821
9987
|
}
|
|
9822
|
-
) })
|
|
9988
|
+
) }),
|
|
9989
|
+
isCheckout && selectedToken.icon_url && /* @__PURE__ */ jsxs39("div", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2 uf-py-2", children: [
|
|
9990
|
+
/* @__PURE__ */ jsxs39("div", { className: "uf-relative", children: [
|
|
9991
|
+
/* @__PURE__ */ jsx46(
|
|
9992
|
+
"img",
|
|
9993
|
+
{
|
|
9994
|
+
src: selectedToken.icon_url,
|
|
9995
|
+
alt: selectedToken.symbol,
|
|
9996
|
+
width: 20,
|
|
9997
|
+
height: 20,
|
|
9998
|
+
className: "uf-w-5 uf-h-5 uf-rounded-full"
|
|
9999
|
+
}
|
|
10000
|
+
),
|
|
10001
|
+
selectedToken.chain_icon_url && /* @__PURE__ */ jsx46(
|
|
10002
|
+
"img",
|
|
10003
|
+
{
|
|
10004
|
+
src: selectedToken.chain_icon_url,
|
|
10005
|
+
alt: selectedToken.chain_name,
|
|
10006
|
+
width: 10,
|
|
10007
|
+
height: 10,
|
|
10008
|
+
className: "uf-w-2.5 uf-h-2.5 uf-rounded-full uf-absolute -uf-bottom-0.5 -uf-right-0.5 uf-border",
|
|
10009
|
+
style: { borderColor: colors2.background }
|
|
10010
|
+
}
|
|
10011
|
+
)
|
|
10012
|
+
] }),
|
|
10013
|
+
/* @__PURE__ */ jsxs39(
|
|
10014
|
+
"span",
|
|
10015
|
+
{
|
|
10016
|
+
className: "uf-text-xs",
|
|
10017
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
10018
|
+
children: [
|
|
10019
|
+
selectedToken.symbol,
|
|
10020
|
+
" on ",
|
|
10021
|
+
selectedToken.chain_name
|
|
10022
|
+
]
|
|
10023
|
+
}
|
|
10024
|
+
)
|
|
10025
|
+
] })
|
|
9823
10026
|
] }),
|
|
9824
10027
|
/* @__PURE__ */ jsx46("div", { className: "uf-shrink-0 uf-pt-2", children: /* @__PURE__ */ jsx46(
|
|
9825
10028
|
"button",
|
|
@@ -9845,8 +10048,20 @@ function EnterAmountView({
|
|
|
9845
10048
|
}
|
|
9846
10049
|
|
|
9847
10050
|
// src/components/deposits/browser-wallets/ReviewView.tsx
|
|
9848
|
-
import { ChevronDown as ChevronDown6, ChevronUp as ChevronUp5 } from "lucide-react";
|
|
10051
|
+
import { ChevronDown as ChevronDown6, ChevronUp as ChevronUp5, Loader2 as Loader23 } from "lucide-react";
|
|
9849
10052
|
import { Fragment as Fragment6, jsx as jsx47, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
10053
|
+
var WALLET_ICONS2 = {
|
|
10054
|
+
metamask: MetamaskIcon,
|
|
10055
|
+
phantom: PhantomIcon,
|
|
10056
|
+
coinbase: CoinbaseIcon,
|
|
10057
|
+
trust: TrustIcon,
|
|
10058
|
+
rainbow: RainbowIcon,
|
|
10059
|
+
rabby: RabbyIcon,
|
|
10060
|
+
okx: OkxIcon,
|
|
10061
|
+
solflare: SolflareIcon,
|
|
10062
|
+
backpack: BackpackIcon,
|
|
10063
|
+
glow: GlowIcon
|
|
10064
|
+
};
|
|
9850
10065
|
function ReviewView({
|
|
9851
10066
|
walletInfo,
|
|
9852
10067
|
recipientAddress,
|
|
@@ -9881,30 +10096,17 @@ function ReviewView({
|
|
|
9881
10096
|
),
|
|
9882
10097
|
/* @__PURE__ */ jsxs40("div", { className: "uf-flex uf-min-h-0 uf-flex-1 uf-flex-col", children: [
|
|
9883
10098
|
/* @__PURE__ */ jsxs40("div", { className: "uf-min-h-0 uf-flex-1 uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: [
|
|
9884
|
-
/* @__PURE__ */
|
|
9885
|
-
|
|
9886
|
-
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9890
|
-
|
|
9891
|
-
|
|
9892
|
-
|
|
9893
|
-
|
|
9894
|
-
|
|
9895
|
-
),
|
|
9896
|
-
formattedTokenAmount && /* @__PURE__ */ jsxs40(
|
|
9897
|
-
"div",
|
|
9898
|
-
{
|
|
9899
|
-
className: "uf-text-sm uf-mt-2",
|
|
9900
|
-
style: { color: colors2.foregroundMuted },
|
|
9901
|
-
children: [
|
|
9902
|
-
"\u2248 ",
|
|
9903
|
-
formattedTokenAmount
|
|
9904
|
-
]
|
|
9905
|
-
}
|
|
9906
|
-
)
|
|
9907
|
-
] }),
|
|
10099
|
+
/* @__PURE__ */ jsx47("div", { className: "uf-text-center", children: /* @__PURE__ */ jsxs40(
|
|
10100
|
+
"div",
|
|
10101
|
+
{
|
|
10102
|
+
className: "uf-text-4xl uf-font-medium",
|
|
10103
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
10104
|
+
children: [
|
|
10105
|
+
"$",
|
|
10106
|
+
amountUsd || "0"
|
|
10107
|
+
]
|
|
10108
|
+
}
|
|
10109
|
+
) }),
|
|
9908
10110
|
/* @__PURE__ */ jsxs40(
|
|
9909
10111
|
"div",
|
|
9910
10112
|
{
|
|
@@ -9921,7 +10123,31 @@ function ReviewView({
|
|
|
9921
10123
|
{
|
|
9922
10124
|
className: "uf-text-sm",
|
|
9923
10125
|
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
9924
|
-
children: "
|
|
10126
|
+
children: "From"
|
|
10127
|
+
}
|
|
10128
|
+
),
|
|
10129
|
+
/* @__PURE__ */ jsxs40("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
10130
|
+
WALLET_ICONS2[walletInfo.icon] && (() => {
|
|
10131
|
+
const Icon2 = WALLET_ICONS2[walletInfo.icon];
|
|
10132
|
+
return /* @__PURE__ */ jsx47("div", { className: "uf-w-5 uf-h-5 uf-rounded-full uf-overflow-hidden uf-flex-shrink-0", children: /* @__PURE__ */ jsx47(Icon2, { size: 20, variant: "color" }) });
|
|
10133
|
+
})(),
|
|
10134
|
+
/* @__PURE__ */ jsx47(
|
|
10135
|
+
"span",
|
|
10136
|
+
{
|
|
10137
|
+
className: "uf-text-sm uf-font-medium",
|
|
10138
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
10139
|
+
children: walletInfo.name
|
|
10140
|
+
}
|
|
10141
|
+
)
|
|
10142
|
+
] })
|
|
10143
|
+
] }),
|
|
10144
|
+
/* @__PURE__ */ jsxs40("div", { className: "uf-flex uf-justify-between uf-items-center", children: [
|
|
10145
|
+
/* @__PURE__ */ jsx47(
|
|
10146
|
+
"span",
|
|
10147
|
+
{
|
|
10148
|
+
className: "uf-text-sm",
|
|
10149
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
10150
|
+
children: "You send"
|
|
9925
10151
|
}
|
|
9926
10152
|
),
|
|
9927
10153
|
/* @__PURE__ */ jsxs40("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
@@ -9933,17 +10159,12 @@ function ReviewView({
|
|
|
9933
10159
|
className: "uf-w-5 uf-h-5 uf-rounded-full"
|
|
9934
10160
|
}
|
|
9935
10161
|
),
|
|
9936
|
-
/* @__PURE__ */
|
|
10162
|
+
/* @__PURE__ */ jsx47(
|
|
9937
10163
|
"span",
|
|
9938
10164
|
{
|
|
9939
10165
|
className: "uf-text-sm uf-font-medium",
|
|
9940
10166
|
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
9941
|
-
children:
|
|
9942
|
-
walletInfo.name,
|
|
9943
|
-
" (",
|
|
9944
|
-
truncateAddress2(walletInfo.address),
|
|
9945
|
-
")"
|
|
9946
|
-
]
|
|
10167
|
+
children: formattedTokenAmount || `$${amountUsd}`
|
|
9947
10168
|
}
|
|
9948
10169
|
)
|
|
9949
10170
|
] })
|
|
@@ -10106,7 +10327,10 @@ function ReviewView({
|
|
|
10106
10327
|
borderRadius: components.button.borderRadius,
|
|
10107
10328
|
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
|
|
10108
10329
|
},
|
|
10109
|
-
children: isConfirming ? "
|
|
10330
|
+
children: isConfirming ? /* @__PURE__ */ jsxs40("span", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2", children: [
|
|
10331
|
+
/* @__PURE__ */ jsx47(Loader23, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
|
|
10332
|
+
"Confirming..."
|
|
10333
|
+
] }) : "Confirm Order"
|
|
10110
10334
|
}
|
|
10111
10335
|
) })
|
|
10112
10336
|
] })
|
|
@@ -10117,20 +10341,38 @@ function ReviewView({
|
|
|
10117
10341
|
}
|
|
10118
10342
|
|
|
10119
10343
|
// src/components/deposits/browser-wallets/ConfirmingView.tsx
|
|
10120
|
-
import { useCallback as useCallback2, useState as useState24 } from "react";
|
|
10121
|
-
import { Loader2 as
|
|
10344
|
+
import { useCallback as useCallback2, useEffect as useEffect19, useState as useState24 } from "react";
|
|
10345
|
+
import { Loader2 as Loader24, CheckCircle2, ArrowRight } from "lucide-react";
|
|
10122
10346
|
import { Fragment as Fragment7, jsx as jsx48, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
10347
|
+
var SETTLE_FALLBACK_MS = 15e3;
|
|
10123
10348
|
function ConfirmingView({
|
|
10124
10349
|
isConfirming,
|
|
10125
10350
|
onClose,
|
|
10126
10351
|
executions = [],
|
|
10127
|
-
isPolling = false
|
|
10352
|
+
isPolling = false,
|
|
10353
|
+
onNewDeposit,
|
|
10354
|
+
onDone,
|
|
10355
|
+
paymentIntentStatus,
|
|
10356
|
+
amountReceivedUsd,
|
|
10357
|
+
amountReceivedUsdAtSubmission
|
|
10128
10358
|
}) {
|
|
10129
|
-
const { colors: colors2, fonts } = useTheme();
|
|
10359
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
10130
10360
|
const [containerEl, setContainerEl] = useState24(null);
|
|
10131
10361
|
const containerCallbackRef = useCallback2((el) => {
|
|
10132
10362
|
setContainerEl(el);
|
|
10133
10363
|
}, []);
|
|
10364
|
+
const [fallbackSettled, setFallbackSettled] = useState24(false);
|
|
10365
|
+
const hasExecution = executions.length > 0;
|
|
10366
|
+
const isCheckoutMode = paymentIntentStatus != null;
|
|
10367
|
+
const isPaymentComplete = paymentIntentStatus === "succeeded";
|
|
10368
|
+
const amountChanged = amountReceivedUsdAtSubmission != null && amountReceivedUsd != null && amountReceivedUsd !== amountReceivedUsdAtSubmission;
|
|
10369
|
+
const piSettled = !isCheckoutMode || isPaymentComplete || amountChanged || fallbackSettled;
|
|
10370
|
+
useEffect19(() => {
|
|
10371
|
+
if (!hasExecution || piSettled) return;
|
|
10372
|
+
const timeout = setTimeout(() => setFallbackSettled(true), SETTLE_FALLBACK_MS);
|
|
10373
|
+
return () => clearTimeout(timeout);
|
|
10374
|
+
}, [hasExecution, piSettled]);
|
|
10375
|
+
const showButtons = hasExecution && piSettled;
|
|
10134
10376
|
return /* @__PURE__ */ jsx48(PortalContainerProvider, { value: containerEl, children: /* @__PURE__ */ jsxs41(
|
|
10135
10377
|
"div",
|
|
10136
10378
|
{
|
|
@@ -10143,13 +10385,13 @@ function ConfirmingView({
|
|
|
10143
10385
|
/* @__PURE__ */ jsx48(
|
|
10144
10386
|
DepositHeader,
|
|
10145
10387
|
{
|
|
10146
|
-
title: isConfirming ? "Confirming..." : "Processing",
|
|
10147
|
-
onClose
|
|
10388
|
+
title: isConfirming ? "Confirming..." : hasExecution && isPaymentComplete ? "Payment Complete" : hasExecution ? "Deposit Received" : "Processing",
|
|
10389
|
+
onClose: isPaymentComplete && onDone ? onDone : onClose
|
|
10148
10390
|
}
|
|
10149
10391
|
),
|
|
10150
10392
|
/* @__PURE__ */ jsx48("div", { className: "uf-flex uf-flex-1 uf-flex-col uf-items-center uf-justify-center uf-py-8", children: isConfirming ? /* @__PURE__ */ jsxs41(Fragment7, { children: [
|
|
10151
10393
|
/* @__PURE__ */ jsx48(
|
|
10152
|
-
|
|
10394
|
+
Loader24,
|
|
10153
10395
|
{
|
|
10154
10396
|
className: "uf-w-12 uf-h-12 uf-animate-spin uf-mb-4",
|
|
10155
10397
|
style: { color: colors2.primary }
|
|
@@ -10171,11 +10413,70 @@ function ConfirmingView({
|
|
|
10171
10413
|
children: "Please confirm the transaction in your wallet"
|
|
10172
10414
|
}
|
|
10173
10415
|
)
|
|
10174
|
-
] }) : /* @__PURE__ */ jsxs41(Fragment7, { children: [
|
|
10416
|
+
] }) : hasExecution ? /* @__PURE__ */ jsxs41(Fragment7, { children: [
|
|
10175
10417
|
/* @__PURE__ */ jsx48(
|
|
10176
10418
|
CheckCircle2,
|
|
10177
10419
|
{
|
|
10178
10420
|
className: "uf-w-12 uf-h-12 uf-mb-4",
|
|
10421
|
+
style: { color: "rgb(34, 197, 94)" }
|
|
10422
|
+
}
|
|
10423
|
+
),
|
|
10424
|
+
/* @__PURE__ */ jsx48(
|
|
10425
|
+
"div",
|
|
10426
|
+
{
|
|
10427
|
+
className: "uf-text-lg uf-font-medium",
|
|
10428
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
10429
|
+
children: isPaymentComplete ? "Payment Complete" : "Deposit Received"
|
|
10430
|
+
}
|
|
10431
|
+
),
|
|
10432
|
+
/* @__PURE__ */ jsx48(
|
|
10433
|
+
"div",
|
|
10434
|
+
{
|
|
10435
|
+
className: "uf-text-sm uf-mt-2 uf-text-center uf-px-6",
|
|
10436
|
+
style: { color: colors2.foregroundMuted },
|
|
10437
|
+
children: isPaymentComplete ? "Your payment has been fulfilled." : showButtons ? "Your deposit is being processed." : "Checking payment status..."
|
|
10438
|
+
}
|
|
10439
|
+
),
|
|
10440
|
+
/* @__PURE__ */ jsx48("div", { className: "uf-mt-6 uf-flex uf-flex-col uf-items-center uf-gap-3", children: !showButtons ? /* @__PURE__ */ jsx48(
|
|
10441
|
+
Loader24,
|
|
10442
|
+
{
|
|
10443
|
+
className: "uf-w-5 uf-h-5 uf-animate-spin",
|
|
10444
|
+
style: { color: colors2.foregroundMuted }
|
|
10445
|
+
}
|
|
10446
|
+
) : isPaymentComplete && onDone ? /* @__PURE__ */ jsx48(
|
|
10447
|
+
"button",
|
|
10448
|
+
{
|
|
10449
|
+
onClick: onDone,
|
|
10450
|
+
className: "uf-w-full uf-py-3 uf-px-8 uf-text-sm uf-font-medium uf-transition-opacity hover:uf-opacity-80",
|
|
10451
|
+
style: {
|
|
10452
|
+
backgroundColor: colors2.primary,
|
|
10453
|
+
color: colors2.primaryForeground,
|
|
10454
|
+
fontFamily: fonts.medium,
|
|
10455
|
+
borderRadius: components.button.borderRadius
|
|
10456
|
+
},
|
|
10457
|
+
children: "Done"
|
|
10458
|
+
}
|
|
10459
|
+
) : onNewDeposit ? /* @__PURE__ */ jsxs41(
|
|
10460
|
+
"button",
|
|
10461
|
+
{
|
|
10462
|
+
onClick: onNewDeposit,
|
|
10463
|
+
className: "uf-flex uf-items-center uf-gap-2 uf-px-5 uf-py-2.5 uf-rounded-lg uf-text-sm uf-font-medium uf-transition-opacity hover:uf-opacity-80",
|
|
10464
|
+
style: {
|
|
10465
|
+
backgroundColor: colors2.primary,
|
|
10466
|
+
color: colors2.primaryForeground,
|
|
10467
|
+
fontFamily: fonts.medium
|
|
10468
|
+
},
|
|
10469
|
+
children: [
|
|
10470
|
+
"Make another deposit",
|
|
10471
|
+
/* @__PURE__ */ jsx48(ArrowRight, { className: "uf-w-4 uf-h-4" })
|
|
10472
|
+
]
|
|
10473
|
+
}
|
|
10474
|
+
) : null })
|
|
10475
|
+
] }) : /* @__PURE__ */ jsxs41(Fragment7, { children: [
|
|
10476
|
+
/* @__PURE__ */ jsx48(
|
|
10477
|
+
Loader24,
|
|
10478
|
+
{
|
|
10479
|
+
className: "uf-w-12 uf-h-12 uf-animate-spin uf-mb-4",
|
|
10179
10480
|
style: { color: colors2.primary }
|
|
10180
10481
|
}
|
|
10181
10482
|
),
|
|
@@ -10192,7 +10493,7 @@ function ConfirmingView({
|
|
|
10192
10493
|
{
|
|
10193
10494
|
className: "uf-text-sm uf-mt-2 uf-text-center uf-px-6",
|
|
10194
10495
|
style: { color: colors2.foregroundMuted },
|
|
10195
|
-
children: "
|
|
10496
|
+
children: "Waiting for your deposit to be detected..."
|
|
10196
10497
|
}
|
|
10197
10498
|
)
|
|
10198
10499
|
] }) }),
|
|
@@ -10219,6 +10520,7 @@ function BrowserWalletModal({
|
|
|
10219
10520
|
depositWallet,
|
|
10220
10521
|
userId,
|
|
10221
10522
|
publishableKey,
|
|
10523
|
+
clientSecret,
|
|
10222
10524
|
assetCdnUrl,
|
|
10223
10525
|
projectName,
|
|
10224
10526
|
theme = "dark",
|
|
@@ -10227,7 +10529,13 @@ function BrowserWalletModal({
|
|
|
10227
10529
|
onDepositSuccess,
|
|
10228
10530
|
onDepositError,
|
|
10229
10531
|
amountQuickSelect = "percentage",
|
|
10230
|
-
onWalletDisconnect
|
|
10532
|
+
onWalletDisconnect,
|
|
10533
|
+
prefillAmountUsd,
|
|
10534
|
+
checkoutAmountUsd,
|
|
10535
|
+
checkoutReceivedUsd,
|
|
10536
|
+
onNewDeposit,
|
|
10537
|
+
onDone,
|
|
10538
|
+
paymentIntentStatus
|
|
10231
10539
|
}) {
|
|
10232
10540
|
const { colors: colors2, fonts, components } = useTheme();
|
|
10233
10541
|
const [step, setStep] = React26.useState("select-token");
|
|
@@ -10245,6 +10553,7 @@ function BrowserWalletModal({
|
|
|
10245
10553
|
const [tokenChainDetails, setTokenChainDetails] = React26.useState(null);
|
|
10246
10554
|
const [loadingTokenDetails, setLoadingTokenDetails] = React26.useState(false);
|
|
10247
10555
|
const [showTransactionDetails, setShowTransactionDetails] = React26.useState(false);
|
|
10556
|
+
const [receivedUsdAtSubmission, setReceivedUsdAtSubmission] = React26.useState(null);
|
|
10248
10557
|
const themeClass = theme === "dark" ? "uf-dark" : "";
|
|
10249
10558
|
const chainType = depositWallet.chain_type;
|
|
10250
10559
|
const recipientAddress = depositWallet.address;
|
|
@@ -10252,15 +10561,19 @@ function BrowserWalletModal({
|
|
|
10252
10561
|
const { executions: depositExecutions, isPolling } = useDepositPolling({
|
|
10253
10562
|
userId,
|
|
10254
10563
|
publishableKey,
|
|
10564
|
+
clientSecret,
|
|
10255
10565
|
enabled: open && hasSignedTransaction,
|
|
10256
10566
|
onDepositSuccess,
|
|
10257
10567
|
onDepositError
|
|
10258
10568
|
});
|
|
10569
|
+
const prevOpenRef = React26.useRef(false);
|
|
10259
10570
|
React26.useEffect(() => {
|
|
10260
|
-
|
|
10571
|
+
const wasOpen = prevOpenRef.current;
|
|
10572
|
+
prevOpenRef.current = open;
|
|
10573
|
+
if (open && !wasOpen) {
|
|
10261
10574
|
setStep("select-token");
|
|
10262
10575
|
setSelectedBalance(null);
|
|
10263
|
-
setAmountUsd("");
|
|
10576
|
+
setAmountUsd(prefillAmountUsd ?? "");
|
|
10264
10577
|
setError(null);
|
|
10265
10578
|
setIsConfirming(false);
|
|
10266
10579
|
setTokenChainDetails(null);
|
|
@@ -10268,7 +10581,15 @@ function BrowserWalletModal({
|
|
|
10268
10581
|
setHasSignedTransaction(false);
|
|
10269
10582
|
setIsDisconnectingWallet(false);
|
|
10270
10583
|
}
|
|
10271
|
-
}, [open]);
|
|
10584
|
+
}, [open, prefillAmountUsd]);
|
|
10585
|
+
React26.useEffect(() => {
|
|
10586
|
+
if (!prefillAmountUsd || !tokenChainDetails || step !== "input-amount") return;
|
|
10587
|
+
const minDeposit = tokenChainDetails.minimum_deposit_amount_usd || 0;
|
|
10588
|
+
const currentAmount = parseFloat(amountUsd) || 0;
|
|
10589
|
+
if (currentAmount > 0 && currentAmount < minDeposit) {
|
|
10590
|
+
setAmountUsd(minDeposit.toFixed(2));
|
|
10591
|
+
}
|
|
10592
|
+
}, [tokenChainDetails, step, prefillAmountUsd]);
|
|
10272
10593
|
React26.useEffect(() => {
|
|
10273
10594
|
if (step === "review") {
|
|
10274
10595
|
setShowTransactionDetails(false);
|
|
@@ -10295,7 +10616,7 @@ function BrowserWalletModal({
|
|
|
10295
10616
|
);
|
|
10296
10617
|
if (cancelled) return;
|
|
10297
10618
|
const supportedToken = response.data.find(
|
|
10298
|
-
(
|
|
10619
|
+
(t11) => t11.symbol.toLowerCase() === token.symbol.toLowerCase()
|
|
10299
10620
|
);
|
|
10300
10621
|
if (supportedToken) {
|
|
10301
10622
|
const chainDetail = supportedToken.chains.find(
|
|
@@ -10386,7 +10707,7 @@ function BrowserWalletModal({
|
|
|
10386
10707
|
setError(null);
|
|
10387
10708
|
if (step === "input-amount") {
|
|
10388
10709
|
setStep("select-token");
|
|
10389
|
-
setAmountUsd("");
|
|
10710
|
+
setAmountUsd(prefillAmountUsd ?? "");
|
|
10390
10711
|
setTokenChainDetails(null);
|
|
10391
10712
|
} else if (step === "review") {
|
|
10392
10713
|
setStep("input-amount");
|
|
@@ -10472,7 +10793,6 @@ function BrowserWalletModal({
|
|
|
10472
10793
|
}
|
|
10473
10794
|
}
|
|
10474
10795
|
setIsConfirming(true);
|
|
10475
|
-
setStep("confirming");
|
|
10476
10796
|
setError(null);
|
|
10477
10797
|
try {
|
|
10478
10798
|
let txHash;
|
|
@@ -10490,16 +10810,17 @@ function BrowserWalletModal({
|
|
|
10490
10810
|
} else {
|
|
10491
10811
|
txHash = await sendEthereumTransaction(token, tokenAmount.toString());
|
|
10492
10812
|
}
|
|
10813
|
+
setReceivedUsdAtSubmission(checkoutReceivedUsd ?? "0");
|
|
10493
10814
|
setHasSignedTransaction(true);
|
|
10494
|
-
onSuccess?.(txHash);
|
|
10495
10815
|
setIsConfirming(false);
|
|
10816
|
+
setStep("confirming");
|
|
10817
|
+
onSuccess?.(txHash);
|
|
10496
10818
|
} catch (err) {
|
|
10497
10819
|
console.error("[BrowserWalletModal] Transaction error:", err);
|
|
10498
10820
|
const errorMessage = err instanceof Error ? err.message : "Transaction failed";
|
|
10499
10821
|
setError(errorMessage);
|
|
10500
10822
|
onError?.(err instanceof Error ? err : new Error(errorMessage));
|
|
10501
10823
|
setIsConfirming(false);
|
|
10502
|
-
setStep("review");
|
|
10503
10824
|
}
|
|
10504
10825
|
};
|
|
10505
10826
|
const sendEthereumTransaction = async (token, amountStr) => {
|
|
@@ -10748,7 +11069,9 @@ function BrowserWalletModal({
|
|
|
10748
11069
|
onBack: handleClose,
|
|
10749
11070
|
onClose: handleFullClose,
|
|
10750
11071
|
onDisconnectWallet: onWalletDisconnect ? () => void handleDisconnectFromSelectToken() : void 0,
|
|
10751
|
-
isDisconnectingWallet
|
|
11072
|
+
isDisconnectingWallet,
|
|
11073
|
+
checkoutAmountUsd,
|
|
11074
|
+
checkoutReceivedUsd
|
|
10752
11075
|
}
|
|
10753
11076
|
),
|
|
10754
11077
|
step === "input-amount" && selectedToken && selectedBalance && /* @__PURE__ */ jsx49(
|
|
@@ -10769,7 +11092,9 @@ function BrowserWalletModal({
|
|
|
10769
11092
|
onReview: handleReview,
|
|
10770
11093
|
onBack: handleBack,
|
|
10771
11094
|
onClose: handleFullClose,
|
|
10772
|
-
quickSelectMode: amountQuickSelect
|
|
11095
|
+
quickSelectMode: amountQuickSelect,
|
|
11096
|
+
checkoutAmountUsd,
|
|
11097
|
+
checkoutReceivedUsd
|
|
10773
11098
|
}
|
|
10774
11099
|
),
|
|
10775
11100
|
step === "review" && selectedToken && /* @__PURE__ */ jsx49(
|
|
@@ -10798,7 +11123,12 @@ function BrowserWalletModal({
|
|
|
10798
11123
|
isConfirming,
|
|
10799
11124
|
onClose: handleFullClose,
|
|
10800
11125
|
executions: depositExecutions,
|
|
10801
|
-
isPolling
|
|
11126
|
+
isPolling,
|
|
11127
|
+
onNewDeposit,
|
|
11128
|
+
onDone,
|
|
11129
|
+
paymentIntentStatus,
|
|
11130
|
+
amountReceivedUsd: checkoutReceivedUsd,
|
|
11131
|
+
amountReceivedUsdAtSubmission: receivedUsdAtSubmission
|
|
10802
11132
|
}
|
|
10803
11133
|
)
|
|
10804
11134
|
] })
|
|
@@ -10810,9 +11140,9 @@ function BrowserWalletModal({
|
|
|
10810
11140
|
|
|
10811
11141
|
// src/components/deposits/WalletSelectionModal.tsx
|
|
10812
11142
|
import * as React27 from "react";
|
|
10813
|
-
import { ExternalLink as ExternalLink3, Loader2 as
|
|
11143
|
+
import { ExternalLink as ExternalLink3, Loader2 as Loader25 } from "lucide-react";
|
|
10814
11144
|
import { jsx as jsx50, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
10815
|
-
var
|
|
11145
|
+
var WALLET_ICONS3 = {
|
|
10816
11146
|
metamask: MetamaskIcon,
|
|
10817
11147
|
phantom: PhantomIcon,
|
|
10818
11148
|
coinbase: CoinbaseIcon,
|
|
@@ -11251,10 +11581,10 @@ function WalletSelectionModal({
|
|
|
11251
11581
|
},
|
|
11252
11582
|
children: [
|
|
11253
11583
|
/* @__PURE__ */ jsxs43("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
|
|
11254
|
-
|
|
11584
|
+
WALLET_ICONS3[wallet.id] ? /* @__PURE__ */ jsx50(
|
|
11255
11585
|
WalletIconWithNetwork,
|
|
11256
11586
|
{
|
|
11257
|
-
WalletIcon:
|
|
11587
|
+
WalletIcon: WALLET_ICONS3[wallet.id],
|
|
11258
11588
|
networks: wallet.networks,
|
|
11259
11589
|
size: 40,
|
|
11260
11590
|
className: "uf-rounded-lg"
|
|
@@ -11325,10 +11655,10 @@ function WalletSelectionModal({
|
|
|
11325
11655
|
style: { minHeight: WALLET_STEP_BODY_MIN_HEIGHT },
|
|
11326
11656
|
children: [
|
|
11327
11657
|
/* @__PURE__ */ jsxs43("div", { className: "uf-flex uf-flex-col uf-items-center uf-pb-4 uf-shrink-0", children: [
|
|
11328
|
-
/* @__PURE__ */ jsx50("div", { className: "uf-mb-2", children:
|
|
11658
|
+
/* @__PURE__ */ jsx50("div", { className: "uf-mb-2", children: WALLET_ICONS3[selectedWallet.id] ? /* @__PURE__ */ jsx50(
|
|
11329
11659
|
WalletIconWithNetwork,
|
|
11330
11660
|
{
|
|
11331
|
-
WalletIcon:
|
|
11661
|
+
WalletIcon: WALLET_ICONS3[selectedWallet.id],
|
|
11332
11662
|
networks: selectedWallet.networks,
|
|
11333
11663
|
size: 48,
|
|
11334
11664
|
className: "uf-rounded-lg"
|
|
@@ -11403,7 +11733,7 @@ function WalletSelectionModal({
|
|
|
11403
11733
|
] })
|
|
11404
11734
|
] }),
|
|
11405
11735
|
connectingNetwork === network && /* @__PURE__ */ jsx50(
|
|
11406
|
-
|
|
11736
|
+
Loader25,
|
|
11407
11737
|
{
|
|
11408
11738
|
className: "uf-w-4 uf-h-4 uf-animate-spin",
|
|
11409
11739
|
style: { color: colors2.primary }
|
|
@@ -11426,7 +11756,7 @@ function WalletSelectionModal({
|
|
|
11426
11756
|
),
|
|
11427
11757
|
step === "connecting" && /* @__PURE__ */ jsx50("div", { className: "uf-flex uf-min-h-0 uf-flex-1 uf-flex-col", children: /* @__PURE__ */ jsxs43("div", { className: "uf-flex uf-flex-1 uf-flex-col uf-items-center uf-justify-center uf-py-8", children: [
|
|
11428
11758
|
/* @__PURE__ */ jsx50(
|
|
11429
|
-
|
|
11759
|
+
Loader25,
|
|
11430
11760
|
{
|
|
11431
11761
|
className: "uf-w-12 uf-h-12 uf-animate-spin uf-mb-4",
|
|
11432
11762
|
style: { color: colors2.primary }
|
|
@@ -11548,7 +11878,7 @@ function DepositModal({
|
|
|
11548
11878
|
const [view, setView] = useState27(
|
|
11549
11879
|
effectiveInitialScreen
|
|
11550
11880
|
);
|
|
11551
|
-
const resetViewTimeoutRef =
|
|
11881
|
+
const resetViewTimeoutRef = useRef7(null);
|
|
11552
11882
|
const [cardView, setCardView] = useState27(
|
|
11553
11883
|
"amount"
|
|
11554
11884
|
);
|
|
@@ -11578,7 +11908,7 @@ function DepositModal({
|
|
|
11578
11908
|
const [resolvedTheme, setResolvedTheme] = useState27(
|
|
11579
11909
|
theme === "auto" ? "dark" : theme
|
|
11580
11910
|
);
|
|
11581
|
-
|
|
11911
|
+
useEffect22(() => {
|
|
11582
11912
|
if (theme === "auto") {
|
|
11583
11913
|
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
11584
11914
|
setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
@@ -11607,11 +11937,11 @@ function DepositModal({
|
|
|
11607
11937
|
chainType: destinationChainType,
|
|
11608
11938
|
enabled: open
|
|
11609
11939
|
});
|
|
11610
|
-
|
|
11940
|
+
useEffect22(() => {
|
|
11611
11941
|
if (view !== "tracker" || !userId) return;
|
|
11612
11942
|
const fetchExecutions = async () => {
|
|
11613
11943
|
try {
|
|
11614
|
-
const response = await queryExecutions3(userId, publishableKey);
|
|
11944
|
+
const response = await queryExecutions3(userId, publishableKey, ActionType3.Deposit);
|
|
11615
11945
|
const sorted = [...response.data].sort((a, b) => {
|
|
11616
11946
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
11617
11947
|
const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
@@ -11628,7 +11958,7 @@ function DepositModal({
|
|
|
11628
11958
|
clearInterval(pollInterval);
|
|
11629
11959
|
};
|
|
11630
11960
|
}, [view, userId, publishableKey]);
|
|
11631
|
-
|
|
11961
|
+
useEffect22(() => {
|
|
11632
11962
|
if (view !== "tracker") {
|
|
11633
11963
|
setSelectedExecution(null);
|
|
11634
11964
|
}
|
|
@@ -11738,7 +12068,7 @@ function DepositModal({
|
|
|
11738
12068
|
setBrowserWalletInfo(null);
|
|
11739
12069
|
setSelectedExecution(null);
|
|
11740
12070
|
}, [open, effectiveInitialScreen]);
|
|
11741
|
-
|
|
12071
|
+
useEffect22(
|
|
11742
12072
|
() => () => {
|
|
11743
12073
|
if (resetViewTimeoutRef.current) {
|
|
11744
12074
|
clearTimeout(resetViewTimeoutRef.current);
|
|
@@ -12130,9 +12460,2755 @@ function DepositModal({
|
|
|
12130
12460
|
}
|
|
12131
12461
|
) });
|
|
12132
12462
|
}
|
|
12463
|
+
|
|
12464
|
+
// src/components/checkout/CheckoutModal.tsx
|
|
12465
|
+
import {
|
|
12466
|
+
useState as useState28,
|
|
12467
|
+
useEffect as useEffect23,
|
|
12468
|
+
useLayoutEffect as useLayoutEffect3,
|
|
12469
|
+
useCallback as useCallback5,
|
|
12470
|
+
useRef as useRef8,
|
|
12471
|
+
useMemo as useMemo10
|
|
12472
|
+
} from "react";
|
|
12473
|
+
import { AlertTriangle as AlertTriangle2, ChevronRight as ChevronRight12 } from "lucide-react";
|
|
12474
|
+
|
|
12475
|
+
// src/hooks/use-payment-intent.ts
|
|
12476
|
+
import { useQuery as useQuery9 } from "@tanstack/react-query";
|
|
12477
|
+
import { retrievePaymentIntent } from "@unifold/core";
|
|
12478
|
+
function usePaymentIntent(params) {
|
|
12479
|
+
const {
|
|
12480
|
+
clientSecret,
|
|
12481
|
+
publishableKey,
|
|
12482
|
+
enabled = true,
|
|
12483
|
+
pollingInterval = 5e3
|
|
12484
|
+
} = params;
|
|
12485
|
+
return useQuery9({
|
|
12486
|
+
queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
|
|
12487
|
+
queryFn: () => retrievePaymentIntent(clientSecret, publishableKey),
|
|
12488
|
+
enabled: enabled && !!clientSecret && !!publishableKey,
|
|
12489
|
+
staleTime: 0,
|
|
12490
|
+
refetchInterval: pollingInterval || false,
|
|
12491
|
+
refetchOnWindowFocus: true,
|
|
12492
|
+
retry: 3,
|
|
12493
|
+
retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
|
|
12494
|
+
});
|
|
12495
|
+
}
|
|
12496
|
+
|
|
12497
|
+
// src/hooks/use-deposit-quote.ts
|
|
12498
|
+
import { useQuery as useQuery10 } from "@tanstack/react-query";
|
|
12499
|
+
import {
|
|
12500
|
+
getDepositQuote
|
|
12501
|
+
} from "@unifold/core";
|
|
12502
|
+
function useDepositQuote(params) {
|
|
12503
|
+
const {
|
|
12504
|
+
publishableKey,
|
|
12505
|
+
sourceChainType,
|
|
12506
|
+
sourceChainId,
|
|
12507
|
+
sourceTokenAddress,
|
|
12508
|
+
destinationAmount,
|
|
12509
|
+
destinationChainType,
|
|
12510
|
+
destinationChainId,
|
|
12511
|
+
destinationTokenAddress,
|
|
12512
|
+
enabled = true
|
|
12513
|
+
} = params;
|
|
12514
|
+
const request = {
|
|
12515
|
+
source_chain_type: sourceChainType,
|
|
12516
|
+
source_chain_id: sourceChainId,
|
|
12517
|
+
source_token_address: sourceTokenAddress,
|
|
12518
|
+
destination_amount: destinationAmount,
|
|
12519
|
+
destination_chain_type: destinationChainType,
|
|
12520
|
+
destination_chain_id: destinationChainId,
|
|
12521
|
+
destination_token_address: destinationTokenAddress
|
|
12522
|
+
};
|
|
12523
|
+
return useQuery10({
|
|
12524
|
+
queryKey: [
|
|
12525
|
+
"unifold",
|
|
12526
|
+
"depositQuote",
|
|
12527
|
+
sourceChainType,
|
|
12528
|
+
sourceChainId,
|
|
12529
|
+
sourceTokenAddress,
|
|
12530
|
+
destinationAmount,
|
|
12531
|
+
destinationChainType,
|
|
12532
|
+
destinationChainId,
|
|
12533
|
+
destinationTokenAddress,
|
|
12534
|
+
publishableKey
|
|
12535
|
+
],
|
|
12536
|
+
queryFn: () => getDepositQuote(request, publishableKey),
|
|
12537
|
+
enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
|
|
12538
|
+
staleTime: 6e4,
|
|
12539
|
+
gcTime: 5 * 6e4,
|
|
12540
|
+
refetchOnWindowFocus: false,
|
|
12541
|
+
retry: 2,
|
|
12542
|
+
retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 5e3)
|
|
12543
|
+
});
|
|
12544
|
+
}
|
|
12545
|
+
|
|
12546
|
+
// src/components/checkout/CheckoutModal.tsx
|
|
12547
|
+
import { Fragment as Fragment10, jsx as jsx52, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
12548
|
+
function mapDepositAddressesToWallets(depositAddresses, pi) {
|
|
12549
|
+
return depositAddresses.map((da, idx) => ({
|
|
12550
|
+
id: da.id,
|
|
12551
|
+
chain_type: da.chain_type,
|
|
12552
|
+
address_type: da.address_type,
|
|
12553
|
+
address: da.address,
|
|
12554
|
+
destination_chain_type: pi.destination_chain_type,
|
|
12555
|
+
destination_chain_id: pi.destination_chain_id,
|
|
12556
|
+
destination_token_address: pi.destination_token_address,
|
|
12557
|
+
recipient_address: pi.recipient_address,
|
|
12558
|
+
is_primary: idx === 0
|
|
12559
|
+
}));
|
|
12560
|
+
}
|
|
12561
|
+
function SkeletonButton2() {
|
|
12562
|
+
return /* @__PURE__ */ jsxs45("div", { className: "uf-w-full uf-bg-secondary uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-justify-between uf-animate-pulse", children: [
|
|
12563
|
+
/* @__PURE__ */ jsxs45("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
|
|
12564
|
+
/* @__PURE__ */ jsx52("div", { className: "uf-bg-muted uf-rounded-lg uf-w-9 uf-h-9" }),
|
|
12565
|
+
/* @__PURE__ */ jsxs45("div", { className: "uf-space-y-1.5", children: [
|
|
12566
|
+
/* @__PURE__ */ jsx52("div", { className: "uf-h-3.5 uf-w-24 uf-bg-muted uf-rounded" }),
|
|
12567
|
+
/* @__PURE__ */ jsx52("div", { className: "uf-h-3 uf-w-32 uf-bg-muted uf-rounded" })
|
|
12568
|
+
] })
|
|
12569
|
+
] }),
|
|
12570
|
+
/* @__PURE__ */ jsx52("div", { className: "uf-flex uf-items-center uf-gap-2", children: /* @__PURE__ */ jsx52(ChevronRight12, { className: "uf-w-4 uf-h-4 uf-text-muted" }) })
|
|
12571
|
+
] });
|
|
12572
|
+
}
|
|
12573
|
+
function CheckoutModal({
|
|
12574
|
+
open,
|
|
12575
|
+
onOpenChange,
|
|
12576
|
+
clientSecret,
|
|
12577
|
+
publishableKey,
|
|
12578
|
+
modalTitle,
|
|
12579
|
+
enableConnectWallet = false,
|
|
12580
|
+
theme = "dark",
|
|
12581
|
+
onCheckoutSuccess,
|
|
12582
|
+
onCheckoutError
|
|
12583
|
+
}) {
|
|
12584
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
12585
|
+
const [view, setView] = useState28("main");
|
|
12586
|
+
const resetViewTimeoutRef = useRef8(
|
|
12587
|
+
null
|
|
12588
|
+
);
|
|
12589
|
+
const [browserWalletModalOpen, setBrowserWalletModalOpen] = useState28(false);
|
|
12590
|
+
const [browserWalletInfo, setBrowserWalletInfo] = useState28(null);
|
|
12591
|
+
const [walletSelectionModalOpen, setWalletSelectionModalOpen] = useState28(false);
|
|
12592
|
+
const [browserWalletChainType, setBrowserWalletChainType] = useState28(() => getStoredWalletChainType());
|
|
12593
|
+
const isMobileView = useIsMobileViewport();
|
|
12594
|
+
const [resolvedTheme, setResolvedTheme] = useState28(
|
|
12595
|
+
theme === "auto" ? "dark" : theme
|
|
12596
|
+
);
|
|
12597
|
+
useEffect23(() => {
|
|
12598
|
+
if (theme === "auto") {
|
|
12599
|
+
const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
|
|
12600
|
+
setResolvedTheme(mediaQuery.matches ? "dark" : "light");
|
|
12601
|
+
const handler = (e) => {
|
|
12602
|
+
setResolvedTheme(e.matches ? "dark" : "light");
|
|
12603
|
+
};
|
|
12604
|
+
mediaQuery.addEventListener("change", handler);
|
|
12605
|
+
return () => mediaQuery.removeEventListener("change", handler);
|
|
12606
|
+
} else {
|
|
12607
|
+
setResolvedTheme(theme);
|
|
12608
|
+
}
|
|
12609
|
+
}, [theme]);
|
|
12610
|
+
const themeClass = resolvedTheme === "dark" ? "uf-dark" : "";
|
|
12611
|
+
const {
|
|
12612
|
+
data: paymentIntent,
|
|
12613
|
+
isLoading: piLoading,
|
|
12614
|
+
error: piError
|
|
12615
|
+
} = usePaymentIntent({
|
|
12616
|
+
clientSecret,
|
|
12617
|
+
publishableKey,
|
|
12618
|
+
enabled: open && !!clientSecret,
|
|
12619
|
+
pollingInterval: 5e3
|
|
12620
|
+
});
|
|
12621
|
+
const { projectConfig } = useProjectConfig({
|
|
12622
|
+
publishableKey,
|
|
12623
|
+
enabled: open
|
|
12624
|
+
});
|
|
12625
|
+
const prevStatusRef = useRef8(null);
|
|
12626
|
+
useEffect23(() => {
|
|
12627
|
+
if (!paymentIntent) return;
|
|
12628
|
+
const prev = prevStatusRef.current;
|
|
12629
|
+
prevStatusRef.current = paymentIntent.status;
|
|
12630
|
+
if (prev && prev !== paymentIntent.status && paymentIntent.status === "succeeded") {
|
|
12631
|
+
if (!browserWalletModalOpen) {
|
|
12632
|
+
setView("main");
|
|
12633
|
+
}
|
|
12634
|
+
onCheckoutSuccess?.({
|
|
12635
|
+
paymentIntentId: paymentIntent.id,
|
|
12636
|
+
status: paymentIntent.status
|
|
12637
|
+
});
|
|
12638
|
+
}
|
|
12639
|
+
}, [paymentIntent, onCheckoutSuccess, browserWalletModalOpen]);
|
|
12640
|
+
const wallets = useMemo10(() => {
|
|
12641
|
+
if (!paymentIntent) return [];
|
|
12642
|
+
return mapDepositAddressesToWallets(
|
|
12643
|
+
paymentIntent.deposit_addresses,
|
|
12644
|
+
paymentIntent
|
|
12645
|
+
);
|
|
12646
|
+
}, [paymentIntent]);
|
|
12647
|
+
const formatCryptoAmount = useMemo10(() => {
|
|
12648
|
+
if (!paymentIntent) return (_) => "";
|
|
12649
|
+
const decimals = paymentIntent.destination_token_decimals ?? 6;
|
|
12650
|
+
const symbol = paymentIntent.currency.toUpperCase();
|
|
12651
|
+
return (baseUnits) => {
|
|
12652
|
+
const num = Number(baseUnits) / 10 ** decimals;
|
|
12653
|
+
const formatted = num % 1 === 0 ? num.toFixed(0) : num.toFixed(2);
|
|
12654
|
+
return `${formatted} ${symbol}`;
|
|
12655
|
+
};
|
|
12656
|
+
}, [paymentIntent]);
|
|
12657
|
+
const remainingAmountUsd = useMemo10(() => {
|
|
12658
|
+
if (!paymentIntent) return void 0;
|
|
12659
|
+
const total = parseFloat(paymentIntent.amount_usd);
|
|
12660
|
+
const received = parseFloat(paymentIntent.amount_received_usd);
|
|
12661
|
+
if (isNaN(total) || isNaN(received)) return paymentIntent.amount_usd;
|
|
12662
|
+
const remaining = total - received;
|
|
12663
|
+
return remaining > 0 ? remaining.toFixed(2) : "0.00";
|
|
12664
|
+
}, [paymentIntent]);
|
|
12665
|
+
const remainingCrypto = useMemo10(() => {
|
|
12666
|
+
if (!paymentIntent) return void 0;
|
|
12667
|
+
const total = BigInt(paymentIntent.amount);
|
|
12668
|
+
const received = BigInt(paymentIntent.amount_received);
|
|
12669
|
+
const remaining = total - received;
|
|
12670
|
+
return remaining > 0n ? remaining.toString() : "0";
|
|
12671
|
+
}, [paymentIntent]);
|
|
12672
|
+
const [selectedSource, setSelectedSource] = useState28(null);
|
|
12673
|
+
const quoteDestinationAmount = useMemo10(() => {
|
|
12674
|
+
if (!paymentIntent || !selectedSource) return "0";
|
|
12675
|
+
const remaining = BigInt(paymentIntent.amount) - BigInt(paymentIntent.amount_received);
|
|
12676
|
+
const totalBaseUnits = Number(paymentIntent.amount);
|
|
12677
|
+
const totalUsd = parseFloat(paymentIntent.amount_usd);
|
|
12678
|
+
const baseUnitsPerUsd = totalUsd > 0 ? totalBaseUnits / totalUsd : 0;
|
|
12679
|
+
const minUsd = Math.max(selectedSource.minimumDepositAmountUsd, 3);
|
|
12680
|
+
const minDepositBaseUnits = BigInt(Math.ceil(minUsd * baseUnitsPerUsd));
|
|
12681
|
+
const effective = remaining > minDepositBaseUnits ? remaining : minDepositBaseUnits;
|
|
12682
|
+
return effective > 0n ? effective.toString() : "0";
|
|
12683
|
+
}, [paymentIntent, selectedSource]);
|
|
12684
|
+
const { data: sourceQuote } = useDepositQuote({
|
|
12685
|
+
publishableKey,
|
|
12686
|
+
sourceChainType: selectedSource?.chainType ?? "",
|
|
12687
|
+
sourceChainId: selectedSource?.chainId ?? "",
|
|
12688
|
+
sourceTokenAddress: selectedSource?.tokenAddress ?? "",
|
|
12689
|
+
destinationAmount: quoteDestinationAmount,
|
|
12690
|
+
destinationChainType: paymentIntent?.destination_chain_type ?? "",
|
|
12691
|
+
destinationChainId: paymentIntent?.destination_chain_id ?? "",
|
|
12692
|
+
destinationTokenAddress: paymentIntent?.destination_token_address ?? "",
|
|
12693
|
+
enabled: open && view === "transfer" && !!paymentIntent && !!selectedSource && quoteDestinationAmount !== "0"
|
|
12694
|
+
});
|
|
12695
|
+
const handleBrowserWalletClick = useCallback5(
|
|
12696
|
+
(walletInfo) => {
|
|
12697
|
+
const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
|
|
12698
|
+
setStoredWalletChainType(walletChainType);
|
|
12699
|
+
setBrowserWalletChainType(walletChainType);
|
|
12700
|
+
const matchingDepositWallet = wallets.find(
|
|
12701
|
+
(w) => w.chain_type === walletChainType
|
|
12702
|
+
);
|
|
12703
|
+
if (!matchingDepositWallet) {
|
|
12704
|
+
onCheckoutError?.({
|
|
12705
|
+
message: `Unable to pay from ${walletChainType}. Please try a different wallet.`,
|
|
12706
|
+
code: "NO_DEPOSIT_ADDRESS"
|
|
12707
|
+
});
|
|
12708
|
+
return;
|
|
12709
|
+
}
|
|
12710
|
+
setBrowserWalletInfo({
|
|
12711
|
+
...walletInfo,
|
|
12712
|
+
depositWallet: matchingDepositWallet
|
|
12713
|
+
});
|
|
12714
|
+
setBrowserWalletModalOpen(true);
|
|
12715
|
+
},
|
|
12716
|
+
[wallets, onCheckoutError]
|
|
12717
|
+
);
|
|
12718
|
+
const handleWalletConnectClick = useCallback5(() => {
|
|
12719
|
+
setWalletSelectionModalOpen(true);
|
|
12720
|
+
}, []);
|
|
12721
|
+
const handleWalletConnected = useCallback5(
|
|
12722
|
+
(walletInfo) => {
|
|
12723
|
+
const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
|
|
12724
|
+
setStoredWalletChainType(walletChainType);
|
|
12725
|
+
setBrowserWalletChainType(walletChainType);
|
|
12726
|
+
const matchingDepositWallet = wallets.find(
|
|
12727
|
+
(w) => w.chain_type === walletChainType
|
|
12728
|
+
);
|
|
12729
|
+
if (!matchingDepositWallet) {
|
|
12730
|
+
onCheckoutError?.({
|
|
12731
|
+
message: `Unable to pay from ${walletChainType}. Please try a different wallet.`,
|
|
12732
|
+
code: "NO_DEPOSIT_ADDRESS"
|
|
12733
|
+
});
|
|
12734
|
+
setWalletSelectionModalOpen(false);
|
|
12735
|
+
return;
|
|
12736
|
+
}
|
|
12737
|
+
setBrowserWalletInfo({
|
|
12738
|
+
...walletInfo,
|
|
12739
|
+
depositWallet: matchingDepositWallet
|
|
12740
|
+
});
|
|
12741
|
+
setWalletSelectionModalOpen(false);
|
|
12742
|
+
setBrowserWalletModalOpen(true);
|
|
12743
|
+
},
|
|
12744
|
+
[wallets, onCheckoutError]
|
|
12745
|
+
);
|
|
12746
|
+
const handleWalletDisconnect = useCallback5(() => {
|
|
12747
|
+
setUserDisconnectedWallet(true);
|
|
12748
|
+
clearStoredWalletChainType();
|
|
12749
|
+
setBrowserWalletChainType(void 0);
|
|
12750
|
+
setBrowserWalletInfo(null);
|
|
12751
|
+
setBrowserWalletModalOpen(false);
|
|
12752
|
+
}, []);
|
|
12753
|
+
const handleClose = useCallback5(() => {
|
|
12754
|
+
onOpenChange(false);
|
|
12755
|
+
if (resetViewTimeoutRef.current) {
|
|
12756
|
+
clearTimeout(resetViewTimeoutRef.current);
|
|
12757
|
+
}
|
|
12758
|
+
resetViewTimeoutRef.current = setTimeout(() => {
|
|
12759
|
+
setView("main");
|
|
12760
|
+
setBrowserWalletInfo(null);
|
|
12761
|
+
resetViewTimeoutRef.current = null;
|
|
12762
|
+
}, 200);
|
|
12763
|
+
}, [onOpenChange]);
|
|
12764
|
+
useLayoutEffect3(() => {
|
|
12765
|
+
if (!open) return;
|
|
12766
|
+
if (resetViewTimeoutRef.current) {
|
|
12767
|
+
clearTimeout(resetViewTimeoutRef.current);
|
|
12768
|
+
resetViewTimeoutRef.current = null;
|
|
12769
|
+
}
|
|
12770
|
+
setView("main");
|
|
12771
|
+
setBrowserWalletInfo(null);
|
|
12772
|
+
}, [open]);
|
|
12773
|
+
useEffect23(
|
|
12774
|
+
() => () => {
|
|
12775
|
+
if (resetViewTimeoutRef.current) {
|
|
12776
|
+
clearTimeout(resetViewTimeoutRef.current);
|
|
12777
|
+
}
|
|
12778
|
+
},
|
|
12779
|
+
[]
|
|
12780
|
+
);
|
|
12781
|
+
const handleBack = useCallback5(() => {
|
|
12782
|
+
setView("main");
|
|
12783
|
+
}, []);
|
|
12784
|
+
const poweredByFooter = /* @__PURE__ */ jsx52("div", { className: "uf-pt-3", children: /* @__PURE__ */ jsx52(
|
|
12785
|
+
PoweredByUnifold,
|
|
12786
|
+
{
|
|
12787
|
+
color: colors2.foregroundMuted,
|
|
12788
|
+
className: "uf-flex uf-justify-center uf-shrink-0"
|
|
12789
|
+
}
|
|
12790
|
+
) });
|
|
12791
|
+
const progressSection = paymentIntent ? (() => {
|
|
12792
|
+
const received = parseFloat(paymentIntent.amount_received_usd);
|
|
12793
|
+
const total = parseFloat(paymentIntent.amount_usd);
|
|
12794
|
+
const remaining = Math.max(total - received, 0);
|
|
12795
|
+
const pct = total > 0 ? Math.min(received / total * 100, 100) : 0;
|
|
12796
|
+
const hasPartial = received > 0;
|
|
12797
|
+
const amountStr = paymentIntent.amount_usd;
|
|
12798
|
+
const dynamicFontSize = `${Math.max(3.75 - amountStr.length * 0.15, 2)}rem`;
|
|
12799
|
+
return /* @__PURE__ */ jsxs45("div", { className: "uf-text-center uf-py-2 uf-space-y-1", children: [
|
|
12800
|
+
paymentIntent.description && /* @__PURE__ */ jsx52(
|
|
12801
|
+
"div",
|
|
12802
|
+
{
|
|
12803
|
+
className: "uf-text-xs",
|
|
12804
|
+
style: {
|
|
12805
|
+
color: colors2.foregroundMuted,
|
|
12806
|
+
fontFamily: fonts.regular
|
|
12807
|
+
},
|
|
12808
|
+
children: paymentIntent.description
|
|
12809
|
+
}
|
|
12810
|
+
),
|
|
12811
|
+
/* @__PURE__ */ jsxs45("div", { className: "uf-flex uf-items-center uf-justify-center", children: [
|
|
12812
|
+
/* @__PURE__ */ jsx52(
|
|
12813
|
+
"span",
|
|
12814
|
+
{
|
|
12815
|
+
className: "uf-mr-1",
|
|
12816
|
+
style: {
|
|
12817
|
+
fontSize: `calc(${dynamicFontSize} * 0.6)`,
|
|
12818
|
+
color: colors2.foregroundMuted,
|
|
12819
|
+
fontFamily: fonts.regular
|
|
12820
|
+
},
|
|
12821
|
+
children: "$"
|
|
12822
|
+
}
|
|
12823
|
+
),
|
|
12824
|
+
/* @__PURE__ */ jsx52(
|
|
12825
|
+
"span",
|
|
12826
|
+
{
|
|
12827
|
+
style: {
|
|
12828
|
+
fontSize: dynamicFontSize,
|
|
12829
|
+
color: colors2.foreground,
|
|
12830
|
+
fontFamily: fonts.regular,
|
|
12831
|
+
lineHeight: 1.1
|
|
12832
|
+
},
|
|
12833
|
+
children: amountStr
|
|
12834
|
+
}
|
|
12835
|
+
)
|
|
12836
|
+
] }),
|
|
12837
|
+
/* @__PURE__ */ jsx52(
|
|
12838
|
+
"div",
|
|
12839
|
+
{
|
|
12840
|
+
className: "uf-text-xs",
|
|
12841
|
+
style: {
|
|
12842
|
+
color: colors2.foregroundMuted,
|
|
12843
|
+
fontFamily: fonts.regular
|
|
12844
|
+
},
|
|
12845
|
+
children: paymentIntent.currency.toUpperCase()
|
|
12846
|
+
}
|
|
12847
|
+
),
|
|
12848
|
+
hasPartial && /* @__PURE__ */ jsxs45("div", { className: "uf-pt-2 uf-space-y-1.5", children: [
|
|
12849
|
+
/* @__PURE__ */ jsx52(
|
|
12850
|
+
"div",
|
|
12851
|
+
{
|
|
12852
|
+
className: "uf-w-full uf-h-1.5 uf-rounded-full uf-overflow-hidden",
|
|
12853
|
+
style: { backgroundColor: colors2.border },
|
|
12854
|
+
children: /* @__PURE__ */ jsx52(
|
|
12855
|
+
"div",
|
|
12856
|
+
{
|
|
12857
|
+
className: "uf-h-full uf-rounded-full uf-transition-all uf-duration-500",
|
|
12858
|
+
style: {
|
|
12859
|
+
width: `${pct}%`,
|
|
12860
|
+
backgroundColor: paymentIntent.status === "succeeded" ? "rgb(34, 197, 94)" : colors2.primary
|
|
12861
|
+
}
|
|
12862
|
+
}
|
|
12863
|
+
)
|
|
12864
|
+
}
|
|
12865
|
+
),
|
|
12866
|
+
/* @__PURE__ */ jsxs45(
|
|
12867
|
+
"div",
|
|
12868
|
+
{
|
|
12869
|
+
className: "uf-text-xs",
|
|
12870
|
+
style: {
|
|
12871
|
+
color: colors2.foregroundMuted,
|
|
12872
|
+
fontFamily: fonts.regular
|
|
12873
|
+
},
|
|
12874
|
+
children: [
|
|
12875
|
+
"$",
|
|
12876
|
+
paymentIntent.amount_received_usd,
|
|
12877
|
+
" / $",
|
|
12878
|
+
amountStr,
|
|
12879
|
+
" received",
|
|
12880
|
+
remaining > 0 && paymentIntent.status !== "succeeded" && /* @__PURE__ */ jsxs45("span", { style: { color: colors2.foreground, fontFamily: fonts.medium }, children: [
|
|
12881
|
+
" ",
|
|
12882
|
+
"\xB7 $",
|
|
12883
|
+
remaining.toFixed(2),
|
|
12884
|
+
" remaining"
|
|
12885
|
+
] })
|
|
12886
|
+
]
|
|
12887
|
+
}
|
|
12888
|
+
)
|
|
12889
|
+
] }),
|
|
12890
|
+
paymentIntent.status !== "requires_payment" && /* @__PURE__ */ jsx52("div", { className: "uf-pt-1", children: /* @__PURE__ */ jsx52(
|
|
12891
|
+
"span",
|
|
12892
|
+
{
|
|
12893
|
+
className: "uf-text-xs uf-font-medium uf-px-2.5 uf-py-1 uf-rounded-full uf-inline-block",
|
|
12894
|
+
style: {
|
|
12895
|
+
backgroundColor: paymentIntent.status === "succeeded" ? "rgba(34, 197, 94, 0.15)" : paymentIntent.status === "processing" ? "rgba(59, 130, 246, 0.15)" : "rgba(239, 68, 68, 0.15)",
|
|
12896
|
+
color: paymentIntent.status === "succeeded" ? "rgb(34, 197, 94)" : paymentIntent.status === "processing" ? "rgb(59, 130, 246)" : "rgb(239, 68, 68)",
|
|
12897
|
+
fontFamily: fonts.medium
|
|
12898
|
+
},
|
|
12899
|
+
children: paymentIntent.status === "succeeded" ? "Payment Complete" : paymentIntent.status === "processing" ? "Partial Payment Received" : paymentIntent.status === "canceled" ? "Canceled" : paymentIntent.status === "expired" ? "Expired" : paymentIntent.status
|
|
12900
|
+
}
|
|
12901
|
+
) })
|
|
12902
|
+
] });
|
|
12903
|
+
})() : null;
|
|
12904
|
+
return /* @__PURE__ */ jsx52(PortalContainerProvider, { value: null, children: /* @__PURE__ */ jsxs45(Dialog, { open, onOpenChange: handleClose, modal: true, children: [
|
|
12905
|
+
/* @__PURE__ */ jsx52(
|
|
12906
|
+
DialogContent,
|
|
12907
|
+
{
|
|
12908
|
+
className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[60vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${themeClass}`,
|
|
12909
|
+
style: { backgroundColor: colors2.background },
|
|
12910
|
+
onPointerDownOutside: (e) => e.preventDefault(),
|
|
12911
|
+
onInteractOutside: (e) => e.preventDefault(),
|
|
12912
|
+
children: /* @__PURE__ */ jsx52(ThemeStyleInjector, { children: view === "main" ? /* @__PURE__ */ jsxs45(Fragment10, { children: [
|
|
12913
|
+
/* @__PURE__ */ jsx52(
|
|
12914
|
+
DepositHeader,
|
|
12915
|
+
{
|
|
12916
|
+
title: modalTitle || "Checkout",
|
|
12917
|
+
showClose: true,
|
|
12918
|
+
onClose: handleClose
|
|
12919
|
+
}
|
|
12920
|
+
),
|
|
12921
|
+
/* @__PURE__ */ jsxs45("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
12922
|
+
piLoading ? /* @__PURE__ */ jsxs45("div", { className: "uf-space-y-3", children: [
|
|
12923
|
+
/* @__PURE__ */ jsx52(
|
|
12924
|
+
"div",
|
|
12925
|
+
{
|
|
12926
|
+
className: "uf-rounded-xl uf-p-4 uf-animate-pulse",
|
|
12927
|
+
style: {
|
|
12928
|
+
backgroundColor: components.card.backgroundColor,
|
|
12929
|
+
borderRadius: components.card.borderRadius,
|
|
12930
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
12931
|
+
},
|
|
12932
|
+
children: /* @__PURE__ */ jsxs45("div", { className: "uf-flex uf-flex-col uf-items-center uf-gap-2", children: [
|
|
12933
|
+
/* @__PURE__ */ jsx52(
|
|
12934
|
+
"div",
|
|
12935
|
+
{
|
|
12936
|
+
className: "uf-h-8 uf-w-24 uf-rounded",
|
|
12937
|
+
style: {
|
|
12938
|
+
backgroundColor: components.card.borderColor
|
|
12939
|
+
}
|
|
12940
|
+
}
|
|
12941
|
+
),
|
|
12942
|
+
/* @__PURE__ */ jsx52(
|
|
12943
|
+
"div",
|
|
12944
|
+
{
|
|
12945
|
+
className: "uf-h-4 uf-w-16 uf-rounded",
|
|
12946
|
+
style: {
|
|
12947
|
+
backgroundColor: components.card.borderColor
|
|
12948
|
+
}
|
|
12949
|
+
}
|
|
12950
|
+
)
|
|
12951
|
+
] })
|
|
12952
|
+
}
|
|
12953
|
+
),
|
|
12954
|
+
/* @__PURE__ */ jsx52(SkeletonButton2, {}),
|
|
12955
|
+
/* @__PURE__ */ jsx52(SkeletonButton2, {})
|
|
12956
|
+
] }) : piError ? /* @__PURE__ */ jsxs45("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
|
|
12957
|
+
/* @__PURE__ */ jsx52("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__ */ jsx52(AlertTriangle2, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
|
|
12958
|
+
/* @__PURE__ */ jsx52(
|
|
12959
|
+
"h3",
|
|
12960
|
+
{
|
|
12961
|
+
className: "uf-text-lg uf-font-semibold uf-mb-2",
|
|
12962
|
+
style: {
|
|
12963
|
+
color: colors2.foreground,
|
|
12964
|
+
fontFamily: fonts.semibold
|
|
12965
|
+
},
|
|
12966
|
+
children: "Unable to Load Checkout"
|
|
12967
|
+
}
|
|
12968
|
+
),
|
|
12969
|
+
/* @__PURE__ */ jsx52(
|
|
12970
|
+
"p",
|
|
12971
|
+
{
|
|
12972
|
+
className: "uf-text-sm uf-max-w-[280px]",
|
|
12973
|
+
style: {
|
|
12974
|
+
color: colors2.foregroundMuted,
|
|
12975
|
+
fontFamily: fonts.regular
|
|
12976
|
+
},
|
|
12977
|
+
children: piError instanceof Error ? piError.message : "Something went wrong. Please try again."
|
|
12978
|
+
}
|
|
12979
|
+
)
|
|
12980
|
+
] }) : paymentIntent ? /* @__PURE__ */ jsxs45("div", { className: "uf-space-y-3", children: [
|
|
12981
|
+
progressSection,
|
|
12982
|
+
(paymentIntent.status === "requires_payment" || paymentIntent.status === "processing") && /* @__PURE__ */ jsxs45(Fragment10, { children: [
|
|
12983
|
+
/* @__PURE__ */ jsx52(
|
|
12984
|
+
TransferCryptoButton,
|
|
12985
|
+
{
|
|
12986
|
+
onClick: () => setView("transfer"),
|
|
12987
|
+
title: "Transfer Crypto",
|
|
12988
|
+
subtitle: "Send from any wallet or exchange",
|
|
12989
|
+
featuredTokens: projectConfig?.transfer_crypto.networks
|
|
12990
|
+
}
|
|
12991
|
+
),
|
|
12992
|
+
enableConnectWallet && !isMobileView && /* @__PURE__ */ jsx52(
|
|
12993
|
+
BrowserWalletButton,
|
|
12994
|
+
{
|
|
12995
|
+
onClick: handleBrowserWalletClick,
|
|
12996
|
+
onConnectClick: handleWalletConnectClick,
|
|
12997
|
+
onDisconnect: handleWalletDisconnect,
|
|
12998
|
+
chainType: browserWalletChainType,
|
|
12999
|
+
publishableKey
|
|
13000
|
+
}
|
|
13001
|
+
)
|
|
13002
|
+
] })
|
|
13003
|
+
] }) : null,
|
|
13004
|
+
poweredByFooter
|
|
13005
|
+
] })
|
|
13006
|
+
] }) : view === "transfer" ? /* @__PURE__ */ jsxs45(Fragment10, { children: [
|
|
13007
|
+
/* @__PURE__ */ jsx52(
|
|
13008
|
+
DepositHeader,
|
|
13009
|
+
{
|
|
13010
|
+
title: `Pay $${remainingAmountUsd ?? paymentIntent?.amount_usd ?? ""}`,
|
|
13011
|
+
showBack: true,
|
|
13012
|
+
onBack: handleBack,
|
|
13013
|
+
onClose: handleClose
|
|
13014
|
+
}
|
|
13015
|
+
),
|
|
13016
|
+
/* @__PURE__ */ jsxs45("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
13017
|
+
paymentIntent ? /* @__PURE__ */ jsxs45(Fragment10, { children: [
|
|
13018
|
+
/* @__PURE__ */ jsxs45(
|
|
13019
|
+
"div",
|
|
13020
|
+
{
|
|
13021
|
+
className: "uf-rounded-lg uf-px-3 uf-py-2 uf-flex uf-items-center uf-justify-between",
|
|
13022
|
+
style: {
|
|
13023
|
+
backgroundColor: components.card.backgroundColor,
|
|
13024
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`,
|
|
13025
|
+
borderRadius: components.card.borderRadius
|
|
13026
|
+
},
|
|
13027
|
+
children: [
|
|
13028
|
+
/* @__PURE__ */ jsx52(
|
|
13029
|
+
"span",
|
|
13030
|
+
{
|
|
13031
|
+
className: "uf-text-xs",
|
|
13032
|
+
style: {
|
|
13033
|
+
color: colors2.foregroundMuted,
|
|
13034
|
+
fontFamily: fonts.regular
|
|
13035
|
+
},
|
|
13036
|
+
children: parseFloat(paymentIntent.amount_received_usd) > 0 ? `$${paymentIntent.amount_received_usd} / $${paymentIntent.amount_usd} received` : "Amount due"
|
|
13037
|
+
}
|
|
13038
|
+
),
|
|
13039
|
+
/* @__PURE__ */ jsxs45(
|
|
13040
|
+
"span",
|
|
13041
|
+
{
|
|
13042
|
+
className: "uf-text-sm uf-font-semibold",
|
|
13043
|
+
style: {
|
|
13044
|
+
color: colors2.foreground,
|
|
13045
|
+
fontFamily: fonts.semibold
|
|
13046
|
+
},
|
|
13047
|
+
children: [
|
|
13048
|
+
formatCryptoAmount(remainingCrypto ?? paymentIntent.amount),
|
|
13049
|
+
/* @__PURE__ */ jsxs45(
|
|
13050
|
+
"span",
|
|
13051
|
+
{
|
|
13052
|
+
className: "uf-text-xs uf-font-normal uf-ml-1",
|
|
13053
|
+
style: { color: colors2.foregroundMuted },
|
|
13054
|
+
children: [
|
|
13055
|
+
"($",
|
|
13056
|
+
remainingAmountUsd ?? paymentIntent.amount_usd,
|
|
13057
|
+
")"
|
|
13058
|
+
]
|
|
13059
|
+
}
|
|
13060
|
+
)
|
|
13061
|
+
]
|
|
13062
|
+
}
|
|
13063
|
+
)
|
|
13064
|
+
]
|
|
13065
|
+
}
|
|
13066
|
+
),
|
|
13067
|
+
/* @__PURE__ */ jsx52(
|
|
13068
|
+
TransferCryptoSingleInput,
|
|
13069
|
+
{
|
|
13070
|
+
userId: paymentIntent.user_id || "",
|
|
13071
|
+
publishableKey,
|
|
13072
|
+
clientSecret,
|
|
13073
|
+
recipientAddress: paymentIntent.recipient_address,
|
|
13074
|
+
destinationChainType: paymentIntent.destination_chain_type,
|
|
13075
|
+
destinationChainId: paymentIntent.destination_chain_id,
|
|
13076
|
+
destinationTokenAddress: paymentIntent.destination_token_address,
|
|
13077
|
+
depositConfirmationMode: "auto_ui",
|
|
13078
|
+
wallets,
|
|
13079
|
+
onSourceTokenChange: setSelectedSource,
|
|
13080
|
+
checkoutQuote: sourceQuote ? {
|
|
13081
|
+
sourceAmount: sourceQuote.source_amount,
|
|
13082
|
+
sourceTokenDecimals: sourceQuote.source_token_decimals,
|
|
13083
|
+
sourceTokenSymbol: sourceQuote.source_token_symbol,
|
|
13084
|
+
sourceAmountUsd: sourceQuote.source_amount_usd
|
|
13085
|
+
} : null
|
|
13086
|
+
}
|
|
13087
|
+
)
|
|
13088
|
+
] }) : /* @__PURE__ */ jsx52(SkeletonButton2, {}),
|
|
13089
|
+
poweredByFooter
|
|
13090
|
+
] })
|
|
13091
|
+
] }) : null })
|
|
13092
|
+
}
|
|
13093
|
+
),
|
|
13094
|
+
/* @__PURE__ */ jsx52(
|
|
13095
|
+
WalletSelectionModal,
|
|
13096
|
+
{
|
|
13097
|
+
open: walletSelectionModalOpen,
|
|
13098
|
+
onOpenChange: setWalletSelectionModalOpen,
|
|
13099
|
+
onWalletConnected: handleWalletConnected,
|
|
13100
|
+
onClose: () => setWalletSelectionModalOpen(false),
|
|
13101
|
+
theme: resolvedTheme
|
|
13102
|
+
}
|
|
13103
|
+
),
|
|
13104
|
+
browserWalletInfo && browserWalletInfo.depositWallet && /* @__PURE__ */ jsx52(
|
|
13105
|
+
BrowserWalletModal,
|
|
13106
|
+
{
|
|
13107
|
+
open: browserWalletModalOpen,
|
|
13108
|
+
onOpenChange: setBrowserWalletModalOpen,
|
|
13109
|
+
onFullClose: handleClose,
|
|
13110
|
+
walletInfo: browserWalletInfo,
|
|
13111
|
+
depositWallet: browserWalletInfo.depositWallet,
|
|
13112
|
+
userId: paymentIntent?.user_id || "",
|
|
13113
|
+
publishableKey,
|
|
13114
|
+
clientSecret,
|
|
13115
|
+
theme: resolvedTheme,
|
|
13116
|
+
prefillAmountUsd: remainingAmountUsd,
|
|
13117
|
+
checkoutAmountUsd: paymentIntent?.amount_usd,
|
|
13118
|
+
checkoutReceivedUsd: paymentIntent?.amount_received_usd,
|
|
13119
|
+
onSuccess: (txHash) => {
|
|
13120
|
+
onCheckoutSuccess?.({
|
|
13121
|
+
paymentIntentId: paymentIntent?.id || "",
|
|
13122
|
+
status: "processing"
|
|
13123
|
+
});
|
|
13124
|
+
},
|
|
13125
|
+
onError: (error) => {
|
|
13126
|
+
onCheckoutError?.({
|
|
13127
|
+
message: error.message,
|
|
13128
|
+
error
|
|
13129
|
+
});
|
|
13130
|
+
},
|
|
13131
|
+
onWalletDisconnect: handleWalletDisconnect,
|
|
13132
|
+
onNewDeposit: () => {
|
|
13133
|
+
setBrowserWalletModalOpen(false);
|
|
13134
|
+
setView("main");
|
|
13135
|
+
},
|
|
13136
|
+
onDone: () => {
|
|
13137
|
+
setBrowserWalletModalOpen(false);
|
|
13138
|
+
setView("main");
|
|
13139
|
+
},
|
|
13140
|
+
paymentIntentStatus: paymentIntent?.status
|
|
13141
|
+
}
|
|
13142
|
+
)
|
|
13143
|
+
] }) });
|
|
13144
|
+
}
|
|
13145
|
+
|
|
13146
|
+
// src/components/withdrawals/WithdrawModal.tsx
|
|
13147
|
+
import {
|
|
13148
|
+
useState as useState32,
|
|
13149
|
+
useEffect as useEffect27,
|
|
13150
|
+
useLayoutEffect as useLayoutEffect4,
|
|
13151
|
+
useCallback as useCallback7,
|
|
13152
|
+
useRef as useRef10
|
|
13153
|
+
} from "react";
|
|
13154
|
+
import { AlertTriangle as AlertTriangle4, ChevronRight as ChevronRight14, Clock as Clock5 } from "lucide-react";
|
|
13155
|
+
|
|
13156
|
+
// src/hooks/use-supported-destination-tokens.ts
|
|
13157
|
+
import { useQuery as useQuery11 } from "@tanstack/react-query";
|
|
13158
|
+
import {
|
|
13159
|
+
getSupportedDestinationTokens
|
|
13160
|
+
} from "@unifold/core";
|
|
13161
|
+
function useSupportedDestinationTokens(publishableKey, enabled = true) {
|
|
13162
|
+
return useQuery11({
|
|
13163
|
+
queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
|
|
13164
|
+
queryFn: () => getSupportedDestinationTokens(publishableKey),
|
|
13165
|
+
staleTime: 1e3 * 60 * 5,
|
|
13166
|
+
gcTime: 1e3 * 60 * 30,
|
|
13167
|
+
refetchOnMount: false,
|
|
13168
|
+
refetchOnWindowFocus: false,
|
|
13169
|
+
enabled
|
|
13170
|
+
});
|
|
13171
|
+
}
|
|
13172
|
+
|
|
13173
|
+
// src/hooks/use-source-token-validation.ts
|
|
13174
|
+
import { useQuery as useQuery12 } from "@tanstack/react-query";
|
|
13175
|
+
import { getSupportedDepositTokens as getSupportedDepositTokens3 } from "@unifold/core";
|
|
13176
|
+
function useSourceTokenValidation(params) {
|
|
13177
|
+
const {
|
|
13178
|
+
sourceChainType,
|
|
13179
|
+
sourceChainId,
|
|
13180
|
+
sourceTokenAddress,
|
|
13181
|
+
sourceTokenSymbol,
|
|
13182
|
+
publishableKey,
|
|
13183
|
+
enabled = true
|
|
13184
|
+
} = params;
|
|
13185
|
+
const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
|
|
13186
|
+
return useQuery12({
|
|
13187
|
+
queryKey: [
|
|
13188
|
+
"unifold",
|
|
13189
|
+
"sourceTokenValidation",
|
|
13190
|
+
sourceChainType ?? null,
|
|
13191
|
+
sourceChainId ?? null,
|
|
13192
|
+
sourceTokenAddress ?? null,
|
|
13193
|
+
publishableKey
|
|
13194
|
+
],
|
|
13195
|
+
queryFn: async () => {
|
|
13196
|
+
const res = await getSupportedDepositTokens3(publishableKey);
|
|
13197
|
+
let matchedMinUsd = null;
|
|
13198
|
+
let matchedProcessingTime = null;
|
|
13199
|
+
let matchedSlippage = null;
|
|
13200
|
+
let matchedPriceImpact = null;
|
|
13201
|
+
const found = res.data.some(
|
|
13202
|
+
(token) => token.chains.some((chain) => {
|
|
13203
|
+
const match = chain.chain_type === sourceChainType && chain.chain_id === sourceChainId && chain.token_address.toLowerCase() === sourceTokenAddress.toLowerCase();
|
|
13204
|
+
if (match) {
|
|
13205
|
+
matchedMinUsd = chain.minimum_deposit_amount_usd;
|
|
13206
|
+
matchedProcessingTime = chain.estimated_processing_time;
|
|
13207
|
+
matchedSlippage = chain.max_slippage_percent;
|
|
13208
|
+
matchedPriceImpact = chain.estimated_price_impact_percent;
|
|
13209
|
+
}
|
|
13210
|
+
return match;
|
|
13211
|
+
})
|
|
13212
|
+
);
|
|
13213
|
+
return {
|
|
13214
|
+
isSupported: found,
|
|
13215
|
+
minimumAmountUsd: matchedMinUsd,
|
|
13216
|
+
estimatedProcessingTime: matchedProcessingTime,
|
|
13217
|
+
maxSlippagePercent: matchedSlippage,
|
|
13218
|
+
priceImpactPercent: matchedPriceImpact,
|
|
13219
|
+
errorMessage: found ? null : `${sourceTokenSymbol || "Source token"} is not a supported withdrawal token. Supported tokens include USDC, USDT, and other stablecoins.`
|
|
13220
|
+
};
|
|
13221
|
+
},
|
|
13222
|
+
enabled: enabled && hasParams,
|
|
13223
|
+
staleTime: 1e3 * 60 * 5,
|
|
13224
|
+
gcTime: 1e3 * 60 * 30,
|
|
13225
|
+
refetchOnMount: false,
|
|
13226
|
+
refetchOnWindowFocus: false
|
|
13227
|
+
});
|
|
13228
|
+
}
|
|
13229
|
+
|
|
13230
|
+
// src/hooks/use-address-balance.ts
|
|
13231
|
+
import { useQuery as useQuery13 } from "@tanstack/react-query";
|
|
13232
|
+
import { getAddressBalance as getAddressBalance2 } from "@unifold/core";
|
|
13233
|
+
function useAddressBalance(params) {
|
|
13234
|
+
const {
|
|
13235
|
+
address,
|
|
13236
|
+
chainType,
|
|
13237
|
+
chainId,
|
|
13238
|
+
tokenAddress,
|
|
13239
|
+
publishableKey,
|
|
13240
|
+
enabled = true
|
|
13241
|
+
} = params;
|
|
13242
|
+
const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
|
|
13243
|
+
return useQuery13({
|
|
13244
|
+
queryKey: [
|
|
13245
|
+
"unifold",
|
|
13246
|
+
"addressBalance",
|
|
13247
|
+
address ?? null,
|
|
13248
|
+
chainType ?? null,
|
|
13249
|
+
chainId ?? null,
|
|
13250
|
+
tokenAddress ?? null,
|
|
13251
|
+
publishableKey
|
|
13252
|
+
],
|
|
13253
|
+
queryFn: async () => {
|
|
13254
|
+
const res = await getAddressBalance2(
|
|
13255
|
+
address,
|
|
13256
|
+
chainType,
|
|
13257
|
+
chainId,
|
|
13258
|
+
tokenAddress,
|
|
13259
|
+
publishableKey
|
|
13260
|
+
);
|
|
13261
|
+
if (res.balance) {
|
|
13262
|
+
const decimals = res.balance.token?.decimals ?? 6;
|
|
13263
|
+
const symbol = res.balance.token?.symbol ?? "";
|
|
13264
|
+
const baseUnit = res.balance.amount;
|
|
13265
|
+
const raw = BigInt(baseUnit);
|
|
13266
|
+
const divisor = BigInt(10 ** decimals);
|
|
13267
|
+
const whole = raw / divisor;
|
|
13268
|
+
const frac = raw % divisor;
|
|
13269
|
+
const fracStr = frac.toString().padStart(decimals, "0").replace(/0+$/, "");
|
|
13270
|
+
const balanceHuman = fracStr ? `${whole}.${fracStr}` : whole.toString();
|
|
13271
|
+
return {
|
|
13272
|
+
balanceBaseUnit: baseUnit,
|
|
13273
|
+
balanceHuman,
|
|
13274
|
+
balanceUsd: res.balance.amount_usd,
|
|
13275
|
+
exchangeRate: res.balance.exchange_rate,
|
|
13276
|
+
decimals,
|
|
13277
|
+
symbol
|
|
13278
|
+
};
|
|
13279
|
+
}
|
|
13280
|
+
return { balanceBaseUnit: "0", balanceHuman: "0", balanceUsd: "0", exchangeRate: null, decimals: 6, symbol: "" };
|
|
13281
|
+
},
|
|
13282
|
+
enabled: enabled && hasParams,
|
|
13283
|
+
staleTime: 1e3 * 30,
|
|
13284
|
+
gcTime: 1e3 * 60 * 5,
|
|
13285
|
+
refetchInterval: 1e3 * 30,
|
|
13286
|
+
refetchOnMount: "always",
|
|
13287
|
+
refetchOnWindowFocus: false
|
|
13288
|
+
});
|
|
13289
|
+
}
|
|
13290
|
+
|
|
13291
|
+
// src/hooks/use-executions.ts
|
|
13292
|
+
import { useQuery as useQuery14 } from "@tanstack/react-query";
|
|
13293
|
+
import { queryExecutions as queryExecutions4, ActionType as ActionType4 } from "@unifold/core";
|
|
13294
|
+
function useExecutions(userId, publishableKey, options) {
|
|
13295
|
+
const actionType = options?.actionType ?? ActionType4.Deposit;
|
|
13296
|
+
return useQuery14({
|
|
13297
|
+
queryKey: ["unifold", "executions", actionType, userId, publishableKey],
|
|
13298
|
+
queryFn: () => queryExecutions4(userId, publishableKey, actionType),
|
|
13299
|
+
enabled: (options?.enabled ?? true) && !!userId,
|
|
13300
|
+
refetchInterval: options?.refetchInterval ?? 3e3,
|
|
13301
|
+
staleTime: 0,
|
|
13302
|
+
gcTime: 1e3 * 60 * 5,
|
|
13303
|
+
refetchOnWindowFocus: false
|
|
13304
|
+
});
|
|
13305
|
+
}
|
|
13306
|
+
|
|
13307
|
+
// src/hooks/use-withdraw-polling.ts
|
|
13308
|
+
import { useState as useState29, useEffect as useEffect24, useRef as useRef9 } from "react";
|
|
13309
|
+
import {
|
|
13310
|
+
queryExecutions as queryExecutions5,
|
|
13311
|
+
pollDirectExecutions as pollDirectExecutions2,
|
|
13312
|
+
ExecutionStatus as ExecutionStatus5,
|
|
13313
|
+
ActionType as ActionType5
|
|
13314
|
+
} from "@unifold/core";
|
|
13315
|
+
var POLL_INTERVAL_MS2 = 2500;
|
|
13316
|
+
var POLL_ENDPOINT_INTERVAL_MS2 = 3e3;
|
|
13317
|
+
var CUTOFF_BUFFER_MS2 = 6e4;
|
|
13318
|
+
function useWithdrawPolling({
|
|
13319
|
+
userId,
|
|
13320
|
+
publishableKey,
|
|
13321
|
+
depositWalletId,
|
|
13322
|
+
enabled = false,
|
|
13323
|
+
onWithdrawSuccess,
|
|
13324
|
+
onWithdrawError
|
|
13325
|
+
}) {
|
|
13326
|
+
const [executions, setExecutions] = useState29([]);
|
|
13327
|
+
const [isPolling, setIsPolling] = useState29(false);
|
|
13328
|
+
const enabledAtRef = useRef9(/* @__PURE__ */ new Date());
|
|
13329
|
+
const trackedRef = useRef9(/* @__PURE__ */ new Map());
|
|
13330
|
+
const prevEnabledRef = useRef9(false);
|
|
13331
|
+
const onSuccessRef = useRef9(onWithdrawSuccess);
|
|
13332
|
+
const onErrorRef = useRef9(onWithdrawError);
|
|
13333
|
+
useEffect24(() => {
|
|
13334
|
+
onSuccessRef.current = onWithdrawSuccess;
|
|
13335
|
+
}, [onWithdrawSuccess]);
|
|
13336
|
+
useEffect24(() => {
|
|
13337
|
+
onErrorRef.current = onWithdrawError;
|
|
13338
|
+
}, [onWithdrawError]);
|
|
13339
|
+
useEffect24(() => {
|
|
13340
|
+
if (enabled && !prevEnabledRef.current) {
|
|
13341
|
+
enabledAtRef.current = /* @__PURE__ */ new Date();
|
|
13342
|
+
trackedRef.current.clear();
|
|
13343
|
+
}
|
|
13344
|
+
if (!enabled) {
|
|
13345
|
+
trackedRef.current.clear();
|
|
13346
|
+
}
|
|
13347
|
+
prevEnabledRef.current = enabled;
|
|
13348
|
+
}, [enabled]);
|
|
13349
|
+
useEffect24(() => {
|
|
13350
|
+
if (!userId || !enabled) return;
|
|
13351
|
+
const enabledAt = enabledAtRef.current;
|
|
13352
|
+
const poll = async () => {
|
|
13353
|
+
try {
|
|
13354
|
+
const response = await queryExecutions5(userId, publishableKey, ActionType5.Withdraw);
|
|
13355
|
+
const cutoff = new Date(enabledAt.getTime() - CUTOFF_BUFFER_MS2);
|
|
13356
|
+
const sorted = [...response.data].sort((a, b) => {
|
|
13357
|
+
const tA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
13358
|
+
const tB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
13359
|
+
return tB - tA;
|
|
13360
|
+
});
|
|
13361
|
+
const inProgress = [ExecutionStatus5.PENDING, ExecutionStatus5.WAITING, ExecutionStatus5.DELAYED];
|
|
13362
|
+
const terminal = [ExecutionStatus5.SUCCEEDED, ExecutionStatus5.FAILED];
|
|
13363
|
+
let target = null;
|
|
13364
|
+
for (const ex of sorted) {
|
|
13365
|
+
const t11 = ex.created_at ? new Date(ex.created_at) : null;
|
|
13366
|
+
if (!t11 || t11 < cutoff) continue;
|
|
13367
|
+
const prev = trackedRef.current.get(ex.id);
|
|
13368
|
+
if (!prev) {
|
|
13369
|
+
target = ex;
|
|
13370
|
+
break;
|
|
13371
|
+
}
|
|
13372
|
+
if (inProgress.includes(prev) && terminal.includes(ex.status)) {
|
|
13373
|
+
target = ex;
|
|
13374
|
+
break;
|
|
13375
|
+
}
|
|
13376
|
+
}
|
|
13377
|
+
if (target) {
|
|
13378
|
+
const ex = target;
|
|
13379
|
+
const exTime = ex.created_at ? new Date(ex.created_at) : null;
|
|
13380
|
+
if (!exTime || exTime < enabledAtRef.current) return;
|
|
13381
|
+
const prev = trackedRef.current.get(ex.id);
|
|
13382
|
+
trackedRef.current.set(ex.id, ex.status);
|
|
13383
|
+
setExecutions((list) => {
|
|
13384
|
+
const idx = list.findIndex((e) => e.id === ex.id);
|
|
13385
|
+
if (idx >= 0) {
|
|
13386
|
+
const u = [...list];
|
|
13387
|
+
u[idx] = ex;
|
|
13388
|
+
return u;
|
|
13389
|
+
}
|
|
13390
|
+
return [...list, ex];
|
|
13391
|
+
});
|
|
13392
|
+
if (ex.status === ExecutionStatus5.SUCCEEDED && (!prev || inProgress.includes(prev))) {
|
|
13393
|
+
onSuccessRef.current?.({ message: "Withdrawal completed successfully", executionId: ex.id, transaction: ex });
|
|
13394
|
+
} else if (ex.status === ExecutionStatus5.FAILED && prev !== ExecutionStatus5.FAILED) {
|
|
13395
|
+
onErrorRef.current?.({ message: "Withdrawal failed", code: "WITHDRAW_FAILED", error: ex });
|
|
13396
|
+
}
|
|
13397
|
+
}
|
|
13398
|
+
} catch (error) {
|
|
13399
|
+
console.error("Failed to fetch withdraw executions:", error);
|
|
13400
|
+
onErrorRef.current?.({ message: "Failed to fetch withdrawal status", code: "POLLING_ERROR", error });
|
|
13401
|
+
}
|
|
13402
|
+
};
|
|
13403
|
+
void poll();
|
|
13404
|
+
const interval = setInterval(poll, POLL_INTERVAL_MS2);
|
|
13405
|
+
setIsPolling(true);
|
|
13406
|
+
return () => {
|
|
13407
|
+
clearInterval(interval);
|
|
13408
|
+
setIsPolling(false);
|
|
13409
|
+
};
|
|
13410
|
+
}, [userId, publishableKey, enabled]);
|
|
13411
|
+
useEffect24(() => {
|
|
13412
|
+
if (!enabled || !depositWalletId) return;
|
|
13413
|
+
const trigger = async () => {
|
|
13414
|
+
try {
|
|
13415
|
+
await pollDirectExecutions2({ deposit_wallet_id: depositWalletId }, publishableKey);
|
|
13416
|
+
} catch {
|
|
13417
|
+
}
|
|
13418
|
+
};
|
|
13419
|
+
trigger();
|
|
13420
|
+
const interval = setInterval(trigger, POLL_ENDPOINT_INTERVAL_MS2);
|
|
13421
|
+
return () => clearInterval(interval);
|
|
13422
|
+
}, [enabled, depositWalletId, publishableKey]);
|
|
13423
|
+
return { executions, isPolling };
|
|
13424
|
+
}
|
|
13425
|
+
|
|
13426
|
+
// src/components/withdrawals/WithdrawDoubleInput.tsx
|
|
13427
|
+
import { jsx as jsx53, jsxs as jsxs46 } from "react/jsx-runtime";
|
|
13428
|
+
var t7 = i18n.withdrawModal;
|
|
13429
|
+
var getChainKey4 = (chainId, chainType) => `${chainType}:${chainId}`;
|
|
13430
|
+
function WithdrawDoubleInput({
|
|
13431
|
+
tokens,
|
|
13432
|
+
selectedTokenSymbol,
|
|
13433
|
+
selectedChainKey,
|
|
13434
|
+
onTokenChange,
|
|
13435
|
+
onChainChange,
|
|
13436
|
+
isLoading = false
|
|
13437
|
+
}) {
|
|
13438
|
+
const { fonts, components } = useTheme();
|
|
13439
|
+
const isDarkMode = useTheme().themeClass.includes("uf-dark");
|
|
13440
|
+
const selectedToken = selectedTokenSymbol ? tokens.find((t11) => t11.symbol === selectedTokenSymbol) : void 0;
|
|
13441
|
+
const availableChainsForToken = selectedToken?.chains || [];
|
|
13442
|
+
const renderTokenItem = (tokenData) => /* @__PURE__ */ jsxs46("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
13443
|
+
/* @__PURE__ */ jsx53(
|
|
13444
|
+
"img",
|
|
13445
|
+
{
|
|
13446
|
+
src: tokenData.icon_url,
|
|
13447
|
+
alt: tokenData.symbol,
|
|
13448
|
+
width: 20,
|
|
13449
|
+
height: 20,
|
|
13450
|
+
loading: "lazy",
|
|
13451
|
+
className: "uf-rounded-full uf-flex-shrink-0"
|
|
13452
|
+
}
|
|
13453
|
+
),
|
|
13454
|
+
/* @__PURE__ */ jsx53("span", { className: "uf-text-xs uf-font-normal", children: tokenData.symbol })
|
|
13455
|
+
] });
|
|
13456
|
+
const renderChainItem = (chainData) => /* @__PURE__ */ jsxs46("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
13457
|
+
/* @__PURE__ */ jsx53(
|
|
13458
|
+
"img",
|
|
13459
|
+
{
|
|
13460
|
+
src: chainData.icon_url,
|
|
13461
|
+
alt: chainData.chain_name,
|
|
13462
|
+
width: 20,
|
|
13463
|
+
height: 20,
|
|
13464
|
+
loading: "lazy",
|
|
13465
|
+
className: "uf-rounded-full uf-flex-shrink-0"
|
|
13466
|
+
}
|
|
13467
|
+
),
|
|
13468
|
+
/* @__PURE__ */ jsx53("span", { className: "uf-text-xs uf-font-normal", children: chainData.chain_name })
|
|
13469
|
+
] });
|
|
13470
|
+
const currentChainData = selectedChainKey ? availableChainsForToken.find(
|
|
13471
|
+
(c) => getChainKey4(c.chain_id, c.chain_type) === selectedChainKey
|
|
13472
|
+
) : void 0;
|
|
13473
|
+
return /* @__PURE__ */ jsxs46("div", { className: "uf-grid uf-grid-cols-2 uf-gap-2.5", children: [
|
|
13474
|
+
/* @__PURE__ */ jsxs46("div", { children: [
|
|
13475
|
+
/* @__PURE__ */ jsx53(
|
|
13476
|
+
"div",
|
|
13477
|
+
{
|
|
13478
|
+
className: "uf-text-xs uf-mb-2 uf-flex uf-items-center uf-gap-1",
|
|
13479
|
+
style: { color: components.card.labelColor },
|
|
13480
|
+
children: t7.receiveToken
|
|
13481
|
+
}
|
|
13482
|
+
),
|
|
13483
|
+
/* @__PURE__ */ jsxs46(
|
|
13484
|
+
Select,
|
|
13485
|
+
{
|
|
13486
|
+
value: selectedTokenSymbol ?? "",
|
|
13487
|
+
onValueChange: onTokenChange,
|
|
13488
|
+
disabled: isLoading || tokens.length === 0,
|
|
13489
|
+
children: [
|
|
13490
|
+
/* @__PURE__ */ jsx53(
|
|
13491
|
+
SelectTrigger,
|
|
13492
|
+
{
|
|
13493
|
+
className: "uf-h-10 hover:uf-opacity-90 uf-text-foreground disabled:uf-opacity-50",
|
|
13494
|
+
style: {
|
|
13495
|
+
backgroundColor: components.card.backgroundColor,
|
|
13496
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
13497
|
+
},
|
|
13498
|
+
children: /* @__PURE__ */ jsx53(SelectValue, { children: isLoading || !selectedTokenSymbol ? /* @__PURE__ */ jsx53("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t7.loading }) : selectedToken ? renderTokenItem(selectedToken) : /* @__PURE__ */ jsx53("span", { className: "uf-text-xs uf-font-normal", children: selectedTokenSymbol }) })
|
|
13499
|
+
}
|
|
13500
|
+
),
|
|
13501
|
+
/* @__PURE__ */ jsx53(
|
|
13502
|
+
SelectContent,
|
|
13503
|
+
{
|
|
13504
|
+
className: "uf-bg-secondary uf-border uf-text-foreground uf-max-h-[300px]",
|
|
13505
|
+
style: {
|
|
13506
|
+
border: `1px solid ${isDarkMode ? "rgba(255,255,255,0.15)" : "rgba(0,0,0,0.15)"}`,
|
|
13507
|
+
...fonts.regular ? { "--uf-font-family": fonts.regular } : {}
|
|
13508
|
+
},
|
|
13509
|
+
children: tokens.map((tokenData) => /* @__PURE__ */ jsx53(
|
|
13510
|
+
SelectItem,
|
|
13511
|
+
{
|
|
13512
|
+
value: tokenData.symbol,
|
|
13513
|
+
className: "focus:uf-bg-accent focus:uf-text-foreground",
|
|
13514
|
+
children: renderTokenItem(tokenData)
|
|
13515
|
+
},
|
|
13516
|
+
tokenData.symbol
|
|
13517
|
+
))
|
|
13518
|
+
}
|
|
13519
|
+
)
|
|
13520
|
+
]
|
|
13521
|
+
}
|
|
13522
|
+
)
|
|
13523
|
+
] }),
|
|
13524
|
+
/* @__PURE__ */ jsxs46("div", { children: [
|
|
13525
|
+
/* @__PURE__ */ jsx53(
|
|
13526
|
+
"div",
|
|
13527
|
+
{
|
|
13528
|
+
className: "uf-text-xs uf-mb-2 uf-flex uf-items-center uf-gap-1",
|
|
13529
|
+
style: { color: components.card.labelColor },
|
|
13530
|
+
children: t7.receiveChain
|
|
13531
|
+
}
|
|
13532
|
+
),
|
|
13533
|
+
/* @__PURE__ */ jsxs46(
|
|
13534
|
+
Select,
|
|
13535
|
+
{
|
|
13536
|
+
value: selectedChainKey ?? "",
|
|
13537
|
+
onValueChange: onChainChange,
|
|
13538
|
+
disabled: isLoading || availableChainsForToken.length === 0,
|
|
13539
|
+
children: [
|
|
13540
|
+
/* @__PURE__ */ jsx53(
|
|
13541
|
+
SelectTrigger,
|
|
13542
|
+
{
|
|
13543
|
+
className: "uf-h-10 hover:uf-opacity-90 uf-text-foreground disabled:uf-opacity-50",
|
|
13544
|
+
style: {
|
|
13545
|
+
backgroundColor: components.card.backgroundColor,
|
|
13546
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
13547
|
+
},
|
|
13548
|
+
children: /* @__PURE__ */ jsx53(SelectValue, { children: isLoading || !selectedChainKey ? /* @__PURE__ */ jsx53("span", { className: "uf-text-xs uf-font-light uf-text-muted-foreground", children: t7.loading }) : currentChainData ? renderChainItem(currentChainData) : /* @__PURE__ */ jsx53("span", { className: "uf-text-xs uf-font-normal", children: selectedChainKey }) })
|
|
13549
|
+
}
|
|
13550
|
+
),
|
|
13551
|
+
/* @__PURE__ */ jsx53(
|
|
13552
|
+
SelectContent,
|
|
13553
|
+
{
|
|
13554
|
+
align: "end",
|
|
13555
|
+
className: "uf-bg-secondary uf-border uf-text-foreground uf-max-h-[300px] uf-min-w-[200px]",
|
|
13556
|
+
style: {
|
|
13557
|
+
border: `1px solid ${isDarkMode ? "rgba(255,255,255,0.15)" : "rgba(0,0,0,0.15)"}`,
|
|
13558
|
+
...fonts.regular ? { "--uf-font-family": fonts.regular } : {}
|
|
13559
|
+
},
|
|
13560
|
+
children: availableChainsForToken.length === 0 ? /* @__PURE__ */ jsx53("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) => {
|
|
13561
|
+
const chainKey = getChainKey4(chainData.chain_id, chainData.chain_type);
|
|
13562
|
+
return /* @__PURE__ */ jsx53(
|
|
13563
|
+
SelectItem,
|
|
13564
|
+
{
|
|
13565
|
+
value: chainKey,
|
|
13566
|
+
className: "focus:uf-bg-accent focus:uf-text-foreground",
|
|
13567
|
+
children: renderChainItem(chainData)
|
|
13568
|
+
},
|
|
13569
|
+
chainKey
|
|
13570
|
+
);
|
|
13571
|
+
})
|
|
13572
|
+
}
|
|
13573
|
+
)
|
|
13574
|
+
]
|
|
13575
|
+
}
|
|
13576
|
+
)
|
|
13577
|
+
] })
|
|
13578
|
+
] });
|
|
13579
|
+
}
|
|
13580
|
+
|
|
13581
|
+
// src/components/withdrawals/WithdrawForm.tsx
|
|
13582
|
+
import { useState as useState30, useCallback as useCallback6, useMemo as useMemo11, useEffect as useEffect25 } from "react";
|
|
13583
|
+
import {
|
|
13584
|
+
AlertTriangle as AlertTriangle3,
|
|
13585
|
+
ArrowUpDown,
|
|
13586
|
+
ChevronDown as ChevronDown7,
|
|
13587
|
+
ChevronUp as ChevronUp6,
|
|
13588
|
+
Clock as Clock4,
|
|
13589
|
+
ClipboardPaste,
|
|
13590
|
+
DollarSign as DollarSign3,
|
|
13591
|
+
Loader2 as Loader26,
|
|
13592
|
+
ShieldCheck as ShieldCheck3,
|
|
13593
|
+
Wallet as Wallet3
|
|
13594
|
+
} from "lucide-react";
|
|
13595
|
+
|
|
13596
|
+
// src/hooks/use-verify-recipient-address.ts
|
|
13597
|
+
import { useQuery as useQuery15 } from "@tanstack/react-query";
|
|
13598
|
+
import { verifyRecipientAddress as verifyRecipientAddress2 } from "@unifold/core";
|
|
13599
|
+
function useVerifyRecipientAddress(params) {
|
|
13600
|
+
const {
|
|
13601
|
+
chainType,
|
|
13602
|
+
chainId,
|
|
13603
|
+
tokenAddress,
|
|
13604
|
+
recipientAddress,
|
|
13605
|
+
publishableKey,
|
|
13606
|
+
enabled = true
|
|
13607
|
+
} = params;
|
|
13608
|
+
const trimmedAddress = recipientAddress?.trim() || "";
|
|
13609
|
+
const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
|
|
13610
|
+
return useQuery15({
|
|
13611
|
+
queryKey: [
|
|
13612
|
+
"unifold",
|
|
13613
|
+
"verifyRecipientAddress",
|
|
13614
|
+
chainType ?? null,
|
|
13615
|
+
chainId ?? null,
|
|
13616
|
+
tokenAddress ?? null,
|
|
13617
|
+
trimmedAddress,
|
|
13618
|
+
publishableKey
|
|
13619
|
+
],
|
|
13620
|
+
queryFn: () => verifyRecipientAddress2(
|
|
13621
|
+
{
|
|
13622
|
+
chain_type: chainType,
|
|
13623
|
+
chain_id: chainId,
|
|
13624
|
+
token_address: tokenAddress,
|
|
13625
|
+
recipient_address: trimmedAddress
|
|
13626
|
+
},
|
|
13627
|
+
publishableKey
|
|
13628
|
+
),
|
|
13629
|
+
enabled: enabled && hasAllParams,
|
|
13630
|
+
staleTime: 1e3 * 60 * 5,
|
|
13631
|
+
gcTime: 1e3 * 60 * 30,
|
|
13632
|
+
retry: 1,
|
|
13633
|
+
refetchOnMount: false,
|
|
13634
|
+
refetchOnWindowFocus: false
|
|
13635
|
+
});
|
|
13636
|
+
}
|
|
13637
|
+
|
|
13638
|
+
// src/components/withdrawals/send-withdraw.ts
|
|
13639
|
+
import {
|
|
13640
|
+
buildSolanaTransaction as buildSolanaTransaction2,
|
|
13641
|
+
sendSolanaTransaction as sendSolanaTransactionToBackend2,
|
|
13642
|
+
buildHypercoreTransaction as buildHypercoreTransactionFromBackend,
|
|
13643
|
+
sendHypercoreTransaction as sendHypercoreTransactionToBackend
|
|
13644
|
+
} from "@unifold/core";
|
|
13645
|
+
async function sendEvmWithdraw(params) {
|
|
13646
|
+
const {
|
|
13647
|
+
provider,
|
|
13648
|
+
fromAddress,
|
|
13649
|
+
depositWalletAddress,
|
|
13650
|
+
sourceTokenAddress,
|
|
13651
|
+
sourceChainId,
|
|
13652
|
+
amountBaseUnit
|
|
13653
|
+
} = params;
|
|
13654
|
+
const currentChainIdHex = await provider.request({
|
|
13655
|
+
method: "eth_chainId",
|
|
13656
|
+
params: []
|
|
13657
|
+
});
|
|
13658
|
+
const currentChainId = parseInt(currentChainIdHex, 16).toString();
|
|
13659
|
+
if (currentChainId !== sourceChainId) {
|
|
13660
|
+
const requiredHex = "0x" + parseInt(sourceChainId).toString(16);
|
|
13661
|
+
try {
|
|
13662
|
+
await provider.request({
|
|
13663
|
+
method: "wallet_switchEthereumChain",
|
|
13664
|
+
params: [{ chainId: requiredHex }]
|
|
13665
|
+
});
|
|
13666
|
+
const newHex = await provider.request({ method: "eth_chainId", params: [] });
|
|
13667
|
+
if (parseInt(newHex, 16).toString() !== sourceChainId) {
|
|
13668
|
+
throw new Error(`Failed to switch to chain ${sourceChainId}. Please switch manually.`);
|
|
13669
|
+
}
|
|
13670
|
+
} catch (err) {
|
|
13671
|
+
if (err && typeof err === "object" && "code" in err) {
|
|
13672
|
+
const e = err;
|
|
13673
|
+
if (e.code === 4902) throw new Error(`Chain ${sourceChainId} is not configured in your wallet.`);
|
|
13674
|
+
if (e.code === 4001) throw new Error("You must approve the network switch to withdraw.");
|
|
13675
|
+
}
|
|
13676
|
+
throw err;
|
|
13677
|
+
}
|
|
13678
|
+
}
|
|
13679
|
+
const isNative = sourceTokenAddress === "native" || sourceTokenAddress === "0x0000000000000000000000000000000000000000" || sourceTokenAddress === "";
|
|
13680
|
+
const amountBig = BigInt(amountBaseUnit);
|
|
13681
|
+
const txParams = isNative ? { from: fromAddress, to: depositWalletAddress, value: "0x" + amountBig.toString(16) } : {
|
|
13682
|
+
from: fromAddress,
|
|
13683
|
+
to: sourceTokenAddress,
|
|
13684
|
+
data: "0xa9059cbb" + depositWalletAddress.slice(2).padStart(64, "0") + amountBig.toString(16).padStart(64, "0")
|
|
13685
|
+
};
|
|
13686
|
+
let gasEstimate;
|
|
13687
|
+
try {
|
|
13688
|
+
const hex = await provider.request({ method: "eth_estimateGas", params: [txParams] });
|
|
13689
|
+
gasEstimate = BigInt(hex);
|
|
13690
|
+
} catch {
|
|
13691
|
+
gasEstimate = isNative ? BigInt(21e3) : BigInt(65e3);
|
|
13692
|
+
}
|
|
13693
|
+
const gasPrice = BigInt(await provider.request({ method: "eth_gasPrice", params: [] }));
|
|
13694
|
+
const gasWithBuffer = gasEstimate * BigInt(120) / BigInt(100);
|
|
13695
|
+
const gasCost = gasWithBuffer * gasPrice;
|
|
13696
|
+
const ethBalance = BigInt(
|
|
13697
|
+
await provider.request({ method: "eth_getBalance", params: [fromAddress, "latest"] })
|
|
13698
|
+
);
|
|
13699
|
+
const totalRequired = isNative ? gasCost + amountBig : gasCost;
|
|
13700
|
+
if (ethBalance < totalRequired) {
|
|
13701
|
+
const gasFmt = (Number(gasCost) / 1e18).toFixed(6);
|
|
13702
|
+
if (isNative) {
|
|
13703
|
+
throw new Error(`Insufficient balance. Need ${(Number(totalRequired) / 1e18).toFixed(6)} ETH (amount + ~${gasFmt} gas).`);
|
|
13704
|
+
}
|
|
13705
|
+
throw new Error(`Insufficient ETH for gas. Need ~${gasFmt} ETH for fees.`);
|
|
13706
|
+
}
|
|
13707
|
+
const txHash = await provider.request({ method: "eth_sendTransaction", params: [txParams] });
|
|
13708
|
+
return txHash;
|
|
13709
|
+
}
|
|
13710
|
+
async function sendSolanaWithdraw(params) {
|
|
13711
|
+
const {
|
|
13712
|
+
provider,
|
|
13713
|
+
fromAddress,
|
|
13714
|
+
depositWalletAddress,
|
|
13715
|
+
sourceTokenAddress,
|
|
13716
|
+
amountBaseUnit,
|
|
13717
|
+
publishableKey
|
|
13718
|
+
} = params;
|
|
13719
|
+
if (!provider.publicKey) {
|
|
13720
|
+
await provider.connect();
|
|
13721
|
+
}
|
|
13722
|
+
const buildResponse = await buildSolanaTransaction2(
|
|
13723
|
+
{
|
|
13724
|
+
chain_id: "mainnet",
|
|
13725
|
+
token_address: sourceTokenAddress === "" ? "native" : sourceTokenAddress,
|
|
13726
|
+
source_address: fromAddress,
|
|
13727
|
+
destination_address: depositWalletAddress,
|
|
13728
|
+
amount: amountBaseUnit
|
|
13729
|
+
},
|
|
13730
|
+
publishableKey
|
|
13731
|
+
);
|
|
13732
|
+
const { VersionedTransaction } = await import(
|
|
13733
|
+
/* @vite-ignore */
|
|
13734
|
+
"@solana/web3.js"
|
|
13735
|
+
);
|
|
13736
|
+
const binaryString = atob(buildResponse.transaction);
|
|
13737
|
+
const bytes = new Uint8Array(binaryString.length);
|
|
13738
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
13739
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
13740
|
+
}
|
|
13741
|
+
const transaction = VersionedTransaction.deserialize(bytes);
|
|
13742
|
+
const signedTransaction = await provider.signTransaction(transaction);
|
|
13743
|
+
const serialized = signedTransaction.serialize();
|
|
13744
|
+
let binaryStr = "";
|
|
13745
|
+
for (let i = 0; i < serialized.length; i++) {
|
|
13746
|
+
binaryStr += String.fromCharCode(serialized[i]);
|
|
13747
|
+
}
|
|
13748
|
+
const sendResponse = await sendSolanaTransactionToBackend2(
|
|
13749
|
+
{ chain_id: "mainnet", signed_transaction: btoa(binaryStr) },
|
|
13750
|
+
publishableKey
|
|
13751
|
+
);
|
|
13752
|
+
return sendResponse.signature;
|
|
13753
|
+
}
|
|
13754
|
+
var HYPERCORE_CHAIN_ID = "1337";
|
|
13755
|
+
var HYPERCORE_SPOT_USDC_ADDRESS = "0x6d1e7cde53ba9467b783cb7c530ce054";
|
|
13756
|
+
function isHypercoreChain(chainId) {
|
|
13757
|
+
return chainId === HYPERCORE_CHAIN_ID;
|
|
13758
|
+
}
|
|
13759
|
+
async function sendHypercoreWithdraw(params) {
|
|
13760
|
+
const {
|
|
13761
|
+
provider,
|
|
13762
|
+
fromAddress,
|
|
13763
|
+
depositWalletAddress,
|
|
13764
|
+
sourceTokenAddress,
|
|
13765
|
+
amount,
|
|
13766
|
+
tokenSymbol,
|
|
13767
|
+
publishableKey
|
|
13768
|
+
} = params;
|
|
13769
|
+
const isSpot = sourceTokenAddress.toLowerCase() === HYPERCORE_SPOT_USDC_ADDRESS;
|
|
13770
|
+
const currentChainHex = await provider.request({
|
|
13771
|
+
method: "eth_chainId",
|
|
13772
|
+
params: []
|
|
13773
|
+
});
|
|
13774
|
+
const activeChainId = String(parseInt(currentChainHex, 16));
|
|
13775
|
+
const buildResult = await buildHypercoreTransactionFromBackend(
|
|
13776
|
+
{
|
|
13777
|
+
action_type: isSpot ? "spot_send" : "usd_send",
|
|
13778
|
+
signature_chain_type: "ethereum",
|
|
13779
|
+
signature_chain_id: activeChainId,
|
|
13780
|
+
recipient_address: depositWalletAddress,
|
|
13781
|
+
token_address: sourceTokenAddress,
|
|
13782
|
+
token_symbol: tokenSymbol || void 0,
|
|
13783
|
+
amount
|
|
13784
|
+
},
|
|
13785
|
+
publishableKey
|
|
13786
|
+
);
|
|
13787
|
+
const signature = await provider.request({
|
|
13788
|
+
method: "eth_signTypedData_v4",
|
|
13789
|
+
params: [fromAddress, JSON.stringify(buildResult.typed_data)]
|
|
13790
|
+
});
|
|
13791
|
+
await sendHypercoreTransactionToBackend(
|
|
13792
|
+
{
|
|
13793
|
+
action_payload: buildResult.action_payload,
|
|
13794
|
+
signature,
|
|
13795
|
+
nonce: buildResult.nonce
|
|
13796
|
+
},
|
|
13797
|
+
publishableKey
|
|
13798
|
+
);
|
|
13799
|
+
}
|
|
13800
|
+
async function detectBrowserWallet(chainType, senderAddress) {
|
|
13801
|
+
const win = typeof window !== "undefined" ? window : null;
|
|
13802
|
+
if (!win || !senderAddress) return null;
|
|
13803
|
+
const anyWin = win;
|
|
13804
|
+
if (chainType === "solana") {
|
|
13805
|
+
const solProviders = [];
|
|
13806
|
+
if (win.phantom?.solana) solProviders.push({ provider: win.phantom.solana, name: "Phantom" });
|
|
13807
|
+
if (anyWin.solflare) solProviders.push({ provider: anyWin.solflare, name: "Solflare" });
|
|
13808
|
+
if (anyWin.backpack) solProviders.push({ provider: anyWin.backpack, name: "Backpack" });
|
|
13809
|
+
if (anyWin.trustwallet?.solana) solProviders.push({ provider: anyWin.trustwallet.solana, name: "Trust Wallet" });
|
|
13810
|
+
for (const { provider, name } of solProviders) {
|
|
13811
|
+
if (!provider) continue;
|
|
13812
|
+
try {
|
|
13813
|
+
let addr;
|
|
13814
|
+
if (provider.isConnected && provider.publicKey) {
|
|
13815
|
+
addr = provider.publicKey.toString();
|
|
13816
|
+
} else {
|
|
13817
|
+
const resp = await provider.connect({ onlyIfTrusted: true });
|
|
13818
|
+
if (resp?.publicKey) addr = resp.publicKey.toString();
|
|
13819
|
+
}
|
|
13820
|
+
if (addr && addr === senderAddress) {
|
|
13821
|
+
return { chainFamily: "solana", provider, name, address: addr };
|
|
13822
|
+
}
|
|
13823
|
+
} catch {
|
|
13824
|
+
}
|
|
13825
|
+
}
|
|
13826
|
+
}
|
|
13827
|
+
if (chainType === "ethereum") {
|
|
13828
|
+
const evmProviders = [];
|
|
13829
|
+
const seen = /* @__PURE__ */ new Set();
|
|
13830
|
+
const add = (p, name) => {
|
|
13831
|
+
if (p && typeof p.request === "function" && !seen.has(p)) {
|
|
13832
|
+
seen.add(p);
|
|
13833
|
+
evmProviders.push({ provider: p, name });
|
|
13834
|
+
}
|
|
13835
|
+
};
|
|
13836
|
+
add(anyWin.phantom?.ethereum, "Phantom");
|
|
13837
|
+
add(anyWin.coinbaseWalletExtension, "Coinbase");
|
|
13838
|
+
add(anyWin.trustwallet?.ethereum, "Trust Wallet");
|
|
13839
|
+
add(anyWin.okxwallet, "OKX Wallet");
|
|
13840
|
+
if (anyWin.__eip6963Providers) {
|
|
13841
|
+
for (const detail of anyWin.__eip6963Providers) {
|
|
13842
|
+
const rdns = detail.info?.rdns || "";
|
|
13843
|
+
let name = detail.info?.name || "Wallet";
|
|
13844
|
+
if (rdns.includes("metamask")) name = "MetaMask";
|
|
13845
|
+
else if (rdns.includes("rabby")) name = "Rabby";
|
|
13846
|
+
else if (rdns.includes("rainbow")) name = "Rainbow";
|
|
13847
|
+
add(detail.provider, name);
|
|
13848
|
+
}
|
|
13849
|
+
}
|
|
13850
|
+
if (win.ethereum) {
|
|
13851
|
+
const eth = win.ethereum;
|
|
13852
|
+
let name = "Wallet";
|
|
13853
|
+
if (eth.isMetaMask && !eth.isPhantom && !eth.isRabby) name = "MetaMask";
|
|
13854
|
+
else if (eth.isRabby) name = "Rabby";
|
|
13855
|
+
else if (eth.isRainbow) name = "Rainbow";
|
|
13856
|
+
else if (eth.isCoinbaseWallet) name = "Coinbase";
|
|
13857
|
+
add(eth, name);
|
|
13858
|
+
}
|
|
13859
|
+
for (const { provider, name } of evmProviders) {
|
|
13860
|
+
try {
|
|
13861
|
+
const accounts = await provider.request({ method: "eth_accounts" });
|
|
13862
|
+
if (accounts?.length > 0 && accounts[0].toLowerCase() === senderAddress.toLowerCase()) {
|
|
13863
|
+
return { chainFamily: "evm", provider, name, address: accounts[0] };
|
|
13864
|
+
}
|
|
13865
|
+
} catch {
|
|
13866
|
+
}
|
|
13867
|
+
}
|
|
13868
|
+
}
|
|
13869
|
+
return null;
|
|
13870
|
+
}
|
|
13871
|
+
|
|
13872
|
+
// src/components/withdrawals/WithdrawForm.tsx
|
|
13873
|
+
import { Fragment as Fragment11, jsx as jsx54, jsxs as jsxs47 } from "react/jsx-runtime";
|
|
13874
|
+
var t8 = i18n.withdrawModal;
|
|
13875
|
+
var tCrypto = i18n.transferCrypto;
|
|
13876
|
+
function formatProcessingTime2(seconds) {
|
|
13877
|
+
if (seconds === null) {
|
|
13878
|
+
return tCrypto.processingTime.lessThanMinutes.replace("{{minutes}}", "1");
|
|
13879
|
+
}
|
|
13880
|
+
const minutes = Math.ceil(seconds / 60);
|
|
13881
|
+
if (minutes < 60) {
|
|
13882
|
+
return tCrypto.processingTime.lessThanMinutes.replace("{{minutes}}", String(minutes));
|
|
13883
|
+
}
|
|
13884
|
+
const hours = Math.ceil(minutes / 60);
|
|
13885
|
+
return tCrypto.processingTime.lessThanHours.replace("{{hours}}", String(hours));
|
|
13886
|
+
}
|
|
13887
|
+
function computeBaseUnit(balanceBaseUnit, inputAmount, balanceAmount) {
|
|
13888
|
+
if (balanceAmount <= 0 || inputAmount <= 0) return "0";
|
|
13889
|
+
if (inputAmount >= balanceAmount) return balanceBaseUnit;
|
|
13890
|
+
const PRECISION = 10n ** 18n;
|
|
13891
|
+
const ratioScaled = BigInt(Math.round(inputAmount / balanceAmount * Number(PRECISION)));
|
|
13892
|
+
const result = BigInt(balanceBaseUnit) * ratioScaled / PRECISION;
|
|
13893
|
+
return result.toString();
|
|
13894
|
+
}
|
|
13895
|
+
function toSafeDecimalString(n, maxDecimals) {
|
|
13896
|
+
if (n === 0) return "0";
|
|
13897
|
+
return n.toFixed(maxDecimals).replace(/\.?0+$/, "");
|
|
13898
|
+
}
|
|
13899
|
+
function WithdrawForm({
|
|
13900
|
+
publishableKey,
|
|
13901
|
+
externalUserId,
|
|
13902
|
+
sourceChainType,
|
|
13903
|
+
selectedToken,
|
|
13904
|
+
selectedChain,
|
|
13905
|
+
sourceTokenSymbol,
|
|
13906
|
+
recipientAddressProp,
|
|
13907
|
+
balanceData,
|
|
13908
|
+
isLoadingBalance,
|
|
13909
|
+
minimumWithdrawAmountUsd,
|
|
13910
|
+
estimatedProcessingTime,
|
|
13911
|
+
maxSlippagePercent,
|
|
13912
|
+
priceImpactPercent,
|
|
13913
|
+
detectedWallet,
|
|
13914
|
+
sourceChainId,
|
|
13915
|
+
sourceTokenAddress,
|
|
13916
|
+
isWalletMatch,
|
|
13917
|
+
connectedWalletName,
|
|
13918
|
+
canWithdraw,
|
|
13919
|
+
onWithdraw,
|
|
13920
|
+
onWithdrawError,
|
|
13921
|
+
onDepositWalletCreation,
|
|
13922
|
+
onWithdrawSubmitted,
|
|
13923
|
+
footerLeft
|
|
13924
|
+
}) {
|
|
13925
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
13926
|
+
const [recipientAddress, setRecipientAddress] = useState30(recipientAddressProp || "");
|
|
13927
|
+
const [amount, setAmount] = useState30("");
|
|
13928
|
+
const [inputUnit, setInputUnit] = useState30("crypto");
|
|
13929
|
+
const [isSubmitting, setIsSubmitting] = useState30(false);
|
|
13930
|
+
const [submitError, setSubmitError] = useState30(null);
|
|
13931
|
+
const [detailsExpanded, setDetailsExpanded] = useState30(false);
|
|
13932
|
+
const [glossaryOpen, setGlossaryOpen] = useState30(false);
|
|
13933
|
+
useEffect25(() => {
|
|
13934
|
+
setRecipientAddress(recipientAddressProp || "");
|
|
13935
|
+
setAmount("");
|
|
13936
|
+
setInputUnit("crypto");
|
|
13937
|
+
setSubmitError(null);
|
|
13938
|
+
}, [recipientAddressProp]);
|
|
13939
|
+
const trimmedAddress = recipientAddress.trim();
|
|
13940
|
+
const [debouncedAddress, setDebouncedAddress] = useState30(trimmedAddress);
|
|
13941
|
+
useEffect25(() => {
|
|
13942
|
+
const id = setTimeout(() => setDebouncedAddress(trimmedAddress), 500);
|
|
13943
|
+
return () => clearTimeout(id);
|
|
13944
|
+
}, [trimmedAddress]);
|
|
13945
|
+
const {
|
|
13946
|
+
data: addressVerification,
|
|
13947
|
+
isLoading: isVerifyingAddress,
|
|
13948
|
+
error: verifyError
|
|
13949
|
+
} = useVerifyRecipientAddress({
|
|
13950
|
+
chainType: selectedChain?.chain_type,
|
|
13951
|
+
chainId: selectedChain?.chain_id,
|
|
13952
|
+
tokenAddress: selectedChain?.token_address,
|
|
13953
|
+
recipientAddress: debouncedAddress,
|
|
13954
|
+
publishableKey,
|
|
13955
|
+
enabled: debouncedAddress.length > 5 && !!selectedChain
|
|
13956
|
+
});
|
|
13957
|
+
const isDebouncing = trimmedAddress !== debouncedAddress;
|
|
13958
|
+
const addressError = useMemo11(() => {
|
|
13959
|
+
if (!trimmedAddress || trimmedAddress.length <= 5) return null;
|
|
13960
|
+
if (isDebouncing || isVerifyingAddress) return null;
|
|
13961
|
+
if (verifyError) return t8.invalidAddress;
|
|
13962
|
+
if (addressVerification && !addressVerification.valid) {
|
|
13963
|
+
if (addressVerification.failure_code === "account_not_found")
|
|
13964
|
+
return `Account not found on ${selectedChain?.chain_name}`;
|
|
13965
|
+
if (addressVerification.failure_code === "not_opted_in")
|
|
13966
|
+
return `Recipient has not opted in to ${selectedToken?.symbol} on ${selectedChain?.chain_name}`;
|
|
13967
|
+
return t8.invalidAddress;
|
|
13968
|
+
}
|
|
13969
|
+
return null;
|
|
13970
|
+
}, [trimmedAddress, isDebouncing, isVerifyingAddress, verifyError, addressVerification, selectedChain, selectedToken]);
|
|
13971
|
+
const isAddressValid = !isDebouncing && !!addressVerification?.valid && !addressError;
|
|
13972
|
+
const exchangeRate = useMemo11(() => {
|
|
13973
|
+
if (!balanceData?.exchangeRate) return 0;
|
|
13974
|
+
return parseFloat(balanceData.exchangeRate);
|
|
13975
|
+
}, [balanceData]);
|
|
13976
|
+
const balanceCrypto = useMemo11(() => {
|
|
13977
|
+
if (!balanceData?.balanceHuman) return 0;
|
|
13978
|
+
return parseFloat(balanceData.balanceHuman);
|
|
13979
|
+
}, [balanceData]);
|
|
13980
|
+
const balanceUsdNum = useMemo11(() => {
|
|
13981
|
+
if (!balanceData?.balanceUsd) return 0;
|
|
13982
|
+
return parseFloat(balanceData.balanceUsd);
|
|
13983
|
+
}, [balanceData]);
|
|
13984
|
+
const tokenSymbol = sourceTokenSymbol || balanceData?.symbol || "TOKEN";
|
|
13985
|
+
const sourceDecimals = balanceData?.decimals ?? 6;
|
|
13986
|
+
const cryptoAmountFromInput = useMemo11(() => {
|
|
13987
|
+
const val = parseFloat(amount);
|
|
13988
|
+
if (!val || val <= 0) return 0;
|
|
13989
|
+
if (inputUnit === "crypto") return val;
|
|
13990
|
+
return exchangeRate > 0 ? val / exchangeRate : 0;
|
|
13991
|
+
}, [amount, inputUnit, exchangeRate]);
|
|
13992
|
+
const fiatAmountFromInput = useMemo11(() => {
|
|
13993
|
+
const val = parseFloat(amount);
|
|
13994
|
+
if (!val || val <= 0) return 0;
|
|
13995
|
+
if (inputUnit === "fiat") return val;
|
|
13996
|
+
return val * exchangeRate;
|
|
13997
|
+
}, [amount, inputUnit, exchangeRate]);
|
|
13998
|
+
const convertedDisplay = useMemo11(() => {
|
|
13999
|
+
if (!amount || parseFloat(amount) <= 0) return null;
|
|
14000
|
+
if (inputUnit === "crypto") {
|
|
14001
|
+
return `$${fiatAmountFromInput.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
14002
|
+
}
|
|
14003
|
+
return `${cryptoAmountFromInput.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 6 })} ${tokenSymbol}`;
|
|
14004
|
+
}, [amount, inputUnit, fiatAmountFromInput, cryptoAmountFromInput, tokenSymbol]);
|
|
14005
|
+
const balanceDisplay = useMemo11(() => {
|
|
14006
|
+
if (isLoadingBalance || !balanceData) return null;
|
|
14007
|
+
if (inputUnit === "crypto") {
|
|
14008
|
+
return `${balanceCrypto.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })} ${tokenSymbol}`;
|
|
14009
|
+
}
|
|
14010
|
+
return `$${balanceUsdNum.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
14011
|
+
}, [isLoadingBalance, balanceData, inputUnit, balanceCrypto, balanceUsdNum, tokenSymbol]);
|
|
14012
|
+
const handleSwitchUnit = useCallback6(() => {
|
|
14013
|
+
const val = parseFloat(amount);
|
|
14014
|
+
if (!val || val <= 0 || exchangeRate <= 0) {
|
|
14015
|
+
setInputUnit((u) => u === "crypto" ? "fiat" : "crypto");
|
|
14016
|
+
setAmount("");
|
|
14017
|
+
return;
|
|
14018
|
+
}
|
|
14019
|
+
if (inputUnit === "crypto") {
|
|
14020
|
+
const fiat = val * exchangeRate;
|
|
14021
|
+
setAmount(fiat.toFixed(2));
|
|
14022
|
+
setInputUnit("fiat");
|
|
14023
|
+
} else {
|
|
14024
|
+
const crypto = val / exchangeRate;
|
|
14025
|
+
setAmount(crypto.toFixed(sourceDecimals > 6 ? 6 : sourceDecimals));
|
|
14026
|
+
setInputUnit("crypto");
|
|
14027
|
+
}
|
|
14028
|
+
}, [amount, inputUnit, exchangeRate, sourceDecimals]);
|
|
14029
|
+
const handleMaxClick = useCallback6(() => {
|
|
14030
|
+
if (inputUnit === "crypto") {
|
|
14031
|
+
if (balanceCrypto <= 0) return;
|
|
14032
|
+
setAmount(balanceData?.balanceHuman ?? "0");
|
|
14033
|
+
} else {
|
|
14034
|
+
if (balanceUsdNum <= 0) return;
|
|
14035
|
+
setAmount((Math.floor(balanceUsdNum * 100) / 100).toFixed(2));
|
|
14036
|
+
}
|
|
14037
|
+
}, [inputUnit, balanceCrypto, balanceUsdNum, balanceData]);
|
|
14038
|
+
const isBelowMinimum = minimumWithdrawAmountUsd !== null && fiatAmountFromInput > 0 && fiatAmountFromInput < minimumWithdrawAmountUsd;
|
|
14039
|
+
const isOverBalance = inputUnit === "crypto" ? cryptoAmountFromInput > 0 && balanceCrypto > 0 && cryptoAmountFromInput > balanceCrypto : fiatAmountFromInput > 0 && balanceUsdNum > 0 && fiatAmountFromInput > balanceUsdNum;
|
|
14040
|
+
const isFormValid = trimmedAddress.length > 0 && amount.trim().length > 0 && cryptoAmountFromInput > 0 && isAddressValid && !isBelowMinimum && !isOverBalance && !!balanceData;
|
|
14041
|
+
const handleWithdraw = useCallback6(async () => {
|
|
14042
|
+
if (!selectedToken || !selectedChain) return;
|
|
14043
|
+
if (!isFormValid) return;
|
|
14044
|
+
setIsSubmitting(true);
|
|
14045
|
+
setSubmitError(null);
|
|
14046
|
+
try {
|
|
14047
|
+
const depositWallet = await onDepositWalletCreation({
|
|
14048
|
+
destinationChainType: selectedChain.chain_type,
|
|
14049
|
+
destinationChainId: selectedChain.chain_id,
|
|
14050
|
+
destinationTokenAddress: selectedChain.token_address,
|
|
14051
|
+
recipientAddress: trimmedAddress
|
|
14052
|
+
});
|
|
14053
|
+
const amountBaseUnit = computeBaseUnit(
|
|
14054
|
+
balanceData.balanceBaseUnit,
|
|
14055
|
+
parseFloat(amount),
|
|
14056
|
+
inputUnit === "crypto" ? balanceCrypto : balanceUsdNum
|
|
14057
|
+
);
|
|
14058
|
+
const humanAmount = toSafeDecimalString(cryptoAmountFromInput, sourceDecimals);
|
|
14059
|
+
const txInfo = {
|
|
14060
|
+
sourceChainType,
|
|
14061
|
+
sourceChainId,
|
|
14062
|
+
sourceTokenAddress,
|
|
14063
|
+
sourceTokenSymbol: tokenSymbol,
|
|
14064
|
+
destinationChainType: selectedChain.chain_type,
|
|
14065
|
+
destinationChainId: selectedChain.chain_id,
|
|
14066
|
+
destinationTokenAddress: selectedChain.token_address,
|
|
14067
|
+
destinationTokenSymbol: selectedToken.symbol,
|
|
14068
|
+
amount: humanAmount,
|
|
14069
|
+
amountBaseUnit,
|
|
14070
|
+
withdrawIntentAddress: depositWallet.address,
|
|
14071
|
+
recipientAddress: trimmedAddress
|
|
14072
|
+
};
|
|
14073
|
+
if (detectedWallet) {
|
|
14074
|
+
if (detectedWallet.chainFamily === "evm" && isHypercoreChain(sourceChainId)) {
|
|
14075
|
+
await sendHypercoreWithdraw({
|
|
14076
|
+
provider: detectedWallet.provider,
|
|
14077
|
+
fromAddress: detectedWallet.address,
|
|
14078
|
+
depositWalletAddress: depositWallet.address,
|
|
14079
|
+
sourceTokenAddress,
|
|
14080
|
+
amount: humanAmount,
|
|
14081
|
+
tokenSymbol,
|
|
14082
|
+
publishableKey
|
|
14083
|
+
});
|
|
14084
|
+
} else if (detectedWallet.chainFamily === "evm") {
|
|
14085
|
+
await sendEvmWithdraw({
|
|
14086
|
+
provider: detectedWallet.provider,
|
|
14087
|
+
fromAddress: detectedWallet.address,
|
|
14088
|
+
depositWalletAddress: depositWallet.address,
|
|
14089
|
+
sourceTokenAddress,
|
|
14090
|
+
sourceChainId,
|
|
14091
|
+
amountBaseUnit
|
|
14092
|
+
});
|
|
14093
|
+
} else if (detectedWallet.chainFamily === "solana") {
|
|
14094
|
+
await sendSolanaWithdraw({
|
|
14095
|
+
provider: detectedWallet.provider,
|
|
14096
|
+
fromAddress: detectedWallet.address,
|
|
14097
|
+
depositWalletAddress: depositWallet.address,
|
|
14098
|
+
sourceTokenAddress,
|
|
14099
|
+
amountBaseUnit,
|
|
14100
|
+
publishableKey
|
|
14101
|
+
});
|
|
14102
|
+
}
|
|
14103
|
+
} else if (onWithdraw) {
|
|
14104
|
+
await onWithdraw(txInfo);
|
|
14105
|
+
} else {
|
|
14106
|
+
throw new Error("No withdrawal method available. Please connect a wallet.");
|
|
14107
|
+
}
|
|
14108
|
+
onWithdrawSubmitted?.(txInfo);
|
|
14109
|
+
} catch (err) {
|
|
14110
|
+
const raw = err instanceof Error ? err.message : "Withdrawal failed. Please try again.";
|
|
14111
|
+
setSubmitError(raw.length > 120 ? "Withdrawal failed. Please try again." : raw);
|
|
14112
|
+
onWithdrawError?.({
|
|
14113
|
+
message: raw,
|
|
14114
|
+
error: err,
|
|
14115
|
+
code: "WITHDRAW_FAILED"
|
|
14116
|
+
});
|
|
14117
|
+
} finally {
|
|
14118
|
+
setIsSubmitting(false);
|
|
14119
|
+
}
|
|
14120
|
+
}, [selectedToken, selectedChain, isFormValid, cryptoAmountFromInput, sourceDecimals, trimmedAddress, publishableKey, onWithdraw, detectedWallet, sourceTokenAddress, sourceChainId, onWithdrawError, onDepositWalletCreation, onWithdrawSubmitted, amount, inputUnit, balanceCrypto, balanceUsdNum, balanceData]);
|
|
14121
|
+
return /* @__PURE__ */ jsxs47(Fragment11, { children: [
|
|
14122
|
+
/* @__PURE__ */ jsxs47("div", { children: [
|
|
14123
|
+
/* @__PURE__ */ jsx54(
|
|
14124
|
+
"div",
|
|
14125
|
+
{
|
|
14126
|
+
className: "uf-text-xs uf-mb-1.5",
|
|
14127
|
+
style: { color: components.card.labelColor, fontFamily: fonts.medium },
|
|
14128
|
+
children: t8.recipientAddress
|
|
14129
|
+
}
|
|
14130
|
+
),
|
|
14131
|
+
/* @__PURE__ */ jsx54(
|
|
14132
|
+
"style",
|
|
14133
|
+
{
|
|
14134
|
+
dangerouslySetInnerHTML: {
|
|
14135
|
+
__html: `.uf-withdraw-addr::placeholder { color: ${components.search.placeholderColor}; }`
|
|
14136
|
+
}
|
|
14137
|
+
}
|
|
14138
|
+
),
|
|
14139
|
+
/* @__PURE__ */ jsxs47(
|
|
14140
|
+
"div",
|
|
14141
|
+
{
|
|
14142
|
+
className: "uf-flex uf-items-center uf-gap-1 uf-pr-2",
|
|
14143
|
+
style: {
|
|
14144
|
+
backgroundColor: components.search.backgroundColor,
|
|
14145
|
+
borderRadius: components.input.borderRadius,
|
|
14146
|
+
border: `${components.input.borderWidth}px solid ${addressError ? colors2.error : components.input.borderColor}`
|
|
14147
|
+
},
|
|
14148
|
+
children: [
|
|
14149
|
+
/* @__PURE__ */ jsx54(
|
|
14150
|
+
"input",
|
|
14151
|
+
{
|
|
14152
|
+
type: "text",
|
|
14153
|
+
placeholder: t8.recipientAddressPlaceholder,
|
|
14154
|
+
value: recipientAddress,
|
|
14155
|
+
onChange: (e) => {
|
|
14156
|
+
setRecipientAddress(e.target.value);
|
|
14157
|
+
setSubmitError(null);
|
|
14158
|
+
},
|
|
14159
|
+
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",
|
|
14160
|
+
style: {
|
|
14161
|
+
color: components.search.inputColor,
|
|
14162
|
+
fontFamily: fonts.regular
|
|
14163
|
+
}
|
|
14164
|
+
}
|
|
14165
|
+
),
|
|
14166
|
+
/* @__PURE__ */ jsx54(
|
|
14167
|
+
"button",
|
|
14168
|
+
{
|
|
14169
|
+
type: "button",
|
|
14170
|
+
onClick: async () => {
|
|
14171
|
+
try {
|
|
14172
|
+
const text = await navigator.clipboard.readText();
|
|
14173
|
+
if (text) {
|
|
14174
|
+
setRecipientAddress(text.trim());
|
|
14175
|
+
setSubmitError(null);
|
|
14176
|
+
}
|
|
14177
|
+
} catch {
|
|
14178
|
+
}
|
|
14179
|
+
},
|
|
14180
|
+
className: "uf-flex-shrink-0 uf-p-1 uf-rounded uf-transition-colors hover:uf-opacity-70",
|
|
14181
|
+
style: { color: colors2.foregroundMuted },
|
|
14182
|
+
title: "Paste from clipboard",
|
|
14183
|
+
children: /* @__PURE__ */ jsx54(ClipboardPaste, { className: "uf-w-4 uf-h-4" })
|
|
14184
|
+
}
|
|
14185
|
+
)
|
|
14186
|
+
]
|
|
14187
|
+
}
|
|
14188
|
+
),
|
|
14189
|
+
(isDebouncing || isVerifyingAddress) && trimmedAddress.length > 5 && /* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-1.5", children: [
|
|
14190
|
+
/* @__PURE__ */ jsx54(Loader26, { className: "uf-w-3 uf-h-3 uf-animate-spin", style: { color: colors2.foregroundMuted } }),
|
|
14191
|
+
/* @__PURE__ */ jsx54("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: t8.verifyingAddress })
|
|
14192
|
+
] }),
|
|
14193
|
+
addressError && /* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-gap-1.5 uf-mt-1.5", children: [
|
|
14194
|
+
/* @__PURE__ */ jsx54(AlertTriangle3, { className: "uf-w-3 uf-h-3", style: { color: colors2.error } }),
|
|
14195
|
+
/* @__PURE__ */ jsx54("span", { className: "uf-text-xs", style: { color: colors2.error, fontFamily: fonts.regular }, children: addressError })
|
|
14196
|
+
] })
|
|
14197
|
+
] }),
|
|
14198
|
+
/* @__PURE__ */ jsxs47("div", { children: [
|
|
14199
|
+
/* @__PURE__ */ jsxs47("div", { className: "uf-text-xs uf-mb-1.5", style: { color: components.card.labelColor, fontFamily: fonts.medium }, children: [
|
|
14200
|
+
t8.amount,
|
|
14201
|
+
minimumWithdrawAmountUsd != null && minimumWithdrawAmountUsd > 0 && /* @__PURE__ */ jsx54("span", { style: { color: colors2.warning, fontFamily: fonts.regular }, children: ` ($${minimumWithdrawAmountUsd.toFixed(2)} min)` })
|
|
14202
|
+
] }),
|
|
14203
|
+
/* @__PURE__ */ jsx54(
|
|
14204
|
+
"style",
|
|
14205
|
+
{
|
|
14206
|
+
dangerouslySetInnerHTML: {
|
|
14207
|
+
__html: `.uf-withdraw-amt::placeholder { color: ${components.search.placeholderColor}; }`
|
|
14208
|
+
}
|
|
14209
|
+
}
|
|
14210
|
+
),
|
|
14211
|
+
/* @__PURE__ */ jsxs47(
|
|
14212
|
+
"div",
|
|
14213
|
+
{
|
|
14214
|
+
className: "uf-flex uf-items-center uf-gap-2 uf-px-3 uf-py-2.5",
|
|
14215
|
+
style: {
|
|
14216
|
+
backgroundColor: components.search.backgroundColor,
|
|
14217
|
+
borderRadius: components.input.borderRadius,
|
|
14218
|
+
border: `${components.input.borderWidth}px solid ${components.input.borderColor}`
|
|
14219
|
+
},
|
|
14220
|
+
children: [
|
|
14221
|
+
/* @__PURE__ */ jsx54(
|
|
14222
|
+
"input",
|
|
14223
|
+
{
|
|
14224
|
+
type: "text",
|
|
14225
|
+
inputMode: "decimal",
|
|
14226
|
+
placeholder: "0.00",
|
|
14227
|
+
value: amount,
|
|
14228
|
+
onChange: (e) => {
|
|
14229
|
+
const val = e.target.value;
|
|
14230
|
+
if (val === "" || /^\d*\.?\d*$/.test(val)) {
|
|
14231
|
+
setAmount(val);
|
|
14232
|
+
setSubmitError(null);
|
|
14233
|
+
}
|
|
14234
|
+
},
|
|
14235
|
+
className: "uf-withdraw-amt uf-flex-1 uf-min-w-0 uf-bg-transparent uf-text-sm uf-outline-none",
|
|
14236
|
+
style: {
|
|
14237
|
+
color: components.search.inputColor,
|
|
14238
|
+
fontFamily: fonts.regular
|
|
14239
|
+
}
|
|
14240
|
+
}
|
|
14241
|
+
),
|
|
14242
|
+
/* @__PURE__ */ jsx54("span", { className: "uf-text-sm uf-shrink-0", style: { color: colors2.foregroundMuted, fontFamily: fonts.medium }, children: inputUnit === "crypto" ? tokenSymbol : "USD" }),
|
|
14243
|
+
/* @__PURE__ */ jsx54(
|
|
14244
|
+
"button",
|
|
14245
|
+
{
|
|
14246
|
+
type: "button",
|
|
14247
|
+
onClick: handleMaxClick,
|
|
14248
|
+
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",
|
|
14249
|
+
style: { backgroundColor: colors2.primary + "20", color: colors2.primary, fontFamily: fonts.medium },
|
|
14250
|
+
children: "Max"
|
|
14251
|
+
}
|
|
14252
|
+
)
|
|
14253
|
+
]
|
|
14254
|
+
}
|
|
14255
|
+
),
|
|
14256
|
+
/* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-justify-between uf-mt-1.5 uf-px-3", children: [
|
|
14257
|
+
/* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
|
|
14258
|
+
/* @__PURE__ */ jsx54("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: convertedDisplay || (inputUnit === "crypto" ? "$0.00" : `0.00 ${tokenSymbol}`) }),
|
|
14259
|
+
exchangeRate > 0 && /* @__PURE__ */ jsx54(
|
|
14260
|
+
"button",
|
|
14261
|
+
{
|
|
14262
|
+
type: "button",
|
|
14263
|
+
onClick: handleSwitchUnit,
|
|
14264
|
+
className: "uf-p-0.5 uf-rounded uf-transition-colors hover:uf-opacity-70",
|
|
14265
|
+
style: { color: colors2.foregroundMuted },
|
|
14266
|
+
title: "Switch unit",
|
|
14267
|
+
children: /* @__PURE__ */ jsx54(ArrowUpDown, { className: "uf-w-3 uf-h-3" })
|
|
14268
|
+
}
|
|
14269
|
+
)
|
|
14270
|
+
] }),
|
|
14271
|
+
/* @__PURE__ */ jsxs47("div", { children: [
|
|
14272
|
+
balanceDisplay && /* @__PURE__ */ jsxs47("span", { className: "uf-text-xs", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: [
|
|
14273
|
+
t8.balance,
|
|
14274
|
+
": ",
|
|
14275
|
+
balanceDisplay
|
|
14276
|
+
] }),
|
|
14277
|
+
isLoadingBalance && /* @__PURE__ */ jsx54("div", { className: "uf-h-3 uf-w-16 uf-bg-muted uf-rounded uf-animate-pulse" })
|
|
14278
|
+
] })
|
|
14279
|
+
] })
|
|
14280
|
+
] }),
|
|
14281
|
+
/* @__PURE__ */ jsxs47("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: [
|
|
14282
|
+
/* @__PURE__ */ jsxs47(
|
|
14283
|
+
"button",
|
|
14284
|
+
{
|
|
14285
|
+
type: "button",
|
|
14286
|
+
onClick: () => setDetailsExpanded(!detailsExpanded),
|
|
14287
|
+
className: "uf-w-full uf-flex uf-items-center uf-justify-between uf-py-2.5",
|
|
14288
|
+
children: [
|
|
14289
|
+
/* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
14290
|
+
/* @__PURE__ */ jsx54("div", { className: "uf-rounded-full uf-p-1", style: { backgroundColor: components.card.iconBackgroundColor }, children: /* @__PURE__ */ jsx54(Clock4, { className: "uf-w-3 uf-h-3", style: { color: components.card.iconColor } }) }),
|
|
14291
|
+
/* @__PURE__ */ jsxs47("span", { className: "uf-text-xs", style: { color: components.card.labelColor, fontFamily: fonts.regular }, children: [
|
|
14292
|
+
tCrypto.processingTime.label,
|
|
14293
|
+
":",
|
|
14294
|
+
" ",
|
|
14295
|
+
/* @__PURE__ */ jsx54("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: formatProcessingTime2(estimatedProcessingTime) })
|
|
14296
|
+
] })
|
|
14297
|
+
] }),
|
|
14298
|
+
detailsExpanded ? /* @__PURE__ */ jsx54(ChevronUp6, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } }) : /* @__PURE__ */ jsx54(ChevronDown7, { className: "uf-w-4 uf-h-4", style: { color: components.card.actionColor } })
|
|
14299
|
+
]
|
|
14300
|
+
}
|
|
14301
|
+
),
|
|
14302
|
+
detailsExpanded && /* @__PURE__ */ jsxs47("div", { className: "uf-pb-3 uf-space-y-2.5", children: [
|
|
14303
|
+
/* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
14304
|
+
/* @__PURE__ */ jsx54("div", { className: "uf-rounded-full uf-p-1", style: { backgroundColor: components.card.iconBackgroundColor }, children: /* @__PURE__ */ jsx54(ShieldCheck3, { className: "uf-w-3 uf-h-3", style: { color: components.card.iconColor } }) }),
|
|
14305
|
+
/* @__PURE__ */ jsxs47("span", { className: "uf-text-xs", style: { color: components.card.labelColor, fontFamily: fonts.regular }, children: [
|
|
14306
|
+
tCrypto.slippage.label,
|
|
14307
|
+
":",
|
|
14308
|
+
" ",
|
|
14309
|
+
/* @__PURE__ */ jsxs47("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: [
|
|
14310
|
+
tCrypto.slippage.auto,
|
|
14311
|
+
" \u2022 ",
|
|
14312
|
+
(maxSlippagePercent ?? 0.25).toFixed(2),
|
|
14313
|
+
"%"
|
|
14314
|
+
] })
|
|
14315
|
+
] })
|
|
14316
|
+
] }),
|
|
14317
|
+
/* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
14318
|
+
/* @__PURE__ */ jsx54("div", { className: "uf-rounded-full uf-p-1", style: { backgroundColor: components.card.iconBackgroundColor }, children: /* @__PURE__ */ jsx54(DollarSign3, { className: "uf-w-3 uf-h-3", style: { color: components.card.iconColor } }) }),
|
|
14319
|
+
/* @__PURE__ */ jsxs47("span", { className: "uf-text-xs", style: { color: components.card.labelColor, fontFamily: fonts.regular }, children: [
|
|
14320
|
+
tCrypto.priceImpact.label,
|
|
14321
|
+
":",
|
|
14322
|
+
" ",
|
|
14323
|
+
/* @__PURE__ */ jsxs47("span", { style: { color: components.card.titleColor, fontFamily: fonts.medium }, children: [
|
|
14324
|
+
(priceImpactPercent ?? 0).toFixed(2),
|
|
14325
|
+
"%"
|
|
14326
|
+
] })
|
|
14327
|
+
] })
|
|
14328
|
+
] })
|
|
14329
|
+
] })
|
|
14330
|
+
] }),
|
|
14331
|
+
!canWithdraw && !submitError && /* @__PURE__ */ jsxs47(
|
|
14332
|
+
"div",
|
|
14333
|
+
{
|
|
14334
|
+
className: "uf-flex uf-items-start uf-gap-2.5 uf-p-3 uf-rounded-xl",
|
|
14335
|
+
style: { backgroundColor: colors2.card, border: `1px solid ${colors2.border}` },
|
|
14336
|
+
children: [
|
|
14337
|
+
/* @__PURE__ */ jsx54(Wallet3, { className: "uf-w-4 uf-h-4 uf-flex-shrink-0 uf-mt-0.5", style: { color: colors2.warning } }),
|
|
14338
|
+
/* @__PURE__ */ jsx54("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." })
|
|
14339
|
+
]
|
|
14340
|
+
}
|
|
14341
|
+
),
|
|
14342
|
+
isWalletMatch && connectedWalletName ? /* @__PURE__ */ jsx54(
|
|
14343
|
+
"button",
|
|
14344
|
+
{
|
|
14345
|
+
type: "button",
|
|
14346
|
+
onClick: handleWithdraw,
|
|
14347
|
+
disabled: !isFormValid || !canWithdraw || isSubmitting || !selectedToken || !selectedChain,
|
|
14348
|
+
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",
|
|
14349
|
+
style: {
|
|
14350
|
+
backgroundColor: colors2.primary,
|
|
14351
|
+
color: colors2.primaryForeground,
|
|
14352
|
+
fontFamily: fonts.medium,
|
|
14353
|
+
borderRadius: components.button.borderRadius,
|
|
14354
|
+
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
|
|
14355
|
+
},
|
|
14356
|
+
children: isSubmitting ? /* @__PURE__ */ jsxs47(Fragment11, { children: [
|
|
14357
|
+
/* @__PURE__ */ jsx54(Loader26, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
|
|
14358
|
+
"Processing..."
|
|
14359
|
+
] }) : isOverBalance ? /* @__PURE__ */ jsx54(Fragment11, { children: "Insufficient balance" }) : isBelowMinimum ? /* @__PURE__ */ jsx54(Fragment11, { children: "Minimum amount not met" }) : submitError ? /* @__PURE__ */ jsx54(Fragment11, { children: "Withdrawal failed. Try again" }) : /* @__PURE__ */ jsxs47(Fragment11, { children: [
|
|
14360
|
+
/* @__PURE__ */ jsx54(Wallet3, { className: "uf-w-4 uf-h-4" }),
|
|
14361
|
+
"Withdraw from ",
|
|
14362
|
+
connectedWalletName
|
|
14363
|
+
] })
|
|
14364
|
+
}
|
|
14365
|
+
) : /* @__PURE__ */ jsx54(
|
|
14366
|
+
"button",
|
|
14367
|
+
{
|
|
14368
|
+
type: "button",
|
|
14369
|
+
onClick: handleWithdraw,
|
|
14370
|
+
disabled: !isFormValid || !canWithdraw || isSubmitting || !selectedToken || !selectedChain,
|
|
14371
|
+
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",
|
|
14372
|
+
style: {
|
|
14373
|
+
backgroundColor: colors2.primary,
|
|
14374
|
+
color: colors2.primaryForeground,
|
|
14375
|
+
fontFamily: fonts.medium,
|
|
14376
|
+
borderRadius: components.button.borderRadius,
|
|
14377
|
+
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
|
|
14378
|
+
},
|
|
14379
|
+
children: isSubmitting ? /* @__PURE__ */ jsxs47("span", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2", children: [
|
|
14380
|
+
/* @__PURE__ */ jsx54(Loader26, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
|
|
14381
|
+
"Processing..."
|
|
14382
|
+
] }) : isOverBalance ? "Insufficient balance" : isBelowMinimum ? "Minimum amount not met" : submitError ? "Withdrawal failed. Try again" : t8.withdraw
|
|
14383
|
+
}
|
|
14384
|
+
),
|
|
14385
|
+
/* @__PURE__ */ jsxs47("div", { className: "uf-flex uf-items-center uf-justify-between uf-text-xs uf-pt-1", children: [
|
|
14386
|
+
/* @__PURE__ */ jsx54("div", { children: footerLeft }),
|
|
14387
|
+
/* @__PURE__ */ jsx54(DepositFooterLinks, { onGlossaryClick: () => setGlossaryOpen(true) })
|
|
14388
|
+
] }),
|
|
14389
|
+
/* @__PURE__ */ jsx54(
|
|
14390
|
+
GlossaryModal,
|
|
14391
|
+
{
|
|
14392
|
+
open: glossaryOpen,
|
|
14393
|
+
onOpenChange: setGlossaryOpen
|
|
14394
|
+
}
|
|
14395
|
+
)
|
|
14396
|
+
] });
|
|
14397
|
+
}
|
|
14398
|
+
|
|
14399
|
+
// src/components/withdrawals/WithdrawExecutionItem.tsx
|
|
14400
|
+
import { ChevronRight as ChevronRight13 } from "lucide-react";
|
|
14401
|
+
import {
|
|
14402
|
+
ExecutionStatus as ExecutionStatus6,
|
|
14403
|
+
getIconUrl as getIconUrl5
|
|
14404
|
+
} from "@unifold/core";
|
|
14405
|
+
import { jsx as jsx55, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
14406
|
+
function WithdrawExecutionItem({
|
|
14407
|
+
execution,
|
|
14408
|
+
onClick
|
|
14409
|
+
}) {
|
|
14410
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
14411
|
+
const isPending = execution.status === ExecutionStatus6.PENDING || execution.status === ExecutionStatus6.WAITING || execution.status === ExecutionStatus6.DELAYED;
|
|
14412
|
+
const formatDateTime = (timestamp) => {
|
|
14413
|
+
try {
|
|
14414
|
+
const date = new Date(timestamp);
|
|
14415
|
+
const monthDay = date.toLocaleDateString("en-US", {
|
|
14416
|
+
month: "short",
|
|
14417
|
+
day: "numeric",
|
|
14418
|
+
year: "numeric"
|
|
14419
|
+
});
|
|
14420
|
+
const time = date.toLocaleTimeString("en-US", {
|
|
14421
|
+
hour: "numeric",
|
|
14422
|
+
minute: "2-digit",
|
|
14423
|
+
hour12: true
|
|
14424
|
+
}).toLowerCase();
|
|
14425
|
+
return `${monthDay} at ${time}`;
|
|
14426
|
+
} catch {
|
|
14427
|
+
return timestamp;
|
|
14428
|
+
}
|
|
14429
|
+
};
|
|
14430
|
+
const formatUsdAmount2 = (sourceAmountUsd) => {
|
|
14431
|
+
try {
|
|
14432
|
+
const amount = Number(sourceAmountUsd);
|
|
14433
|
+
return new Intl.NumberFormat("en-US", {
|
|
14434
|
+
style: "currency",
|
|
14435
|
+
currency: "USD",
|
|
14436
|
+
minimumFractionDigits: 2,
|
|
14437
|
+
maximumFractionDigits: 2
|
|
14438
|
+
}).format(amount);
|
|
14439
|
+
} catch {
|
|
14440
|
+
return "$0.00";
|
|
14441
|
+
}
|
|
14442
|
+
};
|
|
14443
|
+
return /* @__PURE__ */ jsxs48(
|
|
14444
|
+
"button",
|
|
14445
|
+
{
|
|
14446
|
+
onClick,
|
|
14447
|
+
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",
|
|
14448
|
+
style: {
|
|
14449
|
+
backgroundColor: components.card.backgroundColor,
|
|
14450
|
+
borderRadius: components.list.rowBorderRadius,
|
|
14451
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
14452
|
+
},
|
|
14453
|
+
children: [
|
|
14454
|
+
/* @__PURE__ */ jsxs48("div", { className: "uf-relative uf-flex-shrink-0 uf-w-9 uf-h-9", children: [
|
|
14455
|
+
/* @__PURE__ */ jsx55(
|
|
14456
|
+
"img",
|
|
14457
|
+
{
|
|
14458
|
+
src: execution.destination_token_metadata?.icon_url || getIconUrl5("/icons/tokens/svg/usdc.svg"),
|
|
14459
|
+
alt: "Token",
|
|
14460
|
+
width: 36,
|
|
14461
|
+
height: 36,
|
|
14462
|
+
loading: "lazy",
|
|
14463
|
+
className: "uf-rounded-full uf-w-9 uf-h-9"
|
|
14464
|
+
}
|
|
14465
|
+
),
|
|
14466
|
+
isPending ? /* @__PURE__ */ jsx55(
|
|
14467
|
+
"div",
|
|
14468
|
+
{
|
|
14469
|
+
className: "uf-absolute -uf-bottom-0.5 -uf-right-0.5 uf-rounded-full uf-p-0.5",
|
|
14470
|
+
style: { backgroundColor: colors2.warning },
|
|
14471
|
+
children: /* @__PURE__ */ jsx55(
|
|
14472
|
+
"svg",
|
|
14473
|
+
{
|
|
14474
|
+
width: "10",
|
|
14475
|
+
height: "10",
|
|
14476
|
+
viewBox: "0 0 12 12",
|
|
14477
|
+
fill: "none",
|
|
14478
|
+
className: "uf-animate-spin uf-block",
|
|
14479
|
+
children: /* @__PURE__ */ jsx55(
|
|
14480
|
+
"path",
|
|
14481
|
+
{
|
|
14482
|
+
d: "M6 1V3M6 9V11M1 6H3M9 6H11M2.5 2.5L4 4M8 8L9.5 9.5M2.5 9.5L4 8M8 4L9.5 2.5",
|
|
14483
|
+
stroke: "white",
|
|
14484
|
+
strokeWidth: "2",
|
|
14485
|
+
strokeLinecap: "round"
|
|
14486
|
+
}
|
|
14487
|
+
)
|
|
14488
|
+
}
|
|
14489
|
+
)
|
|
14490
|
+
}
|
|
14491
|
+
) : /* @__PURE__ */ jsx55(
|
|
14492
|
+
"div",
|
|
14493
|
+
{
|
|
14494
|
+
className: "uf-absolute -uf-bottom-0.5 -uf-right-0.5 uf-rounded-full uf-p-0.5",
|
|
14495
|
+
style: { backgroundColor: colors2.success },
|
|
14496
|
+
children: /* @__PURE__ */ jsx55(
|
|
14497
|
+
"svg",
|
|
14498
|
+
{
|
|
14499
|
+
width: "10",
|
|
14500
|
+
height: "10",
|
|
14501
|
+
viewBox: "0 0 12 12",
|
|
14502
|
+
fill: "none",
|
|
14503
|
+
className: "uf-block",
|
|
14504
|
+
children: /* @__PURE__ */ jsx55(
|
|
14505
|
+
"path",
|
|
14506
|
+
{
|
|
14507
|
+
d: "M10 3L4.5 8.5L2 6",
|
|
14508
|
+
stroke: "white",
|
|
14509
|
+
strokeWidth: "2",
|
|
14510
|
+
strokeLinecap: "round",
|
|
14511
|
+
strokeLinejoin: "round"
|
|
14512
|
+
}
|
|
14513
|
+
)
|
|
14514
|
+
}
|
|
14515
|
+
)
|
|
14516
|
+
}
|
|
14517
|
+
)
|
|
14518
|
+
] }),
|
|
14519
|
+
/* @__PURE__ */ jsxs48("div", { className: "uf-flex-1 uf-min-w-0", children: [
|
|
14520
|
+
/* @__PURE__ */ jsx55(
|
|
14521
|
+
"h3",
|
|
14522
|
+
{
|
|
14523
|
+
className: "uf-font-medium uf-text-sm uf-leading-tight",
|
|
14524
|
+
style: {
|
|
14525
|
+
color: components.card.titleColor,
|
|
14526
|
+
fontFamily: fonts.medium
|
|
14527
|
+
},
|
|
14528
|
+
children: isPending ? "Withdrawal processing" : "Withdrawal completed"
|
|
14529
|
+
}
|
|
14530
|
+
),
|
|
14531
|
+
/* @__PURE__ */ jsx55(
|
|
14532
|
+
"p",
|
|
14533
|
+
{
|
|
14534
|
+
className: "uf-text-xs uf-leading-tight",
|
|
14535
|
+
style: {
|
|
14536
|
+
color: components.card.subtitleColor,
|
|
14537
|
+
fontFamily: fonts.regular
|
|
14538
|
+
},
|
|
14539
|
+
children: formatDateTime(execution.created_at || (/* @__PURE__ */ new Date()).toISOString())
|
|
14540
|
+
}
|
|
14541
|
+
)
|
|
14542
|
+
] }),
|
|
14543
|
+
/* @__PURE__ */ jsx55(
|
|
14544
|
+
"span",
|
|
14545
|
+
{
|
|
14546
|
+
className: "uf-font-medium uf-text-sm uf-flex-shrink-0",
|
|
14547
|
+
style: {
|
|
14548
|
+
color: components.card.textRightColor,
|
|
14549
|
+
fontFamily: fonts.medium
|
|
14550
|
+
},
|
|
14551
|
+
children: formatUsdAmount2(execution.source_amount_usd || "0")
|
|
14552
|
+
}
|
|
14553
|
+
),
|
|
14554
|
+
/* @__PURE__ */ jsx55(
|
|
14555
|
+
ChevronRight13,
|
|
14556
|
+
{
|
|
14557
|
+
className: "uf-w-4 uf-h-4 uf-flex-shrink-0",
|
|
14558
|
+
style: { color: components.card.actionColor }
|
|
14559
|
+
}
|
|
14560
|
+
)
|
|
14561
|
+
]
|
|
14562
|
+
}
|
|
14563
|
+
);
|
|
14564
|
+
}
|
|
14565
|
+
|
|
14566
|
+
// src/components/withdrawals/WithdrawConfirmingView.tsx
|
|
14567
|
+
import { useState as useState31, useEffect as useEffect26 } from "react";
|
|
14568
|
+
import { Fragment as Fragment12, jsx as jsx56, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
14569
|
+
function truncateAddress4(addr) {
|
|
14570
|
+
if (addr.length <= 12) return addr;
|
|
14571
|
+
return `${addr.slice(0, 6)}...${addr.slice(-4)}`;
|
|
14572
|
+
}
|
|
14573
|
+
var SHOW_BUTTON_DELAY_MS = 5e3;
|
|
14574
|
+
function WithdrawConfirmingView({
|
|
14575
|
+
txInfo,
|
|
14576
|
+
executions,
|
|
14577
|
+
onClose,
|
|
14578
|
+
onViewTracker
|
|
14579
|
+
}) {
|
|
14580
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
14581
|
+
const [showButton, setShowButton] = useState31(false);
|
|
14582
|
+
const latestExecution = executions.length > 0 ? executions[executions.length - 1] : null;
|
|
14583
|
+
useEffect26(() => {
|
|
14584
|
+
if (latestExecution) return;
|
|
14585
|
+
const timer = setTimeout(() => setShowButton(true), SHOW_BUTTON_DELAY_MS);
|
|
14586
|
+
return () => clearTimeout(timer);
|
|
14587
|
+
}, [latestExecution]);
|
|
14588
|
+
const btnRadius = components.button.borderRadius;
|
|
14589
|
+
const btnBorder = `${components.button.borderWidth}px solid ${components.button.borderColor}`;
|
|
14590
|
+
if (latestExecution) {
|
|
14591
|
+
return /* @__PURE__ */ jsxs49(Fragment12, { children: [
|
|
14592
|
+
/* @__PURE__ */ jsx56(DepositHeader, { title: "Withdrawal Details", showClose: true, onClose }),
|
|
14593
|
+
/* @__PURE__ */ jsx56(DepositDetailContent, { execution: latestExecution, variant: "withdraw" }),
|
|
14594
|
+
/* @__PURE__ */ jsxs49("div", { className: "uf-flex uf-gap-2 uf-px-2 uf-pt-2", children: [
|
|
14595
|
+
/* @__PURE__ */ jsx56(
|
|
14596
|
+
"button",
|
|
14597
|
+
{
|
|
14598
|
+
type: "button",
|
|
14599
|
+
onClick: onViewTracker,
|
|
14600
|
+
className: "uf-flex-1 uf-py-2.5 uf-text-sm uf-transition-colors hover:uf-opacity-90",
|
|
14601
|
+
style: {
|
|
14602
|
+
backgroundColor: components.button.secondaryBackground,
|
|
14603
|
+
color: components.button.secondaryText,
|
|
14604
|
+
fontFamily: fonts.medium,
|
|
14605
|
+
borderRadius: btnRadius,
|
|
14606
|
+
border: btnBorder
|
|
14607
|
+
},
|
|
14608
|
+
children: "Withdrawal History"
|
|
14609
|
+
}
|
|
14610
|
+
),
|
|
14611
|
+
/* @__PURE__ */ jsx56(
|
|
14612
|
+
"button",
|
|
14613
|
+
{
|
|
14614
|
+
type: "button",
|
|
14615
|
+
onClick: onClose,
|
|
14616
|
+
className: "uf-flex-1 uf-py-2.5 uf-text-sm uf-transition-colors hover:uf-opacity-90",
|
|
14617
|
+
style: {
|
|
14618
|
+
backgroundColor: components.button.primaryBackground,
|
|
14619
|
+
color: components.button.primaryText,
|
|
14620
|
+
fontFamily: fonts.medium,
|
|
14621
|
+
borderRadius: btnRadius,
|
|
14622
|
+
border: btnBorder
|
|
14623
|
+
},
|
|
14624
|
+
children: "Close"
|
|
14625
|
+
}
|
|
14626
|
+
)
|
|
14627
|
+
] }),
|
|
14628
|
+
/* @__PURE__ */ jsx56("div", { className: "uf-pt-3", children: /* @__PURE__ */ jsx56(
|
|
14629
|
+
PoweredByUnifold,
|
|
14630
|
+
{
|
|
14631
|
+
color: colors2.foregroundMuted,
|
|
14632
|
+
className: "uf-flex uf-justify-center uf-shrink-0"
|
|
14633
|
+
}
|
|
14634
|
+
) })
|
|
14635
|
+
] });
|
|
14636
|
+
}
|
|
14637
|
+
return /* @__PURE__ */ jsxs49(Fragment12, { children: [
|
|
14638
|
+
/* @__PURE__ */ jsx56(DepositHeader, { title: "Withdrawal Status", showClose: true, onClose }),
|
|
14639
|
+
/* @__PURE__ */ jsxs49("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-16 uf-px-4", children: [
|
|
14640
|
+
/* @__PURE__ */ jsx56(
|
|
14641
|
+
"div",
|
|
14642
|
+
{
|
|
14643
|
+
className: "uf-w-20 uf-h-20 uf-rounded-full uf-flex uf-items-center uf-justify-center uf-mb-6",
|
|
14644
|
+
style: { backgroundColor: `${colors2.primary}20` },
|
|
14645
|
+
children: /* @__PURE__ */ jsx56(
|
|
14646
|
+
"svg",
|
|
14647
|
+
{
|
|
14648
|
+
width: "40",
|
|
14649
|
+
height: "40",
|
|
14650
|
+
viewBox: "0 0 24 24",
|
|
14651
|
+
fill: "none",
|
|
14652
|
+
className: "uf-animate-spin",
|
|
14653
|
+
children: /* @__PURE__ */ jsx56(
|
|
14654
|
+
"path",
|
|
14655
|
+
{
|
|
14656
|
+
d: "M21 12a9 9 0 1 1-6.22-8.56",
|
|
14657
|
+
stroke: colors2.primary,
|
|
14658
|
+
strokeWidth: "2.5",
|
|
14659
|
+
strokeLinecap: "round"
|
|
14660
|
+
}
|
|
14661
|
+
)
|
|
14662
|
+
}
|
|
14663
|
+
)
|
|
14664
|
+
}
|
|
14665
|
+
),
|
|
14666
|
+
/* @__PURE__ */ jsx56(
|
|
14667
|
+
"h3",
|
|
14668
|
+
{
|
|
14669
|
+
className: "uf-text-xl uf-mb-2",
|
|
14670
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
14671
|
+
children: "Checking Withdrawal"
|
|
14672
|
+
}
|
|
14673
|
+
),
|
|
14674
|
+
/* @__PURE__ */ jsxs49(
|
|
14675
|
+
"p",
|
|
14676
|
+
{
|
|
14677
|
+
className: "uf-text-sm uf-text-center",
|
|
14678
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
14679
|
+
children: [
|
|
14680
|
+
txInfo.amount,
|
|
14681
|
+
" ",
|
|
14682
|
+
txInfo.sourceTokenSymbol,
|
|
14683
|
+
" to",
|
|
14684
|
+
" ",
|
|
14685
|
+
truncateAddress4(txInfo.recipientAddress)
|
|
14686
|
+
]
|
|
14687
|
+
}
|
|
14688
|
+
)
|
|
14689
|
+
] }),
|
|
14690
|
+
showButton && /* @__PURE__ */ jsx56("div", { className: "uf-px-1 uf-pb-1", children: /* @__PURE__ */ jsx56(
|
|
14691
|
+
"button",
|
|
14692
|
+
{
|
|
14693
|
+
type: "button",
|
|
14694
|
+
onClick: onViewTracker,
|
|
14695
|
+
className: "uf-w-full uf-py-2.5 uf-text-sm uf-transition-colors hover:uf-opacity-90",
|
|
14696
|
+
style: {
|
|
14697
|
+
backgroundColor: components.button.secondaryBackground,
|
|
14698
|
+
color: components.button.secondaryText,
|
|
14699
|
+
fontFamily: fonts.medium,
|
|
14700
|
+
borderRadius: btnRadius,
|
|
14701
|
+
border: btnBorder
|
|
14702
|
+
},
|
|
14703
|
+
children: "Withdrawal History"
|
|
14704
|
+
}
|
|
14705
|
+
) }),
|
|
14706
|
+
/* @__PURE__ */ jsx56("div", { className: "uf-pt-3", children: /* @__PURE__ */ jsx56(
|
|
14707
|
+
PoweredByUnifold,
|
|
14708
|
+
{
|
|
14709
|
+
color: colors2.foregroundMuted,
|
|
14710
|
+
className: "uf-flex uf-justify-center uf-shrink-0"
|
|
14711
|
+
}
|
|
14712
|
+
) })
|
|
14713
|
+
] });
|
|
14714
|
+
}
|
|
14715
|
+
|
|
14716
|
+
// src/components/withdrawals/WithdrawModal.tsx
|
|
14717
|
+
import {
|
|
14718
|
+
createDepositAddress as createDepositAddress2,
|
|
14719
|
+
getWalletByChainType as getWalletByChainType4,
|
|
14720
|
+
ActionType as ActionType6
|
|
14721
|
+
} from "@unifold/core";
|
|
14722
|
+
import { Fragment as Fragment13, jsx as jsx57, jsxs as jsxs50 } from "react/jsx-runtime";
|
|
14723
|
+
var t9 = i18n.withdrawModal;
|
|
14724
|
+
var getChainKey5 = (chainId, chainType) => `${chainType}:${chainId}`;
|
|
14725
|
+
function WithdrawModal({
|
|
14726
|
+
open,
|
|
14727
|
+
onOpenChange,
|
|
14728
|
+
publishableKey,
|
|
14729
|
+
modalTitle,
|
|
14730
|
+
externalUserId,
|
|
14731
|
+
sourceChainType,
|
|
14732
|
+
sourceChainId,
|
|
14733
|
+
sourceTokenAddress,
|
|
14734
|
+
sourceTokenSymbol,
|
|
14735
|
+
recipientAddress: recipientAddressProp,
|
|
14736
|
+
senderAddress,
|
|
14737
|
+
onWithdraw,
|
|
14738
|
+
onWithdrawSuccess,
|
|
14739
|
+
onWithdrawError,
|
|
14740
|
+
theme = "dark",
|
|
14741
|
+
hideOverlay = false
|
|
14742
|
+
}) {
|
|
14743
|
+
const { colors: colors2, fonts, components } = useTheme();
|
|
14744
|
+
const [containerEl, setContainerEl] = useState32(null);
|
|
14745
|
+
const containerCallbackRef = useCallback7((el) => {
|
|
14746
|
+
setContainerEl(el);
|
|
14747
|
+
}, []);
|
|
14748
|
+
const [resolvedTheme, setResolvedTheme] = useState32(
|
|
14749
|
+
theme === "auto" ? "dark" : theme
|
|
14750
|
+
);
|
|
14751
|
+
useEffect27(() => {
|
|
14752
|
+
if (theme === "auto") {
|
|
14753
|
+
const mq = window.matchMedia("(prefers-color-scheme: dark)");
|
|
14754
|
+
setResolvedTheme(mq.matches ? "dark" : "light");
|
|
14755
|
+
const h = (e) => setResolvedTheme(e.matches ? "dark" : "light");
|
|
14756
|
+
mq.addEventListener("change", h);
|
|
14757
|
+
return () => mq.removeEventListener("change", h);
|
|
14758
|
+
}
|
|
14759
|
+
setResolvedTheme(theme);
|
|
14760
|
+
}, [theme]);
|
|
14761
|
+
const themeClass = resolvedTheme === "dark" ? "uf-dark" : "";
|
|
14762
|
+
const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDestinationTokens(publishableKey, open);
|
|
14763
|
+
const destinationTokens = tokensResponse?.data ?? [];
|
|
14764
|
+
const { data: sourceValidation, isLoading: isCheckingSourceToken } = useSourceTokenValidation({
|
|
14765
|
+
sourceChainType,
|
|
14766
|
+
sourceChainId,
|
|
14767
|
+
sourceTokenAddress,
|
|
14768
|
+
sourceTokenSymbol,
|
|
14769
|
+
publishableKey,
|
|
14770
|
+
enabled: open
|
|
14771
|
+
});
|
|
14772
|
+
const { data: balanceData, isLoading: isLoadingBalance } = useAddressBalance({
|
|
14773
|
+
address: senderAddress,
|
|
14774
|
+
chainType: sourceChainType,
|
|
14775
|
+
chainId: sourceChainId,
|
|
14776
|
+
tokenAddress: sourceTokenAddress,
|
|
14777
|
+
publishableKey,
|
|
14778
|
+
enabled: open
|
|
14779
|
+
});
|
|
14780
|
+
const [selectedToken, setSelectedToken] = useState32(null);
|
|
14781
|
+
const [selectedChain, setSelectedChain] = useState32(null);
|
|
14782
|
+
const [detectedWallet, setDetectedWallet] = useState32(null);
|
|
14783
|
+
const connectedWalletName = detectedWallet?.name ?? null;
|
|
14784
|
+
const isWalletMatch = !!detectedWallet;
|
|
14785
|
+
useEffect27(() => {
|
|
14786
|
+
if (!senderAddress || !open) {
|
|
14787
|
+
setDetectedWallet(null);
|
|
14788
|
+
return;
|
|
14789
|
+
}
|
|
14790
|
+
let cancelled = false;
|
|
14791
|
+
detectBrowserWallet(sourceChainType, senderAddress).then((wallet) => {
|
|
14792
|
+
if (!cancelled) setDetectedWallet(wallet);
|
|
14793
|
+
});
|
|
14794
|
+
return () => {
|
|
14795
|
+
cancelled = true;
|
|
14796
|
+
};
|
|
14797
|
+
}, [senderAddress, sourceChainType, open]);
|
|
14798
|
+
const [view, setView] = useState32("form");
|
|
14799
|
+
const [withdrawDepositWalletId, setWithdrawDepositWalletId] = useState32();
|
|
14800
|
+
const [selectedExecution, setSelectedExecution] = useState32(null);
|
|
14801
|
+
const [submittedTxInfo, setSubmittedTxInfo] = useState32(null);
|
|
14802
|
+
const { executions: realtimeExecutions } = useWithdrawPolling({
|
|
14803
|
+
userId: externalUserId,
|
|
14804
|
+
publishableKey,
|
|
14805
|
+
depositWalletId: withdrawDepositWalletId,
|
|
14806
|
+
enabled: !!withdrawDepositWalletId && open,
|
|
14807
|
+
onWithdrawSuccess: onWithdrawSuccess ? (d) => onWithdrawSuccess({ message: d.message, transaction: d.transaction }) : void 0,
|
|
14808
|
+
onWithdrawError
|
|
14809
|
+
});
|
|
14810
|
+
const { data: allWithdrawalsData } = useExecutions(externalUserId, publishableKey, {
|
|
14811
|
+
actionType: ActionType6.Withdraw,
|
|
14812
|
+
enabled: open,
|
|
14813
|
+
refetchInterval: view === "tracker" || view === "detail" ? 5e3 : 15e3
|
|
14814
|
+
});
|
|
14815
|
+
const allWithdrawals = allWithdrawalsData?.data ?? [];
|
|
14816
|
+
const handleDepositWalletCreation = useCallback7(async (params) => {
|
|
14817
|
+
const { data: wallets } = await createDepositAddress2(
|
|
14818
|
+
{
|
|
14819
|
+
external_user_id: externalUserId,
|
|
14820
|
+
destination_chain_type: params.destinationChainType,
|
|
14821
|
+
destination_chain_id: params.destinationChainId,
|
|
14822
|
+
destination_token_address: params.destinationTokenAddress,
|
|
14823
|
+
recipient_address: params.recipientAddress,
|
|
14824
|
+
action_type: ActionType6.Withdraw
|
|
14825
|
+
},
|
|
14826
|
+
publishableKey
|
|
14827
|
+
);
|
|
14828
|
+
const depositWallet = getWalletByChainType4(wallets, sourceChainType);
|
|
14829
|
+
if (!depositWallet) {
|
|
14830
|
+
throw new Error(`No deposit wallet available for ${sourceChainType}`);
|
|
14831
|
+
}
|
|
14832
|
+
setWithdrawDepositWalletId(depositWallet.id);
|
|
14833
|
+
return depositWallet;
|
|
14834
|
+
}, [externalUserId, publishableKey, sourceChainType]);
|
|
14835
|
+
const handleWithdrawSubmitted = useCallback7((txInfo) => {
|
|
14836
|
+
setSubmittedTxInfo(txInfo);
|
|
14837
|
+
setView("confirming");
|
|
14838
|
+
}, []);
|
|
14839
|
+
useEffect27(() => {
|
|
14840
|
+
if (!destinationTokens.length || selectedToken) return;
|
|
14841
|
+
const first = destinationTokens[0];
|
|
14842
|
+
if (first?.chains.length > 0) {
|
|
14843
|
+
setSelectedToken(first);
|
|
14844
|
+
setSelectedChain(first.chains[0]);
|
|
14845
|
+
}
|
|
14846
|
+
}, [destinationTokens, selectedToken]);
|
|
14847
|
+
const resetViewTimeoutRef = useRef10(null);
|
|
14848
|
+
const handleClose = useCallback7(() => {
|
|
14849
|
+
onOpenChange(false);
|
|
14850
|
+
if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
|
|
14851
|
+
resetViewTimeoutRef.current = setTimeout(() => {
|
|
14852
|
+
setSelectedToken(null);
|
|
14853
|
+
setSelectedChain(null);
|
|
14854
|
+
setView("form");
|
|
14855
|
+
setSelectedExecution(null);
|
|
14856
|
+
setSubmittedTxInfo(null);
|
|
14857
|
+
setWithdrawDepositWalletId(void 0);
|
|
14858
|
+
resetViewTimeoutRef.current = null;
|
|
14859
|
+
}, 200);
|
|
14860
|
+
}, [onOpenChange]);
|
|
14861
|
+
useLayoutEffect4(() => {
|
|
14862
|
+
if (!open) return;
|
|
14863
|
+
if (resetViewTimeoutRef.current) {
|
|
14864
|
+
clearTimeout(resetViewTimeoutRef.current);
|
|
14865
|
+
resetViewTimeoutRef.current = null;
|
|
14866
|
+
}
|
|
14867
|
+
setSelectedToken(null);
|
|
14868
|
+
setSelectedChain(null);
|
|
14869
|
+
setView("form");
|
|
14870
|
+
setSelectedExecution(null);
|
|
14871
|
+
setSubmittedTxInfo(null);
|
|
14872
|
+
setWithdrawDepositWalletId(void 0);
|
|
14873
|
+
}, [open]);
|
|
14874
|
+
useEffect27(() => () => {
|
|
14875
|
+
if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
|
|
14876
|
+
}, []);
|
|
14877
|
+
const handleTokenSymbolChange = useCallback7((symbol) => {
|
|
14878
|
+
const tok = destinationTokens.find((t11) => t11.symbol === symbol);
|
|
14879
|
+
if (tok) {
|
|
14880
|
+
setSelectedToken(tok);
|
|
14881
|
+
if (tok.chains.length > 0) setSelectedChain(tok.chains[0]);
|
|
14882
|
+
}
|
|
14883
|
+
}, [destinationTokens]);
|
|
14884
|
+
const handleChainKeyChange = useCallback7((chainKey) => {
|
|
14885
|
+
if (!selectedToken) return;
|
|
14886
|
+
const chain = selectedToken.chains.find((c) => getChainKey5(c.chain_id, c.chain_type) === chainKey);
|
|
14887
|
+
if (chain) setSelectedChain(chain);
|
|
14888
|
+
}, [selectedToken]);
|
|
14889
|
+
const isSourceSupported = sourceValidation?.isSupported ?? null;
|
|
14890
|
+
const canWithdraw = !!onWithdraw || isWalletMatch;
|
|
14891
|
+
const isAnyLoading = tokensLoading || isCheckingSourceToken;
|
|
14892
|
+
const withdrawPoweredByFooter = /* @__PURE__ */ jsx57("div", { className: "uf-pt-3", children: /* @__PURE__ */ jsx57(PoweredByUnifold, { color: colors2.foregroundMuted, className: "uf-flex uf-justify-center uf-shrink-0" }) });
|
|
14893
|
+
return /* @__PURE__ */ jsx57(PortalContainerProvider, { value: hideOverlay ? containerEl : null, children: /* @__PURE__ */ jsx57(Dialog, { open: hideOverlay || open, onOpenChange: hideOverlay ? void 0 : handleClose, modal: !hideOverlay, children: /* @__PURE__ */ jsx57(
|
|
14894
|
+
DialogContent,
|
|
14895
|
+
{
|
|
14896
|
+
ref: hideOverlay ? containerCallbackRef : void 0,
|
|
14897
|
+
hideOverlay,
|
|
14898
|
+
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}`}`,
|
|
14899
|
+
style: { backgroundColor: colors2.background },
|
|
14900
|
+
onPointerDownOutside: (e) => e.preventDefault(),
|
|
14901
|
+
onInteractOutside: (e) => e.preventDefault(),
|
|
14902
|
+
children: /* @__PURE__ */ jsx57(ThemeStyleInjector, { children: view === "confirming" && submittedTxInfo ? /* @__PURE__ */ jsx57(
|
|
14903
|
+
WithdrawConfirmingView,
|
|
14904
|
+
{
|
|
14905
|
+
txInfo: submittedTxInfo,
|
|
14906
|
+
executions: realtimeExecutions,
|
|
14907
|
+
onClose: handleClose,
|
|
14908
|
+
onViewTracker: () => setView("tracker")
|
|
14909
|
+
}
|
|
14910
|
+
) : view === "detail" && selectedExecution ? /* @__PURE__ */ jsxs50(Fragment13, { children: [
|
|
14911
|
+
/* @__PURE__ */ jsx57(DepositHeader, { title: "Withdrawal Details", showBack: true, showClose: !hideOverlay, onBack: () => {
|
|
14912
|
+
setSelectedExecution(null);
|
|
14913
|
+
setView("tracker");
|
|
14914
|
+
}, onClose: handleClose }),
|
|
14915
|
+
/* @__PURE__ */ jsx57(DepositDetailContent, { execution: selectedExecution, variant: "withdraw" }),
|
|
14916
|
+
withdrawPoweredByFooter
|
|
14917
|
+
] }) : view === "tracker" ? (
|
|
14918
|
+
/* ---------- Tracker view: execution list ---------- */
|
|
14919
|
+
/* @__PURE__ */ jsxs50(Fragment13, { children: [
|
|
14920
|
+
/* @__PURE__ */ jsx57(DepositHeader, { title: "Withdrawal History", showBack: true, showClose: !hideOverlay, onBack: () => setView("form"), onClose: handleClose }),
|
|
14921
|
+
/* @__PURE__ */ jsx57("div", { className: "uf-flex uf-flex-col uf-gap-2", style: { minHeight: 200 }, children: allWithdrawals.length === 0 ? /* @__PURE__ */ jsx57("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ jsx57("p", { className: "uf-text-sm", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: "No withdrawals to track yet" }) }) : allWithdrawals.map((ex) => /* @__PURE__ */ jsx57(
|
|
14922
|
+
WithdrawExecutionItem,
|
|
14923
|
+
{
|
|
14924
|
+
execution: ex,
|
|
14925
|
+
onClick: () => {
|
|
14926
|
+
setSelectedExecution(ex);
|
|
14927
|
+
setView("detail");
|
|
14928
|
+
}
|
|
14929
|
+
},
|
|
14930
|
+
ex.id
|
|
14931
|
+
)) }),
|
|
14932
|
+
withdrawPoweredByFooter
|
|
14933
|
+
] })
|
|
14934
|
+
) : (
|
|
14935
|
+
/* ---------- Form view (default) ---------- */
|
|
14936
|
+
/* @__PURE__ */ jsxs50(Fragment13, { children: [
|
|
14937
|
+
/* @__PURE__ */ jsx57(DepositHeader, { title: modalTitle || t9.title, showClose: !hideOverlay, onClose: handleClose }),
|
|
14938
|
+
/* @__PURE__ */ jsxs50("div", { className: "uf-flex uf-flex-col uf-gap-3", children: [
|
|
14939
|
+
isAnyLoading ? /* @__PURE__ */ jsx57("div", { className: "uf-space-y-3", children: [1, 2, 3].map((i) => /* @__PURE__ */ jsx57("div", { className: "uf-w-full uf-bg-secondary uf-rounded-xl uf-p-3 uf-flex uf-items-center uf-animate-pulse", children: /* @__PURE__ */ jsx57("div", { className: "uf-bg-muted uf-rounded-lg uf-w-full uf-h-10" }) }, i)) }) : isSourceSupported === false ? /* @__PURE__ */ jsxs50("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
|
|
14940
|
+
/* @__PURE__ */ jsx57("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__ */ jsx57(AlertTriangle4, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
|
|
14941
|
+
/* @__PURE__ */ jsx57("h3", { className: "uf-text-lg uf-font-semibold uf-mb-2", style: { color: colors2.foreground, fontFamily: fonts.medium }, children: "Unsupported Source Token" }),
|
|
14942
|
+
/* @__PURE__ */ jsx57("p", { className: "uf-text-sm uf-max-w-[280px]", style: { color: colors2.foregroundMuted, fontFamily: fonts.regular }, children: sourceValidation?.errorMessage })
|
|
14943
|
+
] }) : /* @__PURE__ */ jsxs50(Fragment13, { children: [
|
|
14944
|
+
/* @__PURE__ */ jsx57(
|
|
14945
|
+
WithdrawDoubleInput,
|
|
14946
|
+
{
|
|
14947
|
+
tokens: destinationTokens,
|
|
14948
|
+
selectedTokenSymbol: selectedToken?.symbol ?? null,
|
|
14949
|
+
selectedChainKey: selectedChain ? getChainKey5(selectedChain.chain_id, selectedChain.chain_type) : null,
|
|
14950
|
+
onTokenChange: handleTokenSymbolChange,
|
|
14951
|
+
onChainChange: handleChainKeyChange,
|
|
14952
|
+
isLoading: tokensLoading
|
|
14953
|
+
}
|
|
14954
|
+
),
|
|
14955
|
+
/* @__PURE__ */ jsx57(
|
|
14956
|
+
WithdrawForm,
|
|
14957
|
+
{
|
|
14958
|
+
publishableKey,
|
|
14959
|
+
externalUserId,
|
|
14960
|
+
sourceChainType,
|
|
14961
|
+
selectedToken,
|
|
14962
|
+
selectedChain,
|
|
14963
|
+
sourceTokenSymbol,
|
|
14964
|
+
recipientAddressProp,
|
|
14965
|
+
balanceData: balanceData ?? null,
|
|
14966
|
+
isLoadingBalance,
|
|
14967
|
+
minimumWithdrawAmountUsd: sourceValidation?.minimumAmountUsd ?? null,
|
|
14968
|
+
estimatedProcessingTime: sourceValidation?.estimatedProcessingTime ?? null,
|
|
14969
|
+
maxSlippagePercent: sourceValidation?.maxSlippagePercent ?? null,
|
|
14970
|
+
priceImpactPercent: sourceValidation?.priceImpactPercent ?? null,
|
|
14971
|
+
detectedWallet,
|
|
14972
|
+
sourceChainId,
|
|
14973
|
+
sourceTokenAddress,
|
|
14974
|
+
isWalletMatch,
|
|
14975
|
+
connectedWalletName,
|
|
14976
|
+
canWithdraw,
|
|
14977
|
+
onWithdraw,
|
|
14978
|
+
onWithdrawError,
|
|
14979
|
+
onDepositWalletCreation: handleDepositWalletCreation,
|
|
14980
|
+
onWithdrawSubmitted: handleWithdrawSubmitted,
|
|
14981
|
+
footerLeft: /* @__PURE__ */ jsxs50(
|
|
14982
|
+
"button",
|
|
14983
|
+
{
|
|
14984
|
+
onClick: () => setView("tracker"),
|
|
14985
|
+
className: "uf-flex uf-items-center uf-gap-1 uf-transition-colors hover:uf-opacity-70",
|
|
14986
|
+
style: { color: colors2.foregroundMuted },
|
|
14987
|
+
children: [
|
|
14988
|
+
/* @__PURE__ */ jsx57(Clock5, { className: "uf-w-3.5 uf-h-3.5" }),
|
|
14989
|
+
"Withdrawal History",
|
|
14990
|
+
/* @__PURE__ */ jsx57(ChevronRight14, { className: "uf-w-3 uf-h-3" })
|
|
14991
|
+
]
|
|
14992
|
+
}
|
|
14993
|
+
)
|
|
14994
|
+
}
|
|
14995
|
+
)
|
|
14996
|
+
] }),
|
|
14997
|
+
withdrawPoweredByFooter
|
|
14998
|
+
] })
|
|
14999
|
+
] })
|
|
15000
|
+
) })
|
|
15001
|
+
}
|
|
15002
|
+
) }) });
|
|
15003
|
+
}
|
|
15004
|
+
|
|
15005
|
+
// src/components/withdrawals/WithdrawTokenSelector.tsx
|
|
15006
|
+
import { useState as useState33, useMemo as useMemo12 } from "react";
|
|
15007
|
+
import { Search } from "lucide-react";
|
|
15008
|
+
import { jsx as jsx58, jsxs as jsxs51 } from "react/jsx-runtime";
|
|
15009
|
+
var t10 = i18n.withdrawModal;
|
|
15010
|
+
function WithdrawTokenSelector({
|
|
15011
|
+
tokens,
|
|
15012
|
+
onSelect,
|
|
15013
|
+
onBack
|
|
15014
|
+
}) {
|
|
15015
|
+
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
15016
|
+
const [searchQuery, setSearchQuery] = useState33("");
|
|
15017
|
+
const [hoveredKey, setHoveredKey] = useState33(null);
|
|
15018
|
+
const allOptions = useMemo12(() => {
|
|
15019
|
+
const options = [];
|
|
15020
|
+
tokens.forEach((token) => {
|
|
15021
|
+
token.chains.forEach((chain) => {
|
|
15022
|
+
options.push({ token, chain });
|
|
15023
|
+
});
|
|
15024
|
+
});
|
|
15025
|
+
return options;
|
|
15026
|
+
}, [tokens]);
|
|
15027
|
+
const filteredOptions = useMemo12(() => {
|
|
15028
|
+
if (!searchQuery.trim()) return allOptions;
|
|
15029
|
+
const query = searchQuery.toLowerCase();
|
|
15030
|
+
return allOptions.filter(
|
|
15031
|
+
({ token, chain }) => token.symbol.toLowerCase().includes(query) || token.name.toLowerCase().includes(query) || chain.chain_name.toLowerCase().includes(query)
|
|
15032
|
+
);
|
|
15033
|
+
}, [allOptions, searchQuery]);
|
|
15034
|
+
return /* @__PURE__ */ jsxs51(
|
|
15035
|
+
"div",
|
|
15036
|
+
{
|
|
15037
|
+
className: "uf-flex uf-flex-col",
|
|
15038
|
+
style: { minHeight: 0, flex: 1 },
|
|
15039
|
+
children: [
|
|
15040
|
+
/* @__PURE__ */ jsxs51("div", { className: "uf-pb-3", children: [
|
|
15041
|
+
/* @__PURE__ */ jsx58(
|
|
15042
|
+
"style",
|
|
15043
|
+
{
|
|
15044
|
+
dangerouslySetInnerHTML: {
|
|
15045
|
+
__html: `.uf-withdraw-token-search::placeholder { color: ${components.search.placeholderColor}; }`
|
|
15046
|
+
}
|
|
15047
|
+
}
|
|
15048
|
+
),
|
|
15049
|
+
/* @__PURE__ */ jsxs51("div", { style: { position: "relative" }, children: [
|
|
15050
|
+
/* @__PURE__ */ jsx58(
|
|
15051
|
+
Search,
|
|
15052
|
+
{
|
|
15053
|
+
className: "uf-absolute uf-left-3 uf-top-1/2 uf--translate-y-1/2 uf-w-4 uf-h-4",
|
|
15054
|
+
style: { color: components.search.placeholderColor }
|
|
15055
|
+
}
|
|
15056
|
+
),
|
|
15057
|
+
/* @__PURE__ */ jsx58(
|
|
15058
|
+
"input",
|
|
15059
|
+
{
|
|
15060
|
+
type: "text",
|
|
15061
|
+
placeholder: "Search token or network",
|
|
15062
|
+
value: searchQuery,
|
|
15063
|
+
onChange: (e) => setSearchQuery(e.target.value),
|
|
15064
|
+
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",
|
|
15065
|
+
style: {
|
|
15066
|
+
backgroundColor: components.search.backgroundColor,
|
|
15067
|
+
color: components.search.inputColor,
|
|
15068
|
+
fontFamily: fonts.regular,
|
|
15069
|
+
borderRadius: components.input.borderRadius,
|
|
15070
|
+
border: `${components.input.borderWidth}px solid ${components.input.borderColor}`
|
|
15071
|
+
}
|
|
15072
|
+
}
|
|
15073
|
+
)
|
|
15074
|
+
] })
|
|
15075
|
+
] }),
|
|
15076
|
+
/* @__PURE__ */ jsx58(
|
|
15077
|
+
"div",
|
|
15078
|
+
{
|
|
15079
|
+
className: "uf-text-xs uf-mb-2",
|
|
15080
|
+
style: {
|
|
15081
|
+
color: components.list.titleSectionColor,
|
|
15082
|
+
fontFamily: fonts.medium
|
|
15083
|
+
},
|
|
15084
|
+
children: t10.selectToken
|
|
15085
|
+
}
|
|
15086
|
+
),
|
|
15087
|
+
/* @__PURE__ */ jsx58(
|
|
15088
|
+
"div",
|
|
15089
|
+
{
|
|
15090
|
+
className: "uf-flex-1 uf-overflow-y-auto uf-min-h-0 uf--mx-6 uf-px-6 uf-pb-3",
|
|
15091
|
+
style: { scrollbarWidth: "none" },
|
|
15092
|
+
children: filteredOptions.length === 0 ? /* @__PURE__ */ jsx58(
|
|
15093
|
+
"div",
|
|
15094
|
+
{
|
|
15095
|
+
style: {
|
|
15096
|
+
textAlign: "center",
|
|
15097
|
+
padding: "2rem 0",
|
|
15098
|
+
fontSize: 14,
|
|
15099
|
+
color: components.container.subtitleColor,
|
|
15100
|
+
fontFamily: fonts.regular
|
|
15101
|
+
},
|
|
15102
|
+
children: t10.noTokensAvailable
|
|
15103
|
+
}
|
|
15104
|
+
) : /* @__PURE__ */ jsx58("div", { style: { display: "flex", flexDirection: "column", gap: 4 }, children: filteredOptions.map(({ token, chain }) => {
|
|
15105
|
+
const key = `${token.symbol}-${chain.chain_type}:${chain.chain_id}`;
|
|
15106
|
+
return /* @__PURE__ */ jsxs51(
|
|
15107
|
+
"button",
|
|
15108
|
+
{
|
|
15109
|
+
type: "button",
|
|
15110
|
+
onClick: () => onSelect(token, chain),
|
|
15111
|
+
onMouseEnter: () => setHoveredKey(key),
|
|
15112
|
+
onMouseLeave: () => setHoveredKey(null),
|
|
15113
|
+
className: "uf-transition-colors",
|
|
15114
|
+
style: {
|
|
15115
|
+
width: "100%",
|
|
15116
|
+
display: "flex",
|
|
15117
|
+
alignItems: "center",
|
|
15118
|
+
gap: 12,
|
|
15119
|
+
padding: 12,
|
|
15120
|
+
borderRadius: 12,
|
|
15121
|
+
border: "none",
|
|
15122
|
+
cursor: "pointer",
|
|
15123
|
+
textAlign: "left",
|
|
15124
|
+
backgroundColor: hoveredKey === key ? colors2.cardHover : "transparent"
|
|
15125
|
+
},
|
|
15126
|
+
children: [
|
|
15127
|
+
/* @__PURE__ */ jsxs51("div", { style: { position: "relative", flexShrink: 0 }, children: [
|
|
15128
|
+
/* @__PURE__ */ jsx58(
|
|
15129
|
+
"img",
|
|
15130
|
+
{
|
|
15131
|
+
src: token.icon_url,
|
|
15132
|
+
alt: token.symbol,
|
|
15133
|
+
width: 40,
|
|
15134
|
+
height: 40,
|
|
15135
|
+
loading: "lazy",
|
|
15136
|
+
className: "uf-rounded-full"
|
|
15137
|
+
}
|
|
15138
|
+
),
|
|
15139
|
+
/* @__PURE__ */ jsx58(
|
|
15140
|
+
"div",
|
|
15141
|
+
{
|
|
15142
|
+
style: {
|
|
15143
|
+
position: "absolute",
|
|
15144
|
+
bottom: -4,
|
|
15145
|
+
right: -4
|
|
15146
|
+
},
|
|
15147
|
+
children: /* @__PURE__ */ jsx58(
|
|
15148
|
+
"img",
|
|
15149
|
+
{
|
|
15150
|
+
src: chain.icon_url,
|
|
15151
|
+
alt: chain.chain_name,
|
|
15152
|
+
width: 20,
|
|
15153
|
+
height: 20,
|
|
15154
|
+
loading: "lazy",
|
|
15155
|
+
className: "uf-rounded-full uf-border-2"
|
|
15156
|
+
}
|
|
15157
|
+
)
|
|
15158
|
+
}
|
|
15159
|
+
)
|
|
15160
|
+
] }),
|
|
15161
|
+
/* @__PURE__ */ jsxs51("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
15162
|
+
/* @__PURE__ */ jsx58(
|
|
15163
|
+
"div",
|
|
15164
|
+
{
|
|
15165
|
+
style: {
|
|
15166
|
+
fontSize: 14,
|
|
15167
|
+
fontWeight: 500,
|
|
15168
|
+
color: components.card.titleColor,
|
|
15169
|
+
fontFamily: fonts.medium
|
|
15170
|
+
},
|
|
15171
|
+
children: token.symbol
|
|
15172
|
+
}
|
|
15173
|
+
),
|
|
15174
|
+
/* @__PURE__ */ jsxs51(
|
|
15175
|
+
"div",
|
|
15176
|
+
{
|
|
15177
|
+
style: {
|
|
15178
|
+
fontSize: 12,
|
|
15179
|
+
color: components.card.subtitleColor,
|
|
15180
|
+
fontFamily: fonts.regular
|
|
15181
|
+
},
|
|
15182
|
+
children: [
|
|
15183
|
+
token.name,
|
|
15184
|
+
" \u2022 ",
|
|
15185
|
+
chain.chain_name
|
|
15186
|
+
]
|
|
15187
|
+
}
|
|
15188
|
+
)
|
|
15189
|
+
] })
|
|
15190
|
+
]
|
|
15191
|
+
},
|
|
15192
|
+
key
|
|
15193
|
+
);
|
|
15194
|
+
}) })
|
|
15195
|
+
}
|
|
15196
|
+
),
|
|
15197
|
+
/* @__PURE__ */ jsx58("div", { className: "uf-pt-3 uf-pb-2 uf-shrink-0", children: /* @__PURE__ */ jsx58(
|
|
15198
|
+
PoweredByUnifold,
|
|
15199
|
+
{
|
|
15200
|
+
color: colors2.foregroundMuted,
|
|
15201
|
+
className: "uf-flex uf-justify-center uf-shrink-0"
|
|
15202
|
+
}
|
|
15203
|
+
) })
|
|
15204
|
+
]
|
|
15205
|
+
}
|
|
15206
|
+
);
|
|
15207
|
+
}
|
|
12133
15208
|
export {
|
|
12134
15209
|
Button,
|
|
12135
15210
|
BuyWithCard,
|
|
15211
|
+
CheckoutModal,
|
|
12136
15212
|
ConfirmingView,
|
|
12137
15213
|
CurrencyListItem,
|
|
12138
15214
|
CurrencyListSection,
|
|
@@ -12156,6 +15232,7 @@ export {
|
|
|
12156
15232
|
DialogPortal,
|
|
12157
15233
|
DialogTitle,
|
|
12158
15234
|
DialogTrigger,
|
|
15235
|
+
HYPERCORE_CHAIN_ID,
|
|
12159
15236
|
Select,
|
|
12160
15237
|
SelectContent,
|
|
12161
15238
|
SelectGroup,
|
|
@@ -12175,15 +15252,33 @@ export {
|
|
|
12175
15252
|
TransferCryptoButton,
|
|
12176
15253
|
TransferCryptoDoubleInput,
|
|
12177
15254
|
TransferCryptoSingleInput,
|
|
15255
|
+
WithdrawConfirmingView,
|
|
15256
|
+
WithdrawDoubleInput,
|
|
15257
|
+
WithdrawExecutionItem,
|
|
15258
|
+
WithdrawForm,
|
|
15259
|
+
WithdrawModal,
|
|
15260
|
+
WithdrawTokenSelector,
|
|
12178
15261
|
buttonVariants,
|
|
12179
15262
|
cn,
|
|
12180
15263
|
colors,
|
|
12181
15264
|
defaultColors,
|
|
15265
|
+
detectBrowserWallet,
|
|
12182
15266
|
getColors,
|
|
15267
|
+
isHypercoreChain,
|
|
12183
15268
|
mergeColors,
|
|
12184
15269
|
resolveComponentTokens,
|
|
15270
|
+
sendEvmWithdraw,
|
|
15271
|
+
sendHypercoreWithdraw,
|
|
15272
|
+
sendSolanaWithdraw,
|
|
12185
15273
|
truncateAddress,
|
|
15274
|
+
useAddressBalance,
|
|
12186
15275
|
useAllowedCountry,
|
|
12187
15276
|
useDepositPolling,
|
|
12188
|
-
|
|
15277
|
+
useDepositQuote,
|
|
15278
|
+
usePaymentIntent,
|
|
15279
|
+
useSourceTokenValidation,
|
|
15280
|
+
useSupportedDestinationTokens,
|
|
15281
|
+
useTheme,
|
|
15282
|
+
useVerifyRecipientAddress,
|
|
15283
|
+
useWithdrawPolling
|
|
12189
15284
|
};
|