@zama-fhe/sdk 3.1.0 → 3.1.1-alpha.1

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.
@@ -240,9 +240,7 @@
240
240
  for (const chain of payload.chains) configs.set(chain.id, chain);
241
241
  sendSuccess(id, type, { initialized: true });
242
242
  } catch (error) {
243
- const message = error instanceof Error ? error.message : String(error);
244
- console.error("[Worker] Init error:", message);
245
- sendError(id, type, message);
243
+ sendError(id, type, error instanceof Error ? error.message : String(error));
246
244
  }
247
245
  }
248
246
  /** Coerce a boolean to bigint for numeric FHE types. */
@@ -297,10 +295,7 @@
297
295
  inputProof: encrypted.inputProof
298
296
  }, [encrypted.inputProof.buffer, ...encrypted.handles.map((h) => h.buffer)]);
299
297
  } catch (error) {
300
- const message = error instanceof Error ? error.message : String(error);
301
- const statusCode = extractHttpStatus(error);
302
- console.error("[Worker] Encrypt error:", message);
303
- sendError(id, type, message, statusCode);
298
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
304
299
  }
305
300
  }
306
301
  /**
@@ -316,10 +311,7 @@
316
311
  }));
317
312
  sendSuccess(id, type, { clearValues: await instance.userDecrypt(handleContractPairs, unprefixHex(payload.privateKey), unprefixHex(payload.publicKey), payload.signature, payload.signedContractAddresses, payload.signerAddress, payload.startTimestamp, payload.durationDays) });
318
313
  } catch (error) {
319
- const message = error instanceof Error ? error.message : String(error);
320
- const statusCode = extractHttpStatus(error);
321
- console.error("[Worker] UserDecrypt error:", message);
322
- sendError(id, type, message, statusCode);
314
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
323
315
  }
324
316
  }
325
317
  /**
@@ -345,10 +337,7 @@
345
337
  try {
346
338
  sendSuccess(id, type, { ...await (await getInstance(payload.chainId)).publicDecrypt(payload.encryptedValues) });
347
339
  } catch (error) {
348
- const message = error instanceof Error ? error.message : String(error);
349
- const statusCode = extractHttpStatus(error);
350
- console.error("[Worker] PublicDecrypt error:", message);
351
- sendError(id, type, message, statusCode);
340
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
352
341
  }
353
342
  }
354
343
  /**
@@ -363,9 +352,7 @@
363
352
  privateKey: prefixHex(keypair.privateKey)
364
353
  });
365
354
  } catch (error) {
366
- const message = error instanceof Error ? error.message : String(error);
367
- console.error("[Worker] GenerateKeypair error:", message);
368
- sendError(id, type, message);
355
+ sendError(id, type, error instanceof Error ? error.message : String(error));
369
356
  }
370
357
  }
371
358
  /**
@@ -376,9 +363,7 @@
376
363
  try {
377
364
  sendSuccess(id, type, (await getInstance(payload.chainId)).createEIP712(unprefixHex(payload.publicKey), payload.contractAddresses, payload.startTimestamp, payload.durationDays));
378
365
  } catch (error) {
379
- const message = error instanceof Error ? error.message : String(error);
380
- console.error("[Worker] CreateEIP712 error:", message);
381
- sendError(id, type, message);
366
+ sendError(id, type, error instanceof Error ? error.message : String(error));
382
367
  }
383
368
  }
384
369
  /**
@@ -389,9 +374,7 @@
389
374
  try {
390
375
  sendSuccess(id, type, (await getInstance(payload.chainId)).createDelegatedUserDecryptEIP712(unprefixHex(payload.publicKey), payload.contractAddresses, payload.delegatorAddress, payload.startTimestamp, payload.durationDays));
391
376
  } catch (error) {
392
- const message = error instanceof Error ? error.message : String(error);
393
- console.error("[Worker] CreateDelegatedEIP712 error:", message);
394
- sendError(id, type, message);
377
+ sendError(id, type, error instanceof Error ? error.message : String(error));
395
378
  }
396
379
  }
397
380
  /**
@@ -407,10 +390,7 @@
407
390
  }));
408
391
  sendSuccess(id, type, { clearValues: await instance.delegatedUserDecrypt(handleContractPairs, unprefixHex(payload.privateKey), unprefixHex(payload.publicKey), payload.signature, payload.signedContractAddresses, payload.delegatorAddress, payload.delegateAddress, payload.startTimestamp, payload.durationDays) });
409
392
  } catch (error) {
410
- const message = error instanceof Error ? error.message : String(error);
411
- const statusCode = extractHttpStatus(error);
412
- console.error("[Worker] DelegatedUserDecrypt error:", message);
413
- sendError(id, type, message, statusCode);
393
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
414
394
  }
415
395
  }
416
396
  /**
@@ -422,10 +402,7 @@
422
402
  const result = await (await getInstance(payload.chainId)).requestZKProofVerification(payload.zkProof);
423
403
  sendSuccess(id, type, result, [result.inputProof.buffer, ...result.handles.map((h) => h.buffer)]);
424
404
  } catch (error) {
425
- const message = error instanceof Error ? error.message : String(error);
426
- const statusCode = extractHttpStatus(error);
427
- console.error("[Worker] RequestZKProofVerification error:", message);
428
- sendError(id, type, message, statusCode);
405
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
429
406
  }
430
407
  }
431
408
  /**
@@ -436,10 +413,7 @@
436
413
  try {
437
414
  sendSuccess(id, type, { result: (await getInstance(payload.chainId)).getPublicKey() });
438
415
  } catch (error) {
439
- const message = error instanceof Error ? error.message : String(error);
440
- const statusCode = extractHttpStatus(error);
441
- console.error("[Worker] GetPublicKey error:", message);
442
- sendError(id, type, message, statusCode);
416
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
443
417
  }
444
418
  }
445
419
  /**
@@ -450,10 +424,7 @@
450
424
  try {
451
425
  sendSuccess(id, type, { result: (await getInstance(payload.chainId)).getPublicParams(payload.bits) });
452
426
  } catch (error) {
453
- const message = error instanceof Error ? error.message : String(error);
454
- const statusCode = extractHttpStatus(error);
455
- console.error("[Worker] GetPublicParams error:", message);
456
- sendError(id, type, message, statusCode);
427
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
457
428
  }
458
429
  }
459
430
  /**
@@ -507,7 +478,7 @@
507
478
  case "GET_PUBLIC_PARAMS":
508
479
  await handleGetPublicParams(request);
509
480
  break;
510
- default: console.error("[Worker] Unknown request type:", request.type);
481
+ default: throw new Error(`Unknown request type: ${request.type}`);
511
482
  }
512
483
  } catch (error) {
513
484
  const message = error instanceof Error ? error.message : String(error);
@@ -240,9 +240,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
240
240
  for (const chain of payload.chains) configs.set(chain.id, chain);
241
241
  sendSuccess(id, type, { initialized: true });
242
242
  } catch (error) {
243
- const message = error instanceof Error ? error.message : String(error);
244
- console.error("[Worker] Init error:", message);
245
- sendError(id, type, message);
243
+ sendError(id, type, error instanceof Error ? error.message : String(error));
246
244
  }
247
245
  }
248
246
  /** Coerce a boolean to bigint for numeric FHE types. */
@@ -297,10 +295,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
297
295
  inputProof: encrypted.inputProof
298
296
  }, [encrypted.inputProof.buffer, ...encrypted.handles.map((h) => h.buffer)]);
299
297
  } catch (error) {
300
- const message = error instanceof Error ? error.message : String(error);
301
- const statusCode = extractHttpStatus(error);
302
- console.error("[Worker] Encrypt error:", message);
303
- sendError(id, type, message, statusCode);
298
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
304
299
  }
305
300
  }
