@unifold/ui-react 0.1.51 → 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 CHANGED
@@ -93,7 +93,8 @@ interface EthereumProvider {
93
93
  params?: unknown[];
94
94
  }): Promise<unknown>;
95
95
  on(event: string, callback: (...args: unknown[]) => void): void;
96
- removeListener(event: string, callback: (...args: unknown[]) => void): void;
96
+ off?(event: string, callback: (...args: unknown[]) => void): void;
97
+ removeListener?(event: string, callback: (...args: unknown[]) => void): void;
97
98
  }
98
99
 
99
100
  /** Quick amount chips on the browser wallet "Enter amount" step */
@@ -126,7 +127,8 @@ interface EvmWalletProvider {
126
127
  params?: unknown[];
127
128
  }): Promise<unknown>;
128
129
  on(event: string, callback: (...args: unknown[]) => void): void;
129
- removeListener(event: string, callback: (...args: unknown[]) => void): void;
130
+ off?(event: string, callback: (...args: unknown[]) => void): void;
131
+ removeListener?(event: string, callback: (...args: unknown[]) => void): void;
130
132
  }
131
133
 
132
134
  type DepositModalInitialScreen = "main" | "transfer" | "card" | "tracker";
@@ -273,8 +275,10 @@ interface TransferCryptoSingleInputProps {
273
275
  sourceTokenSymbol: string;
274
276
  sourceAmountUsd: string | null;
275
277
  } | null;
278
+ /** Product context sent to the API — "deposit" (default) or "payment". */
279
+ productType?: "deposit" | "payment";
276
280
  }
277
- 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;
278
282
 
279
283
  interface TransferCryptoDoubleInputProps {
280
284
  userId: string;
@@ -838,6 +842,8 @@ interface UseDepositQuoteParams {
838
842
  destinationChainType: string;
839
843
  destinationChainId: string;
840
844
  destinationTokenAddress: string;
845
+ /** When true, inflates source amount by expected slippage. Typically set by checkout flows. */
846
+ adjustForSlippage?: boolean;
841
847
  enabled?: boolean;
842
848
  }
843
849
  /**
@@ -884,6 +890,7 @@ interface UseSupportedDepositTokensOptions {
884
890
  destination_token_address?: string;
885
891
  destination_chain_id?: string;
886
892
  destination_chain_type?: string;
893
+ product_type?: "deposit" | "payment";
887
894
  }
888
895
  /**
889
896
  * Hook to fetch supported deposit tokens with caching and deduplication via react-query.
package/dist/index.d.ts CHANGED
@@ -93,7 +93,8 @@ interface EthereumProvider {
93
93
  params?: unknown[];
94
94
  }): Promise<unknown>;
95
95
  on(event: string, callback: (...args: unknown[]) => void): void;
96
- removeListener(event: string, callback: (...args: unknown[]) => void): void;
96
+ off?(event: string, callback: (...args: unknown[]) => void): void;
97
+ removeListener?(event: string, callback: (...args: unknown[]) => void): void;
97
98
  }
98
99
 
99
100
  /** Quick amount chips on the browser wallet "Enter amount" step */
@@ -126,7 +127,8 @@ interface EvmWalletProvider {
126
127
  params?: unknown[];
127
128
  }): Promise<unknown>;
128
129
  on(event: string, callback: (...args: unknown[]) => void): void;
129
- removeListener(event: string, callback: (...args: unknown[]) => void): void;
130
+ off?(event: string, callback: (...args: unknown[]) => void): void;
131
+ removeListener?(event: string, callback: (...args: unknown[]) => void): void;
130
132
  }
131
133
 
132
134
  type DepositModalInitialScreen = "main" | "transfer" | "card" | "tracker";
@@ -273,8 +275,10 @@ interface TransferCryptoSingleInputProps {
273
275
  sourceTokenSymbol: string;
274
276
  sourceAmountUsd: string | null;
275
277
  } | null;
278
+ /** Product context sent to the API — "deposit" (default) or "payment". */
279
+ productType?: "deposit" | "payment";
276
280
  }
277
- 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;
278
282
 
