@cedros/login-react 0.0.46 → 0.0.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/README.md +32 -2
  2. package/dist/AdminWithdrawalHistory-CgYehfMH.js +948 -0
  3. package/dist/AdminWithdrawalHistory-CgYehfMH.js.map +1 -0
  4. package/dist/AdminWithdrawalHistory-zDUhPDNi.cjs +1 -0
  5. package/dist/AdminWithdrawalHistory-zDUhPDNi.cjs.map +1 -0
  6. package/dist/EmailRegisterForm-ByYQ43yL.cjs +1 -0
  7. package/dist/EmailRegisterForm-ByYQ43yL.cjs.map +1 -0
  8. package/dist/EmailRegisterForm-DMUcNQT-.js +781 -0
  9. package/dist/EmailRegisterForm-DMUcNQT-.js.map +1 -0
  10. package/dist/GoogleLoginButton-DEwtBp56.cjs +1 -0
  11. package/dist/GoogleLoginButton-DEwtBp56.cjs.map +1 -0
  12. package/dist/{GoogleLoginButton-C1WNu7W3.js → GoogleLoginButton-DwyxvhnL.js} +82 -80
  13. package/dist/GoogleLoginButton-DwyxvhnL.js.map +1 -0
  14. package/dist/{PermissionsSection-mm9hfp-u.js → PermissionsSection-0oNHPZzL.js} +383 -415
  15. package/dist/PermissionsSection-0oNHPZzL.js.map +1 -0
  16. package/dist/PermissionsSection-CZsJuxo4.cjs +1 -0
  17. package/dist/PermissionsSection-CZsJuxo4.cjs.map +1 -0
  18. package/dist/SolanaLoginButton-2504p6cr.cjs +1 -0
  19. package/dist/SolanaLoginButton-2504p6cr.cjs.map +1 -0
  20. package/dist/SolanaLoginButton-C7Kc_m6n.js +234 -0
  21. package/dist/SolanaLoginButton-C7Kc_m6n.js.map +1 -0
  22. package/dist/{TeamSection-Km7EwLWD.cjs → TeamSection-DN8PEHH3.cjs} +1 -1
  23. package/dist/{TeamSection-Km7EwLWD.cjs.map → TeamSection-DN8PEHH3.cjs.map} +1 -1
  24. package/dist/{TeamSection-C_eODdLU.js → TeamSection-gUyP4YDM.js} +1 -1
  25. package/dist/{TeamSection-C_eODdLU.js.map → TeamSection-gUyP4YDM.js.map} +1 -1
  26. package/dist/{UsersSection-C1Tt0ePx.cjs → UsersSection-8wLuD0fr.cjs} +1 -1
  27. package/dist/{UsersSection-C1Tt0ePx.cjs.map → UsersSection-8wLuD0fr.cjs.map} +1 -1
  28. package/dist/{UsersSection-Ct_E-MBF.js → UsersSection-CnsFrG-6.js} +1 -1
  29. package/dist/{UsersSection-Ct_E-MBF.js.map → UsersSection-CnsFrG-6.js.map} +1 -1
  30. package/dist/{WithdrawalsSection-BN-FjTEV.js → WithdrawalsSection-BCG_-DAP.js} +1 -1
  31. package/dist/{WithdrawalsSection-BN-FjTEV.js.map → WithdrawalsSection-BCG_-DAP.js.map} +1 -1
  32. package/dist/{WithdrawalsSection-BhuCwFat.cjs → WithdrawalsSection-DKpL2mt8.cjs} +1 -1
  33. package/dist/{WithdrawalsSection-BhuCwFat.cjs.map → WithdrawalsSection-DKpL2mt8.cjs.map} +1 -1
  34. package/dist/admin-only.cjs +1 -1
  35. package/dist/admin-only.js +1 -1
  36. package/dist/email-only.cjs +1 -1
  37. package/dist/email-only.d.ts +10 -2
  38. package/dist/email-only.js +2 -2
  39. package/dist/google-only.cjs +1 -1
  40. package/dist/google-only.d.ts +7 -2
  41. package/dist/google-only.js +2 -2
  42. package/dist/index.cjs +12 -12
  43. package/dist/index.cjs.map +1 -1
  44. package/dist/index.d.ts +182 -11
  45. package/dist/index.js +5000 -4409
  46. package/dist/index.js.map +1 -1
  47. package/dist/login-react.css +1 -1
  48. package/dist/{plugin-Ci67QMGG.cjs → plugin-C7dru1t-.cjs} +1 -1
  49. package/dist/{plugin-Ci67QMGG.cjs.map → plugin-C7dru1t-.cjs.map} +1 -1
  50. package/dist/{plugin-Cm8Q6O4-.js → plugin-DivbaxSZ.js} +1 -1
  51. package/dist/{plugin-Cm8Q6O4-.js.map → plugin-DivbaxSZ.js.map} +1 -1
  52. package/dist/solana-only.cjs +1 -1
  53. package/dist/solana-only.d.ts +6 -1
  54. package/dist/solana-only.js +2 -2
  55. package/dist/useAuth-2vgrAH-M.cjs +1 -0
  56. package/dist/useAuth-2vgrAH-M.cjs.map +1 -0
  57. package/dist/{useAuth-l-itM5am.js → useAuth-CNflw856.js} +465 -469
  58. package/dist/useAuth-CNflw856.js.map +1 -0
  59. package/dist/useServerFeatures-9_aNPaa6.cjs +1 -0
  60. package/dist/useServerFeatures-9_aNPaa6.cjs.map +1 -0
  61. package/dist/useServerFeatures-DSkYdan-.js +82 -0
  62. package/dist/useServerFeatures-DSkYdan-.js.map +1 -0
  63. package/dist/{useUsersStatsSummary-BGeh3RnI.js → useUsersStatsSummary-B4_RBEYy.js} +504 -442
  64. package/dist/useUsersStatsSummary-B4_RBEYy.js.map +1 -0
  65. package/dist/useUsersStatsSummary-CHRMrlk4.cjs +1 -0
  66. package/dist/useUsersStatsSummary-CHRMrlk4.cjs.map +1 -0
  67. package/package.json +1 -1
  68. package/dist/AdminWithdrawalHistory-B2EY2ZmH.cjs +0 -1
  69. package/dist/AdminWithdrawalHistory-B2EY2ZmH.cjs.map +0 -1
  70. package/dist/AdminWithdrawalHistory-C76bkbjX.js +0 -916
  71. package/dist/AdminWithdrawalHistory-C76bkbjX.js.map +0 -1
  72. package/dist/EmailRegisterForm-p2X5QP58.js +0 -750
  73. package/dist/EmailRegisterForm-p2X5QP58.js.map +0 -1
  74. package/dist/EmailRegisterForm-xFb6MaVA.cjs +0 -1
  75. package/dist/EmailRegisterForm-xFb6MaVA.cjs.map +0 -1
  76. package/dist/GoogleLoginButton-2zNTIKMm.cjs +0 -1
  77. package/dist/GoogleLoginButton-2zNTIKMm.cjs.map +0 -1
  78. package/dist/GoogleLoginButton-C1WNu7W3.js.map +0 -1
  79. package/dist/PermissionsSection-4zcE9Zs9.cjs +0 -1
  80. package/dist/PermissionsSection-4zcE9Zs9.cjs.map +0 -1
  81. package/dist/PermissionsSection-mm9hfp-u.js.map +0 -1
  82. package/dist/SolanaLoginButton-CqdzSSeJ.cjs +0 -1
  83. package/dist/SolanaLoginButton-CqdzSSeJ.cjs.map +0 -1
  84. package/dist/SolanaLoginButton-CyeX35eU.js +0 -232
  85. package/dist/SolanaLoginButton-CyeX35eU.js.map +0 -1
  86. package/dist/sanitization-Bo_tn-L2.cjs +0 -1
  87. package/dist/sanitization-Bo_tn-L2.cjs.map +0 -1
  88. package/dist/sanitization-CQ-H1MSg.js +0 -39
  89. package/dist/sanitization-CQ-H1MSg.js.map +0 -1
  90. package/dist/useAuth-B1yS_YiD.cjs +0 -1
  91. package/dist/useAuth-B1yS_YiD.cjs.map +0 -1
  92. package/dist/useAuth-l-itM5am.js.map +0 -1
  93. package/dist/useUsersStatsSummary-BGeh3RnI.js.map +0 -1
  94. package/dist/useUsersStatsSummary-DnsYtFGX.cjs +0 -1
  95. package/dist/useUsersStatsSummary-DnsYtFGX.cjs.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"SolanaLoginButton-CqdzSSeJ.cjs","sources":["../src/hooks/useSolanaAuth.ts","../src/utils/mobileWalletAdapter.ts","../src/utils/walletDetection.ts","../src/components/solana/SolanaLoginButton.tsx"],"sourcesContent":["import { useState, useCallback, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport { validateSolanaPublicKey } from '../utils/validation';\nimport type { AuthResponse, AuthError, ChallengeResponse } from '../types';\n\nexport interface UseSolanaAuthReturn {\n requestChallenge: (publicKey: string) => Promise<ChallengeResponse>;\n signIn: (publicKey: string, signature: string, message: string) => Promise<AuthResponse>;\n isLoading: boolean;\n error: AuthError | null;\n clearError: () => void;\n}\n\n/**\n * Hook for Solana wallet authentication.\n *\n * @example\n * ```tsx\n * function SolanaLogin() {\n * const { requestChallenge, signIn, isLoading } = useSolanaAuth();\n * const { publicKey, signMessage } = useWallet();\n *\n * const handleLogin = async () => {\n * const challenge = await requestChallenge(publicKey.toBase58());\n * const signature = await signMessage(new TextEncoder().encode(challenge.message));\n * const result = await signIn(\n * publicKey.toBase58(),\n * Buffer.from(signature).toString('base64'),\n * challenge.message\n * );\n * };\n * }\n * ```\n */\nexport function useSolanaAuth(): UseSolanaAuthReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts]\n );\n\n const requestChallenge = useCallback(\n async (publicKey: string): Promise<ChallengeResponse> => {\n // Validate public key format before making API call\n if (!validateSolanaPublicKey(publicKey)) {\n const authError: AuthError = {\n code: 'INVALID_PUBLIC_KEY',\n message: 'Invalid Solana public key format',\n };\n setError(authError);\n throw authError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const data = await apiClient.post<ChallengeResponse>(\n '/solana/challenge',\n { publicKey },\n { credentials: 'omit' }\n );\n return data;\n } catch (err) {\n const authError = handleApiError(err, 'Unable to start wallet verification. Please try again.');\n setError(authError);\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [apiClient]\n );\n\n const signIn = useCallback(\n async (publicKey: string, signature: string, message: string): Promise<AuthResponse> => {\n // Validate public key format before making API call\n if (!validateSolanaPublicKey(publicKey)) {\n const authError: AuthError = {\n code: 'INVALID_PUBLIC_KEY',\n message: 'Invalid Solana public key format',\n };\n setError(authError);\n throw authError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const data = await apiClient.post<AuthResponse>('/solana', {\n publicKey,\n signature,\n message,\n referral: _internal?.getReferralCode?.() ?? undefined,\n });\n config.callbacks?.onLoginSuccess?.(data.user, 'solana');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n return data;\n } catch (err) {\n const authError = handleApiError(err, 'Unable to sign in with your wallet. Please try again.');\n setError(authError);\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [apiClient, config.callbacks, _internal]\n );\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n requestChallenge,\n signIn,\n isLoading,\n error,\n clearError,\n };\n}\n","/**\n * Mobile Wallet Adapter (MWA) registration for web.\n *\n * On Android Chrome, MWA lets users authenticate with their installed Solana\n * wallet app (e.g., Phantom, Solflare) via Android Intents — no browser\n * extension needed.\n *\n * Once registered, MWA appears as a wallet option in the wallet adapter's\n * wallet list (alongside browser extension wallets). Users see it as\n * \"Use Installed Wallet\" in the wallet selector.\n *\n * Requires the optional peer dependency: @solana-mobile/wallet-standard-mobile\n *\n * @see https://docs.solanamobile.com/get-started/web/installation\n */\n\nexport interface MobileWalletConfig {\n /** App name shown in the wallet's authorization dialog */\n name?: string;\n /** App URI for identity verification */\n uri?: string;\n /** App icon path/URL shown in the wallet dialog */\n icon?: string;\n /** Solana cluster(s) to support. Default: ['solana:mainnet'] */\n chains?: string[];\n}\n\n/**\n * Register Mobile Wallet Adapter as a wallet-standard wallet.\n *\n * Call this once at your application root (before rendering). After registration,\n * MWA automatically appears as \"Use Installed Wallet\" for users browsing on\n * Android Chrome with a Solana wallet app installed.\n *\n * Must be called in a non-SSR context (browser only). For Next.js, call in a\n * Client Component with `'use client'`.\n *\n * @example\n * ```tsx\n * import { registerMobileWallet, CedrosLoginProvider } from '@cedros/login-react';\n *\n * // Register before provider mounts\n * registerMobileWallet({ name: 'My App', uri: 'https://myapp.com' });\n *\n * function App() {\n * return (\n * <CedrosLoginProvider config={{ serverUrl: '...' }}>\n * <LoginForm />\n * </CedrosLoginProvider>\n * );\n * }\n * ```\n *\n * @returns Promise resolving to true if registration succeeded, false otherwise\n */\nexport async function registerMobileWallet(config?: MobileWalletConfig): Promise<boolean> {\n if (typeof window === 'undefined') {\n return false;\n }\n\n try {\n // Dynamic import() — works in browser ESM (unlike require() which only\n // works in CJS/Node). The package is externalized in Vite library mode,\n // so the consumer must have it installed for this to resolve.\n const mwa = await import('@solana-mobile/wallet-standard-mobile');\n\n const chains = config?.chains ?? ['solana:mainnet'];\n\n mwa.registerMwa({\n appIdentity: {\n name: config?.name,\n uri: config?.uri,\n icon: config?.icon,\n },\n chains: chains as [`${string}:${string}`, ...`${string}:${string}`[]],\n authorizationCache: mwa.createDefaultAuthorizationCache(),\n chainSelector: mwa.createDefaultChainSelector(),\n onWalletNotFound: mwa.createDefaultWalletNotFoundHandler(),\n });\n return true;\n } catch {\n // @solana-mobile/wallet-standard-mobile not installed or import failed\n return false;\n }\n}\n","/**\n * Wallet detection utilities for Solana browser wallets\n */\n\n/**\n * Type for window with potential Solana wallet extensions\n */\nexport interface WindowWithWallets extends Window {\n phantom?: { solana?: unknown };\n solflare?: { solana?: unknown };\n backpack?: { solana?: unknown };\n glow?: { solana?: unknown };\n slope?: { solana?: unknown };\n sollet?: { solana?: unknown };\n coin98?: { solana?: unknown };\n clover?: { solana?: unknown };\n mathWallet?: { solana?: unknown };\n ledger?: { solana?: unknown };\n torus?: { solana?: unknown };\n walletconnect?: { solana?: unknown };\n solana?: unknown;\n}\n\n/**\n * Known Solana wallet provider names to check for on the window object\n */\ntype WalletProviderName = Exclude<keyof WindowWithWallets, keyof Window>;\n\nexport const WALLET_PROVIDERS: WalletProviderName[] = [\n 'phantom',\n 'solflare',\n 'backpack',\n 'glow',\n 'slope',\n 'sollet',\n 'coin98',\n 'clover',\n 'mathWallet',\n 'ledger',\n 'torus',\n 'walletconnect',\n];\n\n/**\n * UI-9 FIX: Validates that a wallet provider object has expected Solana wallet methods.\n * Prevents spoofed wallet objects from being accepted.\n */\nexport function isValidSolanaProvider(provider: unknown): boolean {\n if (!provider || typeof provider !== 'object') return false;\n const wallet = provider as Record<string, unknown>;\n // Check for at least one expected wallet method/property\n // Real wallets have connect, signMessage, signTransaction, etc.\n return (\n typeof wallet.connect === 'function' ||\n typeof wallet.signMessage === 'function' ||\n typeof wallet.signTransaction === 'function' ||\n 'isConnected' in wallet\n );\n}\n\n/**\n * Detect Android Chrome specifically (MWA only works on Chrome, not Brave/Firefox/Opera).\n * Brave's UA includes \"Chrome\" but exposes `navigator.brave` which Chrome does not.\n * @see https://docs.solanamobile.com/get-started/web/apps\n */\nexport function isAndroidChrome(): boolean {\n if (typeof navigator === 'undefined') return false;\n const ua = navigator.userAgent;\n const isBrave = 'brave' in navigator;\n return /Android/i.test(ua) && /Chrome\\/\\d+/.test(ua) && !isBrave;\n}\n\n/**\n * Detects if any Solana wallet extensions are installed in the browser.\n * Checks for common wallet adapters like Phantom, Solflare, Backpack, etc.\n *\n * @returns true if at least one Solana wallet is detected\n *\n * @example\n * ```tsx\n * if (detectSolanaWallets()) {\n * // Show Solana login button\n * }\n * ```\n */\nexport function detectSolanaWallets(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n\n const win = window as WindowWithWallets;\n\n // Check window object for wallet injections\n // UI-9: Validate wallet has expected methods to reject spoofed providers\n for (const provider of WALLET_PROVIDERS) {\n const walletObj = win[provider];\n if (\n walletObj &&\n typeof walletObj === 'object' &&\n 'solana' in walletObj &&\n isValidSolanaProvider(walletObj.solana)\n ) {\n return true;\n }\n }\n\n // Check for generic Solana provider (e.g., from some mobile wallet browsers)\n // UI-9: Also validate generic provider\n if (isValidSolanaProvider(win.solana)) {\n return true;\n }\n\n // On Android Chrome, MWA connects to native wallet apps (e.g., Phantom, Solflare)\n // via Android intents — no browser extension needed. MWA only works on Chrome,\n // not Brave/Firefox/Opera (per Solana Mobile docs).\n if (isAndroidChrome()) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns list of detected Solana wallet names (for debugging/display)\n *\n * @returns Array of detected wallet provider names\n */\nexport function getDetectedWalletNames(): string[] {\n if (typeof window === 'undefined') {\n return [];\n }\n\n const win = window as WindowWithWallets;\n const detected: string[] = [];\n\n // UI-9: Use validation to reject spoofed providers\n for (const provider of WALLET_PROVIDERS) {\n const walletObj = win[provider];\n if (\n walletObj &&\n typeof walletObj === 'object' &&\n 'solana' in walletObj &&\n isValidSolanaProvider(walletObj.solana)\n ) {\n detected.push(provider);\n }\n }\n\n if (isValidSolanaProvider(win.solana) && detected.length === 0) {\n detected.push('solana');\n }\n\n return detected;\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { WalletProvider, useWallet } from '@solana/wallet-adapter-react';\nimport { WalletModalProvider, useWalletModal } from '@solana/wallet-adapter-react-ui';\nimport type { WalletName } from '@solana/wallet-adapter-base';\nimport { useSolanaAuth } from '../../hooks/useSolanaAuth';\nimport { registerMobileWallet } from '../../utils/mobileWalletAdapter';\nimport { isAndroidChrome } from '../../utils/walletDetection';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\n\n// Auto-register Mobile Wallet Adapter on Android Chrome only.\n// MWA uses Android Intents which only work in Chrome (not Brave/Firefox/Opera).\n// Fire-and-forget: the WalletProvider picks up MWA via wallet-standard events once it resolves.\nif (isAndroidChrome()) {\n void registerMobileWallet();\n}\n\nexport interface SolanaLoginButtonProps {\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n className?: string;\n variant?: 'default' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n disabled?: boolean;\n /**\n * Hide the button if no Solana wallets are detected.\n * When true (default), button renders nothing if no wallets are installed.\n * When false, button always renders (useful for showing \"install wallet\" prompts).\n * @default true\n */\n hideIfNoWallet?: boolean;\n /** Called when the button's loading state changes (connecting, signing, etc.). */\n onLoadingChange?: (loading: boolean) => void;\n /**\n * Solana wallet adapter context. Pass this from @solana/wallet-adapter-react's useWallet().\n * When provided, the component assumes a WalletProvider exists in the React tree and\n * uses the consumer's wallet context for wallet discovery and connection.\n * When omitted, the component provides its own WalletProvider with wallet-standard discovery.\n */\n walletContext?: {\n publicKey: { toBase58: () => string } | null;\n signMessage: ((message: Uint8Array) => Promise<Uint8Array>) | null;\n connected: boolean;\n connecting: boolean;\n connect: () => Promise<void>;\n wallet: { adapter: { name: string } } | null;\n select: (walletName: string) => void;\n wallets: Array<{\n adapter: {\n name: string;\n icon: string;\n readyState: string;\n };\n }>;\n };\n}\n\n/** Stable empty array to avoid re-renders in self-contained WalletProvider. */\nconst EMPTY_ADAPTERS: [] = [];\n\n/**\n * Solana wallet login button with one-click authentication.\n *\n * Uses the standard wallet adapter modal for wallet selection, which provides\n * real brand icons and discovers all wallet-standard-compliant wallets.\n *\n * When `walletContext` is provided, assumes a WalletProvider exists in the tree.\n * Otherwise, wraps itself with WalletProvider for self-contained operation.\n */\nexport function SolanaLoginButton(props: SolanaLoginButtonProps) {\n if (props.walletContext) {\n // Consumer has their own WalletProvider; just add modal capability\n return (\n <WalletModalProvider>\n <SolanaLoginInner {...props} />\n </WalletModalProvider>\n );\n }\n\n // Self-contained: provide wallet-standard discovery + modal\n return (\n <WalletProvider wallets={EMPTY_ADAPTERS} localStorageKey=\"cedros-walletName\">\n <WalletModalProvider>\n <SolanaLoginInner {...props} />\n </WalletModalProvider>\n </WalletProvider>\n );\n}\n\nfunction SolanaLoginInner({\n onSuccess,\n onError,\n className = '',\n variant = 'default',\n size = 'md',\n disabled = false,\n hideIfNoWallet = true,\n onLoadingChange,\n walletContext,\n}: SolanaLoginButtonProps) {\n const { requestChallenge, signIn, isLoading: isAuthLoading } = useSolanaAuth();\n const adapterWallet = useWallet();\n const { visible: modalVisible, setVisible: setModalVisible } = useWalletModal();\n const [pendingLogin, setPendingLogin] = useState(false);\n const [triggerConnect, setTriggerConnect] = useState(false);\n const isProcessingRef = useRef(false);\n const modalWasOpen = useRef(false);\n const signRejectedRef = useRef(false);\n\n // Use walletContext if provided, otherwise use adapter's useWallet()\n const connected = walletContext?.connected ?? adapterWallet.connected;\n const connecting = walletContext?.connecting ?? adapterWallet.connecting;\n const publicKey = walletContext?.publicKey ?? adapterWallet.publicKey;\n const signMessage = walletContext?.signMessage ?? adapterWallet.signMessage;\n const wallet = walletContext?.wallet ?? adapterWallet.wallet;\n const wallets = walletContext?.wallets ?? adapterWallet.wallets;\n const select = walletContext\n ? walletContext.select\n : (name: string) => adapterWallet.select(name as WalletName);\n const connect = walletContext?.connect ?? adapterWallet.connect;\n\n // Get installed/ready wallets\n const installedWallets = wallets.filter(\n (w) => w.adapter.readyState === 'Installed' || w.adapter.readyState === 'Loadable'\n );\n\n // Execute the sign-in flow (challenge → sign → verify)\n const executeSignIn = useCallback(async () => {\n if (isProcessingRef.current) return;\n if (!publicKey || !signMessage) {\n onError?.(new Error('Wallet not ready'));\n return;\n }\n\n isProcessingRef.current = true;\n try {\n const pubKeyString = publicKey.toBase58();\n\n const challenge = await requestChallenge(pubKeyString);\n\n const messageBytes = new TextEncoder().encode(challenge.message);\n const signatureBytes = await signMessage(messageBytes);\n\n if (!(signatureBytes instanceof Uint8Array) || signatureBytes.length === 0) {\n throw new Error('Wallet returned invalid signature');\n }\n\n let signature: string;\n try {\n signature = btoa(String.fromCharCode(...signatureBytes));\n } catch {\n throw new Error('Failed to encode signature');\n }\n\n await signIn(pubKeyString, signature, challenge.message);\n signRejectedRef.current = false;\n onSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n signRejectedRef.current = true;\n onError?.(error);\n } finally {\n isProcessingRef.current = false;\n setPendingLogin(false);\n }\n }, [publicKey, signMessage, requestChallenge, signIn, onSuccess, onError]);\n\n // Auto-connect when wallet is selected and triggerConnect is set\n useEffect(() => {\n if (triggerConnect && wallet && !connected && !connecting) {\n setTriggerConnect(false);\n connect().catch((err) => {\n onError?.(err instanceof Error ? err : new Error(String(err)));\n setPendingLogin(false);\n });\n }\n }, [triggerConnect, wallet, connected, connecting, connect, onError]);\n\n // Auto-execute sign-in when connected with pending login\n useEffect(() => {\n if (pendingLogin && connected && publicKey && signMessage && !isProcessingRef.current) {\n executeSignIn().catch(() => {\n /* Errors already passed to onError callback inside executeSignIn */\n });\n }\n }, [pendingLogin, connected, publicKey, signMessage, executeSignIn]);\n\n // When modal closes: connect if a wallet was selected, else reset.\n // Wallet is always deselected before opening, so any non-null wallet = user chose one.\n useEffect(() => {\n if (modalVisible) {\n modalWasOpen.current = true;\n } else if (modalWasOpen.current) {\n modalWasOpen.current = false;\n if (pendingLogin && !connected && wallet && !connecting) {\n setTriggerConnect(true);\n } else if (pendingLogin && !connected) {\n setPendingLogin(false);\n }\n }\n }, [modalVisible, pendingLogin, connected, wallet, connecting]);\n\n // Hide button if no wallets detected\n if (hideIfNoWallet && installedWallets.length === 0) {\n return null;\n }\n\n const handleClick = async () => {\n if (disabled || isAuthLoading || connecting) return;\n\n if (connected && publicKey && signMessage && !signRejectedRef.current) {\n // Already connected, previous attempt wasn't rejected — sign immediately\n setPendingLogin(true);\n await executeSignIn();\n } else if (installedWallets.length === 1 && !wallet) {\n // Single installed wallet, nothing remembered — auto-select + connect\n select(installedWallets[0].adapter.name);\n setPendingLogin(true);\n setTriggerConnect(true);\n } else {\n // Show wallet picker — deselect any remembered wallet first so that\n // every selection in the modal registers as \"new\" and dismissing\n // leaves wallet as null (no accidental auto-connect).\n signRejectedRef.current = false;\n if (wallet) {\n adapterWallet.select(null as unknown as WalletName);\n }\n setModalVisible(true);\n setPendingLogin(true);\n }\n };\n\n const sizeClasses = {\n sm: 'cedros-button-sm',\n md: 'cedros-button-md',\n lg: 'cedros-button-lg',\n };\n\n const variantClasses = {\n default: 'cedros-button-social',\n outline: 'cedros-button-social-outline',\n };\n\n const isLoading = isAuthLoading || connecting || (pendingLogin && !connected);\n\n // Notify parent of loading state changes\n useEffect(() => {\n onLoadingChange?.(isLoading);\n }, [isLoading, onLoadingChange]);\n\n return (\n <button\n type=\"button\"\n className={`cedros-button ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}\n onClick={handleClick}\n disabled={disabled || isLoading}\n aria-label=\"Continue with Solana\"\n >\n {isLoading ? (\n <LoadingSpinner size=\"sm\" />\n ) : (\n <svg\n className=\"cedros-button-icon\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M25.38 96.04a4.35 4.35 0 0 1 3.07-1.27h91.68c1.93 0 2.9 2.34 1.54 3.7l-17.71 17.72a4.35 4.35 0 0 1-3.07 1.27H9.21c-1.93 0-2.9-2.34-1.54-3.7l17.71-17.72z\" />\n <path d=\"M25.38 11.81a4.47 4.47 0 0 1 3.07-1.27h91.68c1.93 0 2.9 2.34 1.54 3.7L103.96 31.96a4.35 4.35 0 0 1-3.07 1.27H9.21c-1.93 0-2.9-2.34-1.54-3.7L25.38 11.81z\" />\n <path d=\"M102.62 53.76a4.35 4.35 0 0 0-3.07-1.27H7.87c-1.93 0-2.9 2.34-1.54 3.7l17.71 17.72a4.35 4.35 0 0 0 3.07 1.27h91.68c1.93 0 2.9-2.34 1.54-3.7L102.62 53.76z\" />\n </svg>\n )}\n <span>Continue with Solana</span>\n </button>\n );\n}\n"],"names":["useSolanaAuth","config","_internal","useCedrosLogin","isLoading","setIsLoading","useState","error","setError","apiClient","useMemo","ApiClient","requestChallenge","useCallback","publicKey","validateSolanaPublicKey","authError","err","handleApiError","signIn","signature","message","data","clearError","registerMobileWallet","mwa","chains","WALLET_PROVIDERS","isValidSolanaProvider","provider","wallet","isAndroidChrome","ua","isBrave","detectSolanaWallets","win","walletObj","EMPTY_ADAPTERS","SolanaLoginButton","props","WalletModalProvider","jsx","SolanaLoginInner","WalletProvider","onSuccess","onError","className","variant","size","disabled","hideIfNoWallet","onLoadingChange","walletContext","isAuthLoading","adapterWallet","useWallet","modalVisible","setModalVisible","useWalletModal","pendingLogin","setPendingLogin","triggerConnect","setTriggerConnect","isProcessingRef","useRef","modalWasOpen","signRejectedRef","connected","connecting","signMessage","wallets","select","name","connect","installedWallets","w","executeSignIn","pubKeyString","challenge","messageBytes","signatureBytes","useEffect","handleClick","sizeClasses","variantClasses","jsxs","LoadingSpinner"],"mappings":"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"}
