@b3dotfun/sdk 0.0.65-alpha.0 → 0.0.65-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.js +37 -23
  2. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +22 -9
  3. package/dist/cjs/anyspend/react/components/AnySpendCustomExactIn.js +6 -6
  4. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +5 -1
  5. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +15 -9
  6. package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +7 -5
  7. package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +13 -9
  8. package/dist/cjs/anyspend/react/hooks/useCryptoPaymentMethodState.d.ts +42 -0
  9. package/dist/cjs/anyspend/react/hooks/useCryptoPaymentMethodState.js +51 -0
  10. package/dist/esm/anyspend/react/components/AnySpend.js +37 -23
  11. package/dist/esm/anyspend/react/components/AnySpendCustom.js +22 -9
  12. package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +6 -6
  13. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +5 -1
  14. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +15 -9
  15. package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +7 -5
  16. package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +13 -9
  17. package/dist/esm/anyspend/react/hooks/useCryptoPaymentMethodState.d.ts +42 -0
  18. package/dist/esm/anyspend/react/hooks/useCryptoPaymentMethodState.js +48 -0
  19. package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +5 -1
  20. package/dist/types/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +7 -5
  21. package/dist/types/anyspend/react/hooks/useCryptoPaymentMethodState.d.ts +42 -0
  22. package/package.json +1 -1
  23. package/src/anyspend/react/components/AnySpend.tsx +49 -28
  24. package/src/anyspend/react/components/AnySpendCustom.tsx +28 -15
  25. package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +7 -6
  26. package/src/anyspend/react/hooks/useAnyspendFlow.ts +23 -11
  27. package/src/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.ts +20 -12
  28. package/src/anyspend/react/hooks/useCryptoPaymentMethodState.ts +71 -0