306
301
  /**
@@ -316,10 +311,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
316
311
  }));
317
312
  sendSuccess(id, type, { clearValues: await instance.userDecrypt(handleContractPairs, unprefixHex(payload.privateKey), unprefixHex(payload.publicKey), payload.signature, payload.signedContractAddresses, payload.signerAddress, payload.startTimestamp, payload.durationDays) });
318
313
  } catch (error) {
319
- const message = error instanceof Error ? error.message : String(error);
320
- const statusCode = extractHttpStatus(error);
321
- console.error("[Worker] UserDecrypt error:", message);
322
- sendError(id, type, message, statusCode);
314
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
323
315
  }
324
316
  }
325
317
  /**
@@ -345,10 +337,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
345
337
  try {
346
338
  sendSuccess(id, type, { ...await (await getInstance(payload.chainId)).publicDecrypt(payload.encryptedValues) });
347
339
  } catch (error) {
348
- const message = error instanceof Error ? error.message : String(error);
349
- const statusCode = extractHttpStatus(error);
350
- console.error("[Worker] PublicDecrypt error:", message);
351
- sendError(id, type, message, statusCode);
340
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
352
341
  }
353
342
  }
354
343
  /**
@@ -363,9 +352,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
363
352
  privateKey: prefixHex(keypair.privateKey)
364
353
  });
365
354
  } catch (error) {
366
- const message = error instanceof Error ? error.message : String(error);
367
- console.error("[Worker] GenerateKeypair error:", message);
368
- sendError(id, type, message);
355
+ sendError(id, type, error instanceof Error ? error.message : String(error));
369
356
  }
370
357
  }
371
358
  /**
@@ -376,9 +363,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
376
363
  try {
377
364
  sendSuccess(id, type, (await getInstance(payload.chainId)).createEIP712(unprefixHex(payload.publicKey), payload.contractAddresses, payload.startTimestamp, payload.durationDays));
378
365
  } catch (error) {
379
- const message = error instanceof Error ? error.message : String(error);
380
- console.error("[Worker] CreateEIP712 error:", message);
381
- sendError(id, type, message);
366
+ sendError(id, type, error instanceof Error ? error.message : String(error));
382
367
  }
383
368
  }
384
369
  /**
@@ -389,9 +374,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
389
374
  try {
390
375
  sendSuccess(id, type, (await getInstance(payload.chainId)).createDelegatedUserDecryptEIP712(unprefixHex(payload.publicKey), payload.contractAddresses, payload.delegatorAddress, payload.startTimestamp, payload.durationDays));
391
376
  } catch (error) {
392
- const message = error instanceof Error ? error.message : String(error);
393
- console.error("[Worker] CreateDelegatedEIP712 error:", message);
394
- sendError(id, type, message);
377
+ sendError(id, type, error instanceof Error ? error.message : String(error));
395
378
  }
396
379
  }
397
380
  /**
@@ -407,10 +390,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
407
390
  }));
408
391
  sendSuccess(id, type, { clearValues: await instance.delegatedUserDecrypt(handleContractPairs, unprefixHex(payload.privateKey), unprefixHex(payload.publicKey), payload.signature, payload.signedContractAddresses, payload.delegatorAddress, payload.delegateAddress, payload.startTimestamp, payload.durationDays) });
409
392
  } catch (error) {
410
- const message = error instanceof Error ? error.message : String(error);
411
- const statusCode = extractHttpStatus(error);
412
- console.error("[Worker] DelegatedUserDecrypt error:", message);
413
- sendError(id, type, message, statusCode);
393
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
414
394
  }
415
395
  }
416
396
  /**
@@ -422,10 +402,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
422
402
  const result = await (await getInstance(payload.chainId)).requestZKProofVerification(payload.zkProof);
423
403
  sendSuccess(id, type, result, [result.inputProof.buffer, ...result.handles.map((h) => h.buffer)]);
424
404
  } catch (error) {
425
- const message = error instanceof Error ? error.message : String(error);
426
- const statusCode = extractHttpStatus(error);
427
- console.error("[Worker] RequestZKProofVerification error:", message);
428
- sendError(id, type, message, statusCode);
405
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
429
406
  }
430
407
  }
431
408
  /**
@@ -436,10 +413,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
436
413
  try {
437
414
  sendSuccess(id, type, { result: (await getInstance(payload.chainId)).getPublicKey() });
438
415
  } catch (error) {
439
- const message = error instanceof Error ? error.message : String(error);
440
- const statusCode = extractHttpStatus(error);
441
- console.error("[Worker] GetPublicKey error:", message);
442
- sendError(id, type, message, statusCode);
416
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
443
417
  }
444
418
  }
445
419
  /**
@@ -450,10 +424,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
450
424
  try {
451
425
  sendSuccess(id, type, { result: (await getInstance(payload.chainId)).getPublicParams(payload.bits) });
452
426
  } catch (error) {
453
- const message = error instanceof Error ? error.message : String(error);
454
- const statusCode = extractHttpStatus(error);
455
- console.error("[Worker] GetPublicParams error:", message);
456
- sendError(id, type, message, statusCode);
427
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
457
428
  }
458
429
  }
459
430
  /**
@@ -507,7 +478,7 @@ Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=requi
507
478
  case "GET_PUBLIC_PARAMS":
508
479
  await handleGetPublicParams(request);
509
480
  break;
510
- default: console.error("[Worker] Unknown request type:", request.type);
481
+ default: throw new Error(\`Unknown request type: \${request.type}\`);
511
482
  }
512
483
  } catch (error) {
513
484
  const message = error instanceof Error ? error.message : String(error);
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["#initPromise","z","#storage","#chainId","#relayerUrl","#ttlMs","#logger","#publicKeyMem","#publicKeyInflight","#loadFheEncryptionKey","#readCachedEntry","#deleteCorruptEntry","toError","#publicParamsMem","#publicParamsInflight","#loadPublicParams","#readParamsIndex","#revalidationInflight","#revalidateIfDueInner","#lastRevalidatedAt","#collectParamEntries","#parseCachedEntry","#writeEntries","#clearAll","#checkArtifactFreshness","#deleteQuietly","#config","#worker","#artifactCache","#artifactStorage","IndexedDBStorage","#refreshCsrfToken","#getArtifactCache","#worker","#initPromise","#doInitWorker","#pendingRequests","#rejectAllPending","workerFilename","workerCode","z"],"sources":["../../../src/relayer/base-relayer.ts","../../../src/relayer/fhe-artifact-cache.ts","../../../src/relayer/relayer-utils.ts","../../../src/relayer/relayer-web.ts","../../../src/worker/worker.base-client.ts","../../../src/worker/browser-extension.ts","../../../src/worker/worker.client.ts","../../../src/config/web.ts"],"sourcesContent":["import type { Address } from \"viem\";\nimport type { FheChain } from \"../chains/types\";\n\nexport abstract class BaseRelayer {\n #initPromise: Promise<void> | null = null;\n protected abstract readonly chain: FheChain;\n protected abstract init(): Promise<void>;\n\n protected async ensureInit(): Promise<void> {\n if (!this.#initPromise) {\n this.#initPromise = this.init().catch((error) => {\n this.#initPromise = null;\n throw error;\n });\n }\n return this.#initPromise;\n }\n\n protected resetInit(): void {\n this.#initPromise = null;\n }\n\n async getAclAddress(): Promise<Address> {\n return this.chain.aclContractAddress;\n }\n}\n","import { z } from \"zod/mini\";\nimport type { GenericStorage } from \"../types\";\nimport { assertNonNullable, toError } from \"../utils\";\nimport type { GenericLogger } from \"../worker/worker.types\";\nimport type { FheEncryptionKey, PublicParamsData } from \"./relayer-sdk.types\";\n\n// ── Cached data shapes ──────────────────────────────────────\n\nconst CachedArtifactBase = z.object({\n artifactUrl: z.optional(z.string()),\n etag: z.optional(z.string()),\n lastModified: z.optional(z.string()),\n // Optional + default(0) preserves the prior `?? 0` fallback for entries\n // persisted before this field was added; 0 marks them stale via the TTL check.\n // oxlint-disable-next-line no-underscore-dangle -- z._default is the Zod v4 mini API\n lastValidatedAt: z._default(z.optional(z.number().check(z.nonnegative())), 0),\n});\n\n/** Cached shape for the FHE network public key. */\nconst CachedPublicKeySchema = z.extend(CachedArtifactBase, {\n publicKeyId: z.string(),\n publicKey: z.string(),\n});\ntype CachedPublicKey = z.infer<typeof CachedPublicKeySchema>;\n\n/** Cached shape for FHE public params. */\nconst CachedPublicParamsSchema = z.extend(CachedArtifactBase, {\n publicParamsId: z.string(),\n publicParams: z.string(),\n});\ntype CachedPublicParams = z.infer<typeof CachedPublicParamsSchema>;\n\nconst ParamsIndexSchema = z.array(z.int().check(z.nonnegative()));\n\n/**\n * Manifest shape returned by the relayer `/keyurl` endpoint. Only the fields\n * actually consumed (status + first URL of each artifact) are validated; the\n * upstream payload contains additional metadata we ignore.\n */\nconst ManifestSchema = z.object({\n status: z.literal(\"succeeded\"),\n response: z.object({\n fheKeyInfo: z\n .array(\n z.object({\n fhePublicKey: z.object({\n urls: z.array(z.string()).check(z.minLength(1)),\n }),\n }),\n )\n .check(z.minLength(1)),\n crs: z.record(\n z.string(),\n z.object({\n urls: z.array(z.string()).check(z.minLength(1)),\n }),\n ),\n }),\n});\n\n// ── Return types ────────────────────────────────────────────\n\n/** Return type of the FHE encryption key fetcher. */\ntype FheEncryptionKeyResult = FheEncryptionKey | null;\n\n/** Return type of the public params fetcher. */\ntype PublicParamsResult = PublicParamsData | null;\n\n// ── Constants ───────────────────────────────────────────────\n\n/** Max chunk size for String.fromCharCode to avoid call-stack overflow on large buffers. */\nconst CHUNK_SIZE = 8192;\n\n/** On revalidation failure, retry after 5 minutes instead of the full TTL. */\nconst SHORT_RETRY_MS = 5 * 60 * 1000;\n\n// ── Helpers ─────────────────────────────────────────────────\n\nfunction toBase64(bytes: Uint8Array): string {\n const chunks: string[] = [];\n for (let i = 0; i < bytes.length; i += CHUNK_SIZE) {\n chunks.push(String.fromCharCode(...bytes.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(chunks.join(\"\"));\n}\n\nfunction fromBase64(b64: string): Uint8Array {\n let binary: string;\n try {\n binary = atob(b64);\n } catch {\n throw new Error(`Invalid base64 data (length: ${b64.length})`);\n }\n if (binary.length === 0) {\n throw new Error(\"Decoded artifact is empty\");\n }\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;\n}\n\nfunction pubkeyStorageKey(chainId: number): string {\n return `fhe:pubkey:${chainId}`;\n}\n\nfunction paramsStorageKey(chainId: number, bits: number): string {\n return `fhe:params:${chainId}:${bits}`;\n}\n\nfunction paramsIndexKey(chainId: number): string {\n return `fhe:params-index:${chainId}`;\n}\n\ntype LogContext = Record<string, unknown>;\n\n// ── ArtifactCache ──────────────────────────────────────────\n\n/**\n * Persistent cache for FHE network public key and public params.\n * Uses a {@link GenericStorage} backend (e.g. MemoryStorage, or any\n * user-provided async key-value adapter) to avoid re-downloading large\n * binary data on every app instantiation.\n *\n * Cache keys are scoped by chain ID.\n */\nexport class FheArtifactCache {\n readonly #storage: GenericStorage;\n readonly #chainId: number;\n readonly #relayerUrl: string;\n readonly #ttlMs: number;\n readonly #logger: GenericLogger;\n #publicKeyMem: FheEncryptionKeyResult | undefined;\n #publicParamsMem = new Map<number, PublicParamsResult>();\n #publicKeyInflight: Promise<FheEncryptionKeyResult> | null = null;\n #publicParamsInflight = new Map<number, Promise<PublicParamsResult>>();\n #revalidationInflight: Promise<boolean> | null = null;\n /** In-memory guard to skip storage reads when revalidation isn't due. */\n #lastRevalidatedAt: number | null = null;\n\n constructor(opts: {\n storage: GenericStorage;\n chainId: number;\n relayerUrl: string;\n /** Cache TTL in seconds. Default: 86 400 (24 h). Set to 0 to revalidate on every operation. */\n ttl?: number;\n logger?: GenericLogger;\n }) {\n this.#storage = opts.storage;\n this.#chainId = opts.chainId;\n this.#relayerUrl = opts.relayerUrl;\n this.#ttlMs = (opts.ttl ?? 86_400) * 1000;\n this.#logger = opts.logger ?? console;\n }\n\n // ── fetchFheEncryptionKeyBytes ──────────────────────────\n\n async fetchFheEncryptionKeyBytes(\n fetcher: () => Promise<FheEncryptionKeyResult>,\n ): Promise<FheEncryptionKeyResult> {\n if (this.#publicKeyMem !== undefined) {\n return this.#publicKeyMem;\n }\n\n // Deduplicate concurrent calls\n if (this.#publicKeyInflight) {\n return this.#publicKeyInflight;\n }\n\n this.#publicKeyInflight = this.#loadFheEncryptionKey(fetcher);\n try {\n return await this.#publicKeyInflight;\n } finally {\n this.#publicKeyInflight = null;\n }\n }\n\n async #loadFheEncryptionKey(\n fetcher: () => Promise<FheEncryptionKeyResult>,\n ): Promise<FheEncryptionKeyResult> {\n const key = pubkeyStorageKey(this.#chainId);\n\n const stored = await this.#readCachedEntry(\n key,\n CachedPublicKeySchema,\n \"public key\",\n \"Failed to read public key from persistent storage, falling back to network fetch\",\n );\n if (stored) {\n try {\n const result: FheEncryptionKeyResult = {\n publicKeyId: stored.publicKeyId,\n publicKey: fromBase64(stored.publicKey),\n };\n this.#publicKeyMem = result;\n return result;\n } catch (err) {\n await this.#deleteCorruptEntry(key, \"public key\", { error: toError(err).message });\n }\n }\n\n const result = await fetcher();\n if (result === null) {\n return null;\n }\n\n this.#publicKeyMem = result;\n\n try {\n const entry: CachedPublicKey = {\n publicKeyId: result.publicKeyId,\n publicKey: toBase64(result.publicKey),\n lastValidatedAt: Date.now(),\n };\n await this.#storage.set(key, entry);\n } catch (err) {\n this.#logger.warn(\"Failed to persist public key to storage\", {\n chainId: this.#chainId,\n error: toError(err).message,\n });\n }\n\n return result;\n }\n\n // ── getPublicParams ─────────────────────────────────────\n\n async getPublicParams(\n bits: number,\n fetcher: () => Promise<PublicParamsResult>,\n ): Promise<PublicParamsResult> {\n const mem = this.#publicParamsMem.get(bits);\n if (mem !== undefined) {\n return mem;\n }\n\n // Deduplicate concurrent calls\n const inflight = this.#publicParamsInflight.get(bits);\n if (inflight) {\n return inflight;\n }\n\n const promise = this.#loadPublicParams(bits, fetcher);\n this.#publicParamsInflight.set(bits, promise);\n try {\n return await promise;\n } finally {\n this.#publicParamsInflight.delete(bits);\n }\n }\n\n async #loadPublicParams(\n bits: number,\n fetcher: () => Promise<PublicParamsResult>,\n ): Promise<PublicParamsResult> {\n const key = paramsStorageKey(this.#chainId, bits);\n\n const stored = await this.#readCachedEntry(\n key,\n CachedPublicParamsSchema,\n \"params\",\n \"Failed to read public params from persistent storage, falling back to network fetch\",\n { bits },\n );\n if (stored) {\n try {\n const result: PublicParamsResult = {\n publicParamsId: stored.publicParamsId,\n publicParams: fromBase64(stored.publicParams),\n };\n this.#publicParamsMem.set(bits, result);\n return result;\n } catch (err) {\n await this.#deleteCorruptEntry(key, \"params\", { bits, error: toError(err).message });\n }\n }\n\n const result = await fetcher();\n if (result === null) {\n return null;\n }\n\n this.#publicParamsMem.set(bits, result);\n\n try {\n const entry: CachedPublicParams = {\n publicParamsId: result.publicParamsId,\n publicParams: toBase64(result.publicParams),\n lastValidatedAt: Date.now(),\n };\n await this.#storage.set(key, entry);\n\n // Update params index for cold-start CRS detection\n const idxKey = paramsIndexKey(this.#chainId);\n const existing = await this.#readParamsIndex(\"Failed to read params index from storage\");\n if (!existing.includes(bits)) {\n await this.#storage.set(idxKey, [...existing, bits]);\n }\n } catch (err) {\n this.#logger.warn(\"Failed to persist public params to storage\", {\n chainId: this.#chainId,\n bits,\n error: toError(err).message,\n });\n }\n\n return result;\n }\n\n // ── Artifact-level revalidation ─────────────────────────\n\n /**\n * Check whether cached FHE artifacts are still fresh by issuing\n * HTTP conditional requests (ETag / If-None-Match, Last-Modified /\n * If-Modified-Since) against the actual artifact CDN URLs.\n *\n * @returns `true` if the cache was invalidated and the caller should\n * re-fetch artifacts, `false` otherwise.\n */\n async revalidateIfDue(): Promise<boolean> {\n // Concurrency guard — coalesce overlapping calls\n if (this.#revalidationInflight) {\n return this.#revalidationInflight;\n }\n this.#revalidationInflight = this.#revalidateIfDueInner();\n try {\n return await this.#revalidationInflight;\n } finally {\n this.#revalidationInflight = null;\n }\n }\n\n async #revalidateIfDueInner(): Promise<boolean> {\n // Fast path: in-memory timestamp check avoids storage I/O on every call\n const now = Date.now();\n if (this.#lastRevalidatedAt !== null && now - this.#lastRevalidatedAt < this.#ttlMs) {\n return false;\n }\n\n // Skip revalidation when relayerUrl is not configured (e.g. Hardhat)\n if (!this.#relayerUrl) {\n return false;\n }\n\n const pkKey = pubkeyStorageKey(this.#chainId);\n\n // Track partial progress so the catch block can reuse already-read data\n let storedPk: CachedPublicKey | null = null;\n let paramEntries: Array<{\n bits: number;\n key: string;\n data: CachedPublicParams;\n }> = [];\n\n try {\n // 1. Read PK cache entry and collect params entries in parallel\n const [pkRaw, entries] = await Promise.all([\n this.#storage.get(pkKey),\n this.#collectParamEntries(),\n ]);\n\n // Validate PK shape\n if (pkRaw !== null && pkRaw !== undefined) {\n storedPk = await this.#parseCachedEntry(pkKey, pkRaw, CachedPublicKeySchema, \"public key\");\n }\n\n paramEntries = entries;\n\n if (!storedPk) {\n return false;\n }\n\n // 2. Check if all entries are within TTL\n const allEntries: Array<{ lastValidatedAt: number }> = [\n storedPk,\n ...paramEntries.map((e) => e.data),\n ];\n const allFresh = allEntries.every((e) => now - e.lastValidatedAt < this.#ttlMs);\n if (allFresh) {\n this.#lastRevalidatedAt = now;\n return false;\n }\n\n // 3. Fetch manifest to discover current artifact URLs\n const manifestRes = await globalThis.fetch(`${this.#relayerUrl}/keyurl`);\n if (!manifestRes.ok) {\n // Treat as transient failure — use short retry instead of full TTL\n const retryTimestamp = now - this.#ttlMs + SHORT_RETRY_MS;\n this.#logger.warn(\"Manifest fetch failed during revalidation, retrying in 5 min\", {\n status: manifestRes.status,\n relayerUrl: this.#relayerUrl,\n });\n await this.#writeEntries(\n pkKey,\n { ...storedPk, lastValidatedAt: retryTimestamp },\n paramEntries.map((e) => ({\n ...e,\n data: { ...e.data, lastValidatedAt: retryTimestamp },\n })),\n );\n this.#lastRevalidatedAt = retryTimestamp;\n return false;\n }\n\n // Validate manifest shape — a malformed response indicates a permanent\n // config error (wrong relayer URL, API version mismatch), not a transient\n // network issue. Log at error level so it's actionable.\n const manifestParsed = ManifestSchema.safeParse(await manifestRes.json());\n if (!manifestParsed.success) {\n this.#logger.error(\n \"Relayer manifest has unexpected shape — check relayer URL and API version\",\n {\n relayerUrl: this.#relayerUrl,\n error: z.prettifyError(manifestParsed.error),\n },\n );\n // Fail-open with short retry — but the error-level log distinguishes this from transient failures\n const retryTimestamp = now - this.#ttlMs + SHORT_RETRY_MS;\n await this.#writeEntries(\n pkKey,\n { ...storedPk, lastValidatedAt: retryTimestamp },\n paramEntries.map((e) => ({\n ...e,\n data: { ...e.data, lastValidatedAt: retryTimestamp },\n })),\n );\n this.#lastRevalidatedAt = retryTimestamp;\n return false;\n }\n const validManifest = manifestParsed.data.response;\n const fheKeyEntry = validManifest.fheKeyInfo[0];\n assertNonNullable(fheKeyEntry, \"manifest.response.fheKeyInfo[0]\");\n\n // ── 4. Check PK artifact ──────────────────────────\n const pkArtifactUrl = fheKeyEntry.fhePublicKey.urls[0];\n // URL change → stale\n if (storedPk.artifactUrl && pkArtifactUrl && pkArtifactUrl !== storedPk.artifactUrl) {\n await this.#clearAll(pkKey, paramEntries);\n this.#lastRevalidatedAt = null;\n return true;\n }\n\n let updatedPk: CachedPublicKey = { ...storedPk, lastValidatedAt: now };\n if (pkArtifactUrl) {\n const freshness = await this.#checkArtifactFreshness(pkArtifactUrl, storedPk);\n if (!freshness.fresh) {\n await this.#clearAll(pkKey, paramEntries);\n this.#lastRevalidatedAt = null;\n return true;\n }\n updatedPk = {\n ...updatedPk,\n artifactUrl: pkArtifactUrl,\n etag: freshness.etag,\n lastModified: freshness.lastModified,\n };\n }\n\n // ── 5. Check each CRS artifact ────────────────────\n const updatedParamEntries: typeof paramEntries = [];\n for (const entry of paramEntries) {\n const manifestCrs = validManifest.crs[String(entry.bits)];\n const crsUrl = manifestCrs?.urls[0];\n\n // URL change → stale\n if (entry.data.artifactUrl && crsUrl && crsUrl !== entry.data.artifactUrl) {\n await this.#clearAll(pkKey, paramEntries);\n this.#lastRevalidatedAt = null;\n return true;\n }\n\n let updatedData: CachedPublicParams = {\n ...entry.data,\n lastValidatedAt: now,\n };\n if (crsUrl) {\n const freshness = await this.#checkArtifactFreshness(crsUrl, entry.data);\n if (!freshness.fresh) {\n await this.#clearAll(pkKey, paramEntries);\n this.#lastRevalidatedAt = null;\n return true;\n }\n updatedData = {\n ...updatedData,\n artifactUrl: crsUrl,\n etag: freshness.etag,\n lastModified: freshness.lastModified,\n };\n }\n updatedParamEntries.push({ ...entry, data: updatedData });\n }\n\n // 6. All fresh — update timestamps and HTTP validators\n await this.#writeEntries(pkKey, updatedPk, updatedParamEntries);\n this.#lastRevalidatedAt = now;\n return false;\n } catch (err) {\n const error = toError(err);\n const isProgrammingError =\n err instanceof TypeError ||\n err instanceof ReferenceError ||\n err instanceof RangeError ||\n err instanceof SyntaxError;\n const level = isProgrammingError ? \"error\" : \"warn\";\n this.#logger[level](\n isProgrammingError\n ? \"Unexpected error during revalidation (possible bug)\"\n : \"Revalidation failed, using cached artifacts (fail-open)\",\n {\n chainId: this.#chainId,\n relayerUrl: this.#relayerUrl,\n error: error.message,\n },\n );\n\n // Fail-open: use short retry interval (5 min) instead of full TTL\n const retryTimestamp = now - this.#ttlMs + SHORT_RETRY_MS;\n try {\n if (storedPk) {\n await this.#writeEntries(\n pkKey,\n { ...storedPk, lastValidatedAt: retryTimestamp },\n paramEntries.map((e) => ({\n ...e,\n data: { ...e.data, lastValidatedAt: retryTimestamp },\n })),\n );\n }\n } catch (innerErr) {\n this.#logger.warn(\"Failed to update validation timestamps after revalidation error\", {\n chainId: this.#chainId,\n error: toError(innerErr).message,\n });\n }\n this.#lastRevalidatedAt = retryTimestamp;\n return false;\n }\n }\n\n // ── Artifact freshness via HTTP conditional requests ───\n\n async #checkArtifactFreshness(\n url: string,\n cached: { etag?: string; lastModified?: string },\n ): Promise<{ fresh: boolean; etag?: string; lastModified?: string }> {\n const hasValidators = Boolean(cached.etag || cached.lastModified);\n const headers: Record<string, string> = {};\n if (cached.etag) {\n headers[\"If-None-Match\"] = cached.etag;\n }\n if (cached.lastModified) {\n headers[\"If-Modified-Since\"] = cached.lastModified;\n }\n\n // HEAD avoids downloading the (potentially multi-MB) artifact body.\n // With conditional headers, the server returns 304 if unchanged or 200 (no body) if stale.\n let res = await globalThis.fetch(url, { method: \"HEAD\", headers });\n\n // Fallback to GET if HEAD is not supported (e.g. some CDN/WAF configs)\n if (res.status === 405) {\n res = await globalThis.fetch(url, { headers });\n }\n\n // Treat server errors as transient — throw so the outer catch applies fail-open with short retry.\n // Without this, a CDN 5xx would be misinterpreted as \"artifact changed\" and wipe the cache.\n if (!res.ok && res.status !== 304) {\n throw new Error(`Artifact freshness check failed: HEAD ${url} returned ${res.status}`);\n }\n\n const etag = res.headers.get(\"etag\") ?? undefined;\n const lastModified = res.headers.get(\"last-modified\") ?? undefined;\n\n if (res.status === 304) {\n return {\n fresh: true,\n etag: etag ?? cached.etag,\n lastModified: lastModified ?? cached.lastModified,\n };\n }\n\n if (!hasValidators) {\n // First revalidation — capture validators, treat as fresh\n return { fresh: true, etag, lastModified };\n }\n\n // 200 = artifact changed\n return { fresh: false, etag, lastModified };\n }\n\n // ── Internal helpers ────────────────────────────────────\n\n async #collectParamEntries(): Promise<\n Array<{ bits: number; key: string; data: CachedPublicParams }>\n > {\n // Merge in-memory keys with persisted index for cold-start CRS detection\n const persistedBits = await this.#readParamsIndex(\n \"Failed to read params index, CRS revalidation may be incomplete\",\n );\n const allBits = new Set([...this.#publicParamsMem.keys(), ...persistedBits]);\n\n const bitsArray = Array.from(allBits);\n const results = await Promise.all(\n bitsArray.map(async (bits) => {\n const pKey = paramsStorageKey(this.#chainId, bits);\n // Separate storage read from validation so we only delete on corruption\n let raw: unknown;\n try {\n raw = await this.#storage.get(pKey);\n } catch (err) {\n this.#logger.warn(\"Failed to read cached params entry during revalidation\", {\n chainId: this.#chainId,\n bits,\n error: toError(err).message,\n });\n return null;\n }\n if (raw === null || raw === undefined) {\n return null;\n }\n const data = await this.#parseCachedEntry(pKey, raw, CachedPublicParamsSchema, \"params\", {\n bits,\n });\n if (!data) {\n return null;\n }\n return { bits, key: pKey, data };\n }),\n );\n return results.filter(\n (e): e is { bits: number; key: string; data: CachedPublicParams } => e !== null,\n );\n }\n\n async #readCachedEntry<T>(\n key: string,\n schema: z.core.$ZodType<T>,\n label: string,\n readError: string,\n context: LogContext = {},\n ): Promise<T | null> {\n let raw: unknown;\n try {\n raw = await this.#storage.get(key);\n } catch (err) {\n this.#logger.warn(readError, {\n chainId: this.#chainId,\n ...context,\n error: toError(err).message,\n });\n return null;\n }\n if (raw === null || raw === undefined) {\n return null;\n }\n return this.#parseCachedEntry(key, raw, schema, label, context);\n }\n\n async #parseCachedEntry<T>(\n key: string,\n raw: unknown,\n schema: z.core.$ZodType<T>,\n label: string,\n context: LogContext = {},\n ): Promise<T | null> {\n const parsed = z.safeParse(schema, raw);\n if (parsed.success) {\n return parsed.data;\n }\n await this.#deleteCorruptEntry(key, label, {\n ...context,\n error: z.prettifyError(parsed.error),\n });\n return null;\n }\n\n async #readParamsIndex(readError: string): Promise<number[]> {\n const idxKey = paramsIndexKey(this.#chainId);\n const index = await this.#readCachedEntry(idxKey, ParamsIndexSchema, \"params index\", readError);\n return index ?? [];\n }\n\n async #deleteCorruptEntry(key: string, label: string, context: LogContext = {}): Promise<void> {\n await this.#deleteQuietly(key);\n this.#logger.warn(`Corrupt ${label} cache entry detected, deleting`, {\n chainId: this.#chainId,\n ...context,\n });\n }\n\n async #deleteQuietly(key: string): Promise<void> {\n await this.#storage.delete(key).catch((err) => {\n this.#logger.warn(\"Failed to delete cache entry\", {\n chainId: this.#chainId,\n key,\n error: toError(err).message,\n });\n });\n }\n\n async #clearAll(pkKey: string, paramEntries: Array<{ key: string }>): Promise<void> {\n const idxKey = paramsIndexKey(this.#chainId);\n // Delete from persistent storage first — if this fails, in-memory cache\n // still serves stale data, but the next revalidation cycle will retry.\n try {\n await Promise.all([\n this.#storage.delete(pkKey),\n this.#storage.delete(idxKey),\n ...paramEntries.map((entry) => this.#storage.delete(entry.key)),\n ]);\n } catch (err) {\n this.#logger.warn(\"Failed to clear stale artifacts from persistent storage\", {\n chainId: this.#chainId,\n error: toError(err).message,\n });\n }\n // Clear in-memory after storage to avoid re-loading stale entries on failure\n this.#publicKeyMem = undefined;\n this.#publicParamsMem.clear();\n }\n\n async #writeEntries(\n pkKey: string,\n pk: CachedPublicKey,\n paramEntries: Array<{ key: string; data: CachedPublicParams }>,\n ): Promise<void> {\n const writes = [\n this.#storage.set(pkKey, pk).catch((err) => {\n this.#logger.warn(\"Failed to update public key validation timestamp\", {\n chainId: this.#chainId,\n error: toError(err).message,\n });\n }),\n ...paramEntries.map((entry) =>\n this.#storage.set(entry.key, entry.data).catch((err) => {\n this.#logger.warn(\"Failed to update params validation timestamp\", {\n chainId: this.#chainId,\n error: toError(err).message,\n });\n }),\n ),\n ];\n await Promise.all(writes);\n }\n}\n","const MAX_RETRIES = 2;\nconst RETRY_BASE_MS = 500;\n\n/**\n * Retry an async operation with exponential backoff.\n * Only retries on transient errors (timeout, network). Does not retry user-facing errors.\n */\nexport async function withRetry<T>(fn: () => Promise<T>, retries = MAX_RETRIES): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n if (attempt < retries && isTransientError(error)) {\n await sleep(RETRY_BASE_MS * 2 ** attempt);\n continue;\n }\n throw error;\n }\n }\n throw lastError;\n}\n\nfunction isTransientError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n const msg = error.message.toLowerCase();\n return (\n msg.includes(\"timed out\") ||\n msg.includes(\"timeout\") ||\n msg.includes(\"econnreset\") ||\n msg.includes(\"econnrefused\") ||\n msg.includes(\"network\") ||\n msg.includes(\"fetch failed\") ||\n msg.includes(\"socket hang up\") ||\n msg.includes(\"502\") ||\n msg.includes(\"503\") ||\n msg.includes(\"504\")\n );\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type {\n InputProofBytesType,\n KmsDelegatedUserDecryptEIP712Type,\n ZKProofLike,\n} from \"@zama-fhe/relayer-sdk/bundle\";\nimport { toHex } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport { IndexedDBStorage } from \"../storage/indexeddb-storage\";\nimport type { GenericStorage } from \"../types\";\nimport type { RelayerWorkerClient } from \"../worker/worker.client\";\nimport type { FheChain } from \"../chains/types\";\nimport type { TransportKeyPair } from \"../credentials/types\";\nimport { BaseRelayer } from \"./base-relayer\";\nimport { FheArtifactCache } from \"./fhe-artifact-cache\";\nimport type { RelayerSDK } from \"./relayer-sdk\";\nimport type {\n ClearValue,\n DelegatedUserDecryptParams,\n EIP712TypedData,\n EncryptParams,\n EncryptResult,\n EncryptedValue,\n FheEncryptionKey,\n PublicDecryptResult,\n PublicParamsData,\n RelayerWebConfig,\n UserDecryptParams,\n} from \"./relayer-sdk.types\";\nimport { withRetry } from \"./relayer-utils\";\n\n/**\n * Pinned relayer SDK version used for the WASM CDN bundle.\n * Update this when upgrading @zama-fhe/relayer-sdk, and keep the\n * peerDependencies range in package.json in sync (~x.y.z).\n */\nexport const RELAYER_SDK_VERSION = \"0.4.4\";\nexport const CDN_URL = `https://cdn.zama.org/relayer-sdk-js/${RELAYER_SDK_VERSION}/relayer-sdk-js.umd.cjs`;\n/** SHA-384 hex digest of the pinned CDN bundle for integrity verification. */\nexport const CDN_INTEGRITY =\n \"a50426aae8440e802102c8674dd8451f34fe79352d5e2cc6b89d9f1aa340296176c2ee33d9aa4657752f8ca96f74f921\";\n\n/**\n * RelayerWeb — single-chain browser encryption/decryption layer.\n * The worker is injected at construction time; the relayer does not own its lifecycle.\n */\nexport class RelayerWeb extends BaseRelayer implements RelayerSDK, Disposable {\n #artifactCache: FheArtifactCache | null = null;\n #artifactStorage: GenericStorage | null = null;\n readonly #config: RelayerWebConfig;\n\n constructor(config: RelayerWebConfig) {\n super();\n this.#config = config;\n }\n\n protected get chain(): FheChain {\n return this.#config.chain;\n }\n\n protected async init(): Promise<void> {\n await this.#worker.initWorker();\n }\n\n get #worker(): RelayerWorkerClient {\n return this.#config.worker;\n }\n\n #getArtifactCache(): FheArtifactCache {\n if (!this.#artifactCache) {\n if (!this.#artifactStorage) {\n this.#artifactStorage =\n this.#config.fheArtifactStorage ??\n new IndexedDBStorage(\"FheArtifactCache\", 1, \"artifacts\");\n }\n this.#artifactCache = new FheArtifactCache({\n storage: this.#artifactStorage,\n chainId: this.chain.id,\n relayerUrl: this.chain.relayerUrl,\n ttl: this.#config.fheArtifactCacheTTL,\n logger: this.#config.logger,\n });\n }\n return this.#artifactCache;\n }\n\n /**\n * Terminate clears the artifact cache only.\n * The worker is externally owned — the relayer does not terminate it.\n */\n terminate(): void {\n this.#artifactCache = null;\n this.resetInit();\n }\n\n /** Calls {@link terminate}. */\n [Symbol.dispose](): void {\n this.terminate();\n }\n\n /**\n * Refresh the CSRF token in the worker.\n * Call this before making authenticated network requests.\n */\n async #refreshCsrfToken(): Promise<void> {\n const token = this.#config.security?.getCsrfToken?.() ?? \"\";\n if (token) {\n await this.#worker.updateCsrf(token);\n }\n }\n\n /**\n * Generate a transport key pair (ML-KEM public + private key) used for user-decryption.\n */\n async generateTransportKeyPair(): Promise<TransportKeyPair> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const result = await this.#worker.generateKeypair({ chainId });\n return {\n publicKey: result.publicKey,\n privateKey: result.privateKey,\n };\n }\n\n /**\n * Create EIP712 typed data for user decryption authorization.\n */\n async createEIP712(\n publicKey: Hex,\n contractAddresses: Address[],\n startTimestamp: number,\n durationDays = 7,\n ): Promise<EIP712TypedData> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return this.#worker.createEIP712({\n chainId,\n publicKey,\n contractAddresses,\n startTimestamp,\n durationDays,\n });\n }\n\n /**\n * Encrypt values for use in smart contract calls.\n * Each value must specify its FHE type (ebool, euint8–256, eaddress).\n */\n async encrypt(params: EncryptParams): Promise<EncryptResult> {\n const { values, contractAddress, userAddress } = params;\n await this.ensureInit();\n const chainId = this.chain.id;\n\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.encrypt({\n chainId,\n values,\n contractAddress,\n userAddress,\n });\n return {\n encryptedValues: result.handles.map((handle) => toHex(handle)),\n inputProof: toHex(result.inputProof),\n };\n });\n }\n\n /**\n * Decrypt ciphertexts using user's private key.\n * Requires a valid EIP712 signature.\n */\n async userDecrypt(\n params: UserDecryptParams,\n ): Promise<Readonly<Record<EncryptedValue, ClearValue>>> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.userDecrypt({ chainId, ...params });\n return result.clearValues;\n });\n }\n\n /**\n * Public decryption - no authorization needed.\n * Used for publicly visible encrypted values.\n */\n async publicDecrypt(encryptedValues: EncryptedValue[]): Promise<PublicDecryptResult> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.publicDecrypt({\n chainId,\n encryptedValues,\n });\n return {\n clearValues: result.clearValues,\n abiEncodedClearValues: result.abiEncodedClearValues,\n decryptionProof: result.decryptionProof,\n };\n });\n }\n\n /**\n * Create EIP712 typed data for delegated user decryption authorization.\n */\n async createDelegatedUserDecryptEIP712(\n publicKey: Hex,\n contractAddresses: Address[],\n delegatorAddress: Address,\n startTimestamp: number,\n durationDays = 7,\n ): Promise<KmsDelegatedUserDecryptEIP712Type> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return this.#worker.createDelegatedUserDecryptEIP712({\n chainId,\n publicKey,\n contractAddresses,\n delegatorAddress,\n startTimestamp,\n durationDays,\n });\n }\n\n /**\n * Decrypt ciphertexts via delegation.\n * Requires a valid EIP712 signature from the delegator.\n */\n async delegatedUserDecrypt(\n params: DelegatedUserDecryptParams,\n ): Promise<Readonly<Record<EncryptedValue, ClearValue>>> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.delegatedUserDecrypt({\n chainId,\n ...params,\n });\n return result.clearValues;\n });\n }\n\n /**\n * Submit a ZK proof to the relayer for verification.\n */\n async requestZKProofVerification(zkProof: ZKProofLike): Promise<InputProofBytesType> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n return this.#worker.requestZKProofVerification({ chainId, zkProof });\n });\n }\n\n /**\n * Fetch the network's FHE encryption key (ID + bytes).\n * When storage is configured, the result is cached persistently.\n */\n async fetchFheEncryptionKeyBytes(): Promise<FheEncryptionKey | null> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const artifactCache = this.#getArtifactCache();\n return artifactCache.fetchFheEncryptionKeyBytes(\n async () => (await this.#worker.getPublicKey({ chainId })).result,\n );\n }\n\n /**\n * Get public parameters for encryption capacity.\n * When storage is configured, the result is cached persistently.\n */\n async getPublicParams(bits: number): Promise<PublicParamsData | null> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const artifactCache = this.#getArtifactCache();\n return artifactCache.getPublicParams(\n bits,\n async () => (await this.#worker.getPublicParams({ chainId, bits })).result,\n );\n }\n}\n","import type {\n CreateDelegatedEIP712Payload,\n CreateDelegatedEIP712ResponseData,\n CreateEIP712Payload,\n CreateEIP712ResponseData,\n DelegatedUserDecryptPayload,\n DelegatedUserDecryptResponseData,\n EncryptPayload,\n EncryptResponseData,\n GenerateKeypairRequest,\n GenerateKeypairResponseData,\n GetPublicKeyRequest,\n GetPublicKeyResponseData,\n GetPublicParamsRequest,\n GetPublicParamsResponseData,\n InitResponseData,\n PublicDecryptPayload,\n PublicDecryptResponseData,\n RequestZKProofVerificationRequest,\n RequestZKProofVerificationResponseData,\n UserDecryptPayload,\n UserDecryptResponseData,\n GenericLogger,\n WorkerEnv,\n WorkerRequest,\n WorkerRequestType,\n WorkerResponse,\n} from \"./worker.types\";\n\n/** Pending request tracker */\ninterface PendingRequest<T> {\n resolve: (value: T) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n startTime: number;\n type: WorkerRequestType;\n}\n\n/** Default timeout for operations (30 seconds) */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Extended timeout for WASM initialization (60 seconds) */\nexport const INIT_TIMEOUT_MS = 60_000;\n\n/**\n * Abstract base class for worker clients (browser Web Worker and Node.js worker_threads).\n * Encapsulates all shared logic: pending request tracking, timeouts, init dedup, domain methods.\n * Subclasses implement the abstract hooks for platform-specific worker creation and messaging.\n */\nexport abstract class BaseWorkerClient<TWorker, TConfig> {\n #worker: TWorker | null = null;\n #pendingRequests = new Map<string, PendingRequest<unknown>>();\n #initPromise: Promise<TWorker> | null = null;\n protected readonly config: TConfig;\n protected readonly logger: GenericLogger | undefined;\n\n constructor(config: TConfig, logger: GenericLogger | undefined) {\n this.config = config;\n this.logger = logger;\n }\n\n // ===========================================================================\n // Abstract hooks — subclasses must implement\n // ===========================================================================\n\n /** Create the platform-specific worker instance. */\n protected abstract createWorker(): TWorker;\n\n /** Wire message/error/messageerror events on the worker. */\n protected abstract wireEvents(worker: TWorker): void;\n\n /** Post a message to the worker. */\n protected abstract postMessage(worker: TWorker, request: WorkerRequest): void;\n\n /** Terminate the platform-specific worker. */\n protected abstract terminateWorker(worker: TWorker): void;\n\n /** Generate a unique request ID. */\n protected abstract generateRequestId(): string;\n\n /** Return the init request type and payload. */\n protected abstract getInitPayload(): {\n type: WorkerRequestType;\n payload: WorkerRequest[\"payload\"];\n };\n\n /** Subclasses set \"web\" or \"node\" — stamps the env discriminant on INIT payloads. */\n protected abstract readonly env: WorkerEnv;\n\n /** Optional hook called after worker init succeeds (e.g. for node worker.unref()). */\n protected onWorkerReady?(_worker: TWorker): void;\n\n // ===========================================================================\n // Shared init / terminate\n // ===========================================================================\n\n async initWorker(): Promise<TWorker> {\n if (this.#worker) {\n return this.#worker;\n }\n\n if (!this.#initPromise) {\n this.#initPromise = this.#doInitWorker().catch((error) => {\n this.#initPromise = null;\n throw error;\n });\n }\n return this.#initPromise;\n }\n\n async #doInitWorker(): Promise<TWorker> {\n const worker = this.createWorker();\n this.wireEvents(worker);\n\n try {\n const { type, payload } = this.getInitPayload();\n await this.sendRequestTo<InitResponseData>(worker, type, payload, INIT_TIMEOUT_MS);\n this.onWorkerReady?.(worker);\n this.#worker = worker;\n } catch (error) {\n this.terminateWorker(worker);\n throw error;\n }\n\n return this.#worker;\n }\n\n terminate(): void {\n if (this.#worker) {\n for (const [id, pending] of this.#pendingRequests) {\n clearTimeout(pending.timeoutId);\n pending.reject(new Error(\"Worker terminated\"));\n this.#pendingRequests.delete(id);\n }\n\n this.terminateWorker(this.#worker);\n this.#worker = null;\n }\n this.#initPromise = null;\n }\n\n // ===========================================================================\n // Message handling\n // ===========================================================================\n\n protected handleResponse(response: WorkerResponse<unknown>): void {\n const pending = this.#pendingRequests.get(response.id);\n\n if (!pending) {\n this.logger?.warn(\"[WorkerClient] Received response for unknown request\", {\n id: response.id,\n });\n return;\n }\n\n const elapsed = Math.round(performance.now() - pending.startTime);\n\n clearTimeout(pending.timeoutId);\n this.#pendingRequests.delete(response.id);\n\n if (response.success) {\n this.logger?.debug(`[WorkerClient] ← ${pending.type} OK`, {\n id: response.id,\n elapsed,\n });\n pending.resolve(response.data);\n } else {\n this.logger?.error(`[WorkerClient] ← ${pending.type} FAILED`, {\n id: response.id,\n elapsed,\n error: response.error,\n });\n const err = new Error(response.error);\n if (\"statusCode\" in response && typeof response.statusCode === \"number\") {\n (err as Error & { statusCode?: number }).statusCode = response.statusCode;\n }\n pending.reject(err);\n }\n }\n\n protected handleWorkerError(message: string): void {\n this.logger?.error(\"[WorkerClient] Worker error\", { error: message });\n const worker = this.#worker;\n this.#worker = null;\n this.#rejectAllPending(`Worker error: ${message}`);\n if (worker) {\n this.terminateWorker(worker);\n }\n }\n\n protected handleWorkerMessageError(): void {\n this.logger?.error(\"[WorkerClient] Message deserialization failed\");\n const worker = this.#worker;\n this.#worker = null;\n this.#rejectAllPending(\"Worker message deserialization failed\");\n if (worker) {\n this.terminateWorker(worker);\n }\n }\n\n // ===========================================================================\n // Request sending\n // ===========================================================================\n\n protected sendRequestTo<T>(\n worker: TWorker,\n type: WorkerRequestType,\n payload: WorkerRequest[\"payload\"],\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const id = this.generateRequestId();\n const startTime = performance.now();\n this.logger?.debug(`[WorkerClient] → ${type}`, { id });\n\n const timeoutId = setTimeout(() => {\n this.#pendingRequests.delete(id);\n const elapsed = Math.round(performance.now() - startTime);\n this.logger?.error(`[WorkerClient] ${type} timed out after ${timeoutMs}ms`, {\n id,\n elapsed,\n });\n reject(new Error(`Request ${type} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n this.#pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timeoutId,\n startTime,\n type,\n });\n\n const request = { id, type, payload } as WorkerRequest;\n this.postMessage(worker, request);\n });\n }\n\n protected async sendRequest<T>(\n type: WorkerRequestType,\n payload: WorkerRequest[\"payload\"],\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n ): Promise<T> {\n const worker = await this.initWorker();\n return this.sendRequestTo<T>(worker, type, payload, timeoutMs);\n }\n\n // ===========================================================================\n // Domain methods\n // ===========================================================================\n\n async generateKeypair(\n params: GenerateKeypairRequest[\"payload\"],\n ): Promise<GenerateKeypairResponseData> {\n return this.sendRequest<GenerateKeypairResponseData>(\"GENERATE_KEYPAIR\", params);\n }\n\n async createEIP712(params: CreateEIP712Payload): Promise<CreateEIP712ResponseData> {\n return this.sendRequest<CreateEIP712ResponseData>(\"CREATE_EIP712\", params);\n }\n\n async encrypt(params: EncryptPayload): Promise<EncryptResponseData> {\n return this.sendRequest<EncryptResponseData>(\"ENCRYPT\", params);\n }\n\n async userDecrypt(params: UserDecryptPayload): Promise<UserDecryptResponseData> {\n return this.sendRequest<UserDecryptResponseData>(\"USER_DECRYPT\", params);\n }\n\n async publicDecrypt(params: PublicDecryptPayload): Promise<PublicDecryptResponseData> {\n return this.sendRequest<PublicDecryptResponseData>(\"PUBLIC_DECRYPT\", params);\n }\n\n async createDelegatedUserDecryptEIP712(\n params: CreateDelegatedEIP712Payload,\n ): Promise<CreateDelegatedEIP712ResponseData> {\n return this.sendRequest<CreateDelegatedEIP712ResponseData>(\"CREATE_DELEGATED_EIP712\", params);\n }\n\n async delegatedUserDecrypt(\n params: DelegatedUserDecryptPayload,\n ): Promise<DelegatedUserDecryptResponseData> {\n return this.sendRequest<DelegatedUserDecryptResponseData>(\"DELEGATED_USER_DECRYPT\", params);\n }\n\n async requestZKProofVerification(\n params: RequestZKProofVerificationRequest[\"payload\"],\n ): Promise<RequestZKProofVerificationResponseData> {\n return this.sendRequest<RequestZKProofVerificationResponseData>(\n \"REQUEST_ZK_PROOF_VERIFICATION\",\n params,\n );\n }\n\n async getPublicKey(params: GetPublicKeyRequest[\"payload\"]): Promise<GetPublicKeyResponseData> {\n return this.sendRequest<GetPublicKeyResponseData>(\"GET_PUBLIC_KEY\", params);\n }\n\n async getPublicParams(\n params: GetPublicParamsRequest[\"payload\"],\n ): Promise<GetPublicParamsResponseData> {\n return this.sendRequest<GetPublicParamsResponseData>(\"GET_PUBLIC_PARAMS\", params);\n }\n\n // ===========================================================================\n // Internal helpers\n // ===========================================================================\n\n #rejectAllPending(message: string): void {\n for (const [id, pending] of this.#pendingRequests) {\n clearTimeout(pending.timeoutId);\n pending.reject(new Error(message));\n this.#pendingRequests.delete(id);\n }\n }\n}\n","import { assertFunctionProp, assertObject, assertStringProp } from \"../utils/assertions\";\n\n/**\n * Subset of the WebExtensions `runtime` API used by the SDK.\n * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime\n */\nexport interface BrowserExtensionRuntime {\n /** The ID of the extension. */\n id: string;\n /** Convert a relative path within the extension to a fully-qualified URL. */\n getURL: (path: string) => string;\n}\n\nfunction isValidRuntime(runtime: unknown): runtime is BrowserExtensionRuntime {\n try {\n assertObject(runtime, \"runtime\");\n assertStringProp(runtime, \"id\", \"runtime.id\");\n assertFunctionProp<\"getURL\", (path: string) => string>(runtime, \"getURL\", \"runtime.getURL\");\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Return the browser extension runtime object, or `undefined` outside extensions.\n * Works across Chrome/Edge (`chrome.runtime`) and Firefox/Safari (`browser.runtime`).\n * Extensions have restricted CSP that blocks `blob:` URLs, so callers use\n * this to detect the environment and resolve file URLs via `runtime.getURL`.\n */\nexport function getBrowserExtensionRuntime(): BrowserExtensionRuntime | undefined {\n const g = globalThis as unknown as Record<string, unknown>;\n for (const ns of [g.chrome, g.browser]) {\n try {\n assertObject(ns, \"ns\");\n if (isValidRuntime(ns.runtime)) {\n return ns.runtime;\n }\n } catch {\n continue;\n }\n }\n return undefined;\n}\n","import type { FheChain } from \"../chains/types\";\nimport type {\n GenericLogger,\n UpdateCsrfResponseData,\n WorkerEnv,\n WorkerRequest,\n WorkerRequestType,\n WorkerResponse,\n} from \"./worker.types\";\nimport { BaseWorkerClient } from \"./worker.base-client\";\nimport { getBrowserExtensionRuntime } from \"./browser-extension\";\nimport { default as workerCode, filename as workerFilename } from \"./relayer-sdk.worker.ts?iife\";\n\n/** Configuration for the worker client */\nexport interface WorkerClientConfig {\n cdnUrl: string;\n chains: FheChain[];\n csrfToken: string;\n /** Expected SHA-384 hex digest of the CDN bundle for integrity verification. */\n integrity?: string;\n /** Optional logger for tracing worker request lifecycle. */\n logger?: GenericLogger;\n /** Number of WASM threads for parallel FHE operations (passed to `initSDK({ thread })`). */\n thread?: number;\n}\n\n/**\n * Client for communicating with the RelayerSDK Web Worker.\n * Provides a promise-based API for FHE operations.\n */\nexport class RelayerWorkerClient extends BaseWorkerClient<Worker, WorkerClientConfig> {\n protected readonly env: WorkerEnv = \"web\";\n\n constructor(config: WorkerClientConfig) {\n super(config, config.logger);\n }\n\n protected createWorker(): Worker {\n const runtime = getBrowserExtensionRuntime();\n if (runtime) {\n return new Worker(runtime.getURL(workerFilename));\n }\n const blobUrl = URL.createObjectURL(new Blob([workerCode], { type: \"application/javascript\" }));\n try {\n return new Worker(blobUrl);\n } finally {\n URL.revokeObjectURL(blobUrl);\n }\n }\n\n protected wireEvents(worker: Worker): void {\n worker.onmessage = (event: MessageEvent<WorkerResponse<unknown>>) =>\n this.handleResponse(event.data);\n worker.onerror = (event: ErrorEvent) => this.handleWorkerError(event.message);\n worker.onmessageerror = () => this.handleWorkerMessageError();\n }\n\n protected postMessage(worker: Worker, request: WorkerRequest): void {\n worker.postMessage(request);\n }\n\n protected terminateWorker(worker: Worker): void {\n worker.terminate();\n }\n\n protected generateRequestId(): string {\n return crypto.randomUUID();\n }\n\n protected getInitPayload(): {\n type: WorkerRequestType;\n payload: WorkerRequest[\"payload\"];\n } {\n // Explicitly construct the payload from serializable fields only.\n // Functions (e.g. `logger`) cannot be cloned by the structured clone\n // algorithm used by `worker.postMessage()`.\n const { cdnUrl, chains, csrfToken, integrity, thread } = this.config;\n return {\n type: \"INIT\",\n payload: { env: \"web\" as const, cdnUrl, chains, csrfToken, integrity, thread },\n };\n }\n\n /**\n * Update the CSRF token in the worker.\n * Call this before making authenticated requests to ensure the token is fresh.\n */\n async updateCsrf(csrfToken: string): Promise<void> {\n await this.sendRequest<UpdateCsrfResponseData>(\"UPDATE_CSRF\", {\n csrfToken,\n });\n }\n}\n","import { z } from \"zod/mini\";\nimport { CDN_INTEGRITY, CDN_URL, RelayerWeb } from \"../relayer/relayer-web\";\nimport { parseConfiguration } from \"../validation\";\nimport { RelayerWorkerClient } from \"../worker/worker.client\";\nimport type { WebRelayerConfig, WebRelayerOptions } from \"./types\";\n\nconst WebRelayerOptionsSchema = z.object({\n threads: z.optional(z.int().check(z.positive())),\n fheArtifactCacheTTL: z.optional(z.int().check(z.nonnegative())),\n});\n\n/**\n * Browser relayer — routes to RelayerWeb (Web Worker + WASM).\n *\n * @param options - Worker options (threads, security, logger, storage).\n *\n * @example\n * ```ts\n * relayers: {\n * [sepolia.id]: web(),\n * [mainnet.id]: web({ threads: 4 }),\n * }\n * ```\n */\nexport function web(options?: WebRelayerOptions): WebRelayerConfig {\n if (options !== undefined) {\n parseConfiguration(WebRelayerOptionsSchema, options);\n }\n return {\n type: \"web\",\n createWorker: (chains) =>\n new RelayerWorkerClient({\n cdnUrl: CDN_URL,\n chains,\n csrfToken: options?.security?.getCsrfToken?.() ?? \"\",\n integrity: options?.security?.integrityCheck === false ? undefined : CDN_INTEGRITY,\n logger: options?.logger,\n thread: options?.threads,\n }),\n createRelayer: (chain, worker) => new RelayerWeb({ chain, worker, ...options }),\n };\n}\n"],"mappings":"mLAGA,IAAsB,EAAtB,KAAkC,CAChC,GAAqC,KAIrC,MAAgB,YAA4B,CAO1C,MANA,CACE,KAAKA,KAAe,KAAK,KAAK,CAAC,CAAC,MAAO,GAAU,CAE/C,KADA,MAAKA,GAAe,KACd,CACR,CAAC,EAEI,KAAKA,EACd,CAEA,WAA4B,CAC1B,KAAKA,GAAe,IACtB,CAEA,MAAM,eAAkC,CACtC,OAAO,KAAK,MAAM,kBACpB,CACF,ECjBA,MAAM,EAAqBC,EAAAA,EAAE,OAAO,CAClC,YAAaA,EAAAA,EAAE,SAASA,EAAAA,EAAE,OAAO,CAAC,EAClC,KAAMA,EAAAA,EAAE,SAASA,EAAAA,EAAE,OAAO,CAAC,EAC3B,aAAcA,EAAAA,EAAE,SAASA,EAAAA,EAAE,OAAO,CAAC,EAInC,gBAAiBA,EAAAA,EAAE,SAASA,EAAAA,EAAE,SAASA,EAAAA,EAAE,OAAO,CAAC,CAAC,MAAMA,EAAAA,EAAE,YAAY,CAAC,CAAC,EAAG,CAAC,CAC9E,CAAC,EAGK,EAAwBA,EAAAA,EAAE,OAAO,EAAoB,CACzD,YAAaA,EAAAA,EAAE,OAAO,EACtB,UAAWA,EAAAA,EAAE,OAAO,CACtB,CAAC,EAIK,EAA2BA,EAAAA,EAAE,OAAO,EAAoB,CAC5D,eAAgBA,EAAAA,EAAE,OAAO,EACzB,aAAcA,EAAAA,EAAE,OAAO,CACzB,CAAC,EAGK,EAAoBA,EAAAA,EAAE,MAAMA,EAAAA,EAAE,IAAI,CAAC,CAAC,MAAMA,EAAAA,EAAE,YAAY,CAAC,CAAC,EAO1D,EAAiBA,EAAAA,EAAE,OAAO,CAC9B,OAAQA,EAAAA,EAAE,QAAQ,WAAW,EAC7B,SAAUA,EAAAA,EAAE,OAAO,CACjB,WAAYA,EAAAA,EACT,MACCA,EAAAA,EAAE,OAAO,CACP,aAAcA,EAAAA,EAAE,OAAO,CACrB,KAAMA,EAAAA,EAAE,MAAMA,EAAAA,EAAE,OAAO,CAAC,CAAC,CAAC,MAAMA,EAAAA,EAAE,UAAU,CAAC,CAAC,CAChD,CAAC,CACH,CAAC,CACH,CAAC,CACA,MAAMA,EAAAA,EAAE,UAAU,CAAC,CAAC,EACvB,IAAKA,EAAAA,EAAE,OACLA,EAAAA,EAAE,OAAO,EACTA,EAAAA,EAAE,OAAO,CACP,KAAMA,EAAAA,EAAE,MAAMA,EAAAA,EAAE,OAAO,CAAC,CAAC,CAAC,MAAMA,EAAAA,EAAE,UAAU,CAAC,CAAC,CAChD,CAAC,CACH,CACF,CAAC,CACH,CAAC,EAaK,EAAa,KAGb,EAAiB,IAAS,IAIhC,SAAS,EAAS,EAA2B,CAC3C,IAAM,EAAmB,CAAC,EAC1B,IAAK,IAAI,EAAI,EAAG,EAAI,EAAM,OAAQ,GAAK,EACrC,EAAO,KAAK,OAAO,aAAa,GAAG,EAAM,SAAS,EAAG,EAAI,CAAU,CAAC,CAAC,EAEvE,OAAO,KAAK,EAAO,KAAK,EAAE,CAAC,CAC7B,CAEA,SAAS,EAAW,EAAyB,CAC3C,IAAI,EACJ,GAAI,CACF,EAAS,KAAK,CAAG,CACnB,MAAQ,CACN,MAAU,MAAM,gCAAgC,EAAI,OAAO,EAAE,CAC/D,CACA,GAAI,EAAO,SAAW,EACpB,MAAU,MAAM,2BAA2B,EAE7C,IAAM,EAAQ,IAAI,WAAW,EAAO,MAAM,EAC1C,IAAK,IAAI,EAAI,EAAG,EAAI,EAAO,OAAQ,IACjC,EAAM,GAAK,EAAO,WAAW,CAAC,EAEhC,OAAO,CACT,CAEA,SAAS,EAAiB,EAAyB,CACjD,MAAO,cAAc,GACvB,CAEA,SAAS,EAAiB,EAAiB,EAAsB,CAC/D,MAAO,cAAc,EAAQ,GAAG,GAClC,CAEA,SAAS,EAAe,EAAyB,CAC/C,MAAO,oBAAoB,GAC7B,CAcA,IAAa,EAAb,KAA8B,CAC5B,GACA,GACA,GACA,GACA,GACA,GACA,GAAmB,IAAI,IACvB,GAA6D,KAC7D,GAAwB,IAAI,IAC5B,GAAiD,KAEjD,GAAoC,KAEpC,YAAY,EAOT,CACD,KAAKC,GAAW,EAAK,QACrB,KAAKC,GAAW,EAAK,QACrB,KAAKC,GAAc,EAAK,WACxB,KAAKC,IAAU,EAAK,KAAO,OAAU,IACrC,KAAKC,GAAU,EAAK,QAAU,OAChC,CAIA,MAAM,2BACJ,EACiC,CACjC,GAAI,KAAKC,KAAkB,IAAA,GACzB,OAAO,KAAKA,GAId,GAAI,KAAKC,GACP,OAAO,KAAKA,GAGd,KAAKA,GAAqB,KAAKC,GAAsB,CAAO,EAC5D,GAAI,CACF,OAAO,MAAM,KAAKD,EACpB,QAAU,CACR,KAAKA,GAAqB,IAC5B,CACF,CAEA,KAAMC,GACJ,EACiC,CACjC,IAAM,EAAM,EAAiB,KAAKN,EAAQ,EAEpC,EAAS,MAAM,KAAKO,GACxB,EACA,EACA,aACA,kFACF,EACA,GAAI,EACF,GAAI,CACF,IAAM,EAAiC,CACrC,YAAa,EAAO,YACpB,UAAW,EAAW,EAAO,SAAS,CACxC,EAEA,MADA,MAAKH,GAAgB,EACd,CACT,OAAS,EAAK,CACZ,MAAM,KAAKI,GAAoB,EAAK,aAAc,CAAE,MAAOC,EAAAA,EAAQ,CAAG,CAAC,CAAC,OAAQ,CAAC,CACnF,CAGF,IAAM,EAAS,MAAM,EAAQ,EAC7B,GAAI,IAAW,KACb,OAAO,KAGT,KAAKL,GAAgB,EAErB,GAAI,CACF,IAAM,EAAyB,CAC7B,YAAa,EAAO,YACpB,UAAW,EAAS,EAAO,SAAS,EACpC,gBAAiB,KAAK,IAAI,CAC5B,EACA,MAAM,KAAKL,GAAS,IAAI,EAAK,CAAK,CACpC,OAAS,EAAK,CACZ,KAAKI,GAAQ,KAAK,0CAA2C,CAC3D,QAAS,KAAKH,GACd,MAAOS,EAAAA,EAAQ,CAAG,CAAC,CAAC,OACtB,CAAC,CACH,CAEA,OAAO,CACT,CAIA,MAAM,gBACJ,EACA,EAC6B,CAC7B,IAAM,EAAM,KAAKC,GAAiB,IAAI,CAAI,EAC1C,GAAI,IAAQ,IAAA,GACV,OAAO,EAIT,IAAM,EAAW,KAAKC,GAAsB,IAAI,CAAI,EACpD,GAAI,EACF,OAAO,EAGT,IAAM,EAAU,KAAKC,GAAkB,EAAM,CAAO,EACpD,KAAKD,GAAsB,IAAI,EAAM,CAAO,EAC5C,GAAI,CACF,OAAO,MAAM,CACf,QAAU,CACR,KAAKA,GAAsB,OAAO,CAAI,CACxC,CACF,CAEA,KAAMC,GACJ,EACA,EAC6B,CAC7B,IAAM,EAAM,EAAiB,KAAKZ,GAAU,CAAI,EAE1C,EAAS,MAAM,KAAKO,GACxB,EACA,EACA,SACA,sFACA,CAAE,MAAK,CACT,EACA,GAAI,EACF,GAAI,CACF,IAAM,EAA6B,CACjC,eAAgB,EAAO,eACvB,aAAc,EAAW,EAAO,YAAY,CAC9C,EAEA,OADA,KAAKG,GAAiB,IAAI,EAAM,CAAM,EAC/B,CACT,OAAS,EAAK,CACZ,MAAM,KAAKF,GAAoB,EAAK,SAAU,CAAE,OAAM,MAAOC,EAAAA,EAAQ,CAAG,CAAC,CAAC,OAAQ,CAAC,CACrF,CAGF,IAAM,EAAS,MAAM,EAAQ,EAC7B,GAAI,IAAW,KACb,OAAO,KAGT,KAAKC,GAAiB,IAAI,EAAM,CAAM,EAEtC,GAAI,CACF,IAAM,EAA4B,CAChC,eAAgB,EAAO,eACvB,aAAc,EAAS,EAAO,YAAY,EAC1C,gBAAiB,KAAK,IAAI,CAC5B,EACA,MAAM,KAAKX,GAAS,IAAI,EAAK,CAAK,EAGlC,IAAM,EAAS,EAAe,KAAKC,EAAQ,EACrC,EAAW,MAAM,KAAKa,GAAiB,0CAA0C,EAClF,EAAS,SAAS,CAAI,GACzB,MAAM,KAAKd,GAAS,IAAI,EAAQ,CAAC,GAAG,EAAU,CAAI,CAAC,CAEvD,OAAS,EAAK,CACZ,KAAKI,GAAQ,KAAK,6CAA8C,CAC9D,QAAS,KAAKH,GACd,OACA,MAAOS,EAAAA,EAAQ,CAAG,CAAC,CAAC,OACtB,CAAC,CACH,CAEA,OAAO,CACT,CAYA,MAAM,iBAAoC,CAExC,GAAI,KAAKK,GACP,OAAO,KAAKA,GAEd,KAAKA,GAAwB,KAAKC,GAAsB,EACxD,GAAI,CACF,OAAO,MAAM,KAAKD,EACpB,QAAU,CACR,KAAKA,GAAwB,IAC/B,CACF,CAEA,KAAMC,IAA0C,CAE9C,IAAM,EAAM,KAAK,IAAI,EAMrB,GALI,KAAKC,KAAuB,MAAQ,EAAM,KAAKA,GAAqB,KAAKd,IAKzE,CAAC,KAAKD,GACR,MAAO,GAGT,IAAM,EAAQ,EAAiB,KAAKD,EAAQ,EAGxC,EAAmC,KACnC,EAIC,CAAC,EAEN,GAAI,CAEF,GAAM,CAAC,EAAO,GAAW,MAAM,QAAQ,IAAI,CACzC,KAAKD,GAAS,IAAI,CAAK,EACvB,KAAKkB,GAAqB,CAC5B,CAAC,EASD,GANI,GAAU,OACZ,EAAW,MAAM,KAAKC,GAAkB,EAAO,EAAO,EAAuB,YAAY,GAG3F,EAAe,EAEX,CAAC,EACH,MAAO,GAST,GADiB,CAHf,EACA,GAAG,EAAa,IAAK,GAAM,EAAE,IAAI,CAET,CAAC,CAAC,MAAO,GAAM,EAAM,EAAE,gBAAkB,KAAKhB,EAC7D,EAET,MADA,MAAKc,GAAqB,EACnB,GAIT,IAAM,EAAc,MAAM,WAAW,MAAM,GAAG,KAAKf,GAAY,QAAQ,EACvE,GAAI,CAAC,EAAY,GAAI,CAEnB,IAAM,EAAiB,EAAM,KAAKC,GAAS,EAc3C,OAbA,KAAKC,GAAQ,KAAK,+DAAgE,CAChF,OAAQ,EAAY,OACpB,WAAY,KAAKF,EACnB,CAAC,EACD,MAAM,KAAKkB,GACT,EACA,CAAE,GAAG,EAAU,gBAAiB,CAAe,EAC/C,EAAa,IAAK,IAAO,CACvB,GAAG,EACH,KAAM,CAAE,GAAG,EAAE,KAAM,gBAAiB,CAAe,CACrD,EAAE,CACJ,EACA,KAAKH,GAAqB,EACnB,EACT,CAKA,IAAM,EAAiB,EAAe,UAAU,MAAM,EAAY,KAAK,CAAC,EACxE,GAAI,CAAC,EAAe,QAAS,CAC3B,KAAKb,GAAQ,MACX,4EACA,CACE,WAAY,KAAKF,GACjB,MAAOH,EAAAA,EAAE,cAAc,EAAe,KAAK,CAC7C,CACF,EAEA,IAAM,EAAiB,EAAM,KAAKI,GAAS,EAU3C,OATA,MAAM,KAAKiB,GACT,EACA,CAAE,GAAG,EAAU,gBAAiB,CAAe,EAC/C,EAAa,IAAK,IAAO,CACvB,GAAG,EACH,KAAM,CAAE,GAAG,EAAE,KAAM,gBAAiB,CAAe,CACrD,EAAE,CACJ,EACA,KAAKH,GAAqB,EACnB,EACT,CACA,IAAM,EAAgB,EAAe,KAAK,SACpC,EAAc,EAAc,WAAW,GAC7C,EAAA,EAAkB,EAAa,iCAAiC,EAGhE,IAAM,EAAgB,EAAY,aAAa,KAAK,GAEpD,GAAI,EAAS,aAAe,GAAiB,IAAkB,EAAS,YAGtE,OAFA,MAAM,KAAKI,GAAU,EAAO,CAAY,EACxC,KAAKJ,GAAqB,KACnB,GAGT,IAAI,EAA6B,CAAE,GAAG,EAAU,gBAAiB,CAAI,EACrE,GAAI,EAAe,CACjB,IAAM,EAAY,MAAM,KAAKK,GAAwB,EAAe,CAAQ,EAC5E,GAAI,CAAC,EAAU,MAGb,OAFA,MAAM,KAAKD,GAAU,EAAO,CAAY,EACxC,KAAKJ,GAAqB,KACnB,GAET,EAAY,CACV,GAAG,EACH,YAAa,EACb,KAAM,EAAU,KAChB,aAAc,EAAU,YAC1B,CACF,CAGA,IAAM,EAA2C,CAAC,EAClD,IAAK,IAAM,KAAS,EAAc,CAEhC,IAAM,EADc,EAAc,IAAI,OAAO,EAAM,IAAI,EAC7B,EAAE,KAAK,GAGjC,GAAI,EAAM,KAAK,aAAe,GAAU,IAAW,EAAM,KAAK,YAG5D,OAFA,MAAM,KAAKI,GAAU,EAAO,CAAY,EACxC,KAAKJ,GAAqB,KACnB,GAGT,IAAI,EAAkC,CACpC,GAAG,EAAM,KACT,gBAAiB,CACnB,EACA,GAAI,EAAQ,CACV,IAAM,EAAY,MAAM,KAAKK,GAAwB,EAAQ,EAAM,IAAI,EACvE,GAAI,CAAC,EAAU,MAGb,OAFA,MAAM,KAAKD,GAAU,EAAO,CAAY,EACxC,KAAKJ,GAAqB,KACnB,GAET,EAAc,CACZ,GAAG,EACH,YAAa,EACb,KAAM,EAAU,KAChB,aAAc,EAAU,YAC1B,CACF,CACA,EAAoB,KAAK,CAAE,GAAG,EAAO,KAAM,CAAY,CAAC,CAC1D,CAKA,OAFA,MAAM,KAAKG,GAAc,EAAO,EAAW,CAAmB,EAC9D,KAAKH,GAAqB,EACnB,EACT,OAAS,EAAK,CACZ,IAAM,EAAQP,EAAAA,EAAQ,CAAG,EACnB,EACJ,aAAe,WACf,aAAe,gBACf,aAAe,YACf,aAAe,YACX,EAAQ,EAAqB,QAAU,OAC7C,KAAKN,GAAQ,EAAM,CACjB,EACI,sDACA,0DACJ,CACE,QAAS,KAAKH,GACd,WAAY,KAAKC,GACjB,MAAO,EAAM,OACf,CACF,EAGA,IAAM,EAAiB,EAAM,KAAKC,GAAS,EAC3C,GAAI,CACE,GACF,MAAM,KAAKiB,GACT,EACA,CAAE,GAAG,EAAU,gBAAiB,CAAe,EAC/C,EAAa,IAAK,IAAO,CACvB,GAAG,EACH,KAAM,CAAE,GAAG,EAAE,KAAM,gBAAiB,CAAe,CACrD,EAAE,CACJ,CAEJ,OAAS,EAAU,CACjB,KAAKhB,GAAQ,KAAK,kEAAmE,CACnF,QAAS,KAAKH,GACd,MAAOS,EAAAA,EAAQ,CAAQ,CAAC,CAAC,OAC3B,CAAC,CACH,CAEA,MADA,MAAKO,GAAqB,EACnB,EACT,CACF,CAIA,KAAMK,GACJ,EACA,EACmE,CACnE,IAAM,EAAgB,GAAQ,EAAO,MAAQ,EAAO,cAC9C,EAAkC,CAAC,EACrC,EAAO,OACT,EAAQ,iBAAmB,EAAO,MAEhC,EAAO,eACT,EAAQ,qBAAuB,EAAO,cAKxC,IAAI,EAAM,MAAM,WAAW,MAAM,EAAK,CAAE,OAAQ,OAAQ,SAAQ,CAAC,EASjE,GANI,EAAI,SAAW,MACjB,EAAM,MAAM,WAAW,MAAM,EAAK,CAAE,SAAQ,CAAC,GAK3C,CAAC,EAAI,IAAM,EAAI,SAAW,IAC5B,MAAU,MAAM,yCAAyC,EAAI,YAAY,EAAI,QAAQ,EAGvF,IAAM,EAAO,EAAI,QAAQ,IAAI,MAAM,GAAK,IAAA,GAClC,EAAe,EAAI,QAAQ,IAAI,eAAe,GAAK,IAAA,GAgBzD,OAdI,EAAI,SAAW,IACV,CACL,MAAO,GACP,KAAM,GAAQ,EAAO,KACrB,aAAc,GAAgB,EAAO,YACvC,EAGG,EAME,CAAE,MAAO,GAAO,OAAM,cAAa,EAJjC,CAAE,MAAO,GAAM,OAAM,cAAa,CAK7C,CAIA,KAAMJ,IAEJ,CAEA,IAAM,EAAgB,MAAM,KAAKJ,GAC/B,iEACF,EACM,EAAU,IAAI,IAAI,CAAC,GAAG,KAAKH,GAAiB,KAAK,EAAG,GAAG,CAAa,CAAC,EAErE,EAAY,MAAM,KAAK,CAAO,EA4BpC,OAAO,MA3Be,QAAQ,IAC5B,EAAU,IAAI,KAAO,IAAS,CAC5B,IAAM,EAAO,EAAiB,KAAKV,GAAU,CAAI,EAE7C,EACJ,GAAI,CACF,EAAM,MAAM,KAAKD,GAAS,IAAI,CAAI,CACpC,OAAS,EAAK,CAMZ,OALA,KAAKI,GAAQ,KAAK,yDAA0D,CAC1E,QAAS,KAAKH,GACd,OACA,MAAOS,EAAAA,EAAQ,CAAG,CAAC,CAAC,OACtB,CAAC,EACM,IACT,CACA,GAAI,GAAQ,KACV,OAAO,KAET,IAAM,EAAO,MAAM,KAAKS,GAAkB,EAAM,EAAK,EAA0B,SAAU,CACvF,MACF,CAAC,EAID,OAHK,EAGE,CAAE,OAAM,IAAK,EAAM,MAAK,EAFtB,IAGX,CAAC,CACH,EAAA,CACe,OACZ,GAAoE,IAAM,IAC7E,CACF,CAEA,KAAMX,GACJ,EACA,EACA,EACA,EACA,EAAsB,CAAC,EACJ,CACnB,IAAI,EACJ,GAAI,CACF,EAAM,MAAM,KAAKR,GAAS,IAAI,CAAG,CACnC,OAAS,EAAK,CAMZ,OALA,KAAKI,GAAQ,KAAK,EAAW,CAC3B,QAAS,KAAKH,GACd,GAAG,EACH,MAAOS,EAAAA,EAAQ,CAAG,CAAC,CAAC,OACtB,CAAC,EACM,IACT,CAIA,OAHI,GAAQ,KACH,KAEF,KAAKS,GAAkB,EAAK,EAAK,EAAQ,EAAO,CAAO,CAChE,CAEA,KAAMA,GACJ,EACA,EACA,EACA,EACA,EAAsB,CAAC,EACJ,CACnB,IAAM,EAASpB,EAAAA,EAAE,UAAU,EAAQ,CAAG,EAQtC,OAPI,EAAO,QACF,EAAO,MAEhB,MAAM,KAAKU,GAAoB,EAAK,EAAO,CACzC,GAAG,EACH,MAAOV,EAAAA,EAAE,cAAc,EAAO,KAAK,CACrC,CAAC,EACM,KACT,CAEA,KAAMe,GAAiB,EAAsC,CAC3D,IAAM,EAAS,EAAe,KAAKb,EAAQ,EAE3C,OAAO,MADa,KAAKO,GAAiB,EAAQ,EAAmB,eAAgB,CAAS,GAC9E,CAAC,CACnB,CAEA,KAAMC,GAAoB,EAAa,EAAe,EAAsB,CAAC,EAAkB,CAC7F,MAAM,KAAKc,GAAe,CAAG,EAC7B,KAAKnB,GAAQ,KAAK,WAAW,EAAM,iCAAkC,CACnE,QAAS,KAAKH,GACd,GAAG,CACL,CAAC,CACH,CAEA,KAAMsB,GAAe,EAA4B,CAC/C,MAAM,KAAKvB,GAAS,OAAO,CAAG,CAAC,CAAC,MAAO,GAAQ,CAC7C,KAAKI,GAAQ,KAAK,+BAAgC,CAChD,QAAS,KAAKH,GACd,MACA,MAAOS,EAAAA,EAAQ,CAAG,CAAC,CAAC,OACtB,CAAC,CACH,CAAC,CACH,CAEA,KAAMW,GAAU,EAAe,EAAqD,CAClF,IAAM,EAAS,EAAe,KAAKpB,EAAQ,EAG3C,GAAI,CACF,MAAM,QAAQ,IAAI,CAChB,KAAKD,GAAS,OAAO,CAAK,EAC1B,KAAKA,GAAS,OAAO,CAAM,EAC3B,GAAG,EAAa,IAAK,GAAU,KAAKA,GAAS,OAAO,EAAM,GAAG,CAAC,CAChE,CAAC,CACH,OAAS,EAAK,CACZ,KAAKI,GAAQ,KAAK,0DAA2D,CAC3E,QAAS,KAAKH,GACd,MAAOS,EAAAA,EAAQ,CAAG,CAAC,CAAC,OACtB,CAAC,CACH,CAEA,KAAKL,GAAgB,IAAA,GACrB,KAAKM,GAAiB,MAAM,CAC9B,CAEA,KAAMS,GACJ,EACA,EACA,EACe,CACf,IAAM,EAAS,CACb,KAAKpB,GAAS,IAAI,EAAO,CAAE,CAAC,CAAC,MAAO,GAAQ,CAC1C,KAAKI,GAAQ,KAAK,mDAAoD,CACpE,QAAS,KAAKH,GACd,MAAOS,EAAAA,EAAQ,CAAG,CAAC,CAAC,OACtB,CAAC,CACH,CAAC,EACD,GAAG,EAAa,IAAK,GACnB,KAAKV,GAAS,IAAI,EAAM,IAAK,EAAM,IAAI,CAAC,CAAC,MAAO,GAAQ,CACtD,KAAKI,GAAQ,KAAK,+CAAgD,CAChE,QAAS,KAAKH,GACd,MAAOS,EAAAA,EAAQ,CAAG,CAAC,CAAC,OACtB,CAAC,CACH,CAAC,CACH,CACF,EACA,MAAM,QAAQ,IAAI,CAAM,CAC1B,CACF,ECjuBA,eAAsB,EAAa,EAAsB,EAAU,EAAyB,CAC1F,IAAI,EACJ,IAAK,IAAI,EAAU,EAAG,GAAW,EAAS,IACxC,GAAI,CACF,OAAO,MAAM,EAAG,CAClB,OAAS,EAAO,CAEd,GADA,EAAY,EACR,EAAU,GAAW,EAAiB,CAAK,EAAG,CAChD,MAAM,EAAM,IAAgB,GAAK,CAAO,EACxC,QACF,CACA,MAAM,CACR,CAEF,MAAM,CACR,CAEA,SAAS,EAAiB,EAAyB,CACjD,GAAI,EAAE,aAAiB,OACrB,MAAO,GAET,IAAM,EAAM,EAAM,QAAQ,YAAY,EACtC,OACE,EAAI,SAAS,WAAW,GACxB,EAAI,SAAS,SAAS,GACtB,EAAI,SAAS,YAAY,GACzB,EAAI,SAAS,cAAc,GAC3B,EAAI,SAAS,SAAS,GACtB,EAAI,SAAS,cAAc,GAC3B,EAAI,SAAS,gBAAgB,GAC7B,EAAI,SAAS,KAAK,GAClB,EAAI,SAAS,KAAK,GAClB,EAAI,SAAS,KAAK,CAEtB,CAEA,SAAS,EAAM,EAA2B,CACxC,OAAO,IAAI,QAAS,GAAY,WAAW,EAAS,CAAE,CAAC,CACzD,CCAA,IAAa,EAAb,cAAgC,CAA8C,CAC5E,GAA0C,KAC1C,GAA0C,KAC1C,GAEA,YAAY,EAA0B,CACpC,MAAM,EACN,KAAKc,GAAU,CACjB,CAEA,IAAc,OAAkB,CAC9B,OAAO,KAAKA,GAAQ,KACtB,CAEA,MAAgB,MAAsB,CACpC,MAAM,KAAKC,GAAQ,WAAW,CAChC,CAEA,GAAIA,IAA+B,CACjC,OAAO,KAAKD,GAAQ,MACtB,CAEA,IAAsC,CAepC,MAdA,CAME,KAAKE,MALL,AACE,KAAKC,KACH,KAAKH,GAAQ,oBACb,IAAII,EAAAA,EAAiB,mBAAoB,EAAG,WAAW,EAErC,IAAI,EAAiB,CACzC,QAAS,KAAKD,GACd,QAAS,KAAK,MAAM,GACpB,WAAY,KAAK,MAAM,WACvB,IAAK,KAAKH,GAAQ,oBAClB,OAAQ,KAAKA,GAAQ,MACvB,CAAC,GAEI,KAAKE,EACd,CAMA,WAAkB,CAChB,KAAKA,GAAiB,KACtB,KAAK,UAAU,CACjB,CAGA,CAAC,OAAO,UAAiB,CACvB,KAAK,UAAU,CACjB,CAMA,KAAMG,IAAmC,CACvC,IAAM,EAAQ,KAAKL,GAAQ,UAAU,eAAe,GAAK,GACrD,GACF,MAAM,KAAKC,GAAQ,WAAW,CAAK,CAEvC,CAKA,MAAM,0BAAsD,CAC1D,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GACrB,EAAS,MAAM,KAAKA,GAAQ,gBAAgB,CAAE,SAAQ,CAAC,EAC7D,MAAO,CACL,UAAW,EAAO,UAClB,WAAY,EAAO,UACrB,CACF,CAKA,MAAM,aACJ,EACA,EACA,EACA,EAAe,EACW,CAC1B,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAC3B,OAAO,KAAKA,GAAQ,aAAa,CAC/B,UACA,YACA,oBACA,iBACA,cACF,CAAC,CACH,CAMA,MAAM,QAAQ,EAA+C,CAC3D,GAAM,CAAE,SAAQ,kBAAiB,eAAgB,EACjD,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAE3B,OAAO,EAAU,SAAY,CAC3B,MAAM,KAAKI,GAAkB,EAC7B,IAAM,EAAS,MAAM,KAAKJ,GAAQ,QAAQ,CACxC,UACA,SACA,kBACA,aACF,CAAC,EACD,MAAO,CACL,gBAAiB,EAAO,QAAQ,IAAK,IAAA,EAAA,EAAA,MAAA,CAAiB,CAAM,CAAC,EAC7D,YAAA,EAAA,EAAA,MAAA,CAAkB,EAAO,UAAU,CACrC,CACF,CAAC,CACH,CAMA,MAAM,YACJ,EACuD,CACvD,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAC3B,OAAO,EAAU,UACf,MAAM,KAAKI,GAAkB,GAEtB,MADc,KAAKJ,GAAQ,YAAY,CAAE,UAAS,GAAG,CAAO,CAAC,EAAA,CACtD,YACf,CACH,CAMA,MAAM,cAAc,EAAiE,CACnF,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAC3B,OAAO,EAAU,SAAY,CAC3B,MAAM,KAAKI,GAAkB,EAC7B,IAAM,EAAS,MAAM,KAAKJ,GAAQ,cAAc,CAC9C,UACA,iBACF,CAAC,EACD,MAAO,CACL,YAAa,EAAO,YACpB,sBAAuB,EAAO,sBAC9B,gBAAiB,EAAO,eAC1B,CACF,CAAC,CACH,CAKA,MAAM,iCACJ,EACA,EACA,EACA,EACA,EAAe,EAC6B,CAC5C,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAC3B,OAAO,KAAKA,GAAQ,iCAAiC,CACnD,UACA,YACA,oBACA,mBACA,iBACA,cACF,CAAC,CACH,CAMA,MAAM,qBACJ,EACuD,CACvD,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAC3B,OAAO,EAAU,UACf,MAAM,KAAKI,GAAkB,GAKtB,MAJc,KAAKJ,GAAQ,qBAAqB,CACrD,UACA,GAAG,CACL,CAAC,EAAA,CACa,YACf,CACH,CAKA,MAAM,2BAA2B,EAAoD,CACnF,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAC3B,OAAO,EAAU,UACf,MAAM,KAAKI,GAAkB,EACtB,KAAKJ,GAAQ,2BAA2B,CAAE,UAAS,SAAQ,CAAC,EACpE,CACH,CAMA,MAAM,4BAA+D,CACnE,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAE3B,OADsB,KAAKK,GACR,CAAC,CAAC,2BACnB,UAAa,MAAM,KAAKL,GAAQ,aAAa,CAAE,SAAQ,CAAC,EAAA,CAAG,MAC7D,CACF,CAMA,MAAM,gBAAgB,EAAgD,CACpE,MAAM,KAAK,WAAW,EACtB,IAAM,EAAU,KAAK,MAAM,GAE3B,OADsB,KAAKK,GACR,CAAC,CAAC,gBACnB,EACA,UAAa,MAAM,KAAKL,GAAQ,gBAAgB,CAAE,UAAS,MAAK,CAAC,EAAA,CAAG,MACtE,CACF,CACF,ECpPA,MAAa,EAAqB,IAUlC,IAAsB,EAAtB,KAAyD,CACvD,GAA0B,KAC1B,GAAmB,IAAI,IACvB,GAAwC,KACxC,OACA,OAEA,YAAY,EAAiB,EAAmC,CAC9D,KAAK,OAAS,EACd,KAAK,OAAS,CAChB,CAqCA,MAAM,YAA+B,CAWnC,OAVI,KAAKM,GACA,KAAKA,IAGd,AACE,KAAKC,KAAe,KAAKC,GAAc,CAAC,CAAC,MAAO,GAAU,CAExD,KADA,MAAKD,GAAe,KACd,CACR,CAAC,EAEI,KAAKA,GACd,CAEA,KAAMC,IAAkC,CACtC,IAAM,EAAS,KAAK,aAAa,EACjC,KAAK,WAAW,CAAM,EAEtB,GAAI,CACF,GAAM,CAAE,OAAM,WAAY,KAAK,eAAe,EAC9C,MAAM,KAAK,cAAgC,EAAQ,EAAM,EAAS,GAAe,EACjF,KAAK,gBAAgB,CAAM,EAC3B,KAAKF,GAAU,CACjB,OAAS,EAAO,CAEd,MADA,KAAK,gBAAgB,CAAM,EACrB,CACR,CAEA,OAAO,KAAKA,EACd,CAEA,WAAkB,CAChB,GAAI,KAAKA,GAAS,CAChB,IAAK,GAAM,CAAC,EAAI,KAAY,KAAKG,GAC/B,aAAa,EAAQ,SAAS,EAC9B,EAAQ,OAAW,MAAM,mBAAmB,CAAC,EAC7C,KAAKA,GAAiB,OAAO,CAAE,EAGjC,KAAK,gBAAgB,KAAKH,EAAO,EACjC,KAAKA,GAAU,IACjB,CACA,KAAKC,GAAe,IACtB,CAMA,eAAyB,EAAyC,CAChE,IAAM,EAAU,KAAKE,GAAiB,IAAI,EAAS,EAAE,EAErD,GAAI,CAAC,EAAS,CACZ,KAAK,QAAQ,KAAK,uDAAwD,CACxE,GAAI,EAAS,EACf,CAAC,EACD,MACF,CAEA,IAAM,EAAU,KAAK,MAAM,YAAY,IAAI,EAAI,EAAQ,SAAS,EAKhE,GAHA,aAAa,EAAQ,SAAS,EAC9B,KAAKA,GAAiB,OAAO,EAAS,EAAE,EAEpC,EAAS,QACX,KAAK,QAAQ,MAAM,oBAAoB,EAAQ,KAAK,KAAM,CACxD,GAAI,EAAS,GACb,SACF,CAAC,EACD,EAAQ,QAAQ,EAAS,IAAI,MACxB,CACL,KAAK,QAAQ,MAAM,oBAAoB,EAAQ,KAAK,SAAU,CAC5D,GAAI,EAAS,GACb,UACA,MAAO,EAAS,KAClB,CAAC,EACD,IAAM,EAAU,MAAM,EAAS,KAAK,EAChC,eAAgB,GAAY,OAAO,EAAS,YAAe,WAC7D,EAAyC,WAAa,EAAS,YAEjE,EAAQ,OAAO,CAAG,CACpB,CACF,CAEA,kBAA4B,EAAuB,CACjD,KAAK,QAAQ,MAAM,8BAA+B,CAAE,MAAO,CAAQ,CAAC,EACpE,IAAM,EAAS,KAAKH,GACpB,KAAKA,GAAU,KACf,KAAKI,GAAkB,iBAAiB,GAAS,EAC7C,GACF,KAAK,gBAAgB,CAAM,CAE/B,CAEA,0BAA2C,CACzC,KAAK,QAAQ,MAAM,+CAA+C,EAClE,IAAM,EAAS,KAAKJ,GACpB,KAAKA,GAAU,KACf,KAAKI,GAAkB,uCAAuC,EAC1D,GACF,KAAK,gBAAgB,CAAM,CAE/B,CAMA,cACE,EACA,EACA,EACA,EAAoB,EACR,CACZ,OAAO,IAAI,SAAY,EAAS,IAAW,CACzC,IAAM,EAAK,KAAK,kBAAkB,EAC5B,EAAY,YAAY,IAAI,EAClC,KAAK,QAAQ,MAAM,oBAAoB,IAAQ,CAAE,IAAG,CAAC,EAErD,IAAM,EAAY,eAAiB,CACjC,KAAKD,GAAiB,OAAO,CAAE,EAC/B,IAAM,EAAU,KAAK,MAAM,YAAY,IAAI,EAAI,CAAS,EACxD,KAAK,QAAQ,MAAM,kBAAkB,EAAK,mBAAmB,EAAU,IAAK,CAC1E,KACA,SACF,CAAC,EACD,EAAW,MAAM,WAAW,EAAK,mBAAmB,EAAU,GAAG,CAAC,CACpE,EAAG,CAAS,EAEZ,KAAKA,GAAiB,IAAI,EAAI,CACnB,UACT,SACA,YACA,YACA,MACF,CAAC,EAED,IAAM,EAAU,CAAE,KAAI,OAAM,SAAQ,EACpC,KAAK,YAAY,EAAQ,CAAO,CAClC,CAAC,CACH,CAEA,MAAgB,YACd,EACA,EACA,EAAoB,EACR,CACZ,IAAM,EAAS,MAAM,KAAK,WAAW,EACrC,OAAO,KAAK,cAAiB,EAAQ,EAAM,EAAS,CAAS,CAC/D,CAMA,MAAM,gBACJ,EACsC,CACtC,OAAO,KAAK,YAAyC,mBAAoB,CAAM,CACjF,CAEA,MAAM,aAAa,EAAgE,CACjF,OAAO,KAAK,YAAsC,gBAAiB,CAAM,CAC3E,CAEA,MAAM,QAAQ,EAAsD,CAClE,OAAO,KAAK,YAAiC,UAAW,CAAM,CAChE,CAEA,MAAM,YAAY,EAA8D,CAC9E,OAAO,KAAK,YAAqC,eAAgB,CAAM,CACzE,CAEA,MAAM,cAAc,EAAkE,CACpF,OAAO,KAAK,YAAuC,iBAAkB,CAAM,CAC7E,CAEA,MAAM,iCACJ,EAC4C,CAC5C,OAAO,KAAK,YAA+C,0BAA2B,CAAM,CAC9F,CAEA,MAAM,qBACJ,EAC2C,CAC3C,OAAO,KAAK,YAA8C,yBAA0B,CAAM,CAC5F,CAEA,MAAM,2BACJ,EACiD,CACjD,OAAO,KAAK,YACV,gCACA,CACF,CACF,CAEA,MAAM,aAAa,EAA2E,CAC5F,OAAO,KAAK,YAAsC,iBAAkB,CAAM,CAC5E,CAEA,MAAM,gBACJ,EACsC,CACtC,OAAO,KAAK,YAAyC,oBAAqB,CAAM,CAClF,CAMA,GAAkB,EAAuB,CACvC,IAAK,GAAM,CAAC,EAAI,KAAY,KAAKA,GAC/B,aAAa,EAAQ,SAAS,EAC9B,EAAQ,OAAW,MAAM,CAAO,CAAC,EACjC,KAAKA,GAAiB,OAAO,CAAE,CAEnC,CACF,EC9SA,SAAS,EAAe,EAAsD,CAC5E,GAAI,CAIF,OAHA,EAAA,EAAa,EAAS,SAAS,EAC/B,EAAA,EAAiB,EAAS,KAAM,YAAY,EAC5C,EAAA,EAAuD,EAAS,SAAU,gBAAgB,EACnF,EACT,MAAQ,CACN,MAAO,EACT,CACF,CAQA,SAAgB,GAAkE,CAChF,IAAM,EAAI,WACV,IAAK,IAAM,IAAM,CAAC,EAAE,OAAQ,EAAE,OAAO,EACnC,GAAI,CAEF,GADA,EAAA,EAAa,EAAI,IAAI,EACjB,EAAe,EAAG,OAAO,EAC3B,OAAO,EAAG,OAEd,MAAQ,CACN,QACF,CAGJ,CCbA,IAAa,EAAb,cAAyC,CAA6C,CACpF,IAAoC,MAEpC,YAAY,EAA4B,CACtC,MAAM,EAAQ,EAAO,MAAM,CAC7B,CAEA,cAAiC,CAC/B,IAAM,EAAU,EAA2B,EAC3C,GAAI,EACF,OAAO,IAAI,OAAO,EAAQ,OAAOE,uBAAc,CAAC,EAElD,IAAM,EAAU,IAAI,gBAAgB,IAAI,KAAK,CAACC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAAU,EAAG,CAAE,KAAM,wBAAyB,CAAC,CAAC,EAC9F,GAAI,CACF,OAAO,IAAI,OAAO,CAAO,CAC3B,QAAU,CACR,IAAI,gBAAgB,CAAO,CAC7B,CACF,CAEA,WAAqB,EAAsB,CACzC,EAAO,UAAa,GAClB,KAAK,eAAe,EAAM,IAAI,EAChC,EAAO,QAAW,GAAsB,KAAK,kBAAkB,EAAM,OAAO,EAC5E,EAAO,mBAAuB,KAAK,yBAAyB,CAC9D,CAEA,YAAsB,EAAgB,EAA8B,CAClE,EAAO,YAAY,CAAO,CAC5B,CAEA,gBAA0B,EAAsB,CAC9C,EAAO,UAAU,CACnB,CAEA,mBAAsC,CACpC,OAAO,OAAO,WAAW,CAC3B,CAEA,gBAGE,CAIA,GAAM,CAAE,SAAQ,SAAQ,YAAW,YAAW,UAAW,KAAK,OAC9D,MAAO,CACL,KAAM,OACN,QAAS,CAAE,IAAK,MAAgB,SAAQ,SAAQ,YAAW,YAAW,QAAO,CAC/E,CACF,CAMA,MAAM,WAAW,EAAkC,CACjD,MAAM,KAAK,YAAoC,cAAe,CAC5D,WACF,CAAC,CACH,CACF,ECtFA,MAAM,EAA0BC,EAAAA,EAAE,OAAO,CACvC,QAASA,EAAAA,EAAE,SAASA,EAAAA,EAAE,IAAI,CAAC,CAAC,MAAMA,EAAAA,EAAE,SAAS,CAAC,CAAC,EAC/C,oBAAqBA,EAAAA,EAAE,SAASA,EAAAA,EAAE,IAAI,CAAC,CAAC,MAAMA,EAAAA,EAAE,YAAY,CAAC,CAAC,CAChE,CAAC,EAeD,SAAgB,EAAI,EAA+C,CAIjE,OAHI,IAAY,IAAA,IACd,EAAA,EAAmB,EAAyB,CAAO,EAE9C,CACL,KAAM,MACN,aAAe,GACb,IAAI,EAAoB,CACtB,OAAQ,mEACR,SACA,UAAW,GAAS,UAAU,eAAe,GAAK,GAClD,UAAW,GAAS,UAAU,iBAAmB,GAAQ,IAAA,GAAY,mGACrE,OAAQ,GAAS,OACjB,OAAQ,GAAS,OACnB,CAAC,EACH,eAAgB,EAAO,IAAW,IAAI,EAAW,CAAE,QAAO,SAAQ,GAAG,CAAQ,CAAC,CAChF,CACF"}
1
+ {"version":3,"file":"index.cjs","names":["#initPromise","z","#storage","#chainId","#relayerUrl","#ttlMs","#logger","#publicKeyMem","#publicKeyInflight","#loadFheEncryptionKey","#readCachedEntry","#deleteCorruptEntry","toError","#publicParamsMem","#publicParamsInflight","#loadPublicParams","#readParamsIndex","#revalidationInflight","#revalidateIfDueInner","#lastRevalidatedAt","#collectParamEntries","#parseCachedEntry","#writeEntries","#clearAll","#checkArtifactFreshness","#deleteQuietly","#config","#worker","#artifactCache","#artifactStorage","IndexedDBStorage","#refreshCsrfToken","#getArtifactCache","#worker","#initPromise","#doInitWorker","#pendingRequests","#rejectAllPending","workerFilename","workerCode","z"],"sources":["../../../src/relayer/base-relayer.ts","../../../src/relayer/fhe-artifact-cache.ts","../../../src/relayer/relayer-utils.ts","../../../src/relayer/relayer-web.ts","../../../src/worker/worker.base-client.ts","../../../src/worker/browser-extension.ts","../../../src/worker/worker.client.ts","../../../src/config/web.ts"],"sourcesContent":["import type { Address } from \"viem\";\nimport type { FheChain } from \"../chains/types\";\n\nexport abstract class BaseRelayer {\n #initPromise: Promise<void> | null = null;\n protected abstract readonly chain: FheChain;\n protected abstract init(): Promise<void>;\n\n protected async ensureInit(): Promise<void> {\n if (!this.#initPromise) {\n this.#initPromise = this.init().catch((error) => {\n this.#initPromise = null;\n throw error;\n });\n }\n return this.#initPromise;\n }\n\n protected resetInit(): void {\n this.#initPromise = null;\n }\n\n async getAclAddress(): Promise<Address> {\n return this.chain.aclContractAddress;\n }\n}\n","import { z } from \"zod/mini\";\nimport type { GenericStorage } from \"../types\";\nimport { assertNonNullable, toError } from \"../utils\";\nimport type { GenericLogger } from \"../worker/worker.types\";\nimport type { FheEncryptionKey, PublicParamsData } from \"./relayer-sdk.types\";\n\n// ── Cached data shapes ──────────────────────────────────────\n\nconst CachedArtifactBase = z.object({\n artifactUrl: z.optional(z.string()),\n etag: z.optional(z.string()),\n lastModified: z.optional(z.string()),\n // Optional + default(0) preserves the prior `?? 0` fallback for entries\n // persisted before this field was added; 0 marks them stale via the TTL check.\n // oxlint-disable-next-line no-underscore-dangle -- z._default is the Zod v4 mini API\n lastValidatedAt: z._default(z.optional(z.number().check(z.nonnegative())), 0),\n});\n\n/** Cached shape for the FHE network public key. */\nconst CachedPublicKeySchema = z.extend(CachedArtifactBase, {\n publicKeyId: z.string(),\n publicKey: z.string(),\n});\ntype CachedPublicKey = z.infer<typeof CachedPublicKeySchema>;\n\n/** Cached shape for FHE public params. */\nconst CachedPublicParamsSchema = z.extend(CachedArtifactBase, {\n publicParamsId: z.string(),\n publicParams: z.string(),\n});\ntype CachedPublicParams = z.infer<typeof CachedPublicParamsSchema>;\n\nconst ParamsIndexSchema = z.array(z.int().check(z.nonnegative()));\n\n/**\n * Manifest shape returned by the relayer `/keyurl` endpoint. Only the fields\n * actually consumed (status + first URL of each artifact) are validated; the\n * upstream payload contains additional metadata we ignore.\n */\nconst ManifestSchema = z.object({\n status: z.literal(\"succeeded\"),\n response: z.object({\n fheKeyInfo: z\n .array(\n z.object({\n fhePublicKey: z.object({\n urls: z.array(z.string()).check(z.minLength(1)),\n }),\n }),\n )\n .check(z.minLength(1)),\n crs: z.record(\n z.string(),\n z.object({\n urls: z.array(z.string()).check(z.minLength(1)),\n }),\n ),\n }),\n});\n\n// ── Return types ────────────────────────────────────────────\n\n/** Return type of the FHE encryption key fetcher. */\ntype FheEncryptionKeyResult = FheEncryptionKey | null;\n\n/** Return type of the public params fetcher. */\ntype PublicParamsResult = PublicParamsData | null;\n\n// ── Constants ───────────────────────────────────────────────\n\n/** Max chunk size for String.fromCharCode to avoid call-stack overflow on large buffers. */\nconst CHUNK_SIZE = 8192;\n\n/** On revalidation failure, retry after 5 minutes instead of the full TTL. */\nconst SHORT_RETRY_MS = 5 * 60 * 1000;\n\n// ── Helpers ─────────────────────────────────────────────────\n\nfunction toBase64(bytes: Uint8Array): string {\n const chunks: string[] = [];\n for (let i = 0; i < bytes.length; i += CHUNK_SIZE) {\n chunks.push(String.fromCharCode(...bytes.subarray(i, i + CHUNK_SIZE)));\n }\n return btoa(chunks.join(\"\"));\n}\n\nfunction fromBase64(b64: string): Uint8Array {\n let binary: string;\n try {\n binary = atob(b64);\n } catch {\n throw new Error(`Invalid base64 data (length: ${b64.length})`);\n }\n if (binary.length === 0) {\n throw new Error(\"Decoded artifact is empty\");\n }\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;\n}\n\nfunction pubkeyStorageKey(chainId: number): string {\n return `fhe:pubkey:${chainId}`;\n}\n\nfunction paramsStorageKey(chainId: number, bits: number): string {\n return `fhe:params:${chainId}:${bits}`;\n}\n\nfunction paramsIndexKey(chainId: number): string {\n return `fhe:params-index:${chainId}`;\n}\n\ntype LogContext = Record<string, unknown>;\n\n// ── ArtifactCache ──────────────────────────────────────────\n\n/**\n * Persistent cache for FHE network public key and public params.\n * Uses a {@link GenericStorage} backend (e.g. MemoryStorage, or any\n * user-provided async key-value adapter) to avoid re-downloading large\n * binary data on every app instantiation.\n *\n * Cache keys are scoped by chain ID.\n */\nexport class FheArtifactCache {\n readonly #storage: GenericStorage;\n readonly #chainId: number;\n readonly #relayerUrl: string;\n readonly #ttlMs: number;\n readonly #logger: GenericLogger;\n #publicKeyMem: FheEncryptionKeyResult | undefined;\n #publicParamsMem = new Map<number, PublicParamsResult>();\n #publicKeyInflight: Promise<FheEncryptionKeyResult> | null = null;\n #publicParamsInflight = new Map<number, Promise<PublicParamsResult>>();\n #revalidationInflight: Promise<boolean> | null = null;\n /** In-memory guard to skip storage reads when revalidation isn't due. */\n #lastRevalidatedAt: number | null = null;\n\n constructor(opts: {\n storage: GenericStorage;\n chainId: number;\n relayerUrl: string;\n /** Cache TTL in seconds. Default: 86 400 (24 h). Set to 0 to revalidate on every operation. */\n ttl?: number;\n logger?: GenericLogger;\n }) {\n this.#storage = opts.storage;\n this.#chainId = opts.chainId;\n this.#relayerUrl = opts.relayerUrl;\n this.#ttlMs = (opts.ttl ?? 86_400) * 1000;\n this.#logger = opts.logger ?? console;\n }\n\n // ── fetchFheEncryptionKeyBytes ──────────────────────────\n\n async fetchFheEncryptionKeyBytes(\n fetcher: () => Promise<FheEncryptionKeyResult>,\n ): Promise<FheEncryptionKeyResult> {\n if (this.#publicKeyMem !== undefined) {\n return this.#publicKeyMem;\n }\n\n // Deduplicate concurrent calls\n if (this.#publicKeyInflight) {\n return this.#publicKeyInflight;\n }\n\n this.#publicKeyInflight = this.#loadFheEncryptionKey(fetcher);\n try {\n return await this.#publicKeyInflight;\n } finally {\n this.#publicKeyInflight = null;\n }\n }\n\n async #loadFheEncryptionKey(\n fetcher: () => Promise<FheEncryptionKeyResult>,\n ): Promise<FheEncryptionKeyResult> {\n const key = pubkeyStorageKey(this.#chainId);\n\n const stored = await this.#readCachedEntry(\n key,\n CachedPublicKeySchema,\n \"public key\",\n \"Failed to read public key from persistent storage, falling back to network fetch\",\n );\n if (stored) {\n try {\n const result: FheEncryptionKeyResult = {\n publicKeyId: stored.publicKeyId,\n publicKey: fromBase64(stored.publicKey),\n };\n this.#publicKeyMem = result;\n return result;\n } catch (err) {\n await this.#deleteCorruptEntry(key, \"public key\", { error: toError(err).message });\n }\n }\n\n const result = await fetcher();\n if (result === null) {\n return null;\n }\n\n this.#publicKeyMem = result;\n\n try {\n const entry: CachedPublicKey = {\n publicKeyId: result.publicKeyId,\n publicKey: toBase64(result.publicKey),\n lastValidatedAt: Date.now(),\n };\n await this.#storage.set(key, entry);\n } catch (err) {\n this.#logger.warn(\"Failed to persist public key to storage\", {\n chainId: this.#chainId,\n error: toError(err).message,\n });\n }\n\n return result;\n }\n\n // ── getPublicParams ─────────────────────────────────────\n\n async getPublicParams(\n bits: number,\n fetcher: () => Promise<PublicParamsResult>,\n ): Promise<PublicParamsResult> {\n const mem = this.#publicParamsMem.get(bits);\n if (mem !== undefined) {\n return mem;\n }\n\n // Deduplicate concurrent calls\n const inflight = this.#publicParamsInflight.get(bits);\n if (inflight) {\n return inflight;\n }\n\n const promise = this.#loadPublicParams(bits, fetcher);\n this.#publicParamsInflight.set(bits, promise);\n try {\n return await promise;\n } finally {\n this.#publicParamsInflight.delete(bits);\n }\n }\n\n async #loadPublicParams(\n bits: number,\n fetcher: () => Promise<PublicParamsResult>,\n ): Promise<PublicParamsResult> {\n const key = paramsStorageKey(this.#chainId, bits);\n\n const stored = await this.#readCachedEntry(\n key,\n CachedPublicParamsSchema,\n \"params\",\n \"Failed to read public params from persistent storage, falling back to network fetch\",\n { bits },\n );\n if (stored) {\n try {\n const result: PublicParamsResult = {\n publicParamsId: stored.publicParamsId,\n publicParams: fromBase64(stored.publicParams),\n };\n this.#publicParamsMem.set(bits, result);\n return result;\n } catch (err) {\n await this.#deleteCorruptEntry(key, \"params\", { bits, error: toError(err).message });\n }\n }\n\n const result = await fetcher();\n if (result === null) {\n return null;\n }\n\n this.#publicParamsMem.set(bits, result);\n\n try {\n const entry: CachedPublicParams = {\n publicParamsId: result.publicParamsId,\n publicParams: toBase64(result.publicParams),\n lastValidatedAt: Date.now(),\n };\n await this.#storage.set(key, entry);\n\n // Update params index for cold-start CRS detection\n const idxKey = paramsIndexKey(this.#chainId);\n const existing = await this.#readParamsIndex(\"Failed to read params index from storage\");\n if (!existing.includes(bits)) {\n await this.#storage.set(idxKey, [...existing, bits]);\n }\n } catch (err) {\n this.#logger.warn(\"Failed to persist public params to storage\", {\n chainId: this.#chainId,\n bits,\n error: toError(err).message,\n });\n }\n\n return result;\n }\n\n // ── Artifact-level revalidation ─────────────────────────\n\n /**\n * Check whether cached FHE artifacts are still fresh by issuing\n * HTTP conditional requests (ETag / If-None-Match, Last-Modified /\n * If-Modified-Since) against the actual artifact CDN URLs.\n *\n * @returns `true` if the cache was invalidated and the caller should\n * re-fetch artifacts, `false` otherwise.\n */\n async revalidateIfDue(): Promise<boolean> {\n // Concurrency guard — coalesce overlapping calls\n if (this.#revalidationInflight) {\n return this.#revalidationInflight;\n }\n this.#revalidationInflight = this.#revalidateIfDueInner();\n try {\n return await this.#revalidationInflight;\n } finally {\n this.#revalidationInflight = null;\n }\n }\n\n async #revalidateIfDueInner(): Promise<boolean> {\n // Fast path: in-memory timestamp check avoids storage I/O on every call\n const now = Date.now();\n if (this.#lastRevalidatedAt !== null && now - this.#lastRevalidatedAt < this.#ttlMs) {\n return false;\n }\n\n // Skip revalidation when relayerUrl is not configured (e.g. Hardhat)\n if (!this.#relayerUrl) {\n return false;\n }\n\n const pkKey = pubkeyStorageKey(this.#chainId);\n\n // Track partial progress so the catch block can reuse already-read data\n let storedPk: CachedPublicKey | null = null;\n let paramEntries: Array<{\n bits: number;\n key: string;\n data: CachedPublicParams;\n }> = [];\n\n try {\n // 1. Read PK cache entry and collect params entries in parallel\n const [pkRaw, entries] = await Promise.all([\n this.#storage.get(pkKey),\n this.#collectParamEntries(),\n ]);\n\n // Validate PK shape\n if (pkRaw !== null && pkRaw !== undefined) {\n storedPk = await this.#parseCachedEntry(pkKey, pkRaw, CachedPublicKeySchema, \"public key\");\n }\n\n paramEntries = entries;\n\n if (!storedPk) {\n return false;\n }\n\n // 2. Check if all entries are within TTL\n const allEntries: Array<{ lastValidatedAt: number }> = [\n storedPk,\n ...paramEntries.map((e) => e.data),\n ];\n const allFresh = allEntries.every((e) => now - e.lastValidatedAt < this.#ttlMs);\n if (allFresh) {\n this.#lastRevalidatedAt = now;\n return false;\n }\n\n // 3. Fetch manifest to discover current artifact URLs\n const manifestRes = await globalThis.fetch(`${this.#relayerUrl}/keyurl`);\n if (!manifestRes.ok) {\n // Treat as transient failure — use short retry instead of full TTL\n const retryTimestamp = now - this.#ttlMs + SHORT_RETRY_MS;\n this.#logger.warn(\"Manifest fetch failed during revalidation, retrying in 5 min\", {\n status: manifestRes.status,\n relayerUrl: this.#relayerUrl,\n });\n await this.#writeEntries(\n pkKey,\n { ...storedPk, lastValidatedAt: retryTimestamp },\n paramEntries.map((e) => ({\n ...e,\n data: { ...e.data, lastValidatedAt: retryTimestamp },\n })),\n );\n this.#lastRevalidatedAt = retryTimestamp;\n return false;\n }\n\n // Validate manifest shape — a malformed response indicates a permanent\n // config error (wrong relayer URL, API version mismatch), not a transient\n // network issue. Log at error level so it's actionable.\n const manifestParsed = ManifestSchema.safeParse(await manifestRes.json());\n if (!manifestParsed.success) {\n this.#logger.error(\n \"Relayer manifest has unexpected shape — check relayer URL and API version\",\n {\n relayerUrl: this.#relayerUrl,\n error: z.prettifyError(manifestParsed.error),\n },\n );\n // Fail-open with short retry — but the error-level log distinguishes this from transient failures\n const retryTimestamp = now - this.#ttlMs + SHORT_RETRY_MS;\n await this.#writeEntries(\n pkKey,\n { ...storedPk, lastValidatedAt: retryTimestamp },\n paramEntries.map((e) => ({\n ...e,\n data: { ...e.data, lastValidatedAt: retryTimestamp },\n })),\n );\n this.#lastRevalidatedAt = retryTimestamp;\n return false;\n }\n const validManifest = manifestParsed.data.response;\n const fheKeyEntry = validManifest.fheKeyInfo[0];\n assertNonNullable(fheKeyEntry, \"manifest.response.fheKeyInfo[0]\");\n\n // ── 4. Check PK artifact ──────────────────────────\n const pkArtifactUrl = fheKeyEntry.fhePublicKey.urls[0];\n // URL change → stale\n if (storedPk.artifactUrl && pkArtifactUrl && pkArtifactUrl !== storedPk.artifactUrl) {\n await this.#clearAll(pkKey, paramEntries);\n this.#lastRevalidatedAt = null;\n return true;\n }\n\n let updatedPk: CachedPublicKey = { ...storedPk, lastValidatedAt: now };\n if (pkArtifactUrl) {\n const freshness = await this.#checkArtifactFreshness(pkArtifactUrl, storedPk);\n if (!freshness.fresh) {\n await this.#clearAll(pkKey, paramEntries);\n this.#lastRevalidatedAt = null;\n return true;\n }\n updatedPk = {\n ...updatedPk,\n artifactUrl: pkArtifactUrl,\n etag: freshness.etag,\n lastModified: freshness.lastModified,\n };\n }\n\n // ── 5. Check each CRS artifact ────────────────────\n const updatedParamEntries: typeof paramEntries = [];\n for (const entry of paramEntries) {\n const manifestCrs = validManifest.crs[String(entry.bits)];\n const crsUrl = manifestCrs?.urls[0];\n\n // URL change → stale\n if (entry.data.artifactUrl && crsUrl && crsUrl !== entry.data.artifactUrl) {\n await this.#clearAll(pkKey, paramEntries);\n this.#lastRevalidatedAt = null;\n return true;\n }\n\n let updatedData: CachedPublicParams = {\n ...entry.data,\n lastValidatedAt: now,\n };\n if (crsUrl) {\n const freshness = await this.#checkArtifactFreshness(crsUrl, entry.data);\n if (!freshness.fresh) {\n await this.#clearAll(pkKey, paramEntries);\n this.#lastRevalidatedAt = null;\n return true;\n }\n updatedData = {\n ...updatedData,\n artifactUrl: crsUrl,\n etag: freshness.etag,\n lastModified: freshness.lastModified,\n };\n }\n updatedParamEntries.push({ ...entry, data: updatedData });\n }\n\n // 6. All fresh — update timestamps and HTTP validators\n await this.#writeEntries(pkKey, updatedPk, updatedParamEntries);\n this.#lastRevalidatedAt = now;\n return false;\n } catch (err) {\n const error = toError(err);\n const isProgrammingError =\n err instanceof TypeError ||\n err instanceof ReferenceError ||\n err instanceof RangeError ||\n err instanceof SyntaxError;\n const level = isProgrammingError ? \"error\" : \"warn\";\n this.#logger[level](\n isProgrammingError\n ? \"Unexpected error during revalidation (possible bug)\"\n : \"Revalidation failed, using cached artifacts (fail-open)\",\n {\n chainId: this.#chainId,\n relayerUrl: this.#relayerUrl,\n error: error.message,\n },\n );\n\n // Fail-open: use short retry interval (5 min) instead of full TTL\n const retryTimestamp = now - this.#ttlMs + SHORT_RETRY_MS;\n try {\n if (storedPk) {\n await this.#writeEntries(\n pkKey,\n { ...storedPk, lastValidatedAt: retryTimestamp },\n paramEntries.map((e) => ({\n ...e,\n data: { ...e.data, lastValidatedAt: retryTimestamp },\n })),\n );\n }\n } catch (innerErr) {\n this.#logger.warn(\"Failed to update validation timestamps after revalidation error\", {\n chainId: this.#chainId,\n error: toError(innerErr).message,\n });\n }\n this.#lastRevalidatedAt = retryTimestamp;\n return false;\n }\n }\n\n // ── Artifact freshness via HTTP conditional requests ───\n\n async #checkArtifactFreshness(\n url: string,\n cached: { etag?: string; lastModified?: string },\n ): Promise<{ fresh: boolean; etag?: string; lastModified?: string }> {\n const hasValidators = Boolean(cached.etag || cached.lastModified);\n const headers: Record<string, string> = {};\n if (cached.etag) {\n headers[\"If-None-Match\"] = cached.etag;\n }\n if (cached.lastModified) {\n headers[\"If-Modified-Since\"] = cached.lastModified;\n }\n\n // HEAD avoids downloading the (potentially multi-MB) artifact body.\n // With conditional headers, the server returns 304 if unchanged or 200 (no body) if stale.\n let res = await globalThis.fetch(url, { method: \"HEAD\", headers });\n\n // Fallback to GET if HEAD is not supported (e.g. some CDN/WAF configs)\n if (res.status === 405) {\n res = await globalThis.fetch(url, { headers });\n }\n\n // Treat server errors as transient — throw so the outer catch applies fail-open with short retry.\n // Without this, a CDN 5xx would be misinterpreted as \"artifact changed\" and wipe the cache.\n if (!res.ok && res.status !== 304) {\n throw new Error(`Artifact freshness check failed: HEAD ${url} returned ${res.status}`);\n }\n\n const etag = res.headers.get(\"etag\") ?? undefined;\n const lastModified = res.headers.get(\"last-modified\") ?? undefined;\n\n if (res.status === 304) {\n return {\n fresh: true,\n etag: etag ?? cached.etag,\n lastModified: lastModified ?? cached.lastModified,\n };\n }\n\n if (!hasValidators) {\n // First revalidation — capture validators, treat as fresh\n return { fresh: true, etag, lastModified };\n }\n\n // 200 = artifact changed\n return { fresh: false, etag, lastModified };\n }\n\n // ── Internal helpers ────────────────────────────────────\n\n async #collectParamEntries(): Promise<\n Array<{ bits: number; key: string; data: CachedPublicParams }>\n > {\n // Merge in-memory keys with persisted index for cold-start CRS detection\n const persistedBits = await this.#readParamsIndex(\n \"Failed to read params index, CRS revalidation may be incomplete\",\n );\n const allBits = new Set([...this.#publicParamsMem.keys(), ...persistedBits]);\n\n const bitsArray = Array.from(allBits);\n const results = await Promise.all(\n bitsArray.map(async (bits) => {\n const pKey = paramsStorageKey(this.#chainId, bits);\n // Separate storage read from validation so we only delete on corruption\n let raw: unknown;\n try {\n raw = await this.#storage.get(pKey);\n } catch (err) {\n this.#logger.warn(\"Failed to read cached params entry during revalidation\", {\n chainId: this.#chainId,\n bits,\n error: toError(err).message,\n });\n return null;\n }\n if (raw === null || raw === undefined) {\n return null;\n }\n const data = await this.#parseCachedEntry(pKey, raw, CachedPublicParamsSchema, \"params\", {\n bits,\n });\n if (!data) {\n return null;\n }\n return { bits, key: pKey, data };\n }),\n );\n return results.filter(\n (e): e is { bits: number; key: string; data: CachedPublicParams } => e !== null,\n );\n }\n\n async #readCachedEntry<T>(\n key: string,\n schema: z.core.$ZodType<T>,\n label: string,\n readError: string,\n context: LogContext = {},\n ): Promise<T | null> {\n let raw: unknown;\n try {\n raw = await this.#storage.get(key);\n } catch (err) {\n this.#logger.warn(readError, {\n chainId: this.#chainId,\n ...context,\n error: toError(err).message,\n });\n return null;\n }\n if (raw === null || raw === undefined) {\n return null;\n }\n return this.#parseCachedEntry(key, raw, schema, label, context);\n }\n\n async #parseCachedEntry<T>(\n key: string,\n raw: unknown,\n schema: z.core.$ZodType<T>,\n label: string,\n context: LogContext = {},\n ): Promise<T | null> {\n const parsed = z.safeParse(schema, raw);\n if (parsed.success) {\n return parsed.data;\n }\n await this.#deleteCorruptEntry(key, label, {\n ...context,\n error: z.prettifyError(parsed.error),\n });\n return null;\n }\n\n async #readParamsIndex(readError: string): Promise<number[]> {\n const idxKey = paramsIndexKey(this.#chainId);\n const index = await this.#readCachedEntry(idxKey, ParamsIndexSchema, \"params index\", readError);\n return index ?? [];\n }\n\n async #deleteCorruptEntry(key: string, label: string, context: LogContext = {}): Promise<void> {\n await this.#deleteQuietly(key);\n this.#logger.warn(`Corrupt ${label} cache entry detected, deleting`, {\n chainId: this.#chainId,\n ...context,\n });\n }\n\n async #deleteQuietly(key: string): Promise<void> {\n await this.#storage.delete(key).catch((err) => {\n this.#logger.warn(\"Failed to delete cache entry\", {\n chainId: this.#chainId,\n key,\n error: toError(err).message,\n });\n });\n }\n\n async #clearAll(pkKey: string, paramEntries: Array<{ key: string }>): Promise<void> {\n const idxKey = paramsIndexKey(this.#chainId);\n // Delete from persistent storage first — if this fails, in-memory cache\n // still serves stale data, but the next revalidation cycle will retry.\n try {\n await Promise.all([\n this.#storage.delete(pkKey),\n this.#storage.delete(idxKey),\n ...paramEntries.map((entry) => this.#storage.delete(entry.key)),\n ]);\n } catch (err) {\n this.#logger.warn(\"Failed to clear stale artifacts from persistent storage\", {\n chainId: this.#chainId,\n error: toError(err).message,\n });\n }\n // Clear in-memory after storage to avoid re-loading stale entries on failure\n this.#publicKeyMem = undefined;\n this.#publicParamsMem.clear();\n }\n\n async #writeEntries(\n pkKey: string,\n pk: CachedPublicKey,\n paramEntries: Array<{ key: string; data: CachedPublicParams }>,\n ): Promise<void> {\n const writes = [\n this.#storage.set(pkKey, pk).catch((err) => {\n this.#logger.warn(\"Failed to update public key validation timestamp\", {\n chainId: this.#chainId,\n error: toError(err).message,\n });\n }),\n ...paramEntries.map((entry) =>\n this.#storage.set(entry.key, entry.data).catch((err) => {\n this.#logger.warn(\"Failed to update params validation timestamp\", {\n chainId: this.#chainId,\n error: toError(err).message,\n });\n }),\n ),\n ];\n await Promise.all(writes);\n }\n}\n","const MAX_RETRIES = 2;\nconst RETRY_BASE_MS = 500;\n\n/**\n * Retry an async operation with exponential backoff.\n * Only retries on transient errors (timeout, network). Does not retry user-facing errors.\n */\nexport async function withRetry<T>(fn: () => Promise<T>, retries = MAX_RETRIES): Promise<T> {\n let lastError: unknown;\n for (let attempt = 0; attempt <= retries; attempt++) {\n try {\n return await fn();\n } catch (error) {\n lastError = error;\n if (attempt < retries && isTransientError(error)) {\n await sleep(RETRY_BASE_MS * 2 ** attempt);\n continue;\n }\n throw error;\n }\n }\n throw lastError;\n}\n\nfunction isTransientError(error: unknown): boolean {\n if (!(error instanceof Error)) {\n return false;\n }\n const msg = error.message.toLowerCase();\n return (\n msg.includes(\"timed out\") ||\n msg.includes(\"timeout\") ||\n msg.includes(\"econnreset\") ||\n msg.includes(\"econnrefused\") ||\n msg.includes(\"network\") ||\n msg.includes(\"fetch failed\") ||\n msg.includes(\"socket hang up\") ||\n msg.includes(\"502\") ||\n msg.includes(\"503\") ||\n msg.includes(\"504\")\n );\n}\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n","import type {\n InputProofBytesType,\n KmsDelegatedUserDecryptEIP712Type,\n ZKProofLike,\n} from \"@zama-fhe/relayer-sdk/bundle\";\nimport { toHex } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport { IndexedDBStorage } from \"../storage/indexeddb-storage\";\nimport type { GenericStorage } from \"../types\";\nimport type { RelayerWorkerClient } from \"../worker/worker.client\";\nimport type { FheChain } from \"../chains/types\";\nimport type { TransportKeyPair } from \"../credentials/types\";\nimport { BaseRelayer } from \"./base-relayer\";\nimport { FheArtifactCache } from \"./fhe-artifact-cache\";\nimport type { RelayerSDK } from \"./relayer-sdk\";\nimport type {\n ClearValue,\n DelegatedUserDecryptParams,\n EIP712TypedData,\n EncryptParams,\n EncryptResult,\n EncryptedValue,\n FheEncryptionKey,\n PublicDecryptResult,\n PublicParamsData,\n RelayerWebConfig,\n UserDecryptParams,\n} from \"./relayer-sdk.types\";\nimport { withRetry } from \"./relayer-utils\";\n\n/**\n * Pinned relayer SDK version used for the WASM CDN bundle.\n * Update this when upgrading @zama-fhe/relayer-sdk, and keep the\n * peerDependencies range in package.json in sync (~x.y.z).\n */\nexport const RELAYER_SDK_VERSION = \"0.4.4\";\nexport const CDN_URL = `https://cdn.zama.org/relayer-sdk-js/${RELAYER_SDK_VERSION}/relayer-sdk-js.umd.cjs`;\n/** SHA-384 hex digest of the pinned CDN bundle for integrity verification. */\nexport const CDN_INTEGRITY =\n \"a50426aae8440e802102c8674dd8451f34fe79352d5e2cc6b89d9f1aa340296176c2ee33d9aa4657752f8ca96f74f921\";\n\n/**\n * RelayerWeb — single-chain browser encryption/decryption layer.\n * The worker is injected at construction time; the relayer does not own its lifecycle.\n */\nexport class RelayerWeb extends BaseRelayer implements RelayerSDK, Disposable {\n #artifactCache: FheArtifactCache | null = null;\n #artifactStorage: GenericStorage | null = null;\n readonly #config: RelayerWebConfig;\n\n constructor(config: RelayerWebConfig) {\n super();\n this.#config = config;\n }\n\n protected get chain(): FheChain {\n return this.#config.chain;\n }\n\n protected async init(): Promise<void> {\n await this.#worker.initWorker();\n }\n\n get #worker(): RelayerWorkerClient {\n return this.#config.worker;\n }\n\n #getArtifactCache(): FheArtifactCache {\n if (!this.#artifactCache) {\n if (!this.#artifactStorage) {\n this.#artifactStorage =\n this.#config.fheArtifactStorage ??\n new IndexedDBStorage(\"FheArtifactCache\", 1, \"artifacts\");\n }\n this.#artifactCache = new FheArtifactCache({\n storage: this.#artifactStorage,\n chainId: this.chain.id,\n relayerUrl: this.chain.relayerUrl,\n ttl: this.#config.fheArtifactCacheTTL,\n logger: this.#config.logger,\n });\n }\n return this.#artifactCache;\n }\n\n /**\n * Terminate clears the artifact cache only.\n * The worker is externally owned — the relayer does not terminate it.\n */\n terminate(): void {\n this.#artifactCache = null;\n this.resetInit();\n }\n\n /** Calls {@link terminate}. */\n [Symbol.dispose](): void {\n this.terminate();\n }\n\n /**\n * Refresh the CSRF token in the worker.\n * Call this before making authenticated network requests.\n */\n async #refreshCsrfToken(): Promise<void> {\n const token = this.#config.security?.getCsrfToken?.() ?? \"\";\n if (token) {\n await this.#worker.updateCsrf(token);\n }\n }\n\n /**\n * Generate a transport key pair (ML-KEM public + private key) used for user-decryption.\n */\n async generateTransportKeyPair(): Promise<TransportKeyPair> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const result = await this.#worker.generateKeypair({ chainId });\n return {\n publicKey: result.publicKey,\n privateKey: result.privateKey,\n };\n }\n\n /**\n * Create EIP712 typed data for user decryption authorization.\n */\n async createEIP712(\n publicKey: Hex,\n contractAddresses: Address[],\n startTimestamp: number,\n durationDays = 7,\n ): Promise<EIP712TypedData> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return this.#worker.createEIP712({\n chainId,\n publicKey,\n contractAddresses,\n startTimestamp,\n durationDays,\n });\n }\n\n /**\n * Encrypt values for use in smart contract calls.\n * Each value must specify its FHE type (ebool, euint8–256, eaddress).\n */\n async encrypt(params: EncryptParams): Promise<EncryptResult> {\n const { values, contractAddress, userAddress } = params;\n await this.ensureInit();\n const chainId = this.chain.id;\n\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.encrypt({\n chainId,\n values,\n contractAddress,\n userAddress,\n });\n return {\n encryptedValues: result.handles.map((handle) => toHex(handle)),\n inputProof: toHex(result.inputProof),\n };\n });\n }\n\n /**\n * Decrypt ciphertexts using user's private key.\n * Requires a valid EIP712 signature.\n */\n async userDecrypt(\n params: UserDecryptParams,\n ): Promise<Readonly<Record<EncryptedValue, ClearValue>>> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.userDecrypt({ chainId, ...params });\n return result.clearValues;\n });\n }\n\n /**\n * Public decryption - no authorization needed.\n * Used for publicly visible encrypted values.\n */\n async publicDecrypt(encryptedValues: EncryptedValue[]): Promise<PublicDecryptResult> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.publicDecrypt({\n chainId,\n encryptedValues,\n });\n return {\n clearValues: result.clearValues,\n abiEncodedClearValues: result.abiEncodedClearValues,\n decryptionProof: result.decryptionProof,\n };\n });\n }\n\n /**\n * Create EIP712 typed data for delegated user decryption authorization.\n */\n async createDelegatedUserDecryptEIP712(\n publicKey: Hex,\n contractAddresses: Address[],\n delegatorAddress: Address,\n startTimestamp: number,\n durationDays = 7,\n ): Promise<KmsDelegatedUserDecryptEIP712Type> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return this.#worker.createDelegatedUserDecryptEIP712({\n chainId,\n publicKey,\n contractAddresses,\n delegatorAddress,\n startTimestamp,\n durationDays,\n });\n }\n\n /**\n * Decrypt ciphertexts via delegation.\n * Requires a valid EIP712 signature from the delegator.\n */\n async delegatedUserDecrypt(\n params: DelegatedUserDecryptParams,\n ): Promise<Readonly<Record<EncryptedValue, ClearValue>>> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.delegatedUserDecrypt({\n chainId,\n ...params,\n });\n return result.clearValues;\n });\n }\n\n /**\n * Submit a ZK proof to the relayer for verification.\n */\n async requestZKProofVerification(zkProof: ZKProofLike): Promise<InputProofBytesType> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n return this.#worker.requestZKProofVerification({ chainId, zkProof });\n });\n }\n\n /**\n * Fetch the network's FHE encryption key (ID + bytes).\n * When storage is configured, the result is cached persistently.\n */\n async fetchFheEncryptionKeyBytes(): Promise<FheEncryptionKey | null> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const artifactCache = this.#getArtifactCache();\n return artifactCache.fetchFheEncryptionKeyBytes(\n async () => (await this.#worker.getPublicKey({ chainId })).result,\n );\n }\n\n /**\n * Get public parameters for encryption capacity.\n * When storage is configured, the result is cached persistently.\n */\n async getPublicParams(bits: number): Promise<PublicParamsData | null> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const artifactCache = this.#getArtifactCache();\n return artifactCache.getPublicParams(\n bits,\n async () => (await this.#worker.getPublicParams({ chainId, bits })).result,\n );\n }\n}\n","import type {\n CreateDelegatedEIP712Payload,\n CreateDelegatedEIP712ResponseData,\n CreateEIP712Payload,\n CreateEIP712ResponseData,\n DelegatedUserDecryptPayload,\n DelegatedUserDecryptResponseData,\n EncryptPayload,\n EncryptResponseData,\n GenerateKeypairRequest,\n GenerateKeypairResponseData,\n GetPublicKeyRequest,\n GetPublicKeyResponseData,\n GetPublicParamsRequest,\n GetPublicParamsResponseData,\n InitResponseData,\n PublicDecryptPayload,\n PublicDecryptResponseData,\n RequestZKProofVerificationRequest,\n RequestZKProofVerificationResponseData,\n UserDecryptPayload,\n UserDecryptResponseData,\n GenericLogger,\n WorkerEnv,\n WorkerRequest,\n WorkerRequestType,\n WorkerResponse,\n} from \"./worker.types\";\n\n/** Pending request tracker */\ninterface PendingRequest<T> {\n resolve: (value: T) => void;\n reject: (error: Error) => void;\n timeoutId: ReturnType<typeof setTimeout>;\n startTime: number;\n type: WorkerRequestType;\n}\n\n/** Default timeout for operations (30 seconds) */\nexport const DEFAULT_TIMEOUT_MS = 30_000;\n\n/** Extended timeout for WASM initialization (60 seconds) */\nexport const INIT_TIMEOUT_MS = 60_000;\n\n/**\n * Abstract base class for worker clients (browser Web Worker and Node.js worker_threads).\n * Encapsulates all shared logic: pending request tracking, timeouts, init dedup, domain methods.\n * Subclasses implement the abstract hooks for platform-specific worker creation and messaging.\n */\nexport abstract class BaseWorkerClient<TWorker, TConfig> {\n #worker: TWorker | null = null;\n #pendingRequests = new Map<string, PendingRequest<unknown>>();\n #initPromise: Promise<TWorker> | null = null;\n protected readonly config: TConfig;\n protected readonly logger: GenericLogger | undefined;\n\n constructor(config: TConfig, logger: GenericLogger | undefined) {\n this.config = config;\n this.logger = logger;\n }\n\n // ===========================================================================\n // Abstract hooks — subclasses must implement\n // ===========================================================================\n\n /** Create the platform-specific worker instance. */\n protected abstract createWorker(): TWorker;\n\n /** Wire message/error/messageerror events on the worker. */\n protected abstract wireEvents(worker: TWorker): void;\n\n /** Post a message to the worker. */\n protected abstract postMessage(worker: TWorker, request: WorkerRequest): void;\n\n /** Terminate the platform-specific worker. */\n protected abstract terminateWorker(worker: TWorker): void;\n\n /** Generate a unique request ID. */\n protected abstract generateRequestId(): string;\n\n /** Return the init request type and payload. */\n protected abstract getInitPayload(): {\n type: WorkerRequestType;\n payload: WorkerRequest[\"payload\"];\n };\n\n /** Subclasses set \"web\" or \"node\" — stamps the env discriminant on INIT payloads. */\n protected abstract readonly env: WorkerEnv;\n\n /** Optional hook called after worker init succeeds (e.g. for node worker.unref()). */\n protected onWorkerReady?(_worker: TWorker): void;\n\n // ===========================================================================\n // Shared init / terminate\n // ===========================================================================\n\n async initWorker(): Promise<TWorker> {\n if (this.#worker) {\n return this.#worker;\n }\n\n if (!this.#initPromise) {\n this.#initPromise = this.#doInitWorker().catch((error) => {\n this.#initPromise = null;\n throw error;\n });\n }\n return this.#initPromise;\n }\n\n async #doInitWorker(): Promise<TWorker> {\n const worker = this.createWorker();\n this.wireEvents(worker);\n\n try {\n const { type, payload } = this.getInitPayload();\n await this.sendRequestTo<InitResponseData>(worker, type, payload, INIT_TIMEOUT_MS);\n this.onWorkerReady?.(worker);\n this.#worker = worker;\n } catch (error) {\n this.terminateWorker(worker);\n throw error;\n }\n\n return this.#worker;\n }\n\n terminate(): void {\n if (this.#worker) {\n for (const [id, pending] of this.#pendingRequests) {\n clearTimeout(pending.timeoutId);\n pending.reject(new Error(\"Worker terminated\"));\n this.#pendingRequests.delete(id);\n }\n\n this.terminateWorker(this.#worker);\n this.#worker = null;\n }\n this.#initPromise = null;\n }\n\n // ===========================================================================\n // Message handling\n // ===========================================================================\n\n protected handleResponse(response: WorkerResponse<unknown>): void {\n const pending = this.#pendingRequests.get(response.id);\n\n if (!pending) {\n this.logger?.warn(\"[WorkerClient] Received response for unknown request\", {\n id: response.id,\n });\n return;\n }\n\n const elapsed = Math.round(performance.now() - pending.startTime);\n\n clearTimeout(pending.timeoutId);\n this.#pendingRequests.delete(response.id);\n\n if (response.success) {\n this.logger?.debug(`[WorkerClient] ← ${pending.type} OK`, {\n id: response.id,\n elapsed,\n });\n pending.resolve(response.data);\n } else {\n this.logger?.error(`[WorkerClient] ← ${pending.type} FAILED`, {\n id: response.id,\n elapsed,\n error: response.error,\n });\n const err = new Error(response.error);\n if (\"statusCode\" in response && typeof response.statusCode === \"number\") {\n (err as Error & { statusCode?: number }).statusCode = response.statusCode;\n }\n pending.reject(err);\n }\n }\n\n protected handleWorkerError(message: string): void {\n this.logger?.error(\"[WorkerClient] Worker error\", { error: message });\n const worker = this.#worker;\n this.#worker = null;\n this.#rejectAllPending(`Worker error: ${message}`);\n if (worker) {\n this.terminateWorker(worker);\n }\n }\n\n protected handleWorkerMessageError(): void {\n this.logger?.error(\"[WorkerClient] Message deserialization failed\");\n const worker = this.#worker;\n this.#worker = null;\n this.#rejectAllPending(\"Worker message deserialization failed\");\n if (worker) {\n this.terminateWorker(worker);\n }\n }\n\n // ===========================================================================\n // Request sending\n // ===========================================================================\n\n protected sendRequestTo<T>(\n worker: TWorker,\n type: WorkerRequestType,\n payload: WorkerRequest[\"payload\"],\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n ): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n const id = this.generateRequestId();\n const startTime = performance.now();\n this.logger?.debug(`[WorkerClient] → ${type}`, { id });\n\n const timeoutId = setTimeout(() => {\n this.#pendingRequests.delete(id);\n const elapsed = Math.round(performance.now() - startTime);\n this.logger?.error(`[WorkerClient] ${type} timed out after ${timeoutMs}ms`, {\n id,\n elapsed,\n });\n reject(new Error(`Request ${type} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n this.#pendingRequests.set(id, {\n resolve: resolve as (value: unknown) => void,\n reject,\n timeoutId,\n startTime,\n type,\n });\n\n const request = { id, type, payload } as WorkerRequest;\n this.postMessage(worker, request);\n });\n }\n\n protected async sendRequest<T>(\n type: WorkerRequestType,\n payload: WorkerRequest[\"payload\"],\n timeoutMs: number = DEFAULT_TIMEOUT_MS,\n ): Promise<T> {\n const worker = await this.initWorker();\n return this.sendRequestTo<T>(worker, type, payload, timeoutMs);\n }\n\n // ===========================================================================\n // Domain methods\n // ===========================================================================\n\n async generateKeypair(\n params: GenerateKeypairRequest[\"payload\"],\n ): Promise<GenerateKeypairResponseData> {\n return this.sendRequest<GenerateKeypairResponseData>(\"GENERATE_KEYPAIR\", params);\n }\n\n async createEIP712(params: CreateEIP712Payload): Promise<CreateEIP712ResponseData> {\n return this.sendRequest<CreateEIP712ResponseData>(\"CREATE_EIP712\", params);\n }\n\n async encrypt(params: EncryptPayload): Promise<EncryptResponseData> {\n return this.sendRequest<EncryptResponseData>(\"ENCRYPT\", params);\n }\n\n async userDecrypt(params: UserDecryptPayload): Promise<UserDecryptResponseData> {\n return this.sendRequest<UserDecryptResponseData>(\"USER_DECRYPT\", params);\n }\n\n async publicDecrypt(params: PublicDecryptPayload): Promise<PublicDecryptResponseData> {\n return this.sendRequest<PublicDecryptResponseData>(\"PUBLIC_DECRYPT\", params);\n }\n\n async createDelegatedUserDecryptEIP712(\n params: CreateDelegatedEIP712Payload,\n ): Promise<CreateDelegatedEIP712ResponseData> {\n return this.sendRequest<CreateDelegatedEIP712ResponseData>(\"CREATE_DELEGATED_EIP712\", params);\n }\n\n async delegatedUserDecrypt(\n params: DelegatedUserDecryptPayload,\n ): Promise<DelegatedUserDecryptResponseData> {\n return this.sendRequest<DelegatedUserDecryptResponseData>(\"DELEGATED_USER_DECRYPT\", params);\n }\n\n async requestZKProofVerification(\n params: RequestZKProofVerificationRequest[\"payload\"],\n ): Promise<RequestZKProofVerificationResponseData> {\n return this.sendRequest<RequestZKProofVerificationResponseData>(\n \"REQUEST_ZK_PROOF_VERIFICATION\",\n params,\n );\n }\n\n async getPublicKey(params: GetPublicKeyRequest[\"payload\"]): Promise<GetPublicKeyResponseData> {\n return this.sendRequest<GetPublicKeyResponseData>(\"GET_PUBLIC_KEY\", params);\n }\n\n async getPublicParams(\n params: GetPublicParamsRequest[\"payload\"],\n ): Promise<GetPublicParamsResponseData> {\n return this.sendRequest<GetPublicParamsResponseData>(\"GET_PUBLIC_PARAMS\", params);\n }\n\n // ===========================================================================\n // Internal helpers\n // ===========================================================================\n\n #rejectAllPending(message: string): void {\n for (const [id, pending] of this.#pendingRequests) {\n clearTimeout(pending.timeoutId);\n pending.reject(new Error(message));\n this.#pendingRequests.delete(id);\n }\n }\n}\n","import { assertFunctionProp, assertObject, assertStringProp } from \"../utils/assertions\";\n\n/**\n * Subset of the WebExtensions `runtime` API used by the SDK.\n * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime\n */\nexport interface BrowserExtensionRuntime {\n /** The ID of the extension. */\n id: string;\n /** Convert a relative path within the extension to a fully-qualified URL. */\n getURL: (path: string) => string;\n}\n\nfunction isValidRuntime(runtime: unknown): runtime is BrowserExtensionRuntime {\n try {\n assertObject(runtime, \"runtime\");\n assertStringProp(runtime, \"id\", \"runtime.id\");\n assertFunctionProp<\"getURL\", (path: string) => string>(runtime, \"getURL\", \"runtime.getURL\");\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Return the browser extension runtime object, or `undefined` outside extensions.\n * Works across Chrome/Edge (`chrome.runtime`) and Firefox/Safari (`browser.runtime`).\n * Extensions have restricted CSP that blocks `blob:` URLs, so callers use\n * this to detect the environment and resolve file URLs via `runtime.getURL`.\n */\nexport function getBrowserExtensionRuntime(): BrowserExtensionRuntime | undefined {\n const g = globalThis as unknown as Record<string, unknown>;\n for (const ns of [g.chrome, g.browser]) {\n try {\n assertObject(ns, \"ns\");\n if (isValidRuntime(ns.runtime)) {\n return ns.runtime;\n }\n } catch {\n continue;\n }\n }\n return undefined;\n}\n","import type { FheChain } from \"../chains/types\";\nimport type {\n GenericLogger,\n UpdateCsrfResponseData,\n WorkerEnv,\n WorkerRequest,\n WorkerRequestType,\n WorkerResponse,\n} from \"./worker.types\";\nimport { BaseWorkerClient } from \"./worker.base-client\";\nimport { getBrowserExtensionRuntime } from \"./browser-extension\";\nimport { default as workerCode, filename as workerFilename } from \"./relayer-sdk.worker.ts?iife\";\n\n/** Configuration for the worker client */\nexport interface WorkerClientConfig {\n cdnUrl: string;\n chains: FheChain[];\n csrfToken: string;\n /** Expected SHA-384 hex digest of the CDN bundle for integrity verification. */\n integrity?: string;\n /** Optional logger for tracing worker request lifecycle. */\n logger?: GenericLogger;\n /** Number of WASM threads for parallel FHE operations (passed to `initSDK({ thread })`). */\n thread?: number;\n}\n\n/**\n * Client for communicating with the RelayerSDK Web Worker.\n * Provides a promise-based API for FHE operations.\n */\nexport class RelayerWorkerClient extends BaseWorkerClient<Worker, WorkerClientConfig> {\n protected readonly env: WorkerEnv = \"web\";\n\n constructor(config: WorkerClientConfig) {\n super(config, config.logger);\n }\n\n protected createWorker(): Worker {\n const runtime = getBrowserExtensionRuntime();\n if (runtime) {\n return new Worker(runtime.getURL(workerFilename));\n }\n const blobUrl = URL.createObjectURL(new Blob([workerCode], { type: \"application/javascript\" }));\n try {\n return new Worker(blobUrl);\n } finally {\n URL.revokeObjectURL(blobUrl);\n }\n }\n\n protected wireEvents(worker: Worker): void {\n worker.onmessage = (event: MessageEvent<WorkerResponse<unknown>>) =>\n this.handleResponse(event.data);\n worker.onerror = (event: ErrorEvent) => this.handleWorkerError(event.message);\n worker.onmessageerror = () => this.handleWorkerMessageError();\n }\n\n protected postMessage(worker: Worker, request: WorkerRequest): void {\n worker.postMessage(request);\n }\n\n protected terminateWorker(worker: Worker): void {\n worker.terminate();\n }\n\n protected generateRequestId(): string {\n return crypto.randomUUID();\n }\n\n protected getInitPayload(): {\n type: WorkerRequestType;\n payload: WorkerRequest[\"payload\"];\n } {\n // Explicitly construct the payload from serializable fields only.\n // Functions (e.g. `logger`) cannot be cloned by the structured clone\n // algorithm used by `worker.postMessage()`.\n const { cdnUrl, chains, csrfToken, integrity, thread } = this.config;\n return {\n type: \"INIT\",\n payload: { env: \"web\" as const, cdnUrl, chains, csrfToken, integrity, thread },\n };\n }\n\n /**\n * Update the CSRF token in the worker.\n * Call this before making authenticated requests to ensure the token is fresh.\n */\n async updateCsrf(csrfToken: string): Promise<void> {\n await this.sendRequest<UpdateCsrfResponseData>(\"UPDATE_CSRF\", {\n csrfToken,\n });\n }\n}\n","import { z } from \"zod/mini\";\nimport { CDN_INTEGRITY, CDN_URL, RelayerWeb } from \"../relayer/relayer-web\";\nimport { parseConfiguration } from \"../validation\";\nimport { RelayerWorkerClient } from \"../worker/worker.client\";\nimport type { WebRelayerConfig, WebRelayerOptions } from \"./types\";\n\nconst WebRelayerOptionsSchema = z.object({\n threads: z.optional(z.int().check(z.positive())),\n fheArtifactCacheTTL: z.optional(z.int().check(z.nonnegative())),\n});\n\n/**\n * Browser relayer — routes to RelayerWeb (Web Worker + WASM).\n *\n * @param options - Worker options (threads, security, logger, storage).\n *\n * @example\n * ```ts\n * relayers: {\n * [sepolia.id]: web(),\n * [mainnet.id]: web({ threads: 4 }),\n * }\n * ```\n */\nexport function web(options?: WebRelayerOptions): WebRelayerConfig {\n if (options !== undefined) {\n parseConfiguration(WebRelayerOptionsSchema, options);\n }\n return {\n type: \"web\",\n createWorker: (chains) =>\n new RelayerWorkerClient({\n cdnUrl: CDN_URL,\n chains,\n csrfToken: options?.security?.getCsrfToken?.() ?? \"\",\n integrity: options?.security?.integrityCheck === false ? undefined : CDN_INTEGRITY,\n logger: options?.logger,\n thread: options?.threads,\n }),\n createRelayer: (chain, worker) => new RelayerWeb({ chain, worker, ...options }),\n };\n}\n"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- import{n as e,t}from"../hex-CxtyupeQ.js";import{parentPort as n}from"node:worker_threads";if(!n)throw Error(`This script must be run as a worker thread`);const r=n,i=new Map,a=new Map,o=new Map;function s(e){return{...e,chainId:e.id}}async function c(e){let t=i.get(e);if(t)return t;let n=a.get(e);if(n)return n;let r=o.get(e);if(!r)throw Error(`No config for chain ${e}. Available: [${[...o.keys()].join(`, `)}]`);let c=(async()=>(await import(`@zama-fhe/relayer-sdk/node`)).createInstance({...s(r),batchRpcCalls:!1}))().then(t=>(i.set(e,t),a.delete(e),t)).catch(t=>{throw a.delete(e),t});return a.set(e,c),c}function l(e,t,n,i){let a={id:e,type:t,success:!0,data:n};r.postMessage(a,i)}function u(e,t,n){let i={id:e,type:t,success:!1,error:n};r.postMessage(i)}async function d(e){let{id:t,type:n,payload:r}=e;try{for(let e of r.chains)o.set(e.id,e);l(t,n,{initialized:!0})}catch(e){let r=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] Init error:`,r),u(t,n,r)}}function f(e){return typeof e==`boolean`?e?1n:0n:e}function p(e){throw Error(`Unsupported FHE type`)}async function m(e){let{id:t,type:n,payload:r}=e,{values:i,contractAddress:a,userAddress:o}=r;try{let e=(await c(r.chainId)).createEncryptedInput(a,o);for(let t of i){let{value:n,type:r}=t;switch(r){case`ebool`:e.addBool(typeof n==`boolean`?n:n!==0n);break;case`euint8`:e.add8(f(n));break;case`euint16`:e.add16(f(n));break;case`euint32`:e.add32(f(n));break;case`euint64`:e.add64(f(n));break;case`euint128`:e.add128(f(n));break;case`euint256`:e.add256(f(n));break;case`eaddress`:e.addAddress(n);break;default:p(r)}}let s=await e.encrypt();l(t,n,{handles:s.handles,inputProof:s.inputProof},[s.inputProof.buffer,...s.handles.map(e=>e.buffer)])}catch(e){let r=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] Encrypt error:`,r),u(t,n,r)}}async function h(t){let{id:n,type:r,payload:i}=t;try{let t=await c(i.chainId),a=i.encryptedValues.map(e=>({handle:e,contractAddress:i.contractAddress}));l(n,r,{clearValues:await t.userDecrypt(a,e(i.privateKey),e(i.publicKey),i.signature,i.signedContractAddresses,i.signerAddress,i.startTimestamp,i.durationDays)})}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] UserDecrypt error:`,t),u(n,r,t)}}async function g(e){let{id:t,type:n,payload:r}=e;try{l(t,n,{...await(await c(r.chainId)).publicDecrypt(r.encryptedValues)})}catch(e){let r=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] PublicDecrypt error:`,r),u(t,n,r)}}async function _(e){let{id:n,type:r,payload:i}=e;try{let e=(await c(i.chainId)).generateKeypair();l(n,r,{publicKey:t(e.publicKey),privateKey:t(e.privateKey)})}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] GenerateKeypair error:`,t),u(n,r,t)}}async function v(t){let{id:n,type:r,payload:i}=t;try{l(n,r,(await c(i.chainId)).createEIP712(e(i.publicKey),i.contractAddresses,i.startTimestamp,i.durationDays))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] CreateEIP712 error:`,t),u(n,r,t)}}async function y(t){let{id:n,type:r,payload:i}=t;try{l(n,r,(await c(i.chainId)).createDelegatedUserDecryptEIP712(e(i.publicKey),i.contractAddresses,i.delegatorAddress,i.startTimestamp,i.durationDays))}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] CreateDelegatedEIP712 error:`,t),u(n,r,t)}}async function b(t){let{id:n,type:r,payload:i}=t;try{let t=await c(i.chainId),a=i.encryptedValues.map(e=>({handle:e,contractAddress:i.contractAddress}));l(n,r,{clearValues:await t.delegatedUserDecrypt(a,e(i.privateKey),e(i.publicKey),i.signature,i.signedContractAddresses,i.delegatorAddress,i.delegateAddress,i.startTimestamp,i.durationDays)})}catch(e){let t=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] DelegatedUserDecrypt error:`,t),u(n,r,t)}}async function x(e){let{id:t,type:n,payload:r}=e;try{let e=await(await c(r.chainId)).requestZKProofVerification(r.zkProof);l(t,n,e,[e.inputProof.buffer,...e.handles.map(e=>e.buffer)])}catch(e){let r=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] RequestZKProofVerification error:`,r),u(t,n,r)}}async function S(e){let{id:t,type:n,payload:r}=e;try{l(t,n,{result:(await c(r.chainId)).getPublicKey()})}catch(e){let r=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] GetPublicKey error:`,r),u(t,n,r)}}async function C(e){let{id:t,type:n,payload:r}=e;try{l(t,n,{result:(await c(r.chainId)).getPublicParams(r.bits)})}catch(e){let r=e instanceof Error?e.message:String(e);console.error(`[NodeWorker] GetPublicParams error:`,r),u(t,n,r)}}async function w(e){try{switch(e.type){case`INIT`:await d(e);break;case`ENCRYPT`:await m(e);break;case`USER_DECRYPT`:await h(e);break;case`PUBLIC_DECRYPT`:await g(e);break;case`GENERATE_KEYPAIR`:await _(e);break;case`CREATE_EIP712`:await v(e);break;case`CREATE_DELEGATED_EIP712`:await y(e);break;case`DELEGATED_USER_DECRYPT`:await b(e);break;case`REQUEST_ZK_PROOF_VERIFICATION`:await x(e);break;case`GET_PUBLIC_KEY`:await S(e);break;case`GET_PUBLIC_PARAMS`:await C(e);break;default:console.error(`[NodeWorker] Unknown request type:`,e.type)}}catch(t){let n=t instanceof Error?t.message:String(t);u(e.id,e.type,n)}}r.on(`message`,e=>{w(e)});
1
+ import{n as e,t}from"../hex-CxtyupeQ.js";import{parentPort as n}from"node:worker_threads";if(!n)throw Error(`This script must be run as a worker thread`);const r=n,i=new Map,a=new Map,o=new Map;function s(e){return{...e,chainId:e.id}}async function c(e){let t=i.get(e);if(t)return t;let n=a.get(e);if(n)return n;let r=o.get(e);if(!r)throw Error(`No config for chain ${e}. Available: [${[...o.keys()].join(`, `)}]`);let c=(async()=>(await import(`@zama-fhe/relayer-sdk/node`)).createInstance({...s(r),batchRpcCalls:!1}))().then(t=>(i.set(e,t),a.delete(e),t)).catch(t=>{throw a.delete(e),t});return a.set(e,c),c}function l(e,t,n,i){let a={id:e,type:t,success:!0,data:n};r.postMessage(a,i)}function u(e,t,n){let i={id:e,type:t,success:!1,error:n};r.postMessage(i)}async function d(e){let{id:t,type:n,payload:r}=e;try{for(let e of r.chains)o.set(e.id,e);l(t,n,{initialized:!0})}catch(e){u(t,n,e instanceof Error?e.message:String(e))}}function f(e){return typeof e==`boolean`?e?1n:0n:e}function p(e){throw Error(`Unsupported FHE type`)}async function m(e){let{id:t,type:n,payload:r}=e,{values:i,contractAddress:a,userAddress:o}=r;try{let e=(await c(r.chainId)).createEncryptedInput(a,o);for(let t of i){let{value:n,type:r}=t;switch(r){case`ebool`:e.addBool(typeof n==`boolean`?n:n!==0n);break;case`euint8`:e.add8(f(n));break;case`euint16`:e.add16(f(n));break;case`euint32`:e.add32(f(n));break;case`euint64`:e.add64(f(n));break;case`euint128`:e.add128(f(n));break;case`euint256`:e.add256(f(n));break;case`eaddress`:e.addAddress(n);break;default:p(r)}}let s=await e.encrypt();l(t,n,{handles:s.handles,inputProof:s.inputProof},[s.inputProof.buffer,...s.handles.map(e=>e.buffer)])}catch(e){u(t,n,e instanceof Error?e.message:String(e))}}async function h(t){let{id:n,type:r,payload:i}=t;try{let t=await c(i.chainId),a=i.encryptedValues.map(e=>({handle:e,contractAddress:i.contractAddress}));l(n,r,{clearValues:await t.userDecrypt(a,e(i.privateKey),e(i.publicKey),i.signature,i.signedContractAddresses,i.signerAddress,i.startTimestamp,i.durationDays)})}catch(e){u(n,r,e instanceof Error?e.message:String(e))}}async function g(e){let{id:t,type:n,payload:r}=e;try{l(t,n,{...await(await c(r.chainId)).publicDecrypt(r.encryptedValues)})}catch(e){u(t,n,e instanceof Error?e.message:String(e))}}async function _(e){let{id:n,type:r,payload:i}=e;try{let e=(await c(i.chainId)).generateKeypair();l(n,r,{publicKey:t(e.publicKey),privateKey:t(e.privateKey)})}catch(e){u(n,r,e instanceof Error?e.message:String(e))}}async function v(t){let{id:n,type:r,payload:i}=t;try{l(n,r,(await c(i.chainId)).createEIP712(e(i.publicKey),i.contractAddresses,i.startTimestamp,i.durationDays))}catch(e){u(n,r,e instanceof Error?e.message:String(e))}}async function y(t){let{id:n,type:r,payload:i}=t;try{l(n,r,(await c(i.chainId)).createDelegatedUserDecryptEIP712(e(i.publicKey),i.contractAddresses,i.delegatorAddress,i.startTimestamp,i.durationDays))}catch(e){u(n,r,e instanceof Error?e.message:String(e))}}async function b(t){let{id:n,type:r,payload:i}=t;try{let t=await c(i.chainId),a=i.encryptedValues.map(e=>({handle:e,contractAddress:i.contractAddress}));l(n,r,{clearValues:await t.delegatedUserDecrypt(a,e(i.privateKey),e(i.publicKey),i.signature,i.signedContractAddresses,i.delegatorAddress,i.delegateAddress,i.startTimestamp,i.durationDays)})}catch(e){u(n,r,e instanceof Error?e.message:String(e))}}async function x(e){let{id:t,type:n,payload:r}=e;try{let e=await(await c(r.chainId)).requestZKProofVerification(r.zkProof);l(t,n,e,[e.inputProof.buffer,...e.handles.map(e=>e.buffer)])}catch(e){u(t,n,e instanceof Error?e.message:String(e))}}async function S(e){let{id:t,type:n,payload:r}=e;try{l(t,n,{result:(await c(r.chainId)).getPublicKey()})}catch(e){u(t,n,e instanceof Error?e.message:String(e))}}async function C(e){let{id:t,type:n,payload:r}=e;try{l(t,n,{result:(await c(r.chainId)).getPublicParams(r.bits)})}catch(e){u(t,n,e instanceof Error?e.message:String(e))}}async function w(e){try{switch(e.type){case`INIT`:await d(e);break;case`ENCRYPT`:await m(e);break;case`USER_DECRYPT`:await h(e);break;case`PUBLIC_DECRYPT`:await g(e);break;case`GENERATE_KEYPAIR`:await _(e);break;case`CREATE_EIP712`:await v(e);break;case`CREATE_DELEGATED_EIP712`:await y(e);break;case`DELEGATED_USER_DECRYPT`:await b(e);break;case`REQUEST_ZK_PROOF_VERIFICATION`:await x(e);break;case`GET_PUBLIC_KEY`:await S(e);break;case`GET_PUBLIC_PARAMS`:await C(e);break;default:throw Error(`Unknown request type: ${e.type}`)}}catch(t){let n=t instanceof Error?t.message:String(t);u(e.id,e.type,n)}}r.on(`message`,e=>{w(e)});
2
2
  //# sourceMappingURL=relayer-sdk.node-worker.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"relayer-sdk.node-worker.js","names":[],"sources":["../../../src/worker/relayer-sdk.node-worker.ts"],"sourcesContent":["/**\n * Node.js worker thread for RelayerSDK FHE operations.\n * Handles CPU-intensive WASM operations off the main thread using node:worker_threads.\n */\n\nimport type { FhevmInstance, FhevmInstanceConfig } from \"@zama-fhe/relayer-sdk/node\";\nimport type { FheChain } from \"../chains/types\";\nimport { parentPort, type Transferable } from \"node:worker_threads\";\nimport type {\n CreateDelegatedEIP712Request,\n CreateEIP712Request,\n DelegatedUserDecryptRequest,\n DelegatedUserDecryptResponseData,\n EncryptRequest,\n EncryptResponseData,\n ErrorResponse,\n GenerateKeypairRequest,\n GenerateKeypairResponseData,\n GetPublicKeyRequest,\n GetPublicKeyResponseData,\n GetPublicParamsRequest,\n GetPublicParamsResponseData,\n InitRequest,\n PublicDecryptRequest,\n PublicDecryptResponseData,\n RequestZKProofVerificationRequest,\n SuccessResponse,\n UserDecryptRequest,\n UserDecryptResponseData,\n WorkerRequest,\n} from \"./worker.types\";\nimport { prefixHex, unprefixHex } from \"../utils\";\n\nif (!parentPort) {\n throw new Error(\"This script must be run as a worker thread\");\n}\n\nconst port = parentPort;\n\n// ── Multi-chain instance management ─────────────────────────────\nconst instances = new Map<number, FhevmInstance>();\nconst pending = new Map<number, Promise<FhevmInstance>>();\nconst configs = new Map<number, FheChain>();\n\n/** Convert an FheChain to the FhevmInstanceConfig shape expected by createInstance. */\nfunction toInstanceConfig(chain: FheChain): FhevmInstanceConfig {\n return { ...chain, chainId: chain.id };\n}\n\n/**\n * Get or lazily create an FhevmInstance for the given chain.\n */\nasync function getInstance(chainId: number): Promise<FhevmInstance> {\n const existing = instances.get(chainId);\n if (existing) {\n return existing;\n }\n\n const inflight = pending.get(chainId);\n if (inflight) {\n return inflight;\n }\n\n const config = configs.get(chainId);\n if (!config) {\n throw new Error(\n `No config for chain ${chainId}. Available: [${[...configs.keys()].join(\", \")}]`,\n );\n }\n\n const promise = (async () => {\n const nodeSdk = await import(\"@zama-fhe/relayer-sdk/node\");\n return nodeSdk.createInstance({ ...toInstanceConfig(config), batchRpcCalls: false });\n })()\n .then((instance) => {\n instances.set(chainId, instance);\n pending.delete(chainId);\n return instance;\n })\n .catch((err) => {\n pending.delete(chainId);\n throw err;\n });\n\n pending.set(chainId, promise);\n return promise;\n}\n\nfunction sendSuccess<T>(\n id: string,\n type: WorkerRequest[\"type\"],\n data: T,\n transfer?: readonly Transferable[],\n): void {\n const response: SuccessResponse<T> = { id, type, success: true, data };\n port.postMessage(response, transfer);\n}\n\nfunction sendError(id: string, type: WorkerRequest[\"type\"], error: string): void {\n const response: ErrorResponse = { id, type, success: false, error };\n port.postMessage(response);\n}\n\n/**\n * Handle INIT request - register chain configs (instances are lazy).\n */\nasync function handleInit(request: InitRequest): Promise<void> {\n const { id, type, payload } = request;\n try {\n for (const chain of payload.chains) {\n configs.set(chain.id, chain);\n }\n sendSuccess(id, type, { initialized: true });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] Init error:\", message);\n sendError(id, type, message);\n }\n}\n\n/** Coerce a boolean to bigint for numeric FHE types. */\nfunction toBigInt(value: bigint | boolean): bigint {\n return typeof value === \"boolean\" ? (value ? 1n : 0n) : value;\n}\n\nfunction unreachableFheType(_: never): never {\n throw new Error(\"Unsupported FHE type\");\n}\n\nasync function handleEncrypt(request: EncryptRequest): Promise<void> {\n const { id, type, payload } = request;\n const { values, contractAddress, userAddress } = payload;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const input = instance.createEncryptedInput(contractAddress, userAddress);\n\n for (const entry of values) {\n const { value, type: fheType } = entry;\n switch (fheType) {\n case \"ebool\":\n input.addBool(typeof value === \"boolean\" ? value : value !== 0n);\n break;\n case \"euint8\":\n input.add8(toBigInt(value));\n break;\n case \"euint16\":\n input.add16(toBigInt(value));\n break;\n case \"euint32\":\n input.add32(toBigInt(value));\n break;\n case \"euint64\":\n input.add64(toBigInt(value));\n break;\n case \"euint128\":\n input.add128(toBigInt(value));\n break;\n case \"euint256\":\n input.add256(toBigInt(value));\n break;\n case \"eaddress\":\n input.addAddress(value);\n break;\n default:\n unreachableFheType(fheType);\n }\n }\n\n const encrypted = await input.encrypt();\n\n const response: EncryptResponseData = {\n handles: encrypted.handles,\n inputProof: encrypted.inputProof,\n };\n\n const transferList: Transferable[] = [\n encrypted.inputProof.buffer as ArrayBuffer,\n ...encrypted.handles.map((h) => h.buffer as ArrayBuffer),\n ];\n\n sendSuccess(id, type, response, transferList);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] Encrypt error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleUserDecrypt(request: UserDecryptRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const handleContractPairs = payload.encryptedValues.map((encryptedValue) => ({\n handle: encryptedValue,\n contractAddress: payload.contractAddress,\n }));\n\n const result = await instance.userDecrypt(\n handleContractPairs,\n unprefixHex(payload.privateKey),\n unprefixHex(payload.publicKey),\n payload.signature,\n payload.signedContractAddresses,\n payload.signerAddress,\n payload.startTimestamp,\n payload.durationDays,\n );\n\n const response: UserDecryptResponseData = { clearValues: result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] UserDecrypt error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handlePublicDecrypt(request: PublicDecryptRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = await instance.publicDecrypt(payload.encryptedValues);\n\n const response: PublicDecryptResponseData = { ...result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] PublicDecrypt error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleGenerateKeypair(request: GenerateKeypairRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const keypair = instance.generateKeypair();\n\n const response: GenerateKeypairResponseData = {\n publicKey: prefixHex(keypair.publicKey),\n privateKey: prefixHex(keypair.privateKey),\n };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] GenerateKeypair error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleCreateEIP712(request: CreateEIP712Request): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const eip712 = instance.createEIP712(\n unprefixHex(payload.publicKey),\n payload.contractAddresses,\n payload.startTimestamp,\n payload.durationDays,\n );\n\n sendSuccess(id, type, eip712);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] CreateEIP712 error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleCreateDelegatedEIP712(request: CreateDelegatedEIP712Request): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = instance.createDelegatedUserDecryptEIP712(\n unprefixHex(payload.publicKey),\n payload.contractAddresses,\n payload.delegatorAddress,\n payload.startTimestamp,\n payload.durationDays,\n );\n\n sendSuccess(id, type, result);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] CreateDelegatedEIP712 error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleDelegatedUserDecrypt(request: DelegatedUserDecryptRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const handleContractPairs = payload.encryptedValues.map((encryptedValue) => ({\n handle: encryptedValue,\n contractAddress: payload.contractAddress,\n }));\n\n const result = await instance.delegatedUserDecrypt(\n handleContractPairs,\n unprefixHex(payload.privateKey),\n unprefixHex(payload.publicKey),\n payload.signature,\n payload.signedContractAddresses,\n payload.delegatorAddress,\n payload.delegateAddress,\n payload.startTimestamp,\n payload.durationDays,\n );\n\n const response: DelegatedUserDecryptResponseData = { clearValues: result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] DelegatedUserDecrypt error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleRequestZKProofVerification(\n request: RequestZKProofVerificationRequest,\n): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = await instance.requestZKProofVerification(payload.zkProof);\n\n const transferList: Transferable[] = [\n result.inputProof.buffer as ArrayBuffer,\n ...result.handles.map((h) => h.buffer as ArrayBuffer),\n ];\n\n sendSuccess(id, type, result, transferList);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] RequestZKProofVerification error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleGetPublicKey(request: GetPublicKeyRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = instance.getPublicKey();\n\n const response: GetPublicKeyResponseData = { result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] GetPublicKey error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleGetPublicParams(request: GetPublicParamsRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = instance.getPublicParams(\n // oxlint-disable-next-line typescript-eslint/consistent-type-imports -- SDK loaded dynamically\n payload.bits as keyof import(\"@zama-fhe/relayer-sdk/node\").PublicParams<Uint8Array>,\n );\n\n const response: GetPublicParamsResponseData = { result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n console.error(\"[NodeWorker] GetPublicParams error:\", message);\n sendError(id, type, message);\n }\n}\n\nasync function handleMessage(request: WorkerRequest): Promise<void> {\n try {\n switch (request.type) {\n case \"INIT\":\n await handleInit(request);\n break;\n case \"ENCRYPT\":\n await handleEncrypt(request);\n break;\n case \"USER_DECRYPT\":\n await handleUserDecrypt(request);\n break;\n case \"PUBLIC_DECRYPT\":\n await handlePublicDecrypt(request);\n break;\n case \"GENERATE_KEYPAIR\":\n await handleGenerateKeypair(request);\n break;\n case \"CREATE_EIP712\":\n await handleCreateEIP712(request);\n break;\n case \"CREATE_DELEGATED_EIP712\":\n await handleCreateDelegatedEIP712(request);\n break;\n case \"DELEGATED_USER_DECRYPT\":\n await handleDelegatedUserDecrypt(request);\n break;\n case \"REQUEST_ZK_PROOF_VERIFICATION\":\n await handleRequestZKProofVerification(request);\n break;\n case \"GET_PUBLIC_KEY\":\n await handleGetPublicKey(request);\n break;\n case \"GET_PUBLIC_PARAMS\":\n await handleGetPublicParams(request);\n break;\n default:\n console.error(\"[NodeWorker] Unknown request type:\", request.type);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(request.id, request.type, message);\n }\n}\n\nport.on(\"message\", (request: WorkerRequest) => {\n void handleMessage(request);\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"relayer-sdk.node-worker.js","names":[],"sources":["../../../src/worker/relayer-sdk.node-worker.ts"],"sourcesContent":["/**\n * Node.js worker thread for RelayerSDK FHE operations.\n * Handles CPU-intensive WASM operations off the main thread using node:worker_threads.\n */\n\nimport type { FhevmInstance, FhevmInstanceConfig } from \"@zama-fhe/relayer-sdk/node\";\nimport type { FheChain } from \"../chains/types\";\nimport { parentPort, type Transferable } from \"node:worker_threads\";\nimport type {\n CreateDelegatedEIP712Request,\n CreateEIP712Request,\n DelegatedUserDecryptRequest,\n DelegatedUserDecryptResponseData,\n EncryptRequest,\n EncryptResponseData,\n ErrorResponse,\n GenerateKeypairRequest,\n GenerateKeypairResponseData,\n GetPublicKeyRequest,\n GetPublicKeyResponseData,\n GetPublicParamsRequest,\n GetPublicParamsResponseData,\n InitRequest,\n PublicDecryptRequest,\n PublicDecryptResponseData,\n RequestZKProofVerificationRequest,\n SuccessResponse,\n UserDecryptRequest,\n UserDecryptResponseData,\n WorkerRequest,\n} from \"./worker.types\";\nimport { prefixHex, unprefixHex } from \"../utils\";\n\nif (!parentPort) {\n throw new Error(\"This script must be run as a worker thread\");\n}\n\nconst port = parentPort;\n\n// ── Multi-chain instance management ─────────────────────────────\nconst instances = new Map<number, FhevmInstance>();\nconst pending = new Map<number, Promise<FhevmInstance>>();\nconst configs = new Map<number, FheChain>();\n\n/** Convert an FheChain to the FhevmInstanceConfig shape expected by createInstance. */\nfunction toInstanceConfig(chain: FheChain): FhevmInstanceConfig {\n return { ...chain, chainId: chain.id };\n}\n\n/**\n * Get or lazily create an FhevmInstance for the given chain.\n */\nasync function getInstance(chainId: number): Promise<FhevmInstance> {\n const existing = instances.get(chainId);\n if (existing) {\n return existing;\n }\n\n const inflight = pending.get(chainId);\n if (inflight) {\n return inflight;\n }\n\n const config = configs.get(chainId);\n if (!config) {\n throw new Error(\n `No config for chain ${chainId}. Available: [${[...configs.keys()].join(\", \")}]`,\n );\n }\n\n const promise = (async () => {\n const nodeSdk = await import(\"@zama-fhe/relayer-sdk/node\");\n return nodeSdk.createInstance({ ...toInstanceConfig(config), batchRpcCalls: false });\n })()\n .then((instance) => {\n instances.set(chainId, instance);\n pending.delete(chainId);\n return instance;\n })\n .catch((err) => {\n pending.delete(chainId);\n throw err;\n });\n\n pending.set(chainId, promise);\n return promise;\n}\n\nfunction sendSuccess<T>(\n id: string,\n type: WorkerRequest[\"type\"],\n data: T,\n transfer?: readonly Transferable[],\n): void {\n const response: SuccessResponse<T> = { id, type, success: true, data };\n port.postMessage(response, transfer);\n}\n\nfunction sendError(id: string, type: WorkerRequest[\"type\"], error: string): void {\n const response: ErrorResponse = { id, type, success: false, error };\n port.postMessage(response);\n}\n\n/**\n * Handle INIT request - register chain configs (instances are lazy).\n */\nasync function handleInit(request: InitRequest): Promise<void> {\n const { id, type, payload } = request;\n try {\n for (const chain of payload.chains) {\n configs.set(chain.id, chain);\n }\n sendSuccess(id, type, { initialized: true });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\n/** Coerce a boolean to bigint for numeric FHE types. */\nfunction toBigInt(value: bigint | boolean): bigint {\n return typeof value === \"boolean\" ? (value ? 1n : 0n) : value;\n}\n\nfunction unreachableFheType(_: never): never {\n throw new Error(\"Unsupported FHE type\");\n}\n\nasync function handleEncrypt(request: EncryptRequest): Promise<void> {\n const { id, type, payload } = request;\n const { values, contractAddress, userAddress } = payload;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const input = instance.createEncryptedInput(contractAddress, userAddress);\n\n for (const entry of values) {\n const { value, type: fheType } = entry;\n switch (fheType) {\n case \"ebool\":\n input.addBool(typeof value === \"boolean\" ? value : value !== 0n);\n break;\n case \"euint8\":\n input.add8(toBigInt(value));\n break;\n case \"euint16\":\n input.add16(toBigInt(value));\n break;\n case \"euint32\":\n input.add32(toBigInt(value));\n break;\n case \"euint64\":\n input.add64(toBigInt(value));\n break;\n case \"euint128\":\n input.add128(toBigInt(value));\n break;\n case \"euint256\":\n input.add256(toBigInt(value));\n break;\n case \"eaddress\":\n input.addAddress(value);\n break;\n default:\n unreachableFheType(fheType);\n }\n }\n\n const encrypted = await input.encrypt();\n\n const response: EncryptResponseData = {\n handles: encrypted.handles,\n inputProof: encrypted.inputProof,\n };\n\n const transferList: Transferable[] = [\n encrypted.inputProof.buffer as ArrayBuffer,\n ...encrypted.handles.map((h) => h.buffer as ArrayBuffer),\n ];\n\n sendSuccess(id, type, response, transferList);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleUserDecrypt(request: UserDecryptRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const handleContractPairs = payload.encryptedValues.map((encryptedValue) => ({\n handle: encryptedValue,\n contractAddress: payload.contractAddress,\n }));\n\n const result = await instance.userDecrypt(\n handleContractPairs,\n unprefixHex(payload.privateKey),\n unprefixHex(payload.publicKey),\n payload.signature,\n payload.signedContractAddresses,\n payload.signerAddress,\n payload.startTimestamp,\n payload.durationDays,\n );\n\n const response: UserDecryptResponseData = { clearValues: result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handlePublicDecrypt(request: PublicDecryptRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = await instance.publicDecrypt(payload.encryptedValues);\n\n const response: PublicDecryptResponseData = { ...result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleGenerateKeypair(request: GenerateKeypairRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const keypair = instance.generateKeypair();\n\n const response: GenerateKeypairResponseData = {\n publicKey: prefixHex(keypair.publicKey),\n privateKey: prefixHex(keypair.privateKey),\n };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleCreateEIP712(request: CreateEIP712Request): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const eip712 = instance.createEIP712(\n unprefixHex(payload.publicKey),\n payload.contractAddresses,\n payload.startTimestamp,\n payload.durationDays,\n );\n\n sendSuccess(id, type, eip712);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleCreateDelegatedEIP712(request: CreateDelegatedEIP712Request): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = instance.createDelegatedUserDecryptEIP712(\n unprefixHex(payload.publicKey),\n payload.contractAddresses,\n payload.delegatorAddress,\n payload.startTimestamp,\n payload.durationDays,\n );\n\n sendSuccess(id, type, result);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleDelegatedUserDecrypt(request: DelegatedUserDecryptRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const handleContractPairs = payload.encryptedValues.map((encryptedValue) => ({\n handle: encryptedValue,\n contractAddress: payload.contractAddress,\n }));\n\n const result = await instance.delegatedUserDecrypt(\n handleContractPairs,\n unprefixHex(payload.privateKey),\n unprefixHex(payload.publicKey),\n payload.signature,\n payload.signedContractAddresses,\n payload.delegatorAddress,\n payload.delegateAddress,\n payload.startTimestamp,\n payload.durationDays,\n );\n\n const response: DelegatedUserDecryptResponseData = { clearValues: result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleRequestZKProofVerification(\n request: RequestZKProofVerificationRequest,\n): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = await instance.requestZKProofVerification(payload.zkProof);\n\n const transferList: Transferable[] = [\n result.inputProof.buffer as ArrayBuffer,\n ...result.handles.map((h) => h.buffer as ArrayBuffer),\n ];\n\n sendSuccess(id, type, result, transferList);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleGetPublicKey(request: GetPublicKeyRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = instance.getPublicKey();\n\n const response: GetPublicKeyResponseData = { result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleGetPublicParams(request: GetPublicParamsRequest): Promise<void> {\n const { id, type, payload } = request;\n\n try {\n const instance = await getInstance(payload.chainId);\n\n const result = instance.getPublicParams(\n // oxlint-disable-next-line typescript-eslint/consistent-type-imports -- SDK loaded dynamically\n payload.bits as keyof import(\"@zama-fhe/relayer-sdk/node\").PublicParams<Uint8Array>,\n );\n\n const response: GetPublicParamsResponseData = { result };\n\n sendSuccess(id, type, response);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(id, type, message);\n }\n}\n\nasync function handleMessage(request: WorkerRequest): Promise<void> {\n try {\n switch (request.type) {\n case \"INIT\":\n await handleInit(request);\n break;\n case \"ENCRYPT\":\n await handleEncrypt(request);\n break;\n case \"USER_DECRYPT\":\n await handleUserDecrypt(request);\n break;\n case \"PUBLIC_DECRYPT\":\n await handlePublicDecrypt(request);\n break;\n case \"GENERATE_KEYPAIR\":\n await handleGenerateKeypair(request);\n break;\n case \"CREATE_EIP712\":\n await handleCreateEIP712(request);\n break;\n case \"CREATE_DELEGATED_EIP712\":\n await handleCreateDelegatedEIP712(request);\n break;\n case \"DELEGATED_USER_DECRYPT\":\n await handleDelegatedUserDecrypt(request);\n break;\n case \"REQUEST_ZK_PROOF_VERIFICATION\":\n await handleRequestZKProofVerification(request);\n break;\n case \"GET_PUBLIC_KEY\":\n await handleGetPublicKey(request);\n break;\n case \"GET_PUBLIC_PARAMS\":\n await handleGetPublicParams(request);\n break;\n default:\n throw new Error(`Unknown request type: ${(request as WorkerRequest).type}`);\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n sendError(request.id, request.type, message);\n }\n}\n\nport.on(\"message\", (request: WorkerRequest) => {\n void handleMessage(request);\n});\n"],"mappings":"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"}