@@ -1,232 +0,0 @@
1
- import { jsx as c, jsxs as j } from "react/jsx-runtime";
2
- import { useState as P, useMemo as x, useCallback as W, useRef as D, useEffect as M } from "react";
3
- import { WalletProvider as ee, useWallet as te } from "@solana/wallet-adapter-react";
4
- import { WalletModalProvider as K, useWalletModal as ne } from "@solana/wallet-adapter-react-ui";
5
- import { u as ae, A as re, h as q } from "./useCedrosLogin-CFfID-0i.js";
6
- import { a as H } from "./validation-B8kMV3BL.js";
7
- import { L as se } from "./LoadingSpinner-6vml-zwr.js";
8
- function oe() {
9
- const { config: e, _internal: t } = ae(), [o, d] = P(!1), [k, l] = P(null), g = x(
10
- () => new re({
11
- baseUrl: e.serverUrl,
12
- timeoutMs: e.requestTimeout,
13
- retryAttempts: e.retryAttempts
14
- }),
15
- [e.serverUrl, e.requestTimeout, e.retryAttempts]
16
- ), S = W(
17
- async (f) => {
18
- if (!H(f)) {
19
- const i = {
20
- code: "INVALID_PUBLIC_KEY",
21
- message: "Invalid Solana public key format"
22
- };
23
- throw l(i), i;
24
- }
25
- d(!0), l(null);
26
- try {
27
- return await g.post(
28
- "/solana/challenge",
29
- { publicKey: f },
30
- { credentials: "omit" }
31
- );
32
- } catch (i) {
33
- const a = q(i, "Unable to start wallet verification. Please try again.");
34
- throw l(a), a;
35
- } finally {
36
- d(!1);
37
- }
38
- },
39
- [g]
40
- ), s = W(
41
- async (f, i, a) => {
42
- if (!H(f)) {
43
- const r = {
44
- code: "INVALID_PUBLIC_KEY",
45
- message: "Invalid Solana public key format"
46
- };
47
- throw l(r), r;
48
- }
49
- d(!0), l(null);
50
- try {
51
- const r = await g.post("/solana", {
52
- publicKey: f,
53
- signature: i,
54
- message: a,
55
- referral: t?.getReferralCode?.() ?? void 0
56
- });
57
- return e.callbacks?.onLoginSuccess?.(r.user, "solana"), t?.handleLoginSuccess(r.user, r.tokens), r;
58
- } catch (r) {
59
- const v = q(r, "Unable to sign in with your wallet. Please try again.");
60
- throw l(v), v;
61
- } finally {
62
- d(!1);
63
- }
64
- },
65
- [g, e.callbacks, t]
66
- ), L = W(() => l(null), []);
67
- return {
68
- requestChallenge: S,
69
- signIn: s,
70
- isLoading: o,
71
- error: k,
72
- clearError: L
73
- };
74
- }
75
- async function le(e) {
76
- if (typeof window > "u")
77
- return !1;
78
- try {
79
- const t = await import("@solana-mobile/wallet-standard-mobile"), o = e?.chains ?? ["solana:mainnet"];
80
- return t.registerMwa({
81
- appIdentity: {
82
- name: e?.name,
83
- uri: e?.uri,
84
- icon: e?.icon
85
- },
86
- chains: o,
87
- authorizationCache: t.createDefaultAuthorizationCache(),
88
- chainSelector: t.createDefaultChainSelector(),
89
- onWalletNotFound: t.createDefaultWalletNotFoundHandler()
90
- }), !0;
91
- } catch {
92
- return !1;
93
- }
94
- }
95
- const ie = [
96
- "phantom",
97
- "solflare",
98
- "backpack",
99
- "glow",
100
- "slope",
101
- "sollet",
102
- "coin98",
103
- "clover",
104
- "mathWallet",
105
- "ledger",
106
- "torus",
107
- "walletconnect"
108
- ];
109
- function F(e) {
110
- if (!e || typeof e != "object") return !1;
111
- const t = e;
112
- return typeof t.connect == "function" || typeof t.signMessage == "function" || typeof t.signTransaction == "function" || "isConnected" in t;
113
- }
114
- function Y() {
115
- if (typeof navigator > "u") return !1;
116
- const e = navigator.userAgent, t = "brave" in navigator;
117
- return /Android/i.test(e) && /Chrome\/\d+/.test(e) && !t;
118
- }
119
- function ye() {
120
- if (typeof window > "u")
121
- return !1;
122
- const e = window;
123
- for (const t of ie) {
124
- const o = e[t];
125
- if (o && typeof o == "object" && "solana" in o && F(o.solana))
126
- return !0;
127
- }
128
- return !!(F(e.solana) || Y());
129
- }
130
- Y() && le();
131
- const ce = [];
132
- function we(e) {
133
- return e.walletContext ? /* @__PURE__ */ c(K, { children: /* @__PURE__ */ c(O, { ...e }) }) : /* @__PURE__ */ c(ee, { wallets: ce, localStorageKey: "cedros-walletName", children: /* @__PURE__ */ c(K, { children: /* @__PURE__ */ c(O, { ...e }) }) });
134
- }
135
- function O({
136
- onSuccess: e,
137
- onError: t,
138
- className: o = "",
139
- variant: d = "default",
140
- size: k = "md",
141
- disabled: l = !1,
142
- hideIfNoWallet: g = !0,
143
- onLoadingChange: S,
144
- walletContext: s
145
- }) {
146
- const { requestChallenge: L, signIn: f, isLoading: i } = oe(), a = te(), { visible: r, setVisible: v } = ne(), [h, m] = P(!1), [N, B] = P(!1), A = D(!1), R = D(!1), C = D(!1), u = s?.connected ?? a.connected, p = s?.connecting ?? a.connecting, y = s?.publicKey ?? a.publicKey, w = s?.signMessage ?? a.signMessage, b = s?.wallet ?? a.wallet, $ = s?.wallets ?? a.wallets, G = s ? s.select : (n) => a.select(n), V = s?.connect ?? a.connect, T = $.filter(
147
- (n) => n.adapter.readyState === "Installed" || n.adapter.readyState === "Loadable"
148
- ), U = W(async () => {
149
- if (!A.current) {
150
- if (!y || !w) {
151
- t?.(new Error("Wallet not ready"));
152
- return;
153
- }
154
- A.current = !0;
155
- try {
156
- const n = y.toBase58(), I = await L(n), Z = new TextEncoder().encode(I.message), z = await w(Z);
157
- if (!(z instanceof Uint8Array) || z.length === 0)
158
- throw new Error("Wallet returned invalid signature");
159
- let _;
160
- try {
161
- _ = btoa(String.fromCharCode(...z));
162
- } catch {
163
- throw new Error("Failed to encode signature");
164
- }
165
- await f(n, _, I.message), C.current = !1, e?.();
166
- } catch (n) {
167
- const I = n instanceof Error ? n : new Error(String(n));
168
- C.current = !0, t?.(I);
169
- } finally {
170
- A.current = !1, m(!1);
171
- }
172
- }
173
- }, [y, w, L, f, e, t]);
174
- if (M(() => {
175
- N && b && !u && !p && (B(!1), V().catch((n) => {
176
- t?.(n instanceof Error ? n : new Error(String(n))), m(!1);
177
- }));
178
- }, [N, b, u, p, V, t]), M(() => {
179
- h && u && y && w && !A.current && U().catch(() => {
180
- });
181
- }, [h, u, y, w, U]), M(() => {
182
- r ? R.current = !0 : R.current && (R.current = !1, h && !u && b && !p ? B(!0) : h && !u && m(!1));
183
- }, [r, h, u, b, p]), g && T.length === 0)
184
- return null;
185
- const J = async () => {
186
- l || i || p || (u && y && w && !C.current ? (m(!0), await U()) : T.length === 1 && !b ? (G(T[0].adapter.name), m(!0), B(!0)) : (C.current = !1, b && a.select(null), v(!0), m(!0)));
187
- }, Q = {
188
- sm: "cedros-button-sm",
189
- md: "cedros-button-md",
190
- lg: "cedros-button-lg"
191
- }, X = {
192
- default: "cedros-button-social",
193
- outline: "cedros-button-social-outline"
194
- }, E = i || p || h && !u;
195
- return M(() => {
196
- S?.(E);
197
- }, [E, S]), /* @__PURE__ */ j(
198
- "button",
199
- {
200
- type: "button",
201
- className: `cedros-button ${X[d]} ${Q[k]} ${o}`,
202
- onClick: J,
203
- disabled: l || E,
204
- "aria-label": "Continue with Solana",
205
- children: [
206
- E ? /* @__PURE__ */ c(se, { size: "sm" }) : /* @__PURE__ */ j(
207
- "svg",
208
- {
209
- className: "cedros-button-icon",
210
- width: "18",
211
- height: "18",
212
- viewBox: "0 0 128 128",
213
- fill: "currentColor",
214
- "aria-hidden": "true",
215
- children: [
216
- /* @__PURE__ */ c("path", { d: "M25.38 96.04a4.35 4.35 0 0 1 3.07-1.27h91.68c1.93 0 2.9 2.34 1.54 3.7l-17.71 17.72a4.35 4.35 0 0 1-3.07 1.27H9.21c-1.93 0-2.9-2.34-1.54-3.7l17.71-17.72z" }),
217
- /* @__PURE__ */ c("path", { d: "M25.38 11.81a4.47 4.47 0 0 1 3.07-1.27h91.68c1.93 0 2.9 2.34 1.54 3.7L103.96 31.96a4.35 4.35 0 0 1-3.07 1.27H9.21c-1.93 0-2.9-2.34-1.54-3.7L25.38 11.81z" }),
218
- /* @__PURE__ */ c("path", { d: "M102.62 53.76a4.35 4.35 0 0 0-3.07-1.27H7.87c-1.93 0-2.9 2.34-1.54 3.7l17.71 17.72a4.35 4.35 0 0 0 3.07 1.27h91.68c1.93 0 2.9-2.34 1.54-3.7L102.62 53.76z" })
219
- ]
220
- }
221
- ),
222
- /* @__PURE__ */ c("span", { children: "Continue with Solana" })
223
- ]
224
- }
225
- );
226
- }
227
- export {
228
- we as S,
229
- ye as d,
230
- le as r,
231
- oe as u
232
- };
@@ -1 +0,0 @@
1
- {"version":3,"file":"SolanaLoginButton-CyeX35eU.js","sources":["../src/hooks/useSolanaAuth.ts","../src/utils/mobileWalletAdapter.ts","../src/utils/walletDetection.ts","../src/components/solana/SolanaLoginButton.tsx"],"sourcesContent":["import { useState, useCallback, useMemo } from 'react';\nimport { useCedrosLogin } from '../context/useCedrosLogin';\nimport { ApiClient, handleApiError } from '../utils/apiClient';\nimport { validateSolanaPublicKey } from '../utils/validation';\nimport type { AuthResponse, AuthError, ChallengeResponse } from '../types';\n\nexport interface UseSolanaAuthReturn {\n requestChallenge: (publicKey: string) => Promise<ChallengeResponse>;\n signIn: (publicKey: string, signature: string, message: string) => Promise<AuthResponse>;\n isLoading: boolean;\n error: AuthError | null;\n clearError: () => void;\n}\n\n/**\n * Hook for Solana wallet authentication.\n *\n * @example\n * ```tsx\n * function SolanaLogin() {\n * const { requestChallenge, signIn, isLoading } = useSolanaAuth();\n * const { publicKey, signMessage } = useWallet();\n *\n * const handleLogin = async () => {\n * const challenge = await requestChallenge(publicKey.toBase58());\n * const signature = await signMessage(new TextEncoder().encode(challenge.message));\n * const result = await signIn(\n * publicKey.toBase58(),\n * Buffer.from(signature).toString('base64'),\n * challenge.message\n * );\n * };\n * }\n * ```\n */\nexport function useSolanaAuth(): UseSolanaAuthReturn {\n const { config, _internal } = useCedrosLogin();\n const [isLoading, setIsLoading] = useState(false);\n const [error, setError] = useState<AuthError | null>(null);\n\n const apiClient = useMemo(\n () =>\n new ApiClient({\n baseUrl: config.serverUrl,\n timeoutMs: config.requestTimeout,\n retryAttempts: config.retryAttempts,\n }),\n [config.serverUrl, config.requestTimeout, config.retryAttempts]\n );\n\n const requestChallenge = useCallback(\n async (publicKey: string): Promise<ChallengeResponse> => {\n // Validate public key format before making API call\n if (!validateSolanaPublicKey(publicKey)) {\n const authError: AuthError = {\n code: 'INVALID_PUBLIC_KEY',\n message: 'Invalid Solana public key format',\n };\n setError(authError);\n throw authError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const data = await apiClient.post<ChallengeResponse>(\n '/solana/challenge',\n { publicKey },\n { credentials: 'omit' }\n );\n return data;\n } catch (err) {\n const authError = handleApiError(err, 'Unable to start wallet verification. Please try again.');\n setError(authError);\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [apiClient]\n );\n\n const signIn = useCallback(\n async (publicKey: string, signature: string, message: string): Promise<AuthResponse> => {\n // Validate public key format before making API call\n if (!validateSolanaPublicKey(publicKey)) {\n const authError: AuthError = {\n code: 'INVALID_PUBLIC_KEY',\n message: 'Invalid Solana public key format',\n };\n setError(authError);\n throw authError;\n }\n\n setIsLoading(true);\n setError(null);\n\n try {\n const data = await apiClient.post<AuthResponse>('/solana', {\n publicKey,\n signature,\n message,\n referral: _internal?.getReferralCode?.() ?? undefined,\n });\n config.callbacks?.onLoginSuccess?.(data.user, 'solana');\n _internal?.handleLoginSuccess(data.user, data.tokens);\n return data;\n } catch (err) {\n const authError = handleApiError(err, 'Unable to sign in with your wallet. Please try again.');\n setError(authError);\n throw authError;\n } finally {\n setIsLoading(false);\n }\n },\n [apiClient, config.callbacks, _internal]\n );\n\n const clearError = useCallback(() => setError(null), []);\n\n return {\n requestChallenge,\n signIn,\n isLoading,\n error,\n clearError,\n };\n}\n","/**\n * Mobile Wallet Adapter (MWA) registration for web.\n *\n * On Android Chrome, MWA lets users authenticate with their installed Solana\n * wallet app (e.g., Phantom, Solflare) via Android Intents — no browser\n * extension needed.\n *\n * Once registered, MWA appears as a wallet option in the wallet adapter's\n * wallet list (alongside browser extension wallets). Users see it as\n * \"Use Installed Wallet\" in the wallet selector.\n *\n * Requires the optional peer dependency: @solana-mobile/wallet-standard-mobile\n *\n * @see https://docs.solanamobile.com/get-started/web/installation\n */\n\nexport interface MobileWalletConfig {\n /** App name shown in the wallet's authorization dialog */\n name?: string;\n /** App URI for identity verification */\n uri?: string;\n /** App icon path/URL shown in the wallet dialog */\n icon?: string;\n /** Solana cluster(s) to support. Default: ['solana:mainnet'] */\n chains?: string[];\n}\n\n/**\n * Register Mobile Wallet Adapter as a wallet-standard wallet.\n *\n * Call this once at your application root (before rendering). After registration,\n * MWA automatically appears as \"Use Installed Wallet\" for users browsing on\n * Android Chrome with a Solana wallet app installed.\n *\n * Must be called in a non-SSR context (browser only). For Next.js, call in a\n * Client Component with `'use client'`.\n *\n * @example\n * ```tsx\n * import { registerMobileWallet, CedrosLoginProvider } from '@cedros/login-react';\n *\n * // Register before provider mounts\n * registerMobileWallet({ name: 'My App', uri: 'https://myapp.com' });\n *\n * function App() {\n * return (\n * <CedrosLoginProvider config={{ serverUrl: '...' }}>\n * <LoginForm />\n * </CedrosLoginProvider>\n * );\n * }\n * ```\n *\n * @returns Promise resolving to true if registration succeeded, false otherwise\n */\nexport async function registerMobileWallet(config?: MobileWalletConfig): Promise<boolean> {\n if (typeof window === 'undefined') {\n return false;\n }\n\n try {\n // Dynamic import() — works in browser ESM (unlike require() which only\n // works in CJS/Node). The package is externalized in Vite library mode,\n // so the consumer must have it installed for this to resolve.\n const mwa = await import('@solana-mobile/wallet-standard-mobile');\n\n const chains = config?.chains ?? ['solana:mainnet'];\n\n mwa.registerMwa({\n appIdentity: {\n name: config?.name,\n uri: config?.uri,\n icon: config?.icon,\n },\n chains: chains as [`${string}:${string}`, ...`${string}:${string}`[]],\n authorizationCache: mwa.createDefaultAuthorizationCache(),\n chainSelector: mwa.createDefaultChainSelector(),\n onWalletNotFound: mwa.createDefaultWalletNotFoundHandler(),\n });\n return true;\n } catch {\n // @solana-mobile/wallet-standard-mobile not installed or import failed\n return false;\n }\n}\n","/**\n * Wallet detection utilities for Solana browser wallets\n */\n\n/**\n * Type for window with potential Solana wallet extensions\n */\nexport interface WindowWithWallets extends Window {\n phantom?: { solana?: unknown };\n solflare?: { solana?: unknown };\n backpack?: { solana?: unknown };\n glow?: { solana?: unknown };\n slope?: { solana?: unknown };\n sollet?: { solana?: unknown };\n coin98?: { solana?: unknown };\n clover?: { solana?: unknown };\n mathWallet?: { solana?: unknown };\n ledger?: { solana?: unknown };\n torus?: { solana?: unknown };\n walletconnect?: { solana?: unknown };\n solana?: unknown;\n}\n\n/**\n * Known Solana wallet provider names to check for on the window object\n */\ntype WalletProviderName = Exclude<keyof WindowWithWallets, keyof Window>;\n\nexport const WALLET_PROVIDERS: WalletProviderName[] = [\n 'phantom',\n 'solflare',\n 'backpack',\n 'glow',\n 'slope',\n 'sollet',\n 'coin98',\n 'clover',\n 'mathWallet',\n 'ledger',\n 'torus',\n 'walletconnect',\n];\n\n/**\n * UI-9 FIX: Validates that a wallet provider object has expected Solana wallet methods.\n * Prevents spoofed wallet objects from being accepted.\n */\nexport function isValidSolanaProvider(provider: unknown): boolean {\n if (!provider || typeof provider !== 'object') return false;\n const wallet = provider as Record<string, unknown>;\n // Check for at least one expected wallet method/property\n // Real wallets have connect, signMessage, signTransaction, etc.\n return (\n typeof wallet.connect === 'function' ||\n typeof wallet.signMessage === 'function' ||\n typeof wallet.signTransaction === 'function' ||\n 'isConnected' in wallet\n );\n}\n\n/**\n * Detect Android Chrome specifically (MWA only works on Chrome, not Brave/Firefox/Opera).\n * Brave's UA includes \"Chrome\" but exposes `navigator.brave` which Chrome does not.\n * @see https://docs.solanamobile.com/get-started/web/apps\n */\nexport function isAndroidChrome(): boolean {\n if (typeof navigator === 'undefined') return false;\n const ua = navigator.userAgent;\n const isBrave = 'brave' in navigator;\n return /Android/i.test(ua) && /Chrome\\/\\d+/.test(ua) && !isBrave;\n}\n\n/**\n * Detects if any Solana wallet extensions are installed in the browser.\n * Checks for common wallet adapters like Phantom, Solflare, Backpack, etc.\n *\n * @returns true if at least one Solana wallet is detected\n *\n * @example\n * ```tsx\n * if (detectSolanaWallets()) {\n * // Show Solana login button\n * }\n * ```\n */\nexport function detectSolanaWallets(): boolean {\n if (typeof window === 'undefined') {\n return false;\n }\n\n const win = window as WindowWithWallets;\n\n // Check window object for wallet injections\n // UI-9: Validate wallet has expected methods to reject spoofed providers\n for (const provider of WALLET_PROVIDERS) {\n const walletObj = win[provider];\n if (\n walletObj &&\n typeof walletObj === 'object' &&\n 'solana' in walletObj &&\n isValidSolanaProvider(walletObj.solana)\n ) {\n return true;\n }\n }\n\n // Check for generic Solana provider (e.g., from some mobile wallet browsers)\n // UI-9: Also validate generic provider\n if (isValidSolanaProvider(win.solana)) {\n return true;\n }\n\n // On Android Chrome, MWA connects to native wallet apps (e.g., Phantom, Solflare)\n // via Android intents — no browser extension needed. MWA only works on Chrome,\n // not Brave/Firefox/Opera (per Solana Mobile docs).\n if (isAndroidChrome()) {\n return true;\n }\n\n return false;\n}\n\n/**\n * Returns list of detected Solana wallet names (for debugging/display)\n *\n * @returns Array of detected wallet provider names\n */\nexport function getDetectedWalletNames(): string[] {\n if (typeof window === 'undefined') {\n return [];\n }\n\n const win = window as WindowWithWallets;\n const detected: string[] = [];\n\n // UI-9: Use validation to reject spoofed providers\n for (const provider of WALLET_PROVIDERS) {\n const walletObj = win[provider];\n if (\n walletObj &&\n typeof walletObj === 'object' &&\n 'solana' in walletObj &&\n isValidSolanaProvider(walletObj.solana)\n ) {\n detected.push(provider);\n }\n }\n\n if (isValidSolanaProvider(win.solana) && detected.length === 0) {\n detected.push('solana');\n }\n\n return detected;\n}\n","import { useState, useEffect, useCallback, useRef } from 'react';\nimport { WalletProvider, useWallet } from '@solana/wallet-adapter-react';\nimport { WalletModalProvider, useWalletModal } from '@solana/wallet-adapter-react-ui';\nimport type { WalletName } from '@solana/wallet-adapter-base';\nimport { useSolanaAuth } from '../../hooks/useSolanaAuth';\nimport { registerMobileWallet } from '../../utils/mobileWalletAdapter';\nimport { isAndroidChrome } from '../../utils/walletDetection';\nimport { LoadingSpinner } from '../shared/LoadingSpinner';\n\n// Auto-register Mobile Wallet Adapter on Android Chrome only.\n// MWA uses Android Intents which only work in Chrome (not Brave/Firefox/Opera).\n// Fire-and-forget: the WalletProvider picks up MWA via wallet-standard events once it resolves.\nif (isAndroidChrome()) {\n void registerMobileWallet();\n}\n\nexport interface SolanaLoginButtonProps {\n onSuccess?: () => void;\n onError?: (error: Error) => void;\n className?: string;\n variant?: 'default' | 'outline';\n size?: 'sm' | 'md' | 'lg';\n disabled?: boolean;\n /**\n * Hide the button if no Solana wallets are detected.\n * When true (default), button renders nothing if no wallets are installed.\n * When false, button always renders (useful for showing \"install wallet\" prompts).\n * @default true\n */\n hideIfNoWallet?: boolean;\n /** Called when the button's loading state changes (connecting, signing, etc.). */\n onLoadingChange?: (loading: boolean) => void;\n /**\n * Solana wallet adapter context. Pass this from @solana/wallet-adapter-react's useWallet().\n * When provided, the component assumes a WalletProvider exists in the React tree and\n * uses the consumer's wallet context for wallet discovery and connection.\n * When omitted, the component provides its own WalletProvider with wallet-standard discovery.\n */\n walletContext?: {\n publicKey: { toBase58: () => string } | null;\n signMessage: ((message: Uint8Array) => Promise<Uint8Array>) | null;\n connected: boolean;\n connecting: boolean;\n connect: () => Promise<void>;\n wallet: { adapter: { name: string } } | null;\n select: (walletName: string) => void;\n wallets: Array<{\n adapter: {\n name: string;\n icon: string;\n readyState: string;\n };\n }>;\n };\n}\n\n/** Stable empty array to avoid re-renders in self-contained WalletProvider. */\nconst EMPTY_ADAPTERS: [] = [];\n\n/**\n * Solana wallet login button with one-click authentication.\n *\n * Uses the standard wallet adapter modal for wallet selection, which provides\n * real brand icons and discovers all wallet-standard-compliant wallets.\n *\n * When `walletContext` is provided, assumes a WalletProvider exists in the tree.\n * Otherwise, wraps itself with WalletProvider for self-contained operation.\n */\nexport function SolanaLoginButton(props: SolanaLoginButtonProps) {\n if (props.walletContext) {\n // Consumer has their own WalletProvider; just add modal capability\n return (\n <WalletModalProvider>\n <SolanaLoginInner {...props} />\n </WalletModalProvider>\n );\n }\n\n // Self-contained: provide wallet-standard discovery + modal\n return (\n <WalletProvider wallets={EMPTY_ADAPTERS} localStorageKey=\"cedros-walletName\">\n <WalletModalProvider>\n <SolanaLoginInner {...props} />\n </WalletModalProvider>\n </WalletProvider>\n );\n}\n\nfunction SolanaLoginInner({\n onSuccess,\n onError,\n className = '',\n variant = 'default',\n size = 'md',\n disabled = false,\n hideIfNoWallet = true,\n onLoadingChange,\n walletContext,\n}: SolanaLoginButtonProps) {\n const { requestChallenge, signIn, isLoading: isAuthLoading } = useSolanaAuth();\n const adapterWallet = useWallet();\n const { visible: modalVisible, setVisible: setModalVisible } = useWalletModal();\n const [pendingLogin, setPendingLogin] = useState(false);\n const [triggerConnect, setTriggerConnect] = useState(false);\n const isProcessingRef = useRef(false);\n const modalWasOpen = useRef(false);\n const signRejectedRef = useRef(false);\n\n // Use walletContext if provided, otherwise use adapter's useWallet()\n const connected = walletContext?.connected ?? adapterWallet.connected;\n const connecting = walletContext?.connecting ?? adapterWallet.connecting;\n const publicKey = walletContext?.publicKey ?? adapterWallet.publicKey;\n const signMessage = walletContext?.signMessage ?? adapterWallet.signMessage;\n const wallet = walletContext?.wallet ?? adapterWallet.wallet;\n const wallets = walletContext?.wallets ?? adapterWallet.wallets;\n const select = walletContext\n ? walletContext.select\n : (name: string) => adapterWallet.select(name as WalletName);\n const connect = walletContext?.connect ?? adapterWallet.connect;\n\n // Get installed/ready wallets\n const installedWallets = wallets.filter(\n (w) => w.adapter.readyState === 'Installed' || w.adapter.readyState === 'Loadable'\n );\n\n // Execute the sign-in flow (challenge → sign → verify)\n const executeSignIn = useCallback(async () => {\n if (isProcessingRef.current) return;\n if (!publicKey || !signMessage) {\n onError?.(new Error('Wallet not ready'));\n return;\n }\n\n isProcessingRef.current = true;\n try {\n const pubKeyString = publicKey.toBase58();\n\n const challenge = await requestChallenge(pubKeyString);\n\n const messageBytes = new TextEncoder().encode(challenge.message);\n const signatureBytes = await signMessage(messageBytes);\n\n if (!(signatureBytes instanceof Uint8Array) || signatureBytes.length === 0) {\n throw new Error('Wallet returned invalid signature');\n }\n\n let signature: string;\n try {\n signature = btoa(String.fromCharCode(...signatureBytes));\n } catch {\n throw new Error('Failed to encode signature');\n }\n\n await signIn(pubKeyString, signature, challenge.message);\n signRejectedRef.current = false;\n onSuccess?.();\n } catch (err) {\n const error = err instanceof Error ? err : new Error(String(err));\n signRejectedRef.current = true;\n onError?.(error);\n } finally {\n isProcessingRef.current = false;\n setPendingLogin(false);\n }\n }, [publicKey, signMessage, requestChallenge, signIn, onSuccess, onError]);\n\n // Auto-connect when wallet is selected and triggerConnect is set\n useEffect(() => {\n if (triggerConnect && wallet && !connected && !connecting) {\n setTriggerConnect(false);\n connect().catch((err) => {\n onError?.(err instanceof Error ? err : new Error(String(err)));\n setPendingLogin(false);\n });\n }\n }, [triggerConnect, wallet, connected, connecting, connect, onError]);\n\n // Auto-execute sign-in when connected with pending login\n useEffect(() => {\n if (pendingLogin && connected && publicKey && signMessage && !isProcessingRef.current) {\n executeSignIn().catch(() => {\n /* Errors already passed to onError callback inside executeSignIn */\n });\n }\n }, [pendingLogin, connected, publicKey, signMessage, executeSignIn]);\n\n // When modal closes: connect if a wallet was selected, else reset.\n // Wallet is always deselected before opening, so any non-null wallet = user chose one.\n useEffect(() => {\n if (modalVisible) {\n modalWasOpen.current = true;\n } else if (modalWasOpen.current) {\n modalWasOpen.current = false;\n if (pendingLogin && !connected && wallet && !connecting) {\n setTriggerConnect(true);\n } else if (pendingLogin && !connected) {\n setPendingLogin(false);\n }\n }\n }, [modalVisible, pendingLogin, connected, wallet, connecting]);\n\n // Hide button if no wallets detected\n if (hideIfNoWallet && installedWallets.length === 0) {\n return null;\n }\n\n const handleClick = async () => {\n if (disabled || isAuthLoading || connecting) return;\n\n if (connected && publicKey && signMessage && !signRejectedRef.current) {\n // Already connected, previous attempt wasn't rejected — sign immediately\n setPendingLogin(true);\n await executeSignIn();\n } else if (installedWallets.length === 1 && !wallet) {\n // Single installed wallet, nothing remembered — auto-select + connect\n select(installedWallets[0].adapter.name);\n setPendingLogin(true);\n setTriggerConnect(true);\n } else {\n // Show wallet picker — deselect any remembered wallet first so that\n // every selection in the modal registers as \"new\" and dismissing\n // leaves wallet as null (no accidental auto-connect).\n signRejectedRef.current = false;\n if (wallet) {\n adapterWallet.select(null as unknown as WalletName);\n }\n setModalVisible(true);\n setPendingLogin(true);\n }\n };\n\n const sizeClasses = {\n sm: 'cedros-button-sm',\n md: 'cedros-button-md',\n lg: 'cedros-button-lg',\n };\n\n const variantClasses = {\n default: 'cedros-button-social',\n outline: 'cedros-button-social-outline',\n };\n\n const isLoading = isAuthLoading || connecting || (pendingLogin && !connected);\n\n // Notify parent of loading state changes\n useEffect(() => {\n onLoadingChange?.(isLoading);\n }, [isLoading, onLoadingChange]);\n\n return (\n <button\n type=\"button\"\n className={`cedros-button ${variantClasses[variant]} ${sizeClasses[size]} ${className}`}\n onClick={handleClick}\n disabled={disabled || isLoading}\n aria-label=\"Continue with Solana\"\n >\n {isLoading ? (\n <LoadingSpinner size=\"sm\" />\n ) : (\n <svg\n className=\"cedros-button-icon\"\n width=\"18\"\n height=\"18\"\n viewBox=\"0 0 128 128\"\n fill=\"currentColor\"\n aria-hidden=\"true\"\n >\n <path d=\"M25.38 96.04a4.35 4.35 0 0 1 3.07-1.27h91.68c1.93 0 2.9 2.34 1.54 3.7l-17.71 17.72a4.35 4.35 0 0 1-3.07 1.27H9.21c-1.93 0-2.9-2.34-1.54-3.7l17.71-17.72z\" />\n <path d=\"M25.38 11.81a4.47 4.47 0 0 1 3.07-1.27h91.68c1.93 0 2.9 2.34 1.54 3.7L103.96 31.96a4.35 4.35 0 0 1-3.07 1.27H9.21c-1.93 0-2.9-2.34-1.54-3.7L25.38 11.81z\" />\n <path d=\"M102.62 53.76a4.35 4.35 0 0 0-3.07-1.27H7.87c-1.93 0-2.9 2.34-1.54 3.7l17.71 17.72a4.35 4.35 0 0 0 3.07 1.27h91.68c1.93 0 2.9-2.34 1.54-3.7L102.62 53.76z\" />\n </svg>\n )}\n <span>Continue with Solana</span>\n </button>\n );\n}\n"],"names":["useSolanaAuth","config","_internal","useCedrosLogin","isLoading","setIsLoading","useState","error","setError","apiClient","useMemo","ApiClient","requestChallenge","useCallback","publicKey","validateSolanaPublicKey","authError","err","handleApiError","signIn","signature","message","data","clearError","registerMobileWallet","mwa","chains","WALLET_PROVIDERS","isValidSolanaProvider","provider","wallet","isAndroidChrome","ua","isBrave","detectSolanaWallets","win","walletObj","EMPTY_ADAPTERS","SolanaLoginButton","props","WalletModalProvider","jsx","SolanaLoginInner","WalletProvider","onSuccess","onError","className","variant","size","disabled","hideIfNoWallet","onLoadingChange","walletContext","isAuthLoading","adapterWallet","useWallet","modalVisible","setModalVisible","useWalletModal","pendingLogin","setPendingLogin","triggerConnect","setTriggerConnect","isProcessingRef","useRef","modalWasOpen","signRejectedRef","connected","connecting","signMessage","wallets","select","name","connect","installedWallets","w","executeSignIn","pubKeyString","challenge","messageBytes","signatureBytes","useEffect","handleClick","sizeClasses","variantClasses","jsxs","LoadingSpinner"],"mappings":";;;;;;;AAmCO,SAASA,KAAqC;AACnD,QAAM,EAAE,QAAAC,GAAQ,WAAAC,EAAA,IAAcC,GAAA,GACxB,CAACC,GAAWC,CAAY,IAAIC,EAAS,EAAK,GAC1C,CAACC,GAAOC,CAAQ,IAAIF,EAA2B,IAAI,GAEnDG,IAAYC;AAAA,IAChB,MACE,IAAIC,GAAU;AAAA,MACZ,SAASV,EAAO;AAAA,MAChB,WAAWA,EAAO;AAAA,MAClB,eAAeA,EAAO;AAAA,IAAA,CACvB;AAAA,IACH,CAACA,EAAO,WAAWA,EAAO,gBAAgBA,EAAO,aAAa;AAAA,EAAA,GAG1DW,IAAmBC;AAAA,IACvB,OAAOC,MAAkD;AAEvD,UAAI,CAACC,EAAwBD,CAAS,GAAG;AACvC,cAAME,IAAuB;AAAA,UAC3B,MAAM;AAAA,UACN,SAAS;AAAA,QAAA;AAEX,cAAAR,EAASQ,CAAS,GACZA;AAAA,MACR;AAEA,MAAAX,EAAa,EAAI,GACjBG,EAAS,IAAI;AAEb,UAAI;AAMF,eALa,MAAMC,EAAU;AAAA,UAC3B;AAAA,UACA,EAAE,WAAAK,EAAA;AAAA,UACF,EAAE,aAAa,OAAA;AAAA,QAAO;AAAA,MAG1B,SAASG,GAAK;AACZ,cAAMD,IAAYE,EAAeD,GAAK,wDAAwD;AAC9F,cAAAT,EAASQ,CAAS,GACZA;AAAA,MACR,UAAA;AACE,QAAAX,EAAa,EAAK;AAAA,MACpB;AAAA,IACF;AAAA,IACA,CAACI,CAAS;AAAA,EAAA,GAGNU,IAASN;AAAA,IACb,OAAOC,GAAmBM,GAAmBC,MAA2C;AAEtF,UAAI,CAACN,EAAwBD,CAAS,GAAG;AACvC,cAAME,IAAuB;AAAA,UAC3B,MAAM;AAAA,UACN,SAAS;AAAA,QAAA;AAEX,cAAAR,EAASQ,CAAS,GACZA;AAAA,MACR;AAEA,MAAAX,EAAa,EAAI,GACjBG,EAAS,IAAI;AAEb,UAAI;AACF,cAAMc,IAAO,MAAMb,EAAU,KAAmB,WAAW;AAAA,UACzD,WAAAK;AAAA,UACA,WAAAM;AAAA,UACA,SAAAC;AAAA,UACA,UAAUnB,GAAW,kBAAA,KAAuB;AAAA,QAAA,CAC7C;AACD,eAAAD,EAAO,WAAW,iBAAiBqB,EAAK,MAAM,QAAQ,GACtDpB,GAAW,mBAAmBoB,EAAK,MAAMA,EAAK,MAAM,GAC7CA;AAAA,MACT,SAASL,GAAK;AACZ,cAAMD,IAAYE,EAAeD,GAAK,uDAAuD;AAC7F,cAAAT,EAASQ,CAAS,GACZA;AAAA,MACR,UAAA;AACE,QAAAX,EAAa,EAAK;AAAA,MACpB;AAAA,IACF;AAAA,IACA,CAACI,GAAWR,EAAO,WAAWC,CAAS;AAAA,EAAA,GAGnCqB,IAAaV,EAAY,MAAML,EAAS,IAAI,GAAG,CAAA,CAAE;AAEvD,SAAO;AAAA,IACL,kBAAAI;AAAA,IACA,QAAAO;AAAA,IACA,WAAAf;AAAA,IACA,OAAAG;AAAA,IACA,YAAAgB;AAAA,EAAA;AAEJ;ACzEA,eAAsBC,GAAqBvB,GAA+C;AACxF,MAAI,OAAO,SAAW;AACpB,WAAO;AAGT,MAAI;AAIF,UAAMwB,IAAM,MAAM,OAAO,uCAAuC,GAE1DC,IAASzB,GAAQ,UAAU,CAAC,gBAAgB;AAElD,WAAAwB,EAAI,YAAY;AAAA,MACd,aAAa;AAAA,QACX,MAAMxB,GAAQ;AAAA,QACd,KAAKA,GAAQ;AAAA,QACb,MAAMA,GAAQ;AAAA,MAAA;AAAA,MAEhB,QAAAyB;AAAA,MACA,oBAAoBD,EAAI,gCAAA;AAAA,MACxB,eAAeA,EAAI,2BAAA;AAAA,MACnB,kBAAkBA,EAAI,mCAAA;AAAA,IAAmC,CAC1D,GACM;AAAA,EACT,QAAQ;AAEN,WAAO;AAAA,EACT;AACF;ACxDO,MAAME,KAAyC;AAAA,EACpD;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMO,SAASC,EAAsBC,GAA4B;AAChE,MAAI,CAACA,KAAY,OAAOA,KAAa,SAAU,QAAO;AACtD,QAAMC,IAASD;AAGf,SACE,OAAOC,EAAO,WAAY,cAC1B,OAAOA,EAAO,eAAgB,cAC9B,OAAOA,EAAO,mBAAoB,cAClC,iBAAiBA;AAErB;AAOO,SAASC,IAA2B;AACzC,MAAI,OAAO,YAAc,IAAa,QAAO;AAC7C,QAAMC,IAAK,UAAU,WACfC,IAAU,WAAW;AAC3B,SAAO,WAAW,KAAKD,CAAE,KAAK,cAAc,KAAKA,CAAE,KAAK,CAACC;AAC3D;AAeO,SAASC,KAA+B;AAC7C,MAAI,OAAO,SAAW;AACpB,WAAO;AAGT,QAAMC,IAAM;AAIZ,aAAWN,KAAYF,IAAkB;AACvC,UAAMS,IAAYD,EAAIN,CAAQ;AAC9B,QACEO,KACA,OAAOA,KAAc,YACrB,YAAYA,KACZR,EAAsBQ,EAAU,MAAM;AAEtC,aAAO;AAAA,EAEX;AAWA,SAPI,GAAAR,EAAsBO,EAAI,MAAM,KAOhCJ;AAKN;AC5GIA,OACGP,GAAA;AA4CP,MAAMa,KAAqB,CAAA;AAWpB,SAASC,GAAkBC,GAA+B;AAC/D,SAAIA,EAAM,kCAGLC,GAAA,EACC,UAAA,gBAAAC,EAACC,GAAA,EAAkB,GAAGH,GAAO,GAC/B,IAMF,gBAAAE,EAACE,IAAA,EAAe,SAASN,IAAgB,iBAAgB,qBACvD,UAAA,gBAAAI,EAACD,GAAA,EACC,UAAA,gBAAAC,EAACC,GAAA,EAAkB,GAAGH,EAAA,CAAO,GAC/B,GACF;AAEJ;AAEA,SAASG,EAAiB;AAAA,EACxB,WAAAE;AAAA,EACA,SAAAC;AAAA,EACA,WAAAC,IAAY;AAAA,EACZ,SAAAC,IAAU;AAAA,EACV,MAAAC,IAAO;AAAA,EACP,UAAAC,IAAW;AAAA,EACX,gBAAAC,IAAiB;AAAA,EACjB,iBAAAC;AAAA,EACA,eAAAC;AACF,GAA2B;AACzB,QAAM,EAAE,kBAAAxC,GAAkB,QAAAO,GAAQ,WAAWkC,EAAA,IAAkBrD,GAAA,GACzDsD,IAAgBC,GAAA,GAChB,EAAE,SAASC,GAAc,YAAYC,EAAA,IAAoBC,GAAA,GACzD,CAACC,GAAcC,CAAe,IAAItD,EAAS,EAAK,GAChD,CAACuD,GAAgBC,CAAiB,IAAIxD,EAAS,EAAK,GACpDyD,IAAkBC,EAAO,EAAK,GAC9BC,IAAeD,EAAO,EAAK,GAC3BE,IAAkBF,EAAO,EAAK,GAG9BG,IAAYf,GAAe,aAAaE,EAAc,WACtDc,IAAahB,GAAe,cAAcE,EAAc,YACxDxC,IAAYsC,GAAe,aAAaE,EAAc,WACtDe,IAAcjB,GAAe,eAAeE,EAAc,aAC1DxB,IAASsB,GAAe,UAAUE,EAAc,QAChDgB,IAAUlB,GAAe,WAAWE,EAAc,SAClDiB,IAASnB,IACXA,EAAc,SACd,CAACoB,MAAiBlB,EAAc,OAAOkB,CAAkB,GACvDC,IAAUrB,GAAe,WAAWE,EAAc,SAGlDoB,IAAmBJ,EAAQ;AAAA,IAC/B,CAACK,MAAMA,EAAE,QAAQ,eAAe,eAAeA,EAAE,QAAQ,eAAe;AAAA,EAAA,GAIpEC,IAAgB/D,EAAY,YAAY;AAC5C,QAAI,CAAAkD,EAAgB,SACpB;AAAA,UAAI,CAACjD,KAAa,CAACuD,GAAa;AAC9B,QAAAxB,IAAU,IAAI,MAAM,kBAAkB,CAAC;AACvC;AAAA,MACF;AAEA,MAAAkB,EAAgB,UAAU;AAC1B,UAAI;AACF,cAAMc,IAAe/D,EAAU,SAAA,GAEzBgE,IAAY,MAAMlE,EAAiBiE,CAAY,GAE/CE,IAAe,IAAI,YAAA,EAAc,OAAOD,EAAU,OAAO,GACzDE,IAAiB,MAAMX,EAAYU,CAAY;AAErD,YAAI,EAAEC,aAA0B,eAAeA,EAAe,WAAW;AACvE,gBAAM,IAAI,MAAM,mCAAmC;AAGrD,YAAI5D;AACJ,YAAI;AACF,UAAAA,IAAY,KAAK,OAAO,aAAa,GAAG4D,CAAc,CAAC;AAAA,QACzD,QAAQ;AACN,gBAAM,IAAI,MAAM,4BAA4B;AAAA,QAC9C;AAEA,cAAM7D,EAAO0D,GAAczD,GAAW0D,EAAU,OAAO,GACvDZ,EAAgB,UAAU,IAC1BtB,IAAA;AAAA,MACF,SAAS3B,GAAK;AACZ,cAAMV,IAAQU,aAAe,QAAQA,IAAM,IAAI,MAAM,OAAOA,CAAG,CAAC;AAChE,QAAAiD,EAAgB,UAAU,IAC1BrB,IAAUtC,CAAK;AAAA,MACjB,UAAA;AACE,QAAAwD,EAAgB,UAAU,IAC1BH,EAAgB,EAAK;AAAA,MACvB;AAAA;AAAA,EACF,GAAG,CAAC9C,GAAWuD,GAAazD,GAAkBO,GAAQyB,GAAWC,CAAO,CAAC;AAsCzE,MAnCAoC,EAAU,MAAM;AACd,IAAIpB,KAAkB/B,KAAU,CAACqC,KAAa,CAACC,MAC7CN,EAAkB,EAAK,GACvBW,EAAA,EAAU,MAAM,CAACxD,MAAQ;AACvB,MAAA4B,IAAU5B,aAAe,QAAQA,IAAM,IAAI,MAAM,OAAOA,CAAG,CAAC,CAAC,GAC7D2C,EAAgB,EAAK;AAAA,IACvB,CAAC;AAAA,EAEL,GAAG,CAACC,GAAgB/B,GAAQqC,GAAWC,GAAYK,GAAS5B,CAAO,CAAC,GAGpEoC,EAAU,MAAM;AACd,IAAItB,KAAgBQ,KAAarD,KAAauD,KAAe,CAACN,EAAgB,WAC5Ea,EAAA,EAAgB,MAAM,MAAM;AAAA,IAE5B,CAAC;AAAA,EAEL,GAAG,CAACjB,GAAcQ,GAAWrD,GAAWuD,GAAaO,CAAa,CAAC,GAInEK,EAAU,MAAM;AACd,IAAIzB,IACFS,EAAa,UAAU,KACdA,EAAa,YACtBA,EAAa,UAAU,IACnBN,KAAgB,CAACQ,KAAarC,KAAU,CAACsC,IAC3CN,EAAkB,EAAI,IACbH,KAAgB,CAACQ,KAC1BP,EAAgB,EAAK;AAAA,EAG3B,GAAG,CAACJ,GAAcG,GAAcQ,GAAWrC,GAAQsC,CAAU,CAAC,GAG1DlB,KAAkBwB,EAAiB,WAAW;AAChD,WAAO;AAGT,QAAMQ,IAAc,YAAY;AAC9B,IAAIjC,KAAYI,KAAiBe,MAE7BD,KAAarD,KAAauD,KAAe,CAACH,EAAgB,WAE5DN,EAAgB,EAAI,GACpB,MAAMgB,EAAA,KACGF,EAAiB,WAAW,KAAK,CAAC5C,KAE3CyC,EAAOG,EAAiB,CAAC,EAAE,QAAQ,IAAI,GACvCd,EAAgB,EAAI,GACpBE,EAAkB,EAAI,MAKtBI,EAAgB,UAAU,IACtBpC,KACFwB,EAAc,OAAO,IAA6B,GAEpDG,EAAgB,EAAI,GACpBG,EAAgB,EAAI;AAAA,EAExB,GAEMuB,IAAc;AAAA,IAClB,IAAI;AAAA,IACJ,IAAI;AAAA,IACJ,IAAI;AAAA,EAAA,GAGAC,IAAiB;AAAA,IACrB,SAAS;AAAA,IACT,SAAS;AAAA,EAAA,GAGLhF,IAAYiD,KAAiBe,KAAeT,KAAgB,CAACQ;AAGnE,SAAAc,EAAU,MAAM;AACd,IAAA9B,IAAkB/C,CAAS;AAAA,EAC7B,GAAG,CAACA,GAAW+C,CAAe,CAAC,GAG7B,gBAAAkC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,WAAW,iBAAiBD,EAAerC,CAAO,CAAC,IAAIoC,EAAYnC,CAAI,CAAC,IAAIF,CAAS;AAAA,MACrF,SAASoC;AAAA,MACT,UAAUjC,KAAY7C;AAAA,MACtB,cAAW;AAAA,MAEV,UAAA;AAAA,QAAAA,IACC,gBAAAqC,EAAC6C,IAAA,EAAe,MAAK,KAAA,CAAK,IAE1B,gBAAAD;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,WAAU;AAAA,YACV,OAAM;AAAA,YACN,QAAO;AAAA,YACP,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,eAAY;AAAA,YAEZ,UAAA;AAAA,cAAA,gBAAA5C,EAAC,QAAA,EAAK,GAAE,2JAAA,CAA2J;AAAA,cACnK,gBAAAA,EAAC,QAAA,EAAK,GAAE,2JAAA,CAA2J;AAAA,cACnK,gBAAAA,EAAC,QAAA,EAAK,GAAE,4JAAA,CAA4J;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA;AAAA,QAGxK,gBAAAA,EAAC,UAAK,UAAA,uBAAA,CAAoB;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGhC;"}
@@ -1 +0,0 @@
1
- "use strict";const n=["https:"],e=["javascript:","data:","vbscript:","file:"];function s(o){if(!o||typeof o!="string")return;const t=o.trim();if(!t)return;const i=t.toLowerCase();for(const r of e)if(i.startsWith(r))return;try{const r=new URL(t);return n.includes(r.protocol)?t:void 0}catch{return}}function c(o){if(!o||typeof o!="string")return;const t=o.trim();if(!t)return;const i=t.toLowerCase();for(const r of e)if(i.startsWith(r))return;try{const r=new URL(t);return r.protocol!=="https:"&&r.protocol!=="http:"?void 0:t}catch{return}}exports.sanitizeExternalUrl=c;exports.sanitizeImageUrl=s;
@@ -1 +0,0 @@
1
- {"version":3,"file":"sanitization-Bo_tn-L2.cjs","sources":["../src/utils/sanitization.ts"],"sourcesContent":["/**\n * Input sanitization utilities for security\n */\n\n/**\n * Allowed image URL protocols\n */\nconst SAFE_PROTOCOLS = ['https:'];\n\n/**\n * Dangerous protocols that should never be allowed\n */\nconst DANGEROUS_PROTOCOLS = ['javascript:', 'data:', 'vbscript:', 'file:'];\n\n/**\n * Sanitizes an image URL to prevent XSS and other attacks.\n *\n * ## Security Properties\n *\n * - Only allows HTTPS URLs (prevents protocol-based attacks)\n * - Blocks javascript:, data:, vbscript:, file: protocols\n * - Returns undefined for invalid URLs\n *\n * ## Limitations (S-20/SEC-08)\n *\n * This function validates the URL protocol but does NOT validate the domain.\n * Any HTTPS URL will pass validation, including URLs from untrusted domains.\n * This is intentional - domain allowlisting is application-specific and should\n * be implemented at the consumer level (see example below).\n *\n * If your application requires domain validation (e.g., only allowing images\n * from trusted CDNs), implement additional validation:\n *\n * @example Domain allowlisting (application-level)\n * ```ts\n * const ALLOWED_DOMAINS = ['cdn.example.com', 'images.trusted.org'];\n *\n * function isAllowedImageUrl(url: string): boolean {\n * const sanitized = sanitizeImageUrl(url);\n * if (!sanitized) return false;\n *\n * try {\n * const hostname = new URL(sanitized).hostname;\n * return ALLOWED_DOMAINS.some(d => hostname === d || hostname.endsWith('.' + d));\n * } catch {\n * return false;\n * }\n * }\n * ```\n *\n * @param url - The URL to sanitize\n * @returns The sanitized URL or undefined if invalid\n *\n * @example Basic usage\n * ```ts\n * sanitizeImageUrl('https://example.com/avatar.png') // 'https://example.com/avatar.png'\n * sanitizeImageUrl('javascript:alert(1)') // undefined\n * sanitizeImageUrl('data:image/svg+xml,...') // undefined\n * ```\n */\nexport function sanitizeImageUrl(url: string | undefined | null): string | undefined {\n if (!url || typeof url !== 'string') {\n return undefined;\n }\n\n // Trim whitespace\n const trimmedUrl = url.trim();\n if (!trimmedUrl) {\n return undefined;\n }\n\n // Check for dangerous protocols (case-insensitive)\n const lowerUrl = trimmedUrl.toLowerCase();\n for (const protocol of DANGEROUS_PROTOCOLS) {\n if (lowerUrl.startsWith(protocol)) {\n return undefined;\n }\n }\n\n // Try to parse as URL\n try {\n const parsed = new URL(trimmedUrl);\n\n // Only allow safe protocols\n if (!SAFE_PROTOCOLS.includes(parsed.protocol)) {\n return undefined;\n }\n\n // Return the original URL (preserves case)\n return trimmedUrl;\n } catch {\n // Invalid URL\n return undefined;\n }\n}\n\n/**\n * Sanitizes an external link URL for use in href attributes.\n *\n * Security goals:\n * - Block dangerous protocols (javascript:, data:, vbscript:, file:)\n * - Only allow http/https absolute URLs\n */\nexport function sanitizeExternalUrl(url: string | undefined | null): string | undefined {\n if (!url || typeof url !== 'string') {\n return undefined;\n }\n\n const trimmedUrl = url.trim();\n if (!trimmedUrl) {\n return undefined;\n }\n\n const lowerUrl = trimmedUrl.toLowerCase();\n for (const protocol of DANGEROUS_PROTOCOLS) {\n if (lowerUrl.startsWith(protocol)) {\n return undefined;\n }\n }\n\n try {\n const parsed = new URL(trimmedUrl);\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n return undefined;\n }\n return trimmedUrl;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Sanitizes user-provided text to prevent XSS in text content.\n * Escapes HTML special characters.\n *\n * @param text - The text to sanitize\n * @returns The sanitized text\n */\nexport function sanitizeText(text: string | undefined | null): string {\n if (!text || typeof text !== 'string') {\n return '';\n }\n\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#x27;');\n}\n"],"names":["SAFE_PROTOCOLS","DANGEROUS_PROTOCOLS","sanitizeImageUrl","url","trimmedUrl","lowerUrl","protocol","parsed","sanitizeExternalUrl"],"mappings":"aAOA,MAAMA,EAAiB,CAAC,QAAQ,EAK1BC,EAAsB,CAAC,cAAe,QAAS,YAAa,OAAO,EAgDlE,SAASC,EAAiBC,EAAoD,CACnF,GAAI,CAACA,GAAO,OAAOA,GAAQ,SACzB,OAIF,MAAMC,EAAaD,EAAI,KAAA,EACvB,GAAI,CAACC,EACH,OAIF,MAAMC,EAAWD,EAAW,YAAA,EAC5B,UAAWE,KAAYL,EACrB,GAAII,EAAS,WAAWC,CAAQ,EAC9B,OAKJ,GAAI,CACF,MAAMC,EAAS,IAAI,IAAIH,CAAU,EAGjC,OAAKJ,EAAe,SAASO,EAAO,QAAQ,EAKrCH,EAJL,MAKJ,MAAQ,CAEN,MACF,CACF,CASO,SAASI,EAAoBL,EAAoD,CACtF,GAAI,CAACA,GAAO,OAAOA,GAAQ,SACzB,OAGF,MAAMC,EAAaD,EAAI,KAAA,EACvB,GAAI,CAACC,EACH,OAGF,MAAMC,EAAWD,EAAW,YAAA,EAC5B,UAAWE,KAAYL,EACrB,GAAII,EAAS,WAAWC,CAAQ,EAC9B,OAIJ,GAAI,CACF,MAAMC,EAAS,IAAI,IAAIH,CAAU,EACjC,OAAIG,EAAO,WAAa,UAAYA,EAAO,WAAa,QACtD,OAEKH,CACT,MAAQ,CACN,MACF,CACF"}
@@ -1,39 +0,0 @@
1
- const e = ["https:"], n = ["javascript:", "data:", "vbscript:", "file:"];
2
- function s(o) {
3
- if (!o || typeof o != "string")
4
- return;
5
- const t = o.trim();
6
- if (!t)
7
- return;
8
- const i = t.toLowerCase();
9
- for (const r of n)
10
- if (i.startsWith(r))
11
- return;
12
- try {
13
- const r = new URL(t);
14
- return e.includes(r.protocol) ? t : void 0;
15
- } catch {
16
- return;
17
- }
18
- }
19
- function c(o) {
20
- if (!o || typeof o != "string")
21
- return;
22
- const t = o.trim();
23
- if (!t)
24
- return;
25
- const i = t.toLowerCase();
26
- for (const r of n)
27
- if (i.startsWith(r))
28
- return;
29
- try {
30
- const r = new URL(t);
31
- return r.protocol !== "https:" && r.protocol !== "http:" ? void 0 : t;
32
- } catch {
33
- return;
34
- }
35
- }
36
- export {
37
- s as a,
38
- c as s
39
- };
@@ -1 +0,0 @@
1
- {"version":3,"file":"sanitization-CQ-H1MSg.js","sources":["../src/utils/sanitization.ts"],"sourcesContent":["/**\n * Input sanitization utilities for security\n */\n\n/**\n * Allowed image URL protocols\n */\nconst SAFE_PROTOCOLS = ['https:'];\n\n/**\n * Dangerous protocols that should never be allowed\n */\nconst DANGEROUS_PROTOCOLS = ['javascript:', 'data:', 'vbscript:', 'file:'];\n\n/**\n * Sanitizes an image URL to prevent XSS and other attacks.\n *\n * ## Security Properties\n *\n * - Only allows HTTPS URLs (prevents protocol-based attacks)\n * - Blocks javascript:, data:, vbscript:, file: protocols\n * - Returns undefined for invalid URLs\n *\n * ## Limitations (S-20/SEC-08)\n *\n * This function validates the URL protocol but does NOT validate the domain.\n * Any HTTPS URL will pass validation, including URLs from untrusted domains.\n * This is intentional - domain allowlisting is application-specific and should\n * be implemented at the consumer level (see example below).\n *\n * If your application requires domain validation (e.g., only allowing images\n * from trusted CDNs), implement additional validation:\n *\n * @example Domain allowlisting (application-level)\n * ```ts\n * const ALLOWED_DOMAINS = ['cdn.example.com', 'images.trusted.org'];\n *\n * function isAllowedImageUrl(url: string): boolean {\n * const sanitized = sanitizeImageUrl(url);\n * if (!sanitized) return false;\n *\n * try {\n * const hostname = new URL(sanitized).hostname;\n * return ALLOWED_DOMAINS.some(d => hostname === d || hostname.endsWith('.' + d));\n * } catch {\n * return false;\n * }\n * }\n * ```\n *\n * @param url - The URL to sanitize\n * @returns The sanitized URL or undefined if invalid\n *\n * @example Basic usage\n * ```ts\n * sanitizeImageUrl('https://example.com/avatar.png') // 'https://example.com/avatar.png'\n * sanitizeImageUrl('javascript:alert(1)') // undefined\n * sanitizeImageUrl('data:image/svg+xml,...') // undefined\n * ```\n */\nexport function sanitizeImageUrl(url: string | undefined | null): string | undefined {\n if (!url || typeof url !== 'string') {\n return undefined;\n }\n\n // Trim whitespace\n const trimmedUrl = url.trim();\n if (!trimmedUrl) {\n return undefined;\n }\n\n // Check for dangerous protocols (case-insensitive)\n const lowerUrl = trimmedUrl.toLowerCase();\n for (const protocol of DANGEROUS_PROTOCOLS) {\n if (lowerUrl.startsWith(protocol)) {\n return undefined;\n }\n }\n\n // Try to parse as URL\n try {\n const parsed = new URL(trimmedUrl);\n\n // Only allow safe protocols\n if (!SAFE_PROTOCOLS.includes(parsed.protocol)) {\n return undefined;\n }\n\n // Return the original URL (preserves case)\n return trimmedUrl;\n } catch {\n // Invalid URL\n return undefined;\n }\n}\n\n/**\n * Sanitizes an external link URL for use in href attributes.\n *\n * Security goals:\n * - Block dangerous protocols (javascript:, data:, vbscript:, file:)\n * - Only allow http/https absolute URLs\n */\nexport function sanitizeExternalUrl(url: string | undefined | null): string | undefined {\n if (!url || typeof url !== 'string') {\n return undefined;\n }\n\n const trimmedUrl = url.trim();\n if (!trimmedUrl) {\n return undefined;\n }\n\n const lowerUrl = trimmedUrl.toLowerCase();\n for (const protocol of DANGEROUS_PROTOCOLS) {\n if (lowerUrl.startsWith(protocol)) {\n return undefined;\n }\n }\n\n try {\n const parsed = new URL(trimmedUrl);\n if (parsed.protocol !== 'https:' && parsed.protocol !== 'http:') {\n return undefined;\n }\n return trimmedUrl;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Sanitizes user-provided text to prevent XSS in text content.\n * Escapes HTML special characters.\n *\n * @param text - The text to sanitize\n * @returns The sanitized text\n */\nexport function sanitizeText(text: string | undefined | null): string {\n if (!text || typeof text !== 'string') {\n return '';\n }\n\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#x27;');\n}\n"],"names":["SAFE_PROTOCOLS","DANGEROUS_PROTOCOLS","sanitizeImageUrl","url","trimmedUrl","lowerUrl","protocol","parsed","sanitizeExternalUrl"],"mappings":"AAOA,MAAMA,IAAiB,CAAC,QAAQ,GAK1BC,IAAsB,CAAC,eAAe,SAAS,aAAa,OAAO;AAgDlE,SAASC,EAAiBC,GAAoD;AACnF,MAAI,CAACA,KAAO,OAAOA,KAAQ;AACzB;AAIF,QAAMC,IAAaD,EAAI,KAAA;AACvB,MAAI,CAACC;AACH;AAIF,QAAMC,IAAWD,EAAW,YAAA;AAC5B,aAAWE,KAAYL;AACrB,QAAII,EAAS,WAAWC,CAAQ;AAC9B;AAKJ,MAAI;AACF,UAAMC,IAAS,IAAI,IAAIH,CAAU;AAGjC,WAAKJ,EAAe,SAASO,EAAO,QAAQ,IAKrCH,IAJL;AAAA,EAKJ,QAAQ;AAEN;AAAA,EACF;AACF;AASO,SAASI,EAAoBL,GAAoD;AACtF,MAAI,CAACA,KAAO,OAAOA,KAAQ;AACzB;AAGF,QAAMC,IAAaD,EAAI,KAAA;AACvB,MAAI,CAACC;AACH;AAGF,QAAMC,IAAWD,EAAW,YAAA;AAC5B,aAAWE,KAAYL;AACrB,QAAII,EAAS,WAAWC,CAAQ;AAC9B;AAIJ,MAAI;AACF,UAAMC,IAAS,IAAI,IAAIH,CAAU;AACjC,WAAIG,EAAO,aAAa,YAAYA,EAAO,aAAa,UACtD,SAEKH;AAAA,EACT,QAAQ;AACN;AAAA,EACF;AACF;"}
@@ -1 +0,0 @@
1
- "use strict";const X=require("react/jsx-runtime"),o=require("react"),ee=require("./LoadingSpinner-d6sSxgQN.cjs"),F=require("./useCedrosLogin-DtJorrE7.cjs");let W=0;function Ke({theme:e,themeOverrides:t}){o.useEffect(()=>{if(typeof document>"u"||typeof window>"u")return;const A=document.documentElement;let i=!1;e==="dark"?i=!0:e==="light"?i=!1:i=window.matchMedia("(prefers-color-scheme: dark)").matches;let r=!1;i?(W++,r=!0,A.classList.add("cedros-dark")):W===0&&A.classList.remove("cedros-dark");const n=new Map;return t&&Object.entries(t).forEach(([s,g])=>{if(g){const h=A.style.getPropertyValue(s);n.set(s,h),A.style.setProperty(s,g)}}),()=>{r&&(W--,W===0&&A.classList.remove("cedros-dark")),n.forEach((s,g)=>{s?A.style.setProperty(g,s):A.style.removeProperty(g)})}},[e,t])}const He={email:!0,google:!0,apple:!0,solana:!0,webauthn:!0,instantLink:!0};function Je(e,t,A){const[i,r]=o.useState(null),[n,s]=o.useState(),[g,h]=o.useState(),[I,p]=o.useState(),[y,B]=o.useState(),[b,U]=o.useState(),[C,d]=o.useState(),[w,m]=o.useState(t),k=o.useRef(!1);return o.useEffect(()=>{if(!t||k.current)return;k.current=!0,new F.ApiClient({baseUrl:e,timeoutMs:A??5e3,retryAttempts:1}).get("/features",{credentials:"omit"}).then(u=>{r({email:u.email,google:u.google,apple:u.apple,solana:u.solana,webauthn:u.webauthn,instantLink:u.instantLink}),s(u.googleClientId),h(u.appleClientId),p(u.usernameEnabled),B(u.walletEnrollEnabled),U(u.showRecoveryEnabled),d(u.socialButtonOrder)}).catch(()=>{r(He)}).finally(()=>{m(!1)})},[t,e,A]),{features:i,googleClientId:n,appleClientId:g,usernameEnabled:I,walletEnrollEnabled:y,showRecoveryEnabled:b,socialButtonOrder:C,isLoading:w}}const Me="cedros_tokens",Ve=6e4;class Pe{storage;requestedStorage;storageKey;tokens=null;expiresAt=0;refreshTimer=null;onRefreshNeeded=null;onSessionExpired=null;onRefreshError=null;isDestroyed=!1;sessionExpiredFired=!1;allowWebStorage;constructor(t="cookie",A=Me,i={}){this.requestedStorage=t,this.storage=t,this.storageKey=A,this.allowWebStorage=i.allowWebStorage??!1,this.warnIfLocalStorage(),!this.allowWebStorage&&(this.requestedStorage==="localStorage"||this.requestedStorage==="sessionStorage")&&(this.storage="memory"),this.loadFromStorage()}warnIfLocalStorage(){if((this.requestedStorage==="localStorage"||this.requestedStorage==="sessionStorage")&&typeof console<"u"){const t=this.allowWebStorage?"":" (web storage disabled by default; set allowWebStorage=true to enable)";console.warn("[cedros-login] SECURITY: Using web storage for token storage. Tokens are vulnerable to XSS attacks."+t+" PRODUCTION RECOMMENDATIONS: (1) Use httpOnly cookie storage instead, (2) If web storage required: implement strict Content-Security-Policy, sanitize all input/output, audit third-party scripts. See https://owasp.org/www-community/attacks/xss/")}}setRefreshCallback(t){this.onRefreshNeeded=t,this.scheduleRefresh()}setSessionExpiredCallback(t){this.onSessionExpired=t}setRefreshErrorCallback(t){this.onRefreshError=t}setTokens(t){this.tokens=t,this.expiresAt=Date.now()+t.expiresIn*1e3,this.sessionExpiredFired=!1,this.saveToStorage(),this.scheduleRefresh()}getAccessToken(){if(this.isDestroyed)return null;const t=this.tokens?.accessToken;return t?Date.now()>=this.expiresAt?(this.clear(),this.fireSessionExpired(),null):t:null}getRefreshToken(){return this.tokens?.refreshToken??null}clear(){this.tokens=null,this.expiresAt=0,this.cancelRefresh(),this.clearStorage()}hasTokens(){return this.tokens!==null&&Date.now()<this.expiresAt}destroy(){this.isDestroyed=!0,this.cancelRefresh(),this.clearStorage(),this.onRefreshNeeded=null,this.onSessionExpired=null,this.onRefreshError=null,this.tokens=null}getTimeUntilExpiry(){return this.tokens?Math.max(0,this.expiresAt-Date.now()):0}fireSessionExpired(){this.sessionExpiredFired||(this.sessionExpiredFired=!0,this.onSessionExpired?.())}scheduleRefresh(){if(this.cancelRefresh(),!this.tokens||!this.onRefreshNeeded)return;const t=this.getTimeUntilExpiry(),A=Math.max(0,t-Ve);if(A<=0){if(this.isDestroyed)return;this.onRefreshNeeded().catch(i=>{if(this.isDestroyed)return;const r=i instanceof Error?i:new Error("Token refresh failed");this.onRefreshError?.(r),this.clear(),this.fireSessionExpired()});return}this.refreshTimer=setTimeout(()=>{this.isDestroyed||this.onRefreshNeeded?.().catch(i=>{if(this.isDestroyed)return;const r=i instanceof Error?i:new Error("Token refresh failed");this.onRefreshError?.(r),this.clear(),this.fireSessionExpired()})},A)}cancelRefresh(){this.refreshTimer&&(clearTimeout(this.refreshTimer),this.refreshTimer=null)}loadFromStorage(){if(this.storage!=="memory"&&!(typeof window>"u")&&!(!this.allowWebStorage&&(this.storage==="localStorage"||this.storage==="sessionStorage")))try{if(this.storage==="localStorage"||this.storage==="sessionStorage"){const t=this.storage==="localStorage"?localStorage:sessionStorage,A=t.getItem(this.storageKey);if(A){const i=JSON.parse(A);this.isValidStoredTokenData(i)?i.expiresAt>Date.now()?(this.tokens=i.tokens,this.expiresAt=i.expiresAt):t.removeItem(this.storageKey):t.removeItem(this.storageKey)}}}catch{if(this.storage==="localStorage"||this.storage==="sessionStorage"){const t=this.storage==="localStorage"?localStorage:sessionStorage;try{t.removeItem(this.storageKey)}catch{}}}}isValidStoredTokenData(t){if(typeof t!="object"||t===null)return!1;const A=t;if(typeof A.expiresAt!="number"||typeof A.tokens!="object"||A.tokens===null)return!1;const i=A.tokens;return!(typeof i.accessToken!="string"||typeof i.refreshToken!="string"||typeof i.expiresIn!="number")}saveToStorage(){if(!(this.storage==="memory"||!this.tokens)&&!(typeof window>"u")&&!(!this.allowWebStorage&&(this.storage==="localStorage"||this.storage==="sessionStorage")))try{if(this.storage==="localStorage"||this.storage==="sessionStorage"){const t=this.storage==="localStorage"?localStorage:sessionStorage,A={tokens:this.tokens,expiresAt:this.expiresAt};t.setItem(this.storageKey,JSON.stringify(A))}}catch{}}clearStorage(){if(this.storage!=="memory"&&!(typeof window>"u")&&!(!this.allowWebStorage&&(this.storage==="localStorage"||this.storage==="sessionStorage")))try{(this.storage==="localStorage"||this.storage==="sessionStorage")&&(this.storage==="localStorage"?localStorage:sessionStorage).removeItem(this.storageKey)}catch{}}}const Ne="cedros_auth_sync";class Ye{channel=null;callback=null;boundHandler=null;constructor(){typeof window<"u"&&"BroadcastChannel"in window&&(this.channel=new BroadcastChannel(Ne),this.boundHandler=this.handleMessage.bind(this),this.channel.addEventListener("message",this.boundHandler))}handleMessage(t){const A=t.data;if(!(!A||typeof A!="object"||typeof A.type!="string")&&["login","logout","refresh"].includes(A.type)){if(A.type==="login"){const i=A;if(typeof i.user!="object"||i.user===null||typeof i.user.id!="string")return}this.callback?.(A)}}setCallback(t){this.callback=t}broadcastLogin(t){this.channel?.postMessage({type:"login",user:t})}broadcastLogout(){this.channel?.postMessage({type:"logout"})}broadcastRefresh(){this.channel?.postMessage({type:"refresh"})}close(){this.channel&&(this.boundHandler&&(this.channel.removeEventListener("message",this.boundHandler),this.boundHandler=null),this.channel.close(),this.channel=null),this.callback=null}}function j(e){if(typeof e!="object"||e===null)return!1;const t=e;if(typeof t.user!="object"||t.user===null)return!1;const A=t.user;return typeof A.id=="string"&&A.id.length>0}function Oe(e){if(typeof e!="object"||e===null)return!1;const t=e;return typeof t.accessToken=="string"&&t.accessToken.length>0&&typeof t.refreshToken=="string"&&t.refreshToken.length>0&&typeof t.expiresIn=="number"&&t.expiresIn>0}function ve({serverUrl:e,session:t,callbacks:A,requestTimeoutMs:i}){const[r,n]=o.useState(null),[s,g]=o.useState("idle"),h=o.useRef(null),I=o.useRef(null),p=o.useRef(A),y=o.useRef(!0),B=o.useRef(null),b=o.useRef(()=>Promise.resolve()),U=o.useRef(()=>{});o.useEffect(()=>{p.current=A},[A]),o.useEffect(()=>(y.current=!0,()=>{y.current=!1}),[]);const C=o.useCallback(f=>{y.current&&n(f)},[]),d=o.useCallback(f=>{y.current&&g(f)},[]),w=o.useMemo(()=>({storage:t?.storage??"cookie",autoRefresh:t?.autoRefresh??!0,syncTabs:t?.syncTabs??!0,persistKey:t?.persistKey,allowWebStorage:t?.allowWebStorage??!1}),[t?.storage,t?.autoRefresh,t?.syncTabs,t?.persistKey,t?.allowWebStorage]);o.useEffect(()=>{const f=new Pe(w.storage,w.persistKey,{allowWebStorage:w.allowWebStorage});return h.current=f,w.autoRefresh&&f.setRefreshCallback(()=>b.current()),f.setSessionExpiredCallback(()=>U.current()),w.syncTabs&&(I.current=new Ye),()=>{f.destroy(),h.current=null,I.current?.close()}},[w.storage,w.syncTabs,w.persistKey,w.allowWebStorage,w.autoRefresh]);const m=o.useCallback(async()=>{if(B.current)return B.current;const f=h.current?.getRefreshToken(),S=!!f,G=F.getCsrfToken(),H={};S&&(H["Content-Type"]="application/json"),G&&(H["X-CSRF-Token"]=G);let K,J;const V=new Promise((M,v)=>{K=M,J=v});B.current=V,(async()=>{const M=new AbortController,v=i??1e4,Ge=window.setTimeout(()=>M.abort(),v);try{const R=await fetch(`${e}/refresh`,{method:"POST",headers:Object.keys(H).length>0?H:void 0,credentials:"include",body:S?JSON.stringify({refreshToken:f}):void 0,signal:M.signal});if(!R.ok)throw new Error("Token refresh failed");const z=await R.json();if(z.tokens){if(!Oe(z.tokens))throw new Error("Invalid token response structure");h.current?.setTokens(z.tokens)}else if(w.storage!=="cookie")throw new Error("Token refresh failed");I.current?.broadcastRefresh(),K()}catch(R){throw J(R),R}finally{window.clearTimeout(Ge)}})().catch(()=>{});try{await V}finally{B.current=null}},[e,w.storage,i]),k=o.useCallback(()=>{if(w.storage==="cookie")return;const f=h.current?.getAccessToken();if(f)return{Authorization:`Bearer ${f}`}},[w.storage]),E=o.useCallback(()=>{h.current?.clear(),C(null),d("unauthenticated"),p.current?.onSessionExpired?.()},[d,C]);b.current=m,U.current=E;const u=o.useCallback(f=>{const S=new AbortController,G=i??1e4,H=window.setTimeout(()=>S.abort(),G),K={},J=k();J&&Object.assign(K,J);const V=F.getCsrfToken();return V&&(K["X-CSRF-Token"]=V),{promise:fetch(f,{credentials:"include",headers:Object.keys(K).length>0?K:void 0,signal:S.signal}),cleanup:()=>window.clearTimeout(H)}},[k,i]),l=o.useCallback(async()=>{const f=u(`${e}/user`);try{const S=await f.promise;if(S.ok){const G=await S.json();if(j(G)){C(G.user),d("authenticated");return}}if(S.status===401&&w.autoRefresh){try{await m()}catch{E();return}const G=u(`${e}/user`);try{const H=await G.promise;if(H.ok){const K=await H.json();if(j(K)){C(K.user),d("authenticated");return}}}finally{G.cleanup()}}C(null),d("unauthenticated")}catch{C(null),d("unauthenticated")}finally{f.cleanup()}},[e,w.autoRefresh,m,u,E,d,C]);o.useEffect(()=>{!I.current||!w.syncTabs||I.current.setCallback(f=>{switch(f.type){case"login":C(f.user),d("authenticated");break;case"logout":C(null),d("unauthenticated"),h.current?.clear();break;case"refresh":l();break;default:console.warn("[Cedros Login] Unhandled tab sync event:",f)}})},[w.syncTabs,l,d,C]),o.useEffect(()=>{const f=new AbortController,S=i??1e4,G=window.setTimeout(()=>f.abort(),S);return(async()=>{d("loading");try{const K=await fetch(`${e}/user`,{credentials:"include",headers:k(),signal:f.signal});if(K.ok){const J=await K.json();if(j(J)){C(J.user),d("authenticated");return}}if(K.status===401&&w.autoRefresh){try{await m()}catch{E();return}const J=await fetch(`${e}/user`,{credentials:"include",headers:k(),signal:f.signal});if(J.ok){const V=await J.json();if(j(V)){C(V.user),d("authenticated");return}}}C(null),d("unauthenticated")}catch{C(null),d("unauthenticated")}})(),()=>{window.clearTimeout(G),f.abort()}},[e,w.autoRefresh,m,k,E,d,C,i]);const a=o.useCallback((f,S)=>{C(f),d("authenticated"),S&&h.current?.setTokens(S),y.current&&I.current?.broadcastLogin(f)},[C,d]),c=o.useCallback(async()=>{const f=F.getCsrfToken(),S=new AbortController,G=i??1e4,H=window.setTimeout(()=>S.abort(),G);try{await fetch(`${e}/logout`,{method:"POST",headers:{...f?{"X-CSRF-Token":f}:{},...k()??{}},credentials:"include",signal:S.signal})}catch{}finally{window.clearTimeout(H),C(null),d("unauthenticated"),h.current?.clear(),I.current?.broadcastLogout(),p.current?.onLogout?.()}},[e,k,C,d,i]),Q=o.useCallback(()=>h.current?.getAccessToken()??null,[]);return{user:r,authState:s,handleLoginSuccess:a,logout:c,refreshUser:l,getAccessToken:Q}}const de={mCost:19456,tCost:2,pCost:1};function xe(e){return e.length===16}function Re(e){if(e.length===16)return!0;if(e.length<18)return!1;const t=e[0];return t===0||t===1||t===128||t===8}function Te(e){return e.length===32}function Le(e){return e.length===12}function Xe(e){return e.length>=16}function We(e){return e.length===32}function Ee(e){if(!xe(e))throw new Error(`Invalid seed length: expected 16, got ${e.length}`);return e}function je(e){if(!Re(e))throw new Error(`Invalid share length: expected >=16, got ${e.length}`);return e}function le(e){if(!Te(e))throw new Error(`Invalid key length: expected 32, got ${e.length}`);return e}function Ze(e){if(!Le(e))throw new Error(`Invalid nonce length: expected 12, got ${e.length}`);return e}function qe(e){if(!Xe(e))throw new Error(`Invalid salt length: expected >=16, got ${e.length}`);return e}function _e(e){if(!We(e))throw new Error(`Invalid PRF salt length: expected 32, got ${e.length}`);return e}function x(e){return new Uint8Array(e)}function _(e){if(typeof crypto>"u"||!crypto.getRandomValues)throw new Error("WebCrypto API not available. Secure random generation requires a modern browser.");const t=new Uint8Array(e);return crypto.getRandomValues(t),t}function $e(){return Ee(_(16))}function ze(){return Ze(_(12))}function et(){return qe(_(16))}function tt(){return _e(_(32))}function ce(e){if(!(!e||e.length===0)){if(typeof globalThis.crypto?.getRandomValues=="function")globalThis.crypto.getRandomValues(e);else for(let t=0;t<e.length;t++)e[t]=t*90&255;e.fill(0)}}function At(...e){for(const t of e)t&&ce(t)}async function it(e){return crypto.subtle.importKey("raw",x(e),{name:"AES-GCM",length:256},!1,["encrypt","decrypt"])}async function rt(e,t,A){const i=A??ze(),r=await it(t),n=await crypto.subtle.encrypt({name:"AES-GCM",iv:x(i)},r,x(e));return{ciphertext:new Uint8Array(n),nonce:i}}async function nt(e,t){const A=await rt(e,t);return{ciphertext:se(A.ciphertext),nonce:se(A.nonce)}}function se(e){const A=[];for(let i=0;i<e.length;i+=32768){const r=e.subarray(i,Math.min(i+32768,e.length));A.push(String.fromCharCode(...r))}return btoa(A.join(""))}function pe(e){let t;try{t=atob(e)}catch{throw new Error("Invalid base64 string: input is malformed or contains invalid characters")}const A=new Uint8Array(t.length);for(let i=0;i<t.length;i++)A[i]=t.charCodeAt(i);return A}async function ot(e,t,A,i=32){const r=await crypto.subtle.importKey("raw",x(e),"HKDF",!1,["deriveBits"]),n=new TextEncoder().encode(A),s=await crypto.subtle.deriveBits({name:"HKDF",hash:"SHA-256",salt:x(t??new Uint8Array(32)),info:x(n)},r,i*8);return new Uint8Array(s)}async function st(e,t){const A=await ot(e,t,"cedros-wallet-share-b-encryption",32);return le(A)}async function It(){try{const e=await crypto.subtle.importKey("raw",new Uint8Array(32),"HKDF",!1,["deriveBits"]);return await crypto.subtle.deriveBits({name:"HKDF",hash:"SHA-256",salt:new Uint8Array(32),info:new Uint8Array(0)},e,256),!0}catch{return!1}}function O(e,t,A,i){function r(n){return n instanceof A?n:new A(function(s){s(n)})}return new(A||(A=Promise))(function(n,s){function g(p){try{I(i.next(p))}catch(y){s(y)}}function h(p){try{I(i.throw(p))}catch(y){s(y)}}function I(p){p.done?n(p.value):r(p.value).then(g,h)}I((i=i.apply(e,[])).next())})}class D{constructor(){this.mutex=Promise.resolve()}lock(){let t=()=>{};return this.mutex=this.mutex.then(()=>new Promise(t)),new Promise(A=>{t=A})}dispatch(t){return O(this,void 0,void 0,function*(){const A=yield this.lock();try{return yield Promise.resolve(t())}finally{A()}})}}var te;function at(){return typeof globalThis<"u"?globalThis:typeof self<"u"?self:typeof window<"u"?window:global}const Ie=at(),Ae=(te=Ie.Buffer)!==null&&te!==void 0?te:null,gt=Ie.TextEncoder?new Ie.TextEncoder:null;function ye(e,t){return(e&15)+(e>>6|e>>3&8)<<4|(t&15)+(t>>6|t>>3&8)}function ke(e,t){const A=t.length>>1;for(let i=0;i<A;i++){const r=i<<1;e[i]=ye(t.charCodeAt(r),t.charCodeAt(r+1))}}function lt(e,t){if(e.length!==t.length*2)return!1;for(let A=0;A<t.length;A++){const i=A<<1;if(t[A]!==ye(e.charCodeAt(i),e.charCodeAt(i+1)))return!1}return!0}const ue=87,fe=48;function ae(e,t,A){let i=0;for(let r=0;r<A;r++){let n=t[r]>>>4;e[i++]=n>9?n+ue:n+fe,n=t[r]&15,e[i++]=n>9?n+ue:n+fe}return String.fromCharCode.apply(null,e)}const Y=Ae!==null?e=>{if(typeof e=="string"){const t=Ae.from(e,"utf8");return new Uint8Array(t.buffer,t.byteOffset,t.length)}if(Ae.isBuffer(e))return new Uint8Array(e.buffer,e.byteOffset,e.length);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Invalid data type!")}:e=>{if(typeof e=="string")return gt.encode(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw new Error("Invalid data type!")},P="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",L=new Uint8Array(256);for(let e=0;e<P.length;e++)L[P.charCodeAt(e)]=e;function we(e,t=!0){const A=e.length,i=A%3,r=[],n=A-i;for(let s=0;s<n;s+=3){const g=(e[s]<<16&16711680)+(e[s+1]<<8&65280)+(e[s+2]&255),h=P.charAt(g>>18&63)+P.charAt(g>>12&63)+P.charAt(g>>6&63)+P.charAt(g&63);r.push(h)}if(i===1){const s=e[A-1],g=P.charAt(s>>2),h=P.charAt(s<<4&63);r.push(`${g}${h}`),t&&r.push("==")}else if(i===2){const s=(e[A-2]<<8)+e[A-1],g=P.charAt(s>>10),h=P.charAt(s>>4&63),I=P.charAt(s<<2&63);r.push(`${g}${h}${I}`),t&&r.push("=")}return r.join("")}function ct(e){let t=Math.floor(e.length*.75);const A=e.length;return e[A-1]==="="&&(t-=1,e[A-2]==="="&&(t-=1)),t}function Ct(e){const t=ct(e),A=e.length,i=new Uint8Array(t);let r=0;for(let n=0;n<A;n+=4){const s=L[e.charCodeAt(n)],g=L[e.charCodeAt(n+1)],h=L[e.charCodeAt(n+2)],I=L[e.charCodeAt(n+3)];i[r]=s<<2|g>>4,r+=1,i[r]=(g&15)<<4|h>>2,r+=1,i[r]=(h&3)<<6|I&63,r+=1}return i}const Z=16*1024,T=4,ht=new D,ie=new Map;function Se(e,t){return O(this,void 0,void 0,function*(){let A=null,i=null,r=!1;if(typeof WebAssembly>"u")throw new Error("WebAssembly is not supported in this environment!");const n=(l,a=0)=>{i.set(l,a)},s=()=>i,g=()=>A.exports,h=l=>{A.exports.Hash_SetMemorySize(l);const a=A.exports.Hash_GetBuffer(),c=A.exports.memory.buffer;i=new Uint8Array(c,a,l)},I=()=>new DataView(A.exports.memory.buffer).getUint32(A.exports.STATE_SIZE,!0),p=ht.dispatch(()=>O(this,void 0,void 0,function*(){if(!ie.has(e.name)){const a=Ct(e.data),c=WebAssembly.compile(a);ie.set(e.name,c)}const l=yield ie.get(e.name);A=yield WebAssembly.instantiate(l,{})})),y=()=>O(this,void 0,void 0,function*(){A||(yield p);const l=A.exports.Hash_GetBuffer(),a=A.exports.memory.buffer;i=new Uint8Array(a,l,Z)}),B=(l=null)=>{r=!0,A.exports.Hash_Init(l)},b=l=>{let a=0;for(;a<l.length;){const c=l.subarray(a,a+Z);a+=c.length,i.set(c),A.exports.Hash_Update(c.length)}},U=l=>{if(!r)throw new Error("update() called before init()");const a=Y(l);b(a)},C=new Uint8Array(t*2),d=(l,a=null)=>{if(!r)throw new Error("digest() called before init()");return r=!1,A.exports.Hash_Final(a),l==="binary"?i.slice(0,t):ae(C,i,t)},w=()=>{if(!r)throw new Error("save() can only be called after init() and before digest()");const l=A.exports.Hash_GetState(),a=I(),c=A.exports.memory.buffer,Q=new Uint8Array(c,l,a),f=new Uint8Array(T+a);return ke(f,e.hash),f.set(Q,T),f},m=l=>{if(!(l instanceof Uint8Array))throw new Error("load() expects an Uint8Array generated by save()");const a=A.exports.Hash_GetState(),c=I(),Q=T+c,f=A.exports.memory.buffer;if(l.length!==Q)throw new Error(`Bad state length (expected ${Q} bytes, got ${l.length})`);if(!lt(e.hash,l.subarray(0,T)))throw new Error("This state was written by an incompatible hash implementation");const S=l.subarray(T);new Uint8Array(f,a,c).set(S),r=!0},k=l=>typeof l=="string"?l.length<Z/4:l.byteLength<Z;let E=k;switch(e.name){case"argon2":case"scrypt":E=()=>!0;break;case"blake2b":case"blake2s":E=(l,a)=>a<=512&&k(l);break;case"blake3":E=(l,a)=>a===0&&k(l);break;case"xxhash64":case"xxhash3":case"xxhash128":case"crc64":E=()=>!1;break}const u=(l,a=null,c=null)=>{if(!E(l,a))return B(a),U(l),d("hex",c);const Q=Y(l);return i.set(Q),A.exports.Hash_Calculate(Q.length,a,c),ae(C,i,t)};return yield y(),{getMemory:s,writeMemory:n,getExports:g,setMemorySize:h,init:B,update:U,digest:d,save:w,load:m,calculate:u,hashLength:t}})}new D;var ut="argon2",ft="AGFzbQEAAAABKQVgAX8Bf2AAAX9gEH9/f39/f39/f39/f39/f38AYAR/f39/AGACf38AAwYFAAECAwQFBgEBAoCAAgYIAX8BQZCoBAsHQQQGbWVtb3J5AgASSGFzaF9TZXRNZW1vcnlTaXplAAAOSGFzaF9HZXRCdWZmZXIAAQ5IYXNoX0NhbGN1bGF0ZQAECvEyBVgBAn9BACEBAkAgAEEAKAKICCICRg0AAkAgACACayIAQRB2IABBgIB8cSAASWoiAEAAQX9HDQBB/wHADwtBACEBQQBBACkDiAggAEEQdK18NwOICAsgAcALcAECfwJAQQAoAoAIIgANAEEAPwBBEHQiADYCgAhBACgCiAgiAUGAgCBGDQACQEGAgCAgAWsiAEEQdiAAQYCAfHEgAElqIgBAAEF/Rw0AQQAPC0EAQQApA4gIIABBEHStfDcDiAhBACgCgAghAAsgAAvcDgECfiAAIAQpAwAiECAAKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAMIBAgDCkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgBCAQIAQpAwCFQiiJIhA3AwAgACAQIAApAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAwgECAMKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAEIBAgBCkDAIVCAYk3AwAgASAFKQMAIhAgASkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDSAQIA0pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAEgECABKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACANIBAgDSkDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAIgBikDACIQIAIpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIA4gECAOKQMAhUIgiSIQNwMAIAogECAKKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACACIBAgAikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDiAQIA4pAwCFQjCJIhA3AwAgCiAQIAopAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACADIAcpAwAiECADKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAPIBAgDykDAIVCIIkiEDcDACALIBAgCykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAyAQIAMpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA8gECAPKQMAhUIwiSIQNwMAIAsgECALKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgACAFKQMAIhAgACkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDyAQIA8pAwCFQiCJIhA3AwAgCiAQIAopAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAUgECAFKQMAhUIoiSIQNwMAIAAgECAAKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAPIBAgDykDAIVCMIkiEDcDACAKIBAgCikDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBSAQIAUpAwCFQgGJNwMAIAEgBikDACIQIAEpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAwgECAMKQMAhUIgiSIQNwMAIAsgECALKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACAGIBAgBikDAIVCKIkiEDcDACABIBAgASkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgDCAQIAwpAwCFQjCJIhA3AwAgCyAQIAspAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIAYgECAGKQMAhUIBiTcDACACIAcpAwAiECACKQMAIhF8IBFCAYZC/v///x+DIBBC/////w+DfnwiEDcDACANIBAgDSkDAIVCIIkiEDcDACAIIBAgCCkDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgByAQIAcpAwCFQiiJIhA3AwAgAiAQIAIpAwAiEXwgEEL/////D4MgEUIBhkL+////H4N+fCIQNwMAIA0gECANKQMAhUIwiSIQNwMAIAggECAIKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAHIBAgBykDAIVCAYk3AwAgAyAEKQMAIhAgAykDACIRfCARQgGGQv7///8fgyAQQv////8Pg358IhA3AwAgDiAQIA4pAwCFQiCJIhA3AwAgCSAQIAkpAwAiEXwgEUIBhkL+////H4MgEEL/////D4N+fCIQNwMAIAQgECAEKQMAhUIoiSIQNwMAIAMgECADKQMAIhF8IBBC/////w+DIBFCAYZC/v///x+DfnwiEDcDACAOIBAgDikDAIVCMIkiEDcDACAJIBAgCSkDACIRfCAQQv////8PgyARQgGGQv7///8fg358IhA3AwAgBCAQIAQpAwCFQgGJNwMAC98aAQN/QQAhBEEAIAIpAwAgASkDAIU3A5AIQQAgAikDCCABKQMIhTcDmAhBACACKQMQIAEpAxCFNwOgCEEAIAIpAxggASkDGIU3A6gIQQAgAikDICABKQMghTcDsAhBACACKQMoIAEpAyiFNwO4CEEAIAIpAzAgASkDMIU3A8AIQQAgAikDOCABKQM4hTcDyAhBACACKQNAIAEpA0CFNwPQCEEAIAIpA0ggASkDSIU3A9gIQQAgAikDUCABKQNQhTcD4AhBACACKQNYIAEpA1iFNwPoCEEAIAIpA2AgASkDYIU3A/AIQQAgAikDaCABKQNohTcD+AhBACACKQNwIAEpA3CFNwOACUEAIAIpA3ggASkDeIU3A4gJQQAgAikDgAEgASkDgAGFNwOQCUEAIAIpA4gBIAEpA4gBhTcDmAlBACACKQOQASABKQOQAYU3A6AJQQAgAikDmAEgASkDmAGFNwOoCUEAIAIpA6ABIAEpA6ABhTcDsAlBACACKQOoASABKQOoAYU3A7gJQQAgAikDsAEgASkDsAGFNwPACUEAIAIpA7gBIAEpA7gBhTcDyAlBACACKQPAASABKQPAAYU3A9AJQQAgAikDyAEgASkD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",wt="e4cdc523",Qt={name:ut,data:ft,hash:wt},Bt="blake2b",dt="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",Et="c6f286e6",pt={name:Bt,data:dt,hash:Et};new D;function Qe(e){return!Number.isInteger(e)||e<8||e>512||e%8!==0?new Error("Invalid variant! Valid values: 8, 16, ..., 512"):null}function yt(e,t){return e|t<<16}function ge(e=512,t=null){if(Qe(e))return Promise.reject(Qe(e));let A=null,i=e;if(t!==null){if(A=Y(t),A.length>64)return Promise.reject(new Error("Max key length is 64 bytes"));i=yt(e,A.length)}const r=e/8;return Se(pt,r).then(n=>{i>512&&n.writeMemory(A),n.init(i);const s={init:i>512?()=>(n.writeMemory(A),n.init(i),s):()=>(n.init(i),s),update:g=>(n.update(g),s),digest:g=>n.digest(g),save:()=>n.save(),load:g=>(n.load(g),s),blockSize:128,digestSize:r};return s})}function kt(e,t,A){const i=[`m=${t.memorySize}`,`t=${t.iterations}`,`p=${t.parallelism}`].join(",");return`$argon2${t.hashType}$v=19$${i}$${we(e,!1)}$${we(A,!1)}`}const Be=new DataView(new ArrayBuffer(4));function N(e){return Be.setInt32(0,e,!0),new Uint8Array(Be.buffer)}function re(e,t,A){return O(this,void 0,void 0,function*(){if(A<=64){const h=yield ge(A*8);return h.update(N(A)),h.update(t),h.digest("binary")}const i=Math.ceil(A/32)-2,r=new Uint8Array(A);e.init(),e.update(N(A)),e.update(t);let n=e.digest("binary");r.set(n.subarray(0,32),0);for(let h=1;h<i;h++)e.init(),e.update(n),n=e.digest("binary"),r.set(n.subarray(0,32),h*32);const s=A-32*i;let g;return s===64?(g=e,g.init()):g=yield ge(s*8),g.update(n),n=g.digest("binary"),r.set(n.subarray(0,s),i*32),r})}function St(e){switch(e){case"d":return 0;case"i":return 1;default:return 2}}function Dt(e){return O(this,void 0,void 0,function*(){var t;const{parallelism:A,iterations:i,hashLength:r}=e,n=Y(e.password),s=Y(e.salt),g=19,h=St(e.hashType),{memorySize:I}=e,p=Y((t=e.secret)!==null&&t!==void 0?t:""),[y,B]=yield Promise.all([Se(Qt,1024),ge(512)]);y.setMemorySize(I*1024+1024);const b=new Uint8Array(24),U=new DataView(b.buffer);U.setInt32(0,A,!0),U.setInt32(4,r,!0),U.setInt32(8,I,!0),U.setInt32(12,i,!0),U.setInt32(16,g,!0),U.setInt32(20,h,!0),y.writeMemory(b,I*1024),B.init(),B.update(b),B.update(N(n.length)),B.update(n),B.update(N(s.length)),B.update(s),B.update(N(p.length)),B.update(p),B.update(N(0));const d=Math.floor(I/(A*4))*4,w=new Uint8Array(72),m=B.digest("binary");w.set(m);for(let u=0;u<A;u++){w.set(N(0),64),w.set(N(u),68);let l=u*d,a=yield re(B,w,1024);y.writeMemory(a,l*1024),l+=1,w.set(N(1),64),a=yield re(B,w,1024),y.writeMemory(a,l*1024)}const k=new Uint8Array(1024);ke(k,y.calculate(new Uint8Array([]),I));const E=yield re(B,k,r);if(e.outputType==="hex"){const u=new Uint8Array(r*2);return ae(u,E,r)}return e.outputType==="encoded"?kt(s,e,E):E})}const Ft=e=>{var t;if(!e||typeof e!="object")throw new Error("Invalid options parameter. It requires an object.");if(!e.password)throw new Error("Password must be specified");if(e.password=Y(e.password),e.password.length<1)throw new Error("Password must be specified");if(!e.salt)throw new Error("Salt must be specified");if(e.salt=Y(e.salt),e.salt.length<8)throw new Error("Salt should be at least 8 bytes long");if(e.secret=Y((t=e.secret)!==null&&t!==void 0?t:""),!Number.isInteger(e.iterations)||e.iterations<1)throw new Error("Iterations should be a positive number");if(!Number.isInteger(e.parallelism)||e.parallelism<1)throw new Error("Parallelism should be a positive number");if(!Number.isInteger(e.hashLength)||e.hashLength<4)throw new Error("Hash length should be at least 4 bytes.");if(!Number.isInteger(e.memorySize))throw new Error("Memory size should be specified.");if(e.memorySize<8*e.parallelism)throw new Error("Memory size should be at least 8 * parallelism.");if(e.outputType===void 0&&(e.outputType="hex"),!["hex","binary","encoded"].includes(e.outputType))throw new Error(`Insupported output type ${e.outputType}. Valid values: ['hex', 'binary', 'encoded']`)};function De(e){return O(this,void 0,void 0,function*(){return Ft(e),Dt(Object.assign(Object.assign({},e),{hashType:"id"}))})}new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;new D;const Ut=32;async function bt(e,t,A=de){Fe(A);try{const i=await De({password:e,salt:t,iterations:A.tCost,memorySize:A.mCost,parallelism:A.pCost,hashLength:Ut,outputType:"binary"});return le(i)}catch{throw new Error("Key derivation failed")}}function Fe(e){if(e.mCost<16384)throw new Error("KDF memory cost too low (minimum 16 MiB)");if(e.mCost>1048576)throw new Error("KDF memory cost too high (maximum 1 GiB)");if(e.tCost<1)throw new Error("KDF time cost must be at least 1");if(e.tCost>10)throw new Error("KDF time cost too high (maximum 10)");if(e.pCost<1)throw new Error("KDF parallelism must be at least 1");if(e.pCost>4)throw new Error("KDF parallelism too high (maximum 4)")}async function mt(){try{const e=await De({password:"test",salt:new Uint8Array(16),iterations:1,memorySize:1024,parallelism:1,hashLength:32,outputType:"binary"});return e.length!==32?!1:(ce(e),!0)}catch{return!1}}function Gt(e){return e==="localhost"||e==="127.0.0.1"||e.endsWith(".localhost")}function Kt(e){if(typeof window>"u")return;const t=window.location.hostname;if(!Gt(t))throw new Error("[Cedros] WebAuthn RP domain validation is not configured. Set wallet.allowedRpDomains to a non-empty list of allowed domains.")}function Ce(){return typeof window<"u"&&typeof window.PublicKeyCredential<"u"&&typeof navigator.credentials<"u"}async function Ht(){if(!Ce())return!1;try{if(!await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable())return!1;if("getClientCapabilities"in PublicKeyCredential&&typeof PublicKeyCredential.getClientCapabilities=="function"){const t=await PublicKeyCredential.getClientCapabilities();if(t&&"prf"in t)return t.prf===!0}return!0}catch{return!1}}async function Jt(e,t){if(!Ce())throw new Error("WebAuthn is not available in this browser");Kt();const A=pe(e),i=await navigator.credentials.get({publicKey:{challenge:crypto.getRandomValues(new Uint8Array(32)),rpId:window.location.hostname,allowCredentials:[],userVerification:"required",timeout:6e4,extensions:{prf:{eval:{first:A}}}}});if(!i)throw new Error("Passkey authentication was cancelled");const n=i.getClientExtensionResults().prf?.results?.first;if(!n)throw new Error("PRF extension did not return a result during authentication");const s=new Uint8Array(n);if(s.length!==32)throw new Error(`Unexpected PRF output length: expected 32 bytes, got ${s.length}. The authenticator may not be compatible.`);return{prfOutput:s}}async function Mt(){const[e,t,A,i,r,n,s]=await Promise.all([Vt(),Pt(),It(),Nt(),Promise.resolve(Ce()),Ht(),mt()]);return{webCrypto:e,aesGcm:t,hkdf:A,ed25519:i,webAuthn:r,webAuthnPrf:n,argon2:s,allSupported:e&&t&&A&&r&&n&&s}}async function Vt(){try{return typeof crypto<"u"&&typeof crypto.subtle<"u"&&typeof crypto.getRandomValues=="function"}catch{return!1}}async function Pt(){try{const e=await crypto.subtle.generateKey({name:"AES-GCM",length:256},!1,["encrypt","decrypt"]),t=new Uint8Array([1,2,3,4]),A=crypto.getRandomValues(new Uint8Array(12)),i=await crypto.subtle.encrypt({name:"AES-GCM",iv:A},e,t),r=await crypto.subtle.decrypt({name:"AES-GCM",iv:A},e,i),n=new Uint8Array(r);return n.length===t.length&&n.every((s,g)=>s===t[g])}catch{return!1}}async function Nt(){try{return await crypto.subtle.generateKey("Ed25519",!1,["sign","verify"]),!0}catch{return!1}}function Yt(e){if(e.allSupported)return null;const t=[];return e.webCrypto||t.push("Web Crypto API"),e.aesGcm||t.push("AES-GCM encryption"),e.hkdf||t.push("HKDF key derivation"),e.webAuthn||t.push("WebAuthn/Passkeys"),e.webAuthnPrf||t.push("WebAuthn PRF extension (requires platform authenticator)"),e.argon2||t.push("Argon2 password hashing"),t.length===0?null:`Your browser or device is missing required features: ${t.join(", ")}. Please use a modern browser with a platform authenticator (e.g., Touch ID, Face ID, Windows Hello).`}function Ot(){const e=typeof navigator<"u"?navigator.userAgent:"",t=e.match(/Chrome\/(\d+)/);if(t){const n=parseInt(t[1],10);return{browser:"Chrome",version:t[1],likelySupported:n>=116}}const A=e.match(/Version\/(\d+)/);if(A&&e.includes("Safari")&&!e.includes("Chrome")){const n=parseInt(A[1],10);return{browser:"Safari",version:A[1],likelySupported:n>=17}}const i=e.match(/Firefox\/(\d+)/);if(i)return{browser:"Firefox",version:i[1],likelySupported:!1};const r=e.match(/Edg\/(\d+)/);if(r){const n=parseInt(r[1],10);return{browser:"Edge",version:r[1],likelySupported:n>=116}}return{browser:"Unknown",version:"Unknown",likelySupported:!1}}let q=null,ne=null;const vt=6e4;async function xt(e=!1){const t=Date.now(),A=ne===null||t-ne>vt;return!e&&!(typeof window>"u")&&!A&&q!==null||(q=await Mt(),ne=Date.now()),q}function Ue(e){switch(e.type){case"password":return{password:e.password};case"prfOutput":return{prfOutput:e.prfOutput}}}function be(){const e=F.useCedrosLoginOptional(),[t,A]=o.useState(!1),[i,r]=o.useState(null),n=e?.config.serverUrl,s=e?.config.requestTimeout,g=e?.config.retryAttempts,h=e?._internal?.getAccessToken,I=o.useMemo(()=>e?new F.ApiClient({baseUrl:n,timeoutMs:s,retryAttempts:g,getAccessToken:h}):null,[e,n,s,g,h]),p=o.useCallback(async()=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{return await I.get("/wallet/status")}catch(a){const c=F.handleApiError(a,"Failed to fetch wallet status");throw r(c.message),c}finally{A(!1)}},[I]),y=o.useCallback(async()=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{return await I.get("/wallet/material")}catch(a){const c=F.handleApiError(a,"Failed to fetch wallet material");if(c.code==="NOT_FOUND")return null;throw r(c.message),c}finally{A(!1)}},[I]),B=o.useCallback(async a=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{await I.post("/wallet/enroll",a)}catch(c){const Q=F.handleApiError(c,"Failed to enroll wallet");throw r(Q.message),Q}finally{A(!1)}},[I]),b=o.useCallback(async a=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{await I.post("/wallet/recover",a)}catch(c){const Q=F.handleApiError(c,"Failed to recover wallet");throw r(Q.message),Q}finally{A(!1)}},[I]),U=o.useCallback(async a=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{return await I.post("/wallet/sign",a)}catch(c){const Q=F.handleApiError(c,"Failed to sign transaction");throw r(Q.message),Q}finally{A(!1)}},[I]),C=o.useCallback(async a=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{await I.post("/wallet/rotate-user-secret",a)}catch(c){const Q=F.handleApiError(c,"Failed to rotate user secret");throw r(Q.message),Q}finally{A(!1)}},[I]),d=o.useCallback(async a=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{return await I.post("/wallet/unlock",Ue(a))}catch(c){const Q=F.handleApiError(c,"Failed to unlock wallet");throw r(Q.message),Q}finally{A(!1)}},[I]),w=o.useCallback(async()=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{await I.post("/wallet/lock",{})}catch(a){const c=F.handleApiError(a,"Failed to lock wallet");throw r(c.message),c}finally{A(!1)}},[I]),m=o.useCallback(async a=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{return await I.post("/wallet/share-b",a)}catch(c){const Q=F.handleApiError(c,"Failed to get Share B for recovery");throw r(Q.message),Q}finally{A(!1)}},[I]),k=o.useCallback(async a=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{return await I.post("/wallet/derived",a)}catch(c){const Q=F.handleApiError(c,"Failed to create derived wallet");throw r(Q.message),Q}finally{A(!1)}},[I]),E=o.useCallback(async()=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{return await I.get("/wallet/derived")}catch(a){const c=F.handleApiError(a,"Failed to list wallets");throw r(c.message),c}finally{A(!1)}},[I]),u=o.useCallback(async a=>{if(!I)throw new Error("useWalletMaterial must be used within a CedrosLoginProvider");A(!0),r(null);try{await I.delete(`/wallet/derived/${a}`)}catch(c){const Q=F.handleApiError(c,"Failed to delete derived wallet");throw r(Q.message),Q}finally{A(!1)}},[I]),l=o.useCallback(()=>r(null),[]);return{getStatus:p,getMaterial:y,enroll:B,recover:b,signTransaction:U,rotateUserSecret:C,unlock:d,lock:w,getShareBForRecovery:m,createDerivedWallet:k,listAllWallets:E,deleteDerivedWallet:u,isLoading:t,error:i,clearError:l}}const Rt={status:"not_enrolled",solanaPubkey:null,authMethod:null,hasExternalWallet:!1,isUnlocked:!1,capabilities:null,isSupported:!1,error:null,refresh:async()=>{},clearError:()=>{}};function me(){const t=F.useCedrosLoginOptional()!==null,[A,i]=o.useState("loading"),[r,n]=o.useState(null),[s,g]=o.useState(null),[h,I]=o.useState(!1),[p,y]=o.useState(!1),[B,b]=o.useState(null),[U,C]=o.useState(null),{getStatus:d,isLoading:w}=be(),m=o.useRef(!1);o.useEffect(()=>{if(!t)return;let u=!1;return(async()=>{try{const a=await xt();if(u)return;b(a),a.allSupported||(i("error"),C("Your browser or device does not support all required features. Please use a modern browser with a platform authenticator."))}catch{if(u)return;b(null),i("error"),C("Failed to check crypto capabilities")}})(),()=>{u=!0}},[t]);const k=o.useCallback(async()=>{if(!(!t||!B?.allSupported)){i("loading"),C(null);try{const u=await d();n(u.solanaPubkey??null),g(u.authMethod??null),I(u.hasExternalWallet),y(u.unlocked),u.hasExternalWallet?i("enrolled_unlocked"):u.enrolled?i(u.unlocked?"enrolled_unlocked":"enrolled_locked"):i("not_enrolled")}catch(u){i("error"),C(u instanceof Error?u.message:"Failed to fetch wallet status")}}},[t,B?.allSupported,d]);o.useEffect(()=>{t&&B?.allSupported&&!w&&!m.current&&(m.current=!0,k())},[t,B?.allSupported,w,k]);const E=o.useCallback(()=>C(null),[]);return t?{status:A,solanaPubkey:r,authMethod:s,hasExternalWallet:h,isUnlocked:p,capabilities:B,isSupported:B?.allSupported??!1,error:U,refresh:k,clearError:E}:Rt}const $="__CEDROS_EMBEDDED_WALLET__";function Tt(e){typeof window<"u"&&(window[$]=e)}function oe(){typeof window<"u"&&delete window[$]}function Lt(){return typeof window>"u"?!1:window[$]?.available??!1}function Xt(){return typeof window>"u"?null:window[$]??null}function Wt(){const{config:e,user:t}=F.useCedrosLogin(),{status:A,solanaPubkey:i,hasExternalWallet:r}=me(),n=e.wallet?.exposeAvailability??!1,s=e.wallet?.exposePublicKey??!1;return o.useEffect(()=>{if(!n||!t){oe();return}if(r){oe();return}if(A==="loading")return;const g=A==="enrolled_locked"||A==="enrolled_unlocked";return Tt({available:g,publicKey:s&&g?i:null}),()=>{oe()}},[n,s,t,A,i,r]),null}function jt({config:e,children:t}){const[A,i]=o.useState(null),[r,n]=o.useState(!1),s=o.useRef(e.callbacks);s.current=e.callbacks;const g=o.useRef({onLoginSuccess:(...M)=>s.current?.onLoginSuccess?.(...M),onLoginError:(...M)=>s.current?.onLoginError?.(...M),onLogout:()=>s.current?.onLogout?.(),onSessionExpired:()=>s.current?.onSessionExpired?.()}),h=o.useRef(null);o.useEffect(()=>{if(typeof window>"u")return;const M=new URLSearchParams(window.location.search),v=M.get("ref")||M.get("referral");v&&(h.current=v)},[]);const I=e.features==="auto",{features:p,googleClientId:y,appleClientId:B,socialButtonOrder:b,isLoading:U}=Je(e.serverUrl,I,e.requestTimeout),C=o.useMemo(()=>!I||!p?e:{...e,features:p,googleClientId:e.googleClientId??y,appleClientId:e.appleClientId??B},[e,I,p,y,B]),d=o.useMemo(()=>JSON.stringify(C.themeOverrides??null),[C.themeOverrides]),w=o.useMemo(()=>JSON.stringify(C.session??null),[C.session]),m=o.useMemo(()=>JSON.stringify(C.features??null),[C.features]),k=o.useMemo(()=>JSON.stringify(C.forms??null),[C.forms]),E=o.useMemo(()=>C,[C.serverUrl,C.googleClientId,C.appleClientId,C.requestTimeout,C.retryAttempts,C.theme,d,w,m,k]);Ke({theme:E.theme,themeOverrides:E.themeOverrides});const{user:u,authState:l,handleLoginSuccess:a,logout:c,refreshUser:Q,getAccessToken:f}=ve({serverUrl:E.serverUrl,session:E.session,callbacks:g.current,requestTimeoutMs:E.requestTimeout}),S=o.useCallback(async()=>{i(null),await c()},[c]),G=o.useCallback((...M)=>{i(null),a(...M)},[a]),H=o.useCallback(()=>n(!0),[]),K=o.useCallback(()=>n(!1),[]),J=o.useMemo(()=>({config:E,user:u,authState:l,logout:S,refreshUser:Q,socialButtonOrder:I?b:void 0,_internal:{handleLoginSuccess:G,getAccessToken:f,getReferralCode:()=>h.current}}),[E,u,l,S,Q,I,b,G,f]),V=o.useMemo(()=>({error:A,isModalOpen:r,openModal:H,closeModal:K}),[A,r,H,K]),he=o.useMemo(()=>({...J,...V}),[J,V]);return I&&U?null:X.jsx(ee.AuthStateContext.Provider,{value:J,children:X.jsx(ee.AuthUIContext.Provider,{value:V,children:X.jsxs(ee.CedrosLoginContext.Provider,{value:he,children:[X.jsx(Wt,{}),t]})})})}function Zt(){const{user:e,authState:t,error:A,logout:i,refreshUser:r,openModal:n,closeModal:s}=F.useCedrosLogin();return{user:e,authState:t,error:A,isAuthenticated:t==="authenticated"&&e!==null,isLoading:t==="loading",logout:i,refreshUser:r,openLoginModal:n,closeLoginModal:s}}exports.CedrosLoginProvider=jt;exports.DEFAULT_KDF_PARAMS=de;exports.aesGcmEncryptToBase64=nt;exports.argon2Derive=bt;exports.authenticateWithDiscoverablePrf=Jt;exports.base64ToUint8Array=pe;exports.deriveKeyFromPrf=st;exports.generateArgon2Salt=et;exports.generatePrfSalt=tt;exports.generateSeed=$e;exports.getBrowserSupportInfo=Ot;exports.getEmbeddedWalletInfo=Xt;exports.getMissingCapabilitiesMessage=Yt;exports.isEmbeddedWalletAvailable=Lt;exports.toCredentialRequest=Ue;exports.toEncryptionKey=le;exports.toSeed=Ee;exports.toShamirShare=je;exports.uint8ArrayToBase64=se;exports.useAuth=Zt;exports.useWallet=me;exports.useWalletMaterial=be;exports.validateKdfParams=Fe;exports.wipeAll=At;exports.wipeBytes=ce;