@cavos/kit 0.0.3 → 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,6 +1,4 @@
1
- import { spkiToPublicKey, derToRs, challengeOffsetOf, base64urlEncode } from './chunk-BNGLH3Q3.mjs';
2
- export { BackupSigner, Cavos, CavosAuth, CavosSolana, CavosStellar, DEVICE_ACCOUNT_CLASS_HASH, DEVICE_ACCOUNT_PROGRAM_ID, DEVICE_ACCOUNT_WASM_HASH, FACTORY_CONTRACT_ID, HttpRecoveryClient, HttpWalletRegistry, InMemoryWalletRegistry, NATIVE_SAC_ID, SECP256R1_PROGRAM_ID, SOLANA_NETWORKS, STARKNET_NETWORKS, STELLAR_NETWORKS, SolanaAdapter, SolanaRelayer, StarknetAdapter, StarknetDeviceSigner, StellarAdapter, StellarRelayer, UDC_ADDRESS, WebCryptoSigner, anchorDiscriminator, approveDeviceEverywhere, base64urlEncode, batchChallenge, bigIntTo32Bytes, buildSecp256r1Instruction, bytesToBigInt, bytesToHex, compressedPubkey, deriveAddressSeed, deriveAddressSeedSolana, deriveAddressSeedStellar, deriveBackupKey, deviceSignatureScVal, encodeLowSSignature, encodeLowSSignature2 as encodeStellarLowSSignature, generateRecoveryCode, hexToBytes, lowS, recoverCandidatePublicKeys, recoverYParity, sec1Pubkey, serializeInstructions, signatureToFelts, u256ToFelts, webauthnDigest } from './chunk-BNGLH3Q3.mjs';
3
- import { sha256 } from '@noble/hashes/sha256';
1
+ export { BackupSigner, Cavos, CavosAuth, CavosSolana, CavosStellar, DEVICE_ACCOUNT_CLASS_HASH, DEVICE_ACCOUNT_PROGRAM_ID, DEVICE_ACCOUNT_WASM_HASH, FACTORY_CONTRACT_ID, HttpRecoveryClient, HttpWalletRegistry, InMemoryWalletRegistry, NATIVE_SAC_ID, PasskeySigner, SECP256R1_PROGRAM_ID, SOLANA_NETWORKS, STARKNET_NETWORKS, STELLAR_NETWORKS, SolanaAdapter, SolanaRelayer, StarknetAdapter, StarknetDeviceSigner, StellarAdapter, StellarRelayer, UDC_ADDRESS, WebCryptoSigner, anchorDiscriminator, approveDeviceEverywhere, base64urlEncode, batchChallenge, bigIntTo32Bytes, buildSecp256r1Instruction, bytesToBigInt, bytesToHex, compressedPubkey, deriveAddressSeed, deriveAddressSeedSolana, deriveAddressSeedStellar, deriveBackupKey, deviceSignatureScVal, encodeLowSSignature, encodeLowSSignature2 as encodeStellarLowSSignature, generateRecoveryCode, hexToBytes, lowS, recoverCandidatePublicKeys, recoverYParity, sec1Pubkey, serializeInstructions, signatureToFelts, u256ToFelts, webauthnDigest } from './chunk-F2J25XSL.mjs';
4
2
 
5
3
  // src/auth/AuthProvider.ts
6
4
  var StaticIdentity = class {
@@ -11,91 +9,7 @@ var StaticIdentity = class {
11
9
  return this.identity;
12
10
  }
13
11
  };
