@unifold/ui-react 0.1.68-beta.2 → 0.1.69

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.mjs CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  useState as useState40,
4
4
  useEffect as useEffect34,
5
5
  useLayoutEffect as useLayoutEffect2,
6
- useCallback as useCallback8,
7
- useRef as useRef12,
8
- useMemo as useMemo13
6
+ useCallback as useCallback10,
7
+ useRef as useRef13,
8
+ useMemo as useMemo14
9
9
  } from "react";
10
10
  import { ChevronRight as ChevronRight18, MapPinOff as MapPinOff2, AlertTriangle as AlertTriangle3, Bitcoin, DollarSign as DollarSign3 } from "lucide-react";
11
11
 
@@ -465,6 +465,7 @@ var DialogContent = React3.forwardRef(({ className, style, children, omitOverlay
465
465
  className: cn(
466
466
  portalContainer ? "uf-absolute" : "uf-fixed",
467
467
  "uf-bottom-0 uf-left-0 uf-right-0 uf-top-0 uf-z-50 uf-grid uf-w-full uf-max-w-full uf-h-full",
468
+ "focus:uf-outline-none focus-visible:uf-outline-none",
468
469
  !portalContainer && "sm:uf-left-[50%] sm:uf-top-[50%] sm:uf-bottom-auto sm:uf-right-auto sm:uf-translate-x-[-50%] sm:uf-translate-y-[-50%] sm:uf-h-auto",
469
470
  "uf-border uf-bg-background",
470
471
  omitOverlayEmbed ? "uf-gap-0 uf-p-0" : "uf-gap-4 uf-p-6 uf-shadow-lg uf-duration-200",
@@ -480,6 +481,14 @@ var DialogContent = React3.forwardRef(({ className, style, children, omitOverlay
480
481
  ),
481
482
  style: {
482
483
  "--uf-container-radius": `${components.container.borderRadius}px`,
484
+ // Radix traps focus and, when the focused control unmounts during an
485
+ // in-modal screen transition, moves focus onto this container. Modern
486
+ // browsers paint the default focus ring via `:focus-visible`, which
487
+ // flashes a highlight around the whole modal until focus settles on
488
+ // the next screen. Suppress it inline so it works regardless of the
489
+ // Tailwind build (the container is a programmatic focus target, not an
490
+ // interactive control, so it should never show a focus ring).
491
+ outline: "none",
483
492
  ...portalContainer ? { display: "flex", flexDirection: "column" } : {},
484
493
  ...style
485
494
  },
@@ -570,13 +579,16 @@ function GeoRestrictionScreen({ methodName, message }) {
570
579
  }
571
580
 
572
581
  // src/components/deposits/BuyWithCard.tsx
582
+ import * as React5 from "react";
573
583
  import { useState as useState10, useEffect as useEffect6, useRef as useRef2 } from "react";
584
+ import { useQuery as useQuery3 } from "@tanstack/react-query";
574
585
  import { ChevronDown as ChevronDown2, ChevronRight } from "lucide-react";
575
586
  import {
576
587
  getOnrampQuotes,
577
588
  getOnrampSessionStartUrl,
578
589
  getWalletByChainType,
579
590
  getFiatCurrencies,
591
+ getFiatExchangeRates,
580
592
  getTokenMetadata,
581
593
  getIconUrlWithCdn,
582
594
  getPreferredIconUrl as getPreferredIconUrl2,
@@ -2586,13 +2598,25 @@ function BuyWithCard({
2586
2598
  wallets: externalWallets,
2587
2599
  assetCdnUrl,
2588
2600
  hideDepositFlowInfo = false,
2589
- hideDisplayDescription = false
2601
+ hideDisplayDescription = false,
2602
+ prefilledAmountUsd
2590
2603
  }) {
2591
2604
  const { colors: colors2, fonts, components } = useTheme();
2592
- const [amount, setAmount] = useState10("");
2605
+ const cleanedPrefilledAmountUsd = React5.useMemo(() => {
2606
+ if (!prefilledAmountUsd) return "";
2607
+ return prefilledAmountUsd.replace(/[^0-9.]/g, "");
2608
+ }, [prefilledAmountUsd]);
2609
+ const parsedPrefilledAmountUsd = React5.useMemo(() => {
2610
+ const parsed = parseFloat(cleanedPrefilledAmountUsd);
2611
+ return Number.isFinite(parsed) && parsed > 0 ? parsed : null;
2612
+ }, [cleanedPrefilledAmountUsd]);
2613
+ const shouldAutoConvertPrefilledRef = useRef2(!!cleanedPrefilledAmountUsd);
2614
+ const [amount, setAmount] = useState10(() => cleanedPrefilledAmountUsd);
2593
2615
  const [currency, setCurrency] = useState10("usd");
2594
2616
  const [hasManualCurrencySelection, setHasManualCurrencySelection] = useState10(false);
2595
- const [hasManualAmountEntry, setHasManualAmountEntry] = useState10(false);
2617
+ const [hasManualAmountEntry, setHasManualAmountEntry] = useState10(
2618
+ () => !!cleanedPrefilledAmountUsd
2619
+ );
2596
2620
  const [showCurrencyModal, setShowCurrencyModal] = useState10(false);
2597
2621
  const [quotes, setQuotes] = useState10([]);
2598
2622
  const [quotesLoading, setQuotesLoading] = useState10(false);
@@ -2649,6 +2673,71 @@ function BuyWithCard({
2649
2673
  const [preferredCurrencyCodes, setPreferredCurrencyCodes] = useState10([]);
2650
2674
  const [currenciesLoading, setCurrenciesLoading] = useState10(true);
2651
2675
  const [destinationToken, setDestinationToken] = useState10(null);
2676
+ useEffect6(() => {
2677
+ const hasPrefilledAmount = !!cleanedPrefilledAmountUsd;
2678
+ shouldAutoConvertPrefilledRef.current = hasPrefilledAmount;
2679
+ if (!hasPrefilledAmount) return;
2680
+ setAmount(cleanedPrefilledAmountUsd);
2681
+ setHasManualAmountEntry(true);
2682
+ }, [cleanedPrefilledAmountUsd]);
2683
+ const { data: fiatExchangeRatesResponse, isLoading: isFiatExchangeRatesLoading } = useQuery3({
2684
+ queryKey: ["fiat-exchange-rates", publishableKey],
2685
+ staleTime: 3e4,
2686
+ refetchInterval: 3e4,
2687
+ queryFn: async () => {
2688
+ try {
2689
+ return await getFiatExchangeRates({}, publishableKey);
2690
+ } catch (error) {
2691
+ console.error("Error fetching fiat exchange rates:", error);
2692
+ return { base_currency: "usd", rates: {} };
2693
+ }
2694
+ }
2695
+ });
2696
+ const fiatExchangeRates = fiatExchangeRatesResponse?.rates ?? {};
2697
+ const convertAmountBetweenCurrencies = React5.useCallback(
2698
+ (rawAmount, fromCurrencyCode, toCurrencyCode) => {
2699
+ const parsedAmount = parseFloat(rawAmount);
2700
+ if (!Number.isFinite(parsedAmount) || parsedAmount <= 0) return null;
2701
+ const fromCode = fromCurrencyCode.toLowerCase();
2702
+ const toCode = toCurrencyCode.toLowerCase();
2703
+ const fromRate = fromCode === "usd" ? 1 : fiatExchangeRates[fromCode];
2704
+ const toRate = toCode === "usd" ? 1 : fiatExchangeRates[toCode];
2705
+ if (!Number.isFinite(fromRate) || fromRate <= 0) return null;
2706
+ if (!Number.isFinite(toRate) || toRate <= 0) return null;
2707
+ const usdAmount = parsedAmount / fromRate;
2708
+ return parseFloat((usdAmount * toRate).toFixed(2)).toString();
2709
+ },
2710
+ [fiatExchangeRates]
2711
+ );
2712
+ const getConvertedPrefilledAmount = React5.useCallback(
2713
+ (targetCurrencyCode) => {
2714
+ if (!parsedPrefilledAmountUsd) return null;
2715
+ const normalizedTargetCurrency = targetCurrencyCode.toLowerCase();
2716
+ const rate = normalizedTargetCurrency === "usd" ? 1 : fiatExchangeRates[normalizedTargetCurrency];
2717
+ if (!Number.isFinite(rate) || rate <= 0) return null;
2718
+ return parseFloat((parsedPrefilledAmountUsd * rate).toFixed(2)).toString();
2719
+ },
2720
+ [parsedPrefilledAmountUsd, fiatExchangeRates]
2721
+ );
2722
+ useEffect6(() => {
2723
+ if (!cleanedPrefilledAmountUsd || !shouldAutoConvertPrefilledRef.current) return;
2724
+ const convertedAmount = getConvertedPrefilledAmount(currency);
2725
+ if (!convertedAmount) {
2726
+ if (isFiatExchangeRatesLoading) return;
2727
+ const targetCurrency = currency.toLowerCase();
2728
+ if (targetCurrency !== "usd") {
2729
+ setCurrency("usd");
2730
+ }
2731
+ return;
2732
+ }
2733
+ setAmount(convertedAmount);
2734
+ setHasManualAmountEntry(true);
2735
+ }, [
2736
+ cleanedPrefilledAmountUsd,
2737
+ currency,
2738
+ getConvertedPrefilledAmount,
2739
+ isFiatExchangeRatesLoading
2740
+ ]);
2652
2741
  const depositWalletId = defaultToken ? getWalletByChainType(wallets, defaultToken.destination_token_metadata.chain_type)?.id : void 0;
2653
2742
  const { executions, isPolling, showWaitingUi } = useDepositPolling({
2654
2743
  userId,
@@ -2679,6 +2768,7 @@ function BuyWithCard({
2679
2768
  }, [publishableKey]);
2680
2769
  useEffect6(() => {
2681
2770
  if (hasManualCurrencySelection) return;
2771
+ if (hasManualAmountEntry && !shouldAutoConvertPrefilledRef.current) return;
2682
2772
  if (fiatCurrencies.length === 0 || !userIpInfo?.alpha2) return;
2683
2773
  const userCountryCode = userIpInfo.alpha2;
2684
2774
  const matchingCurrency = fiatCurrencies.find((c) => c.country_codes.includes(userCountryCode));
@@ -2697,7 +2787,15 @@ function BuyWithCard({
2697
2787
  const prevCurrencyRef = useRef2(null);
2698
2788
  useEffect6(() => {
2699
2789
  if (fiatCurrencies.length === 0) return;
2790
+ if (shouldAutoConvertPrefilledRef.current) {
2791
+ prevCurrencyRef.current = currency;
2792
+ return;
2793
+ }
2700
2794
  if (prevCurrencyRef.current !== null && prevCurrencyRef.current !== currency) {
2795
+ if (hasManualAmountEntry) {
2796
+ prevCurrencyRef.current = currency;
2797
+ return;
2798
+ }
2701
2799
  const currentCurrency = fiatCurrencies.find(
2702
2800
  (c) => c.currency_code.toLowerCase() === currency.toLowerCase()
2703
2801
  );
@@ -2706,7 +2804,7 @@ function BuyWithCard({
2706
2804
  }
2707
2805
  }
2708
2806
  prevCurrencyRef.current = currency;
2709
- }, [currency]);
2807
+ }, [currency, fiatCurrencies, hasManualAmountEntry]);
2710
2808
  useEffect6(() => {
2711
2809
  async function fetchDestinationToken() {
2712
2810
  try {
@@ -2883,6 +2981,7 @@ function BuyWithCard({
2883
2981
  return () => clearInterval(timer);
2884
2982
  }, [quotes.length, amount]);
2885
2983
  const handleAmountChange = (value) => {
2984
+ shouldAutoConvertPrefilledRef.current = false;
2886
2985
  if (value === "") {
2887
2986
  setAmount(value);
2888
2987
  setHasManualAmountEntry(true);
@@ -2896,6 +2995,7 @@ function BuyWithCard({
2896
2995
  }
2897
2996
  };
2898
2997
  const handleQuickAmount = (quickAmount) => {
2998
+ shouldAutoConvertPrefilledRef.current = false;
2899
2999
  setAmount(quickAmount.toString());
2900
3000
  setHasManualAmountEntry(true);
2901
3001
  };
@@ -3499,8 +3599,43 @@ function BuyWithCard({
3499
3599
  preferredCurrencyCodes,
3500
3600
  selectedCurrency: currency,
3501
3601
  onSelectCurrency: (currencyCode) => {
3502
- setCurrency(currencyCode.toLowerCase());
3602
+ const nextCurrency = currencyCode.toLowerCase();
3603
+ if (nextCurrency === currency.toLowerCase()) {
3604
+ setHasManualCurrencySelection(true);
3605
+ return;
3606
+ }
3607
+ const currentCurrency = currency;
3503
3608
  setHasManualCurrencySelection(true);
3609
+ if (shouldAutoConvertPrefilledRef.current) {
3610
+ const convertedAmount = getConvertedPrefilledAmount(nextCurrency);
3611
+ if (convertedAmount) {
3612
+ setCurrency(nextCurrency);
3613
+ setAmount(convertedAmount);
3614
+ setHasManualAmountEntry(true);
3615
+ } else {
3616
+ if (isFiatExchangeRatesLoading) return;
3617
+ const fallbackUsdAmount = getConvertedPrefilledAmount("usd");
3618
+ setCurrency("usd");
3619
+ if (fallbackUsdAmount) {
3620
+ setAmount(fallbackUsdAmount);
3621
+ setHasManualAmountEntry(true);
3622
+ }
3623
+ }
3624
+ return;
3625
+ }
3626
+ if (hasManualAmountEntry && amount) {
3627
+ const convertedAmount = convertAmountBetweenCurrencies(
3628
+ amount,
3629
+ currentCurrency,
3630
+ nextCurrency
3631
+ );
3632
+ if (convertedAmount) {
3633
+ setCurrency(nextCurrency);
3634
+ setAmount(convertedAmount);
3635
+ }
3636
+ return;
3637
+ }
3638
+ setCurrency(nextCurrency);
3504
3639
  },
3505
3640
  themeClass
3506
3641
  }
@@ -3519,8 +3654,8 @@ function BuyWithCard({
3519
3654
  }
3520
3655
 
3521
3656
  // src/components/deposits/BuyWithApplePay.tsx
3522
- import * as React5 from "react";
3523
- import { useCallback, useEffect as useEffect7, useMemo as useMemo3, useRef as useRef3, useState as useState11 } from "react";
3657
+ import * as React6 from "react";
3658
+ import { useCallback as useCallback2, useEffect as useEffect7, useMemo as useMemo4, useRef as useRef3, useState as useState11 } from "react";
3524
3659
  import { Loader2 as Loader22 } from "lucide-react";
3525
3660
  import {
3526
3661
  createCoinbaseApplePaySession,
@@ -3577,13 +3712,13 @@ function isOnrampTokenFresh(contact) {
3577
3712
  }
3578
3713
 
3579
3714
  // src/hooks/use-coinbase-legal-agreements.ts
3580
- import { useQuery as useQuery3 } from "@tanstack/react-query";
3715
+ import { useQuery as useQuery4 } from "@tanstack/react-query";
3581
3716
  import { getCoinbaseLegalAgreements } from "@unifold/core";
3582
3717
  function useCoinbaseLegalAgreements({
3583
3718
  publishableKey,
3584
3719
  enabled = true
3585
3720
  }) {
3586
- return useQuery3({
3721
+ return useQuery4({
3587
3722
  queryKey: ["unifold", "coinbaseLegalAgreements", publishableKey],
3588
3723
  queryFn: () => getCoinbaseLegalAgreements(publishableKey),
3589
3724
  enabled: enabled && !!publishableKey,
@@ -3596,10 +3731,10 @@ function useCoinbaseLegalAgreements({
3596
3731
  }
3597
3732
 
3598
3733
  // src/hooks/use-apple-pay-initial-screen.ts
3599
- import { useMemo as useMemo2 } from "react";
3734
+ import { useMemo as useMemo3 } from "react";
3600
3735
 
3601
3736
  // src/hooks/use-apple-pay-limits.ts
3602
- import { useQuery as useQuery4 } from "@tanstack/react-query";
3737
+ import { useQuery as useQuery5 } from "@tanstack/react-query";
3603
3738
  import { getCoinbaseApplePayLimits } from "@unifold/core";
3604
3739
  var US_E164_REGEX = /^\+1\d{10}$/;
3605
3740
  function useApplePayLimits({
@@ -3608,7 +3743,7 @@ function useApplePayLimits({
3608
3743
  enabled = true
3609
3744
  }) {
3610
3745
  const phoneValid = US_E164_REGEX.test(phone);
3611
- return useQuery4({
3746
+ return useQuery5({
3612
3747
  queryKey: ["unifold", "applePayLimits", phone, publishableKey],
3613
3748
  queryFn: ({ signal }) => getCoinbaseApplePayLimits(phone, publishableKey, signal),
3614
3749
  enabled: enabled && phoneValid && !!publishableKey,
@@ -3649,7 +3784,7 @@ function useApplePayInitialScreen({
3649
3784
  sessionPhoneVerified,
3650
3785
  isWaiting
3651
3786
  }) {
3652
- const initialStoredSession = useMemo2(() => getStoredApplePaySession(userId), [userId]);
3787
+ const initialStoredSession = useMemo3(() => getStoredApplePaySession(userId), [userId]);
3653
3788
  const phoneVerified = PHONE_REGEX.test(normalizedPhone) && (sessionPhoneVerified || initialStoredSession?.phone === normalizedPhone && !!initialStoredSession?.phoneVerifiedAt);
3654
3789
  const {
3655
3790
  data: applePayLimits,
@@ -3660,7 +3795,7 @@ function useApplePayInitialScreen({
3660
3795
  publishableKey,
3661
3796
  enabled: phoneVerified
3662
3797
  });
3663
- const action = useMemo2(() => {
3798
+ const action = useMemo3(() => {
3664
3799
  if (isWaiting || applePayLimitsLoading) return { kind: "pending" };
3665
3800
  const stored = initialStoredSession;
3666
3801
  const hasUserEmail = !!userEmail && EMAIL_REGEX.test(userEmail);
@@ -3698,7 +3833,7 @@ function useApplePayInitialScreen({
3698
3833
  }
3699
3834
 
3700
3835
  // src/hooks/use-default-onramp-token.ts
3701
- import { useQuery as useQuery5 } from "@tanstack/react-query";
3836
+ import { useQuery as useQuery6 } from "@tanstack/react-query";
3702
3837
  import { getDefaultOnrampToken as getDefaultOnrampToken2 } from "@unifold/core";
3703
3838
  function useDefaultOnrampToken({
3704
3839
  publishableKey,
@@ -3714,7 +3849,7 @@ function useDefaultOnrampToken({
3714
3849
  isLoading,
3715
3850
  isError,
3716
3851
  error
3717
- } = useQuery5({
3852
+ } = useQuery6({
3718
3853
  queryKey: [
3719
3854
  "unifold",
3720
3855
  "defaultOnrampToken",
@@ -3791,7 +3926,7 @@ function parseCoinbasePostMessage(raw) {
3791
3926
  } : void 0
3792
3927
  };
3793
3928
  }
3794
- var BuyWithApplePay = React5.forwardRef(
3929
+ var BuyWithApplePay = React6.forwardRef(
3795
3930
  function BuyWithApplePay2({
3796
3931
  userId,
3797
3932
  publishableKey,
@@ -3862,7 +3997,7 @@ var BuyWithApplePay = React5.forwardRef(
3862
3997
  countryCode: userIpInfo?.alpha2,
3863
3998
  subdivisionCode: userIpInfo?.subdivisionCode ?? void 0
3864
3999
  });
3865
- const depositWallet = useMemo3(() => {
4000
+ const depositWallet = useMemo4(() => {
3866
4001
  const routingChainType = defaultToken?.destination_token_metadata?.chain_type;
3867
4002
  if (!routingChainType) return void 0;
3868
4003
  return getWalletByChainType2(depositWallets ?? [], routingChainType);
@@ -3950,7 +4085,7 @@ var BuyWithApplePay = React5.forwardRef(
3950
4085
  popupRef.current = null;
3951
4086
  };
3952
4087
  }, []);
3953
- React5.useImperativeHandle(
4088
+ React6.useImperativeHandle(
3954
4089
  ref,
3955
4090
  () => ({
3956
4091
  requestBack: () => {
@@ -3992,9 +4127,9 @@ var BuyWithApplePay = React5.forwardRef(
3992
4127
  }),
3993
4128
  [view, emailLocked]
3994
4129
  );
3995
- const normalizedPhone = useMemo3(() => formatPhoneInput(phoneInput), [phoneInput]);
4130
+ const normalizedPhone = useMemo4(() => formatPhoneInput(phoneInput), [phoneInput]);
3996
4131
  const isContactValid = EMAIL_REGEX2.test(email) && PHONE_REGEX2.test(normalizedPhone);
3997
- const storeApplePaySession = useCallback(
4132
+ const storeApplePaySession = useCallback2(
3998
4133
  (patch = {}) => {
3999
4134
  const session = {
4000
4135
  email,
@@ -4006,7 +4141,7 @@ var BuyWithApplePay = React5.forwardRef(
4006
4141
  },
4007
4142
  [email, normalizedPhone, userId]
4008
4143
  );
4009
- const createSessionAndSendOtp = useCallback(async () => {
4144
+ const createSessionAndSendOtp = useCallback2(async () => {
4010
4145
  setView("submitting_session");
4011
4146
  setErrorMessage("");
4012
4147
  try {
@@ -4034,7 +4169,7 @@ var BuyWithApplePay = React5.forwardRef(
4034
4169
  setView("phone_input");
4035
4170
  }
4036
4171
  }, [email, normalizedPhone, publishableKey, storeApplePaySession]);
4037
- const clearUpgradeFields = useCallback(() => {
4172
+ const clearUpgradeFields = useCallback2(() => {
4038
4173
  setSsnLast4("");
4039
4174
  setDobInput("");
4040
4175
  }, []);
@@ -4046,7 +4181,7 @@ var BuyWithApplePay = React5.forwardRef(
4046
4181
  sessionPhoneVerified: verificationSession?.phone?.status === "verified",
4047
4182
  isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
4048
4183
  });
4049
- const pollLimitUpgradeStatus = useCallback(
4184
+ const pollLimitUpgradeStatus = useCallback2(
4050
4185
  async (signal) => {
4051
4186
  const POLL_INTERVAL_MS4 = 1500;
4052
4187
  const POLL_TIMEOUT_MS = 3e4;
@@ -4108,7 +4243,7 @@ var BuyWithApplePay = React5.forwardRef(
4108
4243
  clearUpgradeFields
4109
4244
  ]
4110
4245
  );
4111
- const startUpgradePolling = useCallback(async () => {
4246
+ const startUpgradePolling = useCallback2(async () => {
4112
4247
  upgradeFlowAbortRef.current?.abort();
4113
4248
  const controller = new AbortController();
4114
4249
  upgradeFlowAbortRef.current = controller;
@@ -4120,7 +4255,7 @@ var BuyWithApplePay = React5.forwardRef(
4120
4255
  }
4121
4256
  }
4122
4257
  }, [pollLimitUpgradeStatus]);
4123
- const applyLimitRouting = useCallback(
4258
+ const applyLimitRouting = useCallback2(
4124
4259
  (nextView, status) => {
4125
4260
  if (nextView === "limit_upgrade_form" && status === "resubmit") {
4126
4261
  setLimitUpgradeError(
@@ -4157,11 +4292,11 @@ var BuyWithApplePay = React5.forwardRef(
4157
4292
  break;
4158
4293
  }
4159
4294
  }, [initialAction, applyLimitRouting, createSessionAndSendOtp]);
4160
- const startVerification = useCallback(async () => {
4295
+ const startVerification = useCallback2(async () => {
4161
4296
  if (!isContactValid) return;
4162
4297
  await createSessionAndSendOtp();
4163
4298
  }, [isContactValid, createSessionAndSendOtp]);
4164
- const submitLimitUpgrade = useCallback(async () => {
4299
+ const submitLimitUpgrade = useCallback2(async () => {
4165
4300
  if (upgradeSubmitting) return;
4166
4301
  try {
4167
4302
  const dob = parseDobInput(dobInput);
@@ -4211,7 +4346,7 @@ var BuyWithApplePay = React5.forwardRef(
4211
4346
  startUpgradePolling,
4212
4347
  clearUpgradeFields
4213
4348
  ]);
4214
- const submitPhoneOtp = useCallback(async () => {
4349
+ const submitPhoneOtp = useCallback2(async () => {
4215
4350
  if (!verificationSession || !clientSecret || phoneCode.length !== 6) return;
4216
4351
  if (otpSubmitting) return;
4217
4352
  setOtpError(null);
@@ -4279,7 +4414,7 @@ var BuyWithApplePay = React5.forwardRef(
4279
4414
  getViewForLimitStatus,
4280
4415
  applyLimitRouting
4281
4416
  ]);
4282
- const prepareSession = useCallback(
4417
+ const prepareSession = useCallback2(
4283
4418
  async (token, amt) => {
4284
4419
  setErrorMessage("");
4285
4420
  if (!destinationChainType || !destinationChainId) {
@@ -5260,7 +5395,7 @@ function LegalDisclaimer({ legalAgreements, loading }) {
5260
5395
  children: [
5261
5396
  "By continuing, you agree to Coinbase's",
5262
5397
  " ",
5263
- agreements.map((a, idx, arr) => /* @__PURE__ */ jsxs11(React5.Fragment, { children: [
5398
+ agreements.map((a, idx, arr) => /* @__PURE__ */ jsxs11(React6.Fragment, { children: [
5264
5399
  /* @__PURE__ */ jsx13(
5265
5400
  "a",
5266
5401
  {
@@ -5536,7 +5671,7 @@ function PayWithExchange({
5536
5671
  }
5537
5672
 
5538
5673
  // src/components/deposits/PayWithCashApp.tsx
5539
- import { useState as useState15, useEffect as useEffect10, useCallback as useCallback2 } from "react";
5674
+ import { useState as useState15, useEffect as useEffect10, useCallback as useCallback3 } from "react";
5540
5675
  import { Copy, Check as Check3, Clock, RefreshCw, Loader2 as Loader23 } from "lucide-react";
5541
5676
  import {
5542
5677
  createCashAppSession,
@@ -5546,7 +5681,7 @@ import {
5546
5681
  } from "@unifold/core";
5547
5682
 
5548
5683
  // src/components/deposits/StyledQRCode.tsx
5549
- import { useEffect as useEffect8, useRef as useRef4, useState as useState13, useMemo as useMemo4 } from "react";
5684
+ import { useEffect as useEffect8, useRef as useRef4, useState as useState13, useMemo as useMemo5 } from "react";
5550
5685
  import QRCodeStyling from "qr-code-styling";
5551
5686
  import { jsx as jsx15, jsxs as jsxs13 } from "react/jsx-runtime";
5552
5687
  function createQRConfig(value, size, imageUrl, imageSize, darkMode) {
@@ -5599,7 +5734,7 @@ function QRCodeSkeleton({ size = 180, darkMode = false }) {
5599
5734
  const spacing = size / gridCount;
5600
5735
  const fillColor = darkMode ? "rgba(255,255,255,0.10)" : "rgba(0,0,0,0.08)";
5601
5736
  const cornerColor = darkMode ? "rgba(255,255,255,0.14)" : "rgba(0,0,0,0.12)";
5602
- const dots = useMemo4(() => {
5737
+ const dots = useMemo5(() => {
5603
5738
  const result = [];
5604
5739
  const cornerSize = 7;
5605
5740
  const centerStart = Math.floor(gridCount / 2) - 2;
@@ -5703,10 +5838,10 @@ function useIsMobileViewport() {
5703
5838
  }
5704
5839
 
5705
5840
  // src/hooks/use-cashapp-limits.ts
5706
- import { useQuery as useQuery6 } from "@tanstack/react-query";
5841
+ import { useQuery as useQuery7 } from "@tanstack/react-query";
5707
5842
  import { getCashAppLimits } from "@unifold/core";
5708
5843
  function useCashAppLimits({ publishableKey, currency = "usd" }) {
5709
- return useQuery6({
5844
+ return useQuery7({
5710
5845
  queryKey: ["unifold", "cashAppLimits", currency, publishableKey],
5711
5846
  queryFn: () => getCashAppLimits(currency, publishableKey),
5712
5847
  enabled: !!publishableKey,
@@ -5722,6 +5857,7 @@ var POLL_INTERVAL_MS2 = 5e3;
5722
5857
  var FALLBACK_MIN_USD = 5;
5723
5858
  var SUGGESTED_AMOUNTS = [25, 50, 100];
5724
5859
  var t3 = i18n.depositModal.cashApp;
5860
+ var sanitizePrefilledUsd = (value) => value?.replace(/[^0-9.]/g, "") ?? "";
5725
5861
  function PayWithCashApp({
5726
5862
  userId,
5727
5863
  publishableKey,
@@ -5736,6 +5872,7 @@ function PayWithCashApp({
5736
5872
  onEvent,
5737
5873
  onDepositSuccess,
5738
5874
  onDepositError,
5875
+ prefilledAmountUsd,
5739
5876
  wallets = []
5740
5877
  }) {
5741
5878
  const { colors: colors2, fonts, components } = useTheme();
@@ -5751,14 +5888,14 @@ function PayWithCashApp({
5751
5888
  const { data: limits, isLoading: limitsLoading } = useCashAppLimits({ publishableKey });
5752
5889
  const minUsd = limits?.minimum_amount ?? FALLBACK_MIN_USD;
5753
5890
  const maxUsd = limits?.maximum_amount ?? null;
5754
- const [amount, setAmount] = useState15("");
5891
+ const [amount, setAmount] = useState15(() => sanitizePrefilledUsd(prefilledAmountUsd));
5755
5892
  const [loading, setLoading] = useState15(false);
5756
5893
  const [session, setSession] = useState15(null);
5757
5894
  const [status, setStatus] = useState15("pending");
5758
5895
  const [error, setError] = useState15(null);
5759
5896
  const [copied, setCopied] = useState15(false);
5760
5897
  const [view, setViewInternal] = useState15(controlledView ?? "amount");
5761
- const setView = useCallback2(
5898
+ const setView = useCallback3(
5762
5899
  (v) => {
5763
5900
  setViewInternal(v);
5764
5901
  onViewChange?.(v);
@@ -5788,7 +5925,7 @@ function PayWithCashApp({
5788
5925
  onDepositSuccess,
5789
5926
  onDepositError
5790
5927
  });
5791
- const handleAmountChange = useCallback2(
5928
+ const handleAmountChange = useCallback3(
5792
5929
  (raw) => {
5793
5930
  const cleaned = raw.replace(/[^0-9.]/g, "");
5794
5931
  const parts = cleaned.split(".");
@@ -5800,7 +5937,7 @@ function PayWithCashApp({
5800
5937
  },
5801
5938
  [onAmountChange]
5802
5939
  );
5803
- const handleCreateSession = useCallback2(async () => {
5940
+ const handleCreateSession = useCallback3(async () => {
5804
5941
  if (!amount || !recipientAddress || !destinationChainType || !destinationChainId || !destinationTokenAddress) {
5805
5942
  setError("Missing required fields");
5806
5943
  return;
@@ -5874,6 +6011,13 @@ function PayWithCashApp({
5874
6011
  return () => clearInterval(interval);
5875
6012
  }, [session, view, status, publishableKey, onDepositSuccess, onDepositError]);
5876
6013
  const [softExpired, setSoftExpired] = useState15(false);
6014
+ useEffect10(() => {
6015
+ if (!prefilledAmountUsd) return;
6016
+ const cleaned = sanitizePrefilledUsd(prefilledAmountUsd);
6017
+ if (!cleaned) return;
6018
+ setAmount(cleaned);
6019
+ onAmountChange?.(cleaned);
6020
+ }, [prefilledAmountUsd, onAmountChange]);
5877
6021
  useEffect10(() => {
5878
6022
  if (!session?.expires_at || view !== "payment") return;
5879
6023
  const expiresMs = new Date(session.expires_at).getTime();
@@ -5888,12 +6032,12 @@ function PayWithCashApp({
5888
6032
  const interval = setInterval(tick, 1e3);
5889
6033
  return () => clearInterval(interval);
5890
6034
  }, [session, view, status]);
5891
- const handleCopy = useCallback2(async (text) => {
6035
+ const handleCopy = useCallback3(async (text) => {
5892
6036
  await navigator.clipboard.writeText(text);
5893
6037
  setCopied(true);
5894
6038
  setTimeout(() => setCopied(false), 2e3);
5895
6039
  }, []);
5896
- const handleRecreate = useCallback2(() => {
6040
+ const handleRecreate = useCallback3(() => {
5897
6041
  setSession(null);
5898
6042
  setStatus("pending");
5899
6043
  setError(null);
@@ -6224,18 +6368,19 @@ function PayWithCashApp({
6224
6368
  }
6225
6369
 
6226
6370
  // src/components/deposits/BankTransfer.tsx
6227
- import { useEffect as useEffect11, useMemo as useMemo5, useState as useState16 } from "react";
6371
+ import { useCallback as useCallback4, useEffect as useEffect11, useMemo as useMemo6, useRef as useRef5, useState as useState16 } from "react";
6228
6372
  import { ChevronRight as ChevronRight3, ExternalLink as ExternalLink3, Landmark } from "lucide-react";
6229
6373
  import {
6230
6374
  DepositEventType as DepositEventType5,
6231
6375
  getIconUrlWithCdn as getIconUrlWithCdn2,
6232
6376
  getOnrampSessionStartUrl as getOnrampSessionStartUrl2,
6377
+ getFiatExchangeRates as getFiatExchangeRates2,
6233
6378
  getWalletByChainType as getWalletByChainType3,
6234
6379
  generatePrefixedKSUID as generatePrefixedKSUID5
6235
6380
  } from "@unifold/core";
6236
6381
 
6237
6382
  // src/hooks/use-bank-transfer-providers.ts
6238
- import { useQuery as useQuery7 } from "@tanstack/react-query";
6383
+ import { useQuery as useQuery8 } from "@tanstack/react-query";
6239
6384
  import { getBankTransferProviders } from "@unifold/core";
6240
6385
  function useBankTransferProviders({
6241
6386
  publishableKey,
@@ -6243,7 +6388,7 @@ function useBankTransferProviders({
6243
6388
  countryCode
6244
6389
  }) {
6245
6390
  const normalizedCountry = countryCode?.toUpperCase();
6246
- const { data: providers, isLoading } = useQuery7({
6391
+ const { data: providers, isLoading } = useQuery8({
6247
6392
  queryKey: ["unifold", "bankTransferProviders", publishableKey, normalizedCountry ?? null],
6248
6393
  queryFn: () => getBankTransferProviders(publishableKey, { countryCode: normalizedCountry }),
6249
6394
  enabled,
@@ -6284,7 +6429,8 @@ function BankTransfer({
6284
6429
  assetCdnUrl,
6285
6430
  onDepositSuccess,
6286
6431
  onEvent,
6287
- onDepositError
6432
+ onDepositError,
6433
+ prefilledAmountUsd
6288
6434
  }) {
6289
6435
  const { colors: colors2, fonts, components } = useTheme();
6290
6436
  const [internalView, setInternalView] = useState16("providers");
@@ -6294,6 +6440,10 @@ function BankTransfer({
6294
6440
  const [requestBase, setRequestBase] = useState16(null);
6295
6441
  const [activeRequest, setActiveRequest] = useState16(null);
6296
6442
  const [amount, setAmount] = useState16("");
6443
+ const [fiatExchangeRates, setFiatExchangeRates] = useState16({
6444
+ usd: 1
6445
+ });
6446
+ const providerSelectionRequestIdRef = useRef5(0);
6297
6447
  const currentView = externalView ?? internalView;
6298
6448
  const setView = (v) => {
6299
6449
  setInternalView(v);
@@ -6318,7 +6468,7 @@ function BankTransfer({
6318
6468
  countryCode: userIpInfo?.alpha2
6319
6469
  });
6320
6470
  const providers = providersResponse?.data ?? [];
6321
- const pollingWalletId = useMemo5(() => {
6471
+ const pollingWalletId = useMemo6(() => {
6322
6472
  if (!defaultToken) return void 0;
6323
6473
  return getWalletByChainType3(
6324
6474
  wallets,
@@ -6339,11 +6489,42 @@ function BankTransfer({
6339
6489
  const currencySymbol = getCurrencySymbol2(sourceCurrency);
6340
6490
  const parsedAmount = parseFloat(amount);
6341
6491
  const amountValid = !!amount && Number.isFinite(parsedAmount) && parsedAmount >= MIN_AMOUNT;
6342
- const displayTokenSymbol = useMemo5(
6492
+ const displayTokenSymbol = useMemo6(
6343
6493
  () => destinationTokenSymbol?.toUpperCase() ?? defaultToken?.destination_token_metadata?.symbol?.toUpperCase() ?? defaultToken?.destination_currency?.toUpperCase() ?? "USDC",
6344
6494
  [destinationTokenSymbol, defaultToken]
6345
6495
  );
6346
- const handleProviderClick = (provider) => {
6496
+ const resolvePrefilledSourceAmount = useCallback4(
6497
+ async (sourceCurrencyCode) => {
6498
+ const cleanedPrefilled = prefilledAmountUsd?.replace(/[^0-9.]/g, "") ?? "";
6499
+ if (!cleanedPrefilled) return "";
6500
+ const prefilledUsd = parseFloat(cleanedPrefilled);
6501
+ if (!Number.isFinite(prefilledUsd) || prefilledUsd <= 0) return "";
6502
+ const sourceCurrency2 = sourceCurrencyCode.toLowerCase();
6503
+ let rate = sourceCurrency2 === "usd" ? 1 : fiatExchangeRates[sourceCurrency2];
6504
+ if ((!rate || rate <= 0) && sourceCurrency2 !== "usd") {
6505
+ try {
6506
+ const response = await getFiatExchangeRates2({}, publishableKey);
6507
+ if (response?.rates) {
6508
+ setFiatExchangeRates((prev) => ({
6509
+ ...prev,
6510
+ ...response.rates,
6511
+ usd: 1
6512
+ }));
6513
+ }
6514
+ const fetchedRate = response.rates?.[sourceCurrency2];
6515
+ if (Number.isFinite(fetchedRate) && fetchedRate > 0) {
6516
+ rate = fetchedRate;
6517
+ }
6518
+ } catch (error) {
6519
+ console.error("Error fetching fiat exchange rates for bank transfer:", error);
6520
+ }
6521
+ }
6522
+ if (!rate || rate <= 0) return sourceCurrency2 === "usd" ? cleanedPrefilled : "";
6523
+ return parseFloat((prefilledUsd * rate).toFixed(2)).toString();
6524
+ },
6525
+ [fiatExchangeRates, prefilledAmountUsd, publishableKey]
6526
+ );
6527
+ const handleProviderClick = async (provider) => {
6347
6528
  if (!provider.enabled) return;
6348
6529
  setSessionError(null);
6349
6530
  if (!defaultToken) {
@@ -6362,6 +6543,7 @@ function BankTransfer({
6362
6543
  });
6363
6544
  return;
6364
6545
  }
6546
+ const requestId = ++providerSelectionRequestIdRef.current;
6365
6547
  setRequestBase({
6366
6548
  service_provider: provider.service_provider,
6367
6549
  country_code: (userIpInfo?.alpha2 || "DE").toUpperCase(),
@@ -6375,7 +6557,10 @@ function BankTransfer({
6375
6557
  payment_method: provider.payment_methods[0]
6376
6558
  });
6377
6559
  setActiveProvider(provider);
6378
- setAmount("100");
6560
+ const convertedPrefilled = await resolvePrefilledSourceAmount(provider.source_currency);
6561
+ if (requestId !== providerSelectionRequestIdRef.current) return;
6562
+ const hasPrefilledAmount = !!prefilledAmountUsd?.replace(/[^0-9.]/g, "");
6563
+ setAmount(hasPrefilledAmount ? convertedPrefilled : "100");
6379
6564
  setView("amount");
6380
6565
  };
6381
6566
  const handleAmountChange = (value) => {
@@ -6473,7 +6658,7 @@ function BankTransfer({
6473
6658
  return /* @__PURE__ */ jsxs15(
6474
6659
  "button",
6475
6660
  {
6476
- onClick: () => handleProviderClick(provider),
6661
+ onClick: () => void handleProviderClick(provider),
6477
6662
  onMouseEnter: () => !disabled && setHoveredId(provider.service_provider),
6478
6663
  onMouseLeave: () => setHoveredId(null),
6479
6664
  disabled,
@@ -7042,7 +7227,7 @@ function DepositExecutionItem({ execution, onClick }) {
7042
7227
  }
7043
7228
 
7044
7229
  // src/components/deposits/buttons/TransferCryptoButton.tsx
7045
- import * as React6 from "react";
7230
+ import * as React7 from "react";
7046
7231
  import { Zap, ChevronRight as ChevronRight5 } from "lucide-react";
7047
7232
  import { jsx as jsx19, jsxs as jsxs17 } from "react/jsx-runtime";
7048
7233
  function TransferCryptoButton({
@@ -7052,9 +7237,9 @@ function TransferCryptoButton({
7052
7237
  featuredTokens
7053
7238
  }) {
7054
7239
  const { colors: colors2, fonts, components } = useTheme();
7055
- const [isHovered, setIsHovered] = React6.useState(false);
7056
- const [isTouchDevice, setIsTouchDevice] = React6.useState(false);
7057
- React6.useEffect(() => {
7240
+ const [isHovered, setIsHovered] = React7.useState(false);
7241
+ const [isTouchDevice, setIsTouchDevice] = React7.useState(false);
7242
+ React7.useEffect(() => {
7058
7243
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7059
7244
  }, []);
7060
7245
  const sortedTokens = featuredTokens ? [...featuredTokens].sort((a, b) => a.position - b.position) : [];
@@ -7129,7 +7314,7 @@ function TransferCryptoButton({
7129
7314
  }
7130
7315
 
7131
7316
  // src/components/deposits/buttons/DepositWithCardButton.tsx
7132
- import * as React7 from "react";
7317
+ import * as React8 from "react";
7133
7318
  import { CreditCard, ChevronRight as ChevronRight6 } from "lucide-react";
7134
7319
  import { jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
7135
7320
  function DepositWithCardButton({
@@ -7139,9 +7324,9 @@ function DepositWithCardButton({
7139
7324
  paymentNetworks
7140
7325
  }) {
7141
7326
  const { colors: colors2, fonts, components } = useTheme();
7142
- const [isHovered, setIsHovered] = React7.useState(false);
7143
- const [isTouchDevice, setIsTouchDevice] = React7.useState(false);
7144
- React7.useEffect(() => {
7327
+ const [isHovered, setIsHovered] = React8.useState(false);
7328
+ const [isTouchDevice, setIsTouchDevice] = React8.useState(false);
7329
+ React8.useEffect(() => {
7145
7330
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7146
7331
  }, []);
7147
7332
  return /* @__PURE__ */ jsxs18(
@@ -7214,7 +7399,7 @@ function DepositWithCardButton({
7214
7399
  }
7215
7400
 
7216
7401
  // src/components/deposits/buttons/PayWithExchangeButton.tsx
7217
- import * as React8 from "react";
7402
+ import * as React9 from "react";
7218
7403
  import { ArrowLeftRight, ChevronRight as ChevronRight7 } from "lucide-react";
7219
7404
  import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
7220
7405
  function PayWithExchangeButton({
@@ -7225,9 +7410,9 @@ function PayWithExchangeButton({
7225
7410
  loading = false
7226
7411
  }) {
7227
7412
  const { colors: colors2, fonts, components } = useTheme();
7228
- const [isHovered, setIsHovered] = React8.useState(false);
7229
- const [isTouchDevice, setIsTouchDevice] = React8.useState(false);
7230
- React8.useEffect(() => {
7413
+ const [isHovered, setIsHovered] = React9.useState(false);
7414
+ const [isTouchDevice, setIsTouchDevice] = React9.useState(false);
7415
+ React9.useEffect(() => {
7231
7416
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7232
7417
  }, []);
7233
7418
  if (loading) {
@@ -7306,11 +7491,11 @@ function PayWithExchangeButton({
7306
7491
  }
7307
7492
 
7308
7493
  // src/components/deposits/buttons/ConnectExchangeButton.tsx
7309
- import * as React10 from "react";
7494
+ import * as React11 from "react";
7310
7495
  import { Link2, ChevronRight as ChevronRight8 } from "lucide-react";
7311
7496
 
7312
7497
  // src/components/shared/button.tsx
7313
- import * as React9 from "react";
7498
+ import * as React10 from "react";
7314
7499
  import { Slot } from "@radix-ui/react-slot";
7315
7500
  import { cva } from "class-variance-authority";
7316
7501
  import { jsx as jsx22 } from "react/jsx-runtime";
@@ -7339,11 +7524,11 @@ var buttonVariants = cva(
7339
7524
  }
7340
7525
  }
7341
7526
  );
7342
- var Button = React9.forwardRef(
7527
+ var Button = React10.forwardRef(
7343
7528
  ({ className, variant, size, asChild = false, style, ...props }, ref) => {
7344
7529
  const Comp = asChild ? Slot : "button";
7345
7530
  const { components, fonts } = useTheme();
7346
- const themeStyle = React9.useMemo(() => {
7531
+ const themeStyle = React10.useMemo(() => {
7347
7532
  const baseStyle = { ...style };
7348
7533
  if (variant === "default" || !variant) {
7349
7534
  baseStyle.backgroundColor = components.button.primaryBackground;
@@ -7381,9 +7566,9 @@ function ConnectExchangeButton({
7381
7566
  connectedExchange
7382
7567
  }) {
7383
7568
  const { colors: colors2, fonts, components } = useTheme();
7384
- const [isHovered, setIsHovered] = React10.useState(false);
7385
- const [isTouchDevice, setIsTouchDevice] = React10.useState(false);
7386
- React10.useEffect(() => {
7569
+ const [isHovered, setIsHovered] = React11.useState(false);
7570
+ const [isTouchDevice, setIsTouchDevice] = React11.useState(false);
7571
+ React11.useEffect(() => {
7387
7572
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7388
7573
  }, []);
7389
7574
  const isConnected = connectedExchange != null;
@@ -7523,7 +7708,7 @@ function ConnectExchangeButton({
7523
7708
  }
7524
7709
 
7525
7710
  // src/components/deposits/buttons/DepositTrackerButton.tsx
7526
- import * as React11 from "react";
7711
+ import * as React12 from "react";
7527
7712
  import { Clock as Clock2, ChevronRight as ChevronRight9 } from "lucide-react";
7528
7713
  import { jsx as jsx24, jsxs as jsxs21 } from "react/jsx-runtime";
7529
7714
  function DepositTrackerButton({
@@ -7533,9 +7718,9 @@ function DepositTrackerButton({
7533
7718
  badge
7534
7719
  }) {
7535
7720
  const { colors: colors2, fonts, components } = useTheme();
7536
- const [isHovered, setIsHovered] = React11.useState(false);
7537
- const [isTouchDevice, setIsTouchDevice] = React11.useState(false);
7538
- React11.useEffect(() => {
7721
+ const [isHovered, setIsHovered] = React12.useState(false);
7722
+ const [isTouchDevice, setIsTouchDevice] = React12.useState(false);
7723
+ React12.useEffect(() => {
7539
7724
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7540
7725
  }, []);
7541
7726
  return /* @__PURE__ */ jsxs21(
@@ -7606,14 +7791,14 @@ function DepositTrackerButton({
7606
7791
  }
7607
7792
 
7608
7793
  // src/components/deposits/buttons/CashAppButton.tsx
7609
- import * as React12 from "react";
7794
+ import * as React13 from "react";
7610
7795
  import { ChevronRight as ChevronRight10 } from "lucide-react";
7611
7796
  import { jsx as jsx25, jsxs as jsxs22 } from "react/jsx-runtime";
7612
7797
  function CashAppButton({ onClick, title, subtitle, iconUrl }) {
7613
7798
  const { colors: colors2, fonts, components } = useTheme();
7614
- const [isHovered, setIsHovered] = React12.useState(false);
7615
- const [isTouchDevice, setIsTouchDevice] = React12.useState(false);
7616
- React12.useEffect(() => {
7799
+ const [isHovered, setIsHovered] = React13.useState(false);
7800
+ const [isTouchDevice, setIsTouchDevice] = React13.useState(false);
7801
+ React13.useEffect(() => {
7617
7802
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7618
7803
  }, []);
7619
7804
  return /* @__PURE__ */ jsxs22(
@@ -7677,7 +7862,7 @@ function CashAppButton({ onClick, title, subtitle, iconUrl }) {
7677
7862
  }
7678
7863
 
7679
7864
  // src/components/deposits/buttons/ApplePayButton.tsx
7680
- import * as React13 from "react";
7865
+ import * as React14 from "react";
7681
7866
  import { ChevronRight as ChevronRight11 } from "lucide-react";
7682
7867
  import { jsx as jsx26, jsxs as jsxs23 } from "react/jsx-runtime";
7683
7868
  function AppleLogo({ className, style }) {
@@ -7702,9 +7887,9 @@ function AppleLogo({ className, style }) {
7702
7887
  }
7703
7888
  function ApplePayButton({ onClick, title, subtitle }) {
7704
7889
  const { colors: colors2, fonts, components } = useTheme();
7705
- const [isHovered, setIsHovered] = React13.useState(false);
7706
- const [isTouchDevice, setIsTouchDevice] = React13.useState(false);
7707
- React13.useEffect(() => {
7890
+ const [isHovered, setIsHovered] = React14.useState(false);
7891
+ const [isTouchDevice, setIsTouchDevice] = React14.useState(false);
7892
+ React14.useEffect(() => {
7708
7893
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7709
7894
  }, []);
7710
7895
  return /* @__PURE__ */ jsxs23(
@@ -7761,7 +7946,7 @@ function ApplePayButton({ onClick, title, subtitle }) {
7761
7946
  }
7762
7947
 
7763
7948
  // src/components/deposits/buttons/BankTransferButton.tsx
7764
- import * as React14 from "react";
7949
+ import * as React15 from "react";
7765
7950
  import { Landmark as Landmark2, ChevronRight as ChevronRight12 } from "lucide-react";
7766
7951
  import { jsx as jsx27, jsxs as jsxs24 } from "react/jsx-runtime";
7767
7952
  function BankTransferButton({
@@ -7771,9 +7956,9 @@ function BankTransferButton({
7771
7956
  comingSoon = false
7772
7957
  }) {
7773
7958
  const { colors: colors2, fonts, components } = useTheme();
7774
- const [isHovered, setIsHovered] = React14.useState(false);
7775
- const [isTouchDevice, setIsTouchDevice] = React14.useState(false);
7776
- React14.useEffect(() => {
7959
+ const [isHovered, setIsHovered] = React15.useState(false);
7960
+ const [isTouchDevice, setIsTouchDevice] = React15.useState(false);
7961
+ React15.useEffect(() => {
7777
7962
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
7778
7963
  }, []);
7779
7964
  return /* @__PURE__ */ jsxs24(
@@ -7831,7 +8016,7 @@ function BankTransferButton({
7831
8016
  }
7832
8017
 
7833
8018
  // src/components/deposits/buttons/BrowserWalletButton.tsx
7834
- import * as React28 from "react";
8019
+ import * as React29 from "react";
7835
8020
  import { Wallet, ChevronRight as ChevronRight13, Loader2 as Loader24 } from "lucide-react";
7836
8021
  import { getAddressBalances } from "@unifold/core";
7837
8022
 
@@ -7886,7 +8071,7 @@ function collectAllEip6963EthProviders() {
7886
8071
  }
7887
8072
 
7888
8073
  // src/components/deposits/browser-wallets/useDetectedBrowserWallet.ts
7889
- import * as React15 from "react";
8074
+ import * as React16 from "react";
7890
8075
 
7891
8076
  // src/components/deposits/browser-wallets/detectConnectedWallet.ts
7892
8077
  function identifyEthWallet(provider, hint) {
@@ -8037,18 +8222,18 @@ async function detectConnectedBrowserWallet(chainType) {
8037
8222
  // src/components/deposits/browser-wallets/useDetectedBrowserWallet.ts
8038
8223
  function useDetectedBrowserWallet(opts = {}) {
8039
8224
  const { chainType, enabled = true, onDisconnect } = opts;
8040
- const [wallet, setWallet] = React15.useState(null);
8041
- const [isLoading, setIsLoading] = React15.useState(enabled);
8042
- const [eip6963ProviderCount, setEip6963ProviderCount] = React15.useState(0);
8043
- const onDisconnectRef = React15.useRef(onDisconnect);
8225
+ const [wallet, setWallet] = React16.useState(null);
8226
+ const [isLoading, setIsLoading] = React16.useState(enabled);
8227
+ const [eip6963ProviderCount, setEip6963ProviderCount] = React16.useState(0);
8228
+ const onDisconnectRef = React16.useRef(onDisconnect);
8044
8229
  onDisconnectRef.current = onDisconnect;
8045
- React15.useEffect(() => {
8230
+ React16.useEffect(() => {
8046
8231
  const store = getEip6963Store();
8047
8232
  if (!store) return;
8048
8233
  setEip6963ProviderCount(store.getProviders().length);
8049
8234
  return store.subscribe((providers) => setEip6963ProviderCount(providers.length));
8050
8235
  }, []);
8051
- React15.useEffect(() => {
8236
+ React16.useEffect(() => {
8052
8237
  if (!enabled) {
8053
8238
  setWallet(null);
8054
8239
  setIsLoading(false);
@@ -8192,10 +8377,10 @@ async function disconnectInjectedBrowserWallet(wallet) {
8192
8377
  }
8193
8378
 
8194
8379
  // src/resources/icons/MetamaskIcon.tsx
8195
- import * as React16 from "react";
8380
+ import * as React17 from "react";
8196
8381
  import { jsx as jsx28, jsxs as jsxs25 } from "react/jsx-runtime";
8197
8382
  function MetamaskIcon({ size = 24, className, variant = "color" }) {
8198
- const id = React16.useId();
8383
+ const id = React17.useId();
8199
8384
  if (variant === "light" || variant === "dark") {
8200
8385
  return /* @__PURE__ */ jsxs25(
8201
8386
  "svg",
@@ -8317,10 +8502,10 @@ function MetamaskIcon({ size = 24, className, variant = "color" }) {
8317
8502
  }
8318
8503
 
8319
8504
  // src/resources/icons/PhantomIcon.tsx
8320
- import * as React17 from "react";
8505
+ import * as React18 from "react";
8321
8506
  import { jsx as jsx29, jsxs as jsxs26 } from "react/jsx-runtime";
8322
8507
  function PhantomIcon({ size = 24, className, variant = "color" }) {
8323
- const id = React17.useId();
8508
+ const id = React18.useId();
8324
8509
  if (variant === "light") {
8325
8510
  return /* @__PURE__ */ jsx29(
8326
8511
  "svg",
@@ -8388,10 +8573,10 @@ function PhantomIcon({ size = 24, className, variant = "color" }) {
8388
8573
  }
8389
8574
 
8390
8575
  // src/resources/icons/CoinbaseIcon.tsx
8391
- import * as React18 from "react";
8576
+ import * as React19 from "react";
8392
8577
  import { jsx as jsx30, jsxs as jsxs27 } from "react/jsx-runtime";
8393
8578
  function CoinbaseIcon({ size = 24, className, variant = "color" }) {
8394
- const id = React18.useId();
8579
+ const id = React19.useId();
8395
8580
  if (variant === "light") {
8396
8581
  return /* @__PURE__ */ jsxs27(
8397
8582
  "svg",
@@ -8472,10 +8657,10 @@ function CoinbaseIcon({ size = 24, className, variant = "color" }) {
8472
8657
  }
8473
8658
 
8474
8659
  // src/resources/icons/RabbyIcon.tsx
8475
- import * as React19 from "react";
8660
+ import * as React20 from "react";
8476
8661
  import { jsx as jsx31, jsxs as jsxs28 } from "react/jsx-runtime";
8477
8662
  function RabbyIcon({ size = 24, className, variant = "color" }) {
8478
- const id = React19.useId();
8663
+ const id = React20.useId();
8479
8664
  if (variant === "light") {
8480
8665
  return /* @__PURE__ */ jsxs28(
8481
8666
  "svg",
@@ -8823,10 +9008,10 @@ function RabbyIcon({ size = 24, className, variant = "color" }) {
8823
9008
  }
8824
9009
 
8825
9010
  // src/resources/icons/RainbowIcon.tsx
8826
- import * as React20 from "react";
9011
+ import * as React21 from "react";
8827
9012
  import { jsx as jsx32, jsxs as jsxs29 } from "react/jsx-runtime";
8828
9013
  function RainbowIcon({ size = 24, className, variant = "color" }) {
8829
- const id = React20.useId();
9014
+ const id = React21.useId();
8830
9015
  if (variant === "light") {
8831
9016
  return /* @__PURE__ */ jsxs29(
8832
9017
  "svg",
@@ -9241,10 +9426,10 @@ function RainbowIcon({ size = 24, className, variant = "color" }) {
9241
9426
  }
9242
9427
 
9243
9428
  // src/resources/icons/TrustIcon.tsx
9244
- import * as React21 from "react";
9429
+ import * as React22 from "react";
9245
9430
  import { jsx as jsx33, jsxs as jsxs30 } from "react/jsx-runtime";
9246
9431
  function TrustIcon({ size = 24, className, variant = "color" }) {
9247
- const id = React21.useId();
9432
+ const id = React22.useId();
9248
9433
  if (variant === "light") {
9249
9434
  return /* @__PURE__ */ jsx33(
9250
9435
  "svg",
@@ -9328,10 +9513,10 @@ function TrustIcon({ size = 24, className, variant = "color" }) {
9328
9513
  }
9329
9514
 
9330
9515
  // src/resources/icons/OkxIcon.tsx
9331
- import * as React22 from "react";
9516
+ import * as React23 from "react";
9332
9517
  import { jsx as jsx34, jsxs as jsxs31 } from "react/jsx-runtime";
9333
9518
  function OkxIcon({ size = 24, className, variant = "color" }) {
9334
- const id = React22.useId();
9519
+ const id = React23.useId();
9335
9520
  if (variant === "light") {
9336
9521
  return /* @__PURE__ */ jsx34(
9337
9522
  "svg",
@@ -9387,10 +9572,10 @@ function OkxIcon({ size = 24, className, variant = "color" }) {
9387
9572
  }
9388
9573
 
9389
9574
  // src/resources/icons/GlowIcon.tsx
9390
- import * as React23 from "react";
9575
+ import * as React24 from "react";
9391
9576
  import { jsx as jsx35, jsxs as jsxs32 } from "react/jsx-runtime";
9392
9577
  function GlowIcon({ size = 24, className, variant = "color" }) {
9393
- const id = React23.useId();
9578
+ const id = React24.useId();
9394
9579
  if (variant === "light") {
9395
9580
  return /* @__PURE__ */ jsx35(
9396
9581
  "svg",
@@ -9492,10 +9677,10 @@ function GlowIcon({ size = 24, className, variant = "color" }) {
9492
9677
  }
9493
9678
 
9494
9679
  // src/resources/icons/BackpackIcon.tsx
9495
- import * as React24 from "react";
9680
+ import * as React25 from "react";
9496
9681
  import { jsx as jsx36, jsxs as jsxs33 } from "react/jsx-runtime";
9497
9682
  function BackpackIcon({ size = 24, className, variant = "color" }) {
9498
- const id = React24.useId();
9683
+ const id = React25.useId();
9499
9684
  if (variant === "light") {
9500
9685
  return /* @__PURE__ */ jsx36(
9501
9686
  "svg",
@@ -9569,10 +9754,10 @@ function BackpackIcon({ size = 24, className, variant = "color" }) {
9569
9754
  }
9570
9755
 
9571
9756
  // src/resources/icons/SolflareIcon.tsx
9572
- import * as React25 from "react";
9757
+ import * as React26 from "react";
9573
9758
  import { jsx as jsx37, jsxs as jsxs34 } from "react/jsx-runtime";
9574
9759
  function SolflareIcon({ size = 24, className, variant = "color" }) {
9575
- const id = React25.useId();
9760
+ const id = React26.useId();
9576
9761
  if (variant === "light") {
9577
9762
  return /* @__PURE__ */ jsx37(
9578
9763
  "svg",
@@ -9640,10 +9825,10 @@ function SolflareIcon({ size = 24, className, variant = "color" }) {
9640
9825
  }
9641
9826
 
9642
9827
  // src/resources/icons/EthereumIcon.tsx
9643
- import * as React26 from "react";
9828
+ import * as React27 from "react";
9644
9829
  import { jsx as jsx38, jsxs as jsxs35 } from "react/jsx-runtime";
9645
9830
  function EthereumIcon({ size = 24, className, variant = "color" }) {
9646
- const id = React26.useId();
9831
+ const id = React27.useId();
9647
9832
  if (variant === "light") {
9648
9833
  return /* @__PURE__ */ jsxs35(
9649
9834
  "svg",
@@ -9768,10 +9953,10 @@ function EthereumIcon({ size = 24, className, variant = "color" }) {
9768
9953
  }
9769
9954
 
9770
9955
  // src/resources/icons/SolanaIcon.tsx
9771
- import * as React27 from "react";
9956
+ import * as React28 from "react";
9772
9957
  import { jsx as jsx39, jsxs as jsxs36 } from "react/jsx-runtime";
9773
9958
  function SolanaIcon({ size = 24, className, variant = "color" }) {
9774
- const id = React27.useId();
9959
+ const id = React28.useId();
9775
9960
  if (variant === "light") {
9776
9961
  return /* @__PURE__ */ jsx39(
9777
9962
  "svg",
@@ -10022,19 +10207,19 @@ function BrowserWalletButton({
10022
10207
  subtitle = i18n.depositModal.browserWallet.subtitle
10023
10208
  }) {
10024
10209
  const { colors: colors2, fonts, components } = useTheme();
10025
- const [isHovered, setIsHovered] = React28.useState(false);
10026
- const [isTouchDevice, setIsTouchDevice] = React28.useState(false);
10210
+ const [isHovered, setIsHovered] = React29.useState(false);
10211
+ const [isTouchDevice, setIsTouchDevice] = React29.useState(false);
10027
10212
  const { wallet, isLoading, setWallet } = useDetectedBrowserWallet({ chainType, onDisconnect });
10028
- const [isConnecting, setIsConnecting] = React28.useState(false);
10029
- const [balanceText, setBalanceText] = React28.useState(null);
10030
- const [isLoadingBalance, setIsLoadingBalance] = React28.useState(false);
10031
- const [isDisconnecting, setIsDisconnecting] = React28.useState(false);
10032
- const onDisconnectRef = React28.useRef(onDisconnect);
10213
+ const [isConnecting, setIsConnecting] = React29.useState(false);
10214
+ const [balanceText, setBalanceText] = React29.useState(null);
10215
+ const [isLoadingBalance, setIsLoadingBalance] = React29.useState(false);
10216
+ const [isDisconnecting, setIsDisconnecting] = React29.useState(false);
10217
+ const onDisconnectRef = React29.useRef(onDisconnect);
10033
10218
  onDisconnectRef.current = onDisconnect;
10034
- React28.useEffect(() => {
10219
+ React29.useEffect(() => {
10035
10220
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
10036
10221
  }, []);
10037
- React28.useEffect(() => {
10222
+ React29.useEffect(() => {
10038
10223
  if (!wallet || !publishableKey) {
10039
10224
  setBalanceText(null);
10040
10225
  return;
@@ -10161,7 +10346,7 @@ function BrowserWalletButton({
10161
10346
  border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
10162
10347
  };
10163
10348
  const sortedWallets = featuredWallets ? [...featuredWallets].sort((a, b) => a.position - b.position) : [];
10164
- const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React28.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
10349
+ const walletIconBlock = wallet ? WALLET_ICON_COMPONENTS[wallet.icon] ? React29.createElement(WALLET_ICON_COMPONENTS[wallet.icon], {
10165
10350
  size: 36,
10166
10351
  className: "uf-rounded-lg",
10167
10352
  variant: "color"
@@ -10306,7 +10491,7 @@ function BrowserWalletButton({
10306
10491
  }
10307
10492
 
10308
10493
  // src/components/deposits/buttons/StripeLinkButton.tsx
10309
- import * as React29 from "react";
10494
+ import * as React30 from "react";
10310
10495
  import { ChevronRight as ChevronRight14 } from "lucide-react";
10311
10496
  import { jsx as jsx42, jsxs as jsxs39 } from "react/jsx-runtime";
10312
10497
  var t4 = i18n.depositModal.stripeLink;
@@ -10317,9 +10502,9 @@ function StripeLinkButton({
10317
10502
  iconUrl
10318
10503
  }) {
10319
10504
  const { colors: colors2, fonts, components } = useTheme();
10320
- const [isHovered, setIsHovered] = React29.useState(false);
10321
- const [isTouchDevice, setIsTouchDevice] = React29.useState(false);
10322
- React29.useEffect(() => {
10505
+ const [isHovered, setIsHovered] = React30.useState(false);
10506
+ const [isTouchDevice, setIsTouchDevice] = React30.useState(false);
10507
+ React30.useEffect(() => {
10323
10508
  setIsTouchDevice("ontouchstart" in window || navigator.maxTouchPoints > 0);
10324
10509
  }, []);
10325
10510
  return /* @__PURE__ */ jsxs39(
@@ -10389,7 +10574,7 @@ function StripeLinkButton({
10389
10574
  }
10390
10575
 
10391
10576
  // src/components/deposits/stripe-link/PayWithStripeLink.tsx
10392
- import { useState as useState29, useEffect as useEffect24, useCallback as useCallback4, useRef as useRef8 } from "react";
10577
+ import { useState as useState29, useEffect as useEffect24, useCallback as useCallback6, useRef as useRef9 } from "react";
10393
10578
  import {
10394
10579
  Loader2 as Loader25,
10395
10580
  CreditCard as CreditCard3,
@@ -10626,17 +10811,17 @@ import {
10626
10811
  } from "@unifold/core";
10627
10812
 
10628
10813
  // src/components/deposits/stripe-link/use-stripe-onramp.ts
10629
- import { useState as useState28, useEffect as useEffect23, useRef as useRef7, useCallback as useCallback3 } from "react";
10814
+ import { useState as useState28, useEffect as useEffect23, useRef as useRef8, useCallback as useCallback5 } from "react";
10630
10815
  function useStripeOnramp(stripePublishableKey, isDark = false) {
10631
10816
  const [coordinator, setCoordinator] = useState28(null);
10632
10817
  const [isLoading, setIsLoading] = useState28(false);
10633
10818
  const [error, setError] = useState28(null);
10634
- const coordinatorRef = useRef7(null);
10635
- const coordinatorThemeRef = useRef7(null);
10636
- const initPromiseRef = useRef7(null);
10637
- const isDarkRef = useRef7(isDark);
10819
+ const coordinatorRef = useRef8(null);
10820
+ const coordinatorThemeRef = useRef8(null);
10821
+ const initPromiseRef = useRef8(null);
10822
+ const isDarkRef = useRef8(isDark);
10638
10823
  isDarkRef.current = isDark;
10639
- const initialize = useCallback3(() => {
10824
+ const initialize = useCallback5(() => {
10640
10825
  if (coordinatorRef.current) return Promise.resolve(coordinatorRef.current);
10641
10826
  if (initPromiseRef.current) return initPromiseRef.current;
10642
10827
  if (!stripePublishableKey) return Promise.resolve(null);
@@ -10849,6 +11034,8 @@ function PayWithStripeLink({
10849
11034
  destinationChainType,
10850
11035
  destinationChainId,
10851
11036
  destinationTokenAddress,
11037
+ countryCode,
11038
+ subdivisionCode,
10852
11039
  wallets: externalWallets,
10853
11040
  email: emailProp,
10854
11041
  iconUrl,
@@ -10860,14 +11047,14 @@ function PayWithStripeLink({
10860
11047
  }) {
10861
11048
  const { colors: colors2, fonts, components, isDark } = useTheme();
10862
11049
  const [step, setStepInternal] = useState29(controlledStep ?? "amount");
10863
- const setStep = useCallback4(
11050
+ const setStep = useCallback6(
10864
11051
  (s) => {
10865
11052
  setStepInternal(s);
10866
11053
  onStepChange?.(s);
10867
11054
  },
10868
11055
  [onStepChange]
10869
11056
  );
10870
- const stepRef = useRef8(step);
11057
+ const stepRef = useRef9(step);
10871
11058
  stepRef.current = step;
10872
11059
  useEffect24(() => {
10873
11060
  if (controlledStep && controlledStep !== step) {
@@ -10958,20 +11145,20 @@ function PayWithStripeLink({
10958
11145
  const [restoring, setRestoring] = useState29(true);
10959
11146
  const [errorReturnStep, setErrorReturnStep] = useState29("email");
10960
11147
  const [authIntentId, setAuthIntentId] = useState29(null);
10961
- const sdkAuthenticatedRef = useRef8(false);
10962
- const everAuthenticatedRef = useRef8(false);
10963
- const reauthReturnStepRef = useRef8(null);
10964
- const attemptedWalletReauthRef = useRef8(false);
10965
- const pendingAddPaymentRef = useRef8(false);
10966
- const autoOpenedAddPaymentRef = useRef8(false);
10967
- const checkoutGenRef = useRef8(0);
11148
+ const sdkAuthenticatedRef = useRef9(false);
11149
+ const everAuthenticatedRef = useRef9(false);
11150
+ const reauthReturnStepRef = useRef9(null);
11151
+ const attemptedWalletReauthRef = useRef9(false);
11152
+ const pendingAddPaymentRef = useRef9(false);
11153
+ const autoOpenedAddPaymentRef = useRef9(false);
11154
+ const checkoutGenRef = useRef9(0);
10968
11155
  const [stripePaymentUIReady, setStripePaymentUIReady] = useState29(false);
10969
11156
  const [oauthToken, setOauthToken] = useState29(null);
10970
11157
  const [refreshTokenValue, setRefreshTokenValue] = useState29(null);
10971
11158
  const [customerId, setCustomerId] = useState29(null);
10972
- const accessTokenRef = useRef8("");
10973
- const refreshTokenRef = useRef8("");
10974
- const persistSession = useCallback4(
11159
+ const accessTokenRef = useRef9("");
11160
+ const refreshTokenRef = useRef9("");
11161
+ const persistSession = useCallback6(
10975
11162
  (cid, token, refresh, expiresIn, loginEmail) => {
10976
11163
  accessTokenRef.current = token;
10977
11164
  refreshTokenRef.current = refresh;
@@ -10985,8 +11172,8 @@ function PayWithStripeLink({
10985
11172
  },
10986
11173
  [userId, email]
10987
11174
  );
10988
- const refreshInFlightRef = useRef8(null);
10989
- const tryRefreshToken = useCallback4(async () => {
11175
+ const refreshInFlightRef = useRef9(null);
11176
+ const tryRefreshToken = useCallback6(async () => {
10990
11177
  if (refreshInFlightRef.current) return refreshInFlightRef.current;
10991
11178
  const rt = refreshTokenRef.current;
10992
11179
  if (!rt) return null;
@@ -11016,7 +11203,7 @@ function PayWithStripeLink({
11016
11203
  refreshInFlightRef.current = doRefresh();
11017
11204
  return refreshInFlightRef.current;
11018
11205
  }, [publishableKey, customerId, persistSession, userId]);
11019
- const withTokenRefresh = useCallback4(
11206
+ const withTokenRefresh = useCallback6(
11020
11207
  async (fn) => {
11021
11208
  const token = accessTokenRef.current;
11022
11209
  if (!token) {
@@ -11178,8 +11365,8 @@ function PayWithStripeLink({
11178
11365
  );
11179
11366
  const [selectedPaymentToken, setSelectedPaymentToken] = useState29(null);
11180
11367
  const [paymentDisplay, setPaymentDisplay] = useState29(null);
11181
- const selectedTokenSingleUseRef = useRef8(false);
11182
- const selectPaymentToken = useCallback4(
11368
+ const selectedTokenSingleUseRef = useRef9(false);
11369
+ const selectPaymentToken = useCallback6(
11183
11370
  (token) => {
11184
11371
  selectedTokenSingleUseRef.current = !!token.singleUse;
11185
11372
  setSelectedPaymentToken(token.id);
@@ -11191,7 +11378,7 @@ function PayWithStripeLink({
11191
11378
  },
11192
11379
  [customerId]
11193
11380
  );
11194
- const clearSelectedPaymentToken = useCallback4(() => {
11381
+ const clearSelectedPaymentToken = useCallback6(() => {
11195
11382
  selectedTokenSingleUseRef.current = false;
11196
11383
  const persisted = customerId ? getStoredSelectedToken(customerId) : null;
11197
11384
  if (persisted && !persisted.singleUse) {
@@ -11243,7 +11430,9 @@ function PayWithStripeLink({
11243
11430
  {
11244
11431
  tokenAddress: destinationTokenAddress,
11245
11432
  chainId: destinationChainId,
11246
- chainType: destinationChainType
11433
+ chainType: destinationChainType,
11434
+ countryCode,
11435
+ subdivisionCode
11247
11436
  },
11248
11437
  publishableKey
11249
11438
  ).then((token) => {
@@ -11262,10 +11451,17 @@ function PayWithStripeLink({
11262
11451
  return () => {
11263
11452
  cancelled = true;
11264
11453
  };
11265
- }, [publishableKey, destinationTokenAddress, destinationChainId, destinationChainType]);
11454
+ }, [
11455
+ publishableKey,
11456
+ destinationTokenAddress,
11457
+ destinationChainId,
11458
+ destinationChainType,
11459
+ countryCode,
11460
+ subdivisionCode
11461
+ ]);
11266
11462
  const destinationCurrency = stripeDestCurrency;
11267
- const authInnerRef = useRef8(null);
11268
- const paymentInnerRef = useRef8(null);
11463
+ const authInnerRef = useRef9(null);
11464
+ const paymentInnerRef = useRef9(null);
11269
11465
  const [authReady, setAuthReady] = useState29(false);
11270
11466
  if (typeof document !== "undefined" && !authInnerRef.current) {
11271
11467
  authInnerRef.current = document.createElement("div");
@@ -11273,12 +11469,12 @@ function PayWithStripeLink({
11273
11469
  if (typeof document !== "undefined" && !paymentInnerRef.current) {
11274
11470
  paymentInnerRef.current = document.createElement("div");
11275
11471
  }
11276
- const authMountRef = useCallback4((node) => {
11472
+ const authMountRef = useCallback6((node) => {
11277
11473
  if (node && !node.contains(authInnerRef.current)) {
11278
11474
  node.appendChild(authInnerRef.current);
11279
11475
  }
11280
11476
  }, []);
11281
- const paymentMountRef = useCallback4((node) => {
11477
+ const paymentMountRef = useCallback6((node) => {
11282
11478
  if (node && !node.contains(paymentInnerRef.current)) {
11283
11479
  node.appendChild(paymentInnerRef.current);
11284
11480
  }
@@ -11329,8 +11525,8 @@ function PayWithStripeLink({
11329
11525
  });
11330
11526
  const [confirmedSessionId, setConfirmedSessionId] = useState29(null);
11331
11527
  const [sessionStatus, setSessionStatus] = useState29(null);
11332
- const handledTerminalSessionRef = useRef8(null);
11333
- const executionReconciledSessionRef = useRef8(null);
11528
+ const handledTerminalSessionRef = useRef9(null);
11529
+ const executionReconciledSessionRef = useRef9(null);
11334
11530
  const hasExecution = executions.length > 0;
11335
11531
  const isSessionFulfilled = sessionStatus === STRIPE_SESSION_STATUS.FULFILLMENT_COMPLETE || hasExecution;
11336
11532
  const isSessionFailed = !hasExecution && (sessionStatus === STRIPE_SESSION_STATUS.REJECTED || sessionStatus === STRIPE_SESSION_STATUS.EXPIRED);
@@ -11448,7 +11644,7 @@ function PayWithStripeLink({
11448
11644
  sdkAuthenticatedRef.current = false;
11449
11645
  attemptedWalletReauthRef.current = false;
11450
11646
  }, [coordinator]);
11451
- const handleAuthInterrupted = useCallback4(
11647
+ const handleAuthInterrupted = useCallback6(
11452
11648
  (message) => {
11453
11649
  const alreadySignedIn = !!accessTokenRef.current;
11454
11650
  if (alreadySignedIn || emailProp) {
@@ -11461,7 +11657,7 @@ function PayWithStripeLink({
11461
11657
  },
11462
11658
  [emailProp, setStep]
11463
11659
  );
11464
- const reauthenticateSdk = useCallback4(async () => {
11660
+ const reauthenticateSdk = useCallback6(async () => {
11465
11661
  const current = stepRef.current;
11466
11662
  const preAuthSteps = ["email", "register", "auth"];
11467
11663
  reauthReturnStepRef.current = preAuthSteps.includes(current) ? null : current;
@@ -12160,14 +12356,14 @@ function PayWithStripeLink({
12160
12356
  };
12161
12357
  const [quote, setQuote] = useState29(null);
12162
12358
  const [quoteLoading, setQuoteLoading] = useState29(false);
12163
- const quoteTimerRef = useRef8(null);
12359
+ const quoteTimerRef = useRef9(null);
12164
12360
  const [sessionForCheckout, setSessionForCheckoutState] = useState29(null);
12165
- const sessionForCheckoutRef = useRef8(sessionForCheckout);
12361
+ const sessionForCheckoutRef = useRef9(sessionForCheckout);
12166
12362
  const setSessionForCheckout = (s) => {
12167
12363
  sessionForCheckoutRef.current = s;
12168
12364
  setSessionForCheckoutState(s);
12169
12365
  };
12170
- const loadAndSelectPreferredToken = useCallback4(async () => {
12366
+ const loadAndSelectPreferredToken = useCallback6(async () => {
12171
12367
  if (!customerId) return;
12172
12368
  try {
12173
12369
  const existing = await withTokenRefresh(
@@ -12197,7 +12393,7 @@ function PayWithStripeLink({
12197
12393
  };
12198
12394
  const [quoteError, setQuoteError] = useState29(null);
12199
12395
  const [quoteNonce, setQuoteNonce] = useState29(0);
12200
- const quoteNonceAtReviewRef = useRef8(quoteNonce);
12396
+ const quoteNonceAtReviewRef = useRef9(quoteNonce);
12201
12397
  const [purchaseLimit, setPurchaseLimit] = useState29(null);
12202
12398
  const [limitReachedAmount, setLimitReachedAmount] = useState29(null);
12203
12399
  const [requiredStepUp, setRequiredStepUp] = useState29(null);
@@ -12975,10 +13171,16 @@ function PayWithStripeLink({
12975
13171
  return /* @__PURE__ */ jsxs41(
12976
13172
  "div",
12977
13173
  {
12978
- className: "uf-flex uf-flex-col uf-py-4 uf-overflow-y-auto uf-max-h-[70vh]",
13174
+ className: "uf-flex uf-flex-col uf-py-4 uf-overflow-y-auto uf-overflow-x-hidden uf-max-h-[70vh]",
12979
13175
  style: { backgroundColor: colors2.background },
12980
13176
  children: [
12981
- /* @__PURE__ */ jsx44("div", { ref: paymentMountRef, className: "uf-w-full uf-flex-1 uf-overflow-y-auto" }),
13177
+ /* @__PURE__ */ jsx44(
13178
+ "div",
13179
+ {
13180
+ ref: paymentMountRef,
13181
+ className: "uf-w-full uf-flex-1 uf-overflow-y-auto uf-overflow-x-hidden"
13182
+ }
13183
+ ),
12982
13184
  !stripePaymentUIReady && /* @__PURE__ */ jsx44("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ jsx44(Loader25, { className: "uf-w-8 uf-h-8 uf-animate-spin", style: { color: colors2.primary } }) }),
12983
13185
  error && /* @__PURE__ */ jsx44(
12984
13186
  "div",
@@ -12996,7 +13198,7 @@ function PayWithStripeLink({
12996
13198
  return /* @__PURE__ */ jsxs41(
12997
13199
  "div",
12998
13200
  {
12999
- className: "uf-flex uf-flex-col uf-py-4 uf-overflow-y-auto uf-max-h-[70vh]",
13201
+ className: "uf-flex uf-flex-col uf-py-4 uf-overflow-y-auto uf-overflow-x-hidden uf-max-h-[70vh]",
13000
13202
  style: { backgroundColor: colors2.background },
13001
13203
  children: [
13002
13204
  displayPaymentTokens.length === 0 && !loading && /* @__PURE__ */ jsx44("div", { className: "uf-px-1 uf-mb-3 uf-text-center", children: /* @__PURE__ */ jsx44(
@@ -14106,7 +14308,7 @@ function PayWithStripeLink({
14106
14308
  }
14107
14309
 
14108
14310
  // src/components/deposits/CoinbaseConnect.tsx
14109
- import { useState as useState30, useEffect as useEffect25, useCallback as useCallback5, useMemo as useMemo7, useRef as useRef9 } from "react";
14311
+ import { useState as useState30, useEffect as useEffect25, useCallback as useCallback7, useMemo as useMemo8, useRef as useRef10 } from "react";
14110
14312
  import {
14111
14313
  ChevronRight as ChevronRight15,
14112
14314
  ChevronDown as ChevronDown4,
@@ -14129,25 +14331,38 @@ import {
14129
14331
  } from "@unifold/core";
14130
14332
 
14131
14333
  // src/hooks/use-project-config.ts
14132
- import { useQuery as useQuery8 } from "@tanstack/react-query";
14334
+ import { useQuery as useQuery9, keepPreviousData } from "@tanstack/react-query";
14133
14335
  import { getProjectConfig } from "@unifold/core";
14134
14336
  function useProjectConfig({
14135
14337
  publishableKey,
14136
- enabled = true
14338
+ enabled = true,
14339
+ countryCode,
14340
+ subdivisionCode
14137
14341
  }) {
14138
- const { data: projectConfig, isLoading } = useQuery8({
14139
- queryKey: ["unifold", "projectConfig", publishableKey],
14140
- queryFn: () => getProjectConfig(publishableKey),
14342
+ const {
14343
+ data: projectConfig,
14344
+ isLoading,
14345
+ error
14346
+ } = useQuery9({
14347
+ // Country is part of the key so a region change refetches the region-aware
14348
+ // config. Omitted when undefined so callers that don't pass a country keep
14349
+ // sharing the base cache entry.
14350
+ queryKey: countryCode ? ["unifold", "projectConfig", publishableKey, countryCode, subdivisionCode ?? null] : ["unifold", "projectConfig", publishableKey],
14351
+ queryFn: () => getProjectConfig(publishableKey, countryCode ? { countryCode, subdivisionCode } : void 0),
14141
14352
  enabled,
14353
+ // Keep the previous (e.g. no-country) config visible while the region-aware
14354
+ // config refetches after the country resolves, so unrelated config-driven
14355
+ // UI doesn't flash back to defaults.
14356
+ placeholderData: keepPreviousData,
14142
14357
  staleTime: 1e3 * 60 * 30,
14143
14358
  refetchOnMount: true,
14144
14359
  refetchOnWindowFocus: true
14145
14360
  });
14146
- return { projectConfig, isLoading };
14361
+ return { projectConfig, isLoading, error: error ?? null };
14147
14362
  }
14148
14363
 
14149
14364
  // src/hooks/use-supported-deposit-tokens.ts
14150
- import { useQuery as useQuery9 } from "@tanstack/react-query";
14365
+ import { useQuery as useQuery10 } from "@tanstack/react-query";
14151
14366
  import {
14152
14367
  getSupportedDepositTokens
14153
14368
  } from "@unifold/core";
@@ -14162,7 +14377,7 @@ function useSupportedDepositTokens(publishableKey, options) {
14162
14377
  ...options?.product_type ? { product_type: options.product_type } : {}
14163
14378
  };
14164
14379
  const hasFilteredOptions = Object.keys(filteredOptions).length > 0;
14165
- return useQuery9({
14380
+ return useQuery10({
14166
14381
  queryKey: [
14167
14382
  "unifold",
14168
14383
  "supportedDepositTokens",
@@ -14183,7 +14398,7 @@ function useSupportedDepositTokens(publishableKey, options) {
14183
14398
  }
14184
14399
 
14185
14400
  // src/hooks/use-integration-transfer-default-token.ts
14186
- import { useQuery as useQuery10 } from "@tanstack/react-query";
14401
+ import { useQuery as useQuery11 } from "@tanstack/react-query";
14187
14402
  import {
14188
14403
  getIntegrationTransferDefaultToken
14189
14404
  } from "@unifold/core";
@@ -14192,7 +14407,7 @@ function useIntegrationTransferDefaultToken({
14192
14407
  publishableKey,
14193
14408
  enabled = true
14194
14409
  }) {
14195
- return useQuery10({
14410
+ return useQuery11({
14196
14411
  queryKey: [
14197
14412
  "unifold",
14198
14413
  "integrationTransferDefaultToken",
@@ -14263,7 +14478,8 @@ function CoinbaseConnect({
14263
14478
  defaultSourceChainType,
14264
14479
  defaultSourceChainId,
14265
14480
  defaultSourceTokenAddress,
14266
- defaultSourceSymbol
14481
+ defaultSourceSymbol,
14482
+ prefilledAmountUsd
14267
14483
  }) {
14268
14484
  const { colors: colors2, fonts, components } = useTheme();
14269
14485
  const { projectConfig } = useProjectConfig({ publishableKey });
@@ -14273,12 +14489,12 @@ function CoinbaseConnect({
14273
14489
  destination_chain_id: destinationChainId,
14274
14490
  destination_chain_type: destinationChainType
14275
14491
  });
14276
- const supportedSymbols = useMemo7(() => {
14492
+ const supportedSymbols = useMemo8(() => {
14277
14493
  const set = /* @__PURE__ */ new Set();
14278
14494
  supportedTokensData?.data.forEach((token) => set.add(token.symbol.toLowerCase()));
14279
14495
  return set;
14280
14496
  }, [supportedTokensData]);
14281
- const stablecoinSymbols = useMemo7(() => {
14497
+ const stablecoinSymbols = useMemo8(() => {
14282
14498
  const set = /* @__PURE__ */ new Set();
14283
14499
  supportedTokensData?.data.forEach((token) => {
14284
14500
  if (token.is_stablecoin) set.add(token.symbol.toLowerCase());
@@ -14311,12 +14527,12 @@ function CoinbaseConnect({
14311
14527
  const [transferDepositWalletId, setTransferDepositWalletId] = useState30(
14312
14528
  void 0
14313
14529
  );
14314
- const exchangeSupportedCurrencies = useMemo7(() => {
14530
+ const exchangeSupportedCurrencies = useMemo8(() => {
14315
14531
  const set = /* @__PURE__ */ new Set();
14316
14532
  selectedExchange?.supported_currencies.forEach((c) => set.add(c.toLowerCase()));
14317
14533
  return set;
14318
14534
  }, [selectedExchange]);
14319
- const defaultTokenParams = useMemo7(
14535
+ const defaultTokenParams = useMemo8(
14320
14536
  () => selectedAsset ? {
14321
14537
  integration_provider: IntegrationProvider.COINBASE,
14322
14538
  source_currency: selectedAsset.currency.toLowerCase(),
@@ -14339,7 +14555,7 @@ function CoinbaseConnect({
14339
14555
  params: defaultTokenParams,
14340
14556
  publishableKey
14341
14557
  });
14342
- const defaultSourceCurrency = useMemo7(
14558
+ const defaultSourceCurrency = useMemo8(
14343
14559
  () => resolveDefaultSourceSymbol(supportedTokensData?.data, {
14344
14560
  defaultSourceChainType,
14345
14561
  defaultSourceChainId,
@@ -14354,7 +14570,7 @@ function CoinbaseConnect({
14354
14570
  defaultSourceSymbol
14355
14571
  ]
14356
14572
  );
14357
- const sortedHoldings = useMemo7(() => {
14573
+ const sortedHoldings = useMemo8(() => {
14358
14574
  const supported = [];
14359
14575
  const unsupported = [];
14360
14576
  holdings.forEach((account) => {
@@ -14374,7 +14590,7 @@ function CoinbaseConnect({
14374
14590
  }
14375
14591
  return [...supported, ...unsupported];
14376
14592
  }, [holdings, supportedSymbols, exchangeSupportedCurrencies, defaultSourceCurrency]);
14377
- const selectedHoldingIsSupported = useMemo7(() => {
14593
+ const selectedHoldingIsSupported = useMemo8(() => {
14378
14594
  if (!selectedHolding) return false;
14379
14595
  const currencyLower = selectedHolding.currency.toLowerCase();
14380
14596
  return (supportedSymbols.size === 0 || supportedSymbols.has(currencyLower)) && (exchangeSupportedCurrencies.size === 0 || exchangeSupportedCurrencies.has(currencyLower));
@@ -14418,10 +14634,10 @@ function CoinbaseConnect({
14418
14634
  useEffect25(() => {
14419
14635
  onExecutionsChange?.(depositExecutions);
14420
14636
  }, [depositExecutions, onExecutionsChange]);
14421
- const pollRef = useRef9(null);
14422
- const popupRef = useRef9(null);
14423
- const viewRef = useRef9(initialView);
14424
- const transitionTo = useCallback5((nextView) => {
14637
+ const pollRef = useRef10(null);
14638
+ const popupRef = useRef10(null);
14639
+ const viewRef = useRef10(initialView);
14640
+ const transitionTo = useCallback7((nextView) => {
14425
14641
  if (nextView === viewRef.current) return;
14426
14642
  setIsTransitioning(true);
14427
14643
  setTimeout(() => {
@@ -14431,7 +14647,7 @@ function CoinbaseConnect({
14431
14647
  setIsTransitioning(false);
14432
14648
  }, 150);
14433
14649
  }, []);
14434
- const tryRefreshToken = useCallback5(
14650
+ const tryRefreshToken = useCallback7(
14435
14651
  async (currentToken) => {
14436
14652
  try {
14437
14653
  const result = await refreshIntegrationToken(currentToken, publishableKey);
@@ -14469,7 +14685,7 @@ function CoinbaseConnect({
14469
14685
  }
14470
14686
  }
14471
14687
  }, []);
14472
- const loadHoldings = useCallback5(
14688
+ const loadHoldings = useCallback7(
14473
14689
  async (token) => {
14474
14690
  setIsLoading(true);
14475
14691
  try {
@@ -14521,7 +14737,7 @@ function CoinbaseConnect({
14521
14737
  if (pollRef.current) clearInterval(pollRef.current);
14522
14738
  };
14523
14739
  }, []);
14524
- const minDepositUsd = useMemo7(() => {
14740
+ const minDepositUsd = useMemo8(() => {
14525
14741
  if (!selectedAsset || !defaultTokenData) return 0;
14526
14742
  const supportedToken = supportedTokensData?.data.find(
14527
14743
  (t14) => t14.symbol.toLowerCase() === selectedAsset.currency.toLowerCase()
@@ -14532,7 +14748,7 @@ function CoinbaseConnect({
14532
14748
  );
14533
14749
  return matchingChain?.minimum_deposit_amount_usd ?? Math.min(...supportedToken.chains.map((c) => c.minimum_deposit_amount_usd));
14534
14750
  }, [selectedAsset, supportedTokensData, defaultTokenData]);
14535
- const estimatedProcessingTime = useMemo7(() => {
14751
+ const estimatedProcessingTime = useMemo8(() => {
14536
14752
  if (!selectedAsset || !defaultTokenData) return null;
14537
14753
  const supportedToken = supportedTokensData?.data.find(
14538
14754
  (t14) => t14.symbol.toLowerCase() === selectedAsset.currency.toLowerCase()
@@ -14586,7 +14802,8 @@ function CoinbaseConnect({
14586
14802
  };
14587
14803
  const handleSelectAsset = (asset) => {
14588
14804
  setSelectedAsset(asset);
14589
- setSendAmount("");
14805
+ const cleanedPrefilled = prefilledAmountUsd?.replace(/[^0-9.]/g, "") ?? "";
14806
+ setSendAmount(cleanedPrefilled);
14590
14807
  transitionTo("enter_amount");
14591
14808
  };
14592
14809
  const handleCreateTransfer = async () => {
@@ -16172,13 +16389,13 @@ function CoinbaseConnect({
16172
16389
  CoinbaseConnect.displayName = "CoinbaseConnect";
16173
16390
 
16174
16391
  // src/hooks/use-exchanges.ts
16175
- import { useQuery as useQuery11 } from "@tanstack/react-query";
16392
+ import { useQuery as useQuery12 } from "@tanstack/react-query";
16176
16393
  import { getExchanges } from "@unifold/core";
16177
16394
  function useExchanges({
16178
16395
  publishableKey,
16179
16396
  enabled = true
16180
16397
  }) {
16181
- const { data: exchanges = [], isLoading } = useQuery11({
16398
+ const { data: exchanges = [], isLoading } = useQuery12({
16182
16399
  queryKey: ["unifold", "exchanges", publishableKey],
16183
16400
  queryFn: () => getExchanges(void 0, publishableKey).then((res) => res.data),
16184
16401
  enabled,
@@ -16190,13 +16407,13 @@ function useExchanges({
16190
16407
  }
16191
16408
 
16192
16409
  // src/hooks/use-apple-pay-providers.ts
16193
- import { useQuery as useQuery12 } from "@tanstack/react-query";
16410
+ import { useQuery as useQuery13 } from "@tanstack/react-query";
16194
16411
  import { getApplePayProviders } from "@unifold/core";
16195
16412
  function useApplePayProviders({
16196
16413
  publishableKey,
16197
16414
  enabled = true
16198
16415
  }) {
16199
- const { data: providers, isLoading } = useQuery12({
16416
+ const { data: providers, isLoading } = useQuery13({
16200
16417
  queryKey: ["unifold", "applePayProviders", publishableKey],
16201
16418
  queryFn: () => getApplePayProviders(publishableKey),
16202
16419
  enabled,
@@ -16219,50 +16436,29 @@ import {
16219
16436
  } from "@unifold/core";
16220
16437
 
16221
16438
  // src/hooks/use-allowed-country.ts
16222
- import { useQuery as useQuery13 } from "@tanstack/react-query";
16223
- import {
16224
- getIpAddress as getIpAddress2,
16225
- getProjectConfig as getProjectConfig2
16226
- } from "@unifold/core";
16227
16439
  function useAllowedCountry(publishableKey) {
16440
+ const { userIpInfo, isLoading: isIpLoading, error: ipError } = useUserIp();
16228
16441
  const {
16229
- data: ipData,
16230
- isLoading: isIpLoading,
16231
- error: ipError
16232
- } = useQuery13({
16233
- queryKey: ["unifold", "ipAddress"],
16234
- queryFn: () => getIpAddress2(),
16235
- refetchOnMount: false,
16236
- refetchOnReconnect: true,
16237
- refetchOnWindowFocus: false,
16238
- staleTime: 1e3 * 60 * 60,
16239
- // 1 hour
16240
- gcTime: 1e3 * 60 * 60 * 24
16241
- // 24 hours
16242
- });
16243
- const {
16244
- data: configData,
16442
+ projectConfig,
16245
16443
  isLoading: isConfigLoading,
16246
16444
  error: configError
16247
- } = useQuery13({
16248
- queryKey: ["unifold", "projectConfig", publishableKey],
16249
- queryFn: () => getProjectConfig2(publishableKey),
16250
- refetchOnMount: false,
16251
- refetchOnReconnect: true,
16252
- refetchOnWindowFocus: false,
16253
- staleTime: 1e3 * 60 * 5,
16254
- // 5 minutes
16255
- gcTime: 1e3 * 60 * 60
16256
- // 1 hour
16445
+ } = useProjectConfig({
16446
+ publishableKey,
16447
+ // Wait for the IP so we issue a single country-aware config request rather
16448
+ // than a country-less fetch followed by a country-aware refetch. Shares the
16449
+ // query key with DepositModal's useProjectConfig, so they dedupe.
16450
+ enabled: !isIpLoading,
16451
+ countryCode: userIpInfo?.alpha2,
16452
+ subdivisionCode: userIpInfo?.subdivisionCode ?? void 0
16257
16453
  });
16258
16454
  const isLoading = isIpLoading || isConfigLoading;
16259
16455
  const error = ipError || configError || null;
16456
+ const userSubdivision = userIpInfo?.subdivisionCode || userIpInfo?.state || "";
16260
16457
  let isAllowed = null;
16261
- if (ipData && configData) {
16262
- const blockedCodes = configData.blocked_country_codes || [];
16263
- const blockedSubdivisions = configData.blocked_country_subdivisions || [];
16264
- const userCountryUpper = ipData.alpha2.toUpperCase();
16265
- const userSubdivision = ipData.subdivision_code || ipData.state || "";
16458
+ if (userIpInfo && projectConfig) {
16459
+ const blockedCodes = projectConfig.blocked_country_codes || [];
16460
+ const blockedSubdivisions = projectConfig.blocked_country_subdivisions || [];
16461
+ const userCountryUpper = userIpInfo.alpha2.toUpperCase();
16266
16462
  const userSubdivisionUpper = userSubdivision.toUpperCase();
16267
16463
  const isCountryBlocked = blockedCodes.some((code) => code.toUpperCase() === userCountryUpper);
16268
16464
  const isSubdivisionBlocked = blockedSubdivisions.some((entry) => {
@@ -16271,12 +16467,11 @@ function useAllowedCountry(publishableKey) {
16271
16467
  });
16272
16468
  isAllowed = !isCountryBlocked && !isSubdivisionBlocked;
16273
16469
  }
16274
- const subdivisionCode = ipData?.subdivision_code || ipData?.state || "" || null;
16275
16470
  return {
16276
16471
  isAllowed,
16277
- alpha2: ipData?.alpha2 ?? null,
16278
- country: ipData?.country ?? null,
16279
- subdivisionCode,
16472
+ alpha2: userIpInfo?.alpha2 ?? null,
16473
+ country: userIpInfo?.country ?? null,
16474
+ subdivisionCode: userSubdivision || null,
16280
16475
  isLoading,
16281
16476
  error
16282
16477
  };
@@ -16343,7 +16538,7 @@ function useAddressValidation({
16343
16538
  }
16344
16539
 
16345
16540
  // src/components/deposits/TransferCryptoSingleInput.tsx
16346
- import { useState as useState36, useEffect as useEffect30, useMemo as useMemo10 } from "react";
16541
+ import { useState as useState36, useEffect as useEffect30, useMemo as useMemo11 } from "react";
16347
16542
  import {
16348
16543
  ChevronDown as ChevronDown5,
16349
16544
  ChevronUp as ChevronUp3,
@@ -16361,14 +16556,14 @@ import {
16361
16556
  import { useEffect as useEffect27, useState as useState31 } from "react";
16362
16557
 
16363
16558
  // src/components/shared/ThemeStyleInjector.tsx
16364
- import * as React31 from "react";
16559
+ import * as React32 from "react";
16365
16560
  import { jsx as jsx46 } from "react/jsx-runtime";
16366
16561
  function ThemeStyleInjector({
16367
16562
  children,
16368
16563
  className
16369
16564
  }) {
16370
16565
  const { colors: colors2, fonts, mode } = useTheme();
16371
- const cssVars = React31.useMemo(() => {
16566
+ const cssVars = React32.useMemo(() => {
16372
16567
  const hexToHSL = (hex) => {
16373
16568
  hex = hex.replace("#", "");
16374
16569
  const r = parseInt(hex.slice(0, 2), 16) / 255;
@@ -16428,7 +16623,7 @@ function ThemeStyleInjector({
16428
16623
  ...fonts.regular ? { "--uf-font-family": fonts.regular } : {}
16429
16624
  };
16430
16625
  }, [colors2, fonts.regular]);
16431
- React31.useEffect(() => {
16626
+ React32.useEffect(() => {
16432
16627
  if (typeof document === "undefined") return;
16433
16628
  if (fonts.regular) {
16434
16629
  document.documentElement.style.setProperty("--uf-font-family", fonts.regular);
@@ -16702,7 +16897,7 @@ function DepositsModal({
16702
16897
  }
16703
16898
 
16704
16899
  // src/components/deposits/TokenSelectorSheet.tsx
16705
- import { useState as useState32, useMemo as useMemo9, useEffect as useEffect28 } from "react";
16900
+ import { useState as useState32, useMemo as useMemo10, useEffect as useEffect28 } from "react";
16706
16901
  import { ArrowLeft as ArrowLeft2, X as X4 } from "lucide-react";
16707
16902
  import Fuse from "fuse.js";
16708
16903
  import { jsx as jsx49, jsxs as jsxs45 } from "react/jsx-runtime";
@@ -16769,7 +16964,7 @@ function TokenSelectorSheet({
16769
16964
  useEffect28(() => {
16770
16965
  setRecentTokens(getRecentTokens());
16771
16966
  }, []);
16772
- const allOptions = useMemo9(() => {
16967
+ const allOptions = useMemo10(() => {
16773
16968
  const options = [];
16774
16969
  tokens.forEach((token) => {
16775
16970
  token.chains.forEach((chain) => {
@@ -16778,7 +16973,7 @@ function TokenSelectorSheet({
16778
16973
  });
16779
16974
  return options;
16780
16975
  }, [tokens]);
16781
- const quickSelectOptions = useMemo9(() => {
16976
+ const quickSelectOptions = useMemo10(() => {
16782
16977
  const result = [];
16783
16978
  const seen = /* @__PURE__ */ new Set();
16784
16979
  const addOption = (symbol, chainType, chainId, isRecent) => {
@@ -16810,7 +17005,7 @@ function TokenSelectorSheet({
16810
17005
  });
16811
17006
  setRecentTokens(updated);
16812
17007
  };
16813
- const fuse = useMemo9(
17008
+ const fuse = useMemo10(
16814
17009
  () => new Fuse(allOptions, {
16815
17010
  keys: [
16816
17011
  { name: "token.symbol", weight: 2 },
@@ -16823,7 +17018,7 @@ function TokenSelectorSheet({
16823
17018
  }),
16824
17019
  [allOptions]
16825
17020
  );
16826
- const filteredOptions = useMemo9(() => {
17021
+ const filteredOptions = useMemo10(() => {
16827
17022
  if (!searchQuery.trim()) return allOptions;
16828
17023
  const query = searchQuery.trim();
16829
17024
  const results = fuse.search(query);
@@ -17195,7 +17390,7 @@ function TokenSelectorSheet({
17195
17390
  }
17196
17391
 
17197
17392
  // src/hooks/use-default-token.ts
17198
- import { useState as useState33, useEffect as useEffect29, useRef as useRef10 } from "react";
17393
+ import { useState as useState33, useEffect as useEffect29, useRef as useRef11 } from "react";
17199
17394
  var getChainKey = (chainId, chainType) => {
17200
17395
  return `${chainType}:${chainId}`;
17201
17396
  };
@@ -17253,7 +17448,7 @@ function useDefaultToken({
17253
17448
  const [token, setToken] = useState33(null);
17254
17449
  const [chain, setChain] = useState33(null);
17255
17450
  const [initialSelectionDone, setInitialSelectionDone] = useState33(false);
17256
- const appliedDefaultsRef = useRef10("");
17451
+ const appliedDefaultsRef = useRef11("");
17257
17452
  useEffect29(() => {
17258
17453
  if (!tokens.length) return;
17259
17454
  const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
@@ -17602,7 +17797,7 @@ function useCopyAddress() {
17602
17797
  }
17603
17798
 
17604
17799
  // src/components/shared/tooltip.tsx
17605
- import * as React32 from "react";
17800
+ import * as React33 from "react";
17606
17801
  import * as TooltipPrimitive from "@radix-ui/react-tooltip";
17607
17802
  import { jsx as jsx52 } from "react/jsx-runtime";
17608
17803
  var TooltipProvider = TooltipPrimitive.Provider;
@@ -17610,20 +17805,20 @@ function Tooltip({
17610
17805
  children,
17611
17806
  ...props
17612
17807
  }) {
17613
- const [open, setOpen] = React32.useState(props.defaultOpen ?? false);
17808
+ const [open, setOpen] = React33.useState(props.defaultOpen ?? false);
17614
17809
  const isControlled = props.open !== void 0;
17615
17810
  const isOpen = isControlled ? props.open : open;
17616
17811
  const onOpenChange = isControlled ? props.onOpenChange : (nextOpen) => setOpen(nextOpen);
17617
17812
  return /* @__PURE__ */ jsx52(TooltipContext.Provider, { value: { open: isOpen, onOpenChange }, children: /* @__PURE__ */ jsx52(TooltipPrimitive.Root, { ...props, open: isOpen, onOpenChange, children }) });
17618
17813
  }
17619
- var TooltipContext = React32.createContext({
17814
+ var TooltipContext = React33.createContext({
17620
17815
  open: false,
17621
17816
  onOpenChange: () => {
17622
17817
  }
17623
17818
  });
17624
- var TooltipTrigger = React32.forwardRef(({ onClick, ...props }, ref) => {
17625
- const { open, onOpenChange } = React32.useContext(TooltipContext);
17626
- const handleClick = React32.useCallback(
17819
+ var TooltipTrigger = React33.forwardRef(({ onClick, ...props }, ref) => {
17820
+ const { open, onOpenChange } = React33.useContext(TooltipContext);
17821
+ const handleClick = React33.useCallback(
17627
17822
  (e) => {
17628
17823
  onOpenChange(!open);
17629
17824
  onClick?.(e);
@@ -17633,7 +17828,7 @@ var TooltipTrigger = React32.forwardRef(({ onClick, ...props }, ref) => {
17633
17828
  return /* @__PURE__ */ jsx52(TooltipPrimitive.Trigger, { ref, onClick: handleClick, ...props });
17634
17829
  });
17635
17830
  TooltipTrigger.displayName = TooltipPrimitive.Trigger.displayName;
17636
- var TooltipContent = React32.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
17831
+ var TooltipContent = React33.forwardRef(({ className, sideOffset = 4, ...props }, ref) => {
17637
17832
  const { themeClass, colors: colors2 } = useTheme();
17638
17833
  return /* @__PURE__ */ jsx52(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsx52(
17639
17834
  TooltipPrimitive.Content,
@@ -17764,6 +17959,7 @@ function TransferCryptoSingleInput({
17764
17959
  onDepositError,
17765
17960
  wallets: externalWallets,
17766
17961
  onSourceTokenChange,
17962
+ prefilledAmountUsd,
17767
17963
  checkoutQuote,
17768
17964
  isCheckoutQuoteLoading = false,
17769
17965
  persistCheckingIndicator = false,
@@ -17811,7 +18007,7 @@ function TransferCryptoSingleInput({
17811
18007
  const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
17812
18008
  const loading = externalWallets?.length ? false : walletsLoading;
17813
18009
  const error = walletsError?.message ?? null;
17814
- const allAvailableChains = useMemo10(() => {
18010
+ const allAvailableChains = useMemo11(() => {
17815
18011
  const chainsMap = /* @__PURE__ */ new Map();
17816
18012
  supportedTokens.forEach((t13) => {
17817
18013
  t13.chains.forEach((c) => {
@@ -17907,6 +18103,22 @@ function TransferCryptoSingleInput({
17907
18103
  const maxSlippage = currentChainFromBackend?.max_slippage_percent ?? 0.25;
17908
18104
  const processingTime = currentChainFromBackend?.estimated_processing_time ?? null;
17909
18105
  const minDepositUsd = currentChainFromBackend?.minimum_deposit_amount_usd ?? 3;
18106
+ const parsedPrefilledUsd = useMemo11(() => {
18107
+ const value = parseFloat(prefilledAmountUsd ?? "");
18108
+ return Number.isFinite(value) && value > 0 ? value : null;
18109
+ }, [prefilledAmountUsd]);
18110
+ const effectivePrefilledUsd = useMemo11(() => {
18111
+ if (parsedPrefilledUsd === null) return null;
18112
+ return Math.max(parsedPrefilledUsd, minDepositUsd);
18113
+ }, [parsedPrefilledUsd, minDepositUsd]);
18114
+ const prefillDisplay = useMemo11(() => {
18115
+ if (effectivePrefilledUsd === null) return null;
18116
+ const usdLabel = `$${effectivePrefilledUsd.toFixed(2)}`;
18117
+ if (selectedToken?.is_stablecoin) {
18118
+ return `${effectivePrefilledUsd.toFixed(2)} ${selectedToken.symbol} (${usdLabel})`;
18119
+ }
18120
+ return `${usdLabel} USD`;
18121
+ }, [effectivePrefilledUsd, selectedToken]);
17910
18122
  return /* @__PURE__ */ jsx54(TooltipProvider, { delayDuration: 0, skipDelayDuration: 0, children: /* @__PURE__ */ jsxs49(
17911
18123
  "div",
17912
18124
  {
@@ -18033,7 +18245,7 @@ function TransferCryptoSingleInput({
18033
18245
  /* @__PURE__ */ jsx54("span", { children: "Retrying automatically every 5 seconds..." })
18034
18246
  ] })
18035
18247
  ] }),
18036
- (checkoutQuote || isCheckoutQuoteLoading) && /* @__PURE__ */ jsxs49(
18248
+ (checkoutQuote || isCheckoutQuoteLoading || prefillDisplay) && /* @__PURE__ */ jsxs49(
18037
18249
  "div",
18038
18250
  {
18039
18251
  className: "uf-rounded-xl uf-px-3 uf-py-2 uf-flex uf-items-center uf-justify-between",
@@ -18077,6 +18289,13 @@ function TransferCryptoSingleInput({
18077
18289
  )
18078
18290
  ]
18079
18291
  }
18292
+ ) : prefillDisplay ? /* @__PURE__ */ jsx54(
18293
+ "span",
18294
+ {
18295
+ className: "uf-text-sm uf-font-semibold",
18296
+ style: { color: components.card.titleColor, fontFamily: fonts.semibold },
18297
+ children: prefillDisplay
18298
+ }
18080
18299
  ) : /* @__PURE__ */ jsx54(
18081
18300
  "div",
18082
18301
  {
@@ -18406,7 +18625,7 @@ function TransferCryptoSingleInput({
18406
18625
  }
18407
18626
 
18408
18627
  // src/components/deposits/TransferCryptoDoubleInput.tsx
18409
- import { useState as useState37, useEffect as useEffect31, useMemo as useMemo11 } from "react";
18628
+ import { useState as useState37, useEffect as useEffect31, useMemo as useMemo12 } from "react";
18410
18629
  import {
18411
18630
  ChevronDown as ChevronDown7,
18412
18631
  ChevronUp as ChevronUp5,
@@ -18421,14 +18640,14 @@ import {
18421
18640
  } from "lucide-react";
18422
18641
 
18423
18642
  // src/components/shared/select.tsx
18424
- import * as React33 from "react";
18643
+ import * as React34 from "react";
18425
18644
  import * as SelectPrimitive from "@radix-ui/react-select";
18426
18645
  import { Check as Check5, ChevronDown as ChevronDown6, ChevronUp as ChevronUp4 } from "lucide-react";
18427
18646
  import { jsx as jsx55, jsxs as jsxs50 } from "react/jsx-runtime";
18428
18647
  var Select = SelectPrimitive.Root;
18429
18648
  var SelectGroup = SelectPrimitive.Group;
18430
18649
  var SelectValue = SelectPrimitive.Value;
18431
- var SelectTrigger = React33.forwardRef(({ className, style, children, ...props }, ref) => {
18650
+ var SelectTrigger = React34.forwardRef(({ className, style, children, ...props }, ref) => {
18432
18651
  const { components } = useTheme();
18433
18652
  return /* @__PURE__ */ jsxs50(
18434
18653
  SelectPrimitive.Trigger,
@@ -18452,7 +18671,7 @@ var SelectTrigger = React33.forwardRef(({ className, style, children, ...props }
18452
18671
  );
18453
18672
  });
18454
18673
  SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
18455
- var SelectScrollUpButton = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
18674
+ var SelectScrollUpButton = React34.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
18456
18675
  SelectPrimitive.ScrollUpButton,
18457
18676
  {
18458
18677
  ref,
@@ -18462,7 +18681,7 @@ var SelectScrollUpButton = React33.forwardRef(({ className, ...props }, ref) =>
18462
18681
  }
18463
18682
  ));
18464
18683
  SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
18465
- var SelectScrollDownButton = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
18684
+ var SelectScrollDownButton = React34.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
18466
18685
  SelectPrimitive.ScrollDownButton,
18467
18686
  {
18468
18687
  ref,
@@ -18472,7 +18691,7 @@ var SelectScrollDownButton = React33.forwardRef(({ className, ...props }, ref) =
18472
18691
  }
18473
18692
  ));
18474
18693
  SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
18475
- var SelectContent = React33.forwardRef(({ className, style, children, position = "popper", ...props }, ref) => {
18694
+ var SelectContent = React34.forwardRef(({ className, style, children, position = "popper", ...props }, ref) => {
18476
18695
  const { themeClass, colors: colors2, components } = useTheme();
18477
18696
  return /* @__PURE__ */ jsx55(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs50(
18478
18697
  SelectPrimitive.Content,
@@ -18510,7 +18729,7 @@ var SelectContent = React33.forwardRef(({ className, style, children, position =
18510
18729
  ) });
18511
18730
  });
18512
18731
  SelectContent.displayName = SelectPrimitive.Content.displayName;
18513
- var SelectLabel = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
18732
+ var SelectLabel = React34.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
18514
18733
  SelectPrimitive.Label,
18515
18734
  {
18516
18735
  ref,
@@ -18519,7 +18738,7 @@ var SelectLabel = React33.forwardRef(({ className, ...props }, ref) => /* @__PUR
18519
18738
  }
18520
18739
  ));
18521
18740
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
18522
- var SelectItem = React33.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs50(
18741
+ var SelectItem = React34.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs50(
18523
18742
  SelectPrimitive.Item,
18524
18743
  {
18525
18744
  ref,
@@ -18535,7 +18754,7 @@ var SelectItem = React33.forwardRef(({ className, children, ...props }, ref) =>
18535
18754
  }
18536
18755
  ));
18537
18756
  SelectItem.displayName = SelectPrimitive.Item.displayName;
18538
- var SelectSeparator = React33.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
18757
+ var SelectSeparator = React34.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx55(
18539
18758
  SelectPrimitive.Separator,
18540
18759
  {
18541
18760
  ref,
@@ -18569,6 +18788,7 @@ function TransferCryptoDoubleInput({
18569
18788
  defaultSourceChainId,
18570
18789
  defaultSourceTokenAddress,
18571
18790
  defaultSourceSymbol,
18791
+ prefilledAmountUsd,
18572
18792
  depositConfirmationMode = "auto_ui",
18573
18793
  onExecutionsChange,
18574
18794
  onDepositSuccess,
@@ -18615,7 +18835,7 @@ function TransferCryptoDoubleInput({
18615
18835
  const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
18616
18836
  const loading = externalWallets?.length ? false : walletsLoading;
18617
18837
  const error = walletsError?.message ?? null;
18618
- const allAvailableChains = useMemo11(() => {
18838
+ const allAvailableChains = useMemo12(() => {
18619
18839
  const chainsMap = /* @__PURE__ */ new Map();
18620
18840
  supportedTokens.forEach((t13) => {
18621
18841
  t13.chains.forEach((c) => {
@@ -18693,6 +18913,22 @@ function TransferCryptoDoubleInput({
18693
18913
  const maxSlippage = currentChainFromBackend?.max_slippage_percent ?? 0.25;
18694
18914
  const processingTime = currentChainFromBackend?.estimated_processing_time ?? null;
18695
18915
  const minDepositUsd = currentChainFromBackend?.minimum_deposit_amount_usd ?? 3;
18916
+ const parsedPrefilledUsd = useMemo12(() => {
18917
+ const value = parseFloat(prefilledAmountUsd ?? "");
18918
+ return Number.isFinite(value) && value > 0 ? value : null;
18919
+ }, [prefilledAmountUsd]);
18920
+ const effectivePrefilledUsd = useMemo12(() => {
18921
+ if (parsedPrefilledUsd === null) return null;
18922
+ return Math.max(parsedPrefilledUsd, minDepositUsd);
18923
+ }, [parsedPrefilledUsd, minDepositUsd]);
18924
+ const prefillDisplay = useMemo12(() => {
18925
+ if (effectivePrefilledUsd === null) return null;
18926
+ const usdLabel = `$${effectivePrefilledUsd.toFixed(2)}`;
18927
+ if (selectedToken?.is_stablecoin) {
18928
+ return `${effectivePrefilledUsd.toFixed(2)} ${selectedToken.symbol} (${usdLabel})`;
18929
+ }
18930
+ return `${usdLabel} USD`;
18931
+ }, [effectivePrefilledUsd, selectedToken]);
18696
18932
  const renderTokenItem = (tokenData) => {
18697
18933
  return /* @__PURE__ */ jsxs51("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
18698
18934
  /* @__PURE__ */ jsx56(
@@ -18873,22 +19109,51 @@ function TransferCryptoDoubleInput({
18873
19109
  /* @__PURE__ */ jsx56("span", { children: "Retrying automatically every 5 seconds..." })
18874
19110
  ] })
18875
19111
  ] }),
18876
- /* @__PURE__ */ jsxs51("div", { className: "uf-flex uf-flex-col uf-items-center uf-pt-2", children: [
18877
- /* @__PURE__ */ jsx56(
18878
- "div",
18879
- {
18880
- className: "uf-text-xs uf-mb-2 uf-flex uf-items-center uf-gap-1",
18881
- style: { color: components.card.labelColor },
18882
- children: "Intent address"
18883
- }
18884
- ),
18885
- /* @__PURE__ */ jsx56(
18886
- "div",
18887
- {
18888
- className: "uf-shadow-lg",
18889
- style: {
18890
- borderRadius: components.card.borderRadius,
18891
- border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
19112
+ prefillDisplay && /* @__PURE__ */ jsxs51(
19113
+ "div",
19114
+ {
19115
+ className: "uf-rounded-xl uf-px-3 uf-py-2 uf-flex uf-items-center uf-justify-between",
19116
+ style: {
19117
+ backgroundColor: components.card.backgroundColor,
19118
+ border: `${components.card.borderWidth}px solid ${components.card.borderColor}`,
19119
+ borderRadius: components.card.borderRadius
19120
+ },
19121
+ children: [
19122
+ /* @__PURE__ */ jsx56(
19123
+ "span",
19124
+ {
19125
+ className: "uf-text-xs",
19126
+ style: { color: components.card.subtitleColor, fontFamily: fonts.regular },
19127
+ children: "You send"
19128
+ }
19129
+ ),
19130
+ /* @__PURE__ */ jsx56(
19131
+ "span",
19132
+ {
19133
+ className: "uf-text-sm uf-font-semibold",
19134
+ style: { color: components.card.titleColor, fontFamily: fonts.semibold },
19135
+ children: prefillDisplay
19136
+ }
19137
+ )
19138
+ ]
19139
+ }
19140
+ ),
19141
+ /* @__PURE__ */ jsxs51("div", { className: "uf-flex uf-flex-col uf-items-center uf-pt-2", children: [
19142
+ /* @__PURE__ */ jsx56(
19143
+ "div",
19144
+ {
19145
+ className: "uf-text-xs uf-mb-2 uf-flex uf-items-center uf-gap-1",
19146
+ style: { color: components.card.labelColor },
19147
+ children: "Intent address"
19148
+ }
19149
+ ),
19150
+ /* @__PURE__ */ jsx56(
19151
+ "div",
19152
+ {
19153
+ className: "uf-shadow-lg",
19154
+ style: {
19155
+ borderRadius: components.card.borderRadius,
19156
+ border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
18892
19157
  },
18893
19158
  children: loading || tokensLoading || !initialSelectionDone ? /* @__PURE__ */ jsx56(QRCodeSkeleton, { size: 180, darkMode: isDarkMode }) : depositAddress ? /* @__PURE__ */ jsx56(
18894
19159
  StyledQRCode,
@@ -19155,7 +19420,7 @@ function TransferCryptoDoubleInput({
19155
19420
  }
19156
19421
 
19157
19422
  // src/components/deposits/WalletConnect.tsx
19158
- import * as React34 from "react";
19423
+ import * as React35 from "react";
19159
19424
  import { ExternalLink as ExternalLink4, Loader2 as Loader210 } from "lucide-react";
19160
19425
  import {
19161
19426
  getAddressBalances as getAddressBalances2,
@@ -20515,7 +20780,7 @@ function WalletConnect({
20515
20780
  amountQuickSelect = "percentage",
20516
20781
  onWalletDisconnect,
20517
20782
  onWalletConnected,
20518
- prefillAmountUsd,
20783
+ prefilledAmountUsd,
20519
20784
  checkoutAmountUsd,
20520
20785
  checkoutReceivedUsd,
20521
20786
  onNewDeposit,
@@ -20537,28 +20802,28 @@ function WalletConnect({
20537
20802
  onExecutionsChange
20538
20803
  }) {
20539
20804
  const { colors: colors2, fonts, components, mode } = useTheme();
20540
- const walletProvidedAtMount = React34.useRef(!!initialWalletInfo && !!initialDepositWallet);
20541
- const [activeWalletInfo, setActiveWalletInfo] = React34.useState(
20805
+ const walletProvidedAtMount = React35.useRef(!!initialWalletInfo && !!initialDepositWallet);
20806
+ const [activeWalletInfo, setActiveWalletInfo] = React35.useState(
20542
20807
  initialWalletInfo ?? null
20543
20808
  );
20544
- const [activeDepositWallet, setActiveDepositWallet] = React34.useState(
20809
+ const [activeDepositWallet, setActiveDepositWallet] = React35.useState(
20545
20810
  initialDepositWallet ?? null
20546
20811
  );
20547
20812
  const initialView = initialWalletInfo && initialDepositWallet ? "select_token" : "select_wallet";
20548
- const [view, setView] = React34.useState(initialView);
20549
- const [isTransitioning, setIsTransitioning] = React34.useState(false);
20550
- const viewRef = React34.useRef(initialView);
20813
+ const [view, setView] = React35.useState(initialView);
20814
+ const [isTransitioning, setIsTransitioning] = React35.useState(false);
20815
+ const viewRef = React35.useRef(initialView);
20551
20816
  const standalone = !canGoBack && !walletProvidedAtMount.current;
20552
20817
  const { wallet: detectedWallet, isLoading: detectingWallet } = useDetectedBrowserWallet({
20553
20818
  enabled: standalone
20554
20819
  });
20555
- const [autoResolved, setAutoResolved] = React34.useState(false);
20556
- const [selectedWalletDef, setSelectedWalletDef] = React34.useState(null);
20557
- const [connectingNetwork, setConnectingNetwork] = React34.useState(null);
20558
- const [walletError, setWalletError] = React34.useState(null);
20559
- const [isWalletConnecting, setIsWalletConnecting] = React34.useState(false);
20560
- const [eip6963ProviderCount, setEip6963ProviderCount] = React34.useState(0);
20561
- React34.useEffect(() => {
20820
+ const [autoResolved, setAutoResolved] = React35.useState(false);
20821
+ const [selectedWalletDef, setSelectedWalletDef] = React35.useState(null);
20822
+ const [connectingNetwork, setConnectingNetwork] = React35.useState(null);
20823
+ const [walletError, setWalletError] = React35.useState(null);
20824
+ const [isWalletConnecting, setIsWalletConnecting] = React35.useState(false);
20825
+ const [eip6963ProviderCount, setEip6963ProviderCount] = React35.useState(0);
20826
+ React35.useEffect(() => {
20562
20827
  const store = getEip6963Store();
20563
20828
  if (!store) return;
20564
20829
  setEip6963ProviderCount(store.getProviders().length);
@@ -20567,7 +20832,7 @@ function WalletConnect({
20567
20832
  });
20568
20833
  }, []);
20569
20834
  const { wallets: backendWallets } = useExternalWallets({ publishableKey });
20570
- const walletDefinitions = React34.useMemo(
20835
+ const walletDefinitions = React35.useMemo(
20571
20836
  () => backendWallets.length > 0 ? backendWallets.map((w) => ({
20572
20837
  id: w.id,
20573
20838
  name: w.name,
@@ -20578,32 +20843,32 @@ function WalletConnect({
20578
20843
  })) : FALLBACK_WALLET_DEFINITIONS,
20579
20844
  [backendWallets]
20580
20845
  );
20581
- const [recentWalletId, setRecentWalletIdState] = React34.useState(getLastOpenedWallet);
20582
- React34.useEffect(() => {
20846
+ const [recentWalletId, setRecentWalletIdState] = React35.useState(getLastOpenedWallet);
20847
+ React35.useEffect(() => {
20583
20848
  if (view === "select_wallet") {
20584
20849
  setRecentWalletIdState(getLastOpenedWallet());
20585
20850
  }
20586
20851
  }, [view]);
20587
- const availableWallets = React34.useMemo(
20852
+ const availableWallets = React35.useMemo(
20588
20853
  () => detectAvailableWallets(walletDefinitions, recentWalletId),
20589
20854
  [walletDefinitions, eip6963ProviderCount, recentWalletId]
20590
20855
  );
20591
- const [isMobile, setIsMobile] = React34.useState(false);
20592
- React34.useEffect(() => {
20856
+ const [isMobile, setIsMobile] = React35.useState(false);
20857
+ React35.useEffect(() => {
20593
20858
  setIsMobile(isMobileDevice());
20594
20859
  }, []);
20595
- const mobileDepositAddresses = React34.useMemo(
20860
+ const mobileDepositAddresses = React35.useMemo(
20596
20861
  () => (depositWallets ?? []).map((w) => ({ chain_type: w.chain_type, address: w.address })),
20597
20862
  [depositWallets]
20598
20863
  );
20599
- const mobileDepositWalletIds = React34.useMemo(
20864
+ const mobileDepositWalletIds = React35.useMemo(
20600
20865
  () => (depositWallets ?? []).filter((w) => w.chain_type === "ethereum" || w.chain_type === "solana").map((w) => w.id),
20601
20866
  [depositWallets]
20602
20867
  );
20603
- const [mobileRedirect, setMobileRedirect] = React34.useState(null);
20604
- const [pendingMobileWallet, setPendingMobileWallet] = React34.useState(null);
20605
- const [awaitingMobileDeposit, setAwaitingMobileDeposit] = React34.useState(false);
20606
- React34.useEffect(() => {
20868
+ const [mobileRedirect, setMobileRedirect] = React35.useState(null);
20869
+ const [pendingMobileWallet, setPendingMobileWallet] = React35.useState(null);
20870
+ const [awaitingMobileDeposit, setAwaitingMobileDeposit] = React35.useState(false);
20871
+ React35.useEffect(() => {
20607
20872
  if (!standalone || autoResolved || detectingWallet) return;
20608
20873
  if (!detectedWallet) {
20609
20874
  setAutoResolved(true);
@@ -20629,32 +20894,36 @@ function WalletConnect({
20629
20894
  depositWallets,
20630
20895
  depositWalletsLoading
20631
20896
  ]);
20632
- React34.useEffect(() => {
20897
+ React35.useEffect(() => {
20633
20898
  if (!standalone || autoResolved) return;
20634
20899
  const t13 = setTimeout(() => setAutoResolved(true), 5e3);
20635
20900
  return () => clearTimeout(t13);
20636
20901
  }, [standalone, autoResolved]);
20637
- const [balances, setBalances] = React34.useState([]);
20638
- const [isLoading, setIsLoading] = React34.useState(false);
20639
- const [selectedBalance, setSelectedBalance] = React34.useState(null);
20640
- const [totalBalanceUsd, setTotalBalanceUsd] = React34.useState(null);
20641
- const [error, setError] = React34.useState(null);
20642
- const [isDisconnectingWallet, setIsDisconnectingWallet] = React34.useState(false);
20643
- const [amountUsd, setAmountUsd] = React34.useState(prefillAmountUsd ?? "");
20644
- const [isConfirming, setIsConfirming] = React34.useState(false);
20645
- const [hasSignedTransaction, setHasSignedTransaction] = React34.useState(false);
20646
- const [tokenChainDetails, setTokenChainDetails] = React34.useState(null);
20647
- const [loadingTokenDetails, setLoadingTokenDetails] = React34.useState(false);
20648
- const [showTransactionDetails, setShowTransactionDetails] = React34.useState(false);
20649
- const [receivedUsdAtSubmission, setReceivedUsdAtSubmission] = React34.useState(null);
20902
+ const [balances, setBalances] = React35.useState([]);
20903
+ const [isLoading, setIsLoading] = React35.useState(false);
20904
+ const [selectedBalance, setSelectedBalance] = React35.useState(null);
20905
+ const [totalBalanceUsd, setTotalBalanceUsd] = React35.useState(null);
20906
+ const [error, setError] = React35.useState(null);
20907
+ const [isDisconnectingWallet, setIsDisconnectingWallet] = React35.useState(false);
20908
+ const [amountUsd, setAmountUsd] = React35.useState(prefilledAmountUsd ?? "");
20909
+ const [isConfirming, setIsConfirming] = React35.useState(false);
20910
+ const [hasSignedTransaction, setHasSignedTransaction] = React35.useState(false);
20911
+ const [tokenChainDetails, setTokenChainDetails] = React35.useState(null);
20912
+ const [loadingTokenDetails, setLoadingTokenDetails] = React35.useState(false);
20913
+ const [showTransactionDetails, setShowTransactionDetails] = React35.useState(false);
20914
+ const [receivedUsdAtSubmission, setReceivedUsdAtSubmission] = React35.useState(null);
20650
20915
  const walletInfo = activeWalletInfo;
20651
20916
  const depositWallet = activeDepositWallet;
20652
20917
  const hasWallet = !!activeWalletInfo && !!activeDepositWallet;
20918
+ React35.useEffect(() => {
20919
+ const cleanedPrefilled = prefilledAmountUsd?.replace(/[^0-9.]/g, "") ?? "";
20920
+ setAmountUsd(cleanedPrefilled);
20921
+ }, [prefilledAmountUsd]);
20653
20922
  const chainType = activeDepositWallet?.chain_type ?? "ethereum";
20654
20923
  const recipientAddress = activeDepositWallet?.address ?? "";
20655
20924
  const isCheckoutMode = !!checkoutAmountUsd;
20656
20925
  const supportedChainType = chainType === "algorand" || chainType === "xrpl" || chainType === "cardano" || chainType === "n1" ? "ethereum" : chainType;
20657
- const transitionTo = React34.useCallback((nextView) => {
20926
+ const transitionTo = React35.useCallback((nextView) => {
20658
20927
  if (nextView === viewRef.current) return;
20659
20928
  setIsTransitioning(true);
20660
20929
  setTimeout(() => {
@@ -20719,7 +20988,7 @@ function WalletConnect({
20719
20988
  if (!selectedWalletDef) return;
20720
20989
  handleConnectWallet(selectedWalletDef, network);
20721
20990
  };
20722
- React34.useEffect(() => {
20991
+ React35.useEffect(() => {
20723
20992
  if (!pendingMobileWallet) return;
20724
20993
  if (mobileDepositAddresses.length > 0) {
20725
20994
  const wallet = pendingMobileWallet;
@@ -20883,7 +21152,7 @@ function WalletConnect({
20883
21152
  publishableKey,
20884
21153
  enabled: !!activeWalletInfo && !!recipientAddress
20885
21154
  });
20886
- const effectiveDestinationAmount = React34.useMemo(() => {
21155
+ const effectiveDestinationAmount = React35.useMemo(() => {
20887
21156
  if (!checkoutRemainingBaseUnits || checkoutRemainingBaseUnits === "0") return "0";
20888
21157
  if (!checkoutAmountUsd) return checkoutRemainingBaseUnits;
20889
21158
  const remaining = BigInt(checkoutRemainingBaseUnits);
@@ -20911,7 +21180,7 @@ function WalletConnect({
20911
21180
  stablecoinParity,
20912
21181
  enabled: isCheckoutMode && !!selectedToken && !!checkoutDestination && effectiveDestinationAmount !== "0"
20913
21182
  });
20914
- const activeCheckoutQuote = React34.useMemo(() => {
21183
+ const activeCheckoutQuote = React35.useMemo(() => {
20915
21184
  if (!isCheckoutMode) return null;
20916
21185
  if (walletCheckoutQuote)
20917
21186
  return {
@@ -20941,10 +21210,10 @@ function WalletConnect({
20941
21210
  onDepositSuccess,
20942
21211
  onDepositError
20943
21212
  });
20944
- React34.useEffect(() => {
21213
+ React35.useEffect(() => {
20945
21214
  onExecutionsChange?.(depositExecutions);
20946
21215
  }, [depositExecutions, onExecutionsChange]);
20947
- const latestDepositExecution = React34.useMemo(() => {
21216
+ const latestDepositExecution = React35.useMemo(() => {
20948
21217
  if (depositExecutions.length === 0) return null;
20949
21218
  return [...depositExecutions].sort((a, b) => {
20950
21219
  const ta = a.created_at ? new Date(a.created_at).getTime() : 0;
@@ -20952,21 +21221,21 @@ function WalletConnect({
20952
21221
  return tb - ta;
20953
21222
  })[0];
20954
21223
  }, [depositExecutions]);
20955
- React34.useEffect(() => {
21224
+ React35.useEffect(() => {
20956
21225
  if (awaitingMobileDeposit && latestDepositExecution && (viewRef.current === "mobile_redirect" || viewRef.current === "connecting")) {
20957
21226
  transitionTo("mobile_deposit_status");
20958
21227
  }
20959
21228
  }, [awaitingMobileDeposit, latestDepositExecution, transitionTo]);
20960
- React34.useEffect(() => {
20961
- if (!prefillAmountUsd || !tokenChainDetails || view !== "enter_amount") return;
21229
+ React35.useEffect(() => {
21230
+ if (!isCheckoutMode || !tokenChainDetails || view !== "enter_amount") return;
20962
21231
  const minDeposit = tokenChainDetails.minimum_deposit_amount_usd || 0;
20963
21232
  const currentAmount = parseFloat(amountUsd) || 0;
20964
21233
  if (currentAmount > 0 && currentAmount < minDeposit) setAmountUsd(minDeposit.toFixed(2));
20965
- }, [tokenChainDetails, view, prefillAmountUsd]);
20966
- React34.useEffect(() => {
21234
+ }, [isCheckoutMode, tokenChainDetails, view, amountUsd]);
21235
+ React35.useEffect(() => {
20967
21236
  if (view === "review") setShowTransactionDetails(false);
20968
21237
  }, [view]);
20969
- React34.useEffect(() => {
21238
+ React35.useEffect(() => {
20970
21239
  if (view !== "enter_amount" && view !== "review" || !selectedBalance || !activeDepositWallet)
20971
21240
  return;
20972
21241
  let cancelled = false;
@@ -21003,7 +21272,7 @@ function WalletConnect({
21003
21272
  cancelled = true;
21004
21273
  };
21005
21274
  }, [view, selectedBalance, publishableKey, activeDepositWallet]);
21006
- React34.useEffect(() => {
21275
+ React35.useEffect(() => {
21007
21276
  if (!activeWalletInfo || !activeDepositWallet) return;
21008
21277
  let cancelled = false;
21009
21278
  setIsLoading(true);
@@ -21068,21 +21337,21 @@ function WalletConnect({
21068
21337
  defaultSourceTokenAddress,
21069
21338
  defaultSourceSymbol
21070
21339
  ]);
21071
- const usdToTokenRate = React34.useMemo(() => {
21340
+ const usdToTokenRate = React35.useMemo(() => {
21072
21341
  if (!selectedBalance || !selectedBalance.amount_usd || !selectedToken) return 0;
21073
21342
  const balanceAmount = Number(selectedBalance.amount) / 10 ** selectedToken.decimals;
21074
21343
  const balanceUsd = parseFloat(selectedBalance.amount_usd);
21075
21344
  if (balanceAmount === 0 || balanceUsd === 0) return 0;
21076
21345
  return balanceAmount / balanceUsd;
21077
21346
  }, [selectedBalance, selectedToken]);
21078
- const tokenAmount = React34.useMemo(() => {
21347
+ const tokenAmount = React35.useMemo(() => {
21079
21348
  if (isCheckoutMode && activeCheckoutQuote && selectedToken)
21080
21349
  return Number(activeCheckoutQuote.sourceAmount) / 10 ** activeCheckoutQuote.sourceTokenDecimals;
21081
21350
  const usdNum = parseFloat(amountUsd) || 0;
21082
21351
  if (usdNum === 0 || usdToTokenRate === 0) return 0;
21083
21352
  return usdNum * usdToTokenRate;
21084
21353
  }, [amountUsd, usdToTokenRate, isCheckoutMode, activeCheckoutQuote, selectedToken]);
21085
- React34.useEffect(() => {
21354
+ React35.useEffect(() => {
21086
21355
  if (isCheckoutMode && activeCheckoutQuote?.sourceAmountUsd && view === "enter_amount")
21087
21356
  setAmountUsd(activeCheckoutQuote.sourceAmountUsd);
21088
21357
  }, [isCheckoutMode, activeCheckoutQuote, view]);
@@ -21091,7 +21360,7 @@ function WalletConnect({
21091
21360
  const inputUsdNum = parseFloat(amountUsd) || 0;
21092
21361
  const minDepositUsd = tokenChainDetails?.minimum_deposit_amount_usd || 0;
21093
21362
  const isValidAmount = isCheckoutMode && activeCheckoutQuote ? tokenAmount > 0 && tokenAmount <= maxTokenAmount : inputUsdNum > 0 && inputUsdNum <= maxUsdAmount && inputUsdNum >= minDepositUsd;
21094
- const formattedTokenAmount = React34.useMemo(() => {
21363
+ const formattedTokenAmount = React35.useMemo(() => {
21095
21364
  if (tokenAmount === 0 || !selectedToken) return null;
21096
21365
  return `${tokenAmount.toFixed(6)} ${selectedToken.symbol}`.replace(/\.?0+$/, "");
21097
21366
  }, [tokenAmount, selectedToken]);
@@ -21124,7 +21393,7 @@ function WalletConnect({
21124
21393
  break;
21125
21394
  case "enter_amount":
21126
21395
  transitionTo("select_token");
21127
- setAmountUsd(prefillAmountUsd ?? "");
21396
+ setAmountUsd(prefilledAmountUsd ?? "");
21128
21397
  setTokenChainDetails(null);
21129
21398
  break;
21130
21399
  case "review":
@@ -21156,7 +21425,7 @@ function WalletConnect({
21156
21425
  setSelectedBalance(null);
21157
21426
  setBalances([]);
21158
21427
  setTotalBalanceUsd(null);
21159
- setAmountUsd(prefillAmountUsd ?? "");
21428
+ setAmountUsd(prefilledAmountUsd ?? "");
21160
21429
  setError(null);
21161
21430
  };
21162
21431
  if (standalone) {
@@ -21401,116 +21670,131 @@ function WalletConnect({
21401
21670
  ] });
21402
21671
  }
21403
21672
  if (view === "select_wallet") {
21404
- return /* @__PURE__ */ jsxs56("div", { style: viewTransitionStyle, children: [
21405
- /* @__PURE__ */ jsx62(
21406
- DepositHeader,
21673
+ return (
21674
+ // Mobile: flex column that fills the full-height sheet so the wallet list
21675
+ // scrolls and the footer pins to the bottom. Desktop (sm:): content-sized.
21676
+ /* @__PURE__ */ jsxs56(
21677
+ "div",
21407
21678
  {
21408
- title: "Connect Wallet",
21409
- showBack: canGoBack,
21410
- onBack: handleBack,
21411
- onClose
21412
- }
21413
- ),
21414
- /* @__PURE__ */ jsxs56("div", { className: "uf-pb-4", children: [
21415
- /* @__PURE__ */ jsx62(
21416
- "p",
21417
- {
21418
- className: "uf-text-sm uf-text-center uf-pb-4",
21419
- style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
21420
- children: isMobile ? "Open this page in your wallet's app to connect" : "Select a wallet to connect"
21421
- }
21422
- ),
21423
- /* @__PURE__ */ jsx62("div", { className: "uf-space-y-2", style: { maxHeight: 330, overflowY: "auto" }, children: availableWallets.map((wallet) => {
21424
- const walletPlatformAllowed = !wallet.mobileBrowsePlatforms || wallet.mobileBrowsePlatforms.includes(getMobilePlatform() ?? "");
21425
- const showOpenInApp = isMobile && !wallet.isInstalled && wallet.supportsMobileBrowse !== false && walletPlatformAllowed;
21426
- const isPending = pendingMobileWallet?.id === wallet.id;
21427
- return /* @__PURE__ */ jsxs56(
21428
- "button",
21429
- {
21430
- onClick: () => void handleWalletClick(wallet),
21431
- disabled: isWalletConnecting || !!pendingMobileWallet,
21432
- className: "uf-w-full uf-transition-colors uf-p-3 uf-flex uf-items-center uf-justify-between hover:uf-opacity-90 disabled:uf-opacity-50",
21433
- style: {
21434
- backgroundColor: components.card.backgroundColor,
21435
- borderRadius: components.card.borderRadius,
21436
- border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
21437
- },
21438
- children: [
21439
- /* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
21440
- WALLET_ICONS3[wallet.id] ? /* @__PURE__ */ jsx62(
21441
- WalletIconWithNetwork,
21442
- {
21443
- WalletIcon: WALLET_ICONS3[wallet.id],
21444
- networks: wallet.networks,
21445
- size: 40,
21446
- className: "uf-rounded-lg"
21447
- }
21448
- ) : /* @__PURE__ */ jsx62("div", { className: "uf-w-10 uf-h-10 uf-rounded-lg uf-bg-gray-500" }),
21449
- /* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
21450
- /* @__PURE__ */ jsx62(
21451
- "div",
21452
- {
21453
- className: "uf-text-sm uf-font-medium",
21454
- style: { color: components.card.titleColor, fontFamily: fonts.medium },
21455
- children: wallet.name
21456
- }
21457
- ),
21458
- wallet.id === recentWalletId && /* @__PURE__ */ jsx62(
21459
- "span",
21460
- {
21461
- className: "uf-text-xs uf-px-2 uf-py-0.5 uf-rounded-full",
21462
- style: {
21463
- backgroundColor: colors2.primary + "20",
21464
- color: colors2.primary,
21465
- fontFamily: fonts.medium
21466
- },
21467
- children: "Last used"
21468
- }
21469
- )
21470
- ] })
21471
- ] }),
21472
- isPending ? /* @__PURE__ */ jsx62(
21473
- Loader210,
21474
- {
21475
- className: "uf-w-4 uf-h-4 uf-animate-spin",
21476
- style: { color: colors2.primary }
21477
- }
21478
- ) : wallet.isInstalled ? /* @__PURE__ */ jsx62(
21479
- "span",
21679
+ style: viewTransitionStyle,
21680
+ className: "uf-flex uf-min-h-0 uf-flex-1 uf-flex-col sm:uf-block",
21681
+ children: [
21682
+ /* @__PURE__ */ jsx62(
21683
+ DepositHeader,
21684
+ {
21685
+ title: "Connect Wallet",
21686
+ showBack: canGoBack,
21687
+ onBack: handleBack,
21688
+ onClose
21689
+ }
21690
+ ),
21691
+ /* @__PURE__ */ jsxs56("div", { className: "uf-pb-4 uf-flex uf-min-h-0 uf-flex-1 uf-flex-col sm:uf-block", children: [
21692
+ /* @__PURE__ */ jsx62(
21693
+ "p",
21694
+ {
21695
+ className: "uf-text-sm uf-text-center uf-pb-4",
21696
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
21697
+ children: isMobile ? "Open this page in your wallet's app to connect" : "Select a wallet to connect"
21698
+ }
21699
+ ),
21700
+ /* @__PURE__ */ jsx62("div", { className: "uf-space-y-2 uf-min-h-0 uf-flex-1 uf-overflow-y-auto sm:uf-flex-none sm:uf-max-h-[330px] [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: availableWallets.filter((wallet) => {
21701
+ if (!isMobile || wallet.isInstalled) return true;
21702
+ const platformAllowed = !wallet.mobileBrowsePlatforms || wallet.mobileBrowsePlatforms.includes(getMobilePlatform() ?? "");
21703
+ return wallet.supportsMobileBrowse !== false && platformAllowed;
21704
+ }).map((wallet) => {
21705
+ const walletPlatformAllowed = !wallet.mobileBrowsePlatforms || wallet.mobileBrowsePlatforms.includes(getMobilePlatform() ?? "");
21706
+ const showOpenInApp = isMobile && !wallet.isInstalled && wallet.supportsMobileBrowse !== false && walletPlatformAllowed;
21707
+ const isPending = pendingMobileWallet?.id === wallet.id;
21708
+ return /* @__PURE__ */ jsxs56(
21709
+ "button",
21480
21710
  {
21481
- className: "uf-text-xs uf-px-2 uf-py-1 uf-rounded-full",
21711
+ onClick: () => void handleWalletClick(wallet),
21712
+ disabled: isWalletConnecting || !!pendingMobileWallet,
21713
+ className: "uf-w-full uf-transition-colors uf-p-3 uf-flex uf-items-center uf-justify-between hover:uf-opacity-90 disabled:uf-opacity-50",
21482
21714
  style: {
21483
- backgroundColor: colors2.primary + "20",
21484
- color: colors2.primary,
21485
- fontFamily: fonts.medium
21715
+ backgroundColor: components.card.backgroundColor,
21716
+ borderRadius: components.card.borderRadius,
21717
+ border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
21486
21718
  },
21487
- children: "Detected"
21488
- }
21489
- ) : /* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
21490
- /* @__PURE__ */ jsx62(
21491
- "span",
21492
- {
21493
- className: "uf-text-xs",
21494
- style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
21495
- children: showOpenInApp ? "Open" : "Install"
21496
- }
21497
- ),
21498
- /* @__PURE__ */ jsx62(
21499
- ExternalLink4,
21500
- {
21501
- className: "uf-w-3 uf-h-3",
21502
- style: { color: colors2.foregroundMuted }
21503
- }
21504
- )
21505
- ] })
21506
- ]
21507
- },
21508
- wallet.id
21509
- );
21510
- }) }),
21511
- walletError && /* @__PURE__ */ jsx62("div", { className: "uf-text-center uf-text-sm uf-mt-4 uf-px-4", style: { color: "#ef4444" }, children: walletError })
21512
- ] })
21513
- ] });
21719
+ children: [
21720
+ /* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
21721
+ WALLET_ICONS3[wallet.id] ? /* @__PURE__ */ jsx62(
21722
+ WalletIconWithNetwork,
21723
+ {
21724
+ WalletIcon: WALLET_ICONS3[wallet.id],
21725
+ networks: wallet.networks,
21726
+ size: 40,
21727
+ className: "uf-rounded-lg"
21728
+ }
21729
+ ) : /* @__PURE__ */ jsx62("div", { className: "uf-w-10 uf-h-10 uf-rounded-lg uf-bg-gray-500" }),
21730
+ /* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
21731
+ /* @__PURE__ */ jsx62(
21732
+ "div",
21733
+ {
21734
+ className: "uf-text-sm uf-font-medium",
21735
+ style: { color: components.card.titleColor, fontFamily: fonts.medium },
21736
+ children: wallet.name
21737
+ }
21738
+ ),
21739
+ wallet.id === recentWalletId && /* @__PURE__ */ jsx62(
21740
+ "span",
21741
+ {
21742
+ className: "uf-text-xs uf-px-2 uf-py-0.5 uf-rounded-full",
21743
+ style: {
21744
+ backgroundColor: colors2.primary + "20",
21745
+ color: colors2.primary,
21746
+ fontFamily: fonts.medium
21747
+ },
21748
+ children: "Last used"
21749
+ }
21750
+ )
21751
+ ] })
21752
+ ] }),
21753
+ isPending ? /* @__PURE__ */ jsx62(
21754
+ Loader210,
21755
+ {
21756
+ className: "uf-w-4 uf-h-4 uf-animate-spin",
21757
+ style: { color: colors2.primary }
21758
+ }
21759
+ ) : wallet.isInstalled ? /* @__PURE__ */ jsx62(
21760
+ "span",
21761
+ {
21762
+ className: "uf-text-xs uf-px-2 uf-py-1 uf-rounded-full",
21763
+ style: {
21764
+ backgroundColor: colors2.primary + "20",
21765
+ color: colors2.primary,
21766
+ fontFamily: fonts.medium
21767
+ },
21768
+ children: "Detected"
21769
+ }
21770
+ ) : /* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
21771
+ /* @__PURE__ */ jsx62(
21772
+ "span",
21773
+ {
21774
+ className: "uf-text-xs",
21775
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
21776
+ children: showOpenInApp ? "Open" : "Install"
21777
+ }
21778
+ ),
21779
+ /* @__PURE__ */ jsx62(
21780
+ ExternalLink4,
21781
+ {
21782
+ className: "uf-w-3 uf-h-3",
21783
+ style: { color: colors2.foregroundMuted }
21784
+ }
21785
+ )
21786
+ ] })
21787
+ ]
21788
+ },
21789
+ wallet.id
21790
+ );
21791
+ }) }),
21792
+ walletError && /* @__PURE__ */ jsx62("div", { className: "uf-text-center uf-text-sm uf-mt-4 uf-px-4", style: { color: "#ef4444" }, children: walletError })
21793
+ ] })
21794
+ ]
21795
+ }
21796
+ )
21797
+ );
21514
21798
  }
21515
21799
  const preConnectAccent = selectedWalletDef ? getWalletBrandColor(selectedWalletDef.id, mode) : void 0;
21516
21800
  const preConnectFg = preConnectAccent ? getContrastingTextColor(preConnectAccent) : void 0;
@@ -21868,6 +22152,15 @@ function SkeletonButton({ variant = "default" }) {
21868
22152
  ] });
21869
22153
  }
21870
22154
  var t8 = i18n.depositModal;
22155
+ function normalizePrefilledUsdAmount(value) {
22156
+ if (!value) return void 0;
22157
+ const cleaned = value.replace(/[^0-9.]/g, "");
22158
+ if (!cleaned) return void 0;
22159
+ const normalizedNumeric = cleaned.replace(/(\..*)\./g, "$1");
22160
+ const parsed = parseFloat(normalizedNumeric);
22161
+ if (!Number.isFinite(parsed) || parsed <= 0) return void 0;
22162
+ return parseFloat(parsed.toFixed(2)).toString();
22163
+ }
21871
22164
  function depositTabForScreen(screen) {
21872
22165
  return screen === "card" || screen === "cashapp" || screen === "bank_transfer" || screen === "stripe_link" || screen === "apple_pay" ? "cash" : "crypto";
21873
22166
  }
@@ -21887,6 +22180,7 @@ function DepositModal({
21887
22180
  defaultSourceChainId,
21888
22181
  defaultSourceTokenAddress,
21889
22182
  defaultSourceSymbol,
22183
+ prefilledAmountUsd,
21890
22184
  hideDepositTracker,
21891
22185
  showBalanceHeader = false,
21892
22186
  transferInputVariant = "double_input",
@@ -21902,7 +22196,9 @@ function DepositModal({
21902
22196
  applePayTitle = "Pay with Apple Pay",
21903
22197
  applePaySubTitle = "Instant",
21904
22198
  enableBankTransfer,
21905
- enableStripeLink = false,
22199
+ // No default: left undefined so the backend `stripe_link.enabled` can govern
22200
+ // (via the `??` chain in showStripeLink) once a dashboard toggle exists.
22201
+ enableStripeLink,
21906
22202
  userEmail,
21907
22203
  hideDepositFlowInfo = false,
21908
22204
  hideDisplayDescription = false,
@@ -21920,7 +22216,11 @@ function DepositModal({
21920
22216
  depositTrackerSubTitle = t8.depositTracker.subtitle
21921
22217
  }) {
21922
22218
  const { colors: colors2, fonts, components } = useTheme();
21923
- const onDepositSuccessFor = useCallback8(
22219
+ const normalizedPrefilledAmountUsd = useMemo14(
22220
+ () => normalizePrefilledUsdAmount(prefilledAmountUsd),
22221
+ [prefilledAmountUsd]
22222
+ );
22223
+ const onDepositSuccessFor = useCallback10(
21924
22224
  (method) => onDepositSuccess || onEvent ? (data) => {
21925
22225
  const payload = { ...data, method };
21926
22226
  onDepositSuccess?.(payload);
@@ -21933,11 +22233,11 @@ function DepositModal({
21933
22233
  } : void 0,
21934
22234
  [onDepositSuccess, onEvent]
21935
22235
  );
21936
- const onDepositErrorFor = useCallback8(
22236
+ const onDepositErrorFor = useCallback10(
21937
22237
  (method) => onDepositError ? (error) => onDepositError({ ...error, method }) : void 0,
21938
22238
  [onDepositError]
21939
22239
  );
21940
- const effectiveInitialScreen = useMemo13(() => {
22240
+ const effectiveInitialScreen = useMemo14(() => {
21941
22241
  const s = initialScreen ?? "main";
21942
22242
  if (s === "tracker" && hideDepositTracker === true) return "main";
21943
22243
  if (s === "cashapp" && enableCashApp === false) return "main";
@@ -21963,7 +22263,7 @@ function DepositModal({
21963
22263
  enableStripeLink
21964
22264
  ]);
21965
22265
  const [containerEl, setContainerEl] = useState40(null);
21966
- const containerCallbackRef = useCallback8((el) => {
22266
+ const containerCallbackRef = useCallback10((el) => {
21967
22267
  setContainerEl(el);
21968
22268
  }, []);
21969
22269
  const [view, setView] = useState40(effectiveInitialScreen);
@@ -21972,7 +22272,7 @@ function DepositModal({
21972
22272
  const [depositTab, setDepositTab] = useState40(
21973
22273
  () => depositTabForScreen(effectiveInitialScreen)
21974
22274
  );
21975
- const resetViewTimeoutRef = useRef12(null);
22275
+ const resetViewTimeoutRef = useRef13(null);
21976
22276
  const [cardView, setCardView] = useState40("amount");
21977
22277
  const [exchangeView, setExchangeView] = useState40("providers");
21978
22278
  const [browserWalletModalOpen, setBrowserWalletModalOpen] = useState40(false);
@@ -21983,14 +22283,18 @@ function DepositModal({
21983
22283
  const [allExecutions, setAllExecutions] = useState40([]);
21984
22284
  const [selectedExecution, setSelectedExecution] = useState40(null);
21985
22285
  const [depositExecutions, setDepositExecutions] = useState40([]);
22286
+ const { userIpInfo, isLoading: isLoadingIp } = useUserIp();
21986
22287
  const { projectConfig } = useProjectConfig({
21987
22288
  publishableKey,
21988
- enabled: open
22289
+ enabled: open && !isLoadingIp,
22290
+ countryCode: userIpInfo?.alpha2,
22291
+ subdivisionCode: userIpInfo?.subdivisionCode ?? void 0
21989
22292
  });
21990
22293
  const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
21991
22294
  const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
21992
22295
  const showPayWithExchange = enablePayWithExchange ?? projectConfig?.pay_with_exchange?.enabled ?? true;
21993
22296
  const showFiatOnramp = !projectConfig?.fiat_onramp?.is_hidden && (enableFiatOnramp ?? projectConfig?.fiat_onramp?.enabled ?? true);
22297
+ const showStripeLink = !projectConfig?.stripe_link?.is_hidden && (enableStripeLink ?? projectConfig?.stripe_link?.enabled ?? false);
21994
22298
  const showConnectExchange = enableConnectExchange ?? projectConfig?.connect_exchange?.enabled ?? true;
21995
22299
  const showCashApp = enableCashApp ?? projectConfig?.cash_app?.enabled ?? true;
21996
22300
  const showApplePay = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
@@ -22136,7 +22440,6 @@ function DepositModal({
22136
22440
  publishableKey,
22137
22441
  enabled: open && showPayWithExchange
22138
22442
  });
22139
- const { userIpInfo, isLoading: isLoadingIp } = useUserIp();
22140
22443
  const { providers: bankTransferProviders, isLoading: bankTransferProvidersLoading } = useBankTransferProviders({
22141
22444
  publishableKey,
22142
22445
  enabled: open && !!userIpInfo?.alpha2,
@@ -22313,10 +22616,16 @@ function DepositModal({
22313
22616
  );
22314
22617
  const [cashAppView, setCashAppView] = useState40("amount");
22315
22618
  const [stripeLinkStep, setStripeLinkStep] = useState40("amount");
22316
- const stripeLinkBackRef = useRef12(null);
22619
+ const stripeLinkBackRef = useRef13(null);
22620
+ useEffect34(() => {
22621
+ if (view === "stripe_link" && !showStripeLink && effectiveInitialScreen === "main") {
22622
+ setView("main");
22623
+ setStripeLinkStep("amount");
22624
+ }
22625
+ }, [view, showStripeLink, effectiveInitialScreen]);
22317
22626
  const [cashAppAmount, setCashAppAmount] = useState40("");
22318
22627
  const [applePayView, setApplePayView] = useState40("email_input");
22319
- const applePayHandleRef = useRef12(null);
22628
+ const applePayHandleRef = useRef13(null);
22320
22629
  const applePayHeaderTitle = (() => {
22321
22630
  switch (applePayView) {
22322
22631
  case "email_input":
@@ -22538,7 +22847,7 @@ function DepositModal({
22538
22847
  },
22539
22848
  "cashapp"
22540
22849
  ) : null;
22541
- const stripeLinkMenuButton = enableStripeLink ? /* @__PURE__ */ jsx63(
22850
+ const stripeLinkMenuButton = showStripeLink ? /* @__PURE__ */ jsx63(
22542
22851
  StripeLinkButton,
22543
22852
  {
22544
22853
  onClick: () => setView("stripe_link"),
@@ -22586,11 +22895,13 @@ function DepositModal({
22586
22895
  connectExchangeMenuButton
22587
22896
  ].filter(Boolean);
22588
22897
  const cashMenuButtons = [
22898
+ // Stripe "Pay with Link" is intentionally listed first so it always sits
22899
+ // above "Deposit with Card".
22900
+ stripeLinkMenuButton,
22589
22901
  depositWithCardMenuButton,
22590
22902
  applePayMenuButton,
22591
22903
  cashAppMenuButton,
22592
- bankTransferMenuButton,
22593
- stripeLinkMenuButton
22904
+ bankTransferMenuButton
22594
22905
  ].filter(Boolean);
22595
22906
  const depositTabs = [
22596
22907
  { id: "crypto", label: "Use Crypto", icon: Bitcoin, buttons: cryptoMenuButtons },
@@ -22685,13 +22996,13 @@ function DepositModal({
22685
22996
  const stackedOptions = [
22686
22997
  transferCryptoMenuButton,
22687
22998
  connectWalletMenuButton,
22999
+ stripeLinkMenuButton,
22688
23000
  depositWithCardMenuButton,
22689
23001
  applePayMenuButton,
22690
23002
  payWithExchangeMenuButton,
22691
23003
  connectExchangeMenuButton,
22692
23004
  cashAppMenuButton,
22693
23005
  bankTransferMenuButton,
22694
- stripeLinkMenuButton,
22695
23006
  depositTrackerMenuButton
22696
23007
  ].filter(Boolean);
22697
23008
  return renderScrollableOptions(stackedOptions);
@@ -22707,410 +23018,461 @@ function DepositModal({
22707
23018
  {
22708
23019
  ref: hideOverlay ? containerCallbackRef : void 0,
22709
23020
  hideOverlay,
22710
- className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden ${hideOverlay ? `uf-p-6 uf-overflow-hidden ${themeClass}` : `uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[85vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${themeClass}`}`,
23021
+ className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden ${hideOverlay ? `uf-p-6 uf-overflow-hidden ${themeClass}` : `uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[85vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${// wallet_connect fills the full-height mobile sheet. DialogContent
23022
+ // is a grid, and its single auto row only *grows* to fill free
23023
+ // space (align-content: stretch) — it never shrinks below content,
23024
+ // so a long wallet list would balloon the row past the viewport and
23025
+ // push the footer off-screen instead of scrolling. Clamp the row to
23026
+ // the modal height with minmax(0,1fr) so the inner overflow-y-auto
23027
+ // list scrolls with the footer pinned. Reset to content-sized on
23028
+ // desktop (sm:) where the modal is auto-height and centered.
23029
+ view === "wallet_connect" ? "[grid-template-rows:minmax(0,1fr)] sm:[grid-template-rows:none]" : ""} ${themeClass}`}`,
22711
23030
  style: { backgroundColor: colors2.background },
22712
23031
  onPointerDownOutside: (e) => e.preventDefault(),
22713
23032
  onInteractOutside: (e) => e.preventDefault(),
22714
23033
  children: [
22715
23034
  /* @__PURE__ */ jsx63(DialogTitle, { className: "uf-sr-only", children: modalTitle || "Deposit" }),
22716
- /* @__PURE__ */ jsx63(ThemeStyleInjector, { children: view === "main" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-min-h-0 uf-max-h-full", children: [
22717
- /* @__PURE__ */ jsx63("div", { className: "uf-flex-shrink-0", children: /* @__PURE__ */ jsx63(
22718
- DepositHeader,
22719
- {
22720
- title: modalTitle || "Deposit",
22721
- showClose: !hideOverlay,
22722
- onClose: handleClose,
22723
- showBalance: showBalanceHeader,
22724
- balanceAddress: recipientAddress,
22725
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
22726
- balanceChainId: destinationChainId,
22727
- balanceTokenAddress: destinationTokenAddress,
22728
- projectName: projectConfig?.project_name,
22729
- publishableKey
22730
- }
22731
- ) }),
22732
- renderMainMenuBody(),
22733
- /* @__PURE__ */ jsx63("div", { className: "uf-flex-shrink-0", children: depositPoweredByFooter })
22734
- ] }) : view === "transfer" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
22735
- /* @__PURE__ */ jsx63(
22736
- DepositHeader,
22737
- {
22738
- title: transferCryptoTitle,
22739
- showBack: showBackTransfer,
22740
- onBack: handleBack,
22741
- onClose: handleClose,
22742
- showBalance: showBalanceHeader,
22743
- balanceAddress: recipientAddress,
22744
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
22745
- balanceChainId: destinationChainId,
22746
- balanceTokenAddress: destinationTokenAddress,
22747
- projectName: projectConfig?.project_name,
22748
- publishableKey
22749
- }
22750
- ),
22751
- /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
22752
- standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ jsx63("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : transferInputVariant === "single_input" ? /* @__PURE__ */ jsx63(
22753
- TransferCryptoSingleInput,
22754
- {
22755
- userId,
22756
- publishableKey,
22757
- recipientAddress,
22758
- destinationChainType,
22759
- destinationChainId,
22760
- destinationTokenAddress,
22761
- defaultSourceChainType,
22762
- defaultSourceChainId,
22763
- defaultSourceTokenAddress,
22764
- defaultSourceSymbol,
22765
- depositConfirmationMode,
22766
- onExecutionsChange: setDepositExecutions,
22767
- onDepositSuccess: onDepositSuccessFor("transfer"),
22768
- onDepositError: onDepositErrorFor("transfer"),
22769
- wallets
22770
- }
22771
- ) : /* @__PURE__ */ jsx63(
22772
- TransferCryptoDoubleInput,
22773
- {
22774
- userId,
22775
- publishableKey,
22776
- recipientAddress,
22777
- destinationChainType,
22778
- destinationChainId,
22779
- destinationTokenAddress,
22780
- defaultSourceChainType,
22781
- defaultSourceChainId,
22782
- defaultSourceTokenAddress,
22783
- defaultSourceSymbol,
22784
- depositConfirmationMode,
22785
- onExecutionsChange: setDepositExecutions,
22786
- onDepositSuccess: onDepositSuccessFor("transfer"),
22787
- onDepositError: onDepositErrorFor("transfer"),
22788
- wallets
22789
- }
22790
- ),
22791
- depositPoweredByFooter
22792
- ] })
22793
- ] }) : view === "tracker" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
22794
- /* @__PURE__ */ jsx63(
22795
- DepositHeader,
22796
- {
22797
- title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
22798
- showBack: showBackTracker,
22799
- onBack: handleBack,
22800
- onClose: handleClose
22801
- }
22802
- ),
22803
- /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
22804
- /* @__PURE__ */ jsx63("div", { className: "uf-h-[460px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: selectedExecution ? /* @__PURE__ */ jsx63(DepositDetailContent, { execution: selectedExecution }) : /* @__PURE__ */ jsx63("div", { className: "uf-space-y-2 uf-pb-8", children: allExecutions.length === 0 ? /* @__PURE__ */ jsx63("div", { className: "uf-py-8 uf-px-4 uf-text-center", children: /* @__PURE__ */ jsx63(
22805
- "div",
22806
- {
22807
- className: "uf-text-sm",
22808
- style: {
22809
- color: components.container.subtitleColor,
22810
- fontFamily: fonts.regular
22811
- },
22812
- children: "No deposits yet"
22813
- }
22814
- ) }) : allExecutions.map((execution) => /* @__PURE__ */ jsx63(
22815
- DepositExecutionItem,
22816
- {
22817
- execution,
22818
- onClick: () => setSelectedExecution(execution)
22819
- },
22820
- execution.id
22821
- )) }) }),
22822
- depositPoweredByFooter
22823
- ] })
22824
- ] }) : view === "card" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
22825
- /* @__PURE__ */ jsx63(
22826
- DepositHeader,
22827
- {
22828
- title: cardView === "quotes" ? t8.quotes : depositWithCardTitle,
22829
- showBack: showBackCard,
22830
- onBack: handleBack,
22831
- onClose: handleClose,
22832
- badge: cardView === "quotes" ? { count: quotesCount } : void 0,
22833
- showBalance: showBalanceHeader,
22834
- balanceAddress: recipientAddress,
22835
- balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
22836
- balanceChainId: destinationChainId,
22837
- balanceTokenAddress: destinationTokenAddress,
22838
- projectName: projectConfig?.project_name,
22839
- publishableKey
22840
- }
22841
- ),
22842
- /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
22843
- standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ jsx63("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : !showFiatOnramp ? (
22844
- // Fiat on-ramp resolved hidden/disabled after a direct open
22845
- // (e.g. platform `is_hidden` for a Stripe Link-only project).
22846
- // Show a geo-restriction screen rather than the card UI so the
22847
- // hard-hide is honoured without a flash of "Pay with Card".
22848
- /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Card" })
22849
- ) : /* @__PURE__ */ jsx63(
22850
- BuyWithCard,
22851
- {
22852
- userId,
22853
- publishableKey,
22854
- view: cardView,
22855
- onViewChange: handleCardViewChange,
22856
- destinationTokenSymbol,
22857
- recipientAddress,
22858
- destinationChainType,
22859
- destinationChainId,
22860
- destinationTokenAddress,
22861
- onDepositSuccess: onDepositSuccessFor("card"),
22862
- onDepositError: onDepositErrorFor("card"),
22863
- onEvent,
22864
- themeClass,
22865
- wallets,
22866
- assetCdnUrl: projectConfig?.asset_cdn_url,
22867
- hideDepositFlowInfo,
22868
- hideDisplayDescription
22869
- }
22870
- ),
22871
- depositPoweredByFooter
22872
- ] })
22873
- ] }) : view === "exchange" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
22874
- /* @__PURE__ */ jsx63(
22875
- DepositHeader,
22876
- {
22877
- title: payWithExchangeTitle,
22878
- showBack: exchangeView === "pending" || sessionOpenedFromMenu,
22879
- onBack: handleBack,
22880
- onClose: handleClose
22881
- }
22882
- ),
22883
- /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
22884
- /* @__PURE__ */ jsx63(
22885
- PayWithExchange,
22886
- {
22887
- userId,
22888
- publishableKey,
22889
- exchanges,
22890
- view: exchangeView,
22891
- onViewChange: setExchangeView,
22892
- destinationTokenSymbol,
22893
- recipientAddress,
22894
- destinationChainType,
22895
- destinationChainId,
22896
- destinationTokenAddress,
22897
- onDepositSuccess: onDepositSuccessFor("pay_with_exchange"),
22898
- onDepositError: onDepositErrorFor("pay_with_exchange"),
22899
- wallets,
22900
- defaultToken: defaultToken ?? null
22901
- }
22902
- ),
22903
- depositPoweredByFooter
22904
- ] })
22905
- ] }) : view === "coinbase_connect" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
22906
- /* @__PURE__ */ jsx63(
22907
- CoinbaseConnect,
22908
- {
22909
- publishableKey,
22910
- userId,
22911
- wallets,
22912
- recipientAddress,
22913
- destinationTokenAddress: destinationTokenAddress ?? "",
22914
- destinationChainId: destinationChainId ?? "",
22915
- destinationChainType: destinationChainType ?? "",
22916
- onDepositSuccess: onDepositSuccessFor("exchange_connect"),
22917
- onDepositError: onDepositErrorFor("exchange_connect"),
22918
- onTransferError: (error) => {
22919
- onDepositErrorFor("exchange_connect")?.({
22920
- message: error.message,
22921
- error
22922
- });
22923
- },
22924
- onBack: handleBack,
22925
- onClose: handleClose,
22926
- onDisconnect: handleExchangeDisconnect,
22927
- skipToHoldings: coinbaseSkipToHoldings,
22928
- canGoBack: sessionOpenedFromMenu,
22929
- onExecutionsChange: setDepositExecutions,
22930
- defaultSourceChainType,
22931
- defaultSourceChainId,
22932
- defaultSourceTokenAddress,
22933
- defaultSourceSymbol
22934
- }
22935
- ),
22936
- depositPoweredByFooter
22937
- ] }) : view === "wallet_connect" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
22938
- /* @__PURE__ */ jsx63(
22939
- WalletConnect,
22940
- {
22941
- walletInfo: browserWalletInfo ?? void 0,
22942
- depositWallet: browserWalletInfo?.depositWallet ?? void 0,
22943
- wallets,
22944
- userId,
22945
- publishableKey,
22946
- assetCdnUrl: projectConfig?.asset_cdn_url,
22947
- projectName: projectConfig?.project_name,
22948
- onError: (error) => {
22949
- onDepositErrorFor("wallet_connect")?.({
22950
- message: error.message,
22951
- error
22952
- });
22953
- },
22954
- onDepositSuccess: onDepositSuccessFor("wallet_connect"),
22955
- onDepositError: onDepositErrorFor("wallet_connect"),
22956
- amountQuickSelect: browserWalletAmountQuickSelect,
22957
- onWalletDisconnect: handleWalletDisconnect,
22958
- onWalletConnected: (info, dw) => {
22959
- setBrowserWalletInfo({ ...info, depositWallet: dw });
22960
- setStoredWalletState(info.type);
22961
- setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
22962
- },
22963
- onBack: handleBack,
22964
- onClose: handleClose,
22965
- defaultSourceChainType,
22966
- defaultSourceChainId,
22967
- defaultSourceTokenAddress,
22968
- defaultSourceSymbol,
22969
- canGoBack: sessionOpenedFromMenu,
22970
- depositWalletsLoading: walletsLoading
22971
- }
22972
- ),
22973
- depositPoweredByFooter
22974
- ] }) : view === "bank_transfer" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
22975
- /* @__PURE__ */ jsx63(
22976
- DepositHeader,
22977
- {
22978
- title: t8.bankTransfer.title,
22979
- showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
22980
- onBack: handleBack,
22981
- onClose: handleClose
22982
- }
22983
- ),
22984
- /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
22985
- bankTransferProvidersLoading ? /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" }) : !hasEnabledBankTransferProvider ? /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Bank Transfer" }) : /* @__PURE__ */ jsx63(
22986
- BankTransfer,
22987
- {
22988
- userId,
22989
- publishableKey,
22990
- view: bankTransferView,
22991
- onViewChange: setBankTransferView,
22992
- recipientAddress,
22993
- destinationChainType,
22994
- destinationChainId,
22995
- destinationTokenAddress,
22996
- destinationTokenSymbol,
22997
- wallets,
22998
- defaultToken: defaultToken ?? null,
22999
- assetCdnUrl: projectConfig?.asset_cdn_url,
23000
- onEvent,
23001
- onDepositSuccess,
23002
- onDepositError
23003
- }
23004
- ),
23005
- depositPoweredByFooter
23006
- ] })
23007
- ] }) : view === "stripe_link" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23008
- /* @__PURE__ */ jsx63(
23009
- DepositHeader,
23010
- {
23011
- title: "Deposit with Link",
23012
- showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
23013
- onBack: handleBack,
23014
- showClose: stripeLinkStep !== "checkout",
23015
- onClose: handleClose
23016
- }
23017
- ),
23018
- /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23019
- /* @__PURE__ */ jsx63(
23020
- PayWithStripeLink,
23021
- {
23022
- userId,
23023
- publishableKey,
23024
- recipientAddress,
23025
- destinationChainType,
23026
- destinationChainId,
23027
- destinationTokenAddress,
23028
- wallets,
23029
- email: userEmail,
23030
- iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/link.svg` : void 0,
23031
- step: stripeLinkStep,
23032
- onStepChange: setStripeLinkStep,
23033
- backHandlerRef: stripeLinkBackRef,
23034
- onDepositSuccess,
23035
- onDepositError
23036
- }
23037
- ),
23038
- depositPoweredByFooter
23039
- ] })
23040
- ] }) : view === "cashapp" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23041
- /* @__PURE__ */ jsx63(
23042
- DepositHeader,
23043
- {
23044
- title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
23045
- showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
23046
- onBack: handleBack,
23047
- onClose: handleClose
23048
- }
23049
- ),
23050
- /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23051
- /* @__PURE__ */ jsx63(
23052
- PayWithCashApp,
23053
- {
23054
- userId,
23055
- publishableKey,
23056
- recipientAddress,
23057
- destinationChainType,
23058
- destinationChainId,
23059
- destinationTokenAddress,
23060
- cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
23061
- view: cashAppView,
23062
- onViewChange: setCashAppView,
23063
- onAmountChange: setCashAppAmount,
23064
- onEvent,
23065
- onDepositSuccess: onDepositSuccessFor("cashapp"),
23066
- onDepositError: onDepositErrorFor("cashapp"),
23067
- wallets
23068
- }
23069
- ),
23070
- depositPoweredByFooter
23071
- ] })
23072
- ] }) : view === "apple_pay" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23073
- /* @__PURE__ */ jsx63(
23074
- DepositHeader,
23075
- {
23076
- title: applePayHeaderTitle,
23077
- showBack: applePayShowBack,
23078
- onBack: () => {
23079
- const handled = applePayHandleRef.current?.requestBack() ?? false;
23080
- if (!handled) handleBack();
23081
- },
23082
- onClose: handleClose
23083
- }
23084
- ),
23085
- /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23086
- applePayProvidersLoading ? /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" }) : !hasEnabledApplePayProvider ? /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Apple Pay" }) : /* @__PURE__ */ jsx63(
23087
- BuyWithApplePay,
23088
- {
23089
- ref: applePayHandleRef,
23090
- userId,
23091
- publishableKey,
23092
- destinationChainType,
23093
- destinationChainId,
23094
- destinationTokenAddress,
23095
- userEmail,
23096
- wallets,
23097
- onViewChange: setApplePayView,
23098
- onEvent,
23099
- onDepositSuccess: onDepositSuccessFor("apple_pay"),
23100
- onDepositError: onDepositErrorFor("apple_pay"),
23101
- exitLabel: sessionOpenedFromMenu ? "Return" : "Close",
23102
- onExit: () => {
23103
- if (sessionOpenedFromMenu) {
23104
- setView("main");
23105
- } else {
23106
- handleClose();
23035
+ /* @__PURE__ */ jsx63(
23036
+ ThemeStyleInjector,
23037
+ {
23038
+ className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
23039
+ children: view === "main" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-min-h-0 uf-max-h-full", children: [
23040
+ /* @__PURE__ */ jsx63("div", { className: "uf-flex-shrink-0", children: /* @__PURE__ */ jsx63(
23041
+ DepositHeader,
23042
+ {
23043
+ title: modalTitle || "Deposit",
23044
+ showClose: !hideOverlay,
23045
+ onClose: handleClose,
23046
+ showBalance: showBalanceHeader,
23047
+ balanceAddress: recipientAddress,
23048
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
23049
+ balanceChainId: destinationChainId,
23050
+ balanceTokenAddress: destinationTokenAddress,
23051
+ projectName: projectConfig?.project_name,
23052
+ publishableKey
23053
+ }
23054
+ ) }),
23055
+ renderMainMenuBody(),
23056
+ /* @__PURE__ */ jsx63("div", { className: "uf-flex-shrink-0", children: depositPoweredByFooter })
23057
+ ] }) : view === "transfer" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23058
+ /* @__PURE__ */ jsx63(
23059
+ DepositHeader,
23060
+ {
23061
+ title: transferCryptoTitle,
23062
+ showBack: showBackTransfer,
23063
+ onBack: handleBack,
23064
+ onClose: handleClose,
23065
+ showBalance: showBalanceHeader,
23066
+ balanceAddress: recipientAddress,
23067
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
23068
+ balanceChainId: destinationChainId,
23069
+ balanceTokenAddress: destinationTokenAddress,
23070
+ projectName: projectConfig?.project_name,
23071
+ publishableKey
23072
+ }
23073
+ ),
23074
+ /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23075
+ standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ jsx63("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : transferInputVariant === "single_input" ? /* @__PURE__ */ jsx63(
23076
+ TransferCryptoSingleInput,
23077
+ {
23078
+ userId,
23079
+ publishableKey,
23080
+ recipientAddress,
23081
+ destinationChainType,
23082
+ destinationChainId,
23083
+ destinationTokenAddress,
23084
+ defaultSourceChainType,
23085
+ defaultSourceChainId,
23086
+ defaultSourceTokenAddress,
23087
+ defaultSourceSymbol,
23088
+ prefilledAmountUsd: normalizedPrefilledAmountUsd,
23089
+ depositConfirmationMode,
23090
+ onExecutionsChange: setDepositExecutions,
23091
+ onDepositSuccess: onDepositSuccessFor("transfer"),
23092
+ onDepositError: onDepositErrorFor("transfer"),
23093
+ wallets
23094
+ }
23095
+ ) : /* @__PURE__ */ jsx63(
23096
+ TransferCryptoDoubleInput,
23097
+ {
23098
+ userId,
23099
+ publishableKey,
23100
+ recipientAddress,
23101
+ destinationChainType,
23102
+ destinationChainId,
23103
+ destinationTokenAddress,
23104
+ defaultSourceChainType,
23105
+ defaultSourceChainId,
23106
+ defaultSourceTokenAddress,
23107
+ defaultSourceSymbol,
23108
+ prefilledAmountUsd: normalizedPrefilledAmountUsd,
23109
+ depositConfirmationMode,
23110
+ onExecutionsChange: setDepositExecutions,
23111
+ onDepositSuccess: onDepositSuccessFor("transfer"),
23112
+ onDepositError: onDepositErrorFor("transfer"),
23113
+ wallets
23107
23114
  }
23115
+ ),
23116
+ depositPoweredByFooter
23117
+ ] })
23118
+ ] }) : view === "tracker" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23119
+ /* @__PURE__ */ jsx63(
23120
+ DepositHeader,
23121
+ {
23122
+ title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
23123
+ showBack: showBackTracker,
23124
+ onBack: handleBack,
23125
+ onClose: handleClose
23108
23126
  }
23109
- }
23110
- ),
23111
- depositPoweredByFooter
23112
- ] })
23113
- ] }) : null })
23127
+ ),
23128
+ /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23129
+ /* @__PURE__ */ jsx63("div", { className: "uf-h-[460px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: selectedExecution ? /* @__PURE__ */ jsx63(DepositDetailContent, { execution: selectedExecution }) : /* @__PURE__ */ jsx63("div", { className: "uf-space-y-2 uf-pb-8", children: allExecutions.length === 0 ? /* @__PURE__ */ jsx63("div", { className: "uf-py-8 uf-px-4 uf-text-center", children: /* @__PURE__ */ jsx63(
23130
+ "div",
23131
+ {
23132
+ className: "uf-text-sm",
23133
+ style: {
23134
+ color: components.container.subtitleColor,
23135
+ fontFamily: fonts.regular
23136
+ },
23137
+ children: "No deposits yet"
23138
+ }
23139
+ ) }) : allExecutions.map((execution) => /* @__PURE__ */ jsx63(
23140
+ DepositExecutionItem,
23141
+ {
23142
+ execution,
23143
+ onClick: () => setSelectedExecution(execution)
23144
+ },
23145
+ execution.id
23146
+ )) }) }),
23147
+ depositPoweredByFooter
23148
+ ] })
23149
+ ] }) : view === "card" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23150
+ /* @__PURE__ */ jsx63(
23151
+ DepositHeader,
23152
+ {
23153
+ title: cardView === "quotes" ? t8.quotes : depositWithCardTitle,
23154
+ showBack: showBackCard,
23155
+ onBack: handleBack,
23156
+ onClose: handleClose,
23157
+ badge: cardView === "quotes" ? { count: quotesCount } : void 0,
23158
+ showBalance: showBalanceHeader,
23159
+ balanceAddress: recipientAddress,
23160
+ balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
23161
+ balanceChainId: destinationChainId,
23162
+ balanceTokenAddress: destinationTokenAddress,
23163
+ projectName: projectConfig?.project_name,
23164
+ publishableKey
23165
+ }
23166
+ ),
23167
+ /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23168
+ standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ jsx63("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : !showFiatOnramp ? (
23169
+ // Fiat on-ramp resolved hidden/disabled after a direct open
23170
+ // (e.g. platform `is_hidden` for a Stripe Link-only project).
23171
+ // Show a geo-restriction screen rather than the card UI so the
23172
+ // hard-hide is honoured without a flash of "Pay with Card".
23173
+ /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Card" })
23174
+ ) : /* @__PURE__ */ jsx63(
23175
+ BuyWithCard,
23176
+ {
23177
+ userId,
23178
+ publishableKey,
23179
+ view: cardView,
23180
+ onViewChange: handleCardViewChange,
23181
+ destinationTokenSymbol,
23182
+ recipientAddress,
23183
+ destinationChainType,
23184
+ destinationChainId,
23185
+ destinationTokenAddress,
23186
+ onDepositSuccess: onDepositSuccessFor("card"),
23187
+ onDepositError: onDepositErrorFor("card"),
23188
+ onEvent,
23189
+ themeClass,
23190
+ wallets,
23191
+ assetCdnUrl: projectConfig?.asset_cdn_url,
23192
+ hideDepositFlowInfo,
23193
+ hideDisplayDescription,
23194
+ prefilledAmountUsd: normalizedPrefilledAmountUsd
23195
+ }
23196
+ ),
23197
+ depositPoweredByFooter
23198
+ ] })
23199
+ ] }) : view === "exchange" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23200
+ /* @__PURE__ */ jsx63(
23201
+ DepositHeader,
23202
+ {
23203
+ title: payWithExchangeTitle,
23204
+ showBack: exchangeView === "pending" || sessionOpenedFromMenu,
23205
+ onBack: handleBack,
23206
+ onClose: handleClose
23207
+ }
23208
+ ),
23209
+ /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23210
+ /* @__PURE__ */ jsx63(
23211
+ PayWithExchange,
23212
+ {
23213
+ userId,
23214
+ publishableKey,
23215
+ exchanges,
23216
+ view: exchangeView,
23217
+ onViewChange: setExchangeView,
23218
+ destinationTokenSymbol,
23219
+ recipientAddress,
23220
+ destinationChainType,
23221
+ destinationChainId,
23222
+ destinationTokenAddress,
23223
+ onDepositSuccess: onDepositSuccessFor("pay_with_exchange"),
23224
+ onDepositError: onDepositErrorFor("pay_with_exchange"),
23225
+ wallets,
23226
+ defaultToken: defaultToken ?? null
23227
+ }
23228
+ ),
23229
+ depositPoweredByFooter
23230
+ ] })
23231
+ ] }) : view === "coinbase_connect" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23232
+ /* @__PURE__ */ jsx63(
23233
+ CoinbaseConnect,
23234
+ {
23235
+ publishableKey,
23236
+ userId,
23237
+ wallets,
23238
+ recipientAddress,
23239
+ destinationTokenAddress: destinationTokenAddress ?? "",
23240
+ destinationChainId: destinationChainId ?? "",
23241
+ destinationChainType: destinationChainType ?? "",
23242
+ onDepositSuccess: onDepositSuccessFor("exchange_connect"),
23243
+ onDepositError: onDepositErrorFor("exchange_connect"),
23244
+ onTransferError: (error) => {
23245
+ onDepositErrorFor("exchange_connect")?.({
23246
+ message: error.message,
23247
+ error
23248
+ });
23249
+ },
23250
+ onBack: handleBack,
23251
+ onClose: handleClose,
23252
+ onDisconnect: handleExchangeDisconnect,
23253
+ skipToHoldings: coinbaseSkipToHoldings,
23254
+ canGoBack: sessionOpenedFromMenu,
23255
+ onExecutionsChange: setDepositExecutions,
23256
+ defaultSourceChainType,
23257
+ defaultSourceChainId,
23258
+ defaultSourceTokenAddress,
23259
+ defaultSourceSymbol,
23260
+ prefilledAmountUsd: normalizedPrefilledAmountUsd
23261
+ }
23262
+ ),
23263
+ depositPoweredByFooter
23264
+ ] }) : view === "wallet_connect" ? (
23265
+ // Mobile: flex-fill the full-height dialog body so the wallet list
23266
+ // can grow and scroll, with the footer pinned to the bottom.
23267
+ // Desktop (sm:): stays content-sized.
23268
+ /* @__PURE__ */ jsxs57(
23269
+ "div",
23270
+ {
23271
+ className: "uf-flex uf-flex-col uf-gap-1.5 uf-min-h-0 uf-flex-1 sm:uf-flex-none",
23272
+ children: [
23273
+ /* @__PURE__ */ jsx63(
23274
+ WalletConnect,
23275
+ {
23276
+ walletInfo: browserWalletInfo ?? void 0,
23277
+ depositWallet: browserWalletInfo?.depositWallet ?? void 0,
23278
+ wallets,
23279
+ userId,
23280
+ publishableKey,
23281
+ assetCdnUrl: projectConfig?.asset_cdn_url,
23282
+ projectName: projectConfig?.project_name,
23283
+ onError: (error) => {
23284
+ onDepositErrorFor("wallet_connect")?.({
23285
+ message: error.message,
23286
+ error
23287
+ });
23288
+ },
23289
+ onDepositSuccess: onDepositSuccessFor("wallet_connect"),
23290
+ onDepositError: onDepositErrorFor("wallet_connect"),
23291
+ amountQuickSelect: browserWalletAmountQuickSelect,
23292
+ prefilledAmountUsd: normalizedPrefilledAmountUsd,
23293
+ onWalletDisconnect: handleWalletDisconnect,
23294
+ onWalletConnected: (info, dw) => {
23295
+ setBrowserWalletInfo({ ...info, depositWallet: dw });
23296
+ setStoredWalletState(info.type);
23297
+ setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
23298
+ },
23299
+ onBack: handleBack,
23300
+ onClose: handleClose,
23301
+ defaultSourceChainType,
23302
+ defaultSourceChainId,
23303
+ defaultSourceTokenAddress,
23304
+ defaultSourceSymbol,
23305
+ canGoBack: sessionOpenedFromMenu,
23306
+ depositWalletsLoading: walletsLoading
23307
+ }
23308
+ ),
23309
+ depositPoweredByFooter
23310
+ ]
23311
+ }
23312
+ )
23313
+ ) : view === "bank_transfer" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23314
+ /* @__PURE__ */ jsx63(
23315
+ DepositHeader,
23316
+ {
23317
+ title: t8.bankTransfer.title,
23318
+ showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
23319
+ onBack: handleBack,
23320
+ onClose: handleClose
23321
+ }
23322
+ ),
23323
+ /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23324
+ bankTransferProvidersLoading ? /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" }) : !hasEnabledBankTransferProvider ? /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Bank Transfer" }) : /* @__PURE__ */ jsx63(
23325
+ BankTransfer,
23326
+ {
23327
+ userId,
23328
+ publishableKey,
23329
+ view: bankTransferView,
23330
+ onViewChange: setBankTransferView,
23331
+ recipientAddress,
23332
+ destinationChainType,
23333
+ destinationChainId,
23334
+ destinationTokenAddress,
23335
+ destinationTokenSymbol,
23336
+ wallets,
23337
+ defaultToken: defaultToken ?? null,
23338
+ assetCdnUrl: projectConfig?.asset_cdn_url,
23339
+ onEvent,
23340
+ onDepositSuccess,
23341
+ onDepositError,
23342
+ prefilledAmountUsd: normalizedPrefilledAmountUsd
23343
+ }
23344
+ ),
23345
+ depositPoweredByFooter
23346
+ ] })
23347
+ ] }) : view === "stripe_link" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23348
+ /* @__PURE__ */ jsx63(
23349
+ DepositHeader,
23350
+ {
23351
+ title: "Deposit with Link",
23352
+ showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
23353
+ onBack: handleBack,
23354
+ showClose: stripeLinkStep !== "checkout" && stripeLinkStep !== "auth",
23355
+ onClose: handleClose
23356
+ }
23357
+ ),
23358
+ /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23359
+ isLoadingIp ? (
23360
+ // Hold the geo decision until IP resolves so we don't mount
23361
+ // PayWithStripeLink (which kicks off config/OAuth work) for a
23362
+ // deep-link user who turns out to be outside the US.
23363
+ /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" })
23364
+ ) : !showStripeLink ? (
23365
+ // Stripe Link's crypto on-ramp is US-only. On a direct open
23366
+ // (initialScreen="stripe_link") the row isn't in a menu to
23367
+ // fall back to, so show a geo-restriction screen rather than
23368
+ // the Link UI.
23369
+ /* @__PURE__ */ jsx63(
23370
+ GeoRestrictionScreen,
23371
+ {
23372
+ methodName: t8.stripeLink.title,
23373
+ message: "Pay with Link is only available in the US."
23374
+ }
23375
+ )
23376
+ ) : /* @__PURE__ */ jsx63(
23377
+ PayWithStripeLink,
23378
+ {
23379
+ userId,
23380
+ publishableKey,
23381
+ recipientAddress,
23382
+ destinationChainType,
23383
+ destinationChainId,
23384
+ destinationTokenAddress,
23385
+ countryCode: userIpInfo?.alpha2,
23386
+ subdivisionCode: userIpInfo?.subdivisionCode ?? void 0,
23387
+ wallets,
23388
+ email: userEmail,
23389
+ iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/link.svg` : void 0,
23390
+ step: stripeLinkStep,
23391
+ onStepChange: setStripeLinkStep,
23392
+ backHandlerRef: stripeLinkBackRef,
23393
+ onDepositSuccess,
23394
+ onDepositError
23395
+ }
23396
+ ),
23397
+ depositPoweredByFooter
23398
+ ] })
23399
+ ] }) : view === "cashapp" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23400
+ /* @__PURE__ */ jsx63(
23401
+ DepositHeader,
23402
+ {
23403
+ title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
23404
+ showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
23405
+ onBack: handleBack,
23406
+ onClose: handleClose
23407
+ }
23408
+ ),
23409
+ /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23410
+ /* @__PURE__ */ jsx63(
23411
+ PayWithCashApp,
23412
+ {
23413
+ userId,
23414
+ publishableKey,
23415
+ recipientAddress,
23416
+ destinationChainType,
23417
+ destinationChainId,
23418
+ destinationTokenAddress,
23419
+ cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
23420
+ view: cashAppView,
23421
+ onViewChange: setCashAppView,
23422
+ onAmountChange: setCashAppAmount,
23423
+ onEvent,
23424
+ onDepositSuccess: onDepositSuccessFor("cashapp"),
23425
+ onDepositError: onDepositErrorFor("cashapp"),
23426
+ prefilledAmountUsd: normalizedPrefilledAmountUsd,
23427
+ wallets
23428
+ }
23429
+ ),
23430
+ depositPoweredByFooter
23431
+ ] })
23432
+ ] }) : view === "apple_pay" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
23433
+ /* @__PURE__ */ jsx63(
23434
+ DepositHeader,
23435
+ {
23436
+ title: applePayHeaderTitle,
23437
+ showBack: applePayShowBack,
23438
+ onBack: () => {
23439
+ const handled = applePayHandleRef.current?.requestBack() ?? false;
23440
+ if (!handled) handleBack();
23441
+ },
23442
+ onClose: handleClose
23443
+ }
23444
+ ),
23445
+ /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23446
+ applePayProvidersLoading ? /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" }) : !hasEnabledApplePayProvider ? /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Apple Pay" }) : /* @__PURE__ */ jsx63(
23447
+ BuyWithApplePay,
23448
+ {
23449
+ ref: applePayHandleRef,
23450
+ userId,
23451
+ publishableKey,
23452
+ destinationChainType,
23453
+ destinationChainId,
23454
+ destinationTokenAddress,
23455
+ userEmail,
23456
+ wallets,
23457
+ onViewChange: setApplePayView,
23458
+ onEvent,
23459
+ onDepositSuccess: onDepositSuccessFor("apple_pay"),
23460
+ onDepositError: onDepositErrorFor("apple_pay"),
23461
+ exitLabel: sessionOpenedFromMenu ? "Return" : "Close",
23462
+ onExit: () => {
23463
+ if (sessionOpenedFromMenu) {
23464
+ setView("main");
23465
+ } else {
23466
+ handleClose();
23467
+ }
23468
+ }
23469
+ }
23470
+ ),
23471
+ depositPoweredByFooter
23472
+ ] })
23473
+ ] }) : null
23474
+ }
23475
+ )
23114
23476
  ]
23115
23477
  }
23116
23478
  )
@@ -23119,7 +23481,7 @@ function DepositModal({
23119
23481
  }
23120
23482
 
23121
23483
  // src/components/checkout/CheckoutModal.tsx
23122
- import { useState as useState41, useEffect as useEffect35, useLayoutEffect as useLayoutEffect3, useCallback as useCallback9, useRef as useRef13, useMemo as useMemo14 } from "react";
23484
+ import { useState as useState41, useEffect as useEffect35, useLayoutEffect as useLayoutEffect3, useCallback as useCallback11, useRef as useRef14, useMemo as useMemo15 } from "react";
23123
23485
  import { AlertTriangle as AlertTriangle4, ChevronRight as ChevronRight19 } from "lucide-react";
23124
23486
 
23125
23487
  // src/hooks/use-payment-intent.ts
@@ -23218,11 +23580,11 @@ function CheckoutModal({
23218
23580
  }) {
23219
23581
  const { colors: colors2, fonts, components } = useTheme();
23220
23582
  const [view, setView] = useState41("main");
23221
- const resetViewTimeoutRef = useRef13(null);
23583
+ const resetViewTimeoutRef = useRef14(null);
23222
23584
  const [browserWalletInfo, setBrowserWalletInfo] = useState41(null);
23223
23585
  const [browserWalletChainType, setBrowserWalletChainType] = useState41(() => getStoredWalletState()?.chainType);
23224
- const lastCheckoutMethodRef = useRef13(void 0);
23225
- const emitCheckoutSuccess = useCallback9(
23586
+ const lastCheckoutMethodRef = useRef14(void 0);
23587
+ const emitCheckoutSuccess = useCallback11(
23226
23588
  (data, method) => {
23227
23589
  const isSucceeded = data.status === "succeeded";
23228
23590
  const richIntent = isSucceeded && data.paymentIntent ? mapToCheckoutPaymentIntent(data.paymentIntent) : void 0;
@@ -23285,7 +23647,7 @@ function CheckoutModal({
23285
23647
  setView("main");
23286
23648
  }
23287
23649
  }, [showConnectWallet, showTransferCrypto, view]);
23288
- const prevStatusRef = useRef13(null);
23650
+ const prevStatusRef = useRef14(null);
23289
23651
  useEffect35(() => {
23290
23652
  if (!paymentIntent) return;
23291
23653
  const prev = prevStatusRef.current;
@@ -23304,11 +23666,11 @@ function CheckoutModal({
23304
23666
  );
23305
23667
  }
23306
23668
  }, [emitCheckoutSuccess, paymentIntent, view]);
23307
- const wallets = useMemo14(() => {
23669
+ const wallets = useMemo15(() => {
23308
23670
  if (!paymentIntent) return [];
23309
23671
  return mapDepositAddressesToWallets(paymentIntent.deposit_addresses, paymentIntent);
23310
23672
  }, [paymentIntent]);
23311
- const formatCryptoAmount = useMemo14(() => {
23673
+ const formatCryptoAmount = useMemo15(() => {
23312
23674
  if (!paymentIntent) return (_) => "";
23313
23675
  const decimals = paymentIntent.destination_token_decimals ?? 6;
23314
23676
  const symbol = paymentIntent.currency.toUpperCase();
@@ -23318,7 +23680,7 @@ function CheckoutModal({
23318
23680
  return `${formatted} ${symbol}`;
23319
23681
  };
23320
23682
  }, [paymentIntent]);
23321
- const remainingAmountUsd = useMemo14(() => {
23683
+ const remainingAmountUsd = useMemo15(() => {
23322
23684
  if (!paymentIntent) return void 0;
23323
23685
  const total = parseFloat(paymentIntent.destination_amount_usd || paymentIntent.amount_usd);
23324
23686
  const received = parseFloat(
@@ -23330,7 +23692,7 @@ function CheckoutModal({
23330
23692
  return remaining > 0 ? remaining.toFixed(2) : "0.00";
23331
23693
  }, [paymentIntent]);
23332
23694
  const [selectedSource, setSelectedSource] = useState41(null);
23333
- const remainingDestinationAmount = useMemo14(() => {
23695
+ const remainingDestinationAmount = useMemo15(() => {
23334
23696
  if (!paymentIntent) return "0";
23335
23697
  const remaining = BigInt(paymentIntent.destination_amount) - BigInt(paymentIntent.destination_amount_received);
23336
23698
  return remaining > 0n ? remaining.toString() : "0";
@@ -23352,7 +23714,7 @@ function CheckoutModal({
23352
23714
  stablecoinParity: paymentIntent?.stablecoin_parity ?? false,
23353
23715
  enabled: open && view === "transfer" && !!paymentIntent && !!selectedSource && remainingDestinationAmount !== "0"
23354
23716
  });
23355
- const effectiveCheckoutQuote = useMemo14(() => {
23717
+ const effectiveCheckoutQuote = useMemo15(() => {
23356
23718
  if (!sourceQuote || !selectedSource) return null;
23357
23719
  const baseQuote = {
23358
23720
  sourceAmount: sourceQuote.source_amount,
@@ -23373,7 +23735,7 @@ function CheckoutModal({
23373
23735
  sourceAmountUsd: minUsd.toFixed(2)
23374
23736
  };
23375
23737
  }, [sourceQuote, selectedSource]);
23376
- const handleBrowserWalletClick = useCallback9(
23738
+ const handleBrowserWalletClick = useCallback11(
23377
23739
  (walletInfo) => {
23378
23740
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
23379
23741
  setStoredWalletState(walletInfo.type);
@@ -23396,19 +23758,19 @@ function CheckoutModal({
23396
23758
  },
23397
23759
  [wallets, onCheckoutError]
23398
23760
  );
23399
- const handleWalletConnectClick = useCallback9(() => {
23761
+ const handleWalletConnectClick = useCallback11(() => {
23400
23762
  setBrowserWalletInfo(null);
23401
23763
  lastCheckoutMethodRef.current = "wallet_connect";
23402
23764
  setView("wallet_connect");
23403
23765
  }, []);
23404
- const handleWalletDisconnect = useCallback9(() => {
23766
+ const handleWalletDisconnect = useCallback11(() => {
23405
23767
  setUserDisconnectedWallet(true);
23406
23768
  clearStoredWalletState();
23407
23769
  setBrowserWalletChainType(void 0);
23408
23770
  setBrowserWalletInfo(null);
23409
23771
  setView("main");
23410
23772
  }, []);
23411
- const handleClose = useCallback9(() => {
23773
+ const handleClose = useCallback11(() => {
23412
23774
  onOpenChange(false);
23413
23775
  if (resetViewTimeoutRef.current) {
23414
23776
  clearTimeout(resetViewTimeoutRef.current);
@@ -23438,7 +23800,7 @@ function CheckoutModal({
23438
23800
  },
23439
23801
  []
23440
23802
  );
23441
- const handleBack = useCallback9(() => {
23803
+ const handleBack = useCallback11(() => {
23442
23804
  setView("main");
23443
23805
  }, []);
23444
23806
  const poweredByFooter = /* @__PURE__ */ jsx64("div", { className: "uf-pt-3", children: /* @__PURE__ */ jsx64(
@@ -23564,259 +23926,281 @@ function CheckoutModal({
23564
23926
  return /* @__PURE__ */ jsx64(PortalContainerProvider, { value: null, children: /* @__PURE__ */ jsx64(Dialog, { open, onOpenChange: handleClose, modal: true, children: /* @__PURE__ */ jsx64(
23565
23927
  DialogContent,
23566
23928
  {
23567
- className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[60vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${themeClass}`,
23929
+ className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[60vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${// wallet_connect fills the full-height mobile sheet. DialogContent is a
23930
+ // grid whose single auto row only grows to fill free space and never
23931
+ // shrinks below content, so a long wallet list would balloon the row
23932
+ // past the viewport and push the footer off-screen. Clamp the row to
23933
+ // the modal height with minmax(0,1fr) so the inner overflow-y-auto list
23934
+ // scrolls with the footer pinned. Reset to content-sized on desktop.
23935
+ view === "wallet_connect" ? "[grid-template-rows:minmax(0,1fr)] sm:[grid-template-rows:none]" : ""} ${themeClass}`,
23568
23936
  style: { backgroundColor: colors2.background },
23569
23937
  onPointerDownOutside: (e) => e.preventDefault(),
23570
23938
  onInteractOutside: (e) => e.preventDefault(),
23571
- children: /* @__PURE__ */ jsx64(ThemeStyleInjector, { children: view === "main" ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
23572
- /* @__PURE__ */ jsx64(DepositHeader, { title: modalTitle || "Checkout", showClose: true, onClose: handleClose }),
23573
- /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23574
- piLoading ? /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-3", children: [
23575
- /* @__PURE__ */ jsx64(
23576
- "div",
23577
- {
23578
- className: "uf-rounded-xl uf-p-4 uf-animate-pulse",
23579
- style: {
23580
- backgroundColor: components.card.backgroundColor,
23581
- borderRadius: components.card.borderRadius,
23582
- border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
23583
- },
23584
- children: /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-items-center uf-gap-2", children: [
23585
- /* @__PURE__ */ jsx64(
23586
- "div",
23939
+ children: /* @__PURE__ */ jsx64(
23940
+ ThemeStyleInjector,
23941
+ {
23942
+ className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
23943
+ children: view === "main" ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
23944
+ /* @__PURE__ */ jsx64(DepositHeader, { title: modalTitle || "Checkout", showClose: true, onClose: handleClose }),
23945
+ /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23946
+ piLoading ? /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-3", children: [
23947
+ /* @__PURE__ */ jsx64(
23948
+ "div",
23949
+ {
23950
+ className: "uf-rounded-xl uf-p-4 uf-animate-pulse",
23951
+ style: {
23952
+ backgroundColor: components.card.backgroundColor,
23953
+ borderRadius: components.card.borderRadius,
23954
+ border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
23955
+ },
23956
+ children: /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-items-center uf-gap-2", children: [
23957
+ /* @__PURE__ */ jsx64(
23958
+ "div",
23959
+ {
23960
+ className: "uf-h-8 uf-w-24 uf-rounded",
23961
+ style: {
23962
+ backgroundColor: components.card.borderColor
23963
+ }
23964
+ }
23965
+ ),
23966
+ /* @__PURE__ */ jsx64(
23967
+ "div",
23968
+ {
23969
+ className: "uf-h-4 uf-w-16 uf-rounded",
23970
+ style: {
23971
+ backgroundColor: components.card.borderColor
23972
+ }
23973
+ }
23974
+ )
23975
+ ] })
23976
+ }
23977
+ ),
23978
+ /* @__PURE__ */ jsx64(SkeletonButton2, {}),
23979
+ /* @__PURE__ */ jsx64(SkeletonButton2, {})
23980
+ ] }) : piError ? /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
23981
+ /* @__PURE__ */ jsx64("div", { className: "uf-w-16 uf-h-16 uf-rounded-full uf-bg-muted uf-flex uf-items-center uf-justify-center uf-mb-4", children: /* @__PURE__ */ jsx64(AlertTriangle4, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
23982
+ /* @__PURE__ */ jsx64(
23983
+ "h3",
23984
+ {
23985
+ className: "uf-text-lg uf-font-semibold uf-mb-2",
23986
+ style: {
23987
+ color: colors2.foreground,
23988
+ fontFamily: fonts.semibold
23989
+ },
23990
+ children: "Unable to Load Checkout"
23991
+ }
23992
+ ),
23993
+ /* @__PURE__ */ jsx64(
23994
+ "p",
23995
+ {
23996
+ className: "uf-text-sm uf-max-w-[280px]",
23997
+ style: {
23998
+ color: colors2.foregroundMuted,
23999
+ fontFamily: fonts.regular
24000
+ },
24001
+ children: piError instanceof Error ? piError.message : "Something went wrong. Please try again."
24002
+ }
24003
+ )
24004
+ ] }) : paymentIntent ? /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-3", children: [
24005
+ progressSection,
24006
+ (paymentIntent.status === "requires_payment" || paymentIntent.status === "processing") && /* @__PURE__ */ jsxs58(Fragment15, { children: [
24007
+ showTransferCrypto && /* @__PURE__ */ jsx64(
24008
+ TransferCryptoButton,
23587
24009
  {
23588
- className: "uf-h-8 uf-w-24 uf-rounded",
23589
- style: {
23590
- backgroundColor: components.card.borderColor
23591
- }
24010
+ onClick: () => {
24011
+ lastCheckoutMethodRef.current = "transfer";
24012
+ setView("transfer");
24013
+ },
24014
+ title: i18n.checkoutModal.transferCrypto.title,
24015
+ subtitle: i18n.checkoutModal.transferCrypto.subtitle,
24016
+ featuredTokens: projectConfig?.transfer_crypto.networks
23592
24017
  }
23593
24018
  ),
23594
- /* @__PURE__ */ jsx64(
23595
- "div",
24019
+ showConnectWallet && /* @__PURE__ */ jsx64(
24020
+ BrowserWalletButton,
23596
24021
  {
23597
- className: "uf-h-4 uf-w-16 uf-rounded",
23598
- style: {
23599
- backgroundColor: components.card.borderColor
23600
- }
24022
+ onClick: handleBrowserWalletClick,
24023
+ onConnectClick: handleWalletConnectClick,
24024
+ onDisconnect: handleWalletDisconnect,
24025
+ chainType: browserWalletChainType,
24026
+ publishableKey,
24027
+ featuredWallets: projectConfig?.connect_wallet?.wallets,
24028
+ subtitle: i18n.checkoutModal.browserWallet.subtitle
23601
24029
  }
23602
24030
  )
23603
24031
  ] })
23604
- }
23605
- ),
23606
- /* @__PURE__ */ jsx64(SkeletonButton2, {}),
23607
- /* @__PURE__ */ jsx64(SkeletonButton2, {})
23608
- ] }) : piError ? /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
23609
- /* @__PURE__ */ jsx64("div", { className: "uf-w-16 uf-h-16 uf-rounded-full uf-bg-muted uf-flex uf-items-center uf-justify-center uf-mb-4", children: /* @__PURE__ */ jsx64(AlertTriangle4, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
24032
+ ] }) : null,
24033
+ poweredByFooter
24034
+ ] })
24035
+ ] }) : view === "transfer" ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
23610
24036
  /* @__PURE__ */ jsx64(
23611
- "h3",
24037
+ DepositHeader,
23612
24038
  {
23613
- className: "uf-text-lg uf-font-semibold uf-mb-2",
23614
- style: {
23615
- color: colors2.foreground,
23616
- fontFamily: fonts.semibold
23617
- },
23618
- children: "Unable to Load Checkout"
24039
+ title: modalTitle || "Checkout",
24040
+ showBack: true,
24041
+ onBack: handleBack,
24042
+ onClose: handleClose
23619
24043
  }
23620
24044
  ),
23621
- /* @__PURE__ */ jsx64(
23622
- "p",
23623
- {
23624
- className: "uf-text-sm uf-max-w-[280px]",
23625
- style: {
23626
- color: colors2.foregroundMuted,
23627
- fontFamily: fonts.regular
23628
- },
23629
- children: piError instanceof Error ? piError.message : "Something went wrong. Please try again."
23630
- }
23631
- )
23632
- ] }) : paymentIntent ? /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-3", children: [
23633
- progressSection,
23634
- (paymentIntent.status === "requires_payment" || paymentIntent.status === "processing") && /* @__PURE__ */ jsxs58(Fragment15, { children: [
23635
- showTransferCrypto && /* @__PURE__ */ jsx64(
23636
- TransferCryptoButton,
23637
- {
23638
- onClick: () => {
23639
- lastCheckoutMethodRef.current = "transfer";
23640
- setView("transfer");
23641
- },
23642
- title: i18n.checkoutModal.transferCrypto.title,
23643
- subtitle: i18n.checkoutModal.transferCrypto.subtitle,
23644
- featuredTokens: projectConfig?.transfer_crypto.networks
23645
- }
23646
- ),
23647
- showConnectWallet && /* @__PURE__ */ jsx64(
23648
- BrowserWalletButton,
23649
- {
23650
- onClick: handleBrowserWalletClick,
23651
- onConnectClick: handleWalletConnectClick,
23652
- onDisconnect: handleWalletDisconnect,
23653
- chainType: browserWalletChainType,
23654
- publishableKey,
23655
- featuredWallets: projectConfig?.connect_wallet?.wallets,
23656
- subtitle: i18n.checkoutModal.browserWallet.subtitle
23657
- }
23658
- )
23659
- ] })
23660
- ] }) : null,
23661
- poweredByFooter
23662
- ] })
23663
- ] }) : view === "transfer" ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
23664
- /* @__PURE__ */ jsx64(
23665
- DepositHeader,
23666
- {
23667
- title: modalTitle || "Checkout",
23668
- showBack: true,
23669
- onBack: handleBack,
23670
- onClose: handleClose
23671
- }
23672
- ),
23673
- /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23674
- paymentIntent ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
23675
- (() => {
23676
- const receivedUsd = parseFloat(
23677
- paymentIntent.destination_amount_received_usd || paymentIntent.amount_received_usd
23678
- );
23679
- const totalUsd = parseFloat(
23680
- paymentIntent.destination_amount_usd || paymentIntent.amount_usd
23681
- );
23682
- const pct = totalUsd > 0 ? Math.min(receivedUsd / totalUsd * 100, 100) : 0;
23683
- return /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-2", children: [
23684
- /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-items-center uf-justify-between", children: [
23685
- /* @__PURE__ */ jsx64(
23686
- "span",
23687
- {
23688
- className: "uf-text-xs",
23689
- style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
23690
- children: "Received"
23691
- }
23692
- ),
23693
- /* @__PURE__ */ jsxs58(
23694
- "span",
23695
- {
23696
- className: "uf-text-xs",
23697
- style: { color: colors2.foreground, fontFamily: fonts.medium },
23698
- children: [
23699
- "$",
23700
- receivedUsd.toFixed(2),
23701
- " / $",
23702
- totalUsd.toFixed(2)
23703
- ]
23704
- }
23705
- )
23706
- ] }),
23707
- /* @__PURE__ */ jsx64(
23708
- "div",
23709
- {
23710
- className: "uf-w-full uf-h-1.5 uf-rounded-full uf-overflow-hidden",
23711
- style: { backgroundColor: colors2.border },
23712
- children: /* @__PURE__ */ jsx64(
24045
+ /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
24046
+ paymentIntent ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
24047
+ (() => {
24048
+ const receivedUsd = parseFloat(
24049
+ paymentIntent.destination_amount_received_usd || paymentIntent.amount_received_usd
24050
+ );
24051
+ const totalUsd = parseFloat(
24052
+ paymentIntent.destination_amount_usd || paymentIntent.amount_usd
24053
+ );
24054
+ const pct = totalUsd > 0 ? Math.min(receivedUsd / totalUsd * 100, 100) : 0;
24055
+ return /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-2", children: [
24056
+ /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-items-center uf-justify-between", children: [
24057
+ /* @__PURE__ */ jsx64(
24058
+ "span",
24059
+ {
24060
+ className: "uf-text-xs",
24061
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
24062
+ children: "Received"
24063
+ }
24064
+ ),
24065
+ /* @__PURE__ */ jsxs58(
24066
+ "span",
24067
+ {
24068
+ className: "uf-text-xs",
24069
+ style: { color: colors2.foreground, fontFamily: fonts.medium },
24070
+ children: [
24071
+ "$",
24072
+ receivedUsd.toFixed(2),
24073
+ " / $",
24074
+ totalUsd.toFixed(2)
24075
+ ]
24076
+ }
24077
+ )
24078
+ ] }),
24079
+ /* @__PURE__ */ jsx64(
23713
24080
  "div",
23714
24081
  {
23715
- className: "uf-h-full uf-rounded-full uf-transition-all uf-duration-500",
23716
- style: {
23717
- width: `${pct}%`,
23718
- backgroundColor: paymentIntent.status === "succeeded" ? "rgb(34, 197, 94)" : colors2.primary
23719
- }
24082
+ className: "uf-w-full uf-h-1.5 uf-rounded-full uf-overflow-hidden",
24083
+ style: { backgroundColor: colors2.border },
24084
+ children: /* @__PURE__ */ jsx64(
24085
+ "div",
24086
+ {
24087
+ className: "uf-h-full uf-rounded-full uf-transition-all uf-duration-500",
24088
+ style: {
24089
+ width: `${pct}%`,
24090
+ backgroundColor: paymentIntent.status === "succeeded" ? "rgb(34, 197, 94)" : colors2.primary
24091
+ }
24092
+ }
24093
+ )
23720
24094
  }
23721
24095
  )
24096
+ ] });
24097
+ })(),
24098
+ /* @__PURE__ */ jsx64(
24099
+ TransferCryptoSingleInput,
24100
+ {
24101
+ userId: paymentIntent.user_id || "",
24102
+ publishableKey,
24103
+ clientSecret,
24104
+ recipientAddress: paymentIntent.recipient_address,
24105
+ destinationChainType: paymentIntent.destination_chain_type,
24106
+ destinationChainId: paymentIntent.destination_chain_id,
24107
+ destinationTokenAddress: paymentIntent.destination_token_address,
24108
+ defaultSourceChainType,
24109
+ defaultSourceChainId,
24110
+ defaultSourceTokenAddress,
24111
+ defaultSourceSymbol,
24112
+ depositConfirmationMode: "auto_ui",
24113
+ wallets,
24114
+ onSourceTokenChange: setSelectedSource,
24115
+ persistCheckingIndicator: true,
24116
+ productType: "payment",
24117
+ checkoutQuote: effectiveCheckoutQuote,
24118
+ isCheckoutQuoteLoading: isQuoteLoading || isQuoteFetching
23722
24119
  }
23723
24120
  )
23724
- ] });
23725
- })(),
23726
- /* @__PURE__ */ jsx64(
23727
- TransferCryptoSingleInput,
24121
+ ] }) : /* @__PURE__ */ jsx64(SkeletonButton2, {}),
24122
+ poweredByFooter
24123
+ ] })
24124
+ ] }) : view === "wallet_connect" && paymentIntent ? (
24125
+ // Mobile: flex-fill the full-height sheet so the wallet list grows and
24126
+ // scrolls with the footer pinned. Desktop (sm:): content-sized.
24127
+ /* @__PURE__ */ jsxs58(
24128
+ "div",
23728
24129
  {
23729
- userId: paymentIntent.user_id || "",
23730
- publishableKey,
23731
- clientSecret,
23732
- recipientAddress: paymentIntent.recipient_address,
23733
- destinationChainType: paymentIntent.destination_chain_type,
23734
- destinationChainId: paymentIntent.destination_chain_id,
23735
- destinationTokenAddress: paymentIntent.destination_token_address,
23736
- defaultSourceChainType,
23737
- defaultSourceChainId,
23738
- defaultSourceTokenAddress,
23739
- defaultSourceSymbol,
23740
- depositConfirmationMode: "auto_ui",
23741
- wallets,
23742
- onSourceTokenChange: setSelectedSource,
23743
- persistCheckingIndicator: true,
23744
- productType: "payment",
23745
- checkoutQuote: effectiveCheckoutQuote,
23746
- isCheckoutQuoteLoading: isQuoteLoading || isQuoteFetching
24130
+ className: "uf-flex uf-flex-col uf-gap-1.5 uf-min-h-0 uf-flex-1 sm:uf-flex-none",
24131
+ children: [
24132
+ /* @__PURE__ */ jsx64(
24133
+ WalletConnect,
24134
+ {
24135
+ walletInfo: browserWalletInfo ?? void 0,
24136
+ depositWallet: browserWalletInfo?.depositWallet ?? void 0,
24137
+ wallets,
24138
+ userId: paymentIntent.user_id || "",
24139
+ publishableKey,
24140
+ clientSecret,
24141
+ prefilledAmountUsd: remainingAmountUsd,
24142
+ checkoutAmountUsd: paymentIntent.amount_usd,
24143
+ checkoutReceivedUsd: paymentIntent.amount_received_usd,
24144
+ checkoutDestination: {
24145
+ chainType: paymentIntent.destination_chain_type,
24146
+ chainId: paymentIntent.destination_chain_id,
24147
+ tokenAddress: paymentIntent.destination_token_address,
24148
+ decimals: paymentIntent.destination_token_decimals ?? 6
24149
+ },
24150
+ productType: "payment",
24151
+ stablecoinParity: paymentIntent.stablecoin_parity ?? false,
24152
+ checkoutRemainingBaseUnits: (() => {
24153
+ const remaining = BigInt(paymentIntent.amount) - BigInt(paymentIntent.amount_received);
24154
+ return remaining > 0n ? remaining.toString() : "0";
24155
+ })(),
24156
+ onSuccess: (_txHash) => {
24157
+ emitCheckoutSuccess(
24158
+ {
24159
+ paymentIntentId: paymentIntent.id,
24160
+ status: "processing",
24161
+ paymentIntent
24162
+ },
24163
+ "wallet_connect"
24164
+ );
24165
+ },
24166
+ onError: (error) => {
24167
+ onCheckoutError?.({
24168
+ message: error.message,
24169
+ error,
24170
+ method: "wallet_connect"
24171
+ });
24172
+ },
24173
+ onWalletDisconnect: handleWalletDisconnect,
24174
+ onWalletConnected: (info, dw) => {
24175
+ setBrowserWalletInfo({ ...info, depositWallet: dw });
24176
+ setStoredWalletState(info.type);
24177
+ setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
24178
+ lastCheckoutMethodRef.current = "wallet_connect";
24179
+ },
24180
+ onNewDeposit: () => setView("main"),
24181
+ onDone: () => setView("main"),
24182
+ paymentIntentStatus: paymentIntent.status,
24183
+ onBack: handleBack,
24184
+ onClose: handleClose,
24185
+ defaultSourceChainType,
24186
+ defaultSourceChainId,
24187
+ defaultSourceTokenAddress,
24188
+ defaultSourceSymbol
24189
+ }
24190
+ ),
24191
+ poweredByFooter
24192
+ ]
23747
24193
  }
23748
24194
  )
23749
- ] }) : /* @__PURE__ */ jsx64(SkeletonButton2, {}),
23750
- poweredByFooter
23751
- ] })
23752
- ] }) : view === "wallet_connect" && paymentIntent ? /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
23753
- /* @__PURE__ */ jsx64(
23754
- WalletConnect,
23755
- {
23756
- walletInfo: browserWalletInfo ?? void 0,
23757
- depositWallet: browserWalletInfo?.depositWallet ?? void 0,
23758
- wallets,
23759
- userId: paymentIntent.user_id || "",
23760
- publishableKey,
23761
- clientSecret,
23762
- prefillAmountUsd: remainingAmountUsd,
23763
- checkoutAmountUsd: paymentIntent.amount_usd,
23764
- checkoutReceivedUsd: paymentIntent.amount_received_usd,
23765
- checkoutDestination: {
23766
- chainType: paymentIntent.destination_chain_type,
23767
- chainId: paymentIntent.destination_chain_id,
23768
- tokenAddress: paymentIntent.destination_token_address,
23769
- decimals: paymentIntent.destination_token_decimals ?? 6
23770
- },
23771
- productType: "payment",
23772
- stablecoinParity: paymentIntent.stablecoin_parity ?? false,
23773
- checkoutRemainingBaseUnits: (() => {
23774
- const remaining = BigInt(paymentIntent.amount) - BigInt(paymentIntent.amount_received);
23775
- return remaining > 0n ? remaining.toString() : "0";
23776
- })(),
23777
- onSuccess: (_txHash) => {
23778
- emitCheckoutSuccess(
23779
- {
23780
- paymentIntentId: paymentIntent.id,
23781
- status: "processing",
23782
- paymentIntent
23783
- },
23784
- "wallet_connect"
23785
- );
23786
- },
23787
- onError: (error) => {
23788
- onCheckoutError?.({
23789
- message: error.message,
23790
- error,
23791
- method: "wallet_connect"
23792
- });
23793
- },
23794
- onWalletDisconnect: handleWalletDisconnect,
23795
- onWalletConnected: (info, dw) => {
23796
- setBrowserWalletInfo({ ...info, depositWallet: dw });
23797
- setStoredWalletState(info.type);
23798
- setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
23799
- lastCheckoutMethodRef.current = "wallet_connect";
23800
- },
23801
- onNewDeposit: () => setView("main"),
23802
- onDone: () => setView("main"),
23803
- paymentIntentStatus: paymentIntent.status,
23804
- onBack: handleBack,
23805
- onClose: handleClose,
23806
- defaultSourceChainType,
23807
- defaultSourceChainId,
23808
- defaultSourceTokenAddress,
23809
- defaultSourceSymbol
23810
- }
23811
- ),
23812
- poweredByFooter
23813
- ] }) : null })
24195
+ ) : null
24196
+ }
24197
+ )
23814
24198
  }
23815
24199
  ) }) });
23816
24200
  }
23817
24201
 
23818
24202
  // src/components/withdrawals/WithdrawModal.tsx
23819
- import { useState as useState45, useEffect as useEffect39, useLayoutEffect as useLayoutEffect4, useCallback as useCallback11, useRef as useRef15 } from "react";
24203
+ import { useState as useState45, useEffect as useEffect39, useLayoutEffect as useLayoutEffect4, useCallback as useCallback13, useRef as useRef16 } from "react";
23820
24204
  import { AlertTriangle as AlertTriangle6, ChevronRight as ChevronRight21, Clock as Clock6 } from "lucide-react";
23821
24205
 
23822
24206
  // src/hooks/use-supported-destination-tokens.ts
@@ -23991,7 +24375,7 @@ function useExecutions(userId, publishableKey, options) {
23991
24375
  }
23992
24376
 
23993
24377
  // src/hooks/use-withdraw-polling.ts
23994
- import { useState as useState42, useEffect as useEffect36, useRef as useRef14 } from "react";
24378
+ import { useState as useState42, useEffect as useEffect36, useRef as useRef15 } from "react";
23995
24379
  import {
23996
24380
  queryExecutions as queryExecutions5,
23997
24381
  pollDirectExecutions as pollDirectExecutions2,
@@ -24038,11 +24422,11 @@ function useWithdrawPolling({
24038
24422
  });
24039
24423
  const [executions, setExecutions] = useState42([]);
24040
24424
  const [isPolling, setIsPolling] = useState42(false);
24041
- const enabledAtRef = useRef14(/* @__PURE__ */ new Date());
24042
- const trackedRef = useRef14(/* @__PURE__ */ new Map());
24043
- const prevEnabledRef = useRef14(false);
24044
- const onSuccessRef = useRef14(onWithdrawSuccess);
24045
- const onErrorRef = useRef14(onWithdrawError);
24425
+ const enabledAtRef = useRef15(/* @__PURE__ */ new Date());
24426
+ const trackedRef = useRef15(/* @__PURE__ */ new Map());
24427
+ const prevEnabledRef = useRef15(false);
24428
+ const onSuccessRef = useRef15(onWithdrawSuccess);
24429
+ const onErrorRef = useRef15(onWithdrawError);
24046
24430
  useEffect36(() => {
24047
24431
  onSuccessRef.current = onWithdrawSuccess;
24048
24432
  }, [onWithdrawSuccess]);
@@ -24310,7 +24694,7 @@ function WithdrawDoubleInput({
24310
24694
  }
24311
24695
 
24312
24696
  // src/components/withdrawals/WithdrawForm.tsx
24313
- import { useState as useState43, useCallback as useCallback10, useMemo as useMemo16, useEffect as useEffect37 } from "react";
24697
+ import { useState as useState43, useCallback as useCallback12, useMemo as useMemo17, useEffect as useEffect37 } from "react";
24314
24698
  import {
24315
24699
  AlertTriangle as AlertTriangle5,
24316
24700
  ArrowUpDown,
@@ -24588,7 +24972,7 @@ async function detectBrowserWallet(chainType, senderAddress) {
24588
24972
  }
24589
24973
 
24590
24974
  // src/hooks/use-hypercore-withdraw-activation.ts
24591
- import { useMemo as useMemo15 } from "react";
24975
+ import { useMemo as useMemo16 } from "react";
24592
24976
  import { ActionType as ActionType6 } from "@unifold/core";
24593
24977
 
24594
24978
  // src/hooks/use-get-deposit-address.ts
@@ -24675,7 +25059,7 @@ function useHypercoreWithdrawActivation(params) {
24675
25059
  actionType: ActionType6.Withdraw,
24676
25060
  enabled: enabled && isHypercore(sourceChainId)
24677
25061
  });
24678
- const depositWalletAddress = useMemo15(() => {
25062
+ const depositWalletAddress = useMemo16(() => {
24679
25063
  const wallets = depositWalletLookup.data?.data ?? [];
24680
25064
  return wallets.find((w) => w.chain_type === sourceChainType)?.address;
24681
25065
  }, [depositWalletLookup.data, sourceChainType]);
@@ -24797,7 +25181,7 @@ function WithdrawForm({
24797
25181
  enabled: debouncedAddress.length > 5 && !!selectedChain
24798
25182
  });
24799
25183
  const isDebouncing = trimmedAddress !== debouncedAddress;
24800
- const addressError = useMemo16(() => {
25184
+ const addressError = useMemo17(() => {
24801
25185
  if (!trimmedAddress || trimmedAddress.length <= 5) return null;
24802
25186
  if (isDebouncing || isVerifyingAddress) return null;
24803
25187
  if (verifyError) return t10.invalidAddress;
@@ -24831,33 +25215,33 @@ function WithdrawForm({
24831
25215
  destinationTokenAddress: selectedChain?.token_address,
24832
25216
  enabled: isAddressValid
24833
25217
  });
24834
- const exchangeRate = useMemo16(() => {
25218
+ const exchangeRate = useMemo17(() => {
24835
25219
  if (!balanceData?.exchangeRate) return 0;
24836
25220
  return parseFloat(balanceData.exchangeRate);
24837
25221
  }, [balanceData]);
24838
- const balanceCrypto = useMemo16(() => {
25222
+ const balanceCrypto = useMemo17(() => {
24839
25223
  if (!balanceData?.balanceHuman) return 0;
24840
25224
  return parseFloat(balanceData.balanceHuman);
24841
25225
  }, [balanceData]);
24842
- const balanceUsdNum = useMemo16(() => {
25226
+ const balanceUsdNum = useMemo17(() => {
24843
25227
  if (!balanceData?.balanceUsd) return 0;
24844
25228
  return parseFloat(balanceData.balanceUsd);
24845
25229
  }, [balanceData]);
24846
25230
  const tokenSymbol = sourceTokenSymbol || balanceData?.symbol || "TOKEN";
24847
25231
  const sourceDecimals = balanceData?.decimals ?? 6;
24848
- const cryptoAmountFromInput = useMemo16(() => {
25232
+ const cryptoAmountFromInput = useMemo17(() => {
24849
25233
  const val = parseFloat(amount);
24850
25234
  if (!val || val <= 0) return 0;
24851
25235
  if (inputUnit === "crypto") return val;
24852
25236
  return exchangeRate > 0 ? val / exchangeRate : 0;
24853
25237
  }, [amount, inputUnit, exchangeRate]);
24854
- const fiatAmountFromInput = useMemo16(() => {
25238
+ const fiatAmountFromInput = useMemo17(() => {
24855
25239
  const val = parseFloat(amount);
24856
25240
  if (!val || val <= 0) return 0;
24857
25241
  if (inputUnit === "fiat") return val;
24858
25242
  return val * exchangeRate;
24859
25243
  }, [amount, inputUnit, exchangeRate]);
24860
- const convertedDisplay = useMemo16(() => {
25244
+ const convertedDisplay = useMemo17(() => {
24861
25245
  if (!amount || parseFloat(amount) <= 0) return null;
24862
25246
  if (inputUnit === "crypto") {
24863
25247
  return `$${fiatAmountFromInput.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
@@ -24876,7 +25260,7 @@ function WithdrawForm({
24876
25260
  isMaxed,
24877
25261
  isStablecoin
24878
25262
  ]);
24879
- const balanceDisplay = useMemo16(() => {
25263
+ const balanceDisplay = useMemo17(() => {
24880
25264
  if (isLoadingBalance || !balanceData) return null;
24881
25265
  if (inputUnit === "crypto") {
24882
25266
  const displayDecimals = isStablecoin ? 2 : 6;
@@ -24899,7 +25283,7 @@ function WithdrawForm({
24899
25283
  tokenSymbol,
24900
25284
  isStablecoin
24901
25285
  ]);
24902
- const handleSwitchUnit = useCallback10(() => {
25286
+ const handleSwitchUnit = useCallback12(() => {
24903
25287
  if (isMaxed && balanceData) {
24904
25288
  if (inputUnit === "crypto") {
24905
25289
  setAmount((Math.round(balanceUsdNum * 100) / 100).toFixed(2));
@@ -24926,7 +25310,7 @@ function WithdrawForm({
24926
25310
  setInputUnit("crypto");
24927
25311
  }
24928
25312
  }, [amount, inputUnit, exchangeRate, sourceDecimals, isMaxed, balanceData, balanceUsdNum]);
24929
- const handleMaxClick = useCallback10(() => {
25313
+ const handleMaxClick = useCallback12(() => {
24930
25314
  if (inputUnit === "crypto") {
24931
25315
  if (balanceCrypto <= 0) return;
24932
25316
  setAmount(balanceData?.balanceHuman ?? "0");
@@ -24940,7 +25324,7 @@ function WithdrawForm({
24940
25324
  const isBelowMinimum = minimumWithdrawAmountUsd !== null && fiatAmountFromInput > 0 && Math.round(fiatAmountFromInput * 100) / 100 < minimumWithdrawAmountUsd;
24941
25325
  const isOverBalance = inputUnit === "crypto" ? cryptoAmountFromInput > 0 && balanceCrypto > 0 && cryptoAmountFromInput > balanceCrypto : fiatAmountFromInput > 0 && balanceUsdNum > 0 && Math.round(fiatAmountFromInput * 100) / 100 > Math.round(balanceUsdNum * 100) / 100;
24942
25326
  const isFormValid = trimmedAddress.length > 0 && amount.trim().length > 0 && cryptoAmountFromInput > 0 && isAddressValid && !isBelowMinimum && !isOverBalance && !isBalanceBelowMinimum && !!balanceData;
24943
- const handleWithdraw = useCallback10(async () => {
25327
+ const handleWithdraw = useCallback12(async () => {
24944
25328
  if (!selectedToken || !selectedChain) return;
24945
25329
  if (!isFormValid) return;
24946
25330
  setIsSubmitting(true);
@@ -25726,7 +26110,7 @@ function WithdrawModal({
25726
26110
  theme = "dark",
25727
26111
  hideOverlay = false
25728
26112
  }) {
25729
- const onWithdrawSuccessFor = useCallback11(
26113
+ const onWithdrawSuccessFor = useCallback13(
25730
26114
  (data) => {
25731
26115
  onWithdrawSuccess?.(data);
25732
26116
  if (data.execution) {
@@ -25737,7 +26121,7 @@ function WithdrawModal({
25737
26121
  );
25738
26122
  const { colors: colors2, fonts, components } = useTheme();
25739
26123
  const [containerEl, setContainerEl] = useState45(null);
25740
- const containerCallbackRef = useCallback11((el) => {
26124
+ const containerCallbackRef = useCallback13((el) => {
25741
26125
  setContainerEl(el);
25742
26126
  }, []);
25743
26127
  const [resolvedTheme, setResolvedTheme] = useState45(
@@ -25810,7 +26194,7 @@ function WithdrawModal({
25810
26194
  refetchInterval: view === "tracker" || view === "detail" ? 5e3 : 15e3
25811
26195
  });
25812
26196
  const allWithdrawals = allWithdrawalsData?.data ?? [];
25813
- const handleDepositWalletCreation = useCallback11(
26197
+ const handleDepositWalletCreation = useCallback13(
25814
26198
  async (params) => {
25815
26199
  const { data: wallets } = await createDepositAddress2(
25816
26200
  {
@@ -25833,12 +26217,12 @@ function WithdrawModal({
25833
26217
  },
25834
26218
  [externalUserId, publishableKey, sourceChainType]
25835
26219
  );
25836
- const handleWithdrawSubmitted = useCallback11((txInfo) => {
26220
+ const handleWithdrawSubmitted = useCallback13((txInfo) => {
25837
26221
  setSubmittedTxInfo(txInfo);
25838
26222
  setView("confirming");
25839
26223
  }, []);
25840
- const resetViewTimeoutRef = useRef15(null);
25841
- const handleClose = useCallback11(() => {
26224
+ const resetViewTimeoutRef = useRef16(null);
26225
+ const handleClose = useCallback13(() => {
25842
26226
  onOpenChange(false);
25843
26227
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
25844
26228
  resetViewTimeoutRef.current = setTimeout(() => {
@@ -25866,13 +26250,13 @@ function WithdrawModal({
25866
26250
  },
25867
26251
  []
25868
26252
  );
25869
- const handleTokenSymbolChange = useCallback11(
26253
+ const handleTokenSymbolChange = useCallback13(
25870
26254
  (symbol) => {
25871
26255
  setSelectedTokenSymbol(symbol);
25872
26256
  },
25873
26257
  [setSelectedTokenSymbol]
25874
26258
  );
25875
- const handleChainKeyChange = useCallback11(
26259
+ const handleChainKeyChange = useCallback13(
25876
26260
  (chainKey) => {
25877
26261
  setSelectedChainKey(chainKey);
25878
26262
  },
@@ -26059,7 +26443,7 @@ function WithdrawModal({
26059
26443
  }
26060
26444
 
26061
26445
  // src/components/withdrawals/WithdrawTokenSelector.tsx
26062
- import { useState as useState46, useMemo as useMemo17 } from "react";
26446
+ import { useState as useState46, useMemo as useMemo18 } from "react";
26063
26447
  import { Search } from "lucide-react";
26064
26448
  import Fuse2 from "fuse.js";
26065
26449
  import { jsx as jsx70, jsxs as jsxs64 } from "react/jsx-runtime";
@@ -26068,7 +26452,7 @@ function WithdrawTokenSelector({ tokens, onSelect, onBack }) {
26068
26452
  const { themeClass, colors: colors2, fonts, components } = useTheme();
26069
26453
  const [searchQuery, setSearchQuery] = useState46("");
26070
26454
  const [hoveredKey, setHoveredKey] = useState46(null);
26071
- const allOptions = useMemo17(() => {
26455
+ const allOptions = useMemo18(() => {
26072
26456
  const options = [];
26073
26457
  tokens.forEach((token) => {
26074
26458
  token.chains.forEach((chain) => {
@@ -26077,7 +26461,7 @@ function WithdrawTokenSelector({ tokens, onSelect, onBack }) {
26077
26461
  });
26078
26462
  return options;
26079
26463
  }, [tokens]);
26080
- const fuse = useMemo17(
26464
+ const fuse = useMemo18(
26081
26465
  () => new Fuse2(allOptions, {
26082
26466
  keys: [
26083
26467
  { name: "token.symbol", weight: 2 },
@@ -26090,7 +26474,7 @@ function WithdrawTokenSelector({ tokens, onSelect, onBack }) {
26090
26474
  }),
26091
26475
  [allOptions]
26092
26476
  );
26093
- const filteredOptions = useMemo17(() => {
26477
+ const filteredOptions = useMemo18(() => {
26094
26478
  if (!searchQuery.trim()) return allOptions;
26095
26479
  const query = searchQuery.trim();
26096
26480
  const results = fuse.search(query);