279
283
  interface TransferCryptoDoubleInputProps {
280
284
  userId: string;
@@ -838,6 +842,8 @@ interface UseDepositQuoteParams {
838
842
  destinationChainType: string;
839
843
  destinationChainId: string;
840
844
  destinationTokenAddress: string;
845
+ /** When true, inflates source amount by expected slippage. Typically set by checkout flows. */
846
+ adjustForSlippage?: boolean;
841
847
  enabled?: boolean;
842
848
  }
843
849
  /**
@@ -884,6 +890,7 @@ interface UseSupportedDepositTokensOptions {
884
890
  destination_token_address?: string;
885
891
  destination_chain_id?: string;
886
892
  destination_chain_type?: string;
893
+ product_type?: "deposit" | "payment";
887
894
  }
888
895
  /**
889
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
  }
@@ -6658,8 +6658,11 @@ function BrowserWalletButton({
6658
6658
  solanaProvider.off("accountChanged", handleAccountsChanged);
6659
6659
  }
6660
6660
  for (const provider of ethProviders) {
6661
- provider.removeListener("accountsChanged", handleEthAccountsChanged);
6662
- provider.removeListener("chainChanged", handleAccountsChanged);
6661
+ const off = provider.off?.bind(provider) ?? provider.removeListener?.bind(provider);
6662
+ if (off) {
6663
+ off("accountsChanged", handleEthAccountsChanged);
6664
+ off("chainChanged", handleAccountsChanged);
6665
+ }
6663
6666
  }
6664
6667
  };
6665
6668
  }, [chainType, eip6963ProviderCount]);
@@ -6954,7 +6957,7 @@ function useProjectConfig({
6954
6957
  }
6955
6958
 
6956
6959
  // src/components/deposits/DepositModal.tsx
6957
- var import_core23 = require("@unifold/core");
6960
+ var import_core24 = require("@unifold/core");
6958
6961
 
6959
6962
  // src/hooks/use-allowed-country.ts
6960
6963
  var import_react_query6 = require("@tanstack/react-query");
@@ -7083,11 +7086,16 @@ function useAddressValidation({
7083
7086
  var import_react_query8 = require("@tanstack/react-query");
7084
7087
  var import_core18 = require("@unifold/core");
7085
7088
  function useSupportedDepositTokens(publishableKey, options) {
7086
- const filteredOptions = options?.destination_token_address && options?.destination_chain_id && options?.destination_chain_type ? {
7087
- destination_token_address: options.destination_token_address,
7088
- destination_chain_id: options.destination_chain_id,
7089
- destination_chain_type: options.destination_chain_type
7090
- } : void 0;
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;
7091
7099
  return (0, import_react_query8.useQuery)({
7092
7100
  queryKey: [
7093
7101
  "unifold",
@@ -7095,9 +7103,13 @@ function useSupportedDepositTokens(publishableKey, options) {
7095
7103
  publishableKey,
7096
7104
  filteredOptions?.destination_token_address ?? null,
7097
7105
  filteredOptions?.destination_chain_id ?? null,
7098
- filteredOptions?.destination_chain_type ?? null
7106
+ filteredOptions?.destination_chain_type ?? null,
7107
+ filteredOptions?.product_type ?? null
7099
7108
  ],
7100
- queryFn: () => (0, import_core18.getSupportedDepositTokens)(publishableKey, filteredOptions),
7109
+ queryFn: () => (0, import_core18.getSupportedDepositTokens)(
7110
+ publishableKey,
7111
+ hasFilteredOptions ? filteredOptions : void 0
7112
+ ),
7101
7113
  staleTime: 1e3 * 60 * 5,
7102
7114
  // 5 minutes — token list rarely changes
7103
7115
  gcTime: 1e3 * 60 * 30,
@@ -8375,7 +8387,8 @@ function TransferCryptoSingleInput({
8375
8387
  onDepositError,
8376
8388
  wallets: externalWallets,
8377
8389
  onSourceTokenChange,
8378
- checkoutQuote
8390
+ checkoutQuote,
8391
+ productType
8379
8392
  }) {
8380
8393
  const { themeClass, colors: colors2, fonts, components } = useTheme();
8381
8394
  const isDarkMode = themeClass.includes("uf-dark");
@@ -8388,7 +8401,8 @@ function TransferCryptoSingleInput({
8388
8401
  const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDepositTokens(publishableKey, {
8389
8402
  destination_token_address: destinationTokenAddress,
8390
8403
  destination_chain_id: destinationChainId,
8391
- destination_chain_type: destinationChainType
8404
+ destination_chain_type: destinationChainType,
8405
+ product_type: productType
8392
8406
  });
8393
8407
  const supportedTokens = tokensResponse?.data ?? [];
8394
8408
  const { token, chain, setToken, setChain, initialSelectionDone } = useDefaultSourceToken({
@@ -9441,7 +9455,59 @@ function TransferCryptoDoubleInput({
9441
9455
 
9442
9456
  // src/components/deposits/BrowserWalletModal.tsx
9443
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");
9444
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
+ }
9445
9511
 
9446
9512
  // src/components/deposits/browser-wallets/types.ts
9447
9513
  var BROWSER_WALLET_STEP_MIN_HEIGHT_CLASS = "uf-min-h-[460px]";
@@ -9931,7 +9997,7 @@ function EnterAmountView({
9931
9997
  }
9932
9998
  )
9933
9999
  ] }) }),
9934
- tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && (isCheckout && checkoutAmountUsd && inputUsdNum > parseFloat(checkoutAmountUsd) - parseFloat(checkoutReceivedUsd || "0") + 5e-3 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
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)(
9935
10001
  "div",
9936
10002
  {
9937
10003
  className: "uf-rounded-lg uf-px-3 uf-py-2 uf-mb-3 uf-text-center",
@@ -10545,7 +10611,11 @@ function BrowserWalletModal({
10545
10611
  checkoutReceivedUsd,
10546
10612
  onNewDeposit,
10547
10613
  onDone,
10548
- paymentIntentStatus
10614
+ paymentIntentStatus,
10615
+ checkoutQuote,
10616
+ checkoutDestination,
10617
+ checkoutRemainingBaseUnits,
10618
+ productType
10549
10619
  }) {
10550
10620
  const { colors: colors2, fonts, components } = useTheme();
10551
10621
  const [step, setStep] = React26.useState("select-token");
@@ -10567,7 +10637,49 @@ function BrowserWalletModal({
10567
10637
  const themeClass = theme === "dark" ? "uf-dark" : "";
10568
10638
  const chainType = depositWallet.chain_type;
10569
10639
  const recipientAddress = depositWallet.address;
10640
+ const isCheckoutMode = !!checkoutAmountUsd;
10570
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]);
10571
10683
  const { executions: depositExecutions, isPolling, handleIveDeposited } = useDepositPolling({
10572
10684
  userId,
10573
10685
  publishableKey,
@@ -10619,9 +10731,10 @@ function BrowserWalletModal({
10619
10731
  const options = {
10620
10732
  destination_token_address: depositWallet.destination_token_address,
10621
10733
  destination_chain_id: depositWallet.destination_chain_id,
10622
- destination_chain_type: depositWallet.destination_chain_type
10734
+ destination_chain_type: depositWallet.destination_chain_type,
10735
+ ...productType ? { product_type: productType } : {}
10623
10736
  };
10624
- const response = await (0, import_core22.getSupportedDepositTokens)(
10737
+ const response = await (0, import_core23.getSupportedDepositTokens)(
10625
10738
  publishableKey,
10626
10739
  options
10627
10740
  );
@@ -10658,7 +10771,7 @@ function BrowserWalletModal({
10658
10771
  let cancelled = false;
10659
10772
  setIsLoading(true);
10660
10773
  setError(null);
10661
- (0, import_core22.getAddressBalances)(walletInfo.address, supportedChainType, publishableKey).then((response) => {
10774
+ (0, import_core23.getAddressBalances)(walletInfo.address, supportedChainType, publishableKey).then((response) => {
10662
10775
  if (cancelled) return;
10663
10776
  const nonZeroBalances = response.balances.filter(
10664
10777
  (b) => b.amount !== "0"
@@ -10982,7 +11095,7 @@ function BrowserWalletModal({
10982
11095
  amountInSmallestUnit = decimalToSmallestUnit(amountStr, token.decimals);
10983
11096
  }
10984
11097
  try {
10985
- const buildResponse = await (0, import_core22.buildSolanaTransaction)(
11098
+ const buildResponse = await (0, import_core23.buildSolanaTransaction)(
10986
11099
  {
10987
11100
  chain_id: "mainnet",
10988
11101
  token_address: token.token_address === "" ? "native" : token.token_address,
@@ -11009,7 +11122,7 @@ function BrowserWalletModal({
11009
11122
  binaryStr += String.fromCharCode(serialized[i]);
11010
11123
  }
11011
11124
  const signedTransactionBase64 = btoa(binaryStr);
11012
- const sendResponse = await (0, import_core22.sendSolanaTransaction)(
11125
+ const sendResponse = await (0, import_core23.sendSolanaTransaction)(
11013
11126
  {
11014
11127
  chain_id: "mainnet",
11015
11128
  signed_transaction: signedTransactionBase64
@@ -11021,7 +11134,6 @@ function BrowserWalletModal({
11021
11134
  throw error2;
11022
11135
  }
11023
11136
  };
11024
- const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
11025
11137
  const usdToTokenRate = React26.useMemo(() => {
11026
11138
  if (!selectedBalance || !selectedBalance.amount_usd || !selectedToken)
11027
11139
  return 0;
@@ -11031,15 +11143,24 @@ function BrowserWalletModal({
11031
11143
  return balanceAmount / balanceUsd;
11032
11144
  }, [selectedBalance, selectedToken]);
11033
11145
  const tokenAmount = React26.useMemo(() => {
11146
+ if (isCheckoutMode && activeCheckoutQuote && selectedToken) {
11147
+ return Number(activeCheckoutQuote.sourceAmount) / 10 ** activeCheckoutQuote.sourceTokenDecimals;
11148
+ }
11034
11149
  const usdNum = parseFloat(amountUsd) || 0;
11035
11150
  if (usdNum === 0 || usdToTokenRate === 0) return 0;
11036
11151
  return usdNum * usdToTokenRate;
11037
- }, [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]);
11038
11159
  const maxTokenAmount = selectedBalance && selectedToken ? Number(selectedBalance.amount) / 10 ** selectedToken.decimals : 0;
11039
11160
  const maxUsdAmount = selectedBalance?.amount_usd ? parseFloat(selectedBalance.amount_usd) : 0;
11040
11161
  const inputUsdNum = parseFloat(amountUsd) || 0;
11041
11162
  const minDepositUsd = tokenChainDetails?.minimum_deposit_amount_usd || 0;
11042
- const isValidAmount = inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
11163
+ const isValidAmount = isCheckoutMode && activeCheckoutQuote ? tokenAmount > 0 && tokenAmount <= maxTokenAmount : inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
11043
11164
  const formattedTokenAmount = React26.useMemo(() => {
11044
11165
  if (tokenAmount === 0 || !selectedToken) return null;
11045
11166
  return `${tokenAmount.toFixed(6)} ${selectedToken.symbol}`.replace(
@@ -11954,7 +12075,7 @@ function DepositModal({
11954
12075
  if (view !== "tracker" || !userId) return;
11955
12076
  const fetchExecutions = async () => {
11956
12077
  try {
11957
- const response = await (0, import_core23.queryExecutions)(userId, publishableKey, import_core23.ActionType.Deposit);
12078
+ const response = await (0, import_core24.queryExecutions)(userId, publishableKey, import_core24.ActionType.Deposit);
11958
12079
  const sorted = [...response.data].sort((a, b) => {
11959
12080
  const timeA = a.created_at ? new Date(a.created_at).getTime() : 0;
11960
12081
  const timeB = b.created_at ? new Date(b.created_at).getTime() : 0;
@@ -12480,8 +12601,8 @@ var import_react19 = require("react");
12480
12601
  var import_lucide_react24 = require("lucide-react");
12481
12602
 
12482
12603
  // src/hooks/use-payment-intent.ts
12483
- var import_react_query9 = require("@tanstack/react-query");
12484
- var import_core24 = require("@unifold/core");
12604
+ var import_react_query10 = require("@tanstack/react-query");
12605
+ var import_core25 = require("@unifold/core");
12485
12606
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
12486
12607
  "succeeded",
12487
12608
  "expired",
@@ -12495,9 +12616,9 @@ function usePaymentIntent(params) {
12495
12616
  enabled = true,
12496
12617
  pollingInterval = 3e3
12497
12618
  } = params;
12498
- return (0, import_react_query9.useQuery)({
12619
+ return (0, import_react_query10.useQuery)({
12499
12620
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
12500
- queryFn: () => (0, import_core24.retrievePaymentIntent)(clientSecret, publishableKey),
12621
+ queryFn: () => (0, import_core25.retrievePaymentIntent)(clientSecret, publishableKey),
12501
12622
  enabled: enabled && !!clientSecret && !!publishableKey,
12502
12623
  staleTime: 0,
12503
12624
  refetchInterval: (query) => {
@@ -12512,53 +12633,6 @@ function usePaymentIntent(params) {
12512
12633
  });
12513
12634
  }
12514
12635
 
12515
- // src/hooks/use-deposit-quote.ts
12516
- var import_react_query10 = require("@tanstack/react-query");
12517
- var import_core25 = require("@unifold/core");
12518
- function useDepositQuote(params) {
12519
- const {
12520
- publishableKey,
12521
- sourceChainType,
12522
- sourceChainId,
12523
- sourceTokenAddress,
12524
- destinationAmount,
12525
- destinationChainType,
12526
- destinationChainId,
12527
- destinationTokenAddress,
12528
- enabled = true
12529
- } = params;
12530
- const request = {
12531
- source_chain_type: sourceChainType,
12532
- source_chain_id: sourceChainId,
12533
- source_token_address: sourceTokenAddress,
12534
- destination_amount: destinationAmount,
12535
- destination_chain_type: destinationChainType,
12536
- destination_chain_id: destinationChainId,
12537
- destination_token_address: destinationTokenAddress
12538
- };
12539
- return (0, import_react_query10.useQuery)({
12540
- queryKey: [
12541
- "unifold",
12542
- "depositQuote",
12543
- sourceChainType,
12544
- sourceChainId,
12545
- sourceTokenAddress,
12546
- destinationAmount,
12547
- destinationChainType,
12548
- destinationChainId,
12549
- destinationTokenAddress,
12550
- publishableKey
12551
- ],
12552
- queryFn: () => (0, import_core25.getDepositQuote)(request, publishableKey),
12553
- enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
12554
- staleTime: 6e4,
12555
- gcTime: 5 * 6e4,
12556
- refetchOnWindowFocus: false,
12557
- retry: 2,
12558
- retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 5e3)
12559
- });
12560
- }
12561
-
12562
12636
  // src/components/checkout/CheckoutModal.tsx
12563
12637
  var import_jsx_runtime52 = require("react/jsx-runtime");
12564
12638
  function mapDepositAddressesToWallets(depositAddresses, pi) {
@@ -12710,6 +12784,7 @@ function CheckoutModal({
12710
12784
  destinationChainType: paymentIntent?.destination_chain_type ?? "",
12711
12785
  destinationChainId: paymentIntent?.destination_chain_id ?? "",
12712
12786
  destinationTokenAddress: paymentIntent?.destination_token_address ?? "",
12787
+ adjustForSlippage: true,
12713
12788
  enabled: open && view === "transfer" && !!paymentIntent && !!selectedSource && quoteDestinationAmount !== "0"
12714
12789
  });
12715
12790
  const handleBrowserWalletClick = (0, import_react19.useCallback)(
@@ -13101,6 +13176,7 @@ function CheckoutModal({
13101
13176
  depositConfirmationMode: "auto_ui",
13102
13177
  wallets,
13103
13178
  onSourceTokenChange: setSelectedSource,
13179
+ productType: "payment",
13104
13180
  checkoutQuote: sourceQuote ? {
13105
13181
  sourceAmount: sourceQuote.source_amount,
13106
13182
  sourceTokenDecimals: sourceQuote.source_token_decimals,
@@ -13140,6 +13216,16 @@ function CheckoutModal({
13140
13216
  prefillAmountUsd: remainingAmountUsd,
13141
13217
  checkoutAmountUsd: paymentIntent?.amount_usd,
13142
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,
13143
13229
  onSuccess: (txHash) => {
13144
13230
  onCheckoutSuccess?.({
13145
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
  }
@@ -6586,8 +6586,11 @@ function BrowserWalletButton({
6586
6586
  solanaProvider.off("accountChanged", handleAccountsChanged);
6587
6587
  }
6588
6588
  for (const provider of ethProviders) {
6589
- provider.removeListener("accountsChanged", handleEthAccountsChanged);
6590
- provider.removeListener("chainChanged", handleAccountsChanged);
6589
+ const off = provider.off?.bind(provider) ?? provider.removeListener?.bind(provider);
6590
+ if (off) {
6591
+ off("accountsChanged", handleEthAccountsChanged);
6592
+ off("chainChanged", handleAccountsChanged);
6593
+ }
6591
6594
  }
6592
6595
  };
6593
6596
  }, [chainType, eip6963ProviderCount]);
@@ -7023,11 +7026,16 @@ import {
7023
7026
  getSupportedDepositTokens
7024
7027
  } from "@unifold/core";
7025
7028
  function useSupportedDepositTokens(publishableKey, options) {
7026
- const filteredOptions = options?.destination_token_address && options?.destination_chain_id && options?.destination_chain_type ? {
7027
- destination_token_address: options.destination_token_address,
7028
- destination_chain_id: options.destination_chain_id,
7029
- destination_chain_type: options.destination_chain_type
7030
- } : void 0;
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;
7031
7039
  return useQuery8({
7032
7040
  queryKey: [
7033
7041
  "unifold",
@@ -7035,9 +7043,13 @@ function useSupportedDepositTokens(publishableKey, options) {
7035
7043
  publishableKey,
7036
7044
  filteredOptions?.destination_token_address ?? null,
7037
7045
  filteredOptions?.destination_chain_id ?? null,
7038
- filteredOptions?.destination_chain_type ?? null
7046
+ filteredOptions?.destination_chain_type ?? null,
7047
+ filteredOptions?.product_type ?? null
7039
7048
  ],
7040
- queryFn: () => getSupportedDepositTokens(publishableKey, filteredOptions),
7049
+ queryFn: () => getSupportedDepositTokens(
7050
+ publishableKey,
7051
+ hasFilteredOptions ? filteredOptions : void 0
7052
+ ),
7041
7053
  staleTime: 1e3 * 60 * 5,
7042
7054
  // 5 minutes — token list rarely changes
7043
7055
  gcTime: 1e3 * 60 * 30,
@@ -8328,7 +8340,8 @@ function TransferCryptoSingleInput({
8328
8340
  onDepositError,
8329
8341
  wallets: externalWallets,
8330
8342
  onSourceTokenChange,
8331
- checkoutQuote
8343
+ checkoutQuote,
8344
+ productType
8332
8345
  }) {
8333
8346
  const { themeClass, colors: colors2, fonts, components } = useTheme();
8334
8347
  const isDarkMode = themeClass.includes("uf-dark");
@@ -8341,7 +8354,8 @@ function TransferCryptoSingleInput({
8341
8354
  const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDepositTokens(publishableKey, {
8342
8355
  destination_token_address: destinationTokenAddress,
8343
8356
  destination_chain_id: destinationChainId,
8344
- destination_chain_type: destinationChainType
8357
+ destination_chain_type: destinationChainType,
8358
+ product_type: productType
8345
8359
  });
8346
8360
  const supportedTokens = tokensResponse?.data ?? [];
8347
8361
  const { token, chain, setToken, setChain, initialSelectionDone } = useDefaultSourceToken({
@@ -9414,6 +9428,60 @@ import {
9414
9428
  sendSolanaTransaction as sendSolanaTransactionToBackend
9415
9429
  } from "@unifold/core";
9416
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
+
9417
9485
  // src/components/deposits/browser-wallets/types.ts
9418
9486
  var BROWSER_WALLET_STEP_MIN_HEIGHT_CLASS = "uf-min-h-[460px]";
9419
9487
 
@@ -9902,7 +9970,7 @@ function EnterAmountView({
9902
9970
  }
9903
9971
  )
9904
9972
  ] }) }),
9905
- tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && (isCheckout && checkoutAmountUsd && inputUsdNum > parseFloat(checkoutAmountUsd) - parseFloat(checkoutReceivedUsd || "0") + 5e-3 ? /* @__PURE__ */ jsxs39(
9973
+ tokenChainDetails && tokenChainDetails.minimum_deposit_amount_usd > 0 && (isCheckout && checkoutAmountUsd && tokenChainDetails.minimum_deposit_amount_usd > parseFloat(checkoutAmountUsd) - parseFloat(checkoutReceivedUsd || "0") + 5e-3 ? /* @__PURE__ */ jsxs39(
9906
9974
  "div",
9907
9975
  {
9908
9976
  className: "uf-rounded-lg uf-px-3 uf-py-2 uf-mb-3 uf-text-center",
@@ -10516,7 +10584,11 @@ function BrowserWalletModal({
10516
10584
  checkoutReceivedUsd,
10517
10585
  onNewDeposit,
10518
10586
  onDone,
10519
- paymentIntentStatus
10587
+ paymentIntentStatus,
10588
+ checkoutQuote,
10589
+ checkoutDestination,
10590
+ checkoutRemainingBaseUnits,
10591
+ productType
10520
10592
  }) {
10521
10593
  const { colors: colors2, fonts, components } = useTheme();
10522
10594
  const [step, setStep] = React26.useState("select-token");
@@ -10538,7 +10610,49 @@ function BrowserWalletModal({
10538
10610
  const themeClass = theme === "dark" ? "uf-dark" : "";
10539
10611
  const chainType = depositWallet.chain_type;
10540
10612
  const recipientAddress = depositWallet.address;
10613
+ const isCheckoutMode = !!checkoutAmountUsd;
10541
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]);
10542
10656
  const { executions: depositExecutions, isPolling, handleIveDeposited } = useDepositPolling({
10543
10657
  userId,
10544
10658
  publishableKey,
@@ -10590,7 +10704,8 @@ function BrowserWalletModal({
10590
10704
  const options = {
10591
10705
  destination_token_address: depositWallet.destination_token_address,
10592
10706
  destination_chain_id: depositWallet.destination_chain_id,
10593
- destination_chain_type: depositWallet.destination_chain_type
10707
+ destination_chain_type: depositWallet.destination_chain_type,
10708
+ ...productType ? { product_type: productType } : {}
10594
10709
  };
10595
10710
  const response = await getSupportedDepositTokens2(
10596
10711
  publishableKey,
@@ -10992,7 +11107,6 @@ function BrowserWalletModal({
10992
11107
  throw error2;
10993
11108
  }
10994
11109
  };
10995
- const selectedToken = selectedBalance ? getTokenFromBalance(selectedBalance) : null;
10996
11110
  const usdToTokenRate = React26.useMemo(() => {
10997
11111
  if (!selectedBalance || !selectedBalance.amount_usd || !selectedToken)
10998
11112
  return 0;
@@ -11002,15 +11116,24 @@ function BrowserWalletModal({
11002
11116
  return balanceAmount / balanceUsd;
11003
11117
  }, [selectedBalance, selectedToken]);
11004
11118
  const tokenAmount = React26.useMemo(() => {
11119
+ if (isCheckoutMode && activeCheckoutQuote && selectedToken) {
11120
+ return Number(activeCheckoutQuote.sourceAmount) / 10 ** activeCheckoutQuote.sourceTokenDecimals;
11121
+ }
11005
11122
  const usdNum = parseFloat(amountUsd) || 0;
11006
11123
  if (usdNum === 0 || usdToTokenRate === 0) return 0;
11007
11124
  return usdNum * usdToTokenRate;
11008
- }, [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]);
11009
11132
  const maxTokenAmount = selectedBalance && selectedToken ? Number(selectedBalance.amount) / 10 ** selectedToken.decimals : 0;
11010
11133
  const maxUsdAmount = selectedBalance?.amount_usd ? parseFloat(selectedBalance.amount_usd) : 0;
11011
11134
  const inputUsdNum = parseFloat(amountUsd) || 0;
11012
11135
  const minDepositUsd = tokenChainDetails?.minimum_deposit_amount_usd || 0;
11013
- const isValidAmount = inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
11136
+ const isValidAmount = isCheckoutMode && activeCheckoutQuote ? tokenAmount > 0 && tokenAmount <= maxTokenAmount : inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
11014
11137
  const formattedTokenAmount = React26.useMemo(() => {
11015
11138
  if (tokenAmount === 0 || !selectedToken) return null;
11016
11139
  return `${tokenAmount.toFixed(6)} ${selectedToken.symbol}`.replace(
@@ -12458,7 +12581,7 @@ import {
12458
12581
  import { AlertTriangle as AlertTriangle2, ChevronRight as ChevronRight12 } from "lucide-react";
12459
12582
 
12460
12583
  // src/hooks/use-payment-intent.ts
12461
- import { useQuery as useQuery9 } from "@tanstack/react-query";
12584
+ import { useQuery as useQuery10 } from "@tanstack/react-query";
12462
12585
  import { retrievePaymentIntent } from "@unifold/core";
12463
12586
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
12464
12587
  "succeeded",
@@ -12473,7 +12596,7 @@ function usePaymentIntent(params) {
12473
12596
  enabled = true,
12474
12597
  pollingInterval = 3e3
12475
12598
  } = params;
12476
- return useQuery9({
12599
+ return useQuery10({
12477
12600
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
12478
12601
  queryFn: () => retrievePaymentIntent(clientSecret, publishableKey),
12479
12602
  enabled: enabled && !!clientSecret && !!publishableKey,
@@ -12490,55 +12613,6 @@ function usePaymentIntent(params) {
12490
12613
  });
12491
12614
  }
12492
12615
 
12493
- // src/hooks/use-deposit-quote.ts
12494
- import { useQuery as useQuery10 } from "@tanstack/react-query";
12495
- import {
12496
- getDepositQuote
12497
- } from "@unifold/core";
12498
- function useDepositQuote(params) {
12499
- const {
12500
- publishableKey,
12501
- sourceChainType,
12502
- sourceChainId,
12503
- sourceTokenAddress,
12504
- destinationAmount,
12505
- destinationChainType,
12506
- destinationChainId,
12507
- destinationTokenAddress,
12508
- enabled = true
12509
- } = params;
12510
- const request = {
12511
- source_chain_type: sourceChainType,
12512
- source_chain_id: sourceChainId,
12513
- source_token_address: sourceTokenAddress,
12514
- destination_amount: destinationAmount,
12515
- destination_chain_type: destinationChainType,
12516
- destination_chain_id: destinationChainId,
12517
- destination_token_address: destinationTokenAddress
12518
- };
12519
- return useQuery10({
12520
- queryKey: [
12521
- "unifold",
12522
- "depositQuote",
12523
- sourceChainType,
12524
- sourceChainId,
12525
- sourceTokenAddress,
12526
- destinationAmount,
12527
- destinationChainType,
12528
- destinationChainId,
12529
- destinationTokenAddress,
12530
- publishableKey
12531
- ],
12532
- queryFn: () => getDepositQuote(request, publishableKey),
12533
- enabled: enabled && !!publishableKey && !!sourceChainType && !!sourceChainId && !!sourceTokenAddress && !!destinationAmount && destinationAmount !== "0" && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress,
12534
- staleTime: 6e4,
12535
- gcTime: 5 * 6e4,
12536
- refetchOnWindowFocus: false,
12537
- retry: 2,
12538
- retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 5e3)
12539
- });
12540
- }
12541
-
12542
12616
  // src/components/checkout/CheckoutModal.tsx
12543
12617
  import { Fragment as Fragment10, jsx as jsx52, jsxs as jsxs45 } from "react/jsx-runtime";
12544
12618
  function mapDepositAddressesToWallets(depositAddresses, pi) {
@@ -12690,6 +12764,7 @@ function CheckoutModal({
12690
12764
  destinationChainType: paymentIntent?.destination_chain_type ?? "",
12691
12765
  destinationChainId: paymentIntent?.destination_chain_id ?? "",
12692
12766
  destinationTokenAddress: paymentIntent?.destination_token_address ?? "",
12767
+ adjustForSlippage: true,
12693
12768
  enabled: open && view === "transfer" && !!paymentIntent && !!selectedSource && quoteDestinationAmount !== "0"
12694
12769
  });
12695
12770
  const handleBrowserWalletClick = useCallback5(
@@ -13081,6 +13156,7 @@ function CheckoutModal({
13081
13156
  depositConfirmationMode: "auto_ui",
13082
13157
  wallets,
13083
13158
  onSourceTokenChange: setSelectedSource,
13159
+ productType: "payment",
13084
13160
  checkoutQuote: sourceQuote ? {
13085
13161
  sourceAmount: sourceQuote.source_amount,
13086
13162
  sourceTokenDecimals: sourceQuote.source_token_decimals,
@@ -13120,6 +13196,16 @@ function CheckoutModal({
13120
13196
  prefillAmountUsd: remainingAmountUsd,
13121
13197
  checkoutAmountUsd: paymentIntent?.amount_usd,
13122
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,
13123
13209
  onSuccess: (txHash) => {
13124
13210
  onCheckoutSuccess?.({
13125
13211
  paymentIntentId: paymentIntent?.id || "",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifold/ui-react",
3
- "version": "0.1.51",
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.51"
37
+ "@unifold/core": "0.1.53"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@solana/web3.js": "^1.87.0",