@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
|
@@ -6,7 +6,7 @@ import { cn, formatUsername } from "../../../../shared/utils/index.js";
|
|
|
6
6
|
import { formatAddress } from "../../../../shared/utils/formatAddress.js";
|
|
7
7
|
import { ChevronRight, Info, Wallet } from "lucide-react";
|
|
8
8
|
import { useRef } from "react";
|
|
9
|
-
import { FiatPaymentMethod } from "./FiatPaymentMethod.js";
|
|
9
|
+
import { FIAT_PAYMENT_METHOD_DISPLAY, FiatPaymentMethod } from "./FiatPaymentMethod.js";
|
|
10
10
|
import { OrderTokenAmountFiat } from "./OrderTokenAmountFiat.js";
|
|
11
11
|
import { PointsBadge } from "./PointsBadge.js";
|
|
12
12
|
const ONE_CHAR_WIDTH = 30;
|
|
@@ -75,7 +75,13 @@ export function PanelOnramp({ srcAmountOnRamp, setSrcAmountOnRamp, selectedPayme
|
|
|
75
75
|
const handleQuickAmount = (value) => {
|
|
76
76
|
setSrcAmountOnRamp(value);
|
|
77
77
|
};
|
|
78
|
-
return (_jsxs("div", { className: "panel-onramp bg-as-surface-primary flex w-full flex-col", children: [_jsxs("div", { className: "border-as-border-secondary bg-as-surface-secondary relative flex w-full flex-col rounded-2xl border p-4", children: [_jsxs("div", { className: "flex h-7 w-full items-center justify-between", children: [_jsx("span", { className: "text-as-tertiarry flex items-center text-sm font-bold", children: "Pay" }), _jsx("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm", onClick: () => setActivePanel(fiatPaymentMethodIndex), children:
|
|
78
|
+
return (_jsxs("div", { className: "panel-onramp bg-as-surface-primary flex w-full flex-col", children: [_jsxs("div", { className: "border-as-border-secondary bg-as-surface-secondary relative flex w-full flex-col rounded-2xl border p-4", children: [_jsxs("div", { className: "flex h-7 w-full items-center justify-between", children: [_jsx("span", { className: "text-as-tertiarry flex items-center text-sm font-bold", children: "Pay" }), _jsx("button", { className: "text-as-tertiarry flex h-7 items-center gap-1 text-sm", onClick: () => setActivePanel(fiatPaymentMethodIndex), children: (() => {
|
|
79
|
+
const config = selectedPaymentMethod ? FIAT_PAYMENT_METHOD_DISPLAY[selectedPaymentMethod] : null;
|
|
80
|
+
if (config) {
|
|
81
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "flex h-5 w-5 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" })] }));
|
|
82
|
+
}
|
|
83
|
+
return (_jsxs(_Fragment, { children: ["Select payment method", _jsx(ChevronRight, { className: "h-4 w-4" })] }));
|
|
84
|
+
})() })] }), _jsx("div", { className: "flex items-center justify-center pb-2 pt-8", children: _jsxs("div", { className: "flex gap-1", children: [_jsx("span", { className: "text-as-tertiarry text-2xl font-bold", children: "$" }), _jsx(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: {
|
|
79
85
|
width: `${Math.max(ONE_CHAR_WIDTH, srcAmountOnRamp.length * ONE_CHAR_WIDTH)}px`,
|
|
80
86
|
} })] }) }), _jsx("div", { className: cn("mx-auto mb-6 flex justify-center gap-2", hideDstToken && "mb-0"), children: customUsdInputValues
|
|
81
87
|
.filter(v => !isNaN(Number(v)))
|
|
@@ -162,7 +162,7 @@ export function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySucce
|
|
|
162
162
|
isOpen,
|
|
163
163
|
source,
|
|
164
164
|
});
|
|
165
|
-
if (isConnected && isAuthenticated) {
|
|
165
|
+
if (isConnected && isAuthenticated && user) {
|
|
166
166
|
// Mark that login just completed BEFORE opening manage account or closing modal
|
|
167
167
|
// This allows Turnkey modal to show (if enableTurnkey is true)
|
|
168
168
|
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
|
};
|
|
@@ -1,77 +1,98 @@
|
|
|
1
1
|
import { debugB3React } from "../../../shared/utils/debug.js";
|
|
2
|
-
import {
|
|
2
|
+
import { useEffect } from "react";
|
|
3
|
+
import { create } from "zustand";
|
|
4
|
+
import { persist } from "zustand/middleware";
|
|
3
5
|
const debug = debugB3React("useUserQuery");
|
|
4
6
|
const USER_QUERY_KEY = ["b3-user"];
|
|
5
7
|
/**
|
|
6
|
-
*
|
|
8
|
+
* Zustand store for managing user state
|
|
9
|
+
* Persists user data to localStorage
|
|
7
10
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
if (user) {
|
|
29
|
-
localStorage.setItem("b3-user", JSON.stringify(user));
|
|
30
|
-
}
|
|
31
|
-
else {
|
|
32
|
-
localStorage.removeItem("b3-user");
|
|
33
|
-
}
|
|
34
|
-
}
|
|
11
|
+
const useUserStore = create()(persist(set => ({
|
|
12
|
+
user: null,
|
|
13
|
+
setUser: (newUser) => {
|
|
14
|
+
const userToSave = newUser ?? null;
|
|
15
|
+
set({ user: userToSave });
|
|
16
|
+
debug("User updated", userToSave);
|
|
17
|
+
},
|
|
18
|
+
clearUser: () => {
|
|
19
|
+
set({ user: null });
|
|
20
|
+
debug("User cleared");
|
|
21
|
+
},
|
|
22
|
+
}), {
|
|
23
|
+
name: "b3-user",
|
|
24
|
+
onRehydrateStorage: () => (_, error) => {
|
|
25
|
+
if (error) {
|
|
26
|
+
console.warn("Failed to rehydrate user store:", error);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
35
30
|
/**
|
|
36
31
|
* NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
|
|
37
32
|
*
|
|
38
|
-
* Custom hook to manage user state with
|
|
33
|
+
* Custom hook to manage user state with Zustand
|
|
39
34
|
* This allows for invalidation and refetching of user data
|
|
40
35
|
*/
|
|
41
36
|
export function useUserQuery() {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
const
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
37
|
+
const user = useUserStore(state => state.user);
|
|
38
|
+
const setUserStore = useUserStore(state => state.setUser);
|
|
39
|
+
const clearUserStore = useUserStore(state => state.clearUser);
|
|
40
|
+
// Listen for storage events from other tabs/windows
|
|
41
|
+
useEffect(() => {
|
|
42
|
+
const handleStorageChange = (e) => {
|
|
43
|
+
if (e.key === "b3-user") {
|
|
44
|
+
// Sync with changes from other tabs/windows
|
|
45
|
+
const stored = e.newValue;
|
|
46
|
+
if (stored) {
|
|
47
|
+
try {
|
|
48
|
+
const parsed = JSON.parse(stored);
|
|
49
|
+
// Zustand persist format: { state: { user: ... }, version: ... }
|
|
50
|
+
const userData = parsed?.state?.user ?? parsed?.user ?? null;
|
|
51
|
+
useUserStore.setState({ user: userData });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.warn("Failed to parse user from storage event:", error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
useUserStore.setState({ user: null });
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
window.addEventListener("storage", handleStorageChange);
|
|
63
|
+
return () => {
|
|
64
|
+
window.removeEventListener("storage", handleStorageChange);
|
|
65
|
+
};
|
|
66
|
+
}, []);
|
|
63
67
|
// Helper function to set user (maintains backward compatibility)
|
|
64
68
|
const setUser = (newUser) => {
|
|
65
|
-
|
|
69
|
+
setUserStore(newUser);
|
|
66
70
|
};
|
|
67
71
|
// Helper function to invalidate and refetch user
|
|
68
72
|
const refetchUser = async () => {
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
// Re-read from localStorage and update store
|
|
74
|
+
// Zustand persist stores data as { state: { user: ... }, version: ... }
|
|
75
|
+
const stored = localStorage.getItem("b3-user");
|
|
76
|
+
if (stored) {
|
|
77
|
+
try {
|
|
78
|
+
const parsed = JSON.parse(stored);
|
|
79
|
+
// Zustand persist format: { state: { user: ... }, version: ... }
|
|
80
|
+
const userData = parsed?.state?.user ?? parsed?.user ?? null;
|
|
81
|
+
useUserStore.setState({ user: userData });
|
|
82
|
+
return userData ?? undefined;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
console.warn("Failed to refetch user from localStorage:", error);
|
|
86
|
+
// Fallback to current store state
|
|
87
|
+
return useUserStore.getState().user ?? undefined;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
useUserStore.setState({ user: null });
|
|
91
|
+
return undefined;
|
|
71
92
|
};
|
|
72
93
|
// Helper function to clear user
|
|
73
94
|
const clearUser = () => {
|
|
74
|
-
|
|
95
|
+
clearUserStore();
|
|
75
96
|
};
|
|
76
97
|
return {
|
|
77
98
|
user: user ?? undefined,
|
|
@@ -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;
|
|
@@ -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
|
};
|
package/package.json
CHANGED
|
@@ -510,7 +510,8 @@ function AnySpendInner({
|
|
|
510
510
|
});
|
|
511
511
|
|
|
512
512
|
// Get geo-based onramp options for fiat payments
|
|
513
|
-
const { geoData, coinbaseAvailablePaymentMethods, stripeWeb2Support } =
|
|
513
|
+
const { geoData, coinbaseAvailablePaymentMethods, stripeOnrampSupport, stripeWeb2Support } =
|
|
514
|
+
useGeoOnrampOptions(srcAmountOnRamp);
|
|
514
515
|
|
|
515
516
|
// Helper function to map payment method to onramp vendor
|
|
516
517
|
const getOnrampVendor = (paymentMethod: FiatPaymentMethod): "coinbase" | "stripe" | "stripe-web2" | undefined => {
|
|
@@ -518,11 +519,11 @@ function AnySpendInner({
|
|
|
518
519
|
case FiatPaymentMethod.COINBASE_PAY:
|
|
519
520
|
return "coinbase";
|
|
520
521
|
case FiatPaymentMethod.STRIPE:
|
|
521
|
-
//
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
return undefined;
|
|
522
|
+
// Stripe redirect flow (one-click URL)
|
|
523
|
+
return stripeOnrampSupport ? "stripe" : undefined;
|
|
524
|
+
case FiatPaymentMethod.STRIPE_WEB2:
|
|
525
|
+
// Stripe embedded payment form
|
|
526
|
+
return stripeWeb2Support?.isSupport ? "stripe-web2" : undefined;
|
|
526
527
|
default:
|
|
527
528
|
return undefined;
|
|
528
529
|
}
|
|
@@ -683,7 +684,10 @@ function AnySpendInner({
|
|
|
683
684
|
|
|
684
685
|
// Determine button state and text
|
|
685
686
|
const btnInfo: { text: string; disable: boolean; error: boolean; loading: boolean } = useMemo(() => {
|
|
686
|
-
|
|
687
|
+
// For fiat tab, check srcAmountOnRamp; for crypto tab, check activeInputAmountInWei
|
|
688
|
+
const hasAmount =
|
|
689
|
+
activeTab === "fiat" ? srcAmountOnRamp && parseFloat(srcAmountOnRamp) > 0 : activeInputAmountInWei !== "0";
|
|
690
|
+
if (!hasAmount) return { text: "Enter an amount", disable: true, error: false, loading: false };
|
|
687
691
|
if (isSameChainSameToken)
|
|
688
692
|
return { text: "Select a different token or chain", disable: true, error: false, loading: false };
|
|
689
693
|
if (isLoadingAnyspendQuote) return { text: "Loading quote...", disable: true, error: false, loading: true };
|
|
@@ -739,6 +743,7 @@ function AnySpendInner({
|
|
|
739
743
|
activeTab,
|
|
740
744
|
effectiveCryptoPaymentMethod,
|
|
741
745
|
selectedFiatPaymentMethod,
|
|
746
|
+
srcAmountOnRamp,
|
|
742
747
|
]);
|
|
743
748
|
|
|
744
749
|
// Handle main button click
|
|
@@ -870,11 +875,20 @@ function AnySpendInner({
|
|
|
870
875
|
vendor = "coinbase";
|
|
871
876
|
paymentMethodString = coinbaseAvailablePaymentMethods[0]?.id || ""; // Use first available payment method ID
|
|
872
877
|
} else if (paymentMethod === FiatPaymentMethod.STRIPE) {
|
|
873
|
-
|
|
874
|
-
|
|
878
|
+
// Stripe redirect flow (one-click URL)
|
|
879
|
+
if (!stripeOnrampSupport) {
|
|
880
|
+
toast.error("Credit/Debit Card not available");
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
vendor = "stripe";
|
|
884
|
+
paymentMethodString = "";
|
|
885
|
+
} else if (paymentMethod === FiatPaymentMethod.STRIPE_WEB2) {
|
|
886
|
+
// Stripe embedded payment form
|
|
887
|
+
if (!stripeWeb2Support.isSupport) {
|
|
888
|
+
toast.error("Pay with Card not available");
|
|
875
889
|
return;
|
|
876
890
|
}
|
|
877
|
-
vendor =
|
|
891
|
+
vendor = "stripe-web2";
|
|
878
892
|
paymentMethodString = "";
|
|
879
893
|
} else {
|
|
880
894
|
toast.error("Please select a payment method");
|
|
@@ -50,7 +50,7 @@ import { useRecipientAddressState } from "../hooks/useRecipientAddressState";
|
|
|
50
50
|
import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper";
|
|
51
51
|
import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod";
|
|
52
52
|
import { FeeBreakDown } from "./common/FeeBreakDown";
|
|
53
|
-
import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod";
|
|
53
|
+
import { FIAT_PAYMENT_METHOD_DISPLAY, FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaymentMethod";
|
|
54
54
|
import { OrderDetails } from "./common/OrderDetails";
|
|
55
55
|
import { OrderHistory } from "./common/OrderHistory";
|
|
56
56
|
import { OrderToken } from "./common/OrderToken";
|
|
@@ -355,7 +355,12 @@ function AnySpendCustomInner({
|
|
|
355
355
|
contractType: orderType === "mint_nft" ? metadata?.nftContract?.type : undefined,
|
|
356
356
|
encodedData: encodedData,
|
|
357
357
|
spenderAddress: spenderAddress,
|
|
358
|
-
onrampVendor:
|
|
358
|
+
onrampVendor:
|
|
359
|
+
selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE
|
|
360
|
+
? "stripe"
|
|
361
|
+
: selectedFiatPaymentMethod === FiatPaymentMethod.STRIPE_WEB2
|
|
362
|
+
? "stripe-web2"
|
|
363
|
+
: undefined,
|
|
359
364
|
});
|
|
360
365
|
}, [
|
|
361
366
|
activeTab,
|
|
@@ -1127,32 +1132,28 @@ function AnySpendCustomInner({
|
|
|
1127
1132
|
className="text-as-tertiarry flex flex-wrap items-center justify-end gap-2 text-sm transition-colors hover:text-blue-700"
|
|
1128
1133
|
onClick={() => setActivePanel(PanelView.FIAT_PAYMENT_METHOD)}
|
|
1129
1134
|
>
|
|
1130
|
-
{
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
<span className="whitespace-nowrap">Select payment method</span>
|
|
1153
|
-
<ChevronRight className="h-4 w-4 shrink-0" />
|
|
1154
|
-
</>
|
|
1155
|
-
)}
|
|
1135
|
+
{(() => {
|
|
1136
|
+
const config = FIAT_PAYMENT_METHOD_DISPLAY[selectedFiatPaymentMethod];
|
|
1137
|
+
if (config) {
|
|
1138
|
+
return (
|
|
1139
|
+
<>
|
|
1140
|
+
<div className="flex items-center gap-2 whitespace-nowrap">
|
|
1141
|
+
<div className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-blue-600">
|
|
1142
|
+
<span className="text-xs font-bold text-white">{config.icon}</span>
|
|
1143
|
+
</div>
|
|
1144
|
+
{config.label}
|
|
1145
|
+
</div>
|
|
1146
|
+
<ChevronRight className="h-4 w-4 shrink-0" />
|
|
1147
|
+
</>
|
|
1148
|
+
);
|
|
1149
|
+
}
|
|
1150
|
+
return (
|
|
1151
|
+
<>
|
|
1152
|
+
<span className="whitespace-nowrap">Select payment method</span>
|
|
1153
|
+
<ChevronRight className="h-4 w-4 shrink-0" />
|
|
1154
|
+
</>
|
|
1155
|
+
);
|
|
1156
|
+
})()}
|
|
1156
1157
|
</button>
|
|
1157
1158
|
</motion.div>
|
|
1158
1159
|
|
|
@@ -1318,17 +1319,25 @@ function AnySpendCustomInner({
|
|
|
1318
1319
|
</div>
|
|
1319
1320
|
);
|
|
1320
1321
|
|
|
1322
|
+
// Stable callback for fiat payment method selection
|
|
1323
|
+
const handleFiatPaymentMethodSelect = useCallback((method: FiatPaymentMethod) => {
|
|
1324
|
+
setSelectedFiatPaymentMethod(method);
|
|
1325
|
+
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
1326
|
+
}, []);
|
|
1327
|
+
|
|
1328
|
+
// Stable callback for navigating back to confirm order
|
|
1329
|
+
const handleBackToConfirmOrder = useCallback(() => {
|
|
1330
|
+
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
1331
|
+
}, []);
|
|
1332
|
+
|
|
1321
1333
|
// Fiat payment method view
|
|
1322
1334
|
const fiatPaymentMethodView = (
|
|
1323
1335
|
<div className={cn("bg-as-surface-primary mx-auto w-[460px] max-w-full rounded-xl p-4")}>
|
|
1324
1336
|
<FiatPaymentMethodComponent
|
|
1325
1337
|
selectedPaymentMethod={selectedFiatPaymentMethod}
|
|
1326
1338
|
setSelectedPaymentMethod={setSelectedFiatPaymentMethod}
|
|
1327
|
-
onBack={
|
|
1328
|
-
onSelectPaymentMethod={
|
|
1329
|
-
setSelectedFiatPaymentMethod(method);
|
|
1330
|
-
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
1331
|
-
}}
|
|
1339
|
+
onBack={handleBackToConfirmOrder}
|
|
1340
|
+
onSelectPaymentMethod={handleFiatPaymentMethodSelect}
|
|
1332
1341
|
srcAmountOnRamp={srcFiatAmount}
|
|
1333
1342
|
/>
|
|
1334
1343
|
</div>
|
|
@@ -11,6 +11,14 @@ export enum FiatPaymentMethod {
|
|
|
11
11
|
STRIPE_WEB2 = "stripe_web2", // Stripe embedded payment
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
// Shared display config for fiat payment methods
|
|
15
|
+
export const FIAT_PAYMENT_METHOD_DISPLAY: Record<FiatPaymentMethod, { icon: string; label: string } | null> = {
|
|
16
|
+
[FiatPaymentMethod.COINBASE_PAY]: { icon: "C", label: "Coinbase Pay" },
|
|
17
|
+
[FiatPaymentMethod.STRIPE]: { icon: "S", label: "Pay via Stripe" },
|
|
18
|
+
[FiatPaymentMethod.STRIPE_WEB2]: { icon: "S", label: "Pay with Card" },
|
|
19
|
+
[FiatPaymentMethod.NONE]: null,
|
|
20
|
+
};
|
|
21
|
+
|
|
14
22
|
interface FiatPaymentMethodProps {
|
|
15
23
|
selectedPaymentMethod: FiatPaymentMethod;
|
|
16
24
|
setSelectedPaymentMethod: (method: FiatPaymentMethod) => void;
|
|
@@ -70,26 +78,26 @@ export function FiatPaymentMethodComponent({
|
|
|
70
78
|
});
|
|
71
79
|
}
|
|
72
80
|
|
|
73
|
-
// Add Stripe redirect (one-click) if available -
|
|
81
|
+
// Add Stripe redirect (one-click) if available - redirects to Stripe checkout
|
|
74
82
|
if (stripeOnrampSupport) {
|
|
75
83
|
const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE_WEB2); // Use same fee estimate
|
|
76
84
|
availablePaymentMethods.push({
|
|
77
85
|
id: FiatPaymentMethod.STRIPE,
|
|
78
|
-
name: "
|
|
79
|
-
description: "
|
|
86
|
+
name: "Pay via Stripe",
|
|
87
|
+
description: "Redirects to Stripe checkout",
|
|
80
88
|
badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : undefined,
|
|
81
89
|
badgeColor: "bg-gray-100 text-gray-800",
|
|
82
90
|
available: true,
|
|
83
91
|
});
|
|
84
92
|
}
|
|
85
93
|
|
|
86
|
-
// Add Stripe Web2 (embedded) if available -
|
|
94
|
+
// Add Stripe Web2 (embedded) if available - embedded card form
|
|
87
95
|
if (stripeWeb2Support && stripeWeb2Support.isSupport) {
|
|
88
96
|
const stripeFee = getFeeFromApi(FiatPaymentMethod.STRIPE_WEB2);
|
|
89
97
|
availablePaymentMethods.push({
|
|
90
98
|
id: FiatPaymentMethod.STRIPE_WEB2,
|
|
91
|
-
name: "
|
|
92
|
-
description: "
|
|
99
|
+
name: "Pay with Card",
|
|
100
|
+
description: "Fast checkout",
|
|
93
101
|
badge: stripeFee ? `$${Number(stripeFee).toFixed(2)} fee` : undefined,
|
|
94
102
|
badgeColor: "bg-gray-100 text-gray-800",
|
|
95
103
|
available: true,
|
|
@@ -8,7 +8,7 @@ import { formatAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
|
|
|
8
8
|
import { ChevronRight, Info, Wallet } from "lucide-react";
|
|
9
9
|
import { useRef } from "react";
|
|
10
10
|
|
|
11
|
-
import { FiatPaymentMethod } from "./FiatPaymentMethod";
|
|
11
|
+
import { FIAT_PAYMENT_METHOD_DISPLAY, FiatPaymentMethod } from "./FiatPaymentMethod";
|
|
12
12
|
import { OrderTokenAmountFiat } from "./OrderTokenAmountFiat";
|
|
13
13
|
import { PointsBadge } from "./PointsBadge";
|
|
14
14
|
|
|
@@ -141,32 +141,28 @@ export function PanelOnramp({
|
|
|
141
141
|
className="text-as-tertiarry flex h-7 items-center gap-1 text-sm"
|
|
142
142
|
onClick={() => setActivePanel(fiatPaymentMethodIndex)} // PanelView.FIAT_PAYMENT_METHOD
|
|
143
143
|
>
|
|
144
|
-
{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
Select payment method
|
|
167
|
-
<ChevronRight className="h-4 w-4" />
|
|
168
|
-
</>
|
|
169
|
-
)}
|
|
144
|
+
{(() => {
|
|
145
|
+
const config = selectedPaymentMethod ? FIAT_PAYMENT_METHOD_DISPLAY[selectedPaymentMethod] : null;
|
|
146
|
+
if (config) {
|
|
147
|
+
return (
|
|
148
|
+
<>
|
|
149
|
+
<div className="flex items-center gap-2">
|
|
150
|
+
<div className="flex h-5 w-5 items-center justify-center rounded-full bg-blue-600">
|
|
151
|
+
<span className="text-xs font-bold text-white">{config.icon}</span>
|
|
152
|
+
</div>
|
|
153
|
+
{config.label}
|
|
154
|
+
</div>
|
|
155
|
+
<ChevronRight className="h-4 w-4" />
|
|
156
|
+
</>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
return (
|
|
160
|
+
<>
|
|
161
|
+
Select payment method
|
|
162
|
+
<ChevronRight className="h-4 w-4" />
|
|
163
|
+
</>
|
|
164
|
+
);
|
|
165
|
+
})()}
|
|
170
166
|
</button>
|
|
171
167
|
</div>
|
|
172
168
|
|
|
@@ -198,7 +198,7 @@ export function SignInWithB3Flow({
|
|
|
198
198
|
source,
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
-
if (isConnected && isAuthenticated) {
|
|
201
|
+
if (isConnected && isAuthenticated && user) {
|
|
202
202
|
// Mark that login just completed BEFORE opening manage account or closing modal
|
|
203
203
|
// This allows Turnkey modal to show (if enableTurnkey is true)
|
|
204
204
|
if (closeAfterLogin) {
|