@b3dotfun/sdk 0.1.68-alpha.1 → 0.1.68-alpha.10

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 (229) hide show
  1. package/dist/cjs/anyspend/platform/client.d.ts +35 -0
  2. package/dist/cjs/anyspend/platform/client.js +158 -0
  3. package/dist/cjs/anyspend/platform/errors.d.ts +38 -0
  4. package/dist/cjs/anyspend/platform/errors.js +77 -0
  5. package/dist/cjs/anyspend/platform/index.d.ts +87 -0
  6. package/dist/cjs/anyspend/platform/index.js +85 -0
  7. package/dist/cjs/anyspend/platform/resources/analytics.d.ts +7 -0
  8. package/dist/cjs/anyspend/platform/resources/analytics.js +12 -0
  9. package/dist/cjs/anyspend/platform/resources/checkout-sessions.d.ts +17 -0
  10. package/dist/cjs/anyspend/platform/resources/checkout-sessions.js +27 -0
  11. package/dist/cjs/anyspend/platform/resources/customers.d.ts +19 -0
  12. package/dist/cjs/anyspend/platform/resources/customers.js +34 -0
  13. package/dist/cjs/anyspend/platform/resources/discount-codes.d.ts +29 -0
  14. package/dist/cjs/anyspend/platform/resources/discount-codes.js +31 -0
  15. package/dist/cjs/anyspend/platform/resources/events.d.ts +14 -0
  16. package/dist/cjs/anyspend/platform/resources/events.js +16 -0
  17. package/dist/cjs/anyspend/platform/resources/notifications.d.ts +18 -0
  18. package/dist/cjs/anyspend/platform/resources/notifications.js +27 -0
  19. package/dist/cjs/anyspend/platform/resources/organization.d.ts +17 -0
  20. package/dist/cjs/anyspend/platform/resources/organization.js +15 -0
  21. package/dist/cjs/anyspend/platform/resources/payment-links.d.ts +21 -0
  22. package/dist/cjs/anyspend/platform/resources/payment-links.js +49 -0
  23. package/dist/cjs/anyspend/platform/resources/products.d.ts +27 -0
  24. package/dist/cjs/anyspend/platform/resources/products.js +31 -0
  25. package/dist/cjs/anyspend/platform/resources/transactions.d.ts +11 -0
  26. package/dist/cjs/anyspend/platform/resources/transactions.js +25 -0
  27. package/dist/cjs/anyspend/platform/resources/webhooks.d.ts +14 -0
  28. package/dist/cjs/anyspend/platform/resources/webhooks.js +33 -0
  29. package/dist/cjs/anyspend/platform/resources/widgets.d.ts +38 -0
  30. package/dist/cjs/anyspend/platform/resources/widgets.js +31 -0
  31. package/dist/cjs/anyspend/platform/types.d.ts +478 -0
  32. package/dist/cjs/anyspend/platform/types.js +5 -0
  33. package/dist/cjs/anyspend/platform/utils/idempotency.d.ts +4 -0
  34. package/dist/cjs/anyspend/platform/utils/idempotency.js +17 -0
  35. package/dist/cjs/anyspend/platform/utils/pagination.d.ts +12 -0
  36. package/dist/cjs/anyspend/platform/utils/pagination.js +22 -0
  37. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +5 -1
  38. package/dist/cjs/anyspend/react/components/AnySpend.js +123 -12
  39. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.d.ts +12 -6
  40. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.js +55 -8
  41. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
  42. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckoutTrigger.js +2 -2
  43. package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
  44. package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -2
  45. package/dist/cjs/anyspend/react/components/checkout/CryptoPayPanel.js +1 -1
  46. package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
  47. package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.js +46 -16
  48. package/dist/cjs/anyspend/react/components/checkout/KycGate.d.ts +11 -0
  49. package/dist/cjs/anyspend/react/components/checkout/KycGate.js +203 -0
  50. package/dist/cjs/anyspend/react/components/checkout/VariablePricingInput.d.ts +17 -0
  51. package/dist/cjs/anyspend/react/components/checkout/VariablePricingInput.js +145 -0
  52. package/dist/cjs/anyspend/react/components/index.d.ts +1 -1
  53. package/dist/cjs/anyspend/react/hooks/index.d.ts +1 -0
  54. package/dist/cjs/anyspend/react/hooks/index.js +1 -0
  55. package/dist/cjs/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +13 -0
  56. package/dist/cjs/anyspend/react/hooks/useKycStatus.d.ts +47 -0
  57. package/dist/cjs/anyspend/react/hooks/useKycStatus.js +124 -0
  58. package/dist/cjs/anyspend/services/anyspend.d.ts +3 -1
  59. package/dist/cjs/anyspend/services/anyspend.js +2 -1
  60. package/dist/cjs/global-account/react/components/B3DynamicModal.js +1 -1
  61. package/dist/cjs/global-account/react/components/ManageAccount/BottomNavigation.js +3 -3
  62. package/dist/cjs/global-account/react/components/SignInWithB3/SignIn.js +1 -1
  63. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +13 -5
  64. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Privy.js +1 -1
  65. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStep.d.ts +1 -1
  66. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStep.js +21 -24
  67. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepCustom.js +1 -1
  68. package/dist/cjs/global-account/react/hooks/useAuth.js +1 -1
  69. package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +3 -1
  70. package/dist/cjs/global-account/react/hooks/useAuthentication.js +82 -24
  71. package/dist/cjs/global-account/react/hooks/useGetAllTWSigners.js +2 -1
  72. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +4 -0
  73. package/dist/cjs/global-account/react/stores/useModalStore.js +2 -0
  74. package/dist/cjs/global-account/react/utils/createWagmiConfig.d.ts +18 -0
  75. package/dist/cjs/global-account/react/utils/createWagmiConfig.js +17 -0
  76. package/dist/esm/anyspend/platform/client.d.ts +35 -0
  77. package/dist/esm/anyspend/platform/client.js +153 -0
  78. package/dist/esm/anyspend/platform/errors.d.ts +38 -0
  79. package/dist/esm/anyspend/platform/errors.js +67 -0
  80. package/dist/esm/anyspend/platform/index.d.ts +87 -0
  81. package/dist/esm/anyspend/platform/index.js +75 -0
  82. package/dist/esm/anyspend/platform/resources/analytics.d.ts +7 -0
  83. package/dist/esm/anyspend/platform/resources/analytics.js +8 -0
  84. package/dist/esm/anyspend/platform/resources/checkout-sessions.d.ts +17 -0
  85. package/dist/esm/anyspend/platform/resources/checkout-sessions.js +23 -0
  86. package/dist/esm/anyspend/platform/resources/customers.d.ts +19 -0
  87. package/dist/esm/anyspend/platform/resources/customers.js +30 -0
  88. package/dist/esm/anyspend/platform/resources/discount-codes.d.ts +29 -0
  89. package/dist/esm/anyspend/platform/resources/discount-codes.js +27 -0
  90. package/dist/esm/anyspend/platform/resources/events.d.ts +14 -0
  91. package/dist/esm/anyspend/platform/resources/events.js +12 -0
  92. package/dist/esm/anyspend/platform/resources/notifications.d.ts +18 -0
  93. package/dist/esm/anyspend/platform/resources/notifications.js +23 -0
  94. package/dist/esm/anyspend/platform/resources/organization.d.ts +17 -0
  95. package/dist/esm/anyspend/platform/resources/organization.js +11 -0
  96. package/dist/esm/anyspend/platform/resources/payment-links.d.ts +21 -0
  97. package/dist/esm/anyspend/platform/resources/payment-links.js +45 -0
  98. package/dist/esm/anyspend/platform/resources/products.d.ts +27 -0
  99. package/dist/esm/anyspend/platform/resources/products.js +27 -0
  100. package/dist/esm/anyspend/platform/resources/transactions.d.ts +11 -0
  101. package/dist/esm/anyspend/platform/resources/transactions.js +21 -0
  102. package/dist/esm/anyspend/platform/resources/webhooks.d.ts +14 -0
  103. package/dist/esm/anyspend/platform/resources/webhooks.js +29 -0
  104. package/dist/esm/anyspend/platform/resources/widgets.d.ts +38 -0
  105. package/dist/esm/anyspend/platform/resources/widgets.js +27 -0
  106. package/dist/esm/anyspend/platform/types.d.ts +478 -0
  107. package/dist/esm/anyspend/platform/types.js +4 -0
  108. package/dist/esm/anyspend/platform/utils/idempotency.d.ts +4 -0
  109. package/dist/esm/anyspend/platform/utils/idempotency.js +14 -0
  110. package/dist/esm/anyspend/platform/utils/pagination.d.ts +12 -0
  111. package/dist/esm/anyspend/platform/utils/pagination.js +19 -0
  112. package/dist/esm/anyspend/react/components/AnySpend.d.ts +5 -1
  113. package/dist/esm/anyspend/react/components/AnySpend.js +124 -13
  114. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.d.ts +12 -6
  115. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.js +55 -8
  116. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
  117. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckoutTrigger.js +2 -2
  118. package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
  119. package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -2
  120. package/dist/esm/anyspend/react/components/checkout/CryptoPayPanel.js +1 -1
  121. package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
  122. package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.js +48 -18
  123. package/dist/esm/anyspend/react/components/checkout/KycGate.d.ts +11 -0
  124. package/dist/esm/anyspend/react/components/checkout/KycGate.js +167 -0
  125. package/dist/esm/anyspend/react/components/checkout/VariablePricingInput.d.ts +17 -0
  126. package/dist/esm/anyspend/react/components/checkout/VariablePricingInput.js +142 -0
  127. package/dist/esm/anyspend/react/components/index.d.ts +1 -1
  128. package/dist/esm/anyspend/react/hooks/index.d.ts +1 -0
  129. package/dist/esm/anyspend/react/hooks/index.js +1 -0
  130. package/dist/esm/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +13 -0
  131. package/dist/esm/anyspend/react/hooks/useKycStatus.d.ts +47 -0
  132. package/dist/esm/anyspend/react/hooks/useKycStatus.js +117 -0
  133. package/dist/esm/anyspend/services/anyspend.d.ts +3 -1
  134. package/dist/esm/anyspend/services/anyspend.js +2 -1
  135. package/dist/esm/global-account/react/components/B3DynamicModal.js +1 -1
  136. package/dist/esm/global-account/react/components/ManageAccount/BottomNavigation.js +3 -3
  137. package/dist/esm/global-account/react/components/SignInWithB3/SignIn.js +1 -1
  138. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +13 -5
  139. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Privy.js +1 -1
  140. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStep.d.ts +1 -1
  141. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStep.js +21 -24
  142. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepCustom.js +1 -1
  143. package/dist/esm/global-account/react/hooks/useAuth.js +2 -2
  144. package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +3 -1
  145. package/dist/esm/global-account/react/hooks/useAuthentication.js +82 -24
  146. package/dist/esm/global-account/react/hooks/useGetAllTWSigners.js +2 -1
  147. package/dist/esm/global-account/react/stores/useModalStore.d.ts +4 -0
  148. package/dist/esm/global-account/react/stores/useModalStore.js +2 -0
  149. package/dist/esm/global-account/react/utils/createWagmiConfig.d.ts +18 -0
  150. package/dist/esm/global-account/react/utils/createWagmiConfig.js +16 -0
  151. package/dist/styles/index.css +1 -1
  152. package/dist/types/anyspend/platform/client.d.ts +35 -0
  153. package/dist/types/anyspend/platform/errors.d.ts +38 -0
  154. package/dist/types/anyspend/platform/index.d.ts +87 -0
  155. package/dist/types/anyspend/platform/resources/analytics.d.ts +7 -0
  156. package/dist/types/anyspend/platform/resources/checkout-sessions.d.ts +17 -0
  157. package/dist/types/anyspend/platform/resources/customers.d.ts +19 -0
  158. package/dist/types/anyspend/platform/resources/discount-codes.d.ts +29 -0
  159. package/dist/types/anyspend/platform/resources/events.d.ts +14 -0
  160. package/dist/types/anyspend/platform/resources/notifications.d.ts +18 -0
  161. package/dist/types/anyspend/platform/resources/organization.d.ts +17 -0
  162. package/dist/types/anyspend/platform/resources/payment-links.d.ts +21 -0
  163. package/dist/types/anyspend/platform/resources/products.d.ts +27 -0
  164. package/dist/types/anyspend/platform/resources/transactions.d.ts +11 -0
  165. package/dist/types/anyspend/platform/resources/webhooks.d.ts +14 -0
  166. package/dist/types/anyspend/platform/resources/widgets.d.ts +38 -0
  167. package/dist/types/anyspend/platform/types.d.ts +478 -0
  168. package/dist/types/anyspend/platform/utils/idempotency.d.ts +4 -0
  169. package/dist/types/anyspend/platform/utils/pagination.d.ts +12 -0
  170. package/dist/types/anyspend/react/components/AnySpend.d.ts +5 -1
  171. package/dist/types/anyspend/react/components/checkout/AnySpendCheckout.d.ts +12 -6
  172. package/dist/types/anyspend/react/components/checkout/AnySpendCheckoutTrigger.d.ts +3 -1
  173. package/dist/types/anyspend/react/components/checkout/CheckoutPaymentPanel.d.ts +3 -1
  174. package/dist/types/anyspend/react/components/checkout/FiatCheckoutPanel.d.ts +3 -1
  175. package/dist/types/anyspend/react/components/checkout/KycGate.d.ts +11 -0
  176. package/dist/types/anyspend/react/components/checkout/VariablePricingInput.d.ts +17 -0
  177. package/dist/types/anyspend/react/components/index.d.ts +1 -1
  178. package/dist/types/anyspend/react/hooks/index.d.ts +1 -0
  179. package/dist/types/anyspend/react/hooks/useKycStatus.d.ts +47 -0
  180. package/dist/types/anyspend/services/anyspend.d.ts +3 -1
  181. package/dist/types/global-account/react/components/SignInWithB3/steps/LoginStep.d.ts +1 -1
  182. package/dist/types/global-account/react/hooks/useAuthentication.d.ts +3 -1
  183. package/dist/types/global-account/react/stores/useModalStore.d.ts +4 -0
  184. package/dist/types/global-account/react/utils/createWagmiConfig.d.ts +18 -0
  185. package/package.json +7 -1
  186. package/src/anyspend/docs/checkout-sessions.md +20 -3
  187. package/src/anyspend/platform/client.ts +198 -0
  188. package/src/anyspend/platform/errors.ts +92 -0
  189. package/src/anyspend/platform/index.ts +129 -0
  190. package/src/anyspend/platform/resources/analytics.ts +10 -0
  191. package/src/anyspend/platform/resources/checkout-sessions.ts +36 -0
  192. package/src/anyspend/platform/resources/customers.ts +54 -0
  193. package/src/anyspend/platform/resources/discount-codes.ts +63 -0
  194. package/src/anyspend/platform/resources/events.ts +22 -0
  195. package/src/anyspend/platform/resources/notifications.ts +37 -0
  196. package/src/anyspend/platform/resources/organization.ts +24 -0
  197. package/src/anyspend/platform/resources/payment-links.ts +74 -0
  198. package/src/anyspend/platform/resources/products.ts +59 -0
  199. package/src/anyspend/platform/resources/transactions.ts +33 -0
  200. package/src/anyspend/platform/resources/webhooks.ts +47 -0
  201. package/src/anyspend/platform/resources/widgets.ts +63 -0
  202. package/src/anyspend/platform/types.ts +532 -0
  203. package/src/anyspend/platform/utils/idempotency.ts +15 -0
  204. package/src/anyspend/platform/utils/pagination.ts +32 -0
  205. package/src/anyspend/react/components/AnySpend.tsx +148 -14
  206. package/src/anyspend/react/components/checkout/AnySpendCheckout.tsx +77 -18
  207. package/src/anyspend/react/components/checkout/AnySpendCheckoutTrigger.tsx +4 -0
  208. package/src/anyspend/react/components/checkout/CheckoutPaymentPanel.tsx +4 -0
  209. package/src/anyspend/react/components/checkout/CryptoPayPanel.tsx +4 -13
  210. package/src/anyspend/react/components/checkout/FiatCheckoutPanel.tsx +81 -17
  211. package/src/anyspend/react/components/checkout/KycGate.tsx +387 -0
  212. package/src/anyspend/react/components/checkout/VariablePricingInput.tsx +247 -0
  213. package/src/anyspend/react/components/index.ts +1 -0
  214. package/src/anyspend/react/hooks/index.ts +1 -0
  215. package/src/anyspend/react/hooks/useAnyspendCreateOnrampOrder.ts +14 -0
  216. package/src/anyspend/react/hooks/useKycStatus.ts +150 -0
  217. package/src/anyspend/services/anyspend.ts +4 -0
  218. package/src/global-account/react/components/B3DynamicModal.tsx +0 -2
  219. package/src/global-account/react/components/ManageAccount/BottomNavigation.tsx +7 -7
  220. package/src/global-account/react/components/SignInWithB3/SignIn.tsx +1 -1
  221. package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +13 -5
  222. package/src/global-account/react/components/SignInWithB3/SignInWithB3Privy.tsx +1 -1
  223. package/src/global-account/react/components/SignInWithB3/steps/LoginStep.tsx +35 -25
  224. package/src/global-account/react/components/SignInWithB3/steps/LoginStepCustom.tsx +1 -1
  225. package/src/global-account/react/hooks/useAuth.ts +2 -2
  226. package/src/global-account/react/hooks/useAuthentication.ts +80 -27
  227. package/src/global-account/react/hooks/useGetAllTWSigners.tsx +2 -1
  228. package/src/global-account/react/stores/useModalStore.ts +6 -0
  229. package/src/global-account/react/utils/createWagmiConfig.tsx +18 -0
