@b3dotfun/sdk 0.0.81 → 0.0.82-alpha.0

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.
@@ -165,7 +165,7 @@ function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySuccess, onE
165
165
  isOpen,
166
166
  source,
167
167
  });
168
- if (isConnected && isAuthenticated) {
168
+ if (isConnected && isAuthenticated && user) {
169
169
  // Mark that login just completed BEFORE opening manage account or closing modal
170
170
  // This allows Turnkey modal to show (if enableTurnkey is true)
171
171
  if (closeAfterLogin) {
@@ -2,7 +2,7 @@ import { Users } from "@b3dotfun/b3-api";
2
2
  /**
3
3
  * NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
4
4
  *
5
- * Custom hook to manage user state with react-query
5
+ * Custom hook to manage user state with Zustand
6
6
  * This allows for invalidation and refetching of user data
7
7
  */
8
8
  export declare function useUserQuery(): {
@@ -59,7 +59,7 @@ export declare function useUserQuery(): {
59
59
  };
60
60
  } | undefined;
61
61
  setUser: (newUser?: Users) => void;
62
- refetchUser: () => Promise<void>;
62
+ refetchUser: () => Promise<any>;
63
63
  clearUser: () => void;
64
64
  queryKey: string[];
65
65
  };
@@ -2,79 +2,100 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.useUserQuery = useUserQuery;
4
4
  const debug_1 = require("../../../shared/utils/debug");
5
- const react_query_1 = require("@tanstack/react-query");
5
+ const react_1 = require("react");
6
+ const zustand_1 = require("zustand");
7
+ const middleware_1 = require("zustand/middleware");
6
8
  const debug = (0, debug_1.debugB3React)("useUserQuery");
7
9
  const USER_QUERY_KEY = ["b3-user"];
8
10
  /**
9
- * Retrieves the user from localStorage
11
+ * Zustand store for managing user state
12
+ * Persists user data to localStorage
10
13
  */
11
- function getUserFromStorage() {
12
- if (typeof window === "undefined") {
13
- return null;
14
- }
15
- try {
16
- const storedUser = localStorage.getItem("b3-user");
17
- return storedUser ? JSON.parse(storedUser) : null;
18
- }
19
- catch (error) {
20
- console.warn("Failed to restore user from localStorage:", error);
21
- return null;
22
- }
23
- }
24
- /**
25
- * Saves user to localStorage
26
- */
27
- function saveUserToStorage(user) {
28
- if (typeof window === "undefined") {
29
- return;
30
- }
31
- if (user) {
32
- localStorage.setItem("b3-user", JSON.stringify(user));
33
- }
34
- else {
35
- localStorage.removeItem("b3-user");
36
- }
37
- }
14
+ const useUserStore = (0, zustand_1.create)()((0, middleware_1.persist)(set => ({
15
+ user: null,
16
+ setUser: (newUser) => {
17
+ const userToSave = newUser ?? null;
18
+ set({ user: userToSave });
19
+ debug("User updated", userToSave);
20
+ },
21
+ clearUser: () => {
22
+ set({ user: null });
23
+ debug("User cleared");
24
+ },
25
+ }), {
26
+ name: "b3-user",
27
+ onRehydrateStorage: () => (_, error) => {
28
+ if (error) {
29
+ console.warn("Failed to rehydrate user store:", error);
30
+ }
31
+ },
32
+ }));
38
33
  /**
39
34
  * NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
40
35
  *
41
- * Custom hook to manage user state with react-query
36
+ * Custom hook to manage user state with Zustand
42
37
  * This allows for invalidation and refetching of user data
43
38
  */
44
39
  function useUserQuery() {
45
- const queryClient = (0, react_query_1.useQueryClient)();
46
- // Query to get user data (primarily from cache/localStorage)
47
- const { data: user } = (0, react_query_1.useQuery)({
48
- queryKey: USER_QUERY_KEY,
49
- queryFn: getUserFromStorage,
50
- staleTime: Infinity, // User data doesn't go stale automatically
51
- gcTime: Infinity, // Keep in cache indefinitely
52
- initialData: getUserFromStorage,
53
- });
54
- // Mutation to update user
55
- const setUserMutation = (0, react_query_1.useMutation)({
56
- mutationFn: async (newUser) => {
57
- const userToSave = newUser ?? null;
58
- saveUserToStorage(userToSave);
59
- return userToSave;
60
- },
61
- onSuccess: data => {
62
- queryClient.setQueryData(USER_QUERY_KEY, data);
63
- debug("User updated", data);
64
- },
65
- });
40
+ const user = useUserStore(state => state.user);
41
+ const setUserStore = useUserStore(state => state.setUser);
42
+ const clearUserStore = useUserStore(state => state.clearUser);
43
+ // Listen for storage events from other tabs/windows
44
+ (0, react_1.useEffect)(() => {
45
+ const handleStorageChange = (e) => {
46
+ if (e.key === "b3-user") {
47
+ // Sync with changes from other tabs/windows
48
+ const stored = e.newValue;
49
+ if (stored) {
50
+ try {
51
+ const parsed = JSON.parse(stored);
52
+ // Zustand persist format: { state: { user: ... }, version: ... }
53
+ const userData = parsed?.state?.user ?? parsed?.user ?? null;
54
+ useUserStore.setState({ user: userData });
55
+ }
56
+ catch (error) {
57
+ console.warn("Failed to parse user from storage event:", error);
58
+ }
59
+ }
60
+ else {
61
+ useUserStore.setState({ user: null });
62
+ }
63
+ }
64
+ };
65
+ window.addEventListener("storage", handleStorageChange);
66
+ return () => {
67
+ window.removeEventListener("storage", handleStorageChange);
68
+ };
69
+ }, []);
66
70
  // Helper function to set user (maintains backward compatibility)
67
71
  const setUser = (newUser) => {
68
- setUserMutation.mutate(newUser);
72
+ setUserStore(newUser);
69
73
  };
70
74
  // Helper function to invalidate and refetch user
71
75
  const refetchUser = async () => {
72
- await queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
73
- return queryClient.refetchQueries({ queryKey: USER_QUERY_KEY });
76
+ // Re-read from localStorage and update store
77
+ // Zustand persist stores data as { state: { user: ... }, version: ... }
78
+ const stored = localStorage.getItem("b3-user");
79
+ if (stored) {
80
+ try {
81
+ const parsed = JSON.parse(stored);
82
+ // Zustand persist format: { state: { user: ... }, version: ... }
83
+ const userData = parsed?.state?.user ?? parsed?.user ?? null;
84
+ useUserStore.setState({ user: userData });
85
+ return userData ?? undefined;
86
+ }
87
+ catch (error) {
88
+ console.warn("Failed to refetch user from localStorage:", error);
89
+ // Fallback to current store state
90
+ return useUserStore.getState().user ?? undefined;
91
+ }
92
+ }
93
+ useUserStore.setState({ user: null });
94
+ return undefined;
74
95
  };
75
96
  // Helper function to clear user
76
97
  const clearUser = () => {
77
- setUser(undefined);
98
+ clearUserStore();
78
99
  };
79
100
  return {
80
101
  user: user ?? undefined,
@@ -162,7 +162,7 @@ export function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySucce
162
162
  isOpen,
163
163
  source,
164
164
  });
165
- if (isConnected && isAuthenticated) {
165
+ if (isConnected && isAuthenticated && user) {
166
166
  // Mark that login just completed BEFORE opening manage account or closing modal
167
167
  // This allows Turnkey modal to show (if enableTurnkey is true)
168
168
  if (closeAfterLogin) {
@@ -2,7 +2,7 @@ import { Users } from "@b3dotfun/b3-api";
2
2
  /**
3
3
  * NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
4
4
  *
5
- * Custom hook to manage user state with react-query
5
+ * Custom hook to manage user state with Zustand
6
6
  * This allows for invalidation and refetching of user data
7
7
  */
8
8
  export declare function useUserQuery(): {
@@ -59,7 +59,7 @@ export declare function useUserQuery(): {
59
59
  };
60
60
  } | undefined;
61
61
  setUser: (newUser?: Users) => void;
62
- refetchUser: () => Promise<void>;
62
+ refetchUser: () => Promise<any>;
63
63
  clearUser: () => void;
64
64
  queryKey: string[];
65
65
  };
@@ -1,77 +1,98 @@
1
1
  import { debugB3React } from "../../../shared/utils/debug.js";
2
- import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
2
+ import { useEffect } from "react";
3
+ import { create } from "zustand";
4
+ import { persist } from "zustand/middleware";
3
5
  const debug = debugB3React("useUserQuery");
4
6
  const USER_QUERY_KEY = ["b3-user"];
5
7
  /**
6
- * Retrieves the user from localStorage
8
+ * Zustand store for managing user state
9
+ * Persists user data to localStorage
7
10
  */
8
- function getUserFromStorage() {
9
- if (typeof window === "undefined") {
10
- return null;
11
- }
12
- try {
13
- const storedUser = localStorage.getItem("b3-user");
14
- return storedUser ? JSON.parse(storedUser) : null;
15
- }
16
- catch (error) {
17
- console.warn("Failed to restore user from localStorage:", error);
18
- return null;
19
- }
20
- }
21
- /**
22
- * Saves user to localStorage
23
- */
24
- function saveUserToStorage(user) {
25
- if (typeof window === "undefined") {
26
- return;
27
- }
28
- if (user) {
29
- localStorage.setItem("b3-user", JSON.stringify(user));
30
- }
31
- else {
32
- localStorage.removeItem("b3-user");
33
- }
34
- }
11
+ const useUserStore = create()(persist(set => ({
12
+ user: null,
13
+ setUser: (newUser) => {
14
+ const userToSave = newUser ?? null;
15
+ set({ user: userToSave });
16
+ debug("User updated", userToSave);
17
+ },
18
+ clearUser: () => {
19
+ set({ user: null });
20
+ debug("User cleared");
21
+ },
22
+ }), {
23
+ name: "b3-user",
24
+ onRehydrateStorage: () => (_, error) => {
25
+ if (error) {
26
+ console.warn("Failed to rehydrate user store:", error);
27
+ }
28
+ },
29
+ }));
35
30
  /**
36
31
  * NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
37
32
  *
38
- * Custom hook to manage user state with react-query
33
+ * Custom hook to manage user state with Zustand
39
34
  * This allows for invalidation and refetching of user data
40
35
  */
41
36
  export function useUserQuery() {
42
- const queryClient = useQueryClient();
43
- // Query to get user data (primarily from cache/localStorage)
44
- const { data: user } = useQuery({
45
- queryKey: USER_QUERY_KEY,
46
- queryFn: getUserFromStorage,
47
- staleTime: Infinity, // User data doesn't go stale automatically
48
- gcTime: Infinity, // Keep in cache indefinitely
49
- initialData: getUserFromStorage,
50
- });
51
- // Mutation to update user
52
- const setUserMutation = useMutation({
53
- mutationFn: async (newUser) => {
54
- const userToSave = newUser ?? null;
55
- saveUserToStorage(userToSave);
56
- return userToSave;
57
- },
58
- onSuccess: data => {
59
- queryClient.setQueryData(USER_QUERY_KEY, data);
60
- debug("User updated", data);
61
- },
62
- });
37
+ const user = useUserStore(state => state.user);
38
+ const setUserStore = useUserStore(state => state.setUser);
39
+ const clearUserStore = useUserStore(state => state.clearUser);
40
+ // Listen for storage events from other tabs/windows
41
+ useEffect(() => {
42
+ const handleStorageChange = (e) => {
43
+ if (e.key === "b3-user") {
44
+ // Sync with changes from other tabs/windows
45
+ const stored = e.newValue;
46
+ if (stored) {
47
+ try {
48
+ const parsed = JSON.parse(stored);
49
+ // Zustand persist format: { state: { user: ... }, version: ... }
50
+ const userData = parsed?.state?.user ?? parsed?.user ?? null;
51
+ useUserStore.setState({ user: userData });
52
+ }
53
+ catch (error) {
54
+ console.warn("Failed to parse user from storage event:", error);
55
+ }
56
+ }
57
+ else {
58
+ useUserStore.setState({ user: null });
59
+ }
60
+ }
61
+ };
62
+ window.addEventListener("storage", handleStorageChange);
63
+ return () => {
64
+ window.removeEventListener("storage", handleStorageChange);
65
+ };
66
+ }, []);
63
67
  // Helper function to set user (maintains backward compatibility)
64
68
  const setUser = (newUser) => {
65
- setUserMutation.mutate(newUser);
69
+ setUserStore(newUser);
66
70
  };
67
71
  // Helper function to invalidate and refetch user
68
72
  const refetchUser = async () => {
69
- await queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
70
- return queryClient.refetchQueries({ queryKey: USER_QUERY_KEY });
73
+ // Re-read from localStorage and update store
74
+ // Zustand persist stores data as { state: { user: ... }, version: ... }
75
+ const stored = localStorage.getItem("b3-user");
76
+ if (stored) {
77
+ try {
78
+ const parsed = JSON.parse(stored);
79
+ // Zustand persist format: { state: { user: ... }, version: ... }
80
+ const userData = parsed?.state?.user ?? parsed?.user ?? null;
81
+ useUserStore.setState({ user: userData });
82
+ return userData ?? undefined;
83
+ }
84
+ catch (error) {
85
+ console.warn("Failed to refetch user from localStorage:", error);
86
+ // Fallback to current store state
87
+ return useUserStore.getState().user ?? undefined;
88
+ }
89
+ }
90
+ useUserStore.setState({ user: null });
91
+ return undefined;
71
92
  };
72
93
  // Helper function to clear user
73
94
  const clearUser = () => {
74
- setUser(undefined);
95
+ clearUserStore();
75
96
  };
76
97
  return {
77
98
  user: user ?? undefined,
@@ -2,7 +2,7 @@ import { Users } from "@b3dotfun/b3-api";
2
2
  /**
3
3
  * NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
4
4
  *
5
- * Custom hook to manage user state with react-query
5
+ * Custom hook to manage user state with Zustand
6
6
  * This allows for invalidation and refetching of user data
7
7
  */
8
8
  export declare function useUserQuery(): {
@@ -59,7 +59,7 @@ export declare function useUserQuery(): {
59
59
  };
60
60
  } | undefined;
61
61
  setUser: (newUser?: Users) => void;
62
- refetchUser: () => Promise<void>;
62
+ refetchUser: () => Promise<any>;
63
63
  clearUser: () => void;
64
64
  queryKey: string[];
65
65
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.0.81",
3
+ "version": "0.0.82-alpha.0",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -198,7 +198,7 @@ export function SignInWithB3Flow({
198
198
  source,
199
199
  });
200
200
 
201
- if (isConnected && isAuthenticated) {
201
+ if (isConnected && isAuthenticated && user) {
202
202
  // Mark that login just completed BEFORE opening manage account or closing modal
203
203
  // This allows Turnkey modal to show (if enableTurnkey is true)
204
204
  if (closeAfterLogin) {
@@ -1,88 +1,116 @@
1
1
  import { Users } from "@b3dotfun/b3-api";
2
2
  import { debugB3React } from "@b3dotfun/sdk/shared/utils/debug";
3
- import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
3
+ import { useEffect } from "react";
4
+ import { create } from "zustand";
5
+ import { persist } from "zustand/middleware";
4
6
 
5
7
  const debug = debugB3React("useUserQuery");
6
8
 
7
9
  const USER_QUERY_KEY = ["b3-user"];
8
10
 
9
- /**
10
- * Retrieves the user from localStorage
11
- */
12
- function getUserFromStorage(): Users | null {
13
- if (typeof window === "undefined") {
14
- return null;
15
- }
16
-
17
- try {
18
- const storedUser = localStorage.getItem("b3-user");
19
- return storedUser ? JSON.parse(storedUser) : null;
20
- } catch (error) {
21
- console.warn("Failed to restore user from localStorage:", error);
22
- return null;
23
- }
11
+ interface UserStore {
12
+ user: Users | null;
13
+ setUser: (user: Users | undefined) => void;
14
+ clearUser: () => void;
24
15
  }
25
16
 
26
17
  /**
27
- * Saves user to localStorage
18
+ * Zustand store for managing user state
19
+ * Persists user data to localStorage
28
20
  */
29
- function saveUserToStorage(user: Users | null) {
30
- if (typeof window === "undefined") {
31
- return;
32
- }
33
-
34
- if (user) {
35
- localStorage.setItem("b3-user", JSON.stringify(user));
36
- } else {
37
- localStorage.removeItem("b3-user");
38
- }
39
- }
21
+ const useUserStore = create<UserStore>()(
22
+ persist(
23
+ set => ({
24
+ user: null,
25
+ setUser: (newUser: Users | undefined) => {
26
+ const userToSave = newUser ?? null;
27
+ set({ user: userToSave });
28
+ debug("User updated", userToSave);
29
+ },
30
+ clearUser: () => {
31
+ set({ user: null });
32
+ debug("User cleared");
33
+ },
34
+ }),
35
+ {
36
+ name: "b3-user",
37
+ onRehydrateStorage: () => (_, error) => {
38
+ if (error) {
39
+ console.warn("Failed to rehydrate user store:", error);
40
+ }
41
+ },
42
+ },
43
+ ),
44
+ );
40
45
 
41
46
  /**
42
47
  * NOTE: THIS IS ONLY MEANT FOR INTERNAL USE, from useOnConnect
43
48
  *
44
- * Custom hook to manage user state with react-query
49
+ * Custom hook to manage user state with Zustand
45
50
  * This allows for invalidation and refetching of user data
46
51
  */
47
52
  export function useUserQuery() {
48
- const queryClient = useQueryClient();
53
+ const user = useUserStore(state => state.user);
54
+ const setUserStore = useUserStore(state => state.setUser);
55
+ const clearUserStore = useUserStore(state => state.clearUser);
49
56
 
50
- // Query to get user data (primarily from cache/localStorage)
51
- const { data: user } = useQuery<Users | null>({
52
- queryKey: USER_QUERY_KEY,
53
- queryFn: getUserFromStorage,
54
- staleTime: Infinity, // User data doesn't go stale automatically
55
- gcTime: Infinity, // Keep in cache indefinitely
56
- initialData: getUserFromStorage,
57
- });
57
+ // Listen for storage events from other tabs/windows
58
+ useEffect(() => {
59
+ const handleStorageChange = (e: StorageEvent) => {
60
+ if (e.key === "b3-user") {
61
+ // Sync with changes from other tabs/windows
62
+ const stored = e.newValue;
63
+ if (stored) {
64
+ try {
65
+ const parsed = JSON.parse(stored);
66
+ // Zustand persist format: { state: { user: ... }, version: ... }
67
+ const userData = parsed?.state?.user ?? parsed?.user ?? null;
68
+ useUserStore.setState({ user: userData });
69
+ } catch (error) {
70
+ console.warn("Failed to parse user from storage event:", error);
71
+ }
72
+ } else {
73
+ useUserStore.setState({ user: null });
74
+ }
75
+ }
76
+ };
58
77
 
59
- // Mutation to update user
60
- const setUserMutation = useMutation({
61
- mutationFn: async (newUser: Users | undefined) => {
62
- const userToSave = newUser ?? null;
63
- saveUserToStorage(userToSave);
64
- return userToSave;
65
- },
66
- onSuccess: data => {
67
- queryClient.setQueryData(USER_QUERY_KEY, data);
68
- debug("User updated", data);
69
- },
70
- });
78
+ window.addEventListener("storage", handleStorageChange);
79
+ return () => {
80
+ window.removeEventListener("storage", handleStorageChange);
81
+ };
82
+ }, []);
71
83
 
72
84
  // Helper function to set user (maintains backward compatibility)
73
85
  const setUser = (newUser?: Users) => {
74
- setUserMutation.mutate(newUser);
86
+ setUserStore(newUser);
75
87
  };
76
88
 
77
89
  // Helper function to invalidate and refetch user
78
90
  const refetchUser = async () => {
79
- await queryClient.invalidateQueries({ queryKey: USER_QUERY_KEY });
80
- return queryClient.refetchQueries({ queryKey: USER_QUERY_KEY });
91
+ // Re-read from localStorage and update store
92
+ // Zustand persist stores data as { state: { user: ... }, version: ... }
93
+ const stored = localStorage.getItem("b3-user");
94
+ if (stored) {
95
+ try {
96
+ const parsed = JSON.parse(stored);
97
+ // Zustand persist format: { state: { user: ... }, version: ... }
98
+ const userData = parsed?.state?.user ?? parsed?.user ?? null;
99
+ useUserStore.setState({ user: userData });
100
+ return userData ?? undefined;
101
+ } catch (error) {
102
+ console.warn("Failed to refetch user from localStorage:", error);
103
+ // Fallback to current store state
104
+ return useUserStore.getState().user ?? undefined;
105
+ }
106
+ }
107
+ useUserStore.setState({ user: null });
108
+ return undefined;
81
109
  };
82
110
 
83
111
  // Helper function to clear user
84
112
  const clearUser = () => {
85
- setUser(undefined);
113
+ clearUserStore();
86
114
  };
87
115
 
88
116
  return {