@txnlab/use-wallet-web3auth 5.0.0-rc.3 → 5.0.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.
package/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # @txnlab/use-wallet-web3auth
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@txnlab/use-wallet-web3auth)](https://www.npmjs.com/package/@txnlab/use-wallet-web3auth)
4
+ [![License](https://img.shields.io/github/license/TxnLab/use-wallet)](https://github.com/TxnLab/use-wallet/blob/main/LICENSE)
5
+
6
+ Web3Auth adapter for [use-wallet](https://github.com/TxnLab/use-wallet), the Algorand wallet integration library.
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @txnlab/use-wallet @txnlab/use-wallet-web3auth
12
+ ```
13
+
14
+ If you use a framework adapter (`@txnlab/use-wallet-react`, `-vue`, `-solid`, or `-svelte`), install it in place of `@txnlab/use-wallet`.
15
+
16
+ ## Usage
17
+
18
+ ```typescript
19
+ import { WalletManager } from '@txnlab/use-wallet'
20
+ import { web3auth } from '@txnlab/use-wallet-web3auth'
21
+
22
+ const manager = new WalletManager({
23
+ wallets: [web3auth({ clientId: 'your-client-id' })]
24
+ })
25
+ ```
26
+
27
+ Social login authentication (Google, Facebook, X, Discord, and more) via [Web3Auth](https://web3auth.io). Requires a `clientId` from the [Web3Auth Dashboard](https://dashboard.web3auth.io). Supports scoped private key access via `withPrivateKey`. Supports MainNet only.
28
+
29
+ The factory also accepts an optional `metadata` option to override the wallet's display name and icon.
30
+
31
+ ### Visit [txnlab.gitbook.io/use-wallet](https://txnlab.gitbook.io/use-wallet) for docs, guides, and examples!
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import algosdk from "algosdk";
2
2
  import { AdapterConstructorParams, BaseWallet, WalletAccount, WalletMetadata } from "@txnlab/use-wallet/adapter";
3
- import { WalletAdapterConfig } from "@txnlab/use-wallet";
3
+ import { WalletAdapterConfig, WalletFactoryOptions } from "@txnlab/use-wallet";
4
4
 
5
5
  //#region src/adapter.d.ts
6
6
  /**
@@ -247,7 +247,7 @@ declare class Web3AuthAdapter extends BaseWallet<Web3AuthOptions> {
247
247
  //#endregion
248
248
  //#region src/index.d.ts
249
249
  declare const WALLET_ID: "web3auth";
250
- declare function web3auth(options: Web3AuthOptions): WalletAdapterConfig;
250
+ declare function web3auth(options: Web3AuthOptions & WalletFactoryOptions): WalletAdapterConfig;
251
251
  //#endregion
252
252
  export { WALLET_ID, Web3AuthAdapter, type Web3AuthCredentials, type Web3AuthCustomAuth, type Web3AuthOptions, web3auth };
253
253
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -531,11 +531,15 @@ var Web3AuthAdapter = class extends BaseWallet {
531
531
  //#region src/index.ts
532
532
  const WALLET_ID = "web3auth";
533
533
  function web3auth(options) {
534
+ const { metadata, ...adapterOptions } = options;
534
535
  return {
535
536
  id: WALLET_ID,
536
- metadata: Web3AuthAdapter.defaultMetadata,
537
+ metadata: {
538
+ ...Web3AuthAdapter.defaultMetadata,
539
+ ...metadata
540
+ },
537
541
  Adapter: Web3AuthAdapter,
538
- options,
542
+ options: adapterOptions,
539
543
  capabilities: { supportedNetworks: ["mainnet"] }
540
544
  };
541
545
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/icon.ts","../src/adapter.ts","../src/index.ts"],"sourcesContent":["export const icon = `\n<svg viewBox=\"0 0 40 40\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect fill=\"#0364FF\" width=\"40\" height=\"40\" rx=\"8\"/>\n <path fill=\"#FFFFFF\" d=\"M20 8c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12S26.627 8 20 8zm0 21.6c-5.302 0-9.6-4.298-9.6-9.6S14.698 10.4 20 10.4s9.6 4.298 9.6 9.6-4.298 9.6-9.6 9.6zm0-16.8c-3.976 0-7.2 3.224-7.2 7.2s3.224 7.2 7.2 7.2 7.2-3.224 7.2-7.2-3.224-7.2-7.2-7.2zm0 12c-2.651 0-4.8-2.149-4.8-4.8s2.149-4.8 4.8-4.8 4.8 2.149 4.8 4.8-2.149 4.8-4.8 4.8z\"/>\n</svg>\n`\n","/**\n * Web3Auth Wallet Adapter for Algorand\n *\n * SECURITY CONSIDERATIONS:\n * - Web3Auth exposes the raw private key for non-EVM chains like Algorand\n * - This implementation uses SecureKeyContainer to minimize key exposure\n * - Keys are never persisted to localStorage or any storage\n * - Keys are cleared from memory immediately after signing operations\n * - Session resumption requires re-authentication (keys are not cached)\n *\n * @see https://web3auth.io/docs\n */\n\nimport algosdk from 'algosdk'\nimport {\n BaseWallet,\n SecureKeyContainer,\n zeroMemory,\n deriveAlgorandAccountFromEd25519,\n flattenTxnGroup,\n isSignedTxn,\n isTransactionArray,\n type AdapterConstructorParams,\n type WalletAccount,\n type WalletMetadata,\n type WalletState\n} from '@txnlab/use-wallet/adapter'\n\nconst LOCAL_STORAGE_WEB3AUTH_KEY = '@txnlab/use-wallet:v5:web3auth'\n\n/** Metadata persisted to localStorage for Web3Auth session restoration */\ninterface Web3AuthMetadata {\n /** Whether the session was established using Single Factor Auth (SFA) vs modal */\n usingSFA: boolean\n}\n\n// Type definitions for Web3Auth (to avoid requiring the package at compile time)\n// These are minimal type definitions that match the actual Web3Auth API\ninterface IWeb3AuthProvider {\n request<T>(args: { method: string; params?: unknown }): Promise<T>\n}\n\ninterface IWeb3AuthUserInfo {\n email?: string\n name?: string\n profileImage?: string\n verifier?: string\n verifierId?: string\n typeOfLogin?: string\n aggregateVerifier?: string\n}\n\ninterface IWeb3AuthModal {\n init(): Promise<void>\n connect(): Promise<IWeb3AuthProvider | null>\n logout(): Promise<void>\n connected: boolean\n provider: IWeb3AuthProvider | null\n getUserInfo(): Promise<Partial<IWeb3AuthUserInfo>>\n}\n\n// Single Factor Auth SDK interface (for custom JWT auth)\ninterface IWeb3AuthSFA {\n init(): Promise<void>\n connect(params: {\n verifier: string\n verifierId: string\n idToken: string\n }): Promise<IWeb3AuthProvider | null>\n logout(): Promise<void>\n connected: boolean\n provider: IWeb3AuthProvider | null\n}\n\n/**\n * Parameters for custom authentication (e.g., Firebase, custom JWT)\n */\nexport interface Web3AuthCustomAuth {\n /**\n * Custom verifier name configured in Web3Auth dashboard\n */\n verifier: string\n\n /**\n * User identifier (e.g., email, Firebase UID)\n */\n verifierId: string\n\n /**\n * JWT token from your authentication provider (e.g., Firebase ID token)\n */\n idToken: string\n}\n\n/**\n * Credentials returned by getAuthCredentials callback\n */\nexport interface Web3AuthCredentials {\n /**\n * JWT token from your authentication provider (e.g., Firebase ID token)\n */\n idToken: string\n\n /**\n * User identifier (e.g., email, Firebase UID)\n */\n verifierId: string\n\n /**\n * Custom verifier name (optional, uses options.verifier if not provided)\n */\n verifier?: string\n}\n\n/**\n * Web3Auth configuration options\n */\nexport interface Web3AuthOptions {\n /**\n * Web3Auth Client ID from the dashboard\n * @see https://dashboard.web3auth.io\n */\n clientId: string\n\n /**\n * Web3Auth network (mainnet, testnet, sapphire_mainnet, sapphire_devnet, cyan, aqua)\n * @default 'sapphire_mainnet'\n */\n web3AuthNetwork?: 'mainnet' | 'testnet' | 'sapphire_mainnet' | 'sapphire_devnet' | 'cyan' | 'aqua'\n\n /**\n * Login provider to use (google, facebook, twitter, discord, etc.)\n * If not specified, the Web3Auth modal will be shown\n */\n loginProvider?:\n | 'google'\n | 'facebook'\n | 'twitter'\n | 'discord'\n | 'reddit'\n | 'twitch'\n | 'apple'\n | 'line'\n | 'github'\n | 'kakao'\n | 'linkedin'\n | 'weibo'\n | 'wechat'\n | 'email_passwordless'\n | 'sms_passwordless'\n\n /**\n * Login hint for email_passwordless or sms_passwordless\n */\n loginHint?: string\n\n /**\n * UI configuration for the Web3Auth modal\n */\n uiConfig?: {\n appName?: string\n appUrl?: string\n logoLight?: string\n logoDark?: string\n defaultLanguage?: string\n mode?: 'light' | 'dark' | 'auto'\n theme?: Record<string, string>\n }\n\n /**\n * Whether to use the popup flow instead of redirect\n * @default true\n */\n usePopup?: boolean\n\n /**\n * Default verifier name for custom authentication.\n * When set, connect() can be called with just { idToken, verifierId }\n */\n verifier?: string\n\n /**\n * Callback to get fresh authentication credentials when session expires.\n * Required for automatic re-authentication with Single Factor Auth (SFA).\n *\n * If not provided and the session expires, signTransactions() will throw\n * an error requiring the user to call connect() with fresh credentials.\n *\n * @example\n * ```typescript\n * getAuthCredentials: async () => {\n * const user = firebase.auth().currentUser\n * if (!user) throw new Error('Not logged in')\n * const idToken = await user.getIdToken(true)\n * return { idToken, verifierId: user.email || user.uid }\n * }\n * ```\n */\n getAuthCredentials?: () => Promise<Web3AuthCredentials>\n}\n\nimport { icon } from './icon'\n\nconst ICON = `data:image/svg+xml;base64,${btoa(icon)}`\n\nexport class Web3AuthAdapter extends BaseWallet<Web3AuthOptions> {\n private web3auth: IWeb3AuthModal | null = null\n private web3authSFA: IWeb3AuthSFA | null = null\n private userInfo: Partial<IWeb3AuthUserInfo> | null = null\n\n /**\n * SECURITY: We store only the address, NEVER the private key.\n * Keys are fetched fresh from Web3Auth and immediately cleared after use.\n */\n private _address: string | null = null\n\n /** Track which SDK is currently in use */\n private usingSFA: boolean = false\n\n constructor(params: AdapterConstructorParams<Web3AuthOptions>) {\n super(params)\n\n if (!params.options?.clientId) {\n this.logger.error('Missing required option: clientId')\n throw new Error('Missing required option: clientId')\n }\n\n // Apply defaults\n this.options = {\n web3AuthNetwork: 'sapphire_mainnet',\n usePopup: true,\n ...params.options\n }\n }\n\n static defaultMetadata: WalletMetadata = {\n name: 'Web3Auth',\n icon: ICON\n }\n\n // ---------- Metadata Persistence ----------------------------------- //\n\n private loadMetadata(): Web3AuthMetadata | null {\n if (typeof localStorage === 'undefined') return null\n const data = localStorage.getItem(LOCAL_STORAGE_WEB3AUTH_KEY)\n if (!data) return null\n try {\n return JSON.parse(data) as Web3AuthMetadata\n } catch {\n return null\n }\n }\n\n private saveMetadata(): void {\n if (typeof localStorage === 'undefined') return\n const metadata: Web3AuthMetadata = { usingSFA: this.usingSFA }\n localStorage.setItem(LOCAL_STORAGE_WEB3AUTH_KEY, JSON.stringify(metadata))\n }\n\n private clearMetadata(): void {\n if (typeof localStorage === 'undefined') return\n localStorage.removeItem(LOCAL_STORAGE_WEB3AUTH_KEY)\n }\n\n // ---------- Client Initialization ---------------------------------- //\n\n /**\n * Initialize the Web3Auth client (v10 Modal SDK)\n */\n private async initializeClient(): Promise<IWeb3AuthModal> {\n this.logger.info('Initializing Web3Auth client...')\n\n let Web3Auth: any\n\n let WEB3AUTH_NETWORK: any\n\n try {\n // Dynamic import - @web3auth/modal is a dependency\n const modal = await import('@web3auth/modal')\n Web3Auth = modal.Web3Auth\n WEB3AUTH_NETWORK = modal.WEB3AUTH_NETWORK\n } catch (error) {\n this.logger.error('Failed to load Web3Auth.', error)\n throw new Error('Web3Auth package not found. Please install @web3auth/modal')\n }\n\n const networkMap: Record<string, string> = {\n mainnet: WEB3AUTH_NETWORK.MAINNET,\n testnet: WEB3AUTH_NETWORK.TESTNET,\n sapphire_mainnet: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,\n sapphire_devnet: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,\n cyan: WEB3AUTH_NETWORK.CYAN,\n aqua: WEB3AUTH_NETWORK.AQUA\n }\n\n // v10: Chain config and provider are handled internally for non-EVM chains.\n // Only clientId, web3AuthNetwork, and uiConfig are needed.\n const web3auth = new Web3Auth({\n clientId: this.options.clientId,\n web3AuthNetwork: networkMap[this.options.web3AuthNetwork || 'sapphire_mainnet'] as any,\n uiConfig: this.options.uiConfig\n })\n\n await web3auth.init()\n this.web3auth = web3auth\n this.logger.info('Web3Auth client initialized')\n\n return web3auth\n }\n\n /**\n * Initialize the Web3Auth Single Factor Auth client for custom JWT authentication.\n * SFA SDK is still at v9 and requires CommonPrivateKeyProvider with chain config.\n */\n private async initializeSFAClient(): Promise<IWeb3AuthSFA> {\n this.logger.info('Initializing Web3Auth Single Factor Auth client...')\n\n let Web3Auth: any\n\n let WEB3AUTH_NETWORK: any\n\n let CommonPrivateKeyProvider: any\n\n try {\n // Dynamic imports\n const sfa = await import('@web3auth/single-factor-auth')\n Web3Auth = sfa.Web3Auth\n // Import WEB3AUTH_NETWORK from @web3auth/modal (v10 re-exports it)\n const modal = await import('@web3auth/modal')\n WEB3AUTH_NETWORK = modal.WEB3AUTH_NETWORK\n const baseProvider = await import('@web3auth/base-provider')\n CommonPrivateKeyProvider = baseProvider.CommonPrivateKeyProvider\n } catch {\n this.logger.error(\n 'Failed to load Web3Auth SFA. Make sure @web3auth/single-factor-auth ' +\n 'and @web3auth/base-provider are installed.'\n )\n throw new Error(\n 'Web3Auth SFA packages not found. Please install @web3auth/single-factor-auth ' +\n 'and @web3auth/base-provider'\n )\n }\n\n const chainConfig = {\n chainNamespace: 'other',\n chainId: 'algorand',\n rpcTarget: 'https://mainnet-api.algonode.cloud',\n displayName: 'Algorand',\n blockExplorerUrl: 'https://lora.algokit.io/mainnet',\n ticker: 'ALGO',\n tickerName: 'Algorand'\n }\n\n const networkMap: Record<string, string> = {\n mainnet: WEB3AUTH_NETWORK.MAINNET,\n testnet: WEB3AUTH_NETWORK.TESTNET,\n sapphire_mainnet: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,\n sapphire_devnet: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,\n cyan: WEB3AUTH_NETWORK.CYAN,\n aqua: WEB3AUTH_NETWORK.AQUA\n }\n\n // SFA v9 still requires CommonPrivateKeyProvider for non-EVM chains\n const privateKeyProvider = new CommonPrivateKeyProvider({\n config: { chainConfig }\n })\n\n const web3authSFA = new Web3Auth({\n clientId: this.options.clientId,\n web3AuthNetwork: networkMap[this.options.web3AuthNetwork || 'sapphire_mainnet'] as any,\n privateKeyProvider\n })\n\n await web3authSFA.init()\n this.web3authSFA = web3authSFA\n this.logger.info('Web3Auth SFA client initialized')\n\n return web3authSFA\n }\n\n // ---------- Secure Key Handling ------------------------------------ //\n\n /**\n * SECURITY: Fetch the private key from Web3Auth and return it in a SecureKeyContainer.\n * The caller MUST call container.clear() when done.\n *\n * @returns SecureKeyContainer holding the private key\n */\n private async getSecureKey(): Promise<SecureKeyContainer> {\n // Get the provider from either the modal SDK or SFA SDK\n const provider = this.usingSFA ? this.web3authSFA?.provider : this.web3auth?.provider\n\n if (!provider) {\n throw new Error('Web3Auth not connected')\n }\n\n this.logger.debug('Fetching private key from Web3Auth...')\n\n // Request the private key from Web3Auth\n // For non-EVM chains, Web3Auth returns the raw ed25519 private key\n const privateKeyHex = await provider.request<string>({\n method: 'private_key'\n })\n\n if (!privateKeyHex || typeof privateKeyHex !== 'string') {\n throw new Error('Failed to retrieve private key from Web3Auth')\n }\n\n // Convert hex string to Uint8Array\n const privateKeyBytes = this.hexToBytes(privateKeyHex)\n\n // SECURITY: Immediately clear the hex string from our scope\n // (The original string may still exist in Web3Auth's scope)\n\n // Wrap in SecureKeyContainer for safe handling\n const container = new SecureKeyContainer(privateKeyBytes)\n\n // SECURITY: Zero the local copy now that it's in the container\n zeroMemory(privateKeyBytes)\n\n this.logger.debug('Private key retrieved and secured')\n return container\n }\n\n /**\n * Convert a hex string to Uint8Array\n */\n private hexToBytes(hex: string): Uint8Array {\n // Remove 0x prefix if present\n const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex\n const bytes = new Uint8Array(cleanHex.length / 2)\n for (let i = 0; i < cleanHex.length; i += 2) {\n bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16)\n }\n return bytes\n }\n\n // ---------- Session Management ------------------------------------- //\n\n /**\n * Check if Web3Auth is currently connected with a valid session\n */\n private isWeb3AuthConnected(): boolean {\n if (this.usingSFA) {\n return Boolean(this.web3authSFA?.connected && this.web3authSFA?.provider)\n }\n return Boolean(this.web3auth?.connected && this.web3auth?.provider)\n }\n\n /**\n * Ensure Web3Auth is connected and ready for signing.\n * Re-authenticates if the session has expired.\n *\n * This is called lazily when signTransactions() is invoked.\n */\n private async ensureConnected(): Promise<void> {\n if (this.isWeb3AuthConnected()) {\n this.logger.debug('Web3Auth session still valid')\n return\n }\n\n this.logger.info('Web3Auth session expired or not initialized, re-authenticating...')\n\n if (this.usingSFA) {\n await this.reconnectSFA()\n } else {\n await this.reconnectModal()\n }\n }\n\n /**\n * Re-authenticate using Single Factor Auth (Firebase, custom JWT)\n *\n * Requires getAuthCredentials callback to be configured in options.\n * If the callback returns credentials for a different user, this will\n * disconnect the current wallet (the user logged out and back in as someone else).\n */\n private async reconnectSFA(): Promise<void> {\n if (!this.options.getAuthCredentials) {\n this.logger.error('Cannot re-authenticate: getAuthCredentials callback not configured')\n throw new Error(\n 'Web3Auth session expired. Configure getAuthCredentials option for automatic re-auth, ' +\n 'or call disconnect() and connect() with fresh credentials.'\n )\n }\n\n this.logger.info('Getting fresh credentials for SFA re-authentication...')\n\n let credentials: Web3AuthCredentials\n try {\n credentials = await this.options.getAuthCredentials()\n } catch (error: any) {\n // User is no longer authenticated with the identity provider (e.g., logged out of Firebase)\n this.logger.warn('Failed to get auth credentials, user may have logged out:', error.message)\n this.onDisconnect()\n throw new Error('Authentication provider session expired. Please log in again.')\n }\n\n // Initialize SFA client if needed\n const web3authSFA = this.web3authSFA || (await this.initializeSFAClient())\n\n // Logout first if still connected (stale session)\n if (web3authSFA.connected) {\n try {\n await web3authSFA.logout()\n } catch {\n // Ignore logout errors\n }\n }\n\n const verifier = credentials.verifier || this.options.verifier\n if (!verifier) {\n throw new Error('No verifier configured for SFA authentication')\n }\n\n // Connect with fresh credentials\n const provider = await web3authSFA.connect({\n verifier,\n verifierId: credentials.verifierId,\n idToken: credentials.idToken\n })\n\n if (!provider) {\n throw new Error('Failed to re-authenticate with Web3Auth SFA')\n }\n\n this.usingSFA = true\n this.saveMetadata()\n\n // Verify we got the same address (same user)\n await this.verifyAddressMatch()\n }\n\n /**\n * Re-authenticate using the Web3Auth modal\n *\n * Shows the Web3Auth login modal for the user to authenticate again.\n * If they log in as a different user, this will disconnect the current wallet.\n */\n private async reconnectModal(): Promise<void> {\n this.logger.info('Showing Web3Auth modal for re-authentication...')\n\n const web3auth = this.web3auth || (await this.initializeClient())\n\n // Logout first if still connected (stale session)\n if (web3auth.connected) {\n try {\n await web3auth.logout()\n } catch {\n // Ignore logout errors\n }\n }\n\n const provider = await web3auth.connect()\n\n if (!provider) {\n throw new Error('Re-authentication cancelled or failed')\n }\n\n this.usingSFA = false\n this.saveMetadata()\n\n // Get updated user info\n this.userInfo = await web3auth.getUserInfo()\n\n // Verify we got the same address (same user)\n await this.verifyAddressMatch()\n }\n\n /**\n * Verify that the current Web3Auth session matches the cached address.\n *\n * If the address doesn't match (user logged in as someone else),\n * this disconnects the wallet entirely -- it's a different identity.\n */\n private async verifyAddressMatch(): Promise<void> {\n const keyContainer = await this.getSecureKey()\n\n try {\n const currentAddress = await keyContainer.useKey(async (secretKey) => {\n const account = await deriveAlgorandAccountFromEd25519(secretKey)\n const addr = account.addr\n zeroMemory(account.sk)\n return addr\n })\n\n if (currentAddress !== this._address) {\n this.logger.warn('Re-authenticated as different user, disconnecting wallet', {\n expected: this._address,\n actual: currentAddress\n })\n\n // Different user = different wallet. Full disconnect required.\n this.onDisconnect()\n\n throw new Error(\n `Re-authenticated as a different account. Expected ${this._address}, ` +\n `got ${currentAddress}. Please connect again with the correct account.`\n )\n }\n\n this.logger.info('Address verified, session restored')\n } finally {\n keyContainer.clear()\n }\n }\n\n // ---------- Public Methods ----------------------------------------- //\n\n /**\n * Connect to Web3Auth\n *\n * @param args - Optional connection arguments\n * @param args.idToken - JWT token for custom authentication (e.g., Firebase ID token)\n * @param args.verifierId - User identifier for custom authentication (e.g., email, uid)\n * @param args.verifier - Custom verifier name (uses options.verifier if not provided)\n *\n * @example\n * // Standard modal connection\n * await wallet.connect()\n *\n * @example\n * // Custom authentication with Firebase\n * await wallet.connect({\n * idToken: firebaseIdToken,\n * verifierId: user.email,\n * verifier: 'my-firebase-verifier'\n * })\n */\n public connect = async (args?: Record<string, any>): Promise<WalletAccount[]> => {\n this.logger.info('Connecting to Web3Auth...')\n\n try {\n let provider: IWeb3AuthProvider | null\n\n // Check if custom authentication params are provided\n const idToken = args?.idToken as string | undefined\n const verifierId = args?.verifierId as string | undefined\n const verifier = (args?.verifier as string | undefined) || this.options.verifier\n\n if (idToken && verifierId) {\n // Custom authentication flow using Single Factor Auth (e.g., Firebase)\n if (!verifier) {\n throw new Error(\n 'Custom authentication requires a verifier. Provide it in connect() args or options.verifier'\n )\n }\n\n this.logger.info('Connecting with custom authentication (SFA)...', {\n verifier,\n verifierId\n })\n\n // Initialize the SFA client\n const web3authSFA = this.web3authSFA || (await this.initializeSFAClient())\n\n // If already connected, logout first to allow reconnection with potentially different credentials\n if (web3authSFA.connected) {\n this.logger.debug('SFA already connected, logging out first...')\n try {\n await web3authSFA.logout()\n } catch {\n // Ignore logout errors\n }\n }\n\n // Connect using Single Factor Auth - no modal, direct connection\n provider = await web3authSFA.connect({\n verifier,\n verifierId,\n idToken\n })\n\n this.usingSFA = true\n\n // SFA doesn't provide getUserInfo, use verifierId as display name\n this.userInfo = { email: verifierId }\n } else {\n // Standard modal connection\n const web3auth = this.web3auth || (await this.initializeClient())\n provider = await web3auth.connect()\n\n this.usingSFA = false\n\n // Get user info for display purposes (modal SDK only)\n this.userInfo = await web3auth.getUserInfo()\n this.logger.debug('User info retrieved', {\n email: this.userInfo.email\n })\n }\n\n if (!provider) {\n throw new Error('Failed to connect to Web3Auth')\n }\n\n // SECURITY: Get the key, derive the address, and immediately clear the key\n const keyContainer = await this.getSecureKey()\n\n try {\n const address = await keyContainer.useKey(async (secretKey) => {\n const account = await deriveAlgorandAccountFromEd25519(secretKey)\n // SECURITY: Zero the derived account's secret key immediately\n const addr = account.addr\n zeroMemory(account.sk)\n return addr\n })\n\n this._address = address\n } finally {\n // SECURITY: Always clear the key container\n keyContainer.clear()\n }\n\n const walletAccount: WalletAccount = {\n name: this.userInfo.name || this.userInfo.email || `${this.metadata.name} Account`,\n address: this._address\n }\n\n const walletState: WalletState = {\n accounts: [walletAccount],\n activeAccount: walletAccount\n }\n\n this.store.addWallet(walletState)\n\n // Save metadata only after successful connection\n this.saveMetadata()\n\n this.logger.info('Connected successfully', { address: this._address })\n return [walletAccount]\n } catch (error: any) {\n this.logger.error('Error connecting to Web3Auth:', error.message)\n throw error\n }\n }\n\n /**\n * Disconnect from Web3Auth\n */\n public disconnect = async (): Promise<void> => {\n this.logger.info('Disconnecting from Web3Auth...')\n\n try {\n if (this.usingSFA && this.web3authSFA?.connected) {\n await this.web3authSFA.logout()\n } else if (this.web3auth?.connected) {\n await this.web3auth.logout()\n }\n } catch (error: any) {\n this.logger.warn('Error during Web3Auth logout:', error.message)\n }\n\n // Clear local state\n this._address = null\n this.userInfo = null\n this.usingSFA = false\n this.clearMetadata()\n this.onDisconnect()\n\n this.logger.info('Disconnected')\n }\n\n /**\n * Resume session from cached state\n *\n * LAZY AUTHENTICATION: We do NOT connect to Web3Auth here.\n * We simply restore the cached address from localStorage.\n * Web3Auth connection is deferred until signTransactions() is called.\n */\n public resumeSession = async (): Promise<void> => {\n try {\n const walletState = this.store.getWalletState()\n\n if (!walletState) {\n this.logger.info('No session to resume')\n return\n }\n\n const storedAccount = walletState.accounts[0]\n\n if (!storedAccount?.address) {\n this.logger.warn('No address found in cached session')\n this.onDisconnect()\n return\n }\n\n // Just restore the cached address - don't initialize Web3Auth\n this._address = storedAccount.address\n this.userInfo = { name: storedAccount.name }\n\n // Restore usingSFA flag from metadata\n const metadata = this.loadMetadata()\n if (metadata) {\n this.usingSFA = metadata.usingSFA\n }\n\n this.logger.info('Session restored from cache (lazy mode)', {\n address: this._address\n })\n } catch (error: any) {\n this.logger.error('Error resuming session:', error.message)\n this.onDisconnect()\n throw error\n }\n }\n\n // ---------- Private Key Access ------------------------------------- //\n\n public canUsePrivateKey = true\n\n /**\n * Provide scoped access to the private key via a callback.\n *\n * The callback receives a 64-byte Algorand secret key (ed25519 seed + public key).\n * The key is a fresh copy that is guaranteed to be zeroed from memory when the\n * callback completes, whether it succeeds or throws.\n *\n * SECURITY: The key is fetched fresh from Web3Auth for each call and never cached.\n *\n * @example\n * ```typescript\n * const result = await wallet.withPrivateKey(async (secretKey) => {\n * // secretKey is a 64-byte Uint8Array\n * // Use for custom signing, authentication, etc.\n * return doSomethingWith(secretKey)\n * })\n * // secretKey is zeroed at this point\n * ```\n */\n public withPrivateKey = async <T>(\n callback: (secretKey: Uint8Array) => Promise<T>\n ): Promise<T> => {\n this.logger.debug('withPrivateKey: Providing private key access...')\n\n // Ensure Web3Auth is connected (re-authenticates if session expired)\n await this.ensureConnected()\n\n // SECURITY: Fetch key, derive Algorand account, provide copy to consumer\n const keyContainer = await this.getSecureKey()\n\n try {\n return await keyContainer.useKey(async (secretKey) => {\n const account = await deriveAlgorandAccountFromEd25519(secretKey)\n\n // Create a copy for the consumer\n const skCopy = new Uint8Array(account.sk)\n\n // SECURITY: Zero the derived account's secret key immediately\n zeroMemory(account.sk)\n\n try {\n return await callback(skCopy)\n } finally {\n // SECURITY: Always zero the consumer's copy\n zeroMemory(skCopy)\n }\n })\n } finally {\n // SECURITY: Always clear the key container\n keyContainer.clear()\n }\n }\n\n // ---------- Transaction Signing ------------------------------------ //\n\n /**\n * Process transactions for signing\n */\n private processTxns(\n txnGroup: algosdk.Transaction[],\n indexesToSign?: number[]\n ): algosdk.Transaction[] {\n const txnsToSign: algosdk.Transaction[] = []\n\n txnGroup.forEach((txn, index) => {\n const isIndexMatch = !indexesToSign || indexesToSign.includes(index)\n const signer = txn.sender.toString()\n const canSignTxn = signer === this._address\n\n if (isIndexMatch && canSignTxn) {\n txnsToSign.push(txn)\n }\n })\n\n return txnsToSign\n }\n\n /**\n * Process encoded transactions for signing\n */\n private processEncodedTxns(\n txnGroup: Uint8Array[],\n indexesToSign?: number[]\n ): algosdk.Transaction[] {\n const txnsToSign: algosdk.Transaction[] = []\n\n txnGroup.forEach((txnBuffer, index) => {\n const decodedObj = algosdk.msgpackRawDecode(txnBuffer)\n const isSigned = isSignedTxn(decodedObj)\n\n const txn: algosdk.Transaction = isSigned\n ? algosdk.decodeSignedTransaction(txnBuffer).txn\n : algosdk.decodeUnsignedTransaction(txnBuffer)\n\n const isIndexMatch = !indexesToSign || indexesToSign.includes(index)\n const signer = txn.sender.toString()\n const canSignTxn = !isSigned && signer === this._address\n\n if (isIndexMatch && canSignTxn) {\n txnsToSign.push(txn)\n }\n })\n\n return txnsToSign\n }\n\n /**\n * Sign transactions\n *\n * LAZY AUTHENTICATION: If the Web3Auth session has expired, this will\n * automatically re-authenticate before signing.\n *\n * SECURITY: The private key is fetched fresh, used for signing,\n * and immediately cleared from memory. The key is never stored\n * between signing operations.\n */\n public signTransactions = async <T extends algosdk.Transaction[] | Uint8Array[]>(\n txnGroup: T | T[],\n indexesToSign?: number[]\n ): Promise<(Uint8Array | null)[]> => {\n try {\n this.logger.debug('Signing transactions...', {\n txnGroup,\n indexesToSign\n })\n\n // Ensure Web3Auth is connected (re-authenticates if session expired)\n await this.ensureConnected()\n\n let txnsToSign: algosdk.Transaction[] = []\n\n // Determine type and process transactions for signing\n if (isTransactionArray(txnGroup)) {\n const flatTxns: algosdk.Transaction[] = flattenTxnGroup(txnGroup)\n txnsToSign = this.processTxns(flatTxns, indexesToSign)\n } else {\n const flatTxns: Uint8Array[] = flattenTxnGroup(txnGroup as Uint8Array[])\n txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign)\n }\n\n if (txnsToSign.length === 0) {\n this.logger.debug('No transactions to sign')\n return []\n }\n\n // SECURITY: Fetch key, sign, and immediately clear\n const keyContainer = await this.getSecureKey()\n let signedTxns: Uint8Array[] = []\n\n try {\n signedTxns = await keyContainer.useKey(async (secretKey) => {\n const account = await deriveAlgorandAccountFromEd25519(secretKey)\n\n try {\n // Sign all transactions\n const signed = txnsToSign.map((txn) => txn.signTxn(account.sk))\n return signed\n } finally {\n // SECURITY: Always zero the account's secret key\n zeroMemory(account.sk)\n }\n })\n } finally {\n // SECURITY: Always clear the key container\n keyContainer.clear()\n }\n\n this.logger.debug('Transactions signed successfully', {\n count: signedTxns.length\n })\n return signedTxns\n } catch (error: any) {\n this.logger.error('Error signing transactions:', error.message)\n throw error\n }\n }\n}\n","import { Web3AuthAdapter } from './adapter'\nimport type { Web3AuthOptions } from './adapter'\nimport type { WalletAdapterConfig } from '@txnlab/use-wallet'\n\nexport const WALLET_ID = 'web3auth' as const\n\nexport function web3auth(options: Web3AuthOptions): WalletAdapterConfig {\n return {\n id: WALLET_ID,\n metadata: Web3AuthAdapter.defaultMetadata,\n Adapter: Web3AuthAdapter as unknown as WalletAdapterConfig['Adapter'],\n options: options as unknown as Record<string, unknown>,\n capabilities: { supportedNetworks: ['mainnet'] }\n }\n}\n\nexport { Web3AuthAdapter }\nexport type { Web3AuthOptions, Web3AuthCustomAuth, Web3AuthCredentials } from './adapter'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/icon.ts","../src/adapter.ts","../src/index.ts"],"sourcesContent":["export const icon = `\n<svg viewBox=\"0 0 40 40\" xmlns=\"http://www.w3.org/2000/svg\">\n <rect fill=\"#0364FF\" width=\"40\" height=\"40\" rx=\"8\"/>\n <path fill=\"#FFFFFF\" d=\"M20 8c-6.627 0-12 5.373-12 12s5.373 12 12 12 12-5.373 12-12S26.627 8 20 8zm0 21.6c-5.302 0-9.6-4.298-9.6-9.6S14.698 10.4 20 10.4s9.6 4.298 9.6 9.6-4.298 9.6-9.6 9.6zm0-16.8c-3.976 0-7.2 3.224-7.2 7.2s3.224 7.2 7.2 7.2 7.2-3.224 7.2-7.2-3.224-7.2-7.2-7.2zm0 12c-2.651 0-4.8-2.149-4.8-4.8s2.149-4.8 4.8-4.8 4.8 2.149 4.8 4.8-2.149 4.8-4.8 4.8z\"/>\n</svg>\n`\n","/**\n * Web3Auth Wallet Adapter for Algorand\n *\n * SECURITY CONSIDERATIONS:\n * - Web3Auth exposes the raw private key for non-EVM chains like Algorand\n * - This implementation uses SecureKeyContainer to minimize key exposure\n * - Keys are never persisted to localStorage or any storage\n * - Keys are cleared from memory immediately after signing operations\n * - Session resumption requires re-authentication (keys are not cached)\n *\n * @see https://web3auth.io/docs\n */\n\nimport algosdk from 'algosdk'\nimport {\n BaseWallet,\n SecureKeyContainer,\n zeroMemory,\n deriveAlgorandAccountFromEd25519,\n flattenTxnGroup,\n isSignedTxn,\n isTransactionArray,\n type AdapterConstructorParams,\n type WalletAccount,\n type WalletMetadata,\n type WalletState\n} from '@txnlab/use-wallet/adapter'\n\nconst LOCAL_STORAGE_WEB3AUTH_KEY = '@txnlab/use-wallet:v5:web3auth'\n\n/** Metadata persisted to localStorage for Web3Auth session restoration */\ninterface Web3AuthMetadata {\n /** Whether the session was established using Single Factor Auth (SFA) vs modal */\n usingSFA: boolean\n}\n\n// Type definitions for Web3Auth (to avoid requiring the package at compile time)\n// These are minimal type definitions that match the actual Web3Auth API\ninterface IWeb3AuthProvider {\n request<T>(args: { method: string; params?: unknown }): Promise<T>\n}\n\ninterface IWeb3AuthUserInfo {\n email?: string\n name?: string\n profileImage?: string\n verifier?: string\n verifierId?: string\n typeOfLogin?: string\n aggregateVerifier?: string\n}\n\ninterface IWeb3AuthModal {\n init(): Promise<void>\n connect(): Promise<IWeb3AuthProvider | null>\n logout(): Promise<void>\n connected: boolean\n provider: IWeb3AuthProvider | null\n getUserInfo(): Promise<Partial<IWeb3AuthUserInfo>>\n}\n\n// Single Factor Auth SDK interface (for custom JWT auth)\ninterface IWeb3AuthSFA {\n init(): Promise<void>\n connect(params: {\n verifier: string\n verifierId: string\n idToken: string\n }): Promise<IWeb3AuthProvider | null>\n logout(): Promise<void>\n connected: boolean\n provider: IWeb3AuthProvider | null\n}\n\n/**\n * Parameters for custom authentication (e.g., Firebase, custom JWT)\n */\nexport interface Web3AuthCustomAuth {\n /**\n * Custom verifier name configured in Web3Auth dashboard\n */\n verifier: string\n\n /**\n * User identifier (e.g., email, Firebase UID)\n */\n verifierId: string\n\n /**\n * JWT token from your authentication provider (e.g., Firebase ID token)\n */\n idToken: string\n}\n\n/**\n * Credentials returned by getAuthCredentials callback\n */\nexport interface Web3AuthCredentials {\n /**\n * JWT token from your authentication provider (e.g., Firebase ID token)\n */\n idToken: string\n\n /**\n * User identifier (e.g., email, Firebase UID)\n */\n verifierId: string\n\n /**\n * Custom verifier name (optional, uses options.verifier if not provided)\n */\n verifier?: string\n}\n\n/**\n * Web3Auth configuration options\n */\nexport interface Web3AuthOptions {\n /**\n * Web3Auth Client ID from the dashboard\n * @see https://dashboard.web3auth.io\n */\n clientId: string\n\n /**\n * Web3Auth network (mainnet, testnet, sapphire_mainnet, sapphire_devnet, cyan, aqua)\n * @default 'sapphire_mainnet'\n */\n web3AuthNetwork?: 'mainnet' | 'testnet' | 'sapphire_mainnet' | 'sapphire_devnet' | 'cyan' | 'aqua'\n\n /**\n * Login provider to use (google, facebook, twitter, discord, etc.)\n * If not specified, the Web3Auth modal will be shown\n */\n loginProvider?:\n | 'google'\n | 'facebook'\n | 'twitter'\n | 'discord'\n | 'reddit'\n | 'twitch'\n | 'apple'\n | 'line'\n | 'github'\n | 'kakao'\n | 'linkedin'\n | 'weibo'\n | 'wechat'\n | 'email_passwordless'\n | 'sms_passwordless'\n\n /**\n * Login hint for email_passwordless or sms_passwordless\n */\n loginHint?: string\n\n /**\n * UI configuration for the Web3Auth modal\n */\n uiConfig?: {\n appName?: string\n appUrl?: string\n logoLight?: string\n logoDark?: string\n defaultLanguage?: string\n mode?: 'light' | 'dark' | 'auto'\n theme?: Record<string, string>\n }\n\n /**\n * Whether to use the popup flow instead of redirect\n * @default true\n */\n usePopup?: boolean\n\n /**\n * Default verifier name for custom authentication.\n * When set, connect() can be called with just { idToken, verifierId }\n */\n verifier?: string\n\n /**\n * Callback to get fresh authentication credentials when session expires.\n * Required for automatic re-authentication with Single Factor Auth (SFA).\n *\n * If not provided and the session expires, signTransactions() will throw\n * an error requiring the user to call connect() with fresh credentials.\n *\n * @example\n * ```typescript\n * getAuthCredentials: async () => {\n * const user = firebase.auth().currentUser\n * if (!user) throw new Error('Not logged in')\n * const idToken = await user.getIdToken(true)\n * return { idToken, verifierId: user.email || user.uid }\n * }\n * ```\n */\n getAuthCredentials?: () => Promise<Web3AuthCredentials>\n}\n\nimport { icon } from './icon'\n\nconst ICON = `data:image/svg+xml;base64,${btoa(icon)}`\n\nexport class Web3AuthAdapter extends BaseWallet<Web3AuthOptions> {\n private web3auth: IWeb3AuthModal | null = null\n private web3authSFA: IWeb3AuthSFA | null = null\n private userInfo: Partial<IWeb3AuthUserInfo> | null = null\n\n /**\n * SECURITY: We store only the address, NEVER the private key.\n * Keys are fetched fresh from Web3Auth and immediately cleared after use.\n */\n private _address: string | null = null\n\n /** Track which SDK is currently in use */\n private usingSFA: boolean = false\n\n constructor(params: AdapterConstructorParams<Web3AuthOptions>) {\n super(params)\n\n if (!params.options?.clientId) {\n this.logger.error('Missing required option: clientId')\n throw new Error('Missing required option: clientId')\n }\n\n // Apply defaults\n this.options = {\n web3AuthNetwork: 'sapphire_mainnet',\n usePopup: true,\n ...params.options\n }\n }\n\n static defaultMetadata: WalletMetadata = {\n name: 'Web3Auth',\n icon: ICON\n }\n\n // ---------- Metadata Persistence ----------------------------------- //\n\n private loadMetadata(): Web3AuthMetadata | null {\n if (typeof localStorage === 'undefined') return null\n const data = localStorage.getItem(LOCAL_STORAGE_WEB3AUTH_KEY)\n if (!data) return null\n try {\n return JSON.parse(data) as Web3AuthMetadata\n } catch {\n return null\n }\n }\n\n private saveMetadata(): void {\n if (typeof localStorage === 'undefined') return\n const metadata: Web3AuthMetadata = { usingSFA: this.usingSFA }\n localStorage.setItem(LOCAL_STORAGE_WEB3AUTH_KEY, JSON.stringify(metadata))\n }\n\n private clearMetadata(): void {\n if (typeof localStorage === 'undefined') return\n localStorage.removeItem(LOCAL_STORAGE_WEB3AUTH_KEY)\n }\n\n // ---------- Client Initialization ---------------------------------- //\n\n /**\n * Initialize the Web3Auth client (v10 Modal SDK)\n */\n private async initializeClient(): Promise<IWeb3AuthModal> {\n this.logger.info('Initializing Web3Auth client...')\n\n let Web3Auth: any\n\n let WEB3AUTH_NETWORK: any\n\n try {\n // Dynamic import - @web3auth/modal is a dependency\n const modal = await import('@web3auth/modal')\n Web3Auth = modal.Web3Auth\n WEB3AUTH_NETWORK = modal.WEB3AUTH_NETWORK\n } catch (error) {\n this.logger.error('Failed to load Web3Auth.', error)\n throw new Error('Web3Auth package not found. Please install @web3auth/modal')\n }\n\n const networkMap: Record<string, string> = {\n mainnet: WEB3AUTH_NETWORK.MAINNET,\n testnet: WEB3AUTH_NETWORK.TESTNET,\n sapphire_mainnet: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,\n sapphire_devnet: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,\n cyan: WEB3AUTH_NETWORK.CYAN,\n aqua: WEB3AUTH_NETWORK.AQUA\n }\n\n // v10: Chain config and provider are handled internally for non-EVM chains.\n // Only clientId, web3AuthNetwork, and uiConfig are needed.\n const web3auth = new Web3Auth({\n clientId: this.options.clientId,\n web3AuthNetwork: networkMap[this.options.web3AuthNetwork || 'sapphire_mainnet'] as any,\n uiConfig: this.options.uiConfig\n })\n\n await web3auth.init()\n this.web3auth = web3auth\n this.logger.info('Web3Auth client initialized')\n\n return web3auth\n }\n\n /**\n * Initialize the Web3Auth Single Factor Auth client for custom JWT authentication.\n * SFA SDK is still at v9 and requires CommonPrivateKeyProvider with chain config.\n */\n private async initializeSFAClient(): Promise<IWeb3AuthSFA> {\n this.logger.info('Initializing Web3Auth Single Factor Auth client...')\n\n let Web3Auth: any\n\n let WEB3AUTH_NETWORK: any\n\n let CommonPrivateKeyProvider: any\n\n try {\n // Dynamic imports\n const sfa = await import('@web3auth/single-factor-auth')\n Web3Auth = sfa.Web3Auth\n // Import WEB3AUTH_NETWORK from @web3auth/modal (v10 re-exports it)\n const modal = await import('@web3auth/modal')\n WEB3AUTH_NETWORK = modal.WEB3AUTH_NETWORK\n const baseProvider = await import('@web3auth/base-provider')\n CommonPrivateKeyProvider = baseProvider.CommonPrivateKeyProvider\n } catch {\n this.logger.error(\n 'Failed to load Web3Auth SFA. Make sure @web3auth/single-factor-auth ' +\n 'and @web3auth/base-provider are installed.'\n )\n throw new Error(\n 'Web3Auth SFA packages not found. Please install @web3auth/single-factor-auth ' +\n 'and @web3auth/base-provider'\n )\n }\n\n const chainConfig = {\n chainNamespace: 'other',\n chainId: 'algorand',\n rpcTarget: 'https://mainnet-api.algonode.cloud',\n displayName: 'Algorand',\n blockExplorerUrl: 'https://lora.algokit.io/mainnet',\n ticker: 'ALGO',\n tickerName: 'Algorand'\n }\n\n const networkMap: Record<string, string> = {\n mainnet: WEB3AUTH_NETWORK.MAINNET,\n testnet: WEB3AUTH_NETWORK.TESTNET,\n sapphire_mainnet: WEB3AUTH_NETWORK.SAPPHIRE_MAINNET,\n sapphire_devnet: WEB3AUTH_NETWORK.SAPPHIRE_DEVNET,\n cyan: WEB3AUTH_NETWORK.CYAN,\n aqua: WEB3AUTH_NETWORK.AQUA\n }\n\n // SFA v9 still requires CommonPrivateKeyProvider for non-EVM chains\n const privateKeyProvider = new CommonPrivateKeyProvider({\n config: { chainConfig }\n })\n\n const web3authSFA = new Web3Auth({\n clientId: this.options.clientId,\n web3AuthNetwork: networkMap[this.options.web3AuthNetwork || 'sapphire_mainnet'] as any,\n privateKeyProvider\n })\n\n await web3authSFA.init()\n this.web3authSFA = web3authSFA\n this.logger.info('Web3Auth SFA client initialized')\n\n return web3authSFA\n }\n\n // ---------- Secure Key Handling ------------------------------------ //\n\n /**\n * SECURITY: Fetch the private key from Web3Auth and return it in a SecureKeyContainer.\n * The caller MUST call container.clear() when done.\n *\n * @returns SecureKeyContainer holding the private key\n */\n private async getSecureKey(): Promise<SecureKeyContainer> {\n // Get the provider from either the modal SDK or SFA SDK\n const provider = this.usingSFA ? this.web3authSFA?.provider : this.web3auth?.provider\n\n if (!provider) {\n throw new Error('Web3Auth not connected')\n }\n\n this.logger.debug('Fetching private key from Web3Auth...')\n\n // Request the private key from Web3Auth\n // For non-EVM chains, Web3Auth returns the raw ed25519 private key\n const privateKeyHex = await provider.request<string>({\n method: 'private_key'\n })\n\n if (!privateKeyHex || typeof privateKeyHex !== 'string') {\n throw new Error('Failed to retrieve private key from Web3Auth')\n }\n\n // Convert hex string to Uint8Array\n const privateKeyBytes = this.hexToBytes(privateKeyHex)\n\n // SECURITY: Immediately clear the hex string from our scope\n // (The original string may still exist in Web3Auth's scope)\n\n // Wrap in SecureKeyContainer for safe handling\n const container = new SecureKeyContainer(privateKeyBytes)\n\n // SECURITY: Zero the local copy now that it's in the container\n zeroMemory(privateKeyBytes)\n\n this.logger.debug('Private key retrieved and secured')\n return container\n }\n\n /**\n * Convert a hex string to Uint8Array\n */\n private hexToBytes(hex: string): Uint8Array {\n // Remove 0x prefix if present\n const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex\n const bytes = new Uint8Array(cleanHex.length / 2)\n for (let i = 0; i < cleanHex.length; i += 2) {\n bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16)\n }\n return bytes\n }\n\n // ---------- Session Management ------------------------------------- //\n\n /**\n * Check if Web3Auth is currently connected with a valid session\n */\n private isWeb3AuthConnected(): boolean {\n if (this.usingSFA) {\n return Boolean(this.web3authSFA?.connected && this.web3authSFA?.provider)\n }\n return Boolean(this.web3auth?.connected && this.web3auth?.provider)\n }\n\n /**\n * Ensure Web3Auth is connected and ready for signing.\n * Re-authenticates if the session has expired.\n *\n * This is called lazily when signTransactions() is invoked.\n */\n private async ensureConnected(): Promise<void> {\n if (this.isWeb3AuthConnected()) {\n this.logger.debug('Web3Auth session still valid')\n return\n }\n\n this.logger.info('Web3Auth session expired or not initialized, re-authenticating...')\n\n if (this.usingSFA) {\n await this.reconnectSFA()\n } else {\n await this.reconnectModal()\n }\n }\n\n /**\n * Re-authenticate using Single Factor Auth (Firebase, custom JWT)\n *\n * Requires getAuthCredentials callback to be configured in options.\n * If the callback returns credentials for a different user, this will\n * disconnect the current wallet (the user logged out and back in as someone else).\n */\n private async reconnectSFA(): Promise<void> {\n if (!this.options.getAuthCredentials) {\n this.logger.error('Cannot re-authenticate: getAuthCredentials callback not configured')\n throw new Error(\n 'Web3Auth session expired. Configure getAuthCredentials option for automatic re-auth, ' +\n 'or call disconnect() and connect() with fresh credentials.'\n )\n }\n\n this.logger.info('Getting fresh credentials for SFA re-authentication...')\n\n let credentials: Web3AuthCredentials\n try {\n credentials = await this.options.getAuthCredentials()\n } catch (error: any) {\n // User is no longer authenticated with the identity provider (e.g., logged out of Firebase)\n this.logger.warn('Failed to get auth credentials, user may have logged out:', error.message)\n this.onDisconnect()\n throw new Error('Authentication provider session expired. Please log in again.')\n }\n\n // Initialize SFA client if needed\n const web3authSFA = this.web3authSFA || (await this.initializeSFAClient())\n\n // Logout first if still connected (stale session)\n if (web3authSFA.connected) {\n try {\n await web3authSFA.logout()\n } catch {\n // Ignore logout errors\n }\n }\n\n const verifier = credentials.verifier || this.options.verifier\n if (!verifier) {\n throw new Error('No verifier configured for SFA authentication')\n }\n\n // Connect with fresh credentials\n const provider = await web3authSFA.connect({\n verifier,\n verifierId: credentials.verifierId,\n idToken: credentials.idToken\n })\n\n if (!provider) {\n throw new Error('Failed to re-authenticate with Web3Auth SFA')\n }\n\n this.usingSFA = true\n this.saveMetadata()\n\n // Verify we got the same address (same user)\n await this.verifyAddressMatch()\n }\n\n /**\n * Re-authenticate using the Web3Auth modal\n *\n * Shows the Web3Auth login modal for the user to authenticate again.\n * If they log in as a different user, this will disconnect the current wallet.\n */\n private async reconnectModal(): Promise<void> {\n this.logger.info('Showing Web3Auth modal for re-authentication...')\n\n const web3auth = this.web3auth || (await this.initializeClient())\n\n // Logout first if still connected (stale session)\n if (web3auth.connected) {\n try {\n await web3auth.logout()\n } catch {\n // Ignore logout errors\n }\n }\n\n const provider = await web3auth.connect()\n\n if (!provider) {\n throw new Error('Re-authentication cancelled or failed')\n }\n\n this.usingSFA = false\n this.saveMetadata()\n\n // Get updated user info\n this.userInfo = await web3auth.getUserInfo()\n\n // Verify we got the same address (same user)\n await this.verifyAddressMatch()\n }\n\n /**\n * Verify that the current Web3Auth session matches the cached address.\n *\n * If the address doesn't match (user logged in as someone else),\n * this disconnects the wallet entirely -- it's a different identity.\n */\n private async verifyAddressMatch(): Promise<void> {\n const keyContainer = await this.getSecureKey()\n\n try {\n const currentAddress = await keyContainer.useKey(async (secretKey) => {\n const account = await deriveAlgorandAccountFromEd25519(secretKey)\n const addr = account.addr\n zeroMemory(account.sk)\n return addr\n })\n\n if (currentAddress !== this._address) {\n this.logger.warn('Re-authenticated as different user, disconnecting wallet', {\n expected: this._address,\n actual: currentAddress\n })\n\n // Different user = different wallet. Full disconnect required.\n this.onDisconnect()\n\n throw new Error(\n `Re-authenticated as a different account. Expected ${this._address}, ` +\n `got ${currentAddress}. Please connect again with the correct account.`\n )\n }\n\n this.logger.info('Address verified, session restored')\n } finally {\n keyContainer.clear()\n }\n }\n\n // ---------- Public Methods ----------------------------------------- //\n\n /**\n * Connect to Web3Auth\n *\n * @param args - Optional connection arguments\n * @param args.idToken - JWT token for custom authentication (e.g., Firebase ID token)\n * @param args.verifierId - User identifier for custom authentication (e.g., email, uid)\n * @param args.verifier - Custom verifier name (uses options.verifier if not provided)\n *\n * @example\n * // Standard modal connection\n * await wallet.connect()\n *\n * @example\n * // Custom authentication with Firebase\n * await wallet.connect({\n * idToken: firebaseIdToken,\n * verifierId: user.email,\n * verifier: 'my-firebase-verifier'\n * })\n */\n public connect = async (args?: Record<string, any>): Promise<WalletAccount[]> => {\n this.logger.info('Connecting to Web3Auth...')\n\n try {\n let provider: IWeb3AuthProvider | null\n\n // Check if custom authentication params are provided\n const idToken = args?.idToken as string | undefined\n const verifierId = args?.verifierId as string | undefined\n const verifier = (args?.verifier as string | undefined) || this.options.verifier\n\n if (idToken && verifierId) {\n // Custom authentication flow using Single Factor Auth (e.g., Firebase)\n if (!verifier) {\n throw new Error(\n 'Custom authentication requires a verifier. Provide it in connect() args or options.verifier'\n )\n }\n\n this.logger.info('Connecting with custom authentication (SFA)...', {\n verifier,\n verifierId\n })\n\n // Initialize the SFA client\n const web3authSFA = this.web3authSFA || (await this.initializeSFAClient())\n\n // If already connected, logout first to allow reconnection with potentially different credentials\n if (web3authSFA.connected) {\n this.logger.debug('SFA already connected, logging out first...')\n try {\n await web3authSFA.logout()\n } catch {\n // Ignore logout errors\n }\n }\n\n // Connect using Single Factor Auth - no modal, direct connection\n provider = await web3authSFA.connect({\n verifier,\n verifierId,\n idToken\n })\n\n this.usingSFA = true\n\n // SFA doesn't provide getUserInfo, use verifierId as display name\n this.userInfo = { email: verifierId }\n } else {\n // Standard modal connection\n const web3auth = this.web3auth || (await this.initializeClient())\n provider = await web3auth.connect()\n\n this.usingSFA = false\n\n // Get user info for display purposes (modal SDK only)\n this.userInfo = await web3auth.getUserInfo()\n this.logger.debug('User info retrieved', {\n email: this.userInfo.email\n })\n }\n\n if (!provider) {\n throw new Error('Failed to connect to Web3Auth')\n }\n\n // SECURITY: Get the key, derive the address, and immediately clear the key\n const keyContainer = await this.getSecureKey()\n\n try {\n const address = await keyContainer.useKey(async (secretKey) => {\n const account = await deriveAlgorandAccountFromEd25519(secretKey)\n // SECURITY: Zero the derived account's secret key immediately\n const addr = account.addr\n zeroMemory(account.sk)\n return addr\n })\n\n this._address = address\n } finally {\n // SECURITY: Always clear the key container\n keyContainer.clear()\n }\n\n const walletAccount: WalletAccount = {\n name: this.userInfo.name || this.userInfo.email || `${this.metadata.name} Account`,\n address: this._address\n }\n\n const walletState: WalletState = {\n accounts: [walletAccount],\n activeAccount: walletAccount\n }\n\n this.store.addWallet(walletState)\n\n // Save metadata only after successful connection\n this.saveMetadata()\n\n this.logger.info('Connected successfully', { address: this._address })\n return [walletAccount]\n } catch (error: any) {\n this.logger.error('Error connecting to Web3Auth:', error.message)\n throw error\n }\n }\n\n /**\n * Disconnect from Web3Auth\n */\n public disconnect = async (): Promise<void> => {\n this.logger.info('Disconnecting from Web3Auth...')\n\n try {\n if (this.usingSFA && this.web3authSFA?.connected) {\n await this.web3authSFA.logout()\n } else if (this.web3auth?.connected) {\n await this.web3auth.logout()\n }\n } catch (error: any) {\n this.logger.warn('Error during Web3Auth logout:', error.message)\n }\n\n // Clear local state\n this._address = null\n this.userInfo = null\n this.usingSFA = false\n this.clearMetadata()\n this.onDisconnect()\n\n this.logger.info('Disconnected')\n }\n\n /**\n * Resume session from cached state\n *\n * LAZY AUTHENTICATION: We do NOT connect to Web3Auth here.\n * We simply restore the cached address from localStorage.\n * Web3Auth connection is deferred until signTransactions() is called.\n */\n public resumeSession = async (): Promise<void> => {\n try {\n const walletState = this.store.getWalletState()\n\n if (!walletState) {\n this.logger.info('No session to resume')\n return\n }\n\n const storedAccount = walletState.accounts[0]\n\n if (!storedAccount?.address) {\n this.logger.warn('No address found in cached session')\n this.onDisconnect()\n return\n }\n\n // Just restore the cached address - don't initialize Web3Auth\n this._address = storedAccount.address\n this.userInfo = { name: storedAccount.name }\n\n // Restore usingSFA flag from metadata\n const metadata = this.loadMetadata()\n if (metadata) {\n this.usingSFA = metadata.usingSFA\n }\n\n this.logger.info('Session restored from cache (lazy mode)', {\n address: this._address\n })\n } catch (error: any) {\n this.logger.error('Error resuming session:', error.message)\n this.onDisconnect()\n throw error\n }\n }\n\n // ---------- Private Key Access ------------------------------------- //\n\n public canUsePrivateKey = true\n\n /**\n * Provide scoped access to the private key via a callback.\n *\n * The callback receives a 64-byte Algorand secret key (ed25519 seed + public key).\n * The key is a fresh copy that is guaranteed to be zeroed from memory when the\n * callback completes, whether it succeeds or throws.\n *\n * SECURITY: The key is fetched fresh from Web3Auth for each call and never cached.\n *\n * @example\n * ```typescript\n * const result = await wallet.withPrivateKey(async (secretKey) => {\n * // secretKey is a 64-byte Uint8Array\n * // Use for custom signing, authentication, etc.\n * return doSomethingWith(secretKey)\n * })\n * // secretKey is zeroed at this point\n * ```\n */\n public withPrivateKey = async <T>(\n callback: (secretKey: Uint8Array) => Promise<T>\n ): Promise<T> => {\n this.logger.debug('withPrivateKey: Providing private key access...')\n\n // Ensure Web3Auth is connected (re-authenticates if session expired)\n await this.ensureConnected()\n\n // SECURITY: Fetch key, derive Algorand account, provide copy to consumer\n const keyContainer = await this.getSecureKey()\n\n try {\n return await keyContainer.useKey(async (secretKey) => {\n const account = await deriveAlgorandAccountFromEd25519(secretKey)\n\n // Create a copy for the consumer\n const skCopy = new Uint8Array(account.sk)\n\n // SECURITY: Zero the derived account's secret key immediately\n zeroMemory(account.sk)\n\n try {\n return await callback(skCopy)\n } finally {\n // SECURITY: Always zero the consumer's copy\n zeroMemory(skCopy)\n }\n })\n } finally {\n // SECURITY: Always clear the key container\n keyContainer.clear()\n }\n }\n\n // ---------- Transaction Signing ------------------------------------ //\n\n /**\n * Process transactions for signing\n */\n private processTxns(\n txnGroup: algosdk.Transaction[],\n indexesToSign?: number[]\n ): algosdk.Transaction[] {\n const txnsToSign: algosdk.Transaction[] = []\n\n txnGroup.forEach((txn, index) => {\n const isIndexMatch = !indexesToSign || indexesToSign.includes(index)\n const signer = txn.sender.toString()\n const canSignTxn = signer === this._address\n\n if (isIndexMatch && canSignTxn) {\n txnsToSign.push(txn)\n }\n })\n\n return txnsToSign\n }\n\n /**\n * Process encoded transactions for signing\n */\n private processEncodedTxns(\n txnGroup: Uint8Array[],\n indexesToSign?: number[]\n ): algosdk.Transaction[] {\n const txnsToSign: algosdk.Transaction[] = []\n\n txnGroup.forEach((txnBuffer, index) => {\n const decodedObj = algosdk.msgpackRawDecode(txnBuffer)\n const isSigned = isSignedTxn(decodedObj)\n\n const txn: algosdk.Transaction = isSigned\n ? algosdk.decodeSignedTransaction(txnBuffer).txn\n : algosdk.decodeUnsignedTransaction(txnBuffer)\n\n const isIndexMatch = !indexesToSign || indexesToSign.includes(index)\n const signer = txn.sender.toString()\n const canSignTxn = !isSigned && signer === this._address\n\n if (isIndexMatch && canSignTxn) {\n txnsToSign.push(txn)\n }\n })\n\n return txnsToSign\n }\n\n /**\n * Sign transactions\n *\n * LAZY AUTHENTICATION: If the Web3Auth session has expired, this will\n * automatically re-authenticate before signing.\n *\n * SECURITY: The private key is fetched fresh, used for signing,\n * and immediately cleared from memory. The key is never stored\n * between signing operations.\n */\n public signTransactions = async <T extends algosdk.Transaction[] | Uint8Array[]>(\n txnGroup: T | T[],\n indexesToSign?: number[]\n ): Promise<(Uint8Array | null)[]> => {\n try {\n this.logger.debug('Signing transactions...', {\n txnGroup,\n indexesToSign\n })\n\n // Ensure Web3Auth is connected (re-authenticates if session expired)\n await this.ensureConnected()\n\n let txnsToSign: algosdk.Transaction[] = []\n\n // Determine type and process transactions for signing\n if (isTransactionArray(txnGroup)) {\n const flatTxns: algosdk.Transaction[] = flattenTxnGroup(txnGroup)\n txnsToSign = this.processTxns(flatTxns, indexesToSign)\n } else {\n const flatTxns: Uint8Array[] = flattenTxnGroup(txnGroup as Uint8Array[])\n txnsToSign = this.processEncodedTxns(flatTxns, indexesToSign)\n }\n\n if (txnsToSign.length === 0) {\n this.logger.debug('No transactions to sign')\n return []\n }\n\n // SECURITY: Fetch key, sign, and immediately clear\n const keyContainer = await this.getSecureKey()\n let signedTxns: Uint8Array[] = []\n\n try {\n signedTxns = await keyContainer.useKey(async (secretKey) => {\n const account = await deriveAlgorandAccountFromEd25519(secretKey)\n\n try {\n // Sign all transactions\n const signed = txnsToSign.map((txn) => txn.signTxn(account.sk))\n return signed\n } finally {\n // SECURITY: Always zero the account's secret key\n zeroMemory(account.sk)\n }\n })\n } finally {\n // SECURITY: Always clear the key container\n keyContainer.clear()\n }\n\n this.logger.debug('Transactions signed successfully', {\n count: signedTxns.length\n })\n return signedTxns\n } catch (error: any) {\n this.logger.error('Error signing transactions:', error.message)\n throw error\n }\n }\n}\n","import { Web3AuthAdapter } from './adapter'\nimport type { Web3AuthOptions } from './adapter'\nimport type { WalletAdapterConfig, WalletFactoryOptions } from '@txnlab/use-wallet'\n\nexport const WALLET_ID = 'web3auth' as const\n\nexport function web3auth(options: Web3AuthOptions & WalletFactoryOptions): WalletAdapterConfig {\n const { metadata, ...adapterOptions } = options\n return {\n id: WALLET_ID,\n metadata: { ...Web3AuthAdapter.defaultMetadata, ...metadata },\n Adapter: Web3AuthAdapter as unknown as WalletAdapterConfig['Adapter'],\n options: adapterOptions as unknown as Record<string, unknown>,\n capabilities: { supportedNetworks: ['mainnet'] }\n }\n}\n\nexport { Web3AuthAdapter }\nexport type { Web3AuthOptions, Web3AuthCustomAuth, Web3AuthCredentials } from './adapter'\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@txnlab/use-wallet-web3auth",
3
- "version": "5.0.0-rc.3",
3
+ "version": "5.0.0",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "provenance": true
@@ -8,12 +8,16 @@
8
8
  "description": "Web3Auth wallet adapter for @txnlab/use-wallet",
9
9
  "author": "Doug Richar <drichar@gmail.com>",
10
10
  "license": "MIT",
11
+ "engines": {
12
+ "node": ">=22"
13
+ },
11
14
  "repository": {
12
15
  "type": "git",
13
16
  "url": "git+https://github.com/TxnLab/use-wallet.git",
14
17
  "directory": "packages/wallets/web3auth"
15
18
  },
16
19
  "type": "module",
20
+ "sideEffects": false,
17
21
  "main": "./dist/index.js",
18
22
  "types": "./dist/index.d.ts",
19
23
  "exports": {
@@ -35,10 +39,10 @@
35
39
  "@web3auth/single-factor-auth": "9.5.0"
36
40
  },
37
41
  "devDependencies": {
38
- "algosdk": "3.5.2",
42
+ "algosdk": "3.6.0",
39
43
  "tsdown": "0.21.0",
40
44
  "typescript": "5.9.3",
41
- "@txnlab/use-wallet": "5.0.0-rc.3"
45
+ "@txnlab/use-wallet": "5.0.0"
42
46
  },
43
47
  "scripts": {
44
48
  "build": "tsdown",