@@ -240,9 +240,7 @@
240
240
  for (const chain of payload.chains) configs.set(chain.id, chain);
241
241
  sendSuccess(id, type, { initialized: true });
242
242
  } catch (error) {
243
- const message = error instanceof Error ? error.message : String(error);
244
- console.error("[Worker] Init error:", message);
245
- sendError(id, type, message);
243
+ sendError(id, type, error instanceof Error ? error.message : String(error));
246
244
  }
247
245
  }
248
246
  /** Coerce a boolean to bigint for numeric FHE types. */
@@ -297,10 +295,7 @@
297
295
  inputProof: encrypted.inputProof
298
296
  }, [encrypted.inputProof.buffer, ...encrypted.handles.map((h) => h.buffer)]);
299
297
  } catch (error) {
300
- const message = error instanceof Error ? error.message : String(error);
301
- const statusCode = extractHttpStatus(error);
302
- console.error("[Worker] Encrypt error:", message);
303
- sendError(id, type, message, statusCode);
298
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
304
299
  }
305
300
  }
306
301
  /**
@@ -316,10 +311,7 @@
316
311
  }));
317
312
  sendSuccess(id, type, { clearValues: await instance.userDecrypt(handleContractPairs, unprefixHex(payload.privateKey), unprefixHex(payload.publicKey), payload.signature, payload.signedContractAddresses, payload.signerAddress, payload.startTimestamp, payload.durationDays) });
318
313
  } catch (error) {
319
- const message = error instanceof Error ? error.message : String(error);
320
- const statusCode = extractHttpStatus(error);
321
- console.error("[Worker] UserDecrypt error:", message);
322
- sendError(id, type, message, statusCode);
314
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
323
315
  }
324
316
  }
325
317
  /**
@@ -345,10 +337,7 @@
345
337
  try {
346
338
  sendSuccess(id, type, { ...await (await getInstance(payload.chainId)).publicDecrypt(payload.encryptedValues) });
347
339
  } catch (error) {
348
- const message = error instanceof Error ? error.message : String(error);
349
- const statusCode = extractHttpStatus(error);
350
- console.error("[Worker] PublicDecrypt error:", message);
351
- sendError(id, type, message, statusCode);
340
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
352
341
  }
353
342
  }
354
343
  /**
@@ -363,9 +352,7 @@
363
352
  privateKey: prefixHex(keypair.privateKey)
364
353
  });
365
354
  } catch (error) {
366
- const message = error instanceof Error ? error.message : String(error);
367
- console.error("[Worker] GenerateKeypair error:", message);
368
- sendError(id, type, message);
355
+ sendError(id, type, error instanceof Error ? error.message : String(error));
369
356
  }
370
357
  }
371
358
  /**
@@ -376,9 +363,7 @@
376
363
  try {
377
364
  sendSuccess(id, type, (await getInstance(payload.chainId)).createEIP712(unprefixHex(payload.publicKey), payload.contractAddresses, payload.startTimestamp, payload.durationDays));
378
365
  } catch (error) {
379
- const message = error instanceof Error ? error.message : String(error);
380
- console.error("[Worker] CreateEIP712 error:", message);
381
- sendError(id, type, message);
366
+ sendError(id, type, error instanceof Error ? error.message : String(error));
382
367
  }
383
368
  }
384
369
  /**
@@ -389,9 +374,7 @@
389
374
  try {
390
375
  sendSuccess(id, type, (await getInstance(payload.chainId)).createDelegatedUserDecryptEIP712(unprefixHex(payload.publicKey), payload.contractAddresses, payload.delegatorAddress, payload.startTimestamp, payload.durationDays));
391
376
  } catch (error) {
392
- const message = error instanceof Error ? error.message : String(error);
393
- console.error("[Worker] CreateDelegatedEIP712 error:", message);
394
- sendError(id, type, message);
377
+ sendError(id, type, error instanceof Error ? error.message : String(error));
395
378
  }
396
379
  }
397
380
  /**
@@ -407,10 +390,7 @@
407
390
  }));
408
391
  sendSuccess(id, type, { clearValues: await instance.delegatedUserDecrypt(handleContractPairs, unprefixHex(payload.privateKey), unprefixHex(payload.publicKey), payload.signature, payload.signedContractAddresses, payload.delegatorAddress, payload.delegateAddress, payload.startTimestamp, payload.durationDays) });
409
392
  } catch (error) {
410
- const message = error instanceof Error ? error.message : String(error);
411
- const statusCode = extractHttpStatus(error);
412
- console.error("[Worker] DelegatedUserDecrypt error:", message);
413
- sendError(id, type, message, statusCode);
393
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
414
394
  }
415
395
  }
416
396
  /**
@@ -422,10 +402,7 @@
422
402
  const result = await (await getInstance(payload.chainId)).requestZKProofVerification(payload.zkProof);
423
403
  sendSuccess(id, type, result, [result.inputProof.buffer, ...result.handles.map((h) => h.buffer)]);
424
404
  } catch (error) {
425
- const message = error instanceof Error ? error.message : String(error);
426
- const statusCode = extractHttpStatus(error);
427
- console.error("[Worker] RequestZKProofVerification error:", message);
428
- sendError(id, type, message, statusCode);
405
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
429
406
  }
430
407
  }
431
408
  /**
@@ -436,10 +413,7 @@
436
413
  try {
437
414
  sendSuccess(id, type, { result: (await getInstance(payload.chainId)).getPublicKey() });
438
415
  } catch (error) {
439
- const message = error instanceof Error ? error.message : String(error);
440
- const statusCode = extractHttpStatus(error);
441
- console.error("[Worker] GetPublicKey error:", message);
442
- sendError(id, type, message, statusCode);
416
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
443
417
  }
444
418
  }
445
419
  /**
@@ -450,10 +424,7 @@
450
424
  try {
451
425
  sendSuccess(id, type, { result: (await getInstance(payload.chainId)).getPublicParams(payload.bits) });
452
426
  } catch (error) {
453
- const message = error instanceof Error ? error.message : String(error);
454
- const statusCode = extractHttpStatus(error);
455
- console.error("[Worker] GetPublicParams error:", message);
456
- sendError(id, type, message, statusCode);
427
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
457
428
  }
458
429
  }
459
430
  /**
@@ -507,7 +478,7 @@
507
478
  case "GET_PUBLIC_PARAMS":
508
479
  await handleGetPublicParams(request);
509
480
  break;
510
- default: console.error("[Worker] Unknown request type:", request.type);
481
+ default: throw new Error(`Unknown request type: ${request.type}`);
511
482
  }
512
483
  } catch (error) {
513
484
  const message = error instanceof Error ? error.message : String(error);
@@ -240,9 +240,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
240
240
  for (const chain of payload.chains) configs.set(chain.id, chain);
241
241
  sendSuccess(id, type, { initialized: true });
242
242
  } catch (error) {
243
- const message = error instanceof Error ? error.message : String(error);
244
- console.error("[Worker] Init error:", message);
245
- sendError(id, type, message);
243
+ sendError(id, type, error instanceof Error ? error.message : String(error));
246
244
  }
247
245
  }
248
246
  /** Coerce a boolean to bigint for numeric FHE types. */
