@unifold/connect-react 0.1.68-beta.1 → 0.1.68-beta.2

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.js CHANGED
@@ -1205,7 +1205,7 @@ __export(index_exports, {
1205
1205
  module.exports = __toCommonJS(index_exports);
1206
1206
 
1207
1207
  // src/provider.tsx
1208
- var import_react40 = __toESM(require("react"));
1208
+ var import_react41 = __toESM(require("react"));
1209
1209
 
1210
1210
  // ../react-provider/dist/index.mjs
1211
1211
  var import_react = require("react");
@@ -7588,6 +7588,59 @@ async function exchangeOnrampVerificationToken(id, clientSecret, publishableKey)
7588
7588
  "Failed to exchange verification token"
7589
7589
  );
7590
7590
  }
7591
+ function isApplePayLimitReached(response) {
7592
+ return response.limits.some((l) => l.remaining === "0");
7593
+ }
7594
+ function getApplePayLimitUpgradeStatus(response) {
7595
+ const opt = response.limit_upgrade_options?.[0];
7596
+ if (!opt || typeof opt.status !== "string") return null;
7597
+ return opt.status;
7598
+ }
7599
+ async function getCoinbaseApplePayLimits(phone, publishableKey, signal) {
7600
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
7601
+ validatePublishableKey(pk);
7602
+ const response = await fetch(
7603
+ `${API_BASE_URL}/v1/public/onramps/headless/coinbase/apple_pay/limits`,
7604
+ {
7605
+ method: "POST",
7606
+ headers: {
7607
+ accept: "application/json",
7608
+ "x-publishable-key": pk,
7609
+ "Content-Type": "application/json"
7610
+ },
7611
+ body: JSON.stringify({ phone }),
7612
+ signal
7613
+ }
7614
+ );
7615
+ const raw = await jsonOrThrow(response, "Failed to fetch Apple Pay limits");
7616
+ return {
7617
+ limits: raw.limits,
7618
+ limit_upgrade_options: raw.limit_upgrade_options,
7619
+ limit_reached: isApplePayLimitReached(raw),
7620
+ upgrade_status: getApplePayLimitUpgradeStatus(raw)
7621
+ };
7622
+ }
7623
+ async function requestCoinbaseApplePayLimitUpgrade(request, publishableKey, signal) {
7624
+ const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
7625
+ validatePublishableKey(pk);
7626
+ const response = await fetch(
7627
+ `${API_BASE_URL}/v1/public/onramps/headless/coinbase/apple_pay/limits/upgrade`,
7628
+ {
7629
+ method: "POST",
7630
+ headers: {
7631
+ accept: "application/json",
7632
+ "x-publishable-key": pk,
7633
+ "Content-Type": "application/json"
7634
+ },
7635
+ body: JSON.stringify(request),
7636
+ signal
7637
+ }
7638
+ );
7639
+ return jsonOrThrow(
7640
+ response,
7641
+ "Failed to request Apple Pay limit upgrade"
7642
+ );
7643
+ }
7591
7644
  async function createCoinbaseApplePaySession(request, onrampToken, publishableKey, signal) {
7592
7645
  const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
7593
7646
  validatePublishableKey(pk);
@@ -7772,19 +7825,20 @@ var import_jsx_runtime29 = require("react/jsx-runtime");
7772
7825
  var React52 = __toESM(require("react"), 1);
7773
7826
  var import_react17 = require("react");
7774
7827
  var import_react_query5 = require("@tanstack/react-query");
7828
+ var import_react18 = require("react");
7775
7829
  var import_react_query6 = require("@tanstack/react-query");
7830
+ var import_react_query7 = require("@tanstack/react-query");
7776
7831
  var import_jsx_runtime30 = require("react/jsx-runtime");
7777
- var import_react18 = require("react");
7778
- var import_jsx_runtime31 = require("react/jsx-runtime");
7779
7832
  var import_react19 = require("react");
7833
+ var import_jsx_runtime31 = require("react/jsx-runtime");
7780
7834
  var import_react20 = require("react");
7835
+ var import_react21 = require("react");
7781
7836
  var import_qr_code_styling = __toESM(require_qr_code_styling(), 1);
7782
7837
  var import_jsx_runtime32 = require("react/jsx-runtime");
7783
- var import_react21 = require("react");
7784
- var import_react_query7 = require("@tanstack/react-query");
7785
- var import_jsx_runtime33 = require("react/jsx-runtime");
7786
7838
  var import_react22 = require("react");
7787
7839
  var import_react_query8 = require("@tanstack/react-query");
7840
+ var import_jsx_runtime33 = require("react/jsx-runtime");
7841
+ var import_react23 = require("react");
7788
7842
  var import_react_query9 = require("@tanstack/react-query");
7789
7843
  var import_jsx_runtime34 = require("react/jsx-runtime");
7790
7844
  var import_jsx_runtime35 = require("react/jsx-runtime");
@@ -8037,25 +8091,26 @@ var import_jsx_runtime57 = require("react/jsx-runtime");
8037
8091
  var import_jsx_runtime58 = require("react/jsx-runtime");
8038
8092
  var React292 = __toESM(require("react"), 1);
8039
8093
  var import_jsx_runtime59 = require("react/jsx-runtime");
8040
- var import_react23 = require("react");
8041
- var import_jsx_runtime60 = require("react/jsx-runtime");
8042
8094
  var import_react24 = require("react");
8043
- var import_jsx_runtime61 = require("react/jsx-runtime");
8095
+ var import_jsx_runtime60 = require("react/jsx-runtime");
8044
8096
  var import_react25 = require("react");
8097
+ var import_jsx_runtime61 = require("react/jsx-runtime");
8098
+ var import_react26 = require("react");
8045
8099
  var import_react_query10 = require("@tanstack/react-query");
8046
8100
  var import_react_query11 = require("@tanstack/react-query");
8047
- var import_jsx_runtime62 = require("react/jsx-runtime");
8048
8101
  var import_react_query12 = require("@tanstack/react-query");
8102
+ var import_jsx_runtime62 = require("react/jsx-runtime");
8049
8103
  var import_react_query13 = require("@tanstack/react-query");
8050
8104
  var import_react_query14 = require("@tanstack/react-query");
8051
8105
  var import_react_query15 = require("@tanstack/react-query");
8052
- var import_react26 = require("react");
8106
+ var import_react_query16 = require("@tanstack/react-query");
8053
8107
  var import_react27 = require("react");
8108
+ var import_react28 = require("react");
8054
8109
  var React312 = __toESM(require("react"), 1);
8055
8110
  var import_jsx_runtime63 = require("react/jsx-runtime");
8056
8111
  var import_jsx_runtime64 = require("react/jsx-runtime");
8057
8112
  var import_jsx_runtime65 = require("react/jsx-runtime");
8058
- var import_react28 = require("react");
8113
+ var import_react29 = require("react");
8059
8114
 
8060
8115
  // ../../node_modules/.pnpm/fuse.js@7.4.0/node_modules/fuse.js/dist/fuse.mjs
8061
8116
  function isArray(value) {
@@ -10057,10 +10112,10 @@ Fuse.use = function(...plugins) {
10057
10112
 
10058
10113
  // ../ui-react/dist/index.mjs
10059
10114
  var import_jsx_runtime66 = require("react/jsx-runtime");
10060
- var import_react29 = require("react");
10115
+ var import_react30 = require("react");
10061
10116
  var import_jsx_runtime67 = require("react/jsx-runtime");
10062
10117
  var import_jsx_runtime68 = require("react/jsx-runtime");
10063
- var import_react30 = require("react");
10118
+ var import_react31 = require("react");
10064
10119
  var React322 = __toESM(require("react"), 1);
10065
10120
 
10066
10121
  // ../../node_modules/.pnpm/@radix-ui+react-tooltip@1.2.8_@types+react-dom@19.2.3_@types+react@19.2.9__@types+react@19.2._udyjcec5g7ve3mpsxbgla63vgi/node_modules/@radix-ui/react-tooltip/dist/index.mjs
@@ -12799,10 +12854,10 @@ var Content22 = TooltipContent;
12799
12854
 
12800
12855
  // ../ui-react/dist/index.mjs
12801
12856
  var import_jsx_runtime69 = require("react/jsx-runtime");
12802
- var import_react_query16 = require("@tanstack/react-query");
12857
+ var import_react_query17 = require("@tanstack/react-query");
12803
12858
  var import_jsx_runtime70 = require("react/jsx-runtime");
12804
12859
  var import_jsx_runtime71 = require("react/jsx-runtime");
12805
- var import_react31 = require("react");
12860
+ var import_react32 = require("react");
12806
12861
  var React332 = __toESM(require("react"), 1);
12807
12862
 
12808
12863
  // ../../node_modules/.pnpm/@radix-ui+react-select@2.2.6_@types+react-dom@19.2.3_@types+react@19.2.9__@types+react@19.2.9_cot3leusltbsophitaz3dgdqdm/node_modules/@radix-ui/react-select/dist/index.mjs
@@ -14041,36 +14096,36 @@ var Separator = SelectSeparator;
14041
14096
  var import_jsx_runtime72 = require("react/jsx-runtime");
14042
14097
  var import_jsx_runtime73 = require("react/jsx-runtime");
14043
14098
  var React342 = __toESM(require("react"), 1);
14044
- var import_react_query17 = require("@tanstack/react-query");
14045
14099
  var import_react_query18 = require("@tanstack/react-query");
14100
+ var import_react_query19 = require("@tanstack/react-query");
14046
14101
  var import_jsx_runtime74 = require("react/jsx-runtime");
14047
14102
  var import_jsx_runtime75 = require("react/jsx-runtime");
14048
14103
  var import_jsx_runtime76 = require("react/jsx-runtime");
14049
14104
  var import_jsx_runtime77 = require("react/jsx-runtime");
14050
- var import_react32 = require("react");
14105
+ var import_react33 = require("react");
14051
14106
  var import_jsx_runtime78 = require("react/jsx-runtime");
14052
14107
  var import_jsx_runtime79 = require("react/jsx-runtime");
14053
14108
  var import_jsx_runtime80 = require("react/jsx-runtime");
14054
- var import_react33 = require("react");
14055
- var import_react_query19 = require("@tanstack/react-query");
14056
- var import_jsx_runtime81 = require("react/jsx-runtime");
14057
14109
  var import_react34 = require("react");
14058
14110
  var import_react_query20 = require("@tanstack/react-query");
14111
+ var import_jsx_runtime81 = require("react/jsx-runtime");
14112
+ var import_react35 = require("react");
14059
14113
  var import_react_query21 = require("@tanstack/react-query");
14060
14114
  var import_react_query22 = require("@tanstack/react-query");
14061
14115
  var import_react_query23 = require("@tanstack/react-query");
14062
- var import_react35 = require("react");
14063
- var import_jsx_runtime82 = require("react/jsx-runtime");
14064
- var import_react36 = require("react");
14065
14116
  var import_react_query24 = require("@tanstack/react-query");
14117
+ var import_react36 = require("react");
14118
+ var import_jsx_runtime82 = require("react/jsx-runtime");
14066
14119
  var import_react37 = require("react");
14067
14120
  var import_react_query25 = require("@tanstack/react-query");
14121
+ var import_react38 = require("react");
14122
+ var import_react_query26 = require("@tanstack/react-query");
14068
14123
  var import_jsx_runtime83 = require("react/jsx-runtime");
14069
14124
  var import_jsx_runtime84 = require("react/jsx-runtime");
14070
- var import_react38 = require("react");
14125
+ var import_react39 = require("react");
14071
14126
  var import_jsx_runtime85 = require("react/jsx-runtime");
14072
14127
  var import_jsx_runtime86 = require("react/jsx-runtime");
14073
- var import_react39 = require("react");
14128
+ var import_react40 = require("react");
14074
14129
  var import_jsx_runtime87 = require("react/jsx-runtime");
14075
14130
  function cn(...inputs) {
14076
14131
  return twMerge(clsx(inputs));
@@ -15460,7 +15515,7 @@ var en_default2 = {
15460
15515
  payWithStripeLink: {
15461
15516
  success: {
15462
15517
  processingTitle: "Payment confirmed",
15463
- processingSubtitle: "We\u2019ve received your payment and are preparing your purchase. This will only take a moment.",
15518
+ processingSubtitle: "We\u2019ve received your payment and are sending your purchase to your wallet. This usually takes just a few minutes.",
15464
15519
  completeTitle: "Your purchase is on the way",
15465
15520
  completeSubtitle: "Your purchase is complete and is being sent to your wallet.",
15466
15521
  failedTitle: "Purchase didn\u2019t go through",
@@ -17444,20 +17499,6 @@ function BuyWithCard({
17444
17499
  }
17445
17500
  );
17446
17501
  }
17447
- function useProjectConfig({
17448
- publishableKey,
17449
- enabled = true
17450
- }) {
17451
- const { data: projectConfig, isLoading } = (0, import_react_query5.useQuery)({
17452
- queryKey: ["unifold", "projectConfig", publishableKey],
17453
- queryFn: () => getProjectConfig(publishableKey),
17454
- enabled,
17455
- staleTime: 1e3 * 60 * 30,
17456
- refetchOnMount: true,
17457
- refetchOnWindowFocus: true
17458
- });
17459
- return { projectConfig, isLoading };
17460
- }
17461
17502
  var STORAGE_KEY_PREFIX = "unifold:apple-pay:session";
17462
17503
  var PHONE_FRESH_MS = 55 * 24 * 60 * 60 * 1e3;
17463
17504
  function isBrowser() {
@@ -17494,7 +17535,7 @@ function useCoinbaseLegalAgreements({
17494
17535
  publishableKey,
17495
17536
  enabled = true
17496
17537
  }) {
17497
- return (0, import_react_query6.useQuery)({
17538
+ return (0, import_react_query5.useQuery)({
17498
17539
  queryKey: ["unifold", "coinbaseLegalAgreements", publishableKey],
17499
17540
  queryFn: () => getCoinbaseLegalAgreements(publishableKey),
17500
17541
  enabled: enabled && !!publishableKey,
@@ -17505,47 +17546,200 @@ function useCoinbaseLegalAgreements({
17505
17546
  retry: 1
17506
17547
  });
17507
17548
  }
17508
- var COINBASE_PAY_ORIGIN = "https://pay.coinbase.com";
17509
- var DEFAULT_MIN_USD = 5;
17510
- var DEFAULT_MAX_USD = 500;
17511
- var DEFAULT_SUGGESTED = [25, 50, 100];
17549
+ var US_E164_REGEX = /^\+1\d{10}$/;
17550
+ function useApplePayLimits({
17551
+ phone,
17552
+ publishableKey,
17553
+ enabled = true
17554
+ }) {
17555
+ const phoneValid = US_E164_REGEX.test(phone);
17556
+ return (0, import_react_query6.useQuery)({
17557
+ queryKey: ["unifold", "applePayLimits", phone, publishableKey],
17558
+ queryFn: ({ signal }) => getCoinbaseApplePayLimits(phone, publishableKey, signal),
17559
+ enabled: enabled && phoneValid && !!publishableKey,
17560
+ // Coinbase's caps don't change second-to-second; 30s is plenty fresh
17561
+ // for the "user opened the modal, edited their phone, opened it
17562
+ // again" usage pattern, while keeping us off their API on rapid
17563
+ // tap-throughs.
17564
+ staleTime: 3e4,
17565
+ gcTime: 5 * 6e4,
17566
+ refetchOnWindowFocus: false,
17567
+ retry: false
17568
+ });
17569
+ }
17512
17570
  var PHONE_REGEX = /^\+1\d{10}$/;
17513
17571
  var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
17514
- function formatPhoneInput(raw) {
17515
- const digits = raw.replace(/\D/g, "");
17516
- if (raw.startsWith("+")) {
17517
- return `+${digits}`;
17572
+ function getViewForLimitStatus(limits) {
17573
+ if (!limits.limit_reached) return void 0;
17574
+ switch (limits.upgrade_status) {
17575
+ case "unrequested":
17576
+ return "limit_upgrade_intro";
17577
+ case "resubmit":
17578
+ return "limit_upgrade_form";
17579
+ case "pending":
17580
+ return "limit_upgrade_submitting";
17581
+ case "active":
17582
+ return void 0;
17583
+ default:
17584
+ return "guest_limit_reached";
17518
17585
  }
17519
- if (digits.length === 10) return `+1${digits}`;
17520
- if (digits.length === 11 && digits.startsWith("1")) return `+${digits}`;
17521
- return digits.length > 0 ? `+${digits}` : "";
17522
17586
  }
17523
- function maskEmail(email) {
17524
- const [local, domain] = email.split("@");
17525
- if (!local || !domain) return email;
17526
- const visible = local.slice(0, Math.min(2, local.length));
17527
- return `${visible}${"*".repeat(Math.max(local.length - visible.length, 1))}@${domain}`;
17587
+ function useApplePayInitialScreen({
17588
+ userId,
17589
+ publishableKey,
17590
+ normalizedPhone,
17591
+ userEmail,
17592
+ sessionPhoneVerified,
17593
+ isWaiting
17594
+ }) {
17595
+ const initialStoredSession = (0, import_react18.useMemo)(() => getStoredApplePaySession(userId), [userId]);
17596
+ const phoneVerified = PHONE_REGEX.test(normalizedPhone) && (sessionPhoneVerified || initialStoredSession?.phone === normalizedPhone && !!initialStoredSession?.phoneVerifiedAt);
17597
+ const {
17598
+ data: applePayLimits,
17599
+ isLoading: applePayLimitsLoading,
17600
+ refetch: refetchApplePayLimits
17601
+ } = useApplePayLimits({
17602
+ phone: normalizedPhone,
17603
+ publishableKey,
17604
+ enabled: phoneVerified
17605
+ });
17606
+ const action = (0, import_react18.useMemo)(() => {
17607
+ if (isWaiting || applePayLimitsLoading) return { kind: "pending" };
17608
+ const stored = initialStoredSession;
17609
+ const hasUserEmail = !!userEmail && EMAIL_REGEX.test(userEmail);
17610
+ if (!stored) {
17611
+ return { kind: "navigate", view: hasUserEmail ? "phone_input" : "email_input" };
17612
+ }
17613
+ if (hasUserEmail && stored.email.toLowerCase() !== userEmail.toLowerCase()) {
17614
+ return { kind: "navigate", view: "phone_input" };
17615
+ }
17616
+ if (applePayLimits) {
17617
+ const limitView = getViewForLimitStatus(applePayLimits);
17618
+ if (limitView) {
17619
+ return { kind: "limit_upgrade", view: limitView, status: applePayLimits.upgrade_status };
17620
+ }
17621
+ }
17622
+ if (isOnrampTokenFresh(stored) && stored.onrampToken && stored.onrampTokenExpiresAtMs) {
17623
+ return {
17624
+ kind: "resume_with_token",
17625
+ token: {
17626
+ token: stored.onrampToken,
17627
+ token_type: "Bearer",
17628
+ expires_in: Math.max(0, Math.floor((stored.onrampTokenExpiresAtMs - Date.now()) / 1e3))
17629
+ }
17630
+ };
17631
+ }
17632
+ return { kind: "resume_send_sms" };
17633
+ }, [isWaiting, applePayLimitsLoading, initialStoredSession, userEmail, applePayLimits]);
17634
+ return {
17635
+ action,
17636
+ applePayLimits,
17637
+ applePayLimitsLoading,
17638
+ refetchApplePayLimits,
17639
+ phoneVerified
17640
+ };
17528
17641
  }
17529
- function maskPhone(phone) {
17530
- if (!/^\+1\d{10}$/.test(phone)) return phone;
17531
- return `+1 (***) ***-${phone.slice(-4)}`;
17642
+ function useDefaultOnrampToken({
17643
+ publishableKey,
17644
+ tokenAddress,
17645
+ chainId,
17646
+ chainType,
17647
+ countryCode,
17648
+ subdivisionCode,
17649
+ enabled = true
17650
+ }) {
17651
+ const {
17652
+ data: defaultToken,
17653
+ isLoading,
17654
+ isError,
17655
+ error
17656
+ } = (0, import_react_query7.useQuery)({
17657
+ queryKey: [
17658
+ "unifold",
17659
+ "defaultOnrampToken",
17660
+ publishableKey,
17661
+ tokenAddress,
17662
+ chainId,
17663
+ chainType,
17664
+ countryCode,
17665
+ subdivisionCode
17666
+ ],
17667
+ queryFn: () => getDefaultOnrampToken(
17668
+ {
17669
+ token_address: tokenAddress,
17670
+ chain_id: chainId,
17671
+ chain_type: chainType,
17672
+ country_code: countryCode,
17673
+ subdivision_code: subdivisionCode
17674
+ },
17675
+ publishableKey
17676
+ ),
17677
+ enabled: enabled && !!tokenAddress && !!chainId && !!chainType,
17678
+ staleTime: 1e3 * 60 * 60,
17679
+ refetchOnMount: false,
17680
+ refetchOnWindowFocus: false
17681
+ });
17682
+ return { defaultToken, isLoading, isError, error: error ?? null };
17683
+ }
17684
+ var COINBASE_PAY_ORIGIN = "https://pay.coinbase.com";
17685
+ var COINBASE_ALLOWED_POSTMESSAGE_ORIGINS = /* @__PURE__ */ new Set([
17686
+ COINBASE_PAY_ORIGIN,
17687
+ "https://www.coinbase.com"
17688
+ ]);
17689
+ var UNIFOLD_SUPPORT_URL = "https://unifold.io/support";
17690
+ var DEFAULT_MIN_USD = 5;
17691
+ var DEFAULT_MAX_USD = 500;
17692
+ var DEFAULT_SUGGESTED = [25, 50, 100];
17693
+ var PHONE_REGEX2 = /^\+1\d{10}$/;
17694
+ var EMAIL_REGEX2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
17695
+ function parseCoinbasePostMessage(raw) {
17696
+ const parseString = (s) => {
17697
+ try {
17698
+ return JSON.parse(s);
17699
+ } catch {
17700
+ return null;
17701
+ }
17702
+ };
17703
+ const asObject = (value) => value && typeof value === "object" ? value : null;
17704
+ let candidate = raw;
17705
+ if (typeof candidate === "string") {
17706
+ candidate = parseString(candidate);
17707
+ }
17708
+ const obj = asObject(candidate);
17709
+ if (!obj) return null;
17710
+ const nestedData = obj.data;
17711
+ let eventName = typeof obj.eventName === "string" && obj.eventName || typeof obj.event_name === "string" && obj.event_name || typeof obj.type === "string" && obj.type || null;
17712
+ let dataObj = asObject(nestedData);
17713
+ if (!eventName && typeof nestedData === "string") {
17714
+ const nestedParsed = parseString(nestedData);
17715
+ const nestedObj = asObject(nestedParsed);
17716
+ if (nestedObj) {
17717
+ eventName = typeof nestedObj.eventName === "string" && nestedObj.eventName || typeof nestedObj.event_name === "string" && nestedObj.event_name || typeof nestedObj.type === "string" && nestedObj.type || null;
17718
+ dataObj = asObject(nestedObj.data);
17719
+ }
17720
+ }
17721
+ if (!eventName || !/^onramp_api\./i.test(eventName)) return null;
17722
+ return {
17723
+ eventName,
17724
+ data: dataObj ? {
17725
+ errorCode: typeof dataObj.errorCode === "string" ? dataObj.errorCode : typeof dataObj.error_code === "string" ? dataObj.error_code : void 0,
17726
+ errorMessage: typeof dataObj.errorMessage === "string" ? dataObj.errorMessage : typeof dataObj.error_message === "string" ? dataObj.error_message : void 0
17727
+ } : void 0
17728
+ };
17532
17729
  }
17533
17730
  var BuyWithApplePay = React52.forwardRef(
17534
17731
  function BuyWithApplePay2({
17535
17732
  userId,
17536
17733
  publishableKey,
17537
- recipientAddress,
17538
17734
  destinationChainType,
17539
17735
  destinationChainId,
17540
17736
  destinationTokenAddress,
17541
- destinationTokenSymbol = "USDC",
17542
- externalUserEmail,
17543
- enableApplePay,
17737
+ userEmail,
17544
17738
  amountUsd,
17545
17739
  minAmountUsd = DEFAULT_MIN_USD,
17546
17740
  maxAmountUsd = DEFAULT_MAX_USD,
17547
17741
  suggestedAmountsUsd = DEFAULT_SUGGESTED,
17548
- wallets: externalWallets,
17742
+ wallets: depositWallets,
17549
17743
  onDepositSuccess,
17550
17744
  onDepositError,
17551
17745
  onEvent,
@@ -17554,48 +17748,61 @@ var BuyWithApplePay = React52.forwardRef(
17554
17748
  onExit
17555
17749
  }, ref) {
17556
17750
  const { colors: colors2, fonts, components } = useTheme();
17557
- const { projectConfig, isLoading: configLoading } = useProjectConfig({ publishableKey });
17558
- const applePayEnabled = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
17559
17751
  const [view, setView] = (0, import_react17.useState)("loading_config");
17560
17752
  const [errorMessage, setErrorMessage] = (0, import_react17.useState)("");
17561
- const [email, setEmail] = (0, import_react17.useState)(externalUserEmail ?? "");
17562
- const [phoneInput, setPhoneInput] = (0, import_react17.useState)("");
17563
- const [, setTosAccepted] = (0, import_react17.useState)(false);
17753
+ const [email, setEmail] = (0, import_react17.useState)(() => {
17754
+ if (userEmail && EMAIL_REGEX2.test(userEmail)) return userEmail;
17755
+ return getStoredApplePaySession(userId)?.email ?? "";
17756
+ });
17757
+ const [phoneInput, setPhoneInput] = (0, import_react17.useState)(() => {
17758
+ const stored = getStoredApplePaySession(userId);
17759
+ if (!stored) return "";
17760
+ if (userEmail && EMAIL_REGEX2.test(userEmail) && stored.email.toLowerCase() !== userEmail.toLowerCase()) {
17761
+ return "";
17762
+ }
17763
+ return stored.phone;
17764
+ });
17564
17765
  const { data: legalAgreementsData, isLoading: legalAgreementsLoading } = useCoinbaseLegalAgreements({
17565
- publishableKey,
17566
- enabled: applePayEnabled
17766
+ publishableKey
17567
17767
  });
17568
17768
  const legalAgreements = legalAgreementsData ?? null;
17569
17769
  const [verificationSession, setVerificationSession] = (0, import_react17.useState)(null);
17570
17770
  const [clientSecret, setClientSecret] = (0, import_react17.useState)(null);
17571
- const [emailCode, setEmailCode] = (0, import_react17.useState)("");
17572
17771
  const [phoneCode, setPhoneCode] = (0, import_react17.useState)("");
17573
17772
  const [otpError, setOtpError] = (0, import_react17.useState)(null);
17574
17773
  const [otpSubmitting, setOtpSubmitting] = (0, import_react17.useState)(false);
17575
17774
  const [resendCooldown, setResendCooldown] = (0, import_react17.useState)(0);
17775
+ const [dobInput, setDobInput] = (0, import_react17.useState)("");
17776
+ const [ssnLast4, setSsnLast4] = (0, import_react17.useState)("");
17777
+ const [limitUpgradeError, setLimitUpgradeError] = (0, import_react17.useState)(null);
17778
+ const [upgradeSubmitting, setUpgradeSubmitting] = (0, import_react17.useState)(false);
17779
+ const upgradeFlowAbortRef = (0, import_react17.useRef)(null);
17576
17780
  const [amount, setAmount] = (0, import_react17.useState)(amountUsd ?? "");
17577
17781
  const [paymentSession, setPaymentSession] = (0, import_react17.useState)(
17578
17782
  null
17579
17783
  );
17580
17784
  const [paymentSessionAmount, setPaymentSessionAmount] = (0, import_react17.useState)(null);
17581
- const [preparingSession, setPreparingSession] = (0, import_react17.useState)(false);
17582
17785
  const popupRef = (0, import_react17.useRef)(null);
17583
17786
  const sessionAbortRef = (0, import_react17.useRef)(null);
17584
17787
  const [onrampToken, setOnrampToken] = (0, import_react17.useState)(null);
17585
- const { data: depositAddressResponse } = useDepositAddress({
17586
- userId,
17788
+ const { userIpInfo, isLoading: userIpInfoLoading } = useUserIp2();
17789
+ const {
17790
+ defaultToken,
17791
+ isLoading: defaultTokenLoading,
17792
+ isError: defaultTokenError
17793
+ } = useDefaultOnrampToken({
17587
17794
  publishableKey,
17588
- recipientAddress,
17589
- destinationChainType,
17590
- destinationChainId,
17591
- destinationTokenAddress,
17592
- enabled: !externalWallets?.length
17795
+ tokenAddress: destinationTokenAddress,
17796
+ chainId: destinationChainId,
17797
+ chainType: destinationChainType,
17798
+ countryCode: userIpInfo?.alpha2,
17799
+ subdivisionCode: userIpInfo?.subdivisionCode ?? void 0
17593
17800
  });
17594
- const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
17595
17801
  const depositWallet = (0, import_react17.useMemo)(() => {
17596
- if (!destinationChainType) return void 0;
17597
- return getWalletByChainType(wallets, destinationChainType);
17598
- }, [wallets, destinationChainType]);
17802
+ const routingChainType = defaultToken?.destination_token_metadata?.chain_type;
17803
+ if (!routingChainType) return void 0;
17804
+ return getWalletByChainType(depositWallets ?? [], routingChainType);
17805
+ }, [depositWallets, defaultToken]);
17599
17806
  const depositWalletId = depositWallet?.id;
17600
17807
  const { executions } = useDepositPolling({
17601
17808
  userId,
@@ -17619,49 +17826,10 @@ var BuyWithApplePay = React52.forwardRef(
17619
17826
  onDepositError(error);
17620
17827
  } : void 0
17621
17828
  });
17622
- const [emailLocked, setEmailLocked] = (0, import_react17.useState)(false);
17623
- (0, import_react17.useEffect)(() => {
17624
- if (configLoading) return;
17625
- if (!applePayEnabled) {
17626
- setView("disabled");
17627
- return;
17628
- }
17629
- setTosAccepted(true);
17630
- const applyStoredOnrampToken = (stored2) => {
17631
- if (!isOnrampTokenFresh(stored2) || !stored2.onrampToken || !stored2.onrampTokenExpiresAtMs) {
17632
- return false;
17633
- }
17634
- setOnrampToken({
17635
- token: stored2.onrampToken,
17636
- token_type: "Bearer",
17637
- expires_in: Math.max(0, Math.floor((stored2.onrampTokenExpiresAtMs - Date.now()) / 1e3))
17638
- });
17639
- setView("amount");
17640
- return true;
17641
- };
17642
- if (externalUserEmail && EMAIL_REGEX.test(externalUserEmail)) {
17643
- setEmail(externalUserEmail);
17644
- setEmailLocked(true);
17645
- const stored2 = getStoredApplePaySession(userId);
17646
- if (stored2?.email?.toLowerCase() === externalUserEmail.toLowerCase()) {
17647
- setPhoneInput(stored2.phone);
17648
- if (applyStoredOnrampToken(stored2)) return;
17649
- }
17650
- setView("phone_input");
17651
- return;
17652
- }
17653
- const stored = getStoredApplePaySession(userId);
17654
- if (stored) {
17655
- setEmail(stored.email);
17656
- setPhoneInput(stored.phone);
17657
- setEmailLocked(true);
17658
- if (applyStoredOnrampToken(stored)) return;
17659
- setView("phone_input");
17660
- return;
17661
- }
17662
- setEmailLocked(false);
17663
- setView("email_input");
17664
- }, [configLoading, applePayEnabled, externalUserEmail, userId]);
17829
+ const [emailLocked, setEmailLocked] = (0, import_react17.useState)(() => {
17830
+ if (userEmail && EMAIL_REGEX2.test(userEmail)) return true;
17831
+ return !!getStoredApplePaySession(userId);
17832
+ });
17665
17833
  (0, import_react17.useEffect)(() => {
17666
17834
  if (resendCooldown <= 0) return;
17667
17835
  const t13 = setInterval(() => setResendCooldown((c) => Math.max(0, c - 1)), 1e3);
@@ -17670,19 +17838,10 @@ var BuyWithApplePay = React52.forwardRef(
17670
17838
  (0, import_react17.useEffect)(() => {
17671
17839
  if (view !== "checking_deposit") return;
17672
17840
  const onMessage = (event) => {
17673
- if (event.origin !== COINBASE_PAY_ORIGIN) return;
17674
- let parsed = null;
17675
- const data = event.data;
17676
- if (typeof data === "string") {
17677
- try {
17678
- parsed = JSON.parse(data);
17679
- } catch {
17680
- return;
17681
- }
17682
- } else if (data && typeof data === "object" && "eventName" in data) {
17683
- parsed = data;
17684
- }
17841
+ if (!COINBASE_ALLOWED_POSTMESSAGE_ORIGINS.has(event.origin)) return;
17842
+ const parsed = parseCoinbasePostMessage(event.data);
17685
17843
  if (!parsed) return;
17844
+ const eventName = parsed.eventName.toLowerCase();
17686
17845
  const code = parsed.data?.errorCode;
17687
17846
  const closePopup = () => {
17688
17847
  try {
@@ -17691,16 +17850,20 @@ var BuyWithApplePay = React52.forwardRef(
17691
17850
  }
17692
17851
  popupRef.current = null;
17693
17852
  };
17694
- switch (parsed.eventName) {
17853
+ switch (eventName) {
17695
17854
  case "onramp_api.commit_success":
17696
17855
  case "onramp_api.polling_success":
17856
+ case "onramp_api.cancel":
17697
17857
  closePopup();
17698
17858
  break;
17699
17859
  case "onramp_api.commit_error":
17860
+ case "onramp_api.polling_failed":
17700
17861
  if (code === "ERROR_CODE_GUEST_TRANSACTION_COUNT" || code === "ERROR_CODE_GUEST_DAILY_TRANSACTION_COUNT" || code === "ERROR_CODE_GUEST_TRANSACTION_LIMIT") {
17701
17862
  closePopup();
17702
17863
  setView("guest_limit_reached");
17864
+ return;
17703
17865
  }
17866
+ closePopup();
17704
17867
  break;
17705
17868
  default:
17706
17869
  break;
@@ -17712,17 +17875,17 @@ var BuyWithApplePay = React52.forwardRef(
17712
17875
  (0, import_react17.useEffect)(() => {
17713
17876
  onViewChange?.(view);
17714
17877
  }, [view, onViewChange]);
17715
- (0, import_react17.useEffect)(
17716
- () => () => {
17878
+ (0, import_react17.useEffect)(() => {
17879
+ return () => {
17717
17880
  sessionAbortRef.current?.abort();
17881
+ upgradeFlowAbortRef.current?.abort();
17718
17882
  try {
17719
17883
  popupRef.current?.close();
17720
17884
  } catch {
17721
17885
  }
17722
17886
  popupRef.current = null;
17723
- },
17724
- []
17725
- );
17887
+ };
17888
+ }, []);
17726
17889
  React52.useImperativeHandle(
17727
17890
  ref,
17728
17891
  () => ({
@@ -17732,14 +17895,20 @@ var BuyWithApplePay = React52.forwardRef(
17732
17895
  setView("email_input");
17733
17896
  return true;
17734
17897
  }
17735
- if (view === "email_otp") {
17736
- setView("phone_input");
17737
- setEmailCode("");
17738
- return true;
17739
- }
17740
17898
  if (view === "phone_otp") {
17741
17899
  setView("phone_input");
17742
17900
  setPhoneCode("");
17901
+ setOtpSubmitting(false);
17902
+ return true;
17903
+ }
17904
+ if (view === "limit_upgrade_intro" || view === "limit_upgrade_failed") {
17905
+ return false;
17906
+ }
17907
+ if (view === "limit_upgrade_form") {
17908
+ setView("limit_upgrade_intro");
17909
+ return true;
17910
+ }
17911
+ if (view === "limit_upgrade_submitting") {
17743
17912
  return true;
17744
17913
  }
17745
17914
  if (view === "checking_deposit") {
@@ -17760,21 +17929,20 @@ var BuyWithApplePay = React52.forwardRef(
17760
17929
  [view, emailLocked]
17761
17930
  );
17762
17931
  const normalizedPhone = (0, import_react17.useMemo)(() => formatPhoneInput(phoneInput), [phoneInput]);
17763
- const isContactValid = EMAIL_REGEX.test(email) && PHONE_REGEX.test(normalizedPhone);
17764
- const persistContact = (0, import_react17.useCallback)(
17932
+ const isContactValid = EMAIL_REGEX2.test(email) && PHONE_REGEX2.test(normalizedPhone);
17933
+ const storeApplePaySession = (0, import_react17.useCallback)(
17765
17934
  (patch = {}) => {
17766
- const base = {
17935
+ const session = {
17767
17936
  email,
17768
17937
  phone: normalizedPhone,
17769
17938
  termsAcceptedAt: (/* @__PURE__ */ new Date()).toISOString(),
17770
17939
  ...patch
17771
17940
  };
17772
- setStoredApplePaySession(userId, base);
17941
+ setStoredApplePaySession(userId, session);
17773
17942
  },
17774
17943
  [email, normalizedPhone, userId]
17775
17944
  );
17776
- const startVerification = (0, import_react17.useCallback)(async () => {
17777
- if (!isContactValid) return;
17945
+ const createSessionAndSendOtp = (0, import_react17.useCallback)(async () => {
17778
17946
  setView("submitting_session");
17779
17947
  setErrorMessage("");
17780
17948
  try {
@@ -17792,71 +17960,192 @@ var BuyWithApplePay = React52.forwardRef(
17792
17960
  throw new Error("Server did not return a client_secret");
17793
17961
  }
17794
17962
  setClientSecret(session.client_secret);
17795
- persistContact();
17796
- if (session.email.status === "verified") {
17797
- await sendOnrampVerificationOtp(
17798
- session.id,
17799
- "phone",
17800
- session.client_secret,
17801
- publishableKey
17802
- );
17803
- setResendCooldown(30);
17804
- setView("phone_otp");
17805
- } else {
17806
- await sendOnrampVerificationOtp(
17807
- session.id,
17808
- "email",
17809
- session.client_secret,
17810
- publishableKey
17811
- );
17812
- setResendCooldown(30);
17813
- setView("email_otp");
17814
- }
17963
+ storeApplePaySession();
17964
+ await sendOnrampVerificationOtp(session.id, "phone", session.client_secret, publishableKey);
17965
+ setResendCooldown(30);
17966
+ setView("phone_otp");
17815
17967
  } catch (err) {
17816
17968
  const raw = err instanceof Error ? err.message : "Failed to start verification";
17817
17969
  setErrorMessage(prettifyVerificationError(raw));
17818
17970
  setView("phone_input");
17819
17971
  }
17820
- }, [isContactValid, email, normalizedPhone, publishableKey, persistContact]);
17821
- const submitEmailOtp = (0, import_react17.useCallback)(async () => {
17822
- if (!verificationSession || !clientSecret || emailCode.length !== 6) return;
17823
- if (otpSubmitting) return;
17824
- setOtpError(null);
17825
- setOtpSubmitting(true);
17972
+ }, [email, normalizedPhone, publishableKey, storeApplePaySession]);
17973
+ const clearUpgradeFields = (0, import_react17.useCallback)(() => {
17974
+ setSsnLast4("");
17975
+ setDobInput("");
17976
+ }, []);
17977
+ const { action: initialAction, refetchApplePayLimits } = useApplePayInitialScreen({
17978
+ userId,
17979
+ publishableKey,
17980
+ normalizedPhone,
17981
+ userEmail,
17982
+ sessionPhoneVerified: verificationSession?.phone?.status === "verified",
17983
+ isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
17984
+ });
17985
+ const pollLimitUpgradeStatus = (0, import_react17.useCallback)(
17986
+ async (signal) => {
17987
+ const POLL_INTERVAL_MS4 = 1500;
17988
+ const POLL_TIMEOUT_MS = 3e4;
17989
+ const startedAt = Date.now();
17990
+ let firstIteration = true;
17991
+ while (Date.now() - startedAt < POLL_TIMEOUT_MS) {
17992
+ if (signal.aborted) return;
17993
+ if (!firstIteration) {
17994
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS4));
17995
+ }
17996
+ firstIteration = false;
17997
+ if (signal.aborted) return;
17998
+ let fresh;
17999
+ try {
18000
+ fresh = await getCoinbaseApplePayLimits(normalizedPhone, publishableKey, signal);
18001
+ } catch {
18002
+ if (signal.aborted) return;
18003
+ continue;
18004
+ }
18005
+ const { upgrade_status: status, limit_reached: stillCapped } = fresh;
18006
+ if (status === "active" || !stillCapped) {
18007
+ await refetchApplePayLimits();
18008
+ clearUpgradeFields();
18009
+ setLimitUpgradeError(null);
18010
+ if (onrampToken) {
18011
+ setView("amount");
18012
+ } else {
18013
+ if (signal.aborted) return;
18014
+ await createSessionAndSendOtp();
18015
+ }
18016
+ return;
18017
+ }
18018
+ if (status === "inactive") {
18019
+ await refetchApplePayLimits();
18020
+ clearUpgradeFields();
18021
+ setLimitUpgradeError(null);
18022
+ setView("guest_limit_reached");
18023
+ return;
18024
+ }
18025
+ if (status === "resubmit") {
18026
+ await refetchApplePayLimits();
18027
+ setSsnLast4("");
18028
+ setLimitUpgradeError(
18029
+ "We couldn't verify your information. Please check your SSN and date of birth and try again."
18030
+ );
18031
+ setView("limit_upgrade_form");
18032
+ return;
18033
+ }
18034
+ }
18035
+ setLimitUpgradeError(null);
18036
+ setView("limit_upgrade_failed");
18037
+ },
18038
+ [
18039
+ normalizedPhone,
18040
+ publishableKey,
18041
+ refetchApplePayLimits,
18042
+ onrampToken,
18043
+ createSessionAndSendOtp,
18044
+ clearUpgradeFields
18045
+ ]
18046
+ );
18047
+ const startUpgradePolling = (0, import_react17.useCallback)(async () => {
18048
+ upgradeFlowAbortRef.current?.abort();
18049
+ const controller = new AbortController();
18050
+ upgradeFlowAbortRef.current = controller;
17826
18051
  try {
17827
- const updated = await verifyOnrampVerificationOtp(
17828
- verificationSession.id,
17829
- "email",
17830
- clientSecret,
17831
- emailCode,
17832
- publishableKey
17833
- );
17834
- setVerificationSession(updated);
17835
- if (updated.email.status === "verified") {
17836
- persistContact({ emailVerifiedAt: updated.email.verified_at });
17837
- await sendOnrampVerificationOtp(updated.id, "phone", clientSecret, publishableKey);
17838
- setEmailCode("");
17839
- setResendCooldown(30);
17840
- setView("phone_otp");
18052
+ await pollLimitUpgradeStatus(controller.signal);
18053
+ } finally {
18054
+ if (upgradeFlowAbortRef.current === controller) {
18055
+ upgradeFlowAbortRef.current = null;
18056
+ }
18057
+ }
18058
+ }, [pollLimitUpgradeStatus]);
18059
+ const applyLimitRouting = (0, import_react17.useCallback)(
18060
+ (nextView, status) => {
18061
+ if (nextView === "limit_upgrade_form" && status === "resubmit") {
18062
+ setLimitUpgradeError(
18063
+ "We couldn't verify your information. Please check your SSN and date of birth and try again."
18064
+ );
17841
18065
  } else {
17842
- setOtpError("Incorrect code. Please try again.");
17843
- setEmailCode("");
18066
+ setLimitUpgradeError(null);
17844
18067
  }
17845
- } catch (err) {
17846
- setOtpError(
17847
- prettifyVerificationError(err instanceof Error ? err.message : "Verification failed")
17848
- );
17849
- setEmailCode("");
18068
+ setView(nextView);
18069
+ if (nextView === "limit_upgrade_submitting") {
18070
+ void startUpgradePolling();
18071
+ }
18072
+ },
18073
+ [startUpgradePolling]
18074
+ );
18075
+ const hasInitializedRef = (0, import_react17.useRef)(false);
18076
+ (0, import_react17.useEffect)(() => {
18077
+ if (hasInitializedRef.current) return;
18078
+ if (initialAction.kind === "pending") return;
18079
+ hasInitializedRef.current = true;
18080
+ switch (initialAction.kind) {
18081
+ case "navigate":
18082
+ setView(initialAction.view);
18083
+ break;
18084
+ case "limit_upgrade":
18085
+ applyLimitRouting(initialAction.view, initialAction.status);
18086
+ break;
18087
+ case "resume_with_token":
18088
+ setOnrampToken(initialAction.token);
18089
+ setView("amount");
18090
+ break;
18091
+ case "resume_send_sms":
18092
+ void createSessionAndSendOtp();
18093
+ break;
18094
+ }
18095
+ }, [initialAction, applyLimitRouting, createSessionAndSendOtp]);
18096
+ const startVerification = (0, import_react17.useCallback)(async () => {
18097
+ if (!isContactValid) return;
18098
+ await createSessionAndSendOtp();
18099
+ }, [isContactValid, createSessionAndSendOtp]);
18100
+ const submitLimitUpgrade = (0, import_react17.useCallback)(async () => {
18101
+ if (upgradeSubmitting) return;
18102
+ try {
18103
+ const dob = parseDobInput(dobInput);
18104
+ if (!dob || !/^\d{4}$/.test(ssnLast4)) return;
18105
+ setUpgradeSubmitting(true);
18106
+ setLimitUpgradeError(null);
18107
+ setView("limit_upgrade_submitting");
18108
+ const requestController = new AbortController();
18109
+ upgradeFlowAbortRef.current?.abort();
18110
+ upgradeFlowAbortRef.current = requestController;
18111
+ try {
18112
+ await requestCoinbaseApplePayLimitUpgrade(
18113
+ {
18114
+ phone: normalizedPhone,
18115
+ fields: { ssnLast4, dateOfBirth: dob }
18116
+ },
18117
+ publishableKey,
18118
+ requestController.signal
18119
+ );
18120
+ } catch (err) {
18121
+ if (requestController.signal.aborted) return;
18122
+ const raw = err instanceof Error ? err.message : "Failed to request limit upgrade";
18123
+ if (isLimitUpgradeTerminalBlock(raw)) {
18124
+ clearUpgradeFields();
18125
+ setLimitUpgradeError(null);
18126
+ setView("guest_limit_reached");
18127
+ return;
18128
+ }
18129
+ setLimitUpgradeError(prettifyVerificationError(raw));
18130
+ setView("limit_upgrade_form");
18131
+ return;
18132
+ } finally {
18133
+ if (upgradeFlowAbortRef.current === requestController) {
18134
+ upgradeFlowAbortRef.current = null;
18135
+ }
18136
+ }
18137
+ await startUpgradePolling();
17850
18138
  } finally {
17851
- setOtpSubmitting(false);
18139
+ setUpgradeSubmitting(false);
17852
18140
  }
17853
18141
  }, [
17854
- verificationSession,
17855
- clientSecret,
17856
- emailCode,
18142
+ upgradeSubmitting,
18143
+ dobInput,
18144
+ ssnLast4,
18145
+ normalizedPhone,
17857
18146
  publishableKey,
17858
- persistContact,
17859
- otpSubmitting
18147
+ startUpgradePolling,
18148
+ clearUpgradeFields
17860
18149
  ]);
17861
18150
  const submitPhoneOtp = (0, import_react17.useCallback)(async () => {
17862
18151
  if (!verificationSession || !clientSecret || phoneCode.length !== 6) return;
@@ -17879,7 +18168,7 @@ var BuyWithApplePay = React52.forwardRef(
17879
18168
  publishableKey
17880
18169
  );
17881
18170
  setOnrampToken(tokenRes);
17882
- persistContact({
18171
+ storeApplePaySession({
17883
18172
  emailVerifiedAt: updated.email.verified_at,
17884
18173
  phoneVerifiedAt: updated.phone.verified_at,
17885
18174
  onrampToken: tokenRes.token,
@@ -17888,17 +18177,30 @@ var BuyWithApplePay = React52.forwardRef(
17888
18177
  setEmailLocked(true);
17889
18178
  setPhoneCode("");
17890
18179
  if (amountUsd) setAmount(amountUsd);
18180
+ try {
18181
+ const result = await refetchApplePayLimits();
18182
+ if (result.data) {
18183
+ const nextView = getViewForLimitStatus(result.data);
18184
+ if (nextView) {
18185
+ setOtpSubmitting(false);
18186
+ applyLimitRouting(nextView, result.data.upgrade_status);
18187
+ return;
18188
+ }
18189
+ }
18190
+ } catch {
18191
+ }
18192
+ setOtpSubmitting(false);
17891
18193
  setView("amount");
17892
- } else {
17893
- setOtpError("Incorrect code. Please try again.");
17894
- setPhoneCode("");
18194
+ return;
17895
18195
  }
18196
+ setOtpError("Incorrect code. Please try again.");
18197
+ setPhoneCode("");
18198
+ setOtpSubmitting(false);
17896
18199
  } catch (err) {
17897
18200
  setOtpError(
17898
18201
  prettifyVerificationError(err instanceof Error ? err.message : "Verification failed")
17899
18202
  );
17900
18203
  setPhoneCode("");
17901
- } finally {
17902
18204
  setOtpSubmitting(false);
17903
18205
  }
17904
18206
  }, [
@@ -17906,22 +18208,25 @@ var BuyWithApplePay = React52.forwardRef(
17906
18208
  clientSecret,
17907
18209
  phoneCode,
17908
18210
  publishableKey,
17909
- persistContact,
18211
+ storeApplePaySession,
17910
18212
  amountUsd,
17911
- otpSubmitting
18213
+ otpSubmitting,
18214
+ refetchApplePayLimits,
18215
+ getViewForLimitStatus,
18216
+ applyLimitRouting
17912
18217
  ]);
17913
18218
  const prepareSession = (0, import_react17.useCallback)(
17914
18219
  async (token, amt) => {
18220
+ setErrorMessage("");
17915
18221
  if (!destinationChainType || !destinationChainId) {
17916
18222
  setErrorMessage("Deposit destination not configured. Please contact support.");
17917
18223
  return;
17918
18224
  }
17919
- const destinationNetwork = destinationChainNameFor(
17920
- destinationChainType,
17921
- destinationChainId
17922
- );
17923
- if (!destinationNetwork) {
17924
- setErrorMessage("Coinbase Apple Pay is not available for this network.");
18225
+ if (defaultTokenLoading) {
18226
+ return;
18227
+ }
18228
+ if (defaultTokenError || !defaultToken) {
18229
+ setErrorMessage("Unable to load token information. Please try again.");
17925
18230
  return;
17926
18231
  }
17927
18232
  const settlementAddress = depositWallet?.address;
@@ -17932,19 +18237,17 @@ var BuyWithApplePay = React52.forwardRef(
17932
18237
  sessionAbortRef.current?.abort();
17933
18238
  const controller = new AbortController();
17934
18239
  sessionAbortRef.current = controller;
17935
- setPreparingSession(true);
17936
- setErrorMessage("");
17937
18240
  try {
17938
18241
  const externalId = generatePrefixedKSUID("orsext");
17939
18242
  const session = await createCoinbaseApplePaySession(
17940
18243
  {
17941
18244
  source_currency: "usd",
17942
18245
  source_amount: amt,
17943
- destination_currency: destinationTokenSymbol.toLowerCase(),
17944
- destination_network: destinationNetwork,
18246
+ destination_currency: defaultToken.destination_currency,
18247
+ destination_network: defaultToken.destination_network,
17945
18248
  wallet_address: settlementAddress,
17946
18249
  external_id: externalId,
17947
- ...externalUserEmail ? { email: externalUserEmail } : {}
18250
+ ...userEmail ? { email: userEmail } : {}
17948
18251
  },
17949
18252
  token,
17950
18253
  publishableKey,
@@ -17988,18 +18291,16 @@ var BuyWithApplePay = React52.forwardRef(
17988
18291
  setPaymentSession(null);
17989
18292
  setPaymentSessionAmount(null);
17990
18293
  setErrorMessage("Unable to process your request. Please try again later.");
17991
- } finally {
17992
- if (sessionAbortRef.current === controller) {
17993
- setPreparingSession(false);
17994
- }
17995
18294
  }
17996
18295
  },
17997
18296
  [
17998
- destinationTokenSymbol,
17999
18297
  destinationChainType,
18000
18298
  destinationChainId,
18299
+ defaultToken,
18300
+ defaultTokenLoading,
18301
+ defaultTokenError,
18001
18302
  depositWallet?.address,
18002
- externalUserEmail,
18303
+ userEmail,
18003
18304
  publishableKey,
18004
18305
  onEvent,
18005
18306
  userId
@@ -18043,42 +18344,8 @@ var BuyWithApplePay = React52.forwardRef(
18043
18344
  if (view === "loading_config") {
18044
18345
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-16", style: containerStyle, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LoaderCircle, { className: "uf-w-6 uf-h-6 uf-animate-spin", style: { color: colors2.primary } }) });
18045
18346
  }
18046
- if (view === "disabled") {
18047
- return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
18048
- "div",
18049
- {
18050
- className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-12 uf-px-4",
18051
- style: containerStyle,
18052
- children: [
18053
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18054
- CircleAlert,
18055
- {
18056
- className: "uf-w-8 uf-h-8 uf-mb-4",
18057
- style: { color: colors2.foregroundMuted }
18058
- }
18059
- ),
18060
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18061
- "h3",
18062
- {
18063
- className: "uf-text-base uf-font-medium uf-mb-1",
18064
- style: { color: colors2.foreground, fontFamily: fonts.medium },
18065
- children: "Apple Pay is unavailable"
18066
- }
18067
- ),
18068
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18069
- "p",
18070
- {
18071
- className: "uf-text-sm uf-text-center",
18072
- style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18073
- children: "Apple Pay is disabled for this project. Try another payment method."
18074
- }
18075
- )
18076
- ]
18077
- }
18078
- );
18079
- }
18080
18347
  if (view === "email_input") {
18081
- const emailValid = EMAIL_REGEX.test(email);
18348
+ const emailValid = EMAIL_REGEX2.test(email);
18082
18349
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "uf-flex uf-flex-col uf-pb-1 uf-pt-2", style: containerStyle, children: [
18083
18350
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18084
18351
  "label",
@@ -18095,9 +18362,7 @@ var BuyWithApplePay = React52.forwardRef(
18095
18362
  value: email,
18096
18363
  onChange: (e) => setEmail(e.target.value.trim()),
18097
18364
  onKeyDown: (e) => {
18098
- if (e.key === "Enter" && emailValid) {
18099
- setView("phone_input");
18100
- }
18365
+ if (e.key === "Enter" && emailValid) setView("phone_input");
18101
18366
  },
18102
18367
  placeholder: "you@example.com",
18103
18368
  autoComplete: "email",
@@ -18133,7 +18398,7 @@ var BuyWithApplePay = React52.forwardRef(
18133
18398
  }
18134
18399
  if (view === "phone_input" || view === "submitting_session") {
18135
18400
  const submitting = view === "submitting_session";
18136
- const phoneValid = PHONE_REGEX.test(normalizedPhone);
18401
+ const phoneValid = PHONE_REGEX2.test(normalizedPhone);
18137
18402
  const rawDigits = (() => {
18138
18403
  const digits = phoneInput.replace(/\D/g, "");
18139
18404
  return digits.startsWith("1") ? digits.slice(1, 11) : digits.slice(0, 10);
@@ -18214,15 +18479,7 @@ var BuyWithApplePay = React52.forwardRef(
18214
18479
  !phoneInput && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "uf-text-xs uf-mb-2 uf-px-1", style: { color: colors2.foregroundMuted }, children: "Re-verified every 60 days." }),
18215
18480
  errorMessage && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "uf-text-xs uf-mt-2 uf-px-1", style: { color: colors2.error }, children: errorMessage }),
18216
18481
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "uf-flex-1" }),
18217
- /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18218
- LegalDisclaimer,
18219
- {
18220
- legalAgreements,
18221
- loading: legalAgreementsLoading,
18222
- colors: colors2,
18223
- fonts
18224
- }
18225
- ),
18482
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LegalDisclaimer, { legalAgreements, loading: legalAgreementsLoading }),
18226
18483
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18227
18484
  "button",
18228
18485
  {
@@ -18241,12 +18498,9 @@ var BuyWithApplePay = React52.forwardRef(
18241
18498
  )
18242
18499
  ] });
18243
18500
  }
18244
- if (view === "email_otp" || view === "phone_otp") {
18245
- const isEmail = view === "email_otp";
18246
- const code = isEmail ? emailCode : phoneCode;
18247
- const setCode = isEmail ? setEmailCode : setPhoneCode;
18248
- const target = isEmail ? maskEmail(email) : maskPhone(normalizedPhone);
18249
- const submit = isEmail ? submitEmailOtp : submitPhoneOtp;
18501
+ if (view === "phone_otp") {
18502
+ const code = phoneCode;
18503
+ const target = maskPhone(normalizedPhone);
18250
18504
  const canSubmit = code.length === 6 && !otpSubmitting;
18251
18505
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "uf-flex uf-flex-col uf-pb-1 uf-items-center uf-pt-2", style: containerStyle, children: [
18252
18506
  /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
@@ -18269,13 +18523,12 @@ var BuyWithApplePay = React52.forwardRef(
18269
18523
  maxLength: 6,
18270
18524
  value: code,
18271
18525
  onChange: (e) => {
18272
- const v = e.target.value.replace(/\D/g, "").slice(0, 6);
18273
- setCode(v);
18526
+ setPhoneCode(e.target.value.replace(/\D/g, "").slice(0, 6));
18274
18527
  setOtpError(null);
18275
18528
  },
18276
18529
  onKeyDown: (e) => {
18277
18530
  if (e.key === "Enter" && code.length === 6 && !otpSubmitting) {
18278
- void submit();
18531
+ void submitPhoneOtp();
18279
18532
  }
18280
18533
  },
18281
18534
  autoFocus: true,
@@ -18302,7 +18555,7 @@ var BuyWithApplePay = React52.forwardRef(
18302
18555
  if (!verificationSession || !clientSecret) return;
18303
18556
  void sendOnrampVerificationOtp(
18304
18557
  verificationSession.id,
18305
- isEmail ? "email" : "phone",
18558
+ "phone",
18306
18559
  clientSecret,
18307
18560
  publishableKey
18308
18561
  ).then(() => setResendCooldown(30));
@@ -18315,7 +18568,7 @@ var BuyWithApplePay = React52.forwardRef(
18315
18568
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18316
18569
  "button",
18317
18570
  {
18318
- onClick: () => void submit(),
18571
+ onClick: submitPhoneOtp,
18319
18572
  disabled: !canSubmit,
18320
18573
  className: "uf-w-full uf-py-3 uf-mt-6 uf-text-sm uf-font-medium uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed uf-flex uf-items-center uf-justify-center uf-gap-2",
18321
18574
  style: {
@@ -18463,7 +18716,7 @@ var BuyWithApplePay = React52.forwardRef(
18463
18716
  border: `${components.button.borderWidth}px solid ${components.button.borderColor}`,
18464
18717
  opacity: 0.5
18465
18718
  },
18466
- children: !hasInput || !validAmount ? "Enter amount" : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
18719
+ children: !hasInput || !validAmount ? "Enter amount" : errorMessage ? "Unable to prepare Apple Pay" : defaultTokenLoading ? "Loading token information\u2026" : defaultTokenError ? "Token routing unavailable" : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
18467
18720
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LoaderCircle, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
18468
18721
  "Preparing Apple Pay"
18469
18722
  ] })
@@ -18501,7 +18754,104 @@ var BuyWithApplePay = React52.forwardRef(
18501
18754
  {
18502
18755
  className: "uf-text-xl uf-mb-2 uf-text-center",
18503
18756
  style: { color: colors2.foreground, fontFamily: fonts.medium },
18504
- children: "Checking for your deposit\u2026"
18757
+ children: "Checking for your deposit\u2026"
18758
+ }
18759
+ ),
18760
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18761
+ "p",
18762
+ {
18763
+ className: "uf-text-sm uf-text-center uf-max-w-[280px]",
18764
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18765
+ children: "Return if the payment is not made."
18766
+ }
18767
+ )
18768
+ ]
18769
+ }
18770
+ );
18771
+ }
18772
+ if (view === "limit_upgrade_intro") {
18773
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "uf-flex uf-flex-col uf-pt-8 uf-pb-2 uf-px-2", style: containerStyle, children: [
18774
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18775
+ "h3",
18776
+ {
18777
+ className: "uf-text-xl uf-mb-3 uf-text-center",
18778
+ style: { color: colors2.foreground, fontFamily: fonts.medium },
18779
+ children: "Apple Pay limit reached"
18780
+ }
18781
+ ),
18782
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18783
+ "p",
18784
+ {
18785
+ className: "uf-text-sm uf-text-center uf-mb-10 uf-max-w-[320px] uf-mx-auto",
18786
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18787
+ children: "Submit your date of birth and SSN to increase your Apple Pay limit."
18788
+ }
18789
+ ),
18790
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18791
+ "button",
18792
+ {
18793
+ onClick: () => {
18794
+ setLimitUpgradeError(null);
18795
+ setView("limit_upgrade_form");
18796
+ },
18797
+ className: "uf-w-full uf-py-3 uf-mb-2 uf-text-sm uf-font-medium uf-transition-colors",
18798
+ style: {
18799
+ backgroundColor: colors2.primary,
18800
+ color: colors2.primaryForeground,
18801
+ fontFamily: fonts.medium,
18802
+ borderRadius: components.button.borderRadius,
18803
+ border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
18804
+ },
18805
+ children: "Continue"
18806
+ }
18807
+ ),
18808
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18809
+ "button",
18810
+ {
18811
+ onClick: () => {
18812
+ setLimitUpgradeError(null);
18813
+ onExit?.();
18814
+ },
18815
+ className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors",
18816
+ style: {
18817
+ backgroundColor: "transparent",
18818
+ color: colors2.error,
18819
+ fontFamily: fonts.medium,
18820
+ borderRadius: components.button.borderRadius,
18821
+ border: `${components.button.borderWidth}px solid transparent`
18822
+ },
18823
+ children: "Cancel"
18824
+ }
18825
+ )
18826
+ ] });
18827
+ }
18828
+ if (view === "limit_upgrade_submitting") {
18829
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
18830
+ "div",
18831
+ {
18832
+ className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-16 uf-px-4",
18833
+ style: containerStyle,
18834
+ children: [
18835
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18836
+ "div",
18837
+ {
18838
+ className: "uf-w-20 uf-h-20 uf-rounded-full uf-flex uf-items-center uf-justify-center uf-mb-6",
18839
+ style: { backgroundColor: `${colors2.primary}20` },
18840
+ children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18841
+ LoaderCircle,
18842
+ {
18843
+ className: "uf-w-10 uf-h-10 uf-animate-spin",
18844
+ style: { color: colors2.primary }
18845
+ }
18846
+ )
18847
+ }
18848
+ ),
18849
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18850
+ "h3",
18851
+ {
18852
+ className: "uf-text-xl uf-mb-2 uf-text-center",
18853
+ style: { color: colors2.foreground, fontFamily: fonts.medium },
18854
+ children: "Verifying your information"
18505
18855
  }
18506
18856
  ),
18507
18857
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
@@ -18509,13 +18859,184 @@ var BuyWithApplePay = React52.forwardRef(
18509
18859
  {
18510
18860
  className: "uf-text-sm uf-text-center uf-max-w-[280px]",
18511
18861
  style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18512
- children: "Return if the payment is not made."
18862
+ children: "Your limit increase request is under review. This usually takes just a few seconds."
18513
18863
  }
18514
18864
  )
18515
18865
  ]
18516
18866
  }
18517
18867
  );
18518
18868
  }
18869
+ if (view === "limit_upgrade_form") {
18870
+ const dobValid = isDobInputValid(dobInput);
18871
+ const ssnValid = /^\d{4}$/.test(ssnLast4);
18872
+ const formValid = dobValid && ssnValid;
18873
+ const formInputStyle = {
18874
+ backgroundColor: components.card.backgroundColor,
18875
+ color: components.input.textColor,
18876
+ fontFamily: fonts.regular,
18877
+ borderRadius: components.card.borderRadius,
18878
+ border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
18879
+ };
18880
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "uf-flex uf-flex-col uf-pb-1 uf-pt-2", style: containerStyle, children: [
18881
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18882
+ "label",
18883
+ {
18884
+ className: "uf-text-xs uf-font-medium uf-mb-1.5 uf-px-1",
18885
+ style: { color: components.card.labelColor, fontFamily: fonts.medium },
18886
+ children: "Date of birth"
18887
+ }
18888
+ ),
18889
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18890
+ "input",
18891
+ {
18892
+ type: "text",
18893
+ inputMode: "numeric",
18894
+ maxLength: 10,
18895
+ value: dobInput,
18896
+ onChange: (e) => {
18897
+ setDobInput(formatDobInput(e.target.value));
18898
+ if (limitUpgradeError) setLimitUpgradeError(null);
18899
+ },
18900
+ onKeyDown: (e) => {
18901
+ if (e.key === "Enter" && formValid) void submitLimitUpgrade();
18902
+ },
18903
+ placeholder: "MM/DD/YYYY",
18904
+ autoComplete: "bday",
18905
+ "aria-label": "Date of birth",
18906
+ className: "uf-w-full uf-px-3 uf-py-3 uf-mb-3 uf-text-sm uf-outline-none",
18907
+ style: formInputStyle
18908
+ }
18909
+ ),
18910
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18911
+ "label",
18912
+ {
18913
+ className: "uf-text-xs uf-font-medium uf-mb-1.5 uf-px-1",
18914
+ style: { color: components.card.labelColor, fontFamily: fonts.medium },
18915
+ children: "Last 4 of SSN"
18916
+ }
18917
+ ),
18918
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18919
+ "input",
18920
+ {
18921
+ type: "password",
18922
+ inputMode: "numeric",
18923
+ pattern: "[0-9]*",
18924
+ maxLength: 4,
18925
+ value: ssnLast4,
18926
+ onChange: (e) => {
18927
+ setSsnLast4(e.target.value.replace(/\D/g, "").slice(0, 4));
18928
+ if (limitUpgradeError) setLimitUpgradeError(null);
18929
+ },
18930
+ onKeyDown: (e) => {
18931
+ if (e.key === "Enter" && formValid) void submitLimitUpgrade();
18932
+ },
18933
+ placeholder: "\u2022\u2022\u2022\u2022",
18934
+ autoComplete: "off",
18935
+ name: "off",
18936
+ autoCorrect: "off",
18937
+ autoCapitalize: "none",
18938
+ spellCheck: false,
18939
+ "data-1p-ignore": "true",
18940
+ "data-lpignore": "true",
18941
+ "data-form-type": "other",
18942
+ "aria-label": "Last 4 digits of SSN",
18943
+ "aria-autocomplete": "none",
18944
+ className: "uf-w-full uf-px-3 uf-py-3 uf-mb-2 uf-text-sm uf-outline-none",
18945
+ style: formInputStyle
18946
+ }
18947
+ ),
18948
+ limitUpgradeError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18949
+ "div",
18950
+ {
18951
+ className: "uf-text-xs uf-mt-2 uf-px-1",
18952
+ style: { color: colors2.error, fontFamily: fonts.regular },
18953
+ children: limitUpgradeError
18954
+ }
18955
+ ),
18956
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "uf-flex-1" }),
18957
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18958
+ "button",
18959
+ {
18960
+ onClick: () => void submitLimitUpgrade(),
18961
+ disabled: !formValid || upgradeSubmitting,
18962
+ className: "uf-w-full uf-py-3 uf-mt-3 uf-text-sm uf-font-medium uf-transition-colors disabled:uf-opacity-50 disabled:uf-cursor-not-allowed",
18963
+ style: {
18964
+ backgroundColor: colors2.primary,
18965
+ color: colors2.primaryForeground,
18966
+ fontFamily: fonts.medium,
18967
+ borderRadius: components.button.borderRadius,
18968
+ border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
18969
+ },
18970
+ children: upgradeSubmitting ? /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2", children: [
18971
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(LoaderCircle, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
18972
+ "Submitting\u2026"
18973
+ ] }) : "Submit"
18974
+ }
18975
+ )
18976
+ ] });
18977
+ }
18978
+ if (view === "limit_upgrade_failed") {
18979
+ return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "uf-flex uf-flex-col uf-pt-8 uf-pb-2 uf-px-2", style: containerStyle, children: [
18980
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18981
+ "h3",
18982
+ {
18983
+ className: "uf-text-xl uf-mb-3 uf-text-center",
18984
+ style: { color: colors2.foreground, fontFamily: fonts.medium },
18985
+ children: "Apple Pay limit reached"
18986
+ }
18987
+ ),
18988
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
18989
+ "p",
18990
+ {
18991
+ className: "uf-text-sm uf-text-center uf-mb-2 uf-max-w-[320px] uf-mx-auto",
18992
+ style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18993
+ children: [
18994
+ "Failed to increase. Please try again later or",
18995
+ " ",
18996
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
18997
+ "a",
18998
+ {
18999
+ href: UNIFOLD_SUPPORT_URL,
19000
+ target: "_blank",
19001
+ rel: "noreferrer noopener",
19002
+ className: "uf-underline",
19003
+ style: { color: colors2.primary },
19004
+ children: "contact support"
19005
+ }
19006
+ ),
19007
+ "."
19008
+ ]
19009
+ }
19010
+ ),
19011
+ limitUpgradeError && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
19012
+ "p",
19013
+ {
19014
+ className: "uf-text-xs uf-text-center uf-mb-2 uf-px-2",
19015
+ style: { color: colors2.error, fontFamily: fonts.regular },
19016
+ children: limitUpgradeError
19017
+ }
19018
+ ),
19019
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { className: "uf-mb-8" }),
19020
+ /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
19021
+ "button",
19022
+ {
19023
+ onClick: () => {
19024
+ setLimitUpgradeError(null);
19025
+ onExit?.();
19026
+ },
19027
+ className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors",
19028
+ style: {
19029
+ backgroundColor: colors2.primary,
19030
+ color: colors2.primaryForeground,
19031
+ fontFamily: fonts.medium,
19032
+ borderRadius: components.button.borderRadius,
19033
+ border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
19034
+ },
19035
+ children: "Return"
19036
+ }
19037
+ )
19038
+ ] });
19039
+ }
18519
19040
  if (view === "guest_limit_reached") {
18520
19041
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
18521
19042
  "div",
@@ -18536,7 +19057,7 @@ var BuyWithApplePay = React52.forwardRef(
18536
19057
  {
18537
19058
  className: "uf-text-sm uf-text-center uf-mb-12 uf-max-w-[300px]",
18538
19059
  style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
18539
- children: "Your account has reached Apple Pay limit. It's not eligible for an increase right now."
19060
+ children: "Your account is not eligible for a limit increase at this time."
18540
19061
  }
18541
19062
  ),
18542
19063
  /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
@@ -18562,7 +19083,95 @@ var BuyWithApplePay = React52.forwardRef(
18562
19083
  }
18563
19084
  );
18564
19085
  BuyWithApplePay.displayName = "BuyWithApplePay";
18565
- function LegalDisclaimer({ legalAgreements, loading, colors: colors2, fonts }) {
19086
+ function formatPhoneInput(raw) {
19087
+ const digits = raw.replace(/\D/g, "");
19088
+ if (raw.startsWith("+")) {
19089
+ return `+${digits}`;
19090
+ }
19091
+ if (digits.length === 10) return `+1${digits}`;
19092
+ if (digits.length === 11 && digits.startsWith("1")) return `+${digits}`;
19093
+ return digits.length > 0 ? `+${digits}` : "";
19094
+ }
19095
+ function maskPhone(phone) {
19096
+ if (!/^\+1\d{10}$/.test(phone)) return phone;
19097
+ return `+1 (***) ***-${phone.slice(-4)}`;
19098
+ }
19099
+ function isGuestLimitError(err) {
19100
+ const message = err instanceof Error ? err.message : String(err ?? "");
19101
+ if (/coinbase_onramp_guest_limit_reached/i.test(message)) return true;
19102
+ if (/guest_(daily_)?transaction_(count|limit)/i.test(message)) return true;
19103
+ return false;
19104
+ }
19105
+ function isLimitUpgradeTerminalBlock(message) {
19106
+ if (/coinbase_onramp_guest_limit_reached/i.test(message)) return true;
19107
+ if (/limit upgrade is not available/i.test(message)) return true;
19108
+ if (/limits.?upgrade.?blocked/i.test(message)) return true;
19109
+ return false;
19110
+ }
19111
+ function prettifyVerificationError(message) {
19112
+ if (/\b429\b|too many requests|rate.?limit|throttle/i.test(message)) {
19113
+ return "Too many attempts. Please wait a few minutes and try again.";
19114
+ }
19115
+ if (/network|failed to fetch|abort/i.test(message)) {
19116
+ return "Network error. Check your connection and try again.";
19117
+ }
19118
+ if (/voip|not a valid US|not a cell/i.test(message)) {
19119
+ return "We can only verify real US cell phones (not VoIP). Try a different number.";
19120
+ }
19121
+ const cleaned = message.replace(/\s*\[[\w_]+\]:\s*.*$/, "").trim();
19122
+ return cleaned || message;
19123
+ }
19124
+ function formatDobInput(raw) {
19125
+ const digits = raw.replace(/\D/g, "").slice(0, 8);
19126
+ if (digits.length <= 2) return digits;
19127
+ if (digits.length <= 4) return `${digits.slice(0, 2)}/${digits.slice(2)}`;
19128
+ return `${digits.slice(0, 2)}/${digits.slice(2, 4)}/${digits.slice(4)}`;
19129
+ }
19130
+ function isDobInputValid(input) {
19131
+ return parseDobInput(input) !== null;
19132
+ }
19133
+ function parseDobInput(input) {
19134
+ const m = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(input);
19135
+ if (!m) return null;
19136
+ const [, month, day, year] = m;
19137
+ if (!/^(0[1-9]|1[0-2])$/.test(month)) return null;
19138
+ if (!/^(0[1-9]|[12]\d|3[01])$/.test(day)) return null;
19139
+ if (!/^(19|20)\d{2}$/.test(year)) return null;
19140
+ return { month, day, year };
19141
+ }
19142
+ var POPUP_W = 500;
19143
+ var POPUP_H = 700;
19144
+ function openCoinbasePaymentPopup(url) {
19145
+ if (typeof window === "undefined") return null;
19146
+ const screenW = window.screen.availWidth ?? window.innerWidth;
19147
+ const screenH = window.screen.availHeight ?? window.innerHeight;
19148
+ const left = Math.max(0, Math.round((screenW - POPUP_W) / 2));
19149
+ const top = Math.max(0, Math.round((screenH - POPUP_H) / 2));
19150
+ return window.open(
19151
+ url,
19152
+ "unifold_coinbase_apple_pay",
19153
+ `popup,width=${POPUP_W},height=${POPUP_H},left=${left},top=${top}`
19154
+ );
19155
+ }
19156
+ var FALLBACK_AGREEMENTS = [
19157
+ {
19158
+ key: "guest_checkout_terms",
19159
+ name: "Guest Checkout Terms of Service",
19160
+ url: "https://www.coinbase.com/legal/cb-pay/onramp-guest-checkout-terms"
19161
+ },
19162
+ {
19163
+ key: "user_agreement",
19164
+ name: "User Agreement",
19165
+ url: "https://www.coinbase.com/legal/user_agreement"
19166
+ },
19167
+ {
19168
+ key: "privacy_policy",
19169
+ name: "Privacy Policy",
19170
+ url: "https://www.coinbase.com/legal/privacy"
19171
+ }
19172
+ ];
19173
+ function LegalDisclaimer({ legalAgreements, loading }) {
19174
+ const { colors: colors2, fonts } = useTheme();
18566
19175
  if (loading) {
18567
19176
  return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
18568
19177
  "div",
@@ -18606,78 +19215,6 @@ function LegalDisclaimer({ legalAgreements, loading, colors: colors2, fonts }) {
18606
19215
  }
18607
19216
  );
18608
19217
  }
18609
- function isGuestLimitError(err) {
18610
- const message = err instanceof Error ? err.message : String(err ?? "");
18611
- if (/coinbase_onramp_guest_limit_reached/i.test(message)) return true;
18612
- if (/guest_(daily_)?transaction_(count|limit)/i.test(message)) return true;
18613
- return false;
18614
- }
18615
- function prettifyVerificationError(message) {
18616
- if (/\b429\b|too many requests|rate.?limit|throttle/i.test(message)) {
18617
- return "Too many attempts. Please wait a few minutes and try again.";
18618
- }
18619
- if (/network|failed to fetch|abort/i.test(message)) {
18620
- return "Network error. Check your connection and try again.";
18621
- }
18622
- if (/voip|not a valid US|not a cell/i.test(message)) {
18623
- return "We can only verify real US cell phones (not VoIP). Try a different number.";
18624
- }
18625
- return message;
18626
- }
18627
- var FALLBACK_AGREEMENTS = [
18628
- {
18629
- key: "guest_checkout_terms",
18630
- name: "Guest Checkout Terms of Service",
18631
- url: "https://www.coinbase.com/legal/cb-pay/onramp-guest-checkout-terms"
18632
- },
18633
- {
18634
- key: "user_agreement",
18635
- name: "User Agreement",
18636
- url: "https://www.coinbase.com/legal/user_agreement"
18637
- },
18638
- {
18639
- key: "privacy_policy",
18640
- name: "Privacy Policy",
18641
- url: "https://www.coinbase.com/legal/privacy"
18642
- }
18643
- ];
18644
- var POPUP_W = 500;
18645
- var POPUP_H = 700;
18646
- function openCoinbasePaymentPopup(url) {
18647
- if (typeof window === "undefined") return null;
18648
- const screenW = window.screen.availWidth ?? window.innerWidth;
18649
- const screenH = window.screen.availHeight ?? window.innerHeight;
18650
- const left = Math.max(0, Math.round((screenW - POPUP_W) / 2));
18651
- const top = Math.max(0, Math.round((screenH - POPUP_H) / 2));
18652
- return window.open(
18653
- url,
18654
- "unifold_coinbase_apple_pay",
18655
- `popup,width=${POPUP_W},height=${POPUP_H},left=${left},top=${top}`
18656
- );
18657
- }
18658
- function destinationChainNameFor(chainType, chainId) {
18659
- if (chainType === "solana") return "solana";
18660
- if (chainType === "bitcoin") return "bitcoin";
18661
- if (chainType === "ethereum") {
18662
- switch (chainId) {
18663
- case "1":
18664
- return "ethereum";
18665
- case "8453":
18666
- return "base";
18667
- case "137":
18668
- return "polygon";
18669
- case "43114":
18670
- return "avalanche";
18671
- case "42161":
18672
- return "arbitrum";
18673
- case "10":
18674
- return "optimism";
18675
- default:
18676
- return null;
18677
- }
18678
- }
18679
- return null;
18680
- }
18681
19218
  var t2 = i18n2.payWithExchange;
18682
19219
  function PayWithExchange({
18683
19220
  userId,
@@ -18692,10 +19229,10 @@ function PayWithExchange({
18692
19229
  defaultToken
18693
19230
  }) {
18694
19231
  const { colors: colors2, fonts, components } = useTheme();
18695
- const [internalView, setInternalView] = (0, import_react18.useState)("providers");
18696
- const [exchangeSession, setExchangeSession] = (0, import_react18.useState)(null);
18697
- const [sessionError, setSessionError] = (0, import_react18.useState)(null);
18698
- const [hoveredIndex, setHoveredIndex] = (0, import_react18.useState)(null);
19232
+ const [internalView, setInternalView] = (0, import_react19.useState)("providers");
19233
+ const [exchangeSession, setExchangeSession] = (0, import_react19.useState)(null);
19234
+ const [sessionError, setSessionError] = (0, import_react19.useState)(null);
19235
+ const [hoveredIndex, setHoveredIndex] = (0, import_react19.useState)(null);
18699
19236
  const currentView = externalView ?? internalView;
18700
19237
  const depositWalletId = wallets.find((w) => ["ethereum", "solana"].includes(w.chain_type))?.id;
18701
19238
  const handleViewChange = (newView) => {
@@ -18975,7 +19512,7 @@ function QRCodeSkeleton({ size: size4 = 180, darkMode = false }) {
18975
19512
  const spacing = size4 / gridCount;
18976
19513
  const fillColor = darkMode ? "rgba(255,255,255,0.10)" : "rgba(0,0,0,0.08)";
18977
19514
  const cornerColor = darkMode ? "rgba(255,255,255,0.14)" : "rgba(0,0,0,0.12)";
18978
- const dots = (0, import_react20.useMemo)(() => {
19515
+ const dots = (0, import_react21.useMemo)(() => {
18979
19516
  const result = [];
18980
19517
  const cornerSize = 7;
18981
19518
  const centerStart = Math.floor(gridCount / 2) - 2;
@@ -19030,10 +19567,10 @@ function StyledQRCode({
19030
19567
  imageSize = 45,
19031
19568
  darkMode = false
19032
19569
  }) {
19033
- const containerRef = (0, import_react20.useRef)(null);
19034
- const qrRef = (0, import_react20.useRef)(null);
19035
- const [ready, setReady] = (0, import_react20.useState)(false);
19036
- (0, import_react20.useEffect)(() => {
19570
+ const containerRef = (0, import_react21.useRef)(null);
19571
+ const qrRef = (0, import_react21.useRef)(null);
19572
+ const [ready, setReady] = (0, import_react21.useState)(false);
19573
+ (0, import_react21.useEffect)(() => {
19037
19574
  if (!containerRef.current || !value) return;
19038
19575
  const config = createQRConfig(value, size4, imageUrl, imageSize, darkMode);
19039
19576
  if (!qrRef.current) {
@@ -19064,8 +19601,8 @@ function StyledQRCode({
19064
19601
  ] });
19065
19602
  }
19066
19603
  function useIsMobileViewport() {
19067
- const [isMobile, setIsMobile] = (0, import_react21.useState)(() => isMobileViewport());
19068
- (0, import_react21.useEffect)(() => {
19604
+ const [isMobile, setIsMobile] = (0, import_react22.useState)(() => isMobileViewport());
19605
+ (0, import_react22.useEffect)(() => {
19069
19606
  setIsMobile(isMobileViewport());
19070
19607
  const mql = window.matchMedia(MOBILE_VIEWPORT_MEDIA_QUERY);
19071
19608
  const update = () => setIsMobile(mql.matches);
@@ -19075,7 +19612,7 @@ function useIsMobileViewport() {
19075
19612
  return isMobile;
19076
19613
  }
19077
19614
  function useCashAppLimits({ publishableKey, currency = "usd" }) {
19078
- return (0, import_react_query7.useQuery)({
19615
+ return (0, import_react_query8.useQuery)({
19079
19616
  queryKey: ["unifold", "cashAppLimits", currency, publishableKey],
19080
19617
  queryFn: () => getCashAppLimits(currency, publishableKey),
19081
19618
  enabled: !!publishableKey,
@@ -19117,21 +19654,21 @@ function PayWithCashApp({
19117
19654
  const { data: limits, isLoading: limitsLoading } = useCashAppLimits({ publishableKey });
19118
19655
  const minUsd = limits?.minimum_amount ?? FALLBACK_MIN_USD;
19119
19656
  const maxUsd = limits?.maximum_amount ?? null;
19120
- const [amount, setAmount] = (0, import_react19.useState)("");
19121
- const [loading, setLoading] = (0, import_react19.useState)(false);
19122
- const [session, setSession] = (0, import_react19.useState)(null);
19123
- const [status, setStatus] = (0, import_react19.useState)("pending");
19124
- const [error, setError] = (0, import_react19.useState)(null);
19125
- const [copied, setCopied] = (0, import_react19.useState)(false);
19126
- const [view, setViewInternal] = (0, import_react19.useState)(controlledView ?? "amount");
19127
- const setView = (0, import_react19.useCallback)(
19657
+ const [amount, setAmount] = (0, import_react20.useState)("");
19658
+ const [loading, setLoading] = (0, import_react20.useState)(false);
19659
+ const [session, setSession] = (0, import_react20.useState)(null);
19660
+ const [status, setStatus] = (0, import_react20.useState)("pending");
19661
+ const [error, setError] = (0, import_react20.useState)(null);
19662
+ const [copied, setCopied] = (0, import_react20.useState)(false);
19663
+ const [view, setViewInternal] = (0, import_react20.useState)(controlledView ?? "amount");
19664
+ const setView = (0, import_react20.useCallback)(
19128
19665
  (v) => {
19129
19666
  setViewInternal(v);
19130
19667
  onViewChange?.(v);
19131
19668
  },
19132
19669
  [onViewChange]
19133
19670
  );
19134
- (0, import_react19.useEffect)(() => {
19671
+ (0, import_react20.useEffect)(() => {
19135
19672
  if (controlledView && controlledView !== view) {
19136
19673
  setViewInternal(controlledView);
19137
19674
  if (controlledView === "amount") {
@@ -19143,7 +19680,7 @@ function PayWithCashApp({
19143
19680
  }
19144
19681
  }
19145
19682
  }, [controlledView]);
19146
- const [timeLeft, setTimeLeft] = (0, import_react19.useState)(null);
19683
+ const [timeLeft, setTimeLeft] = (0, import_react20.useState)(null);
19147
19684
  const depositWalletId = wallets.find((w) => w.chain_type === "ethereum")?.id;
19148
19685
  const { executions, isPolling } = useDepositPolling({
19149
19686
  userId,
@@ -19154,7 +19691,7 @@ function PayWithCashApp({
19154
19691
  onDepositSuccess,
19155
19692
  onDepositError
19156
19693
  });
19157
- const handleAmountChange = (0, import_react19.useCallback)(
19694
+ const handleAmountChange = (0, import_react20.useCallback)(
19158
19695
  (raw) => {
19159
19696
  const cleaned = raw.replace(/[^0-9.]/g, "");
19160
19697
  const parts = cleaned.split(".");
@@ -19166,7 +19703,7 @@ function PayWithCashApp({
19166
19703
  },
19167
19704
  [onAmountChange]
19168
19705
  );
19169
- const handleCreateSession = (0, import_react19.useCallback)(async () => {
19706
+ const handleCreateSession = (0, import_react20.useCallback)(async () => {
19170
19707
  if (!amount || !recipientAddress || !destinationChainType || !destinationChainId || !destinationTokenAddress) {
19171
19708
  setError("Missing required fields");
19172
19709
  return;
@@ -19215,7 +19752,7 @@ function PayWithCashApp({
19215
19752
  onEvent,
19216
19753
  onDepositError
19217
19754
  ]);
19218
- (0, import_react19.useEffect)(() => {
19755
+ (0, import_react20.useEffect)(() => {
19219
19756
  if (!session || view !== "payment" && view !== "confirming") return;
19220
19757
  if (status === "completed" || status === "failed") return;
19221
19758
  const poll = async () => {
@@ -19239,8 +19776,8 @@ function PayWithCashApp({
19239
19776
  poll();
19240
19777
  return () => clearInterval(interval);
19241
19778
  }, [session, view, status, publishableKey, onDepositSuccess, onDepositError]);
19242
- const [softExpired, setSoftExpired] = (0, import_react19.useState)(false);
19243
- (0, import_react19.useEffect)(() => {
19779
+ const [softExpired, setSoftExpired] = (0, import_react20.useState)(false);
19780
+ (0, import_react20.useEffect)(() => {
19244
19781
  if (!session?.expires_at || view !== "payment") return;
19245
19782
  const expiresMs = new Date(session.expires_at).getTime();
19246
19783
  const tick = () => {
@@ -19254,12 +19791,12 @@ function PayWithCashApp({
19254
19791
  const interval = setInterval(tick, 1e3);
19255
19792
  return () => clearInterval(interval);
19256
19793
  }, [session, view, status]);
19257
- const handleCopy = (0, import_react19.useCallback)(async (text) => {
19794
+ const handleCopy = (0, import_react20.useCallback)(async (text) => {
19258
19795
  await navigator.clipboard.writeText(text);
19259
19796
  setCopied(true);
19260
19797
  setTimeout(() => setCopied(false), 2e3);
19261
19798
  }, []);
19262
- const handleRecreate = (0, import_react19.useCallback)(() => {
19799
+ const handleRecreate = (0, import_react20.useCallback)(() => {
19263
19800
  setSession(null);
19264
19801
  setStatus("pending");
19265
19802
  setError(null);
@@ -19588,43 +20125,6 @@ function PayWithCashApp({
19588
20125
  }
19589
20126
  return null;
19590
20127
  }
19591
- function useDefaultOnrampToken({
19592
- publishableKey,
19593
- tokenAddress,
19594
- chainId,
19595
- chainType,
19596
- countryCode,
19597
- subdivisionCode,
19598
- enabled = true
19599
- }) {
19600
- const { data: defaultToken, isLoading } = (0, import_react_query8.useQuery)({
19601
- queryKey: [
19602
- "unifold",
19603
- "defaultOnrampToken",
19604
- publishableKey,
19605
- tokenAddress,
19606
- chainId,
19607
- chainType,
19608
- countryCode,
19609
- subdivisionCode
19610
- ],
19611
- queryFn: () => getDefaultOnrampToken(
19612
- {
19613
- token_address: tokenAddress,
19614
- chain_id: chainId,
19615
- chain_type: chainType,
19616
- country_code: countryCode,
19617
- subdivision_code: subdivisionCode
19618
- },
19619
- publishableKey
19620
- ),
19621
- enabled: enabled && !!tokenAddress && !!chainId && !!chainType,
19622
- staleTime: 1e3 * 60 * 60,
19623
- refetchOnMount: false,
19624
- refetchOnWindowFocus: false
19625
- });
19626
- return { defaultToken, isLoading };
19627
- }
19628
20128
  function useBankTransferProviders({
19629
20129
  publishableKey,
19630
20130
  enabled = true,
@@ -19672,19 +20172,19 @@ function BankTransfer({
19672
20172
  onDepositError
19673
20173
  }) {
19674
20174
  const { colors: colors2, fonts, components } = useTheme();
19675
- const [internalView, setInternalView] = (0, import_react22.useState)("providers");
19676
- const [sessionError, setSessionError] = (0, import_react22.useState)(null);
19677
- const [hoveredId, setHoveredId] = (0, import_react22.useState)(null);
19678
- const [activeProvider, setActiveProvider] = (0, import_react22.useState)(null);
19679
- const [requestBase, setRequestBase] = (0, import_react22.useState)(null);
19680
- const [activeRequest, setActiveRequest] = (0, import_react22.useState)(null);
19681
- const [amount, setAmount] = (0, import_react22.useState)("");
20175
+ const [internalView, setInternalView] = (0, import_react23.useState)("providers");
20176
+ const [sessionError, setSessionError] = (0, import_react23.useState)(null);
20177
+ const [hoveredId, setHoveredId] = (0, import_react23.useState)(null);
20178
+ const [activeProvider, setActiveProvider] = (0, import_react23.useState)(null);
20179
+ const [requestBase, setRequestBase] = (0, import_react23.useState)(null);
20180
+ const [activeRequest, setActiveRequest] = (0, import_react23.useState)(null);
20181
+ const [amount, setAmount] = (0, import_react23.useState)("");
19682
20182
  const currentView = externalView ?? internalView;
19683
20183
  const setView = (v) => {
19684
20184
  setInternalView(v);
19685
20185
  onViewChange?.(v);
19686
20186
  };
19687
- (0, import_react22.useEffect)(() => {
20187
+ (0, import_react23.useEffect)(() => {
19688
20188
  if (externalView) setInternalView(externalView);
19689
20189
  }, [externalView]);
19690
20190
  const { userIpInfo } = useUserIp2();
@@ -19703,7 +20203,7 @@ function BankTransfer({
19703
20203
  countryCode: userIpInfo?.alpha2
19704
20204
  });
19705
20205
  const providers = providersResponse?.data ?? [];
19706
- const pollingWalletId = (0, import_react22.useMemo)(() => {
20206
+ const pollingWalletId = (0, import_react23.useMemo)(() => {
19707
20207
  if (!defaultToken) return void 0;
19708
20208
  return getWalletByChainType(
19709
20209
  wallets,
@@ -19724,7 +20224,7 @@ function BankTransfer({
19724
20224
  const currencySymbol = getCurrencySymbol2(sourceCurrency);
19725
20225
  const parsedAmount = parseFloat(amount);
19726
20226
  const amountValid = !!amount && Number.isFinite(parsedAmount) && parsedAmount >= MIN_AMOUNT;
19727
- const displayTokenSymbol = (0, import_react22.useMemo)(
20227
+ const displayTokenSymbol = (0, import_react23.useMemo)(
19728
20228
  () => destinationTokenSymbol?.toUpperCase() ?? defaultToken?.destination_token_metadata?.symbol?.toUpperCase() ?? defaultToken?.destination_currency?.toUpperCase() ?? "USDC",
19729
20229
  [destinationTokenSymbol, defaultToken]
19730
20230
  );
@@ -23699,16 +24199,114 @@ function AmexIcon({ size: size4 = 24 }) {
23699
24199
  )
23700
24200
  ] });
23701
24201
  }
24202
+ function ApplePayIcon({ size: size4 = 24, color = "#000" }) {
24203
+ const h = size4 * 0.62;
24204
+ const w = h * (512 / 210.2);
24205
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)("svg", { width: w, height: h, viewBox: "0 0 512 210.2", fill: "none", children: /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24206
+ "path",
24207
+ {
24208
+ fill: color,
24209
+ d: "M93.6,27.1C87.6,34.2,78,39.8,68.4,39c-1.2-9.6,3.5-19.8,9-26.1c6-7.3,16.5-12.5,25-12.9 C103.4,10,99.5,19.8,93.6,27.1 M102.3,40.9c-13.9-0.8-25.8,7.9-32.4,7.9c-6.7,0-16.8-7.5-27.8-7.3c-14.3,0.2-27.6,8.3-34.9,21.2 c-15,25.8-3.9,64,10.6,85c7.1,10.4,15.6,21.8,26.8,21.4c10.6-0.4,14.8-6.9,27.6-6.9c12.9,0,16.6,6.9,27.8,6.7 c11.6-0.2,18.9-10.4,26-20.8c8.1-11.8,11.4-23.3,11.6-23.9c-0.2-0.2-22.4-8.7-22.6-34.3c-0.2-21.4,17.5-31.6,18.3-32.2 C123.3,42.9,107.7,41.3,102.3,40.9 M182.6,11.9v155.9h24.2v-53.3h33.5c30.6,0,52.1-21,52.1-51.4c0-30.4-21.1-51.2-51.3-51.2H182.6z M206.8,32.3h27.9c21,0,33,11.2,33,30.9c0,19.7-12,31-33.1,31h-27.8V32.3z M336.6,169c15.2,0,29.3-7.7,35.7-19.9h0.5v18.7h22.4V90.2 c0-22.5-18-37-45.7-37c-25.7,0-44.7,14.7-45.4,34.9h21.8c1.8-9.6,10.7-15.9,22.9-15.9c14.8,0,23.1,6.9,23.1,19.6v8.6l-30.2,1.8 c-28.1,1.7-43.3,13.2-43.3,33.2C298.4,155.6,314.1,169,336.6,169z M343.1,150.5c-12.9,0-21.1-6.2-21.1-15.7c0-9.8,7.9-15.5,23-16.4 l26.9-1.7v8.8C371.9,140.1,359.5,150.5,343.1,150.5z M425.1,210.2c23.6,0,34.7-9,44.4-36.3L512,54.7h-24.6l-28.5,92.1h-0.5 l-28.5-92.1h-25.3l41,113.5l-2.2,6.9c-3.7,11.7-9.7,16.2-20.4,16.2c-1.9,0-5.6-0.2-7.1-0.4v18.7C417.3,210,423.3,210.2,425.1,210.2z"
24210
+ }
24211
+ ) });
24212
+ }
24213
+ function GooglePayIcon({ size: size4 = 24, color = "#202124" }) {
24214
+ const h = size4 * 0.62;
24215
+ const w = h * (80 / 38.1);
24216
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsxs)("svg", { width: w, height: h, viewBox: "0 0 80 38.1", fill: "none", children: [
24217
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24218
+ "path",
24219
+ {
24220
+ fill: color,
24221
+ d: "M37.8,19.7V29h-3V6h7.8c1.9,0,3.7,0.7,5.1,2c1.4,1.2,2.1,3,2.1,4.9c0,1.9-0.7,3.6-2.1,4.9c-1.4,1.3-3.1,2-5.1,2 L37.8,19.7L37.8,19.7z M37.8,8.8v8h5c1.1,0,2.2-0.4,2.9-1.2c1.6-1.5,1.6-4,0.1-5.5c0,0-0.1-0.1-0.1-0.1c-0.8-0.8-1.8-1.3-2.9-1.2 L37.8,8.8L37.8,8.8z"
24222
+ }
24223
+ ),
24224
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24225
+ "path",
24226
+ {
24227
+ fill: color,
24228
+ d: "M56.7,12.8c2.2,0,3.9,0.6,5.2,1.8s1.9,2.8,1.9,4.8V29H61v-2.2h-0.1c-1.2,1.8-2.9,2.7-4.9,2.7 c-1.7,0-3.2-0.5-4.4-1.5c-1.1-1-1.8-2.4-1.8-3.9c0-1.6,0.6-2.9,1.8-3.9c1.2-1,2.9-1.4,4.9-1.4c1.8,0,3.2,0.3,4.3,1v-0.7 c0-1-0.4-2-1.2-2.6c-0.8-0.7-1.8-1.1-2.9-1.1c-1.7,0-3,0.7-3.9,2.1l-2.6-1.6C51.8,13.8,53.9,12.8,56.7,12.8z M52.9,24.2 c0,0.8,0.4,1.5,1,1.9c0.7,0.5,1.5,0.8,2.3,0.8c1.2,0,2.4-0.5,3.3-1.4c1-0.9,1.5-2,1.5-3.2c-0.9-0.7-2.2-1.1-3.9-1.1 c-1.2,0-2.2,0.3-3,0.9C53.3,22.6,52.9,23.3,52.9,24.2z"
24229
+ }
24230
+ ),
24231
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24232
+ "path",
24233
+ {
24234
+ fill: color,
24235
+ d: "M80,13.3l-9.9,22.7h-3l3.7-7.9l-6.5-14.7h3.2l4.7,11.3h0.1l4.6-11.3H80z"
24236
+ }
24237
+ ),
24238
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24239
+ "path",
24240
+ {
24241
+ fill: "#4285F4",
24242
+ d: "M25.9,17.7c0-0.9-0.1-1.8-0.2-2.7H13.2v5.1h7.1c-0.3,1.6-1.2,3.1-2.6,4v3.3H22C24.5,25.1,25.9,21.7,25.9,17.7z"
24243
+ }
24244
+ ),
24245
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24246
+ "path",
24247
+ {
24248
+ fill: "#34A853",
24249
+ d: "M13.2,30.6c3.6,0,6.6-1.2,8.8-3.2l-4.3-3.3c-1.2,0.8-2.7,1.3-4.5,1.3c-3.4,0-6.4-2.3-7.4-5.5H1.4v3.4 C3.7,27.8,8.2,30.6,13.2,30.6z"
24250
+ }
24251
+ ),
24252
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24253
+ "path",
24254
+ {
24255
+ fill: "#FBBC04",
24256
+ d: "M5.8,19.9c-0.6-1.6-0.6-3.4,0-5.1v-3.4H1.4c-1.9,3.7-1.9,8.1,0,11.9L5.8,19.9z"
24257
+ }
24258
+ ),
24259
+ /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(
24260
+ "path",
24261
+ {
24262
+ fill: "#EA4335",
24263
+ d: "M13.2,9.4c1.9,0,3.7,0.7,5.1,2l0,0l3.8-3.8c-2.4-2.2-5.6-3.5-8.8-3.4c-5,0-9.6,2.8-11.8,7.3l4.4,3.4 C6.8,11.7,9.8,9.4,13.2,9.4z"
24264
+ }
24265
+ )
24266
+ ] });
24267
+ }
23702
24268
  function GenericCardIcon({ size: size4 = 24, color = "#888" }) {
23703
24269
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(CreditCard, { width: size4 * 0.8, height: size4 * 0.8, style: { color }, strokeWidth: 1.5 });
23704
24270
  }
24271
+ function parseColor(input) {
24272
+ if (!input) return null;
24273
+ const s = input.trim();
24274
+ if (s.startsWith("#")) {
24275
+ let hex = s.slice(1);
24276
+ if (hex.length === 3)
24277
+ hex = hex.split("").map((c) => c + c).join("");
24278
+ if (hex.length !== 6) return null;
24279
+ const n = parseInt(hex, 16);
24280
+ if (Number.isNaN(n)) return null;
24281
+ return [n >> 16 & 255, n >> 8 & 255, n & 255];
24282
+ }
24283
+ const m = s.match(/rgba?\(([^)]+)\)/i);
24284
+ if (m) {
24285
+ const parts = m[1].split(",").map((p) => parseFloat(p));
24286
+ if (parts.length >= 3 && parts.every((p) => !Number.isNaN(p)))
24287
+ return [parts[0], parts[1], parts[2]];
24288
+ }
24289
+ return null;
24290
+ }
24291
+ function monochromeOn(background) {
24292
+ const rgb = parseColor(background);
24293
+ if (!rgb) return "#000000";
24294
+ const [r2, g, b] = rgb;
24295
+ const luminance = (0.299 * r2 + 0.587 * g + 0.114 * b) / 255;
24296
+ return luminance > 0.6 ? "#000000" : "#FFFFFF";
24297
+ }
23705
24298
  function CardBrandIcon({
23706
24299
  brand,
23707
24300
  size: size4 = 24,
23708
- fallbackColor = "#888"
24301
+ fallbackColor = "#888",
24302
+ monochromeColor = "#000000"
23709
24303
  }) {
23710
24304
  if (!brand) return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(GenericCardIcon, { size: size4, color: fallbackColor });
23711
24305
  const lower = brand.toLowerCase();
24306
+ if (lower.includes("apple_pay") || lower.includes("apple pay") || lower === "applepay")
24307
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(ApplePayIcon, { size: size4, color: monochromeColor });
24308
+ if (lower.includes("google_pay") || lower.includes("google pay") || lower === "googlepay")
24309
+ return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(GooglePayIcon, { size: size4, color: monochromeColor === "#FFFFFF" ? "#FFFFFF" : "#202124" });
23712
24310
  if (lower.includes("visa")) return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(VisaIcon, { size: size4 });
23713
24311
  if (lower.includes("mastercard") || lower.includes("master"))
23714
24312
  return /* @__PURE__ */ (0, import_jsx_runtime60.jsx)(MastercardIcon, { size: size4 });
@@ -23717,17 +24315,28 @@ function CardBrandIcon({
23717
24315
  }
23718
24316
  function formatPaymentToken(token) {
23719
24317
  if (token.card) {
23720
- const brand = token.card.brand ?? "Card";
24318
+ const cardBrand = token.card.brand ?? "Card";
24319
+ const last4 = token.card.last4;
24320
+ const walletType = token.card.wallet?.type;
24321
+ if (walletType === "apple_pay" || walletType === "google_pay") {
24322
+ const funding = token.card.funding ? capitalize(token.card.funding) : null;
24323
+ return {
24324
+ label: last4 ? `${capitalize(cardBrand)} \u2022\u2022\u2022\u2022 ${last4}` : capitalize(cardBrand),
24325
+ sublabel: funding ?? "",
24326
+ brand: walletType
24327
+ };
24328
+ }
23721
24329
  return {
23722
- label: `${capitalize(brand)} \u2022\u2022\u2022\u2022 ${token.card.last4}`,
24330
+ label: `${capitalize(cardBrand)} \u2022\u2022\u2022\u2022 ${last4}`,
23723
24331
  sublabel: `${capitalize(token.card.funding ?? "card")} \xB7 Expires ${token.card.exp_month}/${token.card.exp_year}`,
23724
- brand
24332
+ brand: cardBrand
23725
24333
  };
23726
24334
  }
23727
24335
  if (token.us_bank_account) {
24336
+ const accountType = token.us_bank_account.account_type;
23728
24337
  return {
23729
24338
  label: `${token.us_bank_account.bank_name ?? "Bank"} \u2022\u2022\u2022\u2022 ${token.us_bank_account.last4}`,
23730
- sublabel: "Bank account"
24339
+ sublabel: accountType ? `${capitalize(accountType)} account` : "Bank account"
23731
24340
  };
23732
24341
  }
23733
24342
  return { label: "Payment method", sublabel: token.type };
@@ -23735,59 +24344,82 @@ function formatPaymentToken(token) {
23735
24344
  function capitalize(s) {
23736
24345
  return s.charAt(0).toUpperCase() + s.slice(1);
23737
24346
  }
23738
- function useStripeOnramp(stripePublishableKey) {
23739
- const [coordinator, setCoordinator] = (0, import_react24.useState)(null);
23740
- const [isLoading, setIsLoading] = (0, import_react24.useState)(false);
23741
- const [error, setError] = (0, import_react24.useState)(null);
23742
- const coordinatorRef = (0, import_react24.useRef)(null);
23743
- const initialize = (0, import_react24.useCallback)(async () => {
23744
- if (coordinatorRef.current) return coordinatorRef.current;
23745
- if (!stripePublishableKey) return null;
23746
- setIsLoading(true);
23747
- setError(null);
23748
- try {
23749
- console.log("[PayWithStripeLink] Importing @stripe/crypto...");
23750
- const { loadCryptoOnrampAndInitialize } = await import(
23751
- /* @vite-ignore */
23752
- "@stripe/crypto"
23753
- );
23754
- console.log(
23755
- "[PayWithStripeLink] @stripe/crypto imported, initializing with key:",
23756
- stripePublishableKey?.slice(0, 12) + "..."
23757
- );
23758
- const initPromise = loadCryptoOnrampAndInitialize(stripePublishableKey, { theme: "stripe" });
23759
- const timeoutPromise = new Promise(
23760
- (_, reject) => setTimeout(
23761
- () => reject(
23762
- new Error(
23763
- "Stripe SDK initialization timed out after 15 seconds. Check that your Stripe account has the Crypto Onramp feature enabled."
23764
- )
23765
- ),
23766
- 15e3
23767
- )
23768
- );
23769
- const instance = await Promise.race([initPromise, timeoutPromise]);
23770
- if (!instance) {
23771
- throw new Error("Stripe SDK returned null.");
23772
- }
23773
- console.log("[PayWithStripeLink] Stripe SDK initialized successfully");
23774
- coordinatorRef.current = instance;
23775
- setCoordinator(instance);
23776
- return coordinatorRef.current;
23777
- } catch (err) {
23778
- const raw = err instanceof Error ? err.message : String(err);
23779
- const msg = raw.includes("Cannot find module") || raw.includes("Module not found") || raw.includes("Failed to fetch") ? "Install @stripe/crypto to use Stripe Link: npm install @stripe/crypto" : `Failed to initialize Stripe SDK: ${raw}`;
23780
- setError(msg);
23781
- console.error("[PayWithStripeLink]", msg);
23782
- return null;
23783
- } finally {
23784
- setIsLoading(false);
23785
- }
24347
+ function useStripeOnramp(stripePublishableKey, isDark = false) {
24348
+ const [coordinator, setCoordinator] = (0, import_react25.useState)(null);
24349
+ const [isLoading, setIsLoading] = (0, import_react25.useState)(false);
24350
+ const [error, setError] = (0, import_react25.useState)(null);
24351
+ const coordinatorRef = (0, import_react25.useRef)(null);
24352
+ const coordinatorThemeRef = (0, import_react25.useRef)(null);
24353
+ const initPromiseRef = (0, import_react25.useRef)(null);
24354
+ const isDarkRef = (0, import_react25.useRef)(isDark);
24355
+ isDarkRef.current = isDark;
24356
+ const initialize = (0, import_react25.useCallback)(() => {
24357
+ if (coordinatorRef.current) return Promise.resolve(coordinatorRef.current);
24358
+ if (initPromiseRef.current) return initPromiseRef.current;
24359
+ if (!stripePublishableKey) return Promise.resolve(null);
24360
+ const theme = isDarkRef.current;
24361
+ const promise = (async () => {
24362
+ setIsLoading(true);
24363
+ setError(null);
24364
+ try {
24365
+ console.log("[PayWithStripeLink] Importing @stripe/crypto...");
24366
+ const { loadCryptoOnrampAndInitialize } = await import(
24367
+ /* @vite-ignore */
24368
+ "@stripe/crypto"
24369
+ );
24370
+ console.log(
24371
+ "[PayWithStripeLink] @stripe/crypto imported, initializing with key:",
24372
+ stripePublishableKey?.slice(0, 12) + "..."
24373
+ );
24374
+ const initPromise = loadCryptoOnrampAndInitialize(stripePublishableKey, {
24375
+ theme: theme ? "night" : "stripe"
24376
+ });
24377
+ const timeoutPromise = new Promise(
24378
+ (_, reject) => setTimeout(
24379
+ () => reject(
24380
+ new Error(
24381
+ "Stripe SDK initialization timed out after 15 seconds. Check that your Stripe account has the Crypto Onramp feature enabled."
24382
+ )
24383
+ ),
24384
+ 15e3
24385
+ )
24386
+ );
24387
+ const instance = await Promise.race([initPromise, timeoutPromise]);
24388
+ if (!instance) {
24389
+ throw new Error("Stripe SDK returned null.");
24390
+ }
24391
+ console.log("[PayWithStripeLink] Stripe SDK initialized successfully");
24392
+ coordinatorRef.current = instance;
24393
+ coordinatorThemeRef.current = theme;
24394
+ setCoordinator(instance);
24395
+ return coordinatorRef.current;
24396
+ } catch (err) {
24397
+ const raw = err instanceof Error ? err.message : String(err);
24398
+ const msg = raw.includes("Cannot find module") || raw.includes("Module not found") || raw.includes("Failed to fetch") ? "Install @stripe/crypto to use Stripe Link: npm install @stripe/crypto" : `Failed to initialize Stripe SDK: ${raw}`;
24399
+ setError(msg);
24400
+ console.error("[PayWithStripeLink]", msg);
24401
+ return null;
24402
+ } finally {
24403
+ setIsLoading(false);
24404
+ initPromiseRef.current = null;
24405
+ }
24406
+ })();
24407
+ initPromiseRef.current = promise;
24408
+ return promise;
23786
24409
  }, [stripePublishableKey]);
23787
- (0, import_react24.useEffect)(() => {
24410
+ (0, import_react25.useEffect)(() => {
24411
+ if (!coordinatorRef.current) return;
24412
+ if (coordinatorThemeRef.current === isDark) return;
24413
+ coordinatorRef.current.destroy();
24414
+ coordinatorRef.current = null;
24415
+ coordinatorThemeRef.current = null;
24416
+ setCoordinator(null);
24417
+ }, [isDark, coordinator]);
24418
+ (0, import_react25.useEffect)(() => {
23788
24419
  return () => {
23789
24420
  coordinatorRef.current?.destroy();
23790
24421
  coordinatorRef.current = null;
24422
+ coordinatorThemeRef.current = null;
23791
24423
  };
23792
24424
  }, []);
23793
24425
  return { coordinator, isLoading, error, initialize };
@@ -23938,21 +24570,23 @@ function PayWithStripeLink({
23938
24570
  onDepositSuccess,
23939
24571
  onDepositError
23940
24572
  }) {
23941
- const { colors: colors2, fonts, components } = useTheme();
23942
- const [step, setStepInternal] = (0, import_react23.useState)(controlledStep ?? "amount");
23943
- const setStep = (0, import_react23.useCallback)(
24573
+ const { colors: colors2, fonts, components, isDark } = useTheme();
24574
+ const [step, setStepInternal] = (0, import_react24.useState)(controlledStep ?? "amount");
24575
+ const setStep = (0, import_react24.useCallback)(
23944
24576
  (s) => {
23945
24577
  setStepInternal(s);
23946
24578
  onStepChange?.(s);
23947
24579
  },
23948
24580
  [onStepChange]
23949
24581
  );
23950
- (0, import_react23.useEffect)(() => {
24582
+ const stepRef = (0, import_react24.useRef)(step);
24583
+ stepRef.current = step;
24584
+ (0, import_react24.useEffect)(() => {
23951
24585
  if (controlledStep && controlledStep !== step) {
23952
24586
  setStepInternal(controlledStep);
23953
24587
  }
23954
24588
  }, [controlledStep]);
23955
- (0, import_react23.useEffect)(() => {
24589
+ (0, import_react24.useEffect)(() => {
23956
24590
  setLoading(false);
23957
24591
  setError(null);
23958
24592
  setKycPendingMessage(null);
@@ -23961,9 +24595,9 @@ function PayWithStripeLink({
23961
24595
  checkoutGenRef.current++;
23962
24596
  }
23963
24597
  }, [step]);
23964
- const [resolvedStripeKey, setResolvedStripeKey] = (0, import_react23.useState)();
23965
- const [configError, setConfigError] = (0, import_react23.useState)(null);
23966
- (0, import_react23.useEffect)(() => {
24598
+ const [resolvedStripeKey, setResolvedStripeKey] = (0, import_react24.useState)();
24599
+ const [configError, setConfigError] = (0, import_react24.useState)(null);
24600
+ (0, import_react24.useEffect)(() => {
23967
24601
  let active = true;
23968
24602
  const fetchConfig = async () => {
23969
24603
  try {
@@ -23986,7 +24620,7 @@ function PayWithStripeLink({
23986
24620
  active = false;
23987
24621
  };
23988
24622
  }, [publishableKey]);
23989
- (0, import_react23.useEffect)(() => {
24623
+ (0, import_react24.useEffect)(() => {
23990
24624
  if (step !== "auth" || resolvedStripeKey || configError) return;
23991
24625
  let active = true;
23992
24626
  const retryConfig = async () => {
@@ -24014,8 +24648,8 @@ function PayWithStripeLink({
24014
24648
  isLoading: sdkLoading,
24015
24649
  error: sdkError,
24016
24650
  initialize
24017
- } = useStripeOnramp(resolvedStripeKey);
24018
- (0, import_react23.useEffect)(() => {
24651
+ } = useStripeOnramp(resolvedStripeKey, isDark);
24652
+ (0, import_react24.useEffect)(() => {
24019
24653
  if (step === "auth") {
24020
24654
  console.log("[PayWithStripeLink] Auth step state:", {
24021
24655
  resolvedStripeKey: resolvedStripeKey ? resolvedStripeKey.slice(0, 15) + "..." : void 0,
@@ -24026,27 +24660,30 @@ function PayWithStripeLink({
24026
24660
  });
24027
24661
  }
24028
24662
  }, [step, resolvedStripeKey, coordinator, sdkLoading, sdkError, configError]);
24029
- const [email, setEmail] = (0, import_react23.useState)(emailProp ?? "");
24030
- const [phone, setPhone] = (0, import_react23.useState)("");
24031
- const [country, setCountry] = (0, import_react23.useState)("US");
24032
- const [loading, setLoading] = (0, import_react23.useState)(false);
24033
- const [error, setError] = (0, import_react23.useState)(null);
24034
- const [kycPendingMessage, setKycPendingMessage] = (0, import_react23.useState)(null);
24035
- const [kycRejectionReason, setKycRejectionReason] = (0, import_react23.useState)(null);
24036
- const [restoring, setRestoring] = (0, import_react23.useState)(true);
24037
- const [errorReturnStep, setErrorReturnStep] = (0, import_react23.useState)("email");
24038
- const [authIntentId, setAuthIntentId] = (0, import_react23.useState)(null);
24039
- const sdkAuthenticatedRef = (0, import_react23.useRef)(false);
24040
- const pendingAddPaymentRef = (0, import_react23.useRef)(false);
24041
- const autoOpenedAddPaymentRef = (0, import_react23.useRef)(false);
24042
- const checkoutGenRef = (0, import_react23.useRef)(0);
24043
- const [stripePaymentUIReady, setStripePaymentUIReady] = (0, import_react23.useState)(false);
24044
- const [oauthToken, setOauthToken] = (0, import_react23.useState)(null);
24045
- const [refreshTokenValue, setRefreshTokenValue] = (0, import_react23.useState)(null);
24046
- const [customerId, setCustomerId] = (0, import_react23.useState)(null);
24047
- const accessTokenRef = (0, import_react23.useRef)("");
24048
- const refreshTokenRef = (0, import_react23.useRef)("");
24049
- const persistSession = (0, import_react23.useCallback)(
24663
+ const [email, setEmail] = (0, import_react24.useState)(emailProp ?? "");
24664
+ const [phone, setPhone] = (0, import_react24.useState)("");
24665
+ const [country, setCountry] = (0, import_react24.useState)("US");
24666
+ const [loading, setLoading] = (0, import_react24.useState)(false);
24667
+ const [error, setError] = (0, import_react24.useState)(null);
24668
+ const [kycPendingMessage, setKycPendingMessage] = (0, import_react24.useState)(null);
24669
+ const [kycRejectionReason, setKycRejectionReason] = (0, import_react24.useState)(null);
24670
+ const [restoring, setRestoring] = (0, import_react24.useState)(true);
24671
+ const [errorReturnStep, setErrorReturnStep] = (0, import_react24.useState)("email");
24672
+ const [authIntentId, setAuthIntentId] = (0, import_react24.useState)(null);
24673
+ const sdkAuthenticatedRef = (0, import_react24.useRef)(false);
24674
+ const everAuthenticatedRef = (0, import_react24.useRef)(false);
24675
+ const reauthReturnStepRef = (0, import_react24.useRef)(null);
24676
+ const attemptedWalletReauthRef = (0, import_react24.useRef)(false);
24677
+ const pendingAddPaymentRef = (0, import_react24.useRef)(false);
24678
+ const autoOpenedAddPaymentRef = (0, import_react24.useRef)(false);
24679
+ const checkoutGenRef = (0, import_react24.useRef)(0);
24680
+ const [stripePaymentUIReady, setStripePaymentUIReady] = (0, import_react24.useState)(false);
24681
+ const [oauthToken, setOauthToken] = (0, import_react24.useState)(null);
24682
+ const [refreshTokenValue, setRefreshTokenValue] = (0, import_react24.useState)(null);
24683
+ const [customerId, setCustomerId] = (0, import_react24.useState)(null);
24684
+ const accessTokenRef = (0, import_react24.useRef)("");
24685
+ const refreshTokenRef = (0, import_react24.useRef)("");
24686
+ const persistSession = (0, import_react24.useCallback)(
24050
24687
  (cid, token, refresh, expiresIn, loginEmail) => {
24051
24688
  accessTokenRef.current = token;
24052
24689
  refreshTokenRef.current = refresh;
@@ -24060,8 +24697,8 @@ function PayWithStripeLink({
24060
24697
  },
24061
24698
  [userId, email]
24062
24699
  );
24063
- const refreshInFlightRef = (0, import_react23.useRef)(null);
24064
- const tryRefreshToken = (0, import_react23.useCallback)(async () => {
24700
+ const refreshInFlightRef = (0, import_react24.useRef)(null);
24701
+ const tryRefreshToken = (0, import_react24.useCallback)(async () => {
24065
24702
  if (refreshInFlightRef.current) return refreshInFlightRef.current;
24066
24703
  const rt = refreshTokenRef.current;
24067
24704
  if (!rt) return null;
@@ -24091,7 +24728,7 @@ function PayWithStripeLink({
24091
24728
  refreshInFlightRef.current = doRefresh();
24092
24729
  return refreshInFlightRef.current;
24093
24730
  }, [publishableKey, customerId, persistSession, userId]);
24094
- const withTokenRefresh = (0, import_react23.useCallback)(
24731
+ const withTokenRefresh = (0, import_react24.useCallback)(
24095
24732
  async (fn) => {
24096
24733
  const token = accessTokenRef.current;
24097
24734
  if (!token) {
@@ -24119,7 +24756,7 @@ function PayWithStripeLink({
24119
24756
  },
24120
24757
  [tryRefreshToken, setStep]
24121
24758
  );
24122
- (0, import_react23.useEffect)(() => {
24759
+ (0, import_react24.useEffect)(() => {
24123
24760
  const stored = getStoredStripeSession(userId);
24124
24761
  console.log("[PayWithStripeLink] Restore check:", {
24125
24762
  hasStored: !!stored,
@@ -24210,9 +24847,9 @@ function PayWithStripeLink({
24210
24847
  cancelled = true;
24211
24848
  };
24212
24849
  }, [userId, publishableKey]);
24213
- const [customer, setCustomer] = (0, import_react23.useState)(null);
24214
- const [kycFormMode, setKycFormMode] = (0, import_react23.useState)("name");
24215
- const [kycForm, setKycForm] = (0, import_react23.useState)({
24850
+ const [customer, setCustomer] = (0, import_react24.useState)(null);
24851
+ const [kycFormMode, setKycFormMode] = (0, import_react24.useState)("name");
24852
+ const [kycForm, setKycForm] = (0, import_react24.useState)({
24216
24853
  givenName: "",
24217
24854
  surname: "",
24218
24855
  dob: { day: "", month: "", year: "" },
@@ -24224,7 +24861,7 @@ function PayWithStripeLink({
24224
24861
  addressPostalCode: "",
24225
24862
  addressCountry: "US"
24226
24863
  });
24227
- (0, import_react23.useEffect)(() => {
24864
+ (0, import_react24.useEffect)(() => {
24228
24865
  if (!backHandlerRef) return;
24229
24866
  backHandlerRef.current = () => {
24230
24867
  if (step === "kyc_form" && kycFormMode === "address") {
@@ -24235,6 +24872,7 @@ function PayWithStripeLink({
24235
24872
  if (step === "auth" && (pendingAddPaymentRef.current || !!accessTokenRef.current)) {
24236
24873
  pendingAddPaymentRef.current = false;
24237
24874
  autoOpenedAddPaymentRef.current = false;
24875
+ reauthReturnStepRef.current = null;
24238
24876
  setError(null);
24239
24877
  setStep("amount");
24240
24878
  return true;
@@ -24245,24 +24883,41 @@ function PayWithStripeLink({
24245
24883
  backHandlerRef.current = null;
24246
24884
  };
24247
24885
  }, [backHandlerRef, step, kycFormMode]);
24248
- const [wallets, setWallets] = (0, import_react23.useState)([]);
24249
- const [paymentTokens, setPaymentTokens] = (0, import_react23.useState)([]);
24250
- const [storedSelectedToken, setStoredSelectedTokenState] = (0, import_react23.useState)(
24886
+ const [wallets, setWallets] = (0, import_react24.useState)([]);
24887
+ const [paymentTokens, setPaymentTokens] = (0, import_react24.useState)([]);
24888
+ const [storedSelectedToken, setStoredSelectedTokenState] = (0, import_react24.useState)(
24251
24889
  null
24252
24890
  );
24253
- const [selectedPaymentToken, setSelectedPaymentToken] = (0, import_react23.useState)(null);
24254
- const [paymentDisplay, setPaymentDisplay] = (0, import_react23.useState)(null);
24255
- const selectPaymentToken = (0, import_react23.useCallback)(
24891
+ const [selectedPaymentToken, setSelectedPaymentToken] = (0, import_react24.useState)(null);
24892
+ const [paymentDisplay, setPaymentDisplay] = (0, import_react24.useState)(null);
24893
+ const selectedTokenSingleUseRef = (0, import_react24.useRef)(false);
24894
+ const selectPaymentToken = (0, import_react24.useCallback)(
24256
24895
  (token) => {
24896
+ selectedTokenSingleUseRef.current = !!token.singleUse;
24257
24897
  setSelectedPaymentToken(token.id);
24258
24898
  setPaymentDisplay(
24259
24899
  token.label ? { label: token.label, sublabel: token.sublabel, brand: token.brand } : null
24260
24900
  );
24261
24901
  setStoredSelectedTokenState(token);
24262
- if (customerId) setStoredSelectedToken(customerId, token);
24902
+ if (customerId && !token.singleUse) setStoredSelectedToken(customerId, token);
24263
24903
  },
24264
24904
  [customerId]
24265
24905
  );
24906
+ const clearSelectedPaymentToken = (0, import_react24.useCallback)(() => {
24907
+ selectedTokenSingleUseRef.current = false;
24908
+ const persisted = customerId ? getStoredSelectedToken(customerId) : null;
24909
+ if (persisted && !persisted.singleUse) {
24910
+ setSelectedPaymentToken(persisted.id);
24911
+ setPaymentDisplay(
24912
+ persisted.label ? { label: persisted.label, sublabel: persisted.sublabel, brand: persisted.brand } : null
24913
+ );
24914
+ setStoredSelectedTokenState(persisted);
24915
+ } else {
24916
+ setSelectedPaymentToken(null);
24917
+ setPaymentDisplay(null);
24918
+ setStoredSelectedTokenState(null);
24919
+ }
24920
+ }, [customerId]);
24266
24921
  const displayPaymentTokens = (() => {
24267
24922
  const apiDisplay = paymentTokens.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) }));
24268
24923
  if (storedSelectedToken && !paymentTokens.some((t13) => t13.id === storedSelectedToken.id)) {
@@ -24270,7 +24925,7 @@ function PayWithStripeLink({
24270
24925
  }
24271
24926
  return apiDisplay;
24272
24927
  })();
24273
- (0, import_react23.useEffect)(() => {
24928
+ (0, import_react24.useEffect)(() => {
24274
24929
  if (!customerId) return;
24275
24930
  const stored = getStoredSelectedToken(customerId);
24276
24931
  if (stored) {
@@ -24281,19 +24936,19 @@ function PayWithStripeLink({
24281
24936
  );
24282
24937
  }
24283
24938
  }, [customerId]);
24284
- const [amount, setAmount] = (0, import_react23.useState)("");
24285
- (0, import_react23.useEffect)(() => {
24939
+ const [amount, setAmount] = (0, import_react24.useState)("");
24940
+ (0, import_react24.useEffect)(() => {
24286
24941
  console.log("[PayWithStripeLink] Component mounted/remounted. Amount:", amount, "Step:", step);
24287
24942
  }, []);
24288
24943
  const sourceCurrency = "usd";
24289
24944
  const extractRefreshToken = (res) => res.refresh_token ?? res.refresh?.refresh_token ?? "";
24290
- const [stripeDestCurrency, setStripeDestCurrency] = (0, import_react23.useState)("usdc");
24291
- const [stripeDestNetwork, setStripeDestNetwork] = (0, import_react23.useState)("base");
24292
- const [stripeDestChainType, setStripeDestChainType] = (0, import_react23.useState)("ethereum");
24293
- const [stripeTokenSymbol, setStripeTokenSymbol] = (0, import_react23.useState)("USDC");
24294
- const [stripeTokenIconUrl, setStripeTokenIconUrl] = (0, import_react23.useState)(null);
24295
- const [stripeNetworkName, setStripeNetworkName] = (0, import_react23.useState)("Base");
24296
- (0, import_react23.useEffect)(() => {
24945
+ const [stripeDestCurrency, setStripeDestCurrency] = (0, import_react24.useState)("usdc");
24946
+ const [stripeDestNetwork, setStripeDestNetwork] = (0, import_react24.useState)("base");
24947
+ const [stripeDestChainType, setStripeDestChainType] = (0, import_react24.useState)("ethereum");
24948
+ const [stripeTokenSymbol, setStripeTokenSymbol] = (0, import_react24.useState)("USDC");
24949
+ const [stripeTokenIconUrl, setStripeTokenIconUrl] = (0, import_react24.useState)(null);
24950
+ const [stripeNetworkName, setStripeNetworkName] = (0, import_react24.useState)("Base");
24951
+ (0, import_react24.useEffect)(() => {
24297
24952
  if (!destinationTokenAddress || !destinationChainId || !destinationChainType) return;
24298
24953
  let cancelled = false;
24299
24954
  stripeGetDefaultToken(
@@ -24321,26 +24976,26 @@ function PayWithStripeLink({
24321
24976
  };
24322
24977
  }, [publishableKey, destinationTokenAddress, destinationChainId, destinationChainType]);
24323
24978
  const destinationCurrency = stripeDestCurrency;
24324
- const authInnerRef = (0, import_react23.useRef)(null);
24325
- const paymentInnerRef = (0, import_react23.useRef)(null);
24326
- const [authReady, setAuthReady] = (0, import_react23.useState)(false);
24979
+ const authInnerRef = (0, import_react24.useRef)(null);
24980
+ const paymentInnerRef = (0, import_react24.useRef)(null);
24981
+ const [authReady, setAuthReady] = (0, import_react24.useState)(false);
24327
24982
  if (typeof document !== "undefined" && !authInnerRef.current) {
24328
24983
  authInnerRef.current = document.createElement("div");
24329
24984
  }
24330
24985
  if (typeof document !== "undefined" && !paymentInnerRef.current) {
24331
24986
  paymentInnerRef.current = document.createElement("div");
24332
24987
  }
24333
- const authMountRef = (0, import_react23.useCallback)((node) => {
24988
+ const authMountRef = (0, import_react24.useCallback)((node) => {
24334
24989
  if (node && !node.contains(authInnerRef.current)) {
24335
24990
  node.appendChild(authInnerRef.current);
24336
24991
  }
24337
24992
  }, []);
24338
- const paymentMountRef = (0, import_react23.useCallback)((node) => {
24993
+ const paymentMountRef = (0, import_react24.useCallback)((node) => {
24339
24994
  if (node && !node.contains(paymentInnerRef.current)) {
24340
24995
  node.appendChild(paymentInnerRef.current);
24341
24996
  }
24342
24997
  }, []);
24343
- (0, import_react23.useEffect)(() => {
24998
+ (0, import_react24.useEffect)(() => {
24344
24999
  return () => {
24345
25000
  authInnerRef.current?.remove();
24346
25001
  paymentInnerRef.current?.remove();
@@ -24358,10 +25013,10 @@ function PayWithStripeLink({
24358
25013
  });
24359
25014
  const depositWallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
24360
25015
  const onrampWalletAddress = getWalletByChainType(depositWallets, stripeDestChainType)?.address;
24361
- const [registeredWalletKey, setRegisteredWalletKey] = (0, import_react23.useState)(null);
25016
+ const [registeredWalletKey, setRegisteredWalletKey] = (0, import_react24.useState)(null);
24362
25017
  const walletKeyFor = (address) => `${stripeDestNetwork}:${stripeDestChainType === "ethereum" ? address.toLowerCase() : address}`;
24363
25018
  const isOnrampWalletRegistered = !!onrampWalletAddress && registeredWalletKey === walletKeyFor(onrampWalletAddress);
24364
- (0, import_react23.useEffect)(() => {
25019
+ (0, import_react24.useEffect)(() => {
24365
25020
  if (depositWallets.length > 0 && !onrampWalletAddress) {
24366
25021
  console.warn(
24367
25022
  "[PayWithStripeLink] No deposit-intent wallet matches Stripe chain type",
@@ -24384,14 +25039,14 @@ function PayWithStripeLink({
24384
25039
  onDepositSuccess,
24385
25040
  onDepositError
24386
25041
  });
24387
- const [confirmedSessionId, setConfirmedSessionId] = (0, import_react23.useState)(null);
24388
- const [sessionStatus, setSessionStatus] = (0, import_react23.useState)(null);
24389
- const handledTerminalSessionRef = (0, import_react23.useRef)(null);
24390
- const executionReconciledSessionRef = (0, import_react23.useRef)(null);
25042
+ const [confirmedSessionId, setConfirmedSessionId] = (0, import_react24.useState)(null);
25043
+ const [sessionStatus, setSessionStatus] = (0, import_react24.useState)(null);
25044
+ const handledTerminalSessionRef = (0, import_react24.useRef)(null);
25045
+ const executionReconciledSessionRef = (0, import_react24.useRef)(null);
24391
25046
  const hasExecution = executions.length > 0;
24392
25047
  const isSessionFulfilled = sessionStatus === STRIPE_SESSION_STATUS.FULFILLMENT_COMPLETE || hasExecution;
24393
25048
  const isSessionFailed = !hasExecution && (sessionStatus === STRIPE_SESSION_STATUS.REJECTED || sessionStatus === STRIPE_SESSION_STATUS.EXPIRED);
24394
- (0, import_react23.useEffect)(() => {
25049
+ (0, import_react24.useEffect)(() => {
24395
25050
  if (step !== "success" || !hasExecution || !confirmedSessionId) return;
24396
25051
  if (executionReconciledSessionRef.current === confirmedSessionId) return;
24397
25052
  executionReconciledSessionRef.current = confirmedSessionId;
@@ -24409,7 +25064,7 @@ function PayWithStripeLink({
24409
25064
  cancelled = true;
24410
25065
  };
24411
25066
  }, [step, hasExecution, confirmedSessionId, withTokenRefresh, publishableKey]);
24412
- (0, import_react23.useEffect)(() => {
25067
+ (0, import_react24.useEffect)(() => {
24413
25068
  if (step !== "success" || !confirmedSessionId) return;
24414
25069
  if (hasExecution) return;
24415
25070
  if (handledTerminalSessionRef.current === confirmedSessionId) return;
@@ -24496,12 +25151,16 @@ function PayWithStripeLink({
24496
25151
  setLoading(false);
24497
25152
  }
24498
25153
  };
24499
- (0, import_react23.useEffect)(() => {
25154
+ (0, import_react24.useEffect)(() => {
24500
25155
  if (coordinator || sdkLoading || sdkError) return;
24501
25156
  if (!resolvedStripeKey) return;
24502
25157
  initialize();
24503
25158
  }, [coordinator, sdkLoading, sdkError, resolvedStripeKey, initialize]);
24504
- const handleAuthInterrupted = (0, import_react23.useCallback)(
25159
+ (0, import_react24.useEffect)(() => {
25160
+ sdkAuthenticatedRef.current = false;
25161
+ attemptedWalletReauthRef.current = false;
25162
+ }, [coordinator]);
25163
+ const handleAuthInterrupted = (0, import_react24.useCallback)(
24505
25164
  (message) => {
24506
25165
  const alreadySignedIn = !!accessTokenRef.current;
24507
25166
  if (alreadySignedIn || emailProp) {
@@ -24514,7 +25173,27 @@ function PayWithStripeLink({
24514
25173
  },
24515
25174
  [emailProp, setStep]
24516
25175
  );
24517
- (0, import_react23.useEffect)(() => {
25176
+ const reauthenticateSdk = (0, import_react24.useCallback)(async () => {
25177
+ const current = stepRef.current;
25178
+ const preAuthSteps = ["email", "register", "auth"];
25179
+ reauthReturnStepRef.current = preAuthSteps.includes(current) ? null : current;
25180
+ const knownEmail = (email || emailProp || "").trim();
25181
+ if (!knownEmail) {
25182
+ reauthReturnStepRef.current = null;
25183
+ setStep("email");
25184
+ return;
25185
+ }
25186
+ try {
25187
+ const authResult = await stripeCreateAuthIntent(knownEmail, publishableKey);
25188
+ setAuthIntentId(authResult.auth_intent_id);
25189
+ setStep("auth");
25190
+ } catch (err) {
25191
+ reauthReturnStepRef.current = null;
25192
+ setError(err instanceof Error ? err.message : "Failed to re-verify. Please try again.");
25193
+ setStep("email");
25194
+ }
25195
+ }, [email, emailProp, publishableKey]);
25196
+ (0, import_react24.useEffect)(() => {
24518
25197
  if (step !== "auth" || !coordinator || !authIntentId) return;
24519
25198
  let mounted = true;
24520
25199
  const runAuth = async () => {
@@ -24524,6 +25203,7 @@ function PayWithStripeLink({
24524
25203
  if (result.result === "success" && result.crypto_customer_id) {
24525
25204
  setCustomerId(result.crypto_customer_id);
24526
25205
  sdkAuthenticatedRef.current = true;
25206
+ everAuthenticatedRef.current = true;
24527
25207
  const tokens = await stripeExchangeTokens(authIntentId, publishableKey);
24528
25208
  setOauthToken(tokens.access_token);
24529
25209
  const refresh = extractRefreshToken(tokens);
@@ -24537,16 +25217,22 @@ function PayWithStripeLink({
24537
25217
  tokens.expires_in ?? 3600,
24538
25218
  email.trim()
24539
25219
  );
25220
+ const resumeStep = reauthReturnStepRef.current;
25221
+ reauthReturnStepRef.current = null;
24540
25222
  if (pendingAddPaymentRef.current) {
24541
25223
  setStep("payment");
25224
+ } else if (resumeStep) {
25225
+ setStep(resumeStep);
24542
25226
  } else {
24543
25227
  setStep("kyc");
24544
25228
  }
24545
25229
  } else if (result.result === "abandoned") {
24546
25230
  pendingAddPaymentRef.current = false;
25231
+ reauthReturnStepRef.current = null;
24547
25232
  handleAuthInterrupted("Verification was cancelled.");
24548
25233
  } else if (result.result === "declined") {
24549
25234
  pendingAddPaymentRef.current = false;
25235
+ reauthReturnStepRef.current = null;
24550
25236
  handleAuthInterrupted("You must consent to continue.");
24551
25237
  }
24552
25238
  });
@@ -24558,6 +25244,7 @@ function PayWithStripeLink({
24558
25244
  }
24559
25245
  } catch (err) {
24560
25246
  if (!mounted) return;
25247
+ reauthReturnStepRef.current = null;
24561
25248
  const msg = err instanceof Error ? err.message : "Verification was cancelled.";
24562
25249
  handleAuthInterrupted(msg);
24563
25250
  }
@@ -24569,7 +25256,7 @@ function PayWithStripeLink({
24569
25256
  authInnerRef.current.replaceChildren();
24570
25257
  };
24571
25258
  }, [step, coordinator, authIntentId, publishableKey]);
24572
- (0, import_react23.useEffect)(() => {
25259
+ (0, import_react24.useEffect)(() => {
24573
25260
  if (step !== "kyc" || !oauthToken || !customerId) return;
24574
25261
  let mounted = true;
24575
25262
  let pollTimer = null;
@@ -24659,6 +25346,10 @@ function PayWithStripeLink({
24659
25346
  };
24660
25347
  const handleKycSubmit = async () => {
24661
25348
  if (!coordinator) return;
25349
+ if (!sdkAuthenticatedRef.current) {
25350
+ await reauthenticateSdk();
25351
+ return;
25352
+ }
24662
25353
  let kycInfo;
24663
25354
  if (kycFormMode === "address") {
24664
25355
  if (!kycForm.givenName.trim() || !kycForm.surname.trim()) {
@@ -24713,11 +25404,15 @@ function PayWithStripeLink({
24713
25404
  setLoading(false);
24714
25405
  }
24715
25406
  };
24716
- (0, import_react23.useEffect)(() => {
25407
+ (0, import_react24.useEffect)(() => {
24717
25408
  if (step !== "kyc_document" || !coordinator) return;
24718
25409
  let mounted = true;
24719
25410
  const verify = async () => {
24720
25411
  try {
25412
+ if (!sdkAuthenticatedRef.current) {
25413
+ await reauthenticateSdk();
25414
+ return;
25415
+ }
24721
25416
  const result = await coordinator.verifyDocuments();
24722
25417
  if (!mounted) return;
24723
25418
  const outcome = typeof result === "string" ? result : result?.result;
@@ -24737,8 +25432,8 @@ function PayWithStripeLink({
24737
25432
  return () => {
24738
25433
  mounted = false;
24739
25434
  };
24740
- }, [step, coordinator]);
24741
- (0, import_react23.useEffect)(() => {
25435
+ }, [step, coordinator, reauthenticateSdk]);
25436
+ (0, import_react24.useEffect)(() => {
24742
25437
  if (step !== "wallet" || !oauthToken || !customerId) return;
24743
25438
  let mounted = true;
24744
25439
  const setupWallet = async () => {
@@ -24763,6 +25458,10 @@ function PayWithStripeLink({
24763
25458
  if (!coordinator) {
24764
25459
  return;
24765
25460
  }
25461
+ if (!sdkAuthenticatedRef.current) {
25462
+ await reauthenticateSdk();
25463
+ return;
25464
+ }
24766
25465
  await coordinator.registerWalletAddress(onrampWalletAddress, network);
24767
25466
  }
24768
25467
  if (mounted) setRegisteredWalletKey(walletKeyFor(onrampWalletAddress));
@@ -24779,8 +25478,16 @@ function PayWithStripeLink({
24779
25478
  return () => {
24780
25479
  mounted = false;
24781
25480
  };
24782
- }, [step, oauthToken, customerId, publishableKey, onrampWalletAddress, coordinator]);
24783
- (0, import_react23.useEffect)(() => {
25481
+ }, [
25482
+ step,
25483
+ oauthToken,
25484
+ customerId,
25485
+ publishableKey,
25486
+ onrampWalletAddress,
25487
+ coordinator,
25488
+ reauthenticateSdk
25489
+ ]);
25490
+ (0, import_react24.useEffect)(() => {
24784
25491
  if (step !== "amount" && step !== "review") return;
24785
25492
  if (!customerId || !oauthToken || !onrampWalletAddress) return;
24786
25493
  if (isOnrampWalletRegistered) return;
@@ -24808,6 +25515,10 @@ function PayWithStripeLink({
24808
25515
  if (coordinator && sdkAuthenticatedRef.current) {
24809
25516
  await coordinator.registerWalletAddress(onrampWalletAddress, network);
24810
25517
  if (!cancelled) setRegisteredWalletKey(walletKeyFor(onrampWalletAddress));
25518
+ } else if (coordinator && everAuthenticatedRef.current && !attemptedWalletReauthRef.current) {
25519
+ attemptedWalletReauthRef.current = true;
25520
+ await reauthenticateSdk();
25521
+ return;
24811
25522
  }
24812
25523
  } catch {
24813
25524
  }
@@ -24825,9 +25536,10 @@ function PayWithStripeLink({
24825
25536
  coordinator,
24826
25537
  stripeDestNetwork,
24827
25538
  stripeDestChainType,
24828
- publishableKey
25539
+ publishableKey,
25540
+ reauthenticateSdk
24829
25541
  ]);
24830
- (0, import_react23.useEffect)(() => {
25542
+ (0, import_react24.useEffect)(() => {
24831
25543
  if (step !== "payment" || !oauthToken || !customerId) return;
24832
25544
  if (pendingAddPaymentRef.current) {
24833
25545
  pendingAddPaymentRef.current = false;
@@ -24890,7 +25602,7 @@ function PayWithStripeLink({
24890
25602
  paymentInnerRef.current.replaceChildren();
24891
25603
  };
24892
25604
  }, [step, oauthToken, customerId, publishableKey, coordinator]);
24893
- (0, import_react23.useEffect)(() => {
25605
+ (0, import_react24.useEffect)(() => {
24894
25606
  if (step !== "add_payment") return;
24895
25607
  if (!isCustomerVerified(customer)) {
24896
25608
  setStep("kyc");
@@ -24922,6 +25634,32 @@ function PayWithStripeLink({
24922
25634
  if (!mounted) return;
24923
25635
  const tokenId = result.cryptoPaymentToken;
24924
25636
  let display = null;
25637
+ const pmd = result.paymentMethodDetails;
25638
+ if (pmd) {
25639
+ display = formatPaymentToken(pmd);
25640
+ }
25641
+ const singleUse = pmd?.type === "card" && !!pmd.card.wallet;
25642
+ const applyAndAdvance = () => {
25643
+ selectPaymentToken({
25644
+ id: tokenId,
25645
+ label: display?.label ?? "",
25646
+ sublabel: display?.sublabel ?? "",
25647
+ brand: display?.brand,
25648
+ singleUse
25649
+ });
25650
+ autoOpenedAddPaymentRef.current = false;
25651
+ setStep("amount");
25652
+ };
25653
+ if (display) {
25654
+ applyAndAdvance();
25655
+ if (customerId && accessTokenRef.current) {
25656
+ stripeListPaymentTokens(customerId, accessTokenRef.current, publishableKey).then((tokens) => {
25657
+ if (mounted) setPaymentTokens(tokens.data);
25658
+ }).catch(() => {
25659
+ });
25660
+ }
25661
+ return;
25662
+ }
24925
25663
  try {
24926
25664
  if (customerId && accessTokenRef.current) {
24927
25665
  const tokens = await stripeListPaymentTokens(
@@ -24929,28 +25667,15 @@ function PayWithStripeLink({
24929
25667
  accessTokenRef.current,
24930
25668
  publishableKey
24931
25669
  );
25670
+ if (!mounted) return;
25671
+ setPaymentTokens(tokens.data);
24932
25672
  const match = tokens.data.find((t13) => t13.id === tokenId);
24933
- if (match) {
24934
- display = formatPaymentToken(match);
24935
- setPaymentTokens(tokens.data);
24936
- }
25673
+ if (match) display = formatPaymentToken(match);
24937
25674
  }
24938
25675
  } catch {
24939
25676
  }
24940
- if (!display) {
24941
- const dd = result.displayData;
24942
- if (dd?.label) {
24943
- display = { label: dd.label, sublabel: dd.sublabel ?? "", brand: dd.type };
24944
- }
24945
- }
24946
- selectPaymentToken({
24947
- id: tokenId,
24948
- label: display?.label ?? "",
24949
- sublabel: display?.sublabel ?? "",
24950
- brand: display?.brand
24951
- });
24952
- autoOpenedAddPaymentRef.current = false;
24953
- setStep("amount");
25677
+ if (!mounted) return;
25678
+ applyAndAdvance();
24954
25679
  }
24955
25680
  );
24956
25681
  if (mounted && el) {
@@ -24987,6 +25712,10 @@ function PayWithStripeLink({
24987
25712
  const handleCheckout = async () => {
24988
25713
  if (!amount || !oauthToken || !customerId || !selectedPaymentToken || !onrampWalletAddress || !isOnrampWalletRegistered || !coordinator)
24989
25714
  return;
25715
+ if (!sdkAuthenticatedRef.current) {
25716
+ await reauthenticateSdk();
25717
+ return;
25718
+ }
24990
25719
  const gen = ++checkoutGenRef.current;
24991
25720
  const isStale = () => checkoutGenRef.current !== gen;
24992
25721
  const surfaceStepUpOnAmount = (err, message, tier) => {
@@ -25098,6 +25827,7 @@ function PayWithStripeLink({
25098
25827
  executionReconciledSessionRef.current = null;
25099
25828
  setConfirmedSessionId(activeSessionId);
25100
25829
  setSessionStatus(STRIPE_SESSION_STATUS.FULFILLMENT_PROCESSING);
25830
+ if (selectedTokenSingleUseRef.current) clearSelectedPaymentToken();
25101
25831
  setStep("success");
25102
25832
  } else if (lastError === "quote_rate_drifted" || lastError === "charged_with_expired_quote") {
25103
25833
  setSessionForCheckout(null);
@@ -25140,15 +25870,34 @@ function PayWithStripeLink({
25140
25870
  setLoading(false);
25141
25871
  }
25142
25872
  };
25143
- const [quote, setQuote] = (0, import_react23.useState)(null);
25144
- const [quoteLoading, setQuoteLoading] = (0, import_react23.useState)(false);
25145
- const quoteTimerRef = (0, import_react23.useRef)(null);
25146
- const [sessionForCheckout, setSessionForCheckoutState] = (0, import_react23.useState)(null);
25147
- const sessionForCheckoutRef = (0, import_react23.useRef)(sessionForCheckout);
25873
+ const [quote, setQuote] = (0, import_react24.useState)(null);
25874
+ const [quoteLoading, setQuoteLoading] = (0, import_react24.useState)(false);
25875
+ const quoteTimerRef = (0, import_react24.useRef)(null);
25876
+ const [sessionForCheckout, setSessionForCheckoutState] = (0, import_react24.useState)(null);
25877
+ const sessionForCheckoutRef = (0, import_react24.useRef)(sessionForCheckout);
25148
25878
  const setSessionForCheckout = (s) => {
25149
25879
  sessionForCheckoutRef.current = s;
25150
25880
  setSessionForCheckoutState(s);
25151
25881
  };
25882
+ const loadAndSelectPreferredToken = (0, import_react24.useCallback)(async () => {
25883
+ if (!customerId) return;
25884
+ try {
25885
+ const existing = await withTokenRefresh(
25886
+ (tok) => stripeListPaymentTokens(customerId, tok, publishableKey)
25887
+ );
25888
+ setPaymentTokens(existing.data);
25889
+ const stored = getStoredSelectedToken(customerId);
25890
+ const merged = [
25891
+ ...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
25892
+ ...stored && !existing.data.some((t13) => t13.id === stored.id) ? [stored] : []
25893
+ ];
25894
+ if (merged.length > 0) {
25895
+ const preferred = stored && merged.find((m) => m.id === stored.id) || merged[0];
25896
+ selectPaymentToken(preferred);
25897
+ }
25898
+ } catch {
25899
+ }
25900
+ }, [customerId, publishableKey, selectPaymentToken, withTokenRefresh]);
25152
25901
  const handleDone = () => {
25153
25902
  handledTerminalSessionRef.current = null;
25154
25903
  executionReconciledSessionRef.current = null;
@@ -25156,14 +25905,15 @@ function PayWithStripeLink({
25156
25905
  setSessionStatus(null);
25157
25906
  setSessionForCheckout(null);
25158
25907
  setStep("amount");
25908
+ if (!selectedPaymentToken) void loadAndSelectPreferredToken();
25159
25909
  };
25160
- const [quoteError, setQuoteError] = (0, import_react23.useState)(null);
25161
- const [quoteNonce, setQuoteNonce] = (0, import_react23.useState)(0);
25162
- const quoteNonceAtReviewRef = (0, import_react23.useRef)(quoteNonce);
25163
- const [purchaseLimit, setPurchaseLimit] = (0, import_react23.useState)(null);
25164
- const [limitReachedAmount, setLimitReachedAmount] = (0, import_react23.useState)(null);
25165
- const [requiredStepUp, setRequiredStepUp] = (0, import_react23.useState)(null);
25166
- (0, import_react23.useEffect)(() => {
25910
+ const [quoteError, setQuoteError] = (0, import_react24.useState)(null);
25911
+ const [quoteNonce, setQuoteNonce] = (0, import_react24.useState)(0);
25912
+ const quoteNonceAtReviewRef = (0, import_react24.useRef)(quoteNonce);
25913
+ const [purchaseLimit, setPurchaseLimit] = (0, import_react24.useState)(null);
25914
+ const [limitReachedAmount, setLimitReachedAmount] = (0, import_react24.useState)(null);
25915
+ const [requiredStepUp, setRequiredStepUp] = (0, import_react24.useState)(null);
25916
+ (0, import_react24.useEffect)(() => {
25167
25917
  if (step !== "amount" || !customerId || !onrampWalletAddress) return;
25168
25918
  if (!accessTokenRef.current) return;
25169
25919
  let cancelled = false;
@@ -25216,7 +25966,7 @@ function PayWithStripeLink({
25216
25966
  setQuoteError(null);
25217
25967
  setRequiredStepUp(null);
25218
25968
  };
25219
- (0, import_react23.useEffect)(() => {
25969
+ (0, import_react24.useEffect)(() => {
25220
25970
  if (step === "review") {
25221
25971
  const existing = sessionForCheckoutRef.current;
25222
25972
  const hasFreshSession = !!(existing && existing.amount === amount && existing.paymentToken === selectedPaymentToken);
@@ -25348,9 +26098,9 @@ function PayWithStripeLink({
25348
26098
  quoteNonce
25349
26099
  ]);
25350
26100
  const QUOTE_TTL = 30;
25351
- const [quoteCountdown, setQuoteCountdown] = (0, import_react23.useState)(QUOTE_TTL);
26101
+ const [quoteCountdown, setQuoteCountdown] = (0, import_react24.useState)(QUOTE_TTL);
25352
26102
  const hasReviewSession = !!(customerId && selectedPaymentToken && onrampWalletAddress);
25353
- (0, import_react23.useEffect)(() => {
26103
+ (0, import_react24.useEffect)(() => {
25354
26104
  if (step !== "review" || !hasReviewSession) return;
25355
26105
  quoteNonceAtReviewRef.current = quoteNonce;
25356
26106
  setQuoteCountdown(QUOTE_TTL);
@@ -25995,7 +26745,8 @@ function PayWithStripeLink({
25995
26745
  {
25996
26746
  brand: display.brand,
25997
26747
  size: 28,
25998
- fallbackColor: colors2.foregroundMuted
26748
+ fallbackColor: colors2.foregroundMuted,
26749
+ monochromeColor: monochromeOn(components.card.backgroundColor)
25999
26750
  }
26000
26751
  )
26001
26752
  }
@@ -26580,7 +27331,8 @@ function PayWithStripeLink({
26580
27331
  {
26581
27332
  brand: paymentDisplay.brand,
26582
27333
  size: 20,
26583
- fallbackColor: colors2.foregroundMuted
27334
+ fallbackColor: colors2.foregroundMuted,
27335
+ monochromeColor: monochromeOn(components.card.backgroundColor)
26584
27336
  }
26585
27337
  ),
26586
27338
  /* @__PURE__ */ (0, import_jsx_runtime61.jsx)(
@@ -27064,6 +27816,20 @@ function PayWithStripeLink({
27064
27816
  }
27065
27817
  return null;
27066
27818
  }
27819
+ function useProjectConfig({
27820
+ publishableKey,
27821
+ enabled = true
27822
+ }) {
27823
+ const { data: projectConfig, isLoading } = (0, import_react_query10.useQuery)({
27824
+ queryKey: ["unifold", "projectConfig", publishableKey],
27825
+ queryFn: () => getProjectConfig(publishableKey),
27826
+ enabled,
27827
+ staleTime: 1e3 * 60 * 30,
27828
+ refetchOnMount: true,
27829
+ refetchOnWindowFocus: true
27830
+ });
27831
+ return { projectConfig, isLoading };
27832
+ }
27067
27833
  function useSupportedDepositTokens(publishableKey, options) {
27068
27834
  const hasDestination = options?.destination_token_address && options?.destination_chain_id && options?.destination_chain_type;
27069
27835
  const filteredOptions = {
@@ -27075,7 +27841,7 @@ function useSupportedDepositTokens(publishableKey, options) {
27075
27841
  ...options?.product_type ? { product_type: options.product_type } : {}
27076
27842
  };
27077
27843
  const hasFilteredOptions = Object.keys(filteredOptions).length > 0;
27078
- return (0, import_react_query10.useQuery)({
27844
+ return (0, import_react_query11.useQuery)({
27079
27845
  queryKey: [
27080
27846
  "unifold",
27081
27847
  "supportedDepositTokens",
@@ -27099,7 +27865,7 @@ function useIntegrationTransferDefaultToken({
27099
27865
  publishableKey,
27100
27866
  enabled = true
27101
27867
  }) {
27102
- return (0, import_react_query11.useQuery)({
27868
+ return (0, import_react_query12.useQuery)({
27103
27869
  queryKey: [
27104
27870
  "unifold",
27105
27871
  "integrationTransferDefaultToken",
@@ -27175,12 +27941,12 @@ function CoinbaseConnect({
27175
27941
  destination_chain_id: destinationChainId,
27176
27942
  destination_chain_type: destinationChainType
27177
27943
  });
27178
- const supportedSymbols = (0, import_react25.useMemo)(() => {
27944
+ const supportedSymbols = (0, import_react26.useMemo)(() => {
27179
27945
  const set = /* @__PURE__ */ new Set();
27180
27946
  supportedTokensData?.data.forEach((token) => set.add(token.symbol.toLowerCase()));
27181
27947
  return set;
27182
27948
  }, [supportedTokensData]);
27183
- const stablecoinSymbols = (0, import_react25.useMemo)(() => {
27949
+ const stablecoinSymbols = (0, import_react26.useMemo)(() => {
27184
27950
  const set = /* @__PURE__ */ new Set();
27185
27951
  supportedTokensData?.data.forEach((token) => {
27186
27952
  if (token.is_stablecoin) set.add(token.symbol.toLowerCase());
@@ -27190,35 +27956,35 @@ function CoinbaseConnect({
27190
27956
  const appName = projectConfig?.project_name ?? "Unifold";
27191
27957
  const t13 = i18n2.connectExchange;
27192
27958
  const initialView = skipToHoldings && getStoredIntegrationToken(IntegrationProvider.COINBASE) ? "holdings" : "select_exchange";
27193
- const [view, setView] = (0, import_react25.useState)(initialView);
27194
- const [prevView, setPrevView] = (0, import_react25.useState)(initialView);
27195
- const [isTransitioning, setIsTransitioning] = (0, import_react25.useState)(false);
27196
- const [exchanges, setExchanges] = (0, import_react25.useState)([]);
27197
- const [exchangesLoading, setExchangesLoading] = (0, import_react25.useState)(true);
27198
- const [selectedExchange, setSelectedExchange] = (0, import_react25.useState)(null);
27199
- const [accessToken, setAccessToken] = (0, import_react25.useState)(null);
27200
- const [holdings, setHoldings] = (0, import_react25.useState)([]);
27201
- const [selectedHolding, setSelectedHolding] = (0, import_react25.useState)(null);
27202
- const [selectedAsset, setSelectedAsset] = (0, import_react25.useState)(null);
27203
- const [sendAmount, setSendAmount] = (0, import_react25.useState)("");
27204
- const [transferIntent, setTransferIntent] = (0, import_react25.useState)(
27959
+ const [view, setView] = (0, import_react26.useState)(initialView);
27960
+ const [prevView, setPrevView] = (0, import_react26.useState)(initialView);
27961
+ const [isTransitioning, setIsTransitioning] = (0, import_react26.useState)(false);
27962
+ const [exchanges, setExchanges] = (0, import_react26.useState)([]);
27963
+ const [exchangesLoading, setExchangesLoading] = (0, import_react26.useState)(true);
27964
+ const [selectedExchange, setSelectedExchange] = (0, import_react26.useState)(null);
27965
+ const [accessToken, setAccessToken] = (0, import_react26.useState)(null);
27966
+ const [holdings, setHoldings] = (0, import_react26.useState)([]);
27967
+ const [selectedHolding, setSelectedHolding] = (0, import_react26.useState)(null);
27968
+ const [selectedAsset, setSelectedAsset] = (0, import_react26.useState)(null);
27969
+ const [sendAmount, setSendAmount] = (0, import_react26.useState)("");
27970
+ const [transferIntent, setTransferIntent] = (0, import_react26.useState)(
27205
27971
  null
27206
27972
  );
27207
- const [mfaCode, setMfaCode] = (0, import_react25.useState)("");
27208
- const [mfaError, setMfaError] = (0, import_react25.useState)(false);
27209
- const [errorMessage, setErrorMessage] = (0, import_react25.useState)("");
27210
- const [isLoading, setIsLoading] = (0, import_react25.useState)(initialView === "holdings");
27211
- const [confirmResult, setConfirmResult] = (0, import_react25.useState)(null);
27212
- const [showTransferDetails, setShowTransferDetails] = (0, import_react25.useState)(false);
27213
- const [transferDepositWalletId, setTransferDepositWalletId] = (0, import_react25.useState)(
27973
+ const [mfaCode, setMfaCode] = (0, import_react26.useState)("");
27974
+ const [mfaError, setMfaError] = (0, import_react26.useState)(false);
27975
+ const [errorMessage, setErrorMessage] = (0, import_react26.useState)("");
27976
+ const [isLoading, setIsLoading] = (0, import_react26.useState)(initialView === "holdings");
27977
+ const [confirmResult, setConfirmResult] = (0, import_react26.useState)(null);
27978
+ const [showTransferDetails, setShowTransferDetails] = (0, import_react26.useState)(false);
27979
+ const [transferDepositWalletId, setTransferDepositWalletId] = (0, import_react26.useState)(
27214
27980
  void 0
27215
27981
  );
27216
- const exchangeSupportedCurrencies = (0, import_react25.useMemo)(() => {
27982
+ const exchangeSupportedCurrencies = (0, import_react26.useMemo)(() => {
27217
27983
  const set = /* @__PURE__ */ new Set();
27218
27984
  selectedExchange?.supported_currencies.forEach((c) => set.add(c.toLowerCase()));
27219
27985
  return set;
27220
27986
  }, [selectedExchange]);
27221
- const defaultTokenParams = (0, import_react25.useMemo)(
27987
+ const defaultTokenParams = (0, import_react26.useMemo)(
27222
27988
  () => selectedAsset ? {
27223
27989
  integration_provider: IntegrationProvider.COINBASE,
27224
27990
  source_currency: selectedAsset.currency.toLowerCase(),
@@ -27241,7 +28007,7 @@ function CoinbaseConnect({
27241
28007
  params: defaultTokenParams,
27242
28008
  publishableKey
27243
28009
  });
27244
- const defaultSourceCurrency = (0, import_react25.useMemo)(
28010
+ const defaultSourceCurrency = (0, import_react26.useMemo)(
27245
28011
  () => resolveDefaultSourceSymbol(supportedTokensData?.data, {
27246
28012
  defaultSourceChainType,
27247
28013
  defaultSourceChainId,
@@ -27256,7 +28022,7 @@ function CoinbaseConnect({
27256
28022
  defaultSourceSymbol
27257
28023
  ]
27258
28024
  );
27259
- const sortedHoldings = (0, import_react25.useMemo)(() => {
28025
+ const sortedHoldings = (0, import_react26.useMemo)(() => {
27260
28026
  const supported = [];
27261
28027
  const unsupported = [];
27262
28028
  holdings.forEach((account) => {
@@ -27276,12 +28042,12 @@ function CoinbaseConnect({
27276
28042
  }
27277
28043
  return [...supported, ...unsupported];
27278
28044
  }, [holdings, supportedSymbols, exchangeSupportedCurrencies, defaultSourceCurrency]);
27279
- const selectedHoldingIsSupported = (0, import_react25.useMemo)(() => {
28045
+ const selectedHoldingIsSupported = (0, import_react26.useMemo)(() => {
27280
28046
  if (!selectedHolding) return false;
27281
28047
  const currencyLower = selectedHolding.currency.toLowerCase();
27282
28048
  return (supportedSymbols.size === 0 || supportedSymbols.has(currencyLower)) && (exchangeSupportedCurrencies.size === 0 || exchangeSupportedCurrencies.has(currencyLower));
27283
28049
  }, [selectedHolding, supportedSymbols, exchangeSupportedCurrencies]);
27284
- (0, import_react25.useEffect)(() => {
28050
+ (0, import_react26.useEffect)(() => {
27285
28051
  if (!defaultSourceCurrency || selectedHolding) return;
27286
28052
  const defaultHolding = sortedHoldings.find((account) => {
27287
28053
  const currencyLower = account.currency.toLowerCase();
@@ -27317,13 +28083,13 @@ function CoinbaseConnect({
27317
28083
  onTransferError?.({ message: error.message });
27318
28084
  } : void 0
27319
28085
  });
27320
- (0, import_react25.useEffect)(() => {
28086
+ (0, import_react26.useEffect)(() => {
27321
28087
  onExecutionsChange?.(depositExecutions);
27322
28088
  }, [depositExecutions, onExecutionsChange]);
27323
- const pollRef = (0, import_react25.useRef)(null);
27324
- const popupRef = (0, import_react25.useRef)(null);
27325
- const viewRef = (0, import_react25.useRef)(initialView);
27326
- const transitionTo = (0, import_react25.useCallback)((nextView) => {
28089
+ const pollRef = (0, import_react26.useRef)(null);
28090
+ const popupRef = (0, import_react26.useRef)(null);
28091
+ const viewRef = (0, import_react26.useRef)(initialView);
28092
+ const transitionTo = (0, import_react26.useCallback)((nextView) => {
27327
28093
  if (nextView === viewRef.current) return;
27328
28094
  setIsTransitioning(true);
27329
28095
  setTimeout(() => {
@@ -27333,7 +28099,7 @@ function CoinbaseConnect({
27333
28099
  setIsTransitioning(false);
27334
28100
  }, 150);
27335
28101
  }, []);
27336
- const tryRefreshToken = (0, import_react25.useCallback)(
28102
+ const tryRefreshToken = (0, import_react26.useCallback)(
27337
28103
  async (currentToken) => {
27338
28104
  try {
27339
28105
  const result = await refreshIntegrationToken(currentToken, publishableKey);
@@ -27352,7 +28118,7 @@ function CoinbaseConnect({
27352
28118
  },
27353
28119
  [publishableKey]
27354
28120
  );
27355
- (0, import_react25.useEffect)(() => {
28121
+ (0, import_react26.useEffect)(() => {
27356
28122
  getIntegrationExchanges(publishableKey).then((res) => {
27357
28123
  setExchanges(res.data);
27358
28124
  if (!selectedExchange) {
@@ -27371,7 +28137,7 @@ function CoinbaseConnect({
27371
28137
  }
27372
28138
  }
27373
28139
  }, []);
27374
- const loadHoldings = (0, import_react25.useCallback)(
28140
+ const loadHoldings = (0, import_react26.useCallback)(
27375
28141
  async (token) => {
27376
28142
  setIsLoading(true);
27377
28143
  try {
@@ -27418,12 +28184,12 @@ function CoinbaseConnect({
27418
28184
  },
27419
28185
  [publishableKey, transitionTo, tryRefreshToken]
27420
28186
  );
27421
- (0, import_react25.useEffect)(() => {
28187
+ (0, import_react26.useEffect)(() => {
27422
28188
  return () => {
27423
28189
  if (pollRef.current) clearInterval(pollRef.current);
27424
28190
  };
27425
28191
  }, []);
27426
- const minDepositUsd = (0, import_react25.useMemo)(() => {
28192
+ const minDepositUsd = (0, import_react26.useMemo)(() => {
27427
28193
  if (!selectedAsset || !defaultTokenData) return 0;
27428
28194
  const supportedToken = supportedTokensData?.data.find(
27429
28195
  (t14) => t14.symbol.toLowerCase() === selectedAsset.currency.toLowerCase()
@@ -27434,7 +28200,7 @@ function CoinbaseConnect({
27434
28200
  );
27435
28201
  return matchingChain?.minimum_deposit_amount_usd ?? Math.min(...supportedToken.chains.map((c) => c.minimum_deposit_amount_usd));
27436
28202
  }, [selectedAsset, supportedTokensData, defaultTokenData]);
27437
- const estimatedProcessingTime = (0, import_react25.useMemo)(() => {
28203
+ const estimatedProcessingTime = (0, import_react26.useMemo)(() => {
27438
28204
  if (!selectedAsset || !defaultTokenData) return null;
27439
28205
  const supportedToken = supportedTokensData?.data.find(
27440
28206
  (t14) => t14.symbol.toLowerCase() === selectedAsset.currency.toLowerCase()
@@ -29076,7 +29842,7 @@ function useExchanges({
29076
29842
  publishableKey,
29077
29843
  enabled = true
29078
29844
  }) {
29079
- const { data: exchanges = [], isLoading } = (0, import_react_query12.useQuery)({
29845
+ const { data: exchanges = [], isLoading } = (0, import_react_query13.useQuery)({
29080
29846
  queryKey: ["unifold", "exchanges", publishableKey],
29081
29847
  queryFn: () => getExchanges(void 0, publishableKey).then((res) => res.data),
29082
29848
  enabled,
@@ -29090,7 +29856,7 @@ function useApplePayProviders({
29090
29856
  publishableKey,
29091
29857
  enabled = true
29092
29858
  }) {
29093
- const { data: providers, isLoading } = (0, import_react_query13.useQuery)({
29859
+ const { data: providers, isLoading } = (0, import_react_query14.useQuery)({
29094
29860
  queryKey: ["unifold", "applePayProviders", publishableKey],
29095
29861
  queryFn: () => getApplePayProviders(publishableKey),
29096
29862
  enabled,
@@ -29105,7 +29871,7 @@ function useAllowedCountry(publishableKey) {
29105
29871
  data: ipData,
29106
29872
  isLoading: isIpLoading,
29107
29873
  error: ipError
29108
- } = (0, import_react_query14.useQuery)({
29874
+ } = (0, import_react_query15.useQuery)({
29109
29875
  queryKey: ["unifold", "ipAddress"],
29110
29876
  queryFn: () => getIpAddress(),
29111
29877
  refetchOnMount: false,
@@ -29120,7 +29886,7 @@ function useAllowedCountry(publishableKey) {
29120
29886
  data: configData,
29121
29887
  isLoading: isConfigLoading,
29122
29888
  error: configError
29123
- } = (0, import_react_query14.useQuery)({
29889
+ } = (0, import_react_query15.useQuery)({
29124
29890
  queryKey: ["unifold", "projectConfig", publishableKey],
29125
29891
  queryFn: () => getProjectConfig(publishableKey),
29126
29892
  refetchOnMount: false,
@@ -29167,7 +29933,7 @@ function useAddressValidation({
29167
29933
  refetchOnMount = false
29168
29934
  }) {
29169
29935
  const shouldValidate = enabled && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
29170
- const { data, isLoading, error } = (0, import_react_query15.useQuery)({
29936
+ const { data, isLoading, error } = (0, import_react_query16.useQuery)({
29171
29937
  queryKey: [
29172
29938
  "unifold",
29173
29939
  "addressValidation",
@@ -29451,9 +30217,9 @@ function DepositsModal({
29451
30217
  themeClass = ""
29452
30218
  }) {
29453
30219
  const { colors: colors2, fonts, components } = useTheme();
29454
- const [allExecutions, setAllExecutions] = (0, import_react27.useState)(sessionExecutions);
29455
- const [selectedExecution, setSelectedExecution] = (0, import_react27.useState)(null);
29456
- (0, import_react27.useEffect)(() => {
30220
+ const [allExecutions, setAllExecutions] = (0, import_react28.useState)(sessionExecutions);
30221
+ const [selectedExecution, setSelectedExecution] = (0, import_react28.useState)(null);
30222
+ (0, import_react28.useEffect)(() => {
29457
30223
  if (!open || !userId) return;
29458
30224
  const fetchExecutions = async () => {
29459
30225
  try {
@@ -29475,7 +30241,7 @@ function DepositsModal({
29475
30241
  clearInterval(pollInterval);
29476
30242
  };
29477
30243
  }, [open, userId, publishableKey, sessionExecutions]);
29478
- (0, import_react27.useEffect)(() => {
30244
+ (0, import_react28.useEffect)(() => {
29479
30245
  if (!open) {
29480
30246
  setSelectedExecution(null);
29481
30247
  }
@@ -29598,13 +30364,13 @@ function TokenSelectorSheet({
29598
30364
  }) {
29599
30365
  const { themeClass, colors: colors2, fonts, components } = useTheme();
29600
30366
  const isDarkMode = themeClass.includes("uf-dark");
29601
- const [searchQuery, setSearchQuery] = (0, import_react28.useState)("");
29602
- const [recentTokens, setRecentTokens] = (0, import_react28.useState)([]);
29603
- const [hoveredTokenKey, setHoveredTokenKey] = (0, import_react28.useState)(null);
29604
- (0, import_react28.useEffect)(() => {
30367
+ const [searchQuery, setSearchQuery] = (0, import_react29.useState)("");
30368
+ const [recentTokens, setRecentTokens] = (0, import_react29.useState)([]);
30369
+ const [hoveredTokenKey, setHoveredTokenKey] = (0, import_react29.useState)(null);
30370
+ (0, import_react29.useEffect)(() => {
29605
30371
  setRecentTokens(getRecentTokens());
29606
30372
  }, []);
29607
- const allOptions = (0, import_react28.useMemo)(() => {
30373
+ const allOptions = (0, import_react29.useMemo)(() => {
29608
30374
  const options = [];
29609
30375
  tokens.forEach((token) => {
29610
30376
  token.chains.forEach((chain) => {
@@ -29613,7 +30379,7 @@ function TokenSelectorSheet({
29613
30379
  });
29614
30380
  return options;
29615
30381
  }, [tokens]);
29616
- const quickSelectOptions = (0, import_react28.useMemo)(() => {
30382
+ const quickSelectOptions = (0, import_react29.useMemo)(() => {
29617
30383
  const result = [];
29618
30384
  const seen = /* @__PURE__ */ new Set();
29619
30385
  const addOption = (symbol, chainType, chainId, isRecent) => {
@@ -29645,7 +30411,7 @@ function TokenSelectorSheet({
29645
30411
  });
29646
30412
  setRecentTokens(updated);
29647
30413
  };
29648
- const fuse = (0, import_react28.useMemo)(
30414
+ const fuse = (0, import_react29.useMemo)(
29649
30415
  () => new Fuse(allOptions, {
29650
30416
  keys: [
29651
30417
  { name: "token.symbol", weight: 2 },
@@ -29658,7 +30424,7 @@ function TokenSelectorSheet({
29658
30424
  }),
29659
30425
  [allOptions]
29660
30426
  );
29661
- const filteredOptions = (0, import_react28.useMemo)(() => {
30427
+ const filteredOptions = (0, import_react29.useMemo)(() => {
29662
30428
  if (!searchQuery.trim()) return allOptions;
29663
30429
  const query = searchQuery.trim();
29664
30430
  const results = fuse.search(query);
@@ -30082,11 +30848,11 @@ function useDefaultToken({
30082
30848
  defaultTokenAddress,
30083
30849
  defaultSymbol
30084
30850
  }) {
30085
- const [token, setToken] = (0, import_react29.useState)(null);
30086
- const [chain, setChain] = (0, import_react29.useState)(null);
30087
- const [initialSelectionDone, setInitialSelectionDone] = (0, import_react29.useState)(false);
30088
- const appliedDefaultsRef = (0, import_react29.useRef)("");
30089
- (0, import_react29.useEffect)(() => {
30851
+ const [token, setToken] = (0, import_react30.useState)(null);
30852
+ const [chain, setChain] = (0, import_react30.useState)(null);
30853
+ const [initialSelectionDone, setInitialSelectionDone] = (0, import_react30.useState)(false);
30854
+ const appliedDefaultsRef = (0, import_react30.useRef)("");
30855
+ (0, import_react30.useEffect)(() => {
30090
30856
  if (!tokens.length) return;
30091
30857
  const defaultsKey = `${defaultTokenAddress ?? ""}|${defaultSymbol ?? ""}|${defaultChainType ?? ""}|${defaultChainId ?? ""}`;
30092
30858
  const defaultsChanged = appliedDefaultsRef.current !== defaultsKey;
@@ -30112,7 +30878,7 @@ function useDefaultToken({
30112
30878
  defaultChainId,
30113
30879
  initialSelectionDone
30114
30880
  ]);
30115
- (0, import_react29.useEffect)(() => {
30881
+ (0, import_react30.useEffect)(() => {
30116
30882
  if (!tokens.length || !token) return;
30117
30883
  const currentToken = tokens.find((t13) => t13.symbol === token);
30118
30884
  if (!currentToken || currentToken.chains.length === 0) return;
@@ -30411,7 +31177,7 @@ function GlossaryModal({
30411
31177
  ) });
30412
31178
  }
30413
31179
  function useCopyAddress() {
30414
- const [copied, setCopied] = (0, import_react30.useState)(false);
31180
+ const [copied, setCopied] = (0, import_react31.useState)(false);
30415
31181
  const handleCopy = (address) => {
30416
31182
  if (!address) return;
30417
31183
  navigator.clipboard.writeText(address);
@@ -30469,7 +31235,7 @@ function useHypercoreActivation(params) {
30469
31235
  const recipient = recipientAddress?.trim() ?? "";
30470
31236
  const source = sourceAddress?.trim() ?? "";
30471
31237
  const hasAddresses = !!recipient && !!source;
30472
- const { data, isLoading } = (0, import_react_query16.useQuery)({
31238
+ const { data, isLoading } = (0, import_react_query17.useQuery)({
30473
31239
  queryKey: ["unifold", "hypercoreActivation", source, recipient, publishableKey],
30474
31240
  queryFn: () => checkHypercoreActivation(
30475
31241
  {
@@ -30555,12 +31321,12 @@ function TransferCryptoSingleInput({
30555
31321
  }) {
30556
31322
  const { themeClass, colors: colors2, fonts, components } = useTheme();
30557
31323
  const isDarkMode = themeClass.includes("uf-dark");
30558
- const [copied, setCopied] = (0, import_react26.useState)(false);
31324
+ const [copied, setCopied] = (0, import_react27.useState)(false);
30559
31325
  const { copied: copiedRecipient, handleCopy: handleCopyRecipientAddress } = useCopyAddress();
30560
- const [glossaryOpen, setGlossaryOpen] = (0, import_react26.useState)(false);
30561
- const [detailsExpanded, setDetailsExpanded] = (0, import_react26.useState)(false);
30562
- const [depositsModalOpen, setDepositsModalOpen] = (0, import_react26.useState)(false);
30563
- const [tokenSelectorOpen, setTokenSelectorOpen] = (0, import_react26.useState)(false);
31326
+ const [glossaryOpen, setGlossaryOpen] = (0, import_react27.useState)(false);
31327
+ const [detailsExpanded, setDetailsExpanded] = (0, import_react27.useState)(false);
31328
+ const [depositsModalOpen, setDepositsModalOpen] = (0, import_react27.useState)(false);
31329
+ const [tokenSelectorOpen, setTokenSelectorOpen] = (0, import_react27.useState)(false);
30564
31330
  const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDepositTokens(
30565
31331
  publishableKey,
30566
31332
  {
@@ -30595,7 +31361,7 @@ function TransferCryptoSingleInput({
30595
31361
  const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
30596
31362
  const loading = externalWallets?.length ? false : walletsLoading;
30597
31363
  const error = walletsError?.message ?? null;
30598
- const allAvailableChains = (0, import_react26.useMemo)(() => {
31364
+ const allAvailableChains = (0, import_react27.useMemo)(() => {
30599
31365
  const chainsMap = /* @__PURE__ */ new Map();
30600
31366
  supportedTokens.forEach((t13) => {
30601
31367
  t13.chains.forEach((c) => {
@@ -30640,7 +31406,7 @@ function TransferCryptoSingleInput({
30640
31406
  publishableKey,
30641
31407
  enabled: !!depositAddress && !!recipientAddress
30642
31408
  });
30643
- (0, import_react26.useEffect)(() => {
31409
+ (0, import_react27.useEffect)(() => {
30644
31410
  if (!onSourceTokenChange || !token || !chain || !initialSelectionDone) return;
30645
31411
  const { chainType, chainId } = parseChainKey(chain);
30646
31412
  const matchedToken = supportedTokens.find((t13) => t13.symbol === token);
@@ -30657,7 +31423,7 @@ function TransferCryptoSingleInput({
30657
31423
  isStablecoin: matchedToken?.is_stablecoin ?? false
30658
31424
  });
30659
31425
  }, [token, chain, initialSelectionDone, onSourceTokenChange, supportedTokens]);
30660
- (0, import_react26.useEffect)(() => {
31426
+ (0, import_react27.useEffect)(() => {
30661
31427
  if (onExecutionsChange) {
30662
31428
  onExecutionsChange(depositExecutions);
30663
31429
  }
@@ -31333,11 +32099,11 @@ function TransferCryptoDoubleInput({
31333
32099
  }) {
31334
32100
  const { themeClass, colors: colors2, fonts, components } = useTheme();
31335
32101
  const isDarkMode = themeClass.includes("uf-dark");
31336
- const [copied, setCopied] = (0, import_react31.useState)(false);
32102
+ const [copied, setCopied] = (0, import_react32.useState)(false);
31337
32103
  const { copied: copiedRecipient, handleCopy: handleCopyRecipientAddress } = useCopyAddress();
31338
- const [glossaryOpen, setGlossaryOpen] = (0, import_react31.useState)(false);
31339
- const [detailsExpanded, setDetailsExpanded] = (0, import_react31.useState)(false);
31340
- const [depositsModalOpen, setDepositsModalOpen] = (0, import_react31.useState)(false);
32104
+ const [glossaryOpen, setGlossaryOpen] = (0, import_react32.useState)(false);
32105
+ const [detailsExpanded, setDetailsExpanded] = (0, import_react32.useState)(false);
32106
+ const [depositsModalOpen, setDepositsModalOpen] = (0, import_react32.useState)(false);
31341
32107
  const { data: tokensResponse, isLoading: tokensLoading } = useSupportedDepositTokens(
31342
32108
  publishableKey,
31343
32109
  {
@@ -31371,7 +32137,7 @@ function TransferCryptoDoubleInput({
31371
32137
  const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
31372
32138
  const loading = externalWallets?.length ? false : walletsLoading;
31373
32139
  const error = walletsError?.message ?? null;
31374
- const allAvailableChains = (0, import_react31.useMemo)(() => {
32140
+ const allAvailableChains = (0, import_react32.useMemo)(() => {
31375
32141
  const chainsMap = /* @__PURE__ */ new Map();
31376
32142
  supportedTokens.forEach((t13) => {
31377
32143
  t13.chains.forEach((c) => {
@@ -31415,7 +32181,7 @@ function TransferCryptoDoubleInput({
31415
32181
  publishableKey,
31416
32182
  enabled: !!depositAddress && !!recipientAddress
31417
32183
  });
31418
- (0, import_react31.useEffect)(() => {
32184
+ (0, import_react32.useEffect)(() => {
31419
32185
  if (onExecutionsChange) {
31420
32186
  onExecutionsChange(depositExecutions);
31421
32187
  }
@@ -31967,7 +32733,7 @@ function useDepositQuote(params) {
31967
32733
  ...adjustForSlippage ? { adjust_for_slippage: true } : {},
31968
32734
  ...stablecoinParity ? { stablecoin_parity: true } : {}
31969
32735
  };
31970
- return (0, import_react_query17.useQuery)({
32736
+ return (0, import_react_query18.useQuery)({
31971
32737
  queryKey: [
31972
32738
  "unifold",
31973
32739
  "depositQuote",
@@ -31997,7 +32763,7 @@ function useExternalWallets({
31997
32763
  publishableKey,
31998
32764
  enabled = true
31999
32765
  }) {
32000
- const { data: wallets = [], isLoading } = (0, import_react_query18.useQuery)({
32766
+ const { data: wallets = [], isLoading } = (0, import_react_query19.useQuery)({
32001
32767
  queryKey: ["unifold", "external-wallets", publishableKey],
32002
32768
  queryFn: () => getExternalWallets(publishableKey).then((res) => res.data),
32003
32769
  enabled: enabled && !!publishableKey,
@@ -32861,13 +33627,13 @@ function ConfirmingView({
32861
33627
  amountReceivedUsdAtSubmission
32862
33628
  }) {
32863
33629
  const { colors: colors2, fonts, components } = useTheme();
32864
- const [fallbackSettled, setFallbackSettled] = (0, import_react32.useState)(false);
33630
+ const [fallbackSettled, setFallbackSettled] = (0, import_react33.useState)(false);
32865
33631
  const hasExecution = executions.length > 0;
32866
33632
  const isCheckoutMode = paymentIntentStatus != null;
32867
33633
  const isPaymentComplete = paymentIntentStatus === "succeeded";
32868
33634
  const amountChanged = amountReceivedUsdAtSubmission != null && amountReceivedUsd != null && amountReceivedUsd !== amountReceivedUsdAtSubmission;
32869
33635
  const piSettled = !isCheckoutMode || isPaymentComplete || amountChanged || fallbackSettled;
32870
- (0, import_react32.useEffect)(() => {
33636
+ (0, import_react33.useEffect)(() => {
32871
33637
  if (!hasExecution || piSettled) return;
32872
33638
  const timeout = setTimeout(() => setFallbackSettled(true), SETTLE_FALLBACK_MS);
32873
33639
  return () => clearTimeout(timeout);
@@ -34601,10 +35367,9 @@ function DepositModal({
34601
35367
  applePaySubTitle = "Instant",
34602
35368
  enableBankTransfer,
34603
35369
  enableStripeLink = false,
34604
- email: emailProp,
35370
+ userEmail,
34605
35371
  hideDepositFlowInfo = false,
34606
35372
  hideDisplayDescription = false,
34607
- externalUserEmail,
34608
35373
  onDepositSuccess,
34609
35374
  onDepositError,
34610
35375
  onEvent,
@@ -35035,11 +35800,18 @@ function DepositModal({
35035
35800
  return "Success";
35036
35801
  case "guest_limit_reached":
35037
35802
  return "Limit reached";
35803
+ case "limit_upgrade_intro":
35804
+ case "limit_upgrade_failed":
35805
+ return "Limit reached";
35806
+ case "limit_upgrade_form":
35807
+ return "Verify identity";
35808
+ case "limit_upgrade_submitting":
35809
+ return "Verifying";
35038
35810
  default:
35039
35811
  return "Pay with Apple Pay";
35040
35812
  }
35041
35813
  })();
35042
- const applePayShowBack = sessionOpenedFromMenu || applePayView === "phone_input" || applePayView === "email_otp" || applePayView === "phone_otp" || applePayView === "submitting_session" || applePayView === "checking_deposit";
35814
+ const applePayShowBack = sessionOpenedFromMenu || applePayView === "phone_input" || applePayView === "email_otp" || applePayView === "phone_otp" || applePayView === "submitting_session" || applePayView === "checking_deposit" || applePayView === "limit_upgrade_intro" || applePayView === "limit_upgrade_form" || applePayView === "limit_upgrade_failed";
35043
35815
  const handleBack = () => {
35044
35816
  if (view === "card" && cardView === "quotes") {
35045
35817
  setCardView("amount");
@@ -35718,7 +36490,7 @@ function DepositModal({
35718
36490
  destinationChainId,
35719
36491
  destinationTokenAddress,
35720
36492
  wallets,
35721
- email: emailProp,
36493
+ email: userEmail,
35722
36494
  iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/link.svg` : void 0,
35723
36495
  step: stripeLinkStep,
35724
36496
  onStepChange: setStripeLinkStep,
@@ -35781,13 +36553,10 @@ function DepositModal({
35781
36553
  ref: applePayHandleRef,
35782
36554
  userId,
35783
36555
  publishableKey,
35784
- recipientAddress,
35785
36556
  destinationChainType,
35786
36557
  destinationChainId,
35787
36558
  destinationTokenAddress,
35788
- destinationTokenSymbol,
35789
- externalUserEmail,
35790
- enableApplePay,
36559
+ userEmail,
35791
36560
  wallets,
35792
36561
  onViewChange: setApplePayView,
35793
36562
  onEvent,
@@ -35815,7 +36584,7 @@ function DepositModal({
35815
36584
  var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["succeeded", "expired", "refunded", "canceled"]);
35816
36585
  function usePaymentIntent(params) {
35817
36586
  const { clientSecret, publishableKey, enabled = true, pollingInterval = 3e3 } = params;
35818
- return (0, import_react_query19.useQuery)({
36587
+ return (0, import_react_query20.useQuery)({
35819
36588
  queryKey: ["unifold", "paymentIntent", clientSecret, publishableKey],
35820
36589
  queryFn: () => retrievePaymentIntent(clientSecret, publishableKey),
35821
36590
  enabled: enabled && !!clientSecret && !!publishableKey,
@@ -35897,12 +36666,12 @@ function CheckoutModal({
35897
36666
  onEvent
35898
36667
  }) {
35899
36668
  const { colors: colors2, fonts, components } = useTheme();
35900
- const [view, setView] = (0, import_react33.useState)("main");
35901
- const resetViewTimeoutRef = (0, import_react33.useRef)(null);
35902
- const [browserWalletInfo, setBrowserWalletInfo] = (0, import_react33.useState)(null);
35903
- const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react33.useState)(() => getStoredWalletState()?.chainType);
35904
- const lastCheckoutMethodRef = (0, import_react33.useRef)(void 0);
35905
- const emitCheckoutSuccess = (0, import_react33.useCallback)(
36669
+ const [view, setView] = (0, import_react34.useState)("main");
36670
+ const resetViewTimeoutRef = (0, import_react34.useRef)(null);
36671
+ const [browserWalletInfo, setBrowserWalletInfo] = (0, import_react34.useState)(null);
36672
+ const [browserWalletChainType, setBrowserWalletChainType] = (0, import_react34.useState)(() => getStoredWalletState()?.chainType);
36673
+ const lastCheckoutMethodRef = (0, import_react34.useRef)(void 0);
36674
+ const emitCheckoutSuccess = (0, import_react34.useCallback)(
35906
36675
  (data, method) => {
35907
36676
  const isSucceeded = data.status === "succeeded";
35908
36677
  const richIntent = isSucceeded && data.paymentIntent ? mapToCheckoutPaymentIntent(data.paymentIntent) : void 0;
@@ -35925,10 +36694,10 @@ function CheckoutModal({
35925
36694
  },
35926
36695
  [onCheckoutSuccess, onEvent]
35927
36696
  );
35928
- const [resolvedTheme, setResolvedTheme] = (0, import_react33.useState)(
36697
+ const [resolvedTheme, setResolvedTheme] = (0, import_react34.useState)(
35929
36698
  theme === "auto" ? "dark" : theme
35930
36699
  );
35931
- (0, import_react33.useEffect)(() => {
36700
+ (0, import_react34.useEffect)(() => {
35932
36701
  if (theme === "auto") {
35933
36702
  const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)");
35934
36703
  setResolvedTheme(mediaQuery.matches ? "dark" : "light");
@@ -35958,15 +36727,15 @@ function CheckoutModal({
35958
36727
  });
35959
36728
  const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
35960
36729
  const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
35961
- (0, import_react33.useEffect)(() => {
36730
+ (0, import_react34.useEffect)(() => {
35962
36731
  if (view === "transfer" && !showTransferCrypto) {
35963
36732
  setView("main");
35964
36733
  } else if (view === "wallet_connect" && !showConnectWallet) {
35965
36734
  setView("main");
35966
36735
  }
35967
36736
  }, [showConnectWallet, showTransferCrypto, view]);
35968
- const prevStatusRef = (0, import_react33.useRef)(null);
35969
- (0, import_react33.useEffect)(() => {
36737
+ const prevStatusRef = (0, import_react34.useRef)(null);
36738
+ (0, import_react34.useEffect)(() => {
35970
36739
  if (!paymentIntent) return;
35971
36740
  const prev = prevStatusRef.current;
35972
36741
  prevStatusRef.current = paymentIntent.status;
@@ -35984,11 +36753,11 @@ function CheckoutModal({
35984
36753
  );
35985
36754
  }
35986
36755
  }, [emitCheckoutSuccess, paymentIntent, view]);
35987
- const wallets = (0, import_react33.useMemo)(() => {
36756
+ const wallets = (0, import_react34.useMemo)(() => {
35988
36757
  if (!paymentIntent) return [];
35989
36758
  return mapDepositAddressesToWallets(paymentIntent.deposit_addresses, paymentIntent);
35990
36759
  }, [paymentIntent]);
35991
- const formatCryptoAmount = (0, import_react33.useMemo)(() => {
36760
+ const formatCryptoAmount = (0, import_react34.useMemo)(() => {
35992
36761
  if (!paymentIntent) return (_) => "";
35993
36762
  const decimals = paymentIntent.destination_token_decimals ?? 6;
35994
36763
  const symbol = paymentIntent.currency.toUpperCase();
@@ -35998,7 +36767,7 @@ function CheckoutModal({
35998
36767
  return `${formatted} ${symbol}`;
35999
36768
  };
36000
36769
  }, [paymentIntent]);
36001
- const remainingAmountUsd = (0, import_react33.useMemo)(() => {
36770
+ const remainingAmountUsd = (0, import_react34.useMemo)(() => {
36002
36771
  if (!paymentIntent) return void 0;
36003
36772
  const total = parseFloat(paymentIntent.destination_amount_usd || paymentIntent.amount_usd);
36004
36773
  const received = parseFloat(
@@ -36009,8 +36778,8 @@ function CheckoutModal({
36009
36778
  const remaining = total - received;
36010
36779
  return remaining > 0 ? remaining.toFixed(2) : "0.00";
36011
36780
  }, [paymentIntent]);
36012
- const [selectedSource, setSelectedSource] = (0, import_react33.useState)(null);
36013
- const remainingDestinationAmount = (0, import_react33.useMemo)(() => {
36781
+ const [selectedSource, setSelectedSource] = (0, import_react34.useState)(null);
36782
+ const remainingDestinationAmount = (0, import_react34.useMemo)(() => {
36014
36783
  if (!paymentIntent) return "0";
36015
36784
  const remaining = BigInt(paymentIntent.destination_amount) - BigInt(paymentIntent.destination_amount_received);
36016
36785
  return remaining > 0n ? remaining.toString() : "0";
@@ -36032,7 +36801,7 @@ function CheckoutModal({
36032
36801
  stablecoinParity: paymentIntent?.stablecoin_parity ?? false,
36033
36802
  enabled: open && view === "transfer" && !!paymentIntent && !!selectedSource && remainingDestinationAmount !== "0"
36034
36803
  });
36035
- const effectiveCheckoutQuote = (0, import_react33.useMemo)(() => {
36804
+ const effectiveCheckoutQuote = (0, import_react34.useMemo)(() => {
36036
36805
  if (!sourceQuote || !selectedSource) return null;
36037
36806
  const baseQuote = {
36038
36807
  sourceAmount: sourceQuote.source_amount,
@@ -36053,7 +36822,7 @@ function CheckoutModal({
36053
36822
  sourceAmountUsd: minUsd.toFixed(2)
36054
36823
  };
36055
36824
  }, [sourceQuote, selectedSource]);
36056
- const handleBrowserWalletClick = (0, import_react33.useCallback)(
36825
+ const handleBrowserWalletClick = (0, import_react34.useCallback)(
36057
36826
  (walletInfo) => {
36058
36827
  const walletChainType = walletInfo.type === "phantom-solana" || walletInfo.type === "solflare" || walletInfo.type === "backpack" || walletInfo.type === "glow" ? "solana" : "ethereum";
36059
36828
  setStoredWalletState(walletInfo.type);
@@ -36076,19 +36845,19 @@ function CheckoutModal({
36076
36845
  },
36077
36846
  [wallets, onCheckoutError]
36078
36847
  );
36079
- const handleWalletConnectClick = (0, import_react33.useCallback)(() => {
36848
+ const handleWalletConnectClick = (0, import_react34.useCallback)(() => {
36080
36849
  setBrowserWalletInfo(null);
36081
36850
  lastCheckoutMethodRef.current = "wallet_connect";
36082
36851
  setView("wallet_connect");
36083
36852
  }, []);
36084
- const handleWalletDisconnect = (0, import_react33.useCallback)(() => {
36853
+ const handleWalletDisconnect = (0, import_react34.useCallback)(() => {
36085
36854
  setUserDisconnectedWallet(true);
36086
36855
  clearStoredWalletState();
36087
36856
  setBrowserWalletChainType(void 0);
36088
36857
  setBrowserWalletInfo(null);
36089
36858
  setView("main");
36090
36859
  }, []);
36091
- const handleClose = (0, import_react33.useCallback)(() => {
36860
+ const handleClose = (0, import_react34.useCallback)(() => {
36092
36861
  onOpenChange(false);
36093
36862
  if (resetViewTimeoutRef.current) {
36094
36863
  clearTimeout(resetViewTimeoutRef.current);
@@ -36100,7 +36869,7 @@ function CheckoutModal({
36100
36869
  resetViewTimeoutRef.current = null;
36101
36870
  }, 200);
36102
36871
  }, [onOpenChange]);
36103
- (0, import_react33.useLayoutEffect)(() => {
36872
+ (0, import_react34.useLayoutEffect)(() => {
36104
36873
  if (!open) return;
36105
36874
  if (resetViewTimeoutRef.current) {
36106
36875
  clearTimeout(resetViewTimeoutRef.current);
@@ -36110,7 +36879,7 @@ function CheckoutModal({
36110
36879
  setBrowserWalletInfo(null);
36111
36880
  lastCheckoutMethodRef.current = void 0;
36112
36881
  }, [open]);
36113
- (0, import_react33.useEffect)(
36882
+ (0, import_react34.useEffect)(
36114
36883
  () => () => {
36115
36884
  if (resetViewTimeoutRef.current) {
36116
36885
  clearTimeout(resetViewTimeoutRef.current);
@@ -36118,7 +36887,7 @@ function CheckoutModal({
36118
36887
  },
36119
36888
  []
36120
36889
  );
36121
- const handleBack = (0, import_react33.useCallback)(() => {
36890
+ const handleBack = (0, import_react34.useCallback)(() => {
36122
36891
  setView("main");
36123
36892
  }, []);
36124
36893
  const poweredByFooter = /* @__PURE__ */ (0, import_jsx_runtime81.jsx)("div", { className: "uf-pt-3", children: /* @__PURE__ */ (0, import_jsx_runtime81.jsx)(
@@ -36495,7 +37264,7 @@ function CheckoutModal({
36495
37264
  ) }) });
36496
37265
  }
36497
37266
  function useSupportedDestinationTokens(publishableKey, enabled = true) {
36498
- return (0, import_react_query20.useQuery)({
37267
+ return (0, import_react_query21.useQuery)({
36499
37268
  queryKey: ["unifold", "supportedDestinationTokens", publishableKey],
36500
37269
  queryFn: () => getSupportedDestinationTokens(publishableKey),
36501
37270
  staleTime: 1e3 * 60 * 5,
@@ -36530,7 +37299,7 @@ function useSourceTokenValidation(params) {
36530
37299
  enabled = true
36531
37300
  } = params;
36532
37301
  const hasParams = !!sourceChainType && !!sourceChainId && !!sourceTokenAddress;
36533
- return (0, import_react_query21.useQuery)({
37302
+ return (0, import_react_query22.useQuery)({
36534
37303
  queryKey: [
36535
37304
  "unifold",
36536
37305
  "sourceTokenValidation",
@@ -36579,7 +37348,7 @@ function useSourceTokenValidation(params) {
36579
37348
  function useAddressBalance(params) {
36580
37349
  const { address, chainType, chainId, tokenAddress, publishableKey, enabled = true } = params;
36581
37350
  const hasParams = !!address && !!chainType && !!chainId && !!tokenAddress;
36582
- return (0, import_react_query22.useQuery)({
37351
+ return (0, import_react_query23.useQuery)({
36583
37352
  queryKey: [
36584
37353
  "unifold",
36585
37354
  "addressBalance",
@@ -36635,7 +37404,7 @@ function useAddressBalance(params) {
36635
37404
  }
36636
37405
  function useExecutions(userId, publishableKey, options) {
36637
37406
  const actionType = options?.actionType ?? ActionType.Deposit;
36638
- return (0, import_react_query23.useQuery)({
37407
+ return (0, import_react_query24.useQuery)({
36639
37408
  queryKey: ["unifold", "executions", actionType, userId, publishableKey],
36640
37409
  queryFn: () => queryExecutions(userId, publishableKey, actionType),
36641
37410
  enabled: (options?.enabled ?? true) && !!userId,
@@ -36681,20 +37450,20 @@ function useWithdrawPolling({
36681
37450
  status: execution.status,
36682
37451
  failureReason: execution.failure_reason
36683
37452
  });
36684
- const [executions, setExecutions] = (0, import_react35.useState)([]);
36685
- const [isPolling, setIsPolling] = (0, import_react35.useState)(false);
36686
- const enabledAtRef = (0, import_react35.useRef)(/* @__PURE__ */ new Date());
36687
- const trackedRef = (0, import_react35.useRef)(/* @__PURE__ */ new Map());
36688
- const prevEnabledRef = (0, import_react35.useRef)(false);
36689
- const onSuccessRef = (0, import_react35.useRef)(onWithdrawSuccess);
36690
- const onErrorRef = (0, import_react35.useRef)(onWithdrawError);
36691
- (0, import_react35.useEffect)(() => {
37453
+ const [executions, setExecutions] = (0, import_react36.useState)([]);
37454
+ const [isPolling, setIsPolling] = (0, import_react36.useState)(false);
37455
+ const enabledAtRef = (0, import_react36.useRef)(/* @__PURE__ */ new Date());
37456
+ const trackedRef = (0, import_react36.useRef)(/* @__PURE__ */ new Map());
37457
+ const prevEnabledRef = (0, import_react36.useRef)(false);
37458
+ const onSuccessRef = (0, import_react36.useRef)(onWithdrawSuccess);
37459
+ const onErrorRef = (0, import_react36.useRef)(onWithdrawError);
37460
+ (0, import_react36.useEffect)(() => {
36692
37461
  onSuccessRef.current = onWithdrawSuccess;
36693
37462
  }, [onWithdrawSuccess]);
36694
- (0, import_react35.useEffect)(() => {
37463
+ (0, import_react36.useEffect)(() => {
36695
37464
  onErrorRef.current = onWithdrawError;
36696
37465
  }, [onWithdrawError]);
36697
- (0, import_react35.useEffect)(() => {
37466
+ (0, import_react36.useEffect)(() => {
36698
37467
  if (enabled && !prevEnabledRef.current) {
36699
37468
  enabledAtRef.current = /* @__PURE__ */ new Date();
36700
37469
  trackedRef.current.clear();
@@ -36704,7 +37473,7 @@ function useWithdrawPolling({
36704
37473
  }
36705
37474
  prevEnabledRef.current = enabled;
36706
37475
  }, [enabled]);
36707
- (0, import_react35.useEffect)(() => {
37476
+ (0, import_react36.useEffect)(() => {
36708
37477
  if (!userId || !enabled) return;
36709
37478
  const enabledAt = enabledAtRef.current;
36710
37479
  const poll = async () => {
@@ -36784,7 +37553,7 @@ function useWithdrawPolling({
36784
37553
  setIsPolling(false);
36785
37554
  };
36786
37555
  }, [userId, publishableKey, enabled]);
36787
- (0, import_react35.useEffect)(() => {
37556
+ (0, import_react36.useEffect)(() => {
36788
37557
  if (!enabled || !depositWalletId) return;
36789
37558
  const trigger = async () => {
36790
37559
  try {
@@ -36961,7 +37730,7 @@ function useVerifyRecipientAddress(params) {
36961
37730
  } = params;
36962
37731
  const trimmedAddress = recipientAddress?.trim() || "";
36963
37732
  const hasAllParams = !!chainType && !!chainId && !!tokenAddress && trimmedAddress.length > 0;
36964
- return (0, import_react_query24.useQuery)({
37733
+ return (0, import_react_query25.useQuery)({
36965
37734
  queryKey: [
36966
37735
  "unifold",
36967
37736
  "verifyRecipientAddress",
@@ -37000,7 +37769,7 @@ function useGetDepositAddress(params) {
37000
37769
  enabled = true
37001
37770
  } = params;
37002
37771
  const canFire = !!userId && !!recipientAddress && !!destinationChainType && !!destinationChainId && !!destinationTokenAddress;
37003
- return (0, import_react_query25.useQuery)({
37772
+ return (0, import_react_query26.useQuery)({
37004
37773
  queryKey: [
37005
37774
  "unifold",
37006
37775
  "getDepositAddress",
@@ -37067,7 +37836,7 @@ function useHypercoreWithdrawActivation(params) {
37067
37836
  actionType: ActionType.Withdraw,
37068
37837
  enabled: enabled && isHypercore(sourceChainId)
37069
37838
  });
37070
- const depositWalletAddress = (0, import_react37.useMemo)(() => {
37839
+ const depositWalletAddress = (0, import_react38.useMemo)(() => {
37071
37840
  const wallets = depositWalletLookup.data?.data ?? [];
37072
37841
  return wallets.find((w) => w.chain_type === sourceChainType)?.address;
37073
37842
  }, [depositWalletLookup.data, sourceChainType]);
@@ -37153,22 +37922,22 @@ function WithdrawForm({
37153
37922
  footerLeft
37154
37923
  }) {
37155
37924
  const { colors: colors2, fonts, components } = useTheme();
37156
- const [recipientAddress, setRecipientAddress] = (0, import_react36.useState)(recipientAddressProp || "");
37157
- const [amount, setAmount] = (0, import_react36.useState)("");
37158
- const [inputUnit, setInputUnit] = (0, import_react36.useState)("fiat");
37159
- const [isSubmitting, setIsSubmitting] = (0, import_react36.useState)(false);
37160
- const [submitError, setSubmitError] = (0, import_react36.useState)(null);
37161
- const [detailsExpanded, setDetailsExpanded] = (0, import_react36.useState)(false);
37162
- const [glossaryOpen, setGlossaryOpen] = (0, import_react36.useState)(false);
37163
- const [isMaxed, setIsMaxed] = (0, import_react36.useState)(false);
37164
- (0, import_react36.useEffect)(() => {
37925
+ const [recipientAddress, setRecipientAddress] = (0, import_react37.useState)(recipientAddressProp || "");
37926
+ const [amount, setAmount] = (0, import_react37.useState)("");
37927
+ const [inputUnit, setInputUnit] = (0, import_react37.useState)("fiat");
37928
+ const [isSubmitting, setIsSubmitting] = (0, import_react37.useState)(false);
37929
+ const [submitError, setSubmitError] = (0, import_react37.useState)(null);
37930
+ const [detailsExpanded, setDetailsExpanded] = (0, import_react37.useState)(false);
37931
+ const [glossaryOpen, setGlossaryOpen] = (0, import_react37.useState)(false);
37932
+ const [isMaxed, setIsMaxed] = (0, import_react37.useState)(false);
37933
+ (0, import_react37.useEffect)(() => {
37165
37934
  setRecipientAddress(recipientAddressProp || "");
37166
37935
  setAmount("");
37167
37936
  setInputUnit("fiat");
37168
37937
  setSubmitError(null);
37169
37938
  setIsMaxed(false);
37170
37939
  }, [recipientAddressProp]);
37171
- (0, import_react36.useEffect)(() => {
37940
+ (0, import_react37.useEffect)(() => {
37172
37941
  setIsMaxed(false);
37173
37942
  }, [balanceData?.balanceBaseUnit]);
37174
37943
  const trimmedAddress = recipientAddress.trim();
@@ -37186,7 +37955,7 @@ function WithdrawForm({
37186
37955
  enabled: debouncedAddress.length > 5 && !!selectedChain
37187
37956
  });
37188
37957
  const isDebouncing = trimmedAddress !== debouncedAddress;
37189
- const addressError = (0, import_react36.useMemo)(() => {
37958
+ const addressError = (0, import_react37.useMemo)(() => {
37190
37959
  if (!trimmedAddress || trimmedAddress.length <= 5) return null;
37191
37960
  if (isDebouncing || isVerifyingAddress) return null;
37192
37961
  if (verifyError) return t10.invalidAddress;
@@ -37220,33 +37989,33 @@ function WithdrawForm({
37220
37989
  destinationTokenAddress: selectedChain?.token_address,
37221
37990
  enabled: isAddressValid
37222
37991
  });
37223
- const exchangeRate = (0, import_react36.useMemo)(() => {
37992
+ const exchangeRate = (0, import_react37.useMemo)(() => {
37224
37993
  if (!balanceData?.exchangeRate) return 0;
37225
37994
  return parseFloat(balanceData.exchangeRate);
37226
37995
  }, [balanceData]);
37227
- const balanceCrypto = (0, import_react36.useMemo)(() => {
37996
+ const balanceCrypto = (0, import_react37.useMemo)(() => {
37228
37997
  if (!balanceData?.balanceHuman) return 0;
37229
37998
  return parseFloat(balanceData.balanceHuman);
37230
37999
  }, [balanceData]);
37231
- const balanceUsdNum = (0, import_react36.useMemo)(() => {
38000
+ const balanceUsdNum = (0, import_react37.useMemo)(() => {
37232
38001
  if (!balanceData?.balanceUsd) return 0;
37233
38002
  return parseFloat(balanceData.balanceUsd);
37234
38003
  }, [balanceData]);
37235
38004
  const tokenSymbol = sourceTokenSymbol || balanceData?.symbol || "TOKEN";
37236
38005
  const sourceDecimals = balanceData?.decimals ?? 6;
37237
- const cryptoAmountFromInput = (0, import_react36.useMemo)(() => {
38006
+ const cryptoAmountFromInput = (0, import_react37.useMemo)(() => {
37238
38007
  const val = parseFloat(amount);
37239
38008
  if (!val || val <= 0) return 0;
37240
38009
  if (inputUnit === "crypto") return val;
37241
38010
  return exchangeRate > 0 ? val / exchangeRate : 0;
37242
38011
  }, [amount, inputUnit, exchangeRate]);
37243
- const fiatAmountFromInput = (0, import_react36.useMemo)(() => {
38012
+ const fiatAmountFromInput = (0, import_react37.useMemo)(() => {
37244
38013
  const val = parseFloat(amount);
37245
38014
  if (!val || val <= 0) return 0;
37246
38015
  if (inputUnit === "fiat") return val;
37247
38016
  return val * exchangeRate;
37248
38017
  }, [amount, inputUnit, exchangeRate]);
37249
- const convertedDisplay = (0, import_react36.useMemo)(() => {
38018
+ const convertedDisplay = (0, import_react37.useMemo)(() => {
37250
38019
  if (!amount || parseFloat(amount) <= 0) return null;
37251
38020
  if (inputUnit === "crypto") {
37252
38021
  return `$${fiatAmountFromInput.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
@@ -37265,7 +38034,7 @@ function WithdrawForm({
37265
38034
  isMaxed,
37266
38035
  isStablecoin
37267
38036
  ]);
37268
- const balanceDisplay = (0, import_react36.useMemo)(() => {
38037
+ const balanceDisplay = (0, import_react37.useMemo)(() => {
37269
38038
  if (isLoadingBalance || !balanceData) return null;
37270
38039
  if (inputUnit === "crypto") {
37271
38040
  const displayDecimals = isStablecoin ? 2 : 6;
@@ -37288,7 +38057,7 @@ function WithdrawForm({
37288
38057
  tokenSymbol,
37289
38058
  isStablecoin
37290
38059
  ]);
37291
- const handleSwitchUnit = (0, import_react36.useCallback)(() => {
38060
+ const handleSwitchUnit = (0, import_react37.useCallback)(() => {
37292
38061
  if (isMaxed && balanceData) {
37293
38062
  if (inputUnit === "crypto") {
37294
38063
  setAmount((Math.round(balanceUsdNum * 100) / 100).toFixed(2));
@@ -37315,7 +38084,7 @@ function WithdrawForm({
37315
38084
  setInputUnit("crypto");
37316
38085
  }
37317
38086
  }, [amount, inputUnit, exchangeRate, sourceDecimals, isMaxed, balanceData, balanceUsdNum]);
37318
- const handleMaxClick = (0, import_react36.useCallback)(() => {
38087
+ const handleMaxClick = (0, import_react37.useCallback)(() => {
37319
38088
  if (inputUnit === "crypto") {
37320
38089
  if (balanceCrypto <= 0) return;
37321
38090
  setAmount(balanceData?.balanceHuman ?? "0");
@@ -37329,7 +38098,7 @@ function WithdrawForm({
37329
38098
  const isBelowMinimum = minimumWithdrawAmountUsd !== null && fiatAmountFromInput > 0 && Math.round(fiatAmountFromInput * 100) / 100 < minimumWithdrawAmountUsd;
37330
38099
  const isOverBalance = inputUnit === "crypto" ? cryptoAmountFromInput > 0 && balanceCrypto > 0 && cryptoAmountFromInput > balanceCrypto : fiatAmountFromInput > 0 && balanceUsdNum > 0 && Math.round(fiatAmountFromInput * 100) / 100 > Math.round(balanceUsdNum * 100) / 100;
37331
38100
  const isFormValid = trimmedAddress.length > 0 && amount.trim().length > 0 && cryptoAmountFromInput > 0 && isAddressValid && !isBelowMinimum && !isOverBalance && !isBalanceBelowMinimum && !!balanceData;
37332
- const handleWithdraw = (0, import_react36.useCallback)(async () => {
38101
+ const handleWithdraw = (0, import_react37.useCallback)(async () => {
37333
38102
  if (!selectedToken || !selectedChain) return;
37334
38103
  if (!isFormValid) return;
37335
38104
  setIsSubmitting(true);
@@ -37956,9 +38725,9 @@ function WithdrawConfirmingView({
37956
38725
  onViewTracker
37957
38726
  }) {
37958
38727
  const { colors: colors2, fonts, components } = useTheme();
37959
- const [showButton, setShowButton] = (0, import_react38.useState)(false);
38728
+ const [showButton, setShowButton] = (0, import_react39.useState)(false);
37960
38729
  const latestExecution = executions.length > 0 ? executions[executions.length - 1] : null;
37961
- (0, import_react38.useEffect)(() => {
38730
+ (0, import_react39.useEffect)(() => {
37962
38731
  if (latestExecution) return;
37963
38732
  const timer = setTimeout(() => setShowButton(true), SHOW_BUTTON_DELAY_MS);
37964
38733
  return () => clearTimeout(timer);
@@ -38102,7 +38871,7 @@ function WithdrawModal({
38102
38871
  theme = "dark",
38103
38872
  hideOverlay = false
38104
38873
  }) {
38105
- const onWithdrawSuccessFor = (0, import_react34.useCallback)(
38874
+ const onWithdrawSuccessFor = (0, import_react35.useCallback)(
38106
38875
  (data) => {
38107
38876
  onWithdrawSuccess?.(data);
38108
38877
  if (data.execution) {
@@ -38112,14 +38881,14 @@ function WithdrawModal({
38112
38881
  [onWithdrawSuccess, onEvent]
38113
38882
  );
38114
38883
  const { colors: colors2, fonts, components } = useTheme();
38115
- const [containerEl, setContainerEl] = (0, import_react34.useState)(null);
38116
- const containerCallbackRef = (0, import_react34.useCallback)((el) => {
38884
+ const [containerEl, setContainerEl] = (0, import_react35.useState)(null);
38885
+ const containerCallbackRef = (0, import_react35.useCallback)((el) => {
38117
38886
  setContainerEl(el);
38118
38887
  }, []);
38119
- const [resolvedTheme, setResolvedTheme] = (0, import_react34.useState)(
38888
+ const [resolvedTheme, setResolvedTheme] = (0, import_react35.useState)(
38120
38889
  theme === "auto" ? "dark" : theme
38121
38890
  );
38122
- (0, import_react34.useEffect)(() => {
38891
+ (0, import_react35.useEffect)(() => {
38123
38892
  if (theme === "auto") {
38124
38893
  const mq = window.matchMedia("(prefers-color-scheme: dark)");
38125
38894
  setResolvedTheme(mq.matches ? "dark" : "light");
@@ -38168,10 +38937,10 @@ function WithdrawModal({
38168
38937
  const selectedChain = selectedToken && selectedChainKey ? selectedToken.chains.find(
38169
38938
  (c) => getChainKey5(c.chain_id, c.chain_type) === selectedChainKey
38170
38939
  ) ?? null : null;
38171
- const [view, setView] = (0, import_react34.useState)("form");
38172
- const [withdrawDepositWalletId, setWithdrawDepositWalletId] = (0, import_react34.useState)();
38173
- const [selectedExecution, setSelectedExecution] = (0, import_react34.useState)(null);
38174
- const [submittedTxInfo, setSubmittedTxInfo] = (0, import_react34.useState)(null);
38940
+ const [view, setView] = (0, import_react35.useState)("form");
38941
+ const [withdrawDepositWalletId, setWithdrawDepositWalletId] = (0, import_react35.useState)();
38942
+ const [selectedExecution, setSelectedExecution] = (0, import_react35.useState)(null);
38943
+ const [submittedTxInfo, setSubmittedTxInfo] = (0, import_react35.useState)(null);
38175
38944
  const { executions: realtimeExecutions } = useWithdrawPolling({
38176
38945
  userId: externalUserId,
38177
38946
  publishableKey,
@@ -38186,7 +38955,7 @@ function WithdrawModal({
38186
38955
  refetchInterval: view === "tracker" || view === "detail" ? 5e3 : 15e3
38187
38956
  });
38188
38957
  const allWithdrawals = allWithdrawalsData?.data ?? [];
38189
- const handleDepositWalletCreation = (0, import_react34.useCallback)(
38958
+ const handleDepositWalletCreation = (0, import_react35.useCallback)(
38190
38959
  async (params) => {
38191
38960
  const { data: wallets } = await createDepositAddress(
38192
38961
  {
@@ -38209,12 +38978,12 @@ function WithdrawModal({
38209
38978
  },
38210
38979
  [externalUserId, publishableKey, sourceChainType]
38211
38980
  );
38212
- const handleWithdrawSubmitted = (0, import_react34.useCallback)((txInfo) => {
38981
+ const handleWithdrawSubmitted = (0, import_react35.useCallback)((txInfo) => {
38213
38982
  setSubmittedTxInfo(txInfo);
38214
38983
  setView("confirming");
38215
38984
  }, []);
38216
- const resetViewTimeoutRef = (0, import_react34.useRef)(null);
38217
- const handleClose = (0, import_react34.useCallback)(() => {
38985
+ const resetViewTimeoutRef = (0, import_react35.useRef)(null);
38986
+ const handleClose = (0, import_react35.useCallback)(() => {
38218
38987
  onOpenChange(false);
38219
38988
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
38220
38989
  resetViewTimeoutRef.current = setTimeout(() => {
@@ -38225,7 +38994,7 @@ function WithdrawModal({
38225
38994
  resetViewTimeoutRef.current = null;
38226
38995
  }, 200);
38227
38996
  }, [onOpenChange]);
38228
- (0, import_react34.useLayoutEffect)(() => {
38997
+ (0, import_react35.useLayoutEffect)(() => {
38229
38998
  if (!open) return;
38230
38999
  if (resetViewTimeoutRef.current) {
38231
39000
  clearTimeout(resetViewTimeoutRef.current);
@@ -38236,19 +39005,19 @@ function WithdrawModal({
38236
39005
  setSubmittedTxInfo(null);
38237
39006
  setWithdrawDepositWalletId(void 0);
38238
39007
  }, [open]);
38239
- (0, import_react34.useEffect)(
39008
+ (0, import_react35.useEffect)(
38240
39009
  () => () => {
38241
39010
  if (resetViewTimeoutRef.current) clearTimeout(resetViewTimeoutRef.current);
38242
39011
  },
38243
39012
  []
38244
39013
  );
38245
- const handleTokenSymbolChange = (0, import_react34.useCallback)(
39014
+ const handleTokenSymbolChange = (0, import_react35.useCallback)(
38246
39015
  (symbol) => {
38247
39016
  setSelectedTokenSymbol(symbol);
38248
39017
  },
38249
39018
  [setSelectedTokenSymbol]
38250
39019
  );
38251
- const handleChainKeyChange = (0, import_react34.useCallback)(
39020
+ const handleChainKeyChange = (0, import_react35.useCallback)(
38252
39021
  (chainKey) => {
38253
39022
  setSelectedChainKey(chainKey);
38254
39023
  },
@@ -38443,19 +39212,19 @@ function UnifoldProvider2({
38443
39212
  queryClient,
38444
39213
  config
38445
39214
  }) {
38446
- const [isOpen, setIsOpen] = (0, import_react40.useState)(false);
38447
- const [depositConfig, setDepositConfig] = (0, import_react40.useState)(null);
38448
- const [isCheckoutOpen, setIsCheckoutOpen] = (0, import_react40.useState)(false);
38449
- const [checkoutConfig, setCheckoutConfig] = (0, import_react40.useState)(null);
38450
- const [isWithdrawOpen, setIsWithdrawOpen] = (0, import_react40.useState)(false);
38451
- const [withdrawConfig, setWithdrawConfig] = (0, import_react40.useState)(null);
38452
- const [resolvedTheme, setResolvedTheme] = import_react40.default.useState("dark");
38453
- (0, import_react40.useEffect)(() => {
39215
+ const [isOpen, setIsOpen] = (0, import_react41.useState)(false);
39216
+ const [depositConfig, setDepositConfig] = (0, import_react41.useState)(null);
39217
+ const [isCheckoutOpen, setIsCheckoutOpen] = (0, import_react41.useState)(false);
39218
+ const [checkoutConfig, setCheckoutConfig] = (0, import_react41.useState)(null);
39219
+ const [isWithdrawOpen, setIsWithdrawOpen] = (0, import_react41.useState)(false);
39220
+ const [withdrawConfig, setWithdrawConfig] = (0, import_react41.useState)(null);
39221
+ const [resolvedTheme, setResolvedTheme] = import_react41.default.useState("dark");
39222
+ (0, import_react41.useEffect)(() => {
38454
39223
  if (publishableKey) {
38455
39224
  setApiConfig({ publishableKey });
38456
39225
  }
38457
39226
  }, [publishableKey]);
38458
- import_react40.default.useEffect(() => {
39227
+ import_react41.default.useEffect(() => {
38459
39228
  const appearance = config?.appearance || "dark";
38460
39229
  if (appearance === "auto") {
38461
39230
  const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
@@ -38470,17 +39239,17 @@ function UnifoldProvider2({
38470
39239
  setResolvedTheme(appearance);
38471
39240
  }
38472
39241
  }, [config?.appearance]);
38473
- const depositPromiseRef = import_react40.default.useRef(null);
38474
- const depositConfigRef = import_react40.default.useRef(null);
39242
+ const depositPromiseRef = import_react41.default.useRef(null);
39243
+ const depositConfigRef = import_react41.default.useRef(null);
38475
39244
  depositConfigRef.current = depositConfig;
38476
- const closeTimeoutRef = import_react40.default.useRef(null);
38477
- const closeGuardRef = import_react40.default.useRef(false);
38478
- const withdrawPromiseRef = import_react40.default.useRef(null);
38479
- const withdrawConfigRef = import_react40.default.useRef(null);
39245
+ const closeTimeoutRef = import_react41.default.useRef(null);
39246
+ const closeGuardRef = import_react41.default.useRef(false);
39247
+ const withdrawPromiseRef = import_react41.default.useRef(null);
39248
+ const withdrawConfigRef = import_react41.default.useRef(null);
38480
39249
  withdrawConfigRef.current = withdrawConfig;
38481
- const withdrawCloseTimeoutRef = import_react40.default.useRef(null);
38482
- const withdrawCloseGuardRef = import_react40.default.useRef(false);
38483
- const beginDeposit = (0, import_react40.useCallback)((config2) => {
39250
+ const withdrawCloseTimeoutRef = import_react41.default.useRef(null);
39251
+ const withdrawCloseGuardRef = import_react41.default.useRef(false);
39252
+ const beginDeposit = (0, import_react41.useCallback)((config2) => {
38484
39253
  if (closeTimeoutRef.current) {
38485
39254
  clearTimeout(closeTimeoutRef.current);
38486
39255
  closeTimeoutRef.current = null;
@@ -38515,7 +39284,7 @@ function UnifoldProvider2({
38515
39284
  setIsOpen(true);
38516
39285
  return promise;
38517
39286
  }, []);
38518
- const closeDeposit = (0, import_react40.useCallback)(() => {
39287
+ const closeDeposit = (0, import_react41.useCallback)(() => {
38519
39288
  if (closeGuardRef.current) {
38520
39289
  return;
38521
39290
  }
@@ -38537,7 +39306,7 @@ function UnifoldProvider2({
38537
39306
  closeTimeoutRef.current = null;
38538
39307
  }, 200);
38539
39308
  }, []);
38540
- const handleDepositSuccess = (0, import_react40.useCallback)(
39309
+ const handleDepositSuccess = (0, import_react41.useCallback)(
38541
39310
  (data) => {
38542
39311
  if (depositConfig?.onSuccess) {
38543
39312
  depositConfig.onSuccess(data);
@@ -38549,7 +39318,7 @@ function UnifoldProvider2({
38549
39318
  },
38550
39319
  [depositConfig]
38551
39320
  );
38552
- const handleDepositError = (0, import_react40.useCallback)(
39321
+ const handleDepositError = (0, import_react41.useCallback)(
38553
39322
  (error) => {
38554
39323
  console.error("[UnifoldProvider] Deposit error:", error);
38555
39324
  if (depositConfig?.onError) {
@@ -38562,12 +39331,12 @@ function UnifoldProvider2({
38562
39331
  },
38563
39332
  [depositConfig]
38564
39333
  );
38565
- const checkoutPromiseRef = import_react40.default.useRef(null);
38566
- const checkoutConfigRef = import_react40.default.useRef(null);
39334
+ const checkoutPromiseRef = import_react41.default.useRef(null);
39335
+ const checkoutConfigRef = import_react41.default.useRef(null);
38567
39336
  checkoutConfigRef.current = checkoutConfig;
38568
- const checkoutCloseTimeoutRef = import_react40.default.useRef(null);
38569
- const checkoutCloseGuardRef = import_react40.default.useRef(false);
38570
- const beginCheckout = (0, import_react40.useCallback)((config2) => {
39337
+ const checkoutCloseTimeoutRef = import_react41.default.useRef(null);
39338
+ const checkoutCloseGuardRef = import_react41.default.useRef(false);
39339
+ const beginCheckout = (0, import_react41.useCallback)((config2) => {
38571
39340
  if (checkoutCloseTimeoutRef.current) {
38572
39341
  clearTimeout(checkoutCloseTimeoutRef.current);
38573
39342
  checkoutCloseTimeoutRef.current = null;
@@ -38592,7 +39361,7 @@ function UnifoldProvider2({
38592
39361
  setIsCheckoutOpen(true);
38593
39362
  return promise;
38594
39363
  }, []);
38595
- const closeCheckout = (0, import_react40.useCallback)(() => {
39364
+ const closeCheckout = (0, import_react41.useCallback)(() => {
38596
39365
  if (checkoutCloseGuardRef.current) {
38597
39366
  return;
38598
39367
  }
@@ -38614,7 +39383,7 @@ function UnifoldProvider2({
38614
39383
  checkoutCloseTimeoutRef.current = null;
38615
39384
  }, 200);
38616
39385
  }, []);
38617
- const handleCheckoutSuccess = (0, import_react40.useCallback)(
39386
+ const handleCheckoutSuccess = (0, import_react41.useCallback)(
38618
39387
  (data) => {
38619
39388
  if (checkoutConfig?.onSuccess) {
38620
39389
  checkoutConfig.onSuccess(data);
@@ -38626,7 +39395,7 @@ function UnifoldProvider2({
38626
39395
  },
38627
39396
  [checkoutConfig]
38628
39397
  );
38629
- const handleCheckoutError = (0, import_react40.useCallback)(
39398
+ const handleCheckoutError = (0, import_react41.useCallback)(
38630
39399
  (error) => {
38631
39400
  console.error("[UnifoldProvider] Checkout error:", error);
38632
39401
  if (checkoutConfig?.onError) {
@@ -38639,7 +39408,7 @@ function UnifoldProvider2({
38639
39408
  },
38640
39409
  [checkoutConfig]
38641
39410
  );
38642
- const beginWithdraw = (0, import_react40.useCallback)((config2) => {
39411
+ const beginWithdraw = (0, import_react41.useCallback)((config2) => {
38643
39412
  if (withdrawCloseTimeoutRef.current) {
38644
39413
  clearTimeout(withdrawCloseTimeoutRef.current);
38645
39414
  withdrawCloseTimeoutRef.current = null;
@@ -38664,7 +39433,7 @@ function UnifoldProvider2({
38664
39433
  setIsWithdrawOpen(true);
38665
39434
  return promise;
38666
39435
  }, []);
38667
- const closeWithdraw = (0, import_react40.useCallback)(() => {
39436
+ const closeWithdraw = (0, import_react41.useCallback)(() => {
38668
39437
  if (withdrawCloseGuardRef.current) {
38669
39438
  return;
38670
39439
  }
@@ -38686,7 +39455,7 @@ function UnifoldProvider2({
38686
39455
  withdrawCloseTimeoutRef.current = null;
38687
39456
  }, 200);
38688
39457
  }, []);
38689
- const handleWithdrawSuccess = (0, import_react40.useCallback)((data) => {
39458
+ const handleWithdrawSuccess = (0, import_react41.useCallback)((data) => {
38690
39459
  if (withdrawConfigRef.current?.onSuccess) {
38691
39460
  withdrawConfigRef.current.onSuccess(data);
38692
39461
  }
@@ -38695,7 +39464,7 @@ function UnifoldProvider2({
38695
39464
  withdrawPromiseRef.current = null;
38696
39465
  }
38697
39466
  }, []);
38698
- const handleWithdrawError = (0, import_react40.useCallback)((error) => {
39467
+ const handleWithdrawError = (0, import_react41.useCallback)((error) => {
38699
39468
  console.error("[UnifoldProvider] Withdraw error:", error);
38700
39469
  if (withdrawConfigRef.current?.onError) {
38701
39470
  withdrawConfigRef.current.onError(error);
@@ -38705,7 +39474,7 @@ function UnifoldProvider2({
38705
39474
  withdrawPromiseRef.current = null;
38706
39475
  }
38707
39476
  }, []);
38708
- const contextValue = (0, import_react40.useMemo)(
39477
+ const contextValue = (0, import_react41.useMemo)(
38709
39478
  () => ({
38710
39479
  beginDeposit,
38711
39480
  closeDeposit,
@@ -38800,7 +39569,7 @@ function UnifoldProvider2({
38800
39569
  defaultSourceChainId: depositConfig.defaultSourceChainId,
38801
39570
  defaultSourceTokenAddress: depositConfig.defaultSourceTokenAddress,
38802
39571
  defaultSourceSymbol: depositConfig.defaultSourceSymbol,
38803
- externalUserEmail: depositConfig.externalUserEmail,
39572
+ userEmail: depositConfig.user?.email,
38804
39573
  depositConfirmationMode: depositConfig.depositConfirmationMode ?? "auto_ui",
38805
39574
  hideDepositTracker: config?.hideDepositTracker,
38806
39575
  showBalanceHeader: config?.showBalanceHeader,
@@ -38813,7 +39582,6 @@ function UnifoldProvider2({
38813
39582
  enableConnectExchange: config?.enableConnectExchange,
38814
39583
  enableCashApp: config?.enableCashApp,
38815
39584
  enableStripeLink: config?.enableStripeLink,
38816
- email: depositConfig?.email,
38817
39585
  enableApplePay: config?.enableApplePay,
38818
39586
  applePayTitle: config?.applePayTitle,
38819
39587
  applePaySubTitle: config?.applePaySubTitle,
@@ -38836,10 +39604,10 @@ function UnifoldProvider2({
38836
39604
  }
38837
39605
  ) }) });
38838
39606
  }
38839
- var ConnectContext = import_react40.default.createContext(null);
39607
+ var ConnectContext = import_react41.default.createContext(null);
38840
39608
  function useUnifold2() {
38841
39609
  const baseContext = useUnifold();
38842
- const connectContext = import_react40.default.useContext(ConnectContext);
39610
+ const connectContext = import_react41.default.useContext(ConnectContext);
38843
39611
  if (typeof window === "undefined") {
38844
39612
  return {
38845
39613
  publishableKey: "",