{"version":3,"file":"index.cjs","names":["ZamaError","ZamaErrorCode","ZamaError","ZamaErrorCode","DecryptionFailedError","RelayerRequestFailedError","SigningRejectedError","SigningFailedError","extractHttpStatus","ZamaError","extractHttpStatus","RelayerRequestFailedError","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","#assertAllDelegationsActive","#setHandleResult","isFatalBatchError","#missingBatchItem","#toZamaError","pLimit","isEncryptedValueZero","ZamaSDKEvents","toError","DecryptionFailedError","ZamaError","#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","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","#onEvent","#logger","#cachingService","#lifecycleService","#encryptionService","#decryptionService","#credentialService","#delegationService","WrappersRegistry","CredentialService","Token","checksum","z","hex"],"sources":["../../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/wrapped-token.ts","../../src/zama-sdk.ts","../../src/token/pending-unshield.ts","../../src/storage/chrome-session-storage.ts"],"sourcesContent":["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 typically takes 1–2 minutes.\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 * **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 { SigningRejectedError, SigningFailedError } from \"./signing\";\nimport { extractHttpStatus } from \"../utils/error\";\n\n/**\n * Inspect a caught error for an HTTP status code and return the appropriate\n * typed SDK error (NoCiphertextError for 400, RelayerRequestFailedError for\n * other HTTP errors, or the generic DecryptionFailedError as fallback).\n *\n * Errors that are already typed SDK errors (e.g. {@link SigningRejectedError},\n * {@link DecryptionFailedError}) are returned as-is so callers can still match\n * the original cause.\n *\n * When `isDelegated` is true and the relayer returns a 500, the error is\n * wrapped as {@link DelegationNotPropagatedError} because the most likely\n * cause is that the gateway hasn't synced the delegation from L1 yet.\n */\nexport function wrapDecryptError(\n  error: unknown,\n  fallbackMessage: string,\n  isDelegated = false,\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  ) {\n    return error;\n  }\n\n  const statusCode = extractHttpStatus(error);\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 (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        \"after granting delegation, allow 1–2 minutes for cross-chain synchronization before retrying. \" +\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(\n      error instanceof Error ? error.message : fallbackMessage,\n      statusCode,\n      { cause: error },\n    );\n  }\n\n  return new DecryptionFailedError(fallbackMessage, {\n    cause: error,\n  });\n}\n","import { extractHttpStatus } 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      {\n        cause: error,\n      },\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      {\n        name: \"owner\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"spender\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    stateMutability: \"view\",\n  },\n  {\n    type: \"function\",\n    name: \"approve\",\n    inputs: [\n      {\n        name: \"spender\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"approveAndCall\",\n    inputs: [\n      {\n        name: \"spender\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"approveAndCall\",\n    inputs: [\n      {\n        name: \"spender\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n      {\n        name: \"data\",\n        type: \"bytes\",\n        internalType: \"bytes\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"balanceOf\",\n    inputs: [\n      {\n        name: \"account\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    stateMutability: \"view\",\n  },\n  {\n    type: \"function\",\n    name: \"supportsInterface\",\n    inputs: [\n      {\n        name: \"interfaceId\",\n        type: \"bytes4\",\n        internalType: \"bytes4\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"view\",\n  },\n  {\n    type: \"function\",\n    name: \"totalSupply\",\n    inputs: [],\n    outputs: [\n      {\n        name: \"\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    stateMutability: \"view\",\n  },\n  {\n    type: \"function\",\n    name: \"transfer\",\n    inputs: [\n      {\n        name: \"to\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferAndCall\",\n    inputs: [\n      {\n        name: \"to\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferAndCall\",\n    inputs: [\n      {\n        name: \"to\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n      {\n        name: \"data\",\n        type: \"bytes\",\n        internalType: \"bytes\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferFrom\",\n    inputs: [\n      {\n        name: \"from\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"to\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferFromAndCall\",\n    inputs: [\n      {\n        name: \"from\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"to\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n      {\n        name: \"data\",\n        type: \"bytes\",\n        internalType: \"bytes\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"function\",\n    name: \"transferFromAndCall\",\n    inputs: [\n      {\n        name: \"from\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"to\",\n        type: \"address\",\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        internalType: \"uint256\",\n      },\n    ],\n    outputs: [\n      {\n        name: \"\",\n        type: \"bool\",\n        internalType: \"bool\",\n      },\n    ],\n    stateMutability: \"nonpayable\",\n  },\n  {\n    type: \"event\",\n    name: \"Approval\",\n    inputs: [\n      {\n        name: \"owner\",\n        type: \"address\",\n        indexed: true,\n        internalType: \"address\",\n      },\n      {\n        name: \"spender\",\n        type: \"address\",\n        indexed: true,\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        indexed: false,\n        internalType: \"uint256\",\n      },\n    ],\n    anonymous: false,\n  },\n  {\n    type: \"event\",\n    name: \"Transfer\",\n    inputs: [\n      {\n        name: \"from\",\n        type: \"address\",\n        indexed: true,\n        internalType: \"address\",\n      },\n      {\n        name: \"to\",\n        type: \"address\",\n        indexed: true,\n        internalType: \"address\",\n      },\n      {\n        name: \"value\",\n        type: \"uint256\",\n        indexed: false,\n        internalType: \"uint256\",\n      },\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 { BatchDecryptResult, DecryptionService } from \"../services/decryption-service\";\nimport type { GenericProvider, GenericSigner } from \"../types\";\nimport { requireAlignedWalletAccount } from \"../utils/alignment\";\n\n/**\n * Public namespace for FHE decryption.\n *\n * Exposed as `sdk.decryption`. 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   * @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  ): 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    );\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 {\n        clearValues: {},\n        decryptionProof: \"0x\",\n        abiEncodedClearValues: \"0x\",\n      };\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   * @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  }: {\n    encryptedInputs: EncryptedInput[];\n    delegatorAddress: Address;\n    accountAddress?: Address;\n    maxConcurrency?: number;\n  }): 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    });\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 * allow **1–2 minutes** before attempting delegated decryption to let the gateway\n * sync the ACL state via cross-chain event propagation.\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   * **Important:** After the transaction is mined, allow **1–2 minutes** before\n   * attempting delegated decryption. The delegation is recorded on L1 immediately,\n   * but the gateway must sync the ACL state via cross-chain event propagation.\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 { DecryptionFailedError, isFatalBatchError, wrapDecryptError, ZamaError } 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 { toError } from \"../utils\";\nimport type { CachingService } from \"./caching-service\";\nimport type { DelegationService } from \"./delegation-service\";\n\ninterface DecryptionStrategy {\n  requesterAddress: 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      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  ): Promise<Record<EncryptedValue, ClearValue>> {\n    const normalizedDelegator = getAddress(delegatorAddress);\n    const normalizedDelegate = getAddress(delegateAddress);\n    return this.#decrypt(encryptedValues, {\n      requesterAddress: getAddress(accountAddress),\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  async delegatedBatchDecryptHandlesAs({\n    encryptedInputs,\n    delegatorAddress,\n    delegateAddress,\n    accountAddress,\n    maxConcurrency = 5,\n  }: {\n    encryptedInputs: EncryptedInput[];\n    delegatorAddress: Address;\n    delegateAddress: Address;\n    accountAddress: Address;\n    maxConcurrency?: number;\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 }) => ({\n          encryptedValue,\n          contractAddress,\n        })),\n        delegatorAddress,\n        delegateAddress,\n        normalizedAccount,\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\", true);\n        return { items };\n      }\n    }\n\n    await pLimit(\n      items.map((item) => async () => {\n        try {\n          const decrypted = await this.delegatedUserDecrypt(\n            [\n              {\n                encryptedValue: item.encryptedValue,\n                contractAddress: item.contractAddress,\n              },\n            ],\n            delegatorAddress,\n            delegateAddress,\n            normalizedAccount,\n          );\n          this.#setHandleResult(item, decrypted);\n        } catch (error) {\n          if (isFatalBatchError(error)) {\n            throw error;\n          }\n          item.error = this.#toZamaError(\n            error,\n            \"Failed to decrypt delegated encrypted values\",\n            true,\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      await strategy.validate(nonZeroContracts);\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          const decrypted = await strategy.decryptContract({\n            credentials,\n            contractAddress,\n            encryptedValues,\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      this.#emitEvent({\n        type: ZamaSDKEvents.DecryptError,\n        error: toError(error),\n        durationMs: Date.now() - t0,\n        encryptedValues: uncachedEncryptedValues,\n      });\n      throw wrapDecryptError(error, strategy.errorMessage, strategy.delegated);\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, delegated = false): ZamaError {\n    return error instanceof ZamaError ? error : wrapDecryptError(error, fallbackMessage, delegated);\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    {\n      delegatorAddress,\n      delegateAddress,\n    }: {\n      delegatorAddress: Address;\n      delegateAddress: Address;\n    },\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\", {\n        error,\n      });\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    }: {\n      contractAddress: Address;\n      delegateAddress: Address;\n      delegatorAddress: Address;\n    },\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        {\n          type: ZamaSDKEvents.EncryptEnd,\n          durationMs: Date.now() - t0,\n        },\n        params.contractAddress,\n      );\n      return result;\n    } catch (error) {\n      this.#emitEvent(\n        {\n          type: ZamaSDKEvents.EncryptError,\n          error: toError(error),\n          durationMs: Date.now() - t0,\n        },\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, 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 { 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 = {\n      onFinalizing,\n      onFinalizeSubmitted,\n    };\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  // 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({\n      type: ZamaSDKEvents.UnshieldPhase1Submitted,\n      txHash: unshieldHash,\n      operationId,\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\", {\n        cause: error,\n      });\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    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  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 #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.#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({\n        ...input,\n        tokenAddress,\n        timestamp: Date.now(),\n      } as ZamaSDKEvent);\n    } catch (error) {\n      this.#logger.warn(`${input.type} event listener silently failed`, {\n        error,\n      });\n    }\n  }\n\n  /**\n   * Create a {@link WrappersRegistry} instance bound to this SDK's provider.\n   * On Mainnet and Sepolia the registry address is resolved automatically.\n   *\n   * @param registryAddresses - Optional per-chain overrides for this registry instance.\n   * @returns A {@link WrappersRegistry} instance.\n   *\n   * @example\n   * ```ts\n   * // Mainnet / Sepolia — resolved automatically\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,\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 { 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 */\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 */\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 */\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 */\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 */\nexport async function clearPendingUnshield(\n  storage: GenericStorage,\n  wrapperAddress: Address,\n): Promise<void> {\n  await storage.delete(storageKey(wrapperAddress));\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 *\n * const sdk = new ZamaSDK({\n *   relayer,\n *   signer,\n *   storage: indexedDBStorage,\n *   sessionStorage: chromeSessionStorage,\n * });\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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ACnC,CACF,CACF,CC1BA,SAAgB,EAAU,EAAoB,CAC5C,OAAQ,EAAM,WAAW,IAAI,EAAI,EAAQ,KAAK,GAChD,CCHA,MAAa,GAAa,CACxB,CACE,KAAM,WACN,KAAM,YACN,OAAQ,CACN,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,UACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,gBAAiB,MACnB,EACA,CACE,KAAM,WACN,KAAM,UACN,OAAQ,CACN,CACE,KAAM,UACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,OACN,aAAc,MAChB,CACF,EACA,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,iBACN,OAAQ,CACN,CACE,KAAM,UACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,OACN,aAAc,MAChB,CACF,EACA,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,iBACN,OAAQ,CACN,CACE,KAAM,UACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,OACN,KAAM,QACN,aAAc,OAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,OACN,aAAc,MAChB,CACF,EACA,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,YACN,OAAQ,CACN,CACE,KAAM,UACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,gBAAiB,MACnB,EACA,CACE,KAAM,WACN,KAAM,oBACN,OAAQ,CACN,CACE,KAAM,cACN,KAAM,SACN,aAAc,QAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,OACN,aAAc,MAChB,CACF,EACA,gBAAiB,MACnB,EACA,CACE,KAAM,WACN,KAAM,cACN,OAAQ,CAAC,EACT,QAAS,CACP,CACE,KAAM,GACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,gBAAiB,MACnB,EACA,CACE,KAAM,WACN,KAAM,WACN,OAAQ,CACN,CACE,KAAM,KACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,OACN,aAAc,MAChB,CACF,EACA,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,kBACN,OAAQ,CACN,CACE,KAAM,KACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,OACN,aAAc,MAChB,CACF,EACA,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,kBACN,OAAQ,CACN,CACE,KAAM,KACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,OACN,KAAM,QACN,aAAc,OAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,OACN,aAAc,MAChB,CACF,EACA,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,eACN,OAAQ,CACN,CACE,KAAM,OACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,KACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,CACF,EACA,QAAS,CACP,CACE,KAAM,GACN,KAAM,OACN,aAAc,MAChB,CACF,EACA,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,sBACN,OAAQ,CACN,CACE,KAAM,OACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,KACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,QACN,KAAM,UACN,aAAc,SAChB,EACA,CACE,KAAM,OACN,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"}