@b3dotfun/sdk 0.0.80 → 0.0.81-alpha.1
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/cjs/anyspend/react/components/AnySpend.js +23 -10
- package/dist/cjs/anyspend/react/components/AnySpendCustom.js +22 -6
- package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.d.ts +4 -0
- package/dist/cjs/anyspend/react/components/common/FiatPaymentMethod.js +14 -7
- package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +7 -1
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +1 -1
- package/dist/cjs/global-account/react/hooks/useUserQuery.d.ts +2 -2
- package/dist/cjs/global-account/react/hooks/useUserQuery.js +76 -55
- package/dist/esm/anyspend/react/components/AnySpend.js +23 -10
- package/dist/esm/anyspend/react/components/AnySpendCustom.js +23 -7
- package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.d.ts +4 -0
- package/dist/esm/anyspend/react/components/common/FiatPaymentMethod.js +13 -6
- package/dist/esm/anyspend/react/components/common/PanelOnramp.js +8 -2
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +1 -1
- package/dist/esm/global-account/react/hooks/useUserQuery.d.ts +2 -2
- package/dist/esm/global-account/react/hooks/useUserQuery.js +76 -55
- package/dist/types/anyspend/react/components/common/FiatPaymentMethod.d.ts +4 -0
- package/dist/types/global-account/react/hooks/useUserQuery.d.ts +2 -2
- package/package.json +1 -1
- package/src/anyspend/react/components/AnySpend.tsx +24 -10
- package/src/anyspend/react/components/AnySpendCustom.tsx +42 -33
- package/src/anyspend/react/components/common/FiatPaymentMethod.tsx +14 -6
- package/src/anyspend/react/components/common/PanelOnramp.tsx +23 -27
- package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +1 -1
- package/src/global-account/react/hooks/useUserQuery.ts +82 -54
|
@@ -362,18 +362,18 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
362
362
|
isBalanceLoading,
|
|
363
363
|
});
|
|
364
364
|
// Get geo-based onramp options for fiat payments
|
|
365
|
-
const { geoData, coinbaseAvailablePaymentMethods, stripeWeb2Support } = (0, react_1.useGeoOnrampOptions)(srcAmountOnRamp);
|
|
365
|
+
const { geoData, coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support } = (0, react_1.useGeoOnrampOptions)(srcAmountOnRamp);
|
|
366
366
|
// Helper function to map payment method to onramp vendor
|
|
367
367
|
const getOnrampVendor = (paymentMethod) => {
|
|
368
368
|
switch (paymentMethod) {
|
|
369
369
|
case FiatPaymentMethod_1.FiatPaymentMethod.COINBASE_PAY:
|
|
370
370
|
return "coinbase";
|
|
371
371
|
case FiatPaymentMethod_1.FiatPaymentMethod.STRIPE:
|
|
372
|
-
//
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
return undefined;
|
|
372
|
+
// Stripe redirect flow (one-click URL)
|
|
373
|
+
return stripeOnrampSupport ? "stripe" : undefined;
|
|
374
|
+
case FiatPaymentMethod_1.FiatPaymentMethod.STRIPE_WEB2:
|
|
375
|
+
// Stripe embedded payment form
|
|
376
|
+
return stripeWeb2Support?.isSupport ? "stripe-web2" : undefined;
|
|
377
377
|
default:
|
|
378
378
|
return undefined;
|
|
379
379
|
}
|
|
@@ -518,7 +518,9 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
518
518
|
}, [activeTab, selectedSrcChainId, selectedDstChainId, selectedSrcToken.address, selectedDstToken.address]);
|
|
519
519
|
// Determine button state and text
|
|
520
520
|
const btnInfo = (0, react_4.useMemo)(() => {
|
|
521
|
-
|
|
521
|
+
// For fiat tab, check srcAmountOnRamp; for crypto tab, check activeInputAmountInWei
|
|
522
|
+
const hasAmount = activeTab === "fiat" ? srcAmountOnRamp && parseFloat(srcAmountOnRamp) > 0 : activeInputAmountInWei !== "0";
|
|
523
|
+
if (!hasAmount)
|
|
522
524
|
return { text: "Enter an amount", disable: true, error: false, loading: false };
|
|
523
525
|
if (isSameChainSameToken)
|
|
524
526
|
return { text: "Select a different token or chain", disable: true, error: false, loading: false };
|
|
@@ -569,6 +571,7 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
569
571
|
activeTab,
|
|
570
572
|
effectiveCryptoPaymentMethod,
|
|
571
573
|
selectedFiatPaymentMethod,
|
|
574
|
+
srcAmountOnRamp,
|
|
572
575
|
]);
|
|
573
576
|
// Handle main button click
|
|
574
577
|
const onMainButtonClick = async () => {
|
|
@@ -683,11 +686,21 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
683
686
|
paymentMethodString = coinbaseAvailablePaymentMethods[0]?.id || ""; // Use first available payment method ID
|
|
684
687
|
}
|
|
685
688
|
else if (paymentMethod === FiatPaymentMethod_1.FiatPaymentMethod.STRIPE) {
|
|
686
|
-
|
|
687
|
-
|
|
689
|
+
// Stripe redirect flow (one-click URL)
|
|
690
|
+
if (!stripeOnrampSupport) {
|
|
691
|
+
react_2.toast.error("Credit/Debit Card not available");
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
694
|
+
vendor = "stripe";
|
|
695
|
+
paymentMethodString = "";
|
|
696
|
+
}
|
|
697
|
+
else if (paymentMethod === FiatPaymentMethod_1.FiatPaymentMethod.STRIPE_WEB2) {
|
|
698
|
+
// Stripe embedded payment form
|
|
699
|
+
if (!stripeWeb2Support.isSupport) {
|
|
700
|
+
react_2.toast.error("Pay with Card not available");
|
|
688
701
|
return;
|
|
689
702
|
}
|
|
690
|
-
vendor =
|
|
703
|
+
vendor = "stripe-web2";
|
|
691
704
|
paymentMethodString = "";
|
|
692
705
|
}
|
|
693
706
|
else {
|
|
@@ -236,7 +236,11 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
236
236
|
contractType: orderType === "mint_nft" ? metadata?.nftContract?.type : undefined,
|
|
237
237
|
encodedData: encodedData,
|
|
238
238
|
spenderAddress: spenderAddress,
|
|
239
|
-
onrampVendor: selectedFiatPaymentMethod === FiatPaymentMethod_1.FiatPaymentMethod.STRIPE
|
|
239
|
+
onrampVendor: selectedFiatPaymentMethod === FiatPaymentMethod_1.FiatPaymentMethod.STRIPE
|
|
240
|
+
? "stripe"
|
|
241
|
+
: selectedFiatPaymentMethod === FiatPaymentMethod_1.FiatPaymentMethod.STRIPE_WEB2
|
|
242
|
+
? "stripe-web2"
|
|
243
|
+
: undefined,
|
|
240
244
|
});
|
|
241
245
|
}, [
|
|
242
246
|
activeTab,
|
|
@@ -578,7 +582,13 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
578
582
|
opacity: hasMounted ? 1 : 0,
|
|
579
583
|
y: hasMounted ? 0 : 20,
|
|
580
584
|
filter: hasMounted ? "blur(0px)" : "blur(10px)",
|
|
581
|
-
}, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: "relative flex w-full items-center justify-between", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-tertiarry flex h-7 items-center text-sm", children: "Pay with" }), (0, jsx_runtime_1.jsx)("button", { className: "text-as-tertiarry flex flex-wrap items-center justify-end gap-2 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(PanelView.FIAT_PAYMENT_METHOD), children:
|
|
585
|
+
}, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: "relative flex w-full items-center justify-between", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-tertiarry flex h-7 items-center text-sm", children: "Pay with" }), (0, jsx_runtime_1.jsx)("button", { className: "text-as-tertiarry flex flex-wrap items-center justify-end gap-2 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(PanelView.FIAT_PAYMENT_METHOD), children: (() => {
|
|
586
|
+
const config = FiatPaymentMethod_1.FIAT_PAYMENT_METHOD_DISPLAY[selectedFiatPaymentMethod];
|
|
587
|
+
if (config) {
|
|
588
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2 whitespace-nowrap", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-blue-600", children: (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-bold text-white", children: config.icon }) }), config.label] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4 shrink-0" })] }));
|
|
589
|
+
}
|
|
590
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: "whitespace-nowrap", children: "Select payment method" }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4 shrink-0" })] }));
|
|
591
|
+
})() })] }), (0, jsx_runtime_1.jsx)("div", { className: "divider w-full" }), recipientSection, (0, jsx_runtime_1.jsx)("div", { className: "divider w-full" }), (0, jsx_runtime_1.jsxs)(react_4.motion.div, { initial: false, animate: {
|
|
582
592
|
opacity: hasMounted ? 1 : 0,
|
|
583
593
|
y: hasMounted ? 0 : 20,
|
|
584
594
|
filter: hasMounted ? "blur(0px)" : "blur(10px)",
|
|
@@ -618,11 +628,17 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
618
628
|
setSelectedCryptoPaymentMethod(method);
|
|
619
629
|
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
620
630
|
} }) }));
|
|
631
|
+
// Stable callback for fiat payment method selection
|
|
632
|
+
const handleFiatPaymentMethodSelect = (0, react_5.useCallback)((method) => {
|
|
633
|
+
setSelectedFiatPaymentMethod(method);
|
|
634
|
+
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
635
|
+
}, []);
|
|
636
|
+
// Stable callback for navigating back to confirm order
|
|
637
|
+
const handleBackToConfirmOrder = (0, react_5.useCallback)(() => {
|
|
638
|
+
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
639
|
+
}, []);
|
|
621
640
|
// Fiat payment method view
|
|
622
|
-
const fiatPaymentMethodView = ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: (0, jsx_runtime_1.jsx)(FiatPaymentMethod_1.FiatPaymentMethodComponent, { selectedPaymentMethod: selectedFiatPaymentMethod, setSelectedPaymentMethod: setSelectedFiatPaymentMethod, onBack:
|
|
623
|
-
setSelectedFiatPaymentMethod(method);
|
|
624
|
-
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
625
|
-
}, srcAmountOnRamp: srcFiatAmount }) }));
|
|
641
|
+
const fiatPaymentMethodView = ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: (0, jsx_runtime_1.jsx)(FiatPaymentMethod_1.FiatPaymentMethodComponent, { selectedPaymentMethod: selectedFiatPaymentMethod, setSelectedPaymentMethod: setSelectedFiatPaymentMethod, onBack: handleBackToConfirmOrder, onSelectPaymentMethod: handleFiatPaymentMethodSelect, srcAmountOnRamp: srcFiatAmount }) }));
|
|
626
642
|
// Points detail view
|
|
627
643
|
const pointsDetailView = ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: (0, jsx_runtime_1.jsx)(PointsDetailPanel_1.PointsDetailPanel, { pointsAmount: anyspendQuote?.data?.pointsAmount || 0, onBack: () => setActivePanel(PanelView.CONFIRM_ORDER) }) }));
|
|
628
644
|
// Return the TransitionPanel with all views
|
|
@@ -4,6 +4,10 @@ export declare enum FiatPaymentMethod {
|
|
|
4
4
|
STRIPE = "stripe",// Stripe redirect (one-click buy URL)
|
|
5
5
|
STRIPE_WEB2 = "stripe_web2"
|
|
6
6
|
}
|
|
7
|
+
export declare const FIAT_PAYMENT_METHOD_DISPLAY: Record<FiatPaymentMethod, {
|
|
8
|
+
icon: string;
|
|
9
|
+
label: string;
|
|
10
|
+
} | null>;
|
|
7
11
|
interface FiatPaymentMethodProps {
|
|
8
12
|
selectedPaymentMethod: FiatPaymentMethod;
|
|
9
13
|
setSelectedPaymentMethod: (method: FiatPaymentMethod) => void;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
"use client";
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.FiatPaymentMethod = void 0;
|
|
4
|
+
exports.FIAT_PAYMENT_METHOD_DISPLAY = exports.FiatPaymentMethod = void 0;
|
|
5
5
|
exports.FiatPaymentMethodComponent = FiatPaymentMethodComponent;
|
|
6
6
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
7
7
|
const react_1 = require("../../../../anyspend/react");
|
|
@@ -14,6 +14,13 @@ var FiatPaymentMethod;
|
|
|
14
14
|
FiatPaymentMethod["STRIPE"] = "stripe";
|
|
15
15
|
FiatPaymentMethod["STRIPE_WEB2"] = "stripe_web2";
|
|
16
16
|
})(FiatPaymentMethod || (exports.FiatPaymentMethod = FiatPaymentMethod = {}));
|
|
17
|
+
// Shared display config for fiat payment methods
|
|
18
|
+
exports.FIAT_PAYMENT_METHOD_DISPLAY = {
|
|
19
|
+
[FiatPaymentMethod.COINBASE_PAY]: { icon: "C", label: "Coinbase Pay" },
|
|
20
|
+
[FiatPaymentMethod.STRIPE]: { icon: "S", label: "Pay via Stripe" },
|
|
21
|
+
[FiatPaymentMethod.STRIPE_WEB2]: { icon: "S", label: "Pay with Card" },
|
|
22
|
+
[FiatPaymentMethod.NONE]: null,
|
|
23
|
+
};
|
|
17
24
|
function FiatPaymentMethodComponent({ selectedPaymentMethod, setSelectedPaymentMethod, onBack, onSelectPaymentMethod, srcAmountOnRamp, }) {
|
|
18
25
|
// Load geo-based onramp options like in PanelOnramp
|
|
19
26
|
const { coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = (0, react_1.useGeoOnrampOptions)(srcAmountOnRamp);
|
|
@@ -50,25 +57,25 @@ function FiatPaymentMethodComponent({ selectedPaymentMethod, setSelectedPaymentM
|
|
|
50
57
|
available: true,
|
|
51
58
|
});
|
|
52
59
|
}
|
|
53
|
-
// Add Stripe redirect (one-click) if available -
|
|
60
|
+
// Add Stripe redirect (one-click) if available - redirects to Stripe checkout
|
|
54
61
|
if (stripeOnrampSupport) {
|
|
55
62
|
const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE_WEB2); // Use same fee estimate
|
|
56
63
|
availablePaymentMethods.push({
|
|
57
64
|
id: FiatPaymentMethod.STRIPE,
|
|
58
|
-
name: "
|
|
59
|
-
description: "
|
|
65
|
+
name: "Pay via Stripe",
|
|
66
|
+
description: "Redirects to Stripe checkout",
|
|
60
67
|
badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : undefined,
|
|
61
68
|
badgeColor: "bg-gray-100 text-gray-800",
|
|
62
69
|
available: true,
|
|
63
70
|
});
|
|
64
71
|
}
|
|
65
|
-
// Add Stripe Web2 (embedded) if available -
|
|
72
|
+
// Add Stripe Web2 (embedded) if available - embedded card form
|
|
66
73
|
if (stripeWeb2Support && stripeWeb2Support.isSupport) {
|
|
67
74
|
const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE_WEB2);
|
|
68
75
|
availablePaymentMethods.push({
|
|
69
76
|
id: FiatPaymentMethod.STRIPE_WEB2,
|
|
70
|
-
name: "
|
|
71
|
-
description: "
|
|
77
|
+
name: "Pay with Card",
|
|
78
|
+
description: "Fast checkout",
|
|
72
79
|
badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : undefined,
|
|
73
80
|
badgeColor: "bg-gray-100 text-gray-800",
|
|
74
81
|
available: true,
|
|
@@ -78,7 +78,13 @@ function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPaymentMetho
|
|
|
78
78
|
const handleQuickAmount = (value) => {
|
|
79
79
|
setSrcAmountOnRamp(value);
|
|
80
80
|
};
|
|
81
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: "panel-onramp bg-as-surface-primary flex w-full flex-col", children: [(0, jsx_runtime_1.jsxs)("div", { className: "border-as-border-secondary bg-as-surface-secondary relative flex w-full flex-col rounded-2xl border p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex h-7 w-full items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-tertiarry flex items-center text-sm font-bold", children: "Pay" }), (0, jsx_runtime_1.jsx)("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm", onClick: () => setActivePanel(fiatPaymentMethodIndex), children:
|
|
81
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: "panel-onramp bg-as-surface-primary flex w-full flex-col", children: [(0, jsx_runtime_1.jsxs)("div", { className: "border-as-border-secondary bg-as-surface-secondary relative flex w-full flex-col rounded-2xl border p-4", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex h-7 w-full items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-tertiarry flex items-center text-sm font-bold", children: "Pay" }), (0, jsx_runtime_1.jsx)("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm", onClick: () => setActivePanel(fiatPaymentMethodIndex), children: (() => {
|
|
82
|
+
const config = selectedPaymentMethod ? FiatPaymentMethod_1.FIAT_PAYMENT_METHOD_DISPLAY[selectedPaymentMethod] : null;
|
|
83
|
+
if (config) {
|
|
84
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-2", children: [(0, jsx_runtime_1.jsx)("div", { className: "flex h-5 w-5 items-center justify-center rounded-full bg-blue-600", children: (0, jsx_runtime_1.jsx)("span", { className: "text-xs font-bold text-white", children: config.icon }) }), config.label] }), (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] }));
|
|
85
|
+
}
|
|
86
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: ["Select payment method", (0, jsx_runtime_1.jsx)(lucide_react_1.ChevronRight, { className: "h-4 w-4" })] }));
|
|
87
|
+
})() })] }), (0, jsx_runtime_1.jsx)("div", { className: "flex items-center justify-center pb-2 pt-8", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-tertiarry text-2xl font-bold", children: "$" }), (0, jsx_runtime_1.jsx)(react_2.Input, { ref: amountInputRef, type: "text", value: srcAmountOnRamp, onChange: handleAmountChange, placeholder: "5", className: "text-as-primary placeholder:text-as-primary/50 h-auto border-0 bg-transparent p-0 px-1 pt-1 text-4xl font-bold focus-visible:ring-0 focus-visible:ring-offset-0", style: {
|
|
82
88
|
width: `${Math.max(ONE_CHAR_WIDTH, srcAmountOnRamp.length * ONE_CHAR_WIDTH)}px`,
|
|
83
89
|
} })] }) }), (0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("mx-auto mb-6 flex justify-center gap-2", hideDstToken && "mb-0"), children: customUsdInputValues
|
|
84
90
|
.filter(v => !isNaN(Number(v)))
|
|
@@ -165,7 +165,7 @@ function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySuccess, onE
|
|
|
165
165
|
isOpen,
|
|
166
166
|
source,
|
|
167
167
|
});
|
|
168
|
-
if (isConnected && isAuthenticated) {
|
|
168
|
+
if (isConnected && isAuthenticated && user) {
|
|
169
169
|
// Mark that login just completed BEFORE opening manage account or closing modal
|
|
170
170
|
// This allows Turnkey modal to show (if enableTurnkey is true)
|
|
171
171
|
if (closeAfterLogin) {
|
|
@@ -2,7 +2,7 @@ import { Users } from "@b3dotfun/b3-api";
|
|
|
2
2
|
/**
|
|
3
3
|
* NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
|
|
4
4
|
*
|
|
5
|
-
* Custom hook to manage user state with
|
|
5
|
+
* Custom hook to manage user state with Zustand
|
|
6
6
|
* This allows for invalidation and refetching of user data
|
|
7
7
|
*/
|
|
8
8
|
export declare function useUserQuery(): {
|
|
@@ -59,7 +59,7 @@ export declare function useUserQuery(): {
|
|
|
59
59
|
};
|
|
60
60
|
} | undefined;
|
|
61
61
|
setUser: (newUser?: Users) => void;
|
|
62
|
-
refetchUser: () => Promise<
|
|
62
|
+
refetchUser: () => Promise<any>;
|
|
63
63
|
clearUser: () => void;
|
|
64
64
|
queryKey: string[];
|
|
65
65
|
};
|
|
@@ -2,79 +2,100 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useUserQuery = useUserQuery;
|
|
4
4
|
const debug_1 = require("../../../shared/utils/debug");
|
|
5
|
-
const
|
|
5
|
+
const react_1 = require("react");
|
|
6
|
+
const zustand_1 = require("zustand");
|
|
7
|
+
const middleware_1 = require("zustand/middleware");
|
|
6
8
|
const debug = (0, debug_1.debugB3React)("useUserQuery");
|
|
7
9
|
const USER_QUERY_KEY = ["b3-user"];
|
|
8
10
|
/**
|
|
9
|
-
*
|
|
11
|
+
* Zustand store for managing user state
|
|
12
|
+
* Persists user data to localStorage
|
|
10
13
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
if (user) {
|
|
32
|
-
localStorage.setItem("b3-user", JSON.stringify(user));
|
|
33
|
-
}
|
|
34
|
-
else {
|
|
35
|
-
localStorage.removeItem("b3-user");
|
|
36
|
-
}
|
|
37
|
-
}
|
|
14
|
+
const useUserStore = (0, zustand_1.create)()((0, middleware_1.persist)(set => ({
|
|
15
|
+
user: null,
|
|
16
|
+
setUser: (newUser) => {
|
|
17
|
+
const userToSave = newUser ?? null;
|
|
18
|
+
set({ user: userToSave });
|
|
19
|
+
debug("User updated", userToSave);
|
|
20
|
+
},
|
|
21
|
+
clearUser: () => {
|
|
22
|
+
set({ user: null });
|
|
23
|
+
debug("User cleared");
|
|
24
|
+
},
|
|
25
|
+
}), {
|
|
26
|
+
name: "b3-user",
|
|
27
|
+
onRehydrateStorage: () => (_, error) => {
|
|
28
|
+
if (error) {
|
|
29
|
+
console.warn("Failed to rehydrate user store:", error);
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
}));
|
|
38
33
|
/**
|
|
39
34
|
* NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
|
|
40
35
|
*
|
|
41
|
-
* Custom hook to manage user state with
|
|
36
|
+
* Custom hook to manage user state with Zustand
|
|
42
37
|
* This allows for invalidation and refetching of user data
|
|
43
38
|
*/
|
|
44
39
|
function useUserQuery() {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
40
|
+
const user = useUserStore(state => state.user);
|
|
41
|
+
const setUserStore = useUserStore(state => state.setUser);
|
|
42
|
+
const clearUserStore = useUserStore(state => state.clearUser);
|
|
43
|
+
// Listen for storage events from other tabs/windows
|
|
44
|
+
(0, react_1.useEffect)(() => {
|
|
45
|
+
const handleStorageChange = (e) => {
|
|
46
|
+
if (e.key === "b3-user") {
|
|
47
|
+
// Sync with changes from other tabs/windows
|
|
48
|
+
const stored = e.newValue;
|
|
49
|
+
if (stored) {
|
|
50
|
+
try {
|
|
51
|
+
const parsed = JSON.parse(stored);
|
|
52
|
+
// Zustand persist format: { state: { user: ... }, version: ... }
|
|
53
|
+
const userData = parsed?.state?.user ?? parsed?.user ?? null;
|
|
54
|
+
useUserStore.setState({ user: userData });
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
console.warn("Failed to parse user from storage event:", error);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
useUserStore.setState({ user: null });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
window.addEventListener("storage", handleStorageChange);
|
|
66
|
+
return () => {
|
|
67
|
+
window.removeEventListener("storage", handleStorageChange);
|
|
68
|
+
};
|
|
69
|
+
}, []);
|
|
66
70
|
// Helper function to set user (maintains backward compatibility)
|
|
67
71
|
const setUser = (newUser) => {
|
|
68
|
-
|
|
72
|
+
setUserStore(newUser);
|
|
69
73
|
};
|
|
70
74
|
// Helper function to invalidate and refetch user
|
|
71
75
|
const refetchUser = async () => {
|
|
72
|
-
|
|
73
|
-
|
|
76
|
+
// Re-read from localStorage and update store
|
|
77
|
+
// Zustand persist stores data as { state: { user: ... }, version: ... }
|
|
78
|
+
const stored = localStorage.getItem("b3-user");
|
|
79
|
+
if (stored) {
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(stored);
|
|
82
|
+
// Zustand persist format: { state: { user: ... }, version: ... }
|
|
83
|
+
const userData = parsed?.state?.user ?? parsed?.user ?? null;
|
|
84
|
+
useUserStore.setState({ user: userData });
|
|
85
|
+
return userData ?? undefined;
|
|
86
|
+
}
|
|
87
|
+
catch (error) {
|
|
88
|
+
console.warn("Failed to refetch user from localStorage:", error);
|
|
89
|
+
// Fallback to current store state
|
|
90
|
+
return useUserStore.getState().user ?? undefined;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
useUserStore.setState({ user: null });
|
|
94
|
+
return undefined;
|
|
74
95
|
};
|
|
75
96
|
// Helper function to clear user
|
|
76
97
|
const clearUser = () => {
|
|
77
|
-
|
|
98
|
+
clearUserStore();
|
|
78
99
|
};
|
|
79
100
|
return {
|
|
80
101
|
user: user ?? undefined,
|
|
@@ -355,18 +355,18 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
355
355
|
isBalanceLoading,
|
|
356
356
|
});
|
|
357
357
|
// Get geo-based onramp options for fiat payments
|
|
358
|
-
const { geoData, coinbaseAvailablePaymentMethods, stripeWeb2Support } = useGeoOnrampOptions(srcAmountOnRamp);
|
|
358
|
+
const { geoData, coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support } = useGeoOnrampOptions(srcAmountOnRamp);
|
|
359
359
|
// Helper function to map payment method to onramp vendor
|
|
360
360
|
const getOnrampVendor = (paymentMethod) => {
|
|
361
361
|
switch (paymentMethod) {
|
|
362
362
|
case FiatPaymentMethod.COINBASE_PAY:
|
|
363
363
|
return "coinbase";
|
|
364
364
|
case FiatPaymentMethod.STRIPE:
|
|
365
|
-
//
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
return undefined;
|
|
365
|
+
// Stripe redirect flow (one-click URL)
|
|
366
|
+
return stripeOnrampSupport ? "stripe" : undefined;
|
|
367
|
+
case FiatPaymentMethod.STRIPE_WEB2:
|
|
368
|
+
// Stripe embedded payment form
|
|
369
|
+
return stripeWeb2Support?.isSupport ? "stripe-web2" : undefined;
|
|
370
370
|
default:
|
|
371
371
|
return undefined;
|
|
372
372
|
}
|
|
@@ -511,7 +511,9 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
511
511
|
}, [activeTab, selectedSrcChainId, selectedDstChainId, selectedSrcToken.address, selectedDstToken.address]);
|
|
512
512
|
// Determine button state and text
|
|
513
513
|
const btnInfo = useMemo(() => {
|
|
514
|
-
|
|
514
|
+
// For fiat tab, check srcAmountOnRamp; for crypto tab, check activeInputAmountInWei
|
|
515
|
+
const hasAmount = activeTab === "fiat" ? srcAmountOnRamp && parseFloat(srcAmountOnRamp) > 0 : activeInputAmountInWei !== "0";
|
|
516
|
+
if (!hasAmount)
|
|
515
517
|
return { text: "Enter an amount", disable: true, error: false, loading: false };
|
|
516
518
|
if (isSameChainSameToken)
|
|
517
519
|
return { text: "Select a different token or chain", disable: true, error: false, loading: false };
|
|
@@ -562,6 +564,7 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
562
564
|
activeTab,
|
|
563
565
|
effectiveCryptoPaymentMethod,
|
|
564
566
|
selectedFiatPaymentMethod,
|
|
567
|
+
srcAmountOnRamp,
|
|
565
568
|
]);
|
|
566
569
|
// Handle main button click
|
|
567
570
|
const onMainButtonClick = async () => {
|
|
@@ -676,11 +679,21 @@ function AnySpendInner({ destinationTokenAddress, destinationTokenChainId, mode
|
|
|
676
679
|
paymentMethodString = coinbaseAvailablePaymentMethods[0]?.id || ""; // Use first available payment method ID
|
|
677
680
|
}
|
|
678
681
|
else if (paymentMethod === FiatPaymentMethod.STRIPE) {
|
|
679
|
-
|
|
680
|
-
|
|
682
|
+
// Stripe redirect flow (one-click URL)
|
|
683
|
+
if (!stripeOnrampSupport) {
|
|
684
|
+
toast.error("Credit/Debit Card not available");
|
|
685
|
+
return;
|
|
686
|
+
}
|
|
687
|
+
vendor = "stripe";
|
|
688
|
+
paymentMethodString = "";
|
|
689
|
+
}
|
|
690
|
+
else if (paymentMethod === FiatPaymentMethod.STRIPE_WEB2) {
|
|
691
|
+
// Stripe embedded payment form
|
|
692
|
+
if (!stripeWeb2Support.isSupport) {
|
|
693
|
+
toast.error("Pay with Card not available");
|
|
681
694
|
return;
|
|
682
695
|
}
|
|
683
|
-
vendor =
|
|
696
|
+
vendor = "stripe-web2";
|
|
684
697
|
paymentMethodString = "";
|
|
685
698
|
}
|
|
686
699
|
else {
|
|
@@ -19,7 +19,7 @@ import { useRecipientAddressState } from "../hooks/useRecipientAddressState.js";
|
|
|
19
19
|
import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper.js";
|
|
20
20
|
import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod.js";
|
|
21
21
|
import { FeeBreakDown } from "./common/FeeBreakDown.js";
|
|
22
|
-
import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod.js";
|
|
22
|
+
import { FIAT_PAYMENT_METHOD_DISPLAY, FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod.js";
|
|
23
23
|
import { OrderDetails } from "./common/OrderDetails.js";
|
|
24
24
|
import { OrderHistory } from "./common/OrderHistory.js";
|
|
25
25
|
import { OrderToken } from "./common/OrderToken.js";
|
|
@@ -197,7 +197,11 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
197
197
|
contractType: orderType === "mint_nft" ? metadata?.nftContract?.type : undefined,
|
|
198
198
|
encodedData: encodedData,
|
|
199
199
|
spenderAddress: spenderAddress,
|
|
200
|
-
onrampVendor: selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE
|
|
200
|
+
onrampVendor: selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE
|
|
201
|
+
? "stripe"
|
|
202
|
+
: selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE_WEB2
|
|
203
|
+
? "stripe-web2"
|
|
204
|
+
: undefined,
|
|
201
205
|
});
|
|
202
206
|
}, [
|
|
203
207
|
activeTab,
|
|
@@ -539,7 +543,13 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
539
543
|
opacity: hasMounted ? 1 : 0,
|
|
540
544
|
y: hasMounted ? 0 : 20,
|
|
541
545
|
filter: hasMounted ? "blur(0px)" : "blur(10px)",
|
|
542
|
-
}, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: "relative flex w-full items-center justify-between", children: [_jsx("div", { className: "text-as-tertiarry flex h-7 items-center text-sm", children: "Pay with" }), _jsx("button", { className: "text-as-tertiarry flex flex-wrap items-center justify-end gap-2 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(PanelView.FIAT_PAYMENT_METHOD), children:
|
|
546
|
+
}, transition: { duration: 0.3, delay: 0, ease: "easeInOut" }, className: "relative flex w-full items-center justify-between", children: [_jsx("div", { className: "text-as-tertiarry flex h-7 items-center text-sm", children: "Pay with" }), _jsx("button", { className: "text-as-tertiarry flex flex-wrap items-center justify-end gap-2 text-sm transition-colors hover:text-blue-700", onClick: () => setActivePanel(PanelView.FIAT_PAYMENT_METHOD), children: (() => {
|
|
547
|
+
const config = FIAT_PAYMENT_METHOD_DISPLAY[selectedFiatPaymentMethod];
|
|
548
|
+
if (config) {
|
|
549
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2 whitespace-nowrap", children: [_jsx("div", { className: "flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-blue-600", children: _jsx("span", { className: "text-xs font-bold text-white", children: config.icon }) }), config.label] }), _jsx(ChevronRight, { className: "h-4 w-4 shrink-0" })] }));
|
|
550
|
+
}
|
|
551
|
+
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "whitespace-nowrap", children: "Select payment method" }), _jsx(ChevronRight, { className: "h-4 w-4 shrink-0" })] }));
|
|
552
|
+
})() })] }), _jsx("div", { className: "divider w-full" }), recipientSection, _jsx("div", { className: "divider w-full" }), _jsxs(motion.div, { initial: false, animate: {
|
|
543
553
|
opacity: hasMounted ? 1 : 0,
|
|
544
554
|
y: hasMounted ? 0 : 20,
|
|
545
555
|
filter: hasMounted ? "blur(0px)" : "blur(10px)",
|
|
@@ -579,11 +589,17 @@ function AnySpendCustomInner({ loadOrder, mode = "modal", activeTab: activeTabPr
|
|
|
579
589
|
setSelectedCryptoPaymentMethod(method);
|
|
580
590
|
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
581
591
|
} }) }));
|
|
592
|
+
// Stable callback for fiat payment method selection
|
|
593
|
+
const handleFiatPaymentMethodSelect = useCallback((method) => {
|
|
594
|
+
setSelectedFiatPaymentMethod(method);
|
|
595
|
+
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
596
|
+
}, []);
|
|
597
|
+
// Stable callback for navigating back to confirm order
|
|
598
|
+
const handleBackToConfirmOrder = useCallback(() => {
|
|
599
|
+
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
600
|
+
}, []);
|
|
582
601
|
// Fiat payment method view
|
|
583
|
-
const fiatPaymentMethodView = (_jsx("div", { className: cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: _jsx(FiatPaymentMethodComponent, { selectedPaymentMethod: selectedFiatPaymentMethod, setSelectedPaymentMethod: setSelectedFiatPaymentMethod, onBack:
|
|
584
|
-
setSelectedFiatPaymentMethod(method);
|
|
585
|
-
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
586
|
-
}, srcAmountOnRamp: srcFiatAmount }) }));
|
|
602
|
+
const fiatPaymentMethodView = (_jsx("div", { className: cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: _jsx(FiatPaymentMethodComponent, { selectedPaymentMethod: selectedFiatPaymentMethod, setSelectedPaymentMethod: setSelectedFiatPaymentMethod, onBack: handleBackToConfirmOrder, onSelectPaymentMethod: handleFiatPaymentMethodSelect, srcAmountOnRamp: srcFiatAmount }) }));
|
|
587
603
|
// Points detail view
|
|
588
604
|
const pointsDetailView = (_jsx("div", { className: cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4"), children: _jsx(PointsDetailPanel, { pointsAmount: anyspendQuote?.data?.pointsAmount || 0, onBack: () => setActivePanel(PanelView.CONFIRM_ORDER) }) }));
|
|
589
605
|
// Return the TransitionPanel with all views
|
|
@@ -4,6 +4,10 @@ export declare enum FiatPaymentMethod {
|
|
|
4
4
|
STRIPE = "stripe",// Stripe redirect (one-click buy URL)
|
|
5
5
|
STRIPE_WEB2 = "stripe_web2"
|
|
6
6
|
}
|
|
7
|
+
export declare const FIAT_PAYMENT_METHOD_DISPLAY: Record<FiatPaymentMethod, {
|
|
8
|
+
icon: string;
|
|
9
|
+
label: string;
|
|
10
|
+
} | null>;
|
|
7
11
|
interface FiatPaymentMethodProps {
|
|
8
12
|
selectedPaymentMethod: FiatPaymentMethod;
|
|
9
13
|
setSelectedPaymentMethod: (method: FiatPaymentMethod) => void;
|
|
@@ -10,6 +10,13 @@ export var FiatPaymentMethod;
|
|
|
10
10
|
FiatPaymentMethod["STRIPE"] = "stripe";
|
|
11
11
|
FiatPaymentMethod["STRIPE_WEB2"] = "stripe_web2";
|
|
12
12
|
})(FiatPaymentMethod || (FiatPaymentMethod = {}));
|
|
13
|
+
// Shared display config for fiat payment methods
|
|
14
|
+
export const FIAT_PAYMENT_METHOD_DISPLAY = {
|
|
15
|
+
[FiatPaymentMethod.COINBASE_PAY]: { icon: "C", label: "Coinbase Pay" },
|
|
16
|
+
[FiatPaymentMethod.STRIPE]: { icon: "S", label: "Pay via Stripe" },
|
|
17
|
+
[FiatPaymentMethod.STRIPE_WEB2]: { icon: "S", label: "Pay with Card" },
|
|
18
|
+
[FiatPaymentMethod.NONE]: null,
|
|
19
|
+
};
|
|
13
20
|
export function FiatPaymentMethodComponent({ selectedPaymentMethod, setSelectedPaymentMethod, onBack, onSelectPaymentMethod, srcAmountOnRamp, }) {
|
|
14
21
|
// Load geo-based onramp options like in PanelOnramp
|
|
15
22
|
const { coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support, isLoading: isLoadingGeoOnramp, } = useGeoOnrampOptions(srcAmountOnRamp);
|
|
@@ -46,25 +53,25 @@ export function FiatPaymentMethodComponent({ selectedPaymentMethod, setSelectedP
|
|
|
46
53
|
available: true,
|
|
47
54
|
});
|
|
48
55
|
}
|
|
49
|
-
// Add Stripe redirect (one-click) if available -
|
|
56
|
+
// Add Stripe redirect (one-click) if available - redirects to Stripe checkout
|
|
50
57
|
if (stripeOnrampSupport) {
|
|
51
58
|
const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE_WEB2); // Use same fee estimate
|
|
52
59
|
availablePaymentMethods.push({
|
|
53
60
|
id: FiatPaymentMethod.STRIPE,
|
|
54
|
-
name: "
|
|
55
|
-
description: "
|
|
61
|
+
name: "Pay via Stripe",
|
|
62
|
+
description: "Redirects to Stripe checkout",
|
|
56
63
|
badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : undefined,
|
|
57
64
|
badgeColor: "bg-gray-100 text-gray-800",
|
|
58
65
|
available: true,
|
|
59
66
|
});
|
|
60
67
|
}
|
|
61
|
-
// Add Stripe Web2 (embedded) if available -
|
|
68
|
+
// Add Stripe Web2 (embedded) if available - embedded card form
|
|
62
69
|
if (stripeWeb2Support && stripeWeb2Support.isSupport) {
|
|
63
70
|
const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE_WEB2);
|
|
64
71
|
availablePaymentMethods.push({
|
|
65
72
|
id: FiatPaymentMethod.STRIPE_WEB2,
|
|
66
|
-
name: "
|
|
67
|
-
description: "
|
|
73
|
+
name: "Pay with Card",
|
|
74
|
+
description: "Fast checkout",
|
|
68
75
|
badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : undefined,
|
|
69
76
|
badgeColor: "bg-gray-100 text-gray-800",
|
|
70
77
|
available: true,
|