{"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 { GenericLogger } from \"../worker/worker.types\";\nimport type { GenericStorage } from \"../types\";\nimport { assertNonNullable, toError } from \"../utils\";\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;\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  GenericLogger,\n  UserDecryptPayload,\n  UserDecryptResponseData,\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;\n\n  constructor(config: TConfig, logger: GenericLogger) {\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      // A failed worker response is a handled operation failure: it is\n      // propagated to the caller via `pending.reject(err)` below. Logging it at\n      // `error` would duplicate a handled failure into the consumer's\n      // monitoring (the regression Dfns hit), so it stays at `debug`.\n      this.logger.debug(`[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        // A timeout is surfaced via the rejected promise below, so it is a\n        // handled failure and stays at `debug` rather than `error`.\n        this.logger.debug(`[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  /** SDK-wide 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, logger) =>\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,\n        thread: options?.threads,\n      }),\n    createRelayer: (chain, worker, logger) => new RelayerWeb({ chain, worker, ...options, logger }),\n  };\n}\n"],"mappings":"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"}