@b3dotfun/sdk 0.0.64 → 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 (58) 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 +7 -11
  4. package/dist/cjs/anyspend/react/components/AnyspendDepositHype.js +1 -5
  5. package/dist/cjs/anyspend/react/components/common/CryptoPaymentMethod.js +0 -4
  6. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.d.ts +5 -1
  7. package/dist/cjs/anyspend/react/hooks/useAnyspendFlow.js +15 -9
  8. package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +7 -5
  9. package/dist/cjs/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +13 -9
  10. package/dist/cjs/anyspend/react/hooks/useCryptoPaymentMethodState.d.ts +42 -0
  11. package/dist/cjs/anyspend/react/hooks/useCryptoPaymentMethodState.js +51 -0
  12. package/dist/cjs/anyspend/utils/index.d.ts +0 -1
  13. package/dist/cjs/anyspend/utils/index.js +0 -1
  14. package/dist/cjs/global-account/react/components/B3DynamicModal.js +4 -7
  15. package/dist/cjs/global-account/react/hooks/useAuthentication.js +0 -11
  16. package/dist/cjs/global-account/react/hooks/useGlobalAccount.d.ts +1 -0
  17. package/dist/cjs/global-account/react/hooks/useGlobalAccount.js +3 -0
  18. package/dist/esm/anyspend/react/components/AnySpend.js +37 -23
  19. package/dist/esm/anyspend/react/components/AnySpendCustom.js +22 -9
  20. package/dist/esm/anyspend/react/components/AnySpendCustomExactIn.js +8 -12
  21. package/dist/esm/anyspend/react/components/AnyspendDepositHype.js +2 -6
  22. package/dist/esm/anyspend/react/components/common/CryptoPaymentMethod.js +1 -5
  23. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.d.ts +5 -1
  24. package/dist/esm/anyspend/react/hooks/useAnyspendFlow.js +15 -9
  25. package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +7 -5
  26. package/dist/esm/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.js +13 -9
  27. package/dist/esm/anyspend/react/hooks/useCryptoPaymentMethodState.d.ts +42 -0
  28. package/dist/esm/anyspend/react/hooks/useCryptoPaymentMethodState.js +48 -0
  29. package/dist/esm/anyspend/utils/index.d.ts +0 -1
  30. package/dist/esm/anyspend/utils/index.js +0 -1
  31. package/dist/esm/global-account/react/components/B3DynamicModal.js +5 -8
  32. package/dist/esm/global-account/react/hooks/useAuthentication.js +0 -11
  33. package/dist/esm/global-account/react/hooks/useGlobalAccount.d.ts +1 -0
  34. package/dist/esm/global-account/react/hooks/useGlobalAccount.js +3 -0
  35. package/dist/types/anyspend/react/hooks/useAnyspendFlow.d.ts +5 -1
  36. package/dist/types/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.d.ts +7 -5
  37. package/dist/types/anyspend/react/hooks/useCryptoPaymentMethodState.d.ts +42 -0
  38. package/dist/types/anyspend/utils/index.d.ts +0 -1
  39. package/dist/types/global-account/react/hooks/useGlobalAccount.d.ts +1 -0
  40. package/package.json +1 -1
  41. package/src/anyspend/react/components/AnySpend.tsx +49 -28
  42. package/src/anyspend/react/components/AnySpendCustom.tsx +28 -15
  43. package/src/anyspend/react/components/AnySpendCustomExactIn.tsx +9 -12
  44. package/src/anyspend/react/components/AnyspendDepositHype.tsx +2 -6
  45. package/src/anyspend/react/components/common/CryptoPaymentMethod.tsx +1 -6
  46. package/src/anyspend/react/hooks/useAnyspendFlow.ts +23 -11
  47. package/src/anyspend/react/hooks/useAutoSelectCryptoPaymentMethod.ts +20 -12
  48. package/src/anyspend/react/hooks/useCryptoPaymentMethodState.ts +71 -0
  49. package/src/anyspend/utils/index.ts +0 -1
  50. package/src/global-account/react/components/B3DynamicModal.tsx +5 -9
  51. package/src/global-account/react/hooks/useAuthentication.ts +0 -12
  52. package/src/global-account/react/hooks/useGlobalAccount.tsx +3 -1
  53. package/dist/cjs/anyspend/utils/accountStore.d.ts +0 -7
  54. package/dist/cjs/anyspend/utils/accountStore.js +0 -8
  55. package/dist/esm/anyspend/utils/accountStore.d.ts +0 -7
  56. package/dist/esm/anyspend/utils/accountStore.js +0 -5
  57. package/dist/types/anyspend/utils/accountStore.d.ts +0 -7
  58. package/src/anyspend/utils/accountStore.ts +0 -12
