import * as react from 'react'; import react__default, { ReactNode } from 'react'; import { C as Chain, N as NetworkEnv, a as CavosWallet, b as CavosSession } from '../Cavos-GquO3aJr.mjs'; import { f as AttestationPolicy, I as Identity } from '../VaultClient-CkzLCyXH.mjs'; import { C as ChainCall, E as ExecuteOptions, M as MessageSignature } from '../signing-BC_pkVbS.mjs'; import '../CavosSolana-BgzBk_2P.mjs'; import '@solana/web3.js'; import 'starknet'; import '../CavosStellar-DxAYL2pU.mjs'; import '@stellar/stellar-sdk'; import '../DeviceUnwrapKey-Ct-JUQrB.mjs'; import '../nativeConnect-DPJqSwJj.mjs'; import '@starkware-libs/starknet-privacy-sdk'; /** * How a device that is not a signer yet gets authorized. * * This is the app's decision, not something to discover at runtime. An app * either runs the enclave or it uses passkeys; mixing them means every user * gets whichever the SDK happened to find first, and the integrator cannot say * what their own product does. * * It used to be inferred — a passkey lookup, an enrolment lookup against the * backend, a priority ladder, a fallback to email when either had not answered * yet. That produced approval emails for wallets the enclave was about to * restore in seconds, because the ladder resolved before the lookups did. */ type DeviceApproval = /** The attested enclave authorizes the device, given a fresh login proof. */ "enclave" /** A passkey on the device authorizes it, with one gesture. */ | "passkey"; type DeviceAuthorizationMethod = "enclave" | "passkey" /** * The enclave route, without the proof it needs. That proof is never * persisted — it is what the enclave verifies — so it does not survive a * reload, and signing in again mints a new one. An action, not an error. */ | "enclave-needs-login"; interface CavosConfig { /** Cavos App ID from the dashboard. */ appId?: string; /** Cavos console environment. Defaults to production when omitted. */ environment?: 'development' | 'production'; /** * Target chain (single-chain mode). Defaults to 'starknet'. * @deprecated Use `chains` and `defaultChain` for multi-chain sessions. * When `chains` is provided, this is ignored. If only `chain` is provided, * it's treated as `chains: [chain], defaultChain: chain`. */ chain?: Chain; /** * Chains to configure for this session. Connect derives addresses for all * configured chains but NEVER deploys on connect. Deployment happens lazily * on the first `execute` call for each chain. */ chains?: Chain[]; /** * Default chain for the session. Must be in `chains`. When using the * single-chain `chain` option, `defaultChain` defaults to that chain. */ defaultChain?: Chain; /** Environment: 'testnet' (sepolia/devnet) or 'mainnet'. */ network: NetworkEnv; /** * Device-key slot. On native Solana/Stellar it is also the HKDF salt for the * spend key — never change it after users connect. */ appSalt: string; /** Cavos paymaster API key (sponsors deploy + execute). Required for Starknet. */ paymasterApiKey?: string; /** Override the Cavos auth backend (self-hosted / staging). */ authBackendUrl?: string; /** * Whether a sign-in outlives the tab. Defaults to `true`: the identity is * kept in `localStorage` and the user stays signed in across tabs and * restarts. `false` keeps it in `sessionStorage` instead, so it survives a * reload and the OAuth redirect but ends when the tab closes; an identity * saved earlier in `localStorage` is removed. * * Read once, when the provider mounts. Changing it later has no effect until * the provider remounts (e.g. give it a new `key`). Only the built-in auth * uses it: with the `identity` prop your auth decides, and device keys stay * on the device either way. */ persistSession?: boolean; /** * How a device that is not a signer yet gets authorized: by the attested * enclave, or by a passkey on the device. This is the app's choice — an app * runs one or the other, and inferring it at runtime gave different users * different flows. Defaults to the enclave when `socialRecovery` is on. */ deviceApproval?: DeviceApproval; /** Override the chain RPC. Unambiguous only with a single configured chain. */ rpcUrl?: string; /** * Per-chain RPC overrides, e.g. `{ solana: '…', starknet: '…' }`. Required * instead of `rpcUrl` once `chains` has more than one entry: one node cannot * serve them all, and the mismatched one answers "Method not found". */ rpcUrls?: Partial>; /** * Where Toll lives, for `fee: { token }` — the user pays their own fee in a * token they already hold. Solana only. Omit it and that route is not offered. */ tollUrl?: string; /** Explicit OAuth callback. Optional on web; required by the native provider. */ redirectUri?: string; /** Passkey relying-party id. Optional on web; required by the native provider. */ rpId?: string; /** Native-only key policy; retained here so config objects remain portable. */ minimumKeySecurity?: 'os-protected' | 'hardware'; /** * Turn on hardware-isolated social recovery using the enclave Cavos operates, * pinned by the constants shipped in this package. The feature must also be * enabled for the app's environment in the dashboard. * * Pass an `AttestationPolicy` instead to pin your own measurements — required * if you run your own enclave. Values pinned here are never learned from the * control plane whose enclave is being verified. */ socialRecovery?: boolean | AttestationPolicy; /** * @deprecated Use `socialRecovery`. Passing a policy here still works and * takes precedence, so existing apps keep their explicit pin. */ socialRecoveryAttestation?: AttestationPolicy; /** * Signing keys live in the Cavos vault, not in this page's * storage. On by default when `appId` is set; `false` turns it off. */ vault?: boolean | { url?: string; }; } interface CavosModalConfig { appName?: string; appLogo?: string; /** Logo height in px. Applies to both a custom `appLogo` (img) and the * default Cavos star. Defaults to 40 (img) / 34 (star). */ appLogoSize?: number; providers?: ('google' | 'apple' | 'email')[]; primaryColor?: string; /** 'light' (default) or 'dark'. */ theme?: 'light' | 'dark'; /** Override the modal card background color (defaults to white/#111 per theme). */ backgroundColor?: string; /** Card / button corner radius in px (card defaults to 16, buttons to 8). */ radius?: number; /** * One-time "secure your account" step after a brand-new account is created. * Off by default: login never asks for a passkey. The app calls * `enrollPasskeyDefault` / `approveDeviceWithPasskey` when it wants that * prompt, or sets this to `'optional'` / `'required'` to use the modal's * built-in screen. */ secureStep?: 'optional' | 'required' | 'off'; onSuccess?: (address: string) => void; } /** Minimal wallet-status surface the React layer (and modal) needs. */ interface WalletStatus { /** True while the account is being connected or deployed. */ isDeploying: boolean; /** True once this device holds the wallet key. */ isReady: boolean; /** * True if the account has not been deployed on-chain yet. First execute * will trigger deployment + the user operation atomically. */ isUndeployed: boolean; /** True if this device still needs approval to operate the wallet. */ needsDeviceApproval: boolean; /** True if the account has a passkey that can restore it on a new device. */ hasPasskey: boolean; /** True right after a brand-new account is created (first sign-up), so the UI * can offer a one-time "secure your account" step. Cleared once handled. */ isNewAccount: boolean; /** * Can this user get back in from a device they do not have yet? * * The one recovery question an app actually has to answer. The flags above * describe work in flight; this describes the standing guarantee, and it is * the only one most integrations need to read. `methods` is there so an app * can nudge — "add a passkey" reads better than "you are unprotected". * * `protected` is false until the lookup that fills it returns, so treat it as * "not known to be protected" rather than "known to be unprotected" during * the first moments of a connect. */ recovery: { protected: boolean; methods: ('passkey' | 'social')[]; }; } interface UserInfo { userId: string; email?: string; /** Display name from the OAuth id_token (Google only today). May be unset. */ name?: string; provider?: string; } interface CavosContextValue { /** Open / close the built-in auth modal. */ openModal: () => void; closeModal: () => void; isAuthenticated: boolean; user: UserInfo | null; /** The currently selected chain ('starknet' | 'solana' | 'stellar'). */ chain: Chain; /** All configured chains for this session. */ configuredChains: Chain[]; /** * Switch the selected chain. Must be one of the configured chains. Does not * re-deploy or re-authenticate — just changes which wallet is active. */ setChain: (chain: Chain) => void; /** * The connected wallet for the selected chain, discriminated by `wallet.chain`. * Narrow on `wallet.chain` before chain-native calls (e.g. Solana * `wallet.execute(amount, dest)`). Null until connected. */ wallet: CavosWallet | null; /** * The session containing wallets for all configured chains. Use this to access * wallets for chains other than the selected one: `session.wallet("solana")`. */ session: (CavosWallet & CavosSession) | null; address: string | null; walletStatus: WalletStatus; isLoading: boolean; /** Last unrecoverable auth/connect error surfaced to the UI (e.g. a failed * OAuth callback). Null while things are healthy. Cleared on a new attempt. */ authError: string | null; /** Clear `authError` (e.g. when the user starts a new login attempt). */ clearAuthError: () => void; /** OAuth social login — opens the provider's hosted flow. */ login: (provider: 'google' | 'apple') => Promise; /** Email a 9-character sign-in code generated by the recovery enclave. */ sendOtp: (email: string) => Promise; /** Verify the emailed code inside the enclave and deploy the wallet. */ verifyOtp: (email: string, code: string) => Promise; /** Resolve identity from an OAuth callback (?auth_data=…) and deploy. */ handleCallback: (authData: string) => Promise; /** * Execute a multicall signed by the account key (Starknet-only — on Solana / * Stellar call `wallet.execute(...)` directly). Sponsored (gasless) by default; * pass `{ sponsored: false }` to submit directly with the account paying its * own fee. */ execute: (calls: ChainCall[], opts?: ExecuteOptions) => Promise<{ transactionHash: string; }>; /** * Sign an arbitrary message off-chain with the wallet's signing key. Chain- * agnostic (uniform `MessageSignature` return); delegates to * `wallet.signMessage` after narrowing on `wallet.chain`. See * [Signing](https://docs.cavos.xyz/docs/signing) for per-chain formats * and verification. */ signMessage: (message: string | Uint8Array) => Promise; /** Whether this device can use a platform passkey (Face ID / Touch ID / PIN). */ passkeySupported: boolean; /** * The single way this device should be authorized, when it is not a signer * yet. One decision taken before anything runs, so the UI shows one action * instead of racing every mechanism at once. */ deviceAuthorization: DeviceAuthorizationMethod; /** * Authorize this device on the wallet, by whichever route * `deviceAuthorization` chose. Called for you before any action that needs * the account's authority; call it directly to do it ahead of time. */ authorizeDevice: () => Promise; /** * True while an authorization is being asked for. The modal shows the flow * only then — signing in must not be interrupted by a device that is merely * not a signer yet, the same way a wallet is not deployed until it is used. */ authorizingDevice: boolean; /** * Modal-friendly wrapper: add a synced passkey that restores the wallet on a * new device, using the signed-in user's identity + the app name. Requires a * ready device. */ enrollPasskeyDefault: () => Promise; /** * Modal-friendly wrapper for the new-device flow: prompt the user's synced * passkey to restore the wallet key on THIS device, then refresh to a ready state. */ approveDeviceWithPasskey: () => Promise; /** * Stellar only: register a backup signer derived from a generated recovery * code (gasless). Resolves with the code so the caller can display it once. */ setupRecovery: () => Promise; /** * Stellar only: recover access after losing every device with the recovery * code. Brings the provider to a ready state. */ recover: (code: string) => Promise; /** * Drive social recovery with a provider id_token your own login already * obtained, so the user never signs in twice. * * Reconnects the wallet with that proof, so the enclave seals a new wallet or * restores this device onto an existing one. Pass the raw Google or Apple * `id_token`, not your own session JWT, and pass it straight from a sign-in: * the enclave requires the authentication to be under five minutes old. * * Requires the app's own OAuth client ID to be registered for the environment * in the dashboard, so the enclave accepts tokens minted for your client. */ submitSocialRecoveryToken: (idToken: string) => void; logout: () => void; } interface CavosProviderProps { /** A single chain config. The provider manages exactly one chain. */ config: CavosConfig; modal?: CavosModalConfig; /** * Bring your own auth: the signed-in user from Clerk, Auth0, your own * backend, anything. When set, the provider skips its own login entirely — * the modal never opens and `login()` throws — and connects this user's * wallet directly. * * Pass `null` while your auth is still loading or once the user signs out; * the provider clears its state in step with you. * * This identity is deliberately **not persisted**. Your auth stays the single * source of truth on every mount, so a Cavos session can never outlive the * session that authorized it. * * `userId` must be stable and unique per user — the wallet address derives * from it. Use an immutable primary key, never an email or username. */ identity?: Identity | null; children: ReactNode; } declare function CavosProvider({ config, modal, identity: externalIdentity, children, }: CavosProviderProps): react.JSX.Element; declare function useCavos(): CavosContextValue; interface CavosAuthModalProps { open: boolean; onClose: () => void; onSuccess?: (address: string) => void; appName?: string; appLogo?: string; /** Logo height in px. Applies to both a custom `appLogo` (img) and the * default Cavos star. Defaults to 40 (img) / 34 (star). */ appLogoSize?: number; providers?: ('google' | 'apple' | 'email')[]; primaryColor?: string; /** 'light' (default) or 'dark' */ theme?: 'light' | 'dark'; /** Override the card background color (defaults to white/#111 per theme). */ backgroundColor?: string; /** Card / button corner radius in px (card defaults to 16, buttons to 8). */ radius?: number; /** * Render the card in-flow (no full-screen overlay/backdrop) so it can be * embedded as a live preview. When true, `open` is ignored (always shown). */ inline?: boolean; /** * One-time "secure your account" step after a new account is created. * Off by default: login never asks for a passkey. Set `'optional'` or * `'required'` to use this screen, or call `enrollPasskeyDefault` yourself. */ secureStep?: 'optional' | 'required' | 'off'; } declare function CavosAuthModal({ open, onClose, appName, appLogo, appLogoSize, providers, primaryColor, theme, backgroundColor: backgroundColorProp, radius, inline, secureStep, }: CavosAuthModalProps): react__default.JSX.Element | null; declare function useCavosAuth(): { openModal: () => void; closeModal: () => void; isAuthenticated: boolean; address: string | null; user: UserInfo | null; walletStatus: WalletStatus; logout: () => void; }; interface CavosConfigProblem { /** Stable identifier so hosts can suppress or test a specific check. */ code: "missing-app-salt" | "app-salt-changed" | "missing-app-id" | "missing-paymaster-key" | "unused-paymaster-key" | "social-recovery-without-app-id" | "ambiguous-rpc-url"; /** `error` breaks the integration; `warning` works but is probably a mistake. */ level: "error" | "warning"; message: string; } /** * Check a config for mistakes that are otherwise reported late, indirectly, or * not at all. Pure — see `checkAppSaltDrift` for the check that needs storage. */ declare function validateCavosConfig(config: CavosConfig): CavosConfigProblem[]; /** * Detect an `appSalt` that changed since this browser last connected. * * The salt no longer enters the address, but it does name the device-key slot: * change it and every returning device generates a NEW key, finds the same * wallet in the registry, and lands in `needs-device-approval` — the app keeps * working while every user is locked out until they re-approve. Worth a warning. * * Returns the problem to report, or null. Records the salt on first sight. */ declare function checkAppSaltDrift(config: CavosConfig, storage?: Pick | undefined): CavosConfigProblem | null; /** Format problems for the console. Exported so hosts can render them instead. */ declare function formatConfigProblems(problems: CavosConfigProblem[]): string; export { CavosAuthModal, type CavosAuthModalProps, type CavosConfig, type CavosConfigProblem, type CavosContextValue, type CavosModalConfig, CavosProvider, type CavosProviderProps, type UserInfo, type WalletStatus, checkAppSaltDrift, formatConfigProblems, useCavos, useCavosAuth, validateCavosConfig };