@b3dotfun/sdk 0.1.69-alpha.1 → 0.1.69-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 (125) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpendStakeB3.js +1 -1
  2. package/dist/cjs/anyspend/react/components/AnySpendStakeB3ExactIn.js +1 -1
  3. package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -4
  4. package/dist/cjs/anyspend/react/components/checkout/CheckoutSuccess.d.ts +2 -1
  5. package/dist/cjs/anyspend/react/components/checkout/CheckoutSuccess.js +5 -3
  6. package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.js +1 -2
  7. package/dist/cjs/anyspend/react/components/checkout/KycGate.js +1 -2
  8. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +5 -0
  9. package/dist/cjs/anyspend/react/components/common/OrderStatus.js +37 -6
  10. package/dist/cjs/anyspend/react/components/common/StepProgress.d.ts +2 -0
  11. package/dist/cjs/anyspend/react/components/common/StepProgress.js +7 -2
  12. package/dist/cjs/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +4 -6
  13. package/dist/cjs/anyspend/react/hooks/useKycStatus.d.ts +3 -1
  14. package/dist/cjs/anyspend/react/hooks/useKycStatus.js +11 -7
  15. package/dist/cjs/app.shared.js +9 -7
  16. package/dist/cjs/global-account/react/components/B3DynamicModal.js +5 -2
  17. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
  18. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +2 -2
  19. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.native.js +2 -1
  20. package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
  21. package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.js +3 -1
  22. package/dist/cjs/global-account/react/components/ManageAccount/SessionDurationContent.d.ts +5 -0
  23. package/dist/cjs/global-account/react/components/ManageAccount/SessionDurationContent.js +57 -0
  24. package/dist/cjs/global-account/react/components/ManageAccount/SettingsContent.js +12 -29
  25. package/dist/cjs/global-account/react/components/SignInWithB3/components/AuthButton.js +10 -1
  26. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepCustom.js +96 -15
  27. package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +5 -3
  28. package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.js +15 -2
  29. package/dist/cjs/global-account/react/components/Toast/ToastContext.d.ts +3 -0
  30. package/dist/cjs/global-account/react/components/Toast/ToastContext.js +30 -7
  31. package/dist/cjs/global-account/react/hooks/useAuth.js +26 -15
  32. package/dist/cjs/global-account/react/hooks/useAuthentication.js +23 -12
  33. package/dist/cjs/global-account/react/hooks/useConnect.d.ts +2 -2
  34. package/dist/cjs/global-account/react/hooks/useFirstEOA.d.ts +8 -8
  35. package/dist/cjs/global-account/react/hooks/useTWAuth.js +0 -1
  36. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +10 -1
  37. package/dist/cjs/global-account/react/utils/createWagmiConfig.d.ts +0 -18
  38. package/dist/cjs/global-account/react/utils/createWagmiConfig.js +0 -17
  39. package/dist/cjs/shared/utils/session-duration.d.ts +15 -0
  40. package/dist/cjs/shared/utils/session-duration.js +69 -0
  41. package/dist/esm/anyspend/react/components/AnySpendStakeB3.js +2 -2
  42. package/dist/esm/anyspend/react/components/AnySpendStakeB3ExactIn.js +2 -2
  43. package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -4
  44. package/dist/esm/anyspend/react/components/checkout/CheckoutSuccess.d.ts +2 -1
  45. package/dist/esm/anyspend/react/components/checkout/CheckoutSuccess.js +5 -3
  46. package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.js +2 -3
  47. package/dist/esm/anyspend/react/components/checkout/KycGate.js +2 -3
  48. package/dist/esm/anyspend/react/components/common/OrderDetails.js +6 -1
  49. package/dist/esm/anyspend/react/components/common/OrderStatus.js +34 -3
  50. package/dist/esm/anyspend/react/components/common/StepProgress.d.ts +2 -0
  51. package/dist/esm/anyspend/react/components/common/StepProgress.js +4 -2
  52. package/dist/esm/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +5 -7
  53. package/dist/esm/anyspend/react/hooks/useKycStatus.d.ts +3 -1
  54. package/dist/esm/anyspend/react/hooks/useKycStatus.js +9 -5
  55. package/dist/esm/app.shared.js +9 -7
  56. package/dist/esm/global-account/react/components/B3DynamicModal.js +5 -2
  57. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
  58. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +2 -2
  59. package/dist/esm/global-account/react/components/B3Provider/B3Provider.native.js +2 -1
  60. package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
  61. package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.js +3 -1
  62. package/dist/esm/global-account/react/components/ManageAccount/SessionDurationContent.d.ts +5 -0
  63. package/dist/esm/global-account/react/components/ManageAccount/SessionDurationContent.js +52 -0
  64. package/dist/esm/global-account/react/components/ManageAccount/SettingsContent.js +12 -29
  65. package/dist/esm/global-account/react/components/SignInWithB3/components/AuthButton.js +11 -2
  66. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepCustom.js +100 -19
  67. package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +5 -3
  68. package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.js +14 -1
  69. package/dist/esm/global-account/react/components/Toast/ToastContext.d.ts +3 -0
  70. package/dist/esm/global-account/react/components/Toast/ToastContext.js +30 -7
  71. package/dist/esm/global-account/react/hooks/useAuth.js +28 -17
  72. package/dist/esm/global-account/react/hooks/useAuthentication.js +24 -13
  73. package/dist/esm/global-account/react/hooks/useConnect.d.ts +2 -2
  74. package/dist/esm/global-account/react/hooks/useFirstEOA.d.ts +8 -8
  75. package/dist/esm/global-account/react/hooks/useTWAuth.js +0 -1
  76. package/dist/esm/global-account/react/stores/useModalStore.d.ts +10 -1
  77. package/dist/esm/global-account/react/utils/createWagmiConfig.d.ts +0 -18
  78. package/dist/esm/global-account/react/utils/createWagmiConfig.js +0 -16
  79. package/dist/esm/shared/utils/session-duration.d.ts +15 -0
  80. package/dist/esm/shared/utils/session-duration.js +64 -0
  81. package/dist/styles/index.css +1 -1
  82. package/dist/types/anyspend/react/components/checkout/CheckoutSuccess.d.ts +2 -1
  83. package/dist/types/anyspend/react/components/common/StepProgress.d.ts +2 -0
  84. package/dist/types/anyspend/react/hooks/useKycStatus.d.ts +3 -1
  85. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
  86. package/dist/types/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
  87. package/dist/types/global-account/react/components/ManageAccount/SessionDurationContent.d.ts +5 -0
  88. package/dist/types/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +5 -3
  89. package/dist/types/global-account/react/components/Toast/ToastContext.d.ts +3 -0
  90. package/dist/types/global-account/react/hooks/useConnect.d.ts +2 -2
  91. package/dist/types/global-account/react/hooks/useFirstEOA.d.ts +8 -8
  92. package/dist/types/global-account/react/stores/useModalStore.d.ts +10 -1
  93. package/dist/types/global-account/react/utils/createWagmiConfig.d.ts +0 -18
  94. package/dist/types/shared/utils/session-duration.d.ts +15 -0
  95. package/package.json +2 -1
  96. package/src/anyspend/react/components/AnySpendStakeB3.tsx +2 -2
  97. package/src/anyspend/react/components/AnySpendStakeB3ExactIn.tsx +2 -2
  98. package/src/anyspend/react/components/checkout/CheckoutPaymentPanel.tsx +2 -4
  99. package/src/anyspend/react/components/checkout/CheckoutSuccess.tsx +13 -3
  100. package/src/anyspend/react/components/checkout/FiatCheckoutPanel.tsx +9 -3
  101. package/src/anyspend/react/components/checkout/KycGate.tsx +8 -3
  102. package/src/anyspend/react/components/common/OrderDetails.tsx +8 -0
  103. package/src/anyspend/react/components/common/OrderStatus.tsx +38 -3
  104. package/src/anyspend/react/components/common/StepProgress.tsx +15 -5
  105. package/src/anyspend/react/hooks/useAnyspendCreateOnrampOrder.ts +5 -7
  106. package/src/anyspend/react/hooks/useKycStatus.ts +8 -5
  107. package/src/app.shared.ts +9 -8
  108. package/src/global-account/react/components/B3DynamicModal.tsx +5 -2
  109. package/src/global-account/react/components/B3Provider/B3Provider.native.tsx +2 -1
  110. package/src/global-account/react/components/B3Provider/B3Provider.tsx +7 -1
  111. package/src/global-account/react/components/B3Provider/LocalSDKProvider.tsx +5 -0
  112. package/src/global-account/react/components/ManageAccount/SessionDurationContent.tsx +107 -0
  113. package/src/global-account/react/components/ManageAccount/SettingsContent.tsx +28 -30
  114. package/src/global-account/react/components/SignInWithB3/components/AuthButton.tsx +21 -2
  115. package/src/global-account/react/components/SignInWithB3/steps/LoginStepCustom.tsx +207 -54
  116. package/src/global-account/react/components/SignInWithB3/utils/signInUtils.ts +19 -3
  117. package/src/global-account/react/components/Toast/ToastContext.tsx +39 -7
  118. package/src/global-account/react/hooks/useAuth.ts +28 -17
  119. package/src/global-account/react/hooks/useAuthentication.ts +24 -13
  120. package/src/global-account/react/hooks/useConnect.tsx +2 -2
  121. package/src/global-account/react/hooks/useTWAuth.tsx +0 -1
  122. package/src/global-account/react/stores/useModalStore.ts +11 -0
  123. package/src/global-account/react/utils/createWagmiConfig.tsx +0 -18
  124. package/src/shared/utils/session-duration.ts +64 -0
  125. package/src/types/torph.d.ts +4 -0