@@ -1,4 +1,3 @@
1
- export * from "./accountStore";
2
1
  export * from "./address";
3
2
  export * from "./chain";
4
3
  export * from "./format";
@@ -3,4 +3,5 @@ export declare function useGlobalAccount(): {
3
3
  account: Wallet | undefined;
4
4
  address: string | undefined;
5
5
  info: import("@tanstack/react-query").UseQueryResult<import("thirdweb/wallets").WalletInfo, Error>;
6
+ wallet: Wallet | undefined;
6
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.64",
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
  }}
@@ -8,8 +8,7 @@ import { ArrowDown, Loader2 } from "lucide-react";
8
8
  import { motion } from "motion/react";
9
9
  import { useEffect, useMemo, useRef } from "react";
10
10
  import { toast } from "sonner";
11
- import { useActiveWallet, useSetActiveWallet } from "thirdweb/react";
12
- import { useGlobalWalletState } from "../../utils";
11
+ import { useSetActiveWallet } from "thirdweb/react";
13
12
  import { PanelView, useAnyspendFlow } from "../hooks/useAnyspendFlow";
14
13
  import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper";
15
14
  import { CryptoPaySection } from "./common/CryptoPaySection";
@@ -109,6 +108,7 @@ function AnySpendCustomExactInInner({
109
108
  isSrcInputDirty,
110
109
  setIsSrcInputDirty,
111
110
  selectedCryptoPaymentMethod,
111
+ effectiveCryptoPaymentMethod,
112
112
  setSelectedCryptoPaymentMethod,
113
113
  selectedFiatPaymentMethod,
114
114
  setSelectedFiatPaymentMethod,
@@ -145,19 +145,16 @@ function AnySpendCustomExactInInner({
145
145
 
146
146
  const { connectedEOAWallet } = useAccountWallet();
147
147
  const setActiveWallet = useSetActiveWallet();
148
- const activeWallet = useActiveWallet();
149
- const setGlobalAccountWallet = useGlobalWalletState(state => state.setGlobalAccountWallet);
150
148
  const appliedPreferEoa = useRef(false);
151
149
 
152
150
  useEffect(() => {
153
151
  if (preferEoa && !appliedPreferEoa.current) {
154
152
  if (connectedEOAWallet) {
155
153
  appliedPreferEoa.current = true;
156
- setGlobalAccountWallet(activeWallet);
157
154
  setActiveWallet(connectedEOAWallet);
158
155
  }
159
156
  }
160
- }, [preferEoa, connectedEOAWallet, setActiveWallet, activeWallet, setGlobalAccountWallet]);
157
+ }, [preferEoa, connectedEOAWallet, setActiveWallet]);
161
158
 
162
159
  const selectedRecipientOrDefault = selectedRecipientAddress ?? recipientAddress;
163
160
 
@@ -188,13 +185,13 @@ function AnySpendCustomExactInInner({
188
185
  return { text: "Get quote error", disable: true, error: true, loading: false };
189
186
 
190
187
  if (paymentType === "crypto") {
191
- if (selectedCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
188
+ if (effectiveCryptoPaymentMethod === CryptoPaymentMethodType.NONE) {
192
189
  return { text: "Choose payment method", disable: false, error: false, loading: false };
193
190
  }
194
191
  if (
195
192
  !hasEnoughBalance &&
196
193
  !isBalanceLoading &&
197
- selectedCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET
194
+ effectiveCryptoPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET
198
195
  ) {
199
196
  return { text: "Insufficient balance", disable: true, error: true, loading: false };
200
197
  }
@@ -217,7 +214,7 @@ function AnySpendCustomExactInInner({
217
214
  selectedRecipientOrDefault,
218
215
  anyspendQuote,
219
216
  paymentType,
220
- selectedCryptoPaymentMethod,
217
+ effectiveCryptoPaymentMethod,
221
218
  selectedFiatPaymentMethod,
222
219
  hasEnoughBalance,
223
220
  isBalanceLoading,
@@ -274,7 +271,7 @@ function AnySpendCustomExactInInner({
274
271
  setSrcAmount={setSrcAmount}
275
272
  isSrcInputDirty={isSrcInputDirty}
276
273
  setIsSrcInputDirty={setIsSrcInputDirty}
277
- selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
274
+ selectedCryptoPaymentMethod={effectiveCryptoPaymentMethod}
278
275
  onSelectCryptoPaymentMethod={() => setActivePanel(PanelView.CRYPTO_PAYMENT_METHOD)}
279
276
  anyspendQuote={anyspendQuote}
280
277
  onTokenSelect={onTokenSelect}
@@ -469,8 +466,8 @@ function AnySpendCustomExactInInner({
469
466
  relayTxs={oat.data.relayTxs}
470
467
  executeTx={oat.data.executeTx}
471
468
  refundTxs={oat.data.refundTxs}
472
- cryptoPaymentMethod={paymentType === "fiat" ? CryptoPaymentMethodType.NONE : selectedCryptoPaymentMethod}
473
- selectedCryptoPaymentMethod={selectedCryptoPaymentMethod}
469
+ cryptoPaymentMethod={paymentType === "fiat" ? CryptoPaymentMethodType.NONE : effectiveCryptoPaymentMethod}
470
+ selectedCryptoPaymentMethod={effectiveCryptoPaymentMethod}
474
471
  onPaymentMethodChange={setSelectedCryptoPaymentMethod}
475
472
  onBack={() => {
476
473
  setOrderId(undefined);
@@ -6,7 +6,7 @@ import invariant from "invariant";
6
6
  import { motion } from "motion/react";
7
7
  import { useEffect, useMemo, useRef } from "react";
8
8
  import { toast } from "sonner";
9
- import { useActiveWallet, useSetActiveWallet } from "thirdweb/react";
9
+ import { useSetActiveWallet } from "thirdweb/react";
10
10
  import { base } from "viem/chains";
11
11
  import { PanelView, useAnyspendFlow } from "../hooks/useAnyspendFlow";
12
12
  import { AnySpendFingerprintWrapper, getFingerprintConfig } from "./AnySpendFingerprintWrapper";
@@ -20,7 +20,6 @@ import { PointsDetailPanel } from "./common/PointsDetailPanel";
20
20
  import { RecipientSelection } from "./common/RecipientSelection";
21
21
 
22
22
  import { ArrowDown, Loader2 } from "lucide-react";
23
- import { useGlobalWalletState } from "../../utils";
24
23
  import { PanelOnramp } from "./common/PanelOnramp";
25
24
 
26
25
  const SLIPPAGE_PERCENT = 3;
@@ -119,19 +118,16 @@ function AnySpendDepositHypeInner({
119
118
 
120
119
  const { connectedEOAWallet: connectedEOAWallet } = useAccountWallet();
121
120
  const setActiveWallet = useSetActiveWallet();
122
- const activeWallet = useActiveWallet();
123
- const setGlobalAccountWallet = useGlobalWalletState(state => state.setGlobalAccountWallet);
124
121
  const appliedPreferEoa = useRef(false);
125
122
 
126
123
  useEffect(() => {
127
124
  if (preferEoa && !appliedPreferEoa.current) {
128
125
  if (connectedEOAWallet) {
129
126
  appliedPreferEoa.current = true;
130
- setGlobalAccountWallet(activeWallet);
131
127
  setActiveWallet(connectedEOAWallet);
132
128
  }
133
129
  }
134
- }, [preferEoa, connectedEOAWallet, setActiveWallet, activeWallet, setGlobalAccountWallet]);
130
+ }, [preferEoa, connectedEOAWallet, setActiveWallet]);
135
131
 
136
132
  // Button state logic
137
133
  const btnInfo: { text: string; disable: boolean; error: boolean; loading: boolean } = useMemo(() => {
@@ -1,6 +1,5 @@
1
1
  "use client";
2
2
 
3
- import { useGlobalWalletState } from "@b3dotfun/sdk/anyspend/utils";
4
3
  import { useAccountWallet } from "@b3dotfun/sdk/global-account/react";
5
4
  import { cn } from "@b3dotfun/sdk/shared/utils/cn";
6
5
  import { shortenAddress } from "@b3dotfun/sdk/shared/utils/formatAddress";
@@ -10,7 +9,7 @@ import { ChevronLeft, ChevronRightCircle, Wallet, X, ZapIcon } from "lucide-reac
10
9
  import { useState } from "react";
11
10
  import { createPortal } from "react-dom";
12
11
  import { toast } from "sonner";
13
- import { useActiveWallet, useSetActiveWallet, useWalletInfo } from "thirdweb/react";
12
+ import { useSetActiveWallet, useWalletInfo } from "thirdweb/react";
14
13
  import { WalletId, createWallet } from "thirdweb/wallets";
15
14
  import { useAccount, useConnect, useDisconnect, useWalletClient } from "wagmi";
16
15
  import { useConnectedWalletDisplay } from "../../hooks/useConnectedWalletDisplay";
@@ -56,9 +55,6 @@ export function CryptoPaymentMethod({
56
55
  const setActiveWallet = useSetActiveWallet();
57
56
  const { data: eoaWalletInfo } = useWalletInfo(connectedEOAWallet?.id);
58
57
 
59
- const activeWallet = useActiveWallet();
60
- const setGlobalAccountWallet = useGlobalWalletState(state => state.setGlobalAccountWallet);
61
-
62
58
  const isConnected = !!connectedEOAWallet;
63
59
  const globalAddress = connectedSmartWallet?.getAccount()?.address;
64
60
 
@@ -225,7 +221,6 @@ export function CryptoPaymentMethod({
225
221
  onClick={() => {
226
222
  setSelectedPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
227
223
  onSelectPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
228
- setGlobalAccountWallet(activeWallet);
229
224
  if (connectedEOAWallet) {
230
225
  setActiveWallet(connectedEOAWallet);
231
226
  }
@@ -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
@@ -5,10 +5,12 @@ import { useConnectedWalletDisplay } from "./useConnectedWalletDisplay";
5
5
  interface UseAutoSelectCryptoPaymentMethodParams {
6
6
  /** Current payment type (crypto or fiat) */
7
7
  paymentType?: "crypto" | "fiat";
8
- /** Currently selected payment method */
8
+ /** Auto-selected payment method based on balance (not used in hook logic, but part of state management) */
9
+ cryptoPaymentMethod: CryptoPaymentMethodType;
10
+ /** Function to update the auto-selected payment method */
11
+ setCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
12
+ /** User explicitly selected payment method (NONE means no explicit selection) */
9
13
  selectedCryptoPaymentMethod: CryptoPaymentMethodType;
10
- /** Function to update the selected payment method */
11
- setSelectedCryptoPaymentMethod: (method: CryptoPaymentMethodType) => void;
12
14
  /** Whether user has enough balance to pay */
13
15
  hasEnoughBalance: boolean;
14
16
  /** Whether balance is still loading */
@@ -20,7 +22,7 @@ interface UseAutoSelectCryptoPaymentMethodParams {
20
22
  * based on available wallets and balance.
21
23
  *
22
24
  * Auto-selection logic:
23
- * - Only auto-selects when payment method is NONE (doesn't override user choices)
25
+ * - Only auto-selects when selectedCryptoPaymentMethod is NONE (user hasn't explicitly chosen)
24
26
  * - If EOA/Wagmi wallet connected + has balance → CONNECT_WALLET
25
27
  * - If EOA/Wagmi wallet connected + insufficient balance → TRANSFER_CRYPTO
26
28
  * - If only Global wallet available → GLOBAL_WALLET
@@ -28,8 +30,9 @@ interface UseAutoSelectCryptoPaymentMethodParams {
28
30
  */
29
31
  export function useAutoSelectCryptoPaymentMethod({
30
32
  paymentType = "crypto",
33
+ cryptoPaymentMethod: _cryptoPaymentMethod,
34
+ setCryptoPaymentMethod,
31
35
  selectedCryptoPaymentMethod,
32
- setSelectedCryptoPaymentMethod,
33
36
  hasEnoughBalance,
34
37
  isBalanceLoading,
35
38
  }: UseAutoSelectCryptoPaymentMethodParams) {
@@ -37,8 +40,13 @@ export function useAutoSelectCryptoPaymentMethod({
37
40
  const { suggestedPaymentMethod } = useConnectedWalletDisplay(selectedCryptoPaymentMethod);
38
41
 
39
42
  useEffect(() => {
40
- // Only auto-select when on crypto payment type and payment method is NONE
41
- if (paymentType !== "crypto" || selectedCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
43
+ // Only auto-select when on crypto payment type
44
+ if (paymentType !== "crypto") {
45
+ return;
46
+ }
47
+
48
+ // Only auto-switch if user hasn't explicitly selected a payment method
49
+ if (selectedCryptoPaymentMethod !== CryptoPaymentMethodType.NONE) {
42
50
  return;
43
51
  }
44
52
 
@@ -48,25 +56,25 @@ export function useAutoSelectCryptoPaymentMethod({
48
56
  // Otherwise, default to TRANSFER_CRYPTO if balance is insufficient
49
57
  if (!isBalanceLoading) {
50
58
  if (hasEnoughBalance && suggestedPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET) {
51
- setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
59
+ setCryptoPaymentMethod(CryptoPaymentMethodType.CONNECT_WALLET);
52
60
  } else if (!hasEnoughBalance && suggestedPaymentMethod === CryptoPaymentMethodType.CONNECT_WALLET) {
53
61
  // Wallet connected but insufficient balance - suggest transfer
54
- setSelectedCryptoPaymentMethod(CryptoPaymentMethodType.TRANSFER_CRYPTO);
62
+ setCryptoPaymentMethod(CryptoPaymentMethodType.TRANSFER_CRYPTO);
55
63
  } else {
56
64
  // Use suggested method (e.g., GLOBAL_WALLET)
57
- setSelectedCryptoPaymentMethod(suggestedPaymentMethod);
65
+ setCryptoPaymentMethod(suggestedPaymentMethod);
58
66
  }
59
67
  } else {
60
68
  // Balance still loading, use suggested method
61
- setSelectedCryptoPaymentMethod(suggestedPaymentMethod);
69
+ setCryptoPaymentMethod(suggestedPaymentMethod);
62
70
  }
63
71
  }
64
72
  }, [
65
73
  paymentType,
74
+ setCryptoPaymentMethod,
66
75
  selectedCryptoPaymentMethod,
67
76
  suggestedPaymentMethod,
68
77
  hasEnoughBalance,
69
78
  isBalanceLoading,
70
- setSelectedCryptoPaymentMethod,
71
79
  ]);
72
80
  }