{"version":3,"file":"index.cjs","names":["ZamaError","ZamaError","ZamaErrorCode","ZamaError","ZamaErrorCode","DecryptionFailedError","RelayerRequestFailedError","SigningRejectedError","SigningFailedError","NotEntitledError","RpcRateLimitError","WorkerTimeoutError","WorkerRecycledError","isNotEntitledMessage","parseHandleFromMessage","hasStructuredRpcRateLimitSignal","extractRetryAfter","extractHttpStatus","isRpcRateLimitError","ZamaError","extractHttpStatus","RelayerRequestFailedError","extractRetryAfter","EncryptionFailedError","ConfigurationError","RelayerCleartext","buildZamaConfig","#signer","#provider","#relayer","#decryptionService","requireConfigured","#requireDecryptionService","requireAlignedWalletAccount","#signer","#provider","#delegationService","requireConfigured","#requireSigner","requireAlignedWalletAccount","#signer","#provider","#cachingService","#credentialService","#logger","requireConfigured","#requireCredentialService","requireChainAlignment","requireAlignedWalletAccount","swallow","z","checksummedAddress","#storage","#logger","#decryptNamespace","#decryptKeysNamespace","#buildStorageKey","#indexWriteQueue","#addToIndex","#doDelete","#doClearForRequester","#doClearAll","#readIndex","DecryptionFailedError","checksum","#cache","#credentialService","#delegationService","#relayer","#emitEvent","#decrypt","#withPropagationRetry","#assertAllDelegationsActive","#setHandleResult","isFatalBatchError","#missingBatchItem","#toZamaError","pLimit","isEncryptedValueZero","isRpcRateLimitError","#rpcRateLimitError","ZamaSDKEvents","ZamaError","toError","RpcRateLimitError","extractRetryAfter","DecryptionFailedError","#provider","#relayer","#emitEvent","#logger","MAX_UINT64","#submitAclTransaction","delegateForUserDecryptionContract","revokeDelegationContract","getDelegationExpiryContract","submitTransaction","#throwAclRevertIfMatched","TransactionRevertedError","#relayer","#emitEvent","ZamaSDKEvents","toError","#signer","#relayer","#cachingService","#credentialService","#logger","#walletAccountListeners","#unsubscribeSigner","#handleWalletAccountChange","swallow","checksum","z","hex","Token","SignerNotConfiguredError","#getUnderlying","#isPayable","isPayableTokenContract","allowanceContract","requireAlignedWalletAccount","balanceOfContract","ZamaError","ERC20ReadFailedError","toError","InsufficientERC20BalanceError","#shieldViaTransferAndCall","#shieldViaApproveAndWrap","#requireSigner","#ensureAllowance","wrapContract","approveContract","swallow","#waitAndFinalizeUnshield","EncryptionFailedError","unwrapContract","isEncryptedValueZero","DecryptionFailedError","unwrapFromBalanceContract","requireChainAlignment","finalizeUnwrapContract","#underlying","#underlyingPromise","underlyingContract","ZamaSDKEvents","TransactionRevertedError","#registryTTL","#registryAddresses","#onEvent","#logger","#cachingService","#lifecycleService","#encryptionService","#decryptionService","#credentialService","#delegationService","WrappersRegistry","CredentialService","Token"],"sources":["../../src/errors/match.ts","../../src/errors/credential.ts","../../src/errors/delegation.ts","../../src/errors/decrypt.ts","../../src/errors/encrypt.ts","../../src/config/cleartext.ts","../../src/utils/hex.ts","../../src/abi/erc1363.abi.ts","../../src/contracts/erc1363.ts","../../src/config/create.ts","../../src/namespaces/decryption.ts","../../src/namespaces/delegations.ts","../../src/namespaces/permits.ts","../../src/services/caching-service.ts","../../src/credentials/decrypt-permit.ts","../../src/services/decryption-service.ts","../../src/errors/acl-revert.ts","../../src/services/delegation-service.ts","../../src/services/encryption-service.ts","../../src/services/lifecycle-service.ts","../../src/events/onchain-events.ts","../../src/token/pending-unshield.ts","../../src/token/wrapped-token.ts","../../src/zama-sdk.ts","../../src/storage/chrome-session-storage.ts"],"sourcesContent":["import { ZamaError } from \"./base\";\nimport type { ZamaErrorCode } from \"./base\";\nimport type { ChainMismatchError } from \"./chain\";\nimport type {\n  NoCiphertextError,\n  TransportKeyPairExpiredError,\n  InvalidTransportKeyPairError,\n} from \"./credential\";\nimport type {\n  AclPausedError,\n  DelegationContractIsSelfError,\n  DelegationCooldownError,\n  DelegationDelegateEqualsContractError,\n  DelegationExpirationTooSoonError,\n  DelegationExpiredError,\n  DelegationExpiryUnchangedError,\n  DelegationNotFoundError,\n  DelegationNotPropagatedError,\n  DelegationSelfNotAllowedError,\n} from \"./delegation\";\nimport type { DecryptionFailedError, EncryptionFailedError } from \"./encryption\";\nimport type {\n  BalanceCheckUnavailableError,\n  ERC20ReadFailedError,\n  InsufficientConfidentialBalanceError,\n  InsufficientERC20BalanceError,\n} from \"./balance\";\nimport type { ConfigurationError, RelayerRequestFailedError } from \"./relayer\";\nimport type { NotEntitledError } from \"./entitlement\";\nimport type { RpcRateLimitError } from \"./rpc\";\nimport type {\n  SignerNotConfiguredError,\n  WalletAccountNotReadyError,\n  WalletNotConnectedError,\n} from \"./signer\";\nimport type { SigningFailedError, SigningRejectedError } from \"./signing\";\nimport type { TransactionRevertedError } from \"./transaction\";\nimport type { WorkerRecycledError, WorkerTimeoutError } from \"./timeout\";\n\n/**\n * Identity type that fails to instantiate unless `T` maps every code to a `ZamaError`.\n * Guards presence + value type only: a wrong-but-valid mapping (a code pointing at a\n * structurally identical sibling class) still compiles — `errors.test-d.ts` backstops that.\n */\ntype Complete<T extends Record<ZamaErrorCode, ZamaError>> = T;\n\n/**\n * Maps each {@link ZamaErrorCode} to the error class thrown with that code, so\n * {@link matchZamaError} handlers receive the matched subtype instead of the base\n * `ZamaError`. Hand-maintained; the `Complete` wrapper fails the build if a code is\n * added without an entry here (or mapped to a non-`ZamaError`).\n */\ntype ErrorForCode = Complete<{\n  [ZamaErrorCode.SigningRejected]: SigningRejectedError;\n  [ZamaErrorCode.SigningFailed]: SigningFailedError;\n  [ZamaErrorCode.EncryptionFailed]: EncryptionFailedError;\n  [ZamaErrorCode.DecryptionFailed]: DecryptionFailedError;\n  [ZamaErrorCode.TransactionReverted]: TransactionRevertedError;\n  [ZamaErrorCode.TransportKeyPairExpired]: TransportKeyPairExpiredError;\n  [ZamaErrorCode.InvalidTransportKeyPair]: InvalidTransportKeyPairError;\n  [ZamaErrorCode.NoCiphertext]: NoCiphertextError;\n  [ZamaErrorCode.RelayerRequestFailed]: RelayerRequestFailedError;\n  [ZamaErrorCode.NotEntitled]: NotEntitledError;\n  [ZamaErrorCode.RpcRateLimited]: RpcRateLimitError;\n  [ZamaErrorCode.OperationTimeout]: WorkerTimeoutError;\n  [ZamaErrorCode.WorkerRecycled]: WorkerRecycledError;\n  [ZamaErrorCode.Configuration]: ConfigurationError;\n  [ZamaErrorCode.DelegationSelfNotAllowed]: DelegationSelfNotAllowedError;\n  [ZamaErrorCode.DelegationCooldown]: DelegationCooldownError;\n  [ZamaErrorCode.DelegationNotFound]: DelegationNotFoundError;\n  [ZamaErrorCode.DelegationExpired]: DelegationExpiredError;\n  [ZamaErrorCode.InsufficientConfidentialBalance]: InsufficientConfidentialBalanceError;\n  [ZamaErrorCode.InsufficientERC20Balance]: InsufficientERC20BalanceError;\n  [ZamaErrorCode.BalanceCheckUnavailable]: BalanceCheckUnavailableError;\n  [ZamaErrorCode.ERC20ReadFailed]: ERC20ReadFailedError;\n  [ZamaErrorCode.DelegationExpiryUnchanged]: DelegationExpiryUnchangedError;\n  [ZamaErrorCode.DelegationDelegateEqualsContract]: DelegationDelegateEqualsContractError;\n  [ZamaErrorCode.DelegationContractIsSelf]: DelegationContractIsSelfError;\n  [ZamaErrorCode.AclPaused]: AclPausedError;\n  [ZamaErrorCode.DelegationExpirationTooSoon]: DelegationExpirationTooSoonError;\n  [ZamaErrorCode.DelegationNotPropagated]: DelegationNotPropagatedError;\n  [ZamaErrorCode.ChainMismatch]: ChainMismatchError;\n  [ZamaErrorCode.SignerNotConfigured]: SignerNotConfiguredError;\n  [ZamaErrorCode.WalletNotConnected]: WalletNotConnectedError;\n  [ZamaErrorCode.WalletAccountNotReady]: WalletAccountNotReadyError;\n}>;\n\n/**\n * Pattern-match on a {@link ZamaError} by its error code. Each handler receives the\n * error class for its code, so subclass fields are available without a cast.\n * Falls through to the `_` wildcard handler if no specific handler matches.\n * Returns `undefined` if the error is not a `ZamaError` and no `_` handler is provided.\n *\n * @example\n * ```ts\n * matchZamaError(error, {\n *   SIGNING_REJECTED: () => toast(\"Please approve in wallet\"),\n *   INSUFFICIENT_CONFIDENTIAL_BALANCE: (e) => toast(`Need ${e.requested}, have ${e.available}`),\n *   RELAYER_REQUEST_FAILED: (e) => toast(`Relayer failed (${e.statusCode})`),\n *   _: () => toast(\"Unknown error\"),\n * });\n * ```\n */\nexport function matchZamaError<R>(\n  error: unknown,\n  handlers: { [K in ZamaErrorCode]?: (error: ErrorForCode[K]) => R } & {\n    _?: (error: unknown) => R;\n  },\n): R | undefined {\n  if (error instanceof ZamaError) {\n    // `error.code` narrows the handler at runtime; the cast bridges the per-code param types.\n    const handler = handlers[error.code] as ((error: ZamaError) => R) | undefined;\n    if (handler) {\n      return handler(error);\n    }\n  }\n  return handlers._?.(error);\n}\n","import { ZamaError, ZamaErrorCode } from \"./base\";\n\n/** Transport key pair has expired and needs regeneration. */\nexport class TransportKeyPairExpiredError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.TransportKeyPairExpired, message, options);\n    this.name = \"TransportKeyPairExpiredError\";\n  }\n}\n\n/** Relayer rejected the transport key pair (stale, expired, or malformed). */\nexport class InvalidTransportKeyPairError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.InvalidTransportKeyPair, message, options);\n    this.name = \"InvalidTransportKeyPairError\";\n  }\n}\n\n/** No FHE ciphertext exists for this account (never shielded). */\nexport class NoCiphertextError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.NoCiphertext, message, options);\n    this.name = \"NoCiphertextError\";\n  }\n}\n","import { ZamaError, ZamaErrorCode } from \"./base\";\n\n// Delegation errors — thrown by SDK pre-flight checks and by delegation\n// transaction callsites when they map ACL Solidity revert reasons.\n\n/** Delegation cannot target self (delegate === msg.sender). */\nexport class DelegationSelfNotAllowedError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationSelfNotAllowed, message, options);\n    this.name = \"DelegationSelfNotAllowedError\";\n  }\n}\n\n/** Only one delegate/revoke per (delegator, delegate, contract) per block. */\nexport class DelegationCooldownError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationCooldown, message, options);\n    this.name = \"DelegationCooldownError\";\n  }\n}\n\n/** No active delegation found for this (delegator, delegate, contract) tuple. */\nexport class DelegationNotFoundError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationNotFound, message, options);\n    this.name = \"DelegationNotFoundError\";\n  }\n}\n\n/** The delegation has expired. */\nexport class DelegationExpiredError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationExpired, message, options);\n    this.name = \"DelegationExpiredError\";\n  }\n}\n\n/** The new expiration date equals the current one. */\nexport class DelegationExpiryUnchangedError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationExpiryUnchanged, message, options);\n    this.name = \"DelegationExpiryUnchangedError\";\n  }\n}\n\n/** Delegate address cannot be the contract address. */\nexport class DelegationDelegateEqualsContractError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationDelegateEqualsContract, message, options);\n    this.name = \"DelegationDelegateEqualsContractError\";\n  }\n}\n\n/** Contract address cannot be the sender address. */\nexport class DelegationContractIsSelfError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationContractIsSelf, message, options);\n    this.name = \"DelegationContractIsSelfError\";\n  }\n}\n\n/** The ACL contract is paused. */\nexport class AclPausedError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.AclPaused, message, options);\n    this.name = \"AclPausedError\";\n  }\n}\n\n/** Expiration date is too soon (must be at least 1 hour in the future). */\nexport class DelegationExpirationTooSoonError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationExpirationTooSoon, message, options);\n    this.name = \"DelegationExpirationTooSoonError\";\n  }\n}\n\n/**\n * Delegation exists on L1 but hasn't propagated to the gateway yet.\n *\n * After calling `delegateForUserDecryption()`, the delegation is recorded on-chain\n * immediately. However, the gateway (deployed on Arbitrum) must sync this state\n * via cross-chain event propagation, which usually completes within ~10 blocks\n * (a few seconds).\n *\n * Calling `decryptBalanceAs` during this window will fail because the gateway's\n * `isHandleDelegatedForUserDecryption()` check reads from its own synced copy\n * of the ACL state, which hasn't been updated yet.\n *\n * **You rarely need to handle this directly:** the delegated-decrypt path rides\n * out the propagation window with a bounded internal retry (~30s), so a decrypt\n * issued right after the grant simply waits for sync. This error only surfaces\n * if the window outlasts the retry budget, or when retries are disabled via\n * `waitForPropagation: false`.\n *\n * **Note:** This error is raised as a best-effort heuristic — when a delegated\n * decryption receives an HTTP 500 from the relayer, the most likely cause is a\n * propagation delay. However, the same status code can occur if the gateway or\n * relayer experiences an unrelated internal error.\n */\nexport class DelegationNotPropagatedError extends ZamaError {\n  constructor(message: string, options?: ErrorOptions) {\n    super(ZamaErrorCode.DelegationNotPropagated, message, options);\n    this.name = \"DelegationNotPropagatedError\";\n  }\n}\n","import type { ZamaError } from \"./base\";\nimport { DecryptionFailedError } from \"./encryption\";\nimport { NoCiphertextError } from \"./credential\";\nimport { RelayerRequestFailedError } from \"./relayer\";\nimport { DelegationNotPropagatedError } from \"./delegation\";\nimport { NotEntitledError } from \"./entitlement\";\nimport { RpcRateLimitError } from \"./rpc\";\nimport { SigningRejectedError, SigningFailedError } from \"./signing\";\nimport { WorkerRecycledError, WorkerTimeoutError } from \"./timeout\";\nimport {\n  extractHttpStatus,\n  extractRetryAfter,\n  hasStructuredRpcRateLimitSignal,\n  isNotEntitledMessage,\n  isRpcRateLimitError,\n  parseHandleFromMessage,\n} from \"../utils/error\";\n\n/**\n * Context the caller supplies so a not-entitled / delegation failure can be\n * mapped precisely. The classifier runs on both worker-origin errors (rebuilt\n * from the serialized envelope) and main-thread-origin ones (cleartext relayer,\n * delegation pre-check) — the request context (`contractAddress` / `account`)\n * only exists on the main thread, so it is injected here rather than threaded\n * across the worker boundary.\n */\nexport interface DecryptErrorContext {\n  isDelegated?: boolean;\n  contractAddress?: string;\n  /** The ACL actor (signer, or delegator for delegated decrypt). */\n  account?: string;\n}\n\n/**\n * The single decryption-error classifier. Maps a caught error to the right typed\n * SDK error: not-entitled (ACL), consumer RPC rate-limit, NoCiphertext (400),\n * DelegationNotPropagated (delegated 500 *or* a delegated ACL denial, which is\n * transient), RelayerRequestFailed (other HTTP), or the generic DecryptionFailed\n * fallback.\n *\n * Errors that are already typed SDK errors are returned as-is so callers can\n * still match the original cause. All structured signals (codes, status, cause\n * chain) are read from the error itself — worker-origin errors are first rebuilt\n * by {@link deserializeError}, so this runs identically regardless of origin.\n */\nexport function wrapDecryptError(\n  error: unknown,\n  fallbackMessage: string,\n  ctx: DecryptErrorContext = {},\n): ZamaError {\n  if (\n    error instanceof DecryptionFailedError ||\n    error instanceof NoCiphertextError ||\n    error instanceof RelayerRequestFailedError ||\n    error instanceof DelegationNotPropagatedError ||\n    error instanceof SigningRejectedError ||\n    error instanceof SigningFailedError ||\n    error instanceof NotEntitledError ||\n    error instanceof RpcRateLimitError ||\n    error instanceof WorkerTimeoutError ||\n    error instanceof WorkerRecycledError\n  ) {\n    return error;\n  }\n\n  const message = error instanceof Error ? error.message : fallbackMessage;\n\n  // Actor not entitled (ACL). The relayer throws a message-only Error whose text\n  // survives the worker boundary; the handle is parseable from it and the\n  // contract/account come from the request context the caller holds.\n  if (error instanceof Error && isNotEntitledMessage(error.message)) {\n    // On the delegated path the \"not entitled\" verdict comes from the\n    // *delegator's* `persistAllowed` L1 read, which has no staleness tolerance:\n    // it returns false *transiently* when the delegation has just landed or the\n    // consumer's RPC serves a lagging block. Terminal `NotEntitledError` (\"never\n    // retry\") would be the wrong signal for that propagation window, so — mirroring\n    // the delegated-500 branch below — surface the retryable\n    // `DelegationNotPropagatedError` instead. A direct signer denial (non-\n    // delegated) stays terminal `NotEntitledError`.\n    if (ctx.isDelegated) {\n      return new DelegationNotPropagatedError(\n        \"Delegated decryption was denied by the on-chain ACL check. \" +\n          \"This is most commonly caused by the delegation not having propagated yet, or by the \" +\n          \"RPC node serving a stale block. Propagation usually completes within ~10 blocks (a few \" +\n          \"seconds) and the SDK retries across that window; seeing this means it did not sync in time. \" +\n          \"Retry shortly (and prefer a fresh, low-lag RPC endpoint). If it persists, the delegator may \" +\n          \"genuinely lack the on-chain ACL grant.\",\n        { cause: error },\n      );\n    }\n    return new NotEntitledError(\n      {\n        encryptedValue: parseHandleFromMessage(error.message) ?? \"\",\n        contractAddress: ctx.contractAddress ?? \"\",\n        account: ctx.account ?? \"\",\n      },\n      { cause: error },\n    );\n  }\n\n  // Consumer's RPC provider throttling an on-chain read. An unambiguous\n  // structured signal (-32005 / viem `status: 429`) wins over any HTTP status;\n  // relayer-origin 429s carry `code: \"RELAYER_FETCH_ERROR\"` and are excluded,\n  // staying RelayerRequestFailedError below.\n  if (hasStructuredRpcRateLimitSignal(error)) {\n    return new RpcRateLimitError(message, { cause: error, retryAfter: extractRetryAfter(error) });\n  }\n\n  const statusCode = extractHttpStatus(error);\n\n  // A message-only throttle (\"Too Many Requests\" / \"rate limit\") is trusted only\n  // when no HTTP status is present — otherwise the status classification (e.g. a\n  // relayer error whose body mentions a rate limit) takes precedence.\n  if (statusCode === undefined && isRpcRateLimitError(error)) {\n    return new RpcRateLimitError(message, { cause: error, retryAfter: extractRetryAfter(error) });\n  }\n\n  if (statusCode === 400) {\n    return new NoCiphertextError(\n      error instanceof Error ? error.message : \"No ciphertext for this account\",\n      { cause: error },\n    );\n  }\n\n  if (ctx.isDelegated && statusCode === 500) {\n    return new DelegationNotPropagatedError(\n      \"Delegated decryption failed with a server error. \" +\n        \"This is most commonly caused by the delegation not having propagated to the gateway yet. \" +\n        \"Cross-chain sync usually completes within ~10 blocks (a few seconds) and the SDK retries \" +\n        \"across that window; seeing this means it did not sync in time — retry shortly. \" +\n        \"If the error persists, the gateway or relayer may be experiencing an unrelated issue.\",\n      { cause: error },\n    );\n  }\n\n  if (statusCode !== undefined) {\n    return new RelayerRequestFailedError(message, statusCode, {\n      cause: error,\n      retryAfter: extractRetryAfter(error),\n    });\n  }\n\n  return new DecryptionFailedError(fallbackMessage, { cause: error });\n}\n","import { extractHttpStatus, extractRetryAfter } from \"../utils/error\";\nimport { ZamaError } from \"./base\";\nimport { EncryptionFailedError } from \"./encryption\";\nimport { RelayerRequestFailedError } from \"./relayer\";\n\n/**\n * Inspect a caught encryption error for an HTTP status code and return the\n * appropriate typed SDK error. When the relayer (or an intermediary such as\n * Cloudflare/Kong) carried an HTTP status — e.g. a 401/403 for a missing or\n * invalid `x-api-key` — surface it as a {@link RelayerRequestFailedError} so the\n * status code and the relayer's own message reach the caller, instead of\n * collapsing every failure into a generic {@link EncryptionFailedError}.\n *\n * Errors that are already typed SDK errors are returned as-is so callers can\n * still match the original cause.\n *\n * The worker boundary normalizes the relayer SDK's `cause.status` onto a\n * top-level `statusCode`, so reading `statusCode` here mirrors\n * {@link wrapDecryptError}.\n */\nexport function wrapEncryptError(error: unknown, fallbackMessage: string): ZamaError {\n  if (error instanceof ZamaError) {\n    return error;\n  }\n\n  const statusCode = extractHttpStatus(error);\n\n  if (statusCode !== undefined) {\n    return new RelayerRequestFailedError(\n      error instanceof Error ? error.message : fallbackMessage,\n      statusCode,\n      { cause: error, retryAfter: extractRetryAfter(error) },\n    );\n  }\n\n  return new EncryptionFailedError(fallbackMessage, { cause: error });\n}\n","import { ConfigurationError } from \"../errors\";\nimport { RelayerCleartext } from \"../relayer/cleartext/relayer-cleartext\";\nimport type { CleartextRelayerConfig } from \"./types\";\n\n/**\n * Cleartext relayer — routes to RelayerCleartext (no FHE infrastructure).\n *\n * When `executorAddress` is set on the chain definition (e.g. `hardhat`, `hoodi`),\n * it is picked up automatically.\n *\n * @example\n * ```ts\n * // executorAddress comes from the chain preset:\n * relayers: { [hardhat.id]: cleartext() }\n * ```\n */\nexport function cleartext(): CleartextRelayerConfig {\n  return {\n    type: \"cleartext\",\n    createRelayer: (chain) => {\n      if (!chain.executorAddress) {\n        throw new ConfigurationError(\n          `Cleartext relayer requires an executorAddress. ` +\n            `Either use a chain preset that includes it (e.g. hardhat, hoodi) ` +\n            `or set it on the chain definition.`,\n        );\n      }\n      return new RelayerCleartext(chain);\n    },\n  };\n}\n","import type { Hex } from \"viem\";\nimport { assertCondition } from \"./assertions\";\n\n/** Normalize a un-prefixed hex payload to a 0x-prefixed `Hex` value. */\nexport function prefixHex(value: string): Hex {\n  return (value.startsWith(\"0x\") ? value : `0x${value}`) as Hex;\n}\n\n/** Convert a public `Hex` value back an unprefixed format. */\nexport function unprefixHex(value: Hex): string {\n  assertCondition(value.startsWith(\"0x\"), `Expected 0x-prefixed hex, got: ${value}`);\n  return value.slice(2);\n}\n","// DO NOT EDIT: generated by `pnpm abi:build` from\n// contracts/out/IERC1363.sol/IERC1363.json.\n// Regenerate after `pnpm contracts:build`; `pnpm abi:check` enforces this in CI.\nexport const erc1363Abi = [\n  {\n    type: \"function\",\n    name: \"allowance\",\n    inputs: [\n      { name: \"owner\", type: \"address\", internalType: \"address\" },\n      { name: \"spender\", type: \"address\", internalType: \"address\" },\n    ],\n    outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n    stateMutability: \"view\",\n  },\n  {\n    type: \"function\",\n    name: \"approve\",\n    inputs: [\n      { name: \"spender\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"approveAndCall\",\n    inputs: [\n      { name: \"spender\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"approveAndCall\",\n    inputs: [\n      { name: \"spender\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n      { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"balanceOf\",\n    inputs: [{ name: \"account\", type: \"address\", internalType: \"address\" }],\n    outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n    stateMutability: \"view\",\n  },\n  {\n    type: \"function\",\n    name: \"supportsInterface\",\n    inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"view\",\n  },\n  {\n    type: \"function\",\n    name: \"totalSupply\",\n    inputs: [],\n    outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n    stateMutability: \"view\",\n  },\n  {\n    type: \"function\",\n    name: \"transfer\",\n    inputs: [\n      { name: \"to\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferAndCall\",\n    inputs: [\n      { name: \"to\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferAndCall\",\n    inputs: [\n      { name: \"to\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n      { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferFrom\",\n    inputs: [\n      { name: \"from\", type: \"address\", internalType: \"address\" },\n      { name: \"to\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferFromAndCall\",\n    inputs: [\n      { name: \"from\", type: \"address\", internalType: \"address\" },\n      { name: \"to\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n      { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferFromAndCall\",\n    inputs: [\n      { name: \"from\", type: \"address\", internalType: \"address\" },\n      { name: \"to\", type: \"address\", internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n    ],\n    outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"event\",\n    name: \"Approval\",\n    inputs: [\n      { name: \"owner\", type: \"address\", indexed: true, internalType: \"address\" },\n      { name: \"spender\", type: \"address\", indexed: true, internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n    ],\n    anonymous: false,\n  },\n  {\n    type: \"event\",\n    name: \"Transfer\",\n    inputs: [\n      { name: \"from\", type: \"address\", indexed: true, internalType: \"address\" },\n      { name: \"to\", type: \"address\", indexed: true, internalType: \"address\" },\n      { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n    ],\n    anonymous: false,\n  },\n] as const;\n","import type { Address, Hex } from \"viem\";\nimport { erc1363Abi } from \"../abi/erc1363.abi\";\n\n/**\n * Returns the contract config for an ERC-1363 `transferAndCall`.\n *\n * @param tokenAddress - The ERC-20 token to transfer from (the underlying, not the wrapper).\n * @param to - The recipient of the ERC-20 transfer. In `Token.shield`, this is\n *   the wrapper contract whose `onTransferReceived` callback mints\n *   confidential tokens to the address encoded in `data`.\n * @param amount - The amount to transfer.\n * @param data - Raw 20-byte recipient address for shield-to-other (decoded by\n *   the wrapper as `address(bytes20(data))`). Empty `0x` for self-shield —\n *   the wrapper falls back to `from`.\n */\nexport function transferAndCallContract(\n  tokenAddress: Address,\n  to: Address,\n  amount: bigint,\n  data: Hex = \"0x\",\n) {\n  return {\n    address: tokenAddress,\n    abi: erc1363Abi,\n    functionName: \"transferAndCall\",\n    args: [to, amount, data],\n  } as const;\n}\n","import type { FheChain } from \"../chains\";\nimport { buildZamaConfig } from \"./build\";\nimport type { ZamaConfig, ZamaConfigGeneric } from \"./types\";\n\n/**\n * Create a {@link ZamaConfig} from a custom {@link GenericSigner} and\n * {@link GenericProvider}. Use this when the built-in adapter paths\n * (`@zama-fhe/sdk/viem`, `@zama-fhe/sdk/ethers`, `@zama-fhe/react-sdk/wagmi`)\n * don't cover your setup — e.g. a server-side relayer that implements\n * `GenericSigner` directly.\n *\n * @example\n * ```ts\n * import { createConfig, memoryStorage } from \"@zama-fhe/sdk\";\n * import { web } from \"@zama-fhe/sdk/web\";\n * import { sepolia } from \"@zama-fhe/sdk/chains\";\n *\n * const config = createConfig({\n *   chains: [sepolia],\n *   signer: myCustomSigner,\n *   provider: myCustomProvider,\n *   storage: memoryStorage,\n *   relayers: { [sepolia.id]: web() },\n * });\n * const sdk = new ZamaSDK(config);\n * ```\n */\nexport function createConfig<const TChains extends readonly [FheChain, ...FheChain[]]>(\n  params: ZamaConfigGeneric<TChains>,\n): ZamaConfig {\n  return buildZamaConfig(params.signer, params.provider, params);\n}\n","import type { Address } from \"viem\";\nimport { requireConfigured, wrapDecryptError } from \"../errors\";\nimport type { EncryptedInput } from \"../query/user-decrypt\";\nimport type { RelayerDispatcher } from \"../relayer/relayer-dispatcher\";\nimport type { ClearValue, EncryptedValue, PublicDecryptResult } from \"../relayer/relayer-sdk.types\";\nimport type {\n  BatchDecryptResult,\n  DecryptionService,\n  DelegatedDecryptOptions,\n} from \"../services/decryption-service\";\nimport type { GenericProvider, GenericSigner } from \"../types\";\nimport { requireAlignedWalletAccount } from \"../utils/alignment\";\n\n/**\n * Public namespace for FHE decryption — the canonical way to decrypt.\n *\n * Exposed as `sdk.decryption`. Prefer these methods over the low-level\n * `sdk.relayer.userDecrypt` / `delegatedUserDecrypt` / `publicDecrypt`: they\n * assemble the credential bundle (transport key pair, EIP-712 permit) for you,\n * cache results, and wrap relayer errors. Reach for `sdk.relayer.*` only when\n * you must control credential assembly by hand.\n *\n * Owns the SDK-level guards (signer requirement on\n * `decryptValues` and `delegatedDecryptValues`, empty-array\n * short-circuit on `decryptPublicValues`, relayer error wrapping) and delegates the\n * actual work to the internal {@link DecryptionService} or the relayer directly for\n * `decryptPublicValues`.\n *\n * **Mixed signer requirement:** `decryptValues` and\n * `delegatedDecryptValues` need a configured signer; `decryptPublicValues`\n * does not. Each method documents its requirement in its JSDoc.\n */\nexport class Decryption {\n  readonly #signer: GenericSigner | undefined;\n  readonly #provider: GenericProvider;\n  readonly #relayer: RelayerDispatcher;\n  readonly #decryptionService: DecryptionService | undefined;\n\n  /** @internal */\n  constructor(opts: {\n    signer: GenericSigner | undefined;\n    provider: GenericProvider;\n    relayer: RelayerDispatcher;\n    decryptionService: DecryptionService | undefined;\n  }) {\n    this.#signer = opts.signer;\n    this.#provider = opts.provider;\n    this.#relayer = opts.relayer;\n    this.#decryptionService = opts.decryptionService;\n  }\n\n  #requireDecryptionService(operation: string): DecryptionService {\n    return requireConfigured(this.#decryptionService, operation);\n  }\n\n  /**\n   * Decrypt one or more FHE encrypted values. Results are cached — repeated calls\n   * for the same encrypted value skip the relayer round-trip.\n   *\n   * Zero encrypted values are mapped to `0n` without hitting the relayer.\n   * Events (`DecryptStart/End/Error`) are emitted uniformly.\n   * Relayer errors are wrapped into typed SDK errors.\n   *\n   * @param encryptedInput - Encrypted values to decrypt, each paired with its contract address.\n   * @returns A record mapping each encrypted value to its decrypted clear-text value.\n   * @throws if no signer is configured. {@link SignerNotConfiguredError}\n   * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n   *\n   * @example\n   * ```ts\n   * const values = await sdk.decryption.decryptValues([\n   *   { encryptedValue: balance, contractAddress: cUSDT },\n   * ]);\n   * console.log(values[balance]); // 1000n\n   * ```\n   */\n  async decryptValues(\n    encryptedInput: EncryptedInput[],\n  ): Promise<Record<EncryptedValue, ClearValue>> {\n    const service = this.#requireDecryptionService(\"decryptValues\");\n    const account = await requireAlignedWalletAccount(\n      \"decryptValues\",\n      this.#signer,\n      this.#provider,\n    );\n    return service.userDecrypt(encryptedInput, account.address);\n  }\n\n  /**\n   * Decrypt one or more FHE encrypted values using delegated credentials.\n   *\n   * Mirrors {@link decryptValues} with delegated credentials — same caching and\n   * zero-value short-circuit. Before reading from cache or calling the relayer,\n   * every non-zero encrypted value's contract must have an active delegation from the\n   * delegator to the connected signer; missing or expired delegations fail fast.\n   *\n   * @param encryptedInputs - FHE encrypted values paired with their contract addresses.\n   * @param delegatorAddress - The address that granted delegation rights.\n   * @param accountAddress - Address used as the cache key's \"requester\"\n   *   dimension. Defaults to `delegatorAddress`. Pass the actual account address\n   *   when decrypting on behalf of someone whose balance is stored under a\n   *   different address (e.g. `decryptBalanceAs` with an explicit `accountAddress`).\n   * @param options - Delegated-decrypt options. By default the call rides out the\n   *   gateway propagation window ({@link DelegatedDecryptOptions.waitForPropagation});\n   *   pass `{ waitForPropagation: false }` to fail fast instead.\n   * @returns Map of encrypted value → clear-text value.\n   *\n   * @example\n   * ```ts\n   * const values = await sdk.decryption.delegatedDecryptValues([\n   *   { encryptedValue: balance, contractAddress: tokenAddr },\n   * ], delegatorAddr);\n   * console.log(values[balance]); // 1000n\n   * ```\n   */\n  async delegatedDecryptValues(\n    encryptedInputs: EncryptedInput[],\n    delegatorAddress: Address,\n    accountAddress: Address = delegatorAddress,\n    options?: DelegatedDecryptOptions,\n  ): Promise<Record<EncryptedValue, ClearValue>> {\n    const service = this.#requireDecryptionService(\"delegatedDecryptValues\");\n    const account = await requireAlignedWalletAccount(\n      \"delegatedDecryptValues\",\n      this.#signer,\n      this.#provider,\n    );\n    return service.delegatedUserDecrypt(\n      encryptedInputs,\n      delegatorAddress,\n      account.address,\n      accountAddress,\n      options,\n    );\n  }\n\n  /**\n   * Publicly decrypt one or more FHE encrypted values.\n   *\n   * Signer-independent: works without a configured signer.\n   * Returns the decryption proof alongside the clear-text values so callers\n   * can submit on-chain finalization transactions (e.g. `finalizeUnwrap`).\n   *\n   * @param encryptedValues - FHE encrypted values to decrypt publicly.\n   * @returns Clear-text values, ABI-encoded values, and the decryption proof.\n   *\n   * @example\n   * ```ts\n   * const { clearValues, decryptionProof, abiEncodedClearValues } =\n   *   await sdk.decryption.decryptPublicValues([encryptedValue]);\n   * ```\n   */\n  async decryptPublicValues(encryptedValues: EncryptedValue[]): Promise<PublicDecryptResult> {\n    if (encryptedValues.length === 0) {\n      return { clearValues: {}, decryptionProof: \"0x\", abiEncodedClearValues: \"0x\" };\n    }\n\n    try {\n      return await this.#relayer.publicDecrypt(encryptedValues);\n    } catch (error) {\n      throw wrapDecryptError(error, \"Public decryption failed\");\n    }\n  }\n\n  /**\n   * Batch-decrypt delegated encrypted values with per-entry error isolation.\n   *\n   * Attempts a single batch request first. If the batch fails with a non-fatal\n   * error (e.g. one entry is invalid), falls back to per-entry decryption so\n   * healthy entries still resolve. Each item in the result carries either a\n   * decrypted value or an error — callers decide how to surface partial failures.\n   *\n   * @param encryptedInputs - FHE encrypted values paired with their contract addresses.\n   * @param delegatorAddress - The address that granted delegation rights.\n   * @param accountAddress - The account on whose behalf decryption is performed. Defaults to `delegatorAddress`.\n   * @param maxConcurrency - Maximum parallel decrypt calls during per-entry fallback.\n   * @param waitForPropagation - Ride out the gateway propagation window on the\n   *   initial batch attempt (default `true`). See {@link DelegatedDecryptOptions.waitForPropagation}.\n   * @returns Per-entry results, each with a value or an error.\n   * @throws if no signer is configured. {@link SignerNotConfiguredError}\n   * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n   *\n   * @example\n   * ```ts\n   * const result = await sdk.decryption.delegatedBatchDecryptValues({\n   *   encryptedInputs: [\n   *     { encryptedValue: encryptedValue1, contractAddress: tokenA },\n   *     { encryptedValue: encryptedValue2, contractAddress: tokenB },\n   *   ],\n   *   delegatorAddress: \"0xDelegator\",\n   *   maxConcurrency: 5,\n   * });\n   * for (const item of result.items) {\n   *   if (item.error) console.error(item.encryptedValue, item.error);\n   *   else console.log(item.encryptedValue, item.value);\n   * }\n   * ```\n   */\n  async delegatedBatchDecryptValues({\n    encryptedInputs,\n    delegatorAddress,\n    accountAddress = delegatorAddress,\n    maxConcurrency,\n    waitForPropagation,\n  }: {\n    encryptedInputs: EncryptedInput[];\n    delegatorAddress: Address;\n    accountAddress?: Address;\n    maxConcurrency?: number;\n  } & DelegatedDecryptOptions): Promise<BatchDecryptResult> {\n    const service = this.#requireDecryptionService(\"delegatedBatchDecryptValues\");\n    const account = await requireAlignedWalletAccount(\n      \"delegatedBatchDecryptValues\",\n      this.#signer,\n      this.#provider,\n    );\n    return service.delegatedBatchDecryptHandlesAs({\n      encryptedInputs,\n      delegatorAddress,\n      delegateAddress: account.address,\n      accountAddress,\n      maxConcurrency,\n      waitForPropagation,\n    });\n  }\n}\n","import type { Address } from \"viem\";\nimport type { DelegationService } from \"../services/delegation-service\";\nimport type { GenericProvider, GenericSigner, TransactionResult } from \"../types\";\nimport { requireAlignedWalletAccount } from \"../utils/alignment\";\nimport { requireConfigured } from \"../errors\";\n\n/**\n * Public namespace for on-chain decryption-delegation management.\n *\n * Exposed as `sdk.delegations`. Owns the SDK-level guards (signer requirement, chain\n * alignment, delegator address resolution from the wallet account) and delegates the\n * actual work to the internal {@link DelegationService}.\n *\n * Delegation operations write to the host chain ACL; after a delegation is mined,\n * the gateway syncs the ACL state via cross-chain event propagation — usually\n * within ~10 blocks (a few seconds). Delegated decryption rides out that window\n * with a bounded internal retry, so callers can decrypt right after granting.\n */\nexport class Delegations {\n  readonly #signer: GenericSigner | undefined;\n  readonly #provider: GenericProvider;\n  readonly #delegationService: DelegationService;\n\n  /** @internal */\n  constructor(opts: {\n    signer: GenericSigner | undefined;\n    provider: GenericProvider;\n    delegationService: DelegationService;\n  }) {\n    this.#signer = opts.signer;\n    this.#provider = opts.provider;\n    this.#delegationService = opts.delegationService;\n  }\n\n  #requireSigner(operation: string): GenericSigner {\n    return requireConfigured(this.#signer, operation);\n  }\n\n  /**\n   * Delegate decryption rights for a confidential contract to another address.\n   * Calls `ACL.delegateForUserDecryption()` on-chain.\n   *\n   * The delegation is recorded on L1 immediately, but the gateway must sync the\n   * ACL state via cross-chain event propagation — usually within ~10 blocks (a\n   * few seconds). You do not need to wait: delegated decryption rides out that\n   * window with a bounded internal retry, so you can decrypt right after this\n   * resolves.\n   *\n   * @param contractAddress - The confidential contract address to delegate on.\n   * @param delegateAddress - Address to delegate decryption rights to.\n   * @param expirationDate - Optional expiration date (defaults to permanent delegation via `uint64.max`).\n   * @returns The transaction hash and mined receipt.\n   * @throws if no signer is configured. {@link SignerNotConfiguredError}\n   * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n   * @throws if `expirationDate` is less than 1 hour in the future. {@link DelegationExpirationTooSoonError}\n   * @throws if the delegate equals the connected wallet. {@link DelegationSelfNotAllowedError}\n   * @throws if the delegate equals the contract address. {@link DelegationDelegateEqualsContractError}\n   * @throws if the new expiry equals the current one. {@link DelegationExpiryUnchangedError}\n   * @throws if the delegation transaction reverts. {@link TransactionRevertedError}\n   */\n  async delegateDecryption({\n    contractAddress,\n    delegateAddress,\n    expirationDate,\n  }: {\n    contractAddress: Address;\n    delegateAddress: Address;\n    expirationDate?: Date;\n  }): Promise<TransactionResult> {\n    const signer = this.#requireSigner(\"delegateDecryption\");\n    const account = await requireAlignedWalletAccount(\n      \"delegateDecryption\",\n      this.#signer,\n      this.#provider,\n    );\n    return this.#delegationService.delegateDecryption(signer, {\n      contractAddress,\n      delegateAddress,\n      delegatorAddress: account.address,\n      expirationDate,\n    });\n  }\n\n  /**\n   * Revoke decryption delegation for a confidential contract.\n   * Calls `ACL.revokeDelegationForUserDecryption()` on-chain.\n   *\n   * @param contractAddress - The confidential contract address to revoke delegation on.\n   * @param delegateAddress - Address to revoke delegation from.\n   * @returns The transaction hash and mined receipt.\n   * @throws if no signer is configured. {@link SignerNotConfiguredError}\n   * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n   * @throws if no delegation exists for this (delegator, delegate, contract) tuple. {@link DelegationNotFoundError}\n   * @throws if the revocation transaction reverts. {@link TransactionRevertedError}\n   */\n  async revokeDelegation({\n    contractAddress,\n    delegateAddress,\n  }: {\n    contractAddress: Address;\n    delegateAddress: Address;\n  }): Promise<TransactionResult> {\n    const signer = this.#requireSigner(\"revokeDelegation\");\n    const account = await requireAlignedWalletAccount(\n      \"revokeDelegation\",\n      this.#signer,\n      this.#provider,\n    );\n    return this.#delegationService.revokeDelegation(signer, {\n      contractAddress,\n      delegateAddress,\n      delegatorAddress: account.address,\n    });\n  }\n\n  /**\n   * Check whether a delegation is active for the given contract address.\n   *\n   * Signer-independent: works without a configured signer.\n   *\n   * @param contractAddress - The confidential contract address.\n   * @param delegatorAddress - The address that granted the delegation.\n   * @param delegateAddress - The address that received delegation rights.\n   * @returns `true` if the delegation exists and has not expired.\n   */\n  async isActive(params: {\n    contractAddress: Address;\n    delegatorAddress: Address;\n    delegateAddress: Address;\n  }): Promise<boolean> {\n    return this.#delegationService.isDelegated(params);\n  }\n\n  /**\n   * Get the expiration timestamp of a delegation for the given contract.\n   *\n   * Signer-independent: works without a configured signer.\n   *\n   * @param contractAddress - The confidential contract address.\n   * @param delegatorAddress - The address that granted the delegation.\n   * @param delegateAddress - The address that received delegation rights.\n   * @returns Unix timestamp as bigint. `0n` = no delegation. `2^64 - 1` = permanent.\n   */\n  async getExpiry(params: {\n    contractAddress: Address;\n    delegatorAddress: Address;\n    delegateAddress: Address;\n  }): Promise<bigint> {\n    return this.#delegationService.getDelegationExpiry(params);\n  }\n}\n","import { getAddress, type Address } from \"viem\";\nimport type { CredentialService } from \"../credentials/credential-service\";\nimport { requireConfigured } from \"../errors\";\nimport type { CachingService } from \"../services/caching-service\";\nimport type { GenericProvider, GenericSigner } from \"../types\";\nimport { swallow } from \"../utils\";\nimport { requireAlignedWalletAccount, requireChainAlignment } from \"../utils/alignment\";\nimport type { GenericLogger } from \"../worker/worker.types\";\n\n/**\n * Public namespace for permit and transport-key-pair management.\n *\n * Exposed as `sdk.permits`. Owns the SDK-level guards (chain alignment, empty-array\n * short-circuit, decrypt-cache invalidation) and delegates the actual work to the\n * internal {@link CredentialService}.\n *\n * The namespace is named `permits` because the user-facing concept is the signed-permit\n * store. The transport key pair is invisible plumbing — there is no `getTransportKeyPair()`\n * surfaced; the key pair exists to sign permits and is created automatically when needed.\n * {@link clear} wipes both the permit store and the transport key pair (permits\n * cascade-delete with the key pair).\n */\nexport class Permits {\n  readonly #signer: GenericSigner | undefined;\n  readonly #provider: GenericProvider;\n  readonly #cachingService: CachingService;\n  readonly #credentialService: CredentialService | undefined;\n  readonly #logger: GenericLogger;\n\n  /** @internal */\n  constructor(opts: {\n    signer: GenericSigner | undefined;\n    provider: GenericProvider;\n    cachingService: CachingService;\n    credentialService: CredentialService | undefined;\n    logger: GenericLogger;\n  }) {\n    this.#signer = opts.signer;\n    this.#provider = opts.provider;\n    this.#cachingService = opts.cachingService;\n    this.#credentialService = opts.credentialService;\n    this.#logger = opts.logger;\n  }\n\n  #requireCredentialService(operation: string): CredentialService {\n    return requireConfigured(this.#credentialService, operation);\n  }\n\n  /**\n   * Sign and store an EIP-712 permit authorising direct decryption for the\n   * given contract addresses.\n   *\n   * Idempotent: if a permit covering the requested set already exists, no\n   * wallet prompt occurs. Otherwise the SDK chunks the uncovered subset into\n   * groups of ≤10 contracts and prompts once per chunk; partial mid-flight\n   * rejection is preserved (already-signed chunks are persisted before the\n   * next prompt).\n   *\n   * @param contracts - Contract addresses to authorize.\n   */\n  async grantPermit(contracts: Address[]): Promise<void> {\n    if (contracts.length === 0) {\n      return;\n    }\n    const service = this.#requireCredentialService(\"grantPermit\");\n    await requireChainAlignment(\"grantPermit\", this.#signer, this.#provider);\n    await service.grantPermit(contracts);\n  }\n\n  /**\n   * Sign and store an EIP-712 delegation permit authorising decryption on\n   * behalf of `delegator`. Same idempotence/chunking semantics as {@link grantPermit}.\n   *\n   * @param delegator - The address that delegated decryption rights to the connected signer.\n   * @param contracts - Contract addresses to authorize.\n   */\n  async grantDelegationPermit(delegator: Address, contracts: Address[]): Promise<void> {\n    if (contracts.length === 0) {\n      return;\n    }\n    const service = this.#requireCredentialService(\"grantDelegationPermit\");\n    await requireChainAlignment(\"grantDelegationPermit\", this.#signer, this.#provider);\n    await service.grantPermit(contracts, delegator);\n  }\n\n  /**\n   * Pure store lookup: is there a permit covering `contracts`?\n   * No wallet prompt, no transport key pair generation. Returns `false` when no signer\n   * is configured.\n   */\n  async hasPermit(contracts: Address[]): Promise<boolean> {\n    if (!this.#credentialService) {\n      return false;\n    }\n    return this.#credentialService.hasPermit(contracts);\n  }\n\n  /**\n   * Pure store lookup for a delegation permit. See {@link hasPermit}.\n   *\n   * @param delegator - The address that delegated decryption rights to the connected signer.\n   * @param contracts - Contract addresses to check.\n   * @returns `true` if cached delegation permits cover all requested contracts.\n   */\n  async hasDelegationPermit(delegator: Address, contracts: Address[]): Promise<boolean> {\n    if (!this.#credentialService) {\n      return false;\n    }\n    return this.#credentialService.hasPermit(contracts, delegator);\n  }\n\n  /**\n   * Best-effort transport-key-pair prefetch for the connected signer.\n   *\n   * Optional latency optimization: decrypt and permit flows remain correct\n   * without it because they lazily create the transport key pair when needed.\n   *\n   * Silent no-op when no signer is configured or no wallet account is\n   * available. The transport key pair is generated through the relayer dispatcher's\n   * currently active chain — see {@link LifecycleService}, which calls\n   * `switchChain` before fanning the wallet-account change out to listeners,\n   * so any downstream caller (including React adapters) observes the\n   * dispatcher on the wallet chain by the time it invokes warmup.\n   */\n  async warmTransportKeyPair(): Promise<void> {\n    const service = this.#credentialService;\n    if (!service) {\n      return;\n    }\n    const account = this.#signer?.walletAccount.getSnapshot();\n    if (!account) {\n      return;\n    }\n    await service.warmTransportKeyPair(account.address);\n  }\n\n  /**\n   * Wipe FHE permits for the current signer.\n   *\n   * - With no argument: every permit referencing this signer is removed across\n   *   all chains and delegators. The transport key pair survives — use {@link clear} to\n   *   also wipe the transport key pair.\n   * - With a contract list: every signed permit in the direct-decrypt scope\n   *   (current chain) whose immutable payload touches any listed address is\n   *   removed. Delegation permits are not touched in this mode.\n   *\n   * @throws if no signer is configured. {@link SignerNotConfiguredError}\n   */\n  async revokePermits(contracts?: Address[]): Promise<void> {\n    const service = this.#requireCredentialService(\"revokePermits\");\n    const account = await requireAlignedWalletAccount(\n      \"revokePermits\",\n      this.#signer,\n      this.#provider,\n    );\n    const signerAddress = getAddress(account.address);\n    try {\n      await service.revokePermits(contracts);\n    } finally {\n      await swallow(\n        \"clear decrypt cache\",\n        () => this.#cachingService.clearForRequester(signerAddress),\n        this.#logger,\n      );\n    }\n  }\n\n  /**\n   * Wipe the transport key pair for the current signer and cascade-delete every permit\n   * (across chains and delegators) referencing it.\n   *\n   * @throws if no signer is configured. {@link SignerNotConfiguredError}\n   */\n  async clear(): Promise<void> {\n    const service = this.#requireCredentialService(\"clear\");\n    const account = await requireAlignedWalletAccount(\"clear\", this.#signer, this.#provider);\n    const signerAddress = getAddress(account.address);\n    try {\n      await service.clearCredentials();\n    } finally {\n      await swallow(\n        \"clear decrypt cache\",\n        () => this.#cachingService.clearForRequester(signerAddress),\n        this.#logger,\n      );\n    }\n  }\n}\n","import { getAddress, type Address } from \"viem\";\nimport { z } from \"zod/mini\";\nimport type { ClearValue, EncryptedValue } from \"../relayer/relayer-sdk.types\";\nimport { checksummedAddress } from \"../schemas/primitives\";\nimport type { GenericStorage } from \"../types\";\nimport type { GenericLogger } from \"../worker/worker.types\";\n\nconst CacheValueSchema = z.union([z.bigint(), z.boolean(), checksummedAddress]);\nconst CacheIndexSchema = z.array(z.string());\n\n/**\n * Storage-backed cache for decrypted FHE plaintext values.\n *\n * Each entry is keyed by `(requester, contractAddress, handle)` so different\n * signers cannot read each other's cached decryptions.\n */\nexport class CachingService {\n  readonly #storage: GenericStorage;\n  readonly #logger: GenericLogger;\n  readonly #decryptNamespace = \"zama:decrypt\";\n  readonly #decryptKeysNamespace = `${this.#decryptNamespace}:keys`;\n  #indexWriteQueue: Promise<void> = Promise.resolve();\n\n  constructor(storage: GenericStorage, logger: GenericLogger) {\n    this.#storage = storage;\n    this.#logger = logger;\n  }\n\n  async get(\n    requester: Address,\n    contractAddress: Address,\n    encryptedValue: EncryptedValue,\n  ): Promise<ClearValue | null> {\n    try {\n      const key = this.#buildStorageKey(requester, contractAddress, encryptedValue);\n      const value = await this.#storage.get(key);\n      if (value === null) {\n        return null;\n      }\n      const parsed = CacheValueSchema.safeParse(value);\n      if (!parsed.success) {\n        await this.delete(requester, contractAddress, encryptedValue);\n        return null;\n      }\n      return parsed.data;\n    } catch (error) {\n      this.#logger.warn(\"CachingService.get failed\", { error });\n      return null;\n    }\n  }\n\n  async set(\n    requester: Address,\n    contractAddress: Address,\n    encryptedValue: EncryptedValue,\n    value: ClearValue,\n  ): Promise<void> {\n    try {\n      const key = this.#buildStorageKey(requester, contractAddress, encryptedValue);\n      await this.#storage.set<ClearValue>(key, value);\n      this.#indexWriteQueue = this.#indexWriteQueue.then(() =>\n        this.#addToIndex(key).catch((error) => {\n          this.#logger.warn(\"CachingService index write failed\", { error });\n        }),\n      );\n      await this.#indexWriteQueue;\n    } catch (error) {\n      this.#logger.warn(\"CachingService.set failed\", { error });\n    }\n  }\n\n  async delete(\n    requester: Address,\n    contractAddress: Address,\n    encryptedValue: EncryptedValue,\n  ): Promise<void> {\n    const key = this.#buildStorageKey(requester, contractAddress, encryptedValue);\n    this.#indexWriteQueue = this.#indexWriteQueue.then(() =>\n      this.#doDelete(key).catch((error) => {\n        this.#logger.warn(\"CachingService.delete failed\", { error });\n      }),\n    );\n    await this.#indexWriteQueue;\n  }\n\n  async clearForRequester(requester: Address): Promise<void> {\n    this.#indexWriteQueue = this.#indexWriteQueue.then(() =>\n      this.#doClearForRequester(requester).catch((error) => {\n        this.#logger.warn(\"CachingService.clearForRequester failed\", { error });\n      }),\n    );\n    await this.#indexWriteQueue;\n  }\n\n  async clearAll(): Promise<void> {\n    this.#indexWriteQueue = this.#indexWriteQueue.then(() =>\n      this.#doClearAll().catch((error) => {\n        this.#logger.warn(\"CachingService.clearAll failed\", { error });\n      }),\n    );\n    await this.#indexWriteQueue;\n  }\n\n  async #doDelete(key: string): Promise<void> {\n    await this.#storage.delete(key).catch(() => {});\n    const keys = await this.#readIndex();\n    const remaining = keys.filter((k) => k !== key);\n    if (remaining.length !== keys.length) {\n      await this.#storage.set(this.#decryptKeysNamespace, remaining);\n    }\n  }\n\n  async #doClearForRequester(requester: Address): Promise<void> {\n    const checksumRequester = getAddress(requester);\n    const prefix = `${this.#decryptNamespace}:${checksumRequester}:`;\n    const keys = await this.#readIndex();\n    const toRemove: string[] = [];\n    const remaining: string[] = [];\n    for (const k of keys) {\n      if (k.startsWith(prefix)) {\n        toRemove.push(k);\n      } else {\n        remaining.push(k);\n      }\n    }\n    await Promise.all(toRemove.map((k) => this.#storage.delete(k).catch(() => {})));\n    await this.#storage.set(this.#decryptKeysNamespace, remaining);\n  }\n\n  async #doClearAll(): Promise<void> {\n    const keys = await this.#readIndex();\n    await Promise.all(keys.map((k) => this.#storage.delete(k).catch(() => {})));\n    await this.#storage.delete(this.#decryptKeysNamespace);\n  }\n\n  #buildStorageKey(\n    requester: Address,\n    contractAddress: Address,\n    encryptedValue: EncryptedValue,\n  ): string {\n    return `${this.#decryptNamespace}:${getAddress(requester)}:${getAddress(contractAddress)}:${encryptedValue.toLowerCase()}`;\n  }\n\n  async #readIndex(): Promise<string[]> {\n    const value = await this.#storage.get(this.#decryptKeysNamespace);\n    if (value === null) {\n      return [];\n    }\n    const parsed = CacheIndexSchema.safeParse(value);\n    if (parsed.success) {\n      return parsed.data;\n    }\n    await this.#storage.delete(this.#decryptKeysNamespace).catch(() => {});\n    return [];\n  }\n\n  async #addToIndex(key: string): Promise<void> {\n    const keys = await this.#readIndex();\n    if (!keys.includes(key)) {\n      keys.push(key);\n      await this.#storage.set(this.#decryptKeysNamespace, keys);\n    }\n  }\n}\n","import type { Address } from \"viem\";\nimport { DecryptionFailedError } from \"../errors\";\nimport type { DelegatedUserDecryptParams, UserDecryptParams } from \"../relayer/relayer-sdk.types\";\nimport type { StoredTransportKeyPairWithPermits, Permission } from \"./types\";\nimport { checksum } from \"../schemas/primitives\";\n\nexport type UserDecryptPermitParams = Pick<\n  UserDecryptParams,\n  | \"signedContractAddresses\"\n  | \"privateKey\"\n  | \"publicKey\"\n  | \"signature\"\n  | \"startTimestamp\"\n  | \"durationDays\"\n>;\n\nexport type DelegatedUserDecryptPermitParams = Pick<\n  DelegatedUserDecryptParams,\n  | \"signedContractAddresses\"\n  | \"privateKey\"\n  | \"publicKey\"\n  | \"signature\"\n  | \"delegatorAddress\"\n  | \"startTimestamp\"\n  | \"durationDays\"\n>;\n\nexport function resolveUserDecryptPermit(\n  credentials: StoredTransportKeyPairWithPermits,\n  contractAddress: Address,\n): UserDecryptPermitParams {\n  const permission = findPermissionFor(credentials, contractAddress);\n  if (!permission) {\n    throw new DecryptionFailedError(`No permit covers contract ${contractAddress} after allow()`);\n  }\n  return commonPermitParams(credentials, permission);\n}\n\nexport function resolveDelegatedDecryptPermit(\n  credentials: StoredTransportKeyPairWithPermits,\n  contractAddress: Address,\n): DelegatedUserDecryptPermitParams {\n  const permission = findPermissionFor(credentials, contractAddress);\n  if (!permission) {\n    throw new DecryptionFailedError(\n      `No delegated permit covers contract ${contractAddress} after allow()`,\n    );\n  }\n  return {\n    ...commonPermitParams(credentials, permission),\n    delegatorAddress: permission.delegatorAddress,\n  };\n}\n\nfunction commonPermitParams(\n  credentials: StoredTransportKeyPairWithPermits,\n  permission: Permission,\n) {\n  return {\n    signedContractAddresses: permission.signedContractAddresses,\n    privateKey: credentials.keypair.privateKey,\n    publicKey: credentials.keypair.publicKey,\n    signature: permission.signature,\n    startTimestamp: permission.startTimestamp,\n    durationDays: permission.durationDays,\n  };\n}\n\nfunction findPermissionFor(\n  credentials: StoredTransportKeyPairWithPermits,\n  contractAddress: Address,\n): Permission | undefined {\n  const target = checksum(contractAddress);\n  return credentials.permits.find((permission) =>\n    permission.signedContractAddresses.includes(target),\n  );\n}\n","import { getAddress, type Address } from \"viem\";\nimport type { CredentialService } from \"../credentials/credential-service\";\nimport {\n  resolveDelegatedDecryptPermit,\n  resolveUserDecryptPermit,\n} from \"../credentials/decrypt-permit\";\nimport type { StoredTransportKeyPairWithPermits } from \"../credentials/types\";\nimport {\n  type DecryptErrorContext,\n  DecryptionFailedError,\n  DelegationNotPropagatedError,\n  isFatalBatchError,\n  RpcRateLimitError,\n  wrapDecryptError,\n  ZamaError,\n} from \"../errors\";\nimport type { ZamaSDKEventInput } from \"../events/sdk-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { EncryptedInput } from \"../query/user-decrypt\";\nimport type { RelayerDispatcher } from \"../relayer/relayer-dispatcher\";\nimport type { ClearValue, EncryptedValue } from \"../relayer/relayer-sdk.types\";\nimport { pLimit } from \"../utils/concurrency\";\nimport { isEncryptedValueZero } from \"../utils/handles\";\nimport { extractRetryAfter, isRpcRateLimitError, toError } from \"../utils\";\nimport type { CachingService } from \"./caching-service\";\nimport type { DelegationService } from \"./delegation-service\";\n\n/**\n * How long the delegated-decrypt path keeps retrying while a freshly granted\n * delegation propagates to the gateway. Propagation usually completes within\n * ~10 blocks (a few seconds); this ceiling absorbs a briefly lagging gateway\n * without turning a genuine outage into a long hang.\n */\nconst DELEGATION_PROPAGATION_RETRY_BUDGET_MS = 30_000;\n/** Delay between propagation retries. */\nconst DELEGATION_PROPAGATION_RETRY_INTERVAL_MS = 2_000;\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Options shared by the delegated-decrypt entry points. */\nexport interface DelegatedDecryptOptions {\n  /**\n   * Ride out the gateway propagation window: when a just-granted delegation\n   * has not yet synced, the delegated decrypt is retried (bounded, ~30s) until\n   * it lands instead of throwing {@link DelegationNotPropagatedError}. Defaults\n   * to `true`. Pass `false` to fail fast on the first not-propagated response.\n   */\n  waitForPropagation?: boolean;\n}\n\ninterface DecryptionStrategy {\n  requesterAddress: Address;\n  /** The ACL actor whose entitlement is checked (signer, or delegator when delegated). */\n  aclActorAddress: Address;\n  resolveCredentials: (contractAddresses: Address[]) => Promise<StoredTransportKeyPairWithPermits>;\n  validate?: (contractAddresses: readonly Address[]) => Promise<void>;\n  decryptContract: (args: {\n    credentials: StoredTransportKeyPairWithPermits;\n    contractAddress: Address;\n    encryptedValues: EncryptedValue[];\n  }) => Promise<Record<EncryptedValue, ClearValue>>;\n  errorMessage: string;\n  delegated?: boolean;\n}\n\nexport interface BatchDecryptItem {\n  encryptedValue: EncryptedValue;\n  contractAddress: Address;\n  value?: ClearValue;\n  error?: ZamaError;\n}\n\nexport interface BatchDecryptResult {\n  items: BatchDecryptItem[];\n}\n\nexport class DecryptionService {\n  readonly #cache: CachingService;\n  readonly #credentialService: CredentialService;\n  readonly #delegationService: DelegationService;\n  readonly #relayer: RelayerDispatcher;\n  readonly #emitEvent: (input: ZamaSDKEventInput) => void;\n\n  constructor({\n    cache,\n    credentialService,\n    delegationService,\n    relayer,\n    emitEvent,\n  }: {\n    cache: CachingService;\n    credentialService: CredentialService;\n    delegationService: DelegationService;\n    relayer: RelayerDispatcher;\n    emitEvent: (input: ZamaSDKEventInput) => void;\n  }) {\n    this.#cache = cache;\n    this.#credentialService = credentialService;\n    this.#delegationService = delegationService;\n    this.#relayer = relayer;\n    this.#emitEvent = emitEvent;\n  }\n\n  async userDecrypt(\n    handles: EncryptedInput[],\n    signerAddress: Address,\n  ): Promise<Record<EncryptedValue, ClearValue>> {\n    const normalizedSigner = getAddress(signerAddress);\n    return this.#decrypt(handles, {\n      requesterAddress: normalizedSigner,\n      aclActorAddress: normalizedSigner,\n      resolveCredentials: (contractAddresses) =>\n        this.#credentialService.grantPermit(contractAddresses),\n      decryptContract: async ({ credentials, contractAddress, encryptedValues }) => {\n        return this.#relayer.userDecrypt({\n          encryptedValues,\n          contractAddress,\n          ...resolveUserDecryptPermit(credentials, contractAddress),\n          signerAddress: normalizedSigner,\n        });\n      },\n      errorMessage: \"Failed to decrypt encrypted values\",\n    });\n  }\n\n  async delegatedUserDecrypt(\n    encryptedValues: EncryptedInput[],\n    delegatorAddress: Address,\n    delegateAddress: Address,\n    accountAddress: Address,\n    options?: DelegatedDecryptOptions,\n  ): Promise<Record<EncryptedValue, ClearValue>> {\n    const normalizedDelegator = getAddress(delegatorAddress);\n    const normalizedDelegate = getAddress(delegateAddress);\n    return this.#withPropagationRetry(options?.waitForPropagation ?? true, () =>\n      this.#decrypt(encryptedValues, {\n        requesterAddress: getAddress(accountAddress),\n        aclActorAddress: normalizedDelegator,\n        resolveCredentials: (contractAddresses) =>\n          this.#credentialService.grantPermit(contractAddresses, normalizedDelegator),\n        validate: (contractAddresses) =>\n          this.#assertAllDelegationsActive(contractAddresses, {\n            delegatorAddress: normalizedDelegator,\n            delegateAddress: normalizedDelegate,\n          }),\n        decryptContract: async ({\n          credentials,\n          contractAddress,\n          // oxlint-disable-next-line no-shadow\n          encryptedValues,\n        }) => {\n          return this.#relayer.delegatedUserDecrypt({\n            encryptedValues: encryptedValues,\n            contractAddress,\n            ...resolveDelegatedDecryptPermit(credentials, contractAddress),\n            delegateAddress: normalizedDelegate,\n          });\n        },\n        errorMessage: \"Failed to decrypt delegated encrypted values\",\n        delegated: true,\n      }),\n    );\n  }\n\n  /**\n   * Absorb the gateway propagation window on the delegated path: retry `attempt`\n   * (bounded by {@link DELEGATION_PROPAGATION_RETRY_BUDGET_MS}) while it fails\n   * with a transient {@link DelegationNotPropagatedError}. Every other error —\n   * including a missing/expired grant surfaced by the pre-check — throws\n   * immediately, and passing `waitForPropagation: false` disables the retry so\n   * the first not-propagated response propagates unchanged.\n   */\n  async #withPropagationRetry<T>(\n    waitForPropagation: boolean,\n    attempt: () => Promise<T>,\n  ): Promise<T> {\n    // Fixed-interval polling across the budget: e.g. 30s / 2s = 15 gaps, so 16\n    // attempts. Bounded (no open-ended loop) and deterministic under fake timers.\n    const maxAttempts =\n      Math.floor(\n        DELEGATION_PROPAGATION_RETRY_BUDGET_MS / DELEGATION_PROPAGATION_RETRY_INTERVAL_MS,\n      ) + 1;\n    let lastError: unknown;\n    for (let i = 0; i < maxAttempts; i++) {\n      try {\n        return await attempt();\n      } catch (error) {\n        lastError = error;\n        const canRetry =\n          i < maxAttempts - 1 &&\n          waitForPropagation &&\n          error instanceof DelegationNotPropagatedError;\n        if (!canRetry) {\n          throw error;\n        }\n        await sleep(DELEGATION_PROPAGATION_RETRY_INTERVAL_MS);\n      }\n    }\n    throw lastError;\n  }\n\n  async delegatedBatchDecryptHandlesAs({\n    encryptedInputs,\n    delegatorAddress,\n    delegateAddress,\n    accountAddress,\n    maxConcurrency = 5,\n    waitForPropagation = true,\n  }: {\n    encryptedInputs: EncryptedInput[];\n    delegatorAddress: Address;\n    delegateAddress: Address;\n    accountAddress: Address;\n    maxConcurrency?: number;\n    waitForPropagation?: boolean;\n  }): Promise<BatchDecryptResult> {\n    const items: BatchDecryptItem[] = encryptedInputs.map((h) => ({\n      encryptedValue: h.encryptedValue,\n      contractAddress: getAddress(h.contractAddress),\n    }));\n    if (items.length === 0) {\n      return { items };\n    }\n    const normalizedAccount = getAddress(accountAddress);\n\n    try {\n      const decrypted = await this.delegatedUserDecrypt(\n        items.map(({ encryptedValue, contractAddress }) => ({ encryptedValue, contractAddress })),\n        delegatorAddress,\n        delegateAddress,\n        normalizedAccount,\n        { waitForPropagation },\n      );\n      for (const item of items) {\n        this.#setHandleResult(item, decrypted);\n      }\n      return { items };\n    } catch (error) {\n      if (isFatalBatchError(error)) {\n        throw error;\n      }\n      if (items.length === 1) {\n        const [item = this.#missingBatchItem()] = items;\n        item.error = this.#toZamaError(error, \"Failed to decrypt delegated encrypted values\", {\n          isDelegated: true,\n          contractAddress: item.contractAddress,\n          account: getAddress(delegatorAddress),\n        });\n        return { items };\n      }\n    }\n\n    // `pLimit` has no cancellation: once one worker rethrows a fatal error\n    // (e.g. an RPC rate-limit), the sibling workers would otherwise keep\n    // draining the queue and re-hitting the already-throttled endpoint. A\n    // shared flag lets the still-queued items short-circuit instead.\n    let aborted = false;\n    await pLimit(\n      items.map((item) => async () => {\n        if (aborted) {\n          return;\n        }\n        try {\n          // The batch attempt above already rode out the propagation window for\n          // the whole set; fail fast here so a still-unsynced delegation records\n          // a per-item error instead of each item re-spending the full budget.\n          const decrypted = await this.delegatedUserDecrypt(\n            [{ encryptedValue: item.encryptedValue, contractAddress: item.contractAddress }],\n            delegatorAddress,\n            delegateAddress,\n            normalizedAccount,\n            { waitForPropagation: false },\n          );\n          this.#setHandleResult(item, decrypted);\n        } catch (error) {\n          if (isFatalBatchError(error)) {\n            aborted = true;\n            throw error;\n          }\n          item.error = this.#toZamaError(error, \"Failed to decrypt delegated encrypted values\", {\n            isDelegated: true,\n            contractAddress: item.contractAddress,\n            account: getAddress(delegatorAddress),\n          });\n        }\n      }),\n      maxConcurrency,\n    );\n\n    return { items };\n  }\n\n  async #decrypt(\n    handles: EncryptedInput[],\n    strategy: DecryptionStrategy,\n  ): Promise<Record<EncryptedValue, ClearValue>> {\n    if (handles.length === 0) {\n      return {};\n    }\n\n    const normalized = handles.map((h) => ({\n      encryptedValue: h.encryptedValue,\n      contractAddress: getAddress(h.contractAddress),\n    }));\n    const result: Record<EncryptedValue, ClearValue> = {};\n    const nonZero: EncryptedInput[] = [];\n\n    for (const h of normalized) {\n      if (isEncryptedValueZero(h.encryptedValue)) {\n        result[h.encryptedValue] = 0n;\n      } else {\n        nonZero.push(h);\n      }\n    }\n\n    if (nonZero.length === 0) {\n      return result;\n    }\n\n    const allContracts = Array.from(new Set(normalized.map((h) => h.contractAddress)));\n    const nonZeroContracts = Array.from(new Set(nonZero.map((h) => h.contractAddress)));\n    if (strategy.validate) {\n      try {\n        await strategy.validate(nonZeroContracts);\n      } catch (error) {\n        // The delegation pre-check makes on-chain reads too; classify a throttled\n        // RPC here as well so delegated decrypt branches deterministically.\n        if (isRpcRateLimitError(error)) {\n          throw this.#rpcRateLimitError(error, \"the delegation pre-check\");\n        }\n        throw error;\n      }\n    }\n\n    const uncached: EncryptedInput[] = [];\n    for (const h of nonZero) {\n      const cached = await this.#cache.get(\n        strategy.requesterAddress,\n        h.contractAddress,\n        h.encryptedValue,\n      );\n      if (cached !== null) {\n        result[h.encryptedValue] = cached;\n      } else {\n        uncached.push(h);\n      }\n    }\n\n    if (uncached.length === 0) {\n      return result;\n    }\n\n    const credentials = await strategy.resolveCredentials(allContracts);\n\n    const byContract = new Map<Address, EncryptedValue[]>();\n    for (const h of uncached) {\n      const existing = byContract.get(h.contractAddress);\n      if (existing) {\n        existing.push(h.encryptedValue);\n      } else {\n        byContract.set(h.contractAddress, [h.encryptedValue]);\n      }\n    }\n\n    const t0 = Date.now();\n    const uncachedEncryptedValues = uncached.map((h) => h.encryptedValue);\n    try {\n      this.#emitEvent({\n        type: ZamaSDKEvents.DecryptStart,\n        encryptedValues: uncachedEncryptedValues,\n      });\n\n      await pLimit(\n        [...byContract.entries()].map(([contractAddress, encryptedValues]) => async () => {\n          // Classify per contract so a not-entitled / relayer failure carries the\n          // exact contract + ACL actor (the request context the worker no longer\n          // threads). Already-typed errors pass straight through.\n          let decrypted: Record<EncryptedValue, ClearValue>;\n          try {\n            decrypted = await strategy.decryptContract({\n              credentials,\n              contractAddress,\n              encryptedValues,\n            });\n          } catch (error) {\n            throw wrapDecryptError(error, strategy.errorMessage, {\n              isDelegated: strategy.delegated,\n              contractAddress,\n              account: strategy.aclActorAddress,\n            });\n          }\n\n          for (const [encryptedValue, value] of Object.entries(decrypted)) {\n            result[encryptedValue as EncryptedValue] = value;\n            await this.#cache.set(\n              strategy.requesterAddress,\n              contractAddress,\n              encryptedValue as EncryptedValue,\n              value,\n            );\n          }\n        }),\n        5,\n      );\n\n      const uncachedResult: Record<EncryptedValue, ClearValue> = {};\n      for (const encryptedValue of uncachedEncryptedValues) {\n        const value = result[encryptedValue];\n        if (value !== undefined) {\n          uncachedResult[encryptedValue] = value;\n        }\n      }\n      this.#emitEvent({\n        type: ZamaSDKEvents.DecryptEnd,\n        durationMs: Date.now() - t0,\n        encryptedValues: uncachedEncryptedValues,\n        result: uncachedResult,\n      });\n      return result;\n    } catch (error) {\n      // Per-contract failures are already classified into a typed ZamaError whose\n      // `cause` is the original failure; surface that original in the observability\n      // event so monitoring keeps the root-cause message.\n      const original =\n        error instanceof ZamaError && error.cause instanceof Error ? error.cause : error;\n      this.#emitEvent({\n        type: ZamaSDKEvents.DecryptError,\n        error: toError(original),\n        durationMs: Date.now() - t0,\n        encryptedValues: uncachedEncryptedValues,\n      });\n      // The per-contract wrap above already classified these; this is a passthrough\n      // for them plus a fallback for any non-contract failure (e.g. caching).\n      throw wrapDecryptError(error, strategy.errorMessage, { isDelegated: strategy.delegated });\n    }\n  }\n\n  /** Build an `RpcRateLimitError` for a throttled on-chain read. */\n  #rpcRateLimitError(error: unknown, context: string): RpcRateLimitError {\n    return new RpcRateLimitError(`RPC provider rate-limited ${context}; retry with backoff.`, {\n      cause: error,\n      retryAfter: extractRetryAfter(error),\n    });\n  }\n\n  #setHandleResult(item: BatchDecryptItem, decrypted: Record<EncryptedValue, ClearValue>): void {\n    const value = decrypted[item.encryptedValue];\n    if (value === undefined) {\n      item.error = new DecryptionFailedError(\n        `Batch delegated decryption returned no value for encrypted value ${item.encryptedValue} on contract ${item.contractAddress}`,\n      );\n      return;\n    }\n    item.value = value;\n  }\n\n  #toZamaError(error: unknown, fallbackMessage: string, ctx?: DecryptErrorContext): ZamaError {\n    return error instanceof ZamaError ? error : wrapDecryptError(error, fallbackMessage, ctx);\n  }\n\n  #missingBatchItem(): never {\n    throw new DecryptionFailedError(\"Batch delegated decryption invariant failed: missing item\");\n  }\n\n  async #assertAllDelegationsActive(\n    contractAddresses: readonly Address[],\n    { delegatorAddress, delegateAddress }: { delegatorAddress: Address; delegateAddress: Address },\n  ): Promise<void> {\n    const inactive = await this.#delegationService.findInactiveDelegations(\n      contractAddresses,\n      delegatorAddress,\n      delegateAddress,\n    );\n    if (inactive.size === 0) {\n      return;\n    }\n    for (const error of inactive.values()) {\n      throw error;\n    }\n  }\n}\n","import type { ZamaError } from \"./base\";\nimport {\n  AclPausedError,\n  DelegationContractIsSelfError,\n  DelegationCooldownError,\n  DelegationDelegateEqualsContractError,\n  DelegationExpirationTooSoonError,\n  DelegationExpiryUnchangedError,\n  DelegationNotFoundError,\n  DelegationSelfNotAllowedError,\n} from \"./delegation\";\n\n/** Extract the decoded error name from a viem ContractFunctionRevertedError. */\nfunction extractRevertErrorName(error: unknown): string | null {\n  if (!(error instanceof Error)) {\n    return null;\n  }\n  const cause = error.cause;\n  if (typeof cause !== \"object\" || cause === null || !(\"data\" in cause)) {\n    return null;\n  }\n  const { data } = cause;\n  if (typeof data !== \"object\" || data === null || !(\"errorName\" in data)) {\n    return null;\n  }\n  return typeof data.errorName === \"string\" ? data.errorName : null;\n}\n\n/** ACL error name -> typed SDK error mapping. */\nconst ACL_ERROR_MAP = {\n  AlreadyDelegatedOrRevokedInSameBlock: (cause) =>\n    new DelegationCooldownError(\n      \"Only one delegate/revoke per (delegator, delegate, contract) per block. Wait for the next block before retrying.\",\n      { cause },\n    ),\n  SenderCannotBeContractAddress: (cause) =>\n    new DelegationContractIsSelfError(\"The contract address cannot be the caller address.\", {\n      cause,\n    }),\n  EnforcedPause: (cause) =>\n    new AclPausedError(\n      \"The ACL contract is paused. Delegation operations are temporarily disabled.\",\n      { cause },\n    ),\n  SenderCannotBeDelegate: (cause) =>\n    new DelegationSelfNotAllowedError(\"Cannot delegate to yourself (delegate === msg.sender).\", {\n      cause,\n    }),\n  DelegateCannotBeContractAddress: (cause) =>\n    new DelegationDelegateEqualsContractError(\n      \"Delegate address cannot be the same as the contract address.\",\n      { cause },\n    ),\n  ExpirationDateBeforeOneHour: (cause) =>\n    new DelegationExpirationTooSoonError(\"Expiration date must be at least 1 hour in the future.\", {\n      cause,\n    }),\n  ExpirationDateAlreadySetToSameValue: (cause) =>\n    new DelegationExpiryUnchangedError(\"The new expiration date is the same as the current one.\", {\n      cause,\n    }),\n  NotDelegatedYet: (cause) =>\n    new DelegationNotFoundError(\"Cannot revoke: no active delegation exists.\", { cause }),\n} satisfies Record<string, (cause: unknown) => ZamaError>;\n\nfunction isAclRevertName(name: string): name is keyof typeof ACL_ERROR_MAP {\n  return name in ACL_ERROR_MAP;\n}\n\n/**\n * Map known ACL Solidity revert error names to typed ZamaError subclasses.\n * Prefers viem's structured `error.cause.data.errorName` when available,\n * falling back to string-includes matching on the error message.\n * Returns `null` if the revert reason is not recognized.\n * @internal\n */\nexport function matchAclRevert(error: unknown, mappedCause: unknown): ZamaError | null {\n  // Prefer structured error data from viem's ContractFunctionRevertedError\n  const errorName = extractRevertErrorName(error);\n  if (errorName && isAclRevertName(errorName)) {\n    return ACL_ERROR_MAP[errorName](mappedCause);\n  }\n\n  // Fallback: string matching for non-viem RPC providers\n  const message = error instanceof Error ? error.message : String(error);\n  for (const [name, factory] of Object.entries(ACL_ERROR_MAP)) {\n    if (message.includes(name)) {\n      return factory(mappedCause);\n    }\n  }\n\n  return null;\n}\n","import { getAddress, type Address } from \"viem\";\nimport {\n  delegateForUserDecryptionContract,\n  getDelegationExpiryContract,\n  MAX_UINT64,\n  revokeDelegationContract,\n} from \"../contracts\";\nimport {\n  DelegationDelegateEqualsContractError,\n  DelegationExpirationTooSoonError,\n  DelegationExpiredError,\n  DelegationExpiryUnchangedError,\n  DelegationNotFoundError,\n  DelegationSelfNotAllowedError,\n  TransactionRevertedError,\n} from \"../errors\";\nimport { matchAclRevert } from \"../errors/acl-revert\";\nimport type { TransactionOperation, ZamaSDKEventInput } from \"../events/sdk-events\";\nimport type { RelayerDispatcher } from \"../relayer/relayer-dispatcher\";\nimport type {\n  GenericProvider,\n  GenericSigner,\n  TransactionResult,\n  WriteContractConfig,\n} from \"../types\";\nimport { submitTransaction } from \"../utils/submit-transaction\";\nimport type { GenericLogger } from \"../worker/worker.types\";\n\ntype AclTransactionOperation = Extract<\n  TransactionOperation,\n  \"delegateDecryption\" | \"revokeDelegation\"\n>;\n\nexport class DelegationService {\n  readonly #provider: GenericProvider;\n  readonly #relayer: RelayerDispatcher;\n  readonly #emitEvent: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;\n  readonly #logger: GenericLogger;\n\n  constructor({\n    provider,\n    relayer,\n    emitEvent = () => {},\n    logger,\n  }: {\n    provider: GenericProvider;\n    relayer: RelayerDispatcher;\n    logger: GenericLogger;\n    emitEvent?: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;\n  }) {\n    this.#provider = provider;\n    this.#relayer = relayer;\n    this.#logger = logger;\n    this.#emitEvent = emitEvent;\n  }\n\n  async delegateDecryption(\n    signer: GenericSigner,\n    {\n      contractAddress,\n      delegateAddress,\n      delegatorAddress,\n      expirationDate,\n    }: {\n      contractAddress: Address;\n      delegateAddress: Address;\n      delegatorAddress: Address;\n      expirationDate?: Date;\n    },\n  ): Promise<TransactionResult> {\n    if (expirationDate && expirationDate.getTime() < Date.now() + 3600_000) {\n      throw new DelegationExpirationTooSoonError(\n        \"Expiration date must be at least 1 hour in the future\",\n      );\n    }\n\n    const normalizedContract = getAddress(contractAddress);\n    const normalizedDelegate = getAddress(delegateAddress);\n    const normalizedDelegator = getAddress(delegatorAddress);\n\n    if (normalizedDelegate === normalizedDelegator) {\n      throw new DelegationSelfNotAllowedError(\n        \"Cannot delegate to yourself (delegate === msg.sender).\",\n      );\n    }\n\n    if (normalizedDelegate === normalizedContract) {\n      throw new DelegationDelegateEqualsContractError(\n        `Delegate address cannot be the same as the contract address (${normalizedContract}).`,\n      );\n    }\n\n    const acl = await this.#relayer.getAclAddress();\n    const expDate = expirationDate\n      ? BigInt(Math.floor(expirationDate.getTime() / 1000))\n      : MAX_UINT64;\n\n    let currentExpiry: bigint;\n    try {\n      currentExpiry = await this.getDelegationExpiry({\n        contractAddress: normalizedContract,\n        delegatorAddress: normalizedDelegator,\n        delegateAddress: normalizedDelegate,\n      });\n    } catch (error) {\n      this.#logger.warn(\"delegateDecryption: pre-flight expiry check failed\", { error });\n      currentExpiry = -1n;\n    }\n    if (currentExpiry === expDate) {\n      throw new DelegationExpiryUnchangedError(\n        `The new expiration date (${expDate}) is the same as the current one. No on-chain change needed.`,\n      );\n    }\n\n    return this.#submitAclTransaction({\n      operation: \"delegateDecryption\",\n      signer,\n      contractAddress,\n      config: delegateForUserDecryptionContract(\n        acl,\n        normalizedDelegate,\n        normalizedContract,\n        expDate,\n      ),\n    });\n  }\n\n  async revokeDelegation(\n    signer: GenericSigner,\n    {\n      contractAddress,\n      delegateAddress,\n      delegatorAddress,\n    }: { contractAddress: Address; delegateAddress: Address; delegatorAddress: Address },\n  ): Promise<TransactionResult> {\n    const normalizedContract = getAddress(contractAddress);\n    const normalizedDelegate = getAddress(delegateAddress);\n    const normalizedDelegator = getAddress(delegatorAddress);\n    const acl = await this.#relayer.getAclAddress();\n\n    let currentExpiry: bigint;\n    try {\n      currentExpiry = await this.getDelegationExpiry({\n        contractAddress: normalizedContract,\n        delegatorAddress: normalizedDelegator,\n        delegateAddress: normalizedDelegate,\n      });\n    } catch (error) {\n      this.#logger.warn(\"revokeDelegation: pre-flight expiry check failed\", { error });\n      currentExpiry = 1n;\n    }\n    if (currentExpiry === 0n) {\n      throw new DelegationNotFoundError(\n        `No active delegation found for delegate ${normalizedDelegate} on contract ${normalizedContract}.`,\n      );\n    }\n\n    return this.#submitAclTransaction({\n      operation: \"revokeDelegation\",\n      signer,\n      contractAddress,\n      config: revokeDelegationContract(acl, normalizedDelegate, normalizedContract),\n    });\n  }\n\n  async isDelegated(params: {\n    contractAddress: Address;\n    delegatorAddress: Address;\n    delegateAddress: Address;\n  }): Promise<boolean> {\n    const expiry = await this.getDelegationExpiry(params);\n    if (expiry === 0n) {\n      return false;\n    }\n    if (expiry === MAX_UINT64) {\n      return true;\n    }\n    const now = await this.#provider.getBlockTimestamp();\n    return expiry > now;\n  }\n\n  async getDelegationExpiry({\n    contractAddress,\n    delegatorAddress,\n    delegateAddress,\n  }: {\n    contractAddress: Address;\n    delegatorAddress: Address;\n    delegateAddress: Address;\n  }): Promise<bigint> {\n    const acl = await this.#relayer.getAclAddress();\n    return this.#provider.readContract(\n      getDelegationExpiryContract(\n        acl,\n        getAddress(delegatorAddress),\n        getAddress(delegateAddress),\n        getAddress(contractAddress),\n      ),\n    );\n  }\n\n  async #submitAclTransaction({\n    operation,\n    signer,\n    contractAddress,\n    config,\n  }: {\n    operation: AclTransactionOperation;\n    signer: GenericSigner;\n    contractAddress: Address;\n    config: WriteContractConfig;\n  }): Promise<TransactionResult> {\n    try {\n      return await submitTransaction({\n        operation,\n        signer,\n        provider: this.#provider,\n        config,\n        emit: (input) => this.#emitEvent(input, contractAddress),\n        logger: this.#logger,\n      });\n    } catch (error) {\n      this.#throwAclRevertIfMatched(error);\n      throw error;\n    }\n  }\n\n  #throwAclRevertIfMatched(error: unknown): void {\n    if (!(error instanceof TransactionRevertedError)) {\n      return;\n    }\n    const mapped = matchAclRevert(error.cause ?? error, error);\n    if (mapped) {\n      throw mapped;\n    }\n  }\n\n  async findInactiveDelegations(\n    contractAddresses: readonly Address[],\n    delegatorAddress: Address,\n    delegateAddress: Address,\n  ): Promise<Map<Address, DelegationNotFoundError | DelegationExpiredError>> {\n    const inactive = new Map<Address, DelegationNotFoundError | DelegationExpiredError>();\n    await Promise.all(\n      contractAddresses.map(async (contractAddress) => {\n        try {\n          await this.assertDelegationActive(contractAddress, delegatorAddress, delegateAddress);\n        } catch (error) {\n          if (error instanceof DelegationNotFoundError || error instanceof DelegationExpiredError) {\n            const normalizedContract = getAddress(contractAddress);\n            inactive.set(normalizedContract, error);\n            return;\n          }\n          throw error;\n        }\n      }),\n    );\n    return inactive;\n  }\n\n  async assertDelegationActive(\n    contractAddress: Address,\n    delegatorAddress: Address,\n    delegateAddress: Address,\n  ): Promise<void> {\n    const normalizedContract = getAddress(contractAddress);\n    const normalizedDelegator = getAddress(delegatorAddress);\n    const normalizedDelegate = getAddress(delegateAddress);\n    const expiry = await this.getDelegationExpiry({\n      contractAddress: normalizedContract,\n      delegatorAddress: normalizedDelegator,\n      delegateAddress: normalizedDelegate,\n    });\n    if (expiry === 0n) {\n      throw new DelegationNotFoundError(\n        `No active delegation from ${normalizedDelegator} to ${normalizedDelegate} for ${normalizedContract}`,\n      );\n    }\n    if (expiry !== MAX_UINT64) {\n      const now = await this.#provider.getBlockTimestamp();\n      if (expiry <= now) {\n        throw new DelegationExpiredError(\n          `Delegation from ${normalizedDelegator} to ${normalizedDelegate} for ${normalizedContract} has expired`,\n        );\n      }\n    }\n  }\n}\n","import { wrapEncryptError } from \"../errors\";\nimport type { ZamaSDKEventInput } from \"../events/sdk-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { RelayerDispatcher } from \"../relayer/relayer-dispatcher\";\nimport type { EncryptParams, EncryptResult } from \"../relayer/relayer-sdk.types\";\nimport { toError } from \"../utils\";\n\nexport class EncryptionService {\n  readonly #relayer: RelayerDispatcher;\n  readonly #emitEvent: (\n    input: ZamaSDKEventInput,\n    tokenAddress?: EncryptParams[\"contractAddress\"],\n  ) => void;\n\n  constructor({\n    relayer,\n    emitEvent,\n  }: {\n    relayer: RelayerDispatcher;\n    emitEvent: (input: ZamaSDKEventInput, tokenAddress?: EncryptParams[\"contractAddress\"]) => void;\n  }) {\n    this.#relayer = relayer;\n    this.#emitEvent = emitEvent;\n  }\n\n  async encrypt(params: EncryptParams): Promise<EncryptResult> {\n    const t0 = Date.now();\n    try {\n      this.#emitEvent({ type: ZamaSDKEvents.EncryptStart }, params.contractAddress);\n      const result = await this.#relayer.encrypt(params);\n      this.#emitEvent(\n        { type: ZamaSDKEvents.EncryptEnd, durationMs: Date.now() - t0 },\n        params.contractAddress,\n      );\n      return result;\n    } catch (error) {\n      this.#emitEvent(\n        { type: ZamaSDKEvents.EncryptError, error: toError(error), durationMs: Date.now() - t0 },\n        params.contractAddress,\n      );\n      throw wrapEncryptError(error, \"Encryption failed\");\n    }\n  }\n}\n","import type { CredentialService } from \"../credentials/credential-service\";\nimport type { RelayerDispatcher } from \"../relayer/relayer-dispatcher\";\nimport type { GenericSigner, WalletAccountChange, WalletAccountListener } from \"../types\";\nimport { swallow } from \"../utils\";\nimport type { CachingService } from \"./caching-service\";\nimport type { GenericLogger } from \"../worker/worker.types\";\n\nexport type LifecycleServiceOptions = {\n  signer?: GenericSigner;\n  relayer: RelayerDispatcher;\n  cachingService: CachingService;\n  credentialService?: CredentialService;\n  logger: GenericLogger;\n};\n\n/**\n * Owns signer-lifecycle wiring for {@link ZamaSDK}: subscribes to the signer's\n * wallet-account store on construction, runs the SDK-side cleanup (credential\n * rotation, decrypt-cache invalidation, relayer chain switch) on every change,\n * then fans out to external listeners. Unsubscribes on {@link dispose}.\n *\n * @internal — consumed by ZamaSDK; not part of the public surface.\n */\nexport class LifecycleService {\n  readonly #signer: GenericSigner | undefined;\n  readonly #relayer: RelayerDispatcher;\n  readonly #cachingService: CachingService;\n  readonly #credentialService: CredentialService | undefined;\n  readonly #logger: GenericLogger;\n  readonly #walletAccountListeners = new Set<WalletAccountListener>();\n  #unsubscribeSigner?: () => void;\n\n  constructor(opts: LifecycleServiceOptions) {\n    this.#signer = opts.signer;\n    this.#relayer = opts.relayer;\n    this.#cachingService = opts.cachingService;\n    this.#credentialService = opts.credentialService;\n    this.#logger = opts.logger;\n    if (this.#signer) {\n      this.#unsubscribeSigner = this.#signer.walletAccount.subscribe((change) => {\n        this.#handleWalletAccountChange(change).catch((error) => {\n          this.#logger.warn(\"wallet account handler failed\", { error });\n        });\n      });\n    }\n  }\n\n  onWalletAccountChange(listener: WalletAccountListener): () => void {\n    this.#walletAccountListeners.add(listener);\n    return () => {\n      this.#walletAccountListeners.delete(listener);\n    };\n  }\n\n  dispose(): void {\n    this.#unsubscribeSigner?.();\n    this.#unsubscribeSigner = undefined;\n    this.#walletAccountListeners.clear();\n  }\n\n  async #handleWalletAccountChange(change: WalletAccountChange): Promise<void> {\n    const prev = change.previous;\n    const next = change.next;\n    // switchChain runs first so credential cleanup, decrypt-cache invalidation,\n    // and external listeners observe the dispatcher on next.chainId. Downstream\n    // keypair warming (driven by listeners — see ZamaProvider) therefore\n    // dispatches against the wallet chain rather than chains[0]. `swallow`\n    // suspends one microtask for error containment, not for I/O —\n    // RelayerDispatcher.switchChain is synchronous.\n    const nextChainId = next?.chainId;\n    if (nextChainId !== undefined) {\n      await swallow(\n        \"switch relayer chain\",\n        () => this.#relayer.switchChain(nextChainId),\n        this.#logger,\n      );\n    }\n    const credentialService = this.#credentialService;\n    if (credentialService) {\n      await swallow(\n        \"credential wallet account change\",\n        () => credentialService.handleWalletAccountChange(prev, next),\n        this.#logger,\n      );\n    }\n    if (prev) {\n      await swallow(\n        \"clear decrypt cache\",\n        () => this.#cachingService.clearForRequester(prev.address),\n        this.#logger,\n      );\n    }\n    await Promise.all(\n      Array.from(this.#walletAccountListeners, (listener) =>\n        swallow(\"wallet account listener\", () => listener(change), this.#logger),\n      ),\n    );\n  }\n}\n","/**\n * Framework-agnostic event decoders for confidential token contracts.\n * Works with raw log data from any provider.\n */\n\nimport type { EncryptedValue } from \"../relayer/relayer-sdk.types\";\nimport { getAddress, keccak256, toBytes, type Address, type Hex } from \"viem\";\nimport { prefixHex } from \"../utils\";\nimport type { RawLog } from \"../types/transaction\";\nexport type { RawLog } from \"../types/transaction\";\n\nfunction eventTopic(signature: string): Hex {\n  return keccak256(toBytes(signature));\n}\n\n// ---------------------------------------------------------------------------\n// Event topic0 constants (keccak256 of canonical signature)\n// ---------------------------------------------------------------------------\n\n/**\n * Event topic0 constants (keccak256 of the canonical Solidity signature).\n * Pass to `getLogs({ topics: [Object.values(Topics)] })` to fetch all events.\n */\nexport const Topics = {\n  /** `ConfidentialTransfer(address indexed from, address indexed to, bytes32 indexed amount)` */\n  ConfidentialTransfer: eventTopic(\"ConfidentialTransfer(address,address,bytes32)\"),\n  /** `Wrap(address indexed to, uint256 roundedAmount, euint64 encryptedWrappedAmount)` */\n  Wrap: eventTopic(\"Wrap(address,uint256,bytes32)\"),\n  /** `UnwrapRequested(address indexed receiver, bytes32 indexed unwrapRequestId, bytes32 amount)` */\n  UnwrapRequested: eventTopic(\"UnwrapRequested(address,bytes32,bytes32)\"),\n  /** `UnwrapFinalized(address indexed receiver, bytes32 indexed unwrapRequestId, bytes32 encryptedAmount, uint64 cleartextAmount)` */\n  UnwrapFinalized: eventTopic(\"UnwrapFinalized(address,bytes32,bytes32,uint64)\"),\n} as const;\n\n// ---------------------------------------------------------------------------\n// Typed event interfaces\n// ---------------------------------------------------------------------------\n\n/** Decoded `ConfidentialTransfer` event — an encrypted token transfer. */\nexport interface ConfidentialTransferEvent {\n  readonly eventName: \"ConfidentialTransfer\";\n  /** Sender address. */\n  readonly from: Address;\n  /** Receiver address. */\n  readonly to: Address;\n  /** FHE encrypted value for the transferred amount. */\n  readonly encryptedAmount: EncryptedValue;\n}\n\n/**\n * Decoded `Wrap` event — an ERC-20 shield (wrap) operation. Emitted alongside a\n * `ConfidentialTransfer(from=zeroAddress, ...)`; `encryptedWrappedAmount` is the same FHE\n * handle that lands in `ConfidentialTransfer.encryptedAmount`.\n */\nexport interface WrapEvent {\n  readonly eventName: \"Wrap\";\n  /** Receiver of the minted confidential tokens. */\n  readonly to: Address;\n  /** Cleartext underlying ERC-20 tokens deposited, rounded down to a multiple of the rate. */\n  readonly roundedAmount: bigint;\n  /** FHE encrypted value for the wrapped (minted) amount. */\n  readonly encryptedWrappedAmount: EncryptedValue;\n}\n\n/** Decoded `UnwrapRequested` event — an unshield request submitted. */\nexport interface UnwrapRequestedEvent {\n  readonly eventName: \"UnwrapRequested\";\n  /** Address that will receive the unwrapped ERC-20 tokens. */\n  readonly receiver: Address;\n  /** FHE encrypted value for the requested unshield amount. */\n  readonly encryptedAmount: EncryptedValue;\n  /** Request identifier from the `UnwrapRequested` event topic. */\n  readonly unwrapRequestId?: EncryptedValue;\n}\n\n/** Decoded `UnwrapFinalized` event — an unshield completed on-chain. */\nexport interface UnwrapFinalizedEvent {\n  readonly eventName: \"UnwrapFinalized\";\n  /** Address receiving the unwrapped ERC-20 tokens. */\n  readonly receiver: Address;\n  /** FHE encrypted value of the burnt confidential balance. */\n  readonly encryptedAmount: EncryptedValue;\n  /** Cleartext amount of underlying ERC-20 tokens returned. */\n  readonly cleartextAmount: bigint;\n  /** Request identifier from the `UnwrapFinalized` event topic. */\n  readonly unwrapRequestId?: EncryptedValue;\n}\n\n/** Union of all decoded confidential token event types. */\nexport type OnChainEvent =\n  | ConfidentialTransferEvent\n  | WrapEvent\n  | UnwrapRequestedEvent\n  | UnwrapFinalizedEvent;\n\n// ---------------------------------------------------------------------------\n// ABI decoding helpers (no external deps)\n// ---------------------------------------------------------------------------\n\nfunction topicToAddress(topic: Hex): Address {\n  return getAddress(prefixHex(topic.slice(-40)));\n}\n\nfunction topicToBytes32(topic: Hex): EncryptedValue {\n  // EVM topics are already 32-byte 0x-prefixed hex — cast directly\n  return topic as EncryptedValue;\n}\n\nfunction wordAt(data: Hex, index: number): string {\n  // data starts with \"0x\", each word is 64 hex chars (32 bytes)\n  const start = 2 + index * 64;\n  const word = data.slice(start, start + 64);\n  return word.length === 64 ? word : word.padEnd(64, \"0\");\n}\n\nfunction wordToAddress(data: Hex, index: number): Address {\n  return getAddress(prefixHex(wordAt(data, index).slice(-40)));\n}\n\nfunction wordToBigInt(data: Hex, index: number): bigint {\n  return BigInt(\"0x\" + wordAt(data, index));\n}\n\nfunction wordToBytes32(data: Hex, index: number): EncryptedValue {\n  // wordAt returns exactly 64 hex chars — prefix and cast directly\n  return prefixHex(wordAt(data, index)) as EncryptedValue;\n}\n\n// ---------------------------------------------------------------------------\n// Individual decoders\n// ---------------------------------------------------------------------------\n\n/**\n * ConfidentialTransfer(address indexed from, address indexed to, bytes32 indexed amount)\n * All 3 params indexed → topics[1..3], no data.\n */\nexport function decodeConfidentialTransfer(log: RawLog): ConfidentialTransferEvent | null {\n  if (log.topics[0] !== Topics.ConfidentialTransfer) {\n    return null;\n  }\n  if (log.topics.length < 4) {\n    return null;\n  }\n\n  return {\n    eventName: \"ConfidentialTransfer\",\n    from: topicToAddress(log.topics[1]!),\n    to: topicToAddress(log.topics[2]!),\n    encryptedAmount: topicToBytes32(log.topics[3]!),\n  };\n}\n\n/**\n * Wrap(address indexed to, uint256 roundedAmount, euint64 encryptedWrappedAmount)\n * Indexed: to (topics[1])\n * Data: roundedAmount (uint256), encryptedWrappedAmount (bytes32)\n */\nexport function decodeWrap(log: RawLog): WrapEvent | null {\n  if (log.topics[0] !== Topics.Wrap) {\n    return null;\n  }\n  if (log.topics.length < 2) {\n    return null;\n  }\n\n  return {\n    eventName: \"Wrap\",\n    to: topicToAddress(log.topics[1]!),\n    roundedAmount: wordToBigInt(log.data, 0),\n    encryptedWrappedAmount: wordToBytes32(log.data, 1),\n  };\n}\n\n/**\n * UnwrapRequested(address indexed receiver, bytes32 indexed unwrapRequestId, bytes32 amount)\n */\nexport function decodeUnwrapRequested(log: RawLog): UnwrapRequestedEvent | null {\n  if (log.topics[0] !== Topics.UnwrapRequested) {\n    return null;\n  }\n  if (log.topics.length < 3) {\n    return null;\n  }\n\n  return {\n    eventName: \"UnwrapRequested\",\n    receiver: topicToAddress(log.topics[1]!),\n    unwrapRequestId: topicToBytes32(log.topics[2]!),\n    encryptedAmount: wordToBytes32(log.data, 0),\n  };\n}\n\n/**\n * UnwrapFinalized(address indexed receiver, bytes32 indexed unwrapRequestId, bytes32 encryptedAmount, uint64 cleartextAmount)\n */\nexport function decodeUnwrapFinalized(log: RawLog): UnwrapFinalizedEvent | null {\n  if (log.topics[0] !== Topics.UnwrapFinalized) {\n    return null;\n  }\n  if (log.topics.length < 3) {\n    return null;\n  }\n\n  return {\n    eventName: \"UnwrapFinalized\",\n    receiver: topicToAddress(log.topics[1]!),\n    unwrapRequestId: topicToBytes32(log.topics[2]!),\n    encryptedAmount: wordToBytes32(log.data, 0),\n    cleartextAmount: wordToBigInt(log.data, 1),\n  };\n}\n\n// ---------------------------------------------------------------------------\n// Convenience helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Try all decoders on a single log and return the first match, or `null`.\n *\n * @example\n * ```ts\n * const event = decodeOnChainEvent(log);\n * if (event?.eventName === \"ConfidentialTransfer\") {\n *   console.log(event.from, event.to);\n * }\n * ```\n */\nexport function decodeOnChainEvent(log: RawLog): OnChainEvent | null {\n  return (\n    decodeConfidentialTransfer(log) ??\n    decodeWrap(log) ??\n    decodeUnwrapRequested(log) ??\n    decodeUnwrapFinalized(log)\n  );\n}\n\n/**\n * Batch-decode an array of logs, skipping unrecognized entries.\n *\n * @example\n * ```ts\n * const events = decodeOnChainEvents(receipt.logs);\n * ```\n */\nexport function decodeOnChainEvents(logs: readonly RawLog[]): OnChainEvent[] {\n  const events: OnChainEvent[] = [];\n  for (const log of logs) {\n    const event = decodeOnChainEvent(log);\n    if (event) {\n      events.push(event);\n    }\n  }\n  return events;\n}\n\n/**\n * Find the first {@link UnwrapRequestedEvent} in a logs array.\n *\n * @example\n * ```ts\n * const event = findUnwrapRequested(receipt.logs);\n * if (event) console.log(event.receiver, event.encryptedAmount);\n * ```\n */\nexport function findUnwrapRequested(logs: readonly RawLog[]): UnwrapRequestedEvent | null {\n  for (const log of logs) {\n    const event = decodeUnwrapRequested(log);\n    if (event) {\n      return event;\n    }\n  }\n  return null;\n}\n\n/**\n * Find the first {@link WrapEvent} in a logs array.\n *\n * @example\n * ```ts\n * const event = findWrap(receipt.logs);\n * if (event) console.log(event.to, event.roundedAmount);\n * ```\n */\nexport function findWrap(logs: readonly RawLog[]): WrapEvent | null {\n  for (const log of logs) {\n    const event = decodeWrap(log);\n    if (event) {\n      return event;\n    }\n  }\n  return null;\n}\n\n/**\n * All confidential token event topic0 hashes.\n * Pass to `getLogs({ topics: [TOKEN_TOPICS] })` to fetch\n * all confidential token events in a single RPC call.\n */\nexport const TOKEN_TOPICS = [\n  Topics.ConfidentialTransfer,\n  Topics.Wrap,\n  Topics.UnwrapRequested,\n  Topics.UnwrapFinalized,\n] as const;\n\n// ---------------------------------------------------------------------------\n// ACL delegation event topic0 constants\n// ---------------------------------------------------------------------------\n\n/**\n * ACL delegation event topic0 constants (keccak256 of the canonical Solidity signature).\n * These are ACL events, NOT token events — they are emitted by the ACL contract.\n */\nexport const AclTopics = {\n  /** `DelegatedForUserDecryption(address indexed delegator, address indexed delegate, address contractAddress, uint64 delegationCounter, uint64 oldExpirationDate, uint64 newExpirationDate)` */\n  DelegatedForUserDecryption: eventTopic(\n    \"DelegatedForUserDecryption(address,address,address,uint64,uint64,uint64)\",\n  ),\n  /** `RevokedDelegationForUserDecryption(address indexed delegator, address indexed delegate, address contractAddress, uint64 delegationCounter, uint64 oldExpirationDate)` */\n  RevokedDelegationForUserDecryption: eventTopic(\n    \"RevokedDelegationForUserDecryption(address,address,address,uint64,uint64)\",\n  ),\n} as const;\n\n// ---------------------------------------------------------------------------\n// ACL delegation event interfaces\n// ---------------------------------------------------------------------------\n\n/** Decoded `DelegatedForUserDecryption` event — a delegation was created or renewed. */\nexport interface DelegatedForUserDecryptionEvent {\n  readonly eventName: \"DelegatedForUserDecryption\";\n  /** Address of the delegator (the account granting access). */\n  readonly delegator: Address;\n  /** Address of the delegate (the account receiving access). */\n  readonly delegate: Address;\n  /** Contract address the delegation applies to. */\n  readonly contractAddress: Address;\n  /** Monotonic delegation counter. */\n  readonly delegationCounter: bigint;\n  /** Previous expiration timestamp (0 if first delegation). */\n  readonly oldExpirationDate: bigint;\n  /** New expiration timestamp. */\n  readonly newExpirationDate: bigint;\n}\n\n/** Decoded `RevokedDelegationForUserDecryption` event — a delegation was revoked. */\nexport interface RevokedDelegationForUserDecryptionEvent {\n  readonly eventName: \"RevokedDelegationForUserDecryption\";\n  /** Address of the delegator. */\n  readonly delegator: Address;\n  /** Address of the delegate. */\n  readonly delegate: Address;\n  /** Contract address the revocation applies to. */\n  readonly contractAddress: Address;\n  /** Monotonic delegation counter. */\n  readonly delegationCounter: bigint;\n  /** Expiration date that was active before revocation. */\n  readonly oldExpirationDate: bigint;\n}\n\n/** Union of all decoded ACL delegation event types. */\nexport type AclEvent = DelegatedForUserDecryptionEvent | RevokedDelegationForUserDecryptionEvent;\n\n// ---------------------------------------------------------------------------\n// ACL delegation event decoders\n// ---------------------------------------------------------------------------\n\n/**\n * DelegatedForUserDecryption(address indexed delegator, address indexed delegate,\n *   address contractAddress, uint64 delegationCounter, uint64 oldExpirationDate, uint64 newExpirationDate)\n * Indexed: delegator (topics[1]), delegate (topics[2])\n * Data: contractAddress, delegationCounter, oldExpirationDate, newExpirationDate\n */\nexport function decodeDelegatedForUserDecryption(\n  log: RawLog,\n): DelegatedForUserDecryptionEvent | null {\n  if (log.topics[0] !== AclTopics.DelegatedForUserDecryption) {\n    return null;\n  }\n  if (log.topics.length < 3) {\n    return null;\n  }\n\n  return {\n    eventName: \"DelegatedForUserDecryption\",\n    delegator: topicToAddress(log.topics[1]!),\n    delegate: topicToAddress(log.topics[2]!),\n    contractAddress: wordToAddress(log.data, 0),\n    delegationCounter: wordToBigInt(log.data, 1),\n    oldExpirationDate: wordToBigInt(log.data, 2),\n    newExpirationDate: wordToBigInt(log.data, 3),\n  };\n}\n\n/**\n * RevokedDelegationForUserDecryption(address indexed delegator, address indexed delegate,\n *   address contractAddress, uint64 delegationCounter, uint64 oldExpirationDate)\n * Indexed: delegator (topics[1]), delegate (topics[2])\n * Data: contractAddress, delegationCounter, oldExpirationDate\n */\nexport function decodeRevokedDelegationForUserDecryption(\n  log: RawLog,\n): RevokedDelegationForUserDecryptionEvent | null {\n  if (log.topics[0] !== AclTopics.RevokedDelegationForUserDecryption) {\n    return null;\n  }\n  if (log.topics.length < 3) {\n    return null;\n  }\n\n  return {\n    eventName: \"RevokedDelegationForUserDecryption\",\n    delegator: topicToAddress(log.topics[1]!),\n    delegate: topicToAddress(log.topics[2]!),\n    contractAddress: wordToAddress(log.data, 0),\n    delegationCounter: wordToBigInt(log.data, 1),\n    oldExpirationDate: wordToBigInt(log.data, 2),\n  };\n}\n\n/**\n * Try all ACL delegation decoders on a single log and return the first match, or `null`.\n */\nexport function decodeAclEvent(log: RawLog): AclEvent | null {\n  return decodeDelegatedForUserDecryption(log) ?? decodeRevokedDelegationForUserDecryption(log);\n}\n\n/**\n * Batch-decode an array of logs for ACL delegation events, skipping unrecognized entries.\n */\nexport function decodeAclEvents(logs: readonly RawLog[]): AclEvent[] {\n  const events: AclEvent[] = [];\n  for (const log of logs) {\n    const event = decodeAclEvent(log);\n    if (event) {\n      events.push(event);\n    }\n  }\n  return events;\n}\n\n/**\n * Find the first {@link DelegatedForUserDecryptionEvent} in a logs array.\n */\nexport function findDelegatedForUserDecryption(\n  logs: readonly RawLog[],\n): DelegatedForUserDecryptionEvent | null {\n  for (const log of logs) {\n    const event = decodeDelegatedForUserDecryption(log);\n    if (event) {\n      return event;\n    }\n  }\n  return null;\n}\n\n/**\n * Find the first {@link RevokedDelegationForUserDecryptionEvent} in a logs array.\n */\nexport function findRevokedDelegationForUserDecryption(\n  logs: readonly RawLog[],\n): RevokedDelegationForUserDecryptionEvent | null {\n  for (const log of logs) {\n    const event = decodeRevokedDelegationForUserDecryption(log);\n    if (event) {\n      return event;\n    }\n  }\n  return null;\n}\n\n/**\n * Both ACL delegation event topic0 hashes.\n * Pass to `getLogs({ topics: [ACL_TOPICS] })` to fetch\n * all delegation events in a single RPC call.\n */\nexport const ACL_TOPICS = [\n  AclTopics.DelegatedForUserDecryption,\n  AclTopics.RevokedDelegationForUserDecryption,\n] as const;\n","import type { Address, Hex } from \"viem\";\nimport { z } from \"zod/mini\";\nimport { checksum, hex } from \"../schemas/primitives\";\nimport type { GenericStorage } from \"../types\";\nimport type { EncryptedValue } from \"../relayer/relayer-sdk.types\";\n\nconst STORAGE_PREFIX = \"zama:pending-unshield:\";\nconst CURRENT_VERSION = 1;\n\n/**\n * Persisted state for an in-progress unshield request.\n * Used to resume an interrupted unshield after page reload.\n *\n * @internal\n */\nexport interface PendingUnshieldRequest {\n  /** Transaction hash of the original unwrap call. */\n  readonly unwrapTxHash: Hex;\n  /**\n   * Request identifier from the `UnwrapRequested` event.\n   * Always populated for entries persisted by this SDK version; pass it as\n   * `unwrapRequestId` to `finalizeUnwrap`. Absent only when re-loading a\n   * pending unshield serialized by an older SDK version that did not\n   * record this field — in that case pass the `encryptedAmount` from the\n   * `UnwrapRequested` event to `finalizeUnwrap` instead.\n   */\n  readonly unwrapRequestId?: EncryptedValue;\n}\n\ninterface StoredPendingUnshieldRequest extends PendingUnshieldRequest {\n  readonly version: typeof CURRENT_VERSION;\n}\n\nfunction storageKey(wrapperAddress: Address): string {\n  return `${STORAGE_PREFIX}${checksum(wrapperAddress)}`;\n}\n\nconst PendingUnshieldRequestSchema = z.union([\n  z.pipe(\n    hex,\n    z.transform((unwrapTxHash: Hex) => ({ unwrapTxHash })),\n  ),\n  z.pipe(\n    z.object({\n      version: z.literal(CURRENT_VERSION),\n      unwrapTxHash: hex,\n      unwrapRequestId: z.optional(hex),\n    }),\n    z.transform(\n      ({\n        unwrapTxHash,\n        unwrapRequestId,\n      }: {\n        version: typeof CURRENT_VERSION;\n        unwrapTxHash: Hex;\n        unwrapRequestId?: Hex;\n      }) => ({ unwrapTxHash, unwrapRequestId }),\n    ),\n  ),\n]);\n\n/**\n * Persist the unwrap tx hash so an interrupted unshield can be resumed later\n * (e.g. after a page reload).\n *\n * @internal\n */\nexport async function savePendingUnshield(\n  storage: GenericStorage,\n  wrapperAddress: Address,\n  unwrapTxHash: Hex,\n  unwrapRequestId?: EncryptedValue,\n): Promise<void> {\n  if (unwrapRequestId === undefined) {\n    await storage.set(storageKey(wrapperAddress), unwrapTxHash);\n    return;\n  }\n\n  await storage.set(storageKey(wrapperAddress), {\n    version: CURRENT_VERSION,\n    unwrapTxHash,\n    unwrapRequestId,\n  } satisfies StoredPendingUnshieldRequest);\n}\n\n/**\n * Load a previously saved unwrap tx hash, or `null` if none exists.\n *\n * @internal\n */\nexport async function loadPendingUnshield(\n  storage: GenericStorage,\n  wrapperAddress: Address,\n): Promise<Hex | null> {\n  const request = await loadPendingUnshieldRequest(storage, wrapperAddress);\n  return request?.unwrapTxHash ?? null;\n}\n\n/**\n * Load a previously saved unwrap request, including `unwrapRequestId` when available.\n *\n * `resumeUnshield()` only needs `unwrapTxHash`: it reloads the transaction receipt and\n * rediscovers the right finalize input from the emitted `UnwrapRequested` event.\n * Use `unwrapRequestId` directly only for custom flows that call `finalizeUnwrap()`\n * without reloading the original unwrap receipt.\n *\n * @internal\n */\nexport async function loadPendingUnshieldRequest(\n  storage: GenericStorage,\n  wrapperAddress: Address,\n): Promise<PendingUnshieldRequest | null> {\n  const key = storageKey(wrapperAddress);\n  const value = await storage.get<Hex | StoredPendingUnshieldRequest>(key);\n  if (value === null || value === undefined) {\n    return null;\n  }\n  const parsed = PendingUnshieldRequestSchema.safeParse(value);\n  if (!parsed.success) {\n    await storage.delete(key);\n    return null;\n  }\n  return parsed.data as PendingUnshieldRequest;\n}\n\n/**\n * Clear the saved unwrap tx hash after a successful finalization.\n *\n * @internal\n */\nexport async function clearPendingUnshield(\n  storage: GenericStorage,\n  wrapperAddress: Address,\n): Promise<void> {\n  await storage.delete(storageKey(wrapperAddress));\n}\n","import { type Address, getAddress, type Hex } from \"viem\";\nimport {\n  allowanceContract,\n  approveContract,\n  balanceOfContract,\n  finalizeUnwrapContract,\n  isPayableTokenContract,\n  transferAndCallContract,\n  underlyingContract,\n  unwrapContract,\n  unwrapFromBalanceContract,\n  wrapContract,\n} from \"../contracts\";\nimport { findUnwrapRequested } from \"../events/onchain-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { EncryptedValue } from \"../relayer/relayer-sdk.types\";\nimport {\n  DecryptionFailedError,\n  ERC20ReadFailedError,\n  EncryptionFailedError,\n  InsufficientERC20BalanceError,\n  SignerNotConfiguredError,\n  TransactionRevertedError,\n  ZamaError,\n} from \"../errors\";\nimport { isEncryptedValueZero } from \"../utils/handles\";\nimport { toError } from \"../utils\";\nimport { requireAlignedWalletAccount, requireChainAlignment } from \"../utils/alignment\";\nimport { assertBigint, assertNonNullable } from \"../utils/assertions\";\nimport { swallow } from \"../utils/swallow\";\nimport { clearPendingUnshield, loadPendingUnshield, savePendingUnshield } from \"./pending-unshield\";\nimport { Token } from \"./token\";\nimport type {\n  GenericSigner,\n  ShieldCallbacks,\n  ShieldOptions,\n  TransactionResult,\n  UnshieldCallbacks,\n  UnshieldOptions,\n} from \"../types\";\n\n/**\n * Confidential ERC-20 wrapper (ERC-7984 ERC20Wrapper).\n *\n * Extends {@link Token} with wrapper-specific operations:\n * - `shield` / `unshield` — convert between the underlying ERC-20 and confidential balance\n * - `unwrap` / `unwrapAll` / `finalizeUnwrap` — low-level two-phase primitives\n * - `underlying` / `allowance` — wrapper reads\n *\n * `WrappedToken.address` is the wrapper contract address itself — the wrapper\n * IS the confidential token.\n */\nexport class WrappedToken extends Token {\n  #underlying: Address | undefined;\n  #underlyingPromise: Promise<Address> | null = null;\n  #isPayable: boolean | null = null;\n\n  /** Resolve `sdk.signer` or throw {@link SignerNotConfiguredError} tagged with `operation`. */\n  #requireSigner(operation: string): GenericSigner {\n    try {\n      assertNonNullable(this.sdk.signer, \"WrappedToken.sdk.signer\");\n      return this.sdk.signer;\n    } catch (cause) {\n      throw new SignerNotConfiguredError(operation, { cause });\n    }\n  }\n\n  // WRAPPER READS\n\n  /**\n   * Read the underlying ERC-20 token address from the wrapper contract.\n   *\n   * @returns The underlying ERC-20 token address.\n   */\n  async underlying(): Promise<Address> {\n    return this.#getUnderlying();\n  }\n\n  /**\n   * Check whether the underlying ERC-20 supports ERC-1363 (payable token).\n   * Result is cached per WrappedToken instance (negative results included):\n   * once we know an underlying does not support ERC-1363, subsequent shields\n   * go straight to the `approve` + `wrap` path without re-probing.\n   */\n  async isPayable(): Promise<boolean> {\n    if (this.#isPayable !== null) {\n      return this.#isPayable;\n    }\n    try {\n      const underlying = await this.#getUnderlying();\n      this.#isPayable = await this.sdk.provider.readContract(isPayableTokenContract(underlying));\n    } catch {\n      this.#isPayable = false;\n    }\n    return this.#isPayable;\n  }\n\n  /**\n   * Read the ERC-20 allowance granted by `owner` to this wrapper for the\n   * underlying token.\n   *\n   * @param owner - The owner address whose allowance to read.\n   * @returns The current allowance as a bigint.\n   */\n  async allowance(owner: Address): Promise<bigint> {\n    const underlying = await this.#getUnderlying();\n    return this.sdk.provider.readContract(\n      allowanceContract(underlying, getAddress(owner), this.address),\n    );\n  }\n\n  // SHIELD (ERC-20 → confidential)\n\n  /**\n   * Shield public ERC-20 tokens into confidential tokens.\n   *\n   * The execution path is decided automatically by ERC-165 introspection on\n   * the underlying ERC-20:\n   * - **`transferAndCall`** (single tx): when the underlying supports\n   *   ERC-1363, no approval is required — the wrapper's `onTransferReceived`\n   *   callback mints confidential tokens directly. `approvalStrategy` is\n   *   **ignored** on this path. See {@link ShieldPath}.\n   * - **`approveAndWrap`** (two-tx fallback): otherwise, an `approve` is\n   *   followed by a `wrap`. Approval is controlled by `approvalStrategy`\n   *   (`\"exact\"` by default, `\"max\"` for unlimited, `\"skip\"` to opt out).\n   *\n   * The ERC-20 balance is validated before submitting (public read, no\n   * signing required) so the call works for all wallet types, including\n   * smart wallets.\n   *\n   * @param amount - The plaintext amount to shield.\n   * @param options - Optional: `approvalStrategy`, `to`, callbacks.\n   * @returns The transaction hash and mined receipt.\n   * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n   * @throws if the ERC-20 balance is less than `amount`. {@link InsufficientERC20BalanceError}\n   * @throws if the ERC-20 approval or shield transaction reverts. {@link TransactionRevertedError}\n   *\n   * @example\n   * ```ts\n   * const txHash = await wrappedToken.shield(1000n);\n   * ```\n   */\n  async shield(amount: bigint, options?: ShieldOptions): Promise<TransactionResult> {\n    const account = await requireAlignedWalletAccount(\"shield\", this.sdk.signer, this.sdk.provider);\n\n    const isPayableToken = await this.isPayable();\n    const underlying = await this.#getUnderlying();\n    const userAddress = getAddress(account.address);\n\n    // ERC-20 balance check always runs (public read, no signing needed, works for all wallet types)\n    let erc20Balance: bigint;\n    try {\n      erc20Balance = await this.sdk.provider.readContract(\n        balanceOfContract(underlying, userAddress),\n      );\n    } catch (error) {\n      if (error instanceof ZamaError) {\n        throw error;\n      }\n      throw new ERC20ReadFailedError(\n        `Could not read ERC-20 balance for shield validation (token: ${underlying})`,\n        { cause: toError(error) },\n      );\n    }\n    if (erc20Balance < amount) {\n      throw new InsufficientERC20BalanceError(\n        `Insufficient ERC-20 balance: requested ${amount}, available ${erc20Balance} (token: ${underlying})`,\n        { requested: amount, available: erc20Balance, token: underlying },\n      );\n    }\n\n    if (isPayableToken) {\n      return this.#shieldViaTransferAndCall(amount, underlying, userAddress, options);\n    }\n    return this.#shieldViaApproveAndWrap(amount, userAddress, options);\n  }\n\n  async #shieldViaTransferAndCall(\n    amount: bigint,\n    underlying: Address,\n    userAddress: Address,\n    options?: ShieldOptions,\n  ): Promise<TransactionResult> {\n    this.#requireSigner(\"shield\");\n    const recipient = options?.to ? getAddress(options.to) : userAddress;\n    // ERC7984ERC20Wrapper.onTransferReceived decodes the recipient via\n    // `address(bytes20(data))` — i.e. the first 20 bytes of `data`. We pass\n    // the raw 20-byte address (not ABI-encoded), and the empty payload `0x`\n    // for self-shield so the wrapper falls back to `from`.\n    const data: Hex = recipient === userAddress ? \"0x\" : recipient;\n\n    return this.submitTransaction({\n      operation: \"shield:transferAndCall\",\n      config: transferAndCallContract(underlying, this.address, amount, data),\n      onSubmitted: options?.onShieldSubmitted,\n    });\n  }\n\n  async #shieldViaApproveAndWrap(\n    amount: bigint,\n    userAddress: Address,\n    options?: ShieldOptions,\n  ): Promise<TransactionResult> {\n    this.#requireSigner(\"shield\");\n    const strategy = options?.approvalStrategy ?? \"exact\";\n    if (strategy !== \"skip\") {\n      await this.#ensureAllowance(amount, strategy === \"max\", options);\n    }\n    const recipient = options?.to ? getAddress(options.to) : userAddress;\n    return this.submitTransaction({\n      operation: \"shield:approveAndWrap\",\n      config: wrapContract(this.address, recipient, amount),\n      onSubmitted: options?.onShieldSubmitted,\n    });\n  }\n\n  /**\n   * Approve this wrapper contract to spend the underlying ERC-20.\n   * Defaults to max uint256. Resets to zero first if there's an existing\n   * non-zero allowance (required by tokens like USDT).\n   *\n   * @param amount - Optional approval amount. Defaults to max uint256.\n   * @returns The transaction hash and mined receipt.\n   *\n   * @example\n   * ```ts\n   * await wrappedToken.approveUnderlying(); // max approval\n   * await wrappedToken.approveUnderlying(1000n); // exact amount\n   * ```\n   */\n  async approveUnderlying(amount?: bigint): Promise<TransactionResult> {\n    this.#requireSigner(\"approveUnderlying\");\n    const account = await requireAlignedWalletAccount(\n      \"approveUnderlying\",\n      this.sdk.signer,\n      this.sdk.provider,\n    );\n    const underlying = await this.#getUnderlying();\n    const userAddress = getAddress(account.address);\n\n    const approvalAmount = amount ?? 2n ** 256n - 1n;\n\n    if (approvalAmount > 0n) {\n      const currentAllowance = await this.sdk.provider.readContract(\n        allowanceContract(underlying, userAddress, this.address),\n      );\n\n      if (currentAllowance > 0n) {\n        await this.submitTransaction({\n          operation: \"approveUnderlying:reset\",\n          config: approveContract(underlying, this.address, 0n),\n        });\n      }\n    }\n\n    return this.submitTransaction({\n      operation: \"approveUnderlying\",\n      config: approveContract(underlying, this.address, approvalAmount),\n    });\n  }\n\n  // UNSHIELD (confidential → ERC-20)\n\n  /**\n   * Unshield a specific amount and finalize in one call.\n   * Orchestrates: unshield → wait for receipt → parse event → finalize.\n   *\n   * By default, the SDK validates the confidential balance before submitting.\n   * Set `skipBalanceCheck: true` to bypass this validation (e.g. for smart wallets).\n   *\n   * @param amount - The plaintext amount to unshield.\n   * @param options - Optional: `skipBalanceCheck` (default `false`), callbacks.\n   * @returns The finalize transaction hash and mined receipt.\n   *\n   * @example\n   * ```ts\n   * const txHash = await wrappedToken.unshield(500n);\n   * ```\n   */\n  async unshield(amount: bigint, options?: UnshieldOptions): Promise<TransactionResult> {\n    const {\n      skipBalanceCheck = false,\n      onUnwrapSubmitted,\n      onFinalizing,\n      onFinalizeSubmitted,\n    } = options ?? {};\n\n    if (!skipBalanceCheck) {\n      await this.assertConfidentialBalance(amount);\n    }\n\n    const callbacks: UnshieldCallbacks = { onFinalizing, onFinalizeSubmitted };\n    const operationId = crypto.randomUUID();\n    const unwrapResult = await this.unwrap(amount);\n    void swallow(\n      \"unshield: onUnwrapSubmitted\",\n      () => onUnwrapSubmitted?.(unwrapResult.txHash),\n      this.sdk.logger,\n    );\n    return this.#waitAndFinalizeUnshield(unwrapResult.txHash, operationId, callbacks);\n  }\n\n  /**\n   * Unshield the entire balance and finalize in one call.\n   * Orchestrates: unshieldAll → wait for receipt → parse event → finalize.\n   *\n   * @param callbacks - Optional progress callbacks for each phase.\n   * @returns The finalize transaction hash and mined receipt.\n   * @throws if the balance is zero. {@link DecryptionFailedError}\n   *\n   * @example\n   * ```ts\n   * const txHash = await wrappedToken.unshieldAll();\n   * ```\n   */\n  async unshieldAll(callbacks?: UnshieldCallbacks): Promise<TransactionResult> {\n    const operationId = crypto.randomUUID();\n    const unwrapResult = await this.unwrapAll();\n    void swallow(\n      \"unshieldAll: onUnwrapSubmitted\",\n      () => callbacks?.onUnwrapSubmitted?.(unwrapResult.txHash),\n      this.sdk.logger,\n    );\n    return this.#waitAndFinalizeUnshield(unwrapResult.txHash, operationId, callbacks);\n  }\n\n  /**\n   * Resume an in-progress unshield from an existing unwrap tx hash.\n   * Useful when the user already submitted the unwrap but the finalize step\n   * was interrupted (e.g. page reload, network error).\n   *\n   * @param unwrapTxHash - The transaction hash of the previously submitted unwrap.\n   * @param callbacks - Optional progress callbacks.\n   * @returns The finalize transaction hash and mined receipt.\n   *\n   * @example\n   * ```ts\n   * const txHash = await wrappedToken.resumeUnshield(previousUnwrapTxHash);\n   * ```\n   */\n  async resumeUnshield(\n    unwrapTxHash: Hex,\n    callbacks?: UnshieldCallbacks,\n  ): Promise<TransactionResult> {\n    return this.#waitAndFinalizeUnshield(unwrapTxHash, crypto.randomUUID(), callbacks);\n  }\n\n  /**\n   * Return the unwrap tx hash of an unshield that was interrupted between its\n   * two phases, or `null` if none is pending for this wrapper.\n   *\n   * The SDK persists this automatically when {@link unshield}/{@link unshieldAll}\n   * submit phase 1, and clears it once phase 2 finalizes. Use the returned hash\n   * to surface a \"resume\" affordance, then pass it to {@link resumeUnshield}.\n   * Resuming is intentionally caller-driven — auto-resuming on load would fire a\n   * wallet transaction unprompted.\n   *\n   * @returns The pending unwrap tx hash, or `null`.\n   *\n   * @example\n   * ```ts\n   * const unwrapTxHash = await wrappedToken.getPendingUnshield();\n   * if (unwrapTxHash) await wrappedToken.resumeUnshield(unwrapTxHash);\n   * ```\n   */\n  async getPendingUnshield(): Promise<Hex | null> {\n    return loadPendingUnshield(this.sdk.storage, this.address);\n  }\n\n  // UNSHIELD LOW-LEVEL PRIMITIVES\n\n  /**\n   * Request an unwrap for a specific amount. Encrypts the amount first.\n   * Call {@link finalizeUnwrap} after the request is processed on-chain.\n   *\n   * @param amount - The plaintext amount to unwrap (encrypted automatically).\n   * @returns The transaction hash and mined receipt.\n   *\n   * @example\n   * ```ts\n   * const txHash = await wrappedToken.unwrap(500n);\n   * ```\n   */\n  async unwrap(amount: bigint): Promise<TransactionResult> {\n    this.#requireSigner(\"unwrap\");\n    const account = await requireAlignedWalletAccount(\"unwrap\", this.sdk.signer, this.sdk.provider);\n    const userAddress = getAddress(account.address);\n\n    const { encryptedValues, inputProof } = await this.sdk.encrypt({\n      values: [{ value: amount, type: \"euint64\" }],\n      contractAddress: this.address,\n      userAddress,\n    });\n\n    const [encryptedAmount] = encryptedValues;\n    if (!encryptedAmount) {\n      throw new EncryptionFailedError(\"Encryption returned no encrypted values\");\n    }\n\n    return this.submitTransaction({\n      operation: \"unwrap\",\n      config: unwrapContract(this.address, userAddress, userAddress, encryptedAmount, inputProof),\n    });\n  }\n\n  /**\n   * Request an unwrap for the entire confidential balance.\n   * Uses the on-chain encrypted balance directly (no encryption needed).\n   * Throws if the balance is zero.\n   *\n   * @returns The transaction hash and mined receipt.\n   * @throws if the balance is zero. {@link DecryptionFailedError}\n   *\n   * @example\n   * ```ts\n   * const txHash = await wrappedToken.unwrapAll();\n   * ```\n   */\n  async unwrapAll(): Promise<TransactionResult> {\n    this.#requireSigner(\"unwrapAll\");\n    const account = await requireAlignedWalletAccount(\n      \"unwrapAll\",\n      this.sdk.signer,\n      this.sdk.provider,\n    );\n    const userAddress = getAddress(account.address);\n    const encryptedValue = await this.readConfidentialBalanceOf(userAddress);\n\n    if (isEncryptedValueZero(encryptedValue)) {\n      throw new DecryptionFailedError(\"Cannot unshield: balance is zero\");\n    }\n\n    return this.submitTransaction({\n      operation: \"unwrapAll\",\n      config: unwrapFromBalanceContract(this.address, userAddress, userAddress, encryptedValue),\n    });\n  }\n\n  /**\n   * Complete an unwrap by providing the public decryption proof.\n   * Call this after an unshield request has been processed on-chain.\n   *\n   * @param unwrapRequestId - `unwrapRequestId` from the `UnwrapRequested` event.\n   * @returns The transaction hash and mined receipt.\n   *\n   * @example\n   * ```ts\n   * const event = findUnwrapRequested(receipt.logs);\n   * const txHash = await wrappedToken.finalizeUnwrap(event.unwrapRequestId);\n   * ```\n   */\n  async finalizeUnwrap(unwrapRequestId: EncryptedValue): Promise<TransactionResult> {\n    this.#requireSigner(\"finalizeUnwrap\");\n    await requireChainAlignment(\"finalizeUnwrap\", this.sdk.signer, this.sdk.provider);\n    const result = await this.sdk.decryption.decryptPublicValues([unwrapRequestId]);\n    const clearValue = result.clearValues[unwrapRequestId];\n    assertBigint(clearValue, \"finalizeUnwrap: clearValue\");\n    return this.submitTransaction({\n      operation: \"finalizeUnwrap\",\n      config: finalizeUnwrapContract(\n        this.address,\n        unwrapRequestId,\n        clearValue,\n        result.decryptionProof,\n      ),\n    });\n  }\n\n  // PRIVATE HELPERS\n\n  async #getUnderlying(): Promise<Address> {\n    if (this.#underlying !== undefined) {\n      return this.#underlying;\n    }\n    if (!this.#underlyingPromise) {\n      this.#underlyingPromise = this.sdk.provider\n        .readContract(underlyingContract(this.address))\n        .then((v) => {\n          this.#underlying = v;\n          this.#underlyingPromise = null;\n          return v;\n        })\n        .catch((error) => {\n          this.#underlyingPromise = null;\n          throw error;\n        });\n    }\n    return this.#underlyingPromise;\n  }\n\n  async #waitAndFinalizeUnshield(\n    unshieldHash: Hex,\n    operationId: string,\n    callbacks: UnshieldCallbacks | undefined,\n  ): Promise<TransactionResult> {\n    this.emit({ type: ZamaSDKEvents.UnshieldPhase1Submitted, txHash: unshieldHash, operationId });\n    await swallow(\n      \"unshield: savePendingUnshield\",\n      () => savePendingUnshield(this.sdk.storage, this.address, unshieldHash),\n      this.sdk.logger,\n    );\n    let receipt;\n    try {\n      receipt = await this.sdk.provider.waitForTransactionReceipt(unshieldHash);\n    } catch (error) {\n      if (error instanceof ZamaError) {\n        throw error;\n      }\n      throw new TransactionRevertedError(\"Failed to get unshield receipt\", { cause: error });\n    }\n    const event = findUnwrapRequested(receipt.logs);\n    if (!event) {\n      throw new TransactionRevertedError(\"No UnwrapRequested event found in unshield receipt\");\n    }\n    this.emit({ type: ZamaSDKEvents.UnshieldPhase2Started, operationId });\n    void swallow(\"unshield: onFinalizing\", () => callbacks?.onFinalizing?.(), this.sdk.logger);\n    const finalizeResult = await this.finalizeUnwrap(\n      event.unwrapRequestId ?? event.encryptedAmount,\n    );\n    this.emit({\n      type: ZamaSDKEvents.UnshieldPhase2Submitted,\n      txHash: finalizeResult.txHash,\n      operationId,\n    });\n    void swallow(\n      \"unshield: onFinalizeSubmitted\",\n      () => callbacks?.onFinalizeSubmitted?.(finalizeResult.txHash),\n      this.sdk.logger,\n    );\n    // Phase 2 landed: the persisted recovery state is no longer needed.\n    await swallow(\n      \"unshield: clearPendingUnshield\",\n      () => clearPendingUnshield(this.sdk.storage, this.address),\n      this.sdk.logger,\n    );\n    return finalizeResult;\n  }\n\n  async #ensureAllowance(\n    amount: bigint,\n    maxApproval: boolean,\n    callbacks?: ShieldCallbacks,\n  ): Promise<void> {\n    this.#requireSigner(\"approveUnderlying\");\n    const underlying = await this.#getUnderlying();\n    const account = await requireAlignedWalletAccount(\n      \"approveUnderlying\",\n      this.sdk.signer,\n      this.sdk.provider,\n    );\n    const userAddress = getAddress(account.address);\n    const allowance = await this.sdk.provider.readContract(\n      allowanceContract(underlying, userAddress, this.address),\n    );\n\n    if (allowance >= amount) {\n      return;\n    }\n\n    // Reset to zero first when there's an existing non-zero allowance.\n    // Required by non-standard tokens like USDT, and also mitigates the\n    // ERC-20 approve race condition for all tokens.\n    if (allowance > 0n) {\n      await this.submitTransaction({\n        operation: \"approveUnderlying:reset\",\n        config: approveContract(underlying, this.address, 0n),\n      });\n    }\n\n    const approvalAmount = maxApproval ? 2n ** 256n - 1n : amount;\n\n    await this.submitTransaction({\n      operation: \"approveUnderlying\",\n      config: approveContract(underlying, this.address, approvalAmount),\n      onSubmitted: callbacks?.onApprovalSubmitted,\n    });\n  }\n}\n","import type { Address } from \"viem\";\nimport { Decryption } from \"./namespaces/decryption\";\nimport { Delegations } from \"./namespaces/delegations\";\nimport { Permits } from \"./namespaces/permits\";\nimport type { ZamaConfig } from \"./config/types\";\nimport { CredentialService } from \"./credentials/credential-service\";\nimport type { ZamaSDKEvent, ZamaSDKEventInput, ZamaSDKEventListener } from \"./events/sdk-events\";\nimport type { RelayerDispatcher } from \"./relayer/relayer-dispatcher\";\nimport type { EncryptParams, EncryptResult } from \"./relayer/relayer-sdk.types\";\nimport { CachingService } from \"./services/caching-service\";\nimport { DecryptionService } from \"./services/decryption-service\";\nimport { DelegationService } from \"./services/delegation-service\";\nimport { EncryptionService } from \"./services/encryption-service\";\nimport { LifecycleService } from \"./services/lifecycle-service\";\nimport { Token } from \"./token/token\";\nimport { WrappedToken } from \"./token/wrapped-token\";\nimport type {\n  GenericProvider,\n  GenericSigner,\n  GenericStorage,\n  WalletAccountListener,\n} from \"./types\";\nimport type { GenericLogger } from \"./worker/worker.types\";\nimport { WrappersRegistry } from \"./wrappers-registry\";\n\n/**\n * ZamaSDK — composes a RelayerSDK with contract abstraction.\n *\n * Exposes domain namespaces for permits, delegations, decryption, and tokens,\n * plus an unchanged registry, a top-level `encrypt`, and lifecycle methods. Internal\n * `*Service` classes do the work; the namespace classes own SDK-level guards\n * (chain alignment, signer requirement, event emission).\n */\nexport class ZamaSDK {\n  /** @internal */\n  readonly relayer: RelayerDispatcher;\n  readonly provider: GenericProvider;\n  readonly signer: GenericSigner | undefined;\n  readonly storage: GenericStorage;\n  /**\n   * A {@link WrappersRegistry} instance auto-configured for the current chain.\n   * Uses built-in defaults from chain configs, and the SDK's `registryTTL` if configured.\n   */\n  readonly registry: WrappersRegistry;\n  /** Permit and keypair management. */\n  readonly permits: Permits;\n  /** On-chain decryption-delegation management. */\n  readonly delegations: Delegations;\n  /** FHE decryption (user, delegated user, public). */\n  readonly decryption: Decryption;\n  readonly #registryTTL: number;\n  readonly #registryAddresses: Record<number, Address>;\n  readonly #onEvent: ZamaSDKEventListener;\n  readonly #logger: GenericLogger;\n  readonly #cachingService: CachingService;\n  readonly #lifecycleService: LifecycleService;\n  readonly #encryptionService: EncryptionService;\n  readonly #decryptionService: DecryptionService | undefined;\n  readonly #credentialService: CredentialService | undefined;\n  readonly #delegationService: DelegationService;\n\n  constructor(config: ZamaConfig) {\n    this.relayer = config.relayer;\n    this.provider = config.provider;\n    this.signer = config.signer;\n    this.storage = config.storage;\n    this.#onEvent = config.onEvent ?? function () {};\n    this.#logger = config.logger;\n    this.#cachingService = new CachingService(config.storage, this.#logger);\n    this.#delegationService = new DelegationService({\n      provider: this.provider,\n      relayer: this.relayer,\n      emitEvent: this.emitEvent.bind(this),\n      logger: this.#logger,\n    });\n\n    const registryAddresses: Record<number, Address> = {};\n    for (const chain of config.chains) {\n      if (chain.registryAddress) {\n        registryAddresses[chain.id] = chain.registryAddress;\n      }\n    }\n    this.registry = new WrappersRegistry({\n      provider: this.provider,\n      registryAddresses,\n      registryTTL: config.registryTTL,\n    });\n    this.#registryAddresses = registryAddresses;\n    this.#registryTTL = config.registryTTL;\n\n    if (config.signer) {\n      this.#credentialService = new CredentialService({\n        relayer: this.relayer,\n        signer: config.signer,\n        transportKeyPairTTL: config.transportKeyPairTTL,\n        permitTTL: config.permitTTL,\n        storage: this.storage,\n        permitStorage: config.permitStorage,\n        logger: this.#logger,\n      });\n      this.#decryptionService = new DecryptionService({\n        cache: this.#cachingService,\n        credentialService: this.#credentialService,\n        delegationService: this.#delegationService,\n        relayer: this.relayer,\n        emitEvent: this.emitEvent.bind(this),\n      });\n    }\n    this.#encryptionService = new EncryptionService({\n      relayer: this.relayer,\n      emitEvent: this.emitEvent.bind(this),\n    });\n    this.#lifecycleService = new LifecycleService({\n      signer: config.signer,\n      relayer: this.relayer,\n      cachingService: this.#cachingService,\n      credentialService: this.#credentialService,\n      logger: this.#logger,\n    });\n\n    this.permits = new Permits({\n      signer: this.signer,\n      provider: this.provider,\n      cachingService: this.#cachingService,\n      credentialService: this.#credentialService,\n      logger: this.#logger,\n    });\n    this.delegations = new Delegations({\n      signer: this.signer,\n      provider: this.provider,\n      delegationService: this.#delegationService,\n    });\n    this.decryption = new Decryption({\n      signer: this.signer,\n      provider: this.provider,\n      relayer: this.relayer,\n      decryptionService: this.#decryptionService,\n    });\n  }\n\n  /**\n   * Subscribe to wallet account transitions.\n   *\n   * @param listener - Called on each transition with a {@link WalletAccountChange} carrying\n   *   `previous` and `next` wallet account snapshots; either may be `undefined` for\n   *   connect and disconnect transitions.\n   * @returns An unsubscribe function; calling it removes the listener.\n   *\n   * @internal\n   */\n  onWalletAccountChange(listener: WalletAccountListener): () => void {\n    return this.#lifecycleService.onWalletAccountChange(listener);\n  }\n\n  /**\n   * The SDK-wide logger, exposed so contract abstractions ({@link Token},\n   * {@link WrappedToken}) can route their best-effort failures through the\n   * same sink. Silent by default.\n   *\n   * @internal\n   */\n  get logger(): GenericLogger {\n    return this.#logger;\n  }\n\n  /**\n   * Emit a structured SDK event into the unified SDK event stream.\n   *\n   * Listener exceptions are caught and logged so that a misbehaving subscriber\n   * can never corrupt SDK operations.\n   *\n   * Application code should subscribe via the `onEvent` config option, never\n   * call this directly.\n   *\n   * @internal\n   */\n  emitEvent(input: ZamaSDKEventInput, tokenAddress?: Address): void {\n    try {\n      this.#onEvent({ ...input, tokenAddress, timestamp: Date.now() } as ZamaSDKEvent);\n    } catch (error) {\n      this.#logger.warn(`${input.type} event listener silently failed`, { error });\n    }\n  }\n\n  /**\n   * Create a {@link WrappersRegistry} instance bound to this SDK's provider.\n   * Inherits the registry addresses derived from the SDK's chain configs, so\n   * the result is consistent with {@link ZamaSDK.registry}.\n   *\n   * @param registryAddresses - Optional per-chain overrides for this registry instance.\n   * @returns A {@link WrappersRegistry} instance.\n   *\n   * @example\n   * ```ts\n   * // Addresses resolved from the SDK's chain configs\n   * const registry = sdk.createWrappersRegistry();\n   *\n   * // Hardhat or custom chain — override per chain for this registry instance\n   * const registry = sdk.createWrappersRegistry({ [31337]: \"0xYourRegistry\" });\n   *\n   * const pairs = await registry.getTokenPairs();\n   * ```\n   */\n  createWrappersRegistry(registryAddresses?: Record<number, Address>): WrappersRegistry {\n    return new WrappersRegistry({\n      provider: this.provider,\n      registryAddresses: { ...this.#registryAddresses, ...registryAddresses },\n      registryTTL: this.#registryTTL,\n    });\n  }\n\n  /**\n   * Encrypt one or more plaintext values into FHE ciphertexts.\n   *\n   * @param params - Typed FHE inputs, the target contract address, and the user address.\n   * @returns External encrypted values and the input proof for on-chain submission.\n   * @throws if FHE encryption fails. {@link EncryptionFailedError}\n   *\n   * @example\n   * ```ts\n   * const { encryptedValues, inputProof } = await sdk.encrypt({\n   *   values: [{ value: 1000n, type: \"euint64\" }],\n   *   contractAddress: \"0xToken\",\n   *   userAddress: \"0xUser\",\n   * });\n   * ```\n   */\n  async encrypt(params: EncryptParams): Promise<EncryptResult> {\n    return this.#encryptionService.encrypt(params);\n  }\n\n  /**\n   * Create a high-level ERC-20-style interface for an ERC-7984 confidential token.\n   * Supports balance queries, transfers, operator approvals, and decryption.\n   *\n   * For ERC-7984 wrappers (shield/unshield/allowance), use {@link createWrappedToken} instead.\n   *\n   * @param address - The confidential token contract address.\n   * @returns A {@link Token} instance bound to this SDK.\n   *\n   * @example\n   * ```ts\n   * const token = sdk.createToken(cUSDT);\n   * const balance = await token.balanceOf(userAddress);\n   * ```\n   */\n  createToken(address: Address): Token {\n    return new Token(this, address);\n  }\n\n  /**\n   * Create a high-level interface for an ERC-7984 wrapper token.\n   * Extends {@link Token} with shield/unshield/allowance/finalize-unwrap operations.\n   *\n   * @param address - The wrapper token contract address.\n   * @returns A {@link WrappedToken} instance bound to this SDK.\n   *\n   * @example\n   * ```ts\n   * const wrapped = sdk.createWrappedToken(wUSDT);\n   * await wrapped.shield(1_000_000n);\n   * ```\n   */\n  createWrappedToken(address: Address): WrappedToken {\n    return new WrappedToken(this, address);\n  }\n\n  /**\n   * Unsubscribe from signer lifecycle events without terminating the relayer.\n   * Call this when the SDK instance is being replaced but the relayer is shared\n   * (e.g. React provider remount in Strict Mode).\n   */\n  dispose(): void {\n    this.#lifecycleService.dispose();\n  }\n\n  /**\n   * Terminate the relayer backend and clean up resources.\n   * Call this when the SDK is no longer needed (e.g. on unmount or shutdown).\n   */\n  terminate(): void {\n    this.dispose();\n    this.relayer.terminate();\n    this.signer?.dispose?.();\n  }\n\n  /**\n   * Implements the TC39 Explicit Resource Management protocol.\n   * Calls {@link terminate} when the `using` binding goes out of scope,\n   * unsubscribing signer events and shutting down the relayer.\n   *\n   * @example\n   * ```ts\n   * {\n   *   using sdk = new ZamaSDK({ relayer, provider, signer, storage });\n   *   await sdk.permits.grantPermit([cUSDT]);\n   *   const balance = await sdk.createToken(cUSDT).balanceOf(userAddress);\n   * } // sdk.terminate() called automatically here\n   * ```\n   */\n  [Symbol.dispose](): void {\n    this.terminate();\n  }\n}\n","import type { GenericStorage } from \"../types\";\n\n/** Minimal chrome.storage.session typings (avoids depending on @types/chrome). */\ndeclare const chrome: {\n  storage: {\n    session: {\n      get(key: string): Promise<Record<string, unknown>>;\n      set(items: Record<string, unknown>): Promise<void>;\n      remove(key: string): Promise<void>;\n    };\n  };\n};\n\n/**\n * {@link GenericStorage} backed by `chrome.storage.session`.\n *\n * Use this in MV3 web extensions so the wallet signature survives\n * service worker restarts and is shared across popup, background,\n * and content script contexts.\n *\n * @example\n * ```ts\n * import { ZamaSDK, indexedDBStorage, chromeSessionStorage } from \"@zama-fhe/sdk\";\n * import { createConfig } from \"@zama-fhe/sdk/viem\";\n *\n * const config = createConfig({\n *   chains: [mySepolia],\n *   publicClient,\n *   walletClient,\n *   relayers: { [mySepolia.id]: web() },\n *   storage: indexedDBStorage, // encrypted transport key pair — persistent\n *   permitStorage: chromeSessionStorage, // signed permits — ephemeral\n * });\n * const sdk = new ZamaSDK(config);\n * ```\n */\nexport class ChromeSessionStorage implements GenericStorage {\n  async get<T = unknown>(key: string): Promise<T | null> {\n    const result = await chrome.storage.session.get(key);\n    return (result[key] as T) ?? null;\n  }\n\n  async set(key: string, value: unknown): Promise<void> {\n    await chrome.storage.session.set({ [key]: value });\n  }\n\n  async delete(key: string): Promise<void> {\n    await chrome.storage.session.remove(key);\n  }\n}\n\n/** Default singleton for application-wide use. */\nexport const chromeSessionStorage = new ChromeSessionStorage();\n"],"mappings":"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"}