@unifold/connect-react 0.1.68-beta.1 → 0.1.68
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +14 -9
- package/dist/index.d.ts +14 -9
- package/dist/index.js +2454 -1584
- package/dist/index.mjs +2163 -1293
- package/dist/styles-base.css +1 -1
- package/dist/styles.css +1 -1
- package/package.json +5 -5
package/dist/index.mjs
CHANGED
|
@@ -1144,7 +1144,7 @@ ${new this._window.XMLSerializer().serializeToString(e3)}`;
|
|
|
1144
1144
|
});
|
|
1145
1145
|
|
|
1146
1146
|
// src/provider.tsx
|
|
1147
|
-
import React38, { useState as useState39, useCallback as useCallback13, useMemo as
|
|
1147
|
+
import React38, { useState as useState39, useCallback as useCallback13, useMemo as useMemo18, useEffect as useEffect40 } from "react";
|
|
1148
1148
|
|
|
1149
1149
|
// ../react-provider/dist/index.mjs
|
|
1150
1150
|
import { createContext, useContext, useState, useEffect, useMemo, useRef } from "react";
|
|
@@ -1218,7 +1218,7 @@ import {
|
|
|
1218
1218
|
useLayoutEffect as useLayoutEffect22,
|
|
1219
1219
|
useCallback as useCallback82,
|
|
1220
1220
|
useRef as useRef122,
|
|
1221
|
-
useMemo as
|
|
1221
|
+
useMemo as useMemo13
|
|
1222
1222
|
} from "react";
|
|
1223
1223
|
|
|
1224
1224
|
// ../../node_modules/.pnpm/lucide-react@0.454.0_react@19.2.3/node_modules/lucide-react/dist/esm/createLucideIcon.js
|
|
@@ -7534,6 +7534,59 @@ async function exchangeOnrampVerificationToken(id, clientSecret, publishableKey)
|
|
|
7534
7534
|
"Failed to exchange verification token"
|
|
7535
7535
|
);
|
|
7536
7536
|
}
|
|
7537
|
+
function isApplePayLimitReached(response) {
|
|
7538
|
+
return response.limits.some((l) => l.remaining === "0");
|
|
7539
|
+
}
|
|
7540
|
+
function getApplePayLimitUpgradeStatus(response) {
|
|
7541
|
+
const opt = response.limit_upgrade_options?.[0];
|
|
7542
|
+
if (!opt || typeof opt.status !== "string") return null;
|
|
7543
|
+
return opt.status;
|
|
7544
|
+
}
|
|
7545
|
+
async function getCoinbaseApplePayLimits(phone, publishableKey, signal) {
|
|
7546
|
+
const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
|
|
7547
|
+
validatePublishableKey(pk);
|
|
7548
|
+
const response = await fetch(
|
|
7549
|
+
`${API_BASE_URL}/v1/public/onramps/headless/coinbase/apple_pay/limits`,
|
|
7550
|
+
{
|
|
7551
|
+
method: "POST",
|
|
7552
|
+
headers: {
|
|
7553
|
+
accept: "application/json",
|
|
7554
|
+
"x-publishable-key": pk,
|
|
7555
|
+
"Content-Type": "application/json"
|
|
7556
|
+
},
|
|
7557
|
+
body: JSON.stringify({ phone }),
|
|
7558
|
+
signal
|
|
7559
|
+
}
|
|
7560
|
+
);
|
|
7561
|
+
const raw = await jsonOrThrow(response, "Failed to fetch Apple Pay limits");
|
|
7562
|
+
return {
|
|
7563
|
+
limits: raw.limits,
|
|
7564
|
+
limit_upgrade_options: raw.limit_upgrade_options,
|
|
7565
|
+
limit_reached: isApplePayLimitReached(raw),
|
|
7566
|
+
upgrade_status: getApplePayLimitUpgradeStatus(raw)
|
|
7567
|
+
};
|
|
7568
|
+
}
|
|
7569
|
+
async function requestCoinbaseApplePayLimitUpgrade(request, publishableKey, signal) {
|
|
7570
|
+
const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
|
|
7571
|
+
validatePublishableKey(pk);
|
|
7572
|
+
const response = await fetch(
|
|
7573
|
+
`${API_BASE_URL}/v1/public/onramps/headless/coinbase/apple_pay/limits/upgrade`,
|
|
7574
|
+
{
|
|
7575
|
+
method: "POST",
|
|
7576
|
+
headers: {
|
|
7577
|
+
accept: "application/json",
|
|
7578
|
+
"x-publishable-key": pk,
|
|
7579
|
+
"Content-Type": "application/json"
|
|
7580
|
+
},
|
|
7581
|
+
body: JSON.stringify(request),
|
|
7582
|
+
signal
|
|
7583
|
+
}
|
|
7584
|
+
);
|
|
7585
|
+
return jsonOrThrow(
|
|
7586
|
+
response,
|
|
7587
|
+
"Failed to request Apple Pay limit upgrade"
|
|
7588
|
+
);
|
|
7589
|
+
}
|
|
7537
7590
|
async function createCoinbaseApplePaySession(request, onrampToken, publishableKey, signal) {
|
|
7538
7591
|
const pk = publishableKey || DEFAULT_PUBLISHABLE_KEY;
|
|
7539
7592
|
validatePublishableKey(pk);
|
|
@@ -7716,21 +7769,22 @@ import { Fragment as Fragment23, jsx as jsx102, jsxs as jsxs9 } from "react/jsx-
|
|
|
7716
7769
|
import { jsx as jsx112 } from "react/jsx-runtime";
|
|
7717
7770
|
import { jsx as jsx122, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
7718
7771
|
import * as React52 from "react";
|
|
7719
|
-
import { useCallback as useCallback10, useEffect as useEffect72, useMemo as
|
|
7772
|
+
import { useCallback as useCallback10, useEffect as useEffect72, useMemo as useMemo32, useRef as useRef32, useState as useState112 } from "react";
|
|
7720
7773
|
import { useQuery as useQuery3 } from "@tanstack/react-query";
|
|
7774
|
+
import { useMemo as useMemo22 } from "react";
|
|
7721
7775
|
import { useQuery as useQuery4 } from "@tanstack/react-query";
|
|
7776
|
+
import { useQuery as useQuery5 } from "@tanstack/react-query";
|
|
7722
7777
|
import { Fragment as Fragment42, jsx as jsx132, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
7723
7778
|
import { useState as useState122 } from "react";
|
|
7724
7779
|
import { jsx as jsx142, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
7725
7780
|
import { useState as useState152, useEffect as useEffect102, useCallback as useCallback22 } from "react";
|
|
7726
7781
|
var import_qr_code_styling = __toESM(require_qr_code_styling(), 1);
|
|
7727
|
-
import { useEffect as useEffect82, useRef as useRef42, useState as useState132, useMemo as
|
|
7782
|
+
import { useEffect as useEffect82, useRef as useRef42, useState as useState132, useMemo as useMemo42 } from "react";
|
|
7728
7783
|
import { jsx as jsx152, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
7729
7784
|
import { useState as useState142, useEffect as useEffect92 } from "react";
|
|
7730
|
-
import { useQuery as useQuery5 } from "@tanstack/react-query";
|
|
7731
|
-
import { Fragment as Fragment52, jsx as jsx162, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
7732
|
-
import { useEffect as useEffect112, useMemo as useMemo42, useState as useState162 } from "react";
|
|
7733
7785
|
import { useQuery as useQuery6 } from "@tanstack/react-query";
|
|
7786
|
+
import { Fragment as Fragment52, jsx as jsx162, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
7787
|
+
import { useEffect as useEffect112, useMemo as useMemo52, useState as useState162 } from "react";
|
|
7734
7788
|
import { useQuery as useQuery7 } from "@tanstack/react-query";
|
|
7735
7789
|
import { jsx as jsx172, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
7736
7790
|
import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
@@ -7987,21 +8041,21 @@ import { useState as useState292, useEffect as useEffect242, useCallback as useC
|
|
|
7987
8041
|
import { jsx as jsx43, jsxs as jsxs40 } from "react/jsx-runtime";
|
|
7988
8042
|
import { useState as useState282, useEffect as useEffect232, useRef as useRef72, useCallback as useCallback32 } from "react";
|
|
7989
8043
|
import { Fragment as Fragment62, jsx as jsx44, jsxs as jsxs41 } from "react/jsx-runtime";
|
|
7990
|
-
import { useState as useState30, useEffect as useEffect252, useCallback as useCallback52, useMemo as
|
|
7991
|
-
import { useQuery as useQuery8 } from "@tanstack/react-query";
|
|
8044
|
+
import { useState as useState30, useEffect as useEffect252, useCallback as useCallback52, useMemo as useMemo72, useRef as useRef92 } from "react";
|
|
8045
|
+
import { useQuery as useQuery8, keepPreviousData } from "@tanstack/react-query";
|
|
7992
8046
|
import { useQuery as useQuery9 } from "@tanstack/react-query";
|
|
7993
|
-
import { Fragment as Fragment72, jsx as jsx45, jsxs as jsxs422 } from "react/jsx-runtime";
|
|
7994
8047
|
import { useQuery as useQuery10 } from "@tanstack/react-query";
|
|
8048
|
+
import { Fragment as Fragment72, jsx as jsx45, jsxs as jsxs422 } from "react/jsx-runtime";
|
|
7995
8049
|
import { useQuery as useQuery11 } from "@tanstack/react-query";
|
|
7996
8050
|
import { useQuery as useQuery12 } from "@tanstack/react-query";
|
|
7997
8051
|
import { useQuery as useQuery13 } from "@tanstack/react-query";
|
|
7998
|
-
import { useState as useState36, useEffect as useEffect302, useMemo as
|
|
8052
|
+
import { useState as useState36, useEffect as useEffect302, useMemo as useMemo102 } from "react";
|
|
7999
8053
|
import { useEffect as useEffect272, useState as useState31 } from "react";
|
|
8000
8054
|
import * as React312 from "react";
|
|
8001
8055
|
import { jsx as jsx46 } from "react/jsx-runtime";
|
|
8002
8056
|
import { jsx as jsx47, jsxs as jsxs43 } from "react/jsx-runtime";
|
|
8003
8057
|
import { Fragment as Fragment82, jsx as jsx48, jsxs as jsxs44 } from "react/jsx-runtime";
|
|
8004
|
-
import { useState as useState322, useMemo as
|
|
8058
|
+
import { useState as useState322, useMemo as useMemo92, useEffect as useEffect282 } from "react";
|
|
8005
8059
|
|
|
8006
8060
|
// ../../node_modules/.pnpm/fuse.js@7.4.0/node_modules/fuse.js/dist/fuse.mjs
|
|
8007
8061
|
function isArray(value) {
|
|
@@ -12748,7 +12802,7 @@ import { jsx as jsx522 } from "react/jsx-runtime";
|
|
|
12748
12802
|
import { useQuery as useQuery14 } from "@tanstack/react-query";
|
|
12749
12803
|
import { jsx as jsx53, jsxs as jsxs48 } from "react/jsx-runtime";
|
|
12750
12804
|
import { Fragment as Fragment10, jsx as jsx54, jsxs as jsxs49 } from "react/jsx-runtime";
|
|
12751
|
-
import { useState as useState37, useEffect as useEffect312, useMemo as
|
|
12805
|
+
import { useState as useState37, useEffect as useEffect312, useMemo as useMemo112 } from "react";
|
|
12752
12806
|
import * as React332 from "react";
|
|
12753
12807
|
|
|
12754
12808
|
// ../../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
|
|
@@ -13997,7 +14051,7 @@ import { useEffect as useEffect322, useState as useState382 } from "react";
|
|
|
13997
14051
|
import { Fragment as Fragment13, jsx as jsx61, jsxs as jsxs55 } from "react/jsx-runtime";
|
|
13998
14052
|
import { jsx as jsx622, jsxs as jsxs56 } from "react/jsx-runtime";
|
|
13999
14053
|
import { Fragment as Fragment14, jsx as jsx63, jsxs as jsxs57 } from "react/jsx-runtime";
|
|
14000
|
-
import { useState as useState41, useEffect as useEffect35, useLayoutEffect as useLayoutEffect32, useCallback as useCallback92, useRef as useRef132, useMemo as
|
|
14054
|
+
import { useState as useState41, useEffect as useEffect35, useLayoutEffect as useLayoutEffect32, useCallback as useCallback92, useRef as useRef132, useMemo as useMemo142 } from "react";
|
|
14001
14055
|
import { useQuery as useQuery17 } from "@tanstack/react-query";
|
|
14002
14056
|
import { Fragment as Fragment15, jsx as jsx64, jsxs as jsxs58 } from "react/jsx-runtime";
|
|
14003
14057
|
import { useState as useState45, useEffect as useEffect39, useLayoutEffect as useLayoutEffect42, useCallback as useCallback112, useRef as useRef152 } from "react";
|
|
@@ -14007,16 +14061,16 @@ import { useQuery as useQuery20 } from "@tanstack/react-query";
|
|
|
14007
14061
|
import { useQuery as useQuery21 } from "@tanstack/react-query";
|
|
14008
14062
|
import { useState as useState42, useEffect as useEffect36, useRef as useRef142 } from "react";
|
|
14009
14063
|
import { jsx as jsx65, jsxs as jsxs59 } from "react/jsx-runtime";
|
|
14010
|
-
import { useState as useState43, useCallback as useCallback102, useMemo as
|
|
14064
|
+
import { useState as useState43, useCallback as useCallback102, useMemo as useMemo16, useEffect as useEffect37 } from "react";
|
|
14011
14065
|
import { useQuery as useQuery222 } from "@tanstack/react-query";
|
|
14012
|
-
import { useMemo as
|
|
14066
|
+
import { useMemo as useMemo15 } from "react";
|
|
14013
14067
|
import { useQuery as useQuery23 } from "@tanstack/react-query";
|
|
14014
14068
|
import { Fragment as Fragment16, jsx as jsx66, jsxs as jsxs60 } from "react/jsx-runtime";
|
|
14015
14069
|
import { jsx as jsx67, jsxs as jsxs61 } from "react/jsx-runtime";
|
|
14016
14070
|
import { useState as useState44, useEffect as useEffect38 } from "react";
|
|
14017
14071
|
import { Fragment as Fragment17, jsx as jsx68, jsxs as jsxs62 } from "react/jsx-runtime";
|
|
14018
14072
|
import { Fragment as Fragment18, jsx as jsx69, jsxs as jsxs63 } from "react/jsx-runtime";
|
|
14019
|
-
import { useState as useState46, useMemo as
|
|
14073
|
+
import { useState as useState46, useMemo as useMemo17 } from "react";
|
|
14020
14074
|
import { jsx as jsx70, jsxs as jsxs64 } from "react/jsx-runtime";
|
|
14021
14075
|
function cn(...inputs) {
|
|
14022
14076
|
return twMerge(clsx(inputs));
|
|
@@ -14447,6 +14501,7 @@ var DialogContent2 = React36.forwardRef(({ className, style, children, omitOverl
|
|
|
14447
14501
|
className: cn(
|
|
14448
14502
|
portalContainer ? "uf-absolute" : "uf-fixed",
|
|
14449
14503
|
"uf-bottom-0 uf-left-0 uf-right-0 uf-top-0 uf-z-50 uf-grid uf-w-full uf-max-w-full uf-h-full",
|
|
14504
|
+
"focus:uf-outline-none focus-visible:uf-outline-none",
|
|
14450
14505
|
!portalContainer && "sm:uf-left-[50%] sm:uf-top-[50%] sm:uf-bottom-auto sm:uf-right-auto sm:uf-translate-x-[-50%] sm:uf-translate-y-[-50%] sm:uf-h-auto",
|
|
14451
14506
|
"uf-border uf-bg-background",
|
|
14452
14507
|
omitOverlayEmbed ? "uf-gap-0 uf-p-0" : "uf-gap-4 uf-p-6 uf-shadow-lg uf-duration-200",
|
|
@@ -14462,6 +14517,14 @@ var DialogContent2 = React36.forwardRef(({ className, style, children, omitOverl
|
|
|
14462
14517
|
),
|
|
14463
14518
|
style: {
|
|
14464
14519
|
"--uf-container-radius": `${components.container.borderRadius}px`,
|
|
14520
|
+
// Radix traps focus and, when the focused control unmounts during an
|
|
14521
|
+
// in-modal screen transition, moves focus onto this container. Modern
|
|
14522
|
+
// browsers paint the default focus ring via `:focus-visible`, which
|
|
14523
|
+
// flashes a highlight around the whole modal until focus settles on
|
|
14524
|
+
// the next screen. Suppress it inline so it works regardless of the
|
|
14525
|
+
// Tailwind build (the container is a programmatic focus target, not an
|
|
14526
|
+
// interactive control, so it should never show a focus ring).
|
|
14527
|
+
outline: "none",
|
|
14465
14528
|
...portalContainer ? { display: "flex", flexDirection: "column" } : {},
|
|
14466
14529
|
...style
|
|
14467
14530
|
},
|
|
@@ -15406,7 +15469,7 @@ var en_default2 = {
|
|
|
15406
15469
|
payWithStripeLink: {
|
|
15407
15470
|
success: {
|
|
15408
15471
|
processingTitle: "Payment confirmed",
|
|
15409
|
-
processingSubtitle: "We\u2019ve received your payment and are
|
|
15472
|
+
processingSubtitle: "We\u2019ve received your payment and are sending your purchase to your wallet. This usually takes just a few minutes.",
|
|
15410
15473
|
completeTitle: "Your purchase is on the way",
|
|
15411
15474
|
completeSubtitle: "Your purchase is complete and is being sent to your wallet.",
|
|
15412
15475
|
failedTitle: "Purchase didn\u2019t go through",
|
|
@@ -17390,20 +17453,6 @@ function BuyWithCard({
|
|
|
17390
17453
|
}
|
|
17391
17454
|
);
|
|
17392
17455
|
}
|
|
17393
|
-
function useProjectConfig({
|
|
17394
|
-
publishableKey,
|
|
17395
|
-
enabled = true
|
|
17396
|
-
}) {
|
|
17397
|
-
const { data: projectConfig, isLoading } = useQuery3({
|
|
17398
|
-
queryKey: ["unifold", "projectConfig", publishableKey],
|
|
17399
|
-
queryFn: () => getProjectConfig(publishableKey),
|
|
17400
|
-
enabled,
|
|
17401
|
-
staleTime: 1e3 * 60 * 30,
|
|
17402
|
-
refetchOnMount: true,
|
|
17403
|
-
refetchOnWindowFocus: true
|
|
17404
|
-
});
|
|
17405
|
-
return { projectConfig, isLoading };
|
|
17406
|
-
}
|
|
17407
17456
|
var STORAGE_KEY_PREFIX = "unifold:apple-pay:session";
|
|
17408
17457
|
var PHONE_FRESH_MS = 55 * 24 * 60 * 60 * 1e3;
|
|
17409
17458
|
function isBrowser() {
|
|
@@ -17440,7 +17489,7 @@ function useCoinbaseLegalAgreements({
|
|
|
17440
17489
|
publishableKey,
|
|
17441
17490
|
enabled = true
|
|
17442
17491
|
}) {
|
|
17443
|
-
return
|
|
17492
|
+
return useQuery3({
|
|
17444
17493
|
queryKey: ["unifold", "coinbaseLegalAgreements", publishableKey],
|
|
17445
17494
|
queryFn: () => getCoinbaseLegalAgreements(publishableKey),
|
|
17446
17495
|
enabled: enabled && !!publishableKey,
|
|
@@ -17451,47 +17500,200 @@ function useCoinbaseLegalAgreements({
|
|
|
17451
17500
|
retry: 1
|
|
17452
17501
|
});
|
|
17453
17502
|
}
|
|
17454
|
-
var
|
|
17455
|
-
|
|
17456
|
-
|
|
17457
|
-
|
|
17503
|
+
var US_E164_REGEX = /^\+1\d{10}$/;
|
|
17504
|
+
function useApplePayLimits({
|
|
17505
|
+
phone,
|
|
17506
|
+
publishableKey,
|
|
17507
|
+
enabled = true
|
|
17508
|
+
}) {
|
|
17509
|
+
const phoneValid = US_E164_REGEX.test(phone);
|
|
17510
|
+
return useQuery4({
|
|
17511
|
+
queryKey: ["unifold", "applePayLimits", phone, publishableKey],
|
|
17512
|
+
queryFn: ({ signal }) => getCoinbaseApplePayLimits(phone, publishableKey, signal),
|
|
17513
|
+
enabled: enabled && phoneValid && !!publishableKey,
|
|
17514
|
+
// Coinbase's caps don't change second-to-second; 30s is plenty fresh
|
|
17515
|
+
// for the "user opened the modal, edited their phone, opened it
|
|
17516
|
+
// again" usage pattern, while keeping us off their API on rapid
|
|
17517
|
+
// tap-throughs.
|
|
17518
|
+
staleTime: 3e4,
|
|
17519
|
+
gcTime: 5 * 6e4,
|
|
17520
|
+
refetchOnWindowFocus: false,
|
|
17521
|
+
retry: false
|
|
17522
|
+
});
|
|
17523
|
+
}
|
|
17458
17524
|
var PHONE_REGEX = /^\+1\d{10}$/;
|
|
17459
17525
|
var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
17460
|
-
function
|
|
17461
|
-
|
|
17462
|
-
|
|
17463
|
-
|
|
17526
|
+
function getViewForLimitStatus(limits) {
|
|
17527
|
+
if (!limits.limit_reached) return void 0;
|
|
17528
|
+
switch (limits.upgrade_status) {
|
|
17529
|
+
case "unrequested":
|
|
17530
|
+
return "limit_upgrade_intro";
|
|
17531
|
+
case "resubmit":
|
|
17532
|
+
return "limit_upgrade_form";
|
|
17533
|
+
case "pending":
|
|
17534
|
+
return "limit_upgrade_submitting";
|
|
17535
|
+
case "active":
|
|
17536
|
+
return void 0;
|
|
17537
|
+
default:
|
|
17538
|
+
return "guest_limit_reached";
|
|
17464
17539
|
}
|
|
17465
|
-
if (digits.length === 10) return `+1${digits}`;
|
|
17466
|
-
if (digits.length === 11 && digits.startsWith("1")) return `+${digits}`;
|
|
17467
|
-
return digits.length > 0 ? `+${digits}` : "";
|
|
17468
17540
|
}
|
|
17469
|
-
function
|
|
17470
|
-
|
|
17471
|
-
|
|
17472
|
-
|
|
17473
|
-
|
|
17541
|
+
function useApplePayInitialScreen({
|
|
17542
|
+
userId,
|
|
17543
|
+
publishableKey,
|
|
17544
|
+
normalizedPhone,
|
|
17545
|
+
userEmail,
|
|
17546
|
+
sessionPhoneVerified,
|
|
17547
|
+
isWaiting
|
|
17548
|
+
}) {
|
|
17549
|
+
const initialStoredSession = useMemo22(() => getStoredApplePaySession(userId), [userId]);
|
|
17550
|
+
const phoneVerified = PHONE_REGEX.test(normalizedPhone) && (sessionPhoneVerified || initialStoredSession?.phone === normalizedPhone && !!initialStoredSession?.phoneVerifiedAt);
|
|
17551
|
+
const {
|
|
17552
|
+
data: applePayLimits,
|
|
17553
|
+
isLoading: applePayLimitsLoading,
|
|
17554
|
+
refetch: refetchApplePayLimits
|
|
17555
|
+
} = useApplePayLimits({
|
|
17556
|
+
phone: normalizedPhone,
|
|
17557
|
+
publishableKey,
|
|
17558
|
+
enabled: phoneVerified
|
|
17559
|
+
});
|
|
17560
|
+
const action = useMemo22(() => {
|
|
17561
|
+
if (isWaiting || applePayLimitsLoading) return { kind: "pending" };
|
|
17562
|
+
const stored = initialStoredSession;
|
|
17563
|
+
const hasUserEmail = !!userEmail && EMAIL_REGEX.test(userEmail);
|
|
17564
|
+
if (!stored) {
|
|
17565
|
+
return { kind: "navigate", view: hasUserEmail ? "phone_input" : "email_input" };
|
|
17566
|
+
}
|
|
17567
|
+
if (hasUserEmail && stored.email.toLowerCase() !== userEmail.toLowerCase()) {
|
|
17568
|
+
return { kind: "navigate", view: "phone_input" };
|
|
17569
|
+
}
|
|
17570
|
+
if (applePayLimits) {
|
|
17571
|
+
const limitView = getViewForLimitStatus(applePayLimits);
|
|
17572
|
+
if (limitView) {
|
|
17573
|
+
return { kind: "limit_upgrade", view: limitView, status: applePayLimits.upgrade_status };
|
|
17574
|
+
}
|
|
17575
|
+
}
|
|
17576
|
+
if (isOnrampTokenFresh(stored) && stored.onrampToken && stored.onrampTokenExpiresAtMs) {
|
|
17577
|
+
return {
|
|
17578
|
+
kind: "resume_with_token",
|
|
17579
|
+
token: {
|
|
17580
|
+
token: stored.onrampToken,
|
|
17581
|
+
token_type: "Bearer",
|
|
17582
|
+
expires_in: Math.max(0, Math.floor((stored.onrampTokenExpiresAtMs - Date.now()) / 1e3))
|
|
17583
|
+
}
|
|
17584
|
+
};
|
|
17585
|
+
}
|
|
17586
|
+
return { kind: "resume_send_sms" };
|
|
17587
|
+
}, [isWaiting, applePayLimitsLoading, initialStoredSession, userEmail, applePayLimits]);
|
|
17588
|
+
return {
|
|
17589
|
+
action,
|
|
17590
|
+
applePayLimits,
|
|
17591
|
+
applePayLimitsLoading,
|
|
17592
|
+
refetchApplePayLimits,
|
|
17593
|
+
phoneVerified
|
|
17594
|
+
};
|
|
17474
17595
|
}
|
|
17475
|
-
function
|
|
17476
|
-
|
|
17477
|
-
|
|
17596
|
+
function useDefaultOnrampToken({
|
|
17597
|
+
publishableKey,
|
|
17598
|
+
tokenAddress,
|
|
17599
|
+
chainId,
|
|
17600
|
+
chainType,
|
|
17601
|
+
countryCode,
|
|
17602
|
+
subdivisionCode,
|
|
17603
|
+
enabled = true
|
|
17604
|
+
}) {
|
|
17605
|
+
const {
|
|
17606
|
+
data: defaultToken,
|
|
17607
|
+
isLoading,
|
|
17608
|
+
isError,
|
|
17609
|
+
error
|
|
17610
|
+
} = useQuery5({
|
|
17611
|
+
queryKey: [
|
|
17612
|
+
"unifold",
|
|
17613
|
+
"defaultOnrampToken",
|
|
17614
|
+
publishableKey,
|
|
17615
|
+
tokenAddress,
|
|
17616
|
+
chainId,
|
|
17617
|
+
chainType,
|
|
17618
|
+
countryCode,
|
|
17619
|
+
subdivisionCode
|
|
17620
|
+
],
|
|
17621
|
+
queryFn: () => getDefaultOnrampToken(
|
|
17622
|
+
{
|
|
17623
|
+
token_address: tokenAddress,
|
|
17624
|
+
chain_id: chainId,
|
|
17625
|
+
chain_type: chainType,
|
|
17626
|
+
country_code: countryCode,
|
|
17627
|
+
subdivision_code: subdivisionCode
|
|
17628
|
+
},
|
|
17629
|
+
publishableKey
|
|
17630
|
+
),
|
|
17631
|
+
enabled: enabled && !!tokenAddress && !!chainId && !!chainType,
|
|
17632
|
+
staleTime: 1e3 * 60 * 60,
|
|
17633
|
+
refetchOnMount: false,
|
|
17634
|
+
refetchOnWindowFocus: false
|
|
17635
|
+
});
|
|
17636
|
+
return { defaultToken, isLoading, isError, error: error ?? null };
|
|
17637
|
+
}
|
|
17638
|
+
var COINBASE_PAY_ORIGIN = "https://pay.coinbase.com";
|
|
17639
|
+
var COINBASE_ALLOWED_POSTMESSAGE_ORIGINS = /* @__PURE__ */ new Set([
|
|
17640
|
+
COINBASE_PAY_ORIGIN,
|
|
17641
|
+
"https://www.coinbase.com"
|
|
17642
|
+
]);
|
|
17643
|
+
var UNIFOLD_SUPPORT_URL = "https://unifold.io/support";
|
|
17644
|
+
var DEFAULT_MIN_USD = 5;
|
|
17645
|
+
var DEFAULT_MAX_USD = 500;
|
|
17646
|
+
var DEFAULT_SUGGESTED = [25, 50, 100];
|
|
17647
|
+
var PHONE_REGEX2 = /^\+1\d{10}$/;
|
|
17648
|
+
var EMAIL_REGEX2 = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
17649
|
+
function parseCoinbasePostMessage(raw) {
|
|
17650
|
+
const parseString = (s) => {
|
|
17651
|
+
try {
|
|
17652
|
+
return JSON.parse(s);
|
|
17653
|
+
} catch {
|
|
17654
|
+
return null;
|
|
17655
|
+
}
|
|
17656
|
+
};
|
|
17657
|
+
const asObject = (value) => value && typeof value === "object" ? value : null;
|
|
17658
|
+
let candidate = raw;
|
|
17659
|
+
if (typeof candidate === "string") {
|
|
17660
|
+
candidate = parseString(candidate);
|
|
17661
|
+
}
|
|
17662
|
+
const obj = asObject(candidate);
|
|
17663
|
+
if (!obj) return null;
|
|
17664
|
+
const nestedData = obj.data;
|
|
17665
|
+
let eventName = typeof obj.eventName === "string" && obj.eventName || typeof obj.event_name === "string" && obj.event_name || typeof obj.type === "string" && obj.type || null;
|
|
17666
|
+
let dataObj = asObject(nestedData);
|
|
17667
|
+
if (!eventName && typeof nestedData === "string") {
|
|
17668
|
+
const nestedParsed = parseString(nestedData);
|
|
17669
|
+
const nestedObj = asObject(nestedParsed);
|
|
17670
|
+
if (nestedObj) {
|
|
17671
|
+
eventName = typeof nestedObj.eventName === "string" && nestedObj.eventName || typeof nestedObj.event_name === "string" && nestedObj.event_name || typeof nestedObj.type === "string" && nestedObj.type || null;
|
|
17672
|
+
dataObj = asObject(nestedObj.data);
|
|
17673
|
+
}
|
|
17674
|
+
}
|
|
17675
|
+
if (!eventName || !/^onramp_api\./i.test(eventName)) return null;
|
|
17676
|
+
return {
|
|
17677
|
+
eventName,
|
|
17678
|
+
data: dataObj ? {
|
|
17679
|
+
errorCode: typeof dataObj.errorCode === "string" ? dataObj.errorCode : typeof dataObj.error_code === "string" ? dataObj.error_code : void 0,
|
|
17680
|
+
errorMessage: typeof dataObj.errorMessage === "string" ? dataObj.errorMessage : typeof dataObj.error_message === "string" ? dataObj.error_message : void 0
|
|
17681
|
+
} : void 0
|
|
17682
|
+
};
|
|
17478
17683
|
}
|
|
17479
17684
|
var BuyWithApplePay = React52.forwardRef(
|
|
17480
17685
|
function BuyWithApplePay2({
|
|
17481
17686
|
userId,
|
|
17482
17687
|
publishableKey,
|
|
17483
|
-
recipientAddress,
|
|
17484
17688
|
destinationChainType,
|
|
17485
17689
|
destinationChainId,
|
|
17486
17690
|
destinationTokenAddress,
|
|
17487
|
-
|
|
17488
|
-
externalUserEmail,
|
|
17489
|
-
enableApplePay,
|
|
17691
|
+
userEmail,
|
|
17490
17692
|
amountUsd,
|
|
17491
17693
|
minAmountUsd = DEFAULT_MIN_USD,
|
|
17492
17694
|
maxAmountUsd = DEFAULT_MAX_USD,
|
|
17493
17695
|
suggestedAmountsUsd = DEFAULT_SUGGESTED,
|
|
17494
|
-
wallets:
|
|
17696
|
+
wallets: depositWallets,
|
|
17495
17697
|
onDepositSuccess,
|
|
17496
17698
|
onDepositError,
|
|
17497
17699
|
onEvent,
|
|
@@ -17500,48 +17702,61 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17500
17702
|
onExit
|
|
17501
17703
|
}, ref) {
|
|
17502
17704
|
const { colors: colors2, fonts, components } = useTheme();
|
|
17503
|
-
const { projectConfig, isLoading: configLoading } = useProjectConfig({ publishableKey });
|
|
17504
|
-
const applePayEnabled = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
|
|
17505
17705
|
const [view, setView] = useState112("loading_config");
|
|
17506
17706
|
const [errorMessage, setErrorMessage] = useState112("");
|
|
17507
|
-
const [email, setEmail] = useState112(
|
|
17508
|
-
|
|
17509
|
-
|
|
17707
|
+
const [email, setEmail] = useState112(() => {
|
|
17708
|
+
if (userEmail && EMAIL_REGEX2.test(userEmail)) return userEmail;
|
|
17709
|
+
return getStoredApplePaySession(userId)?.email ?? "";
|
|
17710
|
+
});
|
|
17711
|
+
const [phoneInput, setPhoneInput] = useState112(() => {
|
|
17712
|
+
const stored = getStoredApplePaySession(userId);
|
|
17713
|
+
if (!stored) return "";
|
|
17714
|
+
if (userEmail && EMAIL_REGEX2.test(userEmail) && stored.email.toLowerCase() !== userEmail.toLowerCase()) {
|
|
17715
|
+
return "";
|
|
17716
|
+
}
|
|
17717
|
+
return stored.phone;
|
|
17718
|
+
});
|
|
17510
17719
|
const { data: legalAgreementsData, isLoading: legalAgreementsLoading } = useCoinbaseLegalAgreements({
|
|
17511
|
-
publishableKey
|
|
17512
|
-
enabled: applePayEnabled
|
|
17720
|
+
publishableKey
|
|
17513
17721
|
});
|
|
17514
17722
|
const legalAgreements = legalAgreementsData ?? null;
|
|
17515
17723
|
const [verificationSession, setVerificationSession] = useState112(null);
|
|
17516
17724
|
const [clientSecret, setClientSecret] = useState112(null);
|
|
17517
|
-
const [emailCode, setEmailCode] = useState112("");
|
|
17518
17725
|
const [phoneCode, setPhoneCode] = useState112("");
|
|
17519
17726
|
const [otpError, setOtpError] = useState112(null);
|
|
17520
17727
|
const [otpSubmitting, setOtpSubmitting] = useState112(false);
|
|
17521
17728
|
const [resendCooldown, setResendCooldown] = useState112(0);
|
|
17729
|
+
const [dobInput, setDobInput] = useState112("");
|
|
17730
|
+
const [ssnLast4, setSsnLast4] = useState112("");
|
|
17731
|
+
const [limitUpgradeError, setLimitUpgradeError] = useState112(null);
|
|
17732
|
+
const [upgradeSubmitting, setUpgradeSubmitting] = useState112(false);
|
|
17733
|
+
const upgradeFlowAbortRef = useRef32(null);
|
|
17522
17734
|
const [amount, setAmount] = useState112(amountUsd ?? "");
|
|
17523
17735
|
const [paymentSession, setPaymentSession] = useState112(
|
|
17524
17736
|
null
|
|
17525
17737
|
);
|
|
17526
17738
|
const [paymentSessionAmount, setPaymentSessionAmount] = useState112(null);
|
|
17527
|
-
const [preparingSession, setPreparingSession] = useState112(false);
|
|
17528
17739
|
const popupRef = useRef32(null);
|
|
17529
17740
|
const sessionAbortRef = useRef32(null);
|
|
17530
17741
|
const [onrampToken, setOnrampToken] = useState112(null);
|
|
17531
|
-
const {
|
|
17532
|
-
|
|
17742
|
+
const { userIpInfo, isLoading: userIpInfoLoading } = useUserIp2();
|
|
17743
|
+
const {
|
|
17744
|
+
defaultToken,
|
|
17745
|
+
isLoading: defaultTokenLoading,
|
|
17746
|
+
isError: defaultTokenError
|
|
17747
|
+
} = useDefaultOnrampToken({
|
|
17533
17748
|
publishableKey,
|
|
17534
|
-
|
|
17535
|
-
|
|
17536
|
-
|
|
17537
|
-
|
|
17538
|
-
|
|
17749
|
+
tokenAddress: destinationTokenAddress,
|
|
17750
|
+
chainId: destinationChainId,
|
|
17751
|
+
chainType: destinationChainType,
|
|
17752
|
+
countryCode: userIpInfo?.alpha2,
|
|
17753
|
+
subdivisionCode: userIpInfo?.subdivisionCode ?? void 0
|
|
17539
17754
|
});
|
|
17540
|
-
const
|
|
17541
|
-
|
|
17542
|
-
if (!
|
|
17543
|
-
return getWalletByChainType(
|
|
17544
|
-
}, [
|
|
17755
|
+
const depositWallet = useMemo32(() => {
|
|
17756
|
+
const routingChainType = defaultToken?.destination_token_metadata?.chain_type;
|
|
17757
|
+
if (!routingChainType) return void 0;
|
|
17758
|
+
return getWalletByChainType(depositWallets ?? [], routingChainType);
|
|
17759
|
+
}, [depositWallets, defaultToken]);
|
|
17545
17760
|
const depositWalletId = depositWallet?.id;
|
|
17546
17761
|
const { executions } = useDepositPolling({
|
|
17547
17762
|
userId,
|
|
@@ -17565,49 +17780,10 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17565
17780
|
onDepositError(error);
|
|
17566
17781
|
} : void 0
|
|
17567
17782
|
});
|
|
17568
|
-
const [emailLocked, setEmailLocked] = useState112(
|
|
17569
|
-
|
|
17570
|
-
|
|
17571
|
-
|
|
17572
|
-
setView("disabled");
|
|
17573
|
-
return;
|
|
17574
|
-
}
|
|
17575
|
-
setTosAccepted(true);
|
|
17576
|
-
const applyStoredOnrampToken = (stored2) => {
|
|
17577
|
-
if (!isOnrampTokenFresh(stored2) || !stored2.onrampToken || !stored2.onrampTokenExpiresAtMs) {
|
|
17578
|
-
return false;
|
|
17579
|
-
}
|
|
17580
|
-
setOnrampToken({
|
|
17581
|
-
token: stored2.onrampToken,
|
|
17582
|
-
token_type: "Bearer",
|
|
17583
|
-
expires_in: Math.max(0, Math.floor((stored2.onrampTokenExpiresAtMs - Date.now()) / 1e3))
|
|
17584
|
-
});
|
|
17585
|
-
setView("amount");
|
|
17586
|
-
return true;
|
|
17587
|
-
};
|
|
17588
|
-
if (externalUserEmail && EMAIL_REGEX.test(externalUserEmail)) {
|
|
17589
|
-
setEmail(externalUserEmail);
|
|
17590
|
-
setEmailLocked(true);
|
|
17591
|
-
const stored2 = getStoredApplePaySession(userId);
|
|
17592
|
-
if (stored2?.email?.toLowerCase() === externalUserEmail.toLowerCase()) {
|
|
17593
|
-
setPhoneInput(stored2.phone);
|
|
17594
|
-
if (applyStoredOnrampToken(stored2)) return;
|
|
17595
|
-
}
|
|
17596
|
-
setView("phone_input");
|
|
17597
|
-
return;
|
|
17598
|
-
}
|
|
17599
|
-
const stored = getStoredApplePaySession(userId);
|
|
17600
|
-
if (stored) {
|
|
17601
|
-
setEmail(stored.email);
|
|
17602
|
-
setPhoneInput(stored.phone);
|
|
17603
|
-
setEmailLocked(true);
|
|
17604
|
-
if (applyStoredOnrampToken(stored)) return;
|
|
17605
|
-
setView("phone_input");
|
|
17606
|
-
return;
|
|
17607
|
-
}
|
|
17608
|
-
setEmailLocked(false);
|
|
17609
|
-
setView("email_input");
|
|
17610
|
-
}, [configLoading, applePayEnabled, externalUserEmail, userId]);
|
|
17783
|
+
const [emailLocked, setEmailLocked] = useState112(() => {
|
|
17784
|
+
if (userEmail && EMAIL_REGEX2.test(userEmail)) return true;
|
|
17785
|
+
return !!getStoredApplePaySession(userId);
|
|
17786
|
+
});
|
|
17611
17787
|
useEffect72(() => {
|
|
17612
17788
|
if (resendCooldown <= 0) return;
|
|
17613
17789
|
const t13 = setInterval(() => setResendCooldown((c) => Math.max(0, c - 1)), 1e3);
|
|
@@ -17616,19 +17792,10 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17616
17792
|
useEffect72(() => {
|
|
17617
17793
|
if (view !== "checking_deposit") return;
|
|
17618
17794
|
const onMessage = (event) => {
|
|
17619
|
-
if (event.origin
|
|
17620
|
-
|
|
17621
|
-
const data = event.data;
|
|
17622
|
-
if (typeof data === "string") {
|
|
17623
|
-
try {
|
|
17624
|
-
parsed = JSON.parse(data);
|
|
17625
|
-
} catch {
|
|
17626
|
-
return;
|
|
17627
|
-
}
|
|
17628
|
-
} else if (data && typeof data === "object" && "eventName" in data) {
|
|
17629
|
-
parsed = data;
|
|
17630
|
-
}
|
|
17795
|
+
if (!COINBASE_ALLOWED_POSTMESSAGE_ORIGINS.has(event.origin)) return;
|
|
17796
|
+
const parsed = parseCoinbasePostMessage(event.data);
|
|
17631
17797
|
if (!parsed) return;
|
|
17798
|
+
const eventName = parsed.eventName.toLowerCase();
|
|
17632
17799
|
const code = parsed.data?.errorCode;
|
|
17633
17800
|
const closePopup = () => {
|
|
17634
17801
|
try {
|
|
@@ -17637,16 +17804,20 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17637
17804
|
}
|
|
17638
17805
|
popupRef.current = null;
|
|
17639
17806
|
};
|
|
17640
|
-
switch (
|
|
17807
|
+
switch (eventName) {
|
|
17641
17808
|
case "onramp_api.commit_success":
|
|
17642
17809
|
case "onramp_api.polling_success":
|
|
17810
|
+
case "onramp_api.cancel":
|
|
17643
17811
|
closePopup();
|
|
17644
17812
|
break;
|
|
17645
17813
|
case "onramp_api.commit_error":
|
|
17814
|
+
case "onramp_api.polling_failed":
|
|
17646
17815
|
if (code === "ERROR_CODE_GUEST_TRANSACTION_COUNT" || code === "ERROR_CODE_GUEST_DAILY_TRANSACTION_COUNT" || code === "ERROR_CODE_GUEST_TRANSACTION_LIMIT") {
|
|
17647
17816
|
closePopup();
|
|
17648
17817
|
setView("guest_limit_reached");
|
|
17818
|
+
return;
|
|
17649
17819
|
}
|
|
17820
|
+
closePopup();
|
|
17650
17821
|
break;
|
|
17651
17822
|
default:
|
|
17652
17823
|
break;
|
|
@@ -17658,17 +17829,17 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17658
17829
|
useEffect72(() => {
|
|
17659
17830
|
onViewChange?.(view);
|
|
17660
17831
|
}, [view, onViewChange]);
|
|
17661
|
-
useEffect72(
|
|
17662
|
-
|
|
17832
|
+
useEffect72(() => {
|
|
17833
|
+
return () => {
|
|
17663
17834
|
sessionAbortRef.current?.abort();
|
|
17835
|
+
upgradeFlowAbortRef.current?.abort();
|
|
17664
17836
|
try {
|
|
17665
17837
|
popupRef.current?.close();
|
|
17666
17838
|
} catch {
|
|
17667
17839
|
}
|
|
17668
17840
|
popupRef.current = null;
|
|
17669
|
-
}
|
|
17670
|
-
|
|
17671
|
-
);
|
|
17841
|
+
};
|
|
17842
|
+
}, []);
|
|
17672
17843
|
React52.useImperativeHandle(
|
|
17673
17844
|
ref,
|
|
17674
17845
|
() => ({
|
|
@@ -17678,14 +17849,20 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17678
17849
|
setView("email_input");
|
|
17679
17850
|
return true;
|
|
17680
17851
|
}
|
|
17681
|
-
if (view === "email_otp") {
|
|
17682
|
-
setView("phone_input");
|
|
17683
|
-
setEmailCode("");
|
|
17684
|
-
return true;
|
|
17685
|
-
}
|
|
17686
17852
|
if (view === "phone_otp") {
|
|
17687
17853
|
setView("phone_input");
|
|
17688
17854
|
setPhoneCode("");
|
|
17855
|
+
setOtpSubmitting(false);
|
|
17856
|
+
return true;
|
|
17857
|
+
}
|
|
17858
|
+
if (view === "limit_upgrade_intro" || view === "limit_upgrade_failed") {
|
|
17859
|
+
return false;
|
|
17860
|
+
}
|
|
17861
|
+
if (view === "limit_upgrade_form") {
|
|
17862
|
+
setView("limit_upgrade_intro");
|
|
17863
|
+
return true;
|
|
17864
|
+
}
|
|
17865
|
+
if (view === "limit_upgrade_submitting") {
|
|
17689
17866
|
return true;
|
|
17690
17867
|
}
|
|
17691
17868
|
if (view === "checking_deposit") {
|
|
@@ -17705,22 +17882,21 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17705
17882
|
}),
|
|
17706
17883
|
[view, emailLocked]
|
|
17707
17884
|
);
|
|
17708
|
-
const normalizedPhone =
|
|
17709
|
-
const isContactValid =
|
|
17710
|
-
const
|
|
17885
|
+
const normalizedPhone = useMemo32(() => formatPhoneInput(phoneInput), [phoneInput]);
|
|
17886
|
+
const isContactValid = EMAIL_REGEX2.test(email) && PHONE_REGEX2.test(normalizedPhone);
|
|
17887
|
+
const storeApplePaySession = useCallback10(
|
|
17711
17888
|
(patch = {}) => {
|
|
17712
|
-
const
|
|
17889
|
+
const session = {
|
|
17713
17890
|
email,
|
|
17714
17891
|
phone: normalizedPhone,
|
|
17715
17892
|
termsAcceptedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
17716
17893
|
...patch
|
|
17717
17894
|
};
|
|
17718
|
-
setStoredApplePaySession(userId,
|
|
17895
|
+
setStoredApplePaySession(userId, session);
|
|
17719
17896
|
},
|
|
17720
17897
|
[email, normalizedPhone, userId]
|
|
17721
17898
|
);
|
|
17722
|
-
const
|
|
17723
|
-
if (!isContactValid) return;
|
|
17899
|
+
const createSessionAndSendOtp = useCallback10(async () => {
|
|
17724
17900
|
setView("submitting_session");
|
|
17725
17901
|
setErrorMessage("");
|
|
17726
17902
|
try {
|
|
@@ -17738,71 +17914,192 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17738
17914
|
throw new Error("Server did not return a client_secret");
|
|
17739
17915
|
}
|
|
17740
17916
|
setClientSecret(session.client_secret);
|
|
17741
|
-
|
|
17742
|
-
|
|
17743
|
-
|
|
17744
|
-
|
|
17745
|
-
"phone",
|
|
17746
|
-
session.client_secret,
|
|
17747
|
-
publishableKey
|
|
17748
|
-
);
|
|
17749
|
-
setResendCooldown(30);
|
|
17750
|
-
setView("phone_otp");
|
|
17751
|
-
} else {
|
|
17752
|
-
await sendOnrampVerificationOtp(
|
|
17753
|
-
session.id,
|
|
17754
|
-
"email",
|
|
17755
|
-
session.client_secret,
|
|
17756
|
-
publishableKey
|
|
17757
|
-
);
|
|
17758
|
-
setResendCooldown(30);
|
|
17759
|
-
setView("email_otp");
|
|
17760
|
-
}
|
|
17917
|
+
storeApplePaySession();
|
|
17918
|
+
await sendOnrampVerificationOtp(session.id, "phone", session.client_secret, publishableKey);
|
|
17919
|
+
setResendCooldown(30);
|
|
17920
|
+
setView("phone_otp");
|
|
17761
17921
|
} catch (err) {
|
|
17762
17922
|
const raw = err instanceof Error ? err.message : "Failed to start verification";
|
|
17763
17923
|
setErrorMessage(prettifyVerificationError(raw));
|
|
17764
17924
|
setView("phone_input");
|
|
17765
17925
|
}
|
|
17766
|
-
}, [
|
|
17767
|
-
const
|
|
17768
|
-
|
|
17769
|
-
|
|
17770
|
-
|
|
17771
|
-
|
|
17926
|
+
}, [email, normalizedPhone, publishableKey, storeApplePaySession]);
|
|
17927
|
+
const clearUpgradeFields = useCallback10(() => {
|
|
17928
|
+
setSsnLast4("");
|
|
17929
|
+
setDobInput("");
|
|
17930
|
+
}, []);
|
|
17931
|
+
const { action: initialAction, refetchApplePayLimits } = useApplePayInitialScreen({
|
|
17932
|
+
userId,
|
|
17933
|
+
publishableKey,
|
|
17934
|
+
normalizedPhone,
|
|
17935
|
+
userEmail,
|
|
17936
|
+
sessionPhoneVerified: verificationSession?.phone?.status === "verified",
|
|
17937
|
+
isWaiting: defaultTokenLoading || legalAgreementsLoading || userIpInfoLoading
|
|
17938
|
+
});
|
|
17939
|
+
const pollLimitUpgradeStatus = useCallback10(
|
|
17940
|
+
async (signal) => {
|
|
17941
|
+
const POLL_INTERVAL_MS4 = 1500;
|
|
17942
|
+
const POLL_TIMEOUT_MS = 3e4;
|
|
17943
|
+
const startedAt = Date.now();
|
|
17944
|
+
let firstIteration = true;
|
|
17945
|
+
while (Date.now() - startedAt < POLL_TIMEOUT_MS) {
|
|
17946
|
+
if (signal.aborted) return;
|
|
17947
|
+
if (!firstIteration) {
|
|
17948
|
+
await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL_MS4));
|
|
17949
|
+
}
|
|
17950
|
+
firstIteration = false;
|
|
17951
|
+
if (signal.aborted) return;
|
|
17952
|
+
let fresh;
|
|
17953
|
+
try {
|
|
17954
|
+
fresh = await getCoinbaseApplePayLimits(normalizedPhone, publishableKey, signal);
|
|
17955
|
+
} catch {
|
|
17956
|
+
if (signal.aborted) return;
|
|
17957
|
+
continue;
|
|
17958
|
+
}
|
|
17959
|
+
const { upgrade_status: status, limit_reached: stillCapped } = fresh;
|
|
17960
|
+
if (status === "active" || !stillCapped) {
|
|
17961
|
+
await refetchApplePayLimits();
|
|
17962
|
+
clearUpgradeFields();
|
|
17963
|
+
setLimitUpgradeError(null);
|
|
17964
|
+
if (onrampToken) {
|
|
17965
|
+
setView("amount");
|
|
17966
|
+
} else {
|
|
17967
|
+
if (signal.aborted) return;
|
|
17968
|
+
await createSessionAndSendOtp();
|
|
17969
|
+
}
|
|
17970
|
+
return;
|
|
17971
|
+
}
|
|
17972
|
+
if (status === "inactive") {
|
|
17973
|
+
await refetchApplePayLimits();
|
|
17974
|
+
clearUpgradeFields();
|
|
17975
|
+
setLimitUpgradeError(null);
|
|
17976
|
+
setView("guest_limit_reached");
|
|
17977
|
+
return;
|
|
17978
|
+
}
|
|
17979
|
+
if (status === "resubmit") {
|
|
17980
|
+
await refetchApplePayLimits();
|
|
17981
|
+
setSsnLast4("");
|
|
17982
|
+
setLimitUpgradeError(
|
|
17983
|
+
"We couldn't verify your information. Please check your SSN and date of birth and try again."
|
|
17984
|
+
);
|
|
17985
|
+
setView("limit_upgrade_form");
|
|
17986
|
+
return;
|
|
17987
|
+
}
|
|
17988
|
+
}
|
|
17989
|
+
setLimitUpgradeError(null);
|
|
17990
|
+
setView("limit_upgrade_failed");
|
|
17991
|
+
},
|
|
17992
|
+
[
|
|
17993
|
+
normalizedPhone,
|
|
17994
|
+
publishableKey,
|
|
17995
|
+
refetchApplePayLimits,
|
|
17996
|
+
onrampToken,
|
|
17997
|
+
createSessionAndSendOtp,
|
|
17998
|
+
clearUpgradeFields
|
|
17999
|
+
]
|
|
18000
|
+
);
|
|
18001
|
+
const startUpgradePolling = useCallback10(async () => {
|
|
18002
|
+
upgradeFlowAbortRef.current?.abort();
|
|
18003
|
+
const controller = new AbortController();
|
|
18004
|
+
upgradeFlowAbortRef.current = controller;
|
|
17772
18005
|
try {
|
|
17773
|
-
|
|
17774
|
-
|
|
17775
|
-
|
|
17776
|
-
|
|
17777
|
-
|
|
17778
|
-
|
|
17779
|
-
|
|
17780
|
-
|
|
17781
|
-
|
|
17782
|
-
|
|
17783
|
-
|
|
17784
|
-
|
|
17785
|
-
|
|
17786
|
-
setView("phone_otp");
|
|
18006
|
+
await pollLimitUpgradeStatus(controller.signal);
|
|
18007
|
+
} finally {
|
|
18008
|
+
if (upgradeFlowAbortRef.current === controller) {
|
|
18009
|
+
upgradeFlowAbortRef.current = null;
|
|
18010
|
+
}
|
|
18011
|
+
}
|
|
18012
|
+
}, [pollLimitUpgradeStatus]);
|
|
18013
|
+
const applyLimitRouting = useCallback10(
|
|
18014
|
+
(nextView, status) => {
|
|
18015
|
+
if (nextView === "limit_upgrade_form" && status === "resubmit") {
|
|
18016
|
+
setLimitUpgradeError(
|
|
18017
|
+
"We couldn't verify your information. Please check your SSN and date of birth and try again."
|
|
18018
|
+
);
|
|
17787
18019
|
} else {
|
|
17788
|
-
|
|
17789
|
-
setEmailCode("");
|
|
18020
|
+
setLimitUpgradeError(null);
|
|
17790
18021
|
}
|
|
17791
|
-
|
|
17792
|
-
|
|
17793
|
-
|
|
17794
|
-
|
|
17795
|
-
|
|
18022
|
+
setView(nextView);
|
|
18023
|
+
if (nextView === "limit_upgrade_submitting") {
|
|
18024
|
+
void startUpgradePolling();
|
|
18025
|
+
}
|
|
18026
|
+
},
|
|
18027
|
+
[startUpgradePolling]
|
|
18028
|
+
);
|
|
18029
|
+
const hasInitializedRef = useRef32(false);
|
|
18030
|
+
useEffect72(() => {
|
|
18031
|
+
if (hasInitializedRef.current) return;
|
|
18032
|
+
if (initialAction.kind === "pending") return;
|
|
18033
|
+
hasInitializedRef.current = true;
|
|
18034
|
+
switch (initialAction.kind) {
|
|
18035
|
+
case "navigate":
|
|
18036
|
+
setView(initialAction.view);
|
|
18037
|
+
break;
|
|
18038
|
+
case "limit_upgrade":
|
|
18039
|
+
applyLimitRouting(initialAction.view, initialAction.status);
|
|
18040
|
+
break;
|
|
18041
|
+
case "resume_with_token":
|
|
18042
|
+
setOnrampToken(initialAction.token);
|
|
18043
|
+
setView("amount");
|
|
18044
|
+
break;
|
|
18045
|
+
case "resume_send_sms":
|
|
18046
|
+
void createSessionAndSendOtp();
|
|
18047
|
+
break;
|
|
18048
|
+
}
|
|
18049
|
+
}, [initialAction, applyLimitRouting, createSessionAndSendOtp]);
|
|
18050
|
+
const startVerification = useCallback10(async () => {
|
|
18051
|
+
if (!isContactValid) return;
|
|
18052
|
+
await createSessionAndSendOtp();
|
|
18053
|
+
}, [isContactValid, createSessionAndSendOtp]);
|
|
18054
|
+
const submitLimitUpgrade = useCallback10(async () => {
|
|
18055
|
+
if (upgradeSubmitting) return;
|
|
18056
|
+
try {
|
|
18057
|
+
const dob = parseDobInput(dobInput);
|
|
18058
|
+
if (!dob || !/^\d{4}$/.test(ssnLast4)) return;
|
|
18059
|
+
setUpgradeSubmitting(true);
|
|
18060
|
+
setLimitUpgradeError(null);
|
|
18061
|
+
setView("limit_upgrade_submitting");
|
|
18062
|
+
const requestController = new AbortController();
|
|
18063
|
+
upgradeFlowAbortRef.current?.abort();
|
|
18064
|
+
upgradeFlowAbortRef.current = requestController;
|
|
18065
|
+
try {
|
|
18066
|
+
await requestCoinbaseApplePayLimitUpgrade(
|
|
18067
|
+
{
|
|
18068
|
+
phone: normalizedPhone,
|
|
18069
|
+
fields: { ssnLast4, dateOfBirth: dob }
|
|
18070
|
+
},
|
|
18071
|
+
publishableKey,
|
|
18072
|
+
requestController.signal
|
|
18073
|
+
);
|
|
18074
|
+
} catch (err) {
|
|
18075
|
+
if (requestController.signal.aborted) return;
|
|
18076
|
+
const raw = err instanceof Error ? err.message : "Failed to request limit upgrade";
|
|
18077
|
+
if (isLimitUpgradeTerminalBlock(raw)) {
|
|
18078
|
+
clearUpgradeFields();
|
|
18079
|
+
setLimitUpgradeError(null);
|
|
18080
|
+
setView("guest_limit_reached");
|
|
18081
|
+
return;
|
|
18082
|
+
}
|
|
18083
|
+
setLimitUpgradeError(prettifyVerificationError(raw));
|
|
18084
|
+
setView("limit_upgrade_form");
|
|
18085
|
+
return;
|
|
18086
|
+
} finally {
|
|
18087
|
+
if (upgradeFlowAbortRef.current === requestController) {
|
|
18088
|
+
upgradeFlowAbortRef.current = null;
|
|
18089
|
+
}
|
|
18090
|
+
}
|
|
18091
|
+
await startUpgradePolling();
|
|
17796
18092
|
} finally {
|
|
17797
|
-
|
|
18093
|
+
setUpgradeSubmitting(false);
|
|
17798
18094
|
}
|
|
17799
18095
|
}, [
|
|
17800
|
-
|
|
17801
|
-
|
|
17802
|
-
|
|
18096
|
+
upgradeSubmitting,
|
|
18097
|
+
dobInput,
|
|
18098
|
+
ssnLast4,
|
|
18099
|
+
normalizedPhone,
|
|
17803
18100
|
publishableKey,
|
|
17804
|
-
|
|
17805
|
-
|
|
18101
|
+
startUpgradePolling,
|
|
18102
|
+
clearUpgradeFields
|
|
17806
18103
|
]);
|
|
17807
18104
|
const submitPhoneOtp = useCallback10(async () => {
|
|
17808
18105
|
if (!verificationSession || !clientSecret || phoneCode.length !== 6) return;
|
|
@@ -17825,7 +18122,7 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17825
18122
|
publishableKey
|
|
17826
18123
|
);
|
|
17827
18124
|
setOnrampToken(tokenRes);
|
|
17828
|
-
|
|
18125
|
+
storeApplePaySession({
|
|
17829
18126
|
emailVerifiedAt: updated.email.verified_at,
|
|
17830
18127
|
phoneVerifiedAt: updated.phone.verified_at,
|
|
17831
18128
|
onrampToken: tokenRes.token,
|
|
@@ -17834,17 +18131,30 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17834
18131
|
setEmailLocked(true);
|
|
17835
18132
|
setPhoneCode("");
|
|
17836
18133
|
if (amountUsd) setAmount(amountUsd);
|
|
18134
|
+
try {
|
|
18135
|
+
const result = await refetchApplePayLimits();
|
|
18136
|
+
if (result.data) {
|
|
18137
|
+
const nextView = getViewForLimitStatus(result.data);
|
|
18138
|
+
if (nextView) {
|
|
18139
|
+
setOtpSubmitting(false);
|
|
18140
|
+
applyLimitRouting(nextView, result.data.upgrade_status);
|
|
18141
|
+
return;
|
|
18142
|
+
}
|
|
18143
|
+
}
|
|
18144
|
+
} catch {
|
|
18145
|
+
}
|
|
18146
|
+
setOtpSubmitting(false);
|
|
17837
18147
|
setView("amount");
|
|
17838
|
-
|
|
17839
|
-
setOtpError("Incorrect code. Please try again.");
|
|
17840
|
-
setPhoneCode("");
|
|
18148
|
+
return;
|
|
17841
18149
|
}
|
|
18150
|
+
setOtpError("Incorrect code. Please try again.");
|
|
18151
|
+
setPhoneCode("");
|
|
18152
|
+
setOtpSubmitting(false);
|
|
17842
18153
|
} catch (err) {
|
|
17843
18154
|
setOtpError(
|
|
17844
18155
|
prettifyVerificationError(err instanceof Error ? err.message : "Verification failed")
|
|
17845
18156
|
);
|
|
17846
18157
|
setPhoneCode("");
|
|
17847
|
-
} finally {
|
|
17848
18158
|
setOtpSubmitting(false);
|
|
17849
18159
|
}
|
|
17850
18160
|
}, [
|
|
@@ -17852,22 +18162,25 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17852
18162
|
clientSecret,
|
|
17853
18163
|
phoneCode,
|
|
17854
18164
|
publishableKey,
|
|
17855
|
-
|
|
18165
|
+
storeApplePaySession,
|
|
17856
18166
|
amountUsd,
|
|
17857
|
-
otpSubmitting
|
|
18167
|
+
otpSubmitting,
|
|
18168
|
+
refetchApplePayLimits,
|
|
18169
|
+
getViewForLimitStatus,
|
|
18170
|
+
applyLimitRouting
|
|
17858
18171
|
]);
|
|
17859
18172
|
const prepareSession = useCallback10(
|
|
17860
18173
|
async (token, amt) => {
|
|
18174
|
+
setErrorMessage("");
|
|
17861
18175
|
if (!destinationChainType || !destinationChainId) {
|
|
17862
18176
|
setErrorMessage("Deposit destination not configured. Please contact support.");
|
|
17863
18177
|
return;
|
|
17864
18178
|
}
|
|
17865
|
-
|
|
17866
|
-
|
|
17867
|
-
|
|
17868
|
-
)
|
|
17869
|
-
|
|
17870
|
-
setErrorMessage("Coinbase Apple Pay is not available for this network.");
|
|
18179
|
+
if (defaultTokenLoading) {
|
|
18180
|
+
return;
|
|
18181
|
+
}
|
|
18182
|
+
if (defaultTokenError || !defaultToken) {
|
|
18183
|
+
setErrorMessage("Unable to load token information. Please try again.");
|
|
17871
18184
|
return;
|
|
17872
18185
|
}
|
|
17873
18186
|
const settlementAddress = depositWallet?.address;
|
|
@@ -17878,19 +18191,17 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17878
18191
|
sessionAbortRef.current?.abort();
|
|
17879
18192
|
const controller = new AbortController();
|
|
17880
18193
|
sessionAbortRef.current = controller;
|
|
17881
|
-
setPreparingSession(true);
|
|
17882
|
-
setErrorMessage("");
|
|
17883
18194
|
try {
|
|
17884
18195
|
const externalId = generatePrefixedKSUID("orsext");
|
|
17885
18196
|
const session = await createCoinbaseApplePaySession(
|
|
17886
18197
|
{
|
|
17887
18198
|
source_currency: "usd",
|
|
17888
18199
|
source_amount: amt,
|
|
17889
|
-
destination_currency:
|
|
17890
|
-
destination_network:
|
|
18200
|
+
destination_currency: defaultToken.destination_currency,
|
|
18201
|
+
destination_network: defaultToken.destination_network,
|
|
17891
18202
|
wallet_address: settlementAddress,
|
|
17892
18203
|
external_id: externalId,
|
|
17893
|
-
...
|
|
18204
|
+
...userEmail ? { email: userEmail } : {}
|
|
17894
18205
|
},
|
|
17895
18206
|
token,
|
|
17896
18207
|
publishableKey,
|
|
@@ -17934,18 +18245,16 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17934
18245
|
setPaymentSession(null);
|
|
17935
18246
|
setPaymentSessionAmount(null);
|
|
17936
18247
|
setErrorMessage("Unable to process your request. Please try again later.");
|
|
17937
|
-
} finally {
|
|
17938
|
-
if (sessionAbortRef.current === controller) {
|
|
17939
|
-
setPreparingSession(false);
|
|
17940
|
-
}
|
|
17941
18248
|
}
|
|
17942
18249
|
},
|
|
17943
18250
|
[
|
|
17944
|
-
destinationTokenSymbol,
|
|
17945
18251
|
destinationChainType,
|
|
17946
18252
|
destinationChainId,
|
|
18253
|
+
defaultToken,
|
|
18254
|
+
defaultTokenLoading,
|
|
18255
|
+
defaultTokenError,
|
|
17947
18256
|
depositWallet?.address,
|
|
17948
|
-
|
|
18257
|
+
userEmail,
|
|
17949
18258
|
publishableKey,
|
|
17950
18259
|
onEvent,
|
|
17951
18260
|
userId
|
|
@@ -17989,42 +18298,8 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
17989
18298
|
if (view === "loading_config") {
|
|
17990
18299
|
return /* @__PURE__ */ jsx132("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-16", style: containerStyle, children: /* @__PURE__ */ jsx132(LoaderCircle, { className: "uf-w-6 uf-h-6 uf-animate-spin", style: { color: colors2.primary } }) });
|
|
17991
18300
|
}
|
|
17992
|
-
if (view === "disabled") {
|
|
17993
|
-
return /* @__PURE__ */ jsxs11(
|
|
17994
|
-
"div",
|
|
17995
|
-
{
|
|
17996
|
-
className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-12 uf-px-4",
|
|
17997
|
-
style: containerStyle,
|
|
17998
|
-
children: [
|
|
17999
|
-
/* @__PURE__ */ jsx132(
|
|
18000
|
-
CircleAlert,
|
|
18001
|
-
{
|
|
18002
|
-
className: "uf-w-8 uf-h-8 uf-mb-4",
|
|
18003
|
-
style: { color: colors2.foregroundMuted }
|
|
18004
|
-
}
|
|
18005
|
-
),
|
|
18006
|
-
/* @__PURE__ */ jsx132(
|
|
18007
|
-
"h3",
|
|
18008
|
-
{
|
|
18009
|
-
className: "uf-text-base uf-font-medium uf-mb-1",
|
|
18010
|
-
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
18011
|
-
children: "Apple Pay is unavailable"
|
|
18012
|
-
}
|
|
18013
|
-
),
|
|
18014
|
-
/* @__PURE__ */ jsx132(
|
|
18015
|
-
"p",
|
|
18016
|
-
{
|
|
18017
|
-
className: "uf-text-sm uf-text-center",
|
|
18018
|
-
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
18019
|
-
children: "Apple Pay is disabled for this project. Try another payment method."
|
|
18020
|
-
}
|
|
18021
|
-
)
|
|
18022
|
-
]
|
|
18023
|
-
}
|
|
18024
|
-
);
|
|
18025
|
-
}
|
|
18026
18301
|
if (view === "email_input") {
|
|
18027
|
-
const emailValid =
|
|
18302
|
+
const emailValid = EMAIL_REGEX2.test(email);
|
|
18028
18303
|
return /* @__PURE__ */ jsxs11("div", { className: "uf-flex uf-flex-col uf-pb-1 uf-pt-2", style: containerStyle, children: [
|
|
18029
18304
|
/* @__PURE__ */ jsx132(
|
|
18030
18305
|
"label",
|
|
@@ -18041,9 +18316,7 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18041
18316
|
value: email,
|
|
18042
18317
|
onChange: (e) => setEmail(e.target.value.trim()),
|
|
18043
18318
|
onKeyDown: (e) => {
|
|
18044
|
-
if (e.key === "Enter" && emailValid)
|
|
18045
|
-
setView("phone_input");
|
|
18046
|
-
}
|
|
18319
|
+
if (e.key === "Enter" && emailValid) setView("phone_input");
|
|
18047
18320
|
},
|
|
18048
18321
|
placeholder: "you@example.com",
|
|
18049
18322
|
autoComplete: "email",
|
|
@@ -18079,7 +18352,7 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18079
18352
|
}
|
|
18080
18353
|
if (view === "phone_input" || view === "submitting_session") {
|
|
18081
18354
|
const submitting = view === "submitting_session";
|
|
18082
|
-
const phoneValid =
|
|
18355
|
+
const phoneValid = PHONE_REGEX2.test(normalizedPhone);
|
|
18083
18356
|
const rawDigits = (() => {
|
|
18084
18357
|
const digits = phoneInput.replace(/\D/g, "");
|
|
18085
18358
|
return digits.startsWith("1") ? digits.slice(1, 11) : digits.slice(0, 10);
|
|
@@ -18160,15 +18433,7 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18160
18433
|
!phoneInput && /* @__PURE__ */ jsx132("div", { className: "uf-text-xs uf-mb-2 uf-px-1", style: { color: colors2.foregroundMuted }, children: "Re-verified every 60 days." }),
|
|
18161
18434
|
errorMessage && /* @__PURE__ */ jsx132("div", { className: "uf-text-xs uf-mt-2 uf-px-1", style: { color: colors2.error }, children: errorMessage }),
|
|
18162
18435
|
/* @__PURE__ */ jsx132("div", { className: "uf-flex-1" }),
|
|
18163
|
-
/* @__PURE__ */ jsx132(
|
|
18164
|
-
LegalDisclaimer,
|
|
18165
|
-
{
|
|
18166
|
-
legalAgreements,
|
|
18167
|
-
loading: legalAgreementsLoading,
|
|
18168
|
-
colors: colors2,
|
|
18169
|
-
fonts
|
|
18170
|
-
}
|
|
18171
|
-
),
|
|
18436
|
+
/* @__PURE__ */ jsx132(LegalDisclaimer, { legalAgreements, loading: legalAgreementsLoading }),
|
|
18172
18437
|
/* @__PURE__ */ jsx132(
|
|
18173
18438
|
"button",
|
|
18174
18439
|
{
|
|
@@ -18187,12 +18452,9 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18187
18452
|
)
|
|
18188
18453
|
] });
|
|
18189
18454
|
}
|
|
18190
|
-
if (view === "
|
|
18191
|
-
const
|
|
18192
|
-
const
|
|
18193
|
-
const setCode = isEmail ? setEmailCode : setPhoneCode;
|
|
18194
|
-
const target = isEmail ? maskEmail(email) : maskPhone(normalizedPhone);
|
|
18195
|
-
const submit = isEmail ? submitEmailOtp : submitPhoneOtp;
|
|
18455
|
+
if (view === "phone_otp") {
|
|
18456
|
+
const code = phoneCode;
|
|
18457
|
+
const target = maskPhone(normalizedPhone);
|
|
18196
18458
|
const canSubmit = code.length === 6 && !otpSubmitting;
|
|
18197
18459
|
return /* @__PURE__ */ jsxs11("div", { className: "uf-flex uf-flex-col uf-pb-1 uf-items-center uf-pt-2", style: containerStyle, children: [
|
|
18198
18460
|
/* @__PURE__ */ jsxs11(
|
|
@@ -18215,13 +18477,12 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18215
18477
|
maxLength: 6,
|
|
18216
18478
|
value: code,
|
|
18217
18479
|
onChange: (e) => {
|
|
18218
|
-
|
|
18219
|
-
setCode(v);
|
|
18480
|
+
setPhoneCode(e.target.value.replace(/\D/g, "").slice(0, 6));
|
|
18220
18481
|
setOtpError(null);
|
|
18221
18482
|
},
|
|
18222
18483
|
onKeyDown: (e) => {
|
|
18223
18484
|
if (e.key === "Enter" && code.length === 6 && !otpSubmitting) {
|
|
18224
|
-
void
|
|
18485
|
+
void submitPhoneOtp();
|
|
18225
18486
|
}
|
|
18226
18487
|
},
|
|
18227
18488
|
autoFocus: true,
|
|
@@ -18248,7 +18509,7 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18248
18509
|
if (!verificationSession || !clientSecret) return;
|
|
18249
18510
|
void sendOnrampVerificationOtp(
|
|
18250
18511
|
verificationSession.id,
|
|
18251
|
-
|
|
18512
|
+
"phone",
|
|
18252
18513
|
clientSecret,
|
|
18253
18514
|
publishableKey
|
|
18254
18515
|
).then(() => setResendCooldown(30));
|
|
@@ -18261,7 +18522,7 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18261
18522
|
/* @__PURE__ */ jsx132(
|
|
18262
18523
|
"button",
|
|
18263
18524
|
{
|
|
18264
|
-
onClick:
|
|
18525
|
+
onClick: submitPhoneOtp,
|
|
18265
18526
|
disabled: !canSubmit,
|
|
18266
18527
|
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",
|
|
18267
18528
|
style: {
|
|
@@ -18409,7 +18670,7 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18409
18670
|
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`,
|
|
18410
18671
|
opacity: 0.5
|
|
18411
18672
|
},
|
|
18412
|
-
children: !hasInput || !validAmount ? "Enter amount" : /* @__PURE__ */ jsxs11(Fragment42, { children: [
|
|
18673
|
+
children: !hasInput || !validAmount ? "Enter amount" : errorMessage ? "Unable to prepare Apple Pay" : defaultTokenLoading ? "Loading token information\u2026" : defaultTokenError ? "Token routing unavailable" : /* @__PURE__ */ jsxs11(Fragment42, { children: [
|
|
18413
18674
|
/* @__PURE__ */ jsx132(LoaderCircle, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
|
|
18414
18675
|
"Preparing Apple Pay"
|
|
18415
18676
|
] })
|
|
@@ -18462,6 +18723,274 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18462
18723
|
}
|
|
18463
18724
|
);
|
|
18464
18725
|
}
|
|
18726
|
+
if (view === "limit_upgrade_intro") {
|
|
18727
|
+
return /* @__PURE__ */ jsxs11("div", { className: "uf-flex uf-flex-col uf-pt-8 uf-pb-2 uf-px-2", style: containerStyle, children: [
|
|
18728
|
+
/* @__PURE__ */ jsx132(
|
|
18729
|
+
"h3",
|
|
18730
|
+
{
|
|
18731
|
+
className: "uf-text-xl uf-mb-3 uf-text-center",
|
|
18732
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
18733
|
+
children: "Apple Pay limit reached"
|
|
18734
|
+
}
|
|
18735
|
+
),
|
|
18736
|
+
/* @__PURE__ */ jsx132(
|
|
18737
|
+
"p",
|
|
18738
|
+
{
|
|
18739
|
+
className: "uf-text-sm uf-text-center uf-mb-10 uf-max-w-[320px] uf-mx-auto",
|
|
18740
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
18741
|
+
children: "Submit your date of birth and SSN to increase your Apple Pay limit."
|
|
18742
|
+
}
|
|
18743
|
+
),
|
|
18744
|
+
/* @__PURE__ */ jsx132(
|
|
18745
|
+
"button",
|
|
18746
|
+
{
|
|
18747
|
+
onClick: () => {
|
|
18748
|
+
setLimitUpgradeError(null);
|
|
18749
|
+
setView("limit_upgrade_form");
|
|
18750
|
+
},
|
|
18751
|
+
className: "uf-w-full uf-py-3 uf-mb-2 uf-text-sm uf-font-medium uf-transition-colors",
|
|
18752
|
+
style: {
|
|
18753
|
+
backgroundColor: colors2.primary,
|
|
18754
|
+
color: colors2.primaryForeground,
|
|
18755
|
+
fontFamily: fonts.medium,
|
|
18756
|
+
borderRadius: components.button.borderRadius,
|
|
18757
|
+
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
|
|
18758
|
+
},
|
|
18759
|
+
children: "Continue"
|
|
18760
|
+
}
|
|
18761
|
+
),
|
|
18762
|
+
/* @__PURE__ */ jsx132(
|
|
18763
|
+
"button",
|
|
18764
|
+
{
|
|
18765
|
+
onClick: () => {
|
|
18766
|
+
setLimitUpgradeError(null);
|
|
18767
|
+
onExit?.();
|
|
18768
|
+
},
|
|
18769
|
+
className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors",
|
|
18770
|
+
style: {
|
|
18771
|
+
backgroundColor: "transparent",
|
|
18772
|
+
color: colors2.error,
|
|
18773
|
+
fontFamily: fonts.medium,
|
|
18774
|
+
borderRadius: components.button.borderRadius,
|
|
18775
|
+
border: `${components.button.borderWidth}px solid transparent`
|
|
18776
|
+
},
|
|
18777
|
+
children: "Cancel"
|
|
18778
|
+
}
|
|
18779
|
+
)
|
|
18780
|
+
] });
|
|
18781
|
+
}
|
|
18782
|
+
if (view === "limit_upgrade_submitting") {
|
|
18783
|
+
return /* @__PURE__ */ jsxs11(
|
|
18784
|
+
"div",
|
|
18785
|
+
{
|
|
18786
|
+
className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-16 uf-px-4",
|
|
18787
|
+
style: containerStyle,
|
|
18788
|
+
children: [
|
|
18789
|
+
/* @__PURE__ */ jsx132(
|
|
18790
|
+
"div",
|
|
18791
|
+
{
|
|
18792
|
+
className: "uf-w-20 uf-h-20 uf-rounded-full uf-flex uf-items-center uf-justify-center uf-mb-6",
|
|
18793
|
+
style: { backgroundColor: `${colors2.primary}20` },
|
|
18794
|
+
children: /* @__PURE__ */ jsx132(
|
|
18795
|
+
LoaderCircle,
|
|
18796
|
+
{
|
|
18797
|
+
className: "uf-w-10 uf-h-10 uf-animate-spin",
|
|
18798
|
+
style: { color: colors2.primary }
|
|
18799
|
+
}
|
|
18800
|
+
)
|
|
18801
|
+
}
|
|
18802
|
+
),
|
|
18803
|
+
/* @__PURE__ */ jsx132(
|
|
18804
|
+
"h3",
|
|
18805
|
+
{
|
|
18806
|
+
className: "uf-text-xl uf-mb-2 uf-text-center",
|
|
18807
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
18808
|
+
children: "Verifying your information"
|
|
18809
|
+
}
|
|
18810
|
+
),
|
|
18811
|
+
/* @__PURE__ */ jsx132(
|
|
18812
|
+
"p",
|
|
18813
|
+
{
|
|
18814
|
+
className: "uf-text-sm uf-text-center uf-max-w-[280px]",
|
|
18815
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
18816
|
+
children: "Your limit increase request is under review. This usually takes just a few seconds."
|
|
18817
|
+
}
|
|
18818
|
+
)
|
|
18819
|
+
]
|
|
18820
|
+
}
|
|
18821
|
+
);
|
|
18822
|
+
}
|
|
18823
|
+
if (view === "limit_upgrade_form") {
|
|
18824
|
+
const dobValid = isDobInputValid(dobInput);
|
|
18825
|
+
const ssnValid = /^\d{4}$/.test(ssnLast4);
|
|
18826
|
+
const formValid = dobValid && ssnValid;
|
|
18827
|
+
const formInputStyle = {
|
|
18828
|
+
backgroundColor: components.card.backgroundColor,
|
|
18829
|
+
color: components.input.textColor,
|
|
18830
|
+
fontFamily: fonts.regular,
|
|
18831
|
+
borderRadius: components.card.borderRadius,
|
|
18832
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
18833
|
+
};
|
|
18834
|
+
return /* @__PURE__ */ jsxs11("div", { className: "uf-flex uf-flex-col uf-pb-1 uf-pt-2", style: containerStyle, children: [
|
|
18835
|
+
/* @__PURE__ */ jsx132(
|
|
18836
|
+
"label",
|
|
18837
|
+
{
|
|
18838
|
+
className: "uf-text-xs uf-font-medium uf-mb-1.5 uf-px-1",
|
|
18839
|
+
style: { color: components.card.labelColor, fontFamily: fonts.medium },
|
|
18840
|
+
children: "Date of birth"
|
|
18841
|
+
}
|
|
18842
|
+
),
|
|
18843
|
+
/* @__PURE__ */ jsx132(
|
|
18844
|
+
"input",
|
|
18845
|
+
{
|
|
18846
|
+
type: "text",
|
|
18847
|
+
inputMode: "numeric",
|
|
18848
|
+
maxLength: 10,
|
|
18849
|
+
value: dobInput,
|
|
18850
|
+
onChange: (e) => {
|
|
18851
|
+
setDobInput(formatDobInput(e.target.value));
|
|
18852
|
+
if (limitUpgradeError) setLimitUpgradeError(null);
|
|
18853
|
+
},
|
|
18854
|
+
onKeyDown: (e) => {
|
|
18855
|
+
if (e.key === "Enter" && formValid) void submitLimitUpgrade();
|
|
18856
|
+
},
|
|
18857
|
+
placeholder: "MM/DD/YYYY",
|
|
18858
|
+
autoComplete: "bday",
|
|
18859
|
+
"aria-label": "Date of birth",
|
|
18860
|
+
className: "uf-w-full uf-px-3 uf-py-3 uf-mb-3 uf-text-sm uf-outline-none",
|
|
18861
|
+
style: formInputStyle
|
|
18862
|
+
}
|
|
18863
|
+
),
|
|
18864
|
+
/* @__PURE__ */ jsx132(
|
|
18865
|
+
"label",
|
|
18866
|
+
{
|
|
18867
|
+
className: "uf-text-xs uf-font-medium uf-mb-1.5 uf-px-1",
|
|
18868
|
+
style: { color: components.card.labelColor, fontFamily: fonts.medium },
|
|
18869
|
+
children: "Last 4 of SSN"
|
|
18870
|
+
}
|
|
18871
|
+
),
|
|
18872
|
+
/* @__PURE__ */ jsx132(
|
|
18873
|
+
"input",
|
|
18874
|
+
{
|
|
18875
|
+
type: "password",
|
|
18876
|
+
inputMode: "numeric",
|
|
18877
|
+
pattern: "[0-9]*",
|
|
18878
|
+
maxLength: 4,
|
|
18879
|
+
value: ssnLast4,
|
|
18880
|
+
onChange: (e) => {
|
|
18881
|
+
setSsnLast4(e.target.value.replace(/\D/g, "").slice(0, 4));
|
|
18882
|
+
if (limitUpgradeError) setLimitUpgradeError(null);
|
|
18883
|
+
},
|
|
18884
|
+
onKeyDown: (e) => {
|
|
18885
|
+
if (e.key === "Enter" && formValid) void submitLimitUpgrade();
|
|
18886
|
+
},
|
|
18887
|
+
placeholder: "\u2022\u2022\u2022\u2022",
|
|
18888
|
+
autoComplete: "off",
|
|
18889
|
+
name: "off",
|
|
18890
|
+
autoCorrect: "off",
|
|
18891
|
+
autoCapitalize: "none",
|
|
18892
|
+
spellCheck: false,
|
|
18893
|
+
"data-1p-ignore": "true",
|
|
18894
|
+
"data-lpignore": "true",
|
|
18895
|
+
"data-form-type": "other",
|
|
18896
|
+
"aria-label": "Last 4 digits of SSN",
|
|
18897
|
+
"aria-autocomplete": "none",
|
|
18898
|
+
className: "uf-w-full uf-px-3 uf-py-3 uf-mb-2 uf-text-sm uf-outline-none",
|
|
18899
|
+
style: formInputStyle
|
|
18900
|
+
}
|
|
18901
|
+
),
|
|
18902
|
+
limitUpgradeError && /* @__PURE__ */ jsx132(
|
|
18903
|
+
"div",
|
|
18904
|
+
{
|
|
18905
|
+
className: "uf-text-xs uf-mt-2 uf-px-1",
|
|
18906
|
+
style: { color: colors2.error, fontFamily: fonts.regular },
|
|
18907
|
+
children: limitUpgradeError
|
|
18908
|
+
}
|
|
18909
|
+
),
|
|
18910
|
+
/* @__PURE__ */ jsx132("div", { className: "uf-flex-1" }),
|
|
18911
|
+
/* @__PURE__ */ jsx132(
|
|
18912
|
+
"button",
|
|
18913
|
+
{
|
|
18914
|
+
onClick: () => void submitLimitUpgrade(),
|
|
18915
|
+
disabled: !formValid || upgradeSubmitting,
|
|
18916
|
+
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",
|
|
18917
|
+
style: {
|
|
18918
|
+
backgroundColor: colors2.primary,
|
|
18919
|
+
color: colors2.primaryForeground,
|
|
18920
|
+
fontFamily: fonts.medium,
|
|
18921
|
+
borderRadius: components.button.borderRadius,
|
|
18922
|
+
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
|
|
18923
|
+
},
|
|
18924
|
+
children: upgradeSubmitting ? /* @__PURE__ */ jsxs11("span", { className: "uf-flex uf-items-center uf-justify-center uf-gap-2", children: [
|
|
18925
|
+
/* @__PURE__ */ jsx132(LoaderCircle, { className: "uf-w-4 uf-h-4 uf-animate-spin" }),
|
|
18926
|
+
"Submitting\u2026"
|
|
18927
|
+
] }) : "Submit"
|
|
18928
|
+
}
|
|
18929
|
+
)
|
|
18930
|
+
] });
|
|
18931
|
+
}
|
|
18932
|
+
if (view === "limit_upgrade_failed") {
|
|
18933
|
+
return /* @__PURE__ */ jsxs11("div", { className: "uf-flex uf-flex-col uf-pt-8 uf-pb-2 uf-px-2", style: containerStyle, children: [
|
|
18934
|
+
/* @__PURE__ */ jsx132(
|
|
18935
|
+
"h3",
|
|
18936
|
+
{
|
|
18937
|
+
className: "uf-text-xl uf-mb-3 uf-text-center",
|
|
18938
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
18939
|
+
children: "Apple Pay limit reached"
|
|
18940
|
+
}
|
|
18941
|
+
),
|
|
18942
|
+
/* @__PURE__ */ jsxs11(
|
|
18943
|
+
"p",
|
|
18944
|
+
{
|
|
18945
|
+
className: "uf-text-sm uf-text-center uf-mb-2 uf-max-w-[320px] uf-mx-auto",
|
|
18946
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
18947
|
+
children: [
|
|
18948
|
+
"Failed to increase. Please try again later or",
|
|
18949
|
+
" ",
|
|
18950
|
+
/* @__PURE__ */ jsx132(
|
|
18951
|
+
"a",
|
|
18952
|
+
{
|
|
18953
|
+
href: UNIFOLD_SUPPORT_URL,
|
|
18954
|
+
target: "_blank",
|
|
18955
|
+
rel: "noreferrer noopener",
|
|
18956
|
+
className: "uf-underline",
|
|
18957
|
+
style: { color: colors2.primary },
|
|
18958
|
+
children: "contact support"
|
|
18959
|
+
}
|
|
18960
|
+
),
|
|
18961
|
+
"."
|
|
18962
|
+
]
|
|
18963
|
+
}
|
|
18964
|
+
),
|
|
18965
|
+
limitUpgradeError && /* @__PURE__ */ jsx132(
|
|
18966
|
+
"p",
|
|
18967
|
+
{
|
|
18968
|
+
className: "uf-text-xs uf-text-center uf-mb-2 uf-px-2",
|
|
18969
|
+
style: { color: colors2.error, fontFamily: fonts.regular },
|
|
18970
|
+
children: limitUpgradeError
|
|
18971
|
+
}
|
|
18972
|
+
),
|
|
18973
|
+
/* @__PURE__ */ jsx132("div", { className: "uf-mb-8" }),
|
|
18974
|
+
/* @__PURE__ */ jsx132(
|
|
18975
|
+
"button",
|
|
18976
|
+
{
|
|
18977
|
+
onClick: () => {
|
|
18978
|
+
setLimitUpgradeError(null);
|
|
18979
|
+
onExit?.();
|
|
18980
|
+
},
|
|
18981
|
+
className: "uf-w-full uf-py-3 uf-text-sm uf-font-medium uf-transition-colors",
|
|
18982
|
+
style: {
|
|
18983
|
+
backgroundColor: colors2.primary,
|
|
18984
|
+
color: colors2.primaryForeground,
|
|
18985
|
+
fontFamily: fonts.medium,
|
|
18986
|
+
borderRadius: components.button.borderRadius,
|
|
18987
|
+
border: `${components.button.borderWidth}px solid ${components.button.borderColor}`
|
|
18988
|
+
},
|
|
18989
|
+
children: "Return"
|
|
18990
|
+
}
|
|
18991
|
+
)
|
|
18992
|
+
] });
|
|
18993
|
+
}
|
|
18465
18994
|
if (view === "guest_limit_reached") {
|
|
18466
18995
|
return /* @__PURE__ */ jsxs11(
|
|
18467
18996
|
"div",
|
|
@@ -18482,7 +19011,7 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18482
19011
|
{
|
|
18483
19012
|
className: "uf-text-sm uf-text-center uf-mb-12 uf-max-w-[300px]",
|
|
18484
19013
|
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
18485
|
-
children: "Your account
|
|
19014
|
+
children: "Your account is not eligible for a limit increase at this time."
|
|
18486
19015
|
}
|
|
18487
19016
|
),
|
|
18488
19017
|
/* @__PURE__ */ jsx132(
|
|
@@ -18508,7 +19037,95 @@ var BuyWithApplePay = React52.forwardRef(
|
|
|
18508
19037
|
}
|
|
18509
19038
|
);
|
|
18510
19039
|
BuyWithApplePay.displayName = "BuyWithApplePay";
|
|
18511
|
-
function
|
|
19040
|
+
function formatPhoneInput(raw) {
|
|
19041
|
+
const digits = raw.replace(/\D/g, "");
|
|
19042
|
+
if (raw.startsWith("+")) {
|
|
19043
|
+
return `+${digits}`;
|
|
19044
|
+
}
|
|
19045
|
+
if (digits.length === 10) return `+1${digits}`;
|
|
19046
|
+
if (digits.length === 11 && digits.startsWith("1")) return `+${digits}`;
|
|
19047
|
+
return digits.length > 0 ? `+${digits}` : "";
|
|
19048
|
+
}
|
|
19049
|
+
function maskPhone(phone) {
|
|
19050
|
+
if (!/^\+1\d{10}$/.test(phone)) return phone;
|
|
19051
|
+
return `+1 (***) ***-${phone.slice(-4)}`;
|
|
19052
|
+
}
|
|
19053
|
+
function isGuestLimitError(err) {
|
|
19054
|
+
const message = err instanceof Error ? err.message : String(err ?? "");
|
|
19055
|
+
if (/coinbase_onramp_guest_limit_reached/i.test(message)) return true;
|
|
19056
|
+
if (/guest_(daily_)?transaction_(count|limit)/i.test(message)) return true;
|
|
19057
|
+
return false;
|
|
19058
|
+
}
|
|
19059
|
+
function isLimitUpgradeTerminalBlock(message) {
|
|
19060
|
+
if (/coinbase_onramp_guest_limit_reached/i.test(message)) return true;
|
|
19061
|
+
if (/limit upgrade is not available/i.test(message)) return true;
|
|
19062
|
+
if (/limits.?upgrade.?blocked/i.test(message)) return true;
|
|
19063
|
+
return false;
|
|
19064
|
+
}
|
|
19065
|
+
function prettifyVerificationError(message) {
|
|
19066
|
+
if (/\b429\b|too many requests|rate.?limit|throttle/i.test(message)) {
|
|
19067
|
+
return "Too many attempts. Please wait a few minutes and try again.";
|
|
19068
|
+
}
|
|
19069
|
+
if (/network|failed to fetch|abort/i.test(message)) {
|
|
19070
|
+
return "Network error. Check your connection and try again.";
|
|
19071
|
+
}
|
|
19072
|
+
if (/voip|not a valid US|not a cell/i.test(message)) {
|
|
19073
|
+
return "We can only verify real US cell phones (not VoIP). Try a different number.";
|
|
19074
|
+
}
|
|
19075
|
+
const cleaned = message.replace(/\s*\[[\w_]+\]:\s*.*$/, "").trim();
|
|
19076
|
+
return cleaned || message;
|
|
19077
|
+
}
|
|
19078
|
+
function formatDobInput(raw) {
|
|
19079
|
+
const digits = raw.replace(/\D/g, "").slice(0, 8);
|
|
19080
|
+
if (digits.length <= 2) return digits;
|
|
19081
|
+
if (digits.length <= 4) return `${digits.slice(0, 2)}/${digits.slice(2)}`;
|
|
19082
|
+
return `${digits.slice(0, 2)}/${digits.slice(2, 4)}/${digits.slice(4)}`;
|
|
19083
|
+
}
|
|
19084
|
+
function isDobInputValid(input) {
|
|
19085
|
+
return parseDobInput(input) !== null;
|
|
19086
|
+
}
|
|
19087
|
+
function parseDobInput(input) {
|
|
19088
|
+
const m = /^(\d{2})\/(\d{2})\/(\d{4})$/.exec(input);
|
|
19089
|
+
if (!m) return null;
|
|
19090
|
+
const [, month, day, year] = m;
|
|
19091
|
+
if (!/^(0[1-9]|1[0-2])$/.test(month)) return null;
|
|
19092
|
+
if (!/^(0[1-9]|[12]\d|3[01])$/.test(day)) return null;
|
|
19093
|
+
if (!/^(19|20)\d{2}$/.test(year)) return null;
|
|
19094
|
+
return { month, day, year };
|
|
19095
|
+
}
|
|
19096
|
+
var POPUP_W = 500;
|
|
19097
|
+
var POPUP_H = 700;
|
|
19098
|
+
function openCoinbasePaymentPopup(url) {
|
|
19099
|
+
if (typeof window === "undefined") return null;
|
|
19100
|
+
const screenW = window.screen.availWidth ?? window.innerWidth;
|
|
19101
|
+
const screenH = window.screen.availHeight ?? window.innerHeight;
|
|
19102
|
+
const left = Math.max(0, Math.round((screenW - POPUP_W) / 2));
|
|
19103
|
+
const top = Math.max(0, Math.round((screenH - POPUP_H) / 2));
|
|
19104
|
+
return window.open(
|
|
19105
|
+
url,
|
|
19106
|
+
"unifold_coinbase_apple_pay",
|
|
19107
|
+
`popup,width=${POPUP_W},height=${POPUP_H},left=${left},top=${top}`
|
|
19108
|
+
);
|
|
19109
|
+
}
|
|
19110
|
+
var FALLBACK_AGREEMENTS = [
|
|
19111
|
+
{
|
|
19112
|
+
key: "guest_checkout_terms",
|
|
19113
|
+
name: "Guest Checkout Terms of Service",
|
|
19114
|
+
url: "https://www.coinbase.com/legal/cb-pay/onramp-guest-checkout-terms"
|
|
19115
|
+
},
|
|
19116
|
+
{
|
|
19117
|
+
key: "user_agreement",
|
|
19118
|
+
name: "User Agreement",
|
|
19119
|
+
url: "https://www.coinbase.com/legal/user_agreement"
|
|
19120
|
+
},
|
|
19121
|
+
{
|
|
19122
|
+
key: "privacy_policy",
|
|
19123
|
+
name: "Privacy Policy",
|
|
19124
|
+
url: "https://www.coinbase.com/legal/privacy"
|
|
19125
|
+
}
|
|
19126
|
+
];
|
|
19127
|
+
function LegalDisclaimer({ legalAgreements, loading }) {
|
|
19128
|
+
const { colors: colors2, fonts } = useTheme();
|
|
18512
19129
|
if (loading) {
|
|
18513
19130
|
return /* @__PURE__ */ jsxs11(
|
|
18514
19131
|
"div",
|
|
@@ -18552,78 +19169,6 @@ function LegalDisclaimer({ legalAgreements, loading, colors: colors2, fonts }) {
|
|
|
18552
19169
|
}
|
|
18553
19170
|
);
|
|
18554
19171
|
}
|
|
18555
|
-
function isGuestLimitError(err) {
|
|
18556
|
-
const message = err instanceof Error ? err.message : String(err ?? "");
|
|
18557
|
-
if (/coinbase_onramp_guest_limit_reached/i.test(message)) return true;
|
|
18558
|
-
if (/guest_(daily_)?transaction_(count|limit)/i.test(message)) return true;
|
|
18559
|
-
return false;
|
|
18560
|
-
}
|
|
18561
|
-
function prettifyVerificationError(message) {
|
|
18562
|
-
if (/\b429\b|too many requests|rate.?limit|throttle/i.test(message)) {
|
|
18563
|
-
return "Too many attempts. Please wait a few minutes and try again.";
|
|
18564
|
-
}
|
|
18565
|
-
if (/network|failed to fetch|abort/i.test(message)) {
|
|
18566
|
-
return "Network error. Check your connection and try again.";
|
|
18567
|
-
}
|
|
18568
|
-
if (/voip|not a valid US|not a cell/i.test(message)) {
|
|
18569
|
-
return "We can only verify real US cell phones (not VoIP). Try a different number.";
|
|
18570
|
-
}
|
|
18571
|
-
return message;
|
|
18572
|
-
}
|
|
18573
|
-
var FALLBACK_AGREEMENTS = [
|
|
18574
|
-
{
|
|
18575
|
-
key: "guest_checkout_terms",
|
|
18576
|
-
name: "Guest Checkout Terms of Service",
|
|
18577
|
-
url: "https://www.coinbase.com/legal/cb-pay/onramp-guest-checkout-terms"
|
|
18578
|
-
},
|
|
18579
|
-
{
|
|
18580
|
-
key: "user_agreement",
|
|
18581
|
-
name: "User Agreement",
|
|
18582
|
-
url: "https://www.coinbase.com/legal/user_agreement"
|
|
18583
|
-
},
|
|
18584
|
-
{
|
|
18585
|
-
key: "privacy_policy",
|
|
18586
|
-
name: "Privacy Policy",
|
|
18587
|
-
url: "https://www.coinbase.com/legal/privacy"
|
|
18588
|
-
}
|
|
18589
|
-
];
|
|
18590
|
-
var POPUP_W = 500;
|
|
18591
|
-
var POPUP_H = 700;
|
|
18592
|
-
function openCoinbasePaymentPopup(url) {
|
|
18593
|
-
if (typeof window === "undefined") return null;
|
|
18594
|
-
const screenW = window.screen.availWidth ?? window.innerWidth;
|
|
18595
|
-
const screenH = window.screen.availHeight ?? window.innerHeight;
|
|
18596
|
-
const left = Math.max(0, Math.round((screenW - POPUP_W) / 2));
|
|
18597
|
-
const top = Math.max(0, Math.round((screenH - POPUP_H) / 2));
|
|
18598
|
-
return window.open(
|
|
18599
|
-
url,
|
|
18600
|
-
"unifold_coinbase_apple_pay",
|
|
18601
|
-
`popup,width=${POPUP_W},height=${POPUP_H},left=${left},top=${top}`
|
|
18602
|
-
);
|
|
18603
|
-
}
|
|
18604
|
-
function destinationChainNameFor(chainType, chainId) {
|
|
18605
|
-
if (chainType === "solana") return "solana";
|
|
18606
|
-
if (chainType === "bitcoin") return "bitcoin";
|
|
18607
|
-
if (chainType === "ethereum") {
|
|
18608
|
-
switch (chainId) {
|
|
18609
|
-
case "1":
|
|
18610
|
-
return "ethereum";
|
|
18611
|
-
case "8453":
|
|
18612
|
-
return "base";
|
|
18613
|
-
case "137":
|
|
18614
|
-
return "polygon";
|
|
18615
|
-
case "43114":
|
|
18616
|
-
return "avalanche";
|
|
18617
|
-
case "42161":
|
|
18618
|
-
return "arbitrum";
|
|
18619
|
-
case "10":
|
|
18620
|
-
return "optimism";
|
|
18621
|
-
default:
|
|
18622
|
-
return null;
|
|
18623
|
-
}
|
|
18624
|
-
}
|
|
18625
|
-
return null;
|
|
18626
|
-
}
|
|
18627
19172
|
var t2 = i18n2.payWithExchange;
|
|
18628
19173
|
function PayWithExchange({
|
|
18629
19174
|
userId,
|
|
@@ -18921,7 +19466,7 @@ function QRCodeSkeleton({ size: size4 = 180, darkMode = false }) {
|
|
|
18921
19466
|
const spacing = size4 / gridCount;
|
|
18922
19467
|
const fillColor = darkMode ? "rgba(255,255,255,0.10)" : "rgba(0,0,0,0.08)";
|
|
18923
19468
|
const cornerColor = darkMode ? "rgba(255,255,255,0.14)" : "rgba(0,0,0,0.12)";
|
|
18924
|
-
const dots =
|
|
19469
|
+
const dots = useMemo42(() => {
|
|
18925
19470
|
const result = [];
|
|
18926
19471
|
const cornerSize = 7;
|
|
18927
19472
|
const centerStart = Math.floor(gridCount / 2) - 2;
|
|
@@ -19021,7 +19566,7 @@ function useIsMobileViewport() {
|
|
|
19021
19566
|
return isMobile;
|
|
19022
19567
|
}
|
|
19023
19568
|
function useCashAppLimits({ publishableKey, currency = "usd" }) {
|
|
19024
|
-
return
|
|
19569
|
+
return useQuery6({
|
|
19025
19570
|
queryKey: ["unifold", "cashAppLimits", currency, publishableKey],
|
|
19026
19571
|
queryFn: () => getCashAppLimits(currency, publishableKey),
|
|
19027
19572
|
enabled: !!publishableKey,
|
|
@@ -19534,43 +20079,6 @@ function PayWithCashApp({
|
|
|
19534
20079
|
}
|
|
19535
20080
|
return null;
|
|
19536
20081
|
}
|
|
19537
|
-
function useDefaultOnrampToken({
|
|
19538
|
-
publishableKey,
|
|
19539
|
-
tokenAddress,
|
|
19540
|
-
chainId,
|
|
19541
|
-
chainType,
|
|
19542
|
-
countryCode,
|
|
19543
|
-
subdivisionCode,
|
|
19544
|
-
enabled = true
|
|
19545
|
-
}) {
|
|
19546
|
-
const { data: defaultToken, isLoading } = useQuery6({
|
|
19547
|
-
queryKey: [
|
|
19548
|
-
"unifold",
|
|
19549
|
-
"defaultOnrampToken",
|
|
19550
|
-
publishableKey,
|
|
19551
|
-
tokenAddress,
|
|
19552
|
-
chainId,
|
|
19553
|
-
chainType,
|
|
19554
|
-
countryCode,
|
|
19555
|
-
subdivisionCode
|
|
19556
|
-
],
|
|
19557
|
-
queryFn: () => getDefaultOnrampToken(
|
|
19558
|
-
{
|
|
19559
|
-
token_address: tokenAddress,
|
|
19560
|
-
chain_id: chainId,
|
|
19561
|
-
chain_type: chainType,
|
|
19562
|
-
country_code: countryCode,
|
|
19563
|
-
subdivision_code: subdivisionCode
|
|
19564
|
-
},
|
|
19565
|
-
publishableKey
|
|
19566
|
-
),
|
|
19567
|
-
enabled: enabled && !!tokenAddress && !!chainId && !!chainType,
|
|
19568
|
-
staleTime: 1e3 * 60 * 60,
|
|
19569
|
-
refetchOnMount: false,
|
|
19570
|
-
refetchOnWindowFocus: false
|
|
19571
|
-
});
|
|
19572
|
-
return { defaultToken, isLoading };
|
|
19573
|
-
}
|
|
19574
20082
|
function useBankTransferProviders({
|
|
19575
20083
|
publishableKey,
|
|
19576
20084
|
enabled = true,
|
|
@@ -19649,7 +20157,7 @@ function BankTransfer({
|
|
|
19649
20157
|
countryCode: userIpInfo?.alpha2
|
|
19650
20158
|
});
|
|
19651
20159
|
const providers = providersResponse?.data ?? [];
|
|
19652
|
-
const pollingWalletId =
|
|
20160
|
+
const pollingWalletId = useMemo52(() => {
|
|
19653
20161
|
if (!defaultToken) return void 0;
|
|
19654
20162
|
return getWalletByChainType(
|
|
19655
20163
|
wallets,
|
|
@@ -19670,7 +20178,7 @@ function BankTransfer({
|
|
|
19670
20178
|
const currencySymbol = getCurrencySymbol2(sourceCurrency);
|
|
19671
20179
|
const parsedAmount = parseFloat(amount);
|
|
19672
20180
|
const amountValid = !!amount && Number.isFinite(parsedAmount) && parsedAmount >= MIN_AMOUNT;
|
|
19673
|
-
const displayTokenSymbol =
|
|
20181
|
+
const displayTokenSymbol = useMemo52(
|
|
19674
20182
|
() => destinationTokenSymbol?.toUpperCase() ?? defaultToken?.destination_token_metadata?.symbol?.toUpperCase() ?? defaultToken?.destination_currency?.toUpperCase() ?? "USDC",
|
|
19675
20183
|
[destinationTokenSymbol, defaultToken]
|
|
19676
20184
|
);
|
|
@@ -23645,16 +24153,114 @@ function AmexIcon({ size: size4 = 24 }) {
|
|
|
23645
24153
|
)
|
|
23646
24154
|
] });
|
|
23647
24155
|
}
|
|
24156
|
+
function ApplePayIcon({ size: size4 = 24, color = "#000" }) {
|
|
24157
|
+
const h = size4 * 0.62;
|
|
24158
|
+
const w = h * (512 / 210.2);
|
|
24159
|
+
return /* @__PURE__ */ jsx43("svg", { width: w, height: h, viewBox: "0 0 512 210.2", fill: "none", children: /* @__PURE__ */ jsx43(
|
|
24160
|
+
"path",
|
|
24161
|
+
{
|
|
24162
|
+
fill: color,
|
|
24163
|
+
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"
|
|
24164
|
+
}
|
|
24165
|
+
) });
|
|
24166
|
+
}
|
|
24167
|
+
function GooglePayIcon({ size: size4 = 24, color = "#202124" }) {
|
|
24168
|
+
const h = size4 * 0.62;
|
|
24169
|
+
const w = h * (80 / 38.1);
|
|
24170
|
+
return /* @__PURE__ */ jsxs40("svg", { width: w, height: h, viewBox: "0 0 80 38.1", fill: "none", children: [
|
|
24171
|
+
/* @__PURE__ */ jsx43(
|
|
24172
|
+
"path",
|
|
24173
|
+
{
|
|
24174
|
+
fill: color,
|
|
24175
|
+
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"
|
|
24176
|
+
}
|
|
24177
|
+
),
|
|
24178
|
+
/* @__PURE__ */ jsx43(
|
|
24179
|
+
"path",
|
|
24180
|
+
{
|
|
24181
|
+
fill: color,
|
|
24182
|
+
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"
|
|
24183
|
+
}
|
|
24184
|
+
),
|
|
24185
|
+
/* @__PURE__ */ jsx43(
|
|
24186
|
+
"path",
|
|
24187
|
+
{
|
|
24188
|
+
fill: color,
|
|
24189
|
+
d: "M80,13.3l-9.9,22.7h-3l3.7-7.9l-6.5-14.7h3.2l4.7,11.3h0.1l4.6-11.3H80z"
|
|
24190
|
+
}
|
|
24191
|
+
),
|
|
24192
|
+
/* @__PURE__ */ jsx43(
|
|
24193
|
+
"path",
|
|
24194
|
+
{
|
|
24195
|
+
fill: "#4285F4",
|
|
24196
|
+
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"
|
|
24197
|
+
}
|
|
24198
|
+
),
|
|
24199
|
+
/* @__PURE__ */ jsx43(
|
|
24200
|
+
"path",
|
|
24201
|
+
{
|
|
24202
|
+
fill: "#34A853",
|
|
24203
|
+
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"
|
|
24204
|
+
}
|
|
24205
|
+
),
|
|
24206
|
+
/* @__PURE__ */ jsx43(
|
|
24207
|
+
"path",
|
|
24208
|
+
{
|
|
24209
|
+
fill: "#FBBC04",
|
|
24210
|
+
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"
|
|
24211
|
+
}
|
|
24212
|
+
),
|
|
24213
|
+
/* @__PURE__ */ jsx43(
|
|
24214
|
+
"path",
|
|
24215
|
+
{
|
|
24216
|
+
fill: "#EA4335",
|
|
24217
|
+
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"
|
|
24218
|
+
}
|
|
24219
|
+
)
|
|
24220
|
+
] });
|
|
24221
|
+
}
|
|
23648
24222
|
function GenericCardIcon({ size: size4 = 24, color = "#888" }) {
|
|
23649
24223
|
return /* @__PURE__ */ jsx43(CreditCard, { width: size4 * 0.8, height: size4 * 0.8, style: { color }, strokeWidth: 1.5 });
|
|
23650
24224
|
}
|
|
24225
|
+
function parseColor(input) {
|
|
24226
|
+
if (!input) return null;
|
|
24227
|
+
const s = input.trim();
|
|
24228
|
+
if (s.startsWith("#")) {
|
|
24229
|
+
let hex = s.slice(1);
|
|
24230
|
+
if (hex.length === 3)
|
|
24231
|
+
hex = hex.split("").map((c) => c + c).join("");
|
|
24232
|
+
if (hex.length !== 6) return null;
|
|
24233
|
+
const n = parseInt(hex, 16);
|
|
24234
|
+
if (Number.isNaN(n)) return null;
|
|
24235
|
+
return [n >> 16 & 255, n >> 8 & 255, n & 255];
|
|
24236
|
+
}
|
|
24237
|
+
const m = s.match(/rgba?\(([^)]+)\)/i);
|
|
24238
|
+
if (m) {
|
|
24239
|
+
const parts = m[1].split(",").map((p) => parseFloat(p));
|
|
24240
|
+
if (parts.length >= 3 && parts.every((p) => !Number.isNaN(p)))
|
|
24241
|
+
return [parts[0], parts[1], parts[2]];
|
|
24242
|
+
}
|
|
24243
|
+
return null;
|
|
24244
|
+
}
|
|
24245
|
+
function monochromeOn(background) {
|
|
24246
|
+
const rgb = parseColor(background);
|
|
24247
|
+
if (!rgb) return "#000000";
|
|
24248
|
+
const [r2, g, b] = rgb;
|
|
24249
|
+
const luminance = (0.299 * r2 + 0.587 * g + 0.114 * b) / 255;
|
|
24250
|
+
return luminance > 0.6 ? "#000000" : "#FFFFFF";
|
|
24251
|
+
}
|
|
23651
24252
|
function CardBrandIcon({
|
|
23652
24253
|
brand,
|
|
23653
24254
|
size: size4 = 24,
|
|
23654
|
-
fallbackColor = "#888"
|
|
24255
|
+
fallbackColor = "#888",
|
|
24256
|
+
monochromeColor = "#000000"
|
|
23655
24257
|
}) {
|
|
23656
24258
|
if (!brand) return /* @__PURE__ */ jsx43(GenericCardIcon, { size: size4, color: fallbackColor });
|
|
23657
24259
|
const lower = brand.toLowerCase();
|
|
24260
|
+
if (lower.includes("apple_pay") || lower.includes("apple pay") || lower === "applepay")
|
|
24261
|
+
return /* @__PURE__ */ jsx43(ApplePayIcon, { size: size4, color: monochromeColor });
|
|
24262
|
+
if (lower.includes("google_pay") || lower.includes("google pay") || lower === "googlepay")
|
|
24263
|
+
return /* @__PURE__ */ jsx43(GooglePayIcon, { size: size4, color: monochromeColor === "#FFFFFF" ? "#FFFFFF" : "#202124" });
|
|
23658
24264
|
if (lower.includes("visa")) return /* @__PURE__ */ jsx43(VisaIcon, { size: size4 });
|
|
23659
24265
|
if (lower.includes("mastercard") || lower.includes("master"))
|
|
23660
24266
|
return /* @__PURE__ */ jsx43(MastercardIcon, { size: size4 });
|
|
@@ -23663,17 +24269,28 @@ function CardBrandIcon({
|
|
|
23663
24269
|
}
|
|
23664
24270
|
function formatPaymentToken(token) {
|
|
23665
24271
|
if (token.card) {
|
|
23666
|
-
const
|
|
24272
|
+
const cardBrand = token.card.brand ?? "Card";
|
|
24273
|
+
const last4 = token.card.last4;
|
|
24274
|
+
const walletType = token.card.wallet?.type;
|
|
24275
|
+
if (walletType === "apple_pay" || walletType === "google_pay") {
|
|
24276
|
+
const funding = token.card.funding ? capitalize(token.card.funding) : null;
|
|
24277
|
+
return {
|
|
24278
|
+
label: last4 ? `${capitalize(cardBrand)} \u2022\u2022\u2022\u2022 ${last4}` : capitalize(cardBrand),
|
|
24279
|
+
sublabel: funding ?? "",
|
|
24280
|
+
brand: walletType
|
|
24281
|
+
};
|
|
24282
|
+
}
|
|
23667
24283
|
return {
|
|
23668
|
-
label: `${capitalize(
|
|
24284
|
+
label: `${capitalize(cardBrand)} \u2022\u2022\u2022\u2022 ${last4}`,
|
|
23669
24285
|
sublabel: `${capitalize(token.card.funding ?? "card")} \xB7 Expires ${token.card.exp_month}/${token.card.exp_year}`,
|
|
23670
|
-
brand
|
|
24286
|
+
brand: cardBrand
|
|
23671
24287
|
};
|
|
23672
24288
|
}
|
|
23673
24289
|
if (token.us_bank_account) {
|
|
24290
|
+
const accountType = token.us_bank_account.account_type;
|
|
23674
24291
|
return {
|
|
23675
24292
|
label: `${token.us_bank_account.bank_name ?? "Bank"} \u2022\u2022\u2022\u2022 ${token.us_bank_account.last4}`,
|
|
23676
|
-
sublabel: "Bank account"
|
|
24293
|
+
sublabel: accountType ? `${capitalize(accountType)} account` : "Bank account"
|
|
23677
24294
|
};
|
|
23678
24295
|
}
|
|
23679
24296
|
return { label: "Payment method", sublabel: token.type };
|
|
@@ -23681,59 +24298,82 @@ function formatPaymentToken(token) {
|
|
|
23681
24298
|
function capitalize(s) {
|
|
23682
24299
|
return s.charAt(0).toUpperCase() + s.slice(1);
|
|
23683
24300
|
}
|
|
23684
|
-
function useStripeOnramp(stripePublishableKey) {
|
|
24301
|
+
function useStripeOnramp(stripePublishableKey, isDark = false) {
|
|
23685
24302
|
const [coordinator, setCoordinator] = useState282(null);
|
|
23686
24303
|
const [isLoading, setIsLoading] = useState282(false);
|
|
23687
24304
|
const [error, setError] = useState282(null);
|
|
23688
24305
|
const coordinatorRef = useRef72(null);
|
|
23689
|
-
const
|
|
23690
|
-
|
|
23691
|
-
|
|
23692
|
-
|
|
23693
|
-
|
|
23694
|
-
|
|
23695
|
-
|
|
23696
|
-
|
|
23697
|
-
|
|
23698
|
-
|
|
23699
|
-
);
|
|
23700
|
-
|
|
23701
|
-
|
|
23702
|
-
|
|
23703
|
-
|
|
23704
|
-
|
|
23705
|
-
|
|
23706
|
-
|
|
23707
|
-
|
|
23708
|
-
|
|
23709
|
-
|
|
23710
|
-
|
|
23711
|
-
|
|
23712
|
-
|
|
23713
|
-
)
|
|
23714
|
-
|
|
23715
|
-
|
|
23716
|
-
|
|
23717
|
-
|
|
23718
|
-
|
|
23719
|
-
|
|
23720
|
-
|
|
23721
|
-
|
|
23722
|
-
|
|
23723
|
-
|
|
23724
|
-
|
|
23725
|
-
|
|
23726
|
-
|
|
23727
|
-
|
|
23728
|
-
|
|
23729
|
-
|
|
23730
|
-
|
|
23731
|
-
|
|
24306
|
+
const coordinatorThemeRef = useRef72(null);
|
|
24307
|
+
const initPromiseRef = useRef72(null);
|
|
24308
|
+
const isDarkRef = useRef72(isDark);
|
|
24309
|
+
isDarkRef.current = isDark;
|
|
24310
|
+
const initialize = useCallback32(() => {
|
|
24311
|
+
if (coordinatorRef.current) return Promise.resolve(coordinatorRef.current);
|
|
24312
|
+
if (initPromiseRef.current) return initPromiseRef.current;
|
|
24313
|
+
if (!stripePublishableKey) return Promise.resolve(null);
|
|
24314
|
+
const theme = isDarkRef.current;
|
|
24315
|
+
const promise = (async () => {
|
|
24316
|
+
setIsLoading(true);
|
|
24317
|
+
setError(null);
|
|
24318
|
+
try {
|
|
24319
|
+
console.log("[PayWithStripeLink] Importing @stripe/crypto...");
|
|
24320
|
+
const { loadCryptoOnrampAndInitialize } = await import(
|
|
24321
|
+
/* @vite-ignore */
|
|
24322
|
+
"@stripe/crypto"
|
|
24323
|
+
);
|
|
24324
|
+
console.log(
|
|
24325
|
+
"[PayWithStripeLink] @stripe/crypto imported, initializing with key:",
|
|
24326
|
+
stripePublishableKey?.slice(0, 12) + "..."
|
|
24327
|
+
);
|
|
24328
|
+
const initPromise = loadCryptoOnrampAndInitialize(stripePublishableKey, {
|
|
24329
|
+
theme: theme ? "night" : "stripe"
|
|
24330
|
+
});
|
|
24331
|
+
const timeoutPromise = new Promise(
|
|
24332
|
+
(_, reject) => setTimeout(
|
|
24333
|
+
() => reject(
|
|
24334
|
+
new Error(
|
|
24335
|
+
"Stripe SDK initialization timed out after 15 seconds. Check that your Stripe account has the Crypto Onramp feature enabled."
|
|
24336
|
+
)
|
|
24337
|
+
),
|
|
24338
|
+
15e3
|
|
24339
|
+
)
|
|
24340
|
+
);
|
|
24341
|
+
const instance = await Promise.race([initPromise, timeoutPromise]);
|
|
24342
|
+
if (!instance) {
|
|
24343
|
+
throw new Error("Stripe SDK returned null.");
|
|
24344
|
+
}
|
|
24345
|
+
console.log("[PayWithStripeLink] Stripe SDK initialized successfully");
|
|
24346
|
+
coordinatorRef.current = instance;
|
|
24347
|
+
coordinatorThemeRef.current = theme;
|
|
24348
|
+
setCoordinator(instance);
|
|
24349
|
+
return coordinatorRef.current;
|
|
24350
|
+
} catch (err) {
|
|
24351
|
+
const raw = err instanceof Error ? err.message : String(err);
|
|
24352
|
+
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}`;
|
|
24353
|
+
setError(msg);
|
|
24354
|
+
console.error("[PayWithStripeLink]", msg);
|
|
24355
|
+
return null;
|
|
24356
|
+
} finally {
|
|
24357
|
+
setIsLoading(false);
|
|
24358
|
+
initPromiseRef.current = null;
|
|
24359
|
+
}
|
|
24360
|
+
})();
|
|
24361
|
+
initPromiseRef.current = promise;
|
|
24362
|
+
return promise;
|
|
23732
24363
|
}, [stripePublishableKey]);
|
|
24364
|
+
useEffect232(() => {
|
|
24365
|
+
if (!coordinatorRef.current) return;
|
|
24366
|
+
if (coordinatorThemeRef.current === isDark) return;
|
|
24367
|
+
coordinatorRef.current.destroy();
|
|
24368
|
+
coordinatorRef.current = null;
|
|
24369
|
+
coordinatorThemeRef.current = null;
|
|
24370
|
+
setCoordinator(null);
|
|
24371
|
+
}, [isDark, coordinator]);
|
|
23733
24372
|
useEffect232(() => {
|
|
23734
24373
|
return () => {
|
|
23735
24374
|
coordinatorRef.current?.destroy();
|
|
23736
24375
|
coordinatorRef.current = null;
|
|
24376
|
+
coordinatorThemeRef.current = null;
|
|
23737
24377
|
};
|
|
23738
24378
|
}, []);
|
|
23739
24379
|
return { coordinator, isLoading, error, initialize };
|
|
@@ -23884,7 +24524,7 @@ function PayWithStripeLink({
|
|
|
23884
24524
|
onDepositSuccess,
|
|
23885
24525
|
onDepositError
|
|
23886
24526
|
}) {
|
|
23887
|
-
const { colors: colors2, fonts, components } = useTheme();
|
|
24527
|
+
const { colors: colors2, fonts, components, isDark } = useTheme();
|
|
23888
24528
|
const [step, setStepInternal] = useState292(controlledStep ?? "amount");
|
|
23889
24529
|
const setStep = useCallback42(
|
|
23890
24530
|
(s) => {
|
|
@@ -23893,6 +24533,8 @@ function PayWithStripeLink({
|
|
|
23893
24533
|
},
|
|
23894
24534
|
[onStepChange]
|
|
23895
24535
|
);
|
|
24536
|
+
const stepRef = useRef82(step);
|
|
24537
|
+
stepRef.current = step;
|
|
23896
24538
|
useEffect242(() => {
|
|
23897
24539
|
if (controlledStep && controlledStep !== step) {
|
|
23898
24540
|
setStepInternal(controlledStep);
|
|
@@ -23960,7 +24602,7 @@ function PayWithStripeLink({
|
|
|
23960
24602
|
isLoading: sdkLoading,
|
|
23961
24603
|
error: sdkError,
|
|
23962
24604
|
initialize
|
|
23963
|
-
} = useStripeOnramp(resolvedStripeKey);
|
|
24605
|
+
} = useStripeOnramp(resolvedStripeKey, isDark);
|
|
23964
24606
|
useEffect242(() => {
|
|
23965
24607
|
if (step === "auth") {
|
|
23966
24608
|
console.log("[PayWithStripeLink] Auth step state:", {
|
|
@@ -23983,6 +24625,9 @@ function PayWithStripeLink({
|
|
|
23983
24625
|
const [errorReturnStep, setErrorReturnStep] = useState292("email");
|
|
23984
24626
|
const [authIntentId, setAuthIntentId] = useState292(null);
|
|
23985
24627
|
const sdkAuthenticatedRef = useRef82(false);
|
|
24628
|
+
const everAuthenticatedRef = useRef82(false);
|
|
24629
|
+
const reauthReturnStepRef = useRef82(null);
|
|
24630
|
+
const attemptedWalletReauthRef = useRef82(false);
|
|
23986
24631
|
const pendingAddPaymentRef = useRef82(false);
|
|
23987
24632
|
const autoOpenedAddPaymentRef = useRef82(false);
|
|
23988
24633
|
const checkoutGenRef = useRef82(0);
|
|
@@ -24181,6 +24826,7 @@ function PayWithStripeLink({
|
|
|
24181
24826
|
if (step === "auth" && (pendingAddPaymentRef.current || !!accessTokenRef.current)) {
|
|
24182
24827
|
pendingAddPaymentRef.current = false;
|
|
24183
24828
|
autoOpenedAddPaymentRef.current = false;
|
|
24829
|
+
reauthReturnStepRef.current = null;
|
|
24184
24830
|
setError(null);
|
|
24185
24831
|
setStep("amount");
|
|
24186
24832
|
return true;
|
|
@@ -24198,17 +24844,34 @@ function PayWithStripeLink({
|
|
|
24198
24844
|
);
|
|
24199
24845
|
const [selectedPaymentToken, setSelectedPaymentToken] = useState292(null);
|
|
24200
24846
|
const [paymentDisplay, setPaymentDisplay] = useState292(null);
|
|
24847
|
+
const selectedTokenSingleUseRef = useRef82(false);
|
|
24201
24848
|
const selectPaymentToken = useCallback42(
|
|
24202
24849
|
(token) => {
|
|
24850
|
+
selectedTokenSingleUseRef.current = !!token.singleUse;
|
|
24203
24851
|
setSelectedPaymentToken(token.id);
|
|
24204
24852
|
setPaymentDisplay(
|
|
24205
24853
|
token.label ? { label: token.label, sublabel: token.sublabel, brand: token.brand } : null
|
|
24206
24854
|
);
|
|
24207
24855
|
setStoredSelectedTokenState(token);
|
|
24208
|
-
if (customerId) setStoredSelectedToken(customerId, token);
|
|
24856
|
+
if (customerId && !token.singleUse) setStoredSelectedToken(customerId, token);
|
|
24209
24857
|
},
|
|
24210
24858
|
[customerId]
|
|
24211
24859
|
);
|
|
24860
|
+
const clearSelectedPaymentToken = useCallback42(() => {
|
|
24861
|
+
selectedTokenSingleUseRef.current = false;
|
|
24862
|
+
const persisted = customerId ? getStoredSelectedToken(customerId) : null;
|
|
24863
|
+
if (persisted && !persisted.singleUse) {
|
|
24864
|
+
setSelectedPaymentToken(persisted.id);
|
|
24865
|
+
setPaymentDisplay(
|
|
24866
|
+
persisted.label ? { label: persisted.label, sublabel: persisted.sublabel, brand: persisted.brand } : null
|
|
24867
|
+
);
|
|
24868
|
+
setStoredSelectedTokenState(persisted);
|
|
24869
|
+
} else {
|
|
24870
|
+
setSelectedPaymentToken(null);
|
|
24871
|
+
setPaymentDisplay(null);
|
|
24872
|
+
setStoredSelectedTokenState(null);
|
|
24873
|
+
}
|
|
24874
|
+
}, [customerId]);
|
|
24212
24875
|
const displayPaymentTokens = (() => {
|
|
24213
24876
|
const apiDisplay = paymentTokens.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) }));
|
|
24214
24877
|
if (storedSelectedToken && !paymentTokens.some((t13) => t13.id === storedSelectedToken.id)) {
|
|
@@ -24447,6 +25110,10 @@ function PayWithStripeLink({
|
|
|
24447
25110
|
if (!resolvedStripeKey) return;
|
|
24448
25111
|
initialize();
|
|
24449
25112
|
}, [coordinator, sdkLoading, sdkError, resolvedStripeKey, initialize]);
|
|
25113
|
+
useEffect242(() => {
|
|
25114
|
+
sdkAuthenticatedRef.current = false;
|
|
25115
|
+
attemptedWalletReauthRef.current = false;
|
|
25116
|
+
}, [coordinator]);
|
|
24450
25117
|
const handleAuthInterrupted = useCallback42(
|
|
24451
25118
|
(message) => {
|
|
24452
25119
|
const alreadySignedIn = !!accessTokenRef.current;
|
|
@@ -24460,6 +25127,26 @@ function PayWithStripeLink({
|
|
|
24460
25127
|
},
|
|
24461
25128
|
[emailProp, setStep]
|
|
24462
25129
|
);
|
|
25130
|
+
const reauthenticateSdk = useCallback42(async () => {
|
|
25131
|
+
const current = stepRef.current;
|
|
25132
|
+
const preAuthSteps = ["email", "register", "auth"];
|
|
25133
|
+
reauthReturnStepRef.current = preAuthSteps.includes(current) ? null : current;
|
|
25134
|
+
const knownEmail = (email || emailProp || "").trim();
|
|
25135
|
+
if (!knownEmail) {
|
|
25136
|
+
reauthReturnStepRef.current = null;
|
|
25137
|
+
setStep("email");
|
|
25138
|
+
return;
|
|
25139
|
+
}
|
|
25140
|
+
try {
|
|
25141
|
+
const authResult = await stripeCreateAuthIntent(knownEmail, publishableKey);
|
|
25142
|
+
setAuthIntentId(authResult.auth_intent_id);
|
|
25143
|
+
setStep("auth");
|
|
25144
|
+
} catch (err) {
|
|
25145
|
+
reauthReturnStepRef.current = null;
|
|
25146
|
+
setError(err instanceof Error ? err.message : "Failed to re-verify. Please try again.");
|
|
25147
|
+
setStep("email");
|
|
25148
|
+
}
|
|
25149
|
+
}, [email, emailProp, publishableKey]);
|
|
24463
25150
|
useEffect242(() => {
|
|
24464
25151
|
if (step !== "auth" || !coordinator || !authIntentId) return;
|
|
24465
25152
|
let mounted = true;
|
|
@@ -24470,6 +25157,7 @@ function PayWithStripeLink({
|
|
|
24470
25157
|
if (result.result === "success" && result.crypto_customer_id) {
|
|
24471
25158
|
setCustomerId(result.crypto_customer_id);
|
|
24472
25159
|
sdkAuthenticatedRef.current = true;
|
|
25160
|
+
everAuthenticatedRef.current = true;
|
|
24473
25161
|
const tokens = await stripeExchangeTokens(authIntentId, publishableKey);
|
|
24474
25162
|
setOauthToken(tokens.access_token);
|
|
24475
25163
|
const refresh = extractRefreshToken(tokens);
|
|
@@ -24483,16 +25171,22 @@ function PayWithStripeLink({
|
|
|
24483
25171
|
tokens.expires_in ?? 3600,
|
|
24484
25172
|
email.trim()
|
|
24485
25173
|
);
|
|
25174
|
+
const resumeStep = reauthReturnStepRef.current;
|
|
25175
|
+
reauthReturnStepRef.current = null;
|
|
24486
25176
|
if (pendingAddPaymentRef.current) {
|
|
24487
25177
|
setStep("payment");
|
|
25178
|
+
} else if (resumeStep) {
|
|
25179
|
+
setStep(resumeStep);
|
|
24488
25180
|
} else {
|
|
24489
25181
|
setStep("kyc");
|
|
24490
25182
|
}
|
|
24491
25183
|
} else if (result.result === "abandoned") {
|
|
24492
25184
|
pendingAddPaymentRef.current = false;
|
|
25185
|
+
reauthReturnStepRef.current = null;
|
|
24493
25186
|
handleAuthInterrupted("Verification was cancelled.");
|
|
24494
25187
|
} else if (result.result === "declined") {
|
|
24495
25188
|
pendingAddPaymentRef.current = false;
|
|
25189
|
+
reauthReturnStepRef.current = null;
|
|
24496
25190
|
handleAuthInterrupted("You must consent to continue.");
|
|
24497
25191
|
}
|
|
24498
25192
|
});
|
|
@@ -24504,6 +25198,7 @@ function PayWithStripeLink({
|
|
|
24504
25198
|
}
|
|
24505
25199
|
} catch (err) {
|
|
24506
25200
|
if (!mounted) return;
|
|
25201
|
+
reauthReturnStepRef.current = null;
|
|
24507
25202
|
const msg = err instanceof Error ? err.message : "Verification was cancelled.";
|
|
24508
25203
|
handleAuthInterrupted(msg);
|
|
24509
25204
|
}
|
|
@@ -24605,6 +25300,10 @@ function PayWithStripeLink({
|
|
|
24605
25300
|
};
|
|
24606
25301
|
const handleKycSubmit = async () => {
|
|
24607
25302
|
if (!coordinator) return;
|
|
25303
|
+
if (!sdkAuthenticatedRef.current) {
|
|
25304
|
+
await reauthenticateSdk();
|
|
25305
|
+
return;
|
|
25306
|
+
}
|
|
24608
25307
|
let kycInfo;
|
|
24609
25308
|
if (kycFormMode === "address") {
|
|
24610
25309
|
if (!kycForm.givenName.trim() || !kycForm.surname.trim()) {
|
|
@@ -24664,6 +25363,10 @@ function PayWithStripeLink({
|
|
|
24664
25363
|
let mounted = true;
|
|
24665
25364
|
const verify = async () => {
|
|
24666
25365
|
try {
|
|
25366
|
+
if (!sdkAuthenticatedRef.current) {
|
|
25367
|
+
await reauthenticateSdk();
|
|
25368
|
+
return;
|
|
25369
|
+
}
|
|
24667
25370
|
const result = await coordinator.verifyDocuments();
|
|
24668
25371
|
if (!mounted) return;
|
|
24669
25372
|
const outcome = typeof result === "string" ? result : result?.result;
|
|
@@ -24683,7 +25386,7 @@ function PayWithStripeLink({
|
|
|
24683
25386
|
return () => {
|
|
24684
25387
|
mounted = false;
|
|
24685
25388
|
};
|
|
24686
|
-
}, [step, coordinator]);
|
|
25389
|
+
}, [step, coordinator, reauthenticateSdk]);
|
|
24687
25390
|
useEffect242(() => {
|
|
24688
25391
|
if (step !== "wallet" || !oauthToken || !customerId) return;
|
|
24689
25392
|
let mounted = true;
|
|
@@ -24709,6 +25412,10 @@ function PayWithStripeLink({
|
|
|
24709
25412
|
if (!coordinator) {
|
|
24710
25413
|
return;
|
|
24711
25414
|
}
|
|
25415
|
+
if (!sdkAuthenticatedRef.current) {
|
|
25416
|
+
await reauthenticateSdk();
|
|
25417
|
+
return;
|
|
25418
|
+
}
|
|
24712
25419
|
await coordinator.registerWalletAddress(onrampWalletAddress, network);
|
|
24713
25420
|
}
|
|
24714
25421
|
if (mounted) setRegisteredWalletKey(walletKeyFor(onrampWalletAddress));
|
|
@@ -24725,7 +25432,15 @@ function PayWithStripeLink({
|
|
|
24725
25432
|
return () => {
|
|
24726
25433
|
mounted = false;
|
|
24727
25434
|
};
|
|
24728
|
-
}, [
|
|
25435
|
+
}, [
|
|
25436
|
+
step,
|
|
25437
|
+
oauthToken,
|
|
25438
|
+
customerId,
|
|
25439
|
+
publishableKey,
|
|
25440
|
+
onrampWalletAddress,
|
|
25441
|
+
coordinator,
|
|
25442
|
+
reauthenticateSdk
|
|
25443
|
+
]);
|
|
24729
25444
|
useEffect242(() => {
|
|
24730
25445
|
if (step !== "amount" && step !== "review") return;
|
|
24731
25446
|
if (!customerId || !oauthToken || !onrampWalletAddress) return;
|
|
@@ -24754,6 +25469,10 @@ function PayWithStripeLink({
|
|
|
24754
25469
|
if (coordinator && sdkAuthenticatedRef.current) {
|
|
24755
25470
|
await coordinator.registerWalletAddress(onrampWalletAddress, network);
|
|
24756
25471
|
if (!cancelled) setRegisteredWalletKey(walletKeyFor(onrampWalletAddress));
|
|
25472
|
+
} else if (coordinator && everAuthenticatedRef.current && !attemptedWalletReauthRef.current) {
|
|
25473
|
+
attemptedWalletReauthRef.current = true;
|
|
25474
|
+
await reauthenticateSdk();
|
|
25475
|
+
return;
|
|
24757
25476
|
}
|
|
24758
25477
|
} catch {
|
|
24759
25478
|
}
|
|
@@ -24771,7 +25490,8 @@ function PayWithStripeLink({
|
|
|
24771
25490
|
coordinator,
|
|
24772
25491
|
stripeDestNetwork,
|
|
24773
25492
|
stripeDestChainType,
|
|
24774
|
-
publishableKey
|
|
25493
|
+
publishableKey,
|
|
25494
|
+
reauthenticateSdk
|
|
24775
25495
|
]);
|
|
24776
25496
|
useEffect242(() => {
|
|
24777
25497
|
if (step !== "payment" || !oauthToken || !customerId) return;
|
|
@@ -24868,6 +25588,32 @@ function PayWithStripeLink({
|
|
|
24868
25588
|
if (!mounted) return;
|
|
24869
25589
|
const tokenId = result.cryptoPaymentToken;
|
|
24870
25590
|
let display = null;
|
|
25591
|
+
const pmd = result.paymentMethodDetails;
|
|
25592
|
+
if (pmd) {
|
|
25593
|
+
display = formatPaymentToken(pmd);
|
|
25594
|
+
}
|
|
25595
|
+
const singleUse = pmd?.type === "card" && !!pmd.card.wallet;
|
|
25596
|
+
const applyAndAdvance = () => {
|
|
25597
|
+
selectPaymentToken({
|
|
25598
|
+
id: tokenId,
|
|
25599
|
+
label: display?.label ?? "",
|
|
25600
|
+
sublabel: display?.sublabel ?? "",
|
|
25601
|
+
brand: display?.brand,
|
|
25602
|
+
singleUse
|
|
25603
|
+
});
|
|
25604
|
+
autoOpenedAddPaymentRef.current = false;
|
|
25605
|
+
setStep("amount");
|
|
25606
|
+
};
|
|
25607
|
+
if (display) {
|
|
25608
|
+
applyAndAdvance();
|
|
25609
|
+
if (customerId && accessTokenRef.current) {
|
|
25610
|
+
stripeListPaymentTokens(customerId, accessTokenRef.current, publishableKey).then((tokens) => {
|
|
25611
|
+
if (mounted) setPaymentTokens(tokens.data);
|
|
25612
|
+
}).catch(() => {
|
|
25613
|
+
});
|
|
25614
|
+
}
|
|
25615
|
+
return;
|
|
25616
|
+
}
|
|
24871
25617
|
try {
|
|
24872
25618
|
if (customerId && accessTokenRef.current) {
|
|
24873
25619
|
const tokens = await stripeListPaymentTokens(
|
|
@@ -24875,28 +25621,15 @@ function PayWithStripeLink({
|
|
|
24875
25621
|
accessTokenRef.current,
|
|
24876
25622
|
publishableKey
|
|
24877
25623
|
);
|
|
25624
|
+
if (!mounted) return;
|
|
25625
|
+
setPaymentTokens(tokens.data);
|
|
24878
25626
|
const match = tokens.data.find((t13) => t13.id === tokenId);
|
|
24879
|
-
if (match)
|
|
24880
|
-
display = formatPaymentToken(match);
|
|
24881
|
-
setPaymentTokens(tokens.data);
|
|
24882
|
-
}
|
|
25627
|
+
if (match) display = formatPaymentToken(match);
|
|
24883
25628
|
}
|
|
24884
25629
|
} catch {
|
|
24885
25630
|
}
|
|
24886
|
-
if (!
|
|
24887
|
-
|
|
24888
|
-
if (dd?.label) {
|
|
24889
|
-
display = { label: dd.label, sublabel: dd.sublabel ?? "", brand: dd.type };
|
|
24890
|
-
}
|
|
24891
|
-
}
|
|
24892
|
-
selectPaymentToken({
|
|
24893
|
-
id: tokenId,
|
|
24894
|
-
label: display?.label ?? "",
|
|
24895
|
-
sublabel: display?.sublabel ?? "",
|
|
24896
|
-
brand: display?.brand
|
|
24897
|
-
});
|
|
24898
|
-
autoOpenedAddPaymentRef.current = false;
|
|
24899
|
-
setStep("amount");
|
|
25631
|
+
if (!mounted) return;
|
|
25632
|
+
applyAndAdvance();
|
|
24900
25633
|
}
|
|
24901
25634
|
);
|
|
24902
25635
|
if (mounted && el) {
|
|
@@ -24933,6 +25666,10 @@ function PayWithStripeLink({
|
|
|
24933
25666
|
const handleCheckout = async () => {
|
|
24934
25667
|
if (!amount || !oauthToken || !customerId || !selectedPaymentToken || !onrampWalletAddress || !isOnrampWalletRegistered || !coordinator)
|
|
24935
25668
|
return;
|
|
25669
|
+
if (!sdkAuthenticatedRef.current) {
|
|
25670
|
+
await reauthenticateSdk();
|
|
25671
|
+
return;
|
|
25672
|
+
}
|
|
24936
25673
|
const gen = ++checkoutGenRef.current;
|
|
24937
25674
|
const isStale = () => checkoutGenRef.current !== gen;
|
|
24938
25675
|
const surfaceStepUpOnAmount = (err, message, tier) => {
|
|
@@ -25044,6 +25781,7 @@ function PayWithStripeLink({
|
|
|
25044
25781
|
executionReconciledSessionRef.current = null;
|
|
25045
25782
|
setConfirmedSessionId(activeSessionId);
|
|
25046
25783
|
setSessionStatus(STRIPE_SESSION_STATUS.FULFILLMENT_PROCESSING);
|
|
25784
|
+
if (selectedTokenSingleUseRef.current) clearSelectedPaymentToken();
|
|
25047
25785
|
setStep("success");
|
|
25048
25786
|
} else if (lastError === "quote_rate_drifted" || lastError === "charged_with_expired_quote") {
|
|
25049
25787
|
setSessionForCheckout(null);
|
|
@@ -25095,6 +25833,25 @@ function PayWithStripeLink({
|
|
|
25095
25833
|
sessionForCheckoutRef.current = s;
|
|
25096
25834
|
setSessionForCheckoutState(s);
|
|
25097
25835
|
};
|
|
25836
|
+
const loadAndSelectPreferredToken = useCallback42(async () => {
|
|
25837
|
+
if (!customerId) return;
|
|
25838
|
+
try {
|
|
25839
|
+
const existing = await withTokenRefresh(
|
|
25840
|
+
(tok) => stripeListPaymentTokens(customerId, tok, publishableKey)
|
|
25841
|
+
);
|
|
25842
|
+
setPaymentTokens(existing.data);
|
|
25843
|
+
const stored = getStoredSelectedToken(customerId);
|
|
25844
|
+
const merged = [
|
|
25845
|
+
...existing.data.map((t13) => ({ id: t13.id, ...formatPaymentToken(t13) })),
|
|
25846
|
+
...stored && !existing.data.some((t13) => t13.id === stored.id) ? [stored] : []
|
|
25847
|
+
];
|
|
25848
|
+
if (merged.length > 0) {
|
|
25849
|
+
const preferred = stored && merged.find((m) => m.id === stored.id) || merged[0];
|
|
25850
|
+
selectPaymentToken(preferred);
|
|
25851
|
+
}
|
|
25852
|
+
} catch {
|
|
25853
|
+
}
|
|
25854
|
+
}, [customerId, publishableKey, selectPaymentToken, withTokenRefresh]);
|
|
25098
25855
|
const handleDone = () => {
|
|
25099
25856
|
handledTerminalSessionRef.current = null;
|
|
25100
25857
|
executionReconciledSessionRef.current = null;
|
|
@@ -25102,6 +25859,7 @@ function PayWithStripeLink({
|
|
|
25102
25859
|
setSessionStatus(null);
|
|
25103
25860
|
setSessionForCheckout(null);
|
|
25104
25861
|
setStep("amount");
|
|
25862
|
+
if (!selectedPaymentToken) void loadAndSelectPreferredToken();
|
|
25105
25863
|
};
|
|
25106
25864
|
const [quoteError, setQuoteError] = useState292(null);
|
|
25107
25865
|
const [quoteNonce, setQuoteNonce] = useState292(0);
|
|
@@ -25883,10 +26641,16 @@ function PayWithStripeLink({
|
|
|
25883
26641
|
return /* @__PURE__ */ jsxs41(
|
|
25884
26642
|
"div",
|
|
25885
26643
|
{
|
|
25886
|
-
className: "uf-flex uf-flex-col uf-py-4 uf-overflow-y-auto uf-max-h-[70vh]",
|
|
26644
|
+
className: "uf-flex uf-flex-col uf-py-4 uf-overflow-y-auto uf-overflow-x-hidden uf-max-h-[70vh]",
|
|
25887
26645
|
style: { backgroundColor: colors2.background },
|
|
25888
26646
|
children: [
|
|
25889
|
-
/* @__PURE__ */ jsx44(
|
|
26647
|
+
/* @__PURE__ */ jsx44(
|
|
26648
|
+
"div",
|
|
26649
|
+
{
|
|
26650
|
+
ref: paymentMountRef,
|
|
26651
|
+
className: "uf-w-full uf-flex-1 uf-overflow-y-auto uf-overflow-x-hidden"
|
|
26652
|
+
}
|
|
26653
|
+
),
|
|
25890
26654
|
!stripePaymentUIReady && /* @__PURE__ */ jsx44("div", { className: "uf-flex uf-items-center uf-justify-center uf-py-8", children: /* @__PURE__ */ jsx44(LoaderCircle, { className: "uf-w-8 uf-h-8 uf-animate-spin", style: { color: colors2.primary } }) }),
|
|
25891
26655
|
error && /* @__PURE__ */ jsx44(
|
|
25892
26656
|
"div",
|
|
@@ -25904,7 +26668,7 @@ function PayWithStripeLink({
|
|
|
25904
26668
|
return /* @__PURE__ */ jsxs41(
|
|
25905
26669
|
"div",
|
|
25906
26670
|
{
|
|
25907
|
-
className: "uf-flex uf-flex-col uf-py-4 uf-overflow-y-auto uf-max-h-[70vh]",
|
|
26671
|
+
className: "uf-flex uf-flex-col uf-py-4 uf-overflow-y-auto uf-overflow-x-hidden uf-max-h-[70vh]",
|
|
25908
26672
|
style: { backgroundColor: colors2.background },
|
|
25909
26673
|
children: [
|
|
25910
26674
|
displayPaymentTokens.length === 0 && !loading && /* @__PURE__ */ jsx44("div", { className: "uf-px-1 uf-mb-3 uf-text-center", children: /* @__PURE__ */ jsx44(
|
|
@@ -25941,7 +26705,8 @@ function PayWithStripeLink({
|
|
|
25941
26705
|
{
|
|
25942
26706
|
brand: display.brand,
|
|
25943
26707
|
size: 28,
|
|
25944
|
-
fallbackColor: colors2.foregroundMuted
|
|
26708
|
+
fallbackColor: colors2.foregroundMuted,
|
|
26709
|
+
monochromeColor: monochromeOn(components.card.backgroundColor)
|
|
25945
26710
|
}
|
|
25946
26711
|
)
|
|
25947
26712
|
}
|
|
@@ -26526,7 +27291,8 @@ function PayWithStripeLink({
|
|
|
26526
27291
|
{
|
|
26527
27292
|
brand: paymentDisplay.brand,
|
|
26528
27293
|
size: 20,
|
|
26529
|
-
fallbackColor: colors2.foregroundMuted
|
|
27294
|
+
fallbackColor: colors2.foregroundMuted,
|
|
27295
|
+
monochromeColor: monochromeOn(components.card.backgroundColor)
|
|
26530
27296
|
}
|
|
26531
27297
|
),
|
|
26532
27298
|
/* @__PURE__ */ jsx44(
|
|
@@ -27010,6 +27776,33 @@ function PayWithStripeLink({
|
|
|
27010
27776
|
}
|
|
27011
27777
|
return null;
|
|
27012
27778
|
}
|
|
27779
|
+
function useProjectConfig({
|
|
27780
|
+
publishableKey,
|
|
27781
|
+
enabled = true,
|
|
27782
|
+
countryCode,
|
|
27783
|
+
subdivisionCode
|
|
27784
|
+
}) {
|
|
27785
|
+
const {
|
|
27786
|
+
data: projectConfig,
|
|
27787
|
+
isLoading,
|
|
27788
|
+
error
|
|
27789
|
+
} = useQuery8({
|
|
27790
|
+
// Country is part of the key so a region change refetches the region-aware
|
|
27791
|
+
// config. Omitted when undefined so callers that don't pass a country keep
|
|
27792
|
+
// sharing the base cache entry.
|
|
27793
|
+
queryKey: countryCode ? ["unifold", "projectConfig", publishableKey, countryCode, subdivisionCode ?? null] : ["unifold", "projectConfig", publishableKey],
|
|
27794
|
+
queryFn: () => getProjectConfig(publishableKey, countryCode ? { countryCode, subdivisionCode } : void 0),
|
|
27795
|
+
enabled,
|
|
27796
|
+
// Keep the previous (e.g. no-country) config visible while the region-aware
|
|
27797
|
+
// config refetches after the country resolves, so unrelated config-driven
|
|
27798
|
+
// UI doesn't flash back to defaults.
|
|
27799
|
+
placeholderData: keepPreviousData,
|
|
27800
|
+
staleTime: 1e3 * 60 * 30,
|
|
27801
|
+
refetchOnMount: true,
|
|
27802
|
+
refetchOnWindowFocus: true
|
|
27803
|
+
});
|
|
27804
|
+
return { projectConfig, isLoading, error: error ?? null };
|
|
27805
|
+
}
|
|
27013
27806
|
function useSupportedDepositTokens(publishableKey, options) {
|
|
27014
27807
|
const hasDestination = options?.destination_token_address && options?.destination_chain_id && options?.destination_chain_type;
|
|
27015
27808
|
const filteredOptions = {
|
|
@@ -27021,7 +27814,7 @@ function useSupportedDepositTokens(publishableKey, options) {
|
|
|
27021
27814
|
...options?.product_type ? { product_type: options.product_type } : {}
|
|
27022
27815
|
};
|
|
27023
27816
|
const hasFilteredOptions = Object.keys(filteredOptions).length > 0;
|
|
27024
|
-
return
|
|
27817
|
+
return useQuery9({
|
|
27025
27818
|
queryKey: [
|
|
27026
27819
|
"unifold",
|
|
27027
27820
|
"supportedDepositTokens",
|
|
@@ -27045,7 +27838,7 @@ function useIntegrationTransferDefaultToken({
|
|
|
27045
27838
|
publishableKey,
|
|
27046
27839
|
enabled = true
|
|
27047
27840
|
}) {
|
|
27048
|
-
return
|
|
27841
|
+
return useQuery10({
|
|
27049
27842
|
queryKey: [
|
|
27050
27843
|
"unifold",
|
|
27051
27844
|
"integrationTransferDefaultToken",
|
|
@@ -27121,12 +27914,12 @@ function CoinbaseConnect({
|
|
|
27121
27914
|
destination_chain_id: destinationChainId,
|
|
27122
27915
|
destination_chain_type: destinationChainType
|
|
27123
27916
|
});
|
|
27124
|
-
const supportedSymbols =
|
|
27917
|
+
const supportedSymbols = useMemo72(() => {
|
|
27125
27918
|
const set = /* @__PURE__ */ new Set();
|
|
27126
27919
|
supportedTokensData?.data.forEach((token) => set.add(token.symbol.toLowerCase()));
|
|
27127
27920
|
return set;
|
|
27128
27921
|
}, [supportedTokensData]);
|
|
27129
|
-
const stablecoinSymbols =
|
|
27922
|
+
const stablecoinSymbols = useMemo72(() => {
|
|
27130
27923
|
const set = /* @__PURE__ */ new Set();
|
|
27131
27924
|
supportedTokensData?.data.forEach((token) => {
|
|
27132
27925
|
if (token.is_stablecoin) set.add(token.symbol.toLowerCase());
|
|
@@ -27159,12 +27952,12 @@ function CoinbaseConnect({
|
|
|
27159
27952
|
const [transferDepositWalletId, setTransferDepositWalletId] = useState30(
|
|
27160
27953
|
void 0
|
|
27161
27954
|
);
|
|
27162
|
-
const exchangeSupportedCurrencies =
|
|
27955
|
+
const exchangeSupportedCurrencies = useMemo72(() => {
|
|
27163
27956
|
const set = /* @__PURE__ */ new Set();
|
|
27164
27957
|
selectedExchange?.supported_currencies.forEach((c) => set.add(c.toLowerCase()));
|
|
27165
27958
|
return set;
|
|
27166
27959
|
}, [selectedExchange]);
|
|
27167
|
-
const defaultTokenParams =
|
|
27960
|
+
const defaultTokenParams = useMemo72(
|
|
27168
27961
|
() => selectedAsset ? {
|
|
27169
27962
|
integration_provider: IntegrationProvider.COINBASE,
|
|
27170
27963
|
source_currency: selectedAsset.currency.toLowerCase(),
|
|
@@ -27187,7 +27980,7 @@ function CoinbaseConnect({
|
|
|
27187
27980
|
params: defaultTokenParams,
|
|
27188
27981
|
publishableKey
|
|
27189
27982
|
});
|
|
27190
|
-
const defaultSourceCurrency =
|
|
27983
|
+
const defaultSourceCurrency = useMemo72(
|
|
27191
27984
|
() => resolveDefaultSourceSymbol(supportedTokensData?.data, {
|
|
27192
27985
|
defaultSourceChainType,
|
|
27193
27986
|
defaultSourceChainId,
|
|
@@ -27202,7 +27995,7 @@ function CoinbaseConnect({
|
|
|
27202
27995
|
defaultSourceSymbol
|
|
27203
27996
|
]
|
|
27204
27997
|
);
|
|
27205
|
-
const sortedHoldings =
|
|
27998
|
+
const sortedHoldings = useMemo72(() => {
|
|
27206
27999
|
const supported = [];
|
|
27207
28000
|
const unsupported = [];
|
|
27208
28001
|
holdings.forEach((account) => {
|
|
@@ -27222,7 +28015,7 @@ function CoinbaseConnect({
|
|
|
27222
28015
|
}
|
|
27223
28016
|
return [...supported, ...unsupported];
|
|
27224
28017
|
}, [holdings, supportedSymbols, exchangeSupportedCurrencies, defaultSourceCurrency]);
|
|
27225
|
-
const selectedHoldingIsSupported =
|
|
28018
|
+
const selectedHoldingIsSupported = useMemo72(() => {
|
|
27226
28019
|
if (!selectedHolding) return false;
|
|
27227
28020
|
const currencyLower = selectedHolding.currency.toLowerCase();
|
|
27228
28021
|
return (supportedSymbols.size === 0 || supportedSymbols.has(currencyLower)) && (exchangeSupportedCurrencies.size === 0 || exchangeSupportedCurrencies.has(currencyLower));
|
|
@@ -27369,7 +28162,7 @@ function CoinbaseConnect({
|
|
|
27369
28162
|
if (pollRef.current) clearInterval(pollRef.current);
|
|
27370
28163
|
};
|
|
27371
28164
|
}, []);
|
|
27372
|
-
const minDepositUsd =
|
|
28165
|
+
const minDepositUsd = useMemo72(() => {
|
|
27373
28166
|
if (!selectedAsset || !defaultTokenData) return 0;
|
|
27374
28167
|
const supportedToken = supportedTokensData?.data.find(
|
|
27375
28168
|
(t14) => t14.symbol.toLowerCase() === selectedAsset.currency.toLowerCase()
|
|
@@ -27380,7 +28173,7 @@ function CoinbaseConnect({
|
|
|
27380
28173
|
);
|
|
27381
28174
|
return matchingChain?.minimum_deposit_amount_usd ?? Math.min(...supportedToken.chains.map((c) => c.minimum_deposit_amount_usd));
|
|
27382
28175
|
}, [selectedAsset, supportedTokensData, defaultTokenData]);
|
|
27383
|
-
const estimatedProcessingTime =
|
|
28176
|
+
const estimatedProcessingTime = useMemo72(() => {
|
|
27384
28177
|
if (!selectedAsset || !defaultTokenData) return null;
|
|
27385
28178
|
const supportedToken = supportedTokensData?.data.find(
|
|
27386
28179
|
(t14) => t14.symbol.toLowerCase() === selectedAsset.currency.toLowerCase()
|
|
@@ -29022,7 +29815,7 @@ function useExchanges({
|
|
|
29022
29815
|
publishableKey,
|
|
29023
29816
|
enabled = true
|
|
29024
29817
|
}) {
|
|
29025
|
-
const { data: exchanges = [], isLoading } =
|
|
29818
|
+
const { data: exchanges = [], isLoading } = useQuery11({
|
|
29026
29819
|
queryKey: ["unifold", "exchanges", publishableKey],
|
|
29027
29820
|
queryFn: () => getExchanges(void 0, publishableKey).then((res) => res.data),
|
|
29028
29821
|
enabled,
|
|
@@ -29036,7 +29829,7 @@ function useApplePayProviders({
|
|
|
29036
29829
|
publishableKey,
|
|
29037
29830
|
enabled = true
|
|
29038
29831
|
}) {
|
|
29039
|
-
const { data: providers, isLoading } =
|
|
29832
|
+
const { data: providers, isLoading } = useQuery12({
|
|
29040
29833
|
queryKey: ["unifold", "applePayProviders", publishableKey],
|
|
29041
29834
|
queryFn: () => getApplePayProviders(publishableKey),
|
|
29042
29835
|
enabled,
|
|
@@ -29047,44 +29840,28 @@ function useApplePayProviders({
|
|
|
29047
29840
|
return { providers, isLoading };
|
|
29048
29841
|
}
|
|
29049
29842
|
function useAllowedCountry(publishableKey) {
|
|
29843
|
+
const { userIpInfo, isLoading: isIpLoading, error: ipError } = useUserIp2();
|
|
29050
29844
|
const {
|
|
29051
|
-
|
|
29052
|
-
isLoading: isIpLoading,
|
|
29053
|
-
error: ipError
|
|
29054
|
-
} = useQuery12({
|
|
29055
|
-
queryKey: ["unifold", "ipAddress"],
|
|
29056
|
-
queryFn: () => getIpAddress(),
|
|
29057
|
-
refetchOnMount: false,
|
|
29058
|
-
refetchOnReconnect: true,
|
|
29059
|
-
refetchOnWindowFocus: false,
|
|
29060
|
-
staleTime: 1e3 * 60 * 60,
|
|
29061
|
-
// 1 hour
|
|
29062
|
-
gcTime: 1e3 * 60 * 60 * 24
|
|
29063
|
-
// 24 hours
|
|
29064
|
-
});
|
|
29065
|
-
const {
|
|
29066
|
-
data: configData,
|
|
29845
|
+
projectConfig,
|
|
29067
29846
|
isLoading: isConfigLoading,
|
|
29068
29847
|
error: configError
|
|
29069
|
-
} =
|
|
29070
|
-
|
|
29071
|
-
|
|
29072
|
-
|
|
29073
|
-
|
|
29074
|
-
|
|
29075
|
-
|
|
29076
|
-
|
|
29077
|
-
gcTime: 1e3 * 60 * 60
|
|
29078
|
-
// 1 hour
|
|
29848
|
+
} = useProjectConfig({
|
|
29849
|
+
publishableKey,
|
|
29850
|
+
// Wait for the IP so we issue a single country-aware config request rather
|
|
29851
|
+
// than a country-less fetch followed by a country-aware refetch. Shares the
|
|
29852
|
+
// query key with DepositModal's useProjectConfig, so they dedupe.
|
|
29853
|
+
enabled: !isIpLoading,
|
|
29854
|
+
countryCode: userIpInfo?.alpha2,
|
|
29855
|
+
subdivisionCode: userIpInfo?.subdivisionCode ?? void 0
|
|
29079
29856
|
});
|
|
29080
29857
|
const isLoading = isIpLoading || isConfigLoading;
|
|
29081
29858
|
const error = ipError || configError || null;
|
|
29859
|
+
const userSubdivision = userIpInfo?.subdivisionCode || userIpInfo?.state || "";
|
|
29082
29860
|
let isAllowed = null;
|
|
29083
|
-
if (
|
|
29084
|
-
const blockedCodes =
|
|
29085
|
-
const blockedSubdivisions =
|
|
29086
|
-
const userCountryUpper =
|
|
29087
|
-
const userSubdivision = ipData.subdivision_code || ipData.state || "";
|
|
29861
|
+
if (userIpInfo && projectConfig) {
|
|
29862
|
+
const blockedCodes = projectConfig.blocked_country_codes || [];
|
|
29863
|
+
const blockedSubdivisions = projectConfig.blocked_country_subdivisions || [];
|
|
29864
|
+
const userCountryUpper = userIpInfo.alpha2.toUpperCase();
|
|
29088
29865
|
const userSubdivisionUpper = userSubdivision.toUpperCase();
|
|
29089
29866
|
const isCountryBlocked = blockedCodes.some((code) => code.toUpperCase() === userCountryUpper);
|
|
29090
29867
|
const isSubdivisionBlocked = blockedSubdivisions.some((entry) => {
|
|
@@ -29093,12 +29870,11 @@ function useAllowedCountry(publishableKey) {
|
|
|
29093
29870
|
});
|
|
29094
29871
|
isAllowed = !isCountryBlocked && !isSubdivisionBlocked;
|
|
29095
29872
|
}
|
|
29096
|
-
const subdivisionCode = ipData?.subdivision_code || ipData?.state || "" || null;
|
|
29097
29873
|
return {
|
|
29098
29874
|
isAllowed,
|
|
29099
|
-
alpha2:
|
|
29100
|
-
country:
|
|
29101
|
-
subdivisionCode,
|
|
29875
|
+
alpha2: userIpInfo?.alpha2 ?? null,
|
|
29876
|
+
country: userIpInfo?.country ?? null,
|
|
29877
|
+
subdivisionCode: userSubdivision || null,
|
|
29102
29878
|
isLoading,
|
|
29103
29879
|
error
|
|
29104
29880
|
};
|
|
@@ -29550,7 +30326,7 @@ function TokenSelectorSheet({
|
|
|
29550
30326
|
useEffect282(() => {
|
|
29551
30327
|
setRecentTokens(getRecentTokens());
|
|
29552
30328
|
}, []);
|
|
29553
|
-
const allOptions =
|
|
30329
|
+
const allOptions = useMemo92(() => {
|
|
29554
30330
|
const options = [];
|
|
29555
30331
|
tokens.forEach((token) => {
|
|
29556
30332
|
token.chains.forEach((chain) => {
|
|
@@ -29559,7 +30335,7 @@ function TokenSelectorSheet({
|
|
|
29559
30335
|
});
|
|
29560
30336
|
return options;
|
|
29561
30337
|
}, [tokens]);
|
|
29562
|
-
const quickSelectOptions =
|
|
30338
|
+
const quickSelectOptions = useMemo92(() => {
|
|
29563
30339
|
const result = [];
|
|
29564
30340
|
const seen = /* @__PURE__ */ new Set();
|
|
29565
30341
|
const addOption = (symbol, chainType, chainId, isRecent) => {
|
|
@@ -29591,7 +30367,7 @@ function TokenSelectorSheet({
|
|
|
29591
30367
|
});
|
|
29592
30368
|
setRecentTokens(updated);
|
|
29593
30369
|
};
|
|
29594
|
-
const fuse =
|
|
30370
|
+
const fuse = useMemo92(
|
|
29595
30371
|
() => new Fuse(allOptions, {
|
|
29596
30372
|
keys: [
|
|
29597
30373
|
{ name: "token.symbol", weight: 2 },
|
|
@@ -29604,7 +30380,7 @@ function TokenSelectorSheet({
|
|
|
29604
30380
|
}),
|
|
29605
30381
|
[allOptions]
|
|
29606
30382
|
);
|
|
29607
|
-
const filteredOptions =
|
|
30383
|
+
const filteredOptions = useMemo92(() => {
|
|
29608
30384
|
if (!searchQuery.trim()) return allOptions;
|
|
29609
30385
|
const query = searchQuery.trim();
|
|
29610
30386
|
const results = fuse.search(query);
|
|
@@ -30541,7 +31317,7 @@ function TransferCryptoSingleInput({
|
|
|
30541
31317
|
const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
|
|
30542
31318
|
const loading = externalWallets?.length ? false : walletsLoading;
|
|
30543
31319
|
const error = walletsError?.message ?? null;
|
|
30544
|
-
const allAvailableChains =
|
|
31320
|
+
const allAvailableChains = useMemo102(() => {
|
|
30545
31321
|
const chainsMap = /* @__PURE__ */ new Map();
|
|
30546
31322
|
supportedTokens.forEach((t13) => {
|
|
30547
31323
|
t13.chains.forEach((c) => {
|
|
@@ -31317,7 +32093,7 @@ function TransferCryptoDoubleInput({
|
|
|
31317
32093
|
const wallets = externalWallets?.length ? externalWallets : depositAddressResponse?.data ?? [];
|
|
31318
32094
|
const loading = externalWallets?.length ? false : walletsLoading;
|
|
31319
32095
|
const error = walletsError?.message ?? null;
|
|
31320
|
-
const allAvailableChains =
|
|
32096
|
+
const allAvailableChains = useMemo112(() => {
|
|
31321
32097
|
const chainsMap = /* @__PURE__ */ new Map();
|
|
31322
32098
|
supportedTokens.forEach((t13) => {
|
|
31323
32099
|
t13.chains.forEach((c) => {
|
|
@@ -34048,116 +34824,131 @@ function WalletConnect({
|
|
|
34048
34824
|
] });
|
|
34049
34825
|
}
|
|
34050
34826
|
if (view === "select_wallet") {
|
|
34051
|
-
return
|
|
34052
|
-
|
|
34053
|
-
|
|
34827
|
+
return (
|
|
34828
|
+
// Mobile: flex column that fills the full-height sheet so the wallet list
|
|
34829
|
+
// scrolls and the footer pins to the bottom. Desktop (sm:): content-sized.
|
|
34830
|
+
/* @__PURE__ */ jsxs56(
|
|
34831
|
+
"div",
|
|
34054
34832
|
{
|
|
34055
|
-
|
|
34056
|
-
|
|
34057
|
-
|
|
34058
|
-
|
|
34059
|
-
|
|
34060
|
-
|
|
34061
|
-
|
|
34062
|
-
|
|
34063
|
-
|
|
34064
|
-
|
|
34065
|
-
|
|
34066
|
-
|
|
34067
|
-
|
|
34068
|
-
|
|
34069
|
-
|
|
34070
|
-
|
|
34071
|
-
|
|
34072
|
-
|
|
34073
|
-
|
|
34074
|
-
|
|
34075
|
-
|
|
34076
|
-
|
|
34077
|
-
|
|
34078
|
-
|
|
34079
|
-
|
|
34080
|
-
|
|
34081
|
-
|
|
34082
|
-
|
|
34083
|
-
|
|
34084
|
-
|
|
34085
|
-
|
|
34086
|
-
/* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
|
|
34087
|
-
WALLET_ICONS3[wallet.id] ? /* @__PURE__ */ jsx622(
|
|
34088
|
-
WalletIconWithNetwork,
|
|
34089
|
-
{
|
|
34090
|
-
WalletIcon: WALLET_ICONS3[wallet.id],
|
|
34091
|
-
networks: wallet.networks,
|
|
34092
|
-
size: 40,
|
|
34093
|
-
className: "uf-rounded-lg"
|
|
34094
|
-
}
|
|
34095
|
-
) : /* @__PURE__ */ jsx622("div", { className: "uf-w-10 uf-h-10 uf-rounded-lg uf-bg-gray-500" }),
|
|
34096
|
-
/* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
34097
|
-
/* @__PURE__ */ jsx622(
|
|
34098
|
-
"div",
|
|
34099
|
-
{
|
|
34100
|
-
className: "uf-text-sm uf-font-medium",
|
|
34101
|
-
style: { color: components.card.titleColor, fontFamily: fonts.medium },
|
|
34102
|
-
children: wallet.name
|
|
34103
|
-
}
|
|
34104
|
-
),
|
|
34105
|
-
wallet.id === recentWalletId && /* @__PURE__ */ jsx622(
|
|
34106
|
-
"span",
|
|
34107
|
-
{
|
|
34108
|
-
className: "uf-text-xs uf-px-2 uf-py-0.5 uf-rounded-full",
|
|
34109
|
-
style: {
|
|
34110
|
-
backgroundColor: colors2.primary + "20",
|
|
34111
|
-
color: colors2.primary,
|
|
34112
|
-
fontFamily: fonts.medium
|
|
34113
|
-
},
|
|
34114
|
-
children: "Last used"
|
|
34115
|
-
}
|
|
34116
|
-
)
|
|
34117
|
-
] })
|
|
34118
|
-
] }),
|
|
34119
|
-
isPending ? /* @__PURE__ */ jsx622(
|
|
34120
|
-
LoaderCircle,
|
|
34121
|
-
{
|
|
34122
|
-
className: "uf-w-4 uf-h-4 uf-animate-spin",
|
|
34123
|
-
style: { color: colors2.primary }
|
|
34124
|
-
}
|
|
34125
|
-
) : wallet.isInstalled ? /* @__PURE__ */ jsx622(
|
|
34126
|
-
"span",
|
|
34833
|
+
style: viewTransitionStyle,
|
|
34834
|
+
className: "uf-flex uf-min-h-0 uf-flex-1 uf-flex-col sm:uf-block",
|
|
34835
|
+
children: [
|
|
34836
|
+
/* @__PURE__ */ jsx622(
|
|
34837
|
+
DepositHeader,
|
|
34838
|
+
{
|
|
34839
|
+
title: "Connect Wallet",
|
|
34840
|
+
showBack: canGoBack,
|
|
34841
|
+
onBack: handleBack,
|
|
34842
|
+
onClose
|
|
34843
|
+
}
|
|
34844
|
+
),
|
|
34845
|
+
/* @__PURE__ */ jsxs56("div", { className: "uf-pb-4 uf-flex uf-min-h-0 uf-flex-1 uf-flex-col sm:uf-block", children: [
|
|
34846
|
+
/* @__PURE__ */ jsx622(
|
|
34847
|
+
"p",
|
|
34848
|
+
{
|
|
34849
|
+
className: "uf-text-sm uf-text-center uf-pb-4",
|
|
34850
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
34851
|
+
children: isMobile ? "Open this page in your wallet's app to connect" : "Select a wallet to connect"
|
|
34852
|
+
}
|
|
34853
|
+
),
|
|
34854
|
+
/* @__PURE__ */ jsx622("div", { className: "uf-space-y-2 uf-min-h-0 uf-flex-1 uf-overflow-y-auto sm:uf-flex-none sm:uf-max-h-[330px] [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: availableWallets.filter((wallet) => {
|
|
34855
|
+
if (!isMobile || wallet.isInstalled) return true;
|
|
34856
|
+
const platformAllowed = !wallet.mobileBrowsePlatforms || wallet.mobileBrowsePlatforms.includes(getMobilePlatform() ?? "");
|
|
34857
|
+
return wallet.supportsMobileBrowse !== false && platformAllowed;
|
|
34858
|
+
}).map((wallet) => {
|
|
34859
|
+
const walletPlatformAllowed = !wallet.mobileBrowsePlatforms || wallet.mobileBrowsePlatforms.includes(getMobilePlatform() ?? "");
|
|
34860
|
+
const showOpenInApp = isMobile && !wallet.isInstalled && wallet.supportsMobileBrowse !== false && walletPlatformAllowed;
|
|
34861
|
+
const isPending = pendingMobileWallet?.id === wallet.id;
|
|
34862
|
+
return /* @__PURE__ */ jsxs56(
|
|
34863
|
+
"button",
|
|
34127
34864
|
{
|
|
34128
|
-
|
|
34865
|
+
onClick: () => void handleWalletClick(wallet),
|
|
34866
|
+
disabled: isWalletConnecting || !!pendingMobileWallet,
|
|
34867
|
+
className: "uf-w-full uf-transition-colors uf-p-3 uf-flex uf-items-center uf-justify-between hover:uf-opacity-90 disabled:uf-opacity-50",
|
|
34129
34868
|
style: {
|
|
34130
|
-
backgroundColor:
|
|
34131
|
-
|
|
34132
|
-
|
|
34869
|
+
backgroundColor: components.card.backgroundColor,
|
|
34870
|
+
borderRadius: components.card.borderRadius,
|
|
34871
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
34133
34872
|
},
|
|
34134
|
-
children:
|
|
34135
|
-
|
|
34136
|
-
|
|
34137
|
-
|
|
34138
|
-
|
|
34139
|
-
|
|
34140
|
-
|
|
34141
|
-
|
|
34142
|
-
|
|
34143
|
-
|
|
34144
|
-
|
|
34145
|
-
|
|
34146
|
-
|
|
34147
|
-
|
|
34148
|
-
|
|
34149
|
-
|
|
34150
|
-
|
|
34151
|
-
|
|
34152
|
-
|
|
34153
|
-
|
|
34154
|
-
|
|
34155
|
-
|
|
34156
|
-
|
|
34157
|
-
|
|
34158
|
-
|
|
34159
|
-
|
|
34160
|
-
|
|
34873
|
+
children: [
|
|
34874
|
+
/* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-3", children: [
|
|
34875
|
+
WALLET_ICONS3[wallet.id] ? /* @__PURE__ */ jsx622(
|
|
34876
|
+
WalletIconWithNetwork,
|
|
34877
|
+
{
|
|
34878
|
+
WalletIcon: WALLET_ICONS3[wallet.id],
|
|
34879
|
+
networks: wallet.networks,
|
|
34880
|
+
size: 40,
|
|
34881
|
+
className: "uf-rounded-lg"
|
|
34882
|
+
}
|
|
34883
|
+
) : /* @__PURE__ */ jsx622("div", { className: "uf-w-10 uf-h-10 uf-rounded-lg uf-bg-gray-500" }),
|
|
34884
|
+
/* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-2", children: [
|
|
34885
|
+
/* @__PURE__ */ jsx622(
|
|
34886
|
+
"div",
|
|
34887
|
+
{
|
|
34888
|
+
className: "uf-text-sm uf-font-medium",
|
|
34889
|
+
style: { color: components.card.titleColor, fontFamily: fonts.medium },
|
|
34890
|
+
children: wallet.name
|
|
34891
|
+
}
|
|
34892
|
+
),
|
|
34893
|
+
wallet.id === recentWalletId && /* @__PURE__ */ jsx622(
|
|
34894
|
+
"span",
|
|
34895
|
+
{
|
|
34896
|
+
className: "uf-text-xs uf-px-2 uf-py-0.5 uf-rounded-full",
|
|
34897
|
+
style: {
|
|
34898
|
+
backgroundColor: colors2.primary + "20",
|
|
34899
|
+
color: colors2.primary,
|
|
34900
|
+
fontFamily: fonts.medium
|
|
34901
|
+
},
|
|
34902
|
+
children: "Last used"
|
|
34903
|
+
}
|
|
34904
|
+
)
|
|
34905
|
+
] })
|
|
34906
|
+
] }),
|
|
34907
|
+
isPending ? /* @__PURE__ */ jsx622(
|
|
34908
|
+
LoaderCircle,
|
|
34909
|
+
{
|
|
34910
|
+
className: "uf-w-4 uf-h-4 uf-animate-spin",
|
|
34911
|
+
style: { color: colors2.primary }
|
|
34912
|
+
}
|
|
34913
|
+
) : wallet.isInstalled ? /* @__PURE__ */ jsx622(
|
|
34914
|
+
"span",
|
|
34915
|
+
{
|
|
34916
|
+
className: "uf-text-xs uf-px-2 uf-py-1 uf-rounded-full",
|
|
34917
|
+
style: {
|
|
34918
|
+
backgroundColor: colors2.primary + "20",
|
|
34919
|
+
color: colors2.primary,
|
|
34920
|
+
fontFamily: fonts.medium
|
|
34921
|
+
},
|
|
34922
|
+
children: "Detected"
|
|
34923
|
+
}
|
|
34924
|
+
) : /* @__PURE__ */ jsxs56("div", { className: "uf-flex uf-items-center uf-gap-1", children: [
|
|
34925
|
+
/* @__PURE__ */ jsx622(
|
|
34926
|
+
"span",
|
|
34927
|
+
{
|
|
34928
|
+
className: "uf-text-xs",
|
|
34929
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
34930
|
+
children: showOpenInApp ? "Open" : "Install"
|
|
34931
|
+
}
|
|
34932
|
+
),
|
|
34933
|
+
/* @__PURE__ */ jsx622(
|
|
34934
|
+
ExternalLink,
|
|
34935
|
+
{
|
|
34936
|
+
className: "uf-w-3 uf-h-3",
|
|
34937
|
+
style: { color: colors2.foregroundMuted }
|
|
34938
|
+
}
|
|
34939
|
+
)
|
|
34940
|
+
] })
|
|
34941
|
+
]
|
|
34942
|
+
},
|
|
34943
|
+
wallet.id
|
|
34944
|
+
);
|
|
34945
|
+
}) }),
|
|
34946
|
+
walletError && /* @__PURE__ */ jsx622("div", { className: "uf-text-center uf-text-sm uf-mt-4 uf-px-4", style: { color: "#ef4444" }, children: walletError })
|
|
34947
|
+
] })
|
|
34948
|
+
]
|
|
34949
|
+
}
|
|
34950
|
+
)
|
|
34951
|
+
);
|
|
34161
34952
|
}
|
|
34162
34953
|
const preConnectAccent = selectedWalletDef ? getWalletBrandColor(selectedWalletDef.id, mode) : void 0;
|
|
34163
34954
|
const preConnectFg = preConnectAccent ? getContrastingTextColor(preConnectAccent) : void 0;
|
|
@@ -34546,11 +35337,12 @@ function DepositModal({
|
|
|
34546
35337
|
applePayTitle = "Pay with Apple Pay",
|
|
34547
35338
|
applePaySubTitle = "Instant",
|
|
34548
35339
|
enableBankTransfer,
|
|
34549
|
-
|
|
34550
|
-
|
|
35340
|
+
// No default: left undefined so the backend `stripe_link.enabled` can govern
|
|
35341
|
+
// (via the `??` chain in showStripeLink) once a dashboard toggle exists.
|
|
35342
|
+
enableStripeLink,
|
|
35343
|
+
userEmail,
|
|
34551
35344
|
hideDepositFlowInfo = false,
|
|
34552
35345
|
hideDisplayDescription = false,
|
|
34553
|
-
externalUserEmail,
|
|
34554
35346
|
onDepositSuccess,
|
|
34555
35347
|
onDepositError,
|
|
34556
35348
|
onEvent,
|
|
@@ -34582,7 +35374,7 @@ function DepositModal({
|
|
|
34582
35374
|
(method) => onDepositError ? (error) => onDepositError({ ...error, method }) : void 0,
|
|
34583
35375
|
[onDepositError]
|
|
34584
35376
|
);
|
|
34585
|
-
const effectiveInitialScreen =
|
|
35377
|
+
const effectiveInitialScreen = useMemo13(() => {
|
|
34586
35378
|
const s = initialScreen ?? "main";
|
|
34587
35379
|
if (s === "tracker" && hideDepositTracker === true) return "main";
|
|
34588
35380
|
if (s === "cashapp" && enableCashApp === false) return "main";
|
|
@@ -34628,14 +35420,18 @@ function DepositModal({
|
|
|
34628
35420
|
const [allExecutions, setAllExecutions] = useState40([]);
|
|
34629
35421
|
const [selectedExecution, setSelectedExecution] = useState40(null);
|
|
34630
35422
|
const [depositExecutions, setDepositExecutions] = useState40([]);
|
|
35423
|
+
const { userIpInfo, isLoading: isLoadingIp } = useUserIp2();
|
|
34631
35424
|
const { projectConfig } = useProjectConfig({
|
|
34632
35425
|
publishableKey,
|
|
34633
|
-
enabled: open
|
|
35426
|
+
enabled: open && !isLoadingIp,
|
|
35427
|
+
countryCode: userIpInfo?.alpha2,
|
|
35428
|
+
subdivisionCode: userIpInfo?.subdivisionCode ?? void 0
|
|
34634
35429
|
});
|
|
34635
35430
|
const showTransferCrypto = enableTransferCrypto ?? projectConfig?.transfer_crypto?.enabled ?? true;
|
|
34636
35431
|
const showConnectWallet = enableConnectWallet ?? projectConfig?.connect_wallet?.enabled ?? true;
|
|
34637
35432
|
const showPayWithExchange = enablePayWithExchange ?? projectConfig?.pay_with_exchange?.enabled ?? true;
|
|
34638
35433
|
const showFiatOnramp = !projectConfig?.fiat_onramp?.is_hidden && (enableFiatOnramp ?? projectConfig?.fiat_onramp?.enabled ?? true);
|
|
35434
|
+
const showStripeLink = !projectConfig?.stripe_link?.is_hidden && (enableStripeLink ?? projectConfig?.stripe_link?.enabled ?? false);
|
|
34639
35435
|
const showConnectExchange = enableConnectExchange ?? projectConfig?.connect_exchange?.enabled ?? true;
|
|
34640
35436
|
const showCashApp = enableCashApp ?? projectConfig?.cash_app?.enabled ?? true;
|
|
34641
35437
|
const showApplePay = enableApplePay ?? projectConfig?.apple_pay?.enabled ?? true;
|
|
@@ -34781,7 +35577,6 @@ function DepositModal({
|
|
|
34781
35577
|
publishableKey,
|
|
34782
35578
|
enabled: open && showPayWithExchange
|
|
34783
35579
|
});
|
|
34784
|
-
const { userIpInfo, isLoading: isLoadingIp } = useUserIp2();
|
|
34785
35580
|
const { providers: bankTransferProviders, isLoading: bankTransferProvidersLoading } = useBankTransferProviders({
|
|
34786
35581
|
publishableKey,
|
|
34787
35582
|
enabled: open && !!userIpInfo?.alpha2,
|
|
@@ -34959,6 +35754,12 @@ function DepositModal({
|
|
|
34959
35754
|
const [cashAppView, setCashAppView] = useState40("amount");
|
|
34960
35755
|
const [stripeLinkStep, setStripeLinkStep] = useState40("amount");
|
|
34961
35756
|
const stripeLinkBackRef = useRef122(null);
|
|
35757
|
+
useEffect34(() => {
|
|
35758
|
+
if (view === "stripe_link" && !showStripeLink && effectiveInitialScreen === "main") {
|
|
35759
|
+
setView("main");
|
|
35760
|
+
setStripeLinkStep("amount");
|
|
35761
|
+
}
|
|
35762
|
+
}, [view, showStripeLink, effectiveInitialScreen]);
|
|
34962
35763
|
const [cashAppAmount, setCashAppAmount] = useState40("");
|
|
34963
35764
|
const [applePayView, setApplePayView] = useState40("email_input");
|
|
34964
35765
|
const applePayHandleRef = useRef122(null);
|
|
@@ -34981,11 +35782,18 @@ function DepositModal({
|
|
|
34981
35782
|
return "Success";
|
|
34982
35783
|
case "guest_limit_reached":
|
|
34983
35784
|
return "Limit reached";
|
|
35785
|
+
case "limit_upgrade_intro":
|
|
35786
|
+
case "limit_upgrade_failed":
|
|
35787
|
+
return "Limit reached";
|
|
35788
|
+
case "limit_upgrade_form":
|
|
35789
|
+
return "Verify identity";
|
|
35790
|
+
case "limit_upgrade_submitting":
|
|
35791
|
+
return "Verifying";
|
|
34984
35792
|
default:
|
|
34985
35793
|
return "Pay with Apple Pay";
|
|
34986
35794
|
}
|
|
34987
35795
|
})();
|
|
34988
|
-
const applePayShowBack = sessionOpenedFromMenu || applePayView === "phone_input" || applePayView === "email_otp" || applePayView === "phone_otp" || applePayView === "submitting_session" || applePayView === "checking_deposit";
|
|
35796
|
+
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";
|
|
34989
35797
|
const handleBack = () => {
|
|
34990
35798
|
if (view === "card" && cardView === "quotes") {
|
|
34991
35799
|
setCardView("amount");
|
|
@@ -35176,7 +35984,7 @@ function DepositModal({
|
|
|
35176
35984
|
},
|
|
35177
35985
|
"cashapp"
|
|
35178
35986
|
) : null;
|
|
35179
|
-
const stripeLinkMenuButton =
|
|
35987
|
+
const stripeLinkMenuButton = showStripeLink ? /* @__PURE__ */ jsx63(
|
|
35180
35988
|
StripeLinkButton,
|
|
35181
35989
|
{
|
|
35182
35990
|
onClick: () => setView("stripe_link"),
|
|
@@ -35224,11 +36032,13 @@ function DepositModal({
|
|
|
35224
36032
|
connectExchangeMenuButton
|
|
35225
36033
|
].filter(Boolean);
|
|
35226
36034
|
const cashMenuButtons = [
|
|
36035
|
+
// Stripe "Pay with Link" is intentionally listed first so it always sits
|
|
36036
|
+
// above "Deposit with Card".
|
|
36037
|
+
stripeLinkMenuButton,
|
|
35227
36038
|
depositWithCardMenuButton,
|
|
35228
36039
|
applePayMenuButton,
|
|
35229
36040
|
cashAppMenuButton,
|
|
35230
|
-
bankTransferMenuButton
|
|
35231
|
-
stripeLinkMenuButton
|
|
36041
|
+
bankTransferMenuButton
|
|
35232
36042
|
].filter(Boolean);
|
|
35233
36043
|
const depositTabs = [
|
|
35234
36044
|
{ id: "crypto", label: "Use Crypto", icon: Bitcoin, buttons: cryptoMenuButtons },
|
|
@@ -35323,13 +36133,13 @@ function DepositModal({
|
|
|
35323
36133
|
const stackedOptions = [
|
|
35324
36134
|
transferCryptoMenuButton,
|
|
35325
36135
|
connectWalletMenuButton,
|
|
36136
|
+
stripeLinkMenuButton,
|
|
35326
36137
|
depositWithCardMenuButton,
|
|
35327
36138
|
applePayMenuButton,
|
|
35328
36139
|
payWithExchangeMenuButton,
|
|
35329
36140
|
connectExchangeMenuButton,
|
|
35330
36141
|
cashAppMenuButton,
|
|
35331
36142
|
bankTransferMenuButton,
|
|
35332
|
-
stripeLinkMenuButton,
|
|
35333
36143
|
depositTrackerMenuButton
|
|
35334
36144
|
].filter(Boolean);
|
|
35335
36145
|
return renderScrollableOptions(stackedOptions);
|
|
@@ -35345,413 +36155,452 @@ function DepositModal({
|
|
|
35345
36155
|
{
|
|
35346
36156
|
ref: hideOverlay ? containerCallbackRef : void 0,
|
|
35347
36157
|
hideOverlay,
|
|
35348
|
-
className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden ${hideOverlay ? `uf-p-6 uf-overflow-hidden ${themeClass}` : `uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[85vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${
|
|
36158
|
+
className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden ${hideOverlay ? `uf-p-6 uf-overflow-hidden ${themeClass}` : `uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[85vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${// wallet_connect fills the full-height mobile sheet. DialogContent
|
|
36159
|
+
// is a grid, and its single auto row only *grows* to fill free
|
|
36160
|
+
// space (align-content: stretch) — it never shrinks below content,
|
|
36161
|
+
// so a long wallet list would balloon the row past the viewport and
|
|
36162
|
+
// push the footer off-screen instead of scrolling. Clamp the row to
|
|
36163
|
+
// the modal height with minmax(0,1fr) so the inner overflow-y-auto
|
|
36164
|
+
// list scrolls with the footer pinned. Reset to content-sized on
|
|
36165
|
+
// desktop (sm:) where the modal is auto-height and centered.
|
|
36166
|
+
view === "wallet_connect" ? "[grid-template-rows:minmax(0,1fr)] sm:[grid-template-rows:none]" : ""} ${themeClass}`}`,
|
|
35349
36167
|
style: { backgroundColor: colors2.background },
|
|
35350
36168
|
onPointerDownOutside: (e) => e.preventDefault(),
|
|
35351
36169
|
onInteractOutside: (e) => e.preventDefault(),
|
|
35352
36170
|
children: [
|
|
35353
36171
|
/* @__PURE__ */ jsx63(DialogTitle2, { className: "uf-sr-only", children: modalTitle || "Deposit" }),
|
|
35354
|
-
/* @__PURE__ */ jsx63(
|
|
35355
|
-
|
|
35356
|
-
|
|
35357
|
-
|
|
35358
|
-
|
|
35359
|
-
|
|
35360
|
-
|
|
35361
|
-
|
|
35362
|
-
|
|
35363
|
-
|
|
35364
|
-
|
|
35365
|
-
|
|
35366
|
-
|
|
35367
|
-
|
|
35368
|
-
|
|
35369
|
-
|
|
35370
|
-
|
|
35371
|
-
|
|
35372
|
-
|
|
35373
|
-
|
|
35374
|
-
|
|
35375
|
-
|
|
35376
|
-
|
|
35377
|
-
|
|
35378
|
-
|
|
35379
|
-
|
|
35380
|
-
|
|
35381
|
-
|
|
35382
|
-
|
|
35383
|
-
|
|
35384
|
-
|
|
35385
|
-
|
|
35386
|
-
|
|
35387
|
-
|
|
35388
|
-
|
|
35389
|
-
|
|
35390
|
-
|
|
35391
|
-
|
|
35392
|
-
|
|
35393
|
-
|
|
35394
|
-
|
|
35395
|
-
|
|
35396
|
-
|
|
35397
|
-
|
|
35398
|
-
|
|
35399
|
-
|
|
35400
|
-
|
|
35401
|
-
|
|
35402
|
-
|
|
35403
|
-
|
|
35404
|
-
|
|
35405
|
-
|
|
35406
|
-
|
|
35407
|
-
|
|
35408
|
-
|
|
35409
|
-
|
|
35410
|
-
|
|
35411
|
-
|
|
35412
|
-
|
|
35413
|
-
|
|
35414
|
-
|
|
35415
|
-
|
|
35416
|
-
|
|
35417
|
-
|
|
35418
|
-
|
|
35419
|
-
|
|
35420
|
-
|
|
35421
|
-
|
|
35422
|
-
|
|
35423
|
-
|
|
35424
|
-
|
|
35425
|
-
|
|
35426
|
-
|
|
35427
|
-
|
|
35428
|
-
|
|
35429
|
-
|
|
35430
|
-
|
|
35431
|
-
] }) : view === "tracker" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
35432
|
-
/* @__PURE__ */ jsx63(
|
|
35433
|
-
DepositHeader,
|
|
35434
|
-
{
|
|
35435
|
-
title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
|
|
35436
|
-
showBack: showBackTracker,
|
|
35437
|
-
onBack: handleBack,
|
|
35438
|
-
onClose: handleClose
|
|
35439
|
-
}
|
|
35440
|
-
),
|
|
35441
|
-
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35442
|
-
/* @__PURE__ */ jsx63("div", { className: "uf-h-[460px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: selectedExecution ? /* @__PURE__ */ jsx63(DepositDetailContent, { execution: selectedExecution }) : /* @__PURE__ */ jsx63("div", { className: "uf-space-y-2 uf-pb-8", children: allExecutions.length === 0 ? /* @__PURE__ */ jsx63("div", { className: "uf-py-8 uf-px-4 uf-text-center", children: /* @__PURE__ */ jsx63(
|
|
35443
|
-
"div",
|
|
35444
|
-
{
|
|
35445
|
-
className: "uf-text-sm",
|
|
35446
|
-
style: {
|
|
35447
|
-
color: components.container.subtitleColor,
|
|
35448
|
-
fontFamily: fonts.regular
|
|
35449
|
-
},
|
|
35450
|
-
children: "No deposits yet"
|
|
35451
|
-
}
|
|
35452
|
-
) }) : allExecutions.map((execution) => /* @__PURE__ */ jsx63(
|
|
35453
|
-
DepositExecutionItem,
|
|
35454
|
-
{
|
|
35455
|
-
execution,
|
|
35456
|
-
onClick: () => setSelectedExecution(execution)
|
|
35457
|
-
},
|
|
35458
|
-
execution.id
|
|
35459
|
-
)) }) }),
|
|
35460
|
-
depositPoweredByFooter
|
|
35461
|
-
] })
|
|
35462
|
-
] }) : view === "card" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
35463
|
-
/* @__PURE__ */ jsx63(
|
|
35464
|
-
DepositHeader,
|
|
35465
|
-
{
|
|
35466
|
-
title: cardView === "quotes" ? t8.quotes : depositWithCardTitle,
|
|
35467
|
-
showBack: showBackCard,
|
|
35468
|
-
onBack: handleBack,
|
|
35469
|
-
onClose: handleClose,
|
|
35470
|
-
badge: cardView === "quotes" ? { count: quotesCount } : void 0,
|
|
35471
|
-
showBalance: showBalanceHeader,
|
|
35472
|
-
balanceAddress: recipientAddress,
|
|
35473
|
-
balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
|
|
35474
|
-
balanceChainId: destinationChainId,
|
|
35475
|
-
balanceTokenAddress: destinationTokenAddress,
|
|
35476
|
-
projectName: projectConfig?.project_name,
|
|
35477
|
-
publishableKey
|
|
35478
|
-
}
|
|
35479
|
-
),
|
|
35480
|
-
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35481
|
-
standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ jsx63("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : !showFiatOnramp ? (
|
|
35482
|
-
// Fiat on-ramp resolved hidden/disabled after a direct open
|
|
35483
|
-
// (e.g. platform `is_hidden` for a Stripe Link-only project).
|
|
35484
|
-
// Show a geo-restriction screen rather than the card UI so the
|
|
35485
|
-
// hard-hide is honoured without a flash of "Pay with Card".
|
|
35486
|
-
/* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Card" })
|
|
35487
|
-
) : /* @__PURE__ */ jsx63(
|
|
35488
|
-
BuyWithCard,
|
|
35489
|
-
{
|
|
35490
|
-
userId,
|
|
35491
|
-
publishableKey,
|
|
35492
|
-
view: cardView,
|
|
35493
|
-
onViewChange: handleCardViewChange,
|
|
35494
|
-
destinationTokenSymbol,
|
|
35495
|
-
recipientAddress,
|
|
35496
|
-
destinationChainType,
|
|
35497
|
-
destinationChainId,
|
|
35498
|
-
destinationTokenAddress,
|
|
35499
|
-
onDepositSuccess: onDepositSuccessFor("card"),
|
|
35500
|
-
onDepositError: onDepositErrorFor("card"),
|
|
35501
|
-
onEvent,
|
|
35502
|
-
themeClass,
|
|
35503
|
-
wallets,
|
|
35504
|
-
assetCdnUrl: projectConfig?.asset_cdn_url,
|
|
35505
|
-
hideDepositFlowInfo,
|
|
35506
|
-
hideDisplayDescription
|
|
35507
|
-
}
|
|
35508
|
-
),
|
|
35509
|
-
depositPoweredByFooter
|
|
35510
|
-
] })
|
|
35511
|
-
] }) : view === "exchange" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
35512
|
-
/* @__PURE__ */ jsx63(
|
|
35513
|
-
DepositHeader,
|
|
35514
|
-
{
|
|
35515
|
-
title: payWithExchangeTitle,
|
|
35516
|
-
showBack: exchangeView === "pending" || sessionOpenedFromMenu,
|
|
35517
|
-
onBack: handleBack,
|
|
35518
|
-
onClose: handleClose
|
|
35519
|
-
}
|
|
35520
|
-
),
|
|
35521
|
-
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35522
|
-
/* @__PURE__ */ jsx63(
|
|
35523
|
-
PayWithExchange,
|
|
35524
|
-
{
|
|
35525
|
-
userId,
|
|
35526
|
-
publishableKey,
|
|
35527
|
-
exchanges,
|
|
35528
|
-
view: exchangeView,
|
|
35529
|
-
onViewChange: setExchangeView,
|
|
35530
|
-
destinationTokenSymbol,
|
|
35531
|
-
recipientAddress,
|
|
35532
|
-
destinationChainType,
|
|
35533
|
-
destinationChainId,
|
|
35534
|
-
destinationTokenAddress,
|
|
35535
|
-
onDepositSuccess: onDepositSuccessFor("pay_with_exchange"),
|
|
35536
|
-
onDepositError: onDepositErrorFor("pay_with_exchange"),
|
|
35537
|
-
wallets,
|
|
35538
|
-
defaultToken: defaultToken ?? null
|
|
35539
|
-
}
|
|
35540
|
-
),
|
|
35541
|
-
depositPoweredByFooter
|
|
35542
|
-
] })
|
|
35543
|
-
] }) : view === "coinbase_connect" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35544
|
-
/* @__PURE__ */ jsx63(
|
|
35545
|
-
CoinbaseConnect,
|
|
35546
|
-
{
|
|
35547
|
-
publishableKey,
|
|
35548
|
-
userId,
|
|
35549
|
-
wallets,
|
|
35550
|
-
recipientAddress,
|
|
35551
|
-
destinationTokenAddress: destinationTokenAddress ?? "",
|
|
35552
|
-
destinationChainId: destinationChainId ?? "",
|
|
35553
|
-
destinationChainType: destinationChainType ?? "",
|
|
35554
|
-
onDepositSuccess: onDepositSuccessFor("exchange_connect"),
|
|
35555
|
-
onDepositError: onDepositErrorFor("exchange_connect"),
|
|
35556
|
-
onTransferError: (error) => {
|
|
35557
|
-
onDepositErrorFor("exchange_connect")?.({
|
|
35558
|
-
message: error.message,
|
|
35559
|
-
error
|
|
35560
|
-
});
|
|
35561
|
-
},
|
|
35562
|
-
onBack: handleBack,
|
|
35563
|
-
onClose: handleClose,
|
|
35564
|
-
onDisconnect: handleExchangeDisconnect,
|
|
35565
|
-
skipToHoldings: coinbaseSkipToHoldings,
|
|
35566
|
-
canGoBack: sessionOpenedFromMenu,
|
|
35567
|
-
onExecutionsChange: setDepositExecutions,
|
|
35568
|
-
defaultSourceChainType,
|
|
35569
|
-
defaultSourceChainId,
|
|
35570
|
-
defaultSourceTokenAddress,
|
|
35571
|
-
defaultSourceSymbol
|
|
35572
|
-
}
|
|
35573
|
-
),
|
|
35574
|
-
depositPoweredByFooter
|
|
35575
|
-
] }) : view === "wallet_connect" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35576
|
-
/* @__PURE__ */ jsx63(
|
|
35577
|
-
WalletConnect,
|
|
35578
|
-
{
|
|
35579
|
-
walletInfo: browserWalletInfo ?? void 0,
|
|
35580
|
-
depositWallet: browserWalletInfo?.depositWallet ?? void 0,
|
|
35581
|
-
wallets,
|
|
35582
|
-
userId,
|
|
35583
|
-
publishableKey,
|
|
35584
|
-
assetCdnUrl: projectConfig?.asset_cdn_url,
|
|
35585
|
-
projectName: projectConfig?.project_name,
|
|
35586
|
-
onError: (error) => {
|
|
35587
|
-
onDepositErrorFor("wallet_connect")?.({
|
|
35588
|
-
message: error.message,
|
|
35589
|
-
error
|
|
35590
|
-
});
|
|
35591
|
-
},
|
|
35592
|
-
onDepositSuccess: onDepositSuccessFor("wallet_connect"),
|
|
35593
|
-
onDepositError: onDepositErrorFor("wallet_connect"),
|
|
35594
|
-
amountQuickSelect: browserWalletAmountQuickSelect,
|
|
35595
|
-
onWalletDisconnect: handleWalletDisconnect,
|
|
35596
|
-
onWalletConnected: (info, dw) => {
|
|
35597
|
-
setBrowserWalletInfo({ ...info, depositWallet: dw });
|
|
35598
|
-
setStoredWalletState(info.type);
|
|
35599
|
-
setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
|
|
35600
|
-
},
|
|
35601
|
-
onBack: handleBack,
|
|
35602
|
-
onClose: handleClose,
|
|
35603
|
-
defaultSourceChainType,
|
|
35604
|
-
defaultSourceChainId,
|
|
35605
|
-
defaultSourceTokenAddress,
|
|
35606
|
-
defaultSourceSymbol,
|
|
35607
|
-
canGoBack: sessionOpenedFromMenu,
|
|
35608
|
-
depositWalletsLoading: walletsLoading
|
|
35609
|
-
}
|
|
35610
|
-
),
|
|
35611
|
-
depositPoweredByFooter
|
|
35612
|
-
] }) : view === "bank_transfer" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
35613
|
-
/* @__PURE__ */ jsx63(
|
|
35614
|
-
DepositHeader,
|
|
35615
|
-
{
|
|
35616
|
-
title: t8.bankTransfer.title,
|
|
35617
|
-
showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
|
|
35618
|
-
onBack: handleBack,
|
|
35619
|
-
onClose: handleClose
|
|
35620
|
-
}
|
|
35621
|
-
),
|
|
35622
|
-
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35623
|
-
bankTransferProvidersLoading ? /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" }) : !hasEnabledBankTransferProvider ? /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Bank Transfer" }) : /* @__PURE__ */ jsx63(
|
|
35624
|
-
BankTransfer,
|
|
35625
|
-
{
|
|
35626
|
-
userId,
|
|
35627
|
-
publishableKey,
|
|
35628
|
-
view: bankTransferView,
|
|
35629
|
-
onViewChange: setBankTransferView,
|
|
35630
|
-
recipientAddress,
|
|
35631
|
-
destinationChainType,
|
|
35632
|
-
destinationChainId,
|
|
35633
|
-
destinationTokenAddress,
|
|
35634
|
-
destinationTokenSymbol,
|
|
35635
|
-
wallets,
|
|
35636
|
-
defaultToken: defaultToken ?? null,
|
|
35637
|
-
assetCdnUrl: projectConfig?.asset_cdn_url,
|
|
35638
|
-
onEvent,
|
|
35639
|
-
onDepositSuccess,
|
|
35640
|
-
onDepositError
|
|
35641
|
-
}
|
|
35642
|
-
),
|
|
35643
|
-
depositPoweredByFooter
|
|
35644
|
-
] })
|
|
35645
|
-
] }) : view === "stripe_link" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
35646
|
-
/* @__PURE__ */ jsx63(
|
|
35647
|
-
DepositHeader,
|
|
35648
|
-
{
|
|
35649
|
-
title: "Deposit with Link",
|
|
35650
|
-
showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
|
|
35651
|
-
onBack: handleBack,
|
|
35652
|
-
showClose: stripeLinkStep !== "checkout",
|
|
35653
|
-
onClose: handleClose
|
|
35654
|
-
}
|
|
35655
|
-
),
|
|
35656
|
-
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35657
|
-
/* @__PURE__ */ jsx63(
|
|
35658
|
-
PayWithStripeLink,
|
|
35659
|
-
{
|
|
35660
|
-
userId,
|
|
35661
|
-
publishableKey,
|
|
35662
|
-
recipientAddress,
|
|
35663
|
-
destinationChainType,
|
|
35664
|
-
destinationChainId,
|
|
35665
|
-
destinationTokenAddress,
|
|
35666
|
-
wallets,
|
|
35667
|
-
email: emailProp,
|
|
35668
|
-
iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/link.svg` : void 0,
|
|
35669
|
-
step: stripeLinkStep,
|
|
35670
|
-
onStepChange: setStripeLinkStep,
|
|
35671
|
-
backHandlerRef: stripeLinkBackRef,
|
|
35672
|
-
onDepositSuccess,
|
|
35673
|
-
onDepositError
|
|
35674
|
-
}
|
|
35675
|
-
),
|
|
35676
|
-
depositPoweredByFooter
|
|
35677
|
-
] })
|
|
35678
|
-
] }) : view === "cashapp" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
35679
|
-
/* @__PURE__ */ jsx63(
|
|
35680
|
-
DepositHeader,
|
|
35681
|
-
{
|
|
35682
|
-
title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
|
|
35683
|
-
showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
|
|
35684
|
-
onBack: handleBack,
|
|
35685
|
-
onClose: handleClose
|
|
35686
|
-
}
|
|
35687
|
-
),
|
|
35688
|
-
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35689
|
-
/* @__PURE__ */ jsx63(
|
|
35690
|
-
PayWithCashApp,
|
|
35691
|
-
{
|
|
35692
|
-
userId,
|
|
35693
|
-
publishableKey,
|
|
35694
|
-
recipientAddress,
|
|
35695
|
-
destinationChainType,
|
|
35696
|
-
destinationChainId,
|
|
35697
|
-
destinationTokenAddress,
|
|
35698
|
-
cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
|
|
35699
|
-
view: cashAppView,
|
|
35700
|
-
onViewChange: setCashAppView,
|
|
35701
|
-
onAmountChange: setCashAppAmount,
|
|
35702
|
-
onEvent,
|
|
35703
|
-
onDepositSuccess: onDepositSuccessFor("cashapp"),
|
|
35704
|
-
onDepositError: onDepositErrorFor("cashapp"),
|
|
35705
|
-
wallets
|
|
35706
|
-
}
|
|
35707
|
-
),
|
|
35708
|
-
depositPoweredByFooter
|
|
35709
|
-
] })
|
|
35710
|
-
] }) : view === "apple_pay" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
35711
|
-
/* @__PURE__ */ jsx63(
|
|
35712
|
-
DepositHeader,
|
|
35713
|
-
{
|
|
35714
|
-
title: applePayHeaderTitle,
|
|
35715
|
-
showBack: applePayShowBack,
|
|
35716
|
-
onBack: () => {
|
|
35717
|
-
const handled = applePayHandleRef.current?.requestBack() ?? false;
|
|
35718
|
-
if (!handled) handleBack();
|
|
35719
|
-
},
|
|
35720
|
-
onClose: handleClose
|
|
35721
|
-
}
|
|
35722
|
-
),
|
|
35723
|
-
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
35724
|
-
applePayProvidersLoading ? /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" }) : !hasEnabledApplePayProvider ? /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Apple Pay" }) : /* @__PURE__ */ jsx63(
|
|
35725
|
-
BuyWithApplePay,
|
|
35726
|
-
{
|
|
35727
|
-
ref: applePayHandleRef,
|
|
35728
|
-
userId,
|
|
35729
|
-
publishableKey,
|
|
35730
|
-
recipientAddress,
|
|
35731
|
-
destinationChainType,
|
|
35732
|
-
destinationChainId,
|
|
35733
|
-
destinationTokenAddress,
|
|
35734
|
-
destinationTokenSymbol,
|
|
35735
|
-
externalUserEmail,
|
|
35736
|
-
enableApplePay,
|
|
35737
|
-
wallets,
|
|
35738
|
-
onViewChange: setApplePayView,
|
|
35739
|
-
onEvent,
|
|
35740
|
-
onDepositSuccess: onDepositSuccessFor("apple_pay"),
|
|
35741
|
-
onDepositError: onDepositErrorFor("apple_pay"),
|
|
35742
|
-
exitLabel: sessionOpenedFromMenu ? "Return" : "Close",
|
|
35743
|
-
onExit: () => {
|
|
35744
|
-
if (sessionOpenedFromMenu) {
|
|
35745
|
-
setView("main");
|
|
35746
|
-
} else {
|
|
35747
|
-
handleClose();
|
|
36172
|
+
/* @__PURE__ */ jsx63(
|
|
36173
|
+
ThemeStyleInjector,
|
|
36174
|
+
{
|
|
36175
|
+
className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
|
|
36176
|
+
children: view === "main" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-min-h-0 uf-max-h-full", children: [
|
|
36177
|
+
/* @__PURE__ */ jsx63("div", { className: "uf-flex-shrink-0", children: /* @__PURE__ */ jsx63(
|
|
36178
|
+
DepositHeader,
|
|
36179
|
+
{
|
|
36180
|
+
title: modalTitle || "Deposit",
|
|
36181
|
+
showClose: !hideOverlay,
|
|
36182
|
+
onClose: handleClose,
|
|
36183
|
+
showBalance: showBalanceHeader,
|
|
36184
|
+
balanceAddress: recipientAddress,
|
|
36185
|
+
balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
|
|
36186
|
+
balanceChainId: destinationChainId,
|
|
36187
|
+
balanceTokenAddress: destinationTokenAddress,
|
|
36188
|
+
projectName: projectConfig?.project_name,
|
|
36189
|
+
publishableKey
|
|
36190
|
+
}
|
|
36191
|
+
) }),
|
|
36192
|
+
renderMainMenuBody(),
|
|
36193
|
+
/* @__PURE__ */ jsx63("div", { className: "uf-flex-shrink-0", children: depositPoweredByFooter })
|
|
36194
|
+
] }) : view === "transfer" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
36195
|
+
/* @__PURE__ */ jsx63(
|
|
36196
|
+
DepositHeader,
|
|
36197
|
+
{
|
|
36198
|
+
title: transferCryptoTitle,
|
|
36199
|
+
showBack: showBackTransfer,
|
|
36200
|
+
onBack: handleBack,
|
|
36201
|
+
onClose: handleClose,
|
|
36202
|
+
showBalance: showBalanceHeader,
|
|
36203
|
+
balanceAddress: recipientAddress,
|
|
36204
|
+
balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
|
|
36205
|
+
balanceChainId: destinationChainId,
|
|
36206
|
+
balanceTokenAddress: destinationTokenAddress,
|
|
36207
|
+
projectName: projectConfig?.project_name,
|
|
36208
|
+
publishableKey
|
|
36209
|
+
}
|
|
36210
|
+
),
|
|
36211
|
+
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36212
|
+
standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ jsx63("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : transferInputVariant === "single_input" ? /* @__PURE__ */ jsx63(
|
|
36213
|
+
TransferCryptoSingleInput,
|
|
36214
|
+
{
|
|
36215
|
+
userId,
|
|
36216
|
+
publishableKey,
|
|
36217
|
+
recipientAddress,
|
|
36218
|
+
destinationChainType,
|
|
36219
|
+
destinationChainId,
|
|
36220
|
+
destinationTokenAddress,
|
|
36221
|
+
defaultSourceChainType,
|
|
36222
|
+
defaultSourceChainId,
|
|
36223
|
+
defaultSourceTokenAddress,
|
|
36224
|
+
defaultSourceSymbol,
|
|
36225
|
+
depositConfirmationMode,
|
|
36226
|
+
onExecutionsChange: setDepositExecutions,
|
|
36227
|
+
onDepositSuccess: onDepositSuccessFor("transfer"),
|
|
36228
|
+
onDepositError: onDepositErrorFor("transfer"),
|
|
36229
|
+
wallets
|
|
36230
|
+
}
|
|
36231
|
+
) : /* @__PURE__ */ jsx63(
|
|
36232
|
+
TransferCryptoDoubleInput,
|
|
36233
|
+
{
|
|
36234
|
+
userId,
|
|
36235
|
+
publishableKey,
|
|
36236
|
+
recipientAddress,
|
|
36237
|
+
destinationChainType,
|
|
36238
|
+
destinationChainId,
|
|
36239
|
+
destinationTokenAddress,
|
|
36240
|
+
defaultSourceChainType,
|
|
36241
|
+
defaultSourceChainId,
|
|
36242
|
+
defaultSourceTokenAddress,
|
|
36243
|
+
defaultSourceSymbol,
|
|
36244
|
+
depositConfirmationMode,
|
|
36245
|
+
onExecutionsChange: setDepositExecutions,
|
|
36246
|
+
onDepositSuccess: onDepositSuccessFor("transfer"),
|
|
36247
|
+
onDepositError: onDepositErrorFor("transfer"),
|
|
36248
|
+
wallets
|
|
35748
36249
|
}
|
|
36250
|
+
),
|
|
36251
|
+
depositPoweredByFooter
|
|
36252
|
+
] })
|
|
36253
|
+
] }) : view === "tracker" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
36254
|
+
/* @__PURE__ */ jsx63(
|
|
36255
|
+
DepositHeader,
|
|
36256
|
+
{
|
|
36257
|
+
title: selectedExecution ? "Deposit Details" : depositTrackerTitle,
|
|
36258
|
+
showBack: showBackTracker,
|
|
36259
|
+
onBack: handleBack,
|
|
36260
|
+
onClose: handleClose
|
|
35749
36261
|
}
|
|
35750
|
-
|
|
35751
|
-
|
|
35752
|
-
|
|
35753
|
-
|
|
35754
|
-
|
|
36262
|
+
),
|
|
36263
|
+
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36264
|
+
/* @__PURE__ */ jsx63("div", { className: "uf-h-[460px] uf-overflow-y-auto [scrollbar-width:none] [&::-webkit-scrollbar]:uf-hidden", children: selectedExecution ? /* @__PURE__ */ jsx63(DepositDetailContent, { execution: selectedExecution }) : /* @__PURE__ */ jsx63("div", { className: "uf-space-y-2 uf-pb-8", children: allExecutions.length === 0 ? /* @__PURE__ */ jsx63("div", { className: "uf-py-8 uf-px-4 uf-text-center", children: /* @__PURE__ */ jsx63(
|
|
36265
|
+
"div",
|
|
36266
|
+
{
|
|
36267
|
+
className: "uf-text-sm",
|
|
36268
|
+
style: {
|
|
36269
|
+
color: components.container.subtitleColor,
|
|
36270
|
+
fontFamily: fonts.regular
|
|
36271
|
+
},
|
|
36272
|
+
children: "No deposits yet"
|
|
36273
|
+
}
|
|
36274
|
+
) }) : allExecutions.map((execution) => /* @__PURE__ */ jsx63(
|
|
36275
|
+
DepositExecutionItem,
|
|
36276
|
+
{
|
|
36277
|
+
execution,
|
|
36278
|
+
onClick: () => setSelectedExecution(execution)
|
|
36279
|
+
},
|
|
36280
|
+
execution.id
|
|
36281
|
+
)) }) }),
|
|
36282
|
+
depositPoweredByFooter
|
|
36283
|
+
] })
|
|
36284
|
+
] }) : view === "card" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
36285
|
+
/* @__PURE__ */ jsx63(
|
|
36286
|
+
DepositHeader,
|
|
36287
|
+
{
|
|
36288
|
+
title: cardView === "quotes" ? t8.quotes : depositWithCardTitle,
|
|
36289
|
+
showBack: showBackCard,
|
|
36290
|
+
onBack: handleBack,
|
|
36291
|
+
onClose: handleClose,
|
|
36292
|
+
badge: cardView === "quotes" ? { count: quotesCount } : void 0,
|
|
36293
|
+
showBalance: showBalanceHeader,
|
|
36294
|
+
balanceAddress: recipientAddress,
|
|
36295
|
+
balanceChainType: destinationChainType === "ethereum" || destinationChainType === "solana" || destinationChainType === "bitcoin" || destinationChainType === "n1" ? destinationChainType : void 0,
|
|
36296
|
+
balanceChainId: destinationChainId,
|
|
36297
|
+
balanceTokenAddress: destinationTokenAddress,
|
|
36298
|
+
projectName: projectConfig?.project_name,
|
|
36299
|
+
publishableKey
|
|
36300
|
+
}
|
|
36301
|
+
),
|
|
36302
|
+
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36303
|
+
standaloneNeedsDepositPrereq && depositPrerequisiteBody !== null ? /* @__PURE__ */ jsx63("div", { className: "uf-pb-4 uf-space-y-3", children: depositPrerequisiteBody }) : !showFiatOnramp ? (
|
|
36304
|
+
// Fiat on-ramp resolved hidden/disabled after a direct open
|
|
36305
|
+
// (e.g. platform `is_hidden` for a Stripe Link-only project).
|
|
36306
|
+
// Show a geo-restriction screen rather than the card UI so the
|
|
36307
|
+
// hard-hide is honoured without a flash of "Pay with Card".
|
|
36308
|
+
/* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Card" })
|
|
36309
|
+
) : /* @__PURE__ */ jsx63(
|
|
36310
|
+
BuyWithCard,
|
|
36311
|
+
{
|
|
36312
|
+
userId,
|
|
36313
|
+
publishableKey,
|
|
36314
|
+
view: cardView,
|
|
36315
|
+
onViewChange: handleCardViewChange,
|
|
36316
|
+
destinationTokenSymbol,
|
|
36317
|
+
recipientAddress,
|
|
36318
|
+
destinationChainType,
|
|
36319
|
+
destinationChainId,
|
|
36320
|
+
destinationTokenAddress,
|
|
36321
|
+
onDepositSuccess: onDepositSuccessFor("card"),
|
|
36322
|
+
onDepositError: onDepositErrorFor("card"),
|
|
36323
|
+
onEvent,
|
|
36324
|
+
themeClass,
|
|
36325
|
+
wallets,
|
|
36326
|
+
assetCdnUrl: projectConfig?.asset_cdn_url,
|
|
36327
|
+
hideDepositFlowInfo,
|
|
36328
|
+
hideDisplayDescription
|
|
36329
|
+
}
|
|
36330
|
+
),
|
|
36331
|
+
depositPoweredByFooter
|
|
36332
|
+
] })
|
|
36333
|
+
] }) : view === "exchange" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
36334
|
+
/* @__PURE__ */ jsx63(
|
|
36335
|
+
DepositHeader,
|
|
36336
|
+
{
|
|
36337
|
+
title: payWithExchangeTitle,
|
|
36338
|
+
showBack: exchangeView === "pending" || sessionOpenedFromMenu,
|
|
36339
|
+
onBack: handleBack,
|
|
36340
|
+
onClose: handleClose
|
|
36341
|
+
}
|
|
36342
|
+
),
|
|
36343
|
+
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36344
|
+
/* @__PURE__ */ jsx63(
|
|
36345
|
+
PayWithExchange,
|
|
36346
|
+
{
|
|
36347
|
+
userId,
|
|
36348
|
+
publishableKey,
|
|
36349
|
+
exchanges,
|
|
36350
|
+
view: exchangeView,
|
|
36351
|
+
onViewChange: setExchangeView,
|
|
36352
|
+
destinationTokenSymbol,
|
|
36353
|
+
recipientAddress,
|
|
36354
|
+
destinationChainType,
|
|
36355
|
+
destinationChainId,
|
|
36356
|
+
destinationTokenAddress,
|
|
36357
|
+
onDepositSuccess: onDepositSuccessFor("pay_with_exchange"),
|
|
36358
|
+
onDepositError: onDepositErrorFor("pay_with_exchange"),
|
|
36359
|
+
wallets,
|
|
36360
|
+
defaultToken: defaultToken ?? null
|
|
36361
|
+
}
|
|
36362
|
+
),
|
|
36363
|
+
depositPoweredByFooter
|
|
36364
|
+
] })
|
|
36365
|
+
] }) : view === "coinbase_connect" ? /* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36366
|
+
/* @__PURE__ */ jsx63(
|
|
36367
|
+
CoinbaseConnect,
|
|
36368
|
+
{
|
|
36369
|
+
publishableKey,
|
|
36370
|
+
userId,
|
|
36371
|
+
wallets,
|
|
36372
|
+
recipientAddress,
|
|
36373
|
+
destinationTokenAddress: destinationTokenAddress ?? "",
|
|
36374
|
+
destinationChainId: destinationChainId ?? "",
|
|
36375
|
+
destinationChainType: destinationChainType ?? "",
|
|
36376
|
+
onDepositSuccess: onDepositSuccessFor("exchange_connect"),
|
|
36377
|
+
onDepositError: onDepositErrorFor("exchange_connect"),
|
|
36378
|
+
onTransferError: (error) => {
|
|
36379
|
+
onDepositErrorFor("exchange_connect")?.({
|
|
36380
|
+
message: error.message,
|
|
36381
|
+
error
|
|
36382
|
+
});
|
|
36383
|
+
},
|
|
36384
|
+
onBack: handleBack,
|
|
36385
|
+
onClose: handleClose,
|
|
36386
|
+
onDisconnect: handleExchangeDisconnect,
|
|
36387
|
+
skipToHoldings: coinbaseSkipToHoldings,
|
|
36388
|
+
canGoBack: sessionOpenedFromMenu,
|
|
36389
|
+
onExecutionsChange: setDepositExecutions,
|
|
36390
|
+
defaultSourceChainType,
|
|
36391
|
+
defaultSourceChainId,
|
|
36392
|
+
defaultSourceTokenAddress,
|
|
36393
|
+
defaultSourceSymbol
|
|
36394
|
+
}
|
|
36395
|
+
),
|
|
36396
|
+
depositPoweredByFooter
|
|
36397
|
+
] }) : view === "wallet_connect" ? (
|
|
36398
|
+
// Mobile: flex-fill the full-height dialog body so the wallet list
|
|
36399
|
+
// can grow and scroll, with the footer pinned to the bottom.
|
|
36400
|
+
// Desktop (sm:): stays content-sized.
|
|
36401
|
+
/* @__PURE__ */ jsxs57(
|
|
36402
|
+
"div",
|
|
36403
|
+
{
|
|
36404
|
+
className: "uf-flex uf-flex-col uf-gap-1.5 uf-min-h-0 uf-flex-1 sm:uf-flex-none",
|
|
36405
|
+
children: [
|
|
36406
|
+
/* @__PURE__ */ jsx63(
|
|
36407
|
+
WalletConnect,
|
|
36408
|
+
{
|
|
36409
|
+
walletInfo: browserWalletInfo ?? void 0,
|
|
36410
|
+
depositWallet: browserWalletInfo?.depositWallet ?? void 0,
|
|
36411
|
+
wallets,
|
|
36412
|
+
userId,
|
|
36413
|
+
publishableKey,
|
|
36414
|
+
assetCdnUrl: projectConfig?.asset_cdn_url,
|
|
36415
|
+
projectName: projectConfig?.project_name,
|
|
36416
|
+
onError: (error) => {
|
|
36417
|
+
onDepositErrorFor("wallet_connect")?.({
|
|
36418
|
+
message: error.message,
|
|
36419
|
+
error
|
|
36420
|
+
});
|
|
36421
|
+
},
|
|
36422
|
+
onDepositSuccess: onDepositSuccessFor("wallet_connect"),
|
|
36423
|
+
onDepositError: onDepositErrorFor("wallet_connect"),
|
|
36424
|
+
amountQuickSelect: browserWalletAmountQuickSelect,
|
|
36425
|
+
onWalletDisconnect: handleWalletDisconnect,
|
|
36426
|
+
onWalletConnected: (info, dw) => {
|
|
36427
|
+
setBrowserWalletInfo({ ...info, depositWallet: dw });
|
|
36428
|
+
setStoredWalletState(info.type);
|
|
36429
|
+
setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
|
|
36430
|
+
},
|
|
36431
|
+
onBack: handleBack,
|
|
36432
|
+
onClose: handleClose,
|
|
36433
|
+
defaultSourceChainType,
|
|
36434
|
+
defaultSourceChainId,
|
|
36435
|
+
defaultSourceTokenAddress,
|
|
36436
|
+
defaultSourceSymbol,
|
|
36437
|
+
canGoBack: sessionOpenedFromMenu,
|
|
36438
|
+
depositWalletsLoading: walletsLoading
|
|
36439
|
+
}
|
|
36440
|
+
),
|
|
36441
|
+
depositPoweredByFooter
|
|
36442
|
+
]
|
|
36443
|
+
}
|
|
36444
|
+
)
|
|
36445
|
+
) : view === "bank_transfer" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
36446
|
+
/* @__PURE__ */ jsx63(
|
|
36447
|
+
DepositHeader,
|
|
36448
|
+
{
|
|
36449
|
+
title: t8.bankTransfer.title,
|
|
36450
|
+
showBack: bankTransferView !== "providers" || sessionOpenedFromMenu,
|
|
36451
|
+
onBack: handleBack,
|
|
36452
|
+
onClose: handleClose
|
|
36453
|
+
}
|
|
36454
|
+
),
|
|
36455
|
+
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36456
|
+
bankTransferProvidersLoading ? /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" }) : !hasEnabledBankTransferProvider ? /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Bank Transfer" }) : /* @__PURE__ */ jsx63(
|
|
36457
|
+
BankTransfer,
|
|
36458
|
+
{
|
|
36459
|
+
userId,
|
|
36460
|
+
publishableKey,
|
|
36461
|
+
view: bankTransferView,
|
|
36462
|
+
onViewChange: setBankTransferView,
|
|
36463
|
+
recipientAddress,
|
|
36464
|
+
destinationChainType,
|
|
36465
|
+
destinationChainId,
|
|
36466
|
+
destinationTokenAddress,
|
|
36467
|
+
destinationTokenSymbol,
|
|
36468
|
+
wallets,
|
|
36469
|
+
defaultToken: defaultToken ?? null,
|
|
36470
|
+
assetCdnUrl: projectConfig?.asset_cdn_url,
|
|
36471
|
+
onEvent,
|
|
36472
|
+
onDepositSuccess,
|
|
36473
|
+
onDepositError
|
|
36474
|
+
}
|
|
36475
|
+
),
|
|
36476
|
+
depositPoweredByFooter
|
|
36477
|
+
] })
|
|
36478
|
+
] }) : view === "stripe_link" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
36479
|
+
/* @__PURE__ */ jsx63(
|
|
36480
|
+
DepositHeader,
|
|
36481
|
+
{
|
|
36482
|
+
title: "Deposit with Link",
|
|
36483
|
+
showBack: stripeLinkStep !== "checkout" && stripeLinkStep !== "success",
|
|
36484
|
+
onBack: handleBack,
|
|
36485
|
+
showClose: stripeLinkStep !== "checkout",
|
|
36486
|
+
onClose: handleClose
|
|
36487
|
+
}
|
|
36488
|
+
),
|
|
36489
|
+
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36490
|
+
isLoadingIp ? (
|
|
36491
|
+
// Hold the geo decision until IP resolves so we don't mount
|
|
36492
|
+
// PayWithStripeLink (which kicks off config/OAuth work) for a
|
|
36493
|
+
// deep-link user who turns out to be outside the US.
|
|
36494
|
+
/* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" })
|
|
36495
|
+
) : !showStripeLink ? (
|
|
36496
|
+
// Stripe Link's crypto on-ramp is US-only. On a direct open
|
|
36497
|
+
// (initialScreen="stripe_link") the row isn't in a menu to
|
|
36498
|
+
// fall back to, so show a geo-restriction screen rather than
|
|
36499
|
+
// the Link UI.
|
|
36500
|
+
/* @__PURE__ */ jsx63(
|
|
36501
|
+
GeoRestrictionScreen,
|
|
36502
|
+
{
|
|
36503
|
+
methodName: t8.stripeLink.title,
|
|
36504
|
+
message: "Pay with Link is only available in the US."
|
|
36505
|
+
}
|
|
36506
|
+
)
|
|
36507
|
+
) : /* @__PURE__ */ jsx63(
|
|
36508
|
+
PayWithStripeLink,
|
|
36509
|
+
{
|
|
36510
|
+
userId,
|
|
36511
|
+
publishableKey,
|
|
36512
|
+
recipientAddress,
|
|
36513
|
+
destinationChainType,
|
|
36514
|
+
destinationChainId,
|
|
36515
|
+
destinationTokenAddress,
|
|
36516
|
+
wallets,
|
|
36517
|
+
email: userEmail,
|
|
36518
|
+
iconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/link.svg` : void 0,
|
|
36519
|
+
step: stripeLinkStep,
|
|
36520
|
+
onStepChange: setStripeLinkStep,
|
|
36521
|
+
backHandlerRef: stripeLinkBackRef,
|
|
36522
|
+
onDepositSuccess,
|
|
36523
|
+
onDepositError
|
|
36524
|
+
}
|
|
36525
|
+
),
|
|
36526
|
+
depositPoweredByFooter
|
|
36527
|
+
] })
|
|
36528
|
+
] }) : view === "cashapp" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
36529
|
+
/* @__PURE__ */ jsx63(
|
|
36530
|
+
DepositHeader,
|
|
36531
|
+
{
|
|
36532
|
+
title: cashAppView !== "amount" && cashAppAmount ? `Pay $${cashAppAmount} via Cash App` : "Pay with Cash App",
|
|
36533
|
+
showBack: cashAppView !== "amount" || sessionOpenedFromMenu,
|
|
36534
|
+
onBack: handleBack,
|
|
36535
|
+
onClose: handleClose
|
|
36536
|
+
}
|
|
36537
|
+
),
|
|
36538
|
+
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36539
|
+
/* @__PURE__ */ jsx63(
|
|
36540
|
+
PayWithCashApp,
|
|
36541
|
+
{
|
|
36542
|
+
userId,
|
|
36543
|
+
publishableKey,
|
|
36544
|
+
recipientAddress,
|
|
36545
|
+
destinationChainType,
|
|
36546
|
+
destinationChainId,
|
|
36547
|
+
destinationTokenAddress,
|
|
36548
|
+
cashAppIconUrl: projectConfig?.asset_cdn_url ? `${projectConfig.asset_cdn_url}/api/public/icons/onramps/svg/cashapp.svg` : void 0,
|
|
36549
|
+
view: cashAppView,
|
|
36550
|
+
onViewChange: setCashAppView,
|
|
36551
|
+
onAmountChange: setCashAppAmount,
|
|
36552
|
+
onEvent,
|
|
36553
|
+
onDepositSuccess: onDepositSuccessFor("cashapp"),
|
|
36554
|
+
onDepositError: onDepositErrorFor("cashapp"),
|
|
36555
|
+
wallets
|
|
36556
|
+
}
|
|
36557
|
+
),
|
|
36558
|
+
depositPoweredByFooter
|
|
36559
|
+
] })
|
|
36560
|
+
] }) : view === "apple_pay" ? /* @__PURE__ */ jsxs57(Fragment14, { children: [
|
|
36561
|
+
/* @__PURE__ */ jsx63(
|
|
36562
|
+
DepositHeader,
|
|
36563
|
+
{
|
|
36564
|
+
title: applePayHeaderTitle,
|
|
36565
|
+
showBack: applePayShowBack,
|
|
36566
|
+
onBack: () => {
|
|
36567
|
+
const handled = applePayHandleRef.current?.requestBack() ?? false;
|
|
36568
|
+
if (!handled) handleBack();
|
|
36569
|
+
},
|
|
36570
|
+
onClose: handleClose
|
|
36571
|
+
}
|
|
36572
|
+
),
|
|
36573
|
+
/* @__PURE__ */ jsxs57("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36574
|
+
applePayProvidersLoading ? /* @__PURE__ */ jsx63(SkeletonButton, { variant: "with-icons" }) : !hasEnabledApplePayProvider ? /* @__PURE__ */ jsx63(GeoRestrictionScreen, { methodName: "Apple Pay" }) : /* @__PURE__ */ jsx63(
|
|
36575
|
+
BuyWithApplePay,
|
|
36576
|
+
{
|
|
36577
|
+
ref: applePayHandleRef,
|
|
36578
|
+
userId,
|
|
36579
|
+
publishableKey,
|
|
36580
|
+
destinationChainType,
|
|
36581
|
+
destinationChainId,
|
|
36582
|
+
destinationTokenAddress,
|
|
36583
|
+
userEmail,
|
|
36584
|
+
wallets,
|
|
36585
|
+
onViewChange: setApplePayView,
|
|
36586
|
+
onEvent,
|
|
36587
|
+
onDepositSuccess: onDepositSuccessFor("apple_pay"),
|
|
36588
|
+
onDepositError: onDepositErrorFor("apple_pay"),
|
|
36589
|
+
exitLabel: sessionOpenedFromMenu ? "Return" : "Close",
|
|
36590
|
+
onExit: () => {
|
|
36591
|
+
if (sessionOpenedFromMenu) {
|
|
36592
|
+
setView("main");
|
|
36593
|
+
} else {
|
|
36594
|
+
handleClose();
|
|
36595
|
+
}
|
|
36596
|
+
}
|
|
36597
|
+
}
|
|
36598
|
+
),
|
|
36599
|
+
depositPoweredByFooter
|
|
36600
|
+
] })
|
|
36601
|
+
] }) : null
|
|
36602
|
+
}
|
|
36603
|
+
)
|
|
35755
36604
|
]
|
|
35756
36605
|
}
|
|
35757
36606
|
)
|
|
@@ -35930,11 +36779,11 @@ function CheckoutModal({
|
|
|
35930
36779
|
);
|
|
35931
36780
|
}
|
|
35932
36781
|
}, [emitCheckoutSuccess, paymentIntent, view]);
|
|
35933
|
-
const wallets =
|
|
36782
|
+
const wallets = useMemo142(() => {
|
|
35934
36783
|
if (!paymentIntent) return [];
|
|
35935
36784
|
return mapDepositAddressesToWallets(paymentIntent.deposit_addresses, paymentIntent);
|
|
35936
36785
|
}, [paymentIntent]);
|
|
35937
|
-
const formatCryptoAmount =
|
|
36786
|
+
const formatCryptoAmount = useMemo142(() => {
|
|
35938
36787
|
if (!paymentIntent) return (_) => "";
|
|
35939
36788
|
const decimals = paymentIntent.destination_token_decimals ?? 6;
|
|
35940
36789
|
const symbol = paymentIntent.currency.toUpperCase();
|
|
@@ -35944,7 +36793,7 @@ function CheckoutModal({
|
|
|
35944
36793
|
return `${formatted} ${symbol}`;
|
|
35945
36794
|
};
|
|
35946
36795
|
}, [paymentIntent]);
|
|
35947
|
-
const remainingAmountUsd =
|
|
36796
|
+
const remainingAmountUsd = useMemo142(() => {
|
|
35948
36797
|
if (!paymentIntent) return void 0;
|
|
35949
36798
|
const total = parseFloat(paymentIntent.destination_amount_usd || paymentIntent.amount_usd);
|
|
35950
36799
|
const received = parseFloat(
|
|
@@ -35956,7 +36805,7 @@ function CheckoutModal({
|
|
|
35956
36805
|
return remaining > 0 ? remaining.toFixed(2) : "0.00";
|
|
35957
36806
|
}, [paymentIntent]);
|
|
35958
36807
|
const [selectedSource, setSelectedSource] = useState41(null);
|
|
35959
|
-
const remainingDestinationAmount =
|
|
36808
|
+
const remainingDestinationAmount = useMemo142(() => {
|
|
35960
36809
|
if (!paymentIntent) return "0";
|
|
35961
36810
|
const remaining = BigInt(paymentIntent.destination_amount) - BigInt(paymentIntent.destination_amount_received);
|
|
35962
36811
|
return remaining > 0n ? remaining.toString() : "0";
|
|
@@ -35978,7 +36827,7 @@ function CheckoutModal({
|
|
|
35978
36827
|
stablecoinParity: paymentIntent?.stablecoin_parity ?? false,
|
|
35979
36828
|
enabled: open && view === "transfer" && !!paymentIntent && !!selectedSource && remainingDestinationAmount !== "0"
|
|
35980
36829
|
});
|
|
35981
|
-
const effectiveCheckoutQuote =
|
|
36830
|
+
const effectiveCheckoutQuote = useMemo142(() => {
|
|
35982
36831
|
if (!sourceQuote || !selectedSource) return null;
|
|
35983
36832
|
const baseQuote = {
|
|
35984
36833
|
sourceAmount: sourceQuote.source_amount,
|
|
@@ -36190,253 +37039,275 @@ function CheckoutModal({
|
|
|
36190
37039
|
return /* @__PURE__ */ jsx64(PortalContainerProvider, { value: null, children: /* @__PURE__ */ jsx64(Dialog2, { open, onOpenChange: handleClose, modal: true, children: /* @__PURE__ */ jsx64(
|
|
36191
37040
|
DialogContent2,
|
|
36192
37041
|
{
|
|
36193
|
-
className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[60vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${
|
|
37042
|
+
className: `sm:uf-max-w-[400px] uf-border-secondary uf-text-foreground uf-gap-0 [&>button]:uf-hidden uf-p-0 uf-overflow-visible ${view === "main" ? "!uf-top-auto !uf-h-auto !uf-max-h-[60vh] sm:!uf-max-h-none sm:!uf-top-[50%]" : "!uf-top-0 !uf-h-full sm:!uf-h-auto sm:!uf-top-[50%]"} ${// wallet_connect fills the full-height mobile sheet. DialogContent is a
|
|
37043
|
+
// grid whose single auto row only grows to fill free space and never
|
|
37044
|
+
// shrinks below content, so a long wallet list would balloon the row
|
|
37045
|
+
// past the viewport and push the footer off-screen. Clamp the row to
|
|
37046
|
+
// the modal height with minmax(0,1fr) so the inner overflow-y-auto list
|
|
37047
|
+
// scrolls with the footer pinned. Reset to content-sized on desktop.
|
|
37048
|
+
view === "wallet_connect" ? "[grid-template-rows:minmax(0,1fr)] sm:[grid-template-rows:none]" : ""} ${themeClass}`,
|
|
36194
37049
|
style: { backgroundColor: colors2.background },
|
|
36195
37050
|
onPointerDownOutside: (e) => e.preventDefault(),
|
|
36196
37051
|
onInteractOutside: (e) => e.preventDefault(),
|
|
36197
|
-
children: /* @__PURE__ */ jsx64(
|
|
36198
|
-
|
|
36199
|
-
|
|
36200
|
-
|
|
36201
|
-
|
|
36202
|
-
|
|
36203
|
-
|
|
36204
|
-
|
|
36205
|
-
|
|
36206
|
-
|
|
36207
|
-
|
|
36208
|
-
|
|
36209
|
-
|
|
36210
|
-
|
|
36211
|
-
|
|
36212
|
-
|
|
37052
|
+
children: /* @__PURE__ */ jsx64(
|
|
37053
|
+
ThemeStyleInjector,
|
|
37054
|
+
{
|
|
37055
|
+
className: view === "wallet_connect" ? "uf-flex uf-min-h-0 uf-flex-col" : void 0,
|
|
37056
|
+
children: view === "main" ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
|
|
37057
|
+
/* @__PURE__ */ jsx64(DepositHeader, { title: modalTitle || "Checkout", showClose: true, onClose: handleClose }),
|
|
37058
|
+
/* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
37059
|
+
piLoading ? /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-3", children: [
|
|
37060
|
+
/* @__PURE__ */ jsx64(
|
|
37061
|
+
"div",
|
|
37062
|
+
{
|
|
37063
|
+
className: "uf-rounded-xl uf-p-4 uf-animate-pulse",
|
|
37064
|
+
style: {
|
|
37065
|
+
backgroundColor: components.card.backgroundColor,
|
|
37066
|
+
borderRadius: components.card.borderRadius,
|
|
37067
|
+
border: `${components.card.borderWidth}px solid ${components.card.borderColor}`
|
|
37068
|
+
},
|
|
37069
|
+
children: /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-items-center uf-gap-2", children: [
|
|
37070
|
+
/* @__PURE__ */ jsx64(
|
|
37071
|
+
"div",
|
|
37072
|
+
{
|
|
37073
|
+
className: "uf-h-8 uf-w-24 uf-rounded",
|
|
37074
|
+
style: {
|
|
37075
|
+
backgroundColor: components.card.borderColor
|
|
37076
|
+
}
|
|
37077
|
+
}
|
|
37078
|
+
),
|
|
37079
|
+
/* @__PURE__ */ jsx64(
|
|
37080
|
+
"div",
|
|
37081
|
+
{
|
|
37082
|
+
className: "uf-h-4 uf-w-16 uf-rounded",
|
|
37083
|
+
style: {
|
|
37084
|
+
backgroundColor: components.card.borderColor
|
|
37085
|
+
}
|
|
37086
|
+
}
|
|
37087
|
+
)
|
|
37088
|
+
] })
|
|
37089
|
+
}
|
|
37090
|
+
),
|
|
37091
|
+
/* @__PURE__ */ jsx64(SkeletonButton2, {}),
|
|
37092
|
+
/* @__PURE__ */ jsx64(SkeletonButton2, {})
|
|
37093
|
+
] }) : piError ? /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
|
|
37094
|
+
/* @__PURE__ */ jsx64("div", { className: "uf-w-16 uf-h-16 uf-rounded-full uf-bg-muted uf-flex uf-items-center uf-justify-center uf-mb-4", children: /* @__PURE__ */ jsx64(TriangleAlert, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
|
|
37095
|
+
/* @__PURE__ */ jsx64(
|
|
37096
|
+
"h3",
|
|
37097
|
+
{
|
|
37098
|
+
className: "uf-text-lg uf-font-semibold uf-mb-2",
|
|
37099
|
+
style: {
|
|
37100
|
+
color: colors2.foreground,
|
|
37101
|
+
fontFamily: fonts.semibold
|
|
37102
|
+
},
|
|
37103
|
+
children: "Unable to Load Checkout"
|
|
37104
|
+
}
|
|
37105
|
+
),
|
|
37106
|
+
/* @__PURE__ */ jsx64(
|
|
37107
|
+
"p",
|
|
37108
|
+
{
|
|
37109
|
+
className: "uf-text-sm uf-max-w-[280px]",
|
|
37110
|
+
style: {
|
|
37111
|
+
color: colors2.foregroundMuted,
|
|
37112
|
+
fontFamily: fonts.regular
|
|
37113
|
+
},
|
|
37114
|
+
children: piError instanceof Error ? piError.message : "Something went wrong. Please try again."
|
|
37115
|
+
}
|
|
37116
|
+
)
|
|
37117
|
+
] }) : paymentIntent ? /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-3", children: [
|
|
37118
|
+
progressSection,
|
|
37119
|
+
(paymentIntent.status === "requires_payment" || paymentIntent.status === "processing") && /* @__PURE__ */ jsxs58(Fragment15, { children: [
|
|
37120
|
+
showTransferCrypto && /* @__PURE__ */ jsx64(
|
|
37121
|
+
TransferCryptoButton,
|
|
36213
37122
|
{
|
|
36214
|
-
|
|
36215
|
-
|
|
36216
|
-
|
|
36217
|
-
}
|
|
37123
|
+
onClick: () => {
|
|
37124
|
+
lastCheckoutMethodRef.current = "transfer";
|
|
37125
|
+
setView("transfer");
|
|
37126
|
+
},
|
|
37127
|
+
title: i18n2.checkoutModal.transferCrypto.title,
|
|
37128
|
+
subtitle: i18n2.checkoutModal.transferCrypto.subtitle,
|
|
37129
|
+
featuredTokens: projectConfig?.transfer_crypto.networks
|
|
36218
37130
|
}
|
|
36219
37131
|
),
|
|
36220
|
-
/* @__PURE__ */ jsx64(
|
|
36221
|
-
|
|
37132
|
+
showConnectWallet && /* @__PURE__ */ jsx64(
|
|
37133
|
+
BrowserWalletButton,
|
|
36222
37134
|
{
|
|
36223
|
-
|
|
36224
|
-
|
|
36225
|
-
|
|
36226
|
-
|
|
37135
|
+
onClick: handleBrowserWalletClick,
|
|
37136
|
+
onConnectClick: handleWalletConnectClick,
|
|
37137
|
+
onDisconnect: handleWalletDisconnect,
|
|
37138
|
+
chainType: browserWalletChainType,
|
|
37139
|
+
publishableKey,
|
|
37140
|
+
featuredWallets: projectConfig?.connect_wallet?.wallets,
|
|
37141
|
+
subtitle: i18n2.checkoutModal.browserWallet.subtitle
|
|
36227
37142
|
}
|
|
36228
37143
|
)
|
|
36229
37144
|
] })
|
|
36230
|
-
}
|
|
36231
|
-
|
|
36232
|
-
|
|
36233
|
-
|
|
36234
|
-
] }) : piError ? /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-items-center uf-justify-center uf-py-8 uf-px-4 uf-text-center", children: [
|
|
36235
|
-
/* @__PURE__ */ jsx64("div", { className: "uf-w-16 uf-h-16 uf-rounded-full uf-bg-muted uf-flex uf-items-center uf-justify-center uf-mb-4", children: /* @__PURE__ */ jsx64(TriangleAlert, { className: "uf-w-8 uf-h-8 uf-text-muted-foreground" }) }),
|
|
37145
|
+
] }) : null,
|
|
37146
|
+
poweredByFooter
|
|
37147
|
+
] })
|
|
37148
|
+
] }) : view === "transfer" ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
|
|
36236
37149
|
/* @__PURE__ */ jsx64(
|
|
36237
|
-
|
|
37150
|
+
DepositHeader,
|
|
36238
37151
|
{
|
|
36239
|
-
|
|
36240
|
-
|
|
36241
|
-
|
|
36242
|
-
|
|
36243
|
-
},
|
|
36244
|
-
children: "Unable to Load Checkout"
|
|
37152
|
+
title: modalTitle || "Checkout",
|
|
37153
|
+
showBack: true,
|
|
37154
|
+
onBack: handleBack,
|
|
37155
|
+
onClose: handleClose
|
|
36245
37156
|
}
|
|
36246
37157
|
),
|
|
36247
|
-
/* @__PURE__ */
|
|
36248
|
-
|
|
36249
|
-
|
|
36250
|
-
|
|
36251
|
-
|
|
36252
|
-
|
|
36253
|
-
|
|
36254
|
-
|
|
36255
|
-
|
|
36256
|
-
|
|
36257
|
-
|
|
36258
|
-
|
|
36259
|
-
|
|
36260
|
-
|
|
36261
|
-
|
|
36262
|
-
|
|
36263
|
-
|
|
36264
|
-
|
|
36265
|
-
|
|
36266
|
-
|
|
36267
|
-
|
|
36268
|
-
|
|
36269
|
-
|
|
36270
|
-
|
|
36271
|
-
|
|
36272
|
-
|
|
36273
|
-
|
|
36274
|
-
|
|
36275
|
-
|
|
36276
|
-
|
|
36277
|
-
|
|
36278
|
-
|
|
36279
|
-
|
|
36280
|
-
|
|
36281
|
-
|
|
36282
|
-
subtitle: i18n2.checkoutModal.browserWallet.subtitle
|
|
36283
|
-
}
|
|
36284
|
-
)
|
|
36285
|
-
] })
|
|
36286
|
-
] }) : null,
|
|
36287
|
-
poweredByFooter
|
|
36288
|
-
] })
|
|
36289
|
-
] }) : view === "transfer" ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
|
|
36290
|
-
/* @__PURE__ */ jsx64(
|
|
36291
|
-
DepositHeader,
|
|
36292
|
-
{
|
|
36293
|
-
title: modalTitle || "Checkout",
|
|
36294
|
-
showBack: true,
|
|
36295
|
-
onBack: handleBack,
|
|
36296
|
-
onClose: handleClose
|
|
36297
|
-
}
|
|
36298
|
-
),
|
|
36299
|
-
/* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36300
|
-
paymentIntent ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
|
|
36301
|
-
(() => {
|
|
36302
|
-
const receivedUsd = parseFloat(
|
|
36303
|
-
paymentIntent.destination_amount_received_usd || paymentIntent.amount_received_usd
|
|
36304
|
-
);
|
|
36305
|
-
const totalUsd = parseFloat(
|
|
36306
|
-
paymentIntent.destination_amount_usd || paymentIntent.amount_usd
|
|
36307
|
-
);
|
|
36308
|
-
const pct = totalUsd > 0 ? Math.min(receivedUsd / totalUsd * 100, 100) : 0;
|
|
36309
|
-
return /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-2", children: [
|
|
36310
|
-
/* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-items-center uf-justify-between", children: [
|
|
36311
|
-
/* @__PURE__ */ jsx64(
|
|
36312
|
-
"span",
|
|
36313
|
-
{
|
|
36314
|
-
className: "uf-text-xs",
|
|
36315
|
-
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
36316
|
-
children: "Received"
|
|
36317
|
-
}
|
|
36318
|
-
),
|
|
36319
|
-
/* @__PURE__ */ jsxs58(
|
|
36320
|
-
"span",
|
|
36321
|
-
{
|
|
36322
|
-
className: "uf-text-xs",
|
|
36323
|
-
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
36324
|
-
children: [
|
|
36325
|
-
"$",
|
|
36326
|
-
receivedUsd.toFixed(2),
|
|
36327
|
-
" / $",
|
|
36328
|
-
totalUsd.toFixed(2)
|
|
36329
|
-
]
|
|
36330
|
-
}
|
|
36331
|
-
)
|
|
36332
|
-
] }),
|
|
36333
|
-
/* @__PURE__ */ jsx64(
|
|
36334
|
-
"div",
|
|
36335
|
-
{
|
|
36336
|
-
className: "uf-w-full uf-h-1.5 uf-rounded-full uf-overflow-hidden",
|
|
36337
|
-
style: { backgroundColor: colors2.border },
|
|
36338
|
-
children: /* @__PURE__ */ jsx64(
|
|
37158
|
+
/* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
37159
|
+
paymentIntent ? /* @__PURE__ */ jsxs58(Fragment15, { children: [
|
|
37160
|
+
(() => {
|
|
37161
|
+
const receivedUsd = parseFloat(
|
|
37162
|
+
paymentIntent.destination_amount_received_usd || paymentIntent.amount_received_usd
|
|
37163
|
+
);
|
|
37164
|
+
const totalUsd = parseFloat(
|
|
37165
|
+
paymentIntent.destination_amount_usd || paymentIntent.amount_usd
|
|
37166
|
+
);
|
|
37167
|
+
const pct = totalUsd > 0 ? Math.min(receivedUsd / totalUsd * 100, 100) : 0;
|
|
37168
|
+
return /* @__PURE__ */ jsxs58("div", { className: "uf-space-y-2", children: [
|
|
37169
|
+
/* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-items-center uf-justify-between", children: [
|
|
37170
|
+
/* @__PURE__ */ jsx64(
|
|
37171
|
+
"span",
|
|
37172
|
+
{
|
|
37173
|
+
className: "uf-text-xs",
|
|
37174
|
+
style: { color: colors2.foregroundMuted, fontFamily: fonts.regular },
|
|
37175
|
+
children: "Received"
|
|
37176
|
+
}
|
|
37177
|
+
),
|
|
37178
|
+
/* @__PURE__ */ jsxs58(
|
|
37179
|
+
"span",
|
|
37180
|
+
{
|
|
37181
|
+
className: "uf-text-xs",
|
|
37182
|
+
style: { color: colors2.foreground, fontFamily: fonts.medium },
|
|
37183
|
+
children: [
|
|
37184
|
+
"$",
|
|
37185
|
+
receivedUsd.toFixed(2),
|
|
37186
|
+
" / $",
|
|
37187
|
+
totalUsd.toFixed(2)
|
|
37188
|
+
]
|
|
37189
|
+
}
|
|
37190
|
+
)
|
|
37191
|
+
] }),
|
|
37192
|
+
/* @__PURE__ */ jsx64(
|
|
36339
37193
|
"div",
|
|
36340
37194
|
{
|
|
36341
|
-
className: "uf-
|
|
36342
|
-
style: {
|
|
36343
|
-
|
|
36344
|
-
|
|
36345
|
-
|
|
37195
|
+
className: "uf-w-full uf-h-1.5 uf-rounded-full uf-overflow-hidden",
|
|
37196
|
+
style: { backgroundColor: colors2.border },
|
|
37197
|
+
children: /* @__PURE__ */ jsx64(
|
|
37198
|
+
"div",
|
|
37199
|
+
{
|
|
37200
|
+
className: "uf-h-full uf-rounded-full uf-transition-all uf-duration-500",
|
|
37201
|
+
style: {
|
|
37202
|
+
width: `${pct}%`,
|
|
37203
|
+
backgroundColor: paymentIntent.status === "succeeded" ? "rgb(34, 197, 94)" : colors2.primary
|
|
37204
|
+
}
|
|
37205
|
+
}
|
|
37206
|
+
)
|
|
36346
37207
|
}
|
|
36347
37208
|
)
|
|
37209
|
+
] });
|
|
37210
|
+
})(),
|
|
37211
|
+
/* @__PURE__ */ jsx64(
|
|
37212
|
+
TransferCryptoSingleInput,
|
|
37213
|
+
{
|
|
37214
|
+
userId: paymentIntent.user_id || "",
|
|
37215
|
+
publishableKey,
|
|
37216
|
+
clientSecret,
|
|
37217
|
+
recipientAddress: paymentIntent.recipient_address,
|
|
37218
|
+
destinationChainType: paymentIntent.destination_chain_type,
|
|
37219
|
+
destinationChainId: paymentIntent.destination_chain_id,
|
|
37220
|
+
destinationTokenAddress: paymentIntent.destination_token_address,
|
|
37221
|
+
defaultSourceChainType,
|
|
37222
|
+
defaultSourceChainId,
|
|
37223
|
+
defaultSourceTokenAddress,
|
|
37224
|
+
defaultSourceSymbol,
|
|
37225
|
+
depositConfirmationMode: "auto_ui",
|
|
37226
|
+
wallets,
|
|
37227
|
+
onSourceTokenChange: setSelectedSource,
|
|
37228
|
+
persistCheckingIndicator: true,
|
|
37229
|
+
productType: "payment",
|
|
37230
|
+
checkoutQuote: effectiveCheckoutQuote,
|
|
37231
|
+
isCheckoutQuoteLoading: isQuoteLoading || isQuoteFetching
|
|
36348
37232
|
}
|
|
36349
37233
|
)
|
|
36350
|
-
] })
|
|
36351
|
-
|
|
36352
|
-
|
|
36353
|
-
|
|
37234
|
+
] }) : /* @__PURE__ */ jsx64(SkeletonButton2, {}),
|
|
37235
|
+
poweredByFooter
|
|
37236
|
+
] })
|
|
37237
|
+
] }) : view === "wallet_connect" && paymentIntent ? (
|
|
37238
|
+
// Mobile: flex-fill the full-height sheet so the wallet list grows and
|
|
37239
|
+
// scrolls with the footer pinned. Desktop (sm:): content-sized.
|
|
37240
|
+
/* @__PURE__ */ jsxs58(
|
|
37241
|
+
"div",
|
|
36354
37242
|
{
|
|
36355
|
-
|
|
36356
|
-
|
|
36357
|
-
|
|
36358
|
-
|
|
36359
|
-
|
|
36360
|
-
|
|
36361
|
-
|
|
36362
|
-
|
|
36363
|
-
|
|
36364
|
-
|
|
36365
|
-
|
|
36366
|
-
|
|
36367
|
-
|
|
36368
|
-
|
|
36369
|
-
|
|
36370
|
-
|
|
36371
|
-
|
|
36372
|
-
|
|
37243
|
+
className: "uf-flex uf-flex-col uf-gap-1.5 uf-min-h-0 uf-flex-1 sm:uf-flex-none",
|
|
37244
|
+
children: [
|
|
37245
|
+
/* @__PURE__ */ jsx64(
|
|
37246
|
+
WalletConnect,
|
|
37247
|
+
{
|
|
37248
|
+
walletInfo: browserWalletInfo ?? void 0,
|
|
37249
|
+
depositWallet: browserWalletInfo?.depositWallet ?? void 0,
|
|
37250
|
+
wallets,
|
|
37251
|
+
userId: paymentIntent.user_id || "",
|
|
37252
|
+
publishableKey,
|
|
37253
|
+
clientSecret,
|
|
37254
|
+
prefillAmountUsd: remainingAmountUsd,
|
|
37255
|
+
checkoutAmountUsd: paymentIntent.amount_usd,
|
|
37256
|
+
checkoutReceivedUsd: paymentIntent.amount_received_usd,
|
|
37257
|
+
checkoutDestination: {
|
|
37258
|
+
chainType: paymentIntent.destination_chain_type,
|
|
37259
|
+
chainId: paymentIntent.destination_chain_id,
|
|
37260
|
+
tokenAddress: paymentIntent.destination_token_address,
|
|
37261
|
+
decimals: paymentIntent.destination_token_decimals ?? 6
|
|
37262
|
+
},
|
|
37263
|
+
productType: "payment",
|
|
37264
|
+
stablecoinParity: paymentIntent.stablecoin_parity ?? false,
|
|
37265
|
+
checkoutRemainingBaseUnits: (() => {
|
|
37266
|
+
const remaining = BigInt(paymentIntent.amount) - BigInt(paymentIntent.amount_received);
|
|
37267
|
+
return remaining > 0n ? remaining.toString() : "0";
|
|
37268
|
+
})(),
|
|
37269
|
+
onSuccess: (_txHash) => {
|
|
37270
|
+
emitCheckoutSuccess(
|
|
37271
|
+
{
|
|
37272
|
+
paymentIntentId: paymentIntent.id,
|
|
37273
|
+
status: "processing",
|
|
37274
|
+
paymentIntent
|
|
37275
|
+
},
|
|
37276
|
+
"wallet_connect"
|
|
37277
|
+
);
|
|
37278
|
+
},
|
|
37279
|
+
onError: (error) => {
|
|
37280
|
+
onCheckoutError?.({
|
|
37281
|
+
message: error.message,
|
|
37282
|
+
error,
|
|
37283
|
+
method: "wallet_connect"
|
|
37284
|
+
});
|
|
37285
|
+
},
|
|
37286
|
+
onWalletDisconnect: handleWalletDisconnect,
|
|
37287
|
+
onWalletConnected: (info, dw) => {
|
|
37288
|
+
setBrowserWalletInfo({ ...info, depositWallet: dw });
|
|
37289
|
+
setStoredWalletState(info.type);
|
|
37290
|
+
setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
|
|
37291
|
+
lastCheckoutMethodRef.current = "wallet_connect";
|
|
37292
|
+
},
|
|
37293
|
+
onNewDeposit: () => setView("main"),
|
|
37294
|
+
onDone: () => setView("main"),
|
|
37295
|
+
paymentIntentStatus: paymentIntent.status,
|
|
37296
|
+
onBack: handleBack,
|
|
37297
|
+
onClose: handleClose,
|
|
37298
|
+
defaultSourceChainType,
|
|
37299
|
+
defaultSourceChainId,
|
|
37300
|
+
defaultSourceTokenAddress,
|
|
37301
|
+
defaultSourceSymbol
|
|
37302
|
+
}
|
|
37303
|
+
),
|
|
37304
|
+
poweredByFooter
|
|
37305
|
+
]
|
|
36373
37306
|
}
|
|
36374
37307
|
)
|
|
36375
|
-
|
|
36376
|
-
|
|
36377
|
-
|
|
36378
|
-
] }) : view === "wallet_connect" && paymentIntent ? /* @__PURE__ */ jsxs58("div", { className: "uf-flex uf-flex-col uf-gap-1.5", children: [
|
|
36379
|
-
/* @__PURE__ */ jsx64(
|
|
36380
|
-
WalletConnect,
|
|
36381
|
-
{
|
|
36382
|
-
walletInfo: browserWalletInfo ?? void 0,
|
|
36383
|
-
depositWallet: browserWalletInfo?.depositWallet ?? void 0,
|
|
36384
|
-
wallets,
|
|
36385
|
-
userId: paymentIntent.user_id || "",
|
|
36386
|
-
publishableKey,
|
|
36387
|
-
clientSecret,
|
|
36388
|
-
prefillAmountUsd: remainingAmountUsd,
|
|
36389
|
-
checkoutAmountUsd: paymentIntent.amount_usd,
|
|
36390
|
-
checkoutReceivedUsd: paymentIntent.amount_received_usd,
|
|
36391
|
-
checkoutDestination: {
|
|
36392
|
-
chainType: paymentIntent.destination_chain_type,
|
|
36393
|
-
chainId: paymentIntent.destination_chain_id,
|
|
36394
|
-
tokenAddress: paymentIntent.destination_token_address,
|
|
36395
|
-
decimals: paymentIntent.destination_token_decimals ?? 6
|
|
36396
|
-
},
|
|
36397
|
-
productType: "payment",
|
|
36398
|
-
stablecoinParity: paymentIntent.stablecoin_parity ?? false,
|
|
36399
|
-
checkoutRemainingBaseUnits: (() => {
|
|
36400
|
-
const remaining = BigInt(paymentIntent.amount) - BigInt(paymentIntent.amount_received);
|
|
36401
|
-
return remaining > 0n ? remaining.toString() : "0";
|
|
36402
|
-
})(),
|
|
36403
|
-
onSuccess: (_txHash) => {
|
|
36404
|
-
emitCheckoutSuccess(
|
|
36405
|
-
{
|
|
36406
|
-
paymentIntentId: paymentIntent.id,
|
|
36407
|
-
status: "processing",
|
|
36408
|
-
paymentIntent
|
|
36409
|
-
},
|
|
36410
|
-
"wallet_connect"
|
|
36411
|
-
);
|
|
36412
|
-
},
|
|
36413
|
-
onError: (error) => {
|
|
36414
|
-
onCheckoutError?.({
|
|
36415
|
-
message: error.message,
|
|
36416
|
-
error,
|
|
36417
|
-
method: "wallet_connect"
|
|
36418
|
-
});
|
|
36419
|
-
},
|
|
36420
|
-
onWalletDisconnect: handleWalletDisconnect,
|
|
36421
|
-
onWalletConnected: (info, dw) => {
|
|
36422
|
-
setBrowserWalletInfo({ ...info, depositWallet: dw });
|
|
36423
|
-
setStoredWalletState(info.type);
|
|
36424
|
-
setBrowserWalletChainType(dw.chain_type === "solana" ? "solana" : "ethereum");
|
|
36425
|
-
lastCheckoutMethodRef.current = "wallet_connect";
|
|
36426
|
-
},
|
|
36427
|
-
onNewDeposit: () => setView("main"),
|
|
36428
|
-
onDone: () => setView("main"),
|
|
36429
|
-
paymentIntentStatus: paymentIntent.status,
|
|
36430
|
-
onBack: handleBack,
|
|
36431
|
-
onClose: handleClose,
|
|
36432
|
-
defaultSourceChainType,
|
|
36433
|
-
defaultSourceChainId,
|
|
36434
|
-
defaultSourceTokenAddress,
|
|
36435
|
-
defaultSourceSymbol
|
|
36436
|
-
}
|
|
36437
|
-
),
|
|
36438
|
-
poweredByFooter
|
|
36439
|
-
] }) : null })
|
|
37308
|
+
) : null
|
|
37309
|
+
}
|
|
37310
|
+
)
|
|
36440
37311
|
}
|
|
36441
37312
|
) }) });
|
|
36442
37313
|
}
|
|
@@ -37013,7 +37884,7 @@ function useHypercoreWithdrawActivation(params) {
|
|
|
37013
37884
|
actionType: ActionType.Withdraw,
|
|
37014
37885
|
enabled: enabled && isHypercore(sourceChainId)
|
|
37015
37886
|
});
|
|
37016
|
-
const depositWalletAddress =
|
|
37887
|
+
const depositWalletAddress = useMemo15(() => {
|
|
37017
37888
|
const wallets = depositWalletLookup.data?.data ?? [];
|
|
37018
37889
|
return wallets.find((w) => w.chain_type === sourceChainType)?.address;
|
|
37019
37890
|
}, [depositWalletLookup.data, sourceChainType]);
|
|
@@ -37132,7 +38003,7 @@ function WithdrawForm({
|
|
|
37132
38003
|
enabled: debouncedAddress.length > 5 && !!selectedChain
|
|
37133
38004
|
});
|
|
37134
38005
|
const isDebouncing = trimmedAddress !== debouncedAddress;
|
|
37135
|
-
const addressError =
|
|
38006
|
+
const addressError = useMemo16(() => {
|
|
37136
38007
|
if (!trimmedAddress || trimmedAddress.length <= 5) return null;
|
|
37137
38008
|
if (isDebouncing || isVerifyingAddress) return null;
|
|
37138
38009
|
if (verifyError) return t10.invalidAddress;
|
|
@@ -37166,33 +38037,33 @@ function WithdrawForm({
|
|
|
37166
38037
|
destinationTokenAddress: selectedChain?.token_address,
|
|
37167
38038
|
enabled: isAddressValid
|
|
37168
38039
|
});
|
|
37169
|
-
const exchangeRate =
|
|
38040
|
+
const exchangeRate = useMemo16(() => {
|
|
37170
38041
|
if (!balanceData?.exchangeRate) return 0;
|
|
37171
38042
|
return parseFloat(balanceData.exchangeRate);
|
|
37172
38043
|
}, [balanceData]);
|
|
37173
|
-
const balanceCrypto =
|
|
38044
|
+
const balanceCrypto = useMemo16(() => {
|
|
37174
38045
|
if (!balanceData?.balanceHuman) return 0;
|
|
37175
38046
|
return parseFloat(balanceData.balanceHuman);
|
|
37176
38047
|
}, [balanceData]);
|
|
37177
|
-
const balanceUsdNum =
|
|
38048
|
+
const balanceUsdNum = useMemo16(() => {
|
|
37178
38049
|
if (!balanceData?.balanceUsd) return 0;
|
|
37179
38050
|
return parseFloat(balanceData.balanceUsd);
|
|
37180
38051
|
}, [balanceData]);
|
|
37181
38052
|
const tokenSymbol = sourceTokenSymbol || balanceData?.symbol || "TOKEN";
|
|
37182
38053
|
const sourceDecimals = balanceData?.decimals ?? 6;
|
|
37183
|
-
const cryptoAmountFromInput =
|
|
38054
|
+
const cryptoAmountFromInput = useMemo16(() => {
|
|
37184
38055
|
const val = parseFloat(amount);
|
|
37185
38056
|
if (!val || val <= 0) return 0;
|
|
37186
38057
|
if (inputUnit === "crypto") return val;
|
|
37187
38058
|
return exchangeRate > 0 ? val / exchangeRate : 0;
|
|
37188
38059
|
}, [amount, inputUnit, exchangeRate]);
|
|
37189
|
-
const fiatAmountFromInput =
|
|
38060
|
+
const fiatAmountFromInput = useMemo16(() => {
|
|
37190
38061
|
const val = parseFloat(amount);
|
|
37191
38062
|
if (!val || val <= 0) return 0;
|
|
37192
38063
|
if (inputUnit === "fiat") return val;
|
|
37193
38064
|
return val * exchangeRate;
|
|
37194
38065
|
}, [amount, inputUnit, exchangeRate]);
|
|
37195
|
-
const convertedDisplay =
|
|
38066
|
+
const convertedDisplay = useMemo16(() => {
|
|
37196
38067
|
if (!amount || parseFloat(amount) <= 0) return null;
|
|
37197
38068
|
if (inputUnit === "crypto") {
|
|
37198
38069
|
return `$${fiatAmountFromInput.toLocaleString(void 0, { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
@@ -37211,7 +38082,7 @@ function WithdrawForm({
|
|
|
37211
38082
|
isMaxed,
|
|
37212
38083
|
isStablecoin
|
|
37213
38084
|
]);
|
|
37214
|
-
const balanceDisplay =
|
|
38085
|
+
const balanceDisplay = useMemo16(() => {
|
|
37215
38086
|
if (isLoadingBalance || !balanceData) return null;
|
|
37216
38087
|
if (inputUnit === "crypto") {
|
|
37217
38088
|
const displayDecimals = isStablecoin ? 2 : 6;
|
|
@@ -38651,7 +39522,7 @@ function UnifoldProvider2({
|
|
|
38651
39522
|
withdrawPromiseRef.current = null;
|
|
38652
39523
|
}
|
|
38653
39524
|
}, []);
|
|
38654
|
-
const contextValue =
|
|
39525
|
+
const contextValue = useMemo18(
|
|
38655
39526
|
() => ({
|
|
38656
39527
|
beginDeposit,
|
|
38657
39528
|
closeDeposit,
|
|
@@ -38746,7 +39617,7 @@ function UnifoldProvider2({
|
|
|
38746
39617
|
defaultSourceChainId: depositConfig.defaultSourceChainId,
|
|
38747
39618
|
defaultSourceTokenAddress: depositConfig.defaultSourceTokenAddress,
|
|
38748
39619
|
defaultSourceSymbol: depositConfig.defaultSourceSymbol,
|
|
38749
|
-
|
|
39620
|
+
userEmail: depositConfig.user?.email,
|
|
38750
39621
|
depositConfirmationMode: depositConfig.depositConfirmationMode ?? "auto_ui",
|
|
38751
39622
|
hideDepositTracker: config?.hideDepositTracker,
|
|
38752
39623
|
showBalanceHeader: config?.showBalanceHeader,
|
|
@@ -38759,7 +39630,6 @@ function UnifoldProvider2({
|
|
|
38759
39630
|
enableConnectExchange: config?.enableConnectExchange,
|
|
38760
39631
|
enableCashApp: config?.enableCashApp,
|
|
38761
39632
|
enableStripeLink: config?.enableStripeLink,
|
|
38762
|
-
email: depositConfig?.email,
|
|
38763
39633
|
enableApplePay: config?.enableApplePay,
|
|
38764
39634
|
applePayTitle: config?.applePayTitle,
|
|
38765
39635
|
applePaySubTitle: config?.applePaySubTitle,
|