@@ -27,6 +27,8 @@ import {
27
27
  toast,
28
28
  TransitionPanel,
29
29
  useAccountWallet,
30
+ useAuth,
31
+ useAuthStore,
30
32
  useB3Config,
31
33
  useModalStore,
32
34
  useProfile,
@@ -64,6 +66,8 @@ import { FiatPaymentMethod, FiatPaymentMethodComponent } from "./common/FiatPaym
64
66
  import { GasIndicator } from "./common/GasIndicator";
65
67
  import { OrderDetails, OrderDetailsLoadingView } from "./common/OrderDetails";
66
68
  import { OrderHistory } from "./common/OrderHistory";
69
+ import { KycGate } from "./checkout/KycGate";
70
+ import { LoginStep } from "@b3dotfun/sdk/global-account/react/components/SignInWithB3/steps/LoginStep";
67
71
  import { PanelOnramp } from "./common/PanelOnramp";
68
72
  import { PanelOnrampPayment } from "./common/PanelOnrampPayment";
69
73
  import { PointsDetailPanel } from "./common/PointsDetailPanel";
@@ -94,6 +98,8 @@ export enum PanelView {
94
98
  POINTS_DETAIL,
95
99
  FEE_DETAIL,
96
100
  DIRECT_TRANSFER_SUCCESS,
101
+ FIAT_KYC,
102
+ FIAT_AUTH,
97
103
  }
98
104
 
99
105
  const ANYSPEND_RECIPIENTS_KEY = "anyspend_recipients";
@@ -140,6 +146,8 @@ export function AnySpend(props: {
140
146
  content?: AnySpendContent;
141
147
  /** Structured color/theme configuration */
142
148
  theme?: AnySpendTheme;
149
+ /** When true, shows a KYC gate before Stripe Web2 (credit card) payments. Default false. */
150
+ kycEnabled?: boolean;
143
151
  }) {
144
152
  const fingerprintConfig = getFingerprintConfig();
145
153
 
@@ -175,6 +183,7 @@ function AnySpendInner({
175
183
  destinationTokenAmount,
176
184
  callbackMetadata,
177
185
  senderAddress,
186
+ kycEnabled = false,
178
187
  }: {
179
188
  sourceChainId?: number;
180
189
  destinationTokenAddress?: string;
@@ -201,6 +210,7 @@ function AnySpendInner({
201
210
  slots?: AnySpendSlots;
202
211
  content?: AnySpendContent;
203
212
  theme?: AnySpendTheme;
213
+ kycEnabled?: boolean;
204
214
  }) {
205
215
  const { slots, content } = useAnySpendCustomization();
206
216
  const searchParams = useSearchParamsSSR();
@@ -209,7 +219,13 @@ function AnySpendInner({
209
219
  const { partnerId } = useB3Config();
210
220
  const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
211
221
  const setB3ModalOpen = useModalStore(state => state.setB3ModalOpen);
212
-
222
+ const { isAuthenticated } = useAuth();
223
+ // KYC approval is tracked per-session so we only prompt the wallet
224
+ // signature when the user actually clicks Buy, not on panel mount.
225
+ // useRef so handleFiatOrder can read the updated value synchronously
226
+ // in the same frame that onStatusResolved sets it (setState is async).
227
+ // When kycEnabled is false (default), pre-approve so the KYC gate is skipped.
228
+ const kycApprovedRef = useRef(!kycEnabled);
213
229
  // Determine if we're in "buy mode" based on whether destination token props are provided
214
230
  const isBuyMode = !!(destinationTokenAddress && destinationTokenChainId);
215
231
 
@@ -236,7 +252,17 @@ function AnySpendInner({
236
252
  // Track previous panel for proper back navigation
237
253
  const previousPanel = useRef<PanelView>(PanelView.MAIN);
238
254
 
239
- const [activeTab, setActiveTab] = useState<"crypto" | "fiat">(defaultActiveTab);
255
+ const [activeTab, setActiveTab] = useState<"crypto" | "fiat">(() => {
256
+ if (typeof window !== "undefined") {
257
+ const stored = sessionStorage.getItem("anyspend_active_tab") as "crypto" | "fiat" | null;
258
+ if (stored === "crypto" || stored === "fiat") return stored;
259
+ }
260
+ return defaultActiveTab;
261
+ });
262
+
263
+ useEffect(() => {
264
+ sessionStorage.setItem("anyspend_active_tab", activeTab);
265
+ }, [activeTab]);
240
266
 
241
267
  const [orderId, setOrderId] = useState<string | undefined>(loadOrder);
242
268
  const [directTransferTxHash, setDirectTransferTxHash] = useState<string | undefined>();
@@ -273,10 +299,20 @@ function AnySpendInner({
273
299
  resetPaymentMethods,
274
300
  } = useCryptoPaymentMethodState();
275
301
 
276
- const [selectedFiatPaymentMethod, setSelectedFiatPaymentMethod] = useState<FiatPaymentMethod>(FiatPaymentMethod.NONE);
302
+ const [selectedFiatPaymentMethod, setSelectedFiatPaymentMethod] = useState<FiatPaymentMethod>(() => {
303
+ if (typeof window !== "undefined") {
304
+ const stored = sessionStorage.getItem("anyspend_fiat_method") as FiatPaymentMethod | null;
305
+ if (stored && Object.values(FiatPaymentMethod).includes(stored)) return stored;
306
+ }
307
+ return FiatPaymentMethod.NONE;
308
+ });
277
309
  // const [newRecipientAddress, setNewRecipientAddress] = useState("");
278
310
  // const recipientInputRef = useRef<HTMLInputElement>(null);
279
311
 
312
+ useEffect(() => {
313
+ sessionStorage.setItem("anyspend_fiat_method", selectedFiatPaymentMethod);
314
+ }, [selectedFiatPaymentMethod]);
315
+
280
316
  // Get initial chain IDs from URL or defaults
281
317
  const initialSrcChainId = sourceChainId || parseInt(searchParams.get("fromChainId") || "0") || mainnet.id;
282
318
  const initialDstChainId =
@@ -297,11 +333,27 @@ function AnySpendInner({
297
333
  const { data: srcTokenMetadata } = useTokenData(selectedSrcToken?.chainId, selectedSrcToken?.address);
298
334
  const [srcAmount, setSrcAmount] = useState<string>(searchParams.get("fromAmount") || "0");
299
335
 
300
- // State for onramp amount
301
- const [srcAmountOnRamp, setSrcAmountOnRamp] = useState<string>(searchParams.get("fromAmount") || "5");
336
+ // State for onramp amount — persisted in sessionStorage so it survives Persona KYC roundtrip
337
+ const [srcAmountOnRamp, setSrcAmountOnRamp] = useState<string>(() => {
338
+ if (typeof window !== "undefined") {
339
+ const stored = sessionStorage.getItem("anyspend_fiat_amount");
340
+ if (stored) return stored;
341
+ }
342
+ return searchParams.get("fromAmount") || "5";
343
+ });
302
344
 
303
- // State for destination chain/token selection
304
- const [selectedDstChainId, setSelectedDstChainId] = useState<number>(initialDstChainId);
345
+ useEffect(() => {
346
+ sessionStorage.setItem("anyspend_fiat_amount", srcAmountOnRamp);
347
+ }, [srcAmountOnRamp]);
348
+
349
+ // State for destination chain/token selection (sync effects come after state declarations below) — persisted in sessionStorage for Persona KYC roundtrip
350
+ const [selectedDstChainId, setSelectedDstChainId] = useState<number>(() => {
351
+ if (!isBuyMode && typeof window !== "undefined") {
352
+ const stored = sessionStorage.getItem("anyspend_dst_chain_id");
353
+ if (stored) return parseInt(stored, 10);
354
+ }
355
+ return initialDstChainId;
356
+ });
305
357
  // Helper to check if address is Hyperliquid USDC (supports both 34-char and 42-char formats)
306
358
  const isHyperliquidUSDCAddress = (address?: string) =>
307
359
  eqci(address, HYPERLIQUID_USDC_ADDRESS) || eqci(address, ZERO_ADDRESS);
@@ -323,12 +375,29 @@ function AnySpendInner({
323
375
  defaultToken: defaultDstToken,
324
376
  prefix: "to",
325
377
  });
326
- const [selectedDstToken, setSelectedDstToken] = useState<components["schemas"]["Token"]>(
327
- isBuyMode ? defaultDstToken : dstTokenFromUrl,
328
- );
378
+ const [selectedDstToken, setSelectedDstToken] = useState<components["schemas"]["Token"]>(() => {
379
+ if (!isBuyMode && typeof window !== "undefined") {
380
+ const stored = sessionStorage.getItem("anyspend_dst_token");
381
+ if (stored) {
382
+ try {
383
+ return JSON.parse(stored) as components["schemas"]["Token"];
384
+ } catch {}
385
+ }
386
+ }
387
+ return isBuyMode ? defaultDstToken : dstTokenFromUrl;
388
+ });
329
389
  const { data: dstTokenMetadata } = useTokenData(selectedDstToken?.chainId, selectedDstToken?.address);
330
390
  const [dstAmount, setDstAmount] = useState<string>(searchParams.get("toAmount") || "");
331
391
 
392
+ // Sync dst chain/token to sessionStorage so they survive Persona KYC roundtrip
393
+ useEffect(() => {
394
+ if (!isBuyMode) sessionStorage.setItem("anyspend_dst_chain_id", selectedDstChainId.toString());
395
+ }, [selectedDstChainId, isBuyMode]);
396
+
397
+ useEffect(() => {
398
+ if (!isBuyMode) sessionStorage.setItem("anyspend_dst_token", JSON.stringify(selectedDstToken));
399
+ }, [selectedDstToken, isBuyMode]);
400
+
332
401
  const [isSrcInputDirty, setIsSrcInputDirty] = useState(true);
333
402
  // Add refs to track if we've applied metadata
334
403
  const appliedSrcMetadataRef = useRef(false);
@@ -728,6 +797,17 @@ function AnySpendInner({
728
797
  // Call onSuccess when order is executed
729
798
  useOnOrderSuccess({ orderData: oat, orderId, onSuccess });
730
799
 
800
+ // Clear all persisted selection state once an order is submitted — next open starts fresh
801
+ useEffect(() => {
802
+ if (orderId) {
803
+ sessionStorage.removeItem("anyspend_fiat_amount");
804
+ sessionStorage.removeItem("anyspend_active_tab");
805
+ sessionStorage.removeItem("anyspend_fiat_method");
806
+ sessionStorage.removeItem("anyspend_dst_chain_id");
807
+ sessionStorage.removeItem("anyspend_dst_token");
808
+ }
809
+ }, [orderId]);
810
+
731
811
  const { createOrder, isCreatingOrder } = useAnyspendCreateOrder({
732
812
  onSuccess: data => {
733
813
  const orderId = data.data.id;
@@ -817,8 +897,8 @@ function AnySpendInner({
817
897
  if (selectedFiatPaymentMethod === FiatPaymentMethod.NONE) {
818
898
  return { text: "Select payment method", disable: false, error: false, loading: false };
819
899
  }
820
- // If payment method is selected, show "Buy"
821
- return { text: "Buy", disable: false, error: false, loading: false };
900
+ // If payment method is selected, show "Continue"
901
+ return { text: "Continue", disable: false, error: false, loading: false };
822
902
  }
823
903
 
824
904
  if (activeTab === "crypto") {
@@ -845,7 +925,7 @@ function AnySpendInner({
845
925
  }
846
926
  }
847
927
 
848
- return { text: "Buy", disable: false, error: false, loading: false };
928
+ return { text: "Continue", disable: false, error: false, loading: false };
849
929
  }, [
850
930
  activeInputAmountInWei,
851
931
  isSameChainSameToken,
@@ -1028,7 +1108,20 @@ function AnySpendInner({
1028
1108
  vendor = "stripe";
1029
1109
  paymentMethodString = "";
1030
1110
  } else if (paymentMethod === FiatPaymentMethod.STRIPE_WEB2) {
1031
- // Stripe embedded payment form
1111
+ // Stripe embedded payment form requires authentication + KYC
1112
+ // Read from store directly to avoid stale closure when called from onLoginSuccess callback
1113
+ const currentlyAuthenticated = useAuthStore.getState().isAuthenticated;
1114
+ if (!currentlyAuthenticated) {
1115
+ navigateToPanel(PanelView.FIAT_AUTH, "forward");
1116
+ return;
1117
+ }
1118
+ if (!kycApprovedRef.current) {
1119
+ // Navigate to KYC gate. KycGate shows an explicit "Continue to Verify"
1120
+ // CTA and pre-signs from that user-gesture context before enabling
1121
+ // the useKycStatus query — so no surprise signature popup here.
1122
+ navigateToPanel(PanelView.FIAT_KYC, "forward");
1123
+ return;
1124
+ }
1032
1125
  if (!stripeWeb2Support.isSupport) {
1033
1126
  toast.error("Pay with Card not available");
1034
1127
  return;
@@ -1147,6 +1240,15 @@ function AnySpendInner({
1147
1240
  };
1148
1241
  }, [activePanel, navigateBack]);
1149
1242
 
1243
+ // When auth completes while on the FIAT_AUTH panel, navigate back and retry the order
1244
+ useEffect(() => {
1245
+ if (isAuthenticated && activePanel === PanelView.FIAT_AUTH) {
1246
+ navigateBack();
1247
+ handleFiatOrder(selectedFiatPaymentMethod);
1248
+ }
1249
+ // eslint-disable-next-line react-hooks/exhaustive-deps
1250
+ }, [isAuthenticated]);
1251
+
1150
1252
  const historyView = (
1151
1253
  <div className={"mx-auto flex w-[560px] max-w-full flex-col items-center"}>
1152
1254
  <OrderHistory mode={mode} onBack={navigateBack} onSelectOrder={onSelectOrder} />
@@ -1593,6 +1695,32 @@ function AnySpendInner({
1593
1695
  </div>
1594
1696
  );
1595
1697
 
1698
+ const kycView = (
1699
+ <div className="mx-auto flex w-full max-w-[460px] flex-col gap-4 px-5 pt-5">
1700
+ <KycGate
1701
+ enabled={activePanel === PanelView.FIAT_KYC}
1702
+ onStatusResolved={approved => {
1703
+ if (approved) {
1704
+ kycApprovedRef.current = true;
1705
+ navigateBack();
1706
+ handleFiatOrder(selectedFiatPaymentMethod);
1707
+ }
1708
+ }}
1709
+ />
1710
+ </div>
1711
+ );
1712
+
1713
+ const authView = (
1714
+ <div className="mx-auto w-full max-w-[460px]">
1715
+ <LoginStep
1716
+ chain={baseChain}
1717
+ onSuccess={async () => {
1718
+ // isAuthenticated will be true at this point — the useEffect below handles navigation
1719
+ }}
1720
+ />
1721
+ </div>
1722
+ );
1723
+
1596
1724
  // Add tabs to the main component when no order is loaded
1597
1725
  return (
1598
1726
  <StyleRoot>
@@ -1667,6 +1795,12 @@ function AnySpendInner({
1667
1795
  <div key="direct-transfer-success-view" className={cn(mode === "page" && "p-6")}>
1668
1796
  {directTransferSuccessView}
1669
1797
  </div>,
1798
+ <div key="fiat-kyc-view" className={cn(mode === "page" && "p-6")}>
1799
+ {kycView}
1800
+ </div>,
1801
+ <div key="fiat-auth-view" className={cn(mode === "page" && "p-6")}>
1802
+ {authView}
1803
+ </div>,
1670
1804
  ]}
1671
1805
  </TransitionPanel>
1672
1806
  </div>
@@ -1,29 +1,31 @@
1
1
  "use client";
2
2
 
3
- import { useTokenData } from "@b3dotfun/sdk/global-account/react";
4
3
  import { USDC_BASE } from "@b3dotfun/sdk/anyspend/constants";
4
+ import { useTokenData } from "@b3dotfun/sdk/global-account/react";
5
5
  import { formatUnits, safeBigInt } from "@b3dotfun/sdk/shared/utils/number";
6
- import { type ReactNode, useCallback, useMemo, useState } from "react";
6
+ import { useCallback, useMemo, useState, type ReactNode } from "react";
7
+ import type {
8
+ AddressData,
9
+ CheckoutFormComponentProps,
10
+ CheckoutFormSchema,
11
+ DiscountResult,
12
+ ShippingOption,
13
+ } from "../../../types/forms";
7
14
  import { useAnyspendQuote } from "../../hooks/useAnyspendQuote";
8
15
  import { AnySpendFingerprintWrapper, getFingerprintConfig } from "../AnySpendFingerprintWrapper";
16
+ import { AnySpendCustomizationProvider } from "../context/AnySpendCustomizationContext";
17
+ import type { AnySpendCheckoutClasses } from "../types/classes";
18
+ import type { AnySpendContent, AnySpendSlots, AnySpendTheme } from "../types/customization";
9
19
  import { CheckoutCartPanel } from "./CheckoutCartPanel";
10
20
  import { CheckoutFormPanel } from "./CheckoutFormPanel";
11
21
  import { CheckoutLayout } from "./CheckoutLayout";
12
22
  import { CheckoutPaymentPanel, type PaymentMethod } from "./CheckoutPaymentPanel";
23
+ import { VariablePricingInput, type VariablePricingConfig } from "./VariablePricingInput";
13
24
 
14
25
  export type { AnySpendCheckoutClasses } from "../types/classes";
15
- import type { AnySpendCheckoutClasses } from "../types/classes";
16
- import { AnySpendCustomizationProvider } from "../context/AnySpendCustomizationContext";
17
- import type { AnySpendContent, AnySpendSlots, AnySpendTheme } from "../types/customization";
18
- import type {
19
- CheckoutFormSchema,
20
- CheckoutFormComponentProps,
21
- ShippingOption,
22
- DiscountResult,
23
- AddressData,
24
- } from "../../../types/forms";
25
26
 
26
- export type { CheckoutFormSchema, CheckoutFormComponentProps, ShippingOption, DiscountResult, AddressData };
27
+ export type { VariablePricingConfig } from "./VariablePricingInput";
28
+ export type { AddressData, CheckoutFormComponentProps, CheckoutFormSchema, DiscountResult, ShippingOption };
27
29
 
28
30
  export interface CheckoutItem {
29
31
  id?: string;
@@ -55,7 +57,7 @@ export interface AnySpendCheckoutProps {
55
57
  destinationTokenAddress: string;
56
58
  /** The destination chain ID */
57
59
  destinationTokenChainId: number;
58
- /** Line items */
60
+ /** Line items. When `variablePricing.enabled` is true, pass a single placeholder item (e.g. amount "0") — the user-entered amount overrides the total. */
59
61
  items: CheckoutItem[];
60
62
  /** Override computed total */
61
63
  totalAmount?: string;
@@ -130,8 +132,12 @@ export interface AnySpendCheckoutProps {
130
132
  onDiscountApplied?: (result: DiscountResult) => void;
131
133
  /** Async function to validate a discount code. Returns DiscountResult. */
132
134
  validateDiscount?: (code: string) => Promise<DiscountResult>;
135
+ /** Variable pricing / name your price config. When enabled, user enters amount before payment. */
136
+ variablePricing?: VariablePricingConfig;
133
137
  /** When true, fees are added on top of the amount (payer pays more, receiver gets exact amount) */
134
138
  feeOnTop?: boolean;
139
+ /** When true, identity verification (KYC) is required before card payment. Defaults to false. */
140
+ kycEnabled?: boolean;
135
141
  }
136
142
 
137
143
  const emptyAddress: AddressData = { street: "", city: "", state: "", zip: "", country: "" };
@@ -177,8 +183,16 @@ export function AnySpendCheckout({
177
183
  enableDiscountCode,
178
184
  onDiscountApplied: onDiscountAppliedProp,
179
185
  validateDiscount,
186
+ // Variable pricing
187
+ variablePricing,
180
188
  feeOnTop,
189
+ kycEnabled = false,
181
190
  }: AnySpendCheckoutProps) {
191
+ // ===== Variable pricing state =====
192
+ const [variablePricingAmount, setVariablePricingAmount] = useState<string>("0");
193
+ const isVariablePricingActive = variablePricing?.enabled === true;
194
+ const isVariablePricingValid = isVariablePricingActive ? variablePricingAmount !== "0" : true;
195
+
182
196
  // ===== Form state =====
183
197
  const [formData, setFormData] = useState<Record<string, unknown>>({});
184
198
  const [selectedShipping, setSelectedShipping] = useState<ShippingOption | null>(null);
@@ -239,7 +253,20 @@ export function AnySpendCheckout({
239
253
  }, [appliedDiscount, discountProp]);
240
254
 
241
255
  // Compute total from items + adjustments (including dynamic shipping/discount)
256
+ // Variable pricing overrides the total when active
242
257
  const computedTotal = useMemo(() => {
258
+ if (isVariablePricingActive && variablePricingAmount !== "0") {
259
+ let total = safeBigInt(variablePricingAmount);
260
+ if (effectiveShipping?.amount) total += safeBigInt(effectiveShipping.amount);
261
+ const taxAmt = typeof tax === "string" ? tax : tax?.amount;
262
+ if (taxAmt) total += safeBigInt(taxAmt);
263
+ if (effectiveDiscount?.amount) total -= safeBigInt(effectiveDiscount.amount);
264
+ if (summaryLines) {
265
+ for (const line of summaryLines) total += safeBigInt(line.amount);
266
+ }
267
+ if (total < BigInt(0)) total = BigInt(0);
268
+ return total.toString();
269
+ }
243
270
  if (totalAmountOverride) return totalAmountOverride;
244
271
  let total = BigInt(0);
245
272
  for (const item of items) {
@@ -254,7 +281,16 @@ export function AnySpendCheckout({
254
281
  }
255
282
  if (total < BigInt(0)) total = BigInt(0);
256
283
  return total.toString();
257
- }, [items, totalAmountOverride, effectiveShipping, tax, effectiveDiscount, summaryLines]);
284
+ }, [
285
+ items,
286
+ totalAmountOverride,
287
+ effectiveShipping,
288
+ tax,
289
+ effectiveDiscount,
290
+ summaryLines,
291
+ isVariablePricingActive,
292
+ variablePricingAmount,
293
+ ]);
258
294
 
259
295
  // Get destination token metadata
260
296
  const { data: tokenData } = useTokenData(destinationTokenChainId, destinationTokenAddress);
@@ -303,14 +339,26 @@ export function AnySpendCheckout({
303
339
  if (formData.email) meta.customerEmail = formData.email;
304
340
  if (formData.name) meta.customerName = formData.name;
305
341
  if (checkoutSessionId) meta.checkoutSessionId = checkoutSessionId;
342
+ if (isVariablePricingActive && variablePricingAmount !== "0") {
343
+ meta.variablePricingAmount = variablePricingAmount;
344
+ }
306
345
  return Object.keys(meta).length > 0 ? meta : undefined;
307
- }, [formData, selectedShipping, shippingAddress, appliedDiscount, checkoutSessionId]);
346
+ }, [
347
+ formData,
348
+ selectedShipping,
349
+ shippingAddress,
350
+ appliedDiscount,
351
+ checkoutSessionId,
352
+ isVariablePricingActive,
353
+ variablePricingAmount,
354
+ ]);
308
355
 
309
- // Check if required form fields are filled
356
+ // Check if required form fields are filled and variable pricing is valid
310
357
  const isFormValid = useMemo(() => {
358
+ if (!isVariablePricingValid) return false;
311
359
  if (!formSchema) return true;
312
360
  return formSchema.fields.filter(f => f.required).every(f => formData[f.id] != null && formData[f.id] !== "");
313
- }, [formSchema, formData]);
361
+ }, [formSchema, formData, isVariablePricingValid]);
314
362
 
315
363
  // Check if we have a form panel to show
316
364
  const hasFormContent =
@@ -328,6 +376,16 @@ export function AnySpendCheckout({
328
376
  mode={mode}
329
377
  paymentPanel={
330
378
  <>
379
+ {/* Variable pricing input renders above everything */}
380
+ {isVariablePricingActive && tokenData && variablePricing && (
381
+ <VariablePricingInput
382
+ config={variablePricing}
383
+ tokenDecimals={tokenDecimals}
384
+ tokenSymbol={tokenSymbol}
385
+ themeColor={themeColor}
386
+ onChange={setVariablePricingAmount}
387
+ />
388
+ )}
331
389
  {/* Form panel renders above payment panel in the left/payment column */}
332
390
  {hasFormContent && (
333
391
  <div className="mb-6">
@@ -374,6 +432,7 @@ export function AnySpendCheckout({
374
432
  callbackMetadata={checkoutFormMetadata}
375
433
  isFormValid={isFormValid}
376
434
  feeOnTop={feeOnTop}
435
+ kycEnabled={kycEnabled}
377
436
  />
378
437
  </>
379
438
  }
@@ -73,6 +73,8 @@ export interface AnySpendCheckoutTriggerProps {
73
73
  discount?: string | { amount: string; label?: string; code?: string };
74
74
  /** Additional summary line items (fees, tips, etc.) */
75
75
  summaryLines?: CheckoutSummaryLine[];
76
+ /** When true, identity verification (KYC) is required before card payment. Defaults to false. */
77
+ kycEnabled?: boolean;
76
78
  }
77
79
 
78
80
  export function AnySpendCheckoutTrigger({
@@ -103,6 +105,7 @@ export function AnySpendCheckoutTrigger({
103
105
  tax,
104
106
  discount,
105
107
  summaryLines,
108
+ kycEnabled = false,
106
109
  }: AnySpendCheckoutTriggerProps) {
107
110
  // Merge workflowId + orgId into callbackMetadata
108
111
  const mergedMetadata = useMemo(() => {
@@ -212,6 +215,7 @@ export function AnySpendCheckoutTrigger({
212
215
  classes={classes}
213
216
  defaultPaymentMethod={defaultPaymentMethod}
214
217
  senderAddress={senderAddress}
218
+ kycEnabled={kycEnabled}
215
219
  />
216
220
  </div>
217
221
  </div>
@@ -39,6 +39,8 @@ interface CheckoutPaymentPanelProps {
39
39
  isFormValid?: boolean;
40
40
  /** When true, fees are added on top (payer pays more, receiver gets exact amount) */
41
41
  feeOnTop?: boolean;
42
+ /** When true, identity verification (KYC) is required before card payment. Defaults to false. */
43
+ kycEnabled?: boolean;
42
44
  }
43
45
 
44
46
  function RadioCircle({ selected, themeColor }: { selected: boolean; themeColor?: string }) {
@@ -135,6 +137,7 @@ export function CheckoutPaymentPanel({
135
137
  showOrderId,
136
138
  isFormValid = true,
137
139
  feeOnTop,
140
+ kycEnabled = false,
138
141
  }: CheckoutPaymentPanelProps) {
139
142
  const [paymentMethod, setPaymentMethod] = useState<PaymentMethod | null>(defaultPaymentMethod ?? null);
140
143
 
@@ -295,6 +298,7 @@ export function CheckoutPaymentPanel({
295
298
  callbackMetadata={callbackMetadata}
296
299
  classes={classes}
297
300
  feeOnTop={feeOnTop}
301
+ kycEnabled={kycEnabled}
298
302
  />
299
303
  </div>
300
304
  </motion.div>
@@ -585,14 +585,8 @@ export function CryptoPayPanel({
585
585
  {srcAmountFormatted} {selectedSrcToken?.symbol}
586
586
  </span>{" "}
587
587
  on{" "}
588
- <span className="font-semibold text-gray-900 dark:text-gray-100">
589
- {chainLogoUrl && (
590
- <img
591
- src={chainLogoUrl}
592
- alt=""
593
- className="mb-px mr-0.5 inline h-3.5 w-3.5 rounded-full align-text-bottom"
594
- />
595
- )}
588
+ <span className="inline-flex items-center gap-1 rounded-full bg-gray-100 px-1.5 py-0.5 align-middle font-semibold text-gray-900 dark:bg-white/10 dark:text-gray-100">
589
+ {chainLogoUrl && <img src={chainLogoUrl} alt="" className="h-3.5 w-3.5 rounded-full" />}
596
590
  {chainName}
597
591
  </span>{" "}
598
592
  to:
@@ -613,11 +607,8 @@ export function CryptoPayPanel({
613
607
 
614
608
  {/* Warning */}
615
609
  <p className="text-xs leading-snug text-orange-500/80 dark:text-orange-400/80">
616
- Only send {selectedSrcToken?.symbol} on{" "}
617
- {chainLogoUrl && (
618
- <img src={chainLogoUrl} alt="" className="mr-0.5 inline h-3 w-3 rounded-full align-text-bottom" />
619
- )}
620
- {chainName}. Sending other tokens or using a different network may result in loss of funds.
610
+ Only send {selectedSrcToken?.symbol} on <span className="font-semibold">{chainName}</span>. Sending
611
+ other tokens or using a different network may result in loss of funds.
621
612
  </p>
622
613
  </div>
623
614
  </div>