kentucky-signer-viem 0.1.1 → 0.1.3

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.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/context.tsx","../../src/client.ts","../../src/utils.ts","../../src/auth.ts","../../src/account.ts","../../src/react/hooks.ts"],"sourcesContent":["import React, {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n useMemo,\n type ReactNode,\n} from 'react'\nimport type { AuthSession } from '../types'\nimport { KentuckySignerClient } from '../client'\nimport {\n authenticateWithPasskey,\n isSessionValid,\n refreshSessionIfNeeded,\n LocalStorageTokenStorage,\n} from '../auth'\nimport {\n createKentuckySignerAccount,\n type KentuckySignerAccount,\n} from '../account'\n\n/**\n * Kentucky Signer context state\n */\nexport interface KentuckySignerState {\n /** Whether authentication is in progress */\n isAuthenticating: boolean\n /** Whether the user is authenticated */\n isAuthenticated: boolean\n /** Current session (if authenticated) */\n session: AuthSession | null\n /** Current account (if authenticated) */\n account: KentuckySignerAccount | null\n /** Last error (if any) */\n error: Error | null\n}\n\n/**\n * Kentucky Signer context actions\n */\nexport interface KentuckySignerActions {\n /** Authenticate with passkey */\n authenticate: (accountId: string, options?: { rpId?: string }) => Promise<void>\n /** Logout and clear session */\n logout: () => Promise<void>\n /** Refresh session if needed */\n refreshSession: () => Promise<void>\n /** Clear any errors */\n clearError: () => void\n}\n\n/**\n * Full Kentucky Signer context value\n */\nexport type KentuckySignerContextValue = KentuckySignerState & KentuckySignerActions\n\nconst KentuckySignerContext = createContext<KentuckySignerContextValue | null>(null)\n\n/**\n * Kentucky Signer provider props\n */\nexport interface KentuckySignerProviderProps {\n /** Base URL of the Kentucky Signer API */\n baseUrl: string\n /** Default chain ID for signing */\n defaultChainId?: number\n /** Storage key prefix for persisting tokens */\n storageKeyPrefix?: string\n /** Whether to persist session in localStorage */\n persistSession?: boolean\n /** Children */\n children: ReactNode\n}\n\n/**\n * Kentucky Signer Provider\n *\n * Wraps your app to provide Kentucky Signer authentication and signing context.\n *\n * @example\n * ```tsx\n * <KentuckySignerProvider baseUrl=\"https://signer.example.com\">\n * <App />\n * </KentuckySignerProvider>\n * ```\n */\nexport function KentuckySignerProvider({\n baseUrl,\n defaultChainId = 1,\n storageKeyPrefix = 'kentucky_signer',\n persistSession = true,\n children,\n}: KentuckySignerProviderProps) {\n const [state, setState] = useState<KentuckySignerState>({\n isAuthenticating: false,\n isAuthenticated: false,\n session: null,\n account: null,\n error: null,\n })\n\n const client = useMemo(\n () => new KentuckySignerClient({ baseUrl }),\n [baseUrl]\n )\n\n const storage = useMemo(\n () => (persistSession ? new LocalStorageTokenStorage(storageKeyPrefix) : null),\n [persistSession, storageKeyPrefix]\n )\n\n // Create account from session\n const createAccount = useCallback(\n (session: AuthSession): KentuckySignerAccount => {\n return createKentuckySignerAccount({\n config: { baseUrl, accountId: session.accountId },\n session,\n defaultChainId,\n onSessionExpired: async () => {\n // Try to refresh the session\n const newSession = await refreshSessionIfNeeded(session, baseUrl, 0)\n setState((s) => ({\n ...s,\n session: newSession,\n account: s.account\n ? { ...s.account, session: newSession }\n : null,\n }))\n return newSession\n },\n })\n },\n [baseUrl, defaultChainId]\n )\n\n // Restore session from storage on mount\n useEffect(() => {\n async function restoreSession() {\n if (!storage) return\n\n try {\n const savedSession = localStorage.getItem(`${storageKeyPrefix}_session`)\n if (!savedSession) return\n\n const session: AuthSession = JSON.parse(savedSession)\n if (!isSessionValid(session)) {\n // Try to refresh\n try {\n const refreshed = await refreshSessionIfNeeded(session, baseUrl, 0)\n const account = createAccount(refreshed)\n localStorage.setItem(\n `${storageKeyPrefix}_session`,\n JSON.stringify(refreshed)\n )\n setState({\n isAuthenticating: false,\n isAuthenticated: true,\n session: refreshed,\n account,\n error: null,\n })\n } catch {\n // Clear invalid session\n localStorage.removeItem(`${storageKeyPrefix}_session`)\n }\n return\n }\n\n const account = createAccount(session)\n setState({\n isAuthenticating: false,\n isAuthenticated: true,\n session,\n account,\n error: null,\n })\n } catch {\n localStorage.removeItem(`${storageKeyPrefix}_session`)\n }\n }\n\n restoreSession()\n }, [storage, storageKeyPrefix, baseUrl, createAccount])\n\n // Authenticate with passkey\n const authenticate = useCallback(\n async (accountId: string, options?: { rpId?: string }) => {\n setState((s) => ({ ...s, isAuthenticating: true, error: null }))\n\n try {\n const session = await authenticateWithPasskey({\n baseUrl,\n accountId,\n rpId: options?.rpId,\n })\n\n const account = createAccount(session)\n\n // Persist session\n if (storage) {\n localStorage.setItem(\n `${storageKeyPrefix}_session`,\n JSON.stringify(session)\n )\n }\n\n setState({\n isAuthenticating: false,\n isAuthenticated: true,\n session,\n account,\n error: null,\n })\n } catch (error) {\n setState((s) => ({\n ...s,\n isAuthenticating: false,\n error: error as Error,\n }))\n throw error\n }\n },\n [baseUrl, createAccount, storage, storageKeyPrefix]\n )\n\n // Logout\n const logout = useCallback(async () => {\n try {\n if (state.session) {\n await client.logout(state.session.token)\n }\n } catch {\n // Ignore logout errors\n }\n\n // Clear storage\n if (storage) {\n localStorage.removeItem(`${storageKeyPrefix}_session`)\n }\n\n setState({\n isAuthenticating: false,\n isAuthenticated: false,\n session: null,\n account: null,\n error: null,\n })\n }, [client, state.session, storage, storageKeyPrefix])\n\n // Refresh session\n const refreshSession = useCallback(async () => {\n if (!state.session) return\n\n try {\n const refreshed = await refreshSessionIfNeeded(state.session, baseUrl)\n\n if (refreshed !== state.session) {\n const account = createAccount(refreshed)\n\n if (storage) {\n localStorage.setItem(\n `${storageKeyPrefix}_session`,\n JSON.stringify(refreshed)\n )\n }\n\n setState((s) => ({\n ...s,\n session: refreshed,\n account,\n }))\n }\n } catch (error) {\n setState((s) => ({ ...s, error: error as Error }))\n }\n }, [state.session, baseUrl, createAccount, storage, storageKeyPrefix])\n\n // Clear error\n const clearError = useCallback(() => {\n setState((s) => ({ ...s, error: null }))\n }, [])\n\n const value: KentuckySignerContextValue = useMemo(\n () => ({\n ...state,\n authenticate,\n logout,\n refreshSession,\n clearError,\n }),\n [state, authenticate, logout, refreshSession, clearError]\n )\n\n return (\n <KentuckySignerContext.Provider value={value}>\n {children}\n </KentuckySignerContext.Provider>\n )\n}\n\n/**\n * Use the Kentucky Signer context\n *\n * Must be used within a KentuckySignerProvider.\n *\n * @returns Kentucky Signer context value\n */\nexport function useKentuckySignerContext(): KentuckySignerContextValue {\n const context = useContext(KentuckySignerContext)\n if (!context) {\n throw new Error(\n 'useKentuckySignerContext must be used within a KentuckySignerProvider'\n )\n }\n return context\n}\n","import type {\n ClientOptions,\n ChallengeResponse,\n AuthResponse,\n AccountInfoResponse,\n EvmSignatureResponse,\n ApiErrorResponse,\n PasskeyCredential,\n AccountCreationResponse,\n SignEvmRequest,\n CreatePasswordAccountRequest,\n PasswordAuthRequest,\n} from './types'\nimport type { Hex } from 'viem'\n\n/**\n * Kentucky Signer API error\n */\nexport class KentuckySignerError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: string\n ) {\n super(message)\n this.name = 'KentuckySignerError'\n }\n}\n\n/**\n * Kentucky Signer API client\n *\n * Handles communication with the Kentucky Signer API for authentication,\n * account management, and transaction signing.\n */\nexport class KentuckySignerClient {\n private baseUrl: string\n private fetchImpl: typeof fetch\n private timeout: number\n\n constructor(options: ClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '') // Remove trailing slash\n this.fetchImpl = options.fetch ?? globalThis.fetch\n this.timeout = options.timeout ?? 30000\n }\n\n /**\n * Make an authenticated request to the API\n */\n private async request<T>(\n path: string,\n options: RequestInit & { token?: string } = {}\n ): Promise<T> {\n const { token, ...fetchOptions } = options\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n ...options.headers,\n }\n\n if (token) {\n ;(headers as Record<string, string>)['Authorization'] = `Bearer ${token}`\n }\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await this.fetchImpl(`${this.baseUrl}${path}`, {\n ...fetchOptions,\n headers,\n signal: controller.signal,\n })\n\n const data = await response.json()\n\n if (!response.ok || data.success === false) {\n const error = data as ApiErrorResponse\n throw new KentuckySignerError(\n error.error?.message ?? 'Unknown error',\n error.error?.code ?? 'UNKNOWN_ERROR',\n error.error?.details\n )\n }\n\n return data as T\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Get a challenge for passkey authentication\n *\n * @param accountId - Account ID to authenticate\n * @returns Challenge response with 32-byte challenge\n */\n async getChallenge(accountId: string): Promise<ChallengeResponse> {\n return this.request<ChallengeResponse>('/api/auth/challenge', {\n method: 'POST',\n body: JSON.stringify({ account_id: accountId }),\n })\n }\n\n /**\n * Authenticate with a passkey credential\n *\n * @param accountId - Account ID to authenticate\n * @param credential - WebAuthn credential from navigator.credentials.get()\n * @returns Authentication response with JWT token\n */\n async authenticatePasskey(\n accountId: string,\n credential: PasskeyCredential\n ): Promise<AuthResponse> {\n return this.request<AuthResponse>('/api/auth/passkey', {\n method: 'POST',\n body: JSON.stringify({\n account_id: accountId,\n credential_id: credential.credentialId,\n client_data_json: credential.clientDataJSON,\n authenticator_data: credential.authenticatorData,\n signature: credential.signature,\n user_handle: credential.userHandle,\n }),\n })\n }\n\n /**\n * Refresh an authentication token\n *\n * @param token - Current JWT token\n * @returns New authentication response with fresh token\n */\n async refreshToken(token: string): Promise<AuthResponse> {\n return this.request<AuthResponse>('/api/auth/refresh', {\n method: 'POST',\n token,\n })\n }\n\n /**\n * Logout and invalidate token\n *\n * @param token - JWT token to invalidate\n */\n async logout(token: string): Promise<void> {\n await this.request('/api/auth/logout', {\n method: 'POST',\n token,\n })\n }\n\n /**\n * Get account information\n *\n * @param accountId - Account ID\n * @param token - JWT token\n * @returns Account info with addresses and passkeys\n */\n async getAccountInfo(accountId: string, token: string): Promise<AccountInfoResponse> {\n return this.request<AccountInfoResponse>(`/api/accounts/${accountId}`, {\n method: 'GET',\n token,\n })\n }\n\n /**\n * Check if an account exists\n *\n * @param accountId - Account ID\n * @param token - JWT token\n * @returns True if account exists\n */\n async accountExists(accountId: string, token: string): Promise<boolean> {\n try {\n await this.request(`/api/accounts/${accountId}`, {\n method: 'HEAD',\n token,\n })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Sign an EVM transaction hash\n *\n * @param request - Sign request with tx_hash and chain_id\n * @param token - JWT token\n * @returns Signature response with r, s, v components\n */\n async signEvmTransaction(\n request: SignEvmRequest,\n token: string\n ): Promise<EvmSignatureResponse> {\n return this.request<EvmSignatureResponse>('/api/sign/evm', {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Sign a raw hash for EVM\n *\n * Convenience method that wraps signEvmTransaction.\n *\n * @param hash - 32-byte hash to sign (hex encoded with 0x prefix)\n * @param chainId - Chain ID\n * @param token - JWT token\n * @returns Full signature (hex encoded with 0x prefix)\n */\n async signHash(hash: Hex, chainId: number, token: string): Promise<Hex> {\n const response = await this.signEvmTransaction(\n { tx_hash: hash, chain_id: chainId },\n token\n )\n return response.signature.full\n }\n\n /**\n * Create a new account with passkey authentication\n *\n * @param credential - WebAuthn credential from navigator.credentials.create()\n * @returns Account creation response with account ID and addresses\n */\n async createAccountWithPasskey(\n credential: PasskeyCredential & { publicKey: string }\n ): Promise<AccountCreationResponse> {\n return this.request<AccountCreationResponse>('/api/accounts/create/passkey', {\n method: 'POST',\n body: JSON.stringify({\n credential_id: credential.credentialId,\n public_key: credential.publicKey,\n client_data_json: credential.clientDataJSON,\n authenticator_data: credential.authenticatorData,\n }),\n })\n }\n\n /**\n * Create a new account with password authentication\n *\n * @param request - Password and confirmation\n * @returns Account creation response with account ID and addresses\n */\n async createAccountWithPassword(\n request: CreatePasswordAccountRequest\n ): Promise<AccountCreationResponse> {\n return this.request<AccountCreationResponse>('/api/accounts/create/password', {\n method: 'POST',\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Authenticate with password\n *\n * @param request - Account ID and password\n * @returns Authentication response with JWT token\n */\n async authenticatePassword(request: PasswordAuthRequest): Promise<AuthResponse> {\n return this.request<AuthResponse>('/api/auth/password', {\n method: 'POST',\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Health check\n *\n * @returns True if the API is healthy\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await this.request<{ status: string }>('/api/health', {\n method: 'GET',\n })\n return response.status === 'ok'\n } catch {\n return false\n }\n }\n\n /**\n * Get API version\n *\n * @returns Version string\n */\n async getVersion(): Promise<string> {\n const response = await this.request<{ version: string }>('/api/version', {\n method: 'GET',\n })\n return response.version\n }\n}\n\n/**\n * Create a new Kentucky Signer client\n *\n * @param options - Client options\n * @returns Kentucky Signer client instance\n */\nexport function createClient(options: ClientOptions): KentuckySignerClient {\n return new KentuckySignerClient(options)\n}\n","/**\n * Utility functions for Kentucky Signer Viem integration\n */\n\n/**\n * Base64URL encode a Uint8Array\n *\n * @param data - Data to encode\n * @returns Base64URL encoded string (no padding)\n */\nexport function base64UrlEncode(data: Uint8Array): string {\n // Convert to regular base64\n let base64: string\n if (typeof Buffer !== 'undefined') {\n // Node.js\n base64 = Buffer.from(data).toString('base64')\n } else {\n // Browser\n const binary = Array.from(data)\n .map((byte) => String.fromCharCode(byte))\n .join('')\n base64 = btoa(binary)\n }\n\n // Convert to base64url (replace + with -, / with _, remove padding)\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/**\n * Base64URL decode a string to Uint8Array\n *\n * @param str - Base64URL encoded string\n * @returns Decoded bytes\n */\nexport function base64UrlDecode(str: string): Uint8Array {\n // Convert base64url to regular base64\n let base64 = str.replace(/-/g, '+').replace(/_/g, '/')\n\n // Add padding if needed\n const padding = (4 - (base64.length % 4)) % 4\n base64 += '='.repeat(padding)\n\n if (typeof Buffer !== 'undefined') {\n // Node.js\n return new Uint8Array(Buffer.from(base64, 'base64'))\n } else {\n // Browser\n const binary = atob(base64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return bytes\n }\n}\n\n/**\n * Convert a hex string to Uint8Array\n *\n * @param hex - Hex string (with or without 0x prefix)\n * @returns Byte array\n */\nexport function hexToBytes(hex: string): Uint8Array {\n const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex\n const bytes = new Uint8Array(cleanHex.length / 2)\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(cleanHex.slice(i * 2, i * 2 + 2), 16)\n }\n return bytes\n}\n\n/**\n * Convert a Uint8Array to hex string\n *\n * @param bytes - Byte array\n * @param withPrefix - Include 0x prefix (default: true)\n * @returns Hex string\n */\nexport function bytesToHex(bytes: Uint8Array, withPrefix: boolean = true): string {\n const hex = Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n return withPrefix ? `0x${hex}` : hex\n}\n\n/**\n * Validate an account ID format\n *\n * Account IDs are 64-character hex strings (32 bytes).\n *\n * @param accountId - Account ID to validate\n * @returns True if valid\n */\nexport function isValidAccountId(accountId: string): boolean {\n return /^[0-9a-fA-F]{64}$/.test(accountId)\n}\n\n/**\n * Validate an EVM address format\n *\n * @param address - Address to validate\n * @returns True if valid\n */\nexport function isValidEvmAddress(address: string): boolean {\n return /^0x[0-9a-fA-F]{40}$/.test(address)\n}\n\n/**\n * Sleep for a specified duration\n *\n * @param ms - Milliseconds to sleep\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Retry a function with exponential backoff\n *\n * @param fn - Function to retry\n * @param maxRetries - Maximum number of retries (default: 3)\n * @param baseDelay - Base delay in ms (default: 1000)\n * @returns Result of the function\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n maxRetries: number = 3,\n baseDelay: number = 1000\n): Promise<T> {\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn()\n } catch (error) {\n lastError = error as Error\n\n if (attempt < maxRetries) {\n const delay = baseDelay * Math.pow(2, attempt)\n await sleep(delay)\n }\n }\n }\n\n throw lastError\n}\n\n/**\n * Parse a JWT token (without validation)\n *\n * @param token - JWT token string\n * @returns Decoded payload\n */\nexport function parseJwt(token: string): Record<string, unknown> {\n const parts = token.split('.')\n if (parts.length !== 3) {\n throw new Error('Invalid JWT format')\n }\n\n const payload = base64UrlDecode(parts[1])\n const text = new TextDecoder().decode(payload)\n return JSON.parse(text)\n}\n\n/**\n * Get JWT expiration time\n *\n * @param token - JWT token string\n * @returns Expiration timestamp in milliseconds, or null if no exp claim\n */\nexport function getJwtExpiration(token: string): number | null {\n try {\n const payload = parseJwt(token)\n if (typeof payload.exp === 'number') {\n return payload.exp * 1000 // Convert seconds to milliseconds\n }\n return null\n } catch {\n return null\n }\n}\n\n/**\n * Format an error for display\n *\n * @param error - Error to format\n * @returns Formatted error message\n */\nexport function formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message\n }\n if (typeof error === 'string') {\n return error\n }\n return 'An unknown error occurred'\n}\n","import type {\n AuthSession,\n PasskeyAuthOptions,\n PasskeyCredential,\n PasskeyRegistrationOptions,\n TokenStorage,\n PasswordAuthOptions,\n PasswordAccountCreationOptions,\n AccountCreationResponse,\n} from './types'\nimport { KentuckySignerClient, KentuckySignerError } from './client'\nimport { base64UrlEncode, base64UrlDecode } from './utils'\nimport type { Address } from 'viem'\n\n/**\n * Check if WebAuthn is available in the current environment\n */\nexport function isWebAuthnAvailable(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.PublicKeyCredential !== 'undefined' &&\n typeof navigator.credentials !== 'undefined'\n )\n}\n\n/**\n * In-memory token storage (default implementation)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n private token: string | null = null\n private expiresAt: number = 0\n\n async getToken(): Promise<string | null> {\n if (this.token && Date.now() < this.expiresAt) {\n return this.token\n }\n return null\n }\n\n async setToken(token: string, expiresAt: number): Promise<void> {\n this.token = token\n this.expiresAt = expiresAt\n }\n\n async clearToken(): Promise<void> {\n this.token = null\n this.expiresAt = 0\n }\n}\n\n/**\n * Browser localStorage token storage\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n private keyPrefix: string\n\n constructor(keyPrefix: string = 'kentucky_signer') {\n this.keyPrefix = keyPrefix\n }\n\n async getToken(): Promise<string | null> {\n if (typeof localStorage === 'undefined') return null\n\n const token = localStorage.getItem(`${this.keyPrefix}_token`)\n const expiresAt = localStorage.getItem(`${this.keyPrefix}_expires`)\n\n if (token && expiresAt && Date.now() < parseInt(expiresAt, 10)) {\n return token\n }\n\n // Clear expired token\n await this.clearToken()\n return null\n }\n\n async setToken(token: string, expiresAt: number): Promise<void> {\n if (typeof localStorage === 'undefined') return\n\n localStorage.setItem(`${this.keyPrefix}_token`, token)\n localStorage.setItem(`${this.keyPrefix}_expires`, expiresAt.toString())\n }\n\n async clearToken(): Promise<void> {\n if (typeof localStorage === 'undefined') return\n\n localStorage.removeItem(`${this.keyPrefix}_token`)\n localStorage.removeItem(`${this.keyPrefix}_expires`)\n }\n}\n\n/**\n * Convert a PublicKeyCredential to our PasskeyCredential format\n */\nfunction credentialToPasskey(credential: PublicKeyCredential): PasskeyCredential {\n const response = credential.response as AuthenticatorAssertionResponse\n\n return {\n credentialId: base64UrlEncode(new Uint8Array(credential.rawId)),\n clientDataJSON: base64UrlEncode(new Uint8Array(response.clientDataJSON)),\n authenticatorData: base64UrlEncode(new Uint8Array(response.authenticatorData)),\n signature: base64UrlEncode(new Uint8Array(response.signature)),\n userHandle: response.userHandle\n ? base64UrlEncode(new Uint8Array(response.userHandle))\n : undefined,\n }\n}\n\n/**\n * Authenticate with a passkey (browser only)\n *\n * This function handles the full WebAuthn authentication flow:\n * 1. Request a challenge from the Kentucky Signer\n * 2. Prompt the user to authenticate with their passkey\n * 3. Send the credential to the Kentucky Signer\n * 4. Return an authenticated session\n *\n * @param options - Passkey authentication options\n * @returns Authenticated session\n */\nexport async function authenticateWithPasskey(\n options: PasskeyAuthOptions\n): Promise<AuthSession> {\n if (!isWebAuthnAvailable()) {\n throw new KentuckySignerError(\n 'WebAuthn is not available in this environment',\n 'WEBAUTHN_NOT_AVAILABLE',\n 'Use authenticateWithToken() for server-side authentication'\n )\n }\n\n const client = new KentuckySignerClient({ baseUrl: options.baseUrl })\n\n // Step 1: Get challenge\n const challengeResponse = await client.getChallenge(options.accountId)\n const challengeBytes = base64UrlDecode(challengeResponse.challenge)\n\n // Step 2: Build credential request options\n const credentialRequestOptions: CredentialRequestOptions = {\n publicKey: {\n challenge: challengeBytes.buffer as ArrayBuffer,\n timeout: 60000,\n rpId: options.rpId ?? window.location.hostname,\n userVerification: 'preferred',\n allowCredentials: options.allowCredentials?.map((id) => ({\n type: 'public-key' as const,\n id: base64UrlDecode(id).buffer as ArrayBuffer,\n })),\n },\n }\n\n // Step 3: Request credential from user\n const credential = (await navigator.credentials.get(\n credentialRequestOptions\n )) as PublicKeyCredential | null\n\n if (!credential) {\n throw new KentuckySignerError(\n 'User cancelled passkey authentication',\n 'USER_CANCELLED'\n )\n }\n\n // Step 4: Authenticate with Kentucky Signer\n const passkeyCredential = credentialToPasskey(credential)\n const authResponse = await client.authenticatePasskey(\n options.accountId,\n passkeyCredential\n )\n\n // Step 5: Get account info to retrieve addresses\n const accountInfo = await client.getAccountInfo(\n options.accountId,\n authResponse.token\n )\n\n // Step 6: Build and return session\n const expiresAt = Date.now() + authResponse.expires_in * 1000\n\n return {\n token: authResponse.token,\n accountId: options.accountId,\n evmAddress: accountInfo.addresses.evm as Address,\n btcAddress: accountInfo.addresses.bitcoin,\n solAddress: accountInfo.addresses.solana,\n expiresAt,\n }\n}\n\n/**\n * Create an authenticated session from an existing JWT token (Node.js compatible)\n *\n * Use this for server-side applications where you already have a JWT token.\n *\n * @param baseUrl - Kentucky Signer API URL\n * @param accountId - Account ID\n * @param token - JWT token\n * @param expiresAt - Token expiration timestamp (Unix ms), optional\n * @returns Authenticated session\n */\nexport async function authenticateWithToken(\n baseUrl: string,\n accountId: string,\n token: string,\n expiresAt?: number\n): Promise<AuthSession> {\n const client = new KentuckySignerClient({ baseUrl })\n\n // Get account info to retrieve addresses\n const accountInfo = await client.getAccountInfo(accountId, token)\n\n return {\n token,\n accountId,\n evmAddress: accountInfo.addresses.evm as Address,\n btcAddress: accountInfo.addresses.bitcoin,\n solAddress: accountInfo.addresses.solana,\n expiresAt: expiresAt ?? Date.now() + 3600000, // Default 1 hour if not specified\n }\n}\n\n/**\n * Register a new passkey for account creation (browser only)\n *\n * @param options - Registration options\n * @returns Registration credential with public key\n */\nexport async function registerPasskey(\n options: PasskeyRegistrationOptions\n): Promise<PasskeyCredential & { publicKey: string }> {\n if (!isWebAuthnAvailable()) {\n throw new KentuckySignerError(\n 'WebAuthn is not available in this environment',\n 'WEBAUTHN_NOT_AVAILABLE'\n )\n }\n\n // Generate a random user ID\n const userId = new Uint8Array(32)\n crypto.getRandomValues(userId)\n\n // Generate a random challenge\n const challenge = new Uint8Array(32)\n crypto.getRandomValues(challenge)\n\n const createOptions: CredentialCreationOptions = {\n publicKey: {\n challenge,\n rp: {\n name: options.rpName ?? 'Kentucky Signer',\n id: options.rpId ?? window.location.hostname,\n },\n user: {\n id: userId,\n name: options.username ?? 'user@example.com',\n displayName: options.username ?? 'User',\n },\n pubKeyCredParams: [\n { type: 'public-key', alg: -7 }, // ES256 (P-256)\n { type: 'public-key', alg: -257 }, // RS256\n ],\n authenticatorSelection: {\n authenticatorAttachment: 'platform',\n userVerification: 'preferred',\n residentKey: 'preferred',\n },\n timeout: 60000,\n attestation: 'none',\n },\n }\n\n const credential = (await navigator.credentials.create(\n createOptions\n )) as PublicKeyCredential | null\n\n if (!credential) {\n throw new KentuckySignerError(\n 'User cancelled passkey registration',\n 'USER_CANCELLED'\n )\n }\n\n const response = credential.response as AuthenticatorAttestationResponse\n\n // Extract public key from attestation object\n const publicKeyBytes = response.getPublicKey?.()\n if (!publicKeyBytes) {\n throw new KentuckySignerError(\n 'Failed to get public key from credential',\n 'PUBLIC_KEY_ERROR'\n )\n }\n\n return {\n credentialId: base64UrlEncode(new Uint8Array(credential.rawId)),\n clientDataJSON: base64UrlEncode(new Uint8Array(response.clientDataJSON)),\n authenticatorData: base64UrlEncode(new Uint8Array(response.getAuthenticatorData())),\n signature: '', // Not applicable for registration\n publicKey: base64UrlEncode(new Uint8Array(publicKeyBytes)),\n }\n}\n\n/**\n * Check if a session is still valid\n *\n * @param session - Session to check\n * @param bufferMs - Buffer time before expiration (default 60 seconds)\n * @returns True if session is valid\n */\nexport function isSessionValid(session: AuthSession, bufferMs: number = 60000): boolean {\n return Date.now() + bufferMs < session.expiresAt\n}\n\n/**\n * Refresh a session if needed\n *\n * @param session - Current session\n * @param baseUrl - Kentucky Signer API URL\n * @param bufferMs - Buffer time before expiration (default 60 seconds)\n * @returns Updated session (or original if still valid)\n */\nexport async function refreshSessionIfNeeded(\n session: AuthSession,\n baseUrl: string,\n bufferMs: number = 60000\n): Promise<AuthSession> {\n if (isSessionValid(session, bufferMs)) {\n return session\n }\n\n const client = new KentuckySignerClient({ baseUrl })\n const authResponse = await client.refreshToken(session.token)\n\n return {\n ...session,\n token: authResponse.token,\n expiresAt: Date.now() + authResponse.expires_in * 1000,\n }\n}\n\n/**\n * Authenticate with password (works in browser and Node.js)\n *\n * @param options - Password authentication options\n * @returns Authenticated session\n *\n * @example\n * ```typescript\n * const session = await authenticateWithPassword({\n * baseUrl: 'https://signer.example.com',\n * accountId: '0123456789abcdef...',\n * password: 'your-secure-password',\n * })\n * ```\n */\nexport async function authenticateWithPassword(\n options: PasswordAuthOptions\n): Promise<AuthSession> {\n const client = new KentuckySignerClient({ baseUrl: options.baseUrl })\n\n // Authenticate with password\n const authResponse = await client.authenticatePassword({\n account_id: options.accountId,\n password: options.password,\n })\n\n // Get account info to retrieve addresses\n const accountInfo = await client.getAccountInfo(\n options.accountId,\n authResponse.token\n )\n\n // Build and return session\n const expiresAt = Date.now() + authResponse.expires_in * 1000\n\n return {\n token: authResponse.token,\n accountId: options.accountId,\n evmAddress: accountInfo.addresses.evm as Address,\n btcAddress: accountInfo.addresses.bitcoin,\n solAddress: accountInfo.addresses.solana,\n expiresAt,\n }\n}\n\n/**\n * Create a new account with password authentication (works in browser and Node.js)\n *\n * @param options - Account creation options with password\n * @returns Account creation response with account ID and addresses\n *\n * @example\n * ```typescript\n * const account = await createAccountWithPassword({\n * baseUrl: 'https://signer.example.com',\n * password: 'your-secure-password',\n * confirmation: 'your-secure-password',\n * })\n * console.log('Account ID:', account.account_id)\n * console.log('EVM Address:', account.addresses.evm)\n * ```\n */\nexport async function createAccountWithPassword(\n options: PasswordAccountCreationOptions\n): Promise<AccountCreationResponse> {\n // Validate password matches confirmation\n if (options.password !== options.confirmation) {\n throw new KentuckySignerError(\n 'Password and confirmation do not match',\n 'PASSWORD_MISMATCH'\n )\n }\n\n // Validate password length\n if (options.password.length < 8 || options.password.length > 128) {\n throw new KentuckySignerError(\n 'Password must be 8-128 characters',\n 'INVALID_PASSWORD'\n )\n }\n\n const client = new KentuckySignerClient({ baseUrl: options.baseUrl })\n\n return client.createAccountWithPassword({\n password: options.password,\n confirmation: options.confirmation,\n })\n}\n","import {\n type Account,\n type Address,\n type Chain,\n type Hex,\n type LocalAccount,\n type SignableMessage,\n type TransactionSerializable,\n type TypedData,\n type TypedDataDefinition,\n hashMessage,\n hashTypedData,\n keccak256,\n serializeTransaction,\n toHex,\n concat,\n numberToHex,\n} from 'viem'\nimport { toAccount } from 'viem/accounts'\nimport type { AuthSession, KentuckySignerConfig } from './types'\nimport { KentuckySignerClient, KentuckySignerError } from './client'\n\n/**\n * Options for creating a Kentucky Signer account\n */\nexport interface KentuckySignerAccountOptions {\n /** Kentucky Signer configuration */\n config: KentuckySignerConfig\n /** Authenticated session */\n session: AuthSession\n /** Default chain ID for signing (can be overridden per-transaction) */\n defaultChainId?: number\n /** Callback when session needs refresh */\n onSessionExpired?: () => Promise<AuthSession>\n}\n\n/**\n * Extended account type with Kentucky Signer specific properties\n */\nexport interface KentuckySignerAccount extends LocalAccount<'kentuckySigner'> {\n /** Account ID */\n accountId: string\n /** Current session */\n session: AuthSession\n /** Update the session (e.g., after refresh) */\n updateSession: (session: AuthSession) => void\n}\n\n/**\n * Create a custom Viem account backed by Kentucky Signer\n *\n * This account implementation uses the Kentucky Signer API to sign\n * transactions, messages, and typed data using passkey authentication.\n *\n * @param options - Account options\n * @returns Viem-compatible account\n *\n * @example\n * ```typescript\n * const account = createKentuckySignerAccount({\n * config: {\n * baseUrl: 'https://signer.example.com',\n * accountId: '0x...',\n * },\n * session: authenticatedSession,\n * defaultChainId: 1,\n * })\n *\n * const walletClient = createWalletClient({\n * account,\n * chain: mainnet,\n * transport: http(),\n * })\n *\n * const hash = await walletClient.sendTransaction({\n * to: '0x...',\n * value: parseEther('0.1'),\n * })\n * ```\n */\nexport function createKentuckySignerAccount(\n options: KentuckySignerAccountOptions\n): KentuckySignerAccount {\n const { config, defaultChainId = 1, onSessionExpired } = options\n let session = options.session\n\n const client = new KentuckySignerClient({ baseUrl: config.baseUrl })\n\n /**\n * Get current token, refreshing if needed\n */\n async function getToken(): Promise<string> {\n // Check if session is about to expire (within 60 seconds)\n if (Date.now() + 60000 >= session.expiresAt) {\n if (onSessionExpired) {\n session = await onSessionExpired()\n } else {\n throw new KentuckySignerError(\n 'Session expired',\n 'SESSION_EXPIRED',\n 'Please re-authenticate with your passkey'\n )\n }\n }\n return session.token\n }\n\n /**\n * Sign a hash using Kentucky Signer\n */\n async function signHash(hash: Hex, chainId: number): Promise<Hex> {\n const token = await getToken()\n const response = await client.signEvmTransaction(\n { tx_hash: hash, chain_id: chainId },\n token\n )\n return response.signature.full\n }\n\n /**\n * Parse signature components from full signature\n */\n function parseSignature(signature: Hex): { r: Hex; s: Hex; v: bigint } {\n // Signature is 65 bytes: r (32) + s (32) + v (1)\n const r = `0x${signature.slice(2, 66)}` as Hex\n const s = `0x${signature.slice(66, 130)}` as Hex\n const v = BigInt(`0x${signature.slice(130, 132)}`)\n return { r, s, v }\n }\n\n const account = toAccount({\n address: session.evmAddress,\n\n /**\n * Sign a message\n *\n * Supports string messages, hex messages, and raw bytes.\n */\n async signMessage({ message }: { message: SignableMessage }): Promise<Hex> {\n const messageHash = hashMessage(message)\n return signHash(messageHash, defaultChainId)\n },\n\n /**\n * Sign a transaction\n *\n * Serializes the transaction, hashes it, signs via Kentucky Signer,\n * and returns the signed serialized transaction.\n */\n async signTransaction(\n transaction: TransactionSerializable\n ): Promise<Hex> {\n // Get chain ID from transaction or use default\n const chainId = transaction.chainId ?? defaultChainId\n\n // Serialize unsigned transaction\n const serializedUnsigned = serializeTransaction(transaction)\n\n // Hash the serialized transaction\n const txHash = keccak256(serializedUnsigned)\n\n // Sign the hash\n const signature = await signHash(txHash, chainId)\n\n // Parse signature components\n const { r, s, v } = parseSignature(signature)\n\n // For EIP-1559 and EIP-2930 transactions, v is 0 or 1\n // For legacy transactions, v is chainId * 2 + 35 + recovery\n let yParity: number\n if (\n transaction.type === 'eip1559' ||\n transaction.type === 'eip2930' ||\n transaction.type === 'eip4844' ||\n transaction.type === 'eip7702'\n ) {\n yParity = Number(v) - 27 // Convert from 27/28 to 0/1\n } else {\n // Legacy transaction - v already includes chain ID\n yParity = Number(v)\n }\n\n // Serialize with signature\n const serializedSigned = serializeTransaction(transaction, {\n r,\n s,\n v: BigInt(yParity),\n yParity,\n } as any)\n\n return serializedSigned\n },\n\n /**\n * Sign typed data (EIP-712)\n */\n async signTypedData<\n const TTypedData extends TypedData | Record<string, unknown>,\n TPrimaryType extends keyof TTypedData | 'EIP712Domain' = keyof TTypedData\n >(\n typedData: TypedDataDefinition<TTypedData, TPrimaryType>\n ): Promise<Hex> {\n const hash = hashTypedData(typedData)\n return signHash(hash, defaultChainId)\n },\n }) as KentuckySignerAccount\n\n // Add Kentucky Signer specific properties\n account.source = 'kentuckySigner'\n account.accountId = config.accountId\n account.session = session\n account.updateSession = (newSession: AuthSession) => {\n session = newSession\n // Update address if changed (shouldn't happen but handle it)\n if (newSession.evmAddress !== account.address) {\n ;(account as any).address = newSession.evmAddress\n }\n }\n\n return account\n}\n\n/**\n * Create a Kentucky Signer account for server-side use\n *\n * Convenience function for Node.js environments where you have\n * a pre-existing JWT token.\n *\n * @param baseUrl - Kentucky Signer API URL\n * @param accountId - Account ID\n * @param token - JWT token\n * @param evmAddress - EVM address for the account\n * @param chainId - Default chain ID\n * @returns Kentucky Signer account\n */\nexport function createServerAccount(\n baseUrl: string,\n accountId: string,\n token: string,\n evmAddress: Address,\n chainId: number = 1\n): KentuckySignerAccount {\n const session: AuthSession = {\n token,\n accountId,\n evmAddress,\n expiresAt: Date.now() + 3600000, // 1 hour default\n }\n\n return createKentuckySignerAccount({\n config: { baseUrl, accountId },\n session,\n defaultChainId: chainId,\n })\n}\n","import { useMemo, useCallback, useState } from 'react'\nimport { createWalletClient, http, type Chain, type WalletClient, type Transport } from 'viem'\nimport { useKentuckySignerContext } from './context'\nimport type { KentuckySignerAccount } from '../account'\n\n/**\n * Hook to access Kentucky Signer authentication state\n *\n * @returns Authentication state and actions\n *\n * @example\n * ```tsx\n * function LoginButton() {\n * const { isAuthenticated, isAuthenticating, authenticate, logout } = useKentuckySigner()\n *\n * if (isAuthenticated) {\n * return <button onClick={logout}>Logout</button>\n * }\n *\n * return (\n * <button onClick={() => authenticate('account_id')} disabled={isAuthenticating}>\n * {isAuthenticating ? 'Authenticating...' : 'Login with Passkey'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useKentuckySigner() {\n const context = useKentuckySignerContext()\n\n return {\n isAuthenticated: context.isAuthenticated,\n isAuthenticating: context.isAuthenticating,\n session: context.session,\n account: context.account,\n error: context.error,\n authenticate: context.authenticate,\n logout: context.logout,\n refreshSession: context.refreshSession,\n clearError: context.clearError,\n }\n}\n\n/**\n * Hook to access the Kentucky Signer account\n *\n * @returns Account or null if not authenticated\n *\n * @example\n * ```tsx\n * function AccountInfo() {\n * const account = useKentuckySignerAccount()\n *\n * if (!account) return <div>Not connected</div>\n *\n * return <div>Connected: {account.address}</div>\n * }\n * ```\n */\nexport function useKentuckySignerAccount(): KentuckySignerAccount | null {\n const { account } = useKentuckySignerContext()\n return account\n}\n\n/**\n * Options for useWalletClient hook\n */\nexport interface UseWalletClientOptions {\n /** Viem chain configuration */\n chain: Chain\n /** RPC URL (defaults to chain's default RPC) */\n rpcUrl?: string\n}\n\n/**\n * Hook to create a Viem WalletClient with the Kentucky Signer account\n *\n * @param options - Wallet client options\n * @returns Wallet client or null if not authenticated\n *\n * @example\n * ```tsx\n * import { mainnet } from 'viem/chains'\n *\n * function SendTransaction() {\n * const walletClient = useWalletClient({\n * chain: mainnet,\n * rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/...'\n * })\n *\n * async function send() {\n * if (!walletClient) return\n *\n * const hash = await walletClient.sendTransaction({\n * to: '0x...',\n * value: parseEther('0.1')\n * })\n * console.log('Transaction hash:', hash)\n * }\n *\n * return <button onClick={send} disabled={!walletClient}>Send</button>\n * }\n * ```\n */\nexport function useWalletClient(\n options: UseWalletClientOptions\n): WalletClient<Transport, Chain, KentuckySignerAccount> | null {\n const { account } = useKentuckySignerContext()\n const { chain, rpcUrl } = options\n\n return useMemo(() => {\n if (!account) return null\n\n return createWalletClient({\n account,\n chain,\n transport: http(rpcUrl),\n }) as WalletClient<Transport, Chain, KentuckySignerAccount>\n }, [account, chain, rpcUrl])\n}\n\n/**\n * Hook for passkey authentication flow\n *\n * Provides state management for the authentication process.\n *\n * @returns Authentication state and trigger function\n *\n * @example\n * ```tsx\n * function PasskeyLogin() {\n * const { login, isLoading, error } = usePasskeyAuth()\n *\n * return (\n * <div>\n * <input\n * placeholder=\"Account ID\"\n * onChange={(e) => setAccountId(e.target.value)}\n * />\n * <button onClick={() => login(accountId)} disabled={isLoading}>\n * {isLoading ? 'Authenticating...' : 'Login'}\n * </button>\n * {error && <div className=\"error\">{error.message}</div>}\n * </div>\n * )\n * }\n * ```\n */\nexport function usePasskeyAuth() {\n const { authenticate, isAuthenticating, error, clearError } =\n useKentuckySignerContext()\n\n const login = useCallback(\n async (accountId: string, options?: { rpId?: string }) => {\n clearError()\n await authenticate(accountId, options)\n },\n [authenticate, clearError]\n )\n\n return {\n login,\n isLoading: isAuthenticating,\n error,\n clearError,\n }\n}\n\n/**\n * Hook for signing messages\n *\n * @returns Sign function and loading state\n *\n * @example\n * ```tsx\n * function SignMessage() {\n * const { signMessage, isLoading } = useSignMessage()\n * const [signature, setSignature] = useState('')\n *\n * async function sign() {\n * const sig = await signMessage('Hello, World!')\n * setSignature(sig)\n * }\n *\n * return (\n * <div>\n * <button onClick={sign} disabled={isLoading}>Sign Message</button>\n * {signature && <div>Signature: {signature}</div>}\n * </div>\n * )\n * }\n * ```\n */\nexport function useSignMessage() {\n const { account } = useKentuckySignerContext()\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const signMessage = useCallback(\n async (message: string): Promise<string> => {\n if (!account) {\n throw new Error('Not authenticated')\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const signature = await account.signMessage({ message })\n return signature\n } catch (err) {\n setError(err as Error)\n throw err\n } finally {\n setIsLoading(false)\n }\n },\n [account]\n )\n\n return {\n signMessage,\n isLoading,\n error,\n isAvailable: !!account,\n }\n}\n\n/**\n * Hook for signing typed data (EIP-712)\n *\n * @returns Sign function and loading state\n */\nexport function useSignTypedData() {\n const { account } = useKentuckySignerContext()\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const signTypedData = useCallback(\n async (typedData: Parameters<NonNullable<typeof account>['signTypedData']>[0]): Promise<string> => {\n if (!account) {\n throw new Error('Not authenticated')\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const signature = await account.signTypedData(typedData)\n return signature\n } catch (err) {\n setError(err as Error)\n throw err\n } finally {\n setIsLoading(false)\n }\n },\n [account]\n )\n\n return {\n signTypedData,\n isLoading,\n error,\n isAvailable: !!account,\n }\n}\n\n/**\n * Hook to check if Kentucky Signer is ready\n *\n * @returns Whether the signer is authenticated and ready\n */\nexport function useIsReady(): boolean {\n const { isAuthenticated, account } = useKentuckySignerContext()\n return isAuthenticated && account !== null\n}\n\n/**\n * Hook to get the connected address\n *\n * @returns EVM address or undefined if not connected\n */\nexport function useAddress(): `0x${string}` | undefined {\n const { account } = useKentuckySignerContext()\n return account?.address\n}\n"],"mappings":"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","names":["account","useMemo","useCallback","useState","useMemo","useCallback","useState"]}
1
+ {"version":3,"sources":["../../src/react/context.tsx","../../src/client.ts","../../src/utils.ts","../../src/ephemeral.ts","../../src/secure-client.ts","../../src/auth.ts","../../src/account.ts","../../src/react/hooks.ts"],"sourcesContent":["import {\n createContext,\n useContext,\n useState,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n type ReactNode,\n} from 'react'\nimport type { AuthSession } from '../types'\nimport type { TwoFactorCodes } from '../account'\nimport { KentuckySignerClient } from '../client'\nimport { SecureKentuckySignerClient } from '../secure-client'\nimport {\n authenticateWithPasskey,\n authenticateWithPassword as authWithPassword,\n isSessionValid,\n refreshSessionIfNeeded,\n LocalStorageTokenStorage,\n} from '../auth'\nimport {\n createKentuckySignerAccount,\n type KentuckySignerAccount,\n} from '../account'\nimport {\n EphemeralKeyManager,\n IndexedDBEphemeralKeyStorage,\n MemoryEphemeralKeyStorage,\n} from '../ephemeral'\n\n/**\n * 2FA prompt requirements\n */\nexport interface TwoFactorPromptState {\n /** Whether the 2FA prompt is visible */\n isVisible: boolean\n /** Whether TOTP is required */\n totpRequired: boolean\n /** Whether PIN is required */\n pinRequired: boolean\n /** Expected PIN length (4 or 6) */\n pinLength: number\n /** Callback to resolve with codes */\n resolve?: (codes: TwoFactorCodes | null) => void\n}\n\n/**\n * Kentucky Signer context state\n */\nexport interface KentuckySignerState {\n /** Whether authentication is in progress */\n isAuthenticating: boolean\n /** Whether the user is authenticated */\n isAuthenticated: boolean\n /** Current session (if authenticated) */\n session: AuthSession | null\n /** Current account (if authenticated) */\n account: KentuckySignerAccount | null\n /** Last error (if any) */\n error: Error | null\n /** Whether ephemeral key is bound to the token */\n ephemeralKeyBound: boolean\n /** Whether secure mode (ephemeral key signing) is enabled */\n secureMode: boolean\n /** Whether ephemeral keys are persisted in IndexedDB (survives refresh) */\n persistEphemeralKeys: boolean\n /** 2FA prompt state */\n twoFactorPrompt: TwoFactorPromptState\n}\n\n/**\n * Kentucky Signer context actions\n */\nexport interface KentuckySignerActions {\n /** Authenticate with passkey or set an existing session */\n authenticate: (accountId: string, options?: { rpId?: string; session?: AuthSession }) => Promise<void>\n /** Authenticate with password */\n authenticatePassword: (accountId: string, password: string) => Promise<void>\n /** Logout and clear session */\n logout: () => Promise<void>\n /** Refresh session if needed */\n refreshSession: () => Promise<void>\n /** Clear any errors */\n clearError: () => void\n /** Toggle secure mode (ephemeral key signing) */\n setSecureMode: (enabled: boolean) => void\n /** Toggle ephemeral key persistence (IndexedDB vs memory) */\n setPersistEphemeralKeys: (enabled: boolean) => void\n /** Get the ephemeral public key (for secure mode binding during external auth) */\n getEphemeralPublicKey: () => Promise<string | undefined>\n /** Submit 2FA codes (called by 2FA prompt UI) */\n submit2FA: (codes: TwoFactorCodes) => void\n /** Cancel 2FA prompt */\n cancel2FA: () => void\n}\n\n/**\n * Full Kentucky Signer context value\n */\nexport type KentuckySignerContextValue = KentuckySignerState & KentuckySignerActions\n\nconst KentuckySignerContext = createContext<KentuckySignerContextValue | null>(null)\n\n/**\n * Kentucky Signer provider props\n */\nexport interface KentuckySignerProviderProps {\n /** Base URL of the Kentucky Signer API */\n baseUrl: string\n /** Default chain ID for signing */\n defaultChainId?: number\n /** Storage key prefix for persisting tokens */\n storageKeyPrefix?: string\n /** Whether to persist session in localStorage */\n persistSession?: boolean\n /** Whether to use ephemeral key signing for enhanced security */\n useEphemeralKeys?: boolean\n /** Children */\n children: ReactNode\n}\n\n/**\n * Kentucky Signer Provider\n *\n * Wraps your app to provide Kentucky Signer authentication and signing context.\n *\n * @example\n * ```tsx\n * <KentuckySignerProvider baseUrl=\"https://signer.example.com\">\n * <App />\n * </KentuckySignerProvider>\n * ```\n */\nexport function KentuckySignerProvider({\n baseUrl,\n defaultChainId = 1,\n storageKeyPrefix = 'kentucky_signer',\n persistSession = true,\n useEphemeralKeys = false,\n children,\n}: KentuckySignerProviderProps) {\n // Load persist ephemeral keys setting from localStorage, default to IndexedDB if available\n const getInitialPersistSetting = (): boolean => {\n if (typeof localStorage !== 'undefined') {\n const saved = localStorage.getItem(`${storageKeyPrefix}_persist_ephemeral_keys`)\n if (saved !== null) {\n return saved === 'true'\n }\n }\n // Default to IndexedDB persistence if available\n return typeof indexedDB !== 'undefined'\n }\n\n // Load secure mode setting from localStorage, falling back to useEphemeralKeys prop\n const getInitialSecureModeSetting = (): boolean => {\n if (typeof localStorage !== 'undefined') {\n const saved = localStorage.getItem(`${storageKeyPrefix}_secure_mode`)\n if (saved !== null) {\n return saved === 'true'\n }\n }\n // Fall back to prop value\n return useEphemeralKeys\n }\n\n // Default 2FA prompt state\n const defaultTwoFactorPrompt: TwoFactorPromptState = {\n isVisible: false,\n totpRequired: false,\n pinRequired: false,\n pinLength: 6,\n }\n\n const [state, setState] = useState<KentuckySignerState>({\n isAuthenticating: false,\n isAuthenticated: false,\n session: null,\n account: null,\n error: null,\n ephemeralKeyBound: false,\n secureMode: getInitialSecureModeSetting(),\n persistEphemeralKeys: getInitialPersistSetting(),\n twoFactorPrompt: defaultTwoFactorPrompt,\n })\n\n // Ephemeral key storage instances - we keep both and switch between them\n const indexedDBStorage = useMemo(\n () => typeof indexedDB !== 'undefined' ? new IndexedDBEphemeralKeyStorage() : null,\n []\n )\n const memoryStorage = useMemo(() => new MemoryEphemeralKeyStorage(), [])\n\n // Current active storage based on persist setting\n const ephemeralKeyStorage = state.persistEphemeralKeys && indexedDBStorage\n ? indexedDBStorage\n : memoryStorage\n\n // Single ephemeral key manager instance that we update storage on\n const ephemeralKeyManagerRef = useRef<EphemeralKeyManager | null>(null)\n if (!ephemeralKeyManagerRef.current) {\n ephemeralKeyManagerRef.current = new EphemeralKeyManager(ephemeralKeyStorage)\n }\n const ephemeralKeyManager = ephemeralKeyManagerRef.current\n\n const client = useMemo(\n () => new KentuckySignerClient({ baseUrl }),\n [baseUrl]\n )\n\n // Secure client for ephemeral key signing - uses shared key manager\n const secureClient = useMemo(\n () => new SecureKentuckySignerClient({\n baseUrl,\n ephemeralKeyManager,\n }),\n [baseUrl, ephemeralKeyManager]\n )\n\n const storage = useMemo(\n () => (persistSession ? new LocalStorageTokenStorage(storageKeyPrefix) : null),\n [persistSession, storageKeyPrefix]\n )\n\n // 2FA callback handler - shows prompt and waits for user input\n const handle2FARequired = useCallback(async (requirements: {\n totpRequired: boolean\n pinRequired: boolean\n pinLength: number\n }): Promise<TwoFactorCodes | null> => {\n return new Promise((resolve) => {\n setState((s) => ({\n ...s,\n twoFactorPrompt: {\n isVisible: true,\n totpRequired: requirements.totpRequired,\n pinRequired: requirements.pinRequired,\n pinLength: requirements.pinLength,\n resolve,\n },\n }))\n })\n }, [])\n\n // Create account from session\n const createAccount = useCallback(\n (session: AuthSession, useSecureClient: boolean = false): KentuckySignerAccount => {\n return createKentuckySignerAccount({\n config: { baseUrl, accountId: session.accountId },\n session,\n defaultChainId,\n secureClient: useSecureClient ? secureClient : undefined,\n onSessionExpired: async () => {\n // Try to refresh the session\n const newSession = await refreshSessionIfNeeded(session, baseUrl, 0)\n setState((s) => ({\n ...s,\n session: newSession,\n account: s.account\n ? { ...s.account, session: newSession }\n : null,\n }))\n return newSession\n },\n on2FARequired: handle2FARequired,\n })\n },\n [baseUrl, defaultChainId, secureClient, handle2FARequired]\n )\n\n // Restore session from storage on mount\n useEffect(() => {\n async function restoreSession() {\n if (!storage) return\n\n try {\n const savedSession = localStorage.getItem(`${storageKeyPrefix}_session`)\n if (!savedSession) return\n\n const session: AuthSession = JSON.parse(savedSession)\n if (!isSessionValid(session)) {\n // Try to refresh\n try {\n const refreshed = await refreshSessionIfNeeded(session, baseUrl, 0)\n localStorage.setItem(\n `${storageKeyPrefix}_session`,\n JSON.stringify(refreshed)\n )\n setState((s) => {\n const account = createAccount(refreshed, s.secureMode)\n return {\n isAuthenticating: false,\n isAuthenticated: true,\n session: refreshed,\n account,\n error: null,\n ephemeralKeyBound: false,\n secureMode: s.secureMode,\n persistEphemeralKeys: s.persistEphemeralKeys,\n twoFactorPrompt: s.twoFactorPrompt,\n }\n })\n } catch {\n // Clear invalid session\n localStorage.removeItem(`${storageKeyPrefix}_session`)\n }\n return\n }\n\n setState((s) => {\n const account = createAccount(session, s.secureMode)\n return {\n isAuthenticating: false,\n isAuthenticated: true,\n session,\n account,\n error: null,\n ephemeralKeyBound: false,\n secureMode: s.secureMode,\n persistEphemeralKeys: s.persistEphemeralKeys,\n twoFactorPrompt: s.twoFactorPrompt,\n }\n })\n } catch {\n localStorage.removeItem(`${storageKeyPrefix}_session`)\n }\n }\n\n restoreSession()\n }, [storage, storageKeyPrefix, baseUrl, createAccount])\n\n // Authenticate with passkey or existing session\n const authenticate = useCallback(\n async (accountId: string, options?: { rpId?: string; session?: AuthSession }) => {\n setState((s) => ({ ...s, isAuthenticating: true, error: null }))\n\n try {\n let session: AuthSession\n let ephemeralKeyBound = false\n\n if (options?.session) {\n // Use provided session (no ephemeral binding possible)\n session = options.session\n } else {\n // Get ephemeral public key if secure mode is enabled\n let ephemeralPublicKey: string | undefined\n if (state.secureMode) {\n ephemeralPublicKey = await ephemeralKeyManager.getPublicKey()\n }\n\n // Authenticate with passkey\n session = await authenticateWithPasskey({\n baseUrl,\n accountId,\n rpId: options?.rpId,\n ephemeralPublicKey,\n })\n\n ephemeralKeyBound = !!ephemeralPublicKey\n }\n\n // Persist session\n if (storage) {\n localStorage.setItem(\n `${storageKeyPrefix}_session`,\n JSON.stringify(session)\n )\n }\n\n setState((s) => {\n const account = createAccount(session, s.secureMode)\n return {\n isAuthenticating: false,\n isAuthenticated: true,\n session,\n account,\n error: null,\n ephemeralKeyBound,\n secureMode: s.secureMode,\n persistEphemeralKeys: s.persistEphemeralKeys,\n twoFactorPrompt: s.twoFactorPrompt,\n }\n })\n } catch (error) {\n setState((s) => ({\n ...s,\n isAuthenticating: false,\n error: error as Error,\n }))\n throw error\n }\n },\n [baseUrl, createAccount, storage, storageKeyPrefix, state.secureMode, ephemeralKeyManager]\n )\n\n // Logout\n const logout = useCallback(async () => {\n try {\n if (state.session) {\n await client.logout(state.session.token)\n }\n } catch {\n // Ignore logout errors\n }\n\n // Clear storage\n if (storage) {\n localStorage.removeItem(`${storageKeyPrefix}_session`)\n }\n\n // Clear ephemeral keys if using secure mode\n if (ephemeralKeyManager) {\n await ephemeralKeyManager.clear()\n }\n\n setState((s) => ({\n isAuthenticating: false,\n isAuthenticated: false,\n session: null,\n account: null,\n error: null,\n ephemeralKeyBound: false,\n secureMode: s.secureMode,\n persistEphemeralKeys: s.persistEphemeralKeys,\n twoFactorPrompt: defaultTwoFactorPrompt,\n }))\n }, [client, state.session, storage, storageKeyPrefix, ephemeralKeyManager])\n\n // Refresh session\n const refreshSession = useCallback(async () => {\n if (!state.session) return\n\n try {\n const refreshed = await refreshSessionIfNeeded(state.session, baseUrl)\n\n if (refreshed !== state.session) {\n if (storage) {\n localStorage.setItem(\n `${storageKeyPrefix}_session`,\n JSON.stringify(refreshed)\n )\n }\n\n setState((s) => {\n const account = createAccount(refreshed, s.secureMode)\n return {\n ...s,\n session: refreshed,\n account,\n }\n })\n }\n } catch (error) {\n setState((s) => ({ ...s, error: error as Error }))\n }\n }, [state.session, baseUrl, createAccount, storage, storageKeyPrefix])\n\n // Clear error\n const clearError = useCallback(() => {\n setState((s) => ({ ...s, error: null }))\n }, [])\n\n // Toggle secure mode - recreates account with new client\n const setSecureMode = useCallback((enabled: boolean) => {\n // Persist the setting to localStorage\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(`${storageKeyPrefix}_secure_mode`, String(enabled))\n }\n\n setState((s) => {\n // Recreate account with new secure mode setting if authenticated\n const newAccount = s.session ? createAccount(s.session, enabled) : null\n return {\n ...s,\n secureMode: enabled,\n account: newAccount,\n }\n })\n }, [createAccount, storageKeyPrefix])\n\n // Toggle ephemeral key persistence - migrates key between IndexedDB and memory storage\n const setPersistEphemeralKeys = useCallback(async (enabled: boolean) => {\n // Determine the new storage backend\n const newStorage = enabled && indexedDBStorage\n ? indexedDBStorage\n : memoryStorage\n\n // Migrate the key to the new storage (preserves existing key)\n await ephemeralKeyManager.migrateStorage(newStorage)\n\n // Persist the setting to localStorage\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(`${storageKeyPrefix}_persist_ephemeral_keys`, String(enabled))\n }\n\n // Update state\n setState((s) => ({\n ...s,\n persistEphemeralKeys: enabled,\n }))\n }, [ephemeralKeyManager, storageKeyPrefix, indexedDBStorage, memoryStorage])\n\n // Get ephemeral public key for external auth flows\n const getEphemeralPublicKey = useCallback(async (): Promise<string | undefined> => {\n if (!state.secureMode) {\n return undefined\n }\n return ephemeralKeyManager.getPublicKey()\n }, [state.secureMode, ephemeralKeyManager])\n\n // Authenticate with password\n const authenticatePassword = useCallback(\n async (accountId: string, password: string) => {\n setState((s) => ({ ...s, isAuthenticating: true, error: null }))\n\n try {\n // Get ephemeral public key if secure mode is enabled\n let ephemeralPublicKey: string | undefined\n console.log('[KentuckySigner] authenticatePassword - secureMode:', state.secureMode)\n if (state.secureMode) {\n ephemeralPublicKey = await ephemeralKeyManager.getPublicKey()\n console.log('[KentuckySigner] Got ephemeral public key for binding:', ephemeralPublicKey?.substring(0, 50) + '...')\n }\n\n // Authenticate with password\n const session = await authWithPassword({\n baseUrl,\n accountId,\n password,\n ephemeralPublicKey,\n })\n\n const ephemeralKeyBound = !!ephemeralPublicKey\n\n // Persist session\n if (storage) {\n localStorage.setItem(\n `${storageKeyPrefix}_session`,\n JSON.stringify(session)\n )\n }\n\n setState((s) => {\n const account = createAccount(session, s.secureMode)\n return {\n isAuthenticating: false,\n isAuthenticated: true,\n session,\n account,\n error: null,\n ephemeralKeyBound,\n secureMode: s.secureMode,\n persistEphemeralKeys: s.persistEphemeralKeys,\n twoFactorPrompt: s.twoFactorPrompt,\n }\n })\n } catch (error) {\n setState((s) => ({\n ...s,\n isAuthenticating: false,\n error: error as Error,\n }))\n throw error\n }\n },\n [baseUrl, createAccount, storage, storageKeyPrefix, state.secureMode, ephemeralKeyManager]\n )\n\n // Submit 2FA codes\n const submit2FA = useCallback((codes: TwoFactorCodes) => {\n const { resolve } = state.twoFactorPrompt\n if (resolve) {\n resolve(codes)\n }\n setState((s) => ({\n ...s,\n twoFactorPrompt: defaultTwoFactorPrompt,\n }))\n }, [state.twoFactorPrompt])\n\n // Cancel 2FA prompt\n const cancel2FA = useCallback(() => {\n const { resolve } = state.twoFactorPrompt\n if (resolve) {\n resolve(null)\n }\n setState((s) => ({\n ...s,\n twoFactorPrompt: defaultTwoFactorPrompt,\n }))\n }, [state.twoFactorPrompt])\n\n const value: KentuckySignerContextValue = useMemo(\n () => ({\n ...state,\n authenticate,\n authenticatePassword,\n logout,\n refreshSession,\n clearError,\n setSecureMode,\n setPersistEphemeralKeys,\n getEphemeralPublicKey,\n submit2FA,\n cancel2FA,\n }),\n [state, authenticate, authenticatePassword, logout, refreshSession, clearError, setSecureMode, setPersistEphemeralKeys, getEphemeralPublicKey, submit2FA, cancel2FA]\n )\n\n return (\n <KentuckySignerContext.Provider value={value}>\n {children}\n </KentuckySignerContext.Provider>\n )\n}\n\n/**\n * Use the Kentucky Signer context\n *\n * Must be used within a KentuckySignerProvider.\n *\n * @returns Kentucky Signer context value\n */\nexport function useKentuckySignerContext(): KentuckySignerContextValue {\n const context = useContext(KentuckySignerContext)\n if (!context) {\n throw new Error(\n 'useKentuckySignerContext must be used within a KentuckySignerProvider'\n )\n }\n return context\n}\n","import type {\n ClientOptions,\n ChallengeResponse,\n AuthResponse,\n AccountInfoResponse,\n AccountInfoExtendedResponse,\n EvmSignatureResponse,\n ApiErrorResponse,\n PasskeyCredential,\n AccountCreationResponse,\n SignEvmRequest,\n SignEvmRequestWith2FA,\n CreatePasswordAccountRequest,\n PasswordAuthRequest,\n AddPasswordRequest,\n AddPasswordResponse,\n AddPasskeyRequest,\n AddPasskeyResponse,\n RemovePasskeyResponse,\n AddGuardianRequest,\n AddGuardianResponse,\n RemoveGuardianResponse,\n GetGuardiansResponse,\n InitiateRecoveryResponse,\n VerifyGuardianRequest,\n VerifyGuardianResponse,\n RecoveryStatusResponse,\n CompleteRecoveryResponse,\n CancelRecoveryResponse,\n TwoFactorStatusResponse,\n TotpSetupResponse,\n TwoFactorResponse,\n TwoFactorVerifyResponse,\n PinSetupResponse,\n} from './types'\nimport type { Hex } from 'viem'\n\n/**\n * Kentucky Signer API error\n */\nexport class KentuckySignerError extends Error {\n constructor(\n message: string,\n public code: string,\n public details?: string\n ) {\n super(message)\n this.name = 'KentuckySignerError'\n }\n}\n\n/**\n * Kentucky Signer API client\n *\n * Handles communication with the Kentucky Signer API for authentication,\n * account management, and transaction signing.\n */\nexport class KentuckySignerClient {\n private baseUrl: string\n private fetchImpl: typeof fetch\n private timeout: number\n\n constructor(options: ClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '') // Remove trailing slash\n // Bind fetch to globalThis to avoid \"Illegal invocation\" in browsers\n this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis)\n this.timeout = options.timeout ?? 30000\n }\n\n /**\n * Make an authenticated request to the API\n */\n private async request<T>(\n path: string,\n options: RequestInit & { token?: string } = {}\n ): Promise<T> {\n const { token, ...fetchOptions } = options\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n ...options.headers,\n }\n\n if (token) {\n ;(headers as Record<string, string>)['Authorization'] = `Bearer ${token}`\n }\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await this.fetchImpl(`${this.baseUrl}${path}`, {\n ...fetchOptions,\n headers,\n signal: controller.signal,\n })\n\n const data = await response.json()\n\n if (!response.ok || data.success === false) {\n const error = data as ApiErrorResponse\n throw new KentuckySignerError(\n error.error?.message ?? 'Unknown error',\n error.error?.code ?? 'UNKNOWN_ERROR',\n error.error?.details\n )\n }\n\n return data as T\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Get a challenge for passkey authentication\n *\n * @param accountId - Account ID to authenticate\n * @returns Challenge response with 32-byte challenge\n */\n async getChallenge(accountId: string): Promise<ChallengeResponse> {\n return this.request<ChallengeResponse>('/api/auth/challenge', {\n method: 'POST',\n body: JSON.stringify({ account_id: accountId }),\n })\n }\n\n /**\n * Authenticate with a passkey credential\n *\n * @param accountId - Account ID to authenticate\n * @param credential - WebAuthn credential from navigator.credentials.get()\n * @param ephemeralPublicKey - Optional ephemeral public key for secure mode binding\n * @returns Authentication response with JWT token\n */\n async authenticatePasskey(\n accountId: string,\n credential: PasskeyCredential,\n ephemeralPublicKey?: string\n ): Promise<AuthResponse> {\n const body: Record<string, string | undefined> = {\n account_id: accountId,\n credential_id: credential.credentialId,\n client_data_json: credential.clientDataJSON,\n authenticator_data: credential.authenticatorData,\n signature: credential.signature,\n user_handle: credential.userHandle,\n }\n\n if (ephemeralPublicKey) {\n body.ephemeral_public_key = ephemeralPublicKey\n }\n\n return this.request<AuthResponse>('/api/auth/passkey', {\n method: 'POST',\n body: JSON.stringify(body),\n })\n }\n\n /**\n * Refresh an authentication token\n *\n * @param token - Current JWT token\n * @returns New authentication response with fresh token\n */\n async refreshToken(token: string): Promise<AuthResponse> {\n return this.request<AuthResponse>('/api/auth/refresh', {\n method: 'POST',\n token,\n })\n }\n\n /**\n * Logout and invalidate token\n *\n * @param token - JWT token to invalidate\n */\n async logout(token: string): Promise<void> {\n await this.request('/api/auth/logout', {\n method: 'POST',\n token,\n })\n }\n\n /**\n * Get account information\n *\n * @param accountId - Account ID\n * @param token - JWT token\n * @returns Account info with addresses and passkeys\n */\n async getAccountInfo(accountId: string, token: string): Promise<AccountInfoResponse> {\n return this.request<AccountInfoResponse>(`/api/accounts/${accountId}`, {\n method: 'GET',\n token,\n })\n }\n\n /**\n * Check if an account exists\n *\n * @param accountId - Account ID\n * @param token - JWT token\n * @returns True if account exists\n */\n async accountExists(accountId: string, token: string): Promise<boolean> {\n try {\n await this.request(`/api/accounts/${accountId}`, {\n method: 'HEAD',\n token,\n })\n return true\n } catch {\n return false\n }\n }\n\n /**\n * Sign an EVM transaction hash\n *\n * @param request - Sign request with tx_hash and chain_id\n * @param token - JWT token\n * @returns Signature response with r, s, v components\n */\n async signEvmTransaction(\n request: SignEvmRequest,\n token: string\n ): Promise<EvmSignatureResponse> {\n return this.request<EvmSignatureResponse>('/api/sign/evm', {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Sign a raw hash for EVM\n *\n * Convenience method that wraps signEvmTransaction.\n *\n * @param hash - 32-byte hash to sign (hex encoded with 0x prefix)\n * @param chainId - Chain ID\n * @param token - JWT token\n * @returns Full signature (hex encoded with 0x prefix)\n */\n async signHash(hash: Hex, chainId: number, token: string): Promise<Hex> {\n const response = await this.signEvmTransaction(\n { tx_hash: hash, chain_id: chainId },\n token\n )\n return response.signature.full\n }\n\n /**\n * Create a new account with passkey authentication\n *\n * @param attestationObject - Base64url encoded attestation object from WebAuthn\n * @param label - Optional label for the passkey (defaults to \"Owner Passkey\")\n * @returns Account creation response with account ID and addresses\n */\n async createAccountWithPasskey(\n attestationObject: string,\n label?: string\n ): Promise<AccountCreationResponse> {\n const body: Record<string, string> = {\n attestation_object: attestationObject,\n }\n if (label) {\n body.label = label\n }\n return this.request<AccountCreationResponse>('/api/accounts/create/passkey', {\n method: 'POST',\n body: JSON.stringify(body),\n })\n }\n\n /**\n * Create a new account with password authentication\n *\n * @param request - Password and confirmation\n * @returns Account creation response with account ID and addresses\n */\n async createAccountWithPassword(\n request: CreatePasswordAccountRequest\n ): Promise<AccountCreationResponse> {\n return this.request<AccountCreationResponse>('/api/accounts/create/password', {\n method: 'POST',\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Authenticate with password\n *\n * @param request - Account ID and password\n * @returns Authentication response with JWT token\n */\n async authenticatePassword(request: PasswordAuthRequest): Promise<AuthResponse> {\n return this.request<AuthResponse>('/api/auth/password', {\n method: 'POST',\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Add password authentication to an existing account\n *\n * Enables password-based authentication for an account that was created\n * with passkey-only authentication.\n *\n * @param accountId - Account ID\n * @param request - Password and confirmation\n * @param token - JWT token\n * @returns Success response\n */\n async addPassword(\n accountId: string,\n request: AddPasswordRequest,\n token: string\n ): Promise<AddPasswordResponse> {\n return this.request<AddPasswordResponse>(`/api/accounts/${accountId}/password`, {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Get extended account information including auth config\n *\n * @param accountId - Account ID\n * @param token - JWT token\n * @returns Extended account info with auth config and passkey count\n */\n async getAccountInfoExtended(accountId: string, token: string): Promise<AccountInfoExtendedResponse> {\n return this.request<AccountInfoExtendedResponse>(`/api/accounts/${accountId}`, {\n method: 'GET',\n token,\n })\n }\n\n /**\n * Add a recovery passkey to an existing account\n *\n * @param accountId - Account ID\n * @param request - Passkey data (COSE public key, credential ID, algorithm, label)\n * @param token - JWT token\n * @returns Success response with label\n */\n async addPasskey(\n accountId: string,\n request: AddPasskeyRequest,\n token: string\n ): Promise<AddPasskeyResponse> {\n return this.request<AddPasskeyResponse>(`/api/accounts/${accountId}/passkeys`, {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Remove a passkey from an account\n *\n * Note: Cannot remove the owner passkey (index 0)\n *\n * @param accountId - Account ID\n * @param passkeyIndex - Index of passkey to remove (1-3 for recovery passkeys)\n * @param token - JWT token\n * @returns Success response\n */\n async removePasskey(\n accountId: string,\n passkeyIndex: number,\n token: string\n ): Promise<RemovePasskeyResponse> {\n return this.request<RemovePasskeyResponse>(`/api/accounts/${accountId}/passkeys/${passkeyIndex}`, {\n method: 'DELETE',\n token,\n })\n }\n\n /**\n * Health check\n *\n * @returns True if the API is healthy\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await this.request<{ status: string }>('/api/health', {\n method: 'GET',\n })\n return response.status === 'ok'\n } catch {\n return false\n }\n }\n\n /**\n * Get API version\n *\n * @returns Version string\n */\n async getVersion(): Promise<string> {\n const response = await this.request<{ version: string }>('/api/version', {\n method: 'GET',\n })\n return response.version\n }\n\n // ============================================================================\n // Guardian Management\n // ============================================================================\n\n /**\n * Add a guardian passkey to an account\n *\n * Guardians can participate in account recovery but cannot access the wallet.\n * An account can have up to 3 guardians (indices 1-3).\n *\n * @param request - Guardian data (attestation object and optional label)\n * @param token - JWT token\n * @returns Success response with guardian index and count\n */\n async addGuardian(\n request: AddGuardianRequest,\n token: string\n ): Promise<AddGuardianResponse> {\n return this.request<AddGuardianResponse>('/api/guardians/add', {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Remove a guardian passkey from an account\n *\n * Cannot remove guardians during an active recovery.\n *\n * @param guardianIndex - Index of guardian to remove (1-3)\n * @param token - JWT token\n * @returns Success response with remaining guardian count\n */\n async removeGuardian(\n guardianIndex: number,\n token: string\n ): Promise<RemoveGuardianResponse> {\n return this.request<RemoveGuardianResponse>('/api/guardians/remove', {\n method: 'POST',\n token,\n body: JSON.stringify({ guardian_index: guardianIndex }),\n })\n }\n\n /**\n * Get guardians for an account\n *\n * @param token - JWT token\n * @returns Guardian list with indices and labels\n */\n async getGuardians(token: string): Promise<GetGuardiansResponse> {\n return this.request<GetGuardiansResponse>('/api/guardians', {\n method: 'GET',\n token,\n })\n }\n\n // ============================================================================\n // Account Recovery\n // ============================================================================\n\n /**\n * Initiate account recovery\n *\n * Call this when you've lost access to your account. You'll need to register\n * a new passkey which will become the new owner passkey after recovery completes.\n *\n * @param accountId - Account ID to recover\n * @param attestationObject - WebAuthn attestation object for new owner passkey\n * @param label - Optional label for new owner passkey\n * @returns Challenges for guardians to sign, threshold, and timelock info\n */\n async initiateRecovery(\n accountId: string,\n attestationObject: string,\n label?: string\n ): Promise<InitiateRecoveryResponse> {\n const body: Record<string, string> = {\n account_id: accountId,\n attestation_object: attestationObject,\n }\n if (label) {\n body.label = label\n }\n return this.request<InitiateRecoveryResponse>('/api/recovery/initiate', {\n method: 'POST',\n body: JSON.stringify(body),\n })\n }\n\n /**\n * Submit a guardian signature for recovery\n *\n * Each guardian must sign their challenge using their passkey.\n *\n * @param request - Guardian signature data\n * @returns Current verification status\n */\n async verifyGuardian(request: VerifyGuardianRequest): Promise<VerifyGuardianResponse> {\n return this.request<VerifyGuardianResponse>('/api/recovery/verify', {\n method: 'POST',\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Get recovery status for an account\n *\n * @param accountId - Account ID to check\n * @returns Recovery status including verification count and timelock\n */\n async getRecoveryStatus(accountId: string): Promise<RecoveryStatusResponse> {\n return this.request<RecoveryStatusResponse>('/api/recovery/status', {\n method: 'POST',\n body: JSON.stringify({ account_id: accountId }),\n })\n }\n\n /**\n * Complete account recovery\n *\n * Call this after enough guardians have verified and the timelock has expired.\n * The new owner passkey will replace the old one.\n *\n * @param accountId - Account ID to complete recovery for\n * @returns Success message\n */\n async completeRecovery(accountId: string): Promise<CompleteRecoveryResponse> {\n return this.request<CompleteRecoveryResponse>('/api/recovery/complete', {\n method: 'POST',\n body: JSON.stringify({ account_id: accountId }),\n })\n }\n\n /**\n * Cancel a pending recovery\n *\n * Only the current owner (with valid auth) can cancel a recovery.\n * Use this if you regain access and want to stop an unauthorized recovery.\n *\n * @param token - JWT token (must be authenticated as owner)\n * @returns Success message\n */\n async cancelRecovery(token: string): Promise<CancelRecoveryResponse> {\n return this.request<CancelRecoveryResponse>('/api/recovery/cancel', {\n method: 'POST',\n token,\n })\n }\n\n // ============================================================================\n // Two-Factor Authentication (2FA)\n // ============================================================================\n\n /**\n * Get 2FA status for the authenticated account\n *\n * @param token - JWT token\n * @returns 2FA status including TOTP and PIN enablement\n */\n async get2FAStatus(token: string): Promise<TwoFactorStatusResponse> {\n return this.request<TwoFactorStatusResponse>('/api/2fa/status', {\n method: 'GET',\n token,\n })\n }\n\n /**\n * Setup TOTP for the account\n *\n * Returns an otpauth:// URI for QR code generation and a base32 secret\n * for manual entry. After setup, call enableTOTP with a valid code to\n * complete the setup.\n *\n * @param token - JWT token\n * @returns TOTP setup response with URI and secret\n */\n async setupTOTP(token: string): Promise<TotpSetupResponse> {\n return this.request<TotpSetupResponse>('/api/2fa/totp/setup', {\n method: 'POST',\n token,\n })\n }\n\n /**\n * Verify and enable TOTP for the account\n *\n * Call this after setupTOTP with a valid code from the authenticator app.\n *\n * @param code - 6-digit TOTP code from authenticator app\n * @param token - JWT token\n * @returns Success response\n */\n async enableTOTP(code: string, token: string): Promise<TwoFactorResponse> {\n return this.request<TwoFactorResponse>('/api/2fa/totp/enable', {\n method: 'POST',\n token,\n body: JSON.stringify({ code }),\n })\n }\n\n /**\n * Disable TOTP for the account\n *\n * Requires a valid TOTP code for confirmation.\n *\n * @param code - Current 6-digit TOTP code\n * @param token - JWT token\n * @returns Success response\n */\n async disableTOTP(code: string, token: string): Promise<TwoFactorResponse> {\n return this.request<TwoFactorResponse>('/api/2fa/totp/disable', {\n method: 'POST',\n token,\n body: JSON.stringify({ code }),\n })\n }\n\n /**\n * Verify a TOTP code\n *\n * Use this to verify a TOTP code without performing any other operation.\n *\n * @param code - 6-digit TOTP code\n * @param token - JWT token\n * @returns Verification result\n */\n async verifyTOTP(code: string, token: string): Promise<TwoFactorVerifyResponse> {\n return this.request<TwoFactorVerifyResponse>('/api/2fa/totp/verify', {\n method: 'POST',\n token,\n body: JSON.stringify({ code }),\n })\n }\n\n /**\n * Setup PIN for the account\n *\n * Sets a 4-digit or 6-digit PIN. If a PIN is already set, this replaces it.\n *\n * @param pin - 4 or 6 digit PIN\n * @param token - JWT token\n * @returns Success response with PIN length\n */\n async setupPIN(pin: string, token: string): Promise<PinSetupResponse> {\n return this.request<PinSetupResponse>('/api/2fa/pin/setup', {\n method: 'POST',\n token,\n body: JSON.stringify({ pin }),\n })\n }\n\n /**\n * Disable PIN for the account\n *\n * Requires the current PIN for confirmation.\n *\n * @param pin - Current PIN\n * @param token - JWT token\n * @returns Success response\n */\n async disablePIN(pin: string, token: string): Promise<TwoFactorResponse> {\n return this.request<TwoFactorResponse>('/api/2fa/pin/disable', {\n method: 'POST',\n token,\n body: JSON.stringify({ pin }),\n })\n }\n\n /**\n * Verify a PIN\n *\n * Use this to verify a PIN without performing any other operation.\n *\n * @param pin - PIN to verify\n * @param token - JWT token\n * @returns Verification result\n */\n async verifyPIN(pin: string, token: string): Promise<TwoFactorVerifyResponse> {\n return this.request<TwoFactorVerifyResponse>('/api/2fa/pin/verify', {\n method: 'POST',\n token,\n body: JSON.stringify({ pin }),\n })\n }\n\n /**\n * Sign an EVM transaction with 2FA\n *\n * Use this method when 2FA is enabled. If 2FA is not enabled,\n * you can use the regular signEvmTransaction method instead.\n *\n * @param request - Sign request including tx_hash, chain_id, and optional 2FA codes\n * @param token - JWT token\n * @returns Signature response with r, s, v components\n */\n async signEvmTransactionWith2FA(\n request: SignEvmRequestWith2FA,\n token: string\n ): Promise<EvmSignatureResponse> {\n return this.request<EvmSignatureResponse>('/api/sign/evm', {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n })\n }\n}\n\n/**\n * Create a new Kentucky Signer client\n *\n * @param options - Client options\n * @returns Kentucky Signer client instance\n */\nexport function createClient(options: ClientOptions): KentuckySignerClient {\n return new KentuckySignerClient(options)\n}\n","/**\n * Utility functions for Kentucky Signer Viem integration\n */\n\n/**\n * Base64URL encode a Uint8Array\n *\n * @param data - Data to encode\n * @returns Base64URL encoded string (no padding)\n */\nexport function base64UrlEncode(data: Uint8Array): string {\n // Convert to regular base64\n let base64: string\n if (typeof Buffer !== 'undefined') {\n // Node.js\n base64 = Buffer.from(data).toString('base64')\n } else {\n // Browser\n const binary = Array.from(data)\n .map((byte) => String.fromCharCode(byte))\n .join('')\n base64 = btoa(binary)\n }\n\n // Convert to base64url (replace + with -, / with _, remove padding)\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/**\n * Base64URL decode a string to Uint8Array\n *\n * @param str - Base64URL encoded string\n * @returns Decoded bytes\n */\nexport function base64UrlDecode(str: string): Uint8Array {\n // Convert base64url to regular base64\n let base64 = str.replace(/-/g, '+').replace(/_/g, '/')\n\n // Add padding if needed\n const padding = (4 - (base64.length % 4)) % 4\n base64 += '='.repeat(padding)\n\n if (typeof Buffer !== 'undefined') {\n // Node.js\n return new Uint8Array(Buffer.from(base64, 'base64'))\n } else {\n // Browser\n const binary = atob(base64)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return bytes\n }\n}\n\n/**\n * Convert a hex string to Uint8Array\n *\n * @param hex - Hex string (with or without 0x prefix)\n * @returns Byte array\n */\nexport function hexToBytes(hex: string): Uint8Array {\n const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex\n const bytes = new Uint8Array(cleanHex.length / 2)\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(cleanHex.slice(i * 2, i * 2 + 2), 16)\n }\n return bytes\n}\n\n/**\n * Convert a Uint8Array to hex string\n *\n * @param bytes - Byte array\n * @param withPrefix - Include 0x prefix (default: true)\n * @returns Hex string\n */\nexport function bytesToHex(bytes: Uint8Array, withPrefix: boolean = true): string {\n const hex = Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n return withPrefix ? `0x${hex}` : hex\n}\n\n/**\n * Validate an account ID format\n *\n * Account IDs are 64-character hex strings (32 bytes).\n *\n * @param accountId - Account ID to validate\n * @returns True if valid\n */\nexport function isValidAccountId(accountId: string): boolean {\n return /^[0-9a-fA-F]{64}$/.test(accountId)\n}\n\n/**\n * Validate an EVM address format\n *\n * @param address - Address to validate\n * @returns True if valid\n */\nexport function isValidEvmAddress(address: string): boolean {\n return /^0x[0-9a-fA-F]{40}$/.test(address)\n}\n\n/**\n * Sleep for a specified duration\n *\n * @param ms - Milliseconds to sleep\n */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n\n/**\n * Retry a function with exponential backoff\n *\n * @param fn - Function to retry\n * @param maxRetries - Maximum number of retries (default: 3)\n * @param baseDelay - Base delay in ms (default: 1000)\n * @returns Result of the function\n */\nexport async function withRetry<T>(\n fn: () => Promise<T>,\n maxRetries: number = 3,\n baseDelay: number = 1000\n): Promise<T> {\n let lastError: Error | undefined\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n try {\n return await fn()\n } catch (error) {\n lastError = error as Error\n\n if (attempt < maxRetries) {\n const delay = baseDelay * Math.pow(2, attempt)\n await sleep(delay)\n }\n }\n }\n\n throw lastError\n}\n\n/**\n * Parse a JWT token (without validation)\n *\n * @param token - JWT token string\n * @returns Decoded payload\n */\nexport function parseJwt(token: string): Record<string, unknown> {\n const parts = token.split('.')\n if (parts.length !== 3) {\n throw new Error('Invalid JWT format')\n }\n\n const payload = base64UrlDecode(parts[1])\n const text = new TextDecoder().decode(payload)\n return JSON.parse(text)\n}\n\n/**\n * Get JWT expiration time\n *\n * @param token - JWT token string\n * @returns Expiration timestamp in milliseconds, or null if no exp claim\n */\nexport function getJwtExpiration(token: string): number | null {\n try {\n const payload = parseJwt(token)\n if (typeof payload.exp === 'number') {\n return payload.exp * 1000 // Convert seconds to milliseconds\n }\n return null\n } catch {\n return null\n }\n}\n\n/**\n * Format an error for display\n *\n * @param error - Error to format\n * @returns Formatted error message\n */\nexport function formatError(error: unknown): string {\n if (error instanceof Error) {\n return error.message\n }\n if (typeof error === 'string') {\n return error\n }\n return 'An unknown error occurred'\n}\n","/**\n * Ephemeral Key Management for Kentucky Signer\n *\n * Implements ephemeral ECDSA keys for request signing.\n * The ephemeral public key is bound to the JWT token during authentication,\n * and the private key is used to sign all subsequent request payloads.\n *\n * Security Properties:\n * - Ephemeral keys are generated fresh for each session\n * - Private keys never leave the client\n * - SGX verifies payload signatures before processing\n * - Prevents replay attacks and token theft\n */\n\nimport { base64UrlEncode, base64UrlDecode } from './utils'\n\n/**\n * Ephemeral key pair for request signing\n */\nexport interface EphemeralKeyPair {\n /** Public key in SPKI format (base64url encoded) */\n publicKey: string\n /** Private CryptoKey for signing (not exportable) */\n privateKey: CryptoKey\n /** Algorithm used (ES256 = P-256 with SHA-256) */\n algorithm: 'ES256'\n /** Creation timestamp */\n createdAt: number\n}\n\n/**\n * Signed request payload\n */\nexport interface SignedPayload {\n /** Original payload (JSON string) */\n payload: string\n /** Signature (base64url encoded) */\n signature: string\n /** Timestamp when signature was created */\n timestamp: number\n}\n\n/**\n * Check if WebCrypto is available\n */\nexport function isWebCryptoAvailable(): boolean {\n return (\n typeof crypto !== 'undefined' &&\n typeof crypto.subtle !== 'undefined' &&\n typeof crypto.getRandomValues !== 'undefined'\n )\n}\n\n/**\n * Generate an ephemeral ECDSA key pair using WebCrypto\n *\n * Uses P-256 curve (secp256r1) with SHA-256 for ES256 signatures.\n *\n * @returns Generated key pair\n * @throws Error if WebCrypto is not available\n */\nexport async function generateEphemeralKeyPair(): Promise<EphemeralKeyPair> {\n if (!isWebCryptoAvailable()) {\n throw new Error('WebCrypto is not available in this environment')\n }\n\n // Generate ECDSA key pair on P-256 curve\n const keyPair = await crypto.subtle.generateKey(\n {\n name: 'ECDSA',\n namedCurve: 'P-256',\n },\n true, // extractable (only for public key export)\n ['sign', 'verify']\n )\n\n // Export public key in SPKI format\n const publicKeyBuffer = await crypto.subtle.exportKey('spki', keyPair.publicKey)\n const publicKeyBase64 = base64UrlEncode(new Uint8Array(publicKeyBuffer))\n\n return {\n publicKey: publicKeyBase64,\n privateKey: keyPair.privateKey,\n algorithm: 'ES256',\n createdAt: Date.now(),\n }\n}\n\n/**\n * Sign a request payload with the ephemeral private key\n *\n * The signature covers:\n * - The JSON payload string\n * - A timestamp to prevent replay attacks\n *\n * @param payload - Request payload (will be JSON stringified if object)\n * @param keyPair - Ephemeral key pair\n * @returns Signed payload with signature\n */\nexport async function signPayload(\n payload: string | object,\n keyPair: EphemeralKeyPair\n): Promise<SignedPayload> {\n const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload)\n const timestamp = Date.now()\n\n // Create message to sign: timestamp + payload\n // This prevents replay attacks\n const message = `${timestamp}.${payloadString}`\n const messageBytes = new TextEncoder().encode(message)\n\n // Sign with ECDSA P-256 + SHA-256\n const signatureBuffer = await crypto.subtle.sign(\n {\n name: 'ECDSA',\n hash: 'SHA-256',\n },\n keyPair.privateKey,\n messageBytes\n )\n\n const signatureBase64 = base64UrlEncode(new Uint8Array(signatureBuffer))\n\n return {\n payload: payloadString,\n signature: signatureBase64,\n timestamp,\n }\n}\n\n/**\n * Verify a signed payload (for testing purposes)\n *\n * @param signedPayload - The signed payload to verify\n * @param publicKeyBase64 - Public key in SPKI format (base64url)\n * @returns True if signature is valid\n */\nexport async function verifyPayload(\n signedPayload: SignedPayload,\n publicKeyBase64: string\n): Promise<boolean> {\n try {\n // Import public key\n const publicKeyBytes = base64UrlDecode(publicKeyBase64)\n const publicKey = await crypto.subtle.importKey(\n 'spki',\n publicKeyBytes.buffer as ArrayBuffer,\n {\n name: 'ECDSA',\n namedCurve: 'P-256',\n },\n false,\n ['verify']\n )\n\n // Reconstruct message\n const message = `${signedPayload.timestamp}.${signedPayload.payload}`\n const messageBytes = new TextEncoder().encode(message)\n\n // Decode signature\n const signatureBytes = base64UrlDecode(signedPayload.signature)\n\n // Verify signature\n return await crypto.subtle.verify(\n {\n name: 'ECDSA',\n hash: 'SHA-256',\n },\n publicKey,\n signatureBytes.buffer as ArrayBuffer,\n messageBytes\n )\n } catch {\n return false\n }\n}\n\n/**\n * Storage key for ephemeral key pair\n */\nconst EPHEMERAL_KEY_STORAGE_KEY = 'kentucky_signer_ephemeral'\n\n/**\n * Ephemeral key storage interface\n */\nexport interface EphemeralKeyStorage {\n save(keyPair: EphemeralKeyPair): Promise<void>\n load(): Promise<EphemeralKeyPair | null>\n clear(): Promise<void>\n}\n\n/**\n * In-memory ephemeral key storage\n *\n * Keys are lost when the page is refreshed.\n */\nexport class MemoryEphemeralKeyStorage implements EphemeralKeyStorage {\n private keyPair: EphemeralKeyPair | null = null\n\n async save(keyPair: EphemeralKeyPair): Promise<void> {\n this.keyPair = keyPair\n }\n\n async load(): Promise<EphemeralKeyPair | null> {\n return this.keyPair\n }\n\n async clear(): Promise<void> {\n this.keyPair = null\n }\n}\n\n/**\n * IndexedDB ephemeral key storage\n *\n * Persists keys across page refreshes but not browser restarts.\n * Uses non-extractable keys for security.\n */\nexport class IndexedDBEphemeralKeyStorage implements EphemeralKeyStorage {\n private dbName = 'kentucky_signer_ephemeral_keys'\n private storeName = 'keys'\n\n private async getDB(): Promise<IDBDatabase> {\n return new Promise((resolve, reject) => {\n const request = indexedDB.open(this.dbName, 1)\n\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve(request.result)\n\n request.onupgradeneeded = () => {\n const db = request.result\n if (!db.objectStoreNames.contains(this.storeName)) {\n db.createObjectStore(this.storeName)\n }\n }\n })\n }\n\n async save(keyPair: EphemeralKeyPair): Promise<void> {\n const db = await this.getDB()\n\n // Store the CryptoKey directly (IndexedDB supports structured clone of CryptoKey)\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n\n const data = {\n publicKey: keyPair.publicKey,\n privateKey: keyPair.privateKey,\n algorithm: keyPair.algorithm,\n createdAt: keyPair.createdAt,\n }\n\n const request = store.put(data, EPHEMERAL_KEY_STORAGE_KEY)\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve()\n })\n }\n\n async load(): Promise<EphemeralKeyPair | null> {\n const db = await this.getDB()\n\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.storeName, 'readonly')\n const store = tx.objectStore(this.storeName)\n\n const request = store.get(EPHEMERAL_KEY_STORAGE_KEY)\n request.onerror = () => reject(request.error)\n request.onsuccess = () => {\n if (request.result) {\n resolve({\n publicKey: request.result.publicKey,\n privateKey: request.result.privateKey,\n algorithm: request.result.algorithm,\n createdAt: request.result.createdAt,\n })\n } else {\n resolve(null)\n }\n }\n })\n }\n\n async clear(): Promise<void> {\n const db = await this.getDB()\n\n return new Promise((resolve, reject) => {\n const tx = db.transaction(this.storeName, 'readwrite')\n const store = tx.objectStore(this.storeName)\n\n const request = store.delete(EPHEMERAL_KEY_STORAGE_KEY)\n request.onerror = () => reject(request.error)\n request.onsuccess = () => resolve()\n })\n }\n}\n\n/**\n * Create an ephemeral key manager for a session\n *\n * The manager handles:\n * - Key generation on first use\n * - Key storage and retrieval\n * - Automatic key rotation (optional)\n * - Storage migration (switching between IndexedDB and memory)\n */\nexport class EphemeralKeyManager {\n private keyPair: EphemeralKeyPair | null = null\n private storage: EphemeralKeyStorage\n\n constructor(storage?: EphemeralKeyStorage) {\n this.storage = storage ?? new MemoryEphemeralKeyStorage()\n }\n\n /**\n * Get or generate ephemeral key pair\n */\n async getKeyPair(): Promise<EphemeralKeyPair> {\n // Try to load from storage first\n if (!this.keyPair) {\n this.keyPair = await this.storage.load()\n }\n\n // Generate new key pair if not found\n if (!this.keyPair) {\n this.keyPair = await generateEphemeralKeyPair()\n await this.storage.save(this.keyPair)\n }\n\n return this.keyPair\n }\n\n /**\n * Get the public key for authentication\n */\n async getPublicKey(): Promise<string> {\n const keyPair = await this.getKeyPair()\n return keyPair.publicKey\n }\n\n /**\n * Sign a request payload\n */\n async signPayload(payload: string | object): Promise<SignedPayload> {\n const keyPair = await this.getKeyPair()\n return signPayload(payload, keyPair)\n }\n\n /**\n * Rotate the key pair (generate new keys)\n */\n async rotate(): Promise<EphemeralKeyPair> {\n await this.storage.clear()\n this.keyPair = await generateEphemeralKeyPair()\n await this.storage.save(this.keyPair)\n return this.keyPair\n }\n\n /**\n * Clear the key pair (logout)\n */\n async clear(): Promise<void> {\n await this.storage.clear()\n this.keyPair = null\n }\n\n /**\n * Check if a key pair exists\n */\n async hasKeyPair(): Promise<boolean> {\n if (this.keyPair) return true\n const loaded = await this.storage.load()\n return loaded !== null\n }\n\n /**\n * Migrate key pair to a new storage backend\n *\n * This preserves the existing key pair while switching storage.\n * The key is saved to the new storage and removed from the old storage.\n *\n * @param newStorage - The new storage backend to migrate to\n */\n async migrateStorage(newStorage: EphemeralKeyStorage): Promise<void> {\n // Get current key pair (from memory or old storage)\n const currentKeyPair = this.keyPair ?? await this.storage.load()\n\n // Clear old storage\n await this.storage.clear()\n\n // Switch to new storage\n this.storage = newStorage\n\n // Save key pair to new storage if we had one\n if (currentKeyPair) {\n await this.storage.save(currentKeyPair)\n this.keyPair = currentKeyPair\n }\n }\n\n /**\n * Get the current storage backend\n */\n getStorage(): EphemeralKeyStorage {\n return this.storage\n }\n}\n","/**\n * Secure Kentucky Signer Client with Ephemeral Key Signing\n *\n * This client automatically:\n * - Generates an ephemeral key pair on initialization\n * - Sends the public key during authentication\n * - Signs all request payloads with the ephemeral private key\n */\n\nimport type {\n ClientOptions,\n ChallengeResponse,\n AuthResponse,\n AccountInfoResponse,\n AccountInfoExtendedResponse,\n EvmSignatureResponse,\n ApiErrorResponse,\n PasskeyCredential,\n AccountCreationResponse,\n SignEvmRequest,\n CreatePasswordAccountRequest,\n PasswordAuthRequest,\n AddPasswordRequest,\n AddPasswordResponse,\n AddPasskeyRequest,\n AddPasskeyResponse,\n RemovePasskeyResponse,\n AuthResponseWithEphemeral,\n} from './types'\nimport type { Hex } from 'viem'\nimport {\n EphemeralKeyManager,\n type SignedPayload,\n MemoryEphemeralKeyStorage,\n type EphemeralKeyStorage,\n} from './ephemeral'\nimport { KentuckySignerError } from './client'\n\n/**\n * Options for the secure client\n */\nexport interface SecureClientOptions extends ClientOptions {\n /** Custom ephemeral key storage (defaults to memory storage) */\n ephemeralKeyStorage?: EphemeralKeyStorage\n /** Shared ephemeral key manager (takes precedence over storage) */\n ephemeralKeyManager?: EphemeralKeyManager\n /** Whether to require ephemeral key verification (default: true) */\n requireEphemeralSigning?: boolean\n}\n\n/**\n * Secure Kentucky Signer API client with ephemeral key signing\n *\n * All requests to authenticated endpoints are automatically signed\n * with the ephemeral private key bound during authentication.\n */\nexport class SecureKentuckySignerClient {\n private baseUrl: string\n private fetchImpl: typeof fetch\n private timeout: number\n private keyManager: EphemeralKeyManager\n private requireSigning: boolean\n\n constructor(options: SecureClientOptions) {\n this.baseUrl = options.baseUrl.replace(/\\/$/, '')\n this.fetchImpl = options.fetch ?? globalThis.fetch.bind(globalThis)\n this.timeout = options.timeout ?? 30000\n // Use shared manager if provided, otherwise create one with the storage\n this.keyManager = options.ephemeralKeyManager ?? new EphemeralKeyManager(\n options.ephemeralKeyStorage ?? new MemoryEphemeralKeyStorage()\n )\n this.requireSigning = options.requireEphemeralSigning ?? true\n }\n\n /**\n * Get the ephemeral key manager for advanced usage\n */\n getKeyManager(): EphemeralKeyManager {\n return this.keyManager\n }\n\n /**\n * Make a signed request to the API\n */\n private async request<T>(\n path: string,\n options: RequestInit & { token?: string; skipSigning?: boolean } = {}\n ): Promise<T> {\n const { token, skipSigning, ...fetchOptions } = options\n\n const headers: HeadersInit = {\n 'Content-Type': 'application/json',\n ...options.headers,\n }\n\n if (token) {\n ;(headers as Record<string, string>)['Authorization'] = `Bearer ${token}`\n }\n\n let body = options.body\n\n // Sign the request body if token is present and signing is required\n if (token && !skipSigning && this.requireSigning && body) {\n const signedPayload = await this.keyManager.signPayload(body as string)\n\n // Add signature headers - body is NOT modified\n // The enclave verifies the signature against the original body\n ;(headers as Record<string, string>)['X-Ephemeral-Signature'] =\n signedPayload.signature\n ;(headers as Record<string, string>)['X-Ephemeral-Timestamp'] =\n signedPayload.timestamp.toString()\n }\n\n const controller = new AbortController()\n const timeoutId = setTimeout(() => controller.abort(), this.timeout)\n\n try {\n const response = await this.fetchImpl(`${this.baseUrl}${path}`, {\n ...fetchOptions,\n headers,\n body,\n signal: controller.signal,\n })\n\n const data = await response.json()\n\n if (!response.ok || data.success === false) {\n const error = data as ApiErrorResponse\n throw new KentuckySignerError(\n error.error?.message ?? 'Unknown error',\n error.error?.code ?? 'UNKNOWN_ERROR',\n error.error?.details\n )\n }\n\n return data as T\n } finally {\n clearTimeout(timeoutId)\n }\n }\n\n /**\n * Get a challenge for passkey authentication\n */\n async getChallenge(accountId: string): Promise<ChallengeResponse> {\n return this.request<ChallengeResponse>('/api/auth/challenge', {\n method: 'POST',\n body: JSON.stringify({ account_id: accountId }),\n skipSigning: true, // No token yet\n })\n }\n\n /**\n * Authenticate with a passkey credential\n *\n * Automatically sends the ephemeral public key for binding.\n */\n async authenticatePasskey(\n accountId: string,\n credential: PasskeyCredential\n ): Promise<AuthResponseWithEphemeral> {\n // Get ephemeral public key for binding\n const ephemeralPublicKey = await this.keyManager.getPublicKey()\n\n return this.request<AuthResponseWithEphemeral>('/api/auth/passkey', {\n method: 'POST',\n body: JSON.stringify({\n account_id: accountId,\n credential_id: credential.credentialId,\n client_data_json: credential.clientDataJSON,\n authenticator_data: credential.authenticatorData,\n signature: credential.signature,\n user_handle: credential.userHandle,\n ephemeral_public_key: ephemeralPublicKey,\n }),\n skipSigning: true, // No token yet\n })\n }\n\n /**\n * Authenticate with password\n *\n * Automatically sends the ephemeral public key for binding.\n */\n async authenticatePassword(\n request: PasswordAuthRequest\n ): Promise<AuthResponseWithEphemeral> {\n // Get ephemeral public key for binding\n const ephemeralPublicKey = await this.keyManager.getPublicKey()\n\n return this.request<AuthResponseWithEphemeral>('/api/auth/password', {\n method: 'POST',\n body: JSON.stringify({\n ...request,\n ephemeral_public_key: ephemeralPublicKey,\n }),\n skipSigning: true, // No token yet\n })\n }\n\n /**\n * Refresh an authentication token\n *\n * Generates a new ephemeral key pair and binds it to the new token.\n */\n async refreshToken(token: string): Promise<AuthResponseWithEphemeral> {\n // Rotate ephemeral key on refresh\n await this.keyManager.rotate()\n const ephemeralPublicKey = await this.keyManager.getPublicKey()\n\n return this.request<AuthResponseWithEphemeral>('/api/auth/refresh', {\n method: 'POST',\n token,\n body: JSON.stringify({\n ephemeral_public_key: ephemeralPublicKey,\n }),\n skipSigning: true, // Use old token, but send new key\n })\n }\n\n /**\n * Logout and invalidate token\n *\n * Clears the ephemeral key pair.\n */\n async logout(token: string): Promise<void> {\n await this.request('/api/auth/logout', {\n method: 'POST',\n token,\n skipSigning: true,\n })\n await this.keyManager.clear()\n }\n\n /**\n * Get account information (signed request)\n */\n async getAccountInfo(\n accountId: string,\n token: string\n ): Promise<AccountInfoResponse> {\n // GET requests don't have a body, so we can't sign them the normal way\n // For now, skip signing for GET requests\n return this.request<AccountInfoResponse>(`/api/accounts/${accountId}`, {\n method: 'GET',\n token,\n skipSigning: true,\n })\n }\n\n /**\n * Get extended account information (signed request)\n */\n async getAccountInfoExtended(\n accountId: string,\n token: string\n ): Promise<AccountInfoExtendedResponse> {\n return this.request<AccountInfoExtendedResponse>(\n `/api/accounts/${accountId}`,\n {\n method: 'GET',\n token,\n skipSigning: true,\n }\n )\n }\n\n /**\n * Sign an EVM transaction hash (signed request)\n */\n async signEvmTransaction(\n request: SignEvmRequest,\n token: string\n ): Promise<EvmSignatureResponse> {\n return this.request<EvmSignatureResponse>('/api/sign/evm', {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Sign an EVM transaction hash with 2FA (signed request)\n */\n async signEvmTransactionWith2FA(\n request: SignEvmRequest & { totp_code?: string; pin?: string },\n token: string\n ): Promise<EvmSignatureResponse> {\n return this.request<EvmSignatureResponse>('/api/sign/evm', {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n })\n }\n\n /**\n * Sign a raw hash for EVM (signed request)\n */\n async signHash(hash: Hex, chainId: number, token: string): Promise<Hex> {\n const response = await this.signEvmTransaction(\n { tx_hash: hash, chain_id: chainId },\n token\n )\n return response.signature.full\n }\n\n /**\n * Add password to account (signed request)\n */\n async addPassword(\n accountId: string,\n request: AddPasswordRequest,\n token: string\n ): Promise<AddPasswordResponse> {\n return this.request<AddPasswordResponse>(\n `/api/accounts/${accountId}/password`,\n {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n }\n )\n }\n\n /**\n * Add passkey to account (signed request)\n */\n async addPasskey(\n accountId: string,\n request: AddPasskeyRequest,\n token: string\n ): Promise<AddPasskeyResponse> {\n return this.request<AddPasskeyResponse>(\n `/api/accounts/${accountId}/passkeys`,\n {\n method: 'POST',\n token,\n body: JSON.stringify(request),\n }\n )\n }\n\n /**\n * Remove passkey from account (signed request)\n */\n async removePasskey(\n accountId: string,\n passkeyIndex: number,\n token: string\n ): Promise<RemovePasskeyResponse> {\n return this.request<RemovePasskeyResponse>(\n `/api/accounts/${accountId}/passkeys/${passkeyIndex}`,\n {\n method: 'DELETE',\n token,\n body: JSON.stringify({ passkey_index: passkeyIndex }),\n }\n )\n }\n\n /**\n * Create account with passkey (public endpoint, no signing)\n */\n async createAccountWithPasskey(\n attestationObject: string,\n label?: string\n ): Promise<AccountCreationResponse> {\n const body: Record<string, string> = {\n attestation_object: attestationObject,\n }\n if (label) {\n body.label = label\n }\n return this.request<AccountCreationResponse>('/api/accounts/create/passkey', {\n method: 'POST',\n body: JSON.stringify(body),\n skipSigning: true,\n })\n }\n\n /**\n * Create account with password (public endpoint, no signing)\n */\n async createAccountWithPassword(\n request: CreatePasswordAccountRequest\n ): Promise<AccountCreationResponse> {\n return this.request<AccountCreationResponse>('/api/accounts/create/password', {\n method: 'POST',\n body: JSON.stringify(request),\n skipSigning: true,\n })\n }\n\n /**\n * Health check (public endpoint)\n */\n async healthCheck(): Promise<boolean> {\n try {\n const response = await this.request<{ status: string }>('/api/health', {\n method: 'GET',\n skipSigning: true,\n })\n return response.status === 'ok'\n } catch {\n return false\n }\n }\n}\n\n/**\n * Create a new secure Kentucky Signer client\n */\nexport function createSecureClient(\n options: SecureClientOptions\n): SecureKentuckySignerClient {\n return new SecureKentuckySignerClient(options)\n}\n","import type {\n AuthSession,\n PasskeyAuthOptions,\n PasskeyCredential,\n PasskeyRegistrationOptions,\n TokenStorage,\n PasswordAuthOptions,\n PasswordAccountCreationOptions,\n AccountCreationResponse,\n} from './types'\nimport { KentuckySignerClient, KentuckySignerError } from './client'\nimport { base64UrlEncode, base64UrlDecode } from './utils'\nimport type { Address } from 'viem'\n\n/**\n * Check if WebAuthn is available in the current environment\n */\nexport function isWebAuthnAvailable(): boolean {\n return (\n typeof window !== 'undefined' &&\n typeof window.PublicKeyCredential !== 'undefined' &&\n typeof navigator.credentials !== 'undefined'\n )\n}\n\n/**\n * In-memory token storage (default implementation)\n */\nexport class MemoryTokenStorage implements TokenStorage {\n private token: string | null = null\n private expiresAt: number = 0\n\n async getToken(): Promise<string | null> {\n if (this.token && Date.now() < this.expiresAt) {\n return this.token\n }\n return null\n }\n\n async setToken(token: string, expiresAt: number): Promise<void> {\n this.token = token\n this.expiresAt = expiresAt\n }\n\n async clearToken(): Promise<void> {\n this.token = null\n this.expiresAt = 0\n }\n}\n\n/**\n * Browser localStorage token storage\n */\nexport class LocalStorageTokenStorage implements TokenStorage {\n private keyPrefix: string\n\n constructor(keyPrefix: string = 'kentucky_signer') {\n this.keyPrefix = keyPrefix\n }\n\n async getToken(): Promise<string | null> {\n if (typeof localStorage === 'undefined') return null\n\n const token = localStorage.getItem(`${this.keyPrefix}_token`)\n const expiresAt = localStorage.getItem(`${this.keyPrefix}_expires`)\n\n if (token && expiresAt && Date.now() < parseInt(expiresAt, 10)) {\n return token\n }\n\n // Clear expired token\n await this.clearToken()\n return null\n }\n\n async setToken(token: string, expiresAt: number): Promise<void> {\n if (typeof localStorage === 'undefined') return\n\n localStorage.setItem(`${this.keyPrefix}_token`, token)\n localStorage.setItem(`${this.keyPrefix}_expires`, expiresAt.toString())\n }\n\n async clearToken(): Promise<void> {\n if (typeof localStorage === 'undefined') return\n\n localStorage.removeItem(`${this.keyPrefix}_token`)\n localStorage.removeItem(`${this.keyPrefix}_expires`)\n }\n}\n\n/**\n * Convert a PublicKeyCredential to our PasskeyCredential format\n */\nfunction credentialToPasskey(credential: PublicKeyCredential): PasskeyCredential {\n const response = credential.response as AuthenticatorAssertionResponse\n\n return {\n credentialId: base64UrlEncode(new Uint8Array(credential.rawId)),\n clientDataJSON: base64UrlEncode(new Uint8Array(response.clientDataJSON)),\n authenticatorData: base64UrlEncode(new Uint8Array(response.authenticatorData)),\n signature: base64UrlEncode(new Uint8Array(response.signature)),\n userHandle: response.userHandle\n ? base64UrlEncode(new Uint8Array(response.userHandle))\n : undefined,\n }\n}\n\n/**\n * Authenticate with a passkey (browser only)\n *\n * This function handles the full WebAuthn authentication flow:\n * 1. Request a challenge from the Kentucky Signer\n * 2. Prompt the user to authenticate with their passkey\n * 3. Send the credential to the Kentucky Signer\n * 4. Return an authenticated session\n *\n * @param options - Passkey authentication options\n * @returns Authenticated session\n */\nexport async function authenticateWithPasskey(\n options: PasskeyAuthOptions\n): Promise<AuthSession> {\n if (!isWebAuthnAvailable()) {\n throw new KentuckySignerError(\n 'WebAuthn is not available in this environment',\n 'WEBAUTHN_NOT_AVAILABLE',\n 'Use authenticateWithToken() for server-side authentication'\n )\n }\n\n const client = new KentuckySignerClient({ baseUrl: options.baseUrl })\n\n // Step 1: Get challenge\n const challengeResponse = await client.getChallenge(options.accountId)\n const challengeBytes = base64UrlDecode(challengeResponse.challenge)\n\n // Step 2: Build credential request options\n const credentialRequestOptions: CredentialRequestOptions = {\n publicKey: {\n challenge: challengeBytes.buffer as ArrayBuffer,\n timeout: 60000,\n rpId: options.rpId ?? window.location.hostname,\n userVerification: 'preferred',\n allowCredentials: options.allowCredentials?.map((id) => ({\n type: 'public-key' as const,\n id: base64UrlDecode(id).buffer as ArrayBuffer,\n })),\n },\n }\n\n // Step 3: Request credential from user\n const credential = (await navigator.credentials.get(\n credentialRequestOptions\n )) as PublicKeyCredential | null\n\n if (!credential) {\n throw new KentuckySignerError(\n 'User cancelled passkey authentication',\n 'USER_CANCELLED'\n )\n }\n\n // Step 4: Authenticate with Kentucky Signer\n const passkeyCredential = credentialToPasskey(credential)\n const authResponse = await client.authenticatePasskey(\n options.accountId,\n passkeyCredential,\n options.ephemeralPublicKey\n )\n\n // Step 5: Get account info to retrieve addresses\n const accountInfo = await client.getAccountInfo(\n options.accountId,\n authResponse.token\n )\n\n // Step 6: Build and return session\n const expiresAt = Date.now() + authResponse.expires_in * 1000\n\n return {\n token: authResponse.token,\n accountId: options.accountId,\n evmAddress: accountInfo.addresses.evm as Address,\n btcAddress: accountInfo.addresses.bitcoin,\n solAddress: accountInfo.addresses.solana,\n expiresAt,\n }\n}\n\n/**\n * Create an authenticated session from an existing JWT token (Node.js compatible)\n *\n * Use this for server-side applications where you already have a JWT token.\n *\n * @param baseUrl - Kentucky Signer API URL\n * @param accountId - Account ID\n * @param token - JWT token\n * @param expiresAt - Token expiration timestamp (Unix ms), optional\n * @returns Authenticated session\n */\nexport async function authenticateWithToken(\n baseUrl: string,\n accountId: string,\n token: string,\n expiresAt?: number\n): Promise<AuthSession> {\n const client = new KentuckySignerClient({ baseUrl })\n\n // Get account info to retrieve addresses\n const accountInfo = await client.getAccountInfo(accountId, token)\n\n return {\n token,\n accountId,\n evmAddress: accountInfo.addresses.evm as Address,\n btcAddress: accountInfo.addresses.bitcoin,\n solAddress: accountInfo.addresses.solana,\n expiresAt: expiresAt ?? Date.now() + 3600000, // Default 1 hour if not specified\n }\n}\n\n/**\n * Register a new passkey for account creation (browser only)\n *\n * @param options - Registration options\n * @returns Registration credential with public key and attestation object\n */\nexport async function registerPasskey(\n options: PasskeyRegistrationOptions\n): Promise<PasskeyCredential & { publicKey: string; attestationObject: string }> {\n if (!isWebAuthnAvailable()) {\n throw new KentuckySignerError(\n 'WebAuthn is not available in this environment',\n 'WEBAUTHN_NOT_AVAILABLE'\n )\n }\n\n // Generate a random user ID\n const userId = new Uint8Array(32)\n crypto.getRandomValues(userId)\n\n // Generate a random challenge\n const challenge = new Uint8Array(32)\n crypto.getRandomValues(challenge)\n\n const createOptions: CredentialCreationOptions = {\n publicKey: {\n challenge,\n rp: {\n name: options.rpName ?? 'Kentucky Signer',\n id: options.rpId ?? window.location.hostname,\n },\n user: {\n id: userId,\n name: options.username ?? 'user@example.com',\n displayName: options.username ?? 'User',\n },\n pubKeyCredParams: [\n { type: 'public-key', alg: -7 }, // ES256 (P-256)\n { type: 'public-key', alg: -257 }, // RS256\n ],\n authenticatorSelection: {\n authenticatorAttachment: 'platform',\n userVerification: 'preferred',\n residentKey: 'preferred',\n },\n timeout: 60000,\n attestation: 'none',\n },\n }\n\n const credential = (await navigator.credentials.create(\n createOptions\n )) as PublicKeyCredential | null\n\n if (!credential) {\n throw new KentuckySignerError(\n 'User cancelled passkey registration',\n 'USER_CANCELLED'\n )\n }\n\n const response = credential.response as AuthenticatorAttestationResponse\n\n // Extract public key from attestation object\n const publicKeyBytes = response.getPublicKey?.()\n if (!publicKeyBytes) {\n throw new KentuckySignerError(\n 'Failed to get public key from credential',\n 'PUBLIC_KEY_ERROR'\n )\n }\n\n return {\n credentialId: base64UrlEncode(new Uint8Array(credential.rawId)),\n clientDataJSON: base64UrlEncode(new Uint8Array(response.clientDataJSON)),\n authenticatorData: base64UrlEncode(new Uint8Array(response.getAuthenticatorData())),\n attestationObject: base64UrlEncode(new Uint8Array(response.attestationObject)),\n signature: '', // Not applicable for registration\n publicKey: base64UrlEncode(new Uint8Array(publicKeyBytes)),\n }\n}\n\n/**\n * Check if a session is still valid\n *\n * @param session - Session to check\n * @param bufferMs - Buffer time before expiration (default 60 seconds)\n * @returns True if session is valid\n */\nexport function isSessionValid(session: AuthSession, bufferMs: number = 60000): boolean {\n return Date.now() + bufferMs < session.expiresAt\n}\n\n/**\n * Refresh a session if needed\n *\n * @param session - Current session\n * @param baseUrl - Kentucky Signer API URL\n * @param bufferMs - Buffer time before expiration (default 60 seconds)\n * @returns Updated session (or original if still valid)\n */\nexport async function refreshSessionIfNeeded(\n session: AuthSession,\n baseUrl: string,\n bufferMs: number = 60000\n): Promise<AuthSession> {\n if (isSessionValid(session, bufferMs)) {\n return session\n }\n\n const client = new KentuckySignerClient({ baseUrl })\n const authResponse = await client.refreshToken(session.token)\n\n return {\n ...session,\n token: authResponse.token,\n expiresAt: Date.now() + authResponse.expires_in * 1000,\n }\n}\n\n/**\n * Authenticate with password (works in browser and Node.js)\n *\n * @param options - Password authentication options\n * @returns Authenticated session\n *\n * @example\n * ```typescript\n * const session = await authenticateWithPassword({\n * baseUrl: 'https://signer.example.com',\n * accountId: '0123456789abcdef...',\n * password: 'your-secure-password',\n * })\n * ```\n */\nexport async function authenticateWithPassword(\n options: PasswordAuthOptions\n): Promise<AuthSession> {\n const client = new KentuckySignerClient({ baseUrl: options.baseUrl })\n\n // Build auth request with optional ephemeral key\n const authRequest: { account_id: string; password: string; ephemeral_public_key?: string } = {\n account_id: options.accountId,\n password: options.password,\n }\n\n // Add ephemeral public key if provided (for secure mode binding)\n if (options.ephemeralPublicKey) {\n authRequest.ephemeral_public_key = options.ephemeralPublicKey\n }\n\n // Authenticate with password\n const authResponse = await client.authenticatePassword(authRequest)\n\n // Get account info to retrieve addresses\n const accountInfo = await client.getAccountInfo(\n options.accountId,\n authResponse.token\n )\n\n // Build and return session\n const expiresAt = Date.now() + authResponse.expires_in * 1000\n\n return {\n token: authResponse.token,\n accountId: options.accountId,\n evmAddress: accountInfo.addresses.evm as Address,\n btcAddress: accountInfo.addresses.bitcoin,\n solAddress: accountInfo.addresses.solana,\n expiresAt,\n }\n}\n\n/**\n * Create a new account with password authentication (works in browser and Node.js)\n *\n * @param options - Account creation options with password\n * @returns Account creation response with account ID and addresses\n *\n * @example\n * ```typescript\n * const account = await createAccountWithPassword({\n * baseUrl: 'https://signer.example.com',\n * password: 'your-secure-password',\n * confirmation: 'your-secure-password',\n * })\n * console.log('Account ID:', account.account_id)\n * console.log('EVM Address:', account.addresses.evm)\n * ```\n */\nexport async function createAccountWithPassword(\n options: PasswordAccountCreationOptions\n): Promise<AccountCreationResponse> {\n // Validate password matches confirmation\n if (options.password !== options.confirmation) {\n throw new KentuckySignerError(\n 'Password and confirmation do not match',\n 'PASSWORD_MISMATCH'\n )\n }\n\n // Validate password length\n if (options.password.length < 8 || options.password.length > 128) {\n throw new KentuckySignerError(\n 'Password must be 8-128 characters',\n 'INVALID_PASSWORD'\n )\n }\n\n const client = new KentuckySignerClient({ baseUrl: options.baseUrl })\n\n return client.createAccountWithPassword({\n password: options.password,\n confirmation: options.confirmation,\n })\n}\n","import {\n type Account,\n type Address,\n type Chain,\n type Hex,\n type LocalAccount,\n type SignableMessage,\n type TransactionSerializable,\n type TypedData,\n type TypedDataDefinition,\n hashMessage,\n hashTypedData,\n keccak256,\n serializeTransaction,\n toHex,\n concat,\n numberToHex,\n} from 'viem'\nimport { toAccount } from 'viem/accounts'\nimport type { AuthSession, KentuckySignerConfig } from './types'\nimport { KentuckySignerClient, KentuckySignerError } from './client'\nimport { SecureKentuckySignerClient } from './secure-client'\nimport type { EphemeralKeyManager } from './ephemeral'\n\n/**\n * 2FA codes for signing operations\n */\nexport interface TwoFactorCodes {\n /** TOTP code from authenticator app */\n totpCode?: string\n /** PIN code */\n pin?: string\n}\n\n/**\n * Callback to request 2FA codes from the user\n * Returns null/undefined if user cancels\n */\nexport type TwoFactorCallback = (requirements: {\n totpRequired: boolean\n pinRequired: boolean\n pinLength: number\n}) => Promise<TwoFactorCodes | null | undefined>\n\n/**\n * Options for creating a Kentucky Signer account\n */\nexport interface KentuckySignerAccountOptions {\n /** Kentucky Signer configuration */\n config: KentuckySignerConfig\n /** Authenticated session */\n session: AuthSession\n /** Default chain ID for signing (can be overridden per-transaction) */\n defaultChainId?: number\n /** Callback when session needs refresh */\n onSessionExpired?: () => Promise<AuthSession>\n /** Optional secure client for ephemeral key signing */\n secureClient?: SecureKentuckySignerClient\n /** Callback to request 2FA codes when required */\n on2FARequired?: TwoFactorCallback\n}\n\n/**\n * Extended account type with Kentucky Signer specific properties\n */\nexport interface KentuckySignerAccount extends LocalAccount<'kentuckySigner'> {\n /** Account ID */\n accountId: string\n /** Current session */\n session: AuthSession\n /** Update the session (e.g., after refresh) */\n updateSession: (session: AuthSession) => void\n}\n\n/**\n * Create a custom Viem account backed by Kentucky Signer\n *\n * This account implementation uses the Kentucky Signer API to sign\n * transactions, messages, and typed data using passkey authentication.\n *\n * @param options - Account options\n * @returns Viem-compatible account\n *\n * @example\n * ```typescript\n * const account = createKentuckySignerAccount({\n * config: {\n * baseUrl: 'https://signer.example.com',\n * accountId: '0x...',\n * },\n * session: authenticatedSession,\n * defaultChainId: 1,\n * })\n *\n * const walletClient = createWalletClient({\n * account,\n * chain: mainnet,\n * transport: http(),\n * })\n *\n * const hash = await walletClient.sendTransaction({\n * to: '0x...',\n * value: parseEther('0.1'),\n * })\n * ```\n */\nexport function createKentuckySignerAccount(\n options: KentuckySignerAccountOptions\n): KentuckySignerAccount {\n const { config, defaultChainId = 1, onSessionExpired, secureClient, on2FARequired } = options\n let session = options.session\n\n // Use secure client if provided, otherwise use standard client\n const client = secureClient ?? new KentuckySignerClient({ baseUrl: config.baseUrl })\n\n /**\n * Get current token, refreshing if needed\n */\n async function getToken(): Promise<string> {\n // Check if session is about to expire (within 60 seconds)\n if (Date.now() + 60000 >= session.expiresAt) {\n if (onSessionExpired) {\n session = await onSessionExpired()\n } else {\n throw new KentuckySignerError(\n 'Session expired',\n 'SESSION_EXPIRED',\n 'Please re-authenticate with your passkey'\n )\n }\n }\n return session.token\n }\n\n /**\n * Sign a hash using Kentucky Signer and return full signature\n * Handles 2FA by detecting the error and calling the callback\n */\n async function signHash(hash: Hex, chainId: number): Promise<Hex> {\n const token = await getToken()\n\n // First attempt without 2FA codes\n try {\n const response = await client.signEvmTransaction(\n { tx_hash: hash, chain_id: chainId },\n token\n )\n return response.signature.full\n } catch (err) {\n // Check if 2FA is required\n if (err instanceof KentuckySignerError && err.code === '2FA_REQUIRED' && on2FARequired) {\n // Parse requirements from error details\n const totpRequired = err.message.includes('TOTP') || (err.details?.includes('totp_code') ?? false)\n const pinRequired = err.message.includes('PIN') || (err.details?.includes('pin') ?? false)\n // Default to 6-digit PIN if required\n const pinLength = err.details?.match(/(\\d)-digit/)?.[1] ? parseInt(err.details.match(/(\\d)-digit/)![1]) : 6\n\n // Request 2FA codes from user\n const codes = await on2FARequired({ totpRequired, pinRequired, pinLength })\n if (!codes) {\n throw new KentuckySignerError('2FA verification cancelled', '2FA_CANCELLED', 'User cancelled 2FA input')\n }\n\n // Retry with 2FA codes\n const response = await client.signEvmTransactionWith2FA(\n { tx_hash: hash, chain_id: chainId, totp_code: codes.totpCode, pin: codes.pin },\n token\n )\n return response.signature.full\n }\n throw err\n }\n }\n\n /**\n * Sign a hash using Kentucky Signer and return signature components\n * Handles 2FA by detecting the error and calling the callback\n */\n async function signHashWithComponents(hash: Hex, chainId: number): Promise<{ r: Hex; s: Hex; v: number }> {\n const token = await getToken()\n\n // First attempt without 2FA codes\n try {\n const response = await client.signEvmTransaction(\n { tx_hash: hash, chain_id: chainId },\n token\n )\n return {\n r: response.signature.r,\n s: response.signature.s,\n v: response.signature.v,\n }\n } catch (err) {\n // Check if 2FA is required\n if (err instanceof KentuckySignerError && err.code === '2FA_REQUIRED' && on2FARequired) {\n // Parse requirements from error details\n const totpRequired = err.message.includes('TOTP') || (err.details?.includes('totp_code') ?? false)\n const pinRequired = err.message.includes('PIN') || (err.details?.includes('pin') ?? false)\n // Default to 6-digit PIN if required\n const pinLength = err.details?.match(/(\\d)-digit/)?.[1] ? parseInt(err.details.match(/(\\d)-digit/)![1]) : 6\n\n // Request 2FA codes from user\n const codes = await on2FARequired({ totpRequired, pinRequired, pinLength })\n if (!codes) {\n throw new KentuckySignerError('2FA verification cancelled', '2FA_CANCELLED', 'User cancelled 2FA input')\n }\n\n // Retry with 2FA codes\n const response = await client.signEvmTransactionWith2FA(\n { tx_hash: hash, chain_id: chainId, totp_code: codes.totpCode, pin: codes.pin },\n token\n )\n return {\n r: response.signature.r,\n s: response.signature.s,\n v: response.signature.v,\n }\n }\n throw err\n }\n }\n\n const account = toAccount({\n address: session.evmAddress,\n\n /**\n * Sign a message\n *\n * Supports string messages, hex messages, and raw bytes.\n */\n async signMessage({ message }: { message: SignableMessage }): Promise<Hex> {\n const messageHash = hashMessage(message)\n return signHash(messageHash, defaultChainId)\n },\n\n /**\n * Sign a transaction\n *\n * Serializes the transaction, hashes it, signs via Kentucky Signer,\n * and returns the signed serialized transaction.\n */\n async signTransaction(\n transaction: TransactionSerializable\n ): Promise<Hex> {\n // Get chain ID from transaction or use default\n const chainId = transaction.chainId ?? defaultChainId\n\n // Serialize unsigned transaction\n const serializedUnsigned = serializeTransaction(transaction)\n\n // Hash the serialized transaction\n const txHash = keccak256(serializedUnsigned)\n\n // Sign the hash and get components directly from API\n const { r, s, v } = await signHashWithComponents(txHash, chainId)\n\n // For EIP-1559 and EIP-2930 transactions, v is 0 or 1\n // For legacy transactions, v is chainId * 2 + 35 + recovery\n let yParity: number\n if (\n transaction.type === 'eip1559' ||\n transaction.type === 'eip2930' ||\n transaction.type === 'eip4844' ||\n transaction.type === 'eip7702'\n ) {\n yParity = v >= 27 ? v - 27 : v // Convert from 27/28 to 0/1 if needed\n } else {\n // Legacy transaction - v already includes chain ID\n yParity = v\n }\n\n // Serialize with signature\n const serializedSigned = serializeTransaction(transaction, {\n r,\n s,\n v: BigInt(yParity),\n yParity,\n } as any)\n\n return serializedSigned\n },\n\n /**\n * Sign typed data (EIP-712)\n */\n async signTypedData<\n const TTypedData extends TypedData | Record<string, unknown>,\n TPrimaryType extends keyof TTypedData | 'EIP712Domain' = keyof TTypedData\n >(\n typedData: TypedDataDefinition<TTypedData, TPrimaryType>\n ): Promise<Hex> {\n const hash = hashTypedData(typedData)\n return signHash(hash, defaultChainId)\n },\n }) as KentuckySignerAccount\n\n // Add Kentucky Signer specific properties\n account.source = 'kentuckySigner'\n account.accountId = config.accountId\n account.session = session\n account.updateSession = (newSession: AuthSession) => {\n session = newSession\n // Update address if changed (shouldn't happen but handle it)\n if (newSession.evmAddress !== account.address) {\n ;(account as any).address = newSession.evmAddress\n }\n }\n\n return account\n}\n\n/**\n * Create a Kentucky Signer account for server-side use\n *\n * Convenience function for Node.js environments where you have\n * a pre-existing JWT token.\n *\n * @param baseUrl - Kentucky Signer API URL\n * @param accountId - Account ID\n * @param token - JWT token\n * @param evmAddress - EVM address for the account\n * @param chainId - Default chain ID\n * @returns Kentucky Signer account\n */\nexport function createServerAccount(\n baseUrl: string,\n accountId: string,\n token: string,\n evmAddress: Address,\n chainId: number = 1\n): KentuckySignerAccount {\n const session: AuthSession = {\n token,\n accountId,\n evmAddress,\n expiresAt: Date.now() + 3600000, // 1 hour default\n }\n\n return createKentuckySignerAccount({\n config: { baseUrl, accountId },\n session,\n defaultChainId: chainId,\n })\n}\n","import { useMemo, useCallback, useState } from 'react'\nimport { createWalletClient, http, type Chain, type WalletClient, type Transport } from 'viem'\nimport { useKentuckySignerContext } from './context'\nimport type { KentuckySignerAccount } from '../account'\n\n/**\n * Hook to access Kentucky Signer authentication state\n *\n * @returns Authentication state and actions\n *\n * @example\n * ```tsx\n * function LoginButton() {\n * const { isAuthenticated, isAuthenticating, authenticate, logout } = useKentuckySigner()\n *\n * if (isAuthenticated) {\n * return <button onClick={logout}>Logout</button>\n * }\n *\n * return (\n * <button onClick={() => authenticate('account_id')} disabled={isAuthenticating}>\n * {isAuthenticating ? 'Authenticating...' : 'Login with Passkey'}\n * </button>\n * )\n * }\n * ```\n */\nexport function useKentuckySigner() {\n const context = useKentuckySignerContext()\n\n return {\n isAuthenticated: context.isAuthenticated,\n isAuthenticating: context.isAuthenticating,\n session: context.session,\n account: context.account,\n error: context.error,\n ephemeralKeyBound: context.ephemeralKeyBound,\n authenticate: context.authenticate,\n authenticatePassword: context.authenticatePassword,\n logout: context.logout,\n refreshSession: context.refreshSession,\n clearError: context.clearError,\n secureMode: context.secureMode,\n setSecureMode: context.setSecureMode,\n persistEphemeralKeys: context.persistEphemeralKeys,\n setPersistEphemeralKeys: context.setPersistEphemeralKeys,\n getEphemeralPublicKey: context.getEphemeralPublicKey,\n // 2FA support\n twoFactorPrompt: context.twoFactorPrompt,\n submit2FA: context.submit2FA,\n cancel2FA: context.cancel2FA,\n }\n}\n\n/**\n * Hook to access the Kentucky Signer account\n *\n * @returns Account or null if not authenticated\n *\n * @example\n * ```tsx\n * function AccountInfo() {\n * const account = useKentuckySignerAccount()\n *\n * if (!account) return <div>Not connected</div>\n *\n * return <div>Connected: {account.address}</div>\n * }\n * ```\n */\nexport function useKentuckySignerAccount(): KentuckySignerAccount | null {\n const { account } = useKentuckySignerContext()\n return account\n}\n\n/**\n * Options for useWalletClient hook\n */\nexport interface UseWalletClientOptions {\n /** Viem chain configuration */\n chain: Chain\n /** RPC URL (defaults to chain's default RPC) */\n rpcUrl?: string\n}\n\n/**\n * Hook to create a Viem WalletClient with the Kentucky Signer account\n *\n * @param options - Wallet client options\n * @returns Wallet client or null if not authenticated\n *\n * @example\n * ```tsx\n * import { mainnet } from 'viem/chains'\n *\n * function SendTransaction() {\n * const walletClient = useWalletClient({\n * chain: mainnet,\n * rpcUrl: 'https://eth-mainnet.g.alchemy.com/v2/...'\n * })\n *\n * async function send() {\n * if (!walletClient) return\n *\n * const hash = await walletClient.sendTransaction({\n * to: '0x...',\n * value: parseEther('0.1')\n * })\n * console.log('Transaction hash:', hash)\n * }\n *\n * return <button onClick={send} disabled={!walletClient}>Send</button>\n * }\n * ```\n */\nexport function useWalletClient(\n options: UseWalletClientOptions\n): WalletClient<Transport, Chain, KentuckySignerAccount> | null {\n const { account } = useKentuckySignerContext()\n const { chain, rpcUrl } = options\n\n return useMemo(() => {\n if (!account) return null\n\n return createWalletClient({\n account,\n chain,\n transport: http(rpcUrl),\n }) as WalletClient<Transport, Chain, KentuckySignerAccount>\n }, [account, chain, rpcUrl])\n}\n\n/**\n * Hook for passkey authentication flow\n *\n * Provides state management for the authentication process.\n *\n * @returns Authentication state and trigger function\n *\n * @example\n * ```tsx\n * function PasskeyLogin() {\n * const { login, isLoading, error } = usePasskeyAuth()\n *\n * return (\n * <div>\n * <input\n * placeholder=\"Account ID\"\n * onChange={(e) => setAccountId(e.target.value)}\n * />\n * <button onClick={() => login(accountId)} disabled={isLoading}>\n * {isLoading ? 'Authenticating...' : 'Login'}\n * </button>\n * {error && <div className=\"error\">{error.message}</div>}\n * </div>\n * )\n * }\n * ```\n */\nexport function usePasskeyAuth() {\n const { authenticate, isAuthenticating, error, clearError } =\n useKentuckySignerContext()\n\n const login = useCallback(\n async (accountId: string, options?: { rpId?: string }) => {\n clearError()\n await authenticate(accountId, options)\n },\n [authenticate, clearError]\n )\n\n return {\n login,\n isLoading: isAuthenticating,\n error,\n clearError,\n }\n}\n\n/**\n * Hook for signing messages\n *\n * @returns Sign function and loading state\n *\n * @example\n * ```tsx\n * function SignMessage() {\n * const { signMessage, isLoading } = useSignMessage()\n * const [signature, setSignature] = useState('')\n *\n * async function sign() {\n * const sig = await signMessage('Hello, World!')\n * setSignature(sig)\n * }\n *\n * return (\n * <div>\n * <button onClick={sign} disabled={isLoading}>Sign Message</button>\n * {signature && <div>Signature: {signature}</div>}\n * </div>\n * )\n * }\n * ```\n */\nexport function useSignMessage() {\n const { account } = useKentuckySignerContext()\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const signMessage = useCallback(\n async (message: string): Promise<string> => {\n if (!account) {\n throw new Error('Not authenticated')\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const signature = await account.signMessage({ message })\n return signature\n } catch (err) {\n setError(err as Error)\n throw err\n } finally {\n setIsLoading(false)\n }\n },\n [account]\n )\n\n return {\n signMessage,\n isLoading,\n error,\n isAvailable: !!account,\n }\n}\n\n/**\n * Hook for signing typed data (EIP-712)\n *\n * @returns Sign function and loading state\n */\nexport function useSignTypedData() {\n const { account } = useKentuckySignerContext()\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<Error | null>(null)\n\n const signTypedData = useCallback(\n async (typedData: Parameters<NonNullable<typeof account>['signTypedData']>[0]): Promise<string> => {\n if (!account) {\n throw new Error('Not authenticated')\n }\n\n setIsLoading(true)\n setError(null)\n\n try {\n const signature = await account.signTypedData(typedData)\n return signature\n } catch (err) {\n setError(err as Error)\n throw err\n } finally {\n setIsLoading(false)\n }\n },\n [account]\n )\n\n return {\n signTypedData,\n isLoading,\n error,\n isAvailable: !!account,\n }\n}\n\n/**\n * Hook to check if Kentucky Signer is ready\n *\n * @returns Whether the signer is authenticated and ready\n */\nexport function useIsReady(): boolean {\n const { isAuthenticated, account } = useKentuckySignerContext()\n return isAuthenticated && account !== null\n}\n\n/**\n * Hook to get the connected address\n *\n * @returns EVM address or undefined if not connected\n */\nexport function useAddress(): `0x${string}` | undefined {\n const { account } = useKentuckySignerContext()\n return account?.address\n}\n"],"mappings":"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","names":["useMemo","useCallback","useState","useMemo","useCallback","useState"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kentucky-signer-viem",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "Custom Viem account integration for Kentucky Signer with passkey authentication",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",