@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.
Files changed (80) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +3 -1
  2. package/dist/cjs/anyspend/react/components/AnySpend.js +128 -11
  3. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.d.ts +3 -1
  4. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.js +2 -2
  5. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
  6. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckoutTrigger.js +2 -2
  7. package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
  8. package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -2
  9. package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
  10. package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.js +14 -13
  11. package/dist/cjs/anyspend/react/components/checkout/KycGate.d.ts +11 -0
  12. package/dist/cjs/anyspend/react/components/checkout/KycGate.js +181 -0
  13. package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
  14. package/dist/cjs/anyspend/react/hooks/index.js +1 -0
  15. package/dist/cjs/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +9 -0
  16. package/dist/cjs/anyspend/react/hooks/useKycStatus.d.ts +42 -0
  17. package/dist/cjs/anyspend/react/hooks/useKycStatus.js +113 -0
  18. package/dist/cjs/anyspend/services/anyspend.d.ts +3 -1
  19. package/dist/cjs/anyspend/services/anyspend.js +2 -1
  20. package/dist/cjs/global-account/react/components/B3DynamicModal.js +1 -1
  21. package/dist/cjs/global-account/react/components/ManageAccount/BottomNavigation.js +3 -3
  22. package/dist/cjs/global-account/react/hooks/useAuth.js +1 -1
  23. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +4 -0
  24. package/dist/cjs/global-account/react/stores/useModalStore.js +2 -0
  25. package/dist/cjs/global-account/react/utils/createWagmiConfig.d.ts +18 -0
  26. package/dist/cjs/global-account/react/utils/createWagmiConfig.js +17 -0
  27. package/dist/esm/anyspend/react/components/AnySpend.d.ts +3 -1
  28. package/dist/esm/anyspend/react/components/AnySpend.js +129 -12
  29. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.d.ts +3 -1
  30. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.js +2 -2
  31. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
  32. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckoutTrigger.js +2 -2
  33. package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
  34. package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -2
  35. package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
  36. package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.js +14 -13
  37. package/dist/esm/anyspend/react/components/checkout/KycGate.d.ts +11 -0
  38. package/dist/esm/anyspend/react/components/checkout/KycGate.js +145 -0
  39. package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
  40. package/dist/esm/anyspend/react/hooks/index.js +1 -0
  41. package/dist/esm/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +9 -0
  42. package/dist/esm/anyspend/react/hooks/useKycStatus.d.ts +42 -0
  43. package/dist/esm/anyspend/react/hooks/useKycStatus.js +107 -0
  44. package/dist/esm/anyspend/services/anyspend.d.ts +3 -1
  45. package/dist/esm/anyspend/services/anyspend.js +2 -1
  46. package/dist/esm/global-account/react/components/B3DynamicModal.js +1 -1
  47. package/dist/esm/global-account/react/components/ManageAccount/BottomNavigation.js +3 -3
  48. package/dist/esm/global-account/react/hooks/useAuth.js +2 -2
  49. package/dist/esm/global-account/react/stores/useModalStore.d.ts +4 -0
  50. package/dist/esm/global-account/react/stores/useModalStore.js +2 -0
  51. package/dist/esm/global-account/react/utils/createWagmiConfig.d.ts +18 -0
  52. package/dist/esm/global-account/react/utils/createWagmiConfig.js +16 -0
  53. package/dist/styles/index.css +1 -1
  54. package/dist/types/anyspend/react/components/AnySpend.d.ts +3 -1
  55. package/dist/types/anyspend/react/components/checkout/AnySpendCheckout.d.ts +3 -1
  56. package/dist/types/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
  57. package/dist/types/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
  58. package/dist/types/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
  59. package/dist/types/anyspend/react/components/checkout/KycGate.d.ts +11 -0
  60. package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
  61. package/dist/types/anyspend/react/hooks/useKycStatus.d.ts +42 -0
  62. package/dist/types/anyspend/services/anyspend.d.ts +3 -1
  63. package/dist/types/global-account/react/stores/useModalStore.d.ts +4 -0
  64. package/dist/types/global-account/react/utils/createWagmiConfig.d.ts +18 -0
  65. package/package.json +2 -1
  66. package/src/anyspend/react/components/AnySpend.tsx +150 -13
  67. package/src/anyspend/react/components/checkout/AnySpendCheckout.tsx +4 -0
  68. package/src/anyspend/react/components/checkout/AnySpendCheckoutTrigger.tsx +4 -0
  69. package/src/anyspend/react/components/checkout/CheckoutPaymentPanel.tsx +4 -0
  70. package/src/anyspend/react/components/checkout/FiatCheckoutPanel.tsx +19 -13
  71. package/src/anyspend/react/components/checkout/KycGate.tsx +351 -0
  72. package/src/anyspend/react/hooks/index.ts +1 -0
  73. package/src/anyspend/react/hooks/useAnyspendCreateOnrampOrder.ts +10 -0
  74. package/src/anyspend/react/hooks/useKycStatus.ts +140 -0
  75. package/src/anyspend/services/anyspend.ts +4 -0
  76. package/src/global-account/react/components/B3DynamicModal.tsx +0 -2
  77. package/src/global-account/react/components/ManageAccount/BottomNavigation.tsx +7 -7
  78. package/src/global-account/react/hooks/useAuth.ts +2 -2
  79. package/src/global-account/react/stores/useModalStore.ts +6 -0
  80. 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)(defaultActiveTab);
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)(FiatPaymentMethod_1.FiatPaymentMethod.NONE);
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)(searchParams.get("fromAmount") || "5");
124
- // State for destination chain/token selection
125
- const [selectedDstChainId, setSelectedDstChainId] = (0, react_4.useState)(initialDstChainId);
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)(isBuyMode ? defaultDstToken : dstTokenFromUrl);
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 "Buy"
581
- return { text: "Buy", disable: false, error: false, loading: false };
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: "Buy", disable: false, error: false, loading: false };
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
- function FiatCheckoutPanel({ recipientAddress, destinationTokenAddress, destinationTokenChainId, totalAmount, themeColor, onSuccess, onOrderCreated, onError, callbackMetadata, classes, feeOnTop, }) {
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 {};