@cef-ai/wallet-identity 1.0.0
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/README.md +64 -0
- package/dist/index.cjs +690 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +443 -0
- package/dist/index.d.ts +443 -0
- package/dist/index.js +667 -0
- package/dist/index.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/constants.ts","../src/browser.ts","../src/addresses.ts","../src/derive.ts","../src/base64url.ts","../src/ceremony.ts","../src/SoftAuthenticator.ts","../src/vault.ts","../src/pop.ts","../src/CrossTabSync.ts","../src/IdentityImpl.ts"],"names":["hkdf","sha256","ed25519","concatBytes","secp256k1"],"mappings":"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","file":"index.js","sourcesContent":["import { createHash } from 'node:crypto';\n\n/** Spec §3.2 locked decision #14. Permanent for v1; rotate via \"-v2\" suffix. */\nexport const PRF_INPUT_LABEL = 'cere-wallet-prf-v1';\n\n/**\n * SHA-256(\"cere-wallet-prf-v1\") — 32 bytes. Fed to WebAuthn `prf.eval.first`.\n *\n * Implementation note: `createHash` runs at module evaluation time. In the test\n * environment (Vitest on Node) this works natively via `node:crypto`. In the\n * browser this depends on a `node:crypto` polyfill — `vite-plugin-node-polyfills`\n * is wired in by Cycle 1 Task 8. A follow-up cycle should replace this expression\n * with a hard-coded `Uint8Array` literal to eliminate the polyfill dependency.\n */\nexport const PRF_INPUT_SEED: Uint8Array = new Uint8Array(createHash('sha256').update(PRF_INPUT_LABEL).digest());\n\n/** Spec §3.2. Used as HKDF-SHA256 info to derive the secp256k1 32-byte secret. */\nexport const EVM_HKDF_INFO = 'cere-wallet-evm-secp256k1-v1';\n","/**\n * Runtime support detection for WebAuthn + PRF.\n *\n * Spec §3.7. Real PRF capability is only knowable from a completed ceremony\n * (via `clientExtensionResults.prf.enabled` or `prf.results.first`). This\n * pre-check returns the best signal we can get without spending a credential.\n */\nexport interface PrfSupportResult {\n webAuthn: boolean;\n /**\n * Whether a platform authenticator (Touch ID / Windows Hello) is enrolled.\n * INFORMATIONAL ONLY — it is NOT a precondition for using the wallet, which\n * also works with roaming security keys and phone passkeys (via hybrid).\n */\n platformAuthenticator: boolean;\n /**\n * Best-effort PRF signal. `true` unless we can prove otherwise: modern\n * browsers expose `PublicKeyCredential.getClientCapabilities()`, which gives\n * a definitive `extensions:prf` answer. When that API is absent (older\n * browsers) we stay optimistic and let the ceremony be the final arbiter\n * (it throws `prf-unsupported` if the authenticator returns no PRF output).\n */\n prfPotentiallySupported: boolean;\n}\n\nexport async function detectPrfSupport(): Promise<PrfSupportResult> {\n const PKC = (globalThis as any).PublicKeyCredential;\n const webAuthn = typeof PKC !== 'undefined';\n if (!webAuthn) {\n return { webAuthn: false, platformAuthenticator: false, prfPotentiallySupported: false };\n }\n\n let platformAuthenticator = false;\n try {\n platformAuthenticator =\n typeof PKC.isUserVerifyingPlatformAuthenticatorAvailable === 'function' &&\n (await PKC.isUserVerifyingPlatformAuthenticatorAvailable());\n } catch {\n platformAuthenticator = false;\n }\n\n // Definitive PRF capability when the browser supports getClientCapabilities\n // (Chrome 133+, Safari 18+). Only a hard `false` blocks; absence keeps us\n // optimistic. We deliberately do NOT require a platform authenticator here.\n let prfPotentiallySupported = true;\n try {\n if (typeof PKC.getClientCapabilities === 'function') {\n const caps = await PKC.getClientCapabilities();\n if (caps && caps['extensions:prf'] === false) {\n prfPotentiallySupported = false;\n }\n }\n } catch {\n // Keep optimistic; the ceremony will surface prf-unsupported if needed.\n }\n\n return { webAuthn, platformAuthenticator, prfPotentiallySupported };\n}\n\n/**\n * Inspect a `PublicKeyCredential.getClientExtensionResults()` payload to\n * determine whether PRF actually worked in the ceremony. Spec §3.7 calls this\n * \"final answer; the pre-check above is best-effort only\".\n */\nexport function isPrfSupportedResult(extensions: {\n prf?: { enabled?: boolean; results?: { first?: Uint8Array } };\n}): boolean {\n const prf = extensions?.prf;\n if (!prf) return false;\n if (prf.enabled === true) return true;\n if (prf.results?.first instanceof Uint8Array) return true;\n return false;\n}\n","import bs58 from 'bs58';\nimport { blake2b } from '@noble/hashes/blake2b';\nimport { keccak_256 } from '@noble/hashes/sha3';\nimport { concatBytes } from '@noble/hashes/utils';\n\n/** Cere's SS58 network prefix. Spec §3.2. */\nexport const CERE_SS58_PREFIX = 54;\n\nconst SS58PRE = new TextEncoder().encode('SS58PRE');\n\n/**\n * SS58 address for the Cere network.\n *\n * SS58 spec (Substrate): for prefixes 0–63 the format is:\n * [prefix byte] || [32-byte pubkey] || [2-byte checksum]\n * where checksum = blake2b-512(\"SS58PRE\" || prefix || pubkey)[0..2].\n * The whole thing is base58-encoded. We use prefix 54 (Cere) which fits in\n * the 1-byte encoding (< 64).\n *\n * @param edPubkey 32-byte Ed25519 public key.\n */\nexport function deriveCereAddress(edPubkey: Uint8Array): string {\n if (edPubkey.length !== 32) {\n throw new Error(`expected 32-byte Ed25519 pubkey, got ${edPubkey.length}`);\n }\n const prefix = new Uint8Array([CERE_SS58_PREFIX]);\n const body = concatBytes(prefix, edPubkey);\n const checksum = blake2b(concatBytes(SS58PRE, body), { dkLen: 64 }).slice(0, 2);\n const payload = concatBytes(body, checksum);\n return bs58.encode(payload);\n}\n\n/**\n * Solana address: base58(Ed25519 pubkey). No prefix, no checksum.\n *\n * @param edPubkey 32-byte Ed25519 public key.\n */\nexport function deriveSolanaAddress(edPubkey: Uint8Array): string {\n if (edPubkey.length !== 32) {\n throw new Error(`expected 32-byte Ed25519 pubkey, got ${edPubkey.length}`);\n }\n return bs58.encode(edPubkey);\n}\n\n/**\n * Recover the raw 32-byte Ed25519 public key from a Solana address.\n *\n * The Solana address is `base58(edPubkey)` with no prefix or checksum\n * ({@link deriveSolanaAddress}), so a base58 decode yields the pubkey directly.\n * The public key is not secret — it IS the address — so this introduces no key\n * exposure beyond what the address already reveals; the session keys never\n * leave `SessionVault`. The same Ed25519 key backs the Cere SS58 address.\n *\n * @param solanaAddress base58 Solana address.\n * @returns the 32-byte Ed25519 public key.\n */\nexport function decodeEd25519Pubkey(solanaAddress: string): Uint8Array {\n const pubkey = bs58.decode(solanaAddress);\n if (pubkey.length !== 32) {\n throw new Error(`expected a 32-byte Ed25519 pubkey from the Solana address, got ${pubkey.length}`);\n }\n return pubkey;\n}\n\n/**\n * EVM address: '0x' + last 20 bytes of keccak256(secp256k1 uncompressed pubkey X||Y).\n *\n * Accepts either 64-byte (raw X||Y) or 65-byte (0x04||X||Y) input. The 0x04\n * prefix byte is stripped if present.\n *\n * @param secpPubkey secp256k1 public key.\n */\nexport function deriveEvmAddress(secpPubkey: Uint8Array): string {\n let xy: Uint8Array;\n if (secpPubkey.length === 65 && secpPubkey[0] === 0x04) {\n xy = secpPubkey.slice(1);\n } else if (secpPubkey.length === 64) {\n xy = secpPubkey;\n } else {\n throw new Error(`expected 64-byte (X||Y) or 65-byte (0x04||X||Y) secp256k1 pubkey, got ${secpPubkey.length}`);\n }\n const hash = keccak_256(xy);\n const last20 = hash.slice(12);\n return '0x' + Buffer.from(last20).toString('hex');\n}\n","import { ed25519 } from '@noble/curves/ed25519';\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport { hkdf } from '@noble/hashes/hkdf';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { EVM_HKDF_INFO } from './constants';\n\nexport interface DerivedKeys {\n /** Ed25519 32-byte secret key seed; used for Cere + Solana signing. */\n edSeed: Uint8Array;\n /** secp256k1 32-byte secret key; used for EVM signing. */\n secpKey: Uint8Array;\n /** 32-byte Ed25519 public key derived from edSeed. */\n edPubkey: Uint8Array;\n /** 65-byte uncompressed secp256k1 public key (0x04 || X || Y) derived from secpKey. */\n secpPubkeyUncompressed: Uint8Array;\n}\n\n/**\n * Derive the v2 session keys from a WebAuthn PRF output. Spec §3.2.\n *\n * edSeed = prfOutput\n * secpKey = HKDF-SHA256(prfOutput, salt=\"\", info=\"cere-wallet-evm-secp256k1-v1\", L=32)\n *\n * @param prfOutput 32-byte PRF output from `prf.results.first`.\n */\nexport function derivedKeys(prfOutput: Uint8Array): DerivedKeys {\n if (prfOutput.length !== 32) {\n throw new Error(`expected 32-byte PRF output, got ${prfOutput.length}`);\n }\n const edSeed = new Uint8Array(prfOutput); // copy to detach from caller's buffer\n const secpKey = hkdf(sha256, prfOutput, new Uint8Array(0), EVM_HKDF_INFO, 32);\n\n const edPubkey = ed25519.getPublicKey(edSeed);\n // @noble/curves exposes both compressed and uncompressed forms; we want uncompressed.\n const secpPubkeyUncompressed = secp256k1.getPublicKey(secpKey, false);\n\n return { edSeed, secpKey, edPubkey, secpPubkeyUncompressed };\n}\n","/**\n * Base64url (RFC 4648 §5) helpers used by the WebAuthn ceremony adapter.\n * Trailing `=` padding is stripped on encode; both padded and unpadded inputs\n * are accepted on decode.\n */\n\n/** Encode a Uint8Array or ArrayBuffer as a base64url string (no padding). */\nexport function bytesToB64u(input: Uint8Array | ArrayBuffer): string {\n const bytes = input instanceof Uint8Array ? input : new Uint8Array(input);\n let bin = '';\n for (let i = 0; i < bytes.length; i++) bin += String.fromCharCode(bytes[i]);\n const b64 = btoa(bin);\n return b64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\n/** Decode a base64url string into a Uint8Array. Padding is optional. */\nexport function b64uToBytes(s: string): Uint8Array {\n const b64 = s.replace(/-/g, '+').replace(/_/g, '/');\n const padded = b64 + '='.repeat((4 - (b64.length % 4)) % 4);\n const bin = atob(padded); // throws DOMException on invalid input — correct behavior\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n","import { bytesToB64u, b64uToBytes } from './base64url';\n\n/**\n * `hints` is a top-level field on the WebAuthn creation/request options\n * (WebAuthn L3), but our TS DOM lib doesn't ship it yet. Declare-merge the\n * precise W3C union so the ceremony can request authenticator hints without\n * casts. Drop this augmentation once the workspace lib.dom.d.ts ships `hints`.\n */\ndeclare global {\n interface PublicKeyCredentialCreationOptions {\n hints?: ('client-device' | 'hybrid' | 'security-key')[];\n }\n interface PublicKeyCredentialRequestOptions {\n hints?: ('client-device' | 'hybrid' | 'security-key')[];\n }\n}\n\n/**\n * Adapter that runs WebAuthn ceremonies. Production implementations call\n * `navigator.credentials.create/get`; the test implementation in\n * `SoftAuthenticator` produces deterministic results without browser APIs.\n *\n * Spec §3.7. The `prfOutput` field is the result of the WebAuthn PRF extension\n * — present when the authenticator supports PRF, absent otherwise.\n */\nexport interface CeremonyAdapter {\n register(opts: RegisterOptions): Promise<RegisterResult>;\n login(opts: LoginOptions): Promise<LoginResult>;\n}\n\nexport interface RegisterOptions {\n rpId: string;\n challenge: Uint8Array;\n userHandle: Uint8Array;\n /** 32-byte PRF input (typically `PRF_INPUT_SEED`). */\n prfInput: Uint8Array;\n /** Human-readable label for the credential. Currently a hint, not stored. */\n label?: string;\n}\n\nexport interface RegisterResult {\n credentialId: string; // base64url\n clientDataJSON: string; // base64url\n attestationObject: string; // base64url\n transports: string[];\n /** Present iff PRF extension worked. */\n prfOutput?: Uint8Array;\n}\n\nexport interface LoginOptions {\n rpId: string;\n challenge: Uint8Array;\n /** Optional: if absent, the authenticator picks a credential. Present from us. */\n credentialId?: string;\n prfInput: Uint8Array;\n}\n\nexport interface LoginResult {\n credentialId: string;\n clientDataJSON: string;\n authenticatorData: string;\n signature: string;\n prfOutput?: Uint8Array;\n}\n\nexport interface WebAuthnCeremonyAdapterOptions {\n /**\n * Override for the WebAuthn credentials manager. Defaults to\n * `globalThis.navigator?.credentials`. Tests inject a mock.\n */\n credentials?: CredentialsContainer;\n}\n\n/**\n * Authenticator selection `hints` (WebAuthn L3, Chrome/Edge/Safari 18+).\n *\n * These bias the browser's passkey picker toward authenticators that\n * reliably support the PRF extension — platform authenticators (Touch ID /\n * Windows Hello / Android), phone passkeys (hybrid), and security keys.\n *\n * Hints are *preferences, not filters*: a software password-manager passkey\n * (e.g. Bitwarden, 1Password) still appears in the picker, just de-prioritized.\n * On a machine with Touch ID enrolled this makes \"This device\" the default\n * choice, so users no longer land on Bitwarden's passkey (which can't satisfy\n * PRF and fails the ceremony with `prf-unsupported`). The post-ceremony\n * `prfOutput` check remains the real capability gate.\n */\nconst PRF_CAPABLE_HINTS = ['client-device', 'hybrid', 'security-key'] as const;\n\n/**\n * Production WebAuthn ceremony adapter. Calls `navigator.credentials.create/get`\n * with the PRF extension. Spec §3.7.\n *\n * - `register`: requires a platform authenticator, user verification, Ed25519\n * (`alg: -8`), and the PRF extension with the wallet's input seed.\n * - `login`: allows a specific credentialId if known; otherwise lets the\n * authenticator pick (resident key).\n *\n * Returned ArrayBuffers are base64url-encoded for API transport.\n */\nexport class WebAuthnCeremonyAdapter implements CeremonyAdapter {\n private readonly credentials?: CredentialsContainer;\n\n constructor(opts: WebAuthnCeremonyAdapterOptions = {}) {\n this.credentials = opts.credentials ?? (globalThis as any).navigator?.credentials;\n }\n\n async register(opts: RegisterOptions): Promise<RegisterResult> {\n if (!this.credentials) {\n throw new Error('WebAuthnCeremonyAdapter: navigator.credentials is unavailable');\n }\n const cred = (await this.credentials.create({\n publicKey: {\n challenge: opts.challenge,\n rp: { id: opts.rpId, name: opts.rpId },\n user: {\n id: opts.userHandle,\n name: opts.label ?? 'scp-wallet',\n displayName: opts.label ?? 'SCP Wallet',\n },\n pubKeyCredParams: [\n { alg: -8, type: 'public-key' }, // EdDSA (Ed25519 security keys) — preferred\n { alg: -7, type: 'public-key' }, // ES256 (Apple/Windows/Android platform authenticators)\n ],\n authenticatorSelection: {\n // No `authenticatorAttachment`: allow platform authenticators\n // (Touch ID / Windows Hello), roaming security keys, and phone\n // passkeys via hybrid — PRF works across all of them, and the\n // pubKeyCredParams above explicitly prefer Ed25519 security keys.\n // The post-ceremony PRF result is the real capability gate.\n userVerification: 'required',\n residentKey: 'preferred',\n },\n // Bias the picker toward PRF-capable authenticators so the user\n // doesn't default onto a password-manager passkey. See PRF_CAPABLE_HINTS.\n hints: [...PRF_CAPABLE_HINTS],\n timeout: 60_000,\n extensions: { prf: { eval: { first: opts.prfInput } } } as AuthenticationExtensionsClientInputs,\n },\n })) as PublicKeyCredential | null;\n if (!cred) {\n throw new Error('WebAuthnCeremonyAdapter.register: credentials.create returned null');\n }\n\n const response = cred.response as AuthenticatorAttestationResponse;\n const transports = typeof response.getTransports === 'function' ? response.getTransports() : [];\n const ext = cred.getClientExtensionResults() as { prf?: { results?: { first?: ArrayBuffer } } };\n const prfFirst = ext?.prf?.results?.first;\n\n return {\n credentialId: cred.id,\n clientDataJSON: bytesToB64u(response.clientDataJSON),\n attestationObject: bytesToB64u(response.attestationObject),\n transports,\n prfOutput: prfFirst ? new Uint8Array(prfFirst) : undefined,\n };\n }\n\n async login(opts: LoginOptions): Promise<LoginResult> {\n if (!this.credentials) {\n throw new Error('WebAuthnCeremonyAdapter: navigator.credentials is unavailable');\n }\n const cred = (await this.credentials.get({\n publicKey: {\n challenge: opts.challenge,\n rpId: opts.rpId,\n allowCredentials: opts.credentialId ? [{ id: b64uToBytes(opts.credentialId), type: 'public-key' }] : undefined,\n userVerification: 'required',\n // Bias first-login-on-device (no allowCredentials) toward PRF-capable\n // authenticators, mirroring register. See PRF_CAPABLE_HINTS.\n hints: [...PRF_CAPABLE_HINTS],\n timeout: 60_000,\n extensions: { prf: { eval: { first: opts.prfInput } } } as AuthenticationExtensionsClientInputs,\n },\n })) as PublicKeyCredential | null;\n if (!cred) {\n throw new Error('WebAuthnCeremonyAdapter.login: credentials.get returned null');\n }\n\n const response = cred.response as AuthenticatorAssertionResponse;\n const ext = cred.getClientExtensionResults() as { prf?: { results?: { first?: ArrayBuffer } } };\n const prfFirst = ext?.prf?.results?.first;\n\n return {\n credentialId: cred.id,\n clientDataJSON: bytesToB64u(response.clientDataJSON),\n authenticatorData: bytesToB64u(response.authenticatorData),\n signature: bytesToB64u(response.signature),\n prfOutput: prfFirst ? new Uint8Array(prfFirst) : undefined,\n };\n }\n}\n","import { ed25519 } from '@noble/curves/ed25519';\nimport { sha256 } from '@noble/hashes/sha256';\nimport { hkdf } from '@noble/hashes/hkdf';\nimport { concatBytes } from '@noble/hashes/utils';\nimport type { CeremonyAdapter, RegisterOptions, RegisterResult, LoginOptions, LoginResult } from './ceremony';\n\n/** base64url encode without padding. */\nfunction b64u(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString('base64').replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n}\n\ninterface StoredCredential {\n credentialId: string;\n edSeed: Uint8Array;\n prfSecret: Uint8Array;\n}\n\nexport interface SoftAuthenticatorOptions {\n /**\n * If provided, derive the per-registration `edSeed`, `prfSecret`, and\n * `credentialId` deterministically from this seed (mixed with a monotonic\n * counter so multiple register() calls on the same instance still produce\n * distinct credentials). Used by Playwright e2e specs that pin server-side\n * address stubs against the SoftAuthenticator's output. Production code\n * never sets this — the `useSoft` branch in `createIdentity.ts` is itself\n * forbidden in production builds.\n *\n * Default: undefined (each register() draws fresh CSPRNG bytes, matching\n * the pre-cycle-8.1 behavior used by unit tests in `ceremony.test.ts`).\n */\n seed?: string;\n\n /**\n * When the caller invokes login() without a credentialId, fall back to the\n * most-recently-registered credential in memory. Default: false (login()\n * throws when credentialId is missing, matching pre-cycle-8 behavior).\n *\n * Required for e2e flows that simulate the user signing back in after the\n * vault has been cleared (post-logout re-login): the wallet has discarded\n * the credentialId locally, but the soft authenticator's in-memory creds\n * map still holds the registration, and the spec test needs login() to\n * succeed anyway. Production code must never enable this — real WebAuthn's\n * no-allowCredentials path shows an OS credential picker; the fallback\n * here is a deterministic test convenience, not a real picker, so leaving\n * it on by default would silently let a single registered credential\n * impersonate any login.\n */\n fallbackToLastRegistered?: boolean;\n}\n\n/**\n * Deterministic in-memory WebAuthn authenticator for tests. NOT for production.\n *\n * - Stores credentials in a private Map keyed by credentialId.\n * - `prfOutput` is computed as HKDF-SHA256(prfSecret, salt=\"\", info=prfInput, L=32),\n * so for a given credential and prfInput the result is stable across login calls.\n * - `signature` is a valid Ed25519 signature over `authenticatorData || sha256(clientDataJSON)`.\n *\n * The output shapes match the real WebAuthn response well enough that the\n * `Identity` integration tests (Task 6) can drive register → login → derive\n * → cross-check without a real browser.\n */\nexport class SoftAuthenticator implements CeremonyAdapter {\n private readonly creds: Map<string, StoredCredential> = new Map();\n private readonly seedBytes: Uint8Array | null;\n private readonly fallbackToLastRegistered: boolean;\n /** Monotonic counter mixed into the seed-derived material so successive\n * register() calls on a seeded instance produce distinct credentials. */\n private regCounter = 0;\n\n constructor(opts: SoftAuthenticatorOptions = {}) {\n this.seedBytes = opts.seed != null ? new TextEncoder().encode(opts.seed) : null;\n this.fallbackToLastRegistered = opts.fallbackToLastRegistered === true;\n }\n\n async register(opts: RegisterOptions): Promise<RegisterResult> {\n // Generate per-credential material. When seeded, derive deterministically\n // via HKDF-SHA256(seed, salt=<counter>, info=<purpose>) so the e2e specs\n // can pin server-side address stubs against the resulting addresses.\n let edSeed: Uint8Array;\n let prfSecret: Uint8Array;\n let credentialIdBytes: Uint8Array;\n if (this.seedBytes) {\n const salt = new TextEncoder().encode(`reg-${this.regCounter++}`);\n edSeed = hkdf(sha256, this.seedBytes, salt, 'ed-seed', 32);\n prfSecret = hkdf(sha256, this.seedBytes, salt, 'prf-secret', 32);\n credentialIdBytes = hkdf(sha256, this.seedBytes, salt, 'credential-id', 16);\n } else {\n edSeed = ed25519.utils.randomPrivateKey();\n prfSecret = ed25519.utils.randomPrivateKey(); // 32 random bytes\n credentialIdBytes = ed25519.utils.randomPrivateKey().slice(0, 16); // 16-byte id\n }\n const credentialId = b64u(credentialIdBytes);\n\n this.creds.set(credentialId, { credentialId, edSeed, prfSecret });\n\n // Compose the WebAuthn-shaped artifacts. These are NOT spec-correct attestations;\n // they're test fixtures whose only requirement is to round-trip through identity.\n const clientData = {\n type: 'webauthn.create',\n challenge: b64u(opts.challenge),\n origin: `https://${opts.rpId}`,\n crossOrigin: false,\n };\n const clientDataJSON = new TextEncoder().encode(JSON.stringify(clientData));\n const attestationObject = new Uint8Array([0xaa]); // placeholder; not parsed by client tests\n\n const prfOutput = this.computePrf(prfSecret, opts.prfInput);\n\n return {\n credentialId,\n clientDataJSON: b64u(clientDataJSON),\n attestationObject: b64u(attestationObject),\n transports: ['internal'],\n prfOutput,\n };\n }\n\n async login(opts: LoginOptions): Promise<LoginResult> {\n // Two modes:\n // 1. Explicit credentialId (the common path, including IdentityImpl's\n // warm-vault re-mint flow): look it up and throw on miss.\n // 2. No credentialId: by default this is an error (pre-cycle-8 behaviour),\n // because a silent \"pick the last one\" is a security trap if it ever\n // leaks into production. Callers that genuinely need the fallback\n // (Playwright post-logout re-login) opt in via\n // `new SoftAuthenticator({ fallbackToLastRegistered: true })`.\n let stored: StoredCredential | undefined;\n if (opts.credentialId) {\n stored = this.creds.get(opts.credentialId);\n if (!stored) {\n throw new Error(`SoftAuthenticator.login: unknown credential ${opts.credentialId}`);\n }\n } else {\n if (!this.fallbackToLastRegistered) {\n throw new Error(\n 'SoftAuthenticator.login: credentialId is required ' +\n '(set `fallbackToLastRegistered: true` in the constructor to opt into the e2e convenience of picking the most-recently-registered credential)',\n );\n }\n const all = Array.from(this.creds.values());\n stored = all[all.length - 1];\n if (!stored) {\n throw new Error('SoftAuthenticator.login: no credentials registered');\n }\n }\n\n const clientData = {\n type: 'webauthn.get',\n challenge: b64u(opts.challenge),\n origin: `https://${opts.rpId}`,\n crossOrigin: false,\n };\n const clientDataJSON = new TextEncoder().encode(JSON.stringify(clientData));\n\n // Minimal authenticatorData: 32-byte rpIdHash || 1-byte flags || 4-byte signCount.\n // We don't need a real rpIdHash for client-side tests.\n const authenticatorData = new Uint8Array(37);\n authenticatorData[32] = 0x05; // UP + UV flags\n\n const clientDataHash = sha256(clientDataJSON);\n const toSign = concatBytes(authenticatorData, clientDataHash);\n const signature = ed25519.sign(toSign, stored.edSeed);\n\n const prfOutput = this.computePrf(stored.prfSecret, opts.prfInput);\n\n return {\n credentialId: stored.credentialId,\n clientDataJSON: b64u(clientDataJSON),\n authenticatorData: b64u(authenticatorData),\n signature: b64u(signature),\n prfOutput,\n };\n }\n\n /** Public-key bytes for a credential. Used by integration tests for cross-checks. */\n getEd25519PublicKey(credentialId: string): Uint8Array {\n const stored = this.creds.get(credentialId);\n if (!stored) throw new Error(`unknown credential ${credentialId}`);\n return ed25519.getPublicKey(stored.edSeed);\n }\n\n private computePrf(prfSecret: Uint8Array, prfInput: Uint8Array): Uint8Array {\n // Deterministic per (prfSecret, prfInput) — matches the spirit of how a real\n // authenticator's PRF extension works (HKDF-style mixing of a per-credential\n // secret with the caller's input). NOT identical to any real authenticator.\n return hkdf(sha256, prfSecret, new Uint8Array(0), prfInput, 32);\n }\n}\n","import { ed25519 } from '@noble/curves/ed25519';\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport type { DerivedKeys } from './derive';\nimport type { Addresses, Chain } from './types';\n\nexport interface VaultSnapshot {\n addresses: Addresses;\n credentialId: string;\n}\n\nexport interface SessionVault {\n isOpen(): boolean;\n /** Public-safe view: never includes raw keys. */\n snapshot(): VaultSnapshot | null;\n /** Open the vault with derived keys + the addresses they yielded + the credentialId. */\n set(args: { keys: DerivedKeys; addresses: Addresses; credentialId: string }): void;\n /** Drop the keys and address state. Safe to call when already closed. */\n clear(): void;\n /**\n * Sign a payload with the chain-appropriate key. Spec §3.6 invariant:\n * this is the only way the rest of the package can reach the keys.\n *\n * - 'cere' / 'solana': Ed25519 signature over the raw payload (64 bytes).\n * - 'evm': secp256k1 ECDSA over the raw payload (65 bytes: r || s || v).\n * The caller (an EVM signer) is responsible for framing (e.g. EIP-191)\n * and hashing (keccak256) before passing the digest as the payload.\n */\n sign(chain: Chain, payload: Uint8Array): Promise<Uint8Array>;\n}\n\n/**\n * Closure-encapsulated session vault. The keys live in the closure variables\n * `state.edSeed` / `state.secpKey` and are not reachable from outside.\n *\n * Spec §3.4. Lifetime: from `set()` until `clear()` or tab unload.\n */\nexport function createSessionVault(): SessionVault {\n let state: {\n edSeed: Uint8Array;\n secpKey: Uint8Array;\n addresses: Addresses;\n credentialId: string;\n } | null = null;\n\n return {\n isOpen() {\n return state !== null;\n },\n snapshot() {\n if (!state) return null;\n return { addresses: state.addresses, credentialId: state.credentialId };\n },\n set({ keys, addresses, credentialId }) {\n state = {\n edSeed: new Uint8Array(keys.edSeed),\n secpKey: new Uint8Array(keys.secpKey),\n addresses,\n credentialId,\n };\n },\n clear() {\n if (state) {\n state.edSeed.fill(0);\n state.secpKey.fill(0);\n }\n state = null;\n },\n async sign(chain, payload) {\n if (!state) {\n throw new Error('SessionVault: closed — no session keys available');\n }\n if (chain === 'cere' || chain === 'solana') {\n return ed25519.sign(payload, state.edSeed);\n }\n if (chain === 'evm') {\n // Caller (chain-specific signer) is responsible for framing + hashing.\n // We sign the payload directly and return 65 bytes: r (32) || s (32) || v (1),\n // where v is the recovery byte (0 or 1). Spec §3.6 invariant 1 holds —\n // the secpKey never leaves this closure.\n const sig = secp256k1.sign(payload, state.secpKey);\n const compact = sig.toCompactRawBytes(); // 64 bytes (r || s)\n const v = sig.recovery; // 0 or 1\n const out = new Uint8Array(65);\n out.set(compact, 0);\n out[64] = v;\n return out;\n }\n throw new Error(`SessionVault.sign: unknown chain \"${String(chain)}\"`);\n },\n };\n}\n","import { ed25519 } from '@noble/curves/ed25519';\nimport { secp256k1 } from '@noble/curves/secp256k1';\nimport type { DerivedKeys } from './derive';\n\nexport interface RegistrationProof {\n /** ed25519 signature (64B) over the raw challenge — proves cere + solana. */\n identitySig: Uint8Array;\n /** secp256k1 uncompressed pubkey (65B, 0x04 || X || Y). */\n evmPubkey: Uint8Array;\n /** secp256k1 compact r||s signature (64B) over the raw challenge. */\n evmSig: Uint8Array;\n}\n\n/**\n * Sign the single-use registration challenge with the PRF-derived keys to\n * prove possession of the chain identity. The server (wallet-api)\n * verifies these against the claimed addresses. Spec §3.3 (revised).\n *\n * - ed25519: sign the raw 32-byte challenge (EdDSA hashes internally).\n * - secp256k1: ECDSA over the 32-byte challenge treated as the message digest\n * (matches the server's `ecdsa.Verify(challenge, pubkey)`). The challenge is\n * 32 random single-use bytes, so it is passed directly as the prehashed\n * digest — NOT re-hashed (no `{ prehash: true }`). low-S is enforced by\n * @noble's default, so the compact form is canonical.\n */\nexport function signRegistrationProof(keys: DerivedKeys, challenge: Uint8Array): RegistrationProof {\n const identitySig = ed25519.sign(challenge, keys.edSeed);\n const evmSig = secp256k1.sign(challenge, keys.secpKey).toCompactRawBytes();\n return { identitySig, evmPubkey: keys.secpPubkeyUncompressed, evmSig };\n}\n","/**\n * Cross-tab session synchronisation helper.\n *\n * Wraps a `BroadcastChannel` on a fixed channel name so all tabs of the same\n * origin can coordinate. Today we only use it for `{ type: 'logout' }` — when\n * one tab logs out, every other tab clears its in-memory vault + JWT so its\n * MobX-reactive UI immediately reflects the logged-out state.\n *\n * The channel name must match `BROADCAST_CHANNEL_NAME` in\n * `packages/embed-sdk/src/protocol.ts` ('scp-wallet-v2'). Defined here as a\n * local constant rather than imported to avoid a circular dep between\n * `@cef-ai/wallet-identity` and `@cef-ai/wallet`. The name is part of the\n * wire protocol — if you change one, change the other (and bump the major).\n *\n * Spec §9.4 (cross-tab session sharing).\n */\n\n/** MUST match `packages/embed-sdk/src/protocol.ts` `BROADCAST_CHANNEL_NAME`. */\nconst CHANNEL_NAME = 'scp-wallet-v2';\n\nexport type CrossTabMessage = { type: 'logout' };\n\nexport class CrossTabSync {\n private channel: BroadcastChannel | null;\n private readonly listeners = new Set<(msg: CrossTabMessage) => void>();\n\n constructor() {\n // SSR / Node-without-BroadcastChannel safety. The class becomes a no-op\n // (broadcast() returns silently, subscribe() returns a real unsub that\n // just empties the local set, close() is a no-op).\n if (typeof BroadcastChannel === 'undefined') {\n this.channel = null;\n return;\n }\n this.channel = new BroadcastChannel(CHANNEL_NAME);\n this.channel.onmessage = (ev: MessageEvent) => {\n const msg = ev.data as CrossTabMessage | undefined;\n if (!msg || typeof msg !== 'object' || typeof (msg as { type?: unknown }).type !== 'string') {\n return;\n }\n for (const fn of this.listeners) {\n try {\n fn(msg);\n } catch {\n // Listener errors must not break the channel for other listeners.\n }\n }\n };\n }\n\n /** Broadcast a message to all other tabs (and not to this tab — that's the\n * BroadcastChannel spec). The originating tab is expected to have already\n * applied the state change locally before broadcasting. */\n broadcast(msg: CrossTabMessage): void {\n this.channel?.postMessage(msg);\n }\n\n /** Subscribe to messages from other tabs. Returns an unsubscribe function. */\n subscribe(fn: (msg: CrossTabMessage) => void): () => void {\n this.listeners.add(fn);\n return () => {\n this.listeners.delete(fn);\n };\n }\n\n /**\n * Close the underlying channel and drop all listeners. Idempotent.\n *\n * Sets `this.channel = null` so subsequent `broadcast()` calls become a\n * no-op (the `?.postMessage` short-circuits) and we don't accidentally\n * postMessage on a closed BroadcastChannel (which throws InvalidStateError\n * in some implementations).\n */\n close(): void {\n this.channel?.close();\n this.channel = null;\n this.listeners.clear();\n }\n}\n","import { observable, runInAction } from 'mobx';\nimport { WalletError, type ApiClient, type Addresses as ApiAddresses } from '@cef-ai/wallet-api-client';\nimport type { Identity, Addresses } from './types';\nimport type { CeremonyAdapter } from './ceremony';\nimport { createSessionVault, type SessionVault } from './vault';\nimport { derivedKeys } from './derive';\nimport { signRegistrationProof } from './pop';\nimport { bytesToB64u } from './base64url';\nimport { deriveCereAddress, deriveSolanaAddress, deriveEvmAddress } from './addresses';\nimport { PRF_INPUT_SEED } from './constants';\nimport { CrossTabSync } from './CrossTabSync';\n\nexport interface IdentityImplOptions {\n apiClient: ApiClient;\n ceremony: CeremonyAdapter;\n}\n\n/** Minimum slack before expiry where we treat the JWT as \"needs refresh\". */\nconst JWT_REFRESH_SLACK_MS = 60_000;\n\nfunction decodeJwtExpMs(token: string): number {\n const parts = token.split('.');\n if (parts.length < 2) {\n throw new WalletError('validation', 'JWT does not have 3 parts');\n }\n const payloadB64 = parts[1];\n const payload = JSON.parse(Buffer.from(payloadB64.replace(/-/g, '+').replace(/_/g, '/'), 'base64').toString('utf8'));\n if (typeof payload.exp !== 'number') {\n throw new WalletError('validation', 'JWT missing exp');\n }\n return payload.exp * 1000;\n}\n\nfunction b64uDecode(s: string): Uint8Array {\n return Uint8Array.from(Buffer.from(s.replace(/-/g, '+').replace(/_/g, '/'), 'base64'));\n}\n\nexport class IdentityImpl implements Identity {\n private readonly vault: SessionVault = createSessionVault();\n private cachedJwt: { token: string; expMs: number } | null = null;\n /** Server-returned credential ID (used as the public identity.credentialId). */\n private serverCredentialId: string | null = null;\n\n // Public observable state — derived from vault snapshot + serverCredentialId.\n // Kept in sync via syncPublicState() so React `observer()` wrappers around\n // components reading isAuthenticated/addresses/credentialId actually re-render\n // on register/login/logout. The vault itself stays non-observable (security:\n // the closure-encapsulated keys must not be tracked by MobX).\n private readonly _isAuthenticated = observable.box(false);\n // `deep: false` keeps the stored value a plain object instead of wrapping it\n // in a MobX proxy. addresses is a wholesale-replaced snapshot (never mutated\n // field-by-field), so deep observability buys nothing — and a proxy is not\n // structured-cloneable, which breaks `postMessage` when the embed popup\n // bridge sends addresses to the host page (wallet:login:ok).\n private readonly _addresses = observable.box<Addresses | null>(null, { deep: false });\n private readonly _credentialId = observable.box<string | null>(null);\n\n /** Cross-tab logout coordination via BroadcastChannel('scp-wallet-v2'). */\n private readonly crossTabSync = new CrossTabSync();\n /** Handle to detach the cross-tab logout subscriber on dispose(). */\n private readonly crossTabSyncUnsubscribe: () => void;\n /** Idempotency flag for dispose(). */\n private disposed = false;\n\n constructor(private readonly opts: IdentityImplOptions) {\n // Hydrate the boxes from any existing vault snapshot. Currently the vault\n // starts closed, so this is a no-op — but it's the right call site for a\n // future BroadcastChannel-restored session.\n this.syncPublicState();\n // Cross-tab logout: when another tab broadcasts {type:'logout'}, mirror it\n // locally so this tab's MobX-bound UI re-renders without a page reload.\n // The `vault.isOpen()` guard prevents the originating tab from\n // double-clearing — by the time its own listener fires (BroadcastChannel\n // doesn't deliver to the sender, but defence-in-depth), the vault is\n // already closed. The guard also makes the listener a no-op for tabs\n // that were already signed out.\n //\n // Capture the unsubscribe handle so dispose() can detach this subscriber\n // before closing the channel — without this, a long-lived test suite or\n // a hot-reloaded SPA leaks listener closures into the next IdentityImpl.\n this.crossTabSyncUnsubscribe = this.crossTabSync.subscribe((msg) => {\n if (msg.type === 'logout' && this.vault.isOpen()) {\n this.vault.clear();\n this.cachedJwt = null;\n this.serverCredentialId = null;\n this.syncPublicState();\n }\n });\n }\n\n get isAuthenticated(): boolean {\n return this._isAuthenticated.get();\n }\n\n get addresses(): Addresses | null {\n return this._addresses.get();\n }\n\n /**\n * Returns the server-returned credentialId from the last register/login ceremony.\n * The vault internally tracks the authenticator-generated credential ID for login use.\n */\n get credentialId(): string | null {\n return this._credentialId.get();\n }\n\n /**\n * Read the (non-observable) vault snapshot + cached server credential ID and\n * push the values into the three public observable boxes. Call after any\n * mutation that could change the public derived state: register, login,\n * logout, or constructor (hydration).\n */\n private syncPublicState(): void {\n const snap = this.vault.snapshot();\n runInAction(() => {\n this._isAuthenticated.set(this.vault.isOpen());\n this._addresses.set(snap?.addresses ?? null);\n this._credentialId.set(this.serverCredentialId);\n });\n }\n\n async register(opts: { label?: string } = {}): Promise<void> {\n // 1. Start ceremony — get the challenge from the API.\n // The client-derived addresses are determined post-ceremony from the PRF\n // output. The server only needs them at /finish; at /start we send a\n // placeholder that the server ignores. (Per API.md, /start accepts the\n // addresses field but the load-bearing check is at /finish.)\n const start = await this.opts.apiClient.passkey.registerStart({\n addresses: { cere: '5GplaceholderClientCannotKnowYet' } as any,\n label: opts.label,\n });\n\n // 2. Run the ceremony.\n const cer = await this.opts.ceremony.register({\n rpId: start.rpId,\n challenge: b64uDecode(start.challenge),\n userHandle: b64uDecode(start.userHandle),\n prfInput: PRF_INPUT_SEED,\n label: opts.label,\n });\n if (!cer.prfOutput) {\n throw new WalletError('prf-unsupported', 'authenticator did not return a PRF output');\n }\n\n // 3. Derive keys + addresses locally.\n const keys = derivedKeys(cer.prfOutput);\n const clientAddresses: Addresses = {\n cere: deriveCereAddress(keys.edPubkey),\n solana: deriveSolanaAddress(keys.edPubkey),\n evm: deriveEvmAddress(keys.secpPubkeyUncompressed),\n };\n\n // 4. Prove possession of the PRF-derived chain keys by signing the\n // single-use challenge. The server binds addresses.{cere,solana,evm}\n // to these signatures (proof-of-possession), not to the WebAuthn\n // credential key. Spec §3.3 (revised).\n const proof = signRegistrationProof(keys, b64uDecode(start.challenge));\n\n // 5. Finish ceremony with the API.\n const finish = await this.opts.apiClient.passkey.registerFinish({\n challengeId: start.challengeId,\n clientDataJSON: cer.clientDataJSON,\n attestationObject: cer.attestationObject,\n addresses: clientAddresses,\n transports: cer.transports,\n identitySig: bytesToB64u(proof.identitySig),\n evmPubkey: bytesToB64u(proof.evmPubkey),\n evmSig: bytesToB64u(proof.evmSig),\n });\n\n // 6. Cross-check returned addresses against locally-derived. Spec §3.3.\n this.crossCheckAddresses(clientAddresses, finish.addresses);\n\n // 7. Install the vault + cache the JWT.\n // The vault stores the authenticator-generated credential ID (cer.credentialId)\n // so subsequent login() calls can pass it back to the same authenticator.\n // The server-returned credential ID is tracked separately for the public getter.\n this.vault.set({\n keys,\n addresses: clientAddresses,\n credentialId: cer.credentialId,\n });\n this.serverCredentialId = finish.credentialId;\n this.cachedJwt = { token: finish.token, expMs: decodeJwtExpMs(finish.token) };\n this.syncPublicState();\n }\n\n async login(): Promise<void> {\n const start = await this.opts.apiClient.passkey.loginStart();\n\n const cer = await this.opts.ceremony.login({\n rpId: start.rpId,\n challenge: b64uDecode(start.challenge),\n credentialId: this.vault.snapshot()?.credentialId,\n prfInput: PRF_INPUT_SEED,\n });\n if (!cer.prfOutput) {\n throw new WalletError('prf-unsupported', 'authenticator did not return a PRF output');\n }\n\n const keys = derivedKeys(cer.prfOutput);\n const clientAddresses: Addresses = {\n cere: deriveCereAddress(keys.edPubkey),\n solana: deriveSolanaAddress(keys.edPubkey),\n evm: deriveEvmAddress(keys.secpPubkeyUncompressed),\n };\n\n const finish = await this.opts.apiClient.passkey.loginFinish({\n challengeId: start.challengeId,\n credentialId: cer.credentialId,\n clientDataJSON: cer.clientDataJSON,\n authenticatorData: cer.authenticatorData,\n signature: cer.signature,\n });\n\n this.crossCheckAddresses(clientAddresses, finish.addresses);\n\n this.vault.set({\n keys,\n addresses: clientAddresses,\n credentialId: cer.credentialId,\n });\n this.serverCredentialId = finish.credentialId;\n this.cachedJwt = { token: finish.token, expMs: decodeJwtExpMs(finish.token) };\n this.syncPublicState();\n }\n\n logout(): void {\n this.vault.clear();\n this.cachedJwt = null;\n this.serverCredentialId = null;\n this.syncPublicState();\n // Broadcast AFTER clearing local state so other tabs converge on the same\n // post-logout snapshot. BroadcastChannel does not deliver to the sender,\n // so this tab won't re-enter the subscriber callback above.\n this.crossTabSync.broadcast({ type: 'logout' });\n }\n\n async getJwt(): Promise<string> {\n if (this.cachedJwt && Date.now() < this.cachedJwt.expMs - JWT_REFRESH_SLACK_MS) {\n return this.cachedJwt.token;\n }\n if (!this.vault.isOpen()) {\n throw new WalletError('unauthorized', 'session is closed; call register() or login() first');\n }\n // Vault is warm but JWT is stale — re-run login to mint a fresh JWT.\n await this.login();\n return this.cachedJwt!.token;\n }\n\n /** Helper used by callers (e.g. ApiClient.getAuthToken). */\n getCachedJwtForApiClient(): string | null {\n return this.cachedJwt?.token ?? null;\n }\n\n /**\n * Returns the session vault. Used by popup-side `wallet:sign` handlers\n * which need direct access to `vault.sign(chain, payload)`. NOT for host-\n * side use — keys never reach the host. Spec §3.6 invariant 1.\n */\n getVault(): SessionVault {\n return this.vault;\n }\n\n /**\n * Release the BroadcastChannel + cross-tab subscriber. Idempotent.\n *\n * Called by:\n * - WalletProvider's useEffect cleanup (SPA unmount / apiBaseUrl change)\n * - test afterEach hooks (prevent listener leakage across tests)\n *\n * After dispose(), the identity is unusable: register/login/logout/getJwt\n * still execute their normal logic, but cross-tab broadcasts no longer\n * propagate (channel is closed) and the local subscriber is detached.\n * The vault remains cleared (logout() runs locally). Spec §9.4 lifecycle.\n */\n dispose(): void {\n if (this.disposed) return;\n this.disposed = true;\n // Detach subscriber first so any in-flight onmessage from this channel\n // does not re-enter the now-closing identity.\n this.crossTabSyncUnsubscribe();\n this.crossTabSync.close();\n }\n\n // ---- private --------------------------------------------------------------\n\n private crossCheckAddresses(client: Addresses, server: ApiAddresses | undefined): void {\n if (!server) {\n throw new WalletError('derivation-mismatch', 'API did not return addresses');\n }\n if (server.cere != null && client.cere !== server.cere) {\n throw new WalletError('derivation-mismatch', `Cere mismatch: client=${client.cere} api=${server.cere}`);\n }\n if (server.solana != null && client.solana !== server.solana) {\n throw new WalletError('derivation-mismatch', `Solana mismatch: client=${client.solana} api=${server.solana}`);\n }\n if (server.evm != null && client.evm.toLowerCase() !== server.evm.toLowerCase()) {\n throw new WalletError('derivation-mismatch', `EVM mismatch: client=${client.evm} api=${server.evm}`);\n }\n }\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@cef-ai/wallet-identity",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Passkey-native identity for SCP Wallet — soft authenticator, key derivation, cross-tab session sync.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/cere-io/cere-wallet-client.git",
|
|
9
|
+
"directory": "packages/identity"
|
|
10
|
+
},
|
|
11
|
+
"sideEffects": false,
|
|
12
|
+
"type": "module",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": {
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"default": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"require": {
|
|
21
|
+
"types": "./dist/index.d.cts",
|
|
22
|
+
"default": "./dist/index.cjs"
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"files": [
|
|
27
|
+
"dist",
|
|
28
|
+
"README.md"
|
|
29
|
+
],
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@noble/curves": "^1.6.0",
|
|
32
|
+
"@noble/hashes": "^1.5.0",
|
|
33
|
+
"bs58": "^6.0.0",
|
|
34
|
+
"mobx": "^6.6.2",
|
|
35
|
+
"@cef-ai/wallet-api-client": "1.0.0"
|
|
36
|
+
},
|
|
37
|
+
"devDependencies": {
|
|
38
|
+
"happy-dom": "^15.7.0",
|
|
39
|
+
"msw": "^2.6.0"
|
|
40
|
+
},
|
|
41
|
+
"scripts": {
|
|
42
|
+
"test": "vitest run",
|
|
43
|
+
"check-types": "tsc --noEmit",
|
|
44
|
+
"build": "tsup"
|
|
45
|
+
},
|
|
46
|
+
"main": "./dist/index.cjs",
|
|
47
|
+
"module": "./dist/index.js"
|
|
48
|
+
}
|