@permissionless-technologies/upp-sdk 0.5.6 → 0.6.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/dist/chunk-2GKW4UCQ.js +234 -0
- package/dist/chunk-2GKW4UCQ.js.map +1 -0
- package/dist/chunk-36LLQN63.js +83 -0
- package/dist/chunk-36LLQN63.js.map +1 -0
- package/dist/{chunk-C3HXJ5A6.cjs → chunk-47FETLYV.cjs} +17 -3
- package/dist/chunk-47FETLYV.cjs.map +1 -0
- package/dist/{chunk-2NKFTLPD.js → chunk-7GDDA5VR.js} +17 -3
- package/dist/chunk-7GDDA5VR.js.map +1 -0
- package/dist/chunk-CCWMVO3H.cjs +249 -0
- package/dist/chunk-CCWMVO3H.cjs.map +1 -0
- package/dist/{chunk-UHMHZQZV.js → chunk-D6C2OOOC.js} +2 -2
- package/dist/{chunk-UHMHZQZV.js.map → chunk-D6C2OOOC.js.map} +1 -1
- package/dist/{chunk-HVSP62AH.cjs → chunk-IETMGF5J.cjs} +2 -2
- package/dist/{chunk-HVSP62AH.cjs.map → chunk-IETMGF5J.cjs.map} +1 -1
- package/dist/{chunk-NGXEIUQ6.cjs → chunk-MZDCTYGM.cjs} +4 -4
- package/dist/{chunk-NGXEIUQ6.cjs.map → chunk-MZDCTYGM.cjs.map} +1 -1
- package/dist/{chunk-CRUJLZV7.js → chunk-PJBEE2OI.js} +84 -19
- package/dist/chunk-PJBEE2OI.js.map +1 -0
- package/dist/chunk-PXCVNAWP.cjs +91 -0
- package/dist/chunk-PXCVNAWP.cjs.map +1 -0
- package/dist/{chunk-A6IYQ7UF.js → chunk-QYF2A5SO.js} +3 -3
- package/dist/{chunk-A6IYQ7UF.js.map → chunk-QYF2A5SO.js.map} +1 -1
- package/dist/{chunk-P6E3LE7T.cjs → chunk-SEAXI5UO.cjs} +84 -16
- package/dist/chunk-SEAXI5UO.cjs.map +1 -0
- package/dist/core/index.cjs +113 -113
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +3 -3
- package/dist/{index-DY0XAmFw.d.ts → index-B03HwFbO.d.ts} +16 -5
- package/dist/{index-DOiHUft6.d.cts → index-BSaHIJzn.d.cts} +16 -5
- package/dist/{index-KTJgQUxb.d.cts → index-BafRK5nW.d.cts} +11 -2
- package/dist/{index-DLvLv3mg.d.ts → index-DndOuerz.d.ts} +11 -2
- package/dist/index.cjs +204 -175
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -5
- package/dist/index.d.ts +6 -5
- package/dist/index.js +6 -5
- package/dist/index.js.map +1 -1
- package/dist/indexer/index.cjs +11 -11
- package/dist/indexer/index.d.cts +7 -6
- package/dist/indexer/index.d.ts +7 -6
- package/dist/indexer/index.js +1 -1
- package/dist/keys/index.cjs +56 -27
- package/dist/keys/index.d.cts +33 -3
- package/dist/keys/index.d.ts +33 -3
- package/dist/keys/index.js +2 -1
- package/dist/passkey-Df4lrhN5.d.cts +77 -0
- package/dist/passkey-ZnoYRP-r.d.ts +77 -0
- package/dist/react/index.cjs +262 -129
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +24 -4
- package/dist/react/index.d.ts +24 -4
- package/dist/react/index.js +218 -100
- package/dist/react/index.js.map +1 -1
- package/dist/transfer-7PPJAS3X.js +9 -0
- package/dist/{transfer-2UYFZMIK.js.map → transfer-7PPJAS3X.js.map} +1 -1
- package/dist/{transfer-6OW3XKVC.cjs → transfer-ZZ263JLF.cjs} +13 -9
- package/dist/{transfer-6OW3XKVC.cjs.map → transfer-ZZ263JLF.cjs.map} +1 -1
- package/dist/{transfer-C1XU_z-6.d.cts → transfer-_qaZXsv7.d.cts} +1 -0
- package/dist/{transfer-DgjxZlR7.d.ts → transfer-x7UChjh7.d.ts} +1 -0
- package/dist/{types-CJSbxv4q.d.cts → types-9MmVALxO.d.cts} +1 -1
- package/dist/{types-mLybMxNR.d.ts → types-CI4nEY9S.d.ts} +1 -1
- package/package.json +1 -1
- package/src/deployments/31337.json +14 -14
- package/dist/chunk-2NKFTLPD.js.map +0 -1
- package/dist/chunk-C3HXJ5A6.cjs.map +0 -1
- package/dist/chunk-CRUJLZV7.js.map +0 -1
- package/dist/chunk-FTEXUSHR.js +0 -150
- package/dist/chunk-FTEXUSHR.js.map +0 -1
- package/dist/chunk-LKXC3OQT.cjs +0 -165
- package/dist/chunk-LKXC3OQT.cjs.map +0 -1
- package/dist/chunk-P6E3LE7T.cjs.map +0 -1
- package/dist/transfer-2UYFZMIK.js +0 -9
|
@@ -464,12 +464,26 @@ function deserializeAccount(data) {
|
|
|
464
464
|
}
|
|
465
465
|
return { keys, starkKeys };
|
|
466
466
|
}
|
|
467
|
-
var StorableAccountAdapter = class {
|
|
467
|
+
var StorableAccountAdapter = class _StorableAccountAdapter {
|
|
468
468
|
constructor(storage, ethAddress) {
|
|
469
469
|
this.storage = storage;
|
|
470
470
|
this.storageKey = `account_${ethAddress.toLowerCase()}`;
|
|
471
471
|
}
|
|
472
472
|
storageKey;
|
|
473
|
+
/**
|
|
474
|
+
* Create an adapter keyed by a passkey credential ID instead of an Ethereum address.
|
|
475
|
+
*
|
|
476
|
+
* Uses `account_passkey_` prefix to avoid collisions with wallet-based accounts.
|
|
477
|
+
*
|
|
478
|
+
* @param storage - Storage backend (IndexedDB, localStorage, etc.)
|
|
479
|
+
* @param credentialId - Base64url-encoded WebAuthn credential ID
|
|
480
|
+
*/
|
|
481
|
+
static forPasskey(storage, credentialId) {
|
|
482
|
+
const adapter = Object.create(_StorableAccountAdapter.prototype);
|
|
483
|
+
adapter.storage = storage;
|
|
484
|
+
adapter.storageKey = `account_passkey_${credentialId.slice(0, 32)}`;
|
|
485
|
+
return adapter;
|
|
486
|
+
}
|
|
473
487
|
async load() {
|
|
474
488
|
const data = await this.storage.get(this.storageKey);
|
|
475
489
|
if (!data) return null;
|
|
@@ -671,5 +685,5 @@ function safeGetAddress(addr) {
|
|
|
671
685
|
}
|
|
672
686
|
|
|
673
687
|
export { ADDRESS_VERSION, DirectAccountAdapter, NoteStore, ProofWorkerManager, RATE_PRECISION, STARK_ADDRESS_VERSION, STARK_STEALTH_ADDRESS_PREFIX, STEALTH_ADDRESS_PREFIX, SWAP_EVENTS_ABI, SWAP_ORDER_CANCELLED_EVENT, SWAP_ORDER_CLAIMED_EVENT, SWAP_ORDER_FILLED_EVENT, SWAP_ORDER_PLACED_EVENT, StorableAccountAdapter, computeCancelKeyHash, computeFillPercentage, computeGiveAmount, computeNoteEncryptionKey, computeRate, computeTakeAmount, computeTotalBuyAmount, createOneTimeKeys, decodeStarkStealthAddress, decodeStealthAddress, detectAddressType, encodeStarkStealthAddress, encodeStealthAddress, filterOrdersByASP, filterOrdersByTokenPair, formatRate, generateCancelSecret, generateStarkStealthAddress, generateStealthAddress, generateUPPProofAsync, getCancelSecret, getOwnOrderIds, init_stealth, isFillerASPAccepted, isOrderActive, isValidStarkStealthAddress, isValidStealthAddress, removeCancelSecret, stealth_exports, storeCancelSecret, verifyOwnership };
|
|
674
|
-
//# sourceMappingURL=chunk-
|
|
675
|
-
//# sourceMappingURL=chunk-
|
|
688
|
+
//# sourceMappingURL=chunk-7GDDA5VR.js.map
|
|
689
|
+
//# sourceMappingURL=chunk-7GDDA5VR.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/stealth.ts","../src/core/proof-worker.ts","../src/core/swap.ts","../src/core/account.ts","../src/core/note-store.ts"],"names":["ownerHash","toHex"],"mappings":"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","file":"chunk-7GDDA5VR.js","sourcesContent":["/**\n * Stealth Address Utilities (Post-Quantum, Hash-Based)\n *\n * Implements stealth addresses using Poseidon hashes with bech32m encoding.\n * No BabyJubJub curve operations — ownership is proven via hash preimage.\n *\n * Address Format (bech32m):\n * 0zk1<version><chainId><ownerHash><viewingHash>\n *\n * Key Flow (self-shield):\n * 1. User derives ownerHash = Poseidon(spendingSecret)\n * 2. Commitment = Poseidon(amount, ownerHash, blinding, origin, token)\n * 3. Encrypt note with key derived from viewingSecret\n *\n * Key Flow (send to others, future):\n * 1. Decode recipient's stealth address (ownerHash, viewingHash)\n * 2. Generate per-note secret and derive ownerHash for the note\n * 3. Encrypt note so recipient's viewingSecret can decrypt\n */\n\nimport { bech32m } from 'bech32'\nimport {\n randomFieldElement,\n bigintToBytes,\n bytesToBigint,\n} from '../utils/crypto.js'\nimport type { MasterKeys, StarkMasterKeys, OneTimeKeys } from '../keys/types.js'\nimport type { M31Digest } from '../utils/keccak-m31.js'\n\n/**\n * Stealth address prefix\n */\nexport const STEALTH_ADDRESS_PREFIX = '0zk'\n\n/**\n * Address version (v2 = hash-based, post-quantum)\n */\nexport const ADDRESS_VERSION = 2\n\n/**\n * Maximum length for bech32m encoding\n */\nconst BECH32M_LIMIT = 1023\n\n/**\n * Encode a stealth address in bech32m format\n *\n * Format: 0zk1<version><chainId><ownerHash><viewingHash>\n *\n * @param ownerHash - Owner hash = Poseidon(spendingSecret)\n * @param viewingHash - Viewing hash = Poseidon(viewingSecret)\n * @param chainId - Optional chain ID (0 = any chain)\n * @returns bech32m encoded stealth address\n */\nexport function encodeStealthAddress(\n ownerHash: bigint,\n viewingHash: bigint,\n chainId: number = 0\n): string {\n // Build data buffer: version (1 byte) + chainId (4 bytes) + 2 * 32 bytes = 69 bytes\n const data = new Uint8Array(1 + 4 + 32 * 2)\n let offset = 0\n\n // Version\n data[offset++] = ADDRESS_VERSION\n\n // Chain ID (4 bytes, big-endian)\n data[offset++] = (chainId >> 24) & 0xff\n data[offset++] = (chainId >> 16) & 0xff\n data[offset++] = (chainId >> 8) & 0xff\n data[offset++] = chainId & 0xff\n\n // Owner hash (32 bytes)\n const ownerBytes = bigintToBytes(ownerHash, 32)\n data.set(ownerBytes, offset)\n offset += 32\n\n // Viewing hash (32 bytes)\n const viewingBytes = bigintToBytes(viewingHash, 32)\n data.set(viewingBytes, offset)\n\n // Convert to 5-bit words for bech32m\n const words = bech32m.toWords(data)\n\n // Encode with prefix\n return bech32m.encode(STEALTH_ADDRESS_PREFIX, words, BECH32M_LIMIT)\n}\n\n/**\n * Decode a bech32m stealth address\n *\n * @param address - bech32m encoded stealth address\n * @returns Decoded hash values\n */\nexport function decodeStealthAddress(address: string): {\n version: number\n chainId: number\n ownerHash: bigint\n viewingHash: bigint\n} {\n // Decode bech32m\n const decoded = bech32m.decode(address, BECH32M_LIMIT)\n\n // Verify prefix\n if (decoded.prefix !== STEALTH_ADDRESS_PREFIX) {\n throw new Error(`Invalid stealth address prefix: expected '${STEALTH_ADDRESS_PREFIX}', got '${decoded.prefix}'`)\n }\n\n // Convert from 5-bit words back to bytes\n const data = new Uint8Array(bech32m.fromWords(decoded.words))\n\n // Parse version\n let offset = 0\n const version = data[offset++]!\n\n if (version !== ADDRESS_VERSION) {\n throw new Error(`Unsupported address version: ${version}. Expected v${ADDRESS_VERSION} (hash-based).`)\n }\n\n // Parse chain ID\n const chainId =\n (data[offset++]! << 24) |\n (data[offset++]! << 16) |\n (data[offset++]! << 8) |\n data[offset++]!\n\n // Parse owner hash (32 bytes)\n const ownerHash = bytesToBigint(data.slice(offset, offset + 32))\n offset += 32\n\n // Parse viewing hash (32 bytes)\n const viewingHash = bytesToBigint(data.slice(offset, offset + 32))\n\n return {\n version,\n chainId,\n ownerHash,\n viewingHash,\n }\n}\n\n/**\n * Validate a stealth address format\n */\nexport function isValidStealthAddress(address: string): boolean {\n try {\n decodeStealthAddress(address)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Generate stealth address from master keys\n */\nexport function generateStealthAddress(keys: MasterKeys, chainId: number = 0): string {\n return encodeStealthAddress(keys.ownerHash, keys.viewingHash, chainId)\n}\n\n/**\n * Create one-time keys for a transaction (hash-based)\n *\n * For self-shield: the user uses their own spendingSecret directly\n * as the ownerSecret, producing ownerHash = Poseidon(spendingSecret).\n *\n * For sending to others (future): generate a random oneTimeSecret\n * and derive ownerHash = Poseidon(oneTimeSecret).\n *\n * @param recipientOwnerHash - Recipient's owner hash (for verification)\n * @param selfSecret - If self-shield, the user's spending secret\n * @returns One-time keys for the note\n */\nexport async function createOneTimeKeys(\n _recipientOwnerHash?: bigint,\n selfSecret?: bigint,\n): Promise<OneTimeKeys> {\n const { poseidon } = await import('../utils/poseidon.js')\n\n if (selfSecret !== undefined) {\n // Self-shield: use own spending secret\n const ownerHash = await poseidon([selfSecret])\n return {\n oneTimeSecret: selfSecret,\n ownerHash,\n }\n }\n\n // Generate random one-time secret for the note\n const oneTimeSecret = randomFieldElement()\n const ownerHash = await poseidon([oneTimeSecret])\n\n return {\n oneTimeSecret,\n ownerHash,\n }\n}\n\n/**\n * Verify ownership of a note by checking hash preimage\n *\n * @param secret - Claimed spending secret\n * @param expectedOwnerHash - Owner hash from the note commitment\n * @returns True if the secret hashes to the expected owner hash\n */\nexport async function verifyOwnership(\n secret: bigint,\n expectedOwnerHash: bigint\n): Promise<boolean> {\n const { poseidon } = await import('../utils/poseidon.js')\n const computedHash = await poseidon([secret])\n return computedHash === expectedOwnerHash\n}\n\n/**\n * Compute shared secret for note encryption/decryption (hash-based)\n *\n * For self-shield: just uses the viewing secret directly.\n * For sending to others (future): use Poseidon(viewingSecret, recipientViewingHash)\n *\n * @param viewingSecret - Sender's or recipient's viewing secret\n * @param nonce - Optional nonce for key derivation\n * @returns Encryption key as bigint\n */\nexport async function computeNoteEncryptionKey(\n viewingSecret: bigint,\n nonce?: bigint\n): Promise<bigint> {\n const { poseidon } = await import('../utils/poseidon.js')\n if (nonce !== undefined) {\n return poseidon([viewingSecret, nonce])\n }\n return poseidon([viewingSecret])\n}\n\n// =========================================================================\n// STARK Stealth Addresses (0zs prefix, M31/Keccak-based)\n// =========================================================================\n\n/**\n * STARK stealth address prefix\n */\nexport const STARK_STEALTH_ADDRESS_PREFIX = '0zs'\n\n/**\n * STARK address version (v1 = M31/Keccak)\n */\nexport const STARK_ADDRESS_VERSION = 1\n\n/**\n * Encode a STARK stealth address in bech32m format\n *\n * Format: 0zs1<version><chainId><ownerHash[0..3]><viewingHash[0..3]>\n *\n * Each M31 element is encoded as 4 bytes (little-endian).\n * Total data: 1 (version) + 4 (chainId) + 16 (ownerHash) + 16 (viewingHash) = 37 bytes.\n *\n * @param ownerHash - 4 M31 elements: keccak_m31(starkSecret)\n * @param viewingHash - 4 M31 elements: keccak_m31(starkViewingSecret)\n * @param chainId - Optional chain ID (0 = any chain)\n */\nexport function encodeStarkStealthAddress(\n ownerHash: M31Digest,\n viewingHash: M31Digest,\n chainId: number = 0\n): string {\n const data = new Uint8Array(1 + 4 + 16 + 16) // 37 bytes\n let offset = 0\n\n // Version\n data[offset++] = STARK_ADDRESS_VERSION\n\n // Chain ID (4 bytes, big-endian)\n data[offset++] = (chainId >> 24) & 0xff\n data[offset++] = (chainId >> 16) & 0xff\n data[offset++] = (chainId >> 8) & 0xff\n data[offset++] = chainId & 0xff\n\n // Owner hash: 4 M31 elements, each 4 bytes LE\n for (let i = 0; i < 4; i++) {\n const val = Number(ownerHash[i]!)\n data[offset++] = val & 0xff\n data[offset++] = (val >> 8) & 0xff\n data[offset++] = (val >> 16) & 0xff\n data[offset++] = (val >> 24) & 0xff\n }\n\n // Viewing hash: 4 M31 elements, each 4 bytes LE\n for (let i = 0; i < 4; i++) {\n const val = Number(viewingHash[i]!)\n data[offset++] = val & 0xff\n data[offset++] = (val >> 8) & 0xff\n data[offset++] = (val >> 16) & 0xff\n data[offset++] = (val >> 24) & 0xff\n }\n\n const words = bech32m.toWords(data)\n return bech32m.encode(STARK_STEALTH_ADDRESS_PREFIX, words, BECH32M_LIMIT)\n}\n\n/**\n * Decode a STARK stealth address (0zs prefix)\n */\nexport function decodeStarkStealthAddress(address: string): {\n version: number\n chainId: number\n ownerHash: M31Digest\n viewingHash: M31Digest\n} {\n const decoded = bech32m.decode(address, BECH32M_LIMIT)\n\n if (decoded.prefix !== STARK_STEALTH_ADDRESS_PREFIX) {\n throw new Error(\n `Invalid STARK stealth address prefix: expected '${STARK_STEALTH_ADDRESS_PREFIX}', got '${decoded.prefix}'`\n )\n }\n\n const data = new Uint8Array(bech32m.fromWords(decoded.words))\n let offset = 0\n\n const version = data[offset++]!\n if (version !== STARK_ADDRESS_VERSION) {\n throw new Error(\n `Unsupported STARK address version: ${version}. Expected v${STARK_ADDRESS_VERSION}.`\n )\n }\n\n // Chain ID\n const chainId =\n (data[offset++]! << 24) |\n (data[offset++]! << 16) |\n (data[offset++]! << 8) |\n data[offset++]!\n\n // Owner hash: 4 M31 LE uint32s\n const ownerHash: bigint[] = []\n for (let i = 0; i < 4; i++) {\n const val =\n data[offset]! |\n (data[offset + 1]! << 8) |\n (data[offset + 2]! << 16) |\n (data[offset + 3]! << 24)\n ownerHash.push(BigInt(val >>> 0))\n offset += 4\n }\n\n // Viewing hash: 4 M31 LE uint32s\n const viewingHash: bigint[] = []\n for (let i = 0; i < 4; i++) {\n const val =\n data[offset]! |\n (data[offset + 1]! << 8) |\n (data[offset + 2]! << 16) |\n (data[offset + 3]! << 24)\n viewingHash.push(BigInt(val >>> 0))\n offset += 4\n }\n\n return {\n version,\n chainId,\n ownerHash: ownerHash as unknown as M31Digest,\n viewingHash: viewingHash as unknown as M31Digest,\n }\n}\n\n/**\n * Validate a STARK stealth address format\n */\nexport function isValidStarkStealthAddress(address: string): boolean {\n try {\n decodeStarkStealthAddress(address)\n return true\n } catch {\n return false\n }\n}\n\n/**\n * Generate a STARK stealth address from STARK master keys\n */\nexport function generateStarkStealthAddress(\n keys: StarkMasterKeys,\n chainId: number = 0\n): string {\n return encodeStarkStealthAddress(keys.starkOwnerHash, keys.starkViewingHash, chainId)\n}\n\n/**\n * Detect whether an address is SNARK (0zk) or STARK (0zs)\n */\nexport function detectAddressType(address: string): 'snark' | 'stark' | 'unknown' {\n if (address.startsWith(STEALTH_ADDRESS_PREFIX + '1')) return 'snark'\n if (address.startsWith(STARK_STEALTH_ADDRESS_PREFIX + '1')) return 'stark'\n return 'unknown'\n}\n","/**\n * Proof Worker Manager — off-main-thread PLONK proof generation.\n *\n * Manages a Web Worker that runs snarkjs proof generation, keeping the\n * main thread (and UI) responsive during the 10-30s proving time.\n *\n * @example\n * ```ts\n * // Create worker (consumer handles bundler integration)\n * const worker = new Worker(\n * new URL('@permissionless-technologies/upp-sdk/worker', import.meta.url)\n * )\n * const manager = new ProofWorkerManager(worker)\n *\n * const result = await manager.prove('transfer', circuitInputs, '/circuits/',\n * (stage, msg) => console.log(stage, msg)\n * )\n *\n * // Cleanup\n * manager.terminate()\n * ```\n */\n\nimport type { UPPCircuitType, UPPCircuitInputs, ProofResult, PlonkProvingStage } from './proof.js'\nimport type { DownloadProgress } from './circuit-cache.js'\n\n// ============================================================================\n// Worker Message Types\n// ============================================================================\n\nexport interface ProofWorkerRequest {\n type: 'prove'\n id: string\n circuitType: string\n inputs: Record<string, any>\n baseUrl: string\n}\n\nexport type ProofWorkerResponse =\n | { type: 'progress'; id: string; stage: PlonkProvingStage; message: string }\n | { type: 'download-progress'; id: string; progress: DownloadProgress }\n | { type: 'result'; id: string; proof: ProofResult }\n | { type: 'error'; id: string; message: string }\n\n// ============================================================================\n// ProofWorkerManager\n// ============================================================================\n\ninterface PendingProof {\n resolve: (result: ProofResult) => void\n reject: (error: Error) => void\n onProgress?: (stage: PlonkProvingStage, message: string) => void\n onDownloadProgress?: (progress: DownloadProgress) => void\n}\n\nexport class ProofWorkerManager {\n private worker: Worker\n private pending = new Map<string, PendingProof>()\n private terminated = false\n\n constructor(worker: Worker) {\n this.worker = worker\n\n this.worker.onmessage = (e: MessageEvent<ProofWorkerResponse>) => {\n this.handleMessage(e.data)\n }\n\n this.worker.onerror = (e: ErrorEvent) => {\n console.error('[ProofWorkerManager] Worker error:', e.message, e)\n for (const [, p] of this.pending) {\n p.reject(new Error(`Worker error: ${e.message}`))\n }\n this.pending.clear()\n }\n }\n\n private handleMessage(data: ProofWorkerResponse) {\n const entry = this.pending.get(data.id)\n if (!entry) return\n\n switch (data.type) {\n case 'progress':\n entry.onProgress?.(data.stage, data.message)\n break\n case 'download-progress':\n entry.onDownloadProgress?.(data.progress)\n break\n case 'result':\n this.pending.delete(data.id)\n entry.resolve(data.proof)\n break\n case 'error':\n this.pending.delete(data.id)\n entry.reject(new Error(data.message))\n break\n }\n }\n\n /**\n * Generate a proof in the worker.\n *\n * @param signal - AbortSignal for cancellation. When aborted, the promise\n * rejects with AbortError. Call terminate() for hard cancellation.\n */\n async prove(\n circuitType: UPPCircuitType,\n inputs: UPPCircuitInputs,\n baseUrl: string,\n onProgress?: (stage: PlonkProvingStage, message: string) => void,\n signal?: AbortSignal,\n onDownloadProgress?: (progress: DownloadProgress) => void,\n ): Promise<ProofResult> {\n if (this.terminated) {\n throw new Error('Worker has been terminated')\n }\n\n return new Promise<ProofResult>((resolve, reject) => {\n const id = crypto.randomUUID()\n\n if (signal?.aborted) {\n reject(new DOMException('Proof generation aborted', 'AbortError'))\n return\n }\n\n this.pending.set(id, { resolve, reject, onProgress, onDownloadProgress })\n\n const onAbort = () => {\n this.pending.delete(id)\n reject(new DOMException('Proof generation aborted', 'AbortError'))\n }\n\n signal?.addEventListener('abort', onAbort, { once: true })\n\n // Resolve baseUrl to absolute — workers resolve relative URLs against\n // their own script URL (a webpack chunk), not the page origin.\n const absoluteBaseUrl = typeof window !== 'undefined'\n ? new URL(baseUrl, window.location.href).href\n : baseUrl\n\n this.worker.postMessage({\n type: 'prove',\n id,\n circuitType,\n inputs,\n baseUrl: absoluteBaseUrl,\n } satisfies ProofWorkerRequest)\n })\n }\n\n /**\n * Hard-terminate the worker. All pending proofs are rejected.\n */\n terminate() {\n this.terminated = true\n this.worker.terminate()\n for (const [, p] of this.pending) {\n p.reject(new DOMException('Worker terminated', 'AbortError'))\n }\n this.pending.clear()\n }\n}\n\n// ============================================================================\n// Convenience Function\n// ============================================================================\n\n/**\n * Generate a UPP proof — uses a worker if provided, otherwise main-thread.\n *\n * This is the recommended entry point for proof generation. It provides a\n * unified API regardless of whether a worker is available.\n *\n * Circuit artifacts are automatically cached in IndexedDB after first download.\n */\nexport async function generateUPPProofAsync(\n circuitType: UPPCircuitType,\n inputs: UPPCircuitInputs,\n baseUrl?: string,\n options?: {\n onProgress?: (stage: PlonkProvingStage, message: string) => void\n onDownloadProgress?: (progress: DownloadProgress) => void\n signal?: AbortSignal\n worker?: ProofWorkerManager | null\n },\n): Promise<ProofResult> {\n const { onProgress, onDownloadProgress, signal, worker } = options ?? {}\n\n if (worker) {\n return worker.prove(circuitType, inputs, baseUrl ?? '', onProgress, signal, onDownloadProgress)\n }\n\n // Fallback: main-thread proving (with cache)\n const { generateUPPProof } = await import('./proof.js')\n return generateUPPProof(circuitType, inputs, baseUrl, onProgress, { onDownloadProgress })\n}\n","/**\n * Swap Module\n *\n * Core logic for building and interacting with the UPP in-pool swap order book.\n * Framework-agnostic (no React). Reuses withdraw verifier for proofs.\n */\n\nimport { type Address, type Hex, encodeAbiParameters, keccak256, parseAbiParameters, toHex } from 'viem'\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/**\n * Swap order as stored on-chain\n */\nexport interface SwapOrder {\n /** Order ID (= maker's nullifier) */\n orderId: Hex\n /** Token being sold */\n sellToken: Address\n /** Original total sell amount */\n sellAmount: bigint\n /** Remaining sell amount (decremented on each fill) */\n remainingSellAmount: bigint\n /** Token the maker wants to receive */\n buyToken: Address\n /** Price: buyToken per sellToken (1e18 fixed-point) */\n rate: bigint\n /** Accumulated buy token amount from fills */\n accumulatedBuyAmount: bigint\n /** Maker's ASP ID (public, filterable by takers) */\n makerAspId: bigint\n /** Required filler ASP (0 = any) */\n requiredFillerAspId: bigint\n /** Block number after which order expires */\n expiry: bigint\n /** Whether the maker has claimed */\n claimed: boolean\n /** Whether the order was cancelled */\n cancelled: boolean\n}\n\n/**\n * Parameters to place a swap order\n */\nexport interface SwapOrderParams {\n /** Token to sell */\n sellToken: Address\n /** Amount to sell */\n sellAmount: bigint\n /** Token to buy */\n buyToken: Address\n /** Price: buyToken per sellToken (1e18 fixed-point) */\n rate: bigint\n /** Required filler ASP (0n = accept any) */\n requiredFillerAspId?: bigint\n /** Number of blocks until expiry (from current block) */\n expiryBlocks: bigint\n}\n\n/**\n * Parameters to fill a swap order\n */\nexport interface SwapFillParams {\n /** The order to fill */\n orderId: Hex\n /** How much sellToken the filler wants (≤ remaining) */\n takeAmount: bigint\n}\n\n/**\n * Swap order from event log\n */\nexport interface SwapOrderEvent {\n orderId: Hex\n sellToken: Address\n buyToken: Address\n sellAmount: bigint\n rate: bigint\n makerAspId: bigint\n requiredFillerAspId: bigint\n expiry: bigint\n blockNumber: bigint\n /** On-chain remaining sell amount (populated by useSwapOrderBook) */\n remainingSellAmount?: bigint\n /** Whether the order has been claimed */\n claimed?: boolean\n /** Whether the order has been cancelled */\n cancelled?: boolean\n}\n\n/**\n * Swap fill from event log\n */\nexport interface SwapFillEvent {\n orderId: Hex\n fillerNullifier: Hex\n takeAmount: bigint\n giveAmount: bigint\n fillerAspId: bigint\n remainingSellAmount: bigint\n blockNumber: bigint\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** 1e18 fixed-point precision for swap rates */\nexport const RATE_PRECISION = 10n ** 18n\n\n// ============================================================================\n// Event ABIs (for indexing swap events)\n// ============================================================================\n\nexport const SWAP_ORDER_PLACED_EVENT = {\n type: 'event',\n name: 'SwapOrderPlaced',\n inputs: [\n { name: 'orderId', type: 'bytes32', indexed: true },\n { name: 'sellToken', type: 'address', indexed: true },\n { name: 'buyToken', type: 'address', indexed: true },\n { name: 'sellAmount', type: 'uint256', indexed: false },\n { name: 'rate', type: 'uint256', indexed: false },\n { name: 'makerAspId', type: 'uint256', indexed: false },\n { name: 'requiredFillerAspId', type: 'uint256', indexed: false },\n { name: 'expiry', type: 'uint256', indexed: false },\n ],\n} as const\n\nexport const SWAP_ORDER_FILLED_EVENT = {\n type: 'event',\n name: 'SwapOrderFilled',\n inputs: [\n { name: 'orderId', type: 'bytes32', indexed: true },\n { name: 'fillerNullifier', type: 'bytes32', indexed: true },\n { name: 'fillerOutputCommitment', type: 'bytes32', indexed: true },\n { name: 'takeAmount', type: 'uint256', indexed: false },\n { name: 'giveAmount', type: 'uint256', indexed: false },\n { name: 'fillerAspId', type: 'uint256', indexed: false },\n { name: 'remainingSellAmount', type: 'uint256', indexed: false },\n { name: 'encryptedFillerNote', type: 'bytes', indexed: false },\n ],\n} as const\n\nexport const SWAP_ORDER_CLAIMED_EVENT = {\n type: 'event',\n name: 'SwapOrderClaimed',\n inputs: [\n { name: 'orderId', type: 'bytes32', indexed: true },\n { name: 'accumulatedBuyAmount', type: 'uint256', indexed: false },\n { name: 'refundedSellAmount', type: 'uint256', indexed: false },\n { name: 'buyOutputCommitment', type: 'bytes32', indexed: false },\n { name: 'encryptedBuyNote', type: 'bytes', indexed: false },\n { name: 'refundCommitment', type: 'bytes32', indexed: false },\n { name: 'encryptedRefundNote', type: 'bytes', indexed: false },\n ],\n} as const\n\nexport const SWAP_ORDER_CANCELLED_EVENT = {\n type: 'event',\n name: 'SwapOrderCancelled',\n inputs: [\n { name: 'orderId', type: 'bytes32', indexed: true },\n { name: 'refundedSellAmount', type: 'uint256', indexed: false },\n { name: 'refundCommitment', type: 'bytes32', indexed: false },\n { name: 'encryptedRefundNote', type: 'bytes', indexed: false },\n ],\n} as const\n\nexport const SWAP_EVENTS_ABI = [\n SWAP_ORDER_PLACED_EVENT,\n SWAP_ORDER_FILLED_EVENT,\n SWAP_ORDER_CLAIMED_EVENT,\n SWAP_ORDER_CANCELLED_EVENT,\n] as const\n\n// ============================================================================\n// Rate Calculations\n// ============================================================================\n\n/**\n * Compute the giveAmount (buyToken) for a given takeAmount (sellToken) at a rate.\n * giveAmount = (takeAmount * rate) / 1e18\n */\nexport function computeGiveAmount(takeAmount: bigint, rate: bigint): bigint {\n return (takeAmount * rate) / RATE_PRECISION\n}\n\n/**\n * Compute the maximum takeAmount for a given giveAmount and rate.\n * takeAmount = (giveAmount * 1e18) / rate\n */\nexport function computeTakeAmount(giveAmount: bigint, rate: bigint): bigint {\n if (rate === 0n) throw new Error('Rate cannot be zero')\n return (giveAmount * RATE_PRECISION) / rate\n}\n\n/**\n * Compute rate from a desired trade: I want `buyAmount` of buyToken for `sellAmount` of sellToken.\n * rate = (buyAmount * 1e18) / sellAmount\n */\nexport function computeRate(sellAmount: bigint, buyAmount: bigint): bigint {\n if (sellAmount === 0n) throw new Error('Sell amount cannot be zero')\n return (buyAmount * RATE_PRECISION) / sellAmount\n}\n\n/**\n * Format a rate for human display.\n * Returns a string like \"0.0005\" for rate = 500000000000000n (0.0005e18)\n */\nexport function formatRate(rate: bigint, decimals: number = 6): string {\n const whole = rate / RATE_PRECISION\n const frac = rate % RATE_PRECISION\n const fracStr = frac.toString().padStart(18, '0').slice(0, decimals)\n return `${whole}.${fracStr}`\n}\n\n// ============================================================================\n// Cancel Key Management\n// ============================================================================\n\n/**\n * Generate a cancel key hash from a secret.\n * The secret should be a random 32-byte value stored by the maker.\n */\nexport function computeCancelKeyHash(cancelSecret: Hex): Hex {\n return keccak256(encodeAbiParameters(\n parseAbiParameters('bytes32'),\n [cancelSecret]\n ))\n}\n\n/**\n * Generate a random cancel secret.\n */\nexport function generateCancelSecret(): Hex {\n const bytes = new Uint8Array(32)\n crypto.getRandomValues(bytes)\n return toHex(bytes)\n}\n\n// ============================================================================\n// Order Filtering\n// ============================================================================\n\n/**\n * Filter orders by ASP: only show orders from makers on acceptable ASPs.\n */\nexport function filterOrdersByASP(\n orders: SwapOrderEvent[],\n acceptableAspIds: bigint[]\n): SwapOrderEvent[] {\n const aspSet = new Set(acceptableAspIds.map(id => id.toString()))\n return orders.filter(o => aspSet.has(o.makerAspId.toString()))\n}\n\n/**\n * Filter orders by token pair.\n */\nexport function filterOrdersByTokenPair(\n orders: SwapOrderEvent[],\n sellToken: Address,\n buyToken: Address\n): SwapOrderEvent[] {\n const sell = sellToken.toLowerCase()\n const buy = buyToken.toLowerCase()\n return orders.filter(\n o => o.sellToken.toLowerCase() === sell && o.buyToken.toLowerCase() === buy\n )\n}\n\n/**\n * Check if a filler's ASP is accepted by an order.\n */\nexport function isFillerASPAccepted(order: SwapOrder | SwapOrderEvent, fillerAspId: bigint): boolean {\n const required = 'requiredFillerAspId' in order ? order.requiredFillerAspId : 0n\n return required === 0n || required === fillerAspId\n}\n\n// ============================================================================\n// Cancel Secret Persistence (localStorage)\n// ============================================================================\n\nconst CANCEL_SECRET_PREFIX = 'upp_swap_cancel_'\n\nfunction cancelKey(account: string, orderId: Hex): string {\n return `${CANCEL_SECRET_PREFIX}${account.toLowerCase()}_${orderId}`\n}\n\n/**\n * Store a cancel secret in localStorage, scoped by wallet address.\n * Must be called after placing a swap order.\n */\nexport function storeCancelSecret(orderId: Hex, cancelSecret: Hex, account?: string): void {\n if (typeof localStorage === 'undefined') return\n if (account) {\n localStorage.setItem(cancelKey(account, orderId), cancelSecret)\n }\n // Also store unscoped for backward compat\n localStorage.setItem(`${CANCEL_SECRET_PREFIX}${orderId}`, cancelSecret)\n}\n\n/**\n * Retrieve a cancel secret from localStorage.\n * Returns null if not found (e.g. order was placed by someone else).\n */\nexport function getCancelSecret(orderId: Hex, account?: string): Hex | null {\n if (typeof localStorage === 'undefined') return null\n if (account) {\n const scoped = localStorage.getItem(cancelKey(account, orderId))\n if (scoped) return scoped as Hex\n }\n // Fall back to unscoped key\n return localStorage.getItem(`${CANCEL_SECRET_PREFIX}${orderId}`) as Hex | null\n}\n\n/**\n * Remove a cancel secret from localStorage (after claim or cancel).\n */\nexport function removeCancelSecret(orderId: Hex, account?: string): void {\n if (typeof localStorage === 'undefined') return\n if (account) {\n localStorage.removeItem(cancelKey(account, orderId))\n }\n localStorage.removeItem(`${CANCEL_SECRET_PREFIX}${orderId}`)\n}\n\n/**\n * Get all order IDs for a specific wallet address.\n * Falls back to all cancel secrets if no account provided (backward compat).\n */\nexport function getOwnOrderIds(account?: string): Hex[] {\n if (typeof localStorage === 'undefined') return []\n const prefix = account\n ? `${CANCEL_SECRET_PREFIX}${account.toLowerCase()}_`\n : CANCEL_SECRET_PREFIX\n const ids: Hex[] = []\n for (let i = 0; i < localStorage.length; i++) {\n const key = localStorage.key(i)\n if (key?.startsWith(prefix)) {\n ids.push(key.slice(prefix.length) as Hex)\n }\n }\n return ids\n}\n\n// ============================================================================\n// Order Status Helpers\n// ============================================================================\n\n/**\n * Check if an order is still active (not claimed, not cancelled, not expired).\n */\nexport function isOrderActive(order: SwapOrder, currentBlock: bigint): boolean {\n return !order.claimed && !order.cancelled && currentBlock <= order.expiry && order.remainingSellAmount > 0n\n}\n\n/**\n * Compute the total buyToken amount the maker would receive for a full fill.\n */\nexport function computeTotalBuyAmount(sellAmount: bigint, rate: bigint): bigint {\n return computeGiveAmount(sellAmount, rate)\n}\n\n/**\n * Compute fill percentage (0-100) for display.\n */\nexport function computeFillPercentage(order: SwapOrder): number {\n if (order.sellAmount === 0n) return 0\n const filled = order.sellAmount - order.remainingSellAmount\n return Number((filled * 10000n) / order.sellAmount) / 100\n}\n","/**\n * Account Adapter — Pluggable account creation and persistence\n *\n * Abstracts how master keys are derived/loaded/stored.\n * The SDK doesn't care if keys come from a wallet signature,\n * seed phrase, hardware wallet, or external KMS.\n *\n * Persistence is handled via StorageAdapter (IndexedDB, localStorage, etc.)\n */\n\nimport type { MasterKeys, StarkMasterKeys } from '../keys/types.js'\nimport type { StorageAdapter } from '../indexer/types.js'\nimport { toHex } from 'viem'\n\n// ============================================================================\n// Interface\n// ============================================================================\n\n/**\n * Account adapter interface — pluggable key source.\n *\n * Implement this to bring your own key derivation:\n * - StorableAccountAdapter: persists keys via StorageAdapter (built-in)\n * - DirectAccountAdapter: pre-derived keys, no persistence (built-in, for testing)\n * - Custom: seed phrase, hardware wallet, external KMS\n */\nexport interface IAccountAdapter {\n /** Load persisted keys (returns null if no saved account) */\n load(): Promise<{ keys: MasterKeys; starkKeys?: StarkMasterKeys } | null>\n /** Save keys to storage */\n save(keys: MasterKeys, starkKeys?: StarkMasterKeys): Promise<void>\n /** Clear persisted keys */\n clear(): Promise<void>\n}\n\n// ============================================================================\n// Serialization\n// ============================================================================\n\ninterface SerializedAccount {\n version: 3\n spendingSecret: string\n ownerHash: string\n viewingSecret: string\n viewingHash: string\n starkSecret?: string[]\n starkOwnerHash?: string[]\n starkViewingSecret?: string[]\n starkViewingHash?: string[]\n}\n\nfunction serializeAccount(keys: MasterKeys, starkKeys?: StarkMasterKeys): SerializedAccount {\n return {\n version: 3,\n spendingSecret: toHex(keys.spendingSecret, { size: 32 }),\n ownerHash: toHex(keys.ownerHash, { size: 32 }),\n viewingSecret: toHex(keys.viewingSecret, { size: 32 }),\n viewingHash: toHex(keys.viewingHash, { size: 32 }),\n ...(starkKeys ? {\n starkSecret: starkKeys.starkSecret.map(v => v.toString()),\n starkOwnerHash: starkKeys.starkOwnerHash.map(v => v.toString()),\n starkViewingSecret: starkKeys.starkViewingSecret.map(v => v.toString()),\n starkViewingHash: starkKeys.starkViewingHash.map(v => v.toString()),\n } : {}),\n }\n}\n\nfunction deserializeAccount(data: SerializedAccount): { keys: MasterKeys; starkKeys?: StarkMasterKeys } {\n if (data.version !== 3 || !data.spendingSecret) {\n throw new Error('Invalid or outdated account data')\n }\n\n const keys: MasterKeys = {\n spendingSecret: BigInt(data.spendingSecret),\n ownerHash: BigInt(data.ownerHash),\n viewingSecret: BigInt(data.viewingSecret),\n viewingHash: BigInt(data.viewingHash),\n }\n\n let starkKeys: StarkMasterKeys | undefined\n if (data.starkSecret) {\n starkKeys = {\n starkSecret: data.starkSecret.map(s => BigInt(s)) as any,\n starkOwnerHash: data.starkOwnerHash!.map(s => BigInt(s)) as any,\n starkViewingSecret: data.starkViewingSecret!.map(s => BigInt(s)) as any,\n starkViewingHash: data.starkViewingHash!.map(s => BigInt(s)) as any,\n }\n }\n\n return { keys, starkKeys }\n}\n\n// ============================================================================\n// StorableAccountAdapter — persists via StorageAdapter\n// ============================================================================\n\n/**\n * Account adapter that persists keys via a pluggable StorageAdapter.\n *\n * Works with IndexedDB, localStorage, memory, Redis, Postgres — anything\n * that implements StorageAdapter.\n *\n * @example\n * ```ts\n * const storage = createAutoAdapter('upp_account')\n * const adapter = new StorableAccountAdapter(storage, ethAddress)\n * const saved = await adapter.load()\n * if (!saved) {\n * const keys = await deriveKeysFromSignature(sig)\n * await adapter.save(keys, starkKeys)\n * }\n * ```\n */\nexport class StorableAccountAdapter implements IAccountAdapter {\n private storageKey: string\n\n constructor(\n private storage: StorageAdapter,\n ethAddress: string,\n ) {\n this.storageKey = `account_${ethAddress.toLowerCase()}`\n }\n\n /**\n * Create an adapter keyed by a passkey credential ID instead of an Ethereum address.\n *\n * Uses `account_passkey_` prefix to avoid collisions with wallet-based accounts.\n *\n * @param storage - Storage backend (IndexedDB, localStorage, etc.)\n * @param credentialId - Base64url-encoded WebAuthn credential ID\n */\n static forPasskey(storage: StorageAdapter, credentialId: string): StorableAccountAdapter {\n const adapter = Object.create(StorableAccountAdapter.prototype) as StorableAccountAdapter\n ;(adapter as any).storage = storage\n ;(adapter as any).storageKey = `account_passkey_${credentialId.slice(0, 32)}`\n return adapter\n }\n\n async load(): Promise<{ keys: MasterKeys; starkKeys?: StarkMasterKeys } | null> {\n const data = await this.storage.get<SerializedAccount>(this.storageKey)\n if (!data) return null\n try {\n return deserializeAccount(data)\n } catch {\n // Corrupt or outdated — clear it\n await this.storage.delete(this.storageKey)\n return null\n }\n }\n\n async save(keys: MasterKeys, starkKeys?: StarkMasterKeys): Promise<void> {\n const serialized = serializeAccount(keys, starkKeys)\n await this.storage.set(this.storageKey, serialized)\n }\n\n async clear(): Promise<void> {\n await this.storage.delete(this.storageKey)\n }\n}\n\n// ============================================================================\n// DirectAccountAdapter — no persistence (testing, KMS)\n// ============================================================================\n\n/**\n * Direct account adapter — accepts pre-derived keys, no persistence.\n *\n * @example\n * ```ts\n * const adapter = new DirectAccountAdapter(masterKeys, starkKeys)\n * ```\n */\nexport class DirectAccountAdapter implements IAccountAdapter {\n constructor(\n private keys: MasterKeys,\n private starkKeys?: StarkMasterKeys,\n ) {}\n\n async load() {\n return { keys: this.keys, starkKeys: this.starkKeys }\n }\n\n async save(): Promise<void> {\n // No-op — keys are in memory only\n }\n\n async clear(): Promise<void> {\n // No-op\n }\n}\n","/**\n * NoteStore — Single source of truth for note state\n *\n * Framework-agnostic. Uses StorageAdapter for persistence.\n * Handles deduplication, status management, balance calculation.\n *\n * Usage:\n * const store = new NoteStore(createMemoryAdapter())\n * await store.load()\n * store.addNote(note) // returns false if duplicate\n * store.getBalance() // sum of unspent notes\n */\n\nimport type { StorageAdapter } from '../indexer/types.js'\nimport { getAddress } from 'viem'\nimport type { ShieldedNote, NoteStatus, ProofSystem } from './types.js'\n\n// Note: ShieldedNote, NoteStatus, ProofSystem are exported from core/index.ts\n// via `export * from './types.js'`. No re-export here to avoid DTS duplication.\n\n/** Serialized format for storage (bigints as strings) */\ninterface SerializedNote {\n amount: string\n blinding: string\n commitment: string\n ownerSecret: string\n ownerHash: string\n leafIndex: number\n origin: string\n token: string\n txHash?: string\n status: NoteStatus\n timestamp: number\n proofSystem?: ProofSystem\n}\n\nexport interface INoteStore {\n getNotes(): ShieldedNote[]\n getUnspentNotes(proofSystem?: ProofSystem): ShieldedNote[]\n getBalance(token?: string, proofSystem?: ProofSystem): bigint\n addNote(note: ShieldedNote): boolean\n addNotes(notes: ShieldedNote[]): number\n markSpent(commitment: string): void\n unmarkSpent(commitment: string): void\n updateLeafIndex(commitment: string, leafIndex: number): void\n load(): Promise<void>\n persist(): Promise<void>\n clear(): Promise<void>\n onChange(callback: () => void): () => void\n}\n\n// ============================================================================\n// Implementation\n// ============================================================================\n\nexport class NoteStore implements INoteStore {\n private notes: ShieldedNote[] = []\n private commitmentSet = new Set<string>()\n private listeners = new Set<() => void>()\n private dirty = false\n\n constructor(\n private storage: StorageAdapter,\n private storageKey: string = 'notes',\n ) {}\n\n // ---------- Queries ----------\n\n getNotes(): ShieldedNote[] {\n return [...this.notes]\n }\n\n getUnspentNotes(proofSystem?: ProofSystem): ShieldedNote[] {\n let result = this.notes.filter(n => n.status !== 'spent')\n if (proofSystem) {\n result = result.filter(n => (n.proofSystem ?? 'snark') === proofSystem)\n }\n return result\n }\n\n getBalance(token?: string, proofSystem?: ProofSystem): bigint {\n let notes = this.getUnspentNotes(proofSystem)\n if (token) {\n const normalized = token.toLowerCase()\n notes = notes.filter(n => n.token.toLowerCase() === normalized)\n }\n return notes.reduce((sum, n) => sum + n.amount, 0n)\n }\n\n // ---------- Mutations ----------\n\n /**\n * Add a note. Returns false if duplicate (by commitment).\n * Normalizes token and origin addresses.\n */\n addNote(note: ShieldedNote): boolean {\n const key = note.commitment.toLowerCase()\n if (this.commitmentSet.has(key)) return false\n\n // Normalize addresses\n const normalized: ShieldedNote = {\n ...note,\n commitment: note.commitment.toLowerCase(),\n origin: safeGetAddress(note.origin),\n token: safeGetAddress(note.token),\n }\n\n this.notes.push(normalized)\n this.commitmentSet.add(key)\n this.dirty = true\n this.notify()\n return true\n }\n\n /**\n * Add multiple notes. Returns count of actually added (non-duplicate).\n */\n addNotes(notes: ShieldedNote[]): number {\n let added = 0\n for (const note of notes) {\n if (this.addNote(note)) added++\n }\n return added\n }\n\n /**\n * Mark a note as spent (optimistic — syncNotes reconciles via nullifier check).\n */\n markSpent(commitment: string): void {\n const key = commitment.toLowerCase()\n const note = this.notes.find(n => n.commitment.toLowerCase() === key)\n if (note && note.status !== 'spent') {\n note.status = 'spent'\n this.dirty = true\n this.notify()\n }\n }\n\n /**\n * Un-mark a note as spent (reconciliation: nullifier not found on-chain).\n */\n unmarkSpent(commitment: string): void {\n const key = commitment.toLowerCase()\n const note = this.notes.find(n => n.commitment.toLowerCase() === key)\n if (note && note.status === 'spent') {\n note.status = 'confirmed'\n this.dirty = true\n this.notify()\n }\n }\n\n /**\n * Update the leafIndex for a note (e.g., after confirming on-chain).\n */\n updateLeafIndex(commitment: string, leafIndex: number): void {\n const key = commitment.toLowerCase()\n const note = this.notes.find(n => n.commitment.toLowerCase() === key)\n if (note && note.leafIndex !== leafIndex) {\n note.leafIndex = leafIndex\n this.dirty = true\n this.notify()\n }\n }\n\n // ---------- Persistence ----------\n\n async load(): Promise<void> {\n const serialized = await this.storage.get<SerializedNote[]>(this.storageKey)\n if (!serialized || !Array.isArray(serialized)) {\n this.notes = []\n this.commitmentSet.clear()\n return\n }\n\n // Deduplicate on load — prevents persisted duplicates from propagating\n this.notes = []\n this.commitmentSet.clear()\n let deduped = 0\n for (const s of serialized) {\n const note = deserializeNote(s)\n const key = note.commitment.toLowerCase()\n if (this.commitmentSet.has(key)) { deduped++; continue }\n this.commitmentSet.add(key)\n this.notes.push(note)\n }\n if (deduped > 0) {\n console.log(`[NoteStore] Removed ${deduped} duplicate notes on load`)\n this.dirty = true // will persist the cleaned version\n } else {\n this.dirty = false\n }\n }\n\n async persist(): Promise<void> {\n if (!this.dirty) return\n const serialized = this.notes.map(serializeNote)\n await this.storage.set(this.storageKey, serialized)\n this.dirty = false\n }\n\n async clear(): Promise<void> {\n this.notes = []\n this.commitmentSet.clear()\n this.dirty = false\n await this.storage.delete(this.storageKey)\n this.notify()\n }\n\n // ---------- Events ----------\n\n onChange(callback: () => void): () => void {\n this.listeners.add(callback)\n return () => this.listeners.delete(callback)\n }\n\n private notify(): void {\n for (const listener of this.listeners) {\n listener()\n }\n }\n}\n\n// ============================================================================\n// Serialization\n// ============================================================================\n\nfunction serializeNote(note: ShieldedNote): SerializedNote {\n return {\n ...note,\n amount: note.amount.toString(),\n blinding: note.blinding.toString(),\n }\n}\n\nfunction deserializeNote(s: SerializedNote): ShieldedNote {\n return {\n ...s,\n amount: BigInt(s.amount),\n blinding: BigInt(s.blinding),\n proofSystem: s.proofSystem ?? 'snark',\n }\n}\n\nfunction safeGetAddress(addr: string): string {\n try {\n return getAddress(addr)\n } catch {\n return addr // return as-is if not a valid address (e.g., bigint-encoded origin)\n }\n}\n"]}
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkXSJ5VVH4_cjs = require('./chunk-XSJ5VVH4.cjs');
|
|
4
|
+
var chunkBCSMUH4L_cjs = require('./chunk-BCSMUH4L.cjs');
|
|
5
|
+
var chunkHEHXSV47_cjs = require('./chunk-HEHXSV47.cjs');
|
|
6
|
+
var viem = require('viem');
|
|
7
|
+
|
|
8
|
+
// src/keys/types.ts
|
|
9
|
+
var DEFAULT_KEY_DERIVATION_CONFIG = {
|
|
10
|
+
message: "UPP Stealth Key Derivation v1",
|
|
11
|
+
version: 1
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
// src/keys/derive.ts
|
|
15
|
+
chunkHEHXSV47_cjs.init_poseidon();
|
|
16
|
+
chunkBCSMUH4L_cjs.init_crypto();
|
|
17
|
+
async function deriveKeysFromSeed(seed, config = DEFAULT_KEY_DERIVATION_CONFIG) {
|
|
18
|
+
const { poseidon } = await import('./poseidon-PUSGUIVZ.cjs');
|
|
19
|
+
const spendingSecretHash = viem.keccak256(
|
|
20
|
+
viem.toHex(new TextEncoder().encode(`${seed}:spending:v${config.version}`))
|
|
21
|
+
);
|
|
22
|
+
const spendingSecretRaw = chunkBCSMUH4L_cjs.bytesToBigint(chunkBCSMUH4L_cjs.hexToBytes(spendingSecretHash));
|
|
23
|
+
const spendingSecret = spendingSecretRaw % chunkHEHXSV47_cjs.FIELD_PRIME;
|
|
24
|
+
const ownerHash = await poseidon([spendingSecret]);
|
|
25
|
+
const viewingSecretHash = viem.keccak256(
|
|
26
|
+
viem.toHex(new TextEncoder().encode(`${seed}:viewing:v${config.version}`))
|
|
27
|
+
);
|
|
28
|
+
const viewingSecretRaw = chunkBCSMUH4L_cjs.bytesToBigint(chunkBCSMUH4L_cjs.hexToBytes(viewingSecretHash));
|
|
29
|
+
const viewingSecret = viewingSecretRaw % chunkHEHXSV47_cjs.FIELD_PRIME;
|
|
30
|
+
const viewingHash = await poseidon([viewingSecret]);
|
|
31
|
+
return {
|
|
32
|
+
spendingSecret,
|
|
33
|
+
ownerHash,
|
|
34
|
+
viewingSecret,
|
|
35
|
+
viewingHash
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
async function deriveKeysFromSignature(signature, config = DEFAULT_KEY_DERIVATION_CONFIG) {
|
|
39
|
+
const seed = viem.keccak256(signature);
|
|
40
|
+
return deriveKeysFromSeed(seed, config);
|
|
41
|
+
}
|
|
42
|
+
function getKeyDerivationMessage(config = DEFAULT_KEY_DERIVATION_CONFIG) {
|
|
43
|
+
return config.message;
|
|
44
|
+
}
|
|
45
|
+
async function verifyKeysMatchSignature(keys, signature, config = DEFAULT_KEY_DERIVATION_CONFIG) {
|
|
46
|
+
const derivedKeys = await deriveKeysFromSignature(signature, config);
|
|
47
|
+
return keys.spendingSecret === derivedKeys.spendingSecret && keys.ownerHash === derivedKeys.ownerHash && keys.viewingSecret === derivedKeys.viewingSecret && keys.viewingHash === derivedKeys.viewingHash;
|
|
48
|
+
}
|
|
49
|
+
function deriveStarkKeysFromSeed(seed, config = DEFAULT_KEY_DERIVATION_CONFIG) {
|
|
50
|
+
const starkSpendingHash = viem.keccak256(
|
|
51
|
+
viem.toHex(new TextEncoder().encode(`${seed}:stark:spending:v${config.version}`))
|
|
52
|
+
);
|
|
53
|
+
const starkSecret = chunkXSJ5VVH4_cjs.splitToM31Limbs(starkSpendingHash);
|
|
54
|
+
const starkOwnerHash = chunkXSJ5VVH4_cjs.computeStarkOwnerHash(starkSecret);
|
|
55
|
+
const starkViewingHash = viem.keccak256(
|
|
56
|
+
viem.toHex(new TextEncoder().encode(`${seed}:stark:viewing:v${config.version}`))
|
|
57
|
+
);
|
|
58
|
+
const starkViewingSecret = chunkXSJ5VVH4_cjs.splitToM31Limbs(starkViewingHash);
|
|
59
|
+
const starkViewingHashDigest = chunkXSJ5VVH4_cjs.computeStarkOwnerHash(starkViewingSecret);
|
|
60
|
+
return {
|
|
61
|
+
starkSecret,
|
|
62
|
+
starkOwnerHash,
|
|
63
|
+
starkViewingSecret,
|
|
64
|
+
starkViewingHash: starkViewingHashDigest
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async function deriveDualKeysFromSeed(seed, config = DEFAULT_KEY_DERIVATION_CONFIG) {
|
|
68
|
+
const snark = await deriveKeysFromSeed(seed, config);
|
|
69
|
+
const stark = deriveStarkKeysFromSeed(seed, config);
|
|
70
|
+
return { snark, stark };
|
|
71
|
+
}
|
|
72
|
+
function deriveStarkKeysFromSignature(signature, config = DEFAULT_KEY_DERIVATION_CONFIG) {
|
|
73
|
+
const seed = viem.keccak256(signature);
|
|
74
|
+
return deriveStarkKeysFromSeed(seed, config);
|
|
75
|
+
}
|
|
76
|
+
async function deriveDualKeysFromSignature(signature, config = DEFAULT_KEY_DERIVATION_CONFIG) {
|
|
77
|
+
const seed = viem.keccak256(signature);
|
|
78
|
+
return deriveDualKeysFromSeed(seed, config);
|
|
79
|
+
}
|
|
80
|
+
async function deriveNullifierKey(spendingSecret) {
|
|
81
|
+
const { poseidon } = await import('./poseidon-PUSGUIVZ.cjs');
|
|
82
|
+
return await poseidon([spendingSecret, 0n]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// src/keys/passkey.ts
|
|
86
|
+
chunkBCSMUH4L_cjs.init_crypto();
|
|
87
|
+
var PRF_SALT_INPUT = "UPP-Stealth-Key-Derivation-v1";
|
|
88
|
+
async function computePRFSalt(password) {
|
|
89
|
+
const encoder = new TextEncoder();
|
|
90
|
+
const baseSalt = await crypto.subtle.digest("SHA-256", encoder.encode(PRF_SALT_INPUT));
|
|
91
|
+
if (!password) return baseSalt;
|
|
92
|
+
const passwordHash = viem.keccak256(chunkBCSMUH4L_cjs.bytesToHex(encoder.encode(password)));
|
|
93
|
+
const combined = new Uint8Array(32 + 32);
|
|
94
|
+
combined.set(new Uint8Array(baseSalt), 0);
|
|
95
|
+
for (let i = 0; i < 32; i++) {
|
|
96
|
+
combined[32 + i] = parseInt(passwordHash.slice(2 + i * 2, 4 + i * 2), 16);
|
|
97
|
+
}
|
|
98
|
+
return crypto.subtle.digest("SHA-256", combined);
|
|
99
|
+
}
|
|
100
|
+
function bufferToBase64url(buffer) {
|
|
101
|
+
const bytes = new Uint8Array(buffer);
|
|
102
|
+
let binary = "";
|
|
103
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
104
|
+
binary += String.fromCharCode(bytes[i]);
|
|
105
|
+
}
|
|
106
|
+
return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
107
|
+
}
|
|
108
|
+
function base64urlToBuffer(base64url) {
|
|
109
|
+
const base64 = base64url.replace(/-/g, "+").replace(/_/g, "/");
|
|
110
|
+
const padded = base64 + "=".repeat((4 - base64.length % 4) % 4);
|
|
111
|
+
const binary = atob(padded);
|
|
112
|
+
const bytes = new Uint8Array(binary.length);
|
|
113
|
+
for (let i = 0; i < binary.length; i++) {
|
|
114
|
+
bytes[i] = binary.charCodeAt(i);
|
|
115
|
+
}
|
|
116
|
+
return bytes.buffer;
|
|
117
|
+
}
|
|
118
|
+
function prfOutputToSeed(prfOutput) {
|
|
119
|
+
const hex = chunkBCSMUH4L_cjs.bytesToHex(new Uint8Array(prfOutput));
|
|
120
|
+
return viem.keccak256(hex);
|
|
121
|
+
}
|
|
122
|
+
async function checkPRFSupport() {
|
|
123
|
+
if (typeof window === "undefined" || typeof navigator === "undefined") return false;
|
|
124
|
+
if (!window.PublicKeyCredential) return false;
|
|
125
|
+
try {
|
|
126
|
+
if ("getClientCapabilities" in PublicKeyCredential) {
|
|
127
|
+
const caps = await PublicKeyCredential.getClientCapabilities();
|
|
128
|
+
if (caps?.["extension:prf"] !== void 0) {
|
|
129
|
+
return caps["extension:prf"] === true;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
try {
|
|
135
|
+
return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable();
|
|
136
|
+
} catch {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
async function createPasskeyWithPRF(options = {}) {
|
|
141
|
+
const {
|
|
142
|
+
rpName = "UPP Private Account",
|
|
143
|
+
userName = "UPP User",
|
|
144
|
+
password
|
|
145
|
+
} = options;
|
|
146
|
+
const prfSalt = new Uint8Array(await computePRFSalt(password));
|
|
147
|
+
const userId = new Uint8Array(16);
|
|
148
|
+
crypto.getRandomValues(userId);
|
|
149
|
+
const credential = await navigator.credentials.create({
|
|
150
|
+
publicKey: {
|
|
151
|
+
rp: {
|
|
152
|
+
name: rpName,
|
|
153
|
+
id: window.location.hostname
|
|
154
|
+
},
|
|
155
|
+
user: {
|
|
156
|
+
id: userId,
|
|
157
|
+
name: userName,
|
|
158
|
+
displayName: userName
|
|
159
|
+
},
|
|
160
|
+
challenge: crypto.getRandomValues(new Uint8Array(32)),
|
|
161
|
+
pubKeyCredParams: [
|
|
162
|
+
{ alg: -7, type: "public-key" },
|
|
163
|
+
// ES256 (P-256)
|
|
164
|
+
{ alg: -257, type: "public-key" }
|
|
165
|
+
// RS256 (fallback)
|
|
166
|
+
],
|
|
167
|
+
authenticatorSelection: {
|
|
168
|
+
residentKey: "required",
|
|
169
|
+
requireResidentKey: true,
|
|
170
|
+
userVerification: "required"
|
|
171
|
+
},
|
|
172
|
+
extensions: {
|
|
173
|
+
prf: {
|
|
174
|
+
eval: { first: prfSalt }
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
if (!credential) {
|
|
180
|
+
throw new Error("Passkey creation was cancelled");
|
|
181
|
+
}
|
|
182
|
+
const credentialId = bufferToBase64url(credential.rawId);
|
|
183
|
+
const extResults = credential.getClientExtensionResults();
|
|
184
|
+
const prfResults = extResults?.prf?.results;
|
|
185
|
+
if (!prfResults?.first) {
|
|
186
|
+
throw new Error(
|
|
187
|
+
"PRF extension not supported by this authenticator. Third-party password managers (e.g. Bitwarden, 1Password) may not support PRF yet. Try using your device's built-in passkey (Touch ID, Windows Hello) instead."
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
const seed = prfOutputToSeed(prfResults.first);
|
|
191
|
+
const dualKeys = await deriveDualKeysFromSeed(seed);
|
|
192
|
+
return { credentialId, dualKeys };
|
|
193
|
+
}
|
|
194
|
+
async function getPasskeyPRFSecret(credentialId, password) {
|
|
195
|
+
const prfSalt = new Uint8Array(await computePRFSalt(password));
|
|
196
|
+
const allowCredentials = credentialId ? [{ type: "public-key", id: base64urlToBuffer(credentialId) }] : void 0;
|
|
197
|
+
const assertion = await navigator.credentials.get({
|
|
198
|
+
publicKey: {
|
|
199
|
+
challenge: crypto.getRandomValues(new Uint8Array(32)),
|
|
200
|
+
rpId: window.location.hostname,
|
|
201
|
+
allowCredentials,
|
|
202
|
+
userVerification: "required",
|
|
203
|
+
extensions: {
|
|
204
|
+
prf: {
|
|
205
|
+
eval: { first: prfSalt }
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
if (!assertion) {
|
|
211
|
+
throw new Error("Passkey authentication was cancelled");
|
|
212
|
+
}
|
|
213
|
+
const resolvedCredentialId = bufferToBase64url(assertion.rawId);
|
|
214
|
+
const extResults = assertion.getClientExtensionResults();
|
|
215
|
+
const prfResults = extResults?.prf?.results;
|
|
216
|
+
if (!prfResults?.first) {
|
|
217
|
+
throw new Error(
|
|
218
|
+
"PRF extension not available. Third-party password managers (e.g. Bitwarden, 1Password) may not support PRF yet. Try using your device's built-in passkey (Touch ID, Windows Hello) instead."
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
const seed = prfOutputToSeed(prfResults.first);
|
|
222
|
+
const dualKeys = await deriveDualKeysFromSeed(seed);
|
|
223
|
+
return {
|
|
224
|
+
credentialId: resolvedCredentialId,
|
|
225
|
+
seed,
|
|
226
|
+
dualKeys
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
async function deriveKeysFromPasskey(prfOutput) {
|
|
230
|
+
const seed = prfOutputToSeed(prfOutput.buffer);
|
|
231
|
+
return deriveDualKeysFromSeed(seed);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
exports.DEFAULT_KEY_DERIVATION_CONFIG = DEFAULT_KEY_DERIVATION_CONFIG;
|
|
235
|
+
exports.checkPRFSupport = checkPRFSupport;
|
|
236
|
+
exports.createPasskeyWithPRF = createPasskeyWithPRF;
|
|
237
|
+
exports.deriveDualKeysFromSeed = deriveDualKeysFromSeed;
|
|
238
|
+
exports.deriveDualKeysFromSignature = deriveDualKeysFromSignature;
|
|
239
|
+
exports.deriveKeysFromPasskey = deriveKeysFromPasskey;
|
|
240
|
+
exports.deriveKeysFromSeed = deriveKeysFromSeed;
|
|
241
|
+
exports.deriveKeysFromSignature = deriveKeysFromSignature;
|
|
242
|
+
exports.deriveNullifierKey = deriveNullifierKey;
|
|
243
|
+
exports.deriveStarkKeysFromSeed = deriveStarkKeysFromSeed;
|
|
244
|
+
exports.deriveStarkKeysFromSignature = deriveStarkKeysFromSignature;
|
|
245
|
+
exports.getKeyDerivationMessage = getKeyDerivationMessage;
|
|
246
|
+
exports.getPasskeyPRFSecret = getPasskeyPRFSecret;
|
|
247
|
+
exports.verifyKeysMatchSignature = verifyKeysMatchSignature;
|
|
248
|
+
//# sourceMappingURL=chunk-CCWMVO3H.cjs.map
|
|
249
|
+
//# sourceMappingURL=chunk-CCWMVO3H.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/keys/types.ts","../src/keys/derive.ts","../src/keys/passkey.ts"],"names":["init_poseidon","init_crypto","keccak256","toHex","bytesToBigint","hexToBytes","FIELD_PRIME","splitToM31Limbs","computeStarkOwnerHash","bytesToHex"],"mappings":"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","file":"chunk-CCWMVO3H.cjs","sourcesContent":["/**\n * Key Type Definitions for UPP SDK\n *\n * Post-quantum key structure (hash-based, no elliptic curves):\n *\n * Wallet Signature → Seed\n * ├── Spending Secret → Owner Hash = Poseidon(spendingSecret)\n * └── Viewing Secret (for note encryption, derived from seed)\n *\n * Ownership is proven via hash preimage: \"I know secret such that Poseidon(secret) == ownerHash\"\n * This replaces the previous BabyJubJub ECDLP-based ownership proof.\n */\n\nimport type { Hex, Address } from 'viem'\n\n/**\n * Master keys derived from wallet signature\n *\n * Post-quantum: uses hash-based ownership instead of BabyJubJub curve.\n * ownerHash = Poseidon(spendingSecret) replaces spendingPubKey (curve point).\n */\nexport interface MasterKeys {\n /** Spending secret - for note ownership proofs (hash preimage) */\n spendingSecret: bigint\n /** Owner hash = Poseidon(spendingSecret) - publicly committed in notes */\n ownerHash: bigint\n /** Viewing secret - for note encryption/decryption (symmetric key derivation) */\n viewingSecret: bigint\n /** Viewing hash = Poseidon(viewingSecret) - for search tags and indexing */\n viewingHash: bigint\n}\n\n/**\n * Per-transaction viewing key (for decryption)\n *\n * Can be shared with auditors to reveal specific transactions\n * without compromising the master viewing secret.\n *\n * Post-quantum: uses hash-based key derivation instead of ECDH.\n */\nexport interface TransactionViewingKey {\n /** The Merkle leaf index (for locating the on-chain event) */\n leafIndex: number\n /** The per-note nonce (used in key derivation) */\n nonce: bigint\n /** The per-note decryption key (derived from viewingSecret + nonce) */\n decryptionKey: Hex\n}\n\n/**\n * Exported viewing keys for audit\n *\n * Contains the minimum information needed for an auditor\n * to decrypt specific transactions.\n */\nexport interface AuditKeyExport {\n /** Version for forward compatibility (v4 = post-quantum hash-based) */\n version: 4\n /** Ethereum address that signed to derive keys (for identification) */\n signerAddress: Address\n /** The viewing hash (for verification) */\n viewingHash: bigint\n /** Per-transaction viewing keys */\n viewingKeys: TransactionViewingKey[]\n /** Instructions for auditor */\n instructions: string\n}\n\n/**\n * Stealth address components (simplified for hash-based system)\n * Published once, used by senders to encrypt notes\n */\nexport interface StealthAddressComponents {\n /** Owner hash = Poseidon(spendingSecret) */\n ownerHash: bigint\n /** Viewing hash = Poseidon(viewingSecret) - for encryption */\n viewingHash: bigint\n /** Optional chain ID (for multi-chain support) */\n chainId?: number\n}\n\n/**\n * Configuration for key derivation\n */\nexport interface KeyDerivationConfig {\n /** The message to sign for key derivation */\n message: string\n /** Version number for the key derivation scheme */\n version: 1\n}\n\n/**\n * Default key derivation configuration\n */\nexport const DEFAULT_KEY_DERIVATION_CONFIG: KeyDerivationConfig = {\n message: 'UPP Stealth Key Derivation v1',\n version: 1,\n}\n\n/**\n * Result of deriving one-time keys for a transaction (hash-based)\n */\nexport interface OneTimeKeys {\n /** One-time secret (for the owner to spend the note) */\n oneTimeSecret: bigint\n /** One-time owner hash = Poseidon(oneTimeSecret) - in the commitment */\n ownerHash: bigint\n}\n\n/**\n * Serialized key format for storage\n */\nexport interface SerializedKeys {\n version: 1\n /** Hex-encoded encrypted key data */\n encryptedData: Hex\n /** Salt for key derivation (if password protected) */\n salt?: Hex\n /** Nonce for encryption */\n nonce: Hex\n}\n\n// =========================================================================\n// STARK Key Types (M31/Keccak-based, post-quantum)\n// =========================================================================\n\nimport type { M31Digest, M31Secret } from '../utils/keccak-m31.js'\n\n/** Which proving system to use */\nexport type ProvingSystem = 'snark' | 'stark'\n\n/**\n * STARK master keys derived from wallet signature.\n *\n * Uses M31 field and keccak-256 hashing — no elliptic curves.\n * ownerHash = keccak_m31(starkSecret) — 4 M31 elements.\n */\nexport interface StarkMasterKeys {\n /** 8 M31 limbs (248 bits of entropy) — for ownership proofs */\n starkSecret: M31Secret\n /** keccak_m31(starkSecret) — publicly committed in STARK notes */\n starkOwnerHash: M31Digest\n /** 8 M31 limbs — for note encryption/decryption */\n starkViewingSecret: M31Secret\n /** keccak_m31(starkViewingSecret) — for search tags and indexing */\n starkViewingHash: M31Digest\n}\n\n/**\n * Dual master keys: both SNARK (BN254/Poseidon) and STARK (M31/Keccak).\n *\n * Derived from the same wallet signature via domain-separated keccak256.\n * Breaking BJJ (quantum) does NOT compromise STARK keys (keccak preimage resistance).\n */\nexport interface DualMasterKeys {\n snark: MasterKeys\n stark: StarkMasterKeys\n}\n","/**\n * Key Derivation from Wallet Signature (Post-Quantum / Hash-Based)\n *\n * Derives keys from an Ethereum wallet signature using only hash functions.\n * No elliptic curve operations — quantum-resistant by design.\n *\n * Security Model:\n * - Keys are derived deterministically from the signature\n * - No seed phrase management required\n * - Same signature always produces same keys\n * - Ownership proven via hash preimage (Poseidon), not discrete log\n */\n\nimport { keccak256, toHex, type Hex } from 'viem'\nimport { FIELD_PRIME } from '../utils/poseidon.js'\nimport { hexToBytes, bytesToBigint } from '../utils/crypto.js'\nimport { splitToM31Limbs, computeStarkOwnerHash } from '../utils/keccak-m31.js'\nimport type { MasterKeys, StarkMasterKeys, DualMasterKeys, KeyDerivationConfig } from './types.js'\nimport { DEFAULT_KEY_DERIVATION_CONFIG } from './types.js'\n\n/**\n * Derive master keys from a 32-byte seed (hash-based, post-quantum)\n *\n * This is the core derivation function used by both the wallet-signature\n * and passkey paths. Takes a pre-hashed seed and derives spending/viewing\n * keys via domain-separated keccak256 + Poseidon.\n *\n * @param seed - A 32-byte hex seed (e.g. keccak256 of a signature or PRF output)\n * @param config - Optional key derivation configuration\n * @returns Master keys for stealth operations\n */\nexport async function deriveKeysFromSeed(\n seed: Hex,\n config: KeyDerivationConfig = DEFAULT_KEY_DERIVATION_CONFIG\n): Promise<MasterKeys> {\n const { poseidon } = await import('../utils/poseidon.js')\n\n // Derive spending secret from seed\n const spendingSecretHash = keccak256(\n toHex(new TextEncoder().encode(`${seed}:spending:v${config.version}`))\n )\n const spendingSecretRaw = bytesToBigint(hexToBytes(spendingSecretHash))\n const spendingSecret = spendingSecretRaw % FIELD_PRIME\n\n // Derive owner hash: Poseidon(spendingSecret)\n const ownerHash = await poseidon([spendingSecret])\n\n // Derive viewing secret from seed\n const viewingSecretHash = keccak256(\n toHex(new TextEncoder().encode(`${seed}:viewing:v${config.version}`))\n )\n const viewingSecretRaw = bytesToBigint(hexToBytes(viewingSecretHash))\n const viewingSecret = viewingSecretRaw % FIELD_PRIME\n\n // Derive viewing hash: Poseidon(viewingSecret)\n const viewingHash = await poseidon([viewingSecret])\n\n return {\n spendingSecret,\n ownerHash,\n viewingSecret,\n viewingHash,\n }\n}\n\n/**\n * Derive master keys from a wallet signature (hash-based, post-quantum)\n *\n * This replaces the previous BabyJubJub-based derivation.\n * Instead of curve points, we use Poseidon hashes for ownership proofs.\n *\n * @param signature - The wallet signature (from personal_sign or EIP-712)\n * @param config - Optional key derivation configuration\n * @returns Master keys for stealth operations\n *\n * @example\n * ```ts\n * const signature = await walletClient.signMessage({\n * message: 'UPP Stealth Key Derivation v1'\n * })\n * const keys = await deriveKeysFromSignature(signature)\n * // keys.ownerHash is Poseidon(spendingSecret) — used in note commitments\n * ```\n */\nexport async function deriveKeysFromSignature(\n signature: Hex,\n config: KeyDerivationConfig = DEFAULT_KEY_DERIVATION_CONFIG\n): Promise<MasterKeys> {\n const seed = keccak256(signature)\n return deriveKeysFromSeed(seed, config)\n}\n\n/**\n * Get the message to sign for key derivation\n */\nexport function getKeyDerivationMessage(\n config: KeyDerivationConfig = DEFAULT_KEY_DERIVATION_CONFIG\n): string {\n return config.message\n}\n\n/**\n * Verify that keys match a given signature\n */\nexport async function verifyKeysMatchSignature(\n keys: MasterKeys,\n signature: Hex,\n config: KeyDerivationConfig = DEFAULT_KEY_DERIVATION_CONFIG\n): Promise<boolean> {\n const derivedKeys = await deriveKeysFromSignature(signature, config)\n\n return (\n keys.spendingSecret === derivedKeys.spendingSecret &&\n keys.ownerHash === derivedKeys.ownerHash &&\n keys.viewingSecret === derivedKeys.viewingSecret &&\n keys.viewingHash === derivedKeys.viewingHash\n )\n}\n\n/**\n * Derive STARK master keys from a 32-byte seed (M31/Keccak, post-quantum)\n *\n * Core STARK derivation function used by both wallet-signature and passkey paths.\n *\n * @param seed - A 32-byte hex seed\n * @param config - Optional key derivation configuration\n * @returns STARK master keys for stealth operations\n */\nexport function deriveStarkKeysFromSeed(\n seed: Hex,\n config: KeyDerivationConfig = DEFAULT_KEY_DERIVATION_CONFIG\n): StarkMasterKeys {\n // Derive STARK spending secret: 8 M31 limbs from a single keccak256\n const starkSpendingHash = keccak256(\n toHex(new TextEncoder().encode(`${seed}:stark:spending:v${config.version}`))\n )\n const starkSecret = splitToM31Limbs(starkSpendingHash)\n const starkOwnerHash = computeStarkOwnerHash(starkSecret)\n\n // Derive STARK viewing secret: 8 M31 limbs from a separate keccak256\n const starkViewingHash = keccak256(\n toHex(new TextEncoder().encode(`${seed}:stark:viewing:v${config.version}`))\n )\n const starkViewingSecret = splitToM31Limbs(starkViewingHash)\n const starkViewingHashDigest = computeStarkOwnerHash(starkViewingSecret)\n\n return {\n starkSecret,\n starkOwnerHash,\n starkViewingSecret,\n starkViewingHash: starkViewingHashDigest,\n }\n}\n\n/**\n * Derive both SNARK and STARK keys from a 32-byte seed.\n *\n * @param seed - A 32-byte hex seed\n * @param config - Optional key derivation configuration\n */\nexport async function deriveDualKeysFromSeed(\n seed: Hex,\n config: KeyDerivationConfig = DEFAULT_KEY_DERIVATION_CONFIG\n): Promise<DualMasterKeys> {\n const snark = await deriveKeysFromSeed(seed, config)\n const stark = deriveStarkKeysFromSeed(seed, config)\n return { snark, stark }\n}\n\n/**\n * Derive STARK master keys from a wallet signature (M31/Keccak, post-quantum)\n *\n * Uses domain-separated keccak256 to derive M31 secrets, then keccak_m31\n * for owner/viewing hashes. No elliptic curve operations.\n *\n * @param signature - The wallet signature (same one used for SNARK keys)\n * @param config - Optional key derivation configuration\n * @returns STARK master keys for stealth operations\n */\nexport function deriveStarkKeysFromSignature(\n signature: Hex,\n config: KeyDerivationConfig = DEFAULT_KEY_DERIVATION_CONFIG\n): StarkMasterKeys {\n const seed = keccak256(signature)\n return deriveStarkKeysFromSeed(seed, config)\n}\n\n/**\n * Derive both SNARK and STARK keys from a single wallet signature.\n *\n * Same seed, domain-separated derivation. Breaking BJJ (quantum) does NOT\n * compromise STARK keys — keccak preimage resistance provides 2^128 quantum security.\n */\nexport async function deriveDualKeysFromSignature(\n signature: Hex,\n config: KeyDerivationConfig = DEFAULT_KEY_DERIVATION_CONFIG\n): Promise<DualMasterKeys> {\n const seed = keccak256(signature)\n return deriveDualKeysFromSeed(seed, config)\n}\n\n/**\n * Derive a nullifier key from the spending secret\n *\n * nullifier = Poseidon(nullifierKey, leafIndex, commitment)\n */\nexport async function deriveNullifierKey(spendingSecret: bigint): Promise<bigint> {\n const { poseidon } = await import('../utils/poseidon.js')\n return await poseidon([spendingSecret, 0n]) // 0n = nullifier domain\n}\n","/**\n * Passkey (WebAuthn PRF) Key Derivation\n *\n * Uses the WebAuthn PRF extension (hmac-secret) to derive deterministic\n * secrets from passkeys. Same passkey + same salt = same output, always.\n *\n * The PRF output feeds into the same seed-based derivation pipeline as\n * wallet signatures — no circuit or contract changes needed.\n *\n * Browser support: Chrome 120+, Safari 18+, Edge 120+\n */\n\nimport { keccak256, type Hex } from 'viem'\nimport { bytesToHex } from '../utils/crypto.js'\nimport { deriveDualKeysFromSeed } from './derive.js'\nimport type { DualMasterKeys } from './types.js'\n\n// ============================================================================\n// Types\n// ============================================================================\n\nexport interface PasskeyCreateOptions {\n /** Relying party display name (default: \"UPP Private Account\") */\n rpName?: string\n /** User display name for the credential (default: \"UPP User\") */\n userName?: string\n /** Optional password mixed into PRF salt for account separation */\n password?: string\n}\n\nexport interface PasskeyCredential {\n /** Base64url-encoded credential ID */\n credentialId: string\n /** Derived keys from the passkey's PRF output */\n dualKeys: DualMasterKeys\n}\n\nexport interface PasskeyAuthResult {\n /** Base64url-encoded credential ID */\n credentialId: string\n /** 32-byte keccak256 seed derived from PRF output */\n seed: Hex\n /** Derived dual keys */\n dualKeys: DualMasterKeys\n}\n\n// ============================================================================\n// Constants\n// ============================================================================\n\n/** Fixed domain salt for PRF — deterministic, domain-bound */\nconst PRF_SALT_INPUT = 'UPP-Stealth-Key-Derivation-v1'\n\n// ============================================================================\n// Internal helpers\n// ============================================================================\n\n/**\n * Compute the 32-byte PRF salt, optionally mixing in a password.\n * Uses SHA-256 (native Web Crypto) since PRF salts must be exactly 32 bytes.\n */\nasync function computePRFSalt(password?: string): Promise<ArrayBuffer> {\n const encoder = new TextEncoder()\n const baseSalt = await crypto.subtle.digest('SHA-256', encoder.encode(PRF_SALT_INPUT))\n\n if (!password) return baseSalt\n\n // Mix password into salt: SHA-256(baseSalt || keccak256(password))\n const passwordHash = keccak256(bytesToHex(encoder.encode(password)))\n const combined = new Uint8Array(32 + 32)\n combined.set(new Uint8Array(baseSalt), 0)\n // passwordHash is hex string, convert to bytes\n for (let i = 0; i < 32; i++) {\n combined[32 + i] = parseInt(passwordHash.slice(2 + i * 2, 4 + i * 2), 16)\n }\n return crypto.subtle.digest('SHA-256', combined)\n}\n\n/** Convert ArrayBuffer to base64url string */\nfunction bufferToBase64url(buffer: ArrayBuffer): string {\n const bytes = new Uint8Array(buffer)\n let binary = ''\n for (let i = 0; i < bytes.length; i++) {\n binary += String.fromCharCode(bytes[i]!)\n }\n return btoa(binary).replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '')\n}\n\n/** Convert base64url string to ArrayBuffer */\nfunction base64urlToBuffer(base64url: string): ArrayBuffer {\n const base64 = base64url.replace(/-/g, '+').replace(/_/g, '/')\n const padded = base64 + '='.repeat((4 - (base64.length % 4)) % 4)\n const binary = atob(padded)\n const bytes = new Uint8Array(binary.length)\n for (let i = 0; i < binary.length; i++) {\n bytes[i] = binary.charCodeAt(i)\n }\n return bytes.buffer\n}\n\n/** Convert PRF output bytes to a keccak256 seed (normalizes to 32 bytes) */\nfunction prfOutputToSeed(prfOutput: ArrayBuffer): Hex {\n const hex = bytesToHex(new Uint8Array(prfOutput))\n return keccak256(hex)\n}\n\n// ============================================================================\n// Public API\n// ============================================================================\n\n/**\n * Check whether the current browser supports WebAuthn with PRF extension.\n *\n * Returns false in non-browser environments (SSR, Node.js).\n */\nexport async function checkPRFSupport(): Promise<boolean> {\n if (typeof window === 'undefined' || typeof navigator === 'undefined') return false\n if (!window.PublicKeyCredential) return false\n\n // Use getClientCapabilities if available (modern browsers)\n try {\n if ('getClientCapabilities' in PublicKeyCredential) {\n const caps = await (PublicKeyCredential as any).getClientCapabilities()\n if (caps?.['extension:prf'] !== undefined) {\n return caps['extension:prf'] === true\n }\n }\n } catch {\n // Fall through to heuristic\n }\n\n // Heuristic: check if PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable\n // exists and returns true — a necessary (but not sufficient) condition for PRF\n try {\n return await PublicKeyCredential.isUserVerifyingPlatformAuthenticatorAvailable()\n } catch {\n return false\n }\n}\n\n/**\n * Create a new passkey with PRF extension enabled.\n *\n * This registers a discoverable credential (resident key) with the\n * platform authenticator. The PRF output is used immediately to derive keys.\n *\n * @param options - Configuration for the credential\n * @returns Credential ID + derived dual keys\n * @throws If WebAuthn or PRF extension is not supported\n */\nexport async function createPasskeyWithPRF(\n options: PasskeyCreateOptions = {}\n): Promise<PasskeyCredential> {\n const {\n rpName = 'UPP Private Account',\n userName = 'UPP User',\n password,\n } = options\n\n const prfSalt = new Uint8Array(await computePRFSalt(password))\n\n // Generate random user ID (not sensitive, just a handle)\n const userId = new Uint8Array(16)\n crypto.getRandomValues(userId)\n\n const credential = await navigator.credentials.create({\n publicKey: {\n rp: {\n name: rpName,\n id: window.location.hostname,\n },\n user: {\n id: userId,\n name: userName,\n displayName: userName,\n },\n challenge: crypto.getRandomValues(new Uint8Array(32)),\n pubKeyCredParams: [\n { alg: -7, type: 'public-key' }, // ES256 (P-256)\n { alg: -257, type: 'public-key' }, // RS256 (fallback)\n ],\n authenticatorSelection: {\n residentKey: 'required',\n requireResidentKey: true,\n userVerification: 'required',\n },\n extensions: {\n prf: {\n eval: { first: prfSalt },\n },\n } as AuthenticationExtensionsClientInputs,\n },\n }) as PublicKeyCredential | null\n\n if (!credential) {\n throw new Error('Passkey creation was cancelled')\n }\n\n const credentialId = bufferToBase64url(credential.rawId)\n\n // Extract PRF output from creation response\n const extResults = credential.getClientExtensionResults() as Record<string, any>\n const prfResults = extResults?.prf?.results\n if (!prfResults?.first) {\n throw new Error(\n 'PRF extension not supported by this authenticator. ' +\n 'Third-party password managers (e.g. Bitwarden, 1Password) may not support PRF yet. ' +\n 'Try using your device\\'s built-in passkey (Touch ID, Windows Hello) instead.'\n )\n }\n\n const seed = prfOutputToSeed(prfResults.first as ArrayBuffer)\n const dualKeys = await deriveDualKeysFromSeed(seed)\n\n return { credentialId, dualKeys }\n}\n\n/**\n * Authenticate with an existing passkey and extract PRF secret.\n *\n * If credentialId is provided, the specific credential is requested.\n * Otherwise, the browser shows a discoverable credential picker.\n *\n * @param credentialId - Optional base64url credential ID to request specifically\n * @param password - Optional password (must match what was used during creation)\n * @returns Seed + credential ID + derived dual keys\n */\nexport async function getPasskeyPRFSecret(\n credentialId?: string,\n password?: string,\n): Promise<PasskeyAuthResult> {\n const prfSalt = new Uint8Array(await computePRFSalt(password))\n\n const allowCredentials = credentialId\n ? [{ type: 'public-key' as const, id: base64urlToBuffer(credentialId) }]\n : undefined\n\n const assertion = await navigator.credentials.get({\n publicKey: {\n challenge: crypto.getRandomValues(new Uint8Array(32)),\n rpId: window.location.hostname,\n allowCredentials,\n userVerification: 'required',\n extensions: {\n prf: {\n eval: { first: prfSalt },\n },\n } as AuthenticationExtensionsClientInputs,\n },\n }) as PublicKeyCredential | null\n\n if (!assertion) {\n throw new Error('Passkey authentication was cancelled')\n }\n\n const resolvedCredentialId = bufferToBase64url(assertion.rawId)\n\n const extResults = assertion.getClientExtensionResults() as Record<string, any>\n const prfResults = extResults?.prf?.results\n if (!prfResults?.first) {\n throw new Error(\n 'PRF extension not available. ' +\n 'Third-party password managers (e.g. Bitwarden, 1Password) may not support PRF yet. ' +\n 'Try using your device\\'s built-in passkey (Touch ID, Windows Hello) instead.'\n )\n }\n\n const seed = prfOutputToSeed(prfResults.first as ArrayBuffer)\n const dualKeys = await deriveDualKeysFromSeed(seed)\n\n return {\n credentialId: resolvedCredentialId,\n seed,\n dualKeys,\n }\n}\n\n/**\n * Derive dual keys from raw PRF output bytes.\n *\n * Convenience function for custom WebAuthn flows that handle\n * credential management externally.\n *\n * @param prfOutput - Raw PRF extension output (32 bytes)\n * @returns Derived dual master keys\n */\nexport async function deriveKeysFromPasskey(\n prfOutput: Uint8Array,\n): Promise<DualMasterKeys> {\n const seed = prfOutputToSeed(prfOutput.buffer as ArrayBuffer)\n return deriveDualKeysFromSeed(seed)\n}\n"]}
|
|
@@ -1182,5 +1182,5 @@ function sleep(ms) {
|
|
|
1182
1182
|
}
|
|
1183
1183
|
|
|
1184
1184
|
export { computeSearchTag, createAutoAdapter, createLocalStorageAdapter, createMemoryAdapter, localStorageAdapter, makeRpcIndexer, matchesSearchTag, memoryAdapter, tryDecryptNote, unpackNoteData };
|
|
1185
|
-
//# sourceMappingURL=chunk-
|
|
1186
|
-
//# sourceMappingURL=chunk-
|
|
1185
|
+
//# sourceMappingURL=chunk-D6C2OOOC.js.map
|
|
1186
|
+
//# sourceMappingURL=chunk-D6C2OOOC.js.map
|