@zama-fhe/sdk 3.2.0-alpha.2 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"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 // NOTE: New wrapper contracts no longer emit Wrapped — shields now emit\n // ConfidentialTransfer(from=zeroAddress, ...) instead. Retained for backward\n // compatibility with older deployments.\n /** `Wrapped(address indexed to, uint256 amountIn)` */\n Wrapped: eventTopic(\"Wrapped(address,uint256)\"),\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// NOTE: New wrapper contracts no longer emit this event — shields now emit\n// ConfidentialTransfer(from=zeroAddress, ...) instead. Retained for backward\n// compatibility with older deployments.\n/** Decoded `Wrapped` event — an ERC-20 shield (wrap) operation. */\nexport interface WrappedEvent {\n readonly eventName: \"Wrapped\";\n /** Receiver of the minted confidential tokens. */\n readonly to: Address;\n /** Underlying ERC-20 tokens deposited. */\n readonly amountIn: bigint;\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 | WrappedEvent\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// NOTE: New wrapper contracts no longer emit this event. Retained for backward\n// compatibility with older deployments.\n/**\n * Wrapped(address indexed to, uint256 amountIn)\n * Indexed: to (topics[1])\n * Data: amountIn (uint256)\n */\nexport function decodeWrapped(log: RawLog): WrappedEvent | null {\n if (log.topics[0] !== Topics.Wrapped) {\n return null;\n }\n if (log.topics.length < 2) {\n return null;\n }\n\n return {\n eventName: \"Wrapped\",\n to: topicToAddress(log.topics[1]!),\n amountIn: wordToBigInt(log.data, 0),\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 decodeWrapped(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// NOTE: New wrapper contracts no longer emit this event. Retained for backward\n// compatibility with older deployments.\n/**\n * Find the first {@link WrappedEvent} in a logs array.\n *\n * @example\n * ```ts\n * const event = findWrapped(receipt.logs);\n * if (event) console.log(event.to, event.amountIn);\n * ```\n */\nexport function findWrapped(logs: readonly RawLog[]): WrappedEvent | null {\n for (const log of logs) {\n const event = decodeWrapped(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.Wrapped,\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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"}
1
+ {"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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"}