@@ -297,10 +295,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
297
295
  inputProof: encrypted.inputProof
298
296
  }, [encrypted.inputProof.buffer, ...encrypted.handles.map((h) => h.buffer)]);
299
297
  } catch (error) {
300
- const message = error instanceof Error ? error.message : String(error);
301
- const statusCode = extractHttpStatus(error);
302
- console.error("[Worker] Encrypt error:", message);
303
- sendError(id, type, message, statusCode);
298
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
304
299
  }
305
300
  }
306
301
  /**
@@ -316,10 +311,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
316
311
  }));
317
312
  sendSuccess(id, type, { clearValues: await instance.userDecrypt(handleContractPairs, unprefixHex(payload.privateKey), unprefixHex(payload.publicKey), payload.signature, payload.signedContractAddresses, payload.signerAddress, payload.startTimestamp, payload.durationDays) });
318
313
  } catch (error) {
319
- const message = error instanceof Error ? error.message : String(error);
320
- const statusCode = extractHttpStatus(error);
321
- console.error("[Worker] UserDecrypt error:", message);
322
- sendError(id, type, message, statusCode);
314
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
323
315
  }
324
316
  }
325
317
  /**
@@ -345,10 +337,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
345
337
  try {
346
338
  sendSuccess(id, type, { ...await (await getInstance(payload.chainId)).publicDecrypt(payload.encryptedValues) });
347
339
  } catch (error) {
348
- const message = error instanceof Error ? error.message : String(error);
349
- const statusCode = extractHttpStatus(error);
350
- console.error("[Worker] PublicDecrypt error:", message);
351
- sendError(id, type, message, statusCode);
340
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
352
341
  }
353
342
  }
354
343
  /**
@@ -363,9 +352,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
363
352
  privateKey: prefixHex(keypair.privateKey)
364
353
  });
365
354
  } catch (error) {
366
- const message = error instanceof Error ? error.message : String(error);
367
- console.error("[Worker] GenerateKeypair error:", message);
368
- sendError(id, type, message);
355
+ sendError(id, type, error instanceof Error ? error.message : String(error));
369
356
  }
370
357
  }
371
358
  /**
@@ -376,9 +363,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
376
363
  try {
377
364
  sendSuccess(id, type, (await getInstance(payload.chainId)).createEIP712(unprefixHex(payload.publicKey), payload.contractAddresses, payload.startTimestamp, payload.durationDays));
378
365
  } catch (error) {
379
- const message = error instanceof Error ? error.message : String(error);
380
- console.error("[Worker] CreateEIP712 error:", message);
381
- sendError(id, type, message);
366
+ sendError(id, type, error instanceof Error ? error.message : String(error));
382
367
  }
383
368
  }
384
369
  /**
@@ -389,9 +374,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
389
374
  try {
390
375
  sendSuccess(id, type, (await getInstance(payload.chainId)).createDelegatedUserDecryptEIP712(unprefixHex(payload.publicKey), payload.contractAddresses, payload.delegatorAddress, payload.startTimestamp, payload.durationDays));
391
376
  } catch (error) {
392
- const message = error instanceof Error ? error.message : String(error);
393
- console.error("[Worker] CreateDelegatedEIP712 error:", message);
394
- sendError(id, type, message);
377
+ sendError(id, type, error instanceof Error ? error.message : String(error));
395
378
  }
396
379
  }
397
380
  /**
@@ -407,10 +390,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
407
390
  }));
408
391
  sendSuccess(id, type, { clearValues: await instance.delegatedUserDecrypt(handleContractPairs, unprefixHex(payload.privateKey), unprefixHex(payload.publicKey), payload.signature, payload.signedContractAddresses, payload.delegatorAddress, payload.delegateAddress, payload.startTimestamp, payload.durationDays) });
409
392
  } catch (error) {
410
- const message = error instanceof Error ? error.message : String(error);
411
- const statusCode = extractHttpStatus(error);
412
- console.error("[Worker] DelegatedUserDecrypt error:", message);
413
- sendError(id, type, message, statusCode);
393
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
414
394
  }
415
395
  }
416
396
  /**
@@ -422,10 +402,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
422
402
  const result = await (await getInstance(payload.chainId)).requestZKProofVerification(payload.zkProof);
423
403
  sendSuccess(id, type, result, [result.inputProof.buffer, ...result.handles.map((h) => h.buffer)]);
424
404
  } catch (error) {
425
- const message = error instanceof Error ? error.message : String(error);
426
- const statusCode = extractHttpStatus(error);
427
- console.error("[Worker] RequestZKProofVerification error:", message);
428
- sendError(id, type, message, statusCode);
405
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
429
406
  }
430
407
  }
431
408
  /**
@@ -436,10 +413,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
436
413
  try {
437
414
  sendSuccess(id, type, { result: (await getInstance(payload.chainId)).getPublicKey() });
438
415
  } catch (error) {
439
- const message = error instanceof Error ? error.message : String(error);
440
- const statusCode = extractHttpStatus(error);
441
- console.error("[Worker] GetPublicKey error:", message);
442
- sendError(id, type, message, statusCode);
416
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
443
417
  }
444
418
  }
445
419
  /**
@@ -450,10 +424,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
450
424
  try {
451
425
  sendSuccess(id, type, { result: (await getInstance(payload.chainId)).getPublicParams(payload.bits) });
452
426
  } catch (error) {
453
- const message = error instanceof Error ? error.message : String(error);
454
- const statusCode = extractHttpStatus(error);
455
- console.error("[Worker] GetPublicParams error:", message);
456
- sendError(id, type, message, statusCode);
427
+ sendError(id, type, error instanceof Error ? error.message : String(error), extractHttpStatus(error));
457
428
  }
458
429
  }
459
430
  /**
@@ -507,7 +478,7 @@ import{t as e}from"../indexeddb-storage-CB8-zXAn.js";import{a as t,o as n,r}from
507
478
  case "GET_PUBLIC_PARAMS":
508
479
  await handleGetPublicParams(request);
509
480
  break;
510
- default: console.error("[Worker] Unknown request type:", request.type);
481
+ default: throw new Error(\`Unknown request type: \${request.type}\`);
511
482
  }
512
483
  } catch (error) {
513
484
  const message = error instanceof Error ? error.message : String(error);
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["#config","#worker","#artifactCache","#artifactStorage","#refreshCsrfToken","#getArtifactCache","workerFilename","workerCode"],"sources":["../../../src/relayer/relayer-web.ts","../../../src/worker/browser-extension.ts","../../../src/worker/worker.client.ts","../../../src/config/web.ts"],"sourcesContent":["import type {\n InputProofBytesType,\n KmsDelegatedUserDecryptEIP712Type,\n ZKProofLike,\n} from \"@zama-fhe/relayer-sdk/bundle\";\nimport { toHex } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport { IndexedDBStorage } from \"../storage/indexeddb-storage\";\nimport type { GenericStorage } from \"../types\";\nimport type { RelayerWorkerClient } from \"../worker/worker.client\";\nimport type { FheChain } from \"../chains/types\";\nimport type { TransportKeyPair } from \"../credentials/types\";\nimport { BaseRelayer } from \"./base-relayer\";\nimport { FheArtifactCache } from \"./fhe-artifact-cache\";\nimport type { RelayerSDK } from \"./relayer-sdk\";\nimport type {\n ClearValue,\n DelegatedUserDecryptParams,\n EIP712TypedData,\n EncryptParams,\n EncryptResult,\n EncryptedValue,\n FheEncryptionKey,\n PublicDecryptResult,\n PublicParamsData,\n RelayerWebConfig,\n UserDecryptParams,\n} from \"./relayer-sdk.types\";\nimport { withRetry } from \"./relayer-utils\";\n\n/**\n * Pinned relayer SDK version used for the WASM CDN bundle.\n * Update this when upgrading @zama-fhe/relayer-sdk, and keep the\n * peerDependencies range in package.json in sync (~x.y.z).\n */\nexport const RELAYER_SDK_VERSION = \"0.4.4\";\nexport const CDN_URL = `https://cdn.zama.org/relayer-sdk-js/${RELAYER_SDK_VERSION}/relayer-sdk-js.umd.cjs`;\n/** SHA-384 hex digest of the pinned CDN bundle for integrity verification. */\nexport const CDN_INTEGRITY =\n \"a50426aae8440e802102c8674dd8451f34fe79352d5e2cc6b89d9f1aa340296176c2ee33d9aa4657752f8ca96f74f921\";\n\n/**\n * RelayerWeb — single-chain browser encryption/decryption layer.\n * The worker is injected at construction time; the relayer does not own its lifecycle.\n */\nexport class RelayerWeb extends BaseRelayer implements RelayerSDK, Disposable {\n #artifactCache: FheArtifactCache | null = null;\n #artifactStorage: GenericStorage | null = null;\n readonly #config: RelayerWebConfig;\n\n constructor(config: RelayerWebConfig) {\n super();\n this.#config = config;\n }\n\n protected get chain(): FheChain {\n return this.#config.chain;\n }\n\n protected async init(): Promise<void> {\n await this.#worker.initWorker();\n }\n\n get #worker(): RelayerWorkerClient {\n return this.#config.worker;\n }\n\n #getArtifactCache(): FheArtifactCache {\n if (!this.#artifactCache) {\n if (!this.#artifactStorage) {\n this.#artifactStorage =\n this.#config.fheArtifactStorage ??\n new IndexedDBStorage(\"FheArtifactCache\", 1, \"artifacts\");\n }\n this.#artifactCache = new FheArtifactCache({\n storage: this.#artifactStorage,\n chainId: this.chain.id,\n relayerUrl: this.chain.relayerUrl,\n ttl: this.#config.fheArtifactCacheTTL,\n logger: this.#config.logger,\n });\n }\n return this.#artifactCache;\n }\n\n /**\n * Terminate clears the artifact cache only.\n * The worker is externally owned — the relayer does not terminate it.\n */\n terminate(): void {\n this.#artifactCache = null;\n this.resetInit();\n }\n\n /** Calls {@link terminate}. */\n [Symbol.dispose](): void {\n this.terminate();\n }\n\n /**\n * Refresh the CSRF token in the worker.\n * Call this before making authenticated network requests.\n */\n async #refreshCsrfToken(): Promise<void> {\n const token = this.#config.security?.getCsrfToken?.() ?? \"\";\n if (token) {\n await this.#worker.updateCsrf(token);\n }\n }\n\n /**\n * Generate a transport key pair (ML-KEM public + private key) used for user-decryption.\n */\n async generateTransportKeyPair(): Promise<TransportKeyPair> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const result = await this.#worker.generateKeypair({ chainId });\n return {\n publicKey: result.publicKey,\n privateKey: result.privateKey,\n };\n }\n\n /**\n * Create EIP712 typed data for user decryption authorization.\n */\n async createEIP712(\n publicKey: Hex,\n contractAddresses: Address[],\n startTimestamp: number,\n durationDays = 7,\n ): Promise<EIP712TypedData> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return this.#worker.createEIP712({\n chainId,\n publicKey,\n contractAddresses,\n startTimestamp,\n durationDays,\n });\n }\n\n /**\n * Encrypt values for use in smart contract calls.\n * Each value must specify its FHE type (ebool, euint8–256, eaddress).\n */\n async encrypt(params: EncryptParams): Promise<EncryptResult> {\n const { values, contractAddress, userAddress } = params;\n await this.ensureInit();\n const chainId = this.chain.id;\n\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.encrypt({\n chainId,\n values,\n contractAddress,\n userAddress,\n });\n return {\n encryptedValues: result.handles.map((handle) => toHex(handle)),\n inputProof: toHex(result.inputProof),\n };\n });\n }\n\n /**\n * Decrypt ciphertexts using user's private key.\n * Requires a valid EIP712 signature.\n */\n async userDecrypt(\n params: UserDecryptParams,\n ): Promise<Readonly<Record<EncryptedValue, ClearValue>>> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.userDecrypt({ chainId, ...params });\n return result.clearValues;\n });\n }\n\n /**\n * Public decryption - no authorization needed.\n * Used for publicly visible encrypted values.\n */\n async publicDecrypt(encryptedValues: EncryptedValue[]): Promise<PublicDecryptResult> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.publicDecrypt({\n chainId,\n encryptedValues,\n });\n return {\n clearValues: result.clearValues,\n abiEncodedClearValues: result.abiEncodedClearValues,\n decryptionProof: result.decryptionProof,\n };\n });\n }\n\n /**\n * Create EIP712 typed data for delegated user decryption authorization.\n */\n async createDelegatedUserDecryptEIP712(\n publicKey: Hex,\n contractAddresses: Address[],\n delegatorAddress: Address,\n startTimestamp: number,\n durationDays = 7,\n ): Promise<KmsDelegatedUserDecryptEIP712Type> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return this.#worker.createDelegatedUserDecryptEIP712({\n chainId,\n publicKey,\n contractAddresses,\n delegatorAddress,\n startTimestamp,\n durationDays,\n });\n }\n\n /**\n * Decrypt ciphertexts via delegation.\n * Requires a valid EIP712 signature from the delegator.\n */\n async delegatedUserDecrypt(\n params: DelegatedUserDecryptParams,\n ): Promise<Readonly<Record<EncryptedValue, ClearValue>>> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.delegatedUserDecrypt({\n chainId,\n ...params,\n });\n return result.clearValues;\n });\n }\n\n /**\n * Submit a ZK proof to the relayer for verification.\n */\n async requestZKProofVerification(zkProof: ZKProofLike): Promise<InputProofBytesType> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n return this.#worker.requestZKProofVerification({ chainId, zkProof });\n });\n }\n\n /**\n * Fetch the network's FHE encryption key (ID + bytes).\n * When storage is configured, the result is cached persistently.\n */\n async fetchFheEncryptionKeyBytes(): Promise<FheEncryptionKey | null> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const artifactCache = this.#getArtifactCache();\n return artifactCache.fetchFheEncryptionKeyBytes(\n async () => (await this.#worker.getPublicKey({ chainId })).result,\n );\n }\n\n /**\n * Get public parameters for encryption capacity.\n * When storage is configured, the result is cached persistently.\n */\n async getPublicParams(bits: number): Promise<PublicParamsData | null> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const artifactCache = this.#getArtifactCache();\n return artifactCache.getPublicParams(\n bits,\n async () => (await this.#worker.getPublicParams({ chainId, bits })).result,\n );\n }\n}\n","import { assertFunctionProp, assertObject, assertStringProp } from \"../utils/assertions\";\n\n/**\n * Subset of the WebExtensions `runtime` API used by the SDK.\n * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime\n */\nexport interface BrowserExtensionRuntime {\n /** The ID of the extension. */\n id: string;\n /** Convert a relative path within the extension to a fully-qualified URL. */\n getURL: (path: string) => string;\n}\n\nfunction isValidRuntime(runtime: unknown): runtime is BrowserExtensionRuntime {\n try {\n assertObject(runtime, \"runtime\");\n assertStringProp(runtime, \"id\", \"runtime.id\");\n assertFunctionProp<\"getURL\", (path: string) => string>(runtime, \"getURL\", \"runtime.getURL\");\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Return the browser extension runtime object, or `undefined` outside extensions.\n * Works across Chrome/Edge (`chrome.runtime`) and Firefox/Safari (`browser.runtime`).\n * Extensions have restricted CSP that blocks `blob:` URLs, so callers use\n * this to detect the environment and resolve file URLs via `runtime.getURL`.\n */\nexport function getBrowserExtensionRuntime(): BrowserExtensionRuntime | undefined {\n const g = globalThis as unknown as Record<string, unknown>;\n for (const ns of [g.chrome, g.browser]) {\n try {\n assertObject(ns, \"ns\");\n if (isValidRuntime(ns.runtime)) {\n return ns.runtime;\n }\n } catch {\n continue;\n }\n }\n return undefined;\n}\n","import type { FheChain } from \"../chains/types\";\nimport type {\n GenericLogger,\n UpdateCsrfResponseData,\n WorkerEnv,\n WorkerRequest,\n WorkerRequestType,\n WorkerResponse,\n} from \"./worker.types\";\nimport { BaseWorkerClient } from \"./worker.base-client\";\nimport { getBrowserExtensionRuntime } from \"./browser-extension\";\nimport { default as workerCode, filename as workerFilename } from \"./relayer-sdk.worker.ts?iife\";\n\n/** Configuration for the worker client */\nexport interface WorkerClientConfig {\n cdnUrl: string;\n chains: FheChain[];\n csrfToken: string;\n /** Expected SHA-384 hex digest of the CDN bundle for integrity verification. */\n integrity?: string;\n /** Optional logger for tracing worker request lifecycle. */\n logger?: GenericLogger;\n /** Number of WASM threads for parallel FHE operations (passed to `initSDK({ thread })`). */\n thread?: number;\n}\n\n/**\n * Client for communicating with the RelayerSDK Web Worker.\n * Provides a promise-based API for FHE operations.\n */\nexport class RelayerWorkerClient extends BaseWorkerClient<Worker, WorkerClientConfig> {\n protected readonly env: WorkerEnv = \"web\";\n\n constructor(config: WorkerClientConfig) {\n super(config, config.logger);\n }\n\n protected createWorker(): Worker {\n const runtime = getBrowserExtensionRuntime();\n if (runtime) {\n return new Worker(runtime.getURL(workerFilename));\n }\n const blobUrl = URL.createObjectURL(new Blob([workerCode], { type: \"application/javascript\" }));\n try {\n return new Worker(blobUrl);\n } finally {\n URL.revokeObjectURL(blobUrl);\n }\n }\n\n protected wireEvents(worker: Worker): void {\n worker.onmessage = (event: MessageEvent<WorkerResponse<unknown>>) =>\n this.handleResponse(event.data);\n worker.onerror = (event: ErrorEvent) => this.handleWorkerError(event.message);\n worker.onmessageerror = () => this.handleWorkerMessageError();\n }\n\n protected postMessage(worker: Worker, request: WorkerRequest): void {\n worker.postMessage(request);\n }\n\n protected terminateWorker(worker: Worker): void {\n worker.terminate();\n }\n\n protected generateRequestId(): string {\n return crypto.randomUUID();\n }\n\n protected getInitPayload(): {\n type: WorkerRequestType;\n payload: WorkerRequest[\"payload\"];\n } {\n // Explicitly construct the payload from serializable fields only.\n // Functions (e.g. `logger`) cannot be cloned by the structured clone\n // algorithm used by `worker.postMessage()`.\n const { cdnUrl, chains, csrfToken, integrity, thread } = this.config;\n return {\n type: \"INIT\",\n payload: { env: \"web\" as const, cdnUrl, chains, csrfToken, integrity, thread },\n };\n }\n\n /**\n * Update the CSRF token in the worker.\n * Call this before making authenticated requests to ensure the token is fresh.\n */\n async updateCsrf(csrfToken: string): Promise<void> {\n await this.sendRequest<UpdateCsrfResponseData>(\"UPDATE_CSRF\", {\n csrfToken,\n });\n }\n}\n","import { z } from \"zod/mini\";\nimport { CDN_INTEGRITY, CDN_URL, RelayerWeb } from \"../relayer/relayer-web\";\nimport { parseConfiguration } from \"../validation\";\nimport { RelayerWorkerClient } from \"../worker/worker.client\";\nimport type { WebRelayerConfig, WebRelayerOptions } from \"./types\";\n\nconst WebRelayerOptionsSchema = z.object({\n threads: z.optional(z.int().check(z.positive())),\n fheArtifactCacheTTL: z.optional(z.int().check(z.nonnegative())),\n});\n\n/**\n * Browser relayer — routes to RelayerWeb (Web Worker + WASM).\n *\n * @param options - Worker options (threads, security, logger, storage).\n *\n * @example\n * ```ts\n * relayers: {\n * [sepolia.id]: web(),\n * [mainnet.id]: web({ threads: 4 }),\n * }\n * ```\n */\nexport function web(options?: WebRelayerOptions): WebRelayerConfig {\n if (options !== undefined) {\n parseConfiguration(WebRelayerOptionsSchema, options);\n }\n return {\n type: \"web\",\n createWorker: (chains) =>\n new RelayerWorkerClient({\n cdnUrl: CDN_URL,\n chains,\n csrfToken: options?.security?.getCsrfToken?.() ?? \"\",\n integrity: options?.security?.integrityCheck === false ? undefined : CDN_INTEGRITY,\n logger: options?.logger,\n thread: options?.threads,\n }),\n createRelayer: (chain, worker) => new RelayerWeb({ chain, worker, ...options }),\n };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["#config","#worker","#artifactCache","#artifactStorage","#refreshCsrfToken","#getArtifactCache","workerFilename","workerCode"],"sources":["../../../src/relayer/relayer-web.ts","../../../src/worker/browser-extension.ts","../../../src/worker/worker.client.ts","../../../src/config/web.ts"],"sourcesContent":["import type {\n InputProofBytesType,\n KmsDelegatedUserDecryptEIP712Type,\n ZKProofLike,\n} from \"@zama-fhe/relayer-sdk/bundle\";\nimport { toHex } from \"viem\";\nimport type { Address, Hex } from \"viem\";\nimport { IndexedDBStorage } from \"../storage/indexeddb-storage\";\nimport type { GenericStorage } from \"../types\";\nimport type { RelayerWorkerClient } from \"../worker/worker.client\";\nimport type { FheChain } from \"../chains/types\";\nimport type { TransportKeyPair } from \"../credentials/types\";\nimport { BaseRelayer } from \"./base-relayer\";\nimport { FheArtifactCache } from \"./fhe-artifact-cache\";\nimport type { RelayerSDK } from \"./relayer-sdk\";\nimport type {\n ClearValue,\n DelegatedUserDecryptParams,\n EIP712TypedData,\n EncryptParams,\n EncryptResult,\n EncryptedValue,\n FheEncryptionKey,\n PublicDecryptResult,\n PublicParamsData,\n RelayerWebConfig,\n UserDecryptParams,\n} from \"./relayer-sdk.types\";\nimport { withRetry } from \"./relayer-utils\";\n\n/**\n * Pinned relayer SDK version used for the WASM CDN bundle.\n * Update this when upgrading @zama-fhe/relayer-sdk, and keep the\n * peerDependencies range in package.json in sync (~x.y.z).\n */\nexport const RELAYER_SDK_VERSION = \"0.4.4\";\nexport const CDN_URL = `https://cdn.zama.org/relayer-sdk-js/${RELAYER_SDK_VERSION}/relayer-sdk-js.umd.cjs`;\n/** SHA-384 hex digest of the pinned CDN bundle for integrity verification. */\nexport const CDN_INTEGRITY =\n \"a50426aae8440e802102c8674dd8451f34fe79352d5e2cc6b89d9f1aa340296176c2ee33d9aa4657752f8ca96f74f921\";\n\n/**\n * RelayerWeb — single-chain browser encryption/decryption layer.\n * The worker is injected at construction time; the relayer does not own its lifecycle.\n */\nexport class RelayerWeb extends BaseRelayer implements RelayerSDK, Disposable {\n #artifactCache: FheArtifactCache | null = null;\n #artifactStorage: GenericStorage | null = null;\n readonly #config: RelayerWebConfig;\n\n constructor(config: RelayerWebConfig) {\n super();\n this.#config = config;\n }\n\n protected get chain(): FheChain {\n return this.#config.chain;\n }\n\n protected async init(): Promise<void> {\n await this.#worker.initWorker();\n }\n\n get #worker(): RelayerWorkerClient {\n return this.#config.worker;\n }\n\n #getArtifactCache(): FheArtifactCache {\n if (!this.#artifactCache) {\n if (!this.#artifactStorage) {\n this.#artifactStorage =\n this.#config.fheArtifactStorage ??\n new IndexedDBStorage(\"FheArtifactCache\", 1, \"artifacts\");\n }\n this.#artifactCache = new FheArtifactCache({\n storage: this.#artifactStorage,\n chainId: this.chain.id,\n relayerUrl: this.chain.relayerUrl,\n ttl: this.#config.fheArtifactCacheTTL,\n logger: this.#config.logger,\n });\n }\n return this.#artifactCache;\n }\n\n /**\n * Terminate clears the artifact cache only.\n * The worker is externally owned — the relayer does not terminate it.\n */\n terminate(): void {\n this.#artifactCache = null;\n this.resetInit();\n }\n\n /** Calls {@link terminate}. */\n [Symbol.dispose](): void {\n this.terminate();\n }\n\n /**\n * Refresh the CSRF token in the worker.\n * Call this before making authenticated network requests.\n */\n async #refreshCsrfToken(): Promise<void> {\n const token = this.#config.security?.getCsrfToken?.() ?? \"\";\n if (token) {\n await this.#worker.updateCsrf(token);\n }\n }\n\n /**\n * Generate a transport key pair (ML-KEM public + private key) used for user-decryption.\n */\n async generateTransportKeyPair(): Promise<TransportKeyPair> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const result = await this.#worker.generateKeypair({ chainId });\n return {\n publicKey: result.publicKey,\n privateKey: result.privateKey,\n };\n }\n\n /**\n * Create EIP712 typed data for user decryption authorization.\n */\n async createEIP712(\n publicKey: Hex,\n contractAddresses: Address[],\n startTimestamp: number,\n durationDays = 7,\n ): Promise<EIP712TypedData> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return this.#worker.createEIP712({\n chainId,\n publicKey,\n contractAddresses,\n startTimestamp,\n durationDays,\n });\n }\n\n /**\n * Encrypt values for use in smart contract calls.\n * Each value must specify its FHE type (ebool, euint8–256, eaddress).\n */\n async encrypt(params: EncryptParams): Promise<EncryptResult> {\n const { values, contractAddress, userAddress } = params;\n await this.ensureInit();\n const chainId = this.chain.id;\n\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.encrypt({\n chainId,\n values,\n contractAddress,\n userAddress,\n });\n return {\n encryptedValues: result.handles.map((handle) => toHex(handle)),\n inputProof: toHex(result.inputProof),\n };\n });\n }\n\n /**\n * Decrypt ciphertexts using user's private key.\n * Requires a valid EIP712 signature.\n */\n async userDecrypt(\n params: UserDecryptParams,\n ): Promise<Readonly<Record<EncryptedValue, ClearValue>>> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.userDecrypt({ chainId, ...params });\n return result.clearValues;\n });\n }\n\n /**\n * Public decryption - no authorization needed.\n * Used for publicly visible encrypted values.\n */\n async publicDecrypt(encryptedValues: EncryptedValue[]): Promise<PublicDecryptResult> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.publicDecrypt({\n chainId,\n encryptedValues,\n });\n return {\n clearValues: result.clearValues,\n abiEncodedClearValues: result.abiEncodedClearValues,\n decryptionProof: result.decryptionProof,\n };\n });\n }\n\n /**\n * Create EIP712 typed data for delegated user decryption authorization.\n */\n async createDelegatedUserDecryptEIP712(\n publicKey: Hex,\n contractAddresses: Address[],\n delegatorAddress: Address,\n startTimestamp: number,\n durationDays = 7,\n ): Promise<KmsDelegatedUserDecryptEIP712Type> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return this.#worker.createDelegatedUserDecryptEIP712({\n chainId,\n publicKey,\n contractAddresses,\n delegatorAddress,\n startTimestamp,\n durationDays,\n });\n }\n\n /**\n * Decrypt ciphertexts via delegation.\n * Requires a valid EIP712 signature from the delegator.\n */\n async delegatedUserDecrypt(\n params: DelegatedUserDecryptParams,\n ): Promise<Readonly<Record<EncryptedValue, ClearValue>>> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n const result = await this.#worker.delegatedUserDecrypt({\n chainId,\n ...params,\n });\n return result.clearValues;\n });\n }\n\n /**\n * Submit a ZK proof to the relayer for verification.\n */\n async requestZKProofVerification(zkProof: ZKProofLike): Promise<InputProofBytesType> {\n await this.ensureInit();\n const chainId = this.chain.id;\n return withRetry(async () => {\n await this.#refreshCsrfToken();\n return this.#worker.requestZKProofVerification({ chainId, zkProof });\n });\n }\n\n /**\n * Fetch the network's FHE encryption key (ID + bytes).\n * When storage is configured, the result is cached persistently.\n */\n async fetchFheEncryptionKeyBytes(): Promise<FheEncryptionKey | null> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const artifactCache = this.#getArtifactCache();\n return artifactCache.fetchFheEncryptionKeyBytes(\n async () => (await this.#worker.getPublicKey({ chainId })).result,\n );\n }\n\n /**\n * Get public parameters for encryption capacity.\n * When storage is configured, the result is cached persistently.\n */\n async getPublicParams(bits: number): Promise<PublicParamsData | null> {\n await this.ensureInit();\n const chainId = this.chain.id;\n const artifactCache = this.#getArtifactCache();\n return artifactCache.getPublicParams(\n bits,\n async () => (await this.#worker.getPublicParams({ chainId, bits })).result,\n );\n }\n}\n","import { assertFunctionProp, assertObject, assertStringProp } from \"../utils/assertions\";\n\n/**\n * Subset of the WebExtensions `runtime` API used by the SDK.\n * @see https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime\n */\nexport interface BrowserExtensionRuntime {\n /** The ID of the extension. */\n id: string;\n /** Convert a relative path within the extension to a fully-qualified URL. */\n getURL: (path: string) => string;\n}\n\nfunction isValidRuntime(runtime: unknown): runtime is BrowserExtensionRuntime {\n try {\n assertObject(runtime, \"runtime\");\n assertStringProp(runtime, \"id\", \"runtime.id\");\n assertFunctionProp<\"getURL\", (path: string) => string>(runtime, \"getURL\", \"runtime.getURL\");\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Return the browser extension runtime object, or `undefined` outside extensions.\n * Works across Chrome/Edge (`chrome.runtime`) and Firefox/Safari (`browser.runtime`).\n * Extensions have restricted CSP that blocks `blob:` URLs, so callers use\n * this to detect the environment and resolve file URLs via `runtime.getURL`.\n */\nexport function getBrowserExtensionRuntime(): BrowserExtensionRuntime | undefined {\n const g = globalThis as unknown as Record<string, unknown>;\n for (const ns of [g.chrome, g.browser]) {\n try {\n assertObject(ns, \"ns\");\n if (isValidRuntime(ns.runtime)) {\n return ns.runtime;\n }\n } catch {\n continue;\n }\n }\n return undefined;\n}\n","import type { FheChain } from \"../chains/types\";\nimport type {\n GenericLogger,\n UpdateCsrfResponseData,\n WorkerEnv,\n WorkerRequest,\n WorkerRequestType,\n WorkerResponse,\n} from \"./worker.types\";\nimport { BaseWorkerClient } from \"./worker.base-client\";\nimport { getBrowserExtensionRuntime } from \"./browser-extension\";\nimport { default as workerCode, filename as workerFilename } from \"./relayer-sdk.worker.ts?iife\";\n\n/** Configuration for the worker client */\nexport interface WorkerClientConfig {\n cdnUrl: string;\n chains: FheChain[];\n csrfToken: string;\n /** Expected SHA-384 hex digest of the CDN bundle for integrity verification. */\n integrity?: string;\n /** Optional logger for tracing worker request lifecycle. */\n logger?: GenericLogger;\n /** Number of WASM threads for parallel FHE operations (passed to `initSDK({ thread })`). */\n thread?: number;\n}\n\n/**\n * Client for communicating with the RelayerSDK Web Worker.\n * Provides a promise-based API for FHE operations.\n */\nexport class RelayerWorkerClient extends BaseWorkerClient<Worker, WorkerClientConfig> {\n protected readonly env: WorkerEnv = \"web\";\n\n constructor(config: WorkerClientConfig) {\n super(config, config.logger);\n }\n\n protected createWorker(): Worker {\n const runtime = getBrowserExtensionRuntime();\n if (runtime) {\n return new Worker(runtime.getURL(workerFilename));\n }\n const blobUrl = URL.createObjectURL(new Blob([workerCode], { type: \"application/javascript\" }));\n try {\n return new Worker(blobUrl);\n } finally {\n URL.revokeObjectURL(blobUrl);\n }\n }\n\n protected wireEvents(worker: Worker): void {\n worker.onmessage = (event: MessageEvent<WorkerResponse<unknown>>) =>\n this.handleResponse(event.data);\n worker.onerror = (event: ErrorEvent) => this.handleWorkerError(event.message);\n worker.onmessageerror = () => this.handleWorkerMessageError();\n }\n\n protected postMessage(worker: Worker, request: WorkerRequest): void {\n worker.postMessage(request);\n }\n\n protected terminateWorker(worker: Worker): void {\n worker.terminate();\n }\n\n protected generateRequestId(): string {\n return crypto.randomUUID();\n }\n\n protected getInitPayload(): {\n type: WorkerRequestType;\n payload: WorkerRequest[\"payload\"];\n } {\n // Explicitly construct the payload from serializable fields only.\n // Functions (e.g. `logger`) cannot be cloned by the structured clone\n // algorithm used by `worker.postMessage()`.\n const { cdnUrl, chains, csrfToken, integrity, thread } = this.config;\n return {\n type: \"INIT\",\n payload: { env: \"web\" as const, cdnUrl, chains, csrfToken, integrity, thread },\n };\n }\n\n /**\n * Update the CSRF token in the worker.\n * Call this before making authenticated requests to ensure the token is fresh.\n */\n async updateCsrf(csrfToken: string): Promise<void> {\n await this.sendRequest<UpdateCsrfResponseData>(\"UPDATE_CSRF\", {\n csrfToken,\n });\n }\n}\n","import { z } from \"zod/mini\";\nimport { CDN_INTEGRITY, CDN_URL, RelayerWeb } from \"../relayer/relayer-web\";\nimport { parseConfiguration } from \"../validation\";\nimport { RelayerWorkerClient } from \"../worker/worker.client\";\nimport type { WebRelayerConfig, WebRelayerOptions } from \"./types\";\n\nconst WebRelayerOptionsSchema = z.object({\n threads: z.optional(z.int().check(z.positive())),\n fheArtifactCacheTTL: z.optional(z.int().check(z.nonnegative())),\n});\n\n/**\n * Browser relayer — routes to RelayerWeb (Web Worker + WASM).\n *\n * @param options - Worker options (threads, security, logger, storage).\n *\n * @example\n * ```ts\n * relayers: {\n * [sepolia.id]: web(),\n * [mainnet.id]: web({ threads: 4 }),\n * }\n * ```\n */\nexport function web(options?: WebRelayerOptions): WebRelayerConfig {\n if (options !== undefined) {\n parseConfiguration(WebRelayerOptionsSchema, options);\n }\n return {\n type: \"web\",\n createWorker: (chains) =>\n new RelayerWorkerClient({\n cdnUrl: CDN_URL,\n chains,\n csrfToken: options?.security?.getCsrfToken?.() ?? \"\",\n integrity: options?.security?.integrityCheck === false ? undefined : CDN_INTEGRITY,\n logger: options?.logger,\n thread: options?.threads,\n }),\n createRelayer: (chain, worker) => new RelayerWeb({ chain, worker, ...options }),\n };\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zama-fhe/sdk",
3
- "version": "3.1.0",
3
+ "version": "3.1.1-alpha.1",
4
4
  "description": "TypeScript SDK for Zama fhEVM confidential smart contracts",
5
5
  "license": "BSD-3-Clause-Clear",
6
6
  "author": "Zama",