@b3dotfun/sdk 0.1.68-alpha.4 → 0.1.68-alpha.6
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.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/AnySpend.js +128 -11
- package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.js +2 -2
- package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckoutTrigger.js +2 -2
- package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -2
- package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
- package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.js +14 -13
- package/dist/cjs/anyspend/react/components/checkout/KycGate.d.ts +11 -0
- package/dist/cjs/anyspend/react/components/checkout/KycGate.js +181 -0
- package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/cjs/anyspend/react/hooks/index.js +1 -0
- package/dist/cjs/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +9 -0
- package/dist/cjs/anyspend/react/hooks/useKycStatus.d.ts +42 -0
- package/dist/cjs/anyspend/react/hooks/useKycStatus.js +113 -0
- package/dist/cjs/anyspend/services/anyspend.d.ts +3 -1
- package/dist/cjs/anyspend/services/anyspend.js +2 -1
- package/dist/cjs/global-account/react/components/B3DynamicModal.js +1 -1
- package/dist/cjs/global-account/react/components/ManageAccount/BottomNavigation.js +3 -3
- package/dist/cjs/global-account/react/hooks/useAuth.js +1 -1
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +4 -0
- package/dist/cjs/global-account/react/stores/useModalStore.js +2 -0
- package/dist/cjs/global-account/react/utils/createWagmiConfig.d.ts +18 -0
- package/dist/cjs/global-account/react/utils/createWagmiConfig.js +17 -0
- package/dist/esm/anyspend/react/components/AnySpend.d.ts +3 -1
- package/dist/esm/anyspend/react/components/AnySpend.js +129 -12
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.d.ts +3 -1
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.js +2 -2
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
- package/dist/esm/anyspend/react/components/checkout/AnySpendCheckoutTrigger.js +2 -2
- package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
- package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -2
- package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
- package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.js +14 -13
- package/dist/esm/anyspend/react/components/checkout/KycGate.d.ts +11 -0
- package/dist/esm/anyspend/react/components/checkout/KycGate.js +145 -0
- package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/esm/anyspend/react/hooks/index.js +1 -0
- package/dist/esm/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +9 -0
- package/dist/esm/anyspend/react/hooks/useKycStatus.d.ts +42 -0
- package/dist/esm/anyspend/react/hooks/useKycStatus.js +107 -0
- package/dist/esm/anyspend/services/anyspend.d.ts +3 -1
- package/dist/esm/anyspend/services/anyspend.js +2 -1
- package/dist/esm/global-account/react/components/B3DynamicModal.js +1 -1
- package/dist/esm/global-account/react/components/ManageAccount/BottomNavigation.js +3 -3
- package/dist/esm/global-account/react/hooks/useAuth.js +2 -2
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +4 -0
- package/dist/esm/global-account/react/stores/useModalStore.js +2 -0
- package/dist/esm/global-account/react/utils/createWagmiConfig.d.ts +18 -0
- package/dist/esm/global-account/react/utils/createWagmiConfig.js +16 -0
- package/dist/styles/index.css +1 -1
- package/dist/types/anyspend/react/components/AnySpend.d.ts +3 -1
- package/dist/types/anyspend/react/components/checkout/AnySpendCheckout.d.ts +3 -1
- package/dist/types/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
- package/dist/types/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
- package/dist/types/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
- package/dist/types/anyspend/react/components/checkout/KycGate.d.ts +11 -0
- package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
- package/dist/types/anyspend/react/hooks/useKycStatus.d.ts +42 -0
- package/dist/types/anyspend/services/anyspend.d.ts +3 -1
- package/dist/types/global-account/react/stores/useModalStore.d.ts +4 -0
- package/dist/types/global-account/react/utils/createWagmiConfig.d.ts +18 -0
- package/package.json +2 -1
- package/src/anyspend/react/components/AnySpend.tsx +150 -13
- package/src/anyspend/react/components/checkout/AnySpendCheckout.tsx +4 -0
- package/src/anyspend/react/components/checkout/AnySpendCheckoutTrigger.tsx +4 -0
- package/src/anyspend/react/components/checkout/CheckoutPaymentPanel.tsx +4 -0
- package/src/anyspend/react/components/checkout/FiatCheckoutPanel.tsx +19 -13
- package/src/anyspend/react/components/checkout/KycGate.tsx +351 -0
- package/src/anyspend/react/hooks/index.ts +1 -0
- package/src/anyspend/react/hooks/useAnyspendCreateOnrampOrder.ts +10 -0
- package/src/anyspend/react/hooks/useKycStatus.ts +140 -0
- package/src/anyspend/services/anyspend.ts +4 -0
- package/src/global-account/react/components/B3DynamicModal.tsx +0 -2
- package/src/global-account/react/components/ManageAccount/BottomNavigation.tsx +7 -7
- package/src/global-account/react/hooks/useAuth.ts +2 -2
- package/src/global-account/react/stores/useModalStore.ts +6 -0
- package/src/global-account/react/utils/createWagmiConfig.tsx +18 -0
|
@@ -18,7 +18,9 @@ export declare enum PanelView {
|
|
|
18
18
|
FIAT_PAYMENT_METHOD = 7,
|
|
19
19
|
POINTS_DETAIL = 8,
|
|
20
20
|
FEE_DETAIL = 9,
|
|
21
|
-
DIRECT_TRANSFER_SUCCESS = 10
|
|
21
|
+
DIRECT_TRANSFER_SUCCESS = 10,
|
|
22
|
+
FIAT_KYC = 11,
|
|
23
|
+
FIAT_AUTH = 12
|
|
22
24
|
}
|
|
23
25
|
export declare function AnySpend(props: {
|
|
24
26
|
mode?: "page" | "modal";
|
|
@@ -37,6 +37,9 @@ const FiatPaymentMethod_1 = require("./common/FiatPaymentMethod");
|
|
|
37
37
|
const GasIndicator_1 = require("./common/GasIndicator");
|
|
38
38
|
const OrderDetails_1 = require("./common/OrderDetails");
|
|
39
39
|
const OrderHistory_1 = require("./common/OrderHistory");
|
|
40
|
+
const KycGate_1 = require("./checkout/KycGate");
|
|
41
|
+
const useKycStatus_1 = require("../hooks/useKycStatus");
|
|
42
|
+
const LoginStep_1 = require("../../../global-account/react/components/SignInWithB3/steps/LoginStep");
|
|
40
43
|
const PanelOnramp_1 = require("./common/PanelOnramp");
|
|
41
44
|
const PanelOnrampPayment_1 = require("./common/PanelOnrampPayment");
|
|
42
45
|
const PointsDetailPanel_1 = require("./common/PointsDetailPanel");
|
|
@@ -57,6 +60,8 @@ var PanelView;
|
|
|
57
60
|
PanelView[PanelView["POINTS_DETAIL"] = 8] = "POINTS_DETAIL";
|
|
58
61
|
PanelView[PanelView["FEE_DETAIL"] = 9] = "FEE_DETAIL";
|
|
59
62
|
PanelView[PanelView["DIRECT_TRANSFER_SUCCESS"] = 10] = "DIRECT_TRANSFER_SUCCESS";
|
|
63
|
+
PanelView[PanelView["FIAT_KYC"] = 11] = "FIAT_KYC";
|
|
64
|
+
PanelView[PanelView["FIAT_AUTH"] = 12] = "FIAT_AUTH";
|
|
60
65
|
})(PanelView || (exports.PanelView = PanelView = {}));
|
|
61
66
|
const ANYSPEND_RECIPIENTS_KEY = "anyspend_recipients";
|
|
62
67
|
function AnySpend(props) {
|
|
@@ -70,6 +75,16 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
70
75
|
const { partnerId } = (0, react_2.useB3Config)();
|
|
71
76
|
const setB3ModalContentType = (0, react_2.useModalStore)(state => state.setB3ModalContentType);
|
|
72
77
|
const setB3ModalOpen = (0, react_2.useModalStore)(state => state.setB3ModalOpen);
|
|
78
|
+
const { isAuthenticated } = (0, react_2.useAuth)();
|
|
79
|
+
// KYC approval is tracked per-session so we only prompt the wallet
|
|
80
|
+
// signature when the user actually clicks Buy, not on panel mount.
|
|
81
|
+
// useRef so handleFiatOrder can read the updated value synchronously
|
|
82
|
+
// in the same frame that onStatusResolved sets it (setState is async).
|
|
83
|
+
const kycApprovedRef = (0, react_4.useRef)(false);
|
|
84
|
+
// Pre-warm wallet auth headers inside user-gesture context (button click)
|
|
85
|
+
// so the signing prompt fires before we navigate away — browsers block
|
|
86
|
+
// wallet popups triggered from async/non-gesture contexts (React Query queryFn).
|
|
87
|
+
const { getHeaders: getKycHeaders } = (0, useKycStatus_1.useWalletAuthHeaders)();
|
|
73
88
|
// Determine if we're in "buy mode" based on whether destination token props are provided
|
|
74
89
|
const isBuyMode = !!(destinationTokenAddress && destinationTokenChainId);
|
|
75
90
|
// Add refs to track URL state
|
|
@@ -79,7 +94,17 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
79
94
|
const animationDirection = (0, react_4.useRef)(null);
|
|
80
95
|
// Track previous panel for proper back navigation
|
|
81
96
|
const previousPanel = (0, react_4.useRef)(PanelView.MAIN);
|
|
82
|
-
const [activeTab, setActiveTab] = (0, react_4.useState)(
|
|
97
|
+
const [activeTab, setActiveTab] = (0, react_4.useState)(() => {
|
|
98
|
+
if (typeof window !== "undefined") {
|
|
99
|
+
const stored = sessionStorage.getItem("anyspend_active_tab");
|
|
100
|
+
if (stored === "crypto" || stored === "fiat")
|
|
101
|
+
return stored;
|
|
102
|
+
}
|
|
103
|
+
return defaultActiveTab;
|
|
104
|
+
});
|
|
105
|
+
(0, react_4.useEffect)(() => {
|
|
106
|
+
sessionStorage.setItem("anyspend_active_tab", activeTab);
|
|
107
|
+
}, [activeTab]);
|
|
83
108
|
const [orderId, setOrderId] = (0, react_4.useState)(loadOrder);
|
|
84
109
|
const [directTransferTxHash, setDirectTransferTxHash] = (0, react_4.useState)();
|
|
85
110
|
const { orderAndTransactions: oat, getOrderAndTransactionsError } = (0, react_1.useAnyspendOrderAndTransactions)(orderId);
|
|
@@ -100,9 +125,19 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
100
125
|
const [customRecipients, setCustomRecipients] = (0, react_4.useState)([]);
|
|
101
126
|
// Payment method state with dual-state system (auto + explicit user selection)
|
|
102
127
|
const { cryptoPaymentMethod, setCryptoPaymentMethod, selectedCryptoPaymentMethod, setSelectedCryptoPaymentMethod, effectiveCryptoPaymentMethod, resetPaymentMethods, } = (0, useCryptoPaymentMethodState_1.useCryptoPaymentMethodState)();
|
|
103
|
-
const [selectedFiatPaymentMethod, setSelectedFiatPaymentMethod] = (0, react_4.useState)(
|
|
128
|
+
const [selectedFiatPaymentMethod, setSelectedFiatPaymentMethod] = (0, react_4.useState)(() => {
|
|
129
|
+
if (typeof window !== "undefined") {
|
|
130
|
+
const stored = sessionStorage.getItem("anyspend_fiat_method");
|
|
131
|
+
if (stored && Object.values(FiatPaymentMethod_1.FiatPaymentMethod).includes(stored))
|
|
132
|
+
return stored;
|
|
133
|
+
}
|
|
134
|
+
return FiatPaymentMethod_1.FiatPaymentMethod.NONE;
|
|
135
|
+
});
|
|
104
136
|
// const [newRecipientAddress, setNewRecipientAddress] = useState("");
|
|
105
137
|
// const recipientInputRef = useRef<HTMLInputElement>(null);
|
|
138
|
+
(0, react_4.useEffect)(() => {
|
|
139
|
+
sessionStorage.setItem("anyspend_fiat_method", selectedFiatPaymentMethod);
|
|
140
|
+
}, [selectedFiatPaymentMethod]);
|
|
106
141
|
// Get initial chain IDs from URL or defaults
|
|
107
142
|
const initialSrcChainId = sourceChainId || parseInt(searchParams.get("fromChainId") || "0") || chains_1.mainnet.id;
|
|
108
143
|
const initialDstChainId = parseInt(searchParams.get("toChainId") || "0") || (isBuyMode ? destinationTokenChainId : chains_1.base.id);
|
|
@@ -119,10 +154,27 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
119
154
|
const [selectedSrcToken, setSelectedSrcToken] = (0, react_4.useState)(effectiveSrcToken);
|
|
120
155
|
const { data: srcTokenMetadata } = (0, react_2.useTokenData)(selectedSrcToken?.chainId, selectedSrcToken?.address);
|
|
121
156
|
const [srcAmount, setSrcAmount] = (0, react_4.useState)(searchParams.get("fromAmount") || "0");
|
|
122
|
-
// State for onramp amount
|
|
123
|
-
const [srcAmountOnRamp, setSrcAmountOnRamp] = (0, react_4.useState)(
|
|
124
|
-
|
|
125
|
-
|
|
157
|
+
// State for onramp amount — persisted in sessionStorage so it survives Persona KYC roundtrip
|
|
158
|
+
const [srcAmountOnRamp, setSrcAmountOnRamp] = (0, react_4.useState)(() => {
|
|
159
|
+
if (typeof window !== "undefined") {
|
|
160
|
+
const stored = sessionStorage.getItem("anyspend_fiat_amount");
|
|
161
|
+
if (stored)
|
|
162
|
+
return stored;
|
|
163
|
+
}
|
|
164
|
+
return searchParams.get("fromAmount") || "5";
|
|
165
|
+
});
|
|
166
|
+
(0, react_4.useEffect)(() => {
|
|
167
|
+
sessionStorage.setItem("anyspend_fiat_amount", srcAmountOnRamp);
|
|
168
|
+
}, [srcAmountOnRamp]);
|
|
169
|
+
// State for destination chain/token selection (sync effects come after state declarations below) — persisted in sessionStorage for Persona KYC roundtrip
|
|
170
|
+
const [selectedDstChainId, setSelectedDstChainId] = (0, react_4.useState)(() => {
|
|
171
|
+
if (!isBuyMode && typeof window !== "undefined") {
|
|
172
|
+
const stored = sessionStorage.getItem("anyspend_dst_chain_id");
|
|
173
|
+
if (stored)
|
|
174
|
+
return parseInt(stored, 10);
|
|
175
|
+
}
|
|
176
|
+
return initialDstChainId;
|
|
177
|
+
});
|
|
126
178
|
// Helper to check if address is Hyperliquid USDC (supports both 34-char and 42-char formats)
|
|
127
179
|
const isHyperliquidUSDCAddress = (address) => (0, anyspend_1.eqci)(address, anyspend_1.HYPERLIQUID_USDC_ADDRESS) || (0, anyspend_1.eqci)(address, anyspend_1.ZERO_ADDRESS);
|
|
128
180
|
const defaultDstToken = isBuyMode
|
|
@@ -142,9 +194,29 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
142
194
|
defaultToken: defaultDstToken,
|
|
143
195
|
prefix: "to",
|
|
144
196
|
});
|
|
145
|
-
const [selectedDstToken, setSelectedDstToken] = (0, react_4.useState)(
|
|
197
|
+
const [selectedDstToken, setSelectedDstToken] = (0, react_4.useState)(() => {
|
|
198
|
+
if (!isBuyMode && typeof window !== "undefined") {
|
|
199
|
+
const stored = sessionStorage.getItem("anyspend_dst_token");
|
|
200
|
+
if (stored) {
|
|
201
|
+
try {
|
|
202
|
+
return JSON.parse(stored);
|
|
203
|
+
}
|
|
204
|
+
catch { }
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return isBuyMode ? defaultDstToken : dstTokenFromUrl;
|
|
208
|
+
});
|
|
146
209
|
const { data: dstTokenMetadata } = (0, react_2.useTokenData)(selectedDstToken?.chainId, selectedDstToken?.address);
|
|
147
210
|
const [dstAmount, setDstAmount] = (0, react_4.useState)(searchParams.get("toAmount") || "");
|
|
211
|
+
// Sync dst chain/token to sessionStorage so they survive Persona KYC roundtrip
|
|
212
|
+
(0, react_4.useEffect)(() => {
|
|
213
|
+
if (!isBuyMode)
|
|
214
|
+
sessionStorage.setItem("anyspend_dst_chain_id", selectedDstChainId.toString());
|
|
215
|
+
}, [selectedDstChainId, isBuyMode]);
|
|
216
|
+
(0, react_4.useEffect)(() => {
|
|
217
|
+
if (!isBuyMode)
|
|
218
|
+
sessionStorage.setItem("anyspend_dst_token", JSON.stringify(selectedDstToken));
|
|
219
|
+
}, [selectedDstToken, isBuyMode]);
|
|
148
220
|
const [isSrcInputDirty, setIsSrcInputDirty] = (0, react_4.useState)(true);
|
|
149
221
|
// Add refs to track if we've applied metadata
|
|
150
222
|
const appliedSrcMetadataRef = (0, react_4.useRef)(false);
|
|
@@ -497,6 +569,16 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
497
569
|
}, [anyspendQuote, isSrcInputDirty, destinationTokenAmount]);
|
|
498
570
|
// Call onSuccess when order is executed
|
|
499
571
|
(0, useOnOrderSuccess_1.useOnOrderSuccess)({ orderData: oat, orderId, onSuccess });
|
|
572
|
+
// Clear all persisted selection state once an order is submitted — next open starts fresh
|
|
573
|
+
(0, react_4.useEffect)(() => {
|
|
574
|
+
if (orderId) {
|
|
575
|
+
sessionStorage.removeItem("anyspend_fiat_amount");
|
|
576
|
+
sessionStorage.removeItem("anyspend_active_tab");
|
|
577
|
+
sessionStorage.removeItem("anyspend_fiat_method");
|
|
578
|
+
sessionStorage.removeItem("anyspend_dst_chain_id");
|
|
579
|
+
sessionStorage.removeItem("anyspend_dst_token");
|
|
580
|
+
}
|
|
581
|
+
}, [orderId]);
|
|
500
582
|
const { createOrder, isCreatingOrder } = (0, react_1.useAnyspendCreateOrder)({
|
|
501
583
|
onSuccess: data => {
|
|
502
584
|
const orderId = data.data.id;
|
|
@@ -577,8 +659,8 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
577
659
|
if (selectedFiatPaymentMethod === FiatPaymentMethod_1.FiatPaymentMethod.NONE) {
|
|
578
660
|
return { text: "Select payment method", disable: false, error: false, loading: false };
|
|
579
661
|
}
|
|
580
|
-
// If payment method is selected, show "
|
|
581
|
-
return { text: "
|
|
662
|
+
// If payment method is selected, show "Continue"
|
|
663
|
+
return { text: "Continue", disable: false, error: false, loading: false };
|
|
582
664
|
}
|
|
583
665
|
if (activeTab === "crypto") {
|
|
584
666
|
// For crypto: check payment method first, then recipient
|
|
@@ -599,7 +681,7 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
599
681
|
return { text: "Continue to payment", disable: false, error: false, loading: false };
|
|
600
682
|
}
|
|
601
683
|
}
|
|
602
|
-
return { text: "
|
|
684
|
+
return { text: "Continue", disable: false, error: false, loading: false };
|
|
603
685
|
}, [
|
|
604
686
|
activeInputAmountInWei,
|
|
605
687
|
isSameChainSameToken,
|
|
@@ -761,7 +843,22 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
761
843
|
paymentMethodString = "";
|
|
762
844
|
}
|
|
763
845
|
else if (paymentMethod === FiatPaymentMethod_1.FiatPaymentMethod.STRIPE_WEB2) {
|
|
764
|
-
// Stripe embedded payment form
|
|
846
|
+
// Stripe embedded payment form requires authentication + KYC
|
|
847
|
+
// Read from store directly to avoid stale closure when called from onLoginSuccess callback
|
|
848
|
+
const currentlyAuthenticated = react_2.useAuthStore.getState().isAuthenticated;
|
|
849
|
+
if (!currentlyAuthenticated) {
|
|
850
|
+
navigateToPanel(PanelView.FIAT_AUTH, "forward");
|
|
851
|
+
return;
|
|
852
|
+
}
|
|
853
|
+
if (!kycApprovedRef.current) {
|
|
854
|
+
// Pre-sign the KYC auth message NOW (user-gesture context) so the
|
|
855
|
+
// result is cached before useKycStatus fires its queryFn inside the
|
|
856
|
+
// FIAT_KYC panel. Wallets/browsers block signing prompts from async
|
|
857
|
+
// (non-gesture) contexts, which is exactly what React Query uses.
|
|
858
|
+
await getKycHeaders().catch(() => { });
|
|
859
|
+
navigateToPanel(PanelView.FIAT_KYC, "forward");
|
|
860
|
+
return;
|
|
861
|
+
}
|
|
765
862
|
if (!stripeWeb2Support.isSupport) {
|
|
766
863
|
react_2.toast.error("Pay with Card not available");
|
|
767
864
|
return;
|
|
@@ -870,6 +967,14 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
870
967
|
window.removeEventListener("popstate", handlePopState);
|
|
871
968
|
};
|
|
872
969
|
}, [activePanel, navigateBack]);
|
|
970
|
+
// When auth completes while on the FIAT_AUTH panel, navigate back and retry the order
|
|
971
|
+
(0, react_4.useEffect)(() => {
|
|
972
|
+
if (isAuthenticated && activePanel === PanelView.FIAT_AUTH) {
|
|
973
|
+
navigateBack();
|
|
974
|
+
handleFiatOrder(selectedFiatPaymentMethod);
|
|
975
|
+
}
|
|
976
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
977
|
+
}, [isAuthenticated]);
|
|
873
978
|
const historyView = ((0, jsx_runtime_1.jsx)("div", { className: "mx-auto flex w-[560px] max-w-full flex-col items-center", children: (0, jsx_runtime_1.jsx)(OrderHistory_1.OrderHistory, { mode: mode, onBack: navigateBack, onSelectOrder: onSelectOrder }) }));
|
|
874
979
|
const orderDetailsView = ((0, jsx_runtime_1.jsx)("div", { className: "mx-auto w-[460px] max-w-full p-5", children: (0, jsx_runtime_1.jsx)("div", { className: "relative flex flex-col gap-4", children: oat && ((0, jsx_runtime_1.jsx)(OrderDetails_1.OrderDetails, { mode: mode, order: oat.data.order, depositTxs: oat.data.depositTxs, relayTxs: oat.data.relayTxs, executeTx: oat.data.executeTx, refundTxs: oat.data.refundTxs, selectedCryptoPaymentMethod: effectiveCryptoPaymentMethod, onPaymentMethodChange: method => {
|
|
875
980
|
// When user explicitly changes payment method, set it as selected
|
|
@@ -1004,6 +1109,16 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
1004
1109
|
setDirectTransferTxHash(undefined);
|
|
1005
1110
|
setB3ModalOpen(false);
|
|
1006
1111
|
}, className: "bg-as-brand hover:bg-as-brand/90 w-full text-white", children: resolvedReturnLabel || "Done" })) })] }));
|
|
1112
|
+
const kycView = ((0, jsx_runtime_1.jsx)("div", { className: "mx-auto flex w-full max-w-[460px] flex-col gap-4 px-5 pt-5", children: (0, jsx_runtime_1.jsx)(KycGate_1.KycGate, { enabled: activePanel === PanelView.FIAT_KYC, onStatusResolved: approved => {
|
|
1113
|
+
if (approved) {
|
|
1114
|
+
kycApprovedRef.current = true;
|
|
1115
|
+
navigateBack();
|
|
1116
|
+
handleFiatOrder(selectedFiatPaymentMethod);
|
|
1117
|
+
}
|
|
1118
|
+
} }) }));
|
|
1119
|
+
const authView = ((0, jsx_runtime_1.jsx)("div", { className: "mx-auto w-full max-w-[460px]", children: (0, jsx_runtime_1.jsx)(LoginStep_1.LoginStep, { chain: baseChain, onSuccess: async () => {
|
|
1120
|
+
// isAuthenticated will be true at this point — the useEffect below handles navigation
|
|
1121
|
+
} }) }));
|
|
1007
1122
|
// Add tabs to the main component when no order is loaded
|
|
1008
1123
|
return ((0, jsx_runtime_1.jsx)(react_2.StyleRoot, { children: (0, jsx_runtime_1.jsx)("div", { className: classes?.container ||
|
|
1009
1124
|
(0, cn_1.cn)("anyspend-container font-inter mx-auto w-full max-w-[460px]", mode === "page" &&
|
|
@@ -1037,5 +1152,7 @@ function AnySpendInner({ sourceChainId, destinationTokenAddress, destinationToke
|
|
|
1037
1152
|
(0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: pointsDetailView }, "points-detail-view"),
|
|
1038
1153
|
(0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: feeDetailView }, "fee-detail-view"),
|
|
1039
1154
|
(0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: directTransferSuccessView }, "direct-transfer-success-view"),
|
|
1155
|
+
(0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: kycView }, "fiat-kyc-view"),
|
|
1156
|
+
(0, jsx_runtime_1.jsx)("div", { className: (0, cn_1.cn)(mode === "page" && "p-6"), children: authView }, "fiat-auth-view"),
|
|
1040
1157
|
] }) }) }));
|
|
1041
1158
|
}
|
|
@@ -119,5 +119,7 @@ export interface AnySpendCheckoutProps {
|
|
|
119
119
|
variablePricing?: VariablePricingConfig;
|
|
120
120
|
/** When true, fees are added on top of the amount (payer pays more, receiver gets exact amount) */
|
|
121
121
|
feeOnTop?: boolean;
|
|
122
|
+
/** When true, identity verification (KYC) is required before card payment. Defaults to false. */
|
|
123
|
+
kycEnabled?: boolean;
|
|
122
124
|
}
|
|
123
|
-
export declare function AnySpendCheckout({ mode, recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText, checkoutSessionId, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, showPoints, showOrderId, shipping: shippingProp, tax, discount: discountProp, summaryLines, formSchema, formComponent, onFormSubmit, shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp, enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount, variablePricing, feeOnTop, }: AnySpendCheckoutProps): import("react/jsx-runtime").JSX.Element;
|
|
125
|
+
export declare function AnySpendCheckout({ mode, recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText, checkoutSessionId, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, showPoints, showOrderId, shipping: shippingProp, tax, discount: discountProp, summaryLines, formSchema, formComponent, onFormSubmit, shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp, enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount, variablePricing, feeOnTop, kycEnabled, }: AnySpendCheckoutProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -24,7 +24,7 @@ shippingOptions, collectShippingAddress, onShippingChange: onShippingChangeProp,
|
|
|
24
24
|
// New discount props
|
|
25
25
|
enableDiscountCode, onDiscountApplied: onDiscountAppliedProp, validateDiscount,
|
|
26
26
|
// Variable pricing
|
|
27
|
-
variablePricing, feeOnTop, }) {
|
|
27
|
+
variablePricing, feeOnTop, kycEnabled = false, }) {
|
|
28
28
|
// ===== Variable pricing state =====
|
|
29
29
|
const [variablePricingAmount, setVariablePricingAmount] = (0, react_2.useState)("0");
|
|
30
30
|
const isVariablePricingActive = variablePricing?.enabled === true;
|
|
@@ -201,5 +201,5 @@ variablePricing, feeOnTop, }) {
|
|
|
201
201
|
(shippingOptions && shippingOptions.length > 0) ||
|
|
202
202
|
collectShippingAddress ||
|
|
203
203
|
enableDiscountCode;
|
|
204
|
-
return ((0, jsx_runtime_1.jsx)(AnySpendFingerprintWrapper_1.AnySpendFingerprintWrapper, { fingerprint: fingerprint, children: (0, jsx_runtime_1.jsx)(AnySpendCustomizationContext_1.AnySpendCustomizationProvider, { slots: slots, content: content, theme: theme, children: (0, jsx_runtime_1.jsx)(CheckoutLayout_1.CheckoutLayout, { mode: mode, paymentPanel: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isVariablePricingActive && tokenData && variablePricing && ((0, jsx_runtime_1.jsx)(VariablePricingInput_1.VariablePricingInput, { config: variablePricing, tokenDecimals: tokenDecimals, tokenSymbol: tokenSymbol, themeColor: themeColor, onChange: setVariablePricingAmount })), hasFormContent && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-6", children: [(0, jsx_runtime_1.jsx)(CheckoutFormPanel_1.CheckoutFormPanel, { formSchema: formSchema, formComponent: formComponent, shippingOptions: shippingOptions, collectShippingAddress: collectShippingAddress, enableDiscountCode: enableDiscountCode, validateDiscount: validateDiscount, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, classes: classes, formData: formData, onFormDataChange: handleFormDataChange, selectedShipping: selectedShipping, onShippingChange: handleShippingChange, appliedDiscount: appliedDiscount, onDiscountApplied: handleDiscountApplied, onDiscountRemoved: handleDiscountRemoved, shippingAddress: shippingAddress, onShippingAddressChange: setShippingAddress, checkoutFormSlot: slots?.checkoutForm }), (0, jsx_runtime_1.jsx)("div", { className: "mt-6 border-t border-gray-200 dark:border-neutral-700" })] })), (0, jsx_runtime_1.jsx)(CheckoutPaymentPanel_1.CheckoutPaymentPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: computedTotal, buttonText: buttonText, themeColor: themeColor, returnUrl: returnUrl, returnLabel: returnLabel, onSuccess: onSuccess, onError: onError, classes: classes, defaultPaymentMethod: defaultPaymentMethod, senderAddress: senderAddress, showPoints: showPoints, showOrderId: showOrderId, callbackMetadata: checkoutFormMetadata, isFormValid: isFormValid, feeOnTop: feeOnTop })] }), cartPanel: (0, jsx_runtime_1.jsx)(CheckoutCartPanel_1.CheckoutCartPanel, { items: items, totalAmount: computedTotal, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, organizationName: organizationName, organizationLogo: organizationLogo, classes: classes, footer: footer, shipping: effectiveShipping, tax: typeof tax === "string" ? { amount: tax } : tax, discount: effectiveDiscount, summaryLines: summaryLines, usdEquivalent: usdEquivalent }), classes: classes }) }) }));
|
|
204
|
+
return ((0, jsx_runtime_1.jsx)(AnySpendFingerprintWrapper_1.AnySpendFingerprintWrapper, { fingerprint: fingerprint, children: (0, jsx_runtime_1.jsx)(AnySpendCustomizationContext_1.AnySpendCustomizationProvider, { slots: slots, content: content, theme: theme, children: (0, jsx_runtime_1.jsx)(CheckoutLayout_1.CheckoutLayout, { mode: mode, paymentPanel: (0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [isVariablePricingActive && tokenData && variablePricing && ((0, jsx_runtime_1.jsx)(VariablePricingInput_1.VariablePricingInput, { config: variablePricing, tokenDecimals: tokenDecimals, tokenSymbol: tokenSymbol, themeColor: themeColor, onChange: setVariablePricingAmount })), hasFormContent && ((0, jsx_runtime_1.jsxs)("div", { className: "mb-6", children: [(0, jsx_runtime_1.jsx)(CheckoutFormPanel_1.CheckoutFormPanel, { formSchema: formSchema, formComponent: formComponent, shippingOptions: shippingOptions, collectShippingAddress: collectShippingAddress, enableDiscountCode: enableDiscountCode, validateDiscount: validateDiscount, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, classes: classes, formData: formData, onFormDataChange: handleFormDataChange, selectedShipping: selectedShipping, onShippingChange: handleShippingChange, appliedDiscount: appliedDiscount, onDiscountApplied: handleDiscountApplied, onDiscountRemoved: handleDiscountRemoved, shippingAddress: shippingAddress, onShippingAddressChange: setShippingAddress, checkoutFormSlot: slots?.checkoutForm }), (0, jsx_runtime_1.jsx)("div", { className: "mt-6 border-t border-gray-200 dark:border-neutral-700" })] })), (0, jsx_runtime_1.jsx)(CheckoutPaymentPanel_1.CheckoutPaymentPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: computedTotal, buttonText: buttonText, themeColor: themeColor, returnUrl: returnUrl, returnLabel: returnLabel, onSuccess: onSuccess, onError: onError, classes: classes, defaultPaymentMethod: defaultPaymentMethod, senderAddress: senderAddress, showPoints: showPoints, showOrderId: showOrderId, callbackMetadata: checkoutFormMetadata, isFormValid: isFormValid, feeOnTop: feeOnTop, kycEnabled: kycEnabled })] }), cartPanel: (0, jsx_runtime_1.jsx)(CheckoutCartPanel_1.CheckoutCartPanel, { items: items, totalAmount: computedTotal, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, organizationName: organizationName, organizationLogo: organizationLogo, classes: classes, footer: footer, shipping: effectiveShipping, tax: typeof tax === "string" ? { amount: tax } : tax, discount: effectiveDiscount, summaryLines: summaryLines, usdEquivalent: usdEquivalent }), classes: classes }) }) }));
|
|
205
205
|
}
|
|
@@ -77,5 +77,7 @@ export interface AnySpendCheckoutTriggerProps {
|
|
|
77
77
|
};
|
|
78
78
|
/** Additional summary line items (fees, tips, etc.) */
|
|
79
79
|
summaryLines?: CheckoutSummaryLine[];
|
|
80
|
+
/** When true, identity verification (KYC) is required before card payment. Defaults to false. */
|
|
81
|
+
kycEnabled?: boolean;
|
|
80
82
|
}
|
|
81
|
-
export declare function AnySpendCheckoutTrigger({ recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText, workflowId, orgId, callbackMetadata, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, shipping, tax, discount, summaryLines, }: AnySpendCheckoutTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
83
|
+
export declare function AnySpendCheckoutTrigger({ recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText, workflowId, orgId, callbackMetadata, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, shipping, tax, discount, summaryLines, kycEnabled, }: AnySpendCheckoutTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -12,7 +12,7 @@ const AnySpendCustomizationContext_1 = require("../context/AnySpendCustomization
|
|
|
12
12
|
const CheckoutCartPanel_1 = require("./CheckoutCartPanel");
|
|
13
13
|
const CheckoutPaymentPanel_1 = require("./CheckoutPaymentPanel");
|
|
14
14
|
const PoweredByBranding_1 = require("./PoweredByBranding");
|
|
15
|
-
function AnySpendCheckoutTrigger({ recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText = "Pay", workflowId, orgId, callbackMetadata, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, shipping, tax, discount, summaryLines, }) {
|
|
15
|
+
function AnySpendCheckoutTrigger({ recipientAddress, destinationTokenAddress, destinationTokenChainId, items, totalAmount: totalAmountOverride, organizationName, organizationLogo, themeColor, buttonText = "Pay", workflowId, orgId, callbackMetadata, onSuccess, onError, returnUrl, returnLabel, classes, footer, defaultPaymentMethod, senderAddress, slots, content, theme, shipping, tax, discount, summaryLines, kycEnabled = false, }) {
|
|
16
16
|
// Merge workflowId + orgId into callbackMetadata
|
|
17
17
|
const mergedMetadata = (0, react_2.useMemo)(() => {
|
|
18
18
|
if (!workflowId && !orgId && !callbackMetadata)
|
|
@@ -57,5 +57,5 @@ function AnySpendCheckoutTrigger({ recipientAddress, destinationTokenAddress, de
|
|
|
57
57
|
const formattedTotal = (0, react_2.useMemo)(() => (0, number_1.formatTokenAmount)(BigInt(computedTotal || "0"), tokenDecimals), [computedTotal, tokenDecimals]);
|
|
58
58
|
const hasItems = items && items.length > 0;
|
|
59
59
|
const fingerprint = (0, AnySpendFingerprintWrapper_1.getFingerprintConfig)();
|
|
60
|
-
return ((0, jsx_runtime_1.jsx)(AnySpendFingerprintWrapper_1.AnySpendFingerprintWrapper, { fingerprint: fingerprint, children: (0, jsx_runtime_1.jsx)(AnySpendCustomizationContext_1.AnySpendCustomizationProvider, { slots: slots, content: content, theme: theme, children: (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-checkout-trigger flex flex-col", children: [hasItems && ((0, jsx_runtime_1.jsx)("div", { className: "border-b border-gray-200 p-5 dark:border-neutral-700", children: (0, jsx_runtime_1.jsx)(CheckoutCartPanel_1.CheckoutCartPanel, { items: items, totalAmount: computedTotal, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, organizationName: organizationName, organizationLogo: organizationLogo, classes: classes, footer: footer, shipping: typeof shipping === "string" ? { amount: shipping } : shipping, tax: typeof tax === "string" ? { amount: tax } : tax, discount: typeof discount === "string" ? { amount: discount } : discount, summaryLines: summaryLines }) })), !hasItems && ((0, jsx_runtime_1.jsx)("div", { className: "border-b border-gray-200 p-5 dark:border-neutral-700", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("flex items-center justify-between", classes?.cartSummary), children: [(0, jsx_runtime_1.jsx)("span", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: "Total" }), (0, jsx_runtime_1.jsxs)("span", { className: (0, cn_1.cn)("text-base font-semibold text-gray-900 dark:text-gray-100", classes?.cartTotal), children: [formattedTotal, " ", tokenSymbol] })] }), footer === undefined ? ((0, jsx_runtime_1.jsx)(PoweredByBranding_1.PoweredByBranding, { organizationName: organizationName, organizationLogo: organizationLogo, classes: classes })) : (footer)] }) })), (0, jsx_runtime_1.jsx)("div", { className: "px-2 py-3", children: (0, jsx_runtime_1.jsx)(CheckoutPaymentPanel_1.CheckoutPaymentPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: computedTotal, buttonText: buttonText, themeColor: themeColor, returnUrl: returnUrl, returnLabel: returnLabel, onSuccess: onSuccess, onError: onError, callbackMetadata: mergedMetadata, classes: classes, defaultPaymentMethod: defaultPaymentMethod, senderAddress: senderAddress }) })] }) }) }));
|
|
60
|
+
return ((0, jsx_runtime_1.jsx)(AnySpendFingerprintWrapper_1.AnySpendFingerprintWrapper, { fingerprint: fingerprint, children: (0, jsx_runtime_1.jsx)(AnySpendCustomizationContext_1.AnySpendCustomizationProvider, { slots: slots, content: content, theme: theme, children: (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-checkout-trigger flex flex-col", children: [hasItems && ((0, jsx_runtime_1.jsx)("div", { className: "border-b border-gray-200 p-5 dark:border-neutral-700", children: (0, jsx_runtime_1.jsx)(CheckoutCartPanel_1.CheckoutCartPanel, { items: items, totalAmount: computedTotal, tokenSymbol: tokenSymbol, tokenDecimals: tokenDecimals, organizationName: organizationName, organizationLogo: organizationLogo, classes: classes, footer: footer, shipping: typeof shipping === "string" ? { amount: shipping } : shipping, tax: typeof tax === "string" ? { amount: tax } : tax, discount: typeof discount === "string" ? { amount: discount } : discount, summaryLines: summaryLines }) })), !hasItems && ((0, jsx_runtime_1.jsx)("div", { className: "border-b border-gray-200 p-5 dark:border-neutral-700", children: (0, jsx_runtime_1.jsxs)("div", { className: "flex flex-col gap-3", children: [(0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("flex items-center justify-between", classes?.cartSummary), children: [(0, jsx_runtime_1.jsx)("span", { className: "text-base font-semibold text-gray-900 dark:text-gray-100", children: "Total" }), (0, jsx_runtime_1.jsxs)("span", { className: (0, cn_1.cn)("text-base font-semibold text-gray-900 dark:text-gray-100", classes?.cartTotal), children: [formattedTotal, " ", tokenSymbol] })] }), footer === undefined ? ((0, jsx_runtime_1.jsx)(PoweredByBranding_1.PoweredByBranding, { organizationName: organizationName, organizationLogo: organizationLogo, classes: classes })) : (footer)] }) })), (0, jsx_runtime_1.jsx)("div", { className: "px-2 py-3", children: (0, jsx_runtime_1.jsx)(CheckoutPaymentPanel_1.CheckoutPaymentPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: computedTotal, buttonText: buttonText, themeColor: themeColor, returnUrl: returnUrl, returnLabel: returnLabel, onSuccess: onSuccess, onError: onError, callbackMetadata: mergedMetadata, classes: classes, defaultPaymentMethod: defaultPaymentMethod, senderAddress: senderAddress, kycEnabled: kycEnabled }) })] }) }) }));
|
|
61
61
|
}
|
|
@@ -28,6 +28,8 @@ interface CheckoutPaymentPanelProps {
|
|
|
28
28
|
isFormValid?: boolean;
|
|
29
29
|
/** When true, fees are added on top (payer pays more, receiver gets exact amount) */
|
|
30
30
|
feeOnTop?: boolean;
|
|
31
|
+
/** When true, identity verification (KYC) is required before card payment. Defaults to false. */
|
|
32
|
+
kycEnabled?: boolean;
|
|
31
33
|
}
|
|
32
|
-
export declare function CheckoutPaymentPanel({ recipientAddress, destinationTokenAddress, destinationTokenChainId, totalAmount, buttonText, themeColor, returnUrl, returnLabel, onSuccess, onError, callbackMetadata, classes, defaultPaymentMethod, senderAddress, showPoints, showOrderId, isFormValid, feeOnTop, }: CheckoutPaymentPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
34
|
+
export declare function CheckoutPaymentPanel({ recipientAddress, destinationTokenAddress, destinationTokenChainId, totalAmount, buttonText, themeColor, returnUrl, returnLabel, onSuccess, onError, callbackMetadata, classes, defaultPaymentMethod, senderAddress, showPoints, showOrderId, isFormValid, feeOnTop, kycEnabled, }: CheckoutPaymentPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
33
35
|
export {};
|
|
@@ -29,7 +29,7 @@ function AmexLogo() {
|
|
|
29
29
|
function CoinbaseLogo() {
|
|
30
30
|
return ((0, jsx_runtime_1.jsxs)("svg", { viewBox: "0 0 24 24", style: { width: 20, height: 20 }, "aria-label": "Coinbase", children: [(0, jsx_runtime_1.jsx)("circle", { cx: "12", cy: "12", r: "12", fill: "#0052FF" }), (0, jsx_runtime_1.jsx)("path", { d: "M12 4.5a7.5 7.5 0 1 0 0 15 7.5 7.5 0 0 0 0-15zm-1.8 4.8h3.6c.33 0 .6.27.6.6v4.2c0 .33-.27.6-.6.6h-3.6a.6.6 0 0 1-.6-.6V9.9c0-.33.27-.6.6-.6z", fill: "white" })] }));
|
|
31
31
|
}
|
|
32
|
-
function CheckoutPaymentPanel({ recipientAddress, destinationTokenAddress, destinationTokenChainId, totalAmount, buttonText, themeColor, returnUrl, returnLabel, onSuccess, onError, callbackMetadata, classes, defaultPaymentMethod, senderAddress, showPoints, showOrderId, isFormValid = true, feeOnTop, }) {
|
|
32
|
+
function CheckoutPaymentPanel({ recipientAddress, destinationTokenAddress, destinationTokenChainId, totalAmount, buttonText, themeColor, returnUrl, returnLabel, onSuccess, onError, callbackMetadata, classes, defaultPaymentMethod, senderAddress, showPoints, showOrderId, isFormValid = true, feeOnTop, kycEnabled = false, }) {
|
|
33
33
|
const [paymentMethod, setPaymentMethod] = (0, react_2.useState)(defaultPaymentMethod ?? null);
|
|
34
34
|
// Restore activeOrderId from sessionStorage (handles page refresh / Coinbase return)
|
|
35
35
|
const [activeOrderId, setActiveOrderId] = (0, react_2.useState)(() => {
|
|
@@ -60,5 +60,5 @@ function CheckoutPaymentPanel({ recipientAddress, destinationTokenAddress, desti
|
|
|
60
60
|
? "bg-white dark:bg-neutral-900"
|
|
61
61
|
: "bg-white hover:bg-gray-50 dark:bg-neutral-900 dark:hover:bg-neutral-800", classes?.paymentMethodButton);
|
|
62
62
|
const expandedPanelClass = (0, cn_1.cn)("anyspend-payment-method-panel border-t border-gray-100 bg-white px-4 py-4 dark:border-neutral-800 dark:bg-neutral-900");
|
|
63
|
-
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("anyspend-payment-panel flex flex-col gap-5", classes?.paymentPanel), children: [(0, jsx_runtime_1.jsx)("h2", { className: (0, cn_1.cn)("anyspend-payment-title text-lg font-semibold text-gray-900 dark:text-gray-100", classes?.paymentTitle), children: "Payment" }), !isFormValid && ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-amber-600 dark:text-amber-400", children: "Please complete the required fields above before proceeding to payment." })), (0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("anyspend-payment-methods divide-y divide-gray-200 overflow-hidden rounded-xl border border-gray-200 dark:divide-neutral-700 dark:border-neutral-700", !isFormValid && "pointer-events-none opacity-50", classes?.paymentMethodSelector), children: [(0, jsx_runtime_1.jsxs)("div", { className: "anyspend-method-crypto", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => setPaymentMethod(paymentMethod === "crypto" ? null : "crypto"), className: accordionButtonClass(paymentMethod === "crypto"), children: [(0, jsx_runtime_1.jsx)(RadioCircle, { selected: paymentMethod === "crypto", themeColor: themeColor }), (0, jsx_runtime_1.jsx)(lucide_react_1.Wallet, { className: "h-5 w-5 text-gray-700 dark:text-gray-300" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: "Pay with crypto" })] }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { initial: false, children: paymentMethod === "crypto" && ((0, jsx_runtime_1.jsx)(react_1.motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2, ease: "easeOut" }, style: { overflow: "hidden" }, children: (0, jsx_runtime_1.jsx)("div", { className: expandedPanelClass, children: (0, jsx_runtime_1.jsx)(CryptoPayPanel_1.CryptoPayPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: totalAmount, buttonText: buttonText, themeColor: themeColor, onOrderCreated: handleOrderCreated, onError: onError, callbackMetadata: callbackMetadata, classes: classes, senderAddress: senderAddress }) }) }, "crypto-panel")) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-method-card", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => setPaymentMethod(paymentMethod === "card" ? null : "card"), className: accordionButtonClass(paymentMethod === "card"), children: [(0, jsx_runtime_1.jsx)(RadioCircle, { selected: paymentMethod === "card", themeColor: themeColor }), (0, jsx_runtime_1.jsx)(lucide_react_1.CreditCard, { className: "h-5 w-5 text-gray-700 dark:text-gray-300" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: "Credit or debit card" }), (0, jsx_runtime_1.jsxs)("div", { className: "ml-auto flex items-center gap-1", children: [(0, jsx_runtime_1.jsx)(VisaLogo, {}), (0, jsx_runtime_1.jsx)(MastercardLogo, {}), (0, jsx_runtime_1.jsx)(AmexLogo, {})] })] }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { initial: false, children: paymentMethod === "card" && ((0, jsx_runtime_1.jsx)(react_1.motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2, ease: "easeOut" }, style: { overflow: "hidden" }, children: (0, jsx_runtime_1.jsx)("div", { className: expandedPanelClass, children: (0, jsx_runtime_1.jsx)(FiatCheckoutPanel_1.FiatCheckoutPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: totalAmount, themeColor: themeColor, onOrderCreated: handleOrderCreated, onError: onError, callbackMetadata: callbackMetadata, classes: classes, feeOnTop: feeOnTop }) }) }, "card-panel")) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-method-coinbase", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => setPaymentMethod(paymentMethod === "coinbase" ? null : "coinbase"), className: accordionButtonClass(paymentMethod === "coinbase"), children: [(0, jsx_runtime_1.jsx)(RadioCircle, { selected: paymentMethod === "coinbase", themeColor: themeColor }), (0, jsx_runtime_1.jsx)(CoinbaseLogo, {}), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: "Coinbase Pay" })] }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { initial: false, children: paymentMethod === "coinbase" && ((0, jsx_runtime_1.jsx)(react_1.motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2, ease: "easeOut" }, style: { overflow: "hidden" }, children: (0, jsx_runtime_1.jsx)("div", { className: expandedPanelClass, children: (0, jsx_runtime_1.jsx)(CoinbaseCheckoutPanel_1.CoinbaseCheckoutPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: totalAmount, themeColor: themeColor, onOrderCreated: handleOrderCreated, onError: onError, callbackMetadata: callbackMetadata, classes: classes }) }) }, "coinbase-panel")) })] })] })] }));
|
|
63
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("anyspend-payment-panel flex flex-col gap-5", classes?.paymentPanel), children: [(0, jsx_runtime_1.jsx)("h2", { className: (0, cn_1.cn)("anyspend-payment-title text-lg font-semibold text-gray-900 dark:text-gray-100", classes?.paymentTitle), children: "Payment" }), !isFormValid && ((0, jsx_runtime_1.jsx)("p", { className: "text-sm text-amber-600 dark:text-amber-400", children: "Please complete the required fields above before proceeding to payment." })), (0, jsx_runtime_1.jsxs)("div", { className: (0, cn_1.cn)("anyspend-payment-methods divide-y divide-gray-200 overflow-hidden rounded-xl border border-gray-200 dark:divide-neutral-700 dark:border-neutral-700", !isFormValid && "pointer-events-none opacity-50", classes?.paymentMethodSelector), children: [(0, jsx_runtime_1.jsxs)("div", { className: "anyspend-method-crypto", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => setPaymentMethod(paymentMethod === "crypto" ? null : "crypto"), className: accordionButtonClass(paymentMethod === "crypto"), children: [(0, jsx_runtime_1.jsx)(RadioCircle, { selected: paymentMethod === "crypto", themeColor: themeColor }), (0, jsx_runtime_1.jsx)(lucide_react_1.Wallet, { className: "h-5 w-5 text-gray-700 dark:text-gray-300" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: "Pay with crypto" })] }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { initial: false, children: paymentMethod === "crypto" && ((0, jsx_runtime_1.jsx)(react_1.motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2, ease: "easeOut" }, style: { overflow: "hidden" }, children: (0, jsx_runtime_1.jsx)("div", { className: expandedPanelClass, children: (0, jsx_runtime_1.jsx)(CryptoPayPanel_1.CryptoPayPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: totalAmount, buttonText: buttonText, themeColor: themeColor, onOrderCreated: handleOrderCreated, onError: onError, callbackMetadata: callbackMetadata, classes: classes, senderAddress: senderAddress }) }) }, "crypto-panel")) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-method-card", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => setPaymentMethod(paymentMethod === "card" ? null : "card"), className: accordionButtonClass(paymentMethod === "card"), children: [(0, jsx_runtime_1.jsx)(RadioCircle, { selected: paymentMethod === "card", themeColor: themeColor }), (0, jsx_runtime_1.jsx)(lucide_react_1.CreditCard, { className: "h-5 w-5 text-gray-700 dark:text-gray-300" }), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: "Credit or debit card" }), (0, jsx_runtime_1.jsxs)("div", { className: "ml-auto flex items-center gap-1", children: [(0, jsx_runtime_1.jsx)(VisaLogo, {}), (0, jsx_runtime_1.jsx)(MastercardLogo, {}), (0, jsx_runtime_1.jsx)(AmexLogo, {})] })] }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { initial: false, children: paymentMethod === "card" && ((0, jsx_runtime_1.jsx)(react_1.motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2, ease: "easeOut" }, style: { overflow: "hidden" }, children: (0, jsx_runtime_1.jsx)("div", { className: expandedPanelClass, children: (0, jsx_runtime_1.jsx)(FiatCheckoutPanel_1.FiatCheckoutPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: totalAmount, themeColor: themeColor, onOrderCreated: handleOrderCreated, onError: onError, callbackMetadata: callbackMetadata, classes: classes, feeOnTop: feeOnTop, kycEnabled: kycEnabled }) }) }, "card-panel")) })] }), (0, jsx_runtime_1.jsxs)("div", { className: "anyspend-method-coinbase", children: [(0, jsx_runtime_1.jsxs)("button", { onClick: () => setPaymentMethod(paymentMethod === "coinbase" ? null : "coinbase"), className: accordionButtonClass(paymentMethod === "coinbase"), children: [(0, jsx_runtime_1.jsx)(RadioCircle, { selected: paymentMethod === "coinbase", themeColor: themeColor }), (0, jsx_runtime_1.jsx)(CoinbaseLogo, {}), (0, jsx_runtime_1.jsx)("span", { className: "text-sm font-medium text-gray-900 dark:text-gray-100", children: "Coinbase Pay" })] }), (0, jsx_runtime_1.jsx)(react_1.AnimatePresence, { initial: false, children: paymentMethod === "coinbase" && ((0, jsx_runtime_1.jsx)(react_1.motion.div, { initial: { height: 0, opacity: 0 }, animate: { height: "auto", opacity: 1 }, exit: { height: 0, opacity: 0 }, transition: { duration: 0.2, ease: "easeOut" }, style: { overflow: "hidden" }, children: (0, jsx_runtime_1.jsx)("div", { className: expandedPanelClass, children: (0, jsx_runtime_1.jsx)(CoinbaseCheckoutPanel_1.CoinbaseCheckoutPanel, { recipientAddress: recipientAddress, destinationTokenAddress: destinationTokenAddress, destinationTokenChainId: destinationTokenChainId, totalAmount: totalAmount, themeColor: themeColor, onOrderCreated: handleOrderCreated, onError: onError, callbackMetadata: callbackMetadata, classes: classes }) }) }, "coinbase-panel")) })] })] })] }));
|
|
64
64
|
}
|
|
@@ -17,6 +17,8 @@ interface FiatCheckoutPanelProps {
|
|
|
17
17
|
classes?: AnySpendCheckoutClasses;
|
|
18
18
|
/** When true, fees are added on top (payer pays more, receiver gets exact amount) */
|
|
19
19
|
feeOnTop?: boolean;
|
|
20
|
+
/** When true, identity verification is required before card payment. Defaults to false. */
|
|
21
|
+
kycEnabled?: boolean;
|
|
20
22
|
}
|
|
21
|
-
export declare function FiatCheckoutPanel({ recipientAddress, destinationTokenAddress, destinationTokenChainId, totalAmount, themeColor, onSuccess, onOrderCreated, onError, callbackMetadata, classes, feeOnTop, }: FiatCheckoutPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
export declare function FiatCheckoutPanel({ recipientAddress, destinationTokenAddress, destinationTokenChainId, totalAmount, themeColor, onSuccess, onOrderCreated, onError, callbackMetadata, classes, feeOnTop, kycEnabled, }: FiatCheckoutPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
22
24
|
export {};
|
|
@@ -13,7 +13,8 @@ const react_stripe_js_1 = require("@stripe/react-stripe-js");
|
|
|
13
13
|
const lucide_react_1 = require("lucide-react");
|
|
14
14
|
const react_3 = require("motion/react");
|
|
15
15
|
const react_4 = require("react");
|
|
16
|
-
|
|
16
|
+
const KycGate_1 = require("./KycGate");
|
|
17
|
+
function FiatCheckoutPanel({ recipientAddress, destinationTokenAddress, destinationTokenChainId, totalAmount, themeColor, onSuccess, onOrderCreated, onError, callbackMetadata, classes, feeOnTop, kycEnabled = false, }) {
|
|
17
18
|
// Stable refs for callback props to avoid re-triggering effects
|
|
18
19
|
const onErrorRef = (0, react_4.useRef)(onError);
|
|
19
20
|
onErrorRef.current = onError;
|
|
@@ -51,18 +52,12 @@ function FiatCheckoutPanel({ recipientAddress, destinationTokenAddress, destinat
|
|
|
51
52
|
const raw = (0, number_1.formatUnits)(anyspendQuote.data.currencyIn.amount, constants_1.USDC_BASE.decimals);
|
|
52
53
|
return parseFloat(raw).toFixed(2);
|
|
53
54
|
}, [isStablecoin, formattedAmount, anyspendQuote]);
|
|
54
|
-
// Debug: log computed values for Stripe flow diagnostics
|
|
55
|
-
(0, react_4.useEffect)(() => {
|
|
56
|
-
console.log("@@fiat-checkout:debug", {
|
|
57
|
-
totalAmount,
|
|
58
|
-
formattedAmount,
|
|
59
|
-
isStablecoin,
|
|
60
|
-
isLoadingAnyspendQuote,
|
|
61
|
-
quoteAmount: anyspendQuote?.data?.currencyIn?.amount,
|
|
62
|
-
usdAmount,
|
|
63
|
-
});
|
|
64
|
-
}, [totalAmount, formattedAmount, isStablecoin, isLoadingAnyspendQuote, anyspendQuote, usdAmount]);
|
|
65
55
|
const { geoData, stripeOnrampSupport, stripeWeb2Support, isLoading: isLoadingGeo, } = (0, react_1.useGeoOnrampOptions)(usdAmount || "0");
|
|
56
|
+
// KYC state — pre-approved when kycEnabled is false (feature flag off)
|
|
57
|
+
const [kycApproved, setKycApproved] = (0, react_4.useState)(() => !kycEnabled);
|
|
58
|
+
const handleKycResolved = (0, react_4.useCallback)((approved) => {
|
|
59
|
+
setKycApproved(approved);
|
|
60
|
+
}, []);
|
|
66
61
|
// Order state
|
|
67
62
|
const [orderId, setOrderId] = (0, react_4.useState)(null);
|
|
68
63
|
const [stripePaymentIntentId, setStripePaymentIntentId] = (0, react_4.useState)(null);
|
|
@@ -85,13 +80,14 @@ function FiatCheckoutPanel({ recipientAddress, destinationTokenAddress, destinat
|
|
|
85
80
|
onErrorRef.current?.(error);
|
|
86
81
|
},
|
|
87
82
|
});
|
|
88
|
-
// Auto-create onramp order when Stripe Web2 is supported and all data is ready
|
|
83
|
+
// Auto-create onramp order when Stripe Web2 is supported, KYC approved, and all data is ready
|
|
89
84
|
(0, react_4.useEffect)(() => {
|
|
90
85
|
if (!isLoadingGeo &&
|
|
91
86
|
(!isStablecoin ? !isLoadingAnyspendQuote : true) &&
|
|
92
87
|
usdAmount &&
|
|
93
88
|
parseFloat(usdAmount) > 0 &&
|
|
94
89
|
stripeWeb2Support?.isSupport &&
|
|
90
|
+
kycApproved &&
|
|
95
91
|
!orderCreatedRef.current &&
|
|
96
92
|
!orderId &&
|
|
97
93
|
!isCreatingOrder &&
|
|
@@ -132,6 +128,7 @@ function FiatCheckoutPanel({ recipientAddress, destinationTokenAddress, destinat
|
|
|
132
128
|
isLoadingAnyspendQuote,
|
|
133
129
|
usdAmount,
|
|
134
130
|
stripeWeb2Support,
|
|
131
|
+
kycApproved,
|
|
135
132
|
orderId,
|
|
136
133
|
isCreatingOrder,
|
|
137
134
|
orderError,
|
|
@@ -155,6 +152,10 @@ function FiatCheckoutPanel({ recipientAddress, destinationTokenAddress, destinat
|
|
|
155
152
|
if (!hasStripeWeb2 && !hasStripeRedirect) {
|
|
156
153
|
return ((0, jsx_runtime_1.jsx)(react_3.motion.div, { initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.25, ease: "easeOut" }, className: (0, cn_1.cn)("anyspend-fiat-unavailable py-4 text-center", classes?.fiatPanel), children: (0, jsx_runtime_1.jsx)("p", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Card payments are not available in your region for this amount." }) }));
|
|
157
154
|
}
|
|
155
|
+
// KYC gate — shown before order creation when verification is needed
|
|
156
|
+
if (!kycApproved) {
|
|
157
|
+
return (0, jsx_runtime_1.jsx)(KycGate_1.KycGate, { themeColor: themeColor, classes: classes, enabled: true, onStatusResolved: handleKycResolved });
|
|
158
|
+
}
|
|
158
159
|
// Order creation error - show with retry
|
|
159
160
|
if (orderError) {
|
|
160
161
|
return ((0, jsx_runtime_1.jsxs)(react_3.motion.div, { initial: { opacity: 0, y: 8 }, animate: { opacity: 1, y: 0 }, transition: { duration: 0.25, ease: "easeOut" }, className: (0, cn_1.cn)("anyspend-fiat-error flex flex-col items-center gap-3 py-4", classes?.fiatPanel), children: [(0, jsx_runtime_1.jsx)("p", { className: "text-sm text-red-500", children: orderError }), (0, jsx_runtime_1.jsx)("button", { onClick: () => {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { AnySpendCheckoutClasses } from "./AnySpendCheckout";
|
|
2
|
+
interface KycGateProps {
|
|
3
|
+
themeColor?: string;
|
|
4
|
+
classes?: AnySpendCheckoutClasses;
|
|
5
|
+
/** Only fetch KYC status (and prompt wallet signature) when true. */
|
|
6
|
+
enabled?: boolean;
|
|
7
|
+
/** Called when KYC status is resolved (approved or not required) */
|
|
8
|
+
onStatusResolved: (approved: boolean) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare function KycGate({ themeColor, classes, enabled, onStatusResolved }: KycGateProps): import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
export {};
|