@@ -5,7 +5,8 @@ type WalletType = Wallet["id"];
5
5
  type StrategyType = SingleStepAuthArgsType["strategy"];
6
6
  type CustomStrategyType = "basement" | "privy";
7
7
 
8
- type AllowedStrategies = StrategyType | WalletType | CustomStrategyType;
8
+ type AllowedStrategies = StrategyType | WalletType | CustomStrategyType | "email";
9
+ type NonWalletStrategyType = Exclude<AllowedStrategies, WalletType>;
9
10
  const customStrategies = ["basement", "privy"] as const;
10
11
  // type CustomStrategy = (typeof customStrategies)[number];
11
12
 
@@ -13,9 +14,10 @@ export const allowedStrategies = [
13
14
  // Auth strategies
14
15
  "apple",
15
16
  "google",
17
+ "github",
16
18
  "x",
17
19
  "discord",
18
- // "github",
20
+ "email",
19
21
  "guest",
20
22
 
21
23
  // Wallet IDs
@@ -36,7 +38,7 @@ export function isWalletType(strategy: AllowedStrategies): strategy is WalletTyp
36
38
  return strategy === "walletConnect" || walletIdPattern.test(strategy);
37
39
  }
38
40
 
39
- export function isStrategyType(strategy: AllowedStrategies): strategy is StrategyType {
41
+ export function isStrategyType(strategy: AllowedStrategies): strategy is NonWalletStrategyType {
40
42
  return !isWalletType(strategy);
41
43
  }
42
44
 
@@ -49,6 +51,10 @@ export function getConnectOptionsFromStrategy(strategy: AllowedStrategy): {
49
51
  throw new Error(`Invalid strategy: ${strategy}`);
50
52
  }
51
53
 
54
+ if (strategy === "email") {
55
+ throw new Error("Email strategy requires OTP flow and cannot be connected in a single step");
56
+ }
57
+
52
58
  if (isWalletType(strategy)) {
53
59
  return { strategy: "wallet" as const, wallet: createWallet(strategy) };
54
60
  } else {
@@ -65,6 +71,16 @@ export const strategyIcons: Record<string, string> = {
65
71
  guest: "https://cdn.b3.fun/incognito.svg",
66
72
  // Add more strategies as needed
67
73
  };
74
+
75
+ export const strategyLabels: Record<string, string> = {
76
+ google: "Google",
77
+ x: "X",
78
+ discord: "Discord",
79
+ apple: "Apple",
80
+ guest: "Guest",
81
+ github: "GitHub",
82
+ email: "Email",
83
+ };
68
84
  // Test it
69
85
  // console.log(getConnectOptionsFromStrategy("io.metamask"));
70
86
  // console.log(getConnectOptionsFromStrategy("google"));
@@ -15,6 +15,9 @@ interface ToastContextType {
15
15
  addToast: (type: ToastType, message: string, duration?: number) => string;
16
16
  removeToast: (id: string) => void;
17
17
  clearAll: () => void;
18
+ headerMode: boolean;
19
+ setHeaderMode: (enabled: boolean) => void;
20
+ latestToast: ToastItem | null;
18
21
  }
19
22
 
20
23
  const ToastContext = createContext<ToastContextType | undefined>(undefined);
@@ -23,6 +26,9 @@ let globalToastCounter = 0;
23
26
 
24
27
  export function ToastProvider({ children }: { children: React.ReactNode }) {
25
28
  const [toasts, setToasts] = useState<ToastItem[]>([]);
29
+ const [headerMode, setHeaderMode] = useState(false);
30
+ const headerModeRef = useRef(false);
31
+ const [latestToast, setLatestToast] = useState<ToastItem | null>(null);
26
32
  const timeoutsRef = useRef<Map<string, NodeJS.Timeout>>(new Map());
27
33
 
28
34
  const removeToast = useCallback((id: string) => {
@@ -45,13 +51,23 @@ export function ToastProvider({ children }: { children: React.ReactNode }) {
45
51
  createdAt: Date.now(),
46
52
  };
47
53
 
48
- setToasts(prev => [...prev, newToast]);
54
+ if (headerModeRef.current) {
55
+ setLatestToast(newToast);
56
+ if (duration > 0) {
57
+ const timeout = setTimeout(() => {
58
+ setLatestToast(null);
59
+ }, duration);
60
+ timeoutsRef.current.set(id, timeout);
61
+ }
62
+ } else {
63
+ setToasts(prev => [...prev, newToast]);
49
64
 
50
- if (duration > 0) {
51
- const timeout = setTimeout(() => {
52
- removeToast(id);
53
- }, duration);
54
- timeoutsRef.current.set(id, timeout);
65
+ if (duration > 0) {
66
+ const timeout = setTimeout(() => {
67
+ removeToast(id);
68
+ }, duration);
69
+ timeoutsRef.current.set(id, timeout);
70
+ }
55
71
  }
56
72
 
57
73
  return id;
@@ -65,6 +81,16 @@ export function ToastProvider({ children }: { children: React.ReactNode }) {
65
81
  setToasts([]);
66
82
  }, []);
67
83
 
84
+ const setHeaderModeCallback = useCallback((enabled: boolean) => {
85
+ setHeaderMode(enabled);
86
+ headerModeRef.current = enabled;
87
+ if (!enabled) {
88
+ setLatestToast(null);
89
+ timeoutsRef.current.forEach(timeout => clearTimeout(timeout));
90
+ timeoutsRef.current.clear();
91
+ }
92
+ }, []);
93
+
68
94
  // Cleanup on unmount
69
95
  useEffect(() => {
70
96
  const timeouts = timeoutsRef.current;
@@ -74,7 +100,13 @@ export function ToastProvider({ children }: { children: React.ReactNode }) {
74
100
  };
75
101
  }, []);
76
102
 
77
- return <ToastContext.Provider value={{ toasts, addToast, removeToast, clearAll }}>{children}</ToastContext.Provider>;
103
+ return (
104
+ <ToastContext.Provider
105
+ value={{ toasts, addToast, removeToast, clearAll, headerMode, setHeaderMode: setHeaderModeCallback, latestToast }}
106
+ >
107
+ {children}
108
+ </ToastContext.Provider>
109
+ );
78
110
  }
79
111
 
80
112
  export function useToastContext() {
@@ -6,7 +6,7 @@ import { debugB3React } from "@b3dotfun/sdk/shared/utils/debug";
6
6
  import { client } from "@b3dotfun/sdk/shared/utils/thirdweb";
7
7
  import { ConnectionOptions } from "@thirdweb-dev/wagmi-adapter";
8
8
  import { getConnectors } from "@wagmi/core";
9
- import { useCallback, useContext, useEffect, useRef } from "react";
9
+ import { useCallback, useContext, useEffect, useMemo, useRef } from "react";
10
10
  import {
11
11
  useActiveWallet,
12
12
  useAutoConnect,
@@ -18,7 +18,7 @@ import { Wallet, ecosystemWallet } from "thirdweb/wallets";
18
18
  import { preAuthenticate } from "thirdweb/wallets/in-app";
19
19
  import { useAccount, useConnect, useSwitchAccount } from "wagmi";
20
20
  import { LocalSDKContext } from "../components/B3Provider/LocalSDKProvider";
21
- import { getCachedWagmiConfig } from "../utils/createWagmiConfig";
21
+ import { createWagmiConfig } from "../utils/createWagmiConfig";
22
22
  import { useSearchParam } from "./useSearchParamsSSR";
23
23
  import { useUserQuery } from "./useUserQuery";
24
24
 
@@ -30,7 +30,7 @@ const debug = debugB3React("useAuth");
30
30
  * This hook provides 1:1 feature parity with useAuthentication.ts
31
31
  */
32
32
  export function useAuth() {
33
- const { onConnectCallback } = useContext(LocalSDKContext);
33
+ const { onConnectCallback, disableBSMNTAuthentication } = useContext(LocalSDKContext);
34
34
  const { disconnect } = useDisconnect();
35
35
  const wallets = useConnectedWallets();
36
36
  const activeWallet = useActiveWallet();
@@ -47,7 +47,7 @@ export function useAuth() {
47
47
  const useAutoConnectLoadingPrevious = useRef(false);
48
48
  const referralCode = useSearchParam("referralCode");
49
49
  const { partnerId } = useB3Config();
50
- const wagmiConfig = getCachedWagmiConfig({ partnerId });
50
+ const wagmiConfig = useMemo(() => createWagmiConfig({ partnerId }), [partnerId]);
51
51
  const { connect } = useConnect();
52
52
  const activeWagmiAccount = useAccount();
53
53
  const { switchAccount } = useSwitchAccount();
@@ -76,8 +76,10 @@ export function useAuth() {
76
76
 
77
77
  // Authenticate with BSMNT
78
78
  try {
79
- const b3Jwt = await authenticateWithB3JWT(response.accessToken);
80
- debug("BSMNT re-authentication successful", b3Jwt);
79
+ if (!disableBSMNTAuthentication) {
80
+ const b3Jwt = await authenticateWithB3JWT(response.accessToken);
81
+ debug("BSMNT re-authentication successful", b3Jwt);
82
+ }
81
83
  } catch (bsmntError) {
82
84
  // BSMNT authentication failure shouldn't block the main auth flow
83
85
  debug("BSMNT re-authentication failed (non-critical)", bsmntError);
@@ -88,7 +90,7 @@ export function useAuth() {
88
90
  debug("Re-authentication failed", err);
89
91
  throw err;
90
92
  }
91
- }, [setUser]);
93
+ }, [setUser, disableBSMNTAuthentication]);
92
94
 
93
95
  const syncWagmi = useCallback(async () => {
94
96
  function syncWagmiFunc() {
@@ -136,9 +138,7 @@ export function useAuth() {
136
138
  });
137
139
  }
138
140
  syncWagmiFunc();
139
- // wagmi config shouldn't change
140
- // eslint-disable-next-line react-hooks/exhaustive-deps
141
- }, [partnerId, wallets]);
141
+ }, [wagmiConfig, wallets, connect, switchAccount]);
142
142
 
143
143
  useEffect(() => {
144
144
  syncWagmi();
@@ -159,9 +159,11 @@ export function useAuth() {
159
159
  setIsAuthenticating(false);
160
160
  debug("Re-authenticated successfully", { userAuth });
161
161
 
162
- // Authenticate on BSMNT with B3 JWT
163
- const b3Jwt = await authenticateWithB3JWT(userAuth.accessToken);
164
- debug("@@b3Jwt", b3Jwt);
162
+ if (!disableBSMNTAuthentication) {
163
+ // Authenticate on BSMNT with B3 JWT
164
+ const b3Jwt = await authenticateWithB3JWT(userAuth.accessToken);
165
+ debug("@@b3Jwt", b3Jwt);
166
+ }
165
167
 
166
168
  return userAuth;
167
169
  } catch (error) {
@@ -171,7 +173,14 @@ export function useAuth() {
171
173
  setIsAuthenticating(false);
172
174
  throw new Error("Authentication required. Please authenticate.");
173
175
  }
174
- }, [reAuthenticate, setIsAuthenticated, setIsAuthenticating, setUser, setHasStartedConnecting]);
176
+ }, [
177
+ reAuthenticate,
178
+ setIsAuthenticated,
179
+ setIsAuthenticating,
180
+ setUser,
181
+ setHasStartedConnecting,
182
+ disableBSMNTAuthentication,
183
+ ]);
175
184
 
176
185
  /**
177
186
  * Authenticate with B3
@@ -208,8 +217,10 @@ export function useAuth() {
208
217
 
209
218
  // Step 3: Authenticate with BSMNT for basement integration
210
219
  try {
211
- const b3Jwt = await authenticateWithB3JWT(response.accessToken);
212
- debug("BSMNT authentication successful", b3Jwt);
220
+ if (!disableBSMNTAuthentication) {
221
+ const b3Jwt = await authenticateWithB3JWT(response.accessToken);
222
+ debug("BSMNT authentication successful", b3Jwt);
223
+ }
213
224
  } catch (bsmntError) {
214
225
  // BSMNT authentication failure shouldn't block the main auth flow
215
226
  debug("BSMNT authentication failed (non-critical)", bsmntError);
@@ -221,7 +232,7 @@ export function useAuth() {
221
232
  throw err;
222
233
  }
223
234
  },
224
- [referralCode, setUser],
235
+ [referralCode, setUser, disableBSMNTAuthentication],
225
236
  );
226
237
 
227
238
  /**
@@ -6,7 +6,7 @@ import { debugB3React } from "@b3dotfun/sdk/shared/utils/debug";
6
6
  import { client } from "@b3dotfun/sdk/shared/utils/thirdweb";
7
7
  import { ConnectionOptions } from "@thirdweb-dev/wagmi-adapter";
8
8
  import { getConnectors } from "@wagmi/core";
9
- import { useCallback, useContext, useEffect, useRef } from "react";
9
+ import { useCallback, useContext, useEffect, useMemo, useRef } from "react";
10
10
  import {
11
11
  useActiveWallet,
12
12
  useAutoConnect,
@@ -25,7 +25,7 @@ import { useUserQuery } from "./useUserQuery";
25
25
  const debug = debugB3React("useAuthentication");
26
26
 
27
27
  export function useAuthentication(partnerId: string, { skipAutoConnect = false }: { skipAutoConnect?: boolean } = {}) {
28
- const { onConnectCallback, onLogoutCallback } = useContext(LocalSDKContext);
28
+ const { onConnectCallback, onLogoutCallback, disableBSMNTAuthentication } = useContext(LocalSDKContext);
29
29
  const { disconnect } = useDisconnect();
30
30
  const wallets = useConnectedWallets();
31
31
  // Keep refs so logout() always disconnects current wallets, not stale closure values.
@@ -57,7 +57,7 @@ export function useAuthentication(partnerId: string, { skipAutoConnect = false }
57
57
  const { authenticate } = useTWAuth();
58
58
  const { user, setUser } = useUserQuery();
59
59
  const useAutoConnectLoadingPrevious = useRef(false);
60
- const wagmiConfig = createWagmiConfig({ partnerId });
60
+ const wagmiConfig = useMemo(() => createWagmiConfig({ partnerId }), [partnerId]);
61
61
  const { connect } = useConnect();
62
62
  const activeWagmiAccount = useAccount();
63
63
  const { switchAccount } = useSwitchAccount();
@@ -113,9 +113,7 @@ export function useAuthentication(partnerId: string, { skipAutoConnect = false }
113
113
  });
114
114
  }
115
115
  syncWagmiFunc();
116
- // wagmi config shouldn't change
117
- // eslint-disable-next-line react-hooks/exhaustive-deps
118
- }, [partnerId, wallets]);
116
+ }, [wagmiConfig, wallets, connect, switchAccount]);
119
117
 
120
118
  useEffect(() => {
121
119
  syncWagmi();
@@ -142,9 +140,11 @@ export function useAuthentication(partnerId: string, { skipAutoConnect = false }
142
140
  setIsAuthenticating(false);
143
141
  debug("Re-authenticated successfully", { userAuth });
144
142
 
145
- // Authenticate on BSMNT with B3 JWT
146
- const b3Jwt = await authenticateWithB3JWT(userAuth.accessToken);
147
- debug("@@b3Jwt", b3Jwt);
143
+ if (!disableBSMNTAuthentication) {
144
+ // Authenticate on BSMNT with B3 JWT
145
+ const b3Jwt = await authenticateWithB3JWT(userAuth.accessToken);
146
+ debug("@@b3Jwt", b3Jwt);
147
+ }
148
148
 
149
149
  return userAuth;
150
150
  } catch (error) {
@@ -156,14 +156,25 @@ export function useAuthentication(partnerId: string, { skipAutoConnect = false }
156
156
  setIsAuthenticating(false);
157
157
  debug("Fresh authentication successful", { userAuth });
158
158
 
159
- // Authenticate on BSMNT with B3 JWT
160
- const b3Jwt = await authenticateWithB3JWT(userAuth.accessToken);
161
- debug("@@b3Jwt", b3Jwt);
159
+ if (!disableBSMNTAuthentication) {
160
+ // Authenticate on BSMNT with B3 JWT
161
+ const b3Jwt = await authenticateWithB3JWT(userAuth.accessToken);
162
+ debug("@@b3Jwt", b3Jwt);
163
+ }
162
164
 
163
165
  return userAuth;
164
166
  }
165
167
  },
166
- [activeWallet, partnerId, authenticate, setIsAuthenticated, setIsAuthenticating, setUser, setHasStartedConnecting],
168
+ [
169
+ activeWallet,
170
+ partnerId,
171
+ authenticate,
172
+ setIsAuthenticated,
173
+ setIsAuthenticating,
174
+ setUser,
175
+ setHasStartedConnecting,
176
+ disableBSMNTAuthentication,
177
+ ],
167
178
  );
168
179
 
169
180
  const logout = useCallback(
@@ -4,7 +4,7 @@ import { client } from "@b3dotfun/sdk/shared/utils/thirdweb";
4
4
  import { useCallback, useState } from "react";
5
5
  import { Chain } from "thirdweb";
6
6
  import { useConnect as useConnectTW } from "thirdweb/react";
7
- import { ecosystemWallet, SingleStepAuthArgsType } from "thirdweb/wallets";
7
+ import { ecosystemWallet, MultiStepAuthArgsType, SingleStepAuthArgsType } from "thirdweb/wallets";
8
8
  const debug = debugB3React("useConnect");
9
9
 
10
10
  /**
@@ -23,7 +23,7 @@ export function useConnect(partnerId: string, chain?: Chain) {
23
23
  * It is used to connect to a wallet using the thirdweb client.
24
24
  */
25
25
  const connectTw = useCallback(
26
- async (strategyOptions?: SingleStepAuthArgsType) => {
26
+ async (strategyOptions?: MultiStepAuthArgsType | SingleStepAuthArgsType) => {
27
27
  setIsLoading(true);
28
28
  return await connect(async () => {
29
29
  if (!strategyOptions) throw new Error("Strategy options are required");
@@ -12,7 +12,6 @@ import { useSearchParam } from "./useSearchParamsSSR";
12
12
  * @deprecated Use useAuth() instead
13
13
  */
14
14
  export function useTWAuth() {
15
- console.warn("useTWAuth is deprecated. Please migrate to useAuth() for authentication.");
16
15
  const referralCode = useSearchParam("referralCode");
17
16
 
18
17
  const authenticate = useCallback(
@@ -451,6 +451,16 @@ export interface SendModalProps extends BaseModalProps {
451
451
  onSuccess?: (txHash?: string) => void;
452
452
  }
453
453
 
454
+ /**
455
+ * Props for the Session Duration modal
456
+ * Allows users to configure how long they stay signed in
457
+ */
458
+ export interface SessionDurationModalProps extends BaseModalProps {
459
+ type: "sessionDuration";
460
+ partnerId: string;
461
+ chain: Chain;
462
+ }
463
+
454
464
  /**
455
465
  * Props for the Notifications modal
456
466
  * Allows users to manage notification settings and channels
@@ -677,6 +687,7 @@ export type ModalContentType =
677
687
  | DepositModalProps
678
688
  | SendModalProps
679
689
  | NotificationsModalProps
690
+ | SessionDurationModalProps
680
691
  | AnySpendCollectorClubPurchaseProps
681
692
  | AnySpendDepositModalProps
682
693
  | AnySpendWorkflowTriggerModalProps
@@ -38,21 +38,3 @@ export function createWagmiConfig(options: CreateWagmiConfigOptions) {
38
38
  connectors: finalConnectors,
39
39
  });
40
40
  }
41
-
42
- /** Module-level cache — wagmi configs must not be recreated on every render. */
43
- const wagmiConfigCache = new Map<string, ReturnType<typeof createWagmiConfig>>();
44
-
45
- /**
46
- * Returns a cached wagmi config for the given partnerId.
47
- * Use this instead of calling createWagmiConfig() directly inside React components or hooks
48
- * to avoid registering duplicate EventEmitter listeners on every render.
49
- */
50
- export function getCachedWagmiConfig(options: CreateWagmiConfigOptions) {
51
- const key = options.partnerId;
52
- let config = wagmiConfigCache.get(key);
53
- if (!config) {
54
- config = createWagmiConfig(options);
55
- wagmiConfigCache.set(key, config);
56
- }
57
- return config;
58
- }
@@ -0,0 +1,64 @@
1
+ const STORAGE_KEY_PREFIX = "b3-session-duration";
2
+ const DEFAULT_DAYS = 7;
3
+
4
+ // 0 = session cookie (expires when browser closes)
5
+ export const SESSION_DURATION_OPTIONS = [0, 1, 7, 14, 30] as const;
6
+ export type SessionDurationDays = (typeof SESSION_DURATION_OPTIONS)[number];
7
+
8
+ function storageKey(partnerId?: string) {
9
+ return partnerId ? `${STORAGE_KEY_PREFIX}_${partnerId}` : STORAGE_KEY_PREFIX;
10
+ }
11
+
12
+ /**
13
+ * Read session duration for a specific partner.
14
+ *
15
+ * preferences shape: { [partnerId]: { sessionDuration: number }, sessionDuration?: number }
16
+ *
17
+ * Priority: user.preferences[partnerId].sessionDuration
18
+ * → user.preferences.sessionDuration (global fallback)
19
+ * → localStorage (per-partner) → localStorage (global) → default 7d
20
+ */
21
+ export function getSessionDurationDays(userPreferences?: Record<string, any>, partnerId?: string): SessionDurationDays {
22
+ if (userPreferences) {
23
+ if (partnerId) {
24
+ const v = userPreferences[partnerId]?.sessionDuration;
25
+ if (SESSION_DURATION_OPTIONS.includes(v as SessionDurationDays)) return v as SessionDurationDays;
26
+ }
27
+ const v = userPreferences["sessionDuration"];
28
+ if (SESSION_DURATION_OPTIONS.includes(v as SessionDurationDays)) return v as SessionDurationDays;
29
+ }
30
+ try {
31
+ if (partnerId) {
32
+ const stored = localStorage.getItem(storageKey(partnerId));
33
+ if (stored !== null) {
34
+ const parsed = Number(stored);
35
+ if (SESSION_DURATION_OPTIONS.includes(parsed as SessionDurationDays)) return parsed as SessionDurationDays;
36
+ }
37
+ }
38
+ const stored = localStorage.getItem(STORAGE_KEY_PREFIX);
39
+ if (stored !== null) {
40
+ const parsed = Number(stored);
41
+ if (SESSION_DURATION_OPTIONS.includes(parsed as SessionDurationDays)) return parsed as SessionDurationDays;
42
+ }
43
+ } catch {
44
+ // localStorage unavailable (e.g. SSR)
45
+ }
46
+ return DEFAULT_DAYS;
47
+ }
48
+
49
+ export const SESSION_DURATION_LABELS: Record<SessionDurationDays, string> = {
50
+ 0: "Session only",
51
+ 1: "1 day",
52
+ 7: "7 days",
53
+ 14: "14 days",
54
+ 30: "30 days",
55
+ };
56
+
57
+ /** Cache the preference locally so it's available immediately on next login */
58
+ export function setSessionDurationDays(days: SessionDurationDays, partnerId?: string): void {
59
+ try {
60
+ localStorage.setItem(storageKey(partnerId), String(days));
61
+ } catch {
62
+ // ignore
63
+ }
64
+ }
@@ -0,0 +1,4 @@
1
+ declare module "torph/react" {
2
+ import type { JSX } from "react";
3
+ export function TextMorph(props: { children: string; className?: string }): JSX.Element;
4
+ }