diff --git a/.changeset/tender-guests-kiss.md b/.changeset/tender-guests-kiss.md new file mode 100644 index 00000000..43cd998c --- /dev/null +++ b/.changeset/tender-guests-kiss.md @@ -0,0 +1,5 @@ +--- +"@treasure-dev/tdk-react": patch +--- + +Fixed active wallet missing from TDK API client diff --git a/examples/connect-react/src/constants.ts b/examples/connect-react/src/constants.ts deleted file mode 100644 index 2f21afd3..00000000 --- a/examples/connect-react/src/constants.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { getContractAddress } from "@treasure-dev/tdk-core"; -import { toWei } from "thirdweb"; -import { arbitrumSepolia } from "thirdweb/chains"; - -const TREASURY_ADDRESS = "0xE647b2c46365741e85268ceD243113d08F7E00B8"; - -export const SESSION_OPTIONS_BY_CHAIN_ID = { - [arbitrumSepolia.id]: { - backendWallet: import.meta.env.VITE_TDK_BACKEND_WALLET, - approvedTargets: [ - getContractAddress(arbitrumSepolia.id, "MAGIC"), - TREASURY_ADDRESS, - ], - nativeTokenLimitPerTransaction: toWei("1"), - }, -}; diff --git a/examples/connect-react/src/main.tsx b/examples/connect-react/src/main.tsx index 964d5f20..00d1b6de 100644 --- a/examples/connect-react/src/main.tsx +++ b/examples/connect-react/src/main.tsx @@ -1,14 +1,14 @@ import "@treasure-dev/tdk-react/dist/index.css"; import "@treasure-dev/tailwind-config/fonts.css"; -import { treasureTopaz } from "@treasure-dev/tdk-core"; +import { getContractAddress, treasureTopaz } from "@treasure-dev/tdk-core"; import { TreasureProvider } from "@treasure-dev/tdk-react"; import ReactDOM from "react-dom/client"; +import { toWei } from "thirdweb"; import { arbitrumSepolia } from "thirdweb/chains"; import { ThirdwebProvider } from "thirdweb/react"; import { App } from "./App.tsx"; -import { SESSION_OPTIONS_BY_CHAIN_ID } from "./constants"; import "./index.css"; const root = document.getElementById("root"); @@ -27,7 +27,14 @@ if (root) { clientId={import.meta.env.VITE_TDK_CLIENT_ID} ecosystemId={import.meta.env.VITE_TDK_ECOSYSTEM_ID} ecosystemPartnerId={import.meta.env.VITE_TDK_ECOSYSTEM_PARTNER_ID} - sessionOptions={SESSION_OPTIONS_BY_CHAIN_ID[defaultChainId]} + sessionOptions={{ + backendWallet: import.meta.env.VITE_TDK_BACKEND_WALLET, + approvedTargets: [ + getContractAddress(arbitrumSepolia.id, "MAGIC"), + "0xE647b2c46365741e85268ceD243113d08F7E00B8", // Treasury + ], + nativeTokenLimitPerTransaction: toWei("1"), + }} analyticsOptions={{ apiKey: import.meta.env.VITE_TDK_ANALYTICS_API_KEY, appInfo: { diff --git a/packages/react/src/contexts/treasure.tsx b/packages/react/src/contexts/treasure.tsx index 004cdccf..a66355d5 100644 --- a/packages/react/src/contexts/treasure.tsx +++ b/packages/react/src/contexts/treasure.tsx @@ -36,6 +36,7 @@ import { useIsAutoConnecting, useSwitchActiveWalletChain, } from "thirdweb/react"; +import { isZkSyncChain } from "thirdweb/utils"; import { type Wallet, ecosystemWallet } from "thirdweb/wallets"; import { useLauncher } from "../hooks/useLauncher"; @@ -85,6 +86,7 @@ const TreasureProviderInner = ({ }: Props) => { const [isAuthenticating, setIsAuthenticating] = useState(false); const [user, setUser] = useState(); + const [authToken, setAuthToken] = useState(); const [el, setEl] = useState(null); const client = useMemo( () => createTreasureConnectClient({ clientId }), @@ -102,9 +104,18 @@ const TreasureProviderInner = ({ baseUri: apiUri, chainId: chain.id, backendWallet: sessionOptions?.backendWallet, + authToken, client, + activeWallet, }), - [apiUri, chain.id, sessionOptions?.backendWallet, client], + [ + apiUri, + chain.id, + sessionOptions?.backendWallet, + authToken, + client, + activeWallet, + ], ); const contractAddresses = useMemo( @@ -171,12 +182,12 @@ const TreasureProviderInner = ({ (authToken: string) => { tdk.user.me({ overrideAuthToken: authToken }).then((user) => { setUser(user); + setAuthToken(authToken); setStoredAuthToken(authToken); - tdk.setAuthToken(authToken); onConnect?.(user); }); }, - [tdk.user.me, tdk.setAuthToken, onConnect], + [tdk.user.me, onConnect], ); const { isUsingTreasureLauncher, openLauncherAccountModal } = useLauncher({ @@ -201,8 +212,7 @@ const TreasureProviderInner = ({ }); } setUser(undefined); - tdk.clearAuthToken(); - tdk.clearActiveWallet(); + setAuthToken(undefined); clearStoredAuthToken(); activeWallet?.disconnect(); }; @@ -219,33 +229,40 @@ const TreasureProviderInner = ({ return { user: undefined, legacyProfiles: [] }; } - let user: User | undefined; + if (chainId) { + tdk.chainId = chainId; + } + + let nextUser: User | undefined; + let nextAuthToken: string | undefined; let legacyProfiles: LegacyProfile[] = []; - let authToken = getStoredAuthToken(); // Check for existing stored auth token - if (authToken && !skipCurrentUser) { - // Validate if it's expired before attempting to use it - try { - const { exp: authTokenExpirationDate } = decodeAuthToken(authToken); - if (authTokenExpirationDate > Date.now() / 1000) { - setIsAuthenticating(true); - user = await tdk.user.me({ overrideAuthToken: authToken }); + if (!skipCurrentUser) { + const storedAuthToken = getStoredAuthToken(); + if (storedAuthToken) { + // Validate if it's expired before attempting to use it + try { + const { exp: authTokenExpirationDate } = + decodeAuthToken(storedAuthToken); + if (authTokenExpirationDate > Date.now() / 1000) { + setIsAuthenticating(true); + nextUser = await tdk.user.me({ + overrideAuthToken: storedAuthToken, + }); + nextAuthToken = storedAuthToken; + } + } catch (err) { + console.debug( + "[TreasureProvider] Error fetching user with stored auth token:", + err, + ); + // Ignore errors and proceed with login } - } catch (err) { - console.debug( - "[TreasureProvider] Error fetching user with stored auth token:", - err, - ); - // Ignore errors and proceed with login } } - if (chainId) { - tdk.chainId = chainId; - } - - if (!user) { + if (!nextUser) { setIsAuthenticating(true); try { const result = await authenticateWallet({ @@ -255,8 +272,8 @@ const TreasureProviderInner = ({ authOptions?.authTokenDurationSec ?? sessionOptions?.sessionDurationSec, }); - authToken = result.token; - user = result.user; + nextAuthToken = result.token; + nextUser = result.user; legacyProfiles = result.legacyProfiles; } catch (err) { setIsAuthenticating(false); @@ -264,12 +281,18 @@ const TreasureProviderInner = ({ } } - // Set auth token and wallet on TDK so they can be used in future requests - tdk.setAuthToken(authToken as string); - tdk.setActiveWallet(wallet); + if (!nextUser || !nextAuthToken) { + throw new Error("An unknown error occurred during login"); + } + + // Set auth token on this instance of the TDK for the next request + tdk.setAuthToken(nextAuthToken); - // Start user session if configured - if (sessionOptions) { + // Start user session if configured and not on ZKsync chain + if ( + sessionOptions && + !(await isZkSyncChain(chainId ? defineChain(chainId) : chain)) + ) { setIsAuthenticating(true); try { await startUserSession({ @@ -277,7 +300,7 @@ const TreasureProviderInner = ({ wallet, chainId: chainId ?? chain.id, tdk, - sessions: user.sessions, + sessions: nextUser.sessions, options: sessionOptions, }); } catch (err) { @@ -287,8 +310,9 @@ const TreasureProviderInner = ({ } // Update user state - setUser(user); - setStoredAuthToken(authToken as string); + setUser(nextUser); + setAuthToken(nextAuthToken); + setStoredAuthToken(nextAuthToken); if (analyticsOptions?.automaticTrackLogin !== false) { trackCustomEvent({ @@ -306,10 +330,10 @@ const TreasureProviderInner = ({ } // Trigger completion callback - onConnect?.(user); + onConnect?.(nextUser); setIsAuthenticating(false); - return { user, legacyProfiles }; + return { user: nextUser, legacyProfiles }; }; const switchChain = async (chainId: number) => { @@ -322,6 +346,7 @@ const TreasureProviderInner = ({ // Attempt an automatic background connection useAutoConnect({ client, + chain, wallets: [ ecosystemWallet(ecosystemId, { partnerId: ecosystemPartnerId,