@cavos/kit 0.0.1 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -1,4 +1,6 @@
1
- export { BackupSigner, Cavos, CavosAuth, DEVICE_ACCOUNT_CLASS_HASH, HttpRecoveryClient, HttpWalletRegistry, InMemoryWalletRegistry, STARKNET_NETWORKS, StarknetAdapter, StarknetDeviceSigner, UDC_ADDRESS, WebCryptoSigner, bigIntTo32Bytes, bytesToBigInt, bytesToHex, deriveAddressSeed, deriveBackupKey, generateRecoveryCode, hexToBytes, recoverYParity, signatureToFelts, u256ToFelts } from './chunk-XWBX2ZIO.mjs';
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';
2
4
 
3
5
  // src/auth/AuthProvider.ts
4
6
  var StaticIdentity = class {
@@ -9,7 +11,91 @@ var StaticIdentity = class {
9
11
  return this.identity;
10
12
  }
11
13
  };
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
+ }
12
98
 
13
- export { StaticIdentity };
99
+ export { PasskeySigner, StaticIdentity };
14
100
  //# sourceMappingURL=index.mjs.map
15
101
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
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
+ {"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,18 +1,24 @@
1
1
  import * as react from 'react';
2
2
  import react__default, { ReactNode } from 'react';
3
- import { S as StarknetNetwork, C as ChainCall } from '../constants-C530TZFF.mjs';
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';
4
+ import 'starknet';
5
+ import '@solana/web3.js';
6
+ import '@stellar/stellar-sdk';
4
7
 
5
8
  interface CavosConfig {
6
9
  /** Cavos App ID from the dashboard. */
7
10
  appId?: string;
8
- network: StarknetNetwork;
11
+ /** Target chain. Defaults to 'starknet'. */
12
+ chain?: Chain;
13
+ /** Environment: 'testnet' (sepolia/devnet) or 'mainnet'. */
14
+ network: NetworkEnv;
9
15
  /** Per-app salt so the same user has distinct wallets per app. */
10
16
  appSalt: string;
11
- /** Cavos paymaster API key (sponsors deploy + execute). */
12
- paymasterApiKey: string;
17
+ /** Cavos paymaster API key (sponsors deploy + execute). Required for Starknet. */
18
+ paymasterApiKey?: string;
13
19
  /** Override the Cavos auth backend (self-hosted / staging). */
14
20
  authBackendUrl?: string;
15
- /** Override the Starknet RPC. */
21
+ /** Override the chain RPC. */
16
22
  rpcUrl?: string;
17
23
  }
18
24
  interface CavosModalConfig {
@@ -50,6 +56,14 @@ interface CavosContextValue {
50
56
  closeModal: () => void;
51
57
  isAuthenticated: boolean;
52
58
  user: UserInfo | null;
59
+ /** The active chain ('starknet' | 'solana'). */
60
+ chain: Chain;
61
+ /**
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.
65
+ */
66
+ wallet: CavosWallet | null;
53
67
  address: string | null;
54
68
  walletStatus: WalletStatus;
55
69
  isLoading: boolean;
@@ -81,6 +95,29 @@ interface CavosContextValue {
81
95
  }>;
82
96
  /** Re-request the device-approval email for the current pending request. */
83
97
  resendDeviceApproval: () => Promise<void>;
98
+ /**
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.
102
+ */
103
+ enrollPasskey: (passkey: PasskeySigner, params: PasskeyEnrollParams) => Promise<{
104
+ publicKey: {
105
+ x: bigint;
106
+ y: bigint;
107
+ };
108
+ transactionHash?: string;
109
+ }>;
110
+ /**
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.
115
+ */
116
+ approveThisDeviceWithPasskey: (passkey: PasskeySigner, submit?: (call: ChainCall) => Promise<{
117
+ transactionHash: string;
118
+ }>) => Promise<{
119
+ transactionHash: string;
120
+ }>;
84
121
  /**
85
122
  * Register a backup signer derived from `code` on the current account
86
123
  * (gasless). The code is generated by the kit and shown to the user once.
@@ -1,18 +1,24 @@
1
1
  import * as react from 'react';
2
2
  import react__default, { ReactNode } from 'react';
3
- import { S as StarknetNetwork, C as ChainCall } from '../constants-C530TZFF.js';
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';
4
+ import 'starknet';
5
+ import '@solana/web3.js';
6
+ import '@stellar/stellar-sdk';
4
7
 
5
8
  interface CavosConfig {
6
9
  /** Cavos App ID from the dashboard. */
7
10
  appId?: string;
8
- network: StarknetNetwork;
11
+ /** Target chain. Defaults to 'starknet'. */
12
+ chain?: Chain;
13
+ /** Environment: 'testnet' (sepolia/devnet) or 'mainnet'. */
14
+ network: NetworkEnv;
9
15
  /** Per-app salt so the same user has distinct wallets per app. */
10
16
  appSalt: string;
11
- /** Cavos paymaster API key (sponsors deploy + execute). */
12
- paymasterApiKey: string;
17
+ /** Cavos paymaster API key (sponsors deploy + execute). Required for Starknet. */
18
+ paymasterApiKey?: string;
13
19
  /** Override the Cavos auth backend (self-hosted / staging). */
14
20
  authBackendUrl?: string;
15
- /** Override the Starknet RPC. */
21
+ /** Override the chain RPC. */
16
22
  rpcUrl?: string;
17
23
  }
18
24
  interface CavosModalConfig {
@@ -50,6 +56,14 @@ interface CavosContextValue {
50
56
  closeModal: () => void;
51
57
  isAuthenticated: boolean;
52
58
  user: UserInfo | null;
59
+ /** The active chain ('starknet' | 'solana'). */
60
+ chain: Chain;
61
+ /**
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.
65
+ */
66
+ wallet: CavosWallet | null;
53
67
  address: string | null;
54
68
  walletStatus: WalletStatus;
55
69
  isLoading: boolean;
@@ -81,6 +95,29 @@ interface CavosContextValue {
81
95
  }>;
82
96
  /** Re-request the device-approval email for the current pending request. */
83
97
  resendDeviceApproval: () => Promise<void>;
98
+ /**
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.
102
+ */
103
+ enrollPasskey: (passkey: PasskeySigner, params: PasskeyEnrollParams) => Promise<{
104
+ publicKey: {
105
+ x: bigint;
106
+ y: bigint;
107
+ };
108
+ transactionHash?: string;
109
+ }>;
110
+ /**
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.
115
+ */
116
+ approveThisDeviceWithPasskey: (passkey: PasskeySigner, submit?: (call: ChainCall) => Promise<{
117
+ transactionHash: string;
118
+ }>) => Promise<{
119
+ transactionHash: string;
120
+ }>;
84
121
  /**
85
122
  * Register a backup signer derived from `code` on the current account
86
123
  * (gasless). The code is generated by the kit and shown to the user once.