14
- var PasskeySigner = class {
15
- constructor(opts = {}) {
16
- if (typeof window === "undefined" || !navigator.credentials) {
17
- throw new Error("kit/passkey: WebAuthn is only available in a browser");
18
- }
19
- this.rpId = opts.rpId ?? window.location.hostname;
20
- this.rpName = opts.rpName ?? this.rpId;
21
- if (isIpAddress(this.rpId)) {
22
- throw new Error(
23
- `kit/passkey: passkeys can't use an IP address as the domain ("${this.rpId}"). Use http://localhost, a real HTTPS domain, or a tunnel (cloudflared/ngrok) \u2014 or pass an explicit \`rpId\`. (The silent device key works over an IP; passkeys don't.)`
24
- );
25
- }
26
- }
27
- /** True if this platform advertises a usable passkey (platform authenticator). */
28
- static async isSupported() {
29
- if (typeof window === "undefined" || !window.PublicKeyCredential) return false;
30
- try {
31
- return await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
32
- } catch {
33
- return false;
34
- }
35
- }
36
- /** Create a new synced passkey and return its P-256 public key. */
37
- async enroll(params) {
38
- const challenge = crypto.getRandomValues(new Uint8Array(32));
39
- const cred = await navigator.credentials.create({
40
- publicKey: {
41
- challenge: buf(challenge),
42
- rp: { id: this.rpId, name: this.rpName },
43
- user: {
44
- id: buf(userHandle(params.userId)),
45
- name: params.userName,
46
- displayName: params.displayName ?? params.userName
47
- },
48
- pubKeyCredParams: [{ type: "public-key", alg: -7 }],
49
- // ES256 (P-256)
50
- authenticatorSelection: {
51
- residentKey: "required",
52
- requireResidentKey: true,
53
- userVerification: "preferred"
54
- },
55
- attestation: "none"
56
- }
57
- });
58
- if (!cred) throw new Error("kit/passkey: enrollment cancelled");
59
- const response = cred.response;
60
- const spki = new Uint8Array(response.getPublicKey());
61
- return { publicKey: spkiToPublicKey(spki), credentialId: new Uint8Array(cred.rawId) };
62
- }
63
- /**
64
- * Produce a WebAuthn assertion over `challenge` (a 32-byte value the caller
65
- * derives from the signer being added + the on-chain nonce). Uses discoverable
66
- * credentials — no `allowCredentials` — so it works on a brand-new browser.
67
- */
68
- async assert(challenge) {
69
- const cred = await navigator.credentials.get({
70
- publicKey: {
71
- challenge: buf(challenge),
72
- rpId: this.rpId,
73
- allowCredentials: [],
74
- userVerification: "preferred"
75
- }
76
- });
77
- if (!cred) throw new Error("kit/passkey: assertion cancelled");
78
- const response = cred.response;
79
- const authenticatorData = new Uint8Array(response.authenticatorData);
80
- const clientDataJSON = new Uint8Array(response.clientDataJSON);
81
- const { r, s } = derToRs(new Uint8Array(response.signature));
82
- const challengeOffset = challengeOffsetOf(clientDataJSON, base64urlEncode(challenge));
83
- return { authenticatorData, clientDataJSON, r, s, challengeOffset };
84
- }
85
- };
86
- function isIpAddress(host) {
87
- if (/^\d{1,3}(\.\d{1,3}){3}$/.test(host)) return true;
88
- if (host.includes(":")) return true;
89
- return false;
90
- }
91
- function userHandle(userId) {
92
- const bytes = new TextEncoder().encode(userId);
93
- return bytes.length <= 64 ? bytes : sha256(bytes);
94
- }
95
- function buf(bytes) {
96
- return bytes.slice();
97
- }
98
12
 
99
- export { PasskeySigner, StaticIdentity };
13
+ export { StaticIdentity };
100
14
  //# sourceMappingURL=index.mjs.map
