@unifold/ui-react 0.1.52 → 0.1.53
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 +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +158 -75
- package/dist/index.mjs +152 -69
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -275,8 +275,10 @@ interface TransferCryptoSingleInputProps {
|
|
|
275
275
|
sourceTokenSymbol: string;
|
|
276
276
|
sourceAmountUsd: string | null;
|
|
277
277
|
} | null;
|
|
278
|
+
/** Product context sent to the API — "deposit" (default) or "payment". */
|
|
279
|
+
productType?: "deposit" | "payment";
|
|
278
280
|
}
|
|
279
|
-
declare function TransferCryptoSingleInput({ userId, publishableKey, clientSecret, recipientAddress, destinationChainType, destinationChainId, destinationTokenAddress, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol, depositConfirmationMode, onExecutionsChange, onDepositSuccess, onDepositError, wallets: externalWallets, onSourceTokenChange, checkoutQuote, }: TransferCryptoSingleInputProps): react_jsx_runtime.JSX.Element;
|
|
281
|
+
declare function TransferCryptoSingleInput({ userId, publishableKey, clientSecret, recipientAddress, destinationChainType, destinationChainId, destinationTokenAddress, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol, depositConfirmationMode, onExecutionsChange, onDepositSuccess, onDepositError, wallets: externalWallets, onSourceTokenChange, checkoutQuote, productType, }: TransferCryptoSingleInputProps): react_jsx_runtime.JSX.Element;
|
|
280
282
|
|
|
281
283
|
interface TransferCryptoDoubleInputProps {
|
|
282
284
|
userId: string;
|
|
@@ -840,6 +842,8 @@ interface UseDepositQuoteParams {
|
|
|
840
842
|
destinationChainType: string;
|
|
841
843
|
destinationChainId: string;
|
|
842
844
|
destinationTokenAddress: string;
|
|
845
|
+
/** When true, inflates source amount by expected slippage. Typically set by checkout flows. */
|
|
846
|
+
adjustForSlippage?: boolean;
|
|
843
847
|
enabled?: boolean;
|
|
844
848
|
}
|
|
845
849
|
/**
|
|
@@ -886,6 +890,7 @@ interface UseSupportedDepositTokensOptions {
|
|
|
886
890
|
destination_token_address?: string;
|
|
887
891
|
destination_chain_id?: string;
|
|
888
892
|
destination_chain_type?: string;
|
|
893
|
+
product_type?: "deposit" | "payment";
|
|
889
894
|
}
|
|
890
895
|
/**
|
|
891
896
|
* Hook to fetch supported deposit tokens with caching and deduplication via react-query.
|
package/dist/index.d.ts
CHANGED
|
@@ -275,8 +275,10 @@ interface TransferCryptoSingleInputProps {
|
|
|
275
275
|
sourceTokenSymbol: string;
|
|
276
276
|
sourceAmountUsd: string | null;
|
|
277
277
|
} | null;
|
|
278
|
+
/** Product context sent to the API — "deposit" (default) or "payment". */
|
|
279
|
+
productType?: "deposit" | "payment";
|
|
278
280
|
}
|
|
279
|
-
declare function TransferCryptoSingleInput({ userId, publishableKey, clientSecret, recipientAddress, destinationChainType, destinationChainId, destinationTokenAddress, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol, depositConfirmationMode, onExecutionsChange, onDepositSuccess, onDepositError, wallets: externalWallets, onSourceTokenChange, checkoutQuote, }: TransferCryptoSingleInputProps): react_jsx_runtime.JSX.Element;
|
|
281
|
+
declare function TransferCryptoSingleInput({ userId, publishableKey, clientSecret, recipientAddress, destinationChainType, destinationChainId, destinationTokenAddress, defaultSourceChainType, defaultSourceChainId, defaultSourceTokenAddress, defaultSourceSymbol, depositConfirmationMode, onExecutionsChange, onDepositSuccess, onDepositError, wallets: externalWallets, onSourceTokenChange, checkoutQuote, productType, }: TransferCryptoSingleInputProps): react_jsx_runtime.JSX.Element;
|
|
280
282
|
|
|
281
283
|
interface TransferCryptoDoubleInputProps {
|
|
282
284
|
userId: string;
|
|
@@ -840,6 +842,8 @@ interface UseDepositQuoteParams {
|
|
|
840
842
|
destinationChainType: string;
|
|
841
843
|
destinationChainId: string;
|
|
842
844
|
destinationTokenAddress: string;
|
|
845
|
+
/** When true, inflates source amount by expected slippage. Typically set by checkout flows. */
|
|
846
|
+
adjustForSlippage?: boolean;
|
|
843
847
|
enabled?: boolean;
|
|
844
848
|
}
|
|
845
849
|
/**
|
|
@@ -886,6 +890,7 @@ interface UseSupportedDepositTokensOptions {
|
|
|
886
890
|
destination_token_address?: string;
|
|
887
891
|
destination_chain_id?: string;
|
|
888
892
|
destination_chain_type?: string;
|
|
893
|
+
product_type?: "deposit" | "payment";
|
|
889
894
|
}
|
|
890
895
|
/**
|
|
891
896
|
* Hook to fetch supported deposit tokens with caching and deduplication via react-query.
|
package/dist/index.js
CHANGED
|
@@ -2608,14 +2608,14 @@ function BuyWithCard({
|
|
|
2608
2608
|
);
|
|
2609
2609
|
if (matchingCurrency) {
|
|
2610
2610
|
setCurrency(matchingCurrency.currency_code.toLowerCase());
|
|
2611
|
-
if (!amount && !hasManualAmountEntry) {
|
|
2611
|
+
if (!amount && !hasManualAmountEntry && matchingCurrency.default_amount != null) {
|
|
2612
2612
|
setAmount(matchingCurrency.default_amount.toString());
|
|
2613
2613
|
}
|
|
2614
2614
|
} else if (!amount && !hasManualAmountEntry) {
|
|
2615
2615
|
const usdCurrency = fiatCurrencies.find(
|
|
2616
2616
|
(c) => c.currency_code.toLowerCase() === "usd"
|
|
2617
2617
|
);
|
|
2618
|
-
if (usdCurrency) {
|
|
2618
|
+
if (usdCurrency?.default_amount != null) {
|
|
2619
2619
|
setAmount(usdCurrency.default_amount.toString());
|
|
2620
2620
|
}
|
|
2621
2621
|
}
|
|
@@ -2633,7 +2633,7 @@ function BuyWithCard({
|
|
|
2633
2633
|
const currentCurrency = fiatCurrencies.find(
|
|
2634
2634
|
(c) => c.currency_code.toLowerCase() === currency.toLowerCase()
|
|
2635
2635
|
);
|
|
2636
|
-
if (currentCurrency) {
|
|
2636
|
+
if (currentCurrency?.default_amount != null) {
|
|
2637
2637
|
setAmount(currentCurrency.default_amount.toString());
|
|
2638
2638
|
}
|
|
2639
2639
|
}
|
|
@@ -6957,7 +6957,7 @@ function useProjectConfig({
|
|
|
6957
6957
|
}
|
|
6958
6958
|
|
|
6959
6959
|
// src/components/deposits/DepositModal.tsx
|
|
6960
|
-
var
|
|
6960
|
+
var import_core24 = require("@unifold/core");
|
|
6961
6961
|
|
|
6962
6962
|
// src/hooks/use-allowed-country.ts
|
|
6963
6963
|
var import_react_query6 = require("@tanstack/react-query");
|
|
@@ -7086,11 +7086,16 @@ function useAddressValidation({
|
|
|
7086
7086
|
var import_react_query8 = require("@tanstack/react-query");
|
|
7087
7087
|
var import_core18 = require("@unifold/core");
|
|
7088
7088
|
function useSupportedDepositTokens(publishableKey, options) {
|
|
7089
|
-
const
|
|
7090
|
-
|
|
7091
|
-
|
|
7092
|
-
|
|
7093
|
-
|
|
7089
|
+
const hasDestination = options?.destination_token_address && options?.destination_chain_id && options?.destination_chain_type;
|
|
7090
|
+
const filteredOptions = {
|
|
7091
|
+
...hasDestination ? {
|
|
7092
|
+
destination_token_address: options.destination_token_address,
|
|
7093
|
+
destination_chain_id: options.destination_chain_id,
|
|
7094
|
+
destination_chain_type: options.destination_chain_type
|
|
7095
|
+
} : {},
|
|
7096
|
+
...options?.product_type ? { product_type: options.product_type } : {}
|
|
7097
|
+
};
|
|
7098
|
+
const hasFilteredOptions = Object.keys(filteredOptions).length > 0;
|
|
7094
7099
|
return (0, import_react_query8.useQuery)({
|
|
7095
7100
|
queryKey: [
|
|
7096
7101
|
"unifold",
|
|
@@ -7098,9 +7103,13 @@ function useSupportedDepositTokens(publishableKey, options) {
|
|
|
7098
7103
|
publishableKey,
|
|
7099
7104
|
filteredOptions?.destination_token_address ?? null,
|
|
7100
7105
|
filteredOptions?.destination_chain_id ?? null,
|
|
7101
|
-
filteredOptions?.destination_chain_type ?? null
|
|
7106
|
+
filteredOptions?.destination_chain_type ?? null,
|
|
7107
|
+
filteredOptions?.product_type ?? null
|
|
7102
7108
|
],
|
|
7103
|
-
queryFn: () => (0, import_core18.getSupportedDepositTokens)(
|
|
7109
|
+
queryFn: () => (0, import_core18.getSupportedDepositTokens)(
|
|
7110
|
+
publishableKey,
|
|
7111
|
+
hasFilteredOptions ? filteredOptions : void 0
|
|
7112
|
+
),
|
|
7104
7113
|
staleTime: 1e3 * 60 * 5,
|
|
7105
7114
|
// 5 minutes — token list rarely changes
|
|
7106
7115
|
gcTime: 1e3 * 60 * 30,
|
|
@@ -8378,7 +8387,8 @@ function TransferCryptoSingleInput({
|
|
|
8378
8387
|
onDepositError,
|
|
8379
8388
|
wallets: externalWallets,
|
|
8380
8389
|
onSourceTokenChange,
|
|
8381
|
-
checkoutQuote
|
|
8390
|
+
checkoutQuote,
|
|
8391
|
+
productType
|
|
8382
8392
|
}) {
|
|
8383
8393
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
8384
8394
|
const isDarkMode = themeClass.includes("uf-dark");
|
|
@@ -8391,7 +8401,8 @@ function TransferCryptoSingleInput({
|
|
|
8391
8401
|
const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDepositTokens(publishableKey, {
|
|
8392
8402
|
destination_token_address: destinationTokenAddress,
|
|
8393
8403
|
destination_chain_id: destinationChainId,
|
|
8394
|
-
destination_chain_type: destinationChainType
|
|
8404
|
+
destination_chain_type: destinationChainType,
|
|
8405
|
+
product_type: productType
|
|
8395
8406
|
});
|
|
8396
8407
|
const supportedTokens = tokensResponse?.data ?? [];
|
|
8397
8408
|
const { token, chain, setToken, setChain, initialSelectionDone } = useDefaultSourceToken({
|
|
@@ -9444,7 +9455,59 @@ function TransferCryptoDoubleInput({
|
|
|
9444
9455
|
|
|
9445
9456
|
// src/components/deposits/BrowserWalletModal.tsx
|
|
9446
9457
|
var React26 = __toESM(require("react"));
|
|
9458
|
+
var import_core23 = require("@unifold/core");
|
|
9459
|
+
|
|
9460
|
+
// src/hooks/use-deposit-quote.ts
|
|
9461
|
+
var import_react_query9 = require("@tanstack/react-query");
|
|
9447
9462
|
var import_core22 = require("@unifold/core");
|
|
9463
|
+
function useDepositQuote(params) {
|
|
9464
|
+
const {
|
|
9465
|
+
publishableKey,
|
|
9466
|
+
sourceChainType,
|
|
9467
|
+
sourceChainId,
|
|
9468
|
+
sourceTokenAddress,
|
|
9469
|
+
destinationAmount,
|
|
9470
|
+
destinationChainType,
|
|
9471
|
+
destinationChainId,
|
|
9472
|
+
destinationTokenAddress,
|
|
9473
|
+
adjustForSlippage,
|
|
9474
|
+
enabled = true
|
|
9475
|
+
} = params;
|
|
9476
|
+
const request = {
|
|
9477
|
+
source_chain_type: sourceChainType,
|
|
9478
|
+
source_chain_id: sourceChainId,
|
|
9479
|
+
source_token_address: sourceTokenAddress,
|
|
9480
|
+
destination_amount: destinationAmount,
|
|
9481
|
+
destination_chain_type: destinationChainType,
|
|
9482
|
+
destination_chain_id: destinationChainId,
|
|
9483
|
+
destination_token_address: destinationTokenAddress,
|
|
9484
|
+
...adjustForSlippage ? { adjust_for_slippage: true } : {}
|
|
9485
|
+
};
|
|
9486
|
+
return (0, import_react_query9.useQuery)({
|
|
9487
|
+
queryKey: [
|
|
9488
|
+
"unifold",
|
|
9489
|
+
"depositQuote",
|
|
9490
|
+
sourceChainType,
|
|
9491
|
+
sourceChainId,
|
|
9492
|
+
sourceTokenAddress,
|
|
9493
|
+
destinationAmount,
|
|
9494
|
+
destinationChainType,
|
|
9495
|
+
destinationChainId,
|
|
9496
|
+
destinationTokenAddress,
|
|
9497
|
+
adjustForSlippage,
|
|
9498
|
+
publishableKey
|
|
9499
|
+
],
|
|
9500
|
+
queryFn: () => (0, import_core22.getDepositQuote)(request, publishableKey),
|
|
9501
|
+
enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
|
|
9502
|
+
staleTime: 3e4,
|
|
9503
|
+
gcTime: 5 * 6e4,
|
|
9504
|
+
refetchInterval: 3e4,
|
|
9505
|
+
refetchIntervalInBackground: false,
|
|
9506
|
+
refetchOnWindowFocus: true,
|
|
9507
|
+
retry: 2,
|
|
9508
|
+
retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 5e3)
|
|
9509
|
+
});
|
|
9510
|
+
}
|
|
9448
9511
|
|
|
9449
9512
|
// src/components/deposits/browser-wallets/types.ts
|
|
9450
9513
|
var BROWSER_WALLET_STEP_MIN_HEIGHT_CLASS = "uf-min-h-[460px]";
|
|
@@ -9934,7 +9997,7 @@ function EnterAmountView({
|
|
|
9934
9997
|
}
|
|
9935
9998
|
)
|
|
9936
9999
|
] }) }),
|
|
9937
|
-
tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && (isCheckout && checkoutAmountUsd &&
|
|
10000
|
+
tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && (isCheckout && checkoutAmountUsd && tokenChainDetails.minimum_deposit_amount_usd > parseFloat(checkoutAmountUsd) - parseFloat(checkoutReceivedUsd || "0") + 5e-3 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
9938
10001
|
"div",
|
|
9939
10002
|
{
|
|
9940
10003
|
className: "uf-rounded-lg uf-px-3 uf-py-2 uf-mb-3 uf-text-center",
|
|
@@ -10548,7 +10611,11 @@ function BrowserWalletModal({
|
|
|
10548
10611
|
checkoutReceivedUsd,
|
|
10549
10612
|
onNewDeposit,
|
|
10550
10613
|
onDone,
|
|
10551
|
-
paymentIntentStatus
|
|
10614
|
+
paymentIntentStatus,
|
|
10615
|
+
checkoutQuote,
|
|
10616
|
+
checkoutDestination,
|
|
10617
|
+
checkoutRemainingBaseUnits,
|
|
10618
|
+
productType
|
|
10552
10619
|
}) {
|
|
10553
10620
|
const { colors: colors2, fonts, components } = useTheme();
|
|
10554
10621
|
const [step, setStep] = React26.useState("select-token");
|
|
@@ -10570,7 +10637,49 @@ function BrowserWalletModal({
|
|
|
10570
10637
|
const themeClass = theme === "dark" ? "uf-dark" : "";
|
|
10571
10638
|
const chainType = depositWallet.chain_type;
|
|
10572
10639
|
const recipientAddress = depositWallet.address;
|
|
10640
|
+
const isCheckoutMode = !!checkoutAmountUsd;
|
|
10573
10641
|
const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
|
|
10642
|
+
const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
|
|
10643
|
+
const effectiveDestinationAmount = React26.useMemo(() => {
|
|
10644
|
+
if (!checkoutRemainingBaseUnits || checkoutRemainingBaseUnits === "0") return "0";
|
|
10645
|
+
if (!checkoutAmountUsd) return checkoutRemainingBaseUnits;
|
|
10646
|
+
const remaining = BigInt(checkoutRemainingBaseUnits);
|
|
10647
|
+
const minUsd = Math.max(tokenChainDetails?.minimum_deposit_amount_usd ?? 0, 3);
|
|
10648
|
+
const totalUsd = parseFloat(checkoutAmountUsd);
|
|
10649
|
+
if (totalUsd <= 0) return remaining > 0n ? remaining.toString() : "0";
|
|
10650
|
+
const receivedUsd = parseFloat(checkoutReceivedUsd ?? "0");
|
|
10651
|
+
const remainingUsd = totalUsd - receivedUsd;
|
|
10652
|
+
if (remainingUsd <= 0) return "0";
|
|
10653
|
+
const baseUnitsPerUsd = Number(remaining) / remainingUsd;
|
|
10654
|
+
const minBaseUnits = BigInt(Math.ceil(minUsd * baseUnitsPerUsd));
|
|
10655
|
+
const effective = remaining > minBaseUnits ? remaining : minBaseUnits;
|
|
10656
|
+
return effective > 0n ? effective.toString() : "0";
|
|
10657
|
+
}, [checkoutRemainingBaseUnits, checkoutAmountUsd, checkoutReceivedUsd, tokenChainDetails]);
|
|
10658
|
+
const { data: walletCheckoutQuote } = useDepositQuote({
|
|
10659
|
+
publishableKey,
|
|
10660
|
+
sourceChainType: selectedToken?.chain_type ?? "",
|
|
10661
|
+
sourceChainId: selectedToken?.chain_id ?? "",
|
|
10662
|
+
sourceTokenAddress: selectedToken?.token_address ?? "",
|
|
10663
|
+
destinationAmount: effectiveDestinationAmount,
|
|
10664
|
+
destinationChainType: checkoutDestination?.chainType ?? "",
|
|
10665
|
+
destinationChainId: checkoutDestination?.chainId ?? "",
|
|
10666
|
+
destinationTokenAddress: checkoutDestination?.tokenAddress ?? "",
|
|
10667
|
+
adjustForSlippage: true,
|
|
10668
|
+
enabled: open && isCheckoutMode && !!selectedToken && !!checkoutDestination && effectiveDestinationAmount !== "0"
|
|
10669
|
+
});
|
|
10670
|
+
const activeCheckoutQuote = React26.useMemo(() => {
|
|
10671
|
+
if (!isCheckoutMode) return null;
|
|
10672
|
+
if (walletCheckoutQuote) {
|
|
10673
|
+
return {
|
|
10674
|
+
sourceAmount: walletCheckoutQuote.source_amount,
|
|
10675
|
+
sourceTokenDecimals: walletCheckoutQuote.source_token_decimals,
|
|
10676
|
+
sourceTokenSymbol: walletCheckoutQuote.source_token_symbol,
|
|
10677
|
+
sourceAmountUsd: walletCheckoutQuote.source_amount_usd,
|
|
10678
|
+
slippageBufferPercent: walletCheckoutQuote.slippage_buffer_percent ?? null
|
|
10679
|
+
};
|
|
10680
|
+
}
|
|
10681
|
+
return checkoutQuote ?? null;
|
|
10682
|
+
}, [isCheckoutMode, walletCheckoutQuote, checkoutQuote]);
|
|
10574
10683
|
const { executions: depositExecutions, isPolling, handleIveDeposited } = useDepositPolling({
|
|
10575
10684
|
userId,
|
|
10576
10685
|
publishableKey,
|
|
@@ -10622,9 +10731,10 @@ function BrowserWalletModal({
|
|
|
10622
10731
|
const options = {
|
|
10623
10732
|
destination_token_address: depositWallet.destination_token_address,
|
|
10624
10733
|
destination_chain_id: depositWallet.destination_chain_id,
|
|
10625
|
-
destination_chain_type: depositWallet.destination_chain_type
|
|
10734
|
+
destination_chain_type: depositWallet.destination_chain_type,
|
|
10735
|
+
...productType ? { product_type: productType } : {}
|
|
10626
10736
|
};
|
|
10627
|
-
const response = await (0,
|
|
10737
|
+
const response = await (0, import_core23.getSupportedDepositTokens)(
|
|
10628
10738
|
publishableKey,
|
|
10629
10739
|
options
|
|
10630
10740
|
);
|
|
@@ -10661,7 +10771,7 @@ function BrowserWalletModal({
|
|
|
10661
10771
|
let cancelled = false;
|
|
10662
10772
|
setIsLoading(true);
|
|
10663
10773
|
setError(null);
|
|
10664
|
-
(0,
|
|
10774
|
+
(0, import_core23.getAddressBalances)(walletInfo.address, supportedChainType, publishableKey).then((response) => {
|
|
10665
10775
|
if (cancelled) return;
|
|
10666
10776
|
const nonZeroBalances = response.balances.filter(
|
|
10667
10777
|
(b) => b.amount !== "0"
|
|
@@ -10985,7 +11095,7 @@ function BrowserWalletModal({
|
|
|
10985
11095
|
amountInSmallestUnit = decimalToSmallestUnit(amountStr, token.decimals);
|
|
10986
11096
|
}
|
|
10987
11097
|
try {
|
|
10988
|
-
const buildResponse = await (0,
|
|
11098
|
+
const buildResponse = await (0, import_core23.buildSolanaTransaction)(
|
|
10989
11099
|
{
|
|
10990
11100
|
chain_id: "mainnet",
|
|
10991
11101
|
token_address: token.token_address === "" ? "native" : token.token_address,
|
|
@@ -11012,7 +11122,7 @@ function BrowserWalletModal({
|
|
|
11012
11122
|
binaryStr += String.fromCharCode(serialized[i]);
|
|
11013
11123
|
}
|
|
11014
11124
|
const signedTransactionBase64 = btoa(binaryStr);
|
|
11015
|
-
const sendResponse = await (0,
|
|
11125
|
+
const sendResponse = await (0, import_core23.sendSolanaTransaction)(
|
|
11016
11126
|
{
|
|
11017
11127
|
chain_id: "mainnet",
|
|
11018
11128
|
signed_transaction: signedTransactionBase64
|
|
@@ -11024,7 +11134,6 @@ function BrowserWalletModal({
|
|
|
11024
11134
|
throw error2;
|
|
11025
11135
|
}
|
|
11026
11136
|
};
|
|
11027
|
-
const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
|
|
11028
11137
|
const usdToTokenRate = React26.useMemo(() => {
|
|
11029
11138
|
if (!selectedBalance || !selectedBalance.amount_usd || !selectedToken)
|
|
11030
11139
|
return 0;
|
|
@@ -11034,15 +11143,24 @@ function BrowserWalletModal({
|
|
|
11034
11143
|
return balanceAmount / balanceUsd;
|
|
11035
11144
|
}, [selectedBalance, selectedToken]);
|
|
11036
11145
|
const tokenAmount = React26.useMemo(() => {
|
|
11146
|
+
if (isCheckoutMode && activeCheckoutQuote && selectedToken) {
|
|
11147
|
+
return Number(activeCheckoutQuote.sourceAmount) / 10 ** activeCheckoutQuote.sourceTokenDecimals;
|
|
11148
|
+
}
|
|
11037
11149
|
const usdNum = parseFloat(amountUsd) || 0;
|
|
11038
11150
|
if (usdNum === 0 || usdToTokenRate === 0) return 0;
|
|
11039
11151
|
return usdNum * usdToTokenRate;
|
|
11040
|
-
}, [amountUsd, usdToTokenRate]);
|
|
11152
|
+
}, [amountUsd, usdToTokenRate, isCheckoutMode, activeCheckoutQuote, selectedToken]);
|
|
11153
|
+
React26.useEffect(() => {
|
|
11154
|
+
if (isCheckoutMode && activeCheckoutQuote?.sourceAmountUsd && step === "input-amount") {
|
|
11155
|
+
const quoteUsd = activeCheckoutQuote.sourceAmountUsd;
|
|
11156
|
+
setAmountUsd(quoteUsd);
|
|
11157
|
+
}
|
|
11158
|
+
}, [isCheckoutMode, activeCheckoutQuote, step]);
|
|
11041
11159
|
const maxTokenAmount = selectedBalance && selectedToken ? Number(selectedBalance.amount) / 10 ** selectedToken.decimals : 0;
|
|
11042
11160
|
const maxUsdAmount = selectedBalance?.amount_usd ? parseFloat(selectedBalance.amount_usd) : 0;
|
|
11043
11161
|
const inputUsdNum = parseFloat(amountUsd) || 0;
|
|
11044
11162
|
const minDepositUsd = tokenChainDetails?.minimum_deposit_amount_usd || 0;
|
|
11045
|
-
const isValidAmount = inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
|
|
11163
|
+
const isValidAmount = isCheckoutMode && activeCheckoutQuote ? tokenAmount > 0 && tokenAmount <= maxTokenAmount : inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
|
|
11046
11164
|
const formattedTokenAmount = React26.useMemo(() => {
|
|
11047
11165
|
if (tokenAmount === 0 || !selectedToken) return null;
|
|
11048
11166
|
return `${tokenAmount.toFixed(6)} ${selectedToken.symbol}`.replace(
|
|
@@ -11957,7 +12075,7 @@ function DepositModal({
|
|
|
11957
12075
|
if (view !== "tracker" || !userId) return;
|
|
11958
12076
|
const fetchExecutions = async () => {
|
|
11959
12077
|
try {
|
|
11960
|
-
const response = await (0,
|
|
12078
|
+
const response = await (0, import_core24.queryExecutions)(userId, publishableKey, import_core24.ActionType.Deposit);
|
|
11961
12079
|
const sorted = [...response.data].sort((a, b) => {
|
|
11962
12080
|
const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
|
|
11963
12081
|
const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
|
|
@@ -12483,8 +12601,8 @@ var import_react19 = require("react");
|
|
|
12483
12601
|
var import_lucide_react24 = require("lucide-react");
|
|
12484
12602
|
|
|
12485
12603
|
// src/hooks/use-payment-intent.ts
|
|
12486
|
-
var
|
|
12487
|
-
var
|
|
12604
|
+
var import_react_query10 = require("@tanstack/react-query");
|
|
12605
|
+
var import_core25 = require("@unifold/core");
|
|
12488
12606
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
12489
12607
|
"succeeded",
|
|
12490
12608
|
"expired",
|
|
@@ -12498,9 +12616,9 @@ function usePaymentIntent(params) {
|
|
|
12498
12616
|
enabled = true,
|
|
12499
12617
|
pollingInterval = 3e3
|
|
12500
12618
|
} = params;
|
|
12501
|
-
return (0,
|
|
12619
|
+
return (0, import_react_query10.useQuery)({
|
|
12502
12620
|
queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
|
|
12503
|
-
queryFn: () => (0,
|
|
12621
|
+
queryFn: () => (0, import_core25.retrievePaymentIntent)(clientSecret, publishableKey),
|
|
12504
12622
|
enabled: enabled && !!clientSecret && !!publishableKey,
|
|
12505
12623
|
staleTime: 0,
|
|
12506
12624
|
refetchInterval: (query) => {
|
|
@@ -12515,53 +12633,6 @@ function usePaymentIntent(params) {
|
|
|
12515
12633
|
});
|
|
12516
12634
|
}
|
|
12517
12635
|
|
|
12518
|
-
// src/hooks/use-deposit-quote.ts
|
|
12519
|
-
var import_react_query10 = require("@tanstack/react-query");
|
|
12520
|
-
var import_core25 = require("@unifold/core");
|
|
12521
|
-
function useDepositQuote(params) {
|
|
12522
|
-
const {
|
|
12523
|
-
publishableKey,
|
|
12524
|
-
sourceChainType,
|
|
12525
|
-
sourceChainId,
|
|
12526
|
-
sourceTokenAddress,
|
|
12527
|
-
destinationAmount,
|
|
12528
|
-
destinationChainType,
|
|
12529
|
-
destinationChainId,
|
|
12530
|
-
destinationTokenAddress,
|
|
12531
|
-
enabled = true
|
|
12532
|
-
} = params;
|
|
12533
|
-
const request = {
|
|
12534
|
-
source_chain_type: sourceChainType,
|
|
12535
|
-
source_chain_id: sourceChainId,
|
|
12536
|
-
source_token_address: sourceTokenAddress,
|
|
12537
|
-
destination_amount: destinationAmount,
|
|
12538
|
-
destination_chain_type: destinationChainType,
|
|
12539
|
-
destination_chain_id: destinationChainId,
|
|
12540
|
-
destination_token_address: destinationTokenAddress
|
|
12541
|
-
};
|
|
12542
|
-
return (0, import_react_query10.useQuery)({
|
|
12543
|
-
queryKey: [
|
|
12544
|
-
"unifold",
|
|
12545
|
-
"depositQuote",
|
|
12546
|
-
sourceChainType,
|
|
12547
|
-
sourceChainId,
|
|
12548
|
-
sourceTokenAddress,
|
|
12549
|
-
destinationAmount,
|
|
12550
|
-
destinationChainType,
|
|
12551
|
-
destinationChainId,
|
|
12552
|
-
destinationTokenAddress,
|
|
12553
|
-
publishableKey
|
|
12554
|
-
],
|
|
12555
|
-
queryFn: () => (0, import_core25.getDepositQuote)(request, publishableKey),
|
|
12556
|
-
enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
|
|
12557
|
-
staleTime: 6e4,
|
|
12558
|
-
gcTime: 5 * 6e4,
|
|
12559
|
-
refetchOnWindowFocus: false,
|
|
12560
|
-
retry: 2,
|
|
12561
|
-
retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 5e3)
|
|
12562
|
-
});
|
|
12563
|
-
}
|
|
12564
|
-
|
|
12565
12636
|
// src/components/checkout/CheckoutModal.tsx
|
|
12566
12637
|
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
12567
12638
|
function mapDepositAddressesToWallets(depositAddresses, pi) {
|
|
@@ -12713,6 +12784,7 @@ function CheckoutModal({
|
|
|
12713
12784
|
destinationChainType: paymentIntent?.destination_chain_type ?? "",
|
|
12714
12785
|
destinationChainId: paymentIntent?.destination_chain_id ?? "",
|
|
12715
12786
|
destinationTokenAddress: paymentIntent?.destination_token_address ?? "",
|
|
12787
|
+
adjustForSlippage: true,
|
|
12716
12788
|
enabled: open && view === "transfer" && !!paymentIntent && !!selectedSource && quoteDestinationAmount !== "0"
|
|
12717
12789
|
});
|
|
12718
12790
|
const handleBrowserWalletClick = (0, import_react19.useCallback)(
|
|
@@ -13104,6 +13176,7 @@ function CheckoutModal({
|
|
|
13104
13176
|
depositConfirmationMode: "auto_ui",
|
|
13105
13177
|
wallets,
|
|
13106
13178
|
onSourceTokenChange: setSelectedSource,
|
|
13179
|
+
productType: "payment",
|
|
13107
13180
|
checkoutQuote: sourceQuote ? {
|
|
13108
13181
|
sourceAmount: sourceQuote.source_amount,
|
|
13109
13182
|
sourceTokenDecimals: sourceQuote.source_token_decimals,
|
|
@@ -13143,6 +13216,16 @@ function CheckoutModal({
|
|
|
13143
13216
|
prefillAmountUsd: remainingAmountUsd,
|
|
13144
13217
|
checkoutAmountUsd: paymentIntent?.amount_usd,
|
|
13145
13218
|
checkoutReceivedUsd: paymentIntent?.amount_received_usd,
|
|
13219
|
+
checkoutDestination: paymentIntent ? {
|
|
13220
|
+
chainType: paymentIntent.destination_chain_type,
|
|
13221
|
+
chainId: paymentIntent.destination_chain_id,
|
|
13222
|
+
tokenAddress: paymentIntent.destination_token_address
|
|
13223
|
+
} : void 0,
|
|
13224
|
+
productType: "payment",
|
|
13225
|
+
checkoutRemainingBaseUnits: paymentIntent ? (() => {
|
|
13226
|
+
const remaining = BigInt(paymentIntent.amount) - BigInt(paymentIntent.amount_received);
|
|
13227
|
+
return remaining > 0n ? remaining.toString() : "0";
|
|
13228
|
+
})() : void 0,
|
|
13146
13229
|
onSuccess: (txHash) => {
|
|
13147
13230
|
onCheckoutSuccess?.({
|
|
13148
13231
|
paymentIntentId: paymentIntent?.id || "",
|
package/dist/index.mjs
CHANGED
|
@@ -2531,14 +2531,14 @@ function BuyWithCard({
|
|
|
2531
2531
|
);
|
|
2532
2532
|
if (matchingCurrency) {
|
|
2533
2533
|
setCurrency(matchingCurrency.currency_code.toLowerCase());
|
|
2534
|
-
if (!amount && !hasManualAmountEntry) {
|
|
2534
|
+
if (!amount && !hasManualAmountEntry && matchingCurrency.default_amount != null) {
|
|
2535
2535
|
setAmount(matchingCurrency.default_amount.toString());
|
|
2536
2536
|
}
|
|
2537
2537
|
} else if (!amount && !hasManualAmountEntry) {
|
|
2538
2538
|
const usdCurrency = fiatCurrencies.find(
|
|
2539
2539
|
(c) => c.currency_code.toLowerCase() === "usd"
|
|
2540
2540
|
);
|
|
2541
|
-
if (usdCurrency) {
|
|
2541
|
+
if (usdCurrency?.default_amount != null) {
|
|
2542
2542
|
setAmount(usdCurrency.default_amount.toString());
|
|
2543
2543
|
}
|
|
2544
2544
|
}
|
|
@@ -2556,7 +2556,7 @@ function BuyWithCard({
|
|
|
2556
2556
|
const currentCurrency = fiatCurrencies.find(
|
|
2557
2557
|
(c) => c.currency_code.toLowerCase() === currency.toLowerCase()
|
|
2558
2558
|
);
|
|
2559
|
-
if (currentCurrency) {
|
|
2559
|
+
if (currentCurrency?.default_amount != null) {
|
|
2560
2560
|
setAmount(currentCurrency.default_amount.toString());
|
|
2561
2561
|
}
|
|
2562
2562
|
}
|
|
@@ -7026,11 +7026,16 @@ import {
|
|
|
7026
7026
|
getSupportedDepositTokens
|
|
7027
7027
|
} from "@unifold/core";
|
|
7028
7028
|
function useSupportedDepositTokens(publishableKey, options) {
|
|
7029
|
-
const
|
|
7030
|
-
|
|
7031
|
-
|
|
7032
|
-
|
|
7033
|
-
|
|
7029
|
+
const hasDestination = options?.destination_token_address && options?.destination_chain_id && options?.destination_chain_type;
|
|
7030
|
+
const filteredOptions = {
|
|
7031
|
+
...hasDestination ? {
|
|
7032
|
+
destination_token_address: options.destination_token_address,
|
|
7033
|
+
destination_chain_id: options.destination_chain_id,
|
|
7034
|
+
destination_chain_type: options.destination_chain_type
|
|
7035
|
+
} : {},
|
|
7036
|
+
...options?.product_type ? { product_type: options.product_type } : {}
|
|
7037
|
+
};
|
|
7038
|
+
const hasFilteredOptions = Object.keys(filteredOptions).length > 0;
|
|
7034
7039
|
return useQuery8({
|
|
7035
7040
|
queryKey: [
|
|
7036
7041
|
"unifold",
|
|
@@ -7038,9 +7043,13 @@ function useSupportedDepositTokens(publishableKey, options) {
|
|
|
7038
7043
|
publishableKey,
|
|
7039
7044
|
filteredOptions?.destination_token_address ?? null,
|
|
7040
7045
|
filteredOptions?.destination_chain_id ?? null,
|
|
7041
|
-
filteredOptions?.destination_chain_type ?? null
|
|
7046
|
+
filteredOptions?.destination_chain_type ?? null,
|
|
7047
|
+
filteredOptions?.product_type ?? null
|
|
7042
7048
|
],
|
|
7043
|
-
queryFn: () => getSupportedDepositTokens(
|
|
7049
|
+
queryFn: () => getSupportedDepositTokens(
|
|
7050
|
+
publishableKey,
|
|
7051
|
+
hasFilteredOptions ? filteredOptions : void 0
|
|
7052
|
+
),
|
|
7044
7053
|
staleTime: 1e3 * 60 * 5,
|
|
7045
7054
|
// 5 minutes — token list rarely changes
|
|
7046
7055
|
gcTime: 1e3 * 60 * 30,
|
|
@@ -8331,7 +8340,8 @@ function TransferCryptoSingleInput({
|
|
|
8331
8340
|
onDepositError,
|
|
8332
8341
|
wallets: externalWallets,
|
|
8333
8342
|
onSourceTokenChange,
|
|
8334
|
-
checkoutQuote
|
|
8343
|
+
checkoutQuote,
|
|
8344
|
+
productType
|
|
8335
8345
|
}) {
|
|
8336
8346
|
const { themeClass, colors: colors2, fonts, components } = useTheme();
|
|
8337
8347
|
const isDarkMode = themeClass.includes("uf-dark");
|
|
@@ -8344,7 +8354,8 @@ function TransferCryptoSingleInput({
|
|
|
8344
8354
|
const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDepositTokens(publishableKey, {
|
|
8345
8355
|
destination_token_address: destinationTokenAddress,
|
|
8346
8356
|
destination_chain_id: destinationChainId,
|
|
8347
|
-
destination_chain_type: destinationChainType
|
|
8357
|
+
destination_chain_type: destinationChainType,
|
|
8358
|
+
product_type: productType
|
|
8348
8359
|
});
|
|
8349
8360
|
const supportedTokens = tokensResponse?.data ?? [];
|
|
8350
8361
|
const { token, chain, setToken, setChain, initialSelectionDone } = useDefaultSourceToken({
|
|
@@ -9417,6 +9428,60 @@ import {
|
|
|
9417
9428
|
sendSolanaTransaction as sendSolanaTransactionToBackend
|
|
9418
9429
|
} from "@unifold/core";
|
|
9419
9430
|
|
|
9431
|
+
// src/hooks/use-deposit-quote.ts
|
|
9432
|
+
import { useQuery as useQuery9 } from "@tanstack/react-query";
|
|
9433
|
+
import {
|
|
9434
|
+
getDepositQuote
|
|
9435
|
+
} from "@unifold/core";
|
|
9436
|
+
function useDepositQuote(params) {
|
|
9437
|
+
const {
|
|
9438
|
+
publishableKey,
|
|
9439
|
+
sourceChainType,
|
|
9440
|
+
sourceChainId,
|
|
9441
|
+
sourceTokenAddress,
|
|
9442
|
+
destinationAmount,
|
|
9443
|
+
destinationChainType,
|
|
9444
|
+
destinationChainId,
|
|
9445
|
+
destinationTokenAddress,
|
|
9446
|
+
adjustForSlippage,
|
|
9447
|
+
enabled = true
|
|
9448
|
+
} = params;
|
|
9449
|
+
const request = {
|
|
9450
|
+
source_chain_type: sourceChainType,
|
|
9451
|
+
source_chain_id: sourceChainId,
|
|
9452
|
+
source_token_address: sourceTokenAddress,
|
|
9453
|
+
destination_amount: destinationAmount,
|
|
9454
|
+
destination_chain_type: destinationChainType,
|
|
9455
|
+
destination_chain_id: destinationChainId,
|
|
9456
|
+
destination_token_address: destinationTokenAddress,
|
|
9457
|
+
...adjustForSlippage ? { adjust_for_slippage: true } : {}
|
|
9458
|
+
};
|
|
9459
|
+
return useQuery9({
|
|
9460
|
+
queryKey: [
|
|
9461
|
+
"unifold",
|
|
9462
|
+
"depositQuote",
|
|
9463
|
+
sourceChainType,
|
|
9464
|
+
sourceChainId,
|
|
9465
|
+
sourceTokenAddress,
|
|
9466
|
+
destinationAmount,
|
|
9467
|
+
destinationChainType,
|
|
9468
|
+
destinationChainId,
|
|
9469
|
+
destinationTokenAddress,
|
|
9470
|
+
adjustForSlippage,
|
|
9471
|
+
publishableKey
|
|
9472
|
+
],
|
|
9473
|
+
queryFn: () => getDepositQuote(request, publishableKey),
|
|
9474
|
+
enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
|
|
9475
|
+
staleTime: 3e4,
|
|
9476
|
+
gcTime: 5 * 6e4,
|
|
9477
|
+
refetchInterval: 3e4,
|
|
9478
|
+
refetchIntervalInBackground: false,
|
|
9479
|
+
refetchOnWindowFocus: true,
|
|
9480
|
+
retry: 2,
|
|
9481
|
+
retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 5e3)
|
|
9482
|
+
});
|
|
9483
|
+
}
|
|
9484
|
+
|
|
9420
9485
|
// src/components/deposits/browser-wallets/types.ts
|
|
9421
9486
|
var BROWSER_WALLET_STEP_MIN_HEIGHT_CLASS = "uf-min-h-[460px]";
|
|
9422
9487
|
|
|
@@ -9905,7 +9970,7 @@ function EnterAmountView({
|
|
|
9905
9970
|
}
|
|
9906
9971
|
)
|
|
9907
9972
|
] }) }),
|
|
9908
|
-
tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && (isCheckout && checkoutAmountUsd &&
|
|
9973
|
+
tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && (isCheckout && checkoutAmountUsd && tokenChainDetails.minimum_deposit_amount_usd > parseFloat(checkoutAmountUsd) - parseFloat(checkoutReceivedUsd || "0") + 5e-3 ? /* @__PURE__ */ jsxs39(
|
|
9909
9974
|
"div",
|
|
9910
9975
|
{
|
|
9911
9976
|
className: "uf-rounded-lg uf-px-3 uf-py-2 uf-mb-3 uf-text-center",
|
|
@@ -10519,7 +10584,11 @@ function BrowserWalletModal({
|
|
|
10519
10584
|
checkoutReceivedUsd,
|
|
10520
10585
|
onNewDeposit,
|
|
10521
10586
|
onDone,
|
|
10522
|
-
paymentIntentStatus
|
|
10587
|
+
paymentIntentStatus,
|
|
10588
|
+
checkoutQuote,
|
|
10589
|
+
checkoutDestination,
|
|
10590
|
+
checkoutRemainingBaseUnits,
|
|
10591
|
+
productType
|
|
10523
10592
|
}) {
|
|
10524
10593
|
const { colors: colors2, fonts, components } = useTheme();
|
|
10525
10594
|
const [step, setStep] = React26.useState("select-token");
|
|
@@ -10541,7 +10610,49 @@ function BrowserWalletModal({
|
|
|
10541
10610
|
const themeClass = theme === "dark" ? "uf-dark" : "";
|
|
10542
10611
|
const chainType = depositWallet.chain_type;
|
|
10543
10612
|
const recipientAddress = depositWallet.address;
|
|
10613
|
+
const isCheckoutMode = !!checkoutAmountUsd;
|
|
10544
10614
|
const supportedChainType = chainType === "algorand" || chainType === "xrpl" ? "ethereum" : chainType;
|
|
10615
|
+
const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
|
|
10616
|
+
const effectiveDestinationAmount = React26.useMemo(() => {
|
|
10617
|
+
if (!checkoutRemainingBaseUnits || checkoutRemainingBaseUnits === "0") return "0";
|
|
10618
|
+
if (!checkoutAmountUsd) return checkoutRemainingBaseUnits;
|
|
10619
|
+
const remaining = BigInt(checkoutRemainingBaseUnits);
|
|
10620
|
+
const minUsd = Math.max(tokenChainDetails?.minimum_deposit_amount_usd ?? 0, 3);
|
|
10621
|
+
const totalUsd = parseFloat(checkoutAmountUsd);
|
|
10622
|
+
if (totalUsd <= 0) return remaining > 0n ? remaining.toString() : "0";
|
|
10623
|
+
const receivedUsd = parseFloat(checkoutReceivedUsd ?? "0");
|
|
10624
|
+
const remainingUsd = totalUsd - receivedUsd;
|
|
10625
|
+
if (remainingUsd <= 0) return "0";
|
|
10626
|
+
const baseUnitsPerUsd = Number(remaining) / remainingUsd;
|
|
10627
|
+
const minBaseUnits = BigInt(Math.ceil(minUsd * baseUnitsPerUsd));
|
|
10628
|
+
const effective = remaining > minBaseUnits ? remaining : minBaseUnits;
|
|
10629
|
+
return effective > 0n ? effective.toString() : "0";
|
|
10630
|
+
}, [checkoutRemainingBaseUnits, checkoutAmountUsd, checkoutReceivedUsd, tokenChainDetails]);
|
|
10631
|
+
const { data: walletCheckoutQuote } = useDepositQuote({
|
|
10632
|
+
publishableKey,
|
|
10633
|
+
sourceChainType: selectedToken?.chain_type ?? "",
|
|
10634
|
+
sourceChainId: selectedToken?.chain_id ?? "",
|
|
10635
|
+
sourceTokenAddress: selectedToken?.token_address ?? "",
|
|
10636
|
+
destinationAmount: effectiveDestinationAmount,
|
|
10637
|
+
destinationChainType: checkoutDestination?.chainType ?? "",
|
|
10638
|
+
destinationChainId: checkoutDestination?.chainId ?? "",
|
|
10639
|
+
destinationTokenAddress: checkoutDestination?.tokenAddress ?? "",
|
|
10640
|
+
adjustForSlippage: true,
|
|
10641
|
+
enabled: open && isCheckoutMode && !!selectedToken && !!checkoutDestination && effectiveDestinationAmount !== "0"
|
|
10642
|
+
});
|
|
10643
|
+
const activeCheckoutQuote = React26.useMemo(() => {
|
|
10644
|
+
if (!isCheckoutMode) return null;
|
|
10645
|
+
if (walletCheckoutQuote) {
|
|
10646
|
+
return {
|
|
10647
|
+
sourceAmount: walletCheckoutQuote.source_amount,
|
|
10648
|
+
sourceTokenDecimals: walletCheckoutQuote.source_token_decimals,
|
|
10649
|
+
sourceTokenSymbol: walletCheckoutQuote.source_token_symbol,
|
|
10650
|
+
sourceAmountUsd: walletCheckoutQuote.source_amount_usd,
|
|
10651
|
+
slippageBufferPercent: walletCheckoutQuote.slippage_buffer_percent ?? null
|
|
10652
|
+
};
|
|
10653
|
+
}
|
|
10654
|
+
return checkoutQuote ?? null;
|
|
10655
|
+
}, [isCheckoutMode, walletCheckoutQuote, checkoutQuote]);
|
|
10545
10656
|
const { executions: depositExecutions, isPolling, handleIveDeposited } = useDepositPolling({
|
|
10546
10657
|
userId,
|
|
10547
10658
|
publishableKey,
|
|
@@ -10593,7 +10704,8 @@ function BrowserWalletModal({
|
|
|
10593
10704
|
const options = {
|
|
10594
10705
|
destination_token_address: depositWallet.destination_token_address,
|
|
10595
10706
|
destination_chain_id: depositWallet.destination_chain_id,
|
|
10596
|
-
destination_chain_type: depositWallet.destination_chain_type
|
|
10707
|
+
destination_chain_type: depositWallet.destination_chain_type,
|
|
10708
|
+
...productType ? { product_type: productType } : {}
|
|
10597
10709
|
};
|
|
10598
10710
|
const response = await getSupportedDepositTokens2(
|
|
10599
10711
|
publishableKey,
|
|
@@ -10995,7 +11107,6 @@ function BrowserWalletModal({
|
|
|
10995
11107
|
throw error2;
|
|
10996
11108
|
}
|
|
10997
11109
|
};
|
|
10998
|
-
const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
|
|
10999
11110
|
const usdToTokenRate = React26.useMemo(() => {
|
|
11000
11111
|
if (!selectedBalance || !selectedBalance.amount_usd || !selectedToken)
|
|
11001
11112
|
return 0;
|
|
@@ -11005,15 +11116,24 @@ function BrowserWalletModal({
|
|
|
11005
11116
|
return balanceAmount / balanceUsd;
|
|
11006
11117
|
}, [selectedBalance, selectedToken]);
|
|
11007
11118
|
const tokenAmount = React26.useMemo(() => {
|
|
11119
|
+
if (isCheckoutMode && activeCheckoutQuote && selectedToken) {
|
|
11120
|
+
return Number(activeCheckoutQuote.sourceAmount) / 10 ** activeCheckoutQuote.sourceTokenDecimals;
|
|
11121
|
+
}
|
|
11008
11122
|
const usdNum = parseFloat(amountUsd) || 0;
|
|
11009
11123
|
if (usdNum === 0 || usdToTokenRate === 0) return 0;
|
|
11010
11124
|
return usdNum * usdToTokenRate;
|
|
11011
|
-
}, [amountUsd, usdToTokenRate]);
|
|
11125
|
+
}, [amountUsd, usdToTokenRate, isCheckoutMode, activeCheckoutQuote, selectedToken]);
|
|
11126
|
+
React26.useEffect(() => {
|
|
11127
|
+
if (isCheckoutMode && activeCheckoutQuote?.sourceAmountUsd && step === "input-amount") {
|
|
11128
|
+
const quoteUsd = activeCheckoutQuote.sourceAmountUsd;
|
|
11129
|
+
setAmountUsd(quoteUsd);
|
|
11130
|
+
}
|
|
11131
|
+
}, [isCheckoutMode, activeCheckoutQuote, step]);
|
|
11012
11132
|
const maxTokenAmount = selectedBalance && selectedToken ? Number(selectedBalance.amount) / 10 ** selectedToken.decimals : 0;
|
|
11013
11133
|
const maxUsdAmount = selectedBalance?.amount_usd ? parseFloat(selectedBalance.amount_usd) : 0;
|
|
11014
11134
|
const inputUsdNum = parseFloat(amountUsd) || 0;
|
|
11015
11135
|
const minDepositUsd = tokenChainDetails?.minimum_deposit_amount_usd || 0;
|
|
11016
|
-
const isValidAmount = inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
|
|
11136
|
+
const isValidAmount = isCheckoutMode && activeCheckoutQuote ? tokenAmount > 0 && tokenAmount <= maxTokenAmount : inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
|
|
11017
11137
|
const formattedTokenAmount = React26.useMemo(() => {
|
|
11018
11138
|
if (tokenAmount === 0 || !selectedToken) return null;
|
|
11019
11139
|
return `${tokenAmount.toFixed(6)} ${selectedToken.symbol}`.replace(
|
|
@@ -12461,7 +12581,7 @@ import {
|
|
|
12461
12581
|
import { AlertTriangle as AlertTriangle2, ChevronRight as ChevronRight12 } from "lucide-react";
|
|
12462
12582
|
|
|
12463
12583
|
// src/hooks/use-payment-intent.ts
|
|
12464
|
-
import { useQuery as
|
|
12584
|
+
import { useQuery as useQuery10 } from "@tanstack/react-query";
|
|
12465
12585
|
import { retrievePaymentIntent } from "@unifold/core";
|
|
12466
12586
|
var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
12467
12587
|
"succeeded",
|
|
@@ -12476,7 +12596,7 @@ function usePaymentIntent(params) {
|
|
|
12476
12596
|
enabled = true,
|
|
12477
12597
|
pollingInterval = 3e3
|
|
12478
12598
|
} = params;
|
|
12479
|
-
return
|
|
12599
|
+
return useQuery10({
|
|
12480
12600
|
queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
|
|
12481
12601
|
queryFn: () => retrievePaymentIntent(clientSecret, publishableKey),
|
|
12482
12602
|
enabled: enabled && !!clientSecret && !!publishableKey,
|
|
@@ -12493,55 +12613,6 @@ function usePaymentIntent(params) {
|
|
|
12493
12613
|
});
|
|
12494
12614
|
}
|
|
12495
12615
|
|
|
12496
|
-
// src/hooks/use-deposit-quote.ts
|
|
12497
|
-
import { useQuery as useQuery10 } from "@tanstack/react-query";
|
|
12498
|
-
import {
|
|
12499
|
-
getDepositQuote
|
|
12500
|
-
} from "@unifold/core";
|
|
12501
|
-
function useDepositQuote(params) {
|
|
12502
|
-
const {
|
|
12503
|
-
publishableKey,
|
|
12504
|
-
sourceChainType,
|
|
12505
|
-
sourceChainId,
|
|
12506
|
-
sourceTokenAddress,
|
|
12507
|
-
destinationAmount,
|
|
12508
|
-
destinationChainType,
|
|
12509
|
-
destinationChainId,
|
|
12510
|
-
destinationTokenAddress,
|
|
12511
|
-
enabled = true
|
|
12512
|
-
} = params;
|
|
12513
|
-
const request = {
|
|
12514
|
-
source_chain_type: sourceChainType,
|
|
12515
|
-
source_chain_id: sourceChainId,
|
|
12516
|
-
source_token_address: sourceTokenAddress,
|
|
12517
|
-
destination_amount: destinationAmount,
|
|
12518
|
-
destination_chain_type: destinationChainType,
|
|
12519
|
-
destination_chain_id: destinationChainId,
|
|
12520
|
-
destination_token_address: destinationTokenAddress
|
|
12521
|
-
};
|
|
12522
|
-
return useQuery10({
|
|
12523
|
-
queryKey: [
|
|
12524
|
-
"unifold",
|
|
12525
|
-
"depositQuote",
|
|
12526
|
-
sourceChainType,
|
|
12527
|
-
sourceChainId,
|
|
12528
|
-
sourceTokenAddress,
|
|
12529
|
-
destinationAmount,
|
|
12530
|
-
destinationChainType,
|
|
12531
|
-
destinationChainId,
|
|
12532
|
-
destinationTokenAddress,
|
|
12533
|
-
publishableKey
|
|
12534
|
-
],
|
|
12535
|
-
queryFn: () => getDepositQuote(request, publishableKey),
|
|
12536
|
-
enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
|
|
12537
|
-
staleTime: 6e4,
|
|
12538
|
-
gcTime: 5 * 6e4,
|
|
12539
|
-
refetchOnWindowFocus: false,
|
|
12540
|
-
retry: 2,
|
|
12541
|
-
retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 5e3)
|
|
12542
|
-
});
|
|
12543
|
-
}
|
|
12544
|
-
|
|
12545
12616
|
// src/components/checkout/CheckoutModal.tsx
|
|
12546
12617
|
import { Fragment as Fragment10, jsx as jsx52, jsxs as jsxs45 } from "react/jsx-runtime";
|
|
12547
12618
|
function mapDepositAddressesToWallets(depositAddresses, pi) {
|
|
@@ -12693,6 +12764,7 @@ function CheckoutModal({
|
|
|
12693
12764
|
destinationChainType: paymentIntent?.destination_chain_type ?? "",
|
|
12694
12765
|
destinationChainId: paymentIntent?.destination_chain_id ?? "",
|
|
12695
12766
|
destinationTokenAddress: paymentIntent?.destination_token_address ?? "",
|
|
12767
|
+
adjustForSlippage: true,
|
|
12696
12768
|
enabled: open && view === "transfer" && !!paymentIntent && !!selectedSource && quoteDestinationAmount !== "0"
|
|
12697
12769
|
});
|
|
12698
12770
|
const handleBrowserWalletClick = useCallback5(
|
|
@@ -13084,6 +13156,7 @@ function CheckoutModal({
|
|
|
13084
13156
|
depositConfirmationMode: "auto_ui",
|
|
13085
13157
|
wallets,
|
|
13086
13158
|
onSourceTokenChange: setSelectedSource,
|
|
13159
|
+
productType: "payment",
|
|
13087
13160
|
checkoutQuote: sourceQuote ? {
|
|
13088
13161
|
sourceAmount: sourceQuote.source_amount,
|
|
13089
13162
|
sourceTokenDecimals: sourceQuote.source_token_decimals,
|
|
@@ -13123,6 +13196,16 @@ function CheckoutModal({
|
|
|
13123
13196
|
prefillAmountUsd: remainingAmountUsd,
|
|
13124
13197
|
checkoutAmountUsd: paymentIntent?.amount_usd,
|
|
13125
13198
|
checkoutReceivedUsd: paymentIntent?.amount_received_usd,
|
|
13199
|
+
checkoutDestination: paymentIntent ? {
|
|
13200
|
+
chainType: paymentIntent.destination_chain_type,
|
|
13201
|
+
chainId: paymentIntent.destination_chain_id,
|
|
13202
|
+
tokenAddress: paymentIntent.destination_token_address
|
|
13203
|
+
} : void 0,
|
|
13204
|
+
productType: "payment",
|
|
13205
|
+
checkoutRemainingBaseUnits: paymentIntent ? (() => {
|
|
13206
|
+
const remaining = BigInt(paymentIntent.amount) - BigInt(paymentIntent.amount_received);
|
|
13207
|
+
return remaining > 0n ? remaining.toString() : "0";
|
|
13208
|
+
})() : void 0,
|
|
13126
13209
|
onSuccess: (txHash) => {
|
|
13127
13210
|
onCheckoutSuccess?.({
|
|
13128
13211
|
paymentIntentId: paymentIntent?.id || "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@unifold/ui-react",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.53",
|
|
4
4
|
"description": "Unifold UI React - Deposit and onramp components for React applications",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"lucide-react": "^0.454.0",
|
|
35
35
|
"qr-code-styling": "^1.6.0-rc.1",
|
|
36
36
|
"tailwind-merge": "^2.0.0",
|
|
37
|
-
"@unifold/core": "0.1.
|
|
37
|
+
"@unifold/core": "0.1.53"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@solana/web3.js": "^1.87.0",
|