@@ -0,0 +1,42 @@
1
+ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod";
2
+ interface UseCryptoPaymentMethodStateResult {
3
+ /** Auto-selected payment method based on balance */
4
+ cryptoPaymentMethod: CryptoPaymentMethodType;
5
+ /** Function to update the auto-selected payment method */
6
+ setCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
7
+ /** User explicitly selected payment method (NONE means no explicit selection) */
8
+ selectedCryptoPaymentMethod: CryptoPaymentMethodType;
9
+ /** Function to update the user-selected payment method */
10
+ setSelectedCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
11
+ /** Effective payment method (user selection takes priority over auto-selection) */
12
+ effectiveCryptoPaymentMethod: CryptoPaymentMethodType;
13
+ /** Reset both payment method states to NONE */
14
+ resetPaymentMethods: () => void;
15
+ }
16
+ /**
17
+ * Custom hook to manage crypto payment method state with dual-state system:
18
+ *
19
+ * - `cryptoPaymentMethod`: Auto-selected based on wallet availability and balance
20
+ * - `selectedCryptoPaymentMethod`: Explicitly selected by user
21
+ * - `effectiveCryptoPaymentMethod`: User selection takes priority over auto-selection
22
+ *
23
+ * This allows automatic payment method suggestions while respecting explicit user choices.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const {
28
+ * cryptoPaymentMethod,
29
+ * setCryptoPaymentMethod,
30
+ * selectedCryptoPaymentMethod,
31
+ * setSelectedCryptoPaymentMethod,
32
+ * effectiveCryptoPaymentMethod,
33
+ * resetPaymentMethods
34
+ * } = useCryptoPaymentMethodState();
35
+ *
36
+ * // Use effectiveCryptoPaymentMethod for display
37
+ * // Use setSelectedCryptoPaymentMethod when user explicitly selects
38
+ * // Call resetPaymentMethods when switching tabs or going back
39
+ * ```
40
+ */
41
+ export declare function useCryptoPaymentMethodState(): UseCryptoPaymentMethodStateResult;
42
+ export {};
@@ -0,0 +1,48 @@
1
+ import { useState } from "react";
2
+ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod.js";
3
+ /**
4
+ * Custom hook to manage crypto payment method state with dual-state system:
5
+ *
6
+ * - `cryptoPaymentMethod`: Auto-selected based on wallet availability and balance
7
+ * - `selectedCryptoPaymentMethod`: Explicitly selected by user
8
+ * - `effectiveCryptoPaymentMethod`: User selection takes priority over auto-selection
9
+ *
10
+ * This allows automatic payment method suggestions while respecting explicit user choices.
11
+ *
12
+ * @example
13
+ * ```tsx
14
+ * const {
15
+ * cryptoPaymentMethod,
16
+ * setCryptoPaymentMethod,
17
+ * selectedCryptoPaymentMethod,
18
+ * setSelectedCryptoPaymentMethod,
19
+ * effectiveCryptoPaymentMethod,
20
+ * resetPaymentMethods
21
+ * } = useCryptoPaymentMethodState();
22
+ *
23
+ * // Use effectiveCryptoPaymentMethod for display
24
+ * // Use setSelectedCryptoPaymentMethod when user explicitly selects
25
+ * // Call resetPaymentMethods when switching tabs or going back
26
+ * ```
27
+ */
28
+ export function useCryptoPaymentMethodState() {
29
+ // cryptoPaymentMethod: auto-selected based on balance
30
+ const [cryptoPaymentMethod, setCryptoPaymentMethod] = useState(CryptoPaymentMethodType.NONE);
31
+ // selectedCryptoPaymentMethod: explicitly selected by user (NONE means no explicit selection)
32
+ const [selectedCryptoPaymentMethod, setSelectedCryptoPaymentMethod] = useState(CryptoPaymentMethodType.NONE);
33
+ // The effective payment method (user selection takes priority over auto-selection)
34
+ const effectiveCryptoPaymentMethod = selectedCryptoPaymentMethod !== CryptoPaymentMethodType.NONE ? selectedCryptoPaymentMethod : cryptoPaymentMethod;
35
+ // Helper function to reset both states
36
+ const resetPaymentMethods = () => {
37
+ setCryptoPaymentMethod(CryptoPaymentMethodType.NONE);
38
+ setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.NONE);
39
+ };
40
+ return {
41
+ cryptoPaymentMethod,
42
+ setCryptoPaymentMethod,
43
+ selectedCryptoPaymentMethod,
44
+ setSelectedCryptoPaymentMethod,
45
+ effectiveCryptoPaymentMethod,
46
+ resetPaymentMethods,
47
+ };
48
+ }
@@ -93,8 +93,12 @@ export declare function useAnyspendFlow({ paymentType, recipientAddress, loadOrd
93
93
  setDstAmount: import("react").Dispatch<import("react").SetStateAction<string>>;
94
94
  isSrcInputDirty: boolean;
95
95
  setIsSrcInputDirty: import("react").Dispatch<import("react").SetStateAction<boolean>>;
96
+ cryptoPaymentMethod: CryptoPaymentMethodType;
97
+ setCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
96
98
  selectedCryptoPaymentMethod: CryptoPaymentMethodType;
97
- setSelectedCryptoPaymentMethod: import("react").Dispatch<import("react").SetStateAction<CryptoPaymentMethodType>>;
99
+ setSelectedCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
100
+ effectiveCryptoPaymentMethod: CryptoPaymentMethodType;
101
+ resetPaymentMethods: () => void;
98
102
  selectedFiatPaymentMethod: FiatPaymentMethod;
99
103
  setSelectedFiatPaymentMethod: import("react").Dispatch<import("react").SetStateAction<FiatPaymentMethod>>;
100
104
  selectedRecipientAddress: string | undefined;
@@ -2,10 +2,12 @@ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMetho
2
2
  interface UseAutoSelectCryptoPaymentMethodParams {
3
3
  /** Current payment type (crypto or fiat) */
4
4
  paymentType?: "crypto" | "fiat";
5
- /** Currently selected payment method */
5
+ /** Auto-selected payment method based on balance (not used in hook logic, but part of state management) */
6
+ cryptoPaymentMethod: CryptoPaymentMethodType;
7
+ /** Function to update the auto-selected payment method */
8
+ setCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
9
+ /** User explicitly selected payment method (NONE means no explicit selection) */
6
10
  selectedCryptoPaymentMethod: CryptoPaymentMethodType;
7
- /** Function to update the selected payment method */
8
- setSelectedCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
9
11
  /** Whether user has enough balance to pay */
10
12
  hasEnoughBalance: boolean;
11
13
  /** Whether balance is still loading */
@@ -16,11 +18,11 @@ interface UseAutoSelectCryptoPaymentMethodParams {
16
18
  * based on available wallets and balance.
17
19
  *
18
20
  * Auto-selection logic:
19
- * - Only auto-selects when payment method is NONE (doesn't override user choices)
21
+ * - Only auto-selects when selectedCryptoPaymentMethod is NONE (user hasn't explicitly chosen)
20
22
  * - If EOA/Wagmi wallet connected + has balance → CONNECT_WALLET
21
23
  * - If EOA/Wagmi wallet connected + insufficient balance → TRANSFER_CRYPTO
22
24
  * - If only Global wallet available → GLOBAL_WALLET
23
25
  * - If no wallets → remains NONE
24
26
  */
25
- export declare function useAutoSelectCryptoPaymentMethod({ paymentType, selectedCryptoPaymentMethod, setSelectedCryptoPaymentMethod, hasEnoughBalance, isBalanceLoading, }: UseAutoSelectCryptoPaymentMethodParams): void;
27
+ export declare function useAutoSelectCryptoPaymentMethod({ paymentType, cryptoPaymentMethod: _cryptoPaymentMethod, setCryptoPaymentMethod, selectedCryptoPaymentMethod, hasEnoughBalance, isBalanceLoading, }: UseAutoSelectCryptoPaymentMethodParams): void;
26
28
  export {};
@@ -0,0 +1,42 @@
1
+ import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod";
2
+ interface UseCryptoPaymentMethodStateResult {
3
+ /** Auto-selected payment method based on balance */
4
+ cryptoPaymentMethod: CryptoPaymentMethodType;
5
+ /** Function to update the auto-selected payment method */
6
+ setCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
7
+ /** User explicitly selected payment method (NONE means no explicit selection) */
8
+ selectedCryptoPaymentMethod: CryptoPaymentMethodType;
9
+ /** Function to update the user-selected payment method */
10
+ setSelectedCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
11
+ /** Effective payment method (user selection takes priority over auto-selection) */
12
+ effectiveCryptoPaymentMethod: CryptoPaymentMethodType;
13
+ /** Reset both payment method states to NONE */
14
+ resetPaymentMethods: () => void;
15
+ }
16
+ /**
17
+ * Custom hook to manage crypto payment method state with dual-state system:
18
+ *
19
+ * - `cryptoPaymentMethod`: Auto-selected based on wallet availability and balance
20
+ * - `selectedCryptoPaymentMethod`: Explicitly selected by user
21
+ * - `effectiveCryptoPaymentMethod`: User selection takes priority over auto-selection
22
+ *
23
+ * This allows automatic payment method suggestions while respecting explicit user choices.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * const {
28
+ * cryptoPaymentMethod,
29
+ * setCryptoPaymentMethod,
30
+ * selectedCryptoPaymentMethod,
31
+ * setSelectedCryptoPaymentMethod,
32
+ * effectiveCryptoPaymentMethod,
33
+ * resetPaymentMethods
34
+ * } = useCryptoPaymentMethodState();
35
+ *
36
+ * // Use effectiveCryptoPaymentMethod for display
37
+ * // Use setSelectedCryptoPaymentMethod when user explicitly selects
38
+ * // Call resetPaymentMethods when switching tabs or going back
39
+ * ```
40
+ */
41
+ export declare function useCryptoPaymentMethodState(): UseCryptoPaymentMethodStateResult;
42
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.65-alpha.0",
3
+ "version": "0.0.65-alpha.1",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -33,6 +33,7 @@ import { base, mainnet } from "viem/chains";
33
33
  import { components } from "../../types/api";
34
34
  import { useAutoSelectCryptoPaymentMethod } from "../hooks/useAutoSelectCryptoPaymentMethod";
35
35
  import { useAutoSetActiveWalletFromWagmi } from "../hooks/useAutoSetActiveWalletFromWagmi";
36
+ import { useCryptoPaymentMethodState } from "../hooks/useCryptoPaymentMethodState";
36
37
  import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper";
37
38
  import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod";
38
39
  import { CryptoPaySection } from "./common/CryptoPaySection";
@@ -174,11 +175,17 @@ function AnySpendInner({
174
175
  setActivePanel(targetPanel);
175
176
  }, [activePanel]);
176
177
  const [customRecipients, setCustomRecipients] = useState<RecipientOption[]>([]);
177
- // Add state for selected payment method
178
- const [selectedCryptoPaymentMethod, setSelectedCryptoPaymentMethod] = useState<CryptoPaymentMethodType>(
179
- CryptoPaymentMethodType.NONE,
180
- );
181
- // Add state for selected fiat payment method
178
+
179
+ // Payment method state with dual-state system (auto + explicit user selection)
180
+ const {
181
+ cryptoPaymentMethod,
182
+ setCryptoPaymentMethod,
183
+ selectedCryptoPaymentMethod,
184
+ setSelectedCryptoPaymentMethod,
185
+ effectiveCryptoPaymentMethod,
186
+ resetPaymentMethods,
187
+ } = useCryptoPaymentMethodState();
188
+
182
189
  const [selectedFiatPaymentMethod, setSelectedFiatPaymentMethod] = useState<FiatPaymentMethod>(FiatPaymentMethod.NONE);
183
190
  // const [newRecipientAddress, setNewRecipientAddress] = useState("");
184
191
  // const recipientInputRef = useRef<HTMLInputElement>(null);
@@ -467,8 +474,9 @@ function AnySpendInner({
467
474
  // Auto-select crypto payment method based on available wallets and balance
468
475
  useAutoSelectCryptoPaymentMethod({
469
476
  paymentType: activeTab,
477
+ cryptoPaymentMethod,
478
+ setCryptoPaymentMethod,
470
479
  selectedCryptoPaymentMethod,
471
- setSelectedCryptoPaymentMethod,
472
480
  hasEnoughBalance,
473
481
  isBalanceLoading,
474
482
  });
@@ -602,9 +610,9 @@ function AnySpendInner({
602
610
  // Add orderId and payment method to URL for persistence
603
611
  const params = new URLSearchParams(searchParams.toString()); // Preserve existing params
604
612
  params.set("orderId", orderId);
605
- if (selectedCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
606
- console.log("Setting cryptoPaymentMethod in URL:", selectedCryptoPaymentMethod);
607
- params.set("cryptoPaymentMethod", selectedCryptoPaymentMethod);
613
+ if (effectiveCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
614
+ console.log("Setting cryptoPaymentMethod in URL:", effectiveCryptoPaymentMethod);
615
+ params.set("cryptoPaymentMethod", effectiveCryptoPaymentMethod);
608
616
  } else {
609
617
  console.log("Payment method is NONE, not setting in URL");
610
618
  }
@@ -672,7 +680,7 @@ function AnySpendInner({
672
680
  // For crypto: check payment method first, then recipient
673
681
 
674
682
  // If no payment method selected, show "Choose payment method"
675
- if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
683
+ if (effectiveCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
676
684
  return { text: "Choose payment method", disable: false, error: false, loading: false };
677
685
  }
678
686
 
@@ -681,12 +689,12 @@ function AnySpendInner({
681
689
 
682
690
  // If payment method selected, show appropriate action
683
691
  if (
684
- selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ||
685
- selectedCryptoPaymentMethod === CryptoPaymentMethodType.GLOBAL_WALLET
692
+ effectiveCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ||
693
+ effectiveCryptoPaymentMethod === CryptoPaymentMethodType.GLOBAL_WALLET
686
694
  ) {
687
695
  return { text: "Swap", disable: false, error: false, loading: false };
688
696
  }
689
- if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.TRANSFER_CRYPTO) {
697
+ if (effectiveCryptoPaymentMethod === CryptoPaymentMethodType.TRANSFER_CRYPTO) {
690
698
  return { text: "Continue to payment", disable: false, error: false, loading: false };
691
699
  }
692
700
  }
@@ -701,7 +709,7 @@ function AnySpendInner({
701
709
  isCreatingOnrampOrder,
702
710
  anyspendQuote,
703
711
  activeTab,
704
- selectedCryptoPaymentMethod,
712
+ effectiveCryptoPaymentMethod,
705
713
  selectedFiatPaymentMethod,
706
714
  ]);
707
715
 
@@ -735,7 +743,7 @@ function AnySpendInner({
735
743
  // For crypto: check payment method first, then recipient
736
744
 
737
745
  // If no payment method selected, show payment method selection
738
- if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
746
+ if (effectiveCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
739
747
  console.log("No payment method selected, showing selection panel");
740
748
  navigateToPanel(PanelView.CRYPTO_PAYMENT_METHOD, "forward");
741
749
  return;
@@ -751,12 +759,12 @@ function AnySpendInner({
751
759
 
752
760
  // If payment method is selected, create order with payment method info
753
761
  if (
754
- selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ||
755
- selectedCryptoPaymentMethod === CryptoPaymentMethodType.GLOBAL_WALLET ||
756
- selectedCryptoPaymentMethod === CryptoPaymentMethodType.TRANSFER_CRYPTO
762
+ effectiveCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ||
763
+ effectiveCryptoPaymentMethod === CryptoPaymentMethodType.GLOBAL_WALLET ||
764
+ effectiveCryptoPaymentMethod === CryptoPaymentMethodType.TRANSFER_CRYPTO
757
765
  ) {
758
- console.log("Creating crypto order with payment method:", selectedCryptoPaymentMethod);
759
- await handleCryptoSwap(selectedCryptoPaymentMethod);
766
+ console.log("Creating crypto order with payment method:", effectiveCryptoPaymentMethod);
767
+ await handleCryptoSwap(effectiveCryptoPaymentMethod);
760
768
  return;
761
769
  }
762
770
  }
@@ -962,13 +970,17 @@ function AnySpendInner({
962
970
  relayTxs={oat.data.relayTxs}
963
971
  executeTx={oat.data.executeTx}
964
972
  refundTxs={oat.data.refundTxs}
965
- selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
966
- onPaymentMethodChange={setSelectedCryptoPaymentMethod}
973
+ selectedCryptoPaymentMethod={effectiveCryptoPaymentMethod}
974
+ onPaymentMethodChange={method => {
975
+ // When user explicitly changes payment method, set it as selected
976
+ setSelectedCryptoPaymentMethod(method);
977
+ }}
967
978
  points={oat.data.points || undefined}
968
979
  onBack={() => {
969
980
  setOrderId(undefined);
970
981
  navigateBack();
971
- setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.NONE); // Reset payment method when going back
982
+ // Reset payment methods when going back
983
+ resetPaymentMethods();
972
984
  }}
973
985
  />
974
986
  )}
@@ -1000,7 +1012,12 @@ function AnySpendInner({
1000
1012
  {/* Tab section */}
1001
1013
  <TabSection
1002
1014
  activeTab={activeTab}
1003
- setActiveTab={setActiveTab}
1015
+ setActiveTab={tab => {
1016
+ setActiveTab(tab);
1017
+ // Reset payment methods when switching tabs
1018
+ resetPaymentMethods();
1019
+ setSelectedFiatPaymentMethod(FiatPaymentMethod.NONE);
1020
+ }}
1004
1021
  setSelectedCryptoPaymentMethod={setSelectedCryptoPaymentMethod}
1005
1022
  setSelectedFiatPaymentMethod={setSelectedFiatPaymentMethod}
1006
1023
  />
@@ -1017,7 +1034,7 @@ function AnySpendInner({
1017
1034
  setSrcAmount={setSrcAmount}
1018
1035
  isSrcInputDirty={isSrcInputDirty}
1019
1036
  setIsSrcInputDirty={setIsSrcInputDirty}
1020
- selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
1037
+ selectedCryptoPaymentMethod={effectiveCryptoPaymentMethod}
1021
1038
  onSelectCryptoPaymentMethod={() => navigateToPanel(PanelView.CRYPTO_PAYMENT_METHOD, "forward")}
1022
1039
  anyspendQuote={anyspendQuote}
1023
1040
  onTokenSelect={onTokenSelect}
@@ -1120,7 +1137,7 @@ function AnySpendInner({
1120
1137
  anyspendQuote={anyspendQuote}
1121
1138
  onShowPointsDetail={() => navigateToPanel(PanelView.POINTS_DETAIL, "forward")}
1122
1139
  onShowFeeDetail={() => navigateToPanel(PanelView.FEE_DETAIL, "forward")}
1123
- selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
1140
+ selectedCryptoPaymentMethod={effectiveCryptoPaymentMethod}
1124
1141
  />
1125
1142
  )}
1126
1143
  </div>
@@ -1209,11 +1226,15 @@ function AnySpendInner({
1209
1226
  <CryptoPaymentMethod
1210
1227
  globalAddress={globalAddress}
1211
1228
  globalWallet={globalWallet}
1212
- selectedPaymentMethod={selectedCryptoPaymentMethod}
1213
- setSelectedPaymentMethod={setSelectedCryptoPaymentMethod}
1229
+ selectedPaymentMethod={effectiveCryptoPaymentMethod}
1230
+ setSelectedPaymentMethod={method => {
1231
+ // When user explicitly selects a payment method, save it
1232
+ setSelectedCryptoPaymentMethod(method);
1233
+ }}
1214
1234
  isCreatingOrder={isCreatingOrder}
1215
1235
  onBack={navigateBack}
1216
1236
  onSelectPaymentMethod={(method: CryptoPaymentMethodType) => {
1237
+ // When user explicitly selects a payment method, save it and go back
1217
1238
  setSelectedCryptoPaymentMethod(method);
1218
1239
  navigateBack();
1219
1240
  }}
@@ -45,6 +45,7 @@ import { toast } from "sonner";
45
45
  import { base } from "viem/chains";
46
46
  import { useFeatureFlags } from "../contexts/FeatureFlagsContext";
47
47
  import { useAutoSetActiveWalletFromWagmi } from "../hooks/useAutoSetActiveWalletFromWagmi";
48
+ import { useCryptoPaymentMethodState } from "../hooks/useCryptoPaymentMethodState";
48
49
  import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper";
49
50
  import { CryptoPaymentMethod, CryptoPaymentMethodType } from "./common/CryptoPaymentMethod";
50
51
  import { FeeBreakDown } from "./common/FeeBreakDown";
@@ -250,10 +251,11 @@ function AnySpendCustomInner({
250
251
  );
251
252
  const [activeTab, setActiveTab] = useState<"crypto" | "fiat">(activeTabProps);
252
253
 
253
- // Add state for selected payment methods
254
- const [selectedCryptoPaymentMethod, setSelectedCryptoPaymentMethod] = useState<CryptoPaymentMethodType>(
255
- CryptoPaymentMethodType.NONE,
256
- );
254
+ // Payment method state with dual-state system (auto + explicit user selection)
255
+ // Note: AnySpendCustom doesn't use auto-selection, only explicit user selection
256
+ const { setSelectedCryptoPaymentMethod, effectiveCryptoPaymentMethod, resetPaymentMethods } =
257
+ useCryptoPaymentMethodState();
258
+
257
259
  const [selectedFiatPaymentMethod, setSelectedFiatPaymentMethod] = useState<FiatPaymentMethod>(FiatPaymentMethod.NONE);
258
260
 
259
261
  // Get current user's wallet
@@ -550,7 +552,7 @@ function AnySpendCustomInner({
550
552
  }
551
553
 
552
554
  // Check payment method selection for crypto tab
553
- if (activeTab === "crypto" && selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
555
+ if (activeTab === "crypto" && effectiveCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
554
556
  setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD);
555
557
  return;
556
558
  }
@@ -693,12 +695,17 @@ function AnySpendCustomInner({
693
695
  relayTxs={oat.data.relayTxs}
694
696
  executeTx={oat.data.executeTx}
695
697
  refundTxs={oat.data.refundTxs}
696
- cryptoPaymentMethod={activeTab === "fiat" ? CryptoPaymentMethodType.NONE : selectedCryptoPaymentMethod}
697
- selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
698
- onPaymentMethodChange={setSelectedCryptoPaymentMethod}
698
+ cryptoPaymentMethod={activeTab === "fiat" ? CryptoPaymentMethodType.NONE : effectiveCryptoPaymentMethod}
699
+ selectedCryptoPaymentMethod={effectiveCryptoPaymentMethod}
700
+ onPaymentMethodChange={method => {
701
+ // When user explicitly changes payment method, set it as selected
702
+ setSelectedCryptoPaymentMethod(method);
703
+ }}
699
704
  onBack={() => {
700
705
  setOrderId(undefined);
701
706
  setActivePanel(PanelView.CONFIRM_ORDER);
707
+ // Reset payment methods when going back
708
+ resetPaymentMethods();
702
709
  // Remove orderId from URL when canceling
703
710
  const params = new URLSearchParams(searchParams.toString());
704
711
  params.delete("orderId");
@@ -832,7 +839,8 @@ function AnySpendCustomInner({
832
839
  )}
833
840
  onClick={() => {
834
841
  setActiveTab("crypto");
835
- setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.NONE);
842
+ // Reset payment methods when switching tabs
843
+ resetPaymentMethods();
836
844
  setSelectedFiatPaymentMethod(FiatPaymentMethod.NONE);
837
845
  }}
838
846
  >
@@ -846,7 +854,8 @@ function AnySpendCustomInner({
846
854
  )}
847
855
  onClick={() => {
848
856
  setActiveTab("fiat");
849
- setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.NONE);
857
+ // Reset payment methods when switching tabs
858
+ resetPaymentMethods();
850
859
  setSelectedFiatPaymentMethod(FiatPaymentMethod.NONE);
851
860
  }}
852
861
  >
@@ -902,7 +911,7 @@ function AnySpendCustomInner({
902
911
  className="text-as-tertiarry flex h-7 items-center gap-2 text-sm transition-colors hover:text-blue-700"
903
912
  onClick={() => setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD)}
904
913
  >
905
- {selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ? (
914
+ {effectiveCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET ? (
906
915
  <>
907
916
  {connectedAddress ? (
908
917
  <>
@@ -915,7 +924,7 @@ function AnySpendCustomInner({
915
924
  )}
916
925
  <ChevronRight className="h-4 w-4" />
917
926
  </>
918
- ) : selectedCryptoPaymentMethod === CryptoPaymentMethodType.TRANSFER_CRYPTO ? (
927
+ ) : effectiveCryptoPaymentMethod === CryptoPaymentMethodType.TRANSFER_CRYPTO ? (
919
928
  <>
920
929
  Transfer crypto
921
930
  <ChevronRight className="h-4 w-4" />
@@ -1043,7 +1052,7 @@ function AnySpendCustomInner({
1043
1052
  </div>
1044
1053
  ) : !recipientAddress ? (
1045
1054
  "Select recipient"
1046
- ) : selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE ? (
1055
+ ) : effectiveCryptoPaymentMethod === CryptoPaymentMethodType.NONE ? (
1047
1056
  "Choose payment method"
1048
1057
  ) : anyspendQuote ? (
1049
1058
  <>
@@ -1239,11 +1248,15 @@ function AnySpendCustomInner({
1239
1248
  <CryptoPaymentMethod
1240
1249
  globalAddress={currentWallet?.wallet?.address}
1241
1250
  globalWallet={currentWallet?.wallet}
1242
- selectedPaymentMethod={selectedCryptoPaymentMethod}
1243
- setSelectedPaymentMethod={setSelectedCryptoPaymentMethod}
1251
+ selectedPaymentMethod={effectiveCryptoPaymentMethod}
1252
+ setSelectedPaymentMethod={method => {
1253
+ // When user explicitly selects a payment method, save it
1254
+ setSelectedCryptoPaymentMethod(method);
1255
+ }}
1244
1256
  isCreatingOrder={isCreatingOrder}
1245
1257
  onBack={() => setActivePanel(PanelView.CONFIRM_ORDER)}
1246
1258
  onSelectPaymentMethod={(method: CryptoPaymentMethodType) => {
1259
+ // When user explicitly selects a payment method, save it and go back
1247
1260
  setSelectedCryptoPaymentMethod(method);
1248
1261
  setActivePanel(PanelView.CONFIRM_ORDER);
1249
1262
  }}
@@ -108,6 +108,7 @@ function AnySpendCustomExactInInner({
108
108
  isSrcInputDirty,
109
109
  setIsSrcInputDirty,
110
110
  selectedCryptoPaymentMethod,
111
+ effectiveCryptoPaymentMethod,
111
112
  setSelectedCryptoPaymentMethod,
112
113
  selectedFiatPaymentMethod,
113
114
  setSelectedFiatPaymentMethod,
@@ -184,13 +185,13 @@ function AnySpendCustomExactInInner({
184
185
  return { text: "Get quote error", disable: true, error: true, loading: false };
185
186
 
186
187
  if (paymentType === "crypto") {
187
- if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
188
+ if (effectiveCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
188
189
  return { text: "Choose payment method", disable: false, error: false, loading: false };
189
190
  }
190
191
  if (
191
192
  !hasEnoughBalance &&
192
193
  !isBalanceLoading &&
193
- selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET
194
+ effectiveCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET
194
195
  ) {
195
196
  return { text: "Insufficient balance", disable: true, error: true, loading: false };
196
197
  }
@@ -213,7 +214,7 @@ function AnySpendCustomExactInInner({
213
214
  selectedRecipientOrDefault,
214
215
  anyspendQuote,
215
216
  paymentType,
216
- selectedCryptoPaymentMethod,
217
+ effectiveCryptoPaymentMethod,
217
218
  selectedFiatPaymentMethod,
218
219
  hasEnoughBalance,
219
220
  isBalanceLoading,
@@ -270,7 +271,7 @@ function AnySpendCustomExactInInner({
270
271
  setSrcAmount={setSrcAmount}
271
272
  isSrcInputDirty={isSrcInputDirty}
272
273
  setIsSrcInputDirty={setIsSrcInputDirty}
273
- selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
274
+ selectedCryptoPaymentMethod={effectiveCryptoPaymentMethod}
274
275
  onSelectCryptoPaymentMethod={() => setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD)}
275
276
  anyspendQuote={anyspendQuote}
276
277
  onTokenSelect={onTokenSelect}
@@ -465,8 +466,8 @@ function AnySpendCustomExactInInner({
465
466
  relayTxs={oat.data.relayTxs}
466
467
  executeTx={oat.data.executeTx}
467
468
  refundTxs={oat.data.refundTxs}
468
- cryptoPaymentMethod={paymentType === "fiat" ? CryptoPaymentMethodType.NONE : selectedCryptoPaymentMethod}
469
- selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
469
+ cryptoPaymentMethod={paymentType === "fiat" ? CryptoPaymentMethodType.NONE : effectiveCryptoPaymentMethod}
470
+ selectedCryptoPaymentMethod={effectiveCryptoPaymentMethod}
470
471
  onPaymentMethodChange={setSelectedCryptoPaymentMethod}
471
472
  onBack={() => {
472
473
  setOrderId(undefined);
@@ -19,12 +19,13 @@ import { useEffect, useMemo, useState } from "react";
19
19
  import { toast } from "sonner";
20
20
  import { parseUnits } from "viem";
21
21
  import { base, mainnet } from "viem/chains";
22
- import { useAccount } from "wagmi";
23
22
  import { components } from "../../types/api";
24
23
  import { CryptoPaymentMethodType } from "../components/common/CryptoPaymentMethod";
25
24
  import { FiatPaymentMethod } from "../components/common/FiatPaymentMethod";
26
25
  import { useAutoSelectCryptoPaymentMethod } from "./useAutoSelectCryptoPaymentMethod";
27
26
  import { useAutoSetActiveWalletFromWagmi } from "./useAutoSetActiveWalletFromWagmi";
27
+ import { useConnectedWalletDisplay } from "./useConnectedWalletDisplay";
28
+ import { useCryptoPaymentMethodState } from "./useCryptoPaymentMethodState";
28
29
 
29
30
  export enum PanelView {
30
31
  MAIN,
@@ -92,15 +93,21 @@ export function useAnyspendFlow({
92
93
  // Derive destination chain ID from token or prop (cannot change)
93
94
  const selectedDstChainId = destinationTokenChainId || selectedDstToken.chainId;
94
95
 
95
- // Payment method state
96
- const [selectedCryptoPaymentMethod, setSelectedCryptoPaymentMethod] = useState<CryptoPaymentMethodType>(
97
- CryptoPaymentMethodType.NONE,
98
- );
96
+ // Payment method state with dual-state system (auto + explicit user selection)
97
+ const {
98
+ cryptoPaymentMethod,
99
+ setCryptoPaymentMethod,
100
+ selectedCryptoPaymentMethod,
101
+ setSelectedCryptoPaymentMethod,
102
+ effectiveCryptoPaymentMethod,
103
+ resetPaymentMethods,
104
+ } = useCryptoPaymentMethodState();
105
+
99
106
  const [selectedFiatPaymentMethod, setSelectedFiatPaymentMethod] = useState<FiatPaymentMethod>(FiatPaymentMethod.NONE);
100
107
 
101
108
  // Recipient state
102
109
  const { address: globalAddress } = useAccountWallet();
103
- const { address: wagmiAddress } = useAccount();
110
+ const { walletAddress } = useConnectedWalletDisplay(effectiveCryptoPaymentMethod);
104
111
  const [selectedRecipientAddress, setSelectedRecipientAddress] = useState<string | undefined>(recipientAddress);
105
112
  const recipientProfile = useProfile({ address: selectedRecipientAddress, fresh: true });
106
113
  const recipientName = recipientProfile.data?.name;
@@ -118,7 +125,7 @@ export function useAnyspendFlow({
118
125
  // Check token balance for crypto payments
119
126
  const { rawBalance, isLoading: isBalanceLoading } = useTokenBalance({
120
127
  token: selectedSrcToken,
121
- address: wagmiAddress,
128
+ address: walletAddress,
122
129
  });
123
130
 
124
131
  // Check if user has enough balance
@@ -135,8 +142,9 @@ export function useAnyspendFlow({
135
142
  // Auto-select crypto payment method based on available wallets and balance
136
143
  useAutoSelectCryptoPaymentMethod({
137
144
  paymentType,
145
+ cryptoPaymentMethod,
146
+ setCryptoPaymentMethod,
138
147
  selectedCryptoPaymentMethod,
139
- setSelectedCryptoPaymentMethod,
140
148
  hasEnoughBalance,
141
149
  isBalanceLoading,
142
150
  });
@@ -248,9 +256,9 @@ export function useAnyspendFlow({
248
256
  if (!disableUrlParamManagement) {
249
257
  const params = new URLSearchParams(searchParams.toString()); // Preserve existing params
250
258
  params.set("orderId", newOrderId);
251
- if (selectedCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
252
- console.log("Setting cryptoPaymentMethod in URL:", selectedCryptoPaymentMethod);
253
- params.set("cryptoPaymentMethod", selectedCryptoPaymentMethod);
259
+ if (effectiveCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
260
+ console.log("Setting cryptoPaymentMethod in URL:", effectiveCryptoPaymentMethod);
261
+ params.set("cryptoPaymentMethod", effectiveCryptoPaymentMethod);
254
262
  } else {
255
263
  console.log("Payment method is NONE, not setting in URL");
256
264
  }
@@ -316,8 +324,12 @@ export function useAnyspendFlow({
316
324
  isSrcInputDirty,
317
325
  setIsSrcInputDirty,
318
326
  // Payment methods
327
+ cryptoPaymentMethod,
328
+ setCryptoPaymentMethod,
319
329
  selectedCryptoPaymentMethod,
320
330
  setSelectedCryptoPaymentMethod,
331
+ effectiveCryptoPaymentMethod,
332
+ resetPaymentMethods,
321
333
  selectedFiatPaymentMethod,
322
334
  setSelectedFiatPaymentMethod,
323
335
  // Recipient