@b3dotfun/sdk 0.1.70-alpha.3 → 0.1.70-alpha.5

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 (68) hide show
  1. package/dist/cjs/app.shared.d.ts +8 -0
  2. package/dist/cjs/app.shared.js +19 -0
  3. package/dist/cjs/global-account/better-auth-client.d.ts +8 -0
  4. package/dist/cjs/global-account/better-auth-client.js +26 -3
  5. package/dist/cjs/global-account/client-manager.d.ts +2 -0
  6. package/dist/cjs/global-account/client-manager.js +19 -4
  7. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +10 -1
  8. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +15 -1
  9. package/dist/cjs/global-account/react/components/B3Provider/BetterAuthProvider.js +45 -4
  10. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +1 -5
  11. package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
  12. package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.js +1 -3
  13. package/dist/cjs/global-account/react/components/index.d.ts +0 -1
  14. package/dist/cjs/global-account/react/components/index.js +3 -5
  15. package/dist/cjs/global-account/react/hooks/index.d.ts +0 -1
  16. package/dist/cjs/global-account/react/hooks/index.js +2 -4
  17. package/dist/cjs/global-account/react/hooks/useBetterAuth.js +7 -7
  18. package/dist/cjs/global-account/types/b3-api.types.d.ts +5 -0
  19. package/dist/esm/app.shared.d.ts +8 -0
  20. package/dist/esm/app.shared.js +17 -0
  21. package/dist/esm/global-account/better-auth-client.d.ts +8 -0
  22. package/dist/esm/global-account/better-auth-client.js +25 -4
  23. package/dist/esm/global-account/client-manager.d.ts +2 -0
  24. package/dist/esm/global-account/client-manager.js +19 -5
  25. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +10 -1
  26. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +16 -2
  27. package/dist/esm/global-account/react/components/B3Provider/BetterAuthProvider.js +46 -5
  28. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +1 -5
  29. package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
  30. package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.js +1 -3
  31. package/dist/esm/global-account/react/components/index.d.ts +0 -1
  32. package/dist/esm/global-account/react/components/index.js +0 -1
  33. package/dist/esm/global-account/react/hooks/index.d.ts +0 -1
  34. package/dist/esm/global-account/react/hooks/index.js +0 -1
  35. package/dist/esm/global-account/react/hooks/useBetterAuth.js +8 -8
  36. package/dist/esm/global-account/types/b3-api.types.d.ts +5 -0
  37. package/dist/types/app.shared.d.ts +8 -0
  38. package/dist/types/global-account/better-auth-client.d.ts +8 -0
  39. package/dist/types/global-account/client-manager.d.ts +2 -0
  40. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +10 -1
  41. package/dist/types/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +3 -2
  42. package/dist/types/global-account/react/components/index.d.ts +0 -1
  43. package/dist/types/global-account/react/hooks/index.d.ts +0 -1
  44. package/dist/types/global-account/types/b3-api.types.d.ts +5 -0
  45. package/package.json +2 -2
  46. package/src/app.shared.ts +20 -0
  47. package/src/global-account/better-auth-client.ts +28 -4
  48. package/src/global-account/client-manager.ts +20 -5
  49. package/src/global-account/react/components/B3Provider/B3Provider.tsx +26 -1
  50. package/src/global-account/react/components/B3Provider/BetterAuthProvider.tsx +51 -5
  51. package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +1 -4
  52. package/src/global-account/react/components/SignInWithB3/utils/signInUtils.ts +2 -4
  53. package/src/global-account/react/components/index.ts +0 -1
  54. package/src/global-account/react/hooks/index.ts +0 -1
  55. package/src/global-account/react/hooks/useBetterAuth.ts +8 -8
  56. package/src/global-account/types/b3-api.types.ts +5 -1
  57. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
  58. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Privy.js +0 -46
  59. package/dist/cjs/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
  60. package/dist/cjs/global-account/react/hooks/useHandleConnectWithPrivy.js +0 -70
  61. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
  62. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Privy.js +0 -43
  63. package/dist/esm/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
  64. package/dist/esm/global-account/react/hooks/useHandleConnectWithPrivy.js +0 -67
  65. package/dist/types/global-account/react/components/SignInWithB3/SignInWithB3Privy.d.ts +0 -10
  66. package/dist/types/global-account/react/hooks/useHandleConnectWithPrivy.d.ts +0 -11
  67. package/src/global-account/react/components/SignInWithB3/SignInWithB3Privy.tsx +0 -63
  68. package/src/global-account/react/hooks/useHandleConnectWithPrivy.tsx +0 -79
@@ -2,22 +2,26 @@ import { createClient } from "@b3dotfun/b3-api";
2
2
  import rest from "@feathersjs/rest-client";