101
15
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/auth/AuthProvider.ts","../src/signer/PasskeySigner.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Identity for a Cavos wallet. Login (email / social / OTP) only ever produces a\n * stable `userId`; that's all the wallet needs to derive its address. Auth never\n * touches signing — the device key does that, silently.\n *\n * Privy-style UX: the user \"logs in\" and the wallet is provisioned behind the\n * scenes (device key + auto-deployed smart account). The app never handles keys.\n */\nexport interface Identity {\n /** Stable, backend-managed user identifier. */\n userId: string;\n /** Optional metadata (email, provider) for display only. */\n email?: string;\n provider?: \"google\" | \"apple\" | \"email\" | \"otp\" | string;\n}\n\n/**\n * Authenticates a user and returns their stable identity. Implementations:\n * - `CavosAuth` (hosted, mirrors `@cavos/react`: Google/Apple/email/OTP via the\n * Cavos backend) — the default, Privy-like experience.\n * - any custom provider (the app already authenticated the user elsewhere).\n */\nexport interface AuthProvider {\n authenticate(): Promise<Identity>;\n}\n\n/** Trivial provider when the app already has the user's stable id. */\nexport class StaticIdentity implements AuthProvider {\n constructor(private readonly identity: Identity) {}\n async authenticate(): Promise<Identity> {\n return this.identity;\n }\n}\n","import { sha256 } from \"@noble/hashes/sha256\";\nimport type { DevicePublicKey } from \"./DeviceSigner\";\nimport {\n base64urlEncode,\n challengeOffsetOf,\n derToRs,\n spkiToPublicKey,\n type PasskeyAssertion,\n} from \"../crypto/webauthn\";\n\nexport interface PasskeySignerOptions {\n /** Relying-Party id (usually the eTLD+1). Defaults to `window.location.hostname`. */\n rpId?: string;\n /** Human-readable RP name shown in the OS passkey UI. */\n rpName?: string;\n}\n\nexport interface PasskeyEnrollParams {\n /** Stable user handle for the credential (e.g. the account address or userId). */\n userId: string;\n /** Account name shown in the OS passkey UI (e.g. an email). */\n userName: string;\n displayName?: string;\n}\n\nexport interface EnrolledPasskey {\n publicKey: DevicePublicKey;\n credentialId: Uint8Array;\n}\n\n/**\n * Browser passkey signer. Creates a discoverable (resident) secp256r1 credential\n * that syncs across the user's devices (iCloud Keychain / Google Password\n * Manager), and produces WebAuthn assertions used to authorize `add_signer`.\n *\n * This is a step-up primitive: the app decides WHEN to enroll (e.g. after\n * onboarding, as a \"turn on device approvals\" / 2FA moment). Enrollment\n * registers the passkey on-chain as an approver; later, from any browser, an\n * assertion approves adding that browser's new device key.\n */\nexport class PasskeySigner {\n private readonly rpId: string;\n private readonly rpName: string;\n\n constructor(opts: PasskeySignerOptions = {}) {\n if (typeof window === \"undefined\" || !navigator.credentials) {\n throw new Error(\"kit/passkey: WebAuthn is only available in a browser\");\n }\n this.rpId = opts.rpId ?? window.location.hostname;\n this.rpName = opts.rpName ?? this.rpId;\n // WebAuthn requires the RP ID to be a registrable domain (or \"localhost\").\n // An IP address always fails with a cryptic \"invalid domain\" — surface an\n // actionable message instead (common when devs test over a LAN IP).\n if (isIpAddress(this.rpId)) {\n throw new Error(\n `kit/passkey: passkeys can't use an IP address as the domain (\"${this.rpId}\"). ` +\n \"Use http://localhost, a real HTTPS domain, or a tunnel (cloudflared/ngrok) — \" +\n \"or pass an explicit `rpId`. (The silent device key works over an IP; passkeys don't.)\",\n );\n }\n }\n\n /** True if this platform advertises a usable passkey (platform authenticator). */\n static async isSupported(): Promise<boolean> {\n if (typeof window === \"undefined\" || !window.PublicKeyCredential) return false;\n try {\n return await window.PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();\n } catch {\n return false;\n }\n }\n\n /** Create a new synced passkey and return its P-256 public key. */\n async enroll(params: PasskeyEnrollParams): Promise<EnrolledPasskey> {\n const challenge = crypto.getRandomValues(new Uint8Array(32));\n const cred = (await navigator.credentials.create({\n publicKey: {\n challenge: buf(challenge),\n rp: { id: this.rpId, name: this.rpName },\n user: {\n id: buf(userHandle(params.userId)),\n name: params.userName,\n displayName: params.displayName ?? params.userName,\n },\n pubKeyCredParams: [{ type: \"public-key\", alg: -7 }], // ES256 (P-256)\n authenticatorSelection: {\n residentKey: \"required\",\n requireResidentKey: true,\n userVerification: \"preferred\",\n },\n attestation: \"none\",\n },\n })) as PublicKeyCredential | null;\n if (!cred) throw new Error(\"kit/passkey: enrollment cancelled\");\n\n const response = cred.response as AuthenticatorAttestationResponse;\n const spki = new Uint8Array(response.getPublicKey()!);\n return { publicKey: spkiToPublicKey(spki), credentialId: new Uint8Array(cred.rawId) };\n }\n\n /**\n * Produce a WebAuthn assertion over `challenge` (a 32-byte value the caller\n * derives from the signer being added + the on-chain nonce). Uses discoverable\n * credentials — no `allowCredentials` — so it works on a brand-new browser.\n */\n async assert(challenge: Uint8Array): Promise<PasskeyAssertion> {\n const cred = (await navigator.credentials.get({\n publicKey: {\n challenge: buf(challenge),\n rpId: this.rpId,\n allowCredentials: [],\n userVerification: \"preferred\",\n },\n })) as PublicKeyCredential | null;\n if (!cred) throw new Error(\"kit/passkey: assertion cancelled\");\n\n const response = cred.response as AuthenticatorAssertionResponse;\n const authenticatorData = new Uint8Array(response.authenticatorData);\n const clientDataJSON = new Uint8Array(response.clientDataJSON);\n const { r, s } = derToRs(new Uint8Array(response.signature));\n const challengeOffset = challengeOffsetOf(clientDataJSON, base64urlEncode(challenge));\n return { authenticatorData, clientDataJSON, r, s, challengeOffset };\n }\n}\n\n/**\n * WebAuthn requires the user handle to be 1..64 bytes. `userId` may be longer\n * (e.g. a 66-char Starknet address), so hash anything over 64 bytes to a stable\n * 32-byte handle. The handle is opaque — only its stability matters.\n */\n/** True for IPv4/IPv6 literals — WebAuthn rejects these as an RP ID. */\nfunction isIpAddress(host: string): boolean {\n if (/^\\d{1,3}(\\.\\d{1,3}){3}$/.test(host)) return true; // IPv4\n if (host.includes(\":\")) return true; // IPv6 literal\n return false;\n}\n\nfunction userHandle(userId: string): Uint8Array {\n const bytes = new TextEncoder().encode(userId);\n return bytes.length <= 64 ? bytes : sha256(bytes);\n}\n\n/** Coerce a `Uint8Array` to the `BufferSource` the WebAuthn DOM types want\n * (works around the TS5.7 `ArrayBufferLike` vs `ArrayBuffer` mismatch). */\nfunction buf(bytes: Uint8Array): BufferSource {\n return bytes.slice() as unknown as BufferSource;\n}\n"]}
1
+ {"version":3,"sources":["../src/auth/AuthProvider.ts"],"names":[],"mappings":";;;AA2BO,IAAM,iBAAN,MAA6C;AAAA,EAClD,YAA6B,QAAA,EAAoB;AAApB,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AAAA,EAAqB;AAAA,EAClD,MAAM,YAAA,GAAkC;AACtC,IAAA,OAAO,IAAA,CAAK,QAAA;AAAA,EACd;AACF","file":"index.mjs","sourcesContent":["/**\n * Identity for a Cavos wallet. Login (email / social / OTP) only ever produces a\n * stable `userId`; that's all the wallet needs to derive its address. Auth never\n * touches signing — the device key does that, silently.\n *\n * Privy-style UX: the user \"logs in\" and the wallet is provisioned behind the\n * scenes (device key + auto-deployed smart account). The app never handles keys.\n */\nexport interface Identity {\n /** Stable, backend-managed user identifier. */\n userId: string;\n /** Optional metadata (email, provider) for display only. */\n email?: string;\n provider?: \"google\" | \"apple\" | \"email\" | \"otp\" | string;\n}\n\n/**\n * Authenticates a user and returns their stable identity. Implementations:\n * - `CavosAuth` (hosted, mirrors `@cavos/react`: Google/Apple/email/OTP via the\n * Cavos backend) — the default, Privy-like experience.\n * - any custom provider (the app already authenticated the user elsewhere).\n */\nexport interface AuthProvider {\n authenticate(): Promise<Identity>;\n}\n\n/** Trivial provider when the app already has the user's stable id. */\nexport class StaticIdentity implements AuthProvider {\n constructor(private readonly identity: Identity) {}\n async authenticate(): Promise<Identity> {\n return this.identity;\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import react__default, { ReactNode } from 'react';
3
- import { k as Chain, u as NetworkEnv, j as CavosWallet, e as ChainCall, x as PasskeySigner, w as PasskeyEnrollParams } from '../Cavos-BH2_tOQ2.mjs';
3
+ import { k as Chain, u as NetworkEnv, j as CavosWallet, e as ChainCall, x as PasskeySigner, w as PasskeyEnrollParams } from '../Cavos-x9qFpOvJ.mjs';
4
4
  import 'starknet';
5
5
  import '@solana/web3.js';
6
6
  import '@stellar/stellar-sdk';
@@ -44,6 +44,12 @@ interface WalletStatus {
44
44
  awaitingApproval: boolean;
45
45
  /** The pending device-addition request id, when awaitingApproval. */
46
46
  pendingRequestId: string | null;
47
+ /** True if the account already has a passkey enrolled as an approver, so the
48
+ * modal can offer passkey approval over email on the new-device path. */
49
+ hasPasskey: boolean;
50
+ /** True right after a brand-new account is created (first sign-up), so the UI
51
+ * can offer a one-time "secure your account" step. Cleared once handled. */
52
+ isNewAccount: boolean;
47
53
  }
48
54
  interface UserInfo {
49
55
  userId: string;
@@ -56,12 +62,12 @@ interface CavosContextValue {
56
62
  closeModal: () => void;
57
63
  isAuthenticated: boolean;
58
64
  user: UserInfo | null;
59
- /** The active chain ('starknet' | 'solana'). */
65
+ /** The active chain ('starknet' | 'solana' | 'stellar'). */
60
66
  chain: Chain;
61
67
  /**
62
- * The raw connected wallet, discriminated by `wallet.chain`. Use this for
63
- * chain-native calls (e.g. Solana `wallet.execute(amount, dest)`); narrow on
64
- * `wallet.chain` first. Null until connected.
68
+ * The connected wallet, discriminated by `wallet.chain`. Narrow on
69
+ * `wallet.chain` before chain-native calls (e.g. Solana `wallet.execute(amount,
70
+ * dest)`). Null until connected.
65
71
  */
66
72
  wallet: CavosWallet | null;
67
73
  address: string | null;
@@ -82,7 +88,7 @@ interface CavosContextValue {
82
88
  verifyOtp: (email: string, code: string) => Promise<void>;
83
89
  /** Resolve identity from an OAuth callback (?auth_data=…) and deploy. */
84
90
  handleCallback: (authData: string) => Promise<void>;
85
- /** Execute a sponsored (gasless) multicall, signed by the device key. */
91
+ /** Execute a sponsored (gasless) multicall, signed by the device key (Starknet). */
86
92
  execute: (calls: ChainCall[]) => Promise<{
87
93
  transactionHash: string;
88
94
  }>;
@@ -96,9 +102,8 @@ interface CavosContextValue {
96
102
  /** Re-request the device-approval email for the current pending request. */
97
103
  resendDeviceApproval: () => Promise<void>;
98
104
  /**
99
- * Enroll a passkey as an approver (2FA-style step-up). Works on every chain.
100
- * Call this when you want to let users approve new devices from any browser.
101
- * Requires a ready device; returns the passkey's public key.
105
+ * Enroll a passkey as an approver (2FA-style step-up). Requires a ready device;
106
+ * returns the passkey's public key.
102
107
  */
103
108
  enrollPasskey: (passkey: PasskeySigner, params: PasskeyEnrollParams) => Promise<{
104
109
  publicKey: {
@@ -107,46 +112,49 @@ interface CavosContextValue {
107
112
  };
108
113
  transactionHash?: string;
109
114
  }>;
115
+ /** Whether this device can use a platform passkey (Face ID / Touch ID / PIN). */
116
+ passkeySupported: boolean;
110
117
  /**
111
- * From a fresh browser (status `needs-device-approval`), approve adding THIS
112
- * device using the user's synced passkey. Works on every chain (Starknet
113
- * requires a `submit` relayer callback; Solana/Stellar go through the
114
- * configured relayer). Returns the tx hash.
118
+ * Modal-friendly wrapper: enroll a synced passkey as an approver using the
119
+ * signed-in user's identity + the app name. Requires a ready device.
115
120
  */
116
- approveThisDeviceWithPasskey: (passkey: PasskeySigner, submit?: (call: ChainCall) => Promise<{
117
- transactionHash: string;
118
- }>) => Promise<{
119
- transactionHash: string;
120
- }>;
121
+ enrollPasskeyDefault: () => Promise<void>;
122
+ /**
123
+ * Modal-friendly wrapper for the new-device flow: prompt the user's synced
124
+ * passkey to approve THIS device, then refresh to a ready state. Sponsored by
125
+ * the default paymaster/relayer.
126
+ */
127
+ approveDeviceWithPasskey: () => Promise<void>;
121
128
  /**
122
- * Register a backup signer derived from `code` on the current account
123
- * (gasless). The code is generated by the kit and shown to the user once.
124
- * Resolves with the code so the caller can display it.
129
+ * Register a backup signer derived from a generated recovery code (gasless).
130
+ * Resolves with the code so the caller can display it once.
125
131
  */
126
132
  setupRecovery: () => Promise<string>;
127
133
  /**
128
- * Recover access after losing every device. Requires the recovery code. Runs
129
- * the full Cavos.recover flow and brings the provider to a ready state.
134
+ * Recover access after losing every device. Requires the recovery code. Brings
135
+ * the provider to a ready state.
130
136
  */
131
137
  recover: (code: string) => Promise<void>;
132
138
  logout: () => void;
133
139
  }
134
140
  interface CavosProviderProps {
141
+ /** A single chain config. The provider manages exactly one chain. */
135
142
  config: CavosConfig;
136
143
  modal?: CavosModalConfig;
137
144
  children: ReactNode;
138
145
  }
139
146
  /**
140
- * Drop-in Cavos provider. Wrap your app once; descendants call `useCavos()`.
147
+ * Drop-in Cavos provider for ONE chain. Wrap your app once; descendants call
148
+ * `useCavos()`.
141
149
  *
142
- * <CavosProvider config={{ network: 'sepolia', appSalt, paymasterApiKey }}
143
- * modal={{ appName: 'My App', theme: 'dark', emailMode: 'otp' }}>
150
+ * <CavosProvider config={{ chain: 'solana', network: 'testnet', appId, appSalt }}
151
+ * modal={{ appName: 'My App', theme: 'dark' }}>
144
152
  * <App />
145
153
  * </CavosProvider>
146
154
  *
147
155
  * Behind the scenes: login (social / email) resolves a stable identity, the kit
148
- * deploys a device-signer smart account gaslessly, and `execute()` submits
149
- * gasless multicalls signed silently by the browser's device key.
156
+ * deploys a device-signer smart account gaslessly, and the wallet handle submits
157
+ * gasless transactions signed silently by the browser's device key.
150
158
  */
151
159
  declare function CavosProvider({ config, modal, children }: CavosProviderProps): react.JSX.Element;
152
160
  declare function useCavos(): CavosContextValue;
@@ -1,6 +1,6 @@
1
1
  import * as react from 'react';
2
2
  import react__default, { ReactNode } from 'react';
3
- import { k as Chain, u as NetworkEnv, j as CavosWallet, e as ChainCall, x as PasskeySigner, w as PasskeyEnrollParams } from '../Cavos-BH2_tOQ2.js';
3
+ import { k as Chain, u as NetworkEnv, j as CavosWallet, e as ChainCall, x as PasskeySigner, w as PasskeyEnrollParams } from '../Cavos-x9qFpOvJ.js';
4
4
  import 'starknet';
5
5
  import '@solana/web3.js';
6
6
  import '@stellar/stellar-sdk';
@@ -44,6 +44,12 @@ interface WalletStatus {
44
44
  awaitingApproval: boolean;
45
45
  /** The pending device-addition request id, when awaitingApproval. */
46
46
  pendingRequestId: string | null;
47
+ /** True if the account already has a passkey enrolled as an approver, so the
48
+ * modal can offer passkey approval over email on the new-device path. */
49
+ hasPasskey: boolean;
50
+ /** True right after a brand-new account is created (first sign-up), so the UI
51
+ * can offer a one-time "secure your account" step. Cleared once handled. */
52
+ isNewAccount: boolean;
47
53
  }
48
54
  interface UserInfo {
49
55
  userId: string;
@@ -56,12 +62,12 @@ interface CavosContextValue {
56
62
  closeModal: () => void;
57
63
  isAuthenticated: boolean;
58
64
  user: UserInfo | null;
59
- /** The active chain ('starknet' | 'solana'). */
65
+ /** The active chain ('starknet' | 'solana' | 'stellar'). */
60
66
  chain: Chain;
61
67
  /**
62
- * The raw connected wallet, discriminated by `wallet.chain`. Use this for
63
- * chain-native calls (e.g. Solana `wallet.execute(amount, dest)`); narrow on
64
- * `wallet.chain` first. Null until connected.
68
+ * The connected wallet, discriminated by `wallet.chain`. Narrow on
69
+ * `wallet.chain` before chain-native calls (e.g. Solana `wallet.execute(amount,
70
+ * dest)`). Null until connected.
65
71
  */
66
72
  wallet: CavosWallet | null;
67
73
  address: string | null;
@@ -82,7 +88,7 @@ interface CavosContextValue {
82
88
  verifyOtp: (email: string, code: string) => Promise<void>;
83
89
  /** Resolve identity from an OAuth callback (?auth_data=…) and deploy. */
84
90
  handleCallback: (authData: string) => Promise<void>;
85
- /** Execute a sponsored (gasless) multicall, signed by the device key. */
91
+ /** Execute a sponsored (gasless) multicall, signed by the device key (Starknet). */
86
92
  execute: (calls: ChainCall[]) => Promise<{
87
93
  transactionHash: string;
88
94
  }>;
@@ -96,9 +102,8 @@ interface CavosContextValue {
96
102
  /** Re-request the device-approval email for the current pending request. */
97
103
  resendDeviceApproval: () => Promise<void>;
98
104
  /**
99
- * Enroll a passkey as an approver (2FA-style step-up). Works on every chain.
100
- * Call this when you want to let users approve new devices from any browser.
101
- * Requires a ready device; returns the passkey's public key.
105
+ * Enroll a passkey as an approver (2FA-style step-up). Requires a ready device;
106
+ * returns the passkey's public key.
102
107
  */
103
108
  enrollPasskey: (passkey: PasskeySigner, params: PasskeyEnrollParams) => Promise<{
104
109
  publicKey: {
@@ -107,46 +112,49 @@ interface CavosContextValue {
107
112
  };
108
113
  transactionHash?: string;
109
114
  }>;
115
+ /** Whether this device can use a platform passkey (Face ID / Touch ID / PIN). */
116
+ passkeySupported: boolean;
110
117
  /**
111
- * From a fresh browser (status `needs-device-approval`), approve adding THIS
112
- * device using the user's synced passkey. Works on every chain (Starknet
113
- * requires a `submit` relayer callback; Solana/Stellar go through the
114
- * configured relayer). Returns the tx hash.
118
+ * Modal-friendly wrapper: enroll a synced passkey as an approver using the
119
+ * signed-in user's identity + the app name. Requires a ready device.
115
120
  */
116
- approveThisDeviceWithPasskey: (passkey: PasskeySigner, submit?: (call: ChainCall) => Promise<{
117
- transactionHash: string;
118
- }>) => Promise<{
119
- transactionHash: string;
120
- }>;
121
+ enrollPasskeyDefault: () => Promise<void>;
122
+ /**
123
+ * Modal-friendly wrapper for the new-device flow: prompt the user's synced
124
+ * passkey to approve THIS device, then refresh to a ready state. Sponsored by
125
+ * the default paymaster/relayer.
126
+ */
127
+ approveDeviceWithPasskey: () => Promise<void>;
121
128
  /**
122
- * Register a backup signer derived from `code` on the current account
123
- * (gasless). The code is generated by the kit and shown to the user once.
124
- * Resolves with the code so the caller can display it.
129
+ * Register a backup signer derived from a generated recovery code (gasless).
130
+ * Resolves with the code so the caller can display it once.
125
131
  */
126
132
  setupRecovery: () => Promise<string>;
127
133
  /**
128
- * Recover access after losing every device. Requires the recovery code. Runs
129
- * the full Cavos.recover flow and brings the provider to a ready state.
134
+ * Recover access after losing every device. Requires the recovery code. Brings
135
+ * the provider to a ready state.
130
136
  */
131
137
  recover: (code: string) => Promise<void>;
132
138
  logout: () => void;
133
139
  }
134
140
  interface CavosProviderProps {
141
+ /** A single chain config. The provider manages exactly one chain. */
135
142
  config: CavosConfig;
136
143
  modal?: CavosModalConfig;
137
144
  children: ReactNode;
138
145
  }
139
146
  /**
140
- * Drop-in Cavos provider. Wrap your app once; descendants call `useCavos()`.
147
+ * Drop-in Cavos provider for ONE chain. Wrap your app once; descendants call
148
+ * `useCavos()`.
141
149
  *
142
- * <CavosProvider config={{ network: 'sepolia', appSalt, paymasterApiKey }}
143
- * modal={{ appName: 'My App', theme: 'dark', emailMode: 'otp' }}>
150
+ * <CavosProvider config={{ chain: 'solana', network: 'testnet', appId, appSalt }}
151
+ * modal={{ appName: 'My App', theme: 'dark' }}>
144
152
  * <App />
145
153
  * </CavosProvider>
146
154
  *
147
155
  * Behind the scenes: login (social / email) resolves a stable identity, the kit
148
- * deploys a device-signer smart account gaslessly, and `execute()` submits
149
- * gasless multicalls signed silently by the browser's device key.
156
+ * deploys a device-signer smart account gaslessly, and the wallet handle submits
157
+ * gasless transactions signed silently by the browser's device key.
150
158
  */
151
159
  declare function CavosProvider({ config, modal, children }: CavosProviderProps): react.JSX.Element;
152
160
  declare function useCavos(): CavosContextValue;