@b3dotfun/sdk 0.0.10 → 0.0.11-alpha.0
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/AnySpendCustom.js +1 -1
- package/dist/cjs/anyspend/react/components/common/PaymentStripeWeb2.js +62 -25
- package/dist/cjs/anyspend/react/components/webview/WebviewOnrampPayment.js +29 -6
- package/dist/cjs/anyspend/react/providers/AnyspendProvider.d.ts +1 -0
- package/dist/cjs/anyspend/react/providers/AnyspendProvider.js +3 -1
- package/dist/cjs/anyspend/react/providers/StripeRedirectHandler.d.ts +8 -0
- package/dist/cjs/anyspend/react/providers/StripeRedirectHandler.js +41 -0
- package/dist/cjs/global-account/react/components/B3DynamicModal.js +2 -2
- package/dist/cjs/global-account/react/components/ui/dialog.js +1 -1
- package/dist/cjs/global-account/react/hooks/index.d.ts +1 -0
- package/dist/cjs/global-account/react/hooks/index.js +4 -1
- package/dist/cjs/global-account/react/hooks/useAccountWallet.js +0 -4
- package/dist/cjs/global-account/react/hooks/useProfile.d.ts +38 -0
- package/dist/cjs/global-account/react/hooks/useProfile.js +72 -0
- package/dist/esm/anyspend/react/components/AnySpendCustom.js +1 -1
- package/dist/esm/anyspend/react/components/common/PaymentStripeWeb2.js +64 -27
- package/dist/esm/anyspend/react/components/webview/WebviewOnrampPayment.js +30 -7
- package/dist/esm/anyspend/react/providers/AnyspendProvider.d.ts +1 -0
- package/dist/esm/anyspend/react/providers/AnyspendProvider.js +4 -2
- package/dist/esm/anyspend/react/providers/StripeRedirectHandler.d.ts +8 -0
- package/dist/esm/anyspend/react/providers/StripeRedirectHandler.js +38 -0
- package/dist/esm/global-account/react/components/B3DynamicModal.js +2 -2
- package/dist/esm/global-account/react/components/ui/dialog.js +1 -1
- package/dist/esm/global-account/react/hooks/index.d.ts +1 -0
- package/dist/esm/global-account/react/hooks/index.js +1 -0
- package/dist/esm/global-account/react/hooks/useAccountWallet.js +0 -4
- package/dist/esm/global-account/react/hooks/useProfile.d.ts +38 -0
- package/dist/esm/global-account/react/hooks/useProfile.js +68 -0
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/providers/AnyspendProvider.d.ts +1 -0
- package/dist/types/anyspend/react/providers/StripeRedirectHandler.d.ts +8 -0
- package/dist/types/global-account/react/hooks/index.d.ts +1 -0
- package/dist/types/global-account/react/hooks/useProfile.d.ts +38 -0
- package/package.json +2 -2
- package/src/anyspend/react/components/AnySpendCustom.tsx +1 -1
- package/src/anyspend/react/components/common/PaymentStripeWeb2.tsx +86 -35
- package/src/anyspend/react/components/webview/WebviewOnrampPayment.tsx +39 -7
- package/src/anyspend/react/providers/AnyspendProvider.tsx +6 -1
- package/src/anyspend/react/providers/StripeRedirectHandler.tsx +45 -0
- package/src/global-account/react/components/B3DynamicModal.tsx +2 -2
- package/src/global-account/react/components/ui/dialog.tsx +3 -4
- package/src/global-account/react/components/ui/drawer.tsx +0 -2
- package/src/global-account/react/hooks/index.ts +7 -0
- package/src/global-account/react/hooks/useAccountWallet.tsx +0 -5
- package/src/global-account/react/hooks/useProfile.ts +141 -0
- package/src/styles/index.css +1 -1
|
@@ -369,7 +369,7 @@ function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", recipient
|
|
|
369
369
|
const historyView = ((0, jsx_runtime_1.jsx)("div", { className: (0, utils_1.cn)("mx-auto flex w-full max-w-2xl flex-col items-center p-5", mode === "modal" && "bg-b3-react-background"), children: (0, jsx_runtime_1.jsx)(OrderHistory_1.OrderHistory, { mode: mode, onBack: () => {
|
|
370
370
|
setActivePanel(PanelView.HISTORY);
|
|
371
371
|
}, onSelectOrder: onSelectOrder }) }));
|
|
372
|
-
const orderDetailsView = ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)("mx-auto flex
|
|
372
|
+
const orderDetailsView = ((0, jsx_runtime_1.jsxs)("div", { className: (0, utils_1.cn)("mx-auto flex w-full flex-col items-center gap-4 p-5", mode === "modal" && "bg-b3-react-background"), children: [oat && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(OrderStatus_1.OrderStatus, { order: oat.data.order }), (0, jsx_runtime_1.jsx)(OrderDetails_1.OrderDetails, { isMainnet: isMainnet, mode: mode, order: oat.data.order, depositTxs: oat.data.depositTxs, relayTx: oat.data.relayTx, executeTx: oat.data.executeTx, refundTxs: oat.data.refundTxs, onBack: () => {
|
|
373
373
|
setOrderId(undefined);
|
|
374
374
|
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
375
375
|
// Remove orderId from URL when canceling
|
|
@@ -6,8 +6,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.default = PaymentStripeWeb2;
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const anyspend_1 = require("../../../../anyspend");
|
|
9
|
-
const react_1 = require("../../../../anyspend/react");
|
|
10
9
|
const constants_1 = require("../../../../anyspend/constants");
|
|
10
|
+
const react_1 = require("../../../../anyspend/react");
|
|
11
11
|
const react_2 = require("../../../../global-account/react");
|
|
12
12
|
const payment_utils_1 = require("../../../../shared/utils/payment.utils");
|
|
13
13
|
const react_stripe_js_1 = require("@stripe/react-stripe-js");
|
|
@@ -40,11 +40,13 @@ function StripeErrorState({ error }) {
|
|
|
40
40
|
function StripePaymentForm({ order, clientSecret, onPaymentSuccess, }) {
|
|
41
41
|
const stripe = (0, react_stripe_js_1.useStripe)();
|
|
42
42
|
const elements = (0, react_stripe_js_1.useElements)();
|
|
43
|
+
const setB3ModalOpen = (0, react_2.useModalStore)(state => state.setB3ModalOpen);
|
|
43
44
|
const [loading, setLoading] = (0, react_3.useState)(false);
|
|
44
45
|
const [message, setMessage] = (0, react_3.useState)(null);
|
|
45
46
|
const [amount, setAmount] = (0, react_3.useState)(null);
|
|
46
47
|
const [stripeReady, setStripeReady] = (0, react_3.useState)(false);
|
|
47
48
|
const [showHowItWorks, setShowHowItWorks] = (0, react_3.useState)(false);
|
|
49
|
+
const [showAddressElement, setShowAddressElement] = (0, react_3.useState)(false);
|
|
48
50
|
(0, react_3.useEffect)(() => {
|
|
49
51
|
if (stripe && elements) {
|
|
50
52
|
setStripeReady(true);
|
|
@@ -68,6 +70,12 @@ function StripePaymentForm({ order, clientSecret, onPaymentSuccess, }) {
|
|
|
68
70
|
};
|
|
69
71
|
fetchPaymentIntent();
|
|
70
72
|
}, [clientSecret, stripe]);
|
|
73
|
+
// Handle payment element changes
|
|
74
|
+
const handlePaymentElementChange = (event) => {
|
|
75
|
+
// Show address element only for card payments
|
|
76
|
+
console.log("@@stripe-web2-payment:payment-element-change:", JSON.stringify(event, null, 2));
|
|
77
|
+
setShowAddressElement(event.value.type === "card");
|
|
78
|
+
};
|
|
71
79
|
const handleSubmit = async (e) => {
|
|
72
80
|
e.preventDefault();
|
|
73
81
|
if (!stripe || !elements) {
|
|
@@ -78,25 +86,29 @@ function StripePaymentForm({ order, clientSecret, onPaymentSuccess, }) {
|
|
|
78
86
|
setMessage(null);
|
|
79
87
|
try {
|
|
80
88
|
console.log("@@stripe-web2-payment:confirming-payment:", JSON.stringify({ orderId: order.id }, null, 2));
|
|
81
|
-
const
|
|
89
|
+
const result = (await stripe.confirmPayment({
|
|
82
90
|
elements,
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
console.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
// Add waitingForDeposit=true to query params
|
|
94
|
-
const currentUrl = new URL(window.location.href);
|
|
95
|
-
currentUrl.searchParams.set("waitingForDeposit", "true");
|
|
96
|
-
window.history.replaceState(null, "", currentUrl.toString());
|
|
97
|
-
// Call the success callback if provided
|
|
98
|
-
onPaymentSuccess?.(paymentIntent);
|
|
91
|
+
confirmParams: {
|
|
92
|
+
return_url: `${window.location.origin}/?orderId=${order.id}&waitingForDeposit=true&fromStripe=true`,
|
|
93
|
+
},
|
|
94
|
+
}));
|
|
95
|
+
if (result.error) {
|
|
96
|
+
// This point will only be reached if there is an immediate error.
|
|
97
|
+
// Otherwise, the customer will be redirected to the `return_url`.
|
|
98
|
+
console.error("@@stripe-web2-payment:error:", JSON.stringify(result.error, null, 2));
|
|
99
|
+
setMessage(result.error.message || "An unexpected error occurred.");
|
|
100
|
+
return;
|
|
99
101
|
}
|
|
102
|
+
// At this point TypeScript knows result.paymentIntent exists and error is undefined
|
|
103
|
+
console.log("@@stripe-web2-payment:success:", JSON.stringify({ orderId: order.id, paymentIntentId: result.paymentIntent.id }, null, 2));
|
|
104
|
+
// Payment succeeded without redirect - handle success in the modal
|
|
105
|
+
setMessage(null);
|
|
106
|
+
// Add waitingForDeposit=true to query params
|
|
107
|
+
const currentUrl = new URL(window.location.href);
|
|
108
|
+
currentUrl.searchParams.set("waitingForDeposit", "true");
|
|
109
|
+
window.history.replaceState(null, "", currentUrl.toString());
|
|
110
|
+
// Call the success callback if provided
|
|
111
|
+
onPaymentSuccess?.(result.paymentIntent);
|
|
100
112
|
}
|
|
101
113
|
catch (error) {
|
|
102
114
|
console.error("@@stripe-web2-payment:confirmation-error:", JSON.stringify(error, null, 2));
|
|
@@ -106,17 +118,27 @@ function StripePaymentForm({ order, clientSecret, onPaymentSuccess, }) {
|
|
|
106
118
|
setLoading(false);
|
|
107
119
|
}
|
|
108
120
|
};
|
|
121
|
+
// Handle 3DS redirect
|
|
122
|
+
(0, react_3.useEffect)(() => {
|
|
123
|
+
// Check if we're returning from Stripe
|
|
124
|
+
const url = new URL(window.location.href);
|
|
125
|
+
const fromStripe = url.searchParams.get("fromStripe");
|
|
126
|
+
const paymentIntent = url.searchParams.get("payment_intent");
|
|
127
|
+
console.log("@@stripe-web2-payment:fromStripe:", fromStripe);
|
|
128
|
+
console.log("@@stripe-web2-payment:paymentIntent:", paymentIntent);
|
|
129
|
+
if (fromStripe && paymentIntent) {
|
|
130
|
+
// Close the modal as we're returning from 3DS
|
|
131
|
+
setB3ModalOpen(true);
|
|
132
|
+
// Clean up URL params
|
|
133
|
+
url.searchParams.delete("fromStripe");
|
|
134
|
+
window.history.replaceState({}, "", url.toString());
|
|
135
|
+
}
|
|
136
|
+
}, [setB3ModalOpen]);
|
|
109
137
|
if (!stripeReady) {
|
|
110
138
|
return (0, jsx_runtime_1.jsx)(StripeLoadingState, {});
|
|
111
139
|
}
|
|
112
140
|
const stripeElementOptions = {
|
|
113
141
|
layout: "tabs",
|
|
114
|
-
defaultValues: {
|
|
115
|
-
billingDetails: {
|
|
116
|
-
name: "",
|
|
117
|
-
email: "",
|
|
118
|
-
},
|
|
119
|
-
},
|
|
120
142
|
fields: {
|
|
121
143
|
billingDetails: "auto",
|
|
122
144
|
},
|
|
@@ -144,7 +166,22 @@ function StripePaymentForm({ order, clientSecret, onPaymentSuccess, }) {
|
|
|
144
166
|
const finalAmount = Number(amount);
|
|
145
167
|
const calculatedFee = finalAmount - originalAmount;
|
|
146
168
|
return ((0, jsx_runtime_1.jsxs)("div", { className: "space-y-2", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between text-sm", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/60", children: "Amount" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary", children: ["$", originalAmount.toFixed(2)] })] }), (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between text-sm", children: [(0, jsx_runtime_1.jsxs)("div", { className: "flex items-center gap-1", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary/60", children: "Processing fee" }), (0, jsx_runtime_1.jsx)(Tooltip, { content: `Credit card companies charge a processing fee of 5.4% + $0.30 for all transactions.\n\nThis fee covers secure payment processing and fraud protection.`, children: (0, jsx_runtime_1.jsx)(lucide_react_1.Info, { className: "text-as-primary/40 hover:text-as-primary/60 h-3 w-3 transition-colors" }) })] }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary", children: ["$", calculatedFee.toFixed(2)] })] }), (0, jsx_runtime_1.jsx)("div", { className: "border-as-stroke border-t pt-2", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-as-primary font-semibold", children: "Total Amount" }), (0, jsx_runtime_1.jsxs)("span", { className: "text-as-primary text-2xl font-bold", children: ["$", finalAmount.toFixed(2), " USD"] })] }) })] }));
|
|
147
|
-
})()] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-as-on-surface-1 w-full rounded-2xl p-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary mb-4 text-lg font-semibold", children: "Payment Details" }), (0, jsx_runtime_1.jsx)(react_stripe_js_1.PaymentElement, {
|
|
169
|
+
})()] }))] }), (0, jsx_runtime_1.jsxs)("div", { className: "bg-as-on-surface-1 w-full rounded-2xl p-6", children: [(0, jsx_runtime_1.jsx)("div", { className: "text-as-primary mb-4 text-lg font-semibold", children: "Payment Details" }), (0, jsx_runtime_1.jsx)(react_stripe_js_1.PaymentElement, { onChange: handlePaymentElementChange, options: stripeElementOptions }), showAddressElement && ((0, jsx_runtime_1.jsx)(react_stripe_js_1.AddressElement, { options: {
|
|
170
|
+
mode: "billing",
|
|
171
|
+
fields: {
|
|
172
|
+
phone: "always",
|
|
173
|
+
},
|
|
174
|
+
// More granular control
|
|
175
|
+
display: {
|
|
176
|
+
name: "split", // or 'split' for first/last name separately
|
|
177
|
+
},
|
|
178
|
+
// Validation
|
|
179
|
+
validation: {
|
|
180
|
+
phone: {
|
|
181
|
+
required: "auto", // or 'always', 'never'
|
|
182
|
+
},
|
|
183
|
+
},
|
|
184
|
+
} }))] }), message && ((0, jsx_runtime_1.jsxs)("div", { className: "bg-as-red/10 border-as-red/20 flex w-full items-center gap-3 rounded-2xl border p-4", children: [(0, jsx_runtime_1.jsx)("div", { className: "bg-as-red flex h-6 w-6 shrink-0 items-center justify-center rounded-full", children: (0, jsx_runtime_1.jsx)("svg", { className: "h-4 w-4 text-white", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: (0, jsx_runtime_1.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }), (0, jsx_runtime_1.jsx)("div", { className: "text-as-red text-sm font-medium", children: message })] })), (0, jsx_runtime_1.jsx)(react_2.ShinyButton, { type: "submit", accentColor: "hsl(var(--as-brand))", disabled: !stripe || !elements || loading, className: "relative w-full py-4 text-lg font-semibold", children: loading ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-3", children: [(0, jsx_runtime_1.jsx)("div", { className: "h-5 w-5 animate-spin rounded-full border-2 border-current border-t-transparent" }), (0, jsx_runtime_1.jsx)("span", { className: "text-white", children: "Processing Payment..." })] })) : ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)("span", { className: "text-white", children: "Complete Payment" }), amount && (0, jsx_runtime_1.jsxs)("span", { className: "text-white/90", children: ["$", Number(amount).toFixed(2)] })] })) })] }), showHowItWorks && ((0, jsx_runtime_1.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4", children: (0, jsx_runtime_1.jsxs)("div", { className: "bg-as-on-surface-1 relative max-h-[80vh] w-full max-w-2xl overflow-y-auto rounded-2xl p-6", children: [(0, jsx_runtime_1.jsxs)("div", { className: "mb-6 flex items-center justify-between", children: [(0, jsx_runtime_1.jsx)("h2", { className: "text-as-primary text-xl font-semibold", children: "How it works" }), (0, jsx_runtime_1.jsx)("button", { onClick: () => setShowHowItWorks(false), className: "text-as-primary/60 hover:text-as-primary transition-colors", children: (0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "h-6 w-6" }) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "space-y-6", children: [(0, jsx_runtime_1.jsx)(PaymentMethodIcons_1.default, {}), (0, jsx_runtime_1.jsx)(HowItWorks_1.default, { steps: howItWorksSteps })] })] }) }))] }));
|
|
148
185
|
}
|
|
149
186
|
// Add tooltip component
|
|
150
187
|
function Tooltip({ children, content }) {
|
|
@@ -22,6 +22,7 @@ function StripePaymentForm({ order, onPaymentSuccess, }) {
|
|
|
22
22
|
const elements = (0, react_stripe_js_1.useElements)();
|
|
23
23
|
const [isProcessing, setIsProcessing] = (0, react_2.useState)(false);
|
|
24
24
|
const [error, setError] = (0, react_2.useState)(null);
|
|
25
|
+
const [showAddressElement, setShowAddressElement] = (0, react_2.useState)(false);
|
|
25
26
|
const handleSubmit = async (e) => {
|
|
26
27
|
e.preventDefault();
|
|
27
28
|
if (!stripe || !elements) {
|
|
@@ -51,16 +52,38 @@ function StripePaymentForm({ order, onPaymentSuccess, }) {
|
|
|
51
52
|
setIsProcessing(false);
|
|
52
53
|
}
|
|
53
54
|
};
|
|
55
|
+
// Handle payment element changes
|
|
56
|
+
const handlePaymentElementChange = (event) => {
|
|
57
|
+
// Show address element only for card payments
|
|
58
|
+
console.log("@@stripe-web2-payment:payment-element-change:", JSON.stringify(event, null, 2));
|
|
59
|
+
setShowAddressElement(event.value.type === "card");
|
|
60
|
+
};
|
|
54
61
|
const stripeElementOptions = {
|
|
55
62
|
layout: "tabs",
|
|
56
|
-
|
|
57
|
-
billingDetails:
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
63
|
+
fields: {
|
|
64
|
+
billingDetails: "auto",
|
|
65
|
+
},
|
|
66
|
+
wallets: {
|
|
67
|
+
applePay: "auto",
|
|
68
|
+
googlePay: "auto",
|
|
61
69
|
},
|
|
62
70
|
};
|
|
63
|
-
return ((0, jsx_runtime_1.jsx)("form", { onSubmit: handleSubmit, className: "w-full", children: (0, jsx_runtime_1.jsx)("div", { className: "overflow-hidden rounded-xl bg-white", children: (0, jsx_runtime_1.jsxs)("div", { className: "px-6 py-4", children: [(0, jsx_runtime_1.jsx)("h2", { className: "mb-4 text-lg font-semibold", children: "Payment Details" }), (0, jsx_runtime_1.jsx)(react_stripe_js_1.PaymentElement, { options: stripeElementOptions }),
|
|
71
|
+
return ((0, jsx_runtime_1.jsx)("form", { onSubmit: handleSubmit, className: "w-full", children: (0, jsx_runtime_1.jsx)("div", { className: "overflow-hidden rounded-xl bg-white", children: (0, jsx_runtime_1.jsxs)("div", { className: "px-6 py-4", children: [(0, jsx_runtime_1.jsx)("h2", { className: "mb-4 text-lg font-semibold", children: "Payment Details" }), (0, jsx_runtime_1.jsx)(react_stripe_js_1.PaymentElement, { options: stripeElementOptions, onChange: handlePaymentElementChange }), showAddressElement && ((0, jsx_runtime_1.jsx)("div", { className: "mt-4", children: (0, jsx_runtime_1.jsx)(react_stripe_js_1.AddressElement, { options: {
|
|
72
|
+
mode: "billing",
|
|
73
|
+
fields: {
|
|
74
|
+
phone: "always",
|
|
75
|
+
},
|
|
76
|
+
// More granular control
|
|
77
|
+
display: {
|
|
78
|
+
name: "split", // or 'split' for first/last name separately
|
|
79
|
+
},
|
|
80
|
+
// Validation
|
|
81
|
+
validation: {
|
|
82
|
+
phone: {
|
|
83
|
+
required: "auto", // or 'always', 'never'
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
} }) })), error && ((0, jsx_runtime_1.jsx)("div", { className: "mt-4 rounded-lg border border-red-200 bg-red-50 p-3 text-sm text-red-600", children: error })), (0, jsx_runtime_1.jsx)("button", { type: "submit", disabled: !stripe || isProcessing, className: "mt-6 w-full rounded-xl bg-blue-600 px-4 py-3 font-medium text-white hover:bg-blue-700 disabled:cursor-not-allowed disabled:opacity-50", children: isProcessing ? ((0, jsx_runtime_1.jsxs)("div", { className: "flex items-center justify-center gap-2", children: [(0, jsx_runtime_1.jsx)(lucide_react_1.Loader2, { className: "h-5 w-5 animate-spin" }), (0, jsx_runtime_1.jsx)("span", { children: "Processing..." })] })) : ((0, jsx_runtime_1.jsx)("span", { children: "Complete Payment" })) })] }) }) }));
|
|
64
87
|
}
|
|
65
88
|
function WebviewOnrampPayment({ srcAmountOnRamp, recipientAddress, destinationToken, anyspendQuote, onPaymentSuccess, userId, partnerId, }) {
|
|
66
89
|
const [stableAmountForGeo, setStableAmountForGeo] = (0, react_2.useState)(srcAmountOnRamp);
|
|
@@ -11,6 +11,7 @@ interface AnyspendProviderProps {
|
|
|
11
11
|
* - Optimized for performance with React.memo
|
|
12
12
|
* - Safe to use at the application root
|
|
13
13
|
* - Configures sensible defaults for query caching
|
|
14
|
+
* - Handles Stripe payment redirects and modal state
|
|
14
15
|
*
|
|
15
16
|
* @example
|
|
16
17
|
* ```tsx
|
|
@@ -6,6 +6,7 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
6
6
|
const react_1 = require("../../../global-account/react");
|
|
7
7
|
const react_query_1 = require("@tanstack/react-query");
|
|
8
8
|
const react_2 = require("react");
|
|
9
|
+
const StripeRedirectHandler_1 = require("./StripeRedirectHandler");
|
|
9
10
|
const defaultQueryClientConfig = {
|
|
10
11
|
defaultOptions: {
|
|
11
12
|
queries: {
|
|
@@ -24,6 +25,7 @@ const defaultQueryClientConfig = {
|
|
|
24
25
|
* - Optimized for performance with React.memo
|
|
25
26
|
* - Safe to use at the application root
|
|
26
27
|
* - Configures sensible defaults for query caching
|
|
28
|
+
* - Handles Stripe payment redirects and modal state
|
|
27
29
|
*
|
|
28
30
|
* @example
|
|
29
31
|
* ```tsx
|
|
@@ -38,6 +40,6 @@ const defaultQueryClientConfig = {
|
|
|
38
40
|
*/
|
|
39
41
|
const AnyspendProvider = function AnyspendProvider({ children }) {
|
|
40
42
|
const [queryClient] = (0, react_2.useState)(() => new react_query_1.QueryClient(defaultQueryClientConfig));
|
|
41
|
-
return ((0, jsx_runtime_1.jsx)(react_query_1.QueryClientProvider, { client: queryClient, children: (0, jsx_runtime_1.
|
|
43
|
+
return ((0, jsx_runtime_1.jsx)(react_query_1.QueryClientProvider, { client: queryClient, children: (0, jsx_runtime_1.jsxs)(react_1.TooltipProvider, { children: [(0, jsx_runtime_1.jsx)(StripeRedirectHandler_1.StripeRedirectHandler, {}), children] }) }));
|
|
42
44
|
};
|
|
43
45
|
exports.AnyspendProvider = AnyspendProvider;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Handles Stripe payment redirects by showing the order details modal
|
|
3
|
+
* when returning from Stripe's payment flow.
|
|
4
|
+
*
|
|
5
|
+
* This component should be mounted inside AnyspendProvider to ensure
|
|
6
|
+
* proper modal state management.
|
|
7
|
+
*/
|
|
8
|
+
export declare function StripeRedirectHandler(): null;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.StripeRedirectHandler = StripeRedirectHandler;
|
|
5
|
+
const react_1 = require("../../../global-account/react");
|
|
6
|
+
const react_2 = require("react");
|
|
7
|
+
/**
|
|
8
|
+
* Handles Stripe payment redirects by showing the order details modal
|
|
9
|
+
* when returning from Stripe's payment flow.
|
|
10
|
+
*
|
|
11
|
+
* This component should be mounted inside AnyspendProvider to ensure
|
|
12
|
+
* proper modal state management.
|
|
13
|
+
*/
|
|
14
|
+
function StripeRedirectHandler() {
|
|
15
|
+
const setB3ModalOpen = (0, react_1.useModalStore)(state => state.setB3ModalOpen);
|
|
16
|
+
const setB3ModalContentType = (0, react_1.useModalStore)(state => state.setB3ModalContentType);
|
|
17
|
+
(0, react_2.useEffect)(() => {
|
|
18
|
+
const url = new URL(window.location.href);
|
|
19
|
+
const fromStripe = url.searchParams.get("fromStripe");
|
|
20
|
+
const paymentIntent = url.searchParams.get("payment_intent");
|
|
21
|
+
const orderId = url.searchParams.get("orderId");
|
|
22
|
+
console.log("@@stripe-web2-payment:fromStripe:", fromStripe);
|
|
23
|
+
console.log("@@stripe-web2-payment:paymentIntent:", paymentIntent);
|
|
24
|
+
console.log("@@stripe-web2-payment:orderId:", orderId);
|
|
25
|
+
if (fromStripe && paymentIntent && orderId) {
|
|
26
|
+
// Re-open the modal with the order details
|
|
27
|
+
setB3ModalOpen(true);
|
|
28
|
+
setB3ModalContentType({
|
|
29
|
+
type: "anyspendOrderDetails",
|
|
30
|
+
orderId,
|
|
31
|
+
});
|
|
32
|
+
// Clean up URL params
|
|
33
|
+
url.searchParams.delete("fromStripe");
|
|
34
|
+
url.searchParams.delete("payment_intent");
|
|
35
|
+
url.searchParams.delete("payment_intent_client_secret");
|
|
36
|
+
url.searchParams.delete("redirect_status");
|
|
37
|
+
window.history.replaceState({}, "", url.toString());
|
|
38
|
+
}
|
|
39
|
+
}, [setB3ModalOpen, setB3ModalContentType]);
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
@@ -31,7 +31,7 @@ function B3DynamicModal() {
|
|
|
31
31
|
"anySpendSignatureMint",
|
|
32
32
|
"anySpendBondKit",
|
|
33
33
|
].find(type => contentType?.type === type)) {
|
|
34
|
-
contentClass += "
|
|
34
|
+
contentClass += " w-full";
|
|
35
35
|
}
|
|
36
36
|
if ([
|
|
37
37
|
"anySpendNft",
|
|
@@ -93,5 +93,5 @@ function B3DynamicModal() {
|
|
|
93
93
|
const ModalContent = isMobile ? drawer_1.DrawerContent : dialog_1.DialogContent;
|
|
94
94
|
const ModalTitle = isMobile ? drawer_1.DrawerTitle : dialog_1.DialogTitle;
|
|
95
95
|
const ModalDescription = isMobile ? drawer_1.DrawerDescription : dialog_1.DialogDescription;
|
|
96
|
-
return ((0, jsx_runtime_1.jsx)(ModalComponent, { open: isOpen, onOpenChange: setB3ModalOpen, children: (0, jsx_runtime_1.jsxs)(ModalContent, { className: contentClass, hideCloseButton: hideCloseButton, children: [(0, jsx_runtime_1.jsx)(ModalTitle, { className: "sr-only hidden", children: contentType?.type || "Modal" }), (0, jsx_runtime_1.jsx)(ModalDescription, { className: "sr-only hidden", children: contentType?.type || "Modal Body" }), (0, jsx_runtime_1.jsxs)("div", { className: "overflow-auto", children: [history.length > 0 && contentType?.showBackButton && ((0, jsx_runtime_1.jsxs)("button", { onClick: navigateBack, className: "b3-modal-back-button mb-4 flex items-center gap-2 transition-colors hover:text-white", children: [(0, jsx_runtime_1.jsx)("span", { children: "\u2190" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm", children: "Back" })] })), renderContent()] })] }) }));
|
|
96
|
+
return ((0, jsx_runtime_1.jsx)(ModalComponent, { open: isOpen, onOpenChange: setB3ModalOpen, children: (0, jsx_runtime_1.jsxs)(ModalContent, { className: contentClass, hideCloseButton: hideCloseButton, children: [(0, jsx_runtime_1.jsx)(ModalTitle, { className: "sr-only hidden", children: contentType?.type || "Modal" }), (0, jsx_runtime_1.jsx)(ModalDescription, { className: "sr-only hidden", children: contentType?.type || "Modal Body" }), (0, jsx_runtime_1.jsxs)("div", { className: "no-scrollbar max-h-[90dvh] overflow-auto sm:max-h-[80dvh]", children: [history.length > 0 && contentType?.showBackButton && ((0, jsx_runtime_1.jsxs)("button", { onClick: navigateBack, className: "b3-modal-back-button mb-4 flex items-center gap-2 transition-colors hover:text-white", children: [(0, jsx_runtime_1.jsx)("span", { children: "\u2190" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm", children: "Back" })] })), renderContent()] })] }) }));
|
|
97
97
|
}
|
|
@@ -53,7 +53,7 @@ exports.DialogOverlay = DialogOverlay;
|
|
|
53
53
|
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
54
54
|
const DialogContent = React.forwardRef(({ className, children, hideCloseButton = false, closeBtnClassName, ...props }, ref) => {
|
|
55
55
|
const container = typeof window !== "undefined" ? document.getElementById("b3-root") : null;
|
|
56
|
-
return ((0, jsx_runtime_1.jsxs)(DialogPortal, { container: container, children: [(0, jsx_runtime_1.jsx)(DialogOverlay, {}), (0, jsx_runtime_1.jsxs)(DialogPrimitive.Content, { ref: ref, className: (0, utils_1.cn)("bg-b3-react-background fixed left-
|
|
56
|
+
return ((0, jsx_runtime_1.jsxs)(DialogPortal, { container: container, children: [(0, jsx_runtime_1.jsx)(DialogOverlay, {}), (0, jsx_runtime_1.jsxs)(DialogPrimitive.Content, { ref: ref, className: (0, utils_1.cn)("bg-b3-react-background fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border p-6 shadow-lg !outline-none", "data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 duration-500", "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95", "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]", "[perspective:1200px] [transform-style:preserve-3d] sm:rounded-xl", "transition-all ease-out", className), ...props, children: [children, !hideCloseButton && ((0, jsx_runtime_1.jsxs)(DialogPrimitive.Close, { className: (0, utils_1.cn)("data-[state=open]:bg-b3-react-background data-[state=open]:text-b3-react-muted-foreground absolute right-4 top-4 rounded-sm opacity-70 transition-opacity hover:opacity-100 focus:outline-none disabled:pointer-events-none dark:data-[state=open]:bg-gray-800 dark:data-[state=open]:text-gray-400", closeBtnClassName), children: [(0, jsx_runtime_1.jsx)(lucide_react_1.X, { className: "h-5 w-5" }), (0, jsx_runtime_1.jsx)("span", { className: "sr-only", children: "Close" })] }))] })] }));
|
|
57
57
|
});
|
|
58
58
|
exports.DialogContent = DialogContent;
|
|
59
59
|
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
@@ -20,6 +20,7 @@ export { useMediaQuery } from "./useMediaQuery";
|
|
|
20
20
|
export { useNativeBalance, useNativeBalanceFromRPC } from "./useNativeBalance";
|
|
21
21
|
export { useOnchainName } from "./useOnchainName";
|
|
22
22
|
export { useOneBalance } from "./useOneBalance";
|
|
23
|
+
export { useProfile, useProfilePreference, type Profile, type CombinedProfile, type PreferenceRequestBody, } from "./useProfile";
|
|
23
24
|
export { useQueryB3 } from "./useQueryB3";
|
|
24
25
|
export { useQueryBSMNT } from "./useQueryBSMNT";
|
|
25
26
|
export { useRemoveSessionKey } from "./useRemoveSessionKey";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useURLParams = exports.useTokensFromAddress = exports.useTokenPriceWithFallback = exports.useTokenPrice = exports.useTokenFromUrl = exports.useTokenData = exports.useTokenBalancesByChain = exports.useTokenBalance = exports.useSiwe = exports.useSearchParamsSSR = exports.useRouter = exports.useRemoveSessionKey = exports.useQueryBSMNT = exports.useQueryB3 = exports.useOneBalance = exports.useOnchainName = exports.useNativeBalanceFromRPC = exports.useNativeBalance = exports.useMediaQuery = exports.useIsomorphicLayoutEffect = exports.useIsMobile = exports.useHasMounted = exports.useHandleConnectWithPrivy = exports.useGetGeo = exports.useGetAllTWSigners = exports.useExchangeRate = exports.useConnect = exports.useClaim = exports.useChainSwitchWithAction = exports.useBsmntProfile = exports.useBestTransactionPath = exports.useB3EnsName = exports.useB3BalanceFromAddresses = exports.useAuthentication = exports.useAddTWSessionKey = exports.useAccountWallet = exports.useAccountAssets = void 0;
|
|
3
|
+
exports.useURLParams = exports.useTokensFromAddress = exports.useTokenPriceWithFallback = exports.useTokenPrice = exports.useTokenFromUrl = exports.useTokenData = exports.useTokenBalancesByChain = exports.useTokenBalance = exports.useSiwe = exports.useSearchParamsSSR = exports.useRouter = exports.useRemoveSessionKey = exports.useQueryBSMNT = exports.useQueryB3 = exports.useProfilePreference = exports.useProfile = exports.useOneBalance = exports.useOnchainName = exports.useNativeBalanceFromRPC = exports.useNativeBalance = exports.useMediaQuery = exports.useIsomorphicLayoutEffect = exports.useIsMobile = exports.useHasMounted = exports.useHandleConnectWithPrivy = exports.useGetGeo = exports.useGetAllTWSigners = exports.useExchangeRate = exports.useConnect = exports.useClaim = exports.useChainSwitchWithAction = exports.useBsmntProfile = exports.useBestTransactionPath = exports.useB3EnsName = exports.useB3BalanceFromAddresses = exports.useAuthentication = exports.useAddTWSessionKey = exports.useAccountWallet = exports.useAccountAssets = void 0;
|
|
4
4
|
var useAccountAssets_1 = require("./useAccountAssets");
|
|
5
5
|
Object.defineProperty(exports, "useAccountAssets", { enumerable: true, get: function () { return useAccountAssets_1.useAccountAssets; } });
|
|
6
6
|
var useAccountWallet_1 = require("./useAccountWallet");
|
|
@@ -46,6 +46,9 @@ var useOnchainName_1 = require("./useOnchainName");
|
|
|
46
46
|
Object.defineProperty(exports, "useOnchainName", { enumerable: true, get: function () { return useOnchainName_1.useOnchainName; } });
|
|
47
47
|
var useOneBalance_1 = require("./useOneBalance");
|
|
48
48
|
Object.defineProperty(exports, "useOneBalance", { enumerable: true, get: function () { return useOneBalance_1.useOneBalance; } });
|
|
49
|
+
var useProfile_1 = require("./useProfile");
|
|
50
|
+
Object.defineProperty(exports, "useProfile", { enumerable: true, get: function () { return useProfile_1.useProfile; } });
|
|
51
|
+
Object.defineProperty(exports, "useProfilePreference", { enumerable: true, get: function () { return useProfile_1.useProfilePreference; } });
|
|
49
52
|
var useQueryB3_1 = require("./useQueryB3");
|
|
50
53
|
Object.defineProperty(exports, "useQueryB3", { enumerable: true, get: function () { return useQueryB3_1.useQueryB3; } });
|
|
51
54
|
var useQueryBSMNT_1 = require("./useQueryBSMNT");
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
export interface Profile {
|
|
2
|
+
type: string;
|
|
3
|
+
address?: string;
|
|
4
|
+
name?: string;
|
|
5
|
+
avatar?: string | null;
|
|
6
|
+
bio?: string | null;
|
|
7
|
+
displayName?: string | null;
|
|
8
|
+
}
|
|
9
|
+
export interface CombinedProfile {
|
|
10
|
+
name: string | null;
|
|
11
|
+
address: string | null;
|
|
12
|
+
avatar: string | null;
|
|
13
|
+
bio: string | null;
|
|
14
|
+
displayName: string | null;
|
|
15
|
+
profiles: Profile[];
|
|
16
|
+
}
|
|
17
|
+
export interface PreferenceRequestBody {
|
|
18
|
+
key: string;
|
|
19
|
+
preferredType: string;
|
|
20
|
+
signature: string;
|
|
21
|
+
signer: string;
|
|
22
|
+
timestamp: number;
|
|
23
|
+
}
|
|
24
|
+
export declare function useProfile({ address, name, fresh, }: {
|
|
25
|
+
address?: string;
|
|
26
|
+
name?: string;
|
|
27
|
+
fresh?: boolean;
|
|
28
|
+
}, options?: {
|
|
29
|
+
enabled?: boolean;
|
|
30
|
+
refetchInterval?: number;
|
|
31
|
+
staleTime?: number;
|
|
32
|
+
}): import("@tanstack/react-query").UseQueryResult<CombinedProfile, Error>;
|
|
33
|
+
export declare function useProfilePreference(): {
|
|
34
|
+
setPreference: (key: string, preferredType: string, signerAddress: string, signMessage: (message: string) => Promise<string>) => Promise<{
|
|
35
|
+
success: boolean;
|
|
36
|
+
}>;
|
|
37
|
+
};
|
|
38
|
+
export default useProfile;
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useProfile = useProfile;
|
|
4
|
+
exports.useProfilePreference = useProfilePreference;
|
|
5
|
+
const react_query_1 = require("@tanstack/react-query");
|
|
6
|
+
const PROFILES_API_URL = "https://profiles.b3.fun";
|
|
7
|
+
async function fetchProfile({ address, name, fresh = false, }) {
|
|
8
|
+
if (!address && !name) {
|
|
9
|
+
throw new Error("Either address or name must be provided");
|
|
10
|
+
}
|
|
11
|
+
const params = new URLSearchParams();
|
|
12
|
+
if (address)
|
|
13
|
+
params.append("address", address);
|
|
14
|
+
if (name)
|
|
15
|
+
params.append("name", name);
|
|
16
|
+
if (fresh)
|
|
17
|
+
params.append("fresh", "true");
|
|
18
|
+
const response = await fetch(`${PROFILES_API_URL}?${params.toString()}`);
|
|
19
|
+
if (!response.ok) {
|
|
20
|
+
throw new Error(`Failed to fetch profile: ${response.statusText}`);
|
|
21
|
+
}
|
|
22
|
+
return response.json();
|
|
23
|
+
}
|
|
24
|
+
async function setProfilePreference({ key, preferredType, signature, signer, timestamp, }) {
|
|
25
|
+
const response = await fetch(`${PROFILES_API_URL}/preference`, {
|
|
26
|
+
method: "POST",
|
|
27
|
+
headers: {
|
|
28
|
+
"Content-Type": "application/json",
|
|
29
|
+
},
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
key,
|
|
32
|
+
preferredType,
|
|
33
|
+
signature,
|
|
34
|
+
signer,
|
|
35
|
+
timestamp,
|
|
36
|
+
}),
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
throw new Error(`Failed to set preference: ${response.statusText}`);
|
|
40
|
+
}
|
|
41
|
+
return response.json();
|
|
42
|
+
}
|
|
43
|
+
function useProfile({ address, name, fresh = false, }, options) {
|
|
44
|
+
return (0, react_query_1.useQuery)({
|
|
45
|
+
queryKey: ["profile", address || name, fresh],
|
|
46
|
+
queryFn: () => fetchProfile({ address, name, fresh }),
|
|
47
|
+
enabled: (options?.enabled ?? true) && (!!address || !!name),
|
|
48
|
+
refetchInterval: options?.refetchInterval,
|
|
49
|
+
staleTime: options?.staleTime ?? 5 * 60 * 1000, // 5 minutes default
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
function useProfilePreference() {
|
|
53
|
+
const setPreference = async (key, preferredType, signerAddress, signMessage) => {
|
|
54
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
55
|
+
const message = `SetProfilePreference:${key}:${preferredType}:${timestamp}`;
|
|
56
|
+
try {
|
|
57
|
+
const signature = await signMessage(message);
|
|
58
|
+
return setProfilePreference({
|
|
59
|
+
key,
|
|
60
|
+
preferredType,
|
|
61
|
+
signature,
|
|
62
|
+
signer: signerAddress,
|
|
63
|
+
timestamp,
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new Error(`Failed to set profile preference: ${error}`);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return { setPreference };
|
|
71
|
+
}
|
|
72
|
+
exports.default = useProfile;
|
|
@@ -363,7 +363,7 @@ export function AnySpendCustom({ isMainnet = true, loadOrder, mode = "modal", re
|
|
|
363
363
|
const historyView = (_jsx("div", { className: cn("mx-auto flex w-full max-w-2xl flex-col items-center p-5", mode === "modal" && "bg-b3-react-background"), children: _jsx(OrderHistory, { mode: mode, onBack: () => {
|
|
364
364
|
setActivePanel(PanelView.HISTORY);
|
|
365
365
|
}, onSelectOrder: onSelectOrder }) }));
|
|
366
|
-
const orderDetailsView = (_jsxs("div", { className: cn("mx-auto flex
|
|
366
|
+
const orderDetailsView = (_jsxs("div", { className: cn("mx-auto flex w-full flex-col items-center gap-4 p-5", mode === "modal" && "bg-b3-react-background"), children: [oat && (_jsxs(_Fragment, { children: [_jsx(OrderStatusDisplay, { order: oat.data.order }), _jsx(OrderDetails, { isMainnet: isMainnet, mode: mode, order: oat.data.order, depositTxs: oat.data.depositTxs, relayTx: oat.data.relayTx, executeTx: oat.data.executeTx, refundTxs: oat.data.refundTxs, onBack: () => {
|
|
367
367
|
setOrderId(undefined);
|
|
368
368
|
setActivePanel(PanelView.CONFIRM_ORDER);
|
|
369
369
|
// Remove orderId from URL when canceling
|