diff --git a/packages/thirdweb/src/exports/react.native.ts b/packages/thirdweb/src/exports/react.native.ts index 793031d00d5..2a63d4a9e21 100644 --- a/packages/thirdweb/src/exports/react.native.ts +++ b/packages/thirdweb/src/exports/react.native.ts @@ -9,10 +9,11 @@ export type { // wallet hooks export { useActiveWallet } from "../react/core/hooks/wallets/useActiveWallet.js"; -export { useAdminWallet } from "../react/core/hooks/wallets/useAdminWallet.js"; export { useActiveWalletChain } from "../react/core/hooks/wallets/useActiveWalletChain.js"; export { useActiveWalletConnectionStatus } from "../react/core/hooks/wallets/useActiveWalletConnectionStatus.js"; export { useActiveAccount } from "../react/core/hooks/wallets/useActiveAccount.js"; +export { useAdminWallet } from "../react/core/hooks/wallets/useAdminWallet.js"; +export { useAuthToken } from "../react/core/hooks/wallets/useAuthToken.js"; export { useAutoConnect } from "../react/native/hooks/wallets/useAutoConnect.js"; export { useConnect } from "../react/core/hooks/wallets/useConnect.js"; export { useConnectedWallets } from "../react/core/hooks/wallets/useConnectedWallets.js"; diff --git a/packages/thirdweb/src/exports/react.ts b/packages/thirdweb/src/exports/react.ts index 0cd98f8e2db..5434611744b 100644 --- a/packages/thirdweb/src/exports/react.ts +++ b/packages/thirdweb/src/exports/react.ts @@ -40,10 +40,11 @@ export type { MediaRendererProps } from "../react/web/ui/MediaRenderer/types.js" // wallet hooks export { useActiveWallet } from "../react/core/hooks/wallets/useActiveWallet.js"; -export { useAdminWallet } from "../react/core/hooks/wallets/useAdminWallet.js"; export { useActiveWalletChain } from "../react/core/hooks/wallets/useActiveWalletChain.js"; export { useActiveWalletConnectionStatus } from "../react/core/hooks/wallets/useActiveWalletConnectionStatus.js"; export { useActiveAccount } from "../react/core/hooks/wallets/useActiveAccount.js"; +export { useAdminWallet } from "../react/core/hooks/wallets/useAdminWallet.js"; +export { useAuthToken } from "../react/core/hooks/wallets/useAuthToken.js"; export { useAutoConnect } from "../react/web/hooks/wallets/useAutoConnect.js"; export { useConnect } from "../react/core/hooks/wallets/useConnect.js"; export { useConnectedWallets } from "../react/core/hooks/wallets/useConnectedWallets.js"; diff --git a/packages/thirdweb/src/react/core/hooks/wallets/useAuthToken.ts b/packages/thirdweb/src/react/core/hooks/wallets/useAuthToken.ts new file mode 100644 index 00000000000..65ce148762c --- /dev/null +++ b/packages/thirdweb/src/react/core/hooks/wallets/useAuthToken.ts @@ -0,0 +1,41 @@ +import { useActiveAccount } from "./useActiveAccount.js"; +import { useActiveWallet } from "./useActiveWallet.js"; + +/** + * A hook that returns the authentication token (JWT) for the currently active wallet. + * This token can be used to authorize API calls to your backend server. + * + * @returns The JWT string if the active wallet is an in-app wallet and matches the active account, null otherwise + * + * @example + * ```tsx + * function MyComponent() { + * const authToken = useAuthToken(); + * + * const fetchData = async () => { + * const response = await fetch('https://api.example.com/data', { + * headers: { + * 'Authorization': `Bearer ${authToken}` + * } + * }); + * // ... handle response + * }; + * } + * ``` + * + * @wallet + */ +export function useAuthToken() { + const activeWallet = useActiveWallet(); + const activeAccount = useActiveAccount(); + // if the active wallet is an in-app wallet and the active account is the same as the active wallet's account, return the auth token for the in-app wallet + if ( + activeWallet?.getAuthToken && + activeAccount && + activeAccount.address === activeWallet.getAccount()?.address + ) { + return activeWallet.getAuthToken(); + } + // all other wallets don't expose an auth token for now + return null; +} diff --git a/packages/thirdweb/src/wallets/in-app/core/interfaces/connector.ts b/packages/thirdweb/src/wallets/in-app/core/interfaces/connector.ts index 5afe7d25df4..5a0cf6e747f 100644 --- a/packages/thirdweb/src/wallets/in-app/core/interfaces/connector.ts +++ b/packages/thirdweb/src/wallets/in-app/core/interfaces/connector.ts @@ -1,5 +1,6 @@ import type { SocialAuthOption } from "../../../../wallets/types.js"; import type { Account } from "../../../interfaces/wallet.js"; +import type { ClientScopedStorage } from "../authentication/client-scoped-storage.js"; import type { AuthArgsType, AuthLoginReturnType, @@ -38,4 +39,5 @@ export interface InAppConnector { linkProfile(args: AuthArgsType): Promise; unlinkProfile(args: Profile): Promise; getProfiles(): Promise; + storage: ClientScopedStorage; } diff --git a/packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts b/packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts index 2a652b5bd71..209fb344f8f 100644 --- a/packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts +++ b/packages/thirdweb/src/wallets/in-app/core/wallet/in-app-core.ts @@ -55,9 +55,11 @@ export function createInAppWallet(args: { let adminAccount: Account | undefined = undefined; // Admin account if smartAccountOptions were provided with connection let chain: Chain | undefined = undefined; let client: ThirdwebClient | undefined; + let authToken: string | null = null; return { id: walletId, + getAuthToken: () => authToken, subscribe: emitter.subscribe, getChain() { if (!chain) { @@ -114,6 +116,12 @@ export function createInAppWallet(args: { account = connectedAccount; adminAccount = _adminAccount; chain = connectedChain; + try { + authToken = await connector.storage.getAuthCookie(); + } catch (error) { + console.error("Failed to retrieve auth token:", error); + authToken = null; + } trackConnect({ client: options.client, ecosystem, @@ -168,6 +176,12 @@ export function createInAppWallet(args: { account = connectedAccount; adminAccount = _adminAccount; chain = connectedChain; + try { + authToken = await connector.storage.getAuthCookie(); + } catch (error) { + console.error("Failed to retrieve auth token:", error); + authToken = null; + } trackConnect({ client: options.client, ecosystem, @@ -194,6 +208,7 @@ export function createInAppWallet(args: { account = undefined; adminAccount = undefined; chain = undefined; + authToken = null; emitter.emit("disconnect", undefined); }, switchChain: async (newChain) => { diff --git a/packages/thirdweb/src/wallets/in-app/native/native-connector.ts b/packages/thirdweb/src/wallets/in-app/native/native-connector.ts index 1db22291ae9..8926e1214e2 100644 --- a/packages/thirdweb/src/wallets/in-app/native/native-connector.ts +++ b/packages/thirdweb/src/wallets/in-app/native/native-connector.ts @@ -29,7 +29,7 @@ type NativeConnectorOptions = { export class InAppNativeConnector implements InAppConnector { private client: ThirdwebClient; private ecosystem?: Ecosystem; - private storage: ClientScopedStorage; + public storage: ClientScopedStorage; private passkeyDomain?: string; private wallet?: IWebWallet; diff --git a/packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts b/packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts index db7ab3124b8..d05686a3777 100644 --- a/packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts +++ b/packages/thirdweb/src/wallets/in-app/web/lib/web-connector.ts @@ -50,7 +50,7 @@ export class InAppWebConnector implements InAppConnector { private client: ThirdwebClient; private ecosystem?: Ecosystem; private querier: InAppWalletIframeCommunicator; - private storage: ClientScopedStorage; + public storage: ClientScopedStorage; private wallet?: IWebWallet; /** diff --git a/packages/thirdweb/src/wallets/interfaces/wallet.ts b/packages/thirdweb/src/wallets/interfaces/wallet.ts index a43b2841d48..9eb62ebd463 100644 --- a/packages/thirdweb/src/wallets/interfaces/wallet.ts +++ b/packages/thirdweb/src/wallets/interfaces/wallet.ts @@ -151,8 +151,18 @@ export type Wallet = { * This is useful for smart wallets to get the underlying personal account */ getAdminAccount?: () => Account | undefined; -}; + /** + * Get the authentication token for the wallet. + * + * This method is not available for on all wallets. This method will be `undefined` if the wallet does not support it. + * @example + * ```ts + * const authToken = await wallet.getAuthToken(); + * ``` + */ + getAuthToken?: () => string | null; +}; /** * Account interface *