3
3
  import socketio from "@feathersjs/socketio-client";
4
4
  import io from "socket.io-client";
5
- import { authenticate as authenticateB3, B3_API_URL, clientOptions } from "../app.shared.js";
5
+ import { authenticate as authenticateB3, getB3ApiUrl, clientOptions } from "../app.shared.js";
6
6
  // Global state to track which client type is active
7
7
  let currentClientType = "rest";
8
8
  let currentClient = null;
9
9
  // Socket client instance
10
10
  let socketClient = null;
11
11
  let socketInstance = null;
12
+ let socketClientUrl = null;
12
13
  // REST client instance
13
14
  let restClient = null;
15
+ let restClientUrl = null;
14
16
  /**
15
17
  * Creates a socket client
16
18
  */
17
19
  function createSocketClient() {
18
- if (!socketClient) {
19
- socketInstance = io(B3_API_URL, { transports: ["websocket"] });
20
+ const url = getB3ApiUrl();
21
+ if (!socketClient || socketClientUrl !== url) {
22
+ socketInstance = io(url, { transports: ["websocket"] });
20
23
  socketClient = createClient(socketio(socketInstance), clientOptions);
24
+ socketClientUrl = url;
21
25
  }
22
26
  return socketClient;
23
27
  }
@@ -33,12 +37,22 @@ function resolveFetch() {
33
37
  return require("cross-fetch").fetch;
34
38
  }
35
39
  function createRestClient() {
36
- if (!restClient) {
37
- const connection = rest(B3_API_URL).fetch(resolveFetch());
40
+ const url = getB3ApiUrl();
41
+ if (!restClient || restClientUrl !== url) {
42
+ const connection = rest(url).fetch(resolveFetch());
38
43
  restClient = createClient(connection, clientOptions);
44
+ restClientUrl = url;
39
45
  }
40
46
  return restClient;
41
47
  }
48
+ /** Reset all cached clients (called when API URL changes). */
49
+ export function resetClients() {
50
+ socketClient = null;
51
+ socketClientUrl = null;
52
+ restClient = null;
53
+ restClientUrl = null;
54
+ currentClient = null;
55
+ }
42
56
  /**
43
57
  * Sets the active client type and creates the appropriate client
44
58
  *
@@ -10,7 +10,7 @@ import { ClientType } from "../../../client-manager";
10
10
  /**
11
11
  * Main B3Provider component
12
12
  */
13
- export declare function B3Provider({ theme, children, accountOverride, environment, automaticallySetFirstEoa, defaultEoaProvider, simDuneApiKey, toaster: _toaster, clientType, rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors, createClientReferenceId, defaultPermissions, disableBSMNTAuthentication, queryClient, authStrategy, }: {
13
+ export declare function B3Provider({ theme, children, accountOverride, environment, automaticallySetFirstEoa, defaultEoaProvider, simDuneApiKey, toaster: _toaster, clientType, rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors, createClientReferenceId, defaultPermissions, disableBSMNTAuthentication, queryClient, authStrategy, apiUrl, }: {
14
14
  theme: "light" | "dark";
15
15
  children: React.ReactNode;
16
16
  accountOverride?: Account;
@@ -39,4 +39,13 @@ export declare function B3Provider({ theme, children, accountOverride, environme
39
39
  queryClient?: QueryClient;
40
40
  /** Auth strategy: "thirdweb" (default, ecosystem wallet) or "better-auth" (email/password via Better Auth) */
41
41
  authStrategy?: AuthStrategy;
42
+ /**
43
+ * Override the B3 API URL. When provided, all SDK requests (auth, Feathers,
44
+ * BetterAuth) will use this URL instead of the `NEXT_PUBLIC_B3_API` env var.
45
+ *
46
+ * Useful for local development: pass `http://localhost:3031` to route
47
+ * OAuth callbacks and session checks through your local B3 API.
48
+ * If omitted, defaults to `NEXT_PUBLIC_B3_API` or `https://api.b3.fun`.
49
+ */
50
+ apiUrl?: string;
42
51
  }): import("react/jsx-runtime").JSX.Element;
@@ -5,7 +5,9 @@ import { loadGA4Script } from "../../../../global-account/utils/analytics.js";
5
5
  import { WalletProvider } from "../../../../wallet/react/index.js";
6
6
  import "@relayprotocol/relay-kit-ui/styles.css";
7
7
  import { useEffect, useMemo } from "react";
8
- import { setClientType } from "../../../client-manager.js";
8
+ import { resetClients, setClientType } from "../../../client-manager.js";
9
+ import { setB3ApiUrl } from "../../../../app.shared.js";
10
+ import { resetBetterAuthClient } from "../../../better-auth-client.js";
9
11
  import { StyleRoot } from "../StyleRoot.js";
10
12
  import { setToastContext, ToastProvider, useToastContext } from "../Toast/index.js";
11
13
  import AuthenticationProvider from "./AuthenticationProvider.js";
@@ -17,7 +19,19 @@ import { LocalSDKProvider } from "./LocalSDKProvider.js";
17
19
  */
18
20
  export function B3Provider({ theme = "light", children, accountOverride, environment, automaticallySetFirstEoa, defaultEoaProvider, simDuneApiKey,
19
21
  // deprecated since v0.0.87
20
- toaster: _toaster, clientType = "rest", rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors = false, createClientReferenceId, defaultPermissions, disableBSMNTAuthentication = false, queryClient, authStrategy = "thirdweb", }) {
22
+ toaster: _toaster, clientType = "rest", rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors = false, createClientReferenceId, defaultPermissions, disableBSMNTAuthentication = false, queryClient, authStrategy = "thirdweb", apiUrl, }) {
23
+ // Override the B3 API URL when the `apiUrl` prop is provided.
24
+ // Must run before client initialization and auth providers mount.
25
+ useEffect(() => {
26
+ setB3ApiUrl(apiUrl ?? null);
27
+ if (apiUrl) {
28
+ resetBetterAuthClient();
29
+ resetClients();
30
+ }
31
+ return () => {
32
+ setB3ApiUrl(null);
33
+ };
34
+ }, [apiUrl]);
21
35
  // Initialize Google Analytics on mount
22
36
  useEffect(() => {
23
37
  loadGA4Script();
@@ -4,7 +4,7 @@ import { B3_AUTH_COOKIE_NAME } from "../../../../shared/constants/index.js";
4
4
  import { debugB3React } from "../../../../shared/utils/debug.js";
5
5
  import Cookies from "js-cookie";
6
6
  import { useEffect, useRef } from "react";
7
- import { betterAuthClient } from "../../../better-auth-client.js";
7
+ import { getBetterAuthClient } from "../../../better-auth-client.js";
8
8
  import { useUserQuery } from "../../hooks/useUserQuery.js";
9
9
  const debug = debugB3React("BetterAuthProvider");
10
10
  /**
@@ -40,7 +40,7 @@ const BetterAuthProvider = ({ partnerId }) => {
40
40
  app.logout = async () => {
41
41
  debug("Patched logout: clearing Better Auth session");
42
42
  try {
43
- await betterAuthClient.signOut();
43
+ await getBetterAuthClient().signOut();
44
44
  }
45
45
  catch {
46
46
  debug("Better Auth signOut failed (non-critical)");
@@ -74,9 +74,50 @@ const BetterAuthProvider = ({ partnerId }) => {
74
74
  catch {
75
75
  debug("No existing Feathers JWT");
76
76
  }
77
- // 2. Check for a Better Auth session (e.g. after OAuth redirect sets a cookie)
77
+ // 2. Check for _ba_token in URL (OAuth callback with third-party cookie bypass).
78
+ // When the API and frontend are on different domains, browsers with third-party
79
+ // cookie blocking (Firefox TCP, Safari ITP, Chrome Privacy Sandbox) prevent the
80
+ // better-auth.session_token cookie from being sent on cross-origin requests.
81
+ // The B3 API injects the session token into the redirect URL as _ba_token,
82
+ // allowing direct exchange without relying on cookies.
83
+ const params = new URLSearchParams(window.location.search);
84
+ const baToken = params.get("_ba_token");
85
+ if (baToken) {
86
+ debug("Found _ba_token in URL, exchanging for Feathers JWT");
87
+ // Clean the token from the URL immediately (security)
88
+ params.delete("_ba_token");
89
+ const cleanSearch = params.toString();
90
+ const cleanUrl = window.location.pathname + (cleanSearch ? `?${cleanSearch}` : "") + window.location.hash;
91
+ window.history.replaceState({}, "", cleanUrl);
92
+ try {
93
+ const response = await app.authenticate({
94
+ strategy: "better-auth",
95
+ accessToken: baToken,
96
+ partnerId,
97
+ });
98
+ if (response.accessToken) {
99
+ Cookies.set(B3_AUTH_COOKIE_NAME, response.accessToken, {
100
+ secure: true,
101
+ sameSite: "Lax",
102
+ });
103
+ }
104
+ if (response.user) {
105
+ setUser(response.user);
106
+ setIsAuthenticated(true);
107
+ setIsConnected(true);
108
+ }
109
+ debug("_ba_token exchanged for Feathers JWT", { userId: response.user?.userId });
110
+ setIsAuthenticating(false);
111
+ return;
112
+ }
113
+ catch (err) {
114
+ debug("_ba_token exchange failed", err);
115
+ }
116
+ }
117
+ // 3. Check for a Better Auth session via cookie (works when API and frontend
118
+ // share a domain or when cookies aren't partitioned)
78
119
  try {
79
- const session = await betterAuthClient.getSession();
120
+ const session = await getBetterAuthClient().getSession();
80
121
  if (session.data?.session?.token) {
81
122
  debug("Better Auth session found, exchanging for Feathers JWT", {
82
123
  betterAuthUserId: session.data.user?.id,
@@ -105,7 +146,7 @@ const BetterAuthProvider = ({ partnerId }) => {
105
146
  catch {
106
147
  debug("No Better Auth session to restore");
107
148
  }
108
- // 3. Nothing found — show login UI
149
+ // 4. Nothing found — show login UI
109
150
  setIsAuthenticating(false);
110
151
  };
111
152
  restoreSession();
@@ -4,7 +4,6 @@ import { LoginStepBetterAuth } from "./steps/LoginStepBetterAuth.js";
4
4
  import { debugB3React } from "../../../../shared/utils/debug.js";
5
5
  import { useCallback, useEffect, useRef, useState } from "react";
6
6
  import { useActiveAccount } from "thirdweb/react";
7
- import { SignInWithB3Privy } from "./SignInWithB3Privy.js";
8
7
  import { LoginStep, LoginStepContainer } from "./steps/LoginStep.js";
9
8
  import { LoginStepCustom } from "./steps/LoginStepCustom.js";
10
9
  const debug = debugB3React("SignInWithB3Flow");
@@ -251,10 +250,7 @@ export function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySucce
251
250
  }
252
251
  else {
253
252
  // Custom strategy
254
- if (strategies?.[0] === "privy") {
255
- content = _jsx(SignInWithB3Privy, { onSuccess: handleLoginSuccess, chain: chain });
256
- }
257
- else if (strategies) {
253
+ if (strategies) {
258
254
  // Strategies are explicitly provided
259
255
  content = (_jsx(LoginStepCustom, { strategies: strategies, chain: chain, onSuccess: handleLoginSuccess, onError: onError, automaticallySetFirstEoa: !!automaticallySetFirstEoa }));
260
256
  }
@@ -2,10 +2,11 @@ import { Chain } from "thirdweb";
2
2
  import { SingleStepAuthArgsType, Wallet } from "thirdweb/wallets";
3
3
  type WalletType = Wallet["id"];
4
4
  type StrategyType = SingleStepAuthArgsType["strategy"];
5
- type CustomStrategyType = "basement" | "privy";
5
+ declare const customStrategies: readonly ["basement"];
6
+ type CustomStrategyType = (typeof customStrategies)[number];
6
7
  type AllowedStrategies = StrategyType | WalletType | CustomStrategyType | "email";
7
8
  type NonWalletStrategyType = Exclude<AllowedStrategies, WalletType>;
8
- export declare const allowedStrategies: readonly ["apple", "google", "github", "x", "discord", "email", "guest", "walletConnect", "io.metamask", "com.coinbase.wallet", "basement", "privy"];
9
+ export declare const allowedStrategies: readonly ["apple", "google", "github", "x", "discord", "email", "guest", "walletConnect", "io.metamask", "com.coinbase.wallet", "basement"];
9
10
  export type AllowedStrategy = (typeof allowedStrategies)[number];
10
11
  export declare function isWalletType(strategy: AllowedStrategies): strategy is WalletType;
11
12
  export declare function isStrategyType(strategy: AllowedStrategies): strategy is NonWalletStrategyType;
@@ -1,6 +1,5 @@
1
1
  import { createWallet } from "thirdweb/wallets";
2
- const customStrategies = ["basement", "privy"];
3
- // type CustomStrategy = (typeof customStrategies)[number];
2
+ const customStrategies = ["basement"];
4
3
  export const allowedStrategies = [
5
4
  // Auth strategies
6
5
  "apple",
@@ -15,7 +14,6 @@ export const allowedStrategies = [
15
14
  "io.metamask",
16
15
  "com.coinbase.wallet",
17
16
  // Custom strategies
18
- // TODO: Audit we don't use "privy" directly anymore
19
17
  ...customStrategies,
20
18
  ];
21
19
  export function isWalletType(strategy) {
@@ -14,7 +14,6 @@ export { PermissionItem } from "./SignInWithB3/components/PermissionItem";
14
14
  export { WalletRow } from "./SignInWithB3/components/WalletRow";
15
15
  export { SignInWithB3 } from "./SignInWithB3/SignInWithB3";
16
16
  export { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow";
17
- export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy";
18
17
  export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep";
19
18
  export { getConnectOptionsFromStrategy, isWalletType, type AllowedStrategy } from "./SignInWithB3/utils/signInUtils";
20
19
  export { ManageAccount } from "./ManageAccount/ManageAccount";
@@ -16,7 +16,6 @@ export { PermissionItem } from "./SignInWithB3/components/PermissionItem.js";
16
16
  export { WalletRow } from "./SignInWithB3/components/WalletRow.js";
17
17
  export { SignInWithB3 } from "./SignInWithB3/SignInWithB3.js";
18
18
  export { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow.js";
19
- export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy.js";
20
19
  export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep.js";
21
20
  export { getConnectOptionsFromStrategy, isWalletType } from "./SignInWithB3/utils/signInUtils.js";
22
21
  // ManageAccount Components
@@ -17,7 +17,6 @@ export { useFirstEOA } from "./useFirstEOA";
17
17
  export { useGetAllTWSigners, type TWSignerWithMetadata } from "./useGetAllTWSigners";
18
18
  export { useGetGeo } from "./useGetGeo";
19
19
  export { useGlobalAccount } from "./useGlobalAccount";
20
- export { useHandleConnectWithPrivy } from "./useHandleConnectWithPrivy";
21
20
  export { useHasMounted } from "./useHasMounted";
22
21
  export { useIsMobile } from "./useIsMobile";
23
22
  export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
@@ -17,7 +17,6 @@ export { useFirstEOA } from "./useFirstEOA.js";
17
17
  export { useGetAllTWSigners } from "./useGetAllTWSigners.js";
18
18
  export { useGetGeo } from "./useGetGeo.js";
19
19
  export { useGlobalAccount } from "./useGlobalAccount.js";
20
- export { useHandleConnectWithPrivy } from "./useHandleConnectWithPrivy.js";
21
20
  export { useHasMounted } from "./useHasMounted.js";
22
21
  export { useIsMobile } from "./useIsMobile.js";
23
22
  export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect.js";
@@ -2,7 +2,7 @@ import app from "../../../global-account/app.js";
2
2
  import { useAuthStore, useB3Config } from "../../../global-account/react/index.js";
3
3
  import { debugB3React } from "../../../shared/utils/debug.js";
4
4
  import { useCallback } from "react";
5
- import { betterAuthClient } from "../../better-auth-client.js";
5
+ import { getBetterAuthClient } from "../../better-auth-client.js";
6
6
  import { useUserQuery } from "./useUserQuery.js";
7
7
  const debug = debugB3React("useBetterAuth");
8
8
  /** Thrown when email verification is required before the user can sign in. */
@@ -49,7 +49,7 @@ export function useBetterAuth() {
49
49
  setHasStartedConnecting(true);
50
50
  setIsAuthenticating(true);
51
51
  try {
52
- const result = await betterAuthClient.signIn.email({ email, password });
52
+ const result = await getBetterAuthClient().signIn.email({ email, password });
53
53
  if (result.error) {
54
54
  throw new Error(result.error.message || "Sign in failed");
55
55
  }
@@ -70,7 +70,7 @@ export function useBetterAuth() {
70
70
  setHasStartedConnecting(true);
71
71
  setIsAuthenticating(true);
72
72
  try {
73
- const result = await betterAuthClient.signUp.email({ email, password, name });
73
+ const result = await getBetterAuthClient().signUp.email({ email, password, name });
74
74
  if (result.error) {
75
75
  throw new Error(result.error.message || "Sign up failed");
76
76
  }
@@ -79,7 +79,7 @@ export function useBetterAuth() {
79
79
  // requireEmailVerification is enabled — send verification email with
80
80
  // a callbackURL Better Auth redirects to after server-side verify.
81
81
  // Pass verifyCallbackURL to land on a dedicated confirmation page.
82
- await betterAuthClient.sendVerificationEmail({
82
+ await getBetterAuthClient().sendVerificationEmail({
83
83
  email,
84
84
  callbackURL: verifyCallbackURL || `${window.location.origin}?authStrategy=better-auth`,
85
85
  });
@@ -98,7 +98,7 @@ export function useBetterAuth() {
98
98
  setHasStartedConnecting(true);
99
99
  setIsAuthenticating(true);
100
100
  try {
101
- const result = await betterAuthClient.signIn.social({
101
+ const result = await getBetterAuthClient().signIn.social({
102
102
  provider,
103
103
  callbackURL: window.location.href,
104
104
  });
@@ -116,7 +116,7 @@ export function useBetterAuth() {
116
116
  }, [setIsAuthenticating, setHasStartedConnecting]);
117
117
  const requestPasswordReset = useCallback(async (email, redirectTo) => {
118
118
  debug("Requesting password reset", { email });
119
- const result = await betterAuthClient.requestPasswordReset({
119
+ const result = await getBetterAuthClient().requestPasswordReset({
120
120
  email,
121
121
  redirectTo,
122
122
  });
@@ -128,7 +128,7 @@ export function useBetterAuth() {
128
128
  }, []);
129
129
  const resetPassword = useCallback(async (newPassword, token) => {
130
130
  debug("Resetting password");
131
- const result = await betterAuthClient.resetPassword({
131
+ const result = await getBetterAuthClient().resetPassword({
132
132
  newPassword,
133
133
  token,
134
134
  });
@@ -145,6 +145,6 @@ export function useBetterAuth() {
145
145
  requestPasswordReset,
146
146
  resetPassword,
147
147
  exchangeForFeathersJWT,
148
- betterAuthClient,
148
+ betterAuthClient: getBetterAuthClient(),
149
149
  };
150
150
  }
@@ -3,9 +3,13 @@
3
3
  */
4
4
  type ObjectId = string;
5
5
  interface PartnerIds {
6
+ /** @deprecated Privy is no longer used for authentication. This field exists for legacy data compatibility only. */
6
7
  privyId?: string;
7
8
  thirdwebId?: string;
8
9
  }
10
+ /**
11
+ * @deprecated Privy is no longer used for authentication. This type exists for legacy data compatibility only.
12
+ */
9
13
  interface PrivyLinkedAccount {
10
14
  type: string;
11
15
  address?: string;
@@ -45,6 +49,7 @@ interface User {
45
49
  createdAt: number;
46
50
  updatedAt: number;
47
51
  partnerIds: PartnerIds;
52
+ /** @deprecated Privy is no longer used for authentication. This field exists for legacy data compatibility only. */
48
53
  privyLinkedAccounts?: PrivyLinkedAccount[];
49
54
  twProfiles?: TWProfile[];
50
55
  }
@@ -1,6 +1,14 @@
1
1
  import { ClientApplication } from "@b3dotfun/b3-api";
2
2
  import { AuthenticationClient } from "@feathersjs/authentication-client";
3
+ /** Default API URL derived from environment variables. */
3
4
  export declare const B3_API_URL: string;
5
+ /**
6
+ * Override the B3 API URL at runtime. Called by `B3Provider` when an
7
+ * `apiUrl` prop is provided. Pass `null` to revert to the default.
8
+ */
9
+ export declare function setB3ApiUrl(url: string | null): void;
10
+ /** Get the current B3 API URL (prefers runtime override, then env var). */
11
+ export declare function getB3ApiUrl(): string;
4
12
  export declare const authenticate: (app: ClientApplication, accessToken: string, identityToken: string, params?: Record<string, any>) => Promise<import("@feathersjs/authentication").AuthenticationResult | null>;
5
13
  export declare class MyAuthenticationClient extends AuthenticationClient {
6
14
  getFromLocation(location: any): Promise<any>;
@@ -940,6 +940,14 @@ export declare function createB3BetterAuthClient(baseURL?: string): {
940
940
  };
941
941
  };
942
942
  };
943
+ /** Get the shared BetterAuth client, creating it if needed. */
944
+ export declare function getBetterAuthClient(): B3BetterAuthClient;
945
+ /** Force-recreate the client on next access (e.g. after API URL change). */
946
+ export declare function resetBetterAuthClient(): void;
947
+ /**
948
+ * @deprecated Use `getBetterAuthClient()` instead. This static singleton
949
+ * does not reflect runtime API URL changes via `B3Provider apiUrl` prop.
950
+ */
943
951
  export declare const betterAuthClient: {
944
952
  signIn: {
945
953
  social: <FetchOptions extends import("@better-auth/core").ClientFetchOption<Partial<{
@@ -1,5 +1,7 @@
1
1
  import { ClientApplication } from "@b3dotfun/b3-api";
2
2
  export type ClientType = "socket" | "rest";
3
+ /** Reset all cached clients (called when API URL changes). */
4
+ export declare function resetClients(): void;
3
5
  /**
4
6
  * Sets the active client type and creates the appropriate client
5
7
  *
@@ -10,7 +10,7 @@ import { ClientType } from "../../../client-manager";
10
10
  /**
11
11
  * Main B3Provider component
12
12
  */
13
- export declare function B3Provider({ theme, children, accountOverride, environment, automaticallySetFirstEoa, defaultEoaProvider, simDuneApiKey, toaster: _toaster, clientType, rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors, createClientReferenceId, defaultPermissions, disableBSMNTAuthentication, queryClient, authStrategy, }: {
13
+ export declare function B3Provider({ theme, children, accountOverride, environment, automaticallySetFirstEoa, defaultEoaProvider, simDuneApiKey, toaster: _toaster, clientType, rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors, createClientReferenceId, defaultPermissions, disableBSMNTAuthentication, queryClient, authStrategy, apiUrl, }: {
14
14
  theme: "light" | "dark";
15
15
  children: React.ReactNode;
16
16
  accountOverride?: Account;
@@ -39,4 +39,13 @@ export declare function B3Provider({ theme, children, accountOverride, environme
39
39
  queryClient?: QueryClient;
40
40
  /** Auth strategy: "thirdweb" (default, ecosystem wallet) or "better-auth" (email/password via Better Auth) */
41
41
  authStrategy?: AuthStrategy;
42
+ /**
43
+ * Override the B3 API URL. When provided, all SDK requests (auth, Feathers,
44
+ * BetterAuth) will use this URL instead of the `NEXT_PUBLIC_B3_API` env var.
45
+ *
46
+ * Useful for local development: pass `http://localhost:3031` to route
47
+ * OAuth callbacks and session checks through your local B3 API.
48
+ * If omitted, defaults to `NEXT_PUBLIC_B3_API` or `https://api.b3.fun`.
49
+ */
50
+ apiUrl?: string;
42
51
  }): import("react/jsx-runtime").JSX.Element;
@@ -2,10 +2,11 @@ import { Chain } from "thirdweb";
2
2
  import { SingleStepAuthArgsType, Wallet } from "thirdweb/wallets";
3
3
  type WalletType = Wallet["id"];
4
4
  type StrategyType = SingleStepAuthArgsType["strategy"];
5
- type CustomStrategyType = "basement" | "privy";
5
+ declare const customStrategies: readonly ["basement"];
6
+ type CustomStrategyType = (typeof customStrategies)[number];
6
7
  type AllowedStrategies = StrategyType | WalletType | CustomStrategyType | "email";
7
8
  type NonWalletStrategyType = Exclude<AllowedStrategies, WalletType>;
8
- export declare const allowedStrategies: readonly ["apple", "google", "github", "x", "discord", "email", "guest", "walletConnect", "io.metamask", "com.coinbase.wallet", "basement", "privy"];
9
+ export declare const allowedStrategies: readonly ["apple", "google", "github", "x", "discord", "email", "guest", "walletConnect", "io.metamask", "com.coinbase.wallet", "basement"];
9
10
  export type AllowedStrategy = (typeof allowedStrategies)[number];
10
11
  export declare function isWalletType(strategy: AllowedStrategies): strategy is WalletType;
11
12
  export declare function isStrategyType(strategy: AllowedStrategies): strategy is NonWalletStrategyType;
@@ -14,7 +14,6 @@ export { PermissionItem } from "./SignInWithB3/components/PermissionItem";
14
14
  export { WalletRow } from "./SignInWithB3/components/WalletRow";
15
15
  export { SignInWithB3 } from "./SignInWithB3/SignInWithB3";
16
16
  export { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow";
17
- export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy";
18
17
  export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep";
19
18
  export { getConnectOptionsFromStrategy, isWalletType, type AllowedStrategy } from "./SignInWithB3/utils/signInUtils";
20
19
  export { ManageAccount } from "./ManageAccount/ManageAccount";
@@ -17,7 +17,6 @@ export { useFirstEOA } from "./useFirstEOA";
17
17
  export { useGetAllTWSigners, type TWSignerWithMetadata } from "./useGetAllTWSigners";
18
18
  export { useGetGeo } from "./useGetGeo";
19
19
  export { useGlobalAccount } from "./useGlobalAccount";
20
- export { useHandleConnectWithPrivy } from "./useHandleConnectWithPrivy";
21
20
  export { useHasMounted } from "./useHasMounted";
22
21
  export { useIsMobile } from "./useIsMobile";
23
22
  export { useIsomorphicLayoutEffect } from "./useIsomorphicLayoutEffect";
@@ -3,9 +3,13 @@
3
3
  */
4
4
  type ObjectId = string;
5
5
  interface PartnerIds {
6
+ /** @deprecated Privy is no longer used for authentication. This field exists for legacy data compatibility only. */
6
7
  privyId?: string;
7
8
  thirdwebId?: string;
8
9
  }
10
+ /**
11
+ * @deprecated Privy is no longer used for authentication. This type exists for legacy data compatibility only.
12
+ */
9
13
  interface PrivyLinkedAccount {
10
14
  type: string;
11
15
  address?: string;
@@ -45,6 +49,7 @@ interface User {
45
49
  createdAt: number;
46
50
  updatedAt: number;
47
51
  partnerIds: PartnerIds;
52
+ /** @deprecated Privy is no longer used for authentication. This field exists for legacy data compatibility only. */
48
53
  privyLinkedAccounts?: PrivyLinkedAccount[];
49
54
  twProfiles?: TWProfile[];
50
55
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@b3dotfun/sdk",
3
- "version": "0.1.70-alpha.3",
3
+ "version": "0.1.70-alpha.5",
4
4
  "source": "src/index.ts",
5
5
  "main": "./dist/cjs/index.js",
6
6
  "react-native": "./dist/cjs/index.native.js",
@@ -311,6 +311,7 @@
311
311
  "@feathersjs/socketio-client": "5.0.33",
312
312
  "@feathersjs/typebox": "5.0.33",
313
313
  "@fingerprintjs/fingerprintjs-pro-react": "^2.7.0",
314
+ "@headlessui/react": "^2.2.10",
314
315
  "@hey-api/client-fetch": "0.8.3",
315
316
  "@hey-api/openapi-ts": "0.64.13",
316
317
  "@lottiefiles/dotlottie-react": "0.7.2",
@@ -399,7 +400,6 @@
399
400
  },
400
401
  "peerDependencies": {
401
402
  "@fingerprintjs/fingerprintjs-pro-react": "^2.7.0",
402
- "@privy-io/react-auth": "^2.8.0",
403
403
  "@react-three/postprocessing": "2.16.6",
404
404
  "@tanstack/react-query": "5.55.0",
405
405
  "@wagmi/core": "2.20.3",
package/src/app.shared.ts CHANGED
@@ -4,9 +4,29 @@ import Cookies from "js-cookie";
4
4
  import { B3_AUTH_COOKIE_NAME } from "./shared/constants";
5
5
  import { getSessionDurationDays } from "./shared/utils/session-duration";
6
6
 
7
+ /** Default API URL derived from environment variables. */
7
8
  export const B3_API_URL =
8
9
  process.env.EXPO_PUBLIC_B3_API || process.env.NEXT_PUBLIC_B3_API || process.env.PUBLIC_B3_API || "https://api.b3.fun";
9
10
 
11
+ /**
12
+ * Runtime-overridable API URL. Set by `B3Provider` when an `apiUrl` prop
13
+ * is provided. Falls back to the env-var-derived `B3_API_URL`.
14
+ */
15
+ let _apiUrlOverride: string | null = null;
16
+
17
+ /**
18
+ * Override the B3 API URL at runtime. Called by `B3Provider` when an
19
+ * `apiUrl` prop is provided. Pass `null` to revert to the default.
20
+ */
21
+ export function setB3ApiUrl(url: string | null): void {
22
+ _apiUrlOverride = url;
23
+ }
24
+
25
+ /** Get the current B3 API URL (prefers runtime override, then env var). */
26
+ export function getB3ApiUrl(): string {
27
+ return _apiUrlOverride || B3_API_URL;
28
+ }
29
+
10
30
  export const authenticate = async (
11
31
  app: ClientApplication,
12
32
  accessToken: string,
@@ -1,11 +1,11 @@
1
1
  import { createAuthClient } from "better-auth/client";
2
- import { B3_API_URL } from "../app.shared";
2
+ import { getB3ApiUrl } from "../app.shared";
3
3
 
4
4
  export type B3BetterAuthClient = ReturnType<typeof createB3BetterAuthClient>;
5
5
 
6
- export function createB3BetterAuthClient(baseURL: string = B3_API_URL) {
6
+ export function createB3BetterAuthClient(baseURL?: string) {
7
7
  return createAuthClient({
8
- baseURL,
8
+ baseURL: baseURL ?? getB3ApiUrl(),
9
9
  basePath: "/auth",
10
10
  fetchOptions: {
11
11
  credentials: "include",
@@ -13,5 +13,29 @@ export function createB3BetterAuthClient(baseURL: string = B3_API_URL) {
13
13
  });
14
14
  }
15
15
 
16
- // Default singleton for standard usage
16
+ // Lazily-initialized singleton. Recreated when the API URL changes via
17
+ // `resetBetterAuthClient()` (called by B3Provider when `apiUrl` changes).
18
+ let _client: B3BetterAuthClient | null = null;
19
+ let _clientUrl: string | null = null;
20
+
21
+ /** Get the shared BetterAuth client, creating it if needed. */
22
+ export function getBetterAuthClient(): B3BetterAuthClient {
23
+ const url = getB3ApiUrl();
24
+ if (!_client || _clientUrl !== url) {
25
+ _client = createB3BetterAuthClient(url);
26
+ _clientUrl = url;
27
+ }
28
+ return _client;
29
+ }
30
+
31
+ /** Force-recreate the client on next access (e.g. after API URL change). */
32
+ export function resetBetterAuthClient(): void {
33
+ _client = null;
34
+ _clientUrl = null;
35
+ }
36
+
37
+ /**
38
+ * @deprecated Use `getBetterAuthClient()` instead. This static singleton
39
+ * does not reflect runtime API URL changes via `B3Provider apiUrl` prop.
40
+ */
17
41
  export const betterAuthClient = createB3BetterAuthClient();