@unifold/ui-react 0.1.49 → 0.1.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { AutoSwapResponse, ChainType, DepositEvent, Wallet, FiatCurrency, ExecutionStatus, FeaturedToken, PaymentNetwork, DestinationToken, DestinationTokenChain, PaymentIntent, DepositQuote, SupportedDestinationTokensResponse, VerifyAddressResponse } from '@unifold/core';
2
+ import { AutoSwapResponse, ChainType, DepositEvent, Wallet, FiatCurrency, ExecutionStatus, FeaturedToken, PaymentNetwork, DestinationToken, DestinationTokenChain, PaymentIntent, DepositQuote, SupportedDestinationTokensResponse, SupportedDepositTokensResponse, VerifyAddressResponse } from '@unifold/core';
3
3
  export { ChainType } from '@unifold/core';
4
4
  import * as _tanstack_react_query from '@tanstack/react-query';
5
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
@@ -820,7 +820,10 @@ interface UsePaymentIntentParams {
820
820
  * Hook to retrieve and poll a payment intent via react-query.
821
821
  *
822
822
  * Fetches the payment intent on mount and polls at the configured interval
823
- * so `amount_received_usd` and `status` stay up-to-date in the UI.
823
+ * so `amount_received_usd` and `status` stay up-to-date in the UI. Polling
824
+ * automatically stops once the PI reaches a terminal status. Locked-quote
825
+ * states like `awaiting_refund` / `refunding` / `refund_failed` keep polling
826
+ * because they can still flip.
824
827
  */
825
828
  declare function usePaymentIntent(params: UsePaymentIntentParams): _tanstack_react_query.UseQueryResult<PaymentIntent, Error>;
826
829
 
@@ -875,6 +878,22 @@ declare function useWithdrawPolling({ userId, publishableKey, depositWalletId, e
875
878
  */
876
879
  declare function useSupportedDestinationTokens(publishableKey: string, enabled?: boolean): _tanstack_react_query.UseQueryResult<SupportedDestinationTokensResponse, Error>;
877
880
 
881
+ interface UseSupportedDepositTokensOptions {
882
+ destination_token_address?: string;
883
+ destination_chain_id?: string;
884
+ destination_chain_type?: string;
885
+ }
886
+ /**
887
+ * Hook to fetch supported deposit tokens with caching and deduplication via react-query.
888
+ *
889
+ * Replaces manual useEffect + useState fetching with automatic caching (5 min stale),
890
+ * request deduplication across components, and built-in loading/error states.
891
+ *
892
+ * @param publishableKey - Publishable key for API calls
893
+ * @param options - Optional destination filters (all three must be provided to filter)
894
+ */
895
+ declare function useSupportedDepositTokens(publishableKey: string, options?: UseSupportedDepositTokensOptions): _tanstack_react_query.UseQueryResult<SupportedDepositTokensResponse, Error>;
896
+
878
897
  interface UseVerifyRecipientAddressParams {
879
898
  chainType?: string;
880
899
  chainId?: string;
@@ -1187,4 +1206,4 @@ declare function cn(...inputs: ClassValue[]): string;
1187
1206
  */
1188
1207
  declare function truncateAddress(address: string, startChars?: number, endChars?: number): string;
1189
1208
 
1190
- export { type AllowedCountryResult, type BrowserWalletAmountQuickSelect, Button, type ButtonProps, type ButtonTokens, BuyWithCard, type BuyWithCardProps, type CardTokens, CheckoutModal, type CheckoutModalProps, type ComponentConfig, type ComponentOverrides, type ComponentTokens, ConfirmingView, type ContainerTokens, CurrencyListItem, CurrencyListSection, CurrencyModal, type CustomThemeColors, type DepositConfirmationMode, DepositDetailContent, DepositExecutionItem, DepositHeader, DepositModal, type DepositModalInitialScreen, type DepositModalProps, DepositPollingUi, DepositSuccessToast, DepositTrackerButton, DepositWithCardButton, DepositsModal, type DetectedWallet, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, type EvmWalletProvider, type FontConfig, HYPERCORE_CHAIN_ID, type HeaderTokens, type InputTokens, type ListTokens, type ResolvedFonts, type SearchTokens, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, type SolanaWalletProvider, StyledQRCode, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, type ThemeProviderProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TransferCryptoButton, TransferCryptoDoubleInput, TransferCryptoSingleInput, type UseDepositQuoteParams, type UsePaymentIntentParams, WithdrawConfirmingView, WithdrawDoubleInput, WithdrawExecutionItem, WithdrawForm, WithdrawModal, type WithdrawModalProps, WithdrawTokenSelector, type WithdrawTransactionInfo, buttonVariants, cn, colors, defaultColors, detectBrowserWallet, getColors, isHypercoreChain, mergeColors, resolveComponentTokens, sendEvmWithdraw, sendHypercoreWithdraw, sendSolanaWithdraw, truncateAddress, useAddressBalance, useAllowedCountry, useDepositPolling, useDepositQuote, usePaymentIntent, useSourceTokenValidation, useSupportedDestinationTokens, useTheme, useVerifyRecipientAddress, useWithdrawPolling };
1209
+ export { type AllowedCountryResult, type BrowserWalletAmountQuickSelect, Button, type ButtonProps, type ButtonTokens, BuyWithCard, type BuyWithCardProps, type CardTokens, CheckoutModal, type CheckoutModalProps, type ComponentConfig, type ComponentOverrides, type ComponentTokens, ConfirmingView, type ContainerTokens, CurrencyListItem, CurrencyListSection, CurrencyModal, type CustomThemeColors, type DepositConfirmationMode, DepositDetailContent, DepositExecutionItem, DepositHeader, DepositModal, type DepositModalInitialScreen, type DepositModalProps, DepositPollingUi, DepositSuccessToast, DepositTrackerButton, DepositWithCardButton, DepositsModal, type DetectedWallet, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, type EvmWalletProvider, type FontConfig, HYPERCORE_CHAIN_ID, type HeaderTokens, type InputTokens, type ListTokens, type ResolvedFonts, type SearchTokens, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, type SolanaWalletProvider, StyledQRCode, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, type ThemeProviderProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TransferCryptoButton, TransferCryptoDoubleInput, TransferCryptoSingleInput, type UseDepositQuoteParams, type UsePaymentIntentParams, type UseSupportedDepositTokensOptions, WithdrawConfirmingView, WithdrawDoubleInput, WithdrawExecutionItem, WithdrawForm, WithdrawModal, type WithdrawModalProps, WithdrawTokenSelector, type WithdrawTransactionInfo, buttonVariants, cn, colors, defaultColors, detectBrowserWallet, getColors, isHypercoreChain, mergeColors, resolveComponentTokens, sendEvmWithdraw, sendHypercoreWithdraw, sendSolanaWithdraw, truncateAddress, useAddressBalance, useAllowedCountry, useDepositPolling, useDepositQuote, usePaymentIntent, useSourceTokenValidation, useSupportedDepositTokens, useSupportedDestinationTokens, useTheme, useVerifyRecipientAddress, useWithdrawPolling };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
- import { AutoSwapResponse, ChainType, DepositEvent, Wallet, FiatCurrency, ExecutionStatus, FeaturedToken, PaymentNetwork, DestinationToken, DestinationTokenChain, PaymentIntent, DepositQuote, SupportedDestinationTokensResponse, VerifyAddressResponse } from '@unifold/core';
2
+ import { AutoSwapResponse, ChainType, DepositEvent, Wallet, FiatCurrency, ExecutionStatus, FeaturedToken, PaymentNetwork, DestinationToken, DestinationTokenChain, PaymentIntent, DepositQuote, SupportedDestinationTokensResponse, SupportedDepositTokensResponse, VerifyAddressResponse } from '@unifold/core';
3
3
  export { ChainType } from '@unifold/core';
4
4
  import * as _tanstack_react_query from '@tanstack/react-query';
5
5
  import * as class_variance_authority_types from 'class-variance-authority/types';
@@ -820,7 +820,10 @@ interface UsePaymentIntentParams {
820
820
  * Hook to retrieve and poll a payment intent via react-query.
821
821
  *
822
822
  * Fetches the payment intent on mount and polls at the configured interval
823
- * so `amount_received_usd` and `status` stay up-to-date in the UI.
823
+ * so `amount_received_usd` and `status` stay up-to-date in the UI. Polling
824
+ * automatically stops once the PI reaches a terminal status. Locked-quote
825
+ * states like `awaiting_refund` / `refunding` / `refund_failed` keep polling
826
+ * because they can still flip.
824
827
  */
825
828
  declare function usePaymentIntent(params: UsePaymentIntentParams): _tanstack_react_query.UseQueryResult<PaymentIntent, Error>;
826
829
 
@@ -875,6 +878,22 @@ declare function useWithdrawPolling({ userId, publishableKey, depositWalletId, e
875
878
  */
876
879
  declare function useSupportedDestinationTokens(publishableKey: string, enabled?: boolean): _tanstack_react_query.UseQueryResult<SupportedDestinationTokensResponse, Error>;
877
880
 
881
+ interface UseSupportedDepositTokensOptions {
882
+ destination_token_address?: string;
883
+ destination_chain_id?: string;
884
+ destination_chain_type?: string;
885
+ }
886
+ /**
887
+ * Hook to fetch supported deposit tokens with caching and deduplication via react-query.
888
+ *
889
+ * Replaces manual useEffect + useState fetching with automatic caching (5 min stale),
890
+ * request deduplication across components, and built-in loading/error states.
891
+ *
892
+ * @param publishableKey - Publishable key for API calls
893
+ * @param options - Optional destination filters (all three must be provided to filter)
894
+ */
895
+ declare function useSupportedDepositTokens(publishableKey: string, options?: UseSupportedDepositTokensOptions): _tanstack_react_query.UseQueryResult<SupportedDepositTokensResponse, Error>;
896
+
878
897
  interface UseVerifyRecipientAddressParams {
879
898
  chainType?: string;
880
899
  chainId?: string;
@@ -1187,4 +1206,4 @@ declare function cn(...inputs: ClassValue[]): string;
1187
1206
  */
1188
1207
  declare function truncateAddress(address: string, startChars?: number, endChars?: number): string;
1189
1208
 
1190
- export { type AllowedCountryResult, type BrowserWalletAmountQuickSelect, Button, type ButtonProps, type ButtonTokens, BuyWithCard, type BuyWithCardProps, type CardTokens, CheckoutModal, type CheckoutModalProps, type ComponentConfig, type ComponentOverrides, type ComponentTokens, ConfirmingView, type ContainerTokens, CurrencyListItem, CurrencyListSection, CurrencyModal, type CustomThemeColors, type DepositConfirmationMode, DepositDetailContent, DepositExecutionItem, DepositHeader, DepositModal, type DepositModalInitialScreen, type DepositModalProps, DepositPollingUi, DepositSuccessToast, DepositTrackerButton, DepositWithCardButton, DepositsModal, type DetectedWallet, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, type EvmWalletProvider, type FontConfig, HYPERCORE_CHAIN_ID, type HeaderTokens, type InputTokens, type ListTokens, type ResolvedFonts, type SearchTokens, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, type SolanaWalletProvider, StyledQRCode, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, type ThemeProviderProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TransferCryptoButton, TransferCryptoDoubleInput, TransferCryptoSingleInput, type UseDepositQuoteParams, type UsePaymentIntentParams, WithdrawConfirmingView, WithdrawDoubleInput, WithdrawExecutionItem, WithdrawForm, WithdrawModal, type WithdrawModalProps, WithdrawTokenSelector, type WithdrawTransactionInfo, buttonVariants, cn, colors, defaultColors, detectBrowserWallet, getColors, isHypercoreChain, mergeColors, resolveComponentTokens, sendEvmWithdraw, sendHypercoreWithdraw, sendSolanaWithdraw, truncateAddress, useAddressBalance, useAllowedCountry, useDepositPolling, useDepositQuote, usePaymentIntent, useSourceTokenValidation, useSupportedDestinationTokens, useTheme, useVerifyRecipientAddress, useWithdrawPolling };
1209
+ export { type AllowedCountryResult, type BrowserWalletAmountQuickSelect, Button, type ButtonProps, type ButtonTokens, BuyWithCard, type BuyWithCardProps, type CardTokens, CheckoutModal, type CheckoutModalProps, type ComponentConfig, type ComponentOverrides, type ComponentTokens, ConfirmingView, type ContainerTokens, CurrencyListItem, CurrencyListSection, CurrencyModal, type CustomThemeColors, type DepositConfirmationMode, DepositDetailContent, DepositExecutionItem, DepositHeader, DepositModal, type DepositModalInitialScreen, type DepositModalProps, DepositPollingUi, DepositSuccessToast, DepositTrackerButton, DepositWithCardButton, DepositsModal, type DetectedWallet, Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogOverlay, DialogPortal, DialogTitle, DialogTrigger, type EvmWalletProvider, type FontConfig, HYPERCORE_CHAIN_ID, type HeaderTokens, type InputTokens, type ListTokens, type ResolvedFonts, type SearchTokens, Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue, type SolanaWalletProvider, StyledQRCode, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, type ThemeProviderProps, Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TransferCryptoButton, TransferCryptoDoubleInput, TransferCryptoSingleInput, type UseDepositQuoteParams, type UsePaymentIntentParams, type UseSupportedDepositTokensOptions, WithdrawConfirmingView, WithdrawDoubleInput, WithdrawExecutionItem, WithdrawForm, WithdrawModal, type WithdrawModalProps, WithdrawTokenSelector, type WithdrawTransactionInfo, buttonVariants, cn, colors, defaultColors, detectBrowserWallet, getColors, isHypercoreChain, mergeColors, resolveComponentTokens, sendEvmWithdraw, sendHypercoreWithdraw, sendSolanaWithdraw, truncateAddress, useAddressBalance, useAllowedCountry, useDepositPolling, useDepositQuote, usePaymentIntent, useSourceTokenValidation, useSupportedDepositTokens, useSupportedDestinationTokens, useTheme, useVerifyRecipientAddress, useWithdrawPolling };
package/dist/index.js CHANGED
@@ -101,6 +101,7 @@ __export(index_exports, {
101
101
  useDepositQuote: () => useDepositQuote,
102
102
  usePaymentIntent: () => usePaymentIntent,
103
103
  useSourceTokenValidation: () => useSourceTokenValidation,
104
+ useSupportedDepositTokens: () => useSupportedDepositTokens,
104
105
  useSupportedDestinationTokens: () => useSupportedDestinationTokens,
105
106
  useTheme: () => useTheme,
106
107
  useVerifyRecipientAddress: () => useVerifyRecipientAddress,
@@ -2762,31 +2763,29 @@ function BuyWithCard({
2762
2763
  );
2763
2764
  if (manualProviderStillExists) {
2764
2765
  setSelectedProvider(manualProviderStillExists);
2765
- const bestProvider = response.data.reduce(
2766
- (best, current) => current.destination_amount > best.destination_amount ? current : best
2767
- );
2766
+ const firstProvider = response.data[0];
2768
2767
  if (!autoSelectedProvider) {
2769
- setAutoSelectedProvider(bestProvider.service_provider);
2768
+ setAutoSelectedProvider(firstProvider.service_provider);
2770
2769
  }
2771
2770
  setIsAutoSelected(
2772
2771
  manualProviderStillExists.service_provider === autoSelectedProvider
2773
2772
  );
2774
- } else {
2775
- const bestProvider = response.data.reduce(
2776
- (best, current) => current.destination_amount > best.destination_amount ? current : best
2777
- );
2778
- setSelectedProvider(bestProvider);
2779
- setAutoSelectedProvider(bestProvider.service_provider);
2773
+ } else if (response.data.length > 0) {
2774
+ const firstProvider = response.data[0];
2775
+ setSelectedProvider(firstProvider);
2776
+ setAutoSelectedProvider(firstProvider.service_provider);
2780
2777
  setIsAutoSelected(true);
2781
2778
  setHasManualSelection(false);
2779
+ } else {
2780
+ setSelectedProvider(null);
2781
+ setIsAutoSelected(false);
2782
+ setHasManualSelection(false);
2782
2783
  }
2783
2784
  } else {
2784
2785
  if (response.data.length > 0) {
2785
- const bestProvider = response.data.reduce(
2786
- (best, current) => current.destination_amount > best.destination_amount ? current : best
2787
- );
2788
- setSelectedProvider(bestProvider);
2789
- setAutoSelectedProvider(bestProvider.service_provider);
2786
+ const firstProvider = response.data[0];
2787
+ setSelectedProvider(firstProvider);
2788
+ setAutoSelectedProvider(firstProvider.service_provider);
2790
2789
  setIsAutoSelected(true);
2791
2790
  }
2792
2791
  }
@@ -2882,9 +2881,7 @@ function BuyWithCard({
2882
2881
  window.open(sessionStartUrl, "_blank");
2883
2882
  handleViewChange("onramp");
2884
2883
  };
2885
- const sortedQuotes = [...quotes].sort(
2886
- (a, b) => b.destination_amount - a.destination_amount
2887
- );
2884
+ const sortedQuotes = quotes;
2888
2885
  const currencySymbol = getCurrencySymbol(currency);
2889
2886
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2890
2887
  "div",
@@ -6996,14 +6993,23 @@ function useAllowedCountry(publishableKey) {
6996
6993
  let isAllowed = null;
6997
6994
  if (ipData && configData) {
6998
6995
  const blockedCodes = configData.blocked_country_codes || [];
6996
+ const blockedSubdivisions = configData.blocked_country_subdivisions || [];
6999
6997
  const userCountryUpper = ipData.alpha2.toUpperCase();
7000
- isAllowed = !blockedCodes.some(
6998
+ const userSubdivision = ipData.subdivision_code || ipData.state || "";
6999
+ const userSubdivisionUpper = userSubdivision.toUpperCase();
7000
+ const isCountryBlocked = blockedCodes.some(
7001
7001
  (code) => code.toUpperCase() === userCountryUpper
7002
7002
  );
7003
+ const isSubdivisionBlocked = blockedSubdivisions.some((entry) => {
7004
+ if (entry.country_code.toUpperCase() !== userCountryUpper) return false;
7005
+ return entry.subdivision_codes.some(
7006
+ (code) => code.toUpperCase() === userSubdivisionUpper
7007
+ );
7008
+ });
7009
+ isAllowed = !isCountryBlocked && !isSubdivisionBlocked;
7003
7010
  }
7004
7011
  return {
7005
7012
  isAllowed,
7006
- // Return lowercase for consistency with useUserIp hook
7007
7013
  alpha2: ipData?.alpha2?.toLowerCase() ?? null,
7008
7014
  country: ipData?.country ?? null,
7009
7015
  isLoading,
@@ -12472,19 +12478,30 @@ var import_lucide_react24 = require("lucide-react");
12472
12478
  // src/hooks/use-payment-intent.ts
12473
12479
  var import_react_query9 = require("@tanstack/react-query");
12474
12480
  var import_core24 = require("@unifold/core");
12481
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
12482
+ "succeeded",
12483
+ "expired",
12484
+ "refunded",
12485
+ "canceled"
12486
+ ]);
12475
12487
  function usePaymentIntent(params) {
12476
12488
  const {
12477
12489
  clientSecret,
12478
12490
  publishableKey,
12479
12491
  enabled = true,
12480
- pollingInterval = 5e3
12492
+ pollingInterval = 3e3
12481
12493
  } = params;
12482
12494
  return (0, import_react_query9.useQuery)({
12483
12495
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
12484
12496
  queryFn: () => (0, import_core24.retrievePaymentIntent)(clientSecret, publishableKey),
12485
12497
  enabled: enabled && !!clientSecret && !!publishableKey,
12486
12498
  staleTime: 0,
12487
- refetchInterval: pollingInterval || false,
12499
+ refetchInterval: (query) => {
12500
+ if (!pollingInterval) return false;
12501
+ const status = query.state.data?.status;
12502
+ if (status && TERMINAL_STATUSES.has(status)) return false;
12503
+ return pollingInterval;
12504
+ },
12488
12505
  refetchOnWindowFocus: true,
12489
12506
  retry: 3,
12490
12507
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
@@ -12615,7 +12632,7 @@ function CheckoutModal({
12615
12632
  clientSecret,
12616
12633
  publishableKey,
12617
12634
  enabled: open && !!clientSecret,
12618
- pollingInterval: 5e3
12635
+ pollingInterval: 3e3
12619
12636
  });
12620
12637
  const { projectConfig } = useProjectConfig({
12621
12638
  publishableKey,
@@ -15236,6 +15253,7 @@ function WithdrawTokenSelector({
15236
15253
  useDepositQuote,
15237
15254
  usePaymentIntent,
15238
15255
  useSourceTokenValidation,
15256
+ useSupportedDepositTokens,
15239
15257
  useSupportedDestinationTokens,
15240
15258
  useTheme,
15241
15259
  useVerifyRecipientAddress,
package/dist/index.mjs CHANGED
@@ -2686,31 +2686,29 @@ function BuyWithCard({
2686
2686
  );
2687
2687
  if (manualProviderStillExists) {
2688
2688
  setSelectedProvider(manualProviderStillExists);
2689
- const bestProvider = response.data.reduce(
2690
- (best, current) => current.destination_amount > best.destination_amount ? current : best
2691
- );
2689
+ const firstProvider = response.data[0];
2692
2690
  if (!autoSelectedProvider) {
2693
- setAutoSelectedProvider(bestProvider.service_provider);
2691
+ setAutoSelectedProvider(firstProvider.service_provider);
2694
2692
  }
2695
2693
  setIsAutoSelected(
2696
2694
  manualProviderStillExists.service_provider === autoSelectedProvider
2697
2695
  );
2698
- } else {
2699
- const bestProvider = response.data.reduce(
2700
- (best, current) => current.destination_amount > best.destination_amount ? current : best
2701
- );
2702
- setSelectedProvider(bestProvider);
2703
- setAutoSelectedProvider(bestProvider.service_provider);
2696
+ } else if (response.data.length > 0) {
2697
+ const firstProvider = response.data[0];
2698
+ setSelectedProvider(firstProvider);
2699
+ setAutoSelectedProvider(firstProvider.service_provider);
2704
2700
  setIsAutoSelected(true);
2705
2701
  setHasManualSelection(false);
2702
+ } else {
2703
+ setSelectedProvider(null);
2704
+ setIsAutoSelected(false);
2705
+ setHasManualSelection(false);
2706
2706
  }
2707
2707
  } else {
2708
2708
  if (response.data.length > 0) {
2709
- const bestProvider = response.data.reduce(
2710
- (best, current) => current.destination_amount > best.destination_amount ? current : best
2711
- );
2712
- setSelectedProvider(bestProvider);
2713
- setAutoSelectedProvider(bestProvider.service_provider);
2709
+ const firstProvider = response.data[0];
2710
+ setSelectedProvider(firstProvider);
2711
+ setAutoSelectedProvider(firstProvider.service_provider);
2714
2712
  setIsAutoSelected(true);
2715
2713
  }
2716
2714
  }
@@ -2806,9 +2804,7 @@ function BuyWithCard({
2806
2804
  window.open(sessionStartUrl, "_blank");
2807
2805
  handleViewChange("onramp");
2808
2806
  };
2809
- const sortedQuotes = [...quotes].sort(
2810
- (a, b) => b.destination_amount - a.destination_amount
2811
- );
2807
+ const sortedQuotes = quotes;
2812
2808
  const currencySymbol = getCurrencySymbol(currency);
2813
2809
  return /* @__PURE__ */ jsxs8(
2814
2810
  "div",
@@ -6933,14 +6929,23 @@ function useAllowedCountry(publishableKey) {
6933
6929
  let isAllowed = null;
6934
6930
  if (ipData && configData) {
6935
6931
  const blockedCodes = configData.blocked_country_codes || [];
6932
+ const blockedSubdivisions = configData.blocked_country_subdivisions || [];
6936
6933
  const userCountryUpper = ipData.alpha2.toUpperCase();
6937
- isAllowed = !blockedCodes.some(
6934
+ const userSubdivision = ipData.subdivision_code || ipData.state || "";
6935
+ const userSubdivisionUpper = userSubdivision.toUpperCase();
6936
+ const isCountryBlocked = blockedCodes.some(
6938
6937
  (code) => code.toUpperCase() === userCountryUpper
6939
6938
  );
6939
+ const isSubdivisionBlocked = blockedSubdivisions.some((entry) => {
6940
+ if (entry.country_code.toUpperCase() !== userCountryUpper) return false;
6941
+ return entry.subdivision_codes.some(
6942
+ (code) => code.toUpperCase() === userSubdivisionUpper
6943
+ );
6944
+ });
6945
+ isAllowed = !isCountryBlocked && !isSubdivisionBlocked;
6940
6946
  }
6941
6947
  return {
6942
6948
  isAllowed,
6943
- // Return lowercase for consistency with useUserIp hook
6944
6949
  alpha2: ipData?.alpha2?.toLowerCase() ?? null,
6945
6950
  country: ipData?.country ?? null,
6946
6951
  isLoading,
@@ -12451,19 +12456,30 @@ import { AlertTriangle as AlertTriangle2, ChevronRight as ChevronRight12 } from
12451
12456
  // src/hooks/use-payment-intent.ts
12452
12457
  import { useQuery as useQuery9 } from "@tanstack/react-query";
12453
12458
  import { retrievePaymentIntent } from "@unifold/core";
12459
+ var TERMINAL_STATUSES = /* @__PURE__ */ new Set([
12460
+ "succeeded",
12461
+ "expired",
12462
+ "refunded",
12463
+ "canceled"
12464
+ ]);
12454
12465
  function usePaymentIntent(params) {
12455
12466
  const {
12456
12467
  clientSecret,
12457
12468
  publishableKey,
12458
12469
  enabled = true,
12459
- pollingInterval = 5e3
12470
+ pollingInterval = 3e3
12460
12471
  } = params;
12461
12472
  return useQuery9({
12462
12473
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
12463
12474
  queryFn: () => retrievePaymentIntent(clientSecret, publishableKey),
12464
12475
  enabled: enabled && !!clientSecret && !!publishableKey,
12465
12476
  staleTime: 0,
12466
- refetchInterval: pollingInterval || false,
12477
+ refetchInterval: (query) => {
12478
+ if (!pollingInterval) return false;
12479
+ const status = query.state.data?.status;
12480
+ if (status && TERMINAL_STATUSES.has(status)) return false;
12481
+ return pollingInterval;
12482
+ },
12467
12483
  refetchOnWindowFocus: true,
12468
12484
  retry: 3,
12469
12485
  retryDelay: (attempt) => Math.min(1e3 * 2 ** attempt, 1e4)
@@ -12596,7 +12612,7 @@ function CheckoutModal({
12596
12612
  clientSecret,
12597
12613
  publishableKey,
12598
12614
  enabled: open && !!clientSecret,
12599
- pollingInterval: 5e3
12615
+ pollingInterval: 3e3
12600
12616
  });
12601
12617
  const { projectConfig } = useProjectConfig({
12602
12618
  publishableKey,
@@ -15254,6 +15270,7 @@ export {
15254
15270
  useDepositQuote,
15255
15271
  usePaymentIntent,
15256
15272
  useSourceTokenValidation,
15273
+ useSupportedDepositTokens,
15257
15274
  useSupportedDestinationTokens,
15258
15275
  useTheme,
15259
15276
  useVerifyRecipientAddress,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unifold/ui-react",
3
- "version": "0.1.49",
3
+ "version": "0.1.50",
4
4
  "description": "Unifold UI React - Deposit and onramp components for React applications",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -34,7 +34,7 @@
34
34
  "lucide-react": "^0.454.0",
35
35
  "qr-code-styling": "^1.6.0-rc.1",
36
36
  "tailwind-merge": "^2.0.0",
37
- "@unifold/core": "0.1.49"
37
+ "@unifold/core": "0.1.50"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@solana/web3.js": "^1.87.0",