@zama-fhe/sdk 3.6.0 → 3.7.0-alpha.2

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.
Files changed (79) hide show
  1. package/dist/cjs/base-signer.cjs +1 -1
  2. package/dist/cjs/base-signer.cjs.map +1 -1
  3. package/dist/cjs/chains.cjs +1 -1
  4. package/dist/cjs/chains.cjs.map +1 -1
  5. package/dist/cjs/ethers/index.cjs +1 -1
  6. package/dist/cjs/ethers/index.cjs.map +1 -1
  7. package/dist/cjs/fhevm-relayer.cjs +2 -2
  8. package/dist/cjs/fhevm-relayer.cjs.map +1 -1
  9. package/dist/cjs/index.cjs +1 -1
  10. package/dist/cjs/index.cjs.map +1 -1
  11. package/dist/cjs/query/index.cjs +1 -1
  12. package/dist/cjs/query/index.cjs.map +1 -1
  13. package/dist/cjs/relayer.cjs +1 -1
  14. package/dist/cjs/relayer.cjs.map +1 -1
  15. package/dist/cjs/token.cjs +1 -1
  16. package/dist/cjs/token.cjs.map +1 -1
  17. package/dist/cjs/viem/index.cjs +1 -1
  18. package/dist/cjs/viem/index.cjs.map +1 -1
  19. package/dist/cjs/wrappers-registry.cjs +1 -1
  20. package/dist/cjs/wrappers-registry.cjs.map +1 -1
  21. package/dist/esm/base-signer--sBO2qJp.js +2 -0
  22. package/dist/esm/base-signer--sBO2qJp.js.map +1 -0
  23. package/dist/esm/{base-signer-Iu5Lszrf.d.ts → base-signer-S2Ogf6L4.d.ts} +2 -2
  24. package/dist/esm/chains/index.d.ts +1 -1
  25. package/dist/esm/chains/index.js +1 -1
  26. package/dist/esm/chains-DEpKup1n.js +2 -0
  27. package/dist/esm/chains-DEpKup1n.js.map +1 -0
  28. package/dist/esm/cleartext/index.d.ts +2 -2
  29. package/dist/esm/cleartext/index.js +1 -1
  30. package/dist/esm/{cleartext-iE4sWgSP.js → cleartext-DcbDCDXj.js} +2 -2
  31. package/dist/esm/{cleartext-iE4sWgSP.js.map → cleartext-DcbDCDXj.js.map} +1 -1
  32. package/dist/esm/{cleartext-B2DI8fgm.d.ts → cleartext-pv2blbFU.d.ts} +2 -2
  33. package/dist/esm/encrypt.worker.js +51 -51
  34. package/dist/esm/{encryption-BKoalB4o.js → encryption-DJljZ2oV.js} +2 -2
  35. package/dist/esm/{encryption-BKoalB4o.js.map → encryption-DJljZ2oV.js.map} +1 -1
  36. package/dist/esm/ethers/index.d.ts +5 -5
  37. package/dist/esm/ethers/index.js +1 -1
  38. package/dist/esm/ethers/index.js.map +1 -1
  39. package/dist/esm/fhevm-relayer-CPmCytDX.js +8 -0
  40. package/dist/esm/fhevm-relayer-CPmCytDX.js.map +1 -0
  41. package/dist/esm/{index-BCh3VaZo.d.ts → index-DRrrBtMX.d.ts} +2000 -1115
  42. package/dist/esm/{index-ijgDL4IC.d.ts → index-Gk1S0gjO.d.ts} +14 -1
  43. package/dist/esm/{index-S6QjPkZE.d.ts → index-tfvbrVa2.d.ts} +4 -4
  44. package/dist/esm/index.d.ts +108 -8
  45. package/dist/esm/index.js +1 -1
  46. package/dist/esm/index.js.map +1 -1
  47. package/dist/esm/node/index.d.ts +4 -4
  48. package/dist/esm/node/index.js +1 -1
  49. package/dist/esm/query/index.d.ts +4 -537
  50. package/dist/esm/query/index.js +1 -1
  51. package/dist/esm/query/index.js.map +1 -1
  52. package/dist/esm/relayer-B6Zo6EkX.js +2 -0
  53. package/dist/esm/relayer-B6Zo6EkX.js.map +1 -0
  54. package/dist/esm/token-BMQ6xlrk.js +2 -0
  55. package/dist/esm/{token-BejFVO8m.js.map → token-BMQ6xlrk.js.map} +1 -1
  56. package/dist/esm/{types-D3W3J65M.d.ts → types-BOyFfG7D.d.ts} +42 -7
  57. package/dist/esm/{types-Ce9Lhvrf.d.ts → types-BRIpBy9n.d.ts} +3 -3
  58. package/dist/esm/{types-CFDG6lIJ.d.ts → types-OXQqX_kH.d.ts} +3 -3
  59. package/dist/esm/{validation-BRu06AM_.js → validation-DWe2k89s.js} +2 -2
  60. package/dist/esm/{validation-BRu06AM_.js.map → validation-DWe2k89s.js.map} +1 -1
  61. package/dist/esm/viem/index.d.ts +5 -5
  62. package/dist/esm/viem/index.js +1 -1
  63. package/dist/esm/viem/index.js.map +1 -1
  64. package/dist/esm/web/index.d.ts +1 -1
  65. package/dist/esm/web/index.js +1 -1
  66. package/dist/esm/wrappers-registry-BfQr2QHn.js +2 -0
  67. package/dist/esm/wrappers-registry-BfQr2QHn.js.map +1 -0
  68. package/package.json +2 -2
  69. package/dist/esm/base-signer-DGIEzavu.js +0 -2
  70. package/dist/esm/base-signer-DGIEzavu.js.map +0 -1
  71. package/dist/esm/chains-ByyCdrrd.js +0 -2
  72. package/dist/esm/chains-ByyCdrrd.js.map +0 -1
  73. package/dist/esm/fhevm-relayer-Cm-ZR1vP.js +0 -8
  74. package/dist/esm/fhevm-relayer-Cm-ZR1vP.js.map +0 -1
  75. package/dist/esm/relayer-CVKO9GmQ.js +0 -2
  76. package/dist/esm/relayer-CVKO9GmQ.js.map +0 -1
  77. package/dist/esm/token-BejFVO8m.js +0 -2
  78. package/dist/esm/wrappers-registry-BLe7PkZi.js +0 -2
  79. package/dist/esm/wrappers-registry-BLe7PkZi.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","names":["ZamaError","ZamaError","ZamaErrorCode","ZamaError","ZamaErrorCode","ZamaError","ZamaErrorCode","DecryptionFailedError","NoCiphertextError","RelayerRequestFailedError","SigningRejectedError","SigningFailedError","RpcRateLimitError","InvalidTransportKeyPairError","RevokedKmsContextError","isInvalidTransportKeyPairMessage","isRevokedKmsContextError","isNotEntitledMessage","parseHandleFromMessage","hasStructuredRpcRateLimitSignal","extractRetryAfter","extractHttpStatus","isRpcRateLimitError","isRelayerError","isRelayerTimeoutError","ZamaError","extractHttpStatus","isRelayerTimeoutError","isRelayerError","RelayerRequestFailedError","extractRetryAfter","EncryptionFailedError","buildZamaConfig","#signer","#provider","#cachingService","#credentialService","#logger","#emitEvent","requireConfigured","ZamaSDKEvents","#requireCredentialService","requireChainAlignment","#failPermit","#clearDecryptCacheForRequester","requireAlignedWalletAccount","swallow","#signer","#provider","#delegationService","requireConfigured","#requireSigner","requireAlignedWalletAccount","#signer","#provider","#router","#decryptionService","requireConfigured","#requireDecryptionService","requireAlignedWalletAccount","#offlineService","#credentialService","checksum","z","hex","Token","SignerNotConfiguredError","#getUnderlying","#isPayable","isPayableTokenContract","allowanceContract","requireAlignedWalletAccount","balanceOfContract","ZamaError","ERC20ReadFailedError","toError","InsufficientERC20BalanceError","#shieldViaTransferAndCall","#shieldViaApproveAndWrap","#requireSigner","InsufficientAllowanceError","wrapContract","#ensureAllowance","approveContract","swallow","#finalizeUnshield","TransactionRevertedError","#extractUnwrapRequestId","#isUnwrapRequestConsumed","#clearStoredPendingUnshield","#isPendingUnshieldConsumed","EncryptionFailedError","unwrapContract","isEncryptedValueZero","DecryptionFailedError","unwrapFromBalanceContract","requireChainAlignment","finalizeUnwrapContract","unwrapRequesterContract","zeroAddress","#underlying","#underlyingPromise","underlyingContract","ZamaSDKEvents","z","checksummedAddress","#storage","#logger","#decryptNamespace","#decryptKeysNamespace","#buildStorageKey","#indexWriteQueue","#addToIndex","#doDelete","#doClearForRequester","#doClearAll","#readIndex","DecryptionFailedError","checksum","#cache","#credentialService","#delegationService","#router","#emitEvent","#decrypt","#withPropagationRetry","#assertAllDelegationsActive","#setHandleResult","isFatalBatchError","#missingBatchItem","#toZamaError","pLimit","#decryptValues","isInvalidTransportKeyPairMessage","isEncryptedValueZero","isRpcRateLimitError","#rpcRateLimitError","chunkHandlesByBitBudget","ZamaSDKEvents","#runDecryptRequests","RevokedKmsContextError","SigningFailedError","ZamaError","toError","#decryptRequest","DecryptionFailedError","RpcRateLimitError","extractRetryAfter","#router","#provider","#emitEvent","#logger","#submitAclTransaction","submitTransaction","#throwAclRevertIfMatched","TransactionRevertedError","#router","#emitEvent","ZamaSDKEvents","toError","#signer","#router","#cachingService","#credentialService","#logger","#walletAccountListeners","#unsubscribeSigner","#handleWalletAccountChange","swallow","z","checksummedAddress","unixSeconds","hex","#provider","#router","#encryption","parseSchema","ConfigurationError","#buildCalldata","#buildConfidentialTransfer","#buildConfidentialTransferFrom","#buildSetOperator","#buildUnwrap","#buildUnwrapAll","#buildFinalizeUnwrap","#buildApproveUnderlying","#buildWrap","#buildTransferAndCall","#buildDelegateDecryption","#buildRevokeDelegation","unhandled","EncryptionFailedError","confidentialTransferContract","confidentialTransferFromContract","setOperatorContract","unwrapContract","confidentialBalanceOfContract","unwrapFromBalanceContract","finalizeUnwrapContract","approveContract","wrapContract","ConfigurationError","parseSchema","DerivationSecretSchema","DerivationSecretHolder","#router","#registryTTL","#registryAddresses","#onEvent","#logger","#cachingService","#lifecycleService","#encryptionService","#decryptionService","#credentialService","#delegationService","#offlineService","WrappersRegistry","CredentialService","Token"],"sources":["../../src/errors/match.ts","../../src/errors/entitlement.ts","../../src/errors/delegation.ts","../../src/errors/revert.ts","../../src/errors/unshield.ts","../../src/errors/decrypt.ts","../../src/errors/encrypt.ts","../../src/abi/erc1363.abi.ts","../../src/contracts/erc1363.ts","../../src/abi/acl.abi.ts","../../src/contracts/acl.ts","../../src/contracts/constants.ts","../../src/config/create.ts","../../src/utils/hex.ts","../../src/events/onchain-events.ts","../../src/namespaces/permits.ts","../../src/namespaces/delegations.ts","../../src/namespaces/decryption.ts","../../src/namespaces/offline.ts","../../src/storage/chrome-session-storage.ts","../../src/token/pending-unshield.ts","../../src/token/wrapped-token.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/schemas/offline.ts","../../src/services/offline-service.ts","../../src/zama-sdk.ts"],"sourcesContent":["import { ZamaError } from \"./base\";\nimport type { ZamaErrorCode } from \"./base\";\nimport type { ChainMismatchError } from \"./chain\";\nimport type {\n KeyWrappingError,\n NoCiphertextError,\n PreparedPermitChainMismatchError,\n PreparedPermitExpiredError,\n TransportKeyPairChangedError,\n TransportKeyPairExpiredError,\n InvalidTransportKeyPairError,\n RevokedKmsContextError,\n} from \"./credential\";\nimport type {\n AclPausedError,\n DelegationContractIsSelfError,\n DelegationCooldownError,\n DelegationDelegateEqualsContractError,\n DelegationExpirationTooSoonError,\n DelegationExpiredError,\n DelegationExpiryUnchangedError,\n DelegationNotFoundError,\n DelegationNotPropagatedError,\n DelegationSelfNotAllowedError,\n} from \"./delegation\";\nimport type {\n DecryptionFailedError,\n EncryptionFailedError,\n EncryptOffloadUnavailableError,\n} from \"./encryption\";\nimport type {\n BalanceCheckUnavailableError,\n ERC20ReadFailedError,\n InsufficientAllowanceError,\n InsufficientConfidentialBalanceError,\n InsufficientERC20BalanceError,\n} from \"./balance\";\nimport type { ConfigurationError, RelayerRequestFailedError } from \"./relayer\";\nimport type { NotEntitledError } from \"./entitlement\";\nimport type { RpcRateLimitError } from \"./rpc\";\nimport type {\n SignerNotConfiguredError,\n WalletAccountNotReadyError,\n WalletNotConnectedError,\n} from \"./signer\";\nimport type { SigningFailedError, SigningRejectedError } from \"./signing\";\nimport type { TransactionRevertedError } from \"./transaction\";\nimport type { UnshieldAlreadyFinalizedError } from \"./unshield\";\n\n/**\n * Maps each {@link ZamaErrorCode} to the error class thrown with that code, so\n * {@link matchZamaError} handlers receive the matched subtype instead of the base\n * `ZamaError`.\n */\nexport interface ErrorForCode {\n /** Thrown for {@link ZamaErrorCode.SigningRejected}. */\n [ZamaErrorCode.SigningRejected]: SigningRejectedError;\n /** Thrown for {@link ZamaErrorCode.SigningFailed}. */\n [ZamaErrorCode.SigningFailed]: SigningFailedError;\n /** Thrown for {@link ZamaErrorCode.EncryptionFailed}. */\n [ZamaErrorCode.EncryptionFailed]: EncryptionFailedError;\n /** Thrown for {@link ZamaErrorCode.DecryptionFailed}. */\n [ZamaErrorCode.DecryptionFailed]: DecryptionFailedError;\n /** Thrown for {@link ZamaErrorCode.EncryptOffloadUnavailable}. */\n [ZamaErrorCode.EncryptOffloadUnavailable]: EncryptOffloadUnavailableError;\n /** Thrown for {@link ZamaErrorCode.TransactionReverted}. */\n [ZamaErrorCode.TransactionReverted]: TransactionRevertedError;\n /** Thrown for {@link ZamaErrorCode.TransportKeyPairExpired}. */\n [ZamaErrorCode.TransportKeyPairExpired]: TransportKeyPairExpiredError;\n /** Thrown for {@link ZamaErrorCode.InvalidTransportKeyPair}. */\n [ZamaErrorCode.InvalidTransportKeyPair]: InvalidTransportKeyPairError;\n /** Thrown for {@link ZamaErrorCode.RevokedKmsContext}. */\n [ZamaErrorCode.RevokedKmsContext]: RevokedKmsContextError;\n /** Thrown for {@link ZamaErrorCode.NoCiphertext}. */\n [ZamaErrorCode.NoCiphertext]: NoCiphertextError;\n /** Thrown for {@link ZamaErrorCode.RelayerRequestFailed}. */\n [ZamaErrorCode.RelayerRequestFailed]: RelayerRequestFailedError;\n /** Thrown for {@link ZamaErrorCode.NotEntitled}. */\n [ZamaErrorCode.NotEntitled]: NotEntitledError;\n /** Thrown for {@link ZamaErrorCode.RpcRateLimited}. */\n [ZamaErrorCode.RpcRateLimited]: RpcRateLimitError;\n /** Thrown for {@link ZamaErrorCode.Configuration}. */\n [ZamaErrorCode.Configuration]: ConfigurationError;\n /** Thrown for {@link ZamaErrorCode.DelegationSelfNotAllowed}. */\n [ZamaErrorCode.DelegationSelfNotAllowed]: DelegationSelfNotAllowedError;\n /** Thrown for {@link ZamaErrorCode.DelegationCooldown}. */\n [ZamaErrorCode.DelegationCooldown]: DelegationCooldownError;\n /** Thrown for {@link ZamaErrorCode.DelegationNotFound}. */\n [ZamaErrorCode.DelegationNotFound]: DelegationNotFoundError;\n /** Thrown for {@link ZamaErrorCode.DelegationExpired}. */\n [ZamaErrorCode.DelegationExpired]: DelegationExpiredError;\n /** Thrown for {@link ZamaErrorCode.InsufficientConfidentialBalance}. */\n [ZamaErrorCode.InsufficientConfidentialBalance]: InsufficientConfidentialBalanceError;\n /** Thrown for {@link ZamaErrorCode.InsufficientERC20Balance}. */\n [ZamaErrorCode.InsufficientERC20Balance]: InsufficientERC20BalanceError;\n /** Thrown for {@link ZamaErrorCode.InsufficientAllowance}. */\n [ZamaErrorCode.InsufficientAllowance]: InsufficientAllowanceError;\n /** Thrown for {@link ZamaErrorCode.BalanceCheckUnavailable}. */\n [ZamaErrorCode.BalanceCheckUnavailable]: BalanceCheckUnavailableError;\n /** Thrown for {@link ZamaErrorCode.ERC20ReadFailed}. */\n [ZamaErrorCode.ERC20ReadFailed]: ERC20ReadFailedError;\n /** Thrown for {@link ZamaErrorCode.DelegationExpiryUnchanged}. */\n [ZamaErrorCode.DelegationExpiryUnchanged]: DelegationExpiryUnchangedError;\n /** Thrown for {@link ZamaErrorCode.DelegationDelegateEqualsContract}. */\n [ZamaErrorCode.DelegationDelegateEqualsContract]: DelegationDelegateEqualsContractError;\n /** Thrown for {@link ZamaErrorCode.DelegationContractIsSelf}. */\n [ZamaErrorCode.DelegationContractIsSelf]: DelegationContractIsSelfError;\n /** Thrown for {@link ZamaErrorCode.AclPaused}. */\n [ZamaErrorCode.AclPaused]: AclPausedError;\n /** Thrown for {@link ZamaErrorCode.DelegationExpirationTooSoon}. */\n [ZamaErrorCode.DelegationExpirationTooSoon]: DelegationExpirationTooSoonError;\n /** Thrown for {@link ZamaErrorCode.DelegationNotPropagated}. */\n [ZamaErrorCode.DelegationNotPropagated]: DelegationNotPropagatedError;\n /** Thrown for {@link ZamaErrorCode.ChainMismatch}. */\n [ZamaErrorCode.ChainMismatch]: ChainMismatchError;\n /** Thrown for {@link ZamaErrorCode.SignerNotConfigured}. */\n [ZamaErrorCode.SignerNotConfigured]: SignerNotConfiguredError;\n /** Thrown for {@link ZamaErrorCode.WalletNotConnected}. */\n [ZamaErrorCode.WalletNotConnected]: WalletNotConnectedError;\n /** Thrown for {@link ZamaErrorCode.WalletAccountNotReady}. */\n [ZamaErrorCode.WalletAccountNotReady]: WalletAccountNotReadyError;\n /** Thrown for {@link ZamaErrorCode.KeyWrappingFailed}. */\n [ZamaErrorCode.KeyWrappingFailed]: KeyWrappingError;\n /** Thrown for {@link ZamaErrorCode.TransportKeyPairChanged}. */\n [ZamaErrorCode.TransportKeyPairChanged]: TransportKeyPairChangedError;\n /** Thrown for {@link ZamaErrorCode.PreparedPermitChainMismatch}. */\n [ZamaErrorCode.PreparedPermitChainMismatch]: PreparedPermitChainMismatchError;\n /** Thrown for {@link ZamaErrorCode.PreparedPermitExpired}. */\n [ZamaErrorCode.PreparedPermitExpired]: PreparedPermitExpiredError;\n /** Thrown for {@link ZamaErrorCode.UnshieldAlreadyFinalized}. */\n [ZamaErrorCode.UnshieldAlreadyFinalized]: UnshieldAlreadyFinalizedError;\n}\n\n/**\n * Pattern-match on a {@link ZamaError} by its error code. Each handler receives the\n * error class for its code, so subclass fields are available without a cast.\n * Falls through to the `_` wildcard handler if no specific handler matches.\n * Returns `undefined` if the error is not a `ZamaError` and no `_` handler is provided.\n *\n * @example\n * ```ts\n * matchZamaError(error, {\n * SIGNING_REJECTED: () => toast(\"Please approve in wallet\"),\n * INSUFFICIENT_CONFIDENTIAL_BALANCE: (e) => toast(`Need ${e.requested}, have ${e.available}`),\n * RELAYER_REQUEST_FAILED: (e) => toast(`Relayer failed (${e.statusCode})`),\n * _: () => toast(\"Unknown error\"),\n * });\n * ```\n */\nexport function matchZamaError<R>(\n error: unknown,\n handlers: { [K in ZamaErrorCode]?: (error: ErrorForCode[K]) => R } & {\n _?: (error: unknown) => R;\n },\n): R | undefined {\n if (error instanceof ZamaError) {\n // `error.code` narrows the handler at runtime; the cast bridges the per-code param types.\n const handler = handlers[error.code] as ((error: ZamaError) => R) | undefined;\n if (handler) {\n return handler(error);\n }\n }\n return handlers._?.(error);\n}\n","import { ZamaError, ZamaErrorCode } from \"./base\";\n\n/**\n * The signer (or delegator) lacks ACL permission to decrypt the encrypted value —\n * `persistAllowed` returned `false`. Terminal and **non-retryable**: the fix is\n * an on-chain grant (`FHE.allow`), or for indexers, to wait for a backfill once\n * the grant lands. Distinct from transient failures like {@link RpcRateLimitError}.\n *\n * @example\n * ```ts\n * try {\n * await sdk.decryption.decryptValues([{ encryptedValue, contractAddress }]);\n * } catch (e) {\n * if (e instanceof NotEntitledError) {\n * // don't retry — wait for an ACL grant / backfill\n * }\n * }\n * ```\n */\nexport class NotEntitledError extends ZamaError {\n /** The encrypted value the actor is not entitled to decrypt. */\n readonly encryptedValue: string;\n /** The contract the encrypted value belongs to. */\n readonly contractAddress: string;\n /** The actor (signer or delegator) that lacks ACL permission. */\n readonly account: string;\n\n constructor(\n args: { encryptedValue: string; contractAddress: string; account: string },\n options?: ErrorOptions,\n ) {\n super(\n ZamaErrorCode.NotEntitled,\n `Account ${args.account} is not entitled to decrypt encrypted value ${args.encryptedValue} ` +\n `on contract ${args.contractAddress}. This is not a transient failure — ` +\n `the account needs an on-chain ACL grant before it can decrypt this encrypted value.`,\n options,\n );\n this.name = \"NotEntitledError\";\n this.encryptedValue = args.encryptedValue;\n this.contractAddress = args.contractAddress;\n this.account = args.account;\n }\n}\n","import { ZamaError, ZamaErrorCode } from \"./base\";\n\n// Delegation errors — thrown by SDK pre-flight checks and by delegation\n// transaction callsites when they map ACL Solidity revert reasons.\n\n/** Delegation cannot target self (delegate === msg.sender). */\nexport class DelegationSelfNotAllowedError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationSelfNotAllowed, message, options);\n this.name = \"DelegationSelfNotAllowedError\";\n }\n}\n\n/** Only one delegate/revoke per (delegator, delegate, contract) per block. */\nexport class DelegationCooldownError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationCooldown, message, options);\n this.name = \"DelegationCooldownError\";\n }\n}\n\n/** No active delegation found for this (delegator, delegate, contract) tuple. */\nexport class DelegationNotFoundError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationNotFound, message, options);\n this.name = \"DelegationNotFoundError\";\n }\n}\n\n/** The delegation has expired. */\nexport class DelegationExpiredError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationExpired, message, options);\n this.name = \"DelegationExpiredError\";\n }\n}\n\n/** The new expiration date equals the current one. */\nexport class DelegationExpiryUnchangedError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationExpiryUnchanged, message, options);\n this.name = \"DelegationExpiryUnchangedError\";\n }\n}\n\n/** Delegate address cannot be the contract address. */\nexport class DelegationDelegateEqualsContractError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationDelegateEqualsContract, message, options);\n this.name = \"DelegationDelegateEqualsContractError\";\n }\n}\n\n/** Contract address cannot be the sender address. */\nexport class DelegationContractIsSelfError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationContractIsSelf, message, options);\n this.name = \"DelegationContractIsSelfError\";\n }\n}\n\n/** The ACL contract is paused. */\nexport class AclPausedError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.AclPaused, message, options);\n this.name = \"AclPausedError\";\n }\n}\n\n/** Expiration date is too soon (must be at least 1 hour in the future). */\nexport class DelegationExpirationTooSoonError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationExpirationTooSoon, message, options);\n this.name = \"DelegationExpirationTooSoonError\";\n }\n}\n\n/**\n * Delegation exists on L1 but hasn't propagated to the gateway yet.\n *\n * After calling `delegateForUserDecryption()`, the delegation is recorded on-chain\n * immediately. However, the gateway (deployed on Arbitrum) must sync this state\n * via cross-chain event propagation, which usually completes within ~10 blocks\n * (a few seconds).\n *\n * Calling `decryptBalanceAs` during this window will fail because the gateway's\n * `isHandleDelegatedForUserDecryption()` check reads from its own synced copy\n * of the ACL state, which hasn't been updated yet.\n *\n * **You rarely need to handle this directly:** the delegated-decrypt path rides\n * out the propagation window with a bounded internal retry (~30s), so a decrypt\n * issued right after the grant simply waits for sync. This error only surfaces\n * if the window outlasts the retry budget, or when retries are disabled via\n * `waitForPropagation: false`.\n *\n * **Note:** This error is raised as a best-effort heuristic — when a delegated\n * decryption receives an HTTP 500 from the relayer, the most likely cause is a\n * propagation delay. However, the same status code can occur if the gateway or\n * relayer experiences an unrelated internal error.\n */\nexport class DelegationNotPropagatedError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationNotPropagated, message, options);\n this.name = \"DelegationNotPropagatedError\";\n }\n}\n","/**\n * Extract the decoded custom error name from a viem ContractFunctionRevertedError,\n * or `null` when the error carries no structured revert data.\n * @internal\n */\nexport function 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","import { keccak256, toBytes, type Hex } from \"viem\";\nimport type { EncryptedValue } from \"../relayer/types\";\nimport { ZamaError, ZamaErrorCode } from \"./base\";\nimport { extractRevertErrorName } from \"./revert\";\n\n/** Structured details identifying the consumed unwrap request. */\nexport interface UnshieldAlreadyFinalizedDetails {\n /** Transaction hash of the original unwrap request. */\n readonly unwrapTxHash: Hex;\n /** Request identifier from the `UnwrapRequested` event. */\n readonly unwrapRequestId: EncryptedValue;\n}\n\n/**\n * The unwrap request was already finalized on-chain: the underlying ERC-20\n * tokens were delivered and there is nothing left to resume. The SDK clears\n * the persisted pending-unshield pointer before throwing, so treat this as a\n * success signal: refresh balances and dismiss any \"resume unshield\" prompt.\n */\nexport class UnshieldAlreadyFinalizedError extends ZamaError {\n /** Transaction hash of the original unwrap request. */\n readonly unwrapTxHash: Hex;\n /** Request identifier from the `UnwrapRequested` event. */\n readonly unwrapRequestId: EncryptedValue;\n\n constructor(message: string, details: UnshieldAlreadyFinalizedDetails, options?: ErrorOptions) {\n super(ZamaErrorCode.UnshieldAlreadyFinalized, message, options);\n this.name = \"UnshieldAlreadyFinalizedError\";\n this.unwrapTxHash = details.unwrapTxHash;\n this.unwrapRequestId = details.unwrapRequestId;\n }\n}\n\nconst INVALID_UNWRAP_REQUEST = \"InvalidUnwrapRequest\";\nconst INVALID_UNWRAP_REQUEST_SELECTOR = keccak256(\n toBytes(`${INVALID_UNWRAP_REQUEST}(bytes32)`),\n).slice(0, 10);\n\n/**\n * True if `error` (or anything on its `cause` chain) is the wrapper's\n * `InvalidUnwrapRequest` custom revert. Prefers viem's structured\n * `cause.data.errorName`, falling back to message matching on the error name\n * and the raw 4-byte selector for non-viem providers.\n * @internal\n */\nexport function isInvalidUnwrapRequestRevert(error: unknown): boolean {\n for (let current = error; current instanceof Error; current = current.cause) {\n if (extractRevertErrorName(current) === INVALID_UNWRAP_REQUEST) {\n return true;\n }\n if (\n current.message.includes(INVALID_UNWRAP_REQUEST) ||\n current.message.includes(INVALID_UNWRAP_REQUEST_SELECTOR)\n ) {\n return true;\n }\n }\n return false;\n}\n","import type { ZamaError } from \"./base\";\nimport { DecryptionFailedError } from \"./encryption\";\nimport {\n InvalidTransportKeyPairError,\n NoCiphertextError,\n RevokedKmsContextError,\n} from \"./credential\";\nimport { RelayerRequestFailedError } from \"./relayer\";\nimport { DelegationNotPropagatedError } from \"./delegation\";\nimport { NotEntitledError } from \"./entitlement\";\nimport { RpcRateLimitError } from \"./rpc\";\nimport { SigningRejectedError, SigningFailedError } from \"./signing\";\nimport {\n extractHttpStatus,\n extractRetryAfter,\n hasStructuredRpcRateLimitSignal,\n isInvalidTransportKeyPairMessage,\n isNotEntitledMessage,\n isRelayerError,\n isRelayerTimeoutError,\n isRevokedKmsContextError,\n isRpcRateLimitError,\n parseHandleFromMessage,\n} from \"../utils/error\";\n\n/**\n * Context the caller supplies so a not-entitled / delegation failure can be\n * mapped precisely. The request context (`contractAddress` / `account`) is not\n * present on the raw error, so it is injected here.\n */\nexport interface DecryptErrorContext {\n isDelegated?: boolean;\n contractAddress?: string;\n /** The ACL actor (signer, or delegator for delegated decrypt). */\n account?: string;\n}\n\n/**\n * Every typed SDK error `wrapDecryptError` may see on its way in (from a prior\n * classification, a worker rethrow, or a caller-level retry) and must pass\n * through unchanged rather than collapse into terminal `DecryptionFailedError`.\n * A single source of truth for the early-return check below and for the\n * `errors.test.ts` \"every typed cause passes through unchanged\" test — so a\n * class dropped from this array is caught by that test instead of silently\n * falling through to the generic fallback.\n *\n * This is a fixed, decrypt-scoped subset of the taxonomy maintained by hand\n * (unlike {@link RETRYABLE_BY_CODE} in `base.ts`, it has no `Complete<>` tie\n * to `ZamaErrorCode`) — a new decrypt-path error class must be added here\n * explicitly, since there's no compiler check forcing it.\n */\nexport const DECRYPT_PASSTHROUGH_ERROR_TYPES = [\n DecryptionFailedError,\n NoCiphertextError,\n RelayerRequestFailedError,\n DelegationNotPropagatedError,\n SigningRejectedError,\n SigningFailedError,\n NotEntitledError,\n RpcRateLimitError,\n InvalidTransportKeyPairError,\n RevokedKmsContextError,\n] as const;\n\n/**\n * The single decryption-error classifier. Maps a caught error to the right typed\n * SDK error: not-entitled (ACL), consumer RPC rate-limit, NoCiphertext (400),\n * DelegationNotPropagated (delegated 500 *or* a delegated ACL denial, which is\n * transient), RelayerRequestFailed (other HTTP), or the generic DecryptionFailed\n * fallback.\n *\n * Errors that are already typed SDK errors are returned as-is so callers can\n * still match the original cause. All structured signals (codes, status, cause\n * chain) are read from the error itself.\n */\nexport function wrapDecryptError(\n error: unknown,\n fallbackMessage: string,\n ctx: DecryptErrorContext = {},\n): ZamaError {\n if (DECRYPT_PASSTHROUGH_ERROR_TYPES.some((ErrorType) => error instanceof ErrorType)) {\n return error as ZamaError;\n }\n\n const message = error instanceof Error ? error.message : fallbackMessage;\n\n // Stale transport key pair the relayer can't re-derive (post KMS/TKMS rotation).\n // Typed so the decrypt path can evict the vault entry and regenerate on retry.\n if (error instanceof Error && isInvalidTransportKeyPairMessage(error.message)) {\n return new InvalidTransportKeyPairError(error.message, { cause: error });\n }\n\n // The permit's KMS context was revoked on-chain (InvalidKmsContext revert).\n // Typed so the decrypt path can evict the dead permit, re-grant, and retry once.\n if (isRevokedKmsContextError(error)) {\n return new RevokedKmsContextError(\n \"The permit's KMS context has been revoked on-chain, so the permit is no longer usable. \" +\n \"The SDK evicts the permit and re-grants automatically; if this error surfaced, the retry \" +\n \"failed the same way. The on-chain validity check is cached for up to 15 minutes, so a \" +\n \"just-revoked context can keep failing across that window. Retry after the window; the \" +\n \"SDK re-runs the recovery on the next decrypt, no manual cleanup is needed.\",\n { cause: error },\n );\n }\n\n // Actor not entitled (ACL). The relayer throws a message-only Error; the handle\n // is parseable from it and the contract/account come from the request context\n // the caller holds.\n if (error instanceof Error && isNotEntitledMessage(error.message)) {\n // On the delegated path the \"not entitled\" verdict comes from the\n // *delegator's* `persistAllowed` L1 read, which has no staleness tolerance:\n // it returns false *transiently* when the delegation has just landed or the\n // consumer's RPC serves a lagging block. Terminal `NotEntitledError` (\"never\n // retry\") would be the wrong signal for that propagation window, so — mirroring\n // the delegated-500 branch below — surface the retryable\n // `DelegationNotPropagatedError` instead. A direct signer denial (non-\n // delegated) stays terminal `NotEntitledError`.\n if (ctx.isDelegated) {\n return new DelegationNotPropagatedError(\n \"Delegated decryption was denied by the on-chain ACL check. \" +\n \"This is most commonly caused by the delegation not having propagated yet, or by the \" +\n \"RPC node serving a stale block. Propagation usually completes within ~10 blocks (a few \" +\n \"seconds) and the SDK retries across that window; seeing this means it did not sync in time. \" +\n \"Retry shortly (and prefer a fresh, low-lag RPC endpoint). If it persists, the delegator may \" +\n \"genuinely lack the on-chain ACL grant.\",\n { cause: error },\n );\n }\n return new NotEntitledError(\n {\n encryptedValue: parseHandleFromMessage(error.message) ?? \"\",\n contractAddress: ctx.contractAddress ?? \"\",\n account: ctx.account ?? \"\",\n },\n { cause: error },\n );\n }\n\n // Consumer's RPC provider throttling an on-chain read. An unambiguous\n // structured signal (-32005 / viem `status: 429`) wins over any HTTP status;\n // relayer-origin errors are `@fhevm/sdk` `Relayer*` classes and are excluded by\n // `isRelayerError`, staying RelayerRequestFailedError below.\n if (hasStructuredRpcRateLimitSignal(error)) {\n return new RpcRateLimitError(message, { cause: error, retryAfter: extractRetryAfter(error) });\n }\n\n const statusCode = extractHttpStatus(error);\n\n // A message-only throttle (\"Too Many Requests\" / \"rate limit\") is trusted only\n // when no HTTP status is present — otherwise the status classification (e.g. a\n // relayer error whose body mentions a rate limit) takes precedence.\n if (statusCode === undefined && isRpcRateLimitError(error)) {\n return new RpcRateLimitError(message, { cause: error, retryAfter: extractRetryAfter(error) });\n }\n\n if (statusCode === 400) {\n return new NoCiphertextError(\n error instanceof Error ? error.message : \"No ciphertext for this account\",\n { cause: error },\n );\n }\n\n if (ctx.isDelegated && statusCode === 500) {\n return new DelegationNotPropagatedError(\n \"Delegated decryption failed with a server error. \" +\n \"This is most commonly caused by the delegation not having propagated to the gateway yet. \" +\n \"Cross-chain sync usually completes within ~10 blocks (a few seconds) and the SDK retries \" +\n \"across that window; seeing this means it did not sync in time — retry shortly. \" +\n \"If the error persists, the gateway or relayer may be experiencing an unrelated issue.\",\n { cause: error },\n );\n }\n\n if (isRelayerError(error) || statusCode !== undefined) {\n return new RelayerRequestFailedError(message, statusCode, {\n cause: error,\n retryAfter: extractRetryAfter(error),\n // A relayer timeout carries no HTTP status but is safe to retry; force\n // `retryable` so it isn't misclassified as terminal. Other relayer errors\n // fall back to the status-based default (429 → retryable).\n retryable: isRelayerTimeoutError(error) || undefined,\n });\n }\n\n return new DecryptionFailedError(fallbackMessage, { cause: error });\n}\n","import {\n extractHttpStatus,\n extractRetryAfter,\n isRelayerError,\n isRelayerTimeoutError,\n} 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 `@fhevm/sdk` relayer origin or HTTP\n * status code and return the appropriate typed SDK error. Relayer transport\n * failures without a status, plus HTTP failures from the relayer or an\n * intermediary such as Cloudflare/Kong, surface as\n * {@link RelayerRequestFailedError} instead of collapsing into a generic\n * {@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 relayer's HTTP status may surface as `status` or `statusCode` anywhere in\n * the cause chain; {@link extractHttpStatus} walks the chain for either, mirroring\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 // A relayer timeout carries no HTTP status but is safe to retry — surface it as\n // a retryable RelayerRequestFailedError rather than a terminal EncryptionFailed.\n const isTimeout = isRelayerTimeoutError(error);\n\n if (statusCode !== undefined || isRelayerError(error)) {\n return new RelayerRequestFailedError(\n error instanceof Error ? error.message : fallbackMessage,\n statusCode,\n { cause: error, retryAfter: extractRetryAfter(error), retryable: isTimeout || undefined },\n );\n }\n\n return new EncryptionFailedError(fallbackMessage, { cause: error });\n}\n","// DO NOT EDIT: generated by `pnpm abi:build` from\n// contracts/out/IERC1363.sol/IERC1363.json.\n// Regenerate after `pnpm contracts:build`; `pnpm abi:check` enforces this in CI.\nexport const erc1363Abi = [\n {\n type: \"function\",\n name: \"allowance\",\n inputs: [\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"approve\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"approveAndCall\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"approveAndCall\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"balanceOf\",\n inputs: [{ name: \"account\", type: \"address\", internalType: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"supportsInterface\",\n inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"totalSupply\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"transfer\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferAndCall\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferAndCall\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFrom\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFromAndCall\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFromAndCall\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"event\",\n name: \"Approval\",\n inputs: [\n { name: \"owner\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"spender\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n ],\n anonymous: false,\n },\n {\n type: \"event\",\n name: \"Transfer\",\n inputs: [\n { name: \"from\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"to\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n ],\n anonymous: false,\n },\n] as const;\n","import type { Address, Hex } from \"viem\";\nimport { erc1363Abi } from \"../abi/erc1363.abi\";\n\n/**\n * Returns the contract config for an ERC-1363 `transferAndCall`.\n *\n * @param tokenAddress - The ERC-20 token to transfer from (the underlying, not the wrapper).\n * @param to - The recipient of the ERC-20 transfer. In `Token.shield`, this is\n * the wrapper contract whose `onTransferReceived` callback mints\n * confidential tokens to the address encoded in `data`.\n * @param amount - The amount to transfer.\n * @param data - Raw 20-byte recipient address for shield-to-other (decoded by\n * the wrapper as `address(bytes20(data))`). Empty `0x` for self-shield —\n * the wrapper falls back to `from`.\n */\nexport function transferAndCallContract(\n tokenAddress: Address,\n to: Address,\n amount: bigint,\n data: Hex = \"0x\",\n) {\n return {\n address: tokenAddress,\n abi: erc1363Abi,\n functionName: \"transferAndCall\",\n args: [to, amount, data],\n } as const;\n}\n","// DO NOT EDIT: generated by `pnpm abi:build` from\n// contracts/out/Impl.sol/IACL.json.\n// Regenerate after `pnpm contracts:build`; `pnpm abi:check` enforces this in CI.\nexport const aclAbi = [\n {\n type: \"function\",\n name: \"allow\",\n inputs: [\n { name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"account\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"allowForDecryption\",\n inputs: [{ name: \"handlesList\", type: \"bytes32[]\", internalType: \"bytes32[]\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"allowTransient\",\n inputs: [\n { name: \"ciphertext\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"account\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"cleanTransientStorage\",\n inputs: [],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"delegateForUserDecryption\",\n inputs: [\n { name: \"delegate\", type: \"address\", internalType: \"address\" },\n { name: \"contractAddress\", type: \"address\", internalType: \"address\" },\n { name: \"expirationDate\", type: \"uint64\", internalType: \"uint64\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"getUserDecryptionDelegationExpirationDate\",\n inputs: [\n { name: \"delegator\", type: \"address\", internalType: \"address\" },\n { name: \"delegate\", type: \"address\", internalType: \"address\" },\n { name: \"contractAddress\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint64\", internalType: \"uint64\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"isAccountDenied\",\n inputs: [{ name: \"account\", type: \"address\", internalType: \"address\" }],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"isAllowed\",\n inputs: [\n { name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"account\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"isAllowedForDecryption\",\n inputs: [{ name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" }],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"isHandleDelegatedForUserDecryption\",\n inputs: [\n { name: \"delegator\", type: \"address\", internalType: \"address\" },\n { name: \"delegate\", type: \"address\", internalType: \"address\" },\n { name: \"contractAddress\", type: \"address\", internalType: \"address\" },\n { name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"multicall\",\n inputs: [{ name: \"data\", type: \"bytes[]\", internalType: \"bytes[]\" }],\n outputs: [{ name: \"results\", type: \"bytes[]\", internalType: \"bytes[]\" }],\n stateMutability: \"payable\",\n },\n {\n type: \"function\",\n name: \"persistAllowed\",\n inputs: [\n { name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"account\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"revokeDelegationForUserDecryption\",\n inputs: [\n { name: \"delegate\", type: \"address\", internalType: \"address\" },\n { name: \"contractAddress\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n] as const;\n","import type { Address } from \"viem\";\nimport { aclAbi } from \"../abi/acl.abi\";\n\n/**\n * Returns the contract config to delegate user decryption rights.\n *\n * @example\n * ```ts\n * const txHash = await signer.writeContract(\n * delegateForUserDecryptionContract(aclAddress, delegateAddress, contractAddress, expirationDate),\n * );\n * ```\n */\nexport function delegateForUserDecryptionContract(\n aclAddress: Address,\n delegateAddress: Address,\n contractAddress: Address,\n expirationDate: bigint,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"delegateForUserDecryption\",\n args: [delegateAddress, contractAddress, expirationDate],\n } as const;\n}\n\n/**\n * Returns the contract config to revoke a user decryption delegation.\n *\n * @example\n * ```ts\n * const txHash = await signer.writeContract(\n * revokeDelegationContract(aclAddress, delegateAddress, contractAddress),\n * );\n * ```\n */\nexport function revokeDelegationContract(\n aclAddress: Address,\n delegateAddress: Address,\n contractAddress: Address,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"revokeDelegationForUserDecryption\",\n args: [delegateAddress, contractAddress],\n } as const;\n}\n\n/**\n * Returns the contract config to read the delegation expiry date.\n *\n * @example\n * ```ts\n * const expiry = await provider.readContract(\n * getDelegationExpiryContract(aclAddress, delegatorAddress, delegateAddress, contractAddress),\n * );\n * ```\n */\nexport function getDelegationExpiryContract(\n aclAddress: Address,\n delegatorAddress: Address,\n delegateAddress: Address,\n contractAddress: Address,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"getUserDecryptionDelegationExpirationDate\",\n args: [delegatorAddress, delegateAddress, contractAddress],\n } as const;\n}\n\n/**\n * Returns the contract config to check if a specific handle is delegated.\n *\n * @example\n * ```ts\n * const isDelegated = await provider.readContract(\n * isHandleDelegatedContract(aclAddress, delegatorAddress, delegateAddress, contractAddress, handle),\n * );\n * ```\n */\nexport function isHandleDelegatedContract(\n aclAddress: Address,\n delegatorAddress: Address,\n delegateAddress: Address,\n contractAddress: Address,\n handle: `0x${string}`,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"isHandleDelegatedForUserDecryption\",\n args: [delegatorAddress, delegateAddress, contractAddress, handle],\n } as const;\n}\n","/** uint64 max — represents a permanent (no-expiry) delegation. */\nexport const MAX_UINT64 = 2n ** 64n - 1n;\n\n/**\n * uint48 max — represents a permanent (no-expiry) operator approval.\n * `setOperator`'s `until` argument is a `uint48` timestamp; this fits in a\n * JS number (< 2^53) and mirrors {@link MAX_UINT64}'s \"permanent\" role.\n */\nexport const MAX_UINT48 = 2 ** 48 - 1;\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 { 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","/**\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/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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 { getAddress, type Address, type Hex } from \"viem\";\nimport type { CredentialService } from \"../credentials/credential-service\";\nimport type { PreparedPermit } from \"../credentials/types\";\nimport { requireConfigured } from \"../errors\";\nimport type { PermitOperation, ZamaSDKEventInput } from \"../events/sdk-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { CachingService } from \"../services/caching-service\";\nimport type { GenericLogger, GenericProvider, GenericSigner } from \"../types\";\nimport { swallow } from \"../utils\";\nimport { requireAlignedWalletAccount, requireChainAlignment } from \"../utils/alignment\";\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 *\n * When `transportKeyPairScope` is configured (opt-in shared-tenant scope for B2B2C/WaaS\n * operators), {@link clear} and {@link revokePermits} stay signer-level only — they never\n * touch the shared key pair. {@link revokeTransportKeyPair} is the distinct,\n * operator-level operation for that.\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 readonly #emitEvent: (input: ZamaSDKEventInput) => void;\n\n /** @internal */\n constructor(opts: {\n signer: GenericSigner | undefined;\n provider: GenericProvider;\n cachingService: CachingService;\n credentialService: CredentialService | undefined;\n logger: GenericLogger;\n emitEvent: (input: ZamaSDKEventInput) => void;\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 this.#emitEvent = opts.emitEvent;\n }\n\n #requireCredentialService(operation: string): CredentialService {\n return requireConfigured(this.#credentialService, operation);\n }\n\n /**\n * Emit a {@link ZamaSDKEvents.PermitError} event for a pre-flight guard\n * failure (no signer/CredentialService configured, chain mismatch) and\n * rethrow the same error unchanged. These guards run in this namespace\n * layer, before {@link CredentialService} (and its own equivalent choke\n * point) is ever reached, so without this they'd be invisible to `onEvent`\n * regardless of what CredentialService itself emits.\n *\n * Only for the pre-flight guards below — never wrap a delegated\n * `CredentialService` call in this, since that call already emits\n * internally on failure; doing it here too would double-emit.\n */\n #failPermit(operation: PermitOperation, error: unknown): never {\n this.#emitEvent({\n type: ZamaSDKEvents.PermitError,\n operation,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n throw error;\n }\n\n /**\n * Sign and store an EIP-712 permit authorizing 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 * @throws if `transportKeyPairDerivationSecret` is configured and the keypair fails to wrap or\n * unwrap. {@link KeyWrappingError}\n */\n async grantPermit(contracts: Address[]): Promise<void> {\n if (contracts.length === 0) {\n return;\n }\n let service: CredentialService;\n try {\n service = this.#requireCredentialService(\"grantPermit\");\n await requireChainAlignment(\"grantPermit\", this.#signer, this.#provider);\n } catch (error) {\n this.#failPermit(\"grantPermit\", error);\n }\n await service.grantPermit(contracts);\n }\n\n /**\n * Sign and store an EIP-712 delegation permit authorizing 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 * @throws if `transportKeyPairDerivationSecret` is configured and the keypair fails to wrap or\n * unwrap. {@link KeyWrappingError}\n */\n async grantDelegationPermit(delegator: Address, contracts: Address[]): Promise<void> {\n if (contracts.length === 0) {\n return;\n }\n let service: CredentialService;\n try {\n service = this.#requireCredentialService(\"grantDelegationPermit\");\n await requireChainAlignment(\"grantDelegationPermit\", this.#signer, this.#provider);\n } catch (error) {\n this.#failPermit(\"grantDelegationPermit\", error);\n }\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, or when `transportKeyPairDerivationSecret` is configured and the stored keypair\n * fails to unwrap. Does not swallow other errors (e.g. a failing storage backend), which\n * propagate normally.\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. Never throws when the stored keypair\n * fails to unwrap, reporting no permit instead; other errors still propagate.\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 * Not for pre-warming a shared `transportKeyPairScope`: this call's wallet-account\n * precondition doesn't conceptually apply to a scope-wide key, and would silently\n * no-op precisely when an operator is most likely to be calling it (no end-user\n * connected yet). Use {@link warmTransportKeyPairScope} instead.\n *\n * @throws if `transportKeyPairDerivationSecret` is configured and the keypair fails to wrap or\n * unwrap. {@link KeyWrappingError}\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 * Offline permit flow, phase 2: verify and persist the signature an\n * out-of-process signer produced for a `sdk.offline.preparePermit` payload.\n *\n * No wallet account required: the permit is scoped by `prepared.signerAddress`\n * (and `prepared.delegatorAddress`, if present), not a connected signer.\n *\n * @param prepared - The payload `sdk.offline.preparePermit` returned.\n * @param signature - The 65-byte `eth_signTypedData_v4` signature over `prepared.eip712`.\n * @throws if `prepared` doesn't match the `PreparedPermit` shape (e.g. it crossed a\n * process boundary and was corrupted). {@link ConfigurationError}\n * @throws if the chain embedded in `prepared.eip712` doesn't match the active chain. {@link PreparedPermitChainMismatchError}\n * @throws if the permit's validity window has already elapsed. {@link PreparedPermitExpiredError}\n * @throws if the transport key pair changed since prepare. {@link TransportKeyPairChangedError}\n * @throws if the signature is invalid or malformed. {@link SigningFailedError}\n */\n async registerPermit(prepared: PreparedPermit, signature: Hex): Promise<void> {\n let service: CredentialService;\n try {\n service = this.#requireCredentialService(\"registerPermit\");\n } catch (error) {\n this.#failPermit(\"registerPermit\", error);\n }\n await service.registerPermit(prepared, signature);\n await this.#clearDecryptCacheForRequester(prepared.signerAddress);\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 this.#clearDecryptCacheForRequester(signerAddress);\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 this.#clearDecryptCacheForRequester(signerAddress);\n }\n }\n\n async #clearDecryptCacheForRequester(signerAddress: Address): Promise<void> {\n await swallow(\n \"clear decrypt cache\",\n () => this.#cachingService.clearForRequester(signerAddress),\n this.#logger,\n );\n }\n\n /**\n * Revoke the shared transport key pair for `transportKeyPairScope`. Storage-only,\n * operator-level action: no wallet account or signer needs to be connected.\n *\n * Deletes the shared key pair; every permit in the scope embeds its public key, so\n * they're all treated as stale on next access. Signer-level {@link clear} never does\n * this — it only ever wipes the calling signer's own permits.\n *\n * Not best-effort, unlike most credential-store writes: a storage failure rejects\n * instead of being logged and swallowed. This is the primitive an operator reaches\n * for on suspected key compromise — a resolved promise must mean the key pair is\n * actually gone.\n *\n * Stops the SDK from reissuing or reusing the deleted key — does not revoke any\n * permit already issued under it. A permit is a self-contained, bearer-style EIP-712\n * signature the relayer accepts independently of this SDK; one exfiltrated alongside\n * the key remains usable until its own `permitTTL` expiry regardless of this call.\n *\n * @param scopeId - Must match the configured `transportKeyPairScope`, as a guard\n * against revoking the wrong scope by mistake.\n * @throws if no scope is configured, or `scopeId` doesn't match it. {@link ConfigurationError}\n * @throws if the underlying storage delete fails.\n */\n async revokeTransportKeyPair(scopeId: string): Promise<void> {\n const service = this.#requireCredentialService(\"revokeTransportKeyPair\");\n await service.revokeTransportKeyPair(scopeId);\n }\n\n /**\n * Warm the shared transport key pair for `transportKeyPairScope` — the pre-warm\n * counterpart to {@link revokeTransportKeyPair}. Storage-only, operator-level action:\n * no wallet account or signer needs to be connected. Prefer this over\n * {@link warmTransportKeyPair} for a scoped key pair: unlike that method, this never\n * silently no-ops for lack of a connected wallet, because a scope-wide key was never\n * tied to one in the first place.\n *\n * @param scopeId - Must match the configured `transportKeyPairScope`, as a guard\n * against warming the wrong scope by mistake.\n * @throws if no scope is configured, or `scopeId` doesn't match it. {@link ConfigurationError}\n * @throws if `transportKeyPairDerivationSecret` is configured and the keypair fails to wrap or\n * unwrap. {@link KeyWrappingError}\n */\n async warmTransportKeyPairScope(scopeId: string): Promise<void> {\n const service = this.#requireCredentialService(\"warmTransportKeyPairScope\");\n await service.warmTransportKeyPairScope(scopeId);\n }\n}\n","import type { Address } from \"viem\";\nimport type { DelegationService, DelegationStatus } from \"../services/delegation-service\";\nimport type { GenericProvider, GenericSigner, TransactionResult } from \"../types\";\nimport { requireAlignedWalletAccount } from \"../utils/alignment\";\nimport { requireConfigured } from \"../errors\";\n\n/**\n * Public namespace for on-chain decryption-delegation management.\n *\n * Exposed as `sdk.delegations`. Owns the SDK-level guards (signer requirement, chain\n * alignment, delegator address resolution from the wallet account) and delegates the\n * actual work to the internal {@link DelegationService}.\n *\n * Delegation operations write to the host chain ACL; after a delegation is mined,\n * the gateway syncs the ACL state via cross-chain event propagation — usually\n * within ~10 blocks (a few seconds). Delegated decryption rides out that window\n * with a bounded internal retry, so callers can decrypt right after granting.\n */\nexport class Delegations {\n readonly #signer: GenericSigner | undefined;\n readonly #provider: GenericProvider;\n readonly #delegationService: DelegationService;\n\n /** @internal */\n constructor(opts: {\n signer: GenericSigner | undefined;\n provider: GenericProvider;\n delegationService: DelegationService;\n }) {\n this.#signer = opts.signer;\n this.#provider = opts.provider;\n this.#delegationService = opts.delegationService;\n }\n\n #requireSigner(operation: string): GenericSigner {\n return requireConfigured(this.#signer, operation);\n }\n\n /**\n * Delegate decryption rights for a confidential contract to another address.\n * Calls `ACL.delegateForUserDecryption()` on-chain.\n *\n * The delegation is recorded on L1 immediately, but the gateway must sync the\n * ACL state via cross-chain event propagation — usually within ~10 blocks (a\n * few seconds). You do not need to wait: delegated decryption rides out that\n * window with a bounded internal retry, so you can decrypt right after this\n * resolves.\n *\n * @param contractAddress - The confidential contract address to delegate on.\n * @param delegateAddress - Address to delegate decryption rights to.\n * @param expirationDate - Optional expiration date (defaults to permanent delegation via `uint64.max`).\n * @returns The transaction hash and mined receipt.\n * @throws if no signer is configured. {@link SignerNotConfiguredError}\n * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n * @throws if `expirationDate` is less than 1 hour in the future. {@link DelegationExpirationTooSoonError}\n * @throws if the delegate equals the connected wallet. {@link DelegationSelfNotAllowedError}\n * @throws if the delegate equals the contract address. {@link DelegationDelegateEqualsContractError}\n * @throws if the new expiry equals the current one. {@link DelegationExpiryUnchangedError}\n * @throws if the delegation transaction reverts. {@link TransactionRevertedError}\n */\n async delegateDecryption({\n contractAddress,\n delegateAddress,\n expirationDate,\n }: {\n contractAddress: Address;\n delegateAddress: Address;\n expirationDate?: Date;\n }): Promise<TransactionResult> {\n const signer = this.#requireSigner(\"delegateDecryption\");\n const account = await requireAlignedWalletAccount(\n \"delegateDecryption\",\n this.#signer,\n this.#provider,\n );\n return this.#delegationService.delegateDecryption(signer, {\n contractAddress,\n delegateAddress,\n delegatorAddress: account.address,\n expirationDate,\n });\n }\n\n /**\n * Revoke decryption delegation for a confidential contract.\n * Calls `ACL.revokeDelegationForUserDecryption()` on-chain.\n *\n * @param contractAddress - The confidential contract address to revoke delegation on.\n * @param delegateAddress - Address to revoke delegation from.\n * @returns The transaction hash and mined receipt.\n * @throws if no signer is configured. {@link SignerNotConfiguredError}\n * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n * @throws if no delegation exists for this (delegator, delegate, contract) tuple. {@link DelegationNotFoundError}\n * @throws if the revocation transaction reverts. {@link TransactionRevertedError}\n */\n async revokeDelegation({\n contractAddress,\n delegateAddress,\n }: {\n contractAddress: Address;\n delegateAddress: Address;\n }): Promise<TransactionResult> {\n const signer = this.#requireSigner(\"revokeDelegation\");\n const account = await requireAlignedWalletAccount(\n \"revokeDelegation\",\n this.#signer,\n this.#provider,\n );\n return this.#delegationService.revokeDelegation(signer, {\n contractAddress,\n delegateAddress,\n delegatorAddress: account.address,\n });\n }\n\n /**\n * Check whether a delegation is active for the given contract address.\n *\n * Signer-independent: works without a configured signer.\n *\n * @param contractAddress - The confidential contract address.\n * @param delegatorAddress - The address that granted the delegation.\n * @param delegateAddress - The address that received delegation rights.\n * @returns `true` if the delegation exists and has not expired.\n */\n async isActive(params: {\n contractAddress: Address;\n delegatorAddress: Address;\n delegateAddress: Address;\n }): Promise<boolean> {\n return this.#delegationService.isDelegated(params);\n }\n\n /**\n * Get the expiration timestamp of a delegation for the given contract.\n *\n * Signer-independent: works without a configured signer.\n *\n * @param contractAddress - The confidential contract address.\n * @param delegatorAddress - The address that granted the delegation.\n * @param delegateAddress - The address that received delegation rights.\n * @returns Unix timestamp as bigint. `0n` = no delegation. `2^64 - 1` = permanent.\n */\n async getExpiry(params: {\n contractAddress: Address;\n delegatorAddress: Address;\n delegateAddress: Address;\n }): Promise<bigint> {\n return this.#delegationService.getDelegationExpiry(params);\n }\n\n /**\n * Get activity and expiry together in a single on-chain read, instead of\n * calling {@link isActive} and {@link getExpiry} separately.\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 `{ isActive, expiryTimestamp }` — activity and the raw expiry timestamp together.\n */\n async getStatus(params: {\n contractAddress: Address;\n delegatorAddress: Address;\n delegateAddress: Address;\n }): Promise<DelegationStatus> {\n return this.#delegationService.getStatus(params);\n }\n}\n","import type { Address } from \"viem\";\nimport { requireConfigured, wrapDecryptError } from \"../errors\";\nimport type { EncryptedInput } from \"../query/user-decrypt\";\nimport type { ChainRouter } from \"../chains/router\";\nimport type {\n ClearValue,\n DecryptPublicValuesResult,\n EncryptedValue,\n FhevmRelayerOptions,\n} from \"../relayer/types\";\nimport type {\n BatchDecryptResult,\n DecryptionService,\n DelegatedDecryptOptions,\n} from \"../services/decryption-service\";\nimport type { GenericProvider, GenericSigner } from \"../types\";\nimport { requireAlignedWalletAccount } from \"../utils/alignment\";\nimport { assertNonNullable } from \"../utils\";\n\n/**\n * Public namespace for FHE decryption — the canonical way to decrypt.\n *\n * Exposed as `sdk.decryption`. Prefer these methods over the low-level\n * `sdk.relayer.decryptValues` / `decryptPublicValues`: they\n * assemble the credential bundle (transport key pair, EIP-712 permit) for you,\n * cache results, and wrap relayer errors. Reach for `sdk.relayer.*` only when\n * you must control credential assembly by hand.\n *\n * Owns the SDK-level guards (signer requirement on\n * `decryptValues` and `delegatedDecryptValues`, empty-array\n * short-circuit on `decryptPublicValues`, relayer error wrapping) and delegates the\n * actual work to the internal {@link DecryptionService} or the relayer directly for\n * `decryptPublicValues`.\n *\n * **Mixed signer requirement:** `decryptValues` and\n * `delegatedDecryptValues` need a configured signer; `decryptPublicValues`\n * does not. Each method documents its requirement in its JSDoc.\n *\n * **Request chunking:** decrypt requests are split internally to stay under\n * the relayer's 2048-cleartext-bit per-request budget — callers never need to\n * size batches themselves.\n */\nexport class Decryption {\n readonly #signer: GenericSigner | undefined;\n readonly #provider: GenericProvider;\n readonly #router: ChainRouter;\n readonly #decryptionService: DecryptionService | undefined;\n\n /** @internal */\n constructor(opts: {\n signer: GenericSigner | undefined;\n provider: GenericProvider;\n router: ChainRouter;\n decryptionService: DecryptionService | undefined;\n }) {\n this.#signer = opts.signer;\n this.#provider = opts.provider;\n this.#router = opts.router;\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 * @param options - Per-call `signal` and `timeout` forwarded to the relayer round-trip.\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 options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\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.decryptValues(encryptedInput, account.address, options);\n }\n\n /**\n * Decrypt one or more FHE encrypted values using delegated credentials.\n *\n * Mirrors {@link decryptValues} with delegated credentials — same caching and\n * zero-value short-circuit. Before reading from cache or calling the relayer,\n * every non-zero encrypted value's contract must have an active delegation from the\n * delegator to the connected signer; missing or expired delegations fail fast.\n *\n * @param encryptedInputs - FHE encrypted values paired with their contract addresses.\n * @param delegatorAddress - The address that granted delegation rights.\n * @param accountAddress - Address used as the cache key's \"requester\"\n * dimension. Defaults to `delegatorAddress`. Pass the actual account address\n * when decrypting on behalf of someone whose balance is stored under a\n * different address (e.g. `decryptBalanceAs` with an explicit `accountAddress`).\n * @param options - Delegated-decrypt options. By default the call rides out the\n * gateway propagation window ({@link DelegatedDecryptOptions.waitForPropagation});\n * pass `{ waitForPropagation: false }` to fail fast instead.\n * @returns Map of encrypted value → clear-text value.\n *\n * @example\n * ```ts\n * const values = await sdk.decryption.delegatedDecryptValues([\n * { encryptedValue: balance, contractAddress: tokenAddr },\n * ], delegatorAddr);\n * console.log(values[balance]); // 1000n\n * ```\n */\n async delegatedDecryptValues(\n encryptedInputs: EncryptedInput[],\n delegatorAddress: Address,\n accountAddress: Address = delegatorAddress,\n options?: DelegatedDecryptOptions,\n ): Promise<Record<EncryptedValue, ClearValue>> {\n const service = this.#requireDecryptionService(\"delegatedDecryptValues\");\n const account = await requireAlignedWalletAccount(\n \"delegatedDecryptValues\",\n this.#signer,\n this.#provider,\n );\n return service.delegatedDecryptValues(\n encryptedInputs,\n delegatorAddress,\n account.address,\n accountAddress,\n options,\n );\n }\n\n /**\n * Publicly decrypt one or more FHE encrypted values.\n *\n * Signer-independent: works without a configured signer.\n * Returns the decryption proof alongside the clear-text values so callers\n * can submit on-chain finalization transactions (e.g. `finalizeUnwrap`).\n *\n * @param encryptedValues - FHE encrypted values to decrypt publicly.\n * @param options - Per-call `signal` and `timeout` forwarded to the relayer round-trip.\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(\n encryptedValues: EncryptedValue[],\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<DecryptPublicValuesResult> {\n if (encryptedValues.length === 0) {\n return { clearValues: {}, decryptionProof: \"0x\", abiEncodedClearValues: \"0x\" };\n }\n\n try {\n const result = await this.#router.relayer.decryptPublicValuesWithSignatures({\n encryptedValues,\n options,\n });\n const clearValues: Record<EncryptedValue, ClearValue> = {};\n result.checkSignaturesArgs.handlesList.forEach((handle, i) => {\n assertNonNullable(result.clearValues[i], `result.clearValues[${i}]`);\n clearValues[handle] = result.clearValues[i].value;\n });\n return {\n clearValues,\n abiEncodedClearValues: result.checkSignaturesArgs.abiEncodedCleartexts,\n decryptionProof: result.checkSignaturesArgs.decryptionProof,\n };\n } catch (error) {\n throw wrapDecryptError(error, \"Public decryption failed\");\n }\n }\n\n /**\n * Batch-decrypt delegated encrypted values with per-entry error isolation.\n *\n * Attempts a single batch request first. If the batch fails with a non-fatal\n * error (e.g. one entry is invalid), falls back to per-entry decryption so\n * healthy entries still resolve. Each item in the result carries either a\n * decrypted value or an error — callers decide how to surface partial failures.\n *\n * @param encryptedInputs - FHE encrypted values paired with their contract addresses.\n * @param delegatorAddress - The address that granted delegation rights.\n * @param accountAddress - The account on whose behalf decryption is performed. Defaults to `delegatorAddress`.\n * @param maxConcurrency - Maximum parallel decrypt calls during per-entry fallback.\n * @param waitForPropagation - Ride out the gateway propagation window on the\n * initial batch attempt (default `true`). See {@link DelegatedDecryptOptions.waitForPropagation}.\n * @returns Per-entry results, each with a value or an error.\n * @throws if no signer is configured. {@link SignerNotConfiguredError}\n * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n * @throws A failure that affects the whole session (rejected signature, RPC\n * rate limit, revoked KMS context) rejects the call instead of landing in a\n * per-entry error.\n *\n * @example\n * ```ts\n * const result = await sdk.decryption.delegatedBatchDecryptValues({\n * encryptedInputs: [\n * { encryptedValue: encryptedValue1, contractAddress: tokenA },\n * { encryptedValue: encryptedValue2, contractAddress: tokenB },\n * ],\n * delegatorAddress: \"0xDelegator\",\n * maxConcurrency: 5,\n * });\n * for (const item of result.items) {\n * if (item.error) console.error(item.encryptedValue, item.error);\n * else console.log(item.encryptedValue, item.value);\n * }\n * ```\n */\n async delegatedBatchDecryptValues({\n encryptedInputs,\n delegatorAddress,\n accountAddress = delegatorAddress,\n maxConcurrency,\n waitForPropagation,\n }: {\n encryptedInputs: EncryptedInput[];\n delegatorAddress: Address;\n accountAddress?: Address;\n maxConcurrency?: number;\n } & DelegatedDecryptOptions): Promise<BatchDecryptResult> {\n const service = this.#requireDecryptionService(\"delegatedBatchDecryptValues\");\n const account = await requireAlignedWalletAccount(\n \"delegatedBatchDecryptValues\",\n this.#signer,\n this.#provider,\n );\n return service.delegatedBatchDecryptHandlesAs({\n encryptedInputs,\n delegatorAddress,\n delegateAddress: account.address,\n accountAddress,\n maxConcurrency,\n waitForPropagation,\n });\n }\n}\n","import type { CredentialService } from \"../credentials/credential-service\";\nimport type { PreparedPermit, PreparePermitRequest } from \"../credentials/types\";\nimport type { OfflineService } from \"../services/offline-service\";\nimport type {\n PreparedFor,\n PrepareOptions,\n PrepareTransactionRequest,\n TransactionKind,\n} from \"../types\";\n\n/**\n * Namespace for the offline-signing pipeline —\n * `prepare → [external sign + self-publish]` — for institutional custody, HSM\n * ceremonies, and policy-engine workflows where signing runs out-of-process and\n * cannot happen synchronously in a single Promise.\n */\nexport class Offline {\n readonly #offlineService: OfflineService;\n readonly #credentialService: CredentialService;\n\n /** @internal */\n constructor(offlineService: OfflineService, credentialService: CredentialService) {\n this.#offlineService = offlineService;\n this.#credentialService = credentialService;\n }\n\n /**\n * Build an RLP-encoded unsigned transaction for the given request. The\n * caller signs it externally — via an HSM ceremony, an out-of-process\n * custodian, or any signer holding the key — and broadcasts the signed bytes\n * through its own channel.\n *\n * Signer-optional: works without a configured signer (canonical shape for\n * cross-process custody — the back-end signer service consumes\n * `prepared.unsignedTx` and returns signed bytes).\n *\n * @remarks\n * `request.from` is only a declaration — the SDK does not prove the caller\n * controls it, and an EIP-1559 unsigned tx carries no `from` field at all\n * (the on-chain sender is whichever key signs the bytes). Point `from` at\n * the account the custodian will sign with; custodians enforce key-control\n * at sign time — a signing request for a key the credential can't use fails\n * there — so a mismatched `from` cannot make the custodian sign from an\n * account you don't control. Verifying control of `from` up front is still\n * the application's responsibility.\n */\n prepare<K extends TransactionKind>(\n request: Extract<PrepareTransactionRequest, { kind: K }>,\n options?: PrepareOptions,\n ): Promise<PreparedFor<K>> {\n return this.#offlineService.prepare(request, options);\n }\n\n /**\n * Build the offline-signing payload for a decryption permit: the unsigned\n * EIP-712 typed data plus everything `sdk.permits.registerPermit` needs to\n * verify and persist the signature an out-of-process signer returns for it.\n *\n * Not a `prepare()` transaction kind: a permit is not a transaction —\n * nothing is broadcast, and registering the signature is a local operation,\n * not a relayer round-trip.\n *\n * Signer-optional, like {@link prepare}: `request.signer` is an explicit\n * address, not a connected wallet account. Building the typed data still\n * reads the chain's KMS signers context on-chain — signer-offline, not\n * network-offline.\n *\n * One permit per call: unlike `sdk.permits.grantPermit`, this never widens\n * an existing permit or chunks over 10 contracts — `request.contracts` maps\n * to exactly one signature.\n *\n * @throws if `request.contracts` is empty or exceeds 10 addresses, `request.delegator`\n * equals `request.signer`, or `request.durationDays` exceeds the V1 permit maximum\n * of 365 days. {@link ConfigurationError}\n * @throws if a concurrent `permits.revokeTransportKeyPair()` rotates the transport key\n * pair while this call is generating one. {@link TransportKeyPairChangedError}\n */\n preparePermit(request: PreparePermitRequest): Promise<PreparedPermit> {\n return this.#credentialService.preparePermit(request);\n }\n}\n","import type { GenericStorage } from \"../types\";\n\n/** Minimal chrome.storage.session typings (avoids depending on @types/chrome). */\ndeclare const chrome: {\n storage: {\n session: {\n get(key: string): Promise<Record<string, unknown>>;\n set(items: Record<string, unknown>): Promise<void>;\n remove(key: string): Promise<void>;\n };\n };\n};\n\n/**\n * {@link GenericStorage} backed by `chrome.storage.session`.\n *\n * Use this in MV3 web extensions so the wallet signature survives\n * service worker restarts and is shared across popup, background,\n * and content script contexts.\n *\n * @example\n * ```ts\n * import { ZamaSDK, indexedDBStorage, chromeSessionStorage } from \"@zama-fhe/sdk\";\n * import { createConfig } from \"@zama-fhe/sdk/viem\";\n *\n * const config = createConfig({\n * chains: [mySepolia],\n * publicClient,\n * walletClient,\n * relayers: { [mySepolia.id]: web() },\n * storage: indexedDBStorage, // encrypted transport key pair — persistent\n * permitStorage: chromeSessionStorage, // signed permits — ephemeral\n * });\n * const sdk = new ZamaSDK(config);\n * ```\n */\nexport class ChromeSessionStorage implements GenericStorage {\n /**\n * Retrieve a value by key.\n * @returns The stored value, or `null` if the key does not exist.\n */\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 /** Store a value under the given key, overwriting any existing entry. */\n async set(key: string, value: unknown): Promise<void> {\n await chrome.storage.session.set({ [key]: value });\n }\n\n /** Remove the entry for the given key (no-op if absent). */\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","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/types\";\n\nconst STORAGE_PREFIX = \"zama:pending-unshield:\";\nconst CURRENT_VERSION = 1;\n\n/**\n * Persisted state for an in-progress unshield request.\n * Used to resume an interrupted unshield after page reload.\n *\n * @internal\n */\nexport interface PendingUnshieldRequest {\n /** Transaction hash of the original unwrap call. */\n readonly unwrapTxHash: Hex;\n /**\n * Request identifier from the `UnwrapRequested` event.\n * Always populated for entries persisted by this SDK version; pass it as\n * `unwrapRequestId` to `finalizeUnwrap`. Absent only when re-loading a\n * pending unshield serialized by an older SDK version that did not\n * record this field — in that case pass the `encryptedAmount` from the\n * `UnwrapRequested` event to `finalizeUnwrap` instead.\n */\n readonly unwrapRequestId?: EncryptedValue;\n}\n\ninterface StoredPendingUnshieldRequest extends PendingUnshieldRequest {\n readonly version: typeof CURRENT_VERSION;\n}\n\nfunction storageKey(wrapperAddress: Address): string {\n return `${STORAGE_PREFIX}${checksum(wrapperAddress)}`;\n}\n\nconst PendingUnshieldRequestSchema = z.union([\n z.pipe(\n hex,\n z.transform((unwrapTxHash: Hex) => ({ unwrapTxHash })),\n ),\n z.pipe(\n z.object({\n version: z.literal(CURRENT_VERSION),\n unwrapTxHash: hex,\n unwrapRequestId: z.optional(hex),\n }),\n z.transform(\n ({\n unwrapTxHash,\n unwrapRequestId,\n }: {\n version: typeof CURRENT_VERSION;\n unwrapTxHash: Hex;\n unwrapRequestId?: Hex;\n }) => ({ unwrapTxHash, unwrapRequestId }),\n ),\n ),\n]);\n\n/**\n * Persist the unwrap tx hash so an interrupted unshield can be resumed later\n * (e.g. after a page reload).\n *\n * @internal\n */\nexport async function savePendingUnshield(\n storage: GenericStorage,\n wrapperAddress: Address,\n unwrapTxHash: Hex,\n unwrapRequestId?: EncryptedValue,\n): Promise<void> {\n if (unwrapRequestId === undefined) {\n await storage.set(storageKey(wrapperAddress), unwrapTxHash);\n return;\n }\n\n await storage.set(storageKey(wrapperAddress), {\n version: CURRENT_VERSION,\n unwrapTxHash,\n unwrapRequestId,\n } satisfies StoredPendingUnshieldRequest);\n}\n\n/**\n * Load a previously saved unwrap tx hash, or `null` if none exists.\n *\n * @internal\n */\nexport async function loadPendingUnshield(\n storage: GenericStorage,\n wrapperAddress: Address,\n): Promise<Hex | null> {\n const request = await loadPendingUnshieldRequest(storage, wrapperAddress);\n return request?.unwrapTxHash ?? null;\n}\n\n/**\n * Load a previously saved unwrap request, including `unwrapRequestId` when available.\n *\n * `resumeUnshield()` only needs `unwrapTxHash`: it reloads the transaction receipt and\n * rediscovers the right finalize input from the emitted `UnwrapRequested` event.\n * Use `unwrapRequestId` directly only for custom flows that call `finalizeUnwrap()`\n * without reloading the original unwrap receipt.\n *\n * @internal\n */\nexport async function loadPendingUnshieldRequest(\n storage: GenericStorage,\n wrapperAddress: Address,\n): Promise<PendingUnshieldRequest | null> {\n const key = storageKey(wrapperAddress);\n const value = await storage.get<Hex | StoredPendingUnshieldRequest>(key);\n if (value === null || value === undefined) {\n return null;\n }\n const parsed = PendingUnshieldRequestSchema.safeParse(value);\n if (!parsed.success) {\n await storage.delete(key);\n return null;\n }\n return parsed.data as PendingUnshieldRequest;\n}\n\n/**\n * Clear the saved unwrap tx hash after a successful finalization.\n *\n * @internal\n */\nexport async function clearPendingUnshield(\n storage: GenericStorage,\n wrapperAddress: Address,\n): Promise<void> {\n await storage.delete(storageKey(wrapperAddress));\n}\n","import { getAddress, zeroAddress, type Address, type Hex } from \"viem\";\nimport {\n allowanceContract,\n approveContract,\n balanceOfContract,\n finalizeUnwrapContract,\n isPayableTokenContract,\n transferAndCallContract,\n underlyingContract,\n unwrapContract,\n unwrapFromBalanceContract,\n unwrapRequesterContract,\n wrapContract,\n} from \"../contracts\";\nimport {\n DecryptionFailedError,\n ERC20ReadFailedError,\n EncryptionFailedError,\n InsufficientAllowanceError,\n InsufficientERC20BalanceError,\n SignerNotConfiguredError,\n TransactionRevertedError,\n UnshieldAlreadyFinalizedError,\n ZamaError,\n} from \"../errors\";\nimport { isInvalidUnwrapRequestRevert } from \"../errors/unshield\";\nimport { findUnwrapRequested } from \"../events/onchain-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { EncryptedValue } from \"../relayer/types\";\nimport type {\n GenericSigner,\n ShieldCallbacks,\n ShieldOptions,\n TransactionResult,\n UnshieldCallbacks,\n UnshieldOptions,\n UnwrapResult,\n WrapOptions,\n} from \"../types\";\nimport type { RawLog } from \"../types/transaction\";\nimport { toError } from \"../utils\";\nimport { requireAlignedWalletAccount, requireChainAlignment } from \"../utils/alignment\";\nimport { assertBigint, assertNonNullable } from \"../utils/assertions\";\nimport { isEncryptedValueZero } from \"../utils/handles\";\nimport { swallow } from \"../utils/swallow\";\nimport {\n clearPendingUnshield,\n loadPendingUnshieldRequest,\n savePendingUnshield,\n type PendingUnshieldRequest,\n} from \"./pending-unshield\";\nimport { Token } from \"./token\";\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 /**\n * Wrap already-approved underlying ERC-20 into confidential tokens.\n *\n * Escape hatch for splitting shield across two signatures: call\n * {@link approveUnderlying} first, then `wrap`. Most callers should use\n * {@link shield}, which routes and orchestrates approval automatically.\n *\n * Validates the ERC-20 balance and the allowance granted to this wrapper\n * (public reads, no signing) and fails early with a clear error.\n *\n * @param amount - The plaintext amount to wrap.\n * @param options - Optional `to` recipient and `onWrapSubmitted` callback.\n * @returns The transaction hash and mined receipt.\n * @throws if reading the ERC-20 balance or allowance fails. {@link ERC20ReadFailedError}\n * @throws if the ERC-20 balance is less than `amount`. {@link InsufficientERC20BalanceError}\n * @throws if the allowance granted to the wrapper is less than `amount`. {@link InsufficientAllowanceError}\n *\n * @example\n * ```ts\n * await wrappedToken.approveUnderlying(1000n);\n * await wrappedToken.wrap(1000n);\n * ```\n */\n async wrap(amount: bigint, options?: WrapOptions): Promise<TransactionResult> {\n this.#requireSigner(\"wrap\");\n const account = await requireAlignedWalletAccount(\"wrap\", this.sdk.signer, this.sdk.provider);\n const underlying = await this.#getUnderlying();\n const userAddress = getAddress(account.address);\n\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 wrap 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 let allowance: bigint;\n try {\n allowance = await this.sdk.provider.readContract(\n allowanceContract(underlying, userAddress, this.address),\n );\n } catch (error) {\n if (error instanceof ZamaError) {\n throw error;\n }\n throw new ERC20ReadFailedError(\n `Could not read ERC-20 allowance for wrap validation (token: ${underlying})`,\n { cause: toError(error) },\n );\n }\n if (allowance < amount) {\n throw new InsufficientAllowanceError(\n `Insufficient allowance for wrap: requested ${amount}, approved ${allowance}. Call approveUnderlying() first (token: ${underlying}).`,\n { requested: amount, available: allowance, token: underlying },\n );\n }\n\n const recipient = options?.to ? getAddress(options.to) : userAddress;\n return this.submitTransaction({\n operation: \"wrap\",\n config: wrapContract(this.address, recipient, amount),\n onSubmitted: options?.onWrapSubmitted,\n });\n }\n\n async #shieldViaApproveAndWrap(\n amount: bigint,\n userAddress: Address,\n options?: ShieldOptions,\n ): Promise<TransactionResult> {\n this.#requireSigner(\"shield\");\n const strategy = options?.approvalStrategy ?? \"exact\";\n if (strategy !== \"skip\") {\n await this.#ensureAllowance(amount, strategy === \"max\", options);\n }\n const recipient = options?.to ? getAddress(options.to) : userAddress;\n return this.submitTransaction({\n operation: \"shield:approveAndWrap\",\n config: wrapContract(this.address, recipient, amount),\n onSubmitted: options?.onShieldSubmitted,\n });\n }\n\n /**\n * Approve this wrapper contract to spend the underlying ERC-20.\n * Defaults to max uint256. Resets to zero first if there's an existing\n * non-zero allowance (required by tokens like USDT).\n *\n * @param amount - Optional approval amount. Defaults to max uint256.\n * @returns The transaction hash and mined receipt.\n *\n * @example\n * ```ts\n * await wrappedToken.approveUnderlying(); // max approval\n * await wrappedToken.approveUnderlying(1000n); // exact amount\n * ```\n */\n async approveUnderlying(amount?: bigint): Promise<TransactionResult> {\n this.#requireSigner(\"approveUnderlying\");\n const account = await requireAlignedWalletAccount(\n \"approveUnderlying\",\n this.sdk.signer,\n this.sdk.provider,\n );\n const underlying = await this.#getUnderlying();\n const userAddress = getAddress(account.address);\n\n const approvalAmount = amount ?? 2n ** 256n - 1n;\n\n if (approvalAmount > 0n) {\n const currentAllowance = await this.sdk.provider.readContract(\n allowanceContract(underlying, userAddress, this.address),\n );\n\n if (currentAllowance > 0n) {\n await this.submitTransaction({\n operation: \"approveUnderlying:reset\",\n config: approveContract(underlying, this.address, 0n),\n });\n }\n }\n\n return this.submitTransaction({\n operation: \"approveUnderlying\",\n config: approveContract(underlying, this.address, approvalAmount),\n });\n }\n\n // UNSHIELD (confidential → ERC-20)\n\n /**\n * Unshield a specific amount and finalize in one call.\n * Orchestrates: unshield → wait for receipt → parse event → finalize.\n *\n * By default, the SDK validates the confidential balance before submitting.\n * Set `skipBalanceCheck: true` to bypass this validation (e.g. for smart wallets).\n *\n * @param amount - The plaintext amount to unshield.\n * @param options - Optional: `skipBalanceCheck` (default `false`), callbacks.\n * @returns The finalize transaction hash and mined receipt.\n *\n * @example\n * ```ts\n * const txHash = await wrappedToken.unshield(500n);\n * ```\n */\n async unshield(amount: bigint, options?: UnshieldOptions): Promise<TransactionResult> {\n const {\n skipBalanceCheck = false,\n onUnwrapSubmitted,\n onFinalizing,\n onFinalizeSubmitted,\n } = options ?? {};\n\n if (!skipBalanceCheck) {\n await this.assertConfidentialBalance(amount);\n }\n\n const callbacks: UnshieldCallbacks = { onFinalizing, onFinalizeSubmitted };\n const operationId = crypto.randomUUID();\n const unwrapResult = await this.unwrap(amount);\n void swallow(\n \"unshield: onUnwrapSubmitted\",\n () => onUnwrapSubmitted?.(unwrapResult.txHash),\n this.sdk.logger,\n );\n // Reuse the id `unwrap()` already decoded — no second receipt fetch or decode.\n return this.#finalizeUnshield(\n unwrapResult.unwrapRequestId,\n unwrapResult.txHash,\n operationId,\n callbacks,\n );\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 // Reuse the id `unwrapAll()` already decoded — no second receipt fetch or decode.\n return this.#finalizeUnshield(\n unwrapResult.unwrapRequestId,\n unwrapResult.txHash,\n operationId,\n callbacks,\n );\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 * @throws if the unwrap request was already finalized on-chain; the persisted\n * pending-unshield state is cleared first. {@link UnshieldAlreadyFinalizedError}\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 // The only entry point that starts from a bare hash, so it's the only one\n // that has to fetch the receipt and decode the id from chain.\n let receipt;\n try {\n receipt = await this.sdk.provider.waitForTransactionReceipt(unwrapTxHash);\n } catch (error) {\n if (error instanceof ZamaError) {\n throw error;\n }\n throw new TransactionRevertedError(\"Failed to get unwrap receipt\", { cause: error });\n }\n const unwrapRequestId = this.#extractUnwrapRequestId(receipt.logs);\n if (await this.#isUnwrapRequestConsumed(unwrapRequestId)) {\n await this.#clearStoredPendingUnshield(\"resumeUnshield\");\n throw new UnshieldAlreadyFinalizedError(\n \"Nothing to resume: the unwrap request was already finalized on-chain and the funds were delivered.\",\n { unwrapTxHash, unwrapRequestId },\n );\n }\n return this.#finalizeUnshield(unwrapRequestId, unwrapTxHash, crypto.randomUUID(), callbacks);\n }\n\n /**\n * Return the unwrap tx hash of an unshield that was interrupted between its\n * two phases, or `null` if none is pending for this wrapper.\n *\n * The SDK persists this automatically when {@link unshield}/{@link unshieldAll}\n * submit phase 1, and clears it once phase 2 finalizes. Use the returned hash\n * to surface a \"resume\" affordance, then pass it to {@link resumeUnshield}.\n * Resuming is intentionally caller-driven — auto-resuming on load would fire a\n * wallet transaction unprompted.\n *\n * The pointer is verified on-chain before it is reported: if the unwrap\n * request was already finalized (e.g. the tab closed before the SDK could\n * clear storage), the stale pointer is cleared and `null` is returned. When\n * the verification read fails, the pointer is returned unverified: a\n * network error never deletes recovery state.\n *\n * @returns The pending unwrap tx hash, or `null`.\n *\n * @example\n * ```ts\n * const unwrapTxHash = await wrappedToken.getPendingUnshield();\n * if (unwrapTxHash) await wrappedToken.resumeUnshield(unwrapTxHash);\n * ```\n */\n async getPendingUnshield(): Promise<Hex | null> {\n const pending = await loadPendingUnshieldRequest(this.sdk.storage, this.address);\n if (!pending) {\n return null;\n }\n if (await this.#isPendingUnshieldConsumed(pending)) {\n await this.#clearStoredPendingUnshield(\"getPendingUnshield\");\n return null;\n }\n return pending.unwrapTxHash;\n }\n\n // UNSHIELD LOW-LEVEL PRIMITIVES\n\n /**\n * Request an unwrap for a specific amount. Encrypts the amount first.\n * Pass the result's `unwrapRequestId` to {@link finalizeUnwrap} once the\n * request is processed on-chain.\n *\n * @param amount - The plaintext amount to unwrap (encrypted automatically).\n * @returns The tx hash, mined receipt, and the `unwrapRequestId` for `finalizeUnwrap`.\n *\n * @example\n * ```ts\n * const result = await wrappedToken.unwrap(500n);\n * await wrappedToken.finalizeUnwrap(result.unwrapRequestId);\n * ```\n */\n async unwrap(amount: bigint): Promise<UnwrapResult> {\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 const result = await this.submitTransaction({\n operation: \"unwrap\",\n config: unwrapContract(this.address, userAddress, userAddress, encryptedAmount, inputProof),\n });\n\n return { ...result, unwrapRequestId: this.#extractUnwrapRequestId(result.receipt.logs) };\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 tx hash, mined receipt, and the `unwrapRequestId` for `finalizeUnwrap`.\n * @throws if the balance is zero. {@link DecryptionFailedError}\n *\n * @example\n * ```ts\n * const result = await wrappedToken.unwrapAll();\n * await wrappedToken.finalizeUnwrap(result.unwrapRequestId);\n * ```\n */\n async unwrapAll(): Promise<UnwrapResult> {\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 const result = await this.submitTransaction({\n operation: \"unwrapAll\",\n config: unwrapFromBalanceContract(this.address, userAddress, userAddress, encryptedValue),\n });\n\n return { ...result, unwrapRequestId: this.#extractUnwrapRequestId(result.receipt.logs) };\n }\n\n /**\n * Complete an unwrap by fetching the public decryption proof and finalizing.\n * Call this once the unwrap request has been processed on-chain.\n *\n * @param unwrapRequestId - The `unwrapRequestId` from an {@link UnwrapResult}\n * (`result.unwrapRequestId`) returned by {@link unwrap} / {@link unwrapAll},\n * or one decoded from an `UnwrapRequested` event (e.g. when finalizing\n * across sessions).\n * @returns The transaction hash and mined receipt.\n *\n * @example\n * ```ts\n * const { unwrapRequestId } = await wrappedToken.unwrap(500n);\n * await wrappedToken.finalizeUnwrap(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 /**\n * Decode the `unwrapRequestId` from an unwrap/unshield receipt's logs.\n * Only logs emitted by this wrapper count: a caller-supplied tx hash from a\n * different wrapper must fail here, not decode a foreign request id. Logs\n * without an emitter address (older custom adapters) are kept.\n * Throws when no matching `UnwrapRequested` event is found.\n */\n #extractUnwrapRequestId(logs: readonly RawLog[]): EncryptedValue {\n const ownLogs = logs.filter(\n (log) => log.address === undefined || getAddress(log.address) === this.address,\n );\n const event = findUnwrapRequested(ownLogs);\n if (!event) {\n throw new TransactionRevertedError(\n \"No UnwrapRequested event from this wrapper found in the unwrap receipt\",\n );\n }\n return event.unwrapRequestId;\n }\n\n /**\n * True only when the unwrap request is definitely gone. `unwrapRequester`\n * returns the zero address once finalize deletes the request, and the id\n * always comes from the unwrap tx's own `UnwrapRequested` event, so zero can\n * only mean \"already finalized\". A failed read returns `false`: the check\n * fails open, so a network error never heals recovery state.\n */\n async #isUnwrapRequestConsumed(unwrapRequestId: EncryptedValue): Promise<boolean> {\n try {\n const requester = await this.sdk.provider.readContract(\n unwrapRequesterContract(this.address, unwrapRequestId),\n );\n return requester === zeroAddress;\n } catch {\n return false;\n }\n }\n\n /**\n * Consumed-request check for a persisted pointer; legacy hash-only entries\n * re-derive the request id from the unwrap receipt.\n */\n async #isPendingUnshieldConsumed(pending: PendingUnshieldRequest): Promise<boolean> {\n let unwrapRequestId = pending.unwrapRequestId;\n if (unwrapRequestId === undefined) {\n try {\n const receipt = await this.sdk.provider.waitForTransactionReceipt(pending.unwrapTxHash);\n unwrapRequestId = this.#extractUnwrapRequestId(receipt.logs);\n } catch {\n return false;\n }\n }\n return this.#isUnwrapRequestConsumed(unwrapRequestId);\n }\n\n async #clearStoredPendingUnshield(operation: string): Promise<void> {\n await swallow(\n `${operation}: clearPendingUnshield`,\n () => clearPendingUnshield(this.sdk.storage, this.address),\n this.sdk.logger,\n );\n }\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 /**\n * Phase 2 of unshield, shared by {@link unshield}/{@link unshieldAll} (which\n * pass the id `unwrap`/`unwrapAll` already decoded) and {@link resumeUnshield}\n * (which decoded it from a fetched receipt). Persists the unwrap hash for\n * recovery, finalizes, then clears the persisted state.\n */\n async #finalizeUnshield(\n unwrapRequestId: EncryptedValue,\n unwrapTxHash: Hex,\n operationId: string,\n callbacks: UnshieldCallbacks | undefined,\n ): Promise<TransactionResult> {\n this.emit({ type: ZamaSDKEvents.UnshieldPhase1Submitted, txHash: unwrapTxHash, operationId });\n await swallow(\n \"unshield: savePendingUnshield\",\n () => savePendingUnshield(this.sdk.storage, this.address, unwrapTxHash, unwrapRequestId),\n this.sdk.logger,\n );\n this.emit({ type: ZamaSDKEvents.UnshieldPhase2Started, operationId });\n void swallow(\"unshield: onFinalizing\", () => callbacks?.onFinalizing?.(), this.sdk.logger);\n let finalizeResult: TransactionResult;\n try {\n finalizeResult = await this.finalizeUnwrap(unwrapRequestId);\n } catch (error) {\n // The id comes from this wrapper's own UnwrapRequested event and the only\n // transition to \"gone\" is a successful finalize, so this revert means a\n // concurrent finalize won the race (second tab, double click, third\n // party). The funds arrived; heal.\n if (!isInvalidUnwrapRequestRevert(error)) {\n throw error;\n }\n await this.#clearStoredPendingUnshield(\"unshield\");\n throw new UnshieldAlreadyFinalizedError(\n \"The unwrap request was finalized concurrently — the funds were already delivered.\",\n { unwrapTxHash, unwrapRequestId },\n { cause: error },\n );\n }\n this.emit({\n type: ZamaSDKEvents.UnshieldPhase2Submitted,\n txHash: finalizeResult.txHash,\n operationId,\n });\n void swallow(\n \"unshield: onFinalizeSubmitted\",\n () => callbacks?.onFinalizeSubmitted?.(finalizeResult.txHash),\n this.sdk.logger,\n );\n // Phase 2 landed: the persisted recovery state is no longer needed.\n await this.#clearStoredPendingUnshield(\"unshield\");\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 { getAddress, type Address } from \"viem\";\nimport { z } from \"zod/mini\";\nimport type { ClearValue, EncryptedValue } from \"../relayer/types\";\nimport { checksummedAddress } from \"../schemas/primitives\";\nimport type { GenericLogger, GenericStorage } from \"../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 *\n * @internal\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, Hex } from \"viem\";\nimport { DecryptionFailedError } from \"../errors\";\nimport { checksum } from \"../schemas/primitives\";\nimport type {\n Permission,\n SerializedTransportKeyPairWithPermissions,\n SerializedPermit,\n} from \"./types\";\n\n/**\n * The minimal permit material the decrypt seam needs. Delegation is already\n * encoded in the self-contained `serializedPermit`, so a delegated decrypt and\n * a normal decrypt resolve to the same shape — there is no separate delegated\n * variant.\n */\nexport interface ResolvedPermit {\n privateKey: Hex;\n publicKey: Hex;\n serializedPermit: SerializedPermit;\n}\n\n/**\n * Resolve the signed permit covering `contractAddress` from previously granted\n * credentials. Works uniformly for direct and delegated decryption: the\n * `@fhevm/sdk` signed permit bakes the delegator (if any) into its EIP-712\n * payload, so the decrypt call needs nothing beyond the transport key pair and\n * the serialized permit.\n *\n * @throws if no stored permit covers `contractAddress`. {@link DecryptionFailedError}\n */\nexport function resolvePermit(\n credentials: SerializedTransportKeyPairWithPermissions,\n contractAddress: Address,\n): ResolvedPermit {\n const permission = findPermissionFor(credentials, contractAddress);\n if (!permission) {\n throw new DecryptionFailedError(`No permit covers contract ${contractAddress} after allow()`);\n }\n return {\n privateKey: credentials.keypair.privateKey,\n publicKey: credentials.keypair.publicKey,\n serializedPermit: permission.serializedPermit,\n };\n}\n\nfunction findPermissionFor(\n credentials: SerializedTransportKeyPairWithPermissions,\n contractAddress: Address,\n): Permission | undefined {\n const target = checksum(contractAddress);\n return credentials.permissions.find((permission) =>\n permission.contractAddresses.includes(target),\n );\n}\n","import type { ParseTransportKeyPairReturnType } from \"@fhevm/sdk/actions/chain\";\nimport type { DecryptValuesReturnType } from \"@fhevm/sdk/actions/decrypt\";\nimport { getAddress, type Address } from \"viem\";\nimport type { ChainRouter } from \"../chains/router\";\nimport type { CredentialService } from \"../credentials/credential-service\";\nimport { resolvePermit } from \"../credentials/decrypt-permit\";\nimport type { SerializedTransportKeyPairWithPermissions } from \"../credentials/types\";\nimport {\n type DecryptErrorContext,\n DecryptionFailedError,\n DelegationNotPropagatedError,\n isFatalBatchError,\n RevokedKmsContextError,\n RpcRateLimitError,\n SigningFailedError,\n wrapDecryptError,\n ZamaError,\n} from \"../errors\";\nimport type { ZamaSDKEventInput } from \"../events/sdk-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { EncryptedInput } from \"../query/user-decrypt\";\nimport type { ClearValue, EncryptedValue, FhevmRelayerOptions } from \"../relayer/types\";\nimport { pLimit } from \"../utils/concurrency\";\nimport { chunkHandlesByBitBudget, isEncryptedValueZero } from \"../utils/handles\";\nimport {\n extractRetryAfter,\n isInvalidTransportKeyPairMessage,\n isRpcRateLimitError,\n toError,\n} from \"../utils\";\nimport type { CachingService } from \"./caching-service\";\nimport type { DelegationService } from \"./delegation-service\";\n\n/**\n * How long the delegated-decrypt path keeps retrying while a freshly granted\n * delegation propagates to the gateway. Propagation usually completes within\n * ~10 blocks (a few seconds); this ceiling absorbs a briefly lagging gateway\n * without turning a genuine outage into a long hang.\n */\nconst DELEGATION_PROPAGATION_RETRY_BUDGET_MS = 30_000;\n/** Delay between propagation retries. */\nconst DELEGATION_PROPAGATION_RETRY_INTERVAL_MS = 2_000;\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Options shared by the delegated-decrypt entry points. */\nexport interface DelegatedDecryptOptions {\n /**\n * Ride out the gateway propagation window: when a just-granted delegation\n * has not yet synced, the delegated decrypt is retried (bounded, ~30s) until\n * it lands instead of throwing {@link DelegationNotPropagatedError}. Defaults\n * to `true`. Pass `false` to fail fast on the first not-propagated response.\n */\n waitForPropagation?: boolean;\n}\n\ninterface DecryptionStrategy {\n requesterAddress: Address;\n /**\n * Delegator whose permit scope this decrypt reads; undefined on the direct\n * path. The single delegation discriminator: it also selects the delegated\n * error classification and the ACL actor (delegator, or the requester when\n * direct).\n */\n delegator?: Address;\n validate?: (contractAddresses: readonly Address[]) => Promise<void>;\n errorMessage: string;\n}\n\n/** One decrypt-relayer request: a contract's handles chunked to the bit budget. */\ninterface DecryptRequest {\n contractAddress: Address;\n encryptedValues: EncryptedValue[];\n}\n\n/** Tracks the evict-and-regrant allowance across retried decrypt attempts. */\ninterface RecoveryBudget {\n spent: boolean;\n}\n\n/** Per-handle outcome of a batch decrypt: the decrypted value, or a per-item error. */\nexport interface BatchDecryptItem {\n /** The encrypted value (handle) being decrypted. */\n encryptedValue: EncryptedValue;\n /** Address of the contract the handle belongs to. */\n contractAddress: Address;\n /** Decrypted clear value; set when this item succeeded. */\n value?: ClearValue;\n /** Error for this item; set when this item failed. */\n error?: ZamaError;\n}\n\n/** Result of a batch decrypt: one entry per requested handle, in input order. */\nexport interface BatchDecryptResult {\n /** Per-handle outcomes. */\n items: BatchDecryptItem[];\n}\n\n/** @internal */\nexport class DecryptionService {\n readonly #cache: CachingService;\n readonly #credentialService: CredentialService;\n readonly #delegationService: DelegationService;\n readonly #router: ChainRouter;\n readonly #emitEvent: (input: ZamaSDKEventInput) => void;\n\n constructor({\n cache,\n credentialService,\n delegationService,\n router,\n emitEvent,\n }: {\n cache: CachingService;\n credentialService: CredentialService;\n delegationService: DelegationService;\n router: ChainRouter;\n emitEvent: (input: ZamaSDKEventInput) => void;\n }) {\n this.#cache = cache;\n this.#credentialService = credentialService;\n this.#delegationService = delegationService;\n this.#router = router;\n this.#emitEvent = emitEvent;\n }\n\n async decryptValues(\n handles: EncryptedInput[],\n signerAddress: Address,\n opts?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<Record<EncryptedValue, ClearValue>> {\n const normalizedSigner = getAddress(signerAddress);\n return this.#decrypt(\n handles,\n { requesterAddress: normalizedSigner, errorMessage: \"Failed to decrypt encrypted values\" },\n opts,\n );\n }\n\n async delegatedDecryptValues(\n encryptedInputs: EncryptedInput[],\n delegatorAddress: Address,\n delegateAddress: Address,\n accountAddress: Address,\n opts?: DelegatedDecryptOptions,\n ): Promise<Record<EncryptedValue, ClearValue>> {\n const normalizedDelegator = getAddress(delegatorAddress);\n const normalizedDelegate = getAddress(delegateAddress);\n // One evict-and-regrant across the whole propagation-retry loop, not one\n // per attempt: each retry would otherwise re-arm the recovery and spend a\n // fresh wallet prompt per 2s attempt while the upstream validity cache\n // keeps serving the revoked context.\n const recovery: RecoveryBudget = { spent: false };\n return this.#withPropagationRetry(opts?.waitForPropagation ?? true, () =>\n this.#decrypt(\n encryptedInputs,\n {\n requesterAddress: getAddress(accountAddress),\n delegator: normalizedDelegator,\n validate: (contractAddresses) =>\n this.#assertAllDelegationsActive(contractAddresses, {\n delegatorAddress: normalizedDelegator,\n delegateAddress: normalizedDelegate,\n }),\n errorMessage: \"Failed to decrypt delegated encrypted values\",\n },\n undefined,\n recovery,\n ),\n );\n }\n\n /**\n * Absorb the gateway propagation window on the delegated path: retry `attempt`\n * (bounded by {@link DELEGATION_PROPAGATION_RETRY_BUDGET_MS}) while it fails\n * with a transient {@link DelegationNotPropagatedError}. Every other error —\n * including a missing/expired grant surfaced by the pre-check — throws\n * immediately, and passing `waitForPropagation: false` disables the retry so\n * the first not-propagated response propagates unchanged.\n */\n async #withPropagationRetry<T>(\n waitForPropagation: boolean,\n attempt: () => Promise<T>,\n ): Promise<T> {\n // Fixed-interval polling across the budget: e.g. 30s / 2s = 15 gaps, so 16\n // attempts. Bounded (no open-ended loop) and deterministic under fake timers.\n const maxAttempts =\n Math.floor(\n DELEGATION_PROPAGATION_RETRY_BUDGET_MS / DELEGATION_PROPAGATION_RETRY_INTERVAL_MS,\n ) + 1;\n let lastError: unknown;\n for (let i = 0; i < maxAttempts; i++) {\n try {\n return await attempt();\n } catch (error) {\n lastError = error;\n const canRetry =\n i < maxAttempts - 1 &&\n waitForPropagation &&\n error instanceof DelegationNotPropagatedError;\n if (!canRetry) {\n throw error;\n }\n await sleep(DELEGATION_PROPAGATION_RETRY_INTERVAL_MS);\n }\n }\n throw lastError;\n }\n\n async delegatedBatchDecryptHandlesAs({\n encryptedInputs,\n delegatorAddress,\n delegateAddress,\n accountAddress,\n maxConcurrency = 5,\n waitForPropagation = true,\n }: {\n encryptedInputs: EncryptedInput[];\n delegatorAddress: Address;\n delegateAddress: Address;\n accountAddress: Address;\n maxConcurrency?: number;\n waitForPropagation?: boolean;\n }): Promise<BatchDecryptResult> {\n const items: BatchDecryptItem[] = encryptedInputs.map((h) => ({\n encryptedValue: h.encryptedValue,\n contractAddress: getAddress(h.contractAddress),\n }));\n if (items.length === 0) {\n return { items };\n }\n const normalizedAccount = getAddress(accountAddress);\n\n try {\n const decrypted = await this.delegatedDecryptValues(\n items.map(({ encryptedValue, contractAddress }) => ({ encryptedValue, contractAddress })),\n delegatorAddress,\n delegateAddress,\n normalizedAccount,\n { waitForPropagation },\n );\n for (const item of items) {\n this.#setHandleResult(item, decrypted);\n }\n return { items };\n } catch (error) {\n if (isFatalBatchError(error)) {\n throw error;\n }\n if (items.length === 1) {\n const [item = this.#missingBatchItem()] = items;\n item.error = this.#toZamaError(error, \"Failed to decrypt delegated encrypted values\", {\n isDelegated: true,\n contractAddress: item.contractAddress,\n account: getAddress(delegatorAddress),\n });\n return { items };\n }\n }\n\n // `pLimit` cannot cancel calls that already started. The shared flag stops\n // the queued items from starting once a fatal error (e.g. an RPC rate\n // limit) is seen, instead of re-hitting the failing endpoint.\n let aborted = false;\n let fatal: unknown;\n await pLimit(\n items.map((item) => async () => {\n if (aborted) {\n return;\n }\n try {\n // The batch attempt above already rode out the propagation window for\n // the whole set; fail fast here so a still-unsynced delegation records\n // a per-item error instead of each item re-spending the full budget.\n const decrypted = await this.delegatedDecryptValues(\n [{ encryptedValue: item.encryptedValue, contractAddress: item.contractAddress }],\n delegatorAddress,\n delegateAddress,\n normalizedAccount,\n { waitForPropagation: false },\n );\n this.#setHandleResult(item, decrypted);\n } catch (error) {\n if (isFatalBatchError(error)) {\n aborted = true;\n fatal ??= error;\n return;\n }\n item.error = this.#toZamaError(error, \"Failed to decrypt delegated encrypted values\", {\n isDelegated: true,\n contractAddress: item.contractAddress,\n account: getAddress(delegatorAddress),\n });\n }\n }),\n maxConcurrency,\n );\n\n if (fatal !== undefined) {\n throw fatal;\n }\n\n return { items };\n }\n\n /**\n * Run a user (or delegated-user) decrypt for one contract: rebuild the\n * `@fhevm/sdk` transport key pair and signed permit from the resolved permit,\n * then decrypt. The delegation, if any, is encoded in the permit — both paths\n * share this call. Returns the positional clear values for `encryptedValues`.\n */\n async #decryptValues(\n credentials: SerializedTransportKeyPairWithPermissions,\n contractAddress: Address,\n encryptedValues: EncryptedValue[],\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<DecryptValuesReturnType> {\n const permit = resolvePermit(credentials, contractAddress);\n let transportKeyPair: ParseTransportKeyPairReturnType;\n try {\n transportKeyPair = await this.#router.relayer.parseTransportKeyPair({\n publicKey: permit.publicKey,\n privateKey: permit.privateKey,\n tkmsVersion: credentials.keypair.tkmsVersion,\n });\n } catch (error) {\n // Stale key pair the relayer can't re-derive (post KMS/TKMS rotation):\n // evict it so the next resolveCredentials regenerates and re-signs.\n // wrapDecryptError maps the raw message to InvalidTransportKeyPairError.\n if (error instanceof Error && isInvalidTransportKeyPairMessage(error.message)) {\n await this.#credentialService.evictTransportKeyPair();\n }\n throw error;\n }\n const signedPermit = await this.#router.relayer.parseSignedDecryptionPermit({\n transportKeyPair,\n serializedPermit: permit.serializedPermit,\n });\n return this.#router.relayer.decryptValues({\n transportKeyPair,\n signedPermit,\n encryptedValues,\n contractAddress,\n options,\n });\n }\n\n async #decrypt(\n handles: EncryptedInput[],\n strategy: DecryptionStrategy,\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n recovery: RecoveryBudget = { spent: false },\n ): Promise<Record<EncryptedValue, ClearValue>> {\n if (handles.length === 0) {\n return {};\n }\n\n const normalized = handles.map((h) => ({\n encryptedValue: h.encryptedValue,\n contractAddress: getAddress(h.contractAddress),\n }));\n const result: Record<EncryptedValue, ClearValue> = {};\n const nonZero: EncryptedInput[] = [];\n\n for (const h of normalized) {\n if (isEncryptedValueZero(h.encryptedValue)) {\n result[h.encryptedValue] = 0n;\n } else {\n nonZero.push(h);\n }\n }\n\n if (nonZero.length === 0) {\n return result;\n }\n\n const allContracts = Array.from(new Set(normalized.map((h) => h.contractAddress)));\n const nonZeroContracts = Array.from(new Set(nonZero.map((h) => h.contractAddress)));\n if (strategy.validate) {\n try {\n await strategy.validate(nonZeroContracts);\n } catch (error) {\n // The delegation pre-check makes on-chain reads too; classify a throttled\n // RPC here as well so delegated decrypt branches deterministically.\n if (isRpcRateLimitError(error)) {\n throw this.#rpcRateLimitError(error, \"the delegation pre-check\");\n }\n throw error;\n }\n }\n\n const uncached: EncryptedInput[] = [];\n for (const h of nonZero) {\n const cached = await this.#cache.get(\n strategy.requesterAddress,\n h.contractAddress,\n h.encryptedValue,\n );\n if (cached !== null) {\n result[h.encryptedValue] = cached;\n } else {\n uncached.push(h);\n }\n }\n\n if (uncached.length === 0) {\n return result;\n }\n\n let credentials = await this.#credentialService.grantPermit(allContracts, strategy.delegator);\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 // Split each contract's handles to stay under the relayer's per-request\n // cleartext-bit budget — a contract with many/wide handles becomes\n // several relayer calls instead of one oversized, rejected call.\n const requests: DecryptRequest[] = [];\n for (const [contractAddress, encryptedValues] of byContract) {\n for (const chunk of chunkHandlesByBitBudget(encryptedValues)) {\n requests.push({ contractAddress, encryptedValues: chunk });\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 try {\n await this.#runDecryptRequests(strategy, credentials, requests, result, options);\n } catch (error) {\n if (!(error instanceof RevokedKmsContextError) || recovery.spent) {\n throw error;\n }\n // Identify the permits this attempt used: if they are already gone from\n // the store, a sibling decrypt recovered the scope and re-signing would\n // cost a second prompt for nothing.\n const staleSignatures = credentials.permissions.map((p) => p.serializedPermit.signature);\n // Re-grant under the current context and retry the still-unresolved\n // chunks once; a second revoked failure surfaces instead of looping\n // into the upstream 15-minute validity cache. Spent is set before\n // awaiting so a failing re-grant cannot re-arm the budget.\n recovery.spent = true;\n try {\n credentials = await this.#credentialService.recoverPermits(\n allContracts,\n strategy.delegator,\n staleSignatures,\n );\n } catch (recoveryError) {\n // A re-grant the signer cannot complete must not mask the revocation:\n // the caller's remedy is a new permit, not a signing fix. A user\n // rejecting the prompt stays a rejection.\n if (recoveryError instanceof SigningFailedError) {\n throw new RevokedKmsContextError(\n \"The permit's KMS context has been revoked on-chain and the automatic re-grant \" +\n \"failed, so the decrypt cannot proceed. Establish a new permit for this scope \" +\n \"and retry.\",\n { cause: recoveryError },\n );\n }\n throw recoveryError;\n }\n await this.#runDecryptRequests(\n strategy,\n credentials,\n requests.filter(({ encryptedValues }) =>\n encryptedValues.some((encryptedValue) => result[encryptedValue] === undefined),\n ),\n result,\n options,\n );\n }\n\n const uncachedResult: Record<EncryptedValue, ClearValue> = {};\n for (const encryptedValue of uncachedEncryptedValues) {\n const value = result[encryptedValue];\n if (value !== undefined) {\n uncachedResult[encryptedValue] = value;\n }\n }\n this.#emitEvent({\n type: ZamaSDKEvents.DecryptEnd,\n durationMs: Date.now() - t0,\n encryptedValues: uncachedEncryptedValues,\n result: uncachedResult,\n });\n return result;\n } catch (error) {\n // Per-contract failures are already classified into a typed ZamaError whose\n // `cause` is the original failure; surface that original in the observability\n // event so monitoring keeps the root-cause message.\n const original =\n error instanceof ZamaError && error.cause instanceof Error ? error.cause : error;\n this.#emitEvent({\n type: ZamaSDKEvents.DecryptError,\n error: toError(original),\n durationMs: Date.now() - t0,\n encryptedValues: uncachedEncryptedValues,\n });\n // The per-contract wrap above already classified these; this is a passthrough\n // for them plus a fallback for any non-contract failure (e.g. caching).\n throw wrapDecryptError(error, strategy.errorMessage, {\n isDelegated: strategy.delegator !== undefined,\n });\n }\n }\n\n /**\n * Fan the decrypt requests out (bounded concurrency), writing clear values\n * into `result` and the cache as each settles. Every request is settled\n * before anything is thrown: pLimit rejects on the first settled failure\n * while siblings are still in flight, which would let a sibling's earlier\n * failure hide a revoked-context revert from the recovery decision and let\n * the retry race workers still writing into `result`. Among the settled\n * failures, a {@link RevokedKmsContextError} is surfaced in preference to\n * whichever happened to settle first, so the self-heal always sees it.\n */\n async #runDecryptRequests(\n strategy: DecryptionStrategy,\n credentials: SerializedTransportKeyPairWithPermissions,\n requests: DecryptRequest[],\n result: Record<EncryptedValue, ClearValue>,\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<void> {\n const outcomes = await pLimit(\n requests.map(({ contractAddress, encryptedValues }) => async (): Promise<unknown> => {\n try {\n await this.#decryptRequest(\n strategy,\n credentials,\n contractAddress,\n encryptedValues,\n result,\n options,\n );\n return undefined;\n } catch (error) {\n return error;\n }\n }),\n 5,\n );\n const failures = outcomes.filter((outcome) => outcome !== undefined);\n if (failures.length > 0) {\n throw failures.find((failure) => failure instanceof RevokedKmsContextError) ?? failures[0];\n }\n }\n\n /** Decrypt one contract's chunk of handles into `result` (and the cache). */\n async #decryptRequest(\n strategy: DecryptionStrategy,\n credentials: SerializedTransportKeyPairWithPermissions,\n contractAddress: Address,\n encryptedValues: EncryptedValue[],\n result: Record<EncryptedValue, ClearValue>,\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<void> {\n // Classify per contract so a not-entitled / relayer failure carries the\n // exact contract + ACL actor. Already-typed errors pass straight through.\n let decrypted: DecryptValuesReturnType;\n try {\n decrypted = await this.#decryptValues(credentials, contractAddress, encryptedValues, options);\n } catch (error) {\n throw wrapDecryptError(error, strategy.errorMessage, {\n isDelegated: strategy.delegator !== undefined,\n contractAddress,\n account: strategy.delegator ?? strategy.requesterAddress,\n });\n }\n\n // `decryptValues` returns clear values positionally aligned with the\n // requested `encryptedValues`; zip them back into the handle→value map.\n for (let i = 0; i < encryptedValues.length; i++) {\n const encryptedValue = encryptedValues[i];\n const value = decrypted[i]?.value;\n if (encryptedValue === undefined || value === undefined) {\n continue;\n }\n result[encryptedValue] = value;\n await this.#cache.set(strategy.requesterAddress, contractAddress, encryptedValue, value);\n }\n\n const missing = encryptedValues.filter(\n (encryptedValue) => result[encryptedValue] === undefined,\n );\n if (missing.length > 0) {\n throw new DecryptionFailedError(\n `${strategy.errorMessage}: relayer returned no clear value for ${missing.length} of ${encryptedValues.length} handle(s) on ${contractAddress}`,\n {\n cause: new AggregateError(\n missing.map(\n (encryptedValue) =>\n new DecryptionFailedError(\n `No clear value for handle ${encryptedValue} on ${contractAddress}`,\n ),\n ),\n `${missing.length} handle(s) missing a clear value on ${contractAddress}`,\n ),\n },\n );\n }\n }\n\n /** Build an `RpcRateLimitError` for a throttled on-chain read. */\n #rpcRateLimitError(error: unknown, context: string): RpcRateLimitError {\n return new RpcRateLimitError(`RPC provider rate-limited ${context}; retry with backoff.`, {\n cause: error,\n retryAfter: extractRetryAfter(error),\n });\n }\n\n #setHandleResult(item: BatchDecryptItem, decrypted: Record<EncryptedValue, ClearValue>): void {\n const value = decrypted[item.encryptedValue];\n if (value === undefined) {\n item.error = new DecryptionFailedError(\n `Batch delegated decryption returned no value for encrypted value ${item.encryptedValue} on contract ${item.contractAddress}`,\n );\n return;\n }\n item.value = value;\n }\n\n #toZamaError(error: unknown, fallbackMessage: string, ctx?: DecryptErrorContext): ZamaError {\n return error instanceof ZamaError ? error : wrapDecryptError(error, fallbackMessage, ctx);\n }\n\n #missingBatchItem(): never {\n throw new DecryptionFailedError(\"Batch delegated decryption invariant failed: missing item\");\n }\n\n async #assertAllDelegationsActive(\n contractAddresses: readonly Address[],\n { delegatorAddress, delegateAddress }: { delegatorAddress: Address; delegateAddress: Address },\n ): Promise<void> {\n const inactive = await this.#delegationService.findInactiveDelegations(\n contractAddresses,\n delegatorAddress,\n delegateAddress,\n );\n if (inactive.size === 0) {\n return;\n }\n for (const error of inactive.values()) {\n throw error;\n }\n }\n}\n","import type { ZamaError } from \"./base\";\nimport { extractRevertErrorName } from \"./revert\";\nimport {\n AclPausedError,\n DelegationContractIsSelfError,\n DelegationCooldownError,\n DelegationDelegateEqualsContractError,\n DelegationExpirationTooSoonError,\n DelegationExpiryUnchangedError,\n DelegationNotFoundError,\n DelegationSelfNotAllowedError,\n} from \"./delegation\";\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 Object.hasOwn(ACL_ERROR_MAP, name);\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 { ChainRouter } from \"../chains/router\";\nimport type {\n GenericLogger,\n GenericProvider,\n GenericSigner,\n TransactionResult,\n WriteContractConfig,\n} from \"../types\";\nimport { submitTransaction } from \"../utils/submit-transaction\";\n\ntype AclTransactionOperation = Extract<\n TransactionOperation,\n \"delegateDecryption\" | \"revokeDelegation\"\n>;\n\n/** Delegation activity and expiry, resolved from a single expiry read. */\nexport interface DelegationStatus {\n /** Whether the delegation is currently active (exists and not expired). */\n isActive: boolean;\n /** Unix timestamp (seconds) when the delegation expires; `0n` if none exists. */\n expiryTimestamp: bigint;\n}\n\n/** @internal */\nexport class DelegationService {\n readonly #router: ChainRouter;\n readonly #provider: GenericProvider;\n readonly #emitEvent: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;\n readonly #logger: GenericLogger;\n\n constructor({\n provider,\n router,\n emitEvent = () => {},\n logger,\n }: {\n provider: GenericProvider;\n router: ChainRouter;\n logger: GenericLogger;\n emitEvent?: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;\n }) {\n this.#provider = provider;\n this.#router = router;\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 = this.#router.relayer.chain.aclContractAddress;\n const expDate = expirationDate\n ? BigInt(Math.floor(expirationDate.getTime() / 1000))\n : MAX_UINT64;\n\n let currentExpiry: bigint;\n try {\n currentExpiry = await this.getDelegationExpiry({\n contractAddress: normalizedContract,\n delegatorAddress: normalizedDelegator,\n delegateAddress: normalizedDelegate,\n });\n } catch (error) {\n this.#logger.warn(\"delegateDecryption: pre-flight expiry check failed\", { error });\n currentExpiry = -1n;\n }\n if (currentExpiry === expDate) {\n throw new DelegationExpiryUnchangedError(\n `The new expiration date (${expDate}) is the same as the current one. No on-chain change needed.`,\n );\n }\n\n return this.#submitAclTransaction({\n operation: \"delegateDecryption\",\n signer,\n contractAddress: normalizedContract,\n config: delegateForUserDecryptionContract(\n acl,\n normalizedDelegate,\n normalizedContract,\n expDate,\n ),\n });\n }\n\n async revokeDelegation(\n signer: GenericSigner,\n {\n contractAddress,\n delegateAddress,\n delegatorAddress,\n }: { contractAddress: Address; delegateAddress: Address; delegatorAddress: Address },\n ): Promise<TransactionResult> {\n const normalizedContract = getAddress(contractAddress);\n const normalizedDelegate = getAddress(delegateAddress);\n const normalizedDelegator = getAddress(delegatorAddress);\n const acl = this.#router.relayer.chain.aclContractAddress;\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: normalizedContract,\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 return (await this.getStatus(params)).isActive;\n }\n\n /**\n * Resolve activity and expiry together from a single {@link getDelegationExpiry} read,\n * instead of two separate round trips through {@link isDelegated} and\n * {@link getDelegationExpiry}.\n */\n async getStatus(params: {\n contractAddress: Address;\n delegatorAddress: Address;\n delegateAddress: Address;\n }): Promise<DelegationStatus> {\n const expiryTimestamp = await this.getDelegationExpiry(params);\n if (expiryTimestamp === 0n) {\n return { isActive: false, expiryTimestamp };\n }\n if (expiryTimestamp === MAX_UINT64) {\n return { isActive: true, expiryTimestamp };\n }\n const now = await this.#provider.getBlockTimestamp();\n return { isActive: expiryTimestamp > now, expiryTimestamp };\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 = this.#router.relayer.chain.aclContractAddress;\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 { isActive, expiryTimestamp } = await this.getStatus({\n contractAddress: normalizedContract,\n delegatorAddress: normalizedDelegator,\n delegateAddress: normalizedDelegate,\n });\n if (isActive) {\n return;\n }\n if (expiryTimestamp === 0n) {\n throw new DelegationNotFoundError(\n `No active delegation from ${normalizedDelegator} to ${normalizedDelegate} for ${normalizedContract}`,\n );\n }\n throw new DelegationExpiredError(\n `Delegation from ${normalizedDelegator} to ${normalizedDelegate} for ${normalizedContract} has expired`,\n );\n }\n}\n","import { getAddress } from \"viem\";\nimport type { ChainRouter } from \"../chains/router\";\nimport { wrapEncryptError } from \"../errors\";\nimport type { ZamaSDKEventInput } from \"../events/sdk-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { EncryptParams, EncryptResult, FhevmRelayerOptions } from \"../relayer/types\";\nimport { toError } from \"../utils\";\n\nexport class EncryptionService {\n readonly #router: ChainRouter;\n readonly #emitEvent: (\n input: ZamaSDKEventInput,\n tokenAddress?: EncryptParams[\"contractAddress\"],\n ) => void;\n\n constructor({\n router,\n emitEvent,\n }: {\n router: ChainRouter;\n emitEvent: (input: ZamaSDKEventInput, tokenAddress?: EncryptParams[\"contractAddress\"]) => void;\n }) {\n this.#router = router;\n this.#emitEvent = emitEvent;\n }\n\n async encryptValues(\n params: EncryptParams,\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<EncryptResult> {\n const t0 = Date.now();\n const normalizedContractAddress = getAddress(params.contractAddress);\n try {\n this.#emitEvent({ type: ZamaSDKEvents.EncryptStart }, normalizedContractAddress);\n const result = await this.#router.relayer.encryptValues({ ...params, options });\n this.#emitEvent(\n { type: ZamaSDKEvents.EncryptEnd, durationMs: Date.now() - t0 },\n normalizedContractAddress,\n );\n return result;\n } catch (error) {\n this.#emitEvent(\n { type: ZamaSDKEvents.EncryptError, error: toError(error), durationMs: Date.now() - t0 },\n normalizedContractAddress,\n );\n throw wrapEncryptError(error, \"Encryption failed\");\n }\n }\n}\n","import type { CredentialService } from \"../credentials/credential-service\";\nimport type { ChainRouter } from \"../chains/router\";\nimport type {\n GenericLogger,\n GenericSigner,\n WalletAccountChange,\n WalletAccountListener,\n} from \"../types\";\nimport { swallow } from \"../utils\";\nimport type { CachingService } from \"./caching-service\";\n\nexport type LifecycleServiceOptions = {\n signer?: GenericSigner;\n router: ChainRouter;\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 #router: ChainRouter;\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.#router = opts.router;\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 router on next.chainId. Downstream\n // keypair warming (driven by listeners — see ZamaProvider) therefore\n // dispatches against the wallet chain rather than chains[0]. Switching to a\n // chain with no configured backend does not throw here — the router tracks\n // it and the next relayer op surfaces a ConfigurationError — so `swallow`\n // is defensive only. It suspends one microtask for error containment, not\n // for I/O; ChainRouter.switchChain is synchronous.\n const nextChainId = next?.chainId;\n if (nextChainId !== undefined) {\n await swallow(\n \"switch relayer chain\",\n () => this.#router.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","import { size } from \"viem\";\nimport { z } from \"zod/mini\";\nimport type {\n ApproveUnderlyingRequest,\n ConfidentialTransferFromRequest,\n ConfidentialTransferRequest,\n DelegateDecryptionRequest,\n FinalizeUnwrapRequest,\n PrepareOptions,\n PrepareTransactionRequest,\n RevokeDelegationRequest,\n SetOperatorRequest,\n TransferAndCallRequest,\n UnwrapAllRequest,\n UnwrapRequest,\n WrapRequest,\n WriteContractConfig,\n} from \"../types\";\nimport { checksummedAddress, hex, unixSeconds } from \"./primitives\";\n\n/**\n * {@link ConfidentialTransferRequest} schema.\n * @internal\n */\nexport const confidentialTransferRequest = z.object({\n kind: z.literal(\"ConfidentialTransfer\"),\n from: checksummedAddress,\n token: checksummedAddress,\n to: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<ConfidentialTransferRequest>;\n\n/**\n * {@link ConfidentialTransferFromRequest} schema.\n * @internal\n */\nexport const confidentialTransferFromRequest = z.object({\n kind: z.literal(\"ConfidentialTransferFrom\"),\n from: checksummedAddress,\n token: checksummedAddress,\n owner: checksummedAddress,\n to: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<ConfidentialTransferFromRequest>;\n\n/**\n * {@link SetOperatorRequest} schema. `until` is a required unix timestamp\n * (seconds); pass `0 < until < now` to revoke.\n * @internal\n */\nexport const setOperatorRequest = z.object({\n kind: z.literal(\"SetOperator\"),\n from: checksummedAddress,\n token: checksummedAddress,\n operator: checksummedAddress,\n until: unixSeconds,\n}) satisfies z.ZodMiniType<SetOperatorRequest>;\n\n/**\n * {@link UnwrapRequest} schema.\n * @internal\n */\nexport const unwrapRequest = z.object({\n kind: z.literal(\"Unwrap\"),\n from: checksummedAddress,\n token: checksummedAddress,\n to: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<UnwrapRequest>;\n\n/**\n * {@link UnwrapAllRequest} schema.\n * @internal\n */\nexport const unwrapAllRequest = z.object({\n kind: z.literal(\"UnwrapAll\"),\n from: checksummedAddress,\n token: checksummedAddress,\n to: checksummedAddress,\n}) satisfies z.ZodMiniType<UnwrapAllRequest>;\n\n/**\n * {@link FinalizeUnwrapRequest} schema.\n * @internal\n */\nexport const finalizeUnwrapRequest = z.object({\n kind: z.literal(\"FinalizeUnwrap\"),\n from: checksummedAddress,\n wrapper: checksummedAddress,\n unwrapRequestIdOrAmount: hex,\n}) satisfies z.ZodMiniType<FinalizeUnwrapRequest>;\n\n/**\n * {@link ApproveUnderlyingRequest} schema.\n * @internal\n */\nexport const approveUnderlyingRequest = z.object({\n kind: z.literal(\"ApproveUnderlying\"),\n from: checksummedAddress,\n underlying: checksummedAddress,\n spender: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<ApproveUnderlyingRequest>;\n\n/**\n * {@link WrapRequest} schema.\n * @internal\n */\nexport const wrapRequest = z.object({\n kind: z.literal(\"Wrap\"),\n from: checksummedAddress,\n wrapper: checksummedAddress,\n to: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<WrapRequest>;\n\n/**\n * `TransferAndCall` recipient payload: `0x` (self-shield to the sender) or a\n * raw 20-byte address. The wrapper's receiver hook does\n * `to = data.length < 20 ? from : address(bytes20(data))`, so any other\n * non-empty value (e.g. a 32-byte ABI-encoded address) is truncated to its\n * first 20 bytes — minting the shielded funds to a garbage address. Reject\n * those rather than let the funds go astray; omit for a self-shield.\n */\nconst recipientData = hex.check(\n z.refine(\n (data) => data === \"0x\" || size(data) === 20,\n 'TransferAndCall.recipientData must be \"0x\" (self-shield to the sender) or a raw 20-byte address, ' +\n \"not a 32-byte ABI-encoded value the wrapper would truncate to a garbage address\",\n ),\n);\n\n/**\n * {@link TransferAndCallRequest} schema. `recipientData` is 20 raw bytes or `0x`.\n * @internal\n */\nexport const transferAndCallRequest = z.object({\n kind: z.literal(\"TransferAndCall\"),\n from: checksummedAddress,\n underlying: checksummedAddress,\n wrapper: checksummedAddress,\n amount: z.bigint(),\n recipientData: z.optional(recipientData),\n}) satisfies z.ZodMiniType<TransferAndCallRequest>;\n\n/**\n * {@link DelegateDecryptionRequest} schema. Input takes an optional\n * `expirationDate` (a `Date`); the parsed output is the on-chain `uint64`\n * expiry — seconds since epoch, or `MAX_UINT64` (\"permanent\") when omitted —\n * so callers never hand-roll the encoding.\n *\n * The ≥1h-in-the-future expiry check and the self/contract guards live in the\n * `#buildDelegateDecryption` builder (they throw domain-specific delegation\n * errors this schema can't).\n * @internal\n */\nexport const delegateDecryptionRequest = z.object({\n kind: z.literal(\"DelegateDecryption\"),\n from: checksummedAddress,\n contractAddress: checksummedAddress,\n delegateAddress: checksummedAddress,\n expirationDate: z.optional(z.date()),\n}) satisfies z.ZodMiniType<DelegateDecryptionRequest>;\n\n/**\n * {@link RevokeDelegationRequest} schema.\n * @internal\n */\nexport const revokeDelegationRequest = z.object({\n kind: z.literal(\"RevokeDelegation\"),\n from: checksummedAddress,\n contractAddress: checksummedAddress,\n delegateAddress: checksummedAddress,\n}) satisfies z.ZodMiniType<RevokeDelegationRequest>;\n\n/**\n * Discriminated union (on `kind`) of every offline `prepare` request. Backs\n * both the {@link PrepareTransactionRequest} type and the runtime validation\n * in `OfflineService.prepare`.\n * @internal\n */\nexport const prepareTransactionRequest = z.discriminatedUnion(\"kind\", [\n confidentialTransferRequest,\n confidentialTransferFromRequest,\n setOperatorRequest,\n unwrapRequest,\n unwrapAllRequest,\n finalizeUnwrapRequest,\n approveUnderlyingRequest,\n wrapRequest,\n transferAndCallRequest,\n delegateDecryptionRequest,\n revokeDelegationRequest,\n]) satisfies z.ZodMiniType<PrepareTransactionRequest>;\n\n/**\n * {@link PrepareFees} schema. `maxFeePerGas` and `maxPriorityFeePerGas` live in\n * one object so they can only be supplied together — pinning a cap (the total\n * fee) while the tip is estimated can produce a tip above the cap and fail\n * serialization. Both legs are validated as `bigint` so a JS caller (no\n * compiler) can't slip a `number` into the frozen, signed payload.\n * @internal\n */\nexport const fees = z.strictObject({ maxFeePerGas: z.bigint(), maxPriorityFeePerGas: z.bigint() });\n\n/**\n * {@link PrepareOptions} schema. All fields are optional; omitted ones fall\n * back to the provider's live chain-state defaults.\n * @internal\n */\nexport const prepareOptions = z.object({\n nonce: z.optional(z.int().check(z.nonnegative())),\n gasLimit: z.optional(z.bigint()),\n fees: z.optional(fees),\n}) satisfies z.ZodMiniType<PrepareOptions>;\n\n/**\n * `WriteContractConfig` schema. `abi` and `args` are validated only as\n * arrays — their element shapes are the ABI-typed `TAbi`/`TFunctionName`\n * generics the runtime can't check — so this guards the structural envelope\n * (address, function name, the two arrays, optional `value`/`gas`) a provider's\n * tx-builder consumes.\n * @internal\n */\nexport const writeContractConfig = z.object({\n address: checksummedAddress,\n abi: z.array(z.unknown()),\n functionName: z.string(),\n args: z.array(z.unknown()),\n value: z.optional(z.bigint()),\n gas: z.optional(z.bigint()),\n}) satisfies z.ZodMiniType<WriteContractConfig>;\n\n/**\n * Schema for the argument object of `GenericProvider.prepareTransaction`:\n * the originating `from` wallet, the write-contract `calldata`, and the\n * optional chain-state overrides. Extends {@link prepareOptions} so the\n * `nonce`/`gasLimit`/`fees` legs stay in lockstep with the per-call overrides.\n *\n * `from` is EIP-55 checksummed on parse (the custodian keys off it), so the\n * validated output can flow straight into the prepared handoff.\n * @internal\n */\nexport const prepareTransactionParams = z.extend(prepareOptions, {\n from: checksummedAddress,\n calldata: writeContractConfig,\n});\n","import type { Address } from \"viem\";\nimport type { ChainRouter } from \"../chains/router\";\nimport {\n approveContract,\n confidentialBalanceOfContract,\n confidentialTransferContract,\n confidentialTransferFromContract,\n delegateForUserDecryptionContract,\n finalizeUnwrapContract,\n MAX_UINT64,\n revokeDelegationContract,\n setOperatorContract,\n transferAndCallContract,\n unwrapContract,\n unwrapFromBalanceContract,\n wrapContract,\n} from \"../contracts\";\nimport {\n ConfigurationError,\n DelegationDelegateEqualsContractError,\n DelegationExpirationTooSoonError,\n DelegationSelfNotAllowedError,\n EncryptionFailedError,\n wrapDecryptError,\n} from \"../errors\";\nimport type { ZamaSDKEventInput } from \"../events/sdk-events\";\nimport {\n approveUnderlyingRequest,\n confidentialTransferFromRequest,\n confidentialTransferRequest,\n delegateDecryptionRequest,\n finalizeUnwrapRequest,\n prepareOptions,\n prepareTransactionParams,\n revokeDelegationRequest,\n setOperatorRequest,\n transferAndCallRequest,\n unwrapAllRequest,\n unwrapRequest,\n wrapRequest,\n} from \"../schemas/offline\";\nimport type {\n ApproveUnderlyingRequest,\n ConfidentialTransferFromRequest,\n ConfidentialTransferRequest,\n DelegateDecryptionRequest,\n FinalizeUnwrapRequest,\n GenericProvider,\n PreparedFor,\n PrepareOptions,\n PrepareTransactionRequest,\n RevokeDelegationRequest,\n SetOperatorRequest,\n TransactionKind,\n TransferAndCallRequest,\n UnwrapAllRequest,\n UnwrapRequest,\n WrapRequest,\n} from \"../types\";\nimport { assertBigint } from \"../utils/assertions\";\nimport { parseSchema } from \"../validation\";\nimport type { EncryptionService } from \"./encryption-service\";\n\n/**\n * Configuration for {@link OfflineService}.\n *\n * @internal\n */\nexport interface OfflineServiceConfig {\n readonly provider: GenericProvider;\n readonly router: ChainRouter;\n readonly encryption: EncryptionService;\n readonly emitEvent: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;\n}\n\n/**\n * Offline-signing pipeline. Builds an RLP-encoded unsigned transaction that\n * the caller signs **and** publishes out-of-process — for institutional\n * custody, HSM ceremonies, and policy-engine workflows where signing cannot\n * happen synchronously in a single Promise.\n *\n * Atomic call sites ({@link Token.confidentialTransfer}, etc.) keep their\n * `signer.writeContract` path; this service is the parallel route where the\n * caller signs `prepared.unsignedTx` externally (HSM, custody API, policy\n * engine) and publishes the signed bytes through its own channel.\n *\n * Owned by {@link ZamaSDK}.\n *\n * @internal\n */\nexport class OfflineService {\n readonly #provider: GenericProvider;\n readonly #router: ChainRouter;\n readonly #encryption: EncryptionService;\n\n constructor(config: OfflineServiceConfig) {\n this.#provider = config.provider;\n this.#router = config.router;\n this.#encryption = config.encryption;\n }\n\n // ── prepare ─────────────────────────────────────────────────────────────\n\n /**\n * Build the offline-signing payload for the given transaction request:\n * an RLP-encoded unsigned transaction the caller signs externally (an HSM,\n * custody API, or any out-of-process signer) and publishes through its own\n * channel.\n *\n * Decryption permits are not transactions — acquire them via\n * `sdk.permits.grantPermit`, which signs with the configured signer\n * (including an out-of-process custody signer).\n */\n async prepare<K extends TransactionKind>(\n request: Extract<PrepareTransactionRequest, { kind: K }>,\n options?: PrepareOptions,\n ): Promise<PreparedFor<K>> {\n if (options) {\n options = parseSchema(prepareOptions, options);\n }\n\n // The prepared tx's contract addresses and encrypted inputs are bound to\n // the SDK's configured chain; if the provider is on a different chain it\n // would bake that chain's id into a tx carrying wrong-chain addresses.\n // No signer here (offline is signer-less), so guard router vs provider\n // directly rather than through requireChainAlignment.\n const providerChainId = await this.#provider.getChainId();\n const expectedChainId = this.#router.chain.id;\n if (providerChainId !== expectedChainId) {\n throw new ConfigurationError(\n `Offline.prepare: provider is on chain ${providerChainId} but the SDK is configured for chain ${expectedChainId}. ` +\n `The prepared transaction's contract addresses and encrypted inputs are bound to chain ${expectedChainId} — point the provider at the same chain.`,\n );\n }\n\n const calldata = await this.#buildCalldata(request);\n const params = {\n calldata,\n from: request.from,\n nonce: options?.nonce,\n gasLimit: options?.gasLimit,\n fees: options?.fees,\n };\n const parsed = parseSchema(prepareTransactionParams, params);\n const unsignedTx = await this.#provider.prepareTransaction(parsed);\n return { kind: request.kind, unsignedTx, from: parsed.from } satisfies PreparedFor<K>;\n }\n\n // ── internals ──────────────────────────────────────────────────────────\n\n async #buildCalldata(\n request: PrepareTransactionRequest,\n ): Promise<{\n readonly address: Address;\n readonly abi: readonly unknown[];\n readonly functionName: string;\n readonly args: readonly unknown[];\n }> {\n switch (request.kind) {\n case \"ConfidentialTransfer\":\n return this.#buildConfidentialTransfer(request);\n case \"ConfidentialTransferFrom\":\n return this.#buildConfidentialTransferFrom(request);\n case \"SetOperator\":\n return this.#buildSetOperator(request);\n case \"Unwrap\":\n return this.#buildUnwrap(request);\n case \"UnwrapAll\":\n return this.#buildUnwrapAll(request);\n case \"FinalizeUnwrap\":\n return this.#buildFinalizeUnwrap(request);\n case \"ApproveUnderlying\":\n return this.#buildApproveUnderlying(request);\n case \"Wrap\":\n return this.#buildWrap(request);\n case \"TransferAndCall\":\n return this.#buildTransferAndCall(request);\n case \"DelegateDecryption\":\n return this.#buildDelegateDecryption(request);\n case \"RevokeDelegation\":\n return this.#buildRevokeDelegation(request);\n default: {\n const unhandled: { kind: string } = request;\n throw new ConfigurationError(\n `OfflineService.prepare: unsupported transaction kind '${unhandled.kind}'.`,\n );\n }\n }\n }\n\n async #buildConfidentialTransfer(\n request: ConfidentialTransferRequest,\n ): Promise<ReturnType<typeof confidentialTransferContract>> {\n request = parseSchema(confidentialTransferRequest, request);\n const { encryptedValues, inputProof } = await this.#encryption.encryptValues({\n values: [{ value: request.amount, type: \"euint64\" }],\n contractAddress: request.token,\n userAddress: request.from,\n });\n const handle = encryptedValues[0];\n if (!handle) {\n throw new EncryptionFailedError(\"Encryption returned no handles for ConfidentialTransfer\");\n }\n return confidentialTransferContract(request.token, request.to, handle, inputProof);\n }\n\n async #buildConfidentialTransferFrom(\n request: ConfidentialTransferFromRequest,\n ): Promise<ReturnType<typeof confidentialTransferFromContract>> {\n request = parseSchema(confidentialTransferFromRequest, request);\n // The encrypted input's proof binds to the tx sender (fhevm verifies it\n // against `msg.sender`), which for `transferFrom` is the operator == the\n // `from` wallet that signs and broadcasts — not the `owner` being debited.\n const { encryptedValues, inputProof } = await this.#encryption.encryptValues({\n values: [{ value: request.amount, type: \"euint64\" }],\n contractAddress: request.token,\n userAddress: request.from,\n });\n const handle = encryptedValues[0];\n if (!handle) {\n throw new EncryptionFailedError(\n \"Encryption returned no handles for ConfidentialTransferFrom\",\n );\n }\n return confidentialTransferFromContract(\n request.token,\n request.owner,\n request.to,\n handle,\n inputProof,\n );\n }\n\n #buildSetOperator(request: SetOperatorRequest): ReturnType<typeof setOperatorContract> {\n request = parseSchema(setOperatorRequest, request);\n return setOperatorContract(request.token, request.operator, request.until);\n }\n\n async #buildUnwrap(request: UnwrapRequest): Promise<ReturnType<typeof unwrapContract>> {\n request = parseSchema(unwrapRequest, request);\n const { encryptedValues, inputProof } = await this.#encryption.encryptValues({\n values: [{ value: request.amount, type: \"euint64\" }],\n contractAddress: request.token,\n userAddress: request.from,\n });\n const handle = encryptedValues[0];\n if (!handle) {\n throw new EncryptionFailedError(\"Encryption returned no handles for Unwrap\");\n }\n return unwrapContract(request.token, request.from, request.to, handle, inputProof);\n }\n\n async #buildUnwrapAll(\n request: UnwrapAllRequest,\n ): Promise<ReturnType<typeof unwrapFromBalanceContract>> {\n request = parseSchema(unwrapAllRequest, request);\n const balanceHandle = await this.#provider.readContract(\n confidentialBalanceOfContract(request.token, request.from),\n );\n return unwrapFromBalanceContract(request.token, request.from, request.to, balanceHandle);\n }\n\n async #buildFinalizeUnwrap(\n request: FinalizeUnwrapRequest,\n ): Promise<ReturnType<typeof finalizeUnwrapContract>> {\n request = parseSchema(finalizeUnwrapRequest, request);\n const decrypted = await this.#router.relayer\n .decryptPublicValuesWithSignatures({ encryptedValues: [request.unwrapRequestIdOrAmount] })\n .catch((error: unknown) => {\n throw wrapDecryptError(error, \"Public decryption failed during FinalizeUnwrap\");\n });\n const raw = decrypted.clearValues[0]?.value;\n assertBigint(raw, \"FinalizeUnwrap: decryptPublicValuesWithSignatures(handle).clearValue\");\n return finalizeUnwrapContract(\n request.wrapper,\n request.unwrapRequestIdOrAmount,\n raw,\n decrypted.checkSignaturesArgs.decryptionProof,\n );\n }\n\n #buildApproveUnderlying(request: ApproveUnderlyingRequest): ReturnType<typeof approveContract> {\n request = parseSchema(approveUnderlyingRequest, request);\n return approveContract(request.underlying, request.spender, request.amount);\n }\n\n #buildWrap(request: WrapRequest): ReturnType<typeof wrapContract> {\n request = parseSchema(wrapRequest, request);\n return wrapContract(request.wrapper, request.to, request.amount);\n }\n\n #buildTransferAndCall(\n request: TransferAndCallRequest,\n ): ReturnType<typeof transferAndCallContract> {\n request = parseSchema(transferAndCallRequest, request);\n return transferAndCallContract(\n request.underlying,\n request.wrapper,\n request.amount,\n request.recipientData,\n );\n }\n\n #buildDelegateDecryption(\n request: DelegateDecryptionRequest,\n ): ReturnType<typeof delegateForUserDecryptionContract> {\n request = parseSchema(delegateDecryptionRequest, request);\n // Expiry ≥1h out: an expiry under 1h lands already-expired (or nearly so),\n // and the offline payload is signed/broadcast later, eating into that\n // margin further. Checked against the pre-parse `Date` (the schema\n // transforms it into the on-chain uint64 below).\n if (request.expirationDate && request.expirationDate.getTime() < Date.now() + 3_600_000) {\n throw new DelegationExpirationTooSoonError(\n \"Expiration date must be at least 1 hour in the future\",\n );\n }\n if (request.delegateAddress === request.from) {\n throw new DelegationSelfNotAllowedError(\n \"Cannot delegate to yourself (delegate === msg.sender).\",\n );\n }\n if (request.delegateAddress === request.contractAddress) {\n throw new DelegationDelegateEqualsContractError(\n `Delegate address cannot be the same as the contract address (${request.contractAddress}).`,\n );\n }\n const expirationDate = request.expirationDate\n ? BigInt(Math.floor(request.expirationDate.getTime() / 1000))\n : MAX_UINT64;\n return delegateForUserDecryptionContract(\n this.#router.chain.aclContractAddress,\n request.delegateAddress,\n request.contractAddress,\n expirationDate,\n );\n }\n\n #buildRevokeDelegation(\n request: RevokeDelegationRequest,\n ): ReturnType<typeof revokeDelegationContract> {\n request = parseSchema(revokeDelegationRequest, request);\n return revokeDelegationContract(\n this.#router.chain.aclContractAddress,\n request.delegateAddress,\n request.contractAddress,\n );\n }\n}\n","import type { Address } from \"viem\";\nimport type { ChainRouter } from \"./chains/router\";\nimport type { ZamaConfig } from \"./config/types\";\nimport { CredentialService } from \"./credentials/credential-service\";\nimport { DerivationSecretHolder } from \"./credentials/keypair-wrapping\";\nimport { DerivationSecretSchema } from \"./credentials/schemas\";\nimport { ConfigurationError } from \"./errors\";\nimport type { ZamaSDKEvent, ZamaSDKEventInput, ZamaSDKEventListener } from \"./events/sdk-events\";\nimport { Decryption } from \"./namespaces/decryption\";\nimport { Delegations } from \"./namespaces/delegations\";\nimport { Offline } from \"./namespaces/offline\";\nimport { Permits } from \"./namespaces/permits\";\nimport type { EncryptParams, FhevmRelayerOptions, RelayerSDK } from \"./relayer/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 { OfflineService } from \"./services/offline-service\";\nimport { Token } from \"./token/token\";\nimport { WrappedToken } from \"./token/wrapped-token\";\nimport type {\n GenericLogger,\n GenericProvider,\n GenericSigner,\n GenericStorage,\n WalletAccountListener,\n} from \"./types\";\nimport { parseSchema } from \"./validation\";\nimport { WrappersRegistry } from \"./wrappers-registry\";\n\n/** Instance-level options that are deliberately not part of the shareable config object. */\nexport interface ZamaSDKOptions {\n /**\n * Encrypts the transport key pair's private half at rest. Headless environments only\n * (CLI tools, servers, agents); the constructor rejects it in browser contexts. Supply\n * at least 32 random bytes, or a string of at least 64 characters, from a CSPRNG or\n * secrets manager. The SDK copies a Uint8Array secret and zeroizes its own copy after\n * key import; it never touches your buffer, so zeroize yours after construction.\n * The SDK never persists or exposes this value. Omit for the default:\n * plaintext at rest, security delegated to the storage backend.\n */\n transportKeyPairDerivationSecret?: string | Uint8Array;\n}\n\n/**\n * Omitting the option means cleartext-at-rest by choice; passing it as `undefined` means the\n * caller asked for wrapping and the value went missing, so it must fail instead of downgrading.\n */\nfunction assertDerivationSecretNotUnset(options: ZamaSDKOptions): void {\n if (\n !Object.hasOwn(options, \"transportKeyPairDerivationSecret\") ||\n options.transportKeyPairDerivationSecret !== undefined\n ) {\n return;\n }\n throw new ConfigurationError(\n \"transportKeyPairDerivationSecret was passed as undefined, which usually means the environment variable it reads is unset (e.g. process.env.ZAMA_DERIVATION_SECRET). Supply the secret, or omit the option entirely to persist transport key pairs in cleartext on purpose.\",\n );\n}\n\n/**\n * Wrapping only helps where no platform keystore protects the store, which is the headless\n * case. `importScripts` catches a browser worker, where `window` and `document` are absent.\n */\nfunction assertDerivationSecretHeadless(secret: string | Uint8Array | undefined): void {\n if (secret === undefined) {\n return;\n }\n const { importScripts } = globalThis as { importScripts?: unknown };\n const headless =\n typeof window === \"undefined\" &&\n typeof document === \"undefined\" &&\n typeof importScripts !== \"function\";\n if (headless) {\n return;\n }\n throw new ConfigurationError(\n \"transportKeyPairDerivationSecret is supported in headless environments only (CLI tools, servers, agents). Remove the option: an environment with a platform keystore, or one that ships a bundle, must delegate at-rest security of the transport key pair to the storage backend.\",\n );\n}\n\n/**\n * Copies a `Uint8Array` secret so the holder only ever zeroizes the SDK's own buffer, and\n * a caller zeroizing theirs cannot corrupt later wraps. Strings are immutable, so no copy.\n */\nfunction derivationSecretHolder(\n secret: string | Uint8Array | undefined,\n): DerivationSecretHolder | undefined {\n if (secret === undefined) {\n return undefined;\n }\n const parsed = parseSchema(DerivationSecretSchema, secret);\n return new DerivationSecretHolder(typeof parsed === \"string\" ? parsed : new Uint8Array(parsed));\n}\n\n/**\n * ZamaSDK — composes a RelayerSDK with contract abstraction.\n *\n * Exposes domain namespaces for permits, delegations, decryption, offline\n * signing, and tokens, plus an unchanged registry, a top-level `encrypt`, and\n * lifecycle methods. Internal `*Service` classes do the work; the namespace\n * classes own SDK-level guards (chain alignment, signer requirement, event\n * emission).\n */\nexport class ZamaSDK {\n readonly #router: ChainRouter;\n /** Read-only chain access used for all contract reads. */\n readonly provider: GenericProvider;\n /** Wallet signer used for write operations, or `undefined` when the SDK is read-only. */\n readonly signer: GenericSigner | undefined;\n /** Storage for cached permits and transport key pairs. */\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 /** Offline-signing pipeline: `prepare` builds an unsigned tx the caller signs and broadcasts out-of-process — for HSM, policy-engine, and cross-process custody workflows. */\n readonly offline: Offline;\n readonly #registryTTL: number;\n readonly #registryAddresses: Record<number, Address>;\n readonly #onEvent: ZamaSDKEventListener;\n readonly #logger: GenericLogger;\n readonly #cachingService: CachingService;\n readonly #lifecycleService: LifecycleService;\n readonly #encryptionService: EncryptionService;\n readonly #decryptionService: DecryptionService | undefined;\n readonly #credentialService: CredentialService;\n readonly #delegationService: DelegationService;\n readonly #offlineService: OfflineService;\n\n constructor(config: ZamaConfig, options: ZamaSDKOptions = {}) {\n assertDerivationSecretNotUnset(options);\n assertDerivationSecretHeadless(options.transportKeyPairDerivationSecret);\n // Constructor-local on purpose: neither the raw secret nor the holder may become a field.\n const derivationSecret = derivationSecretHolder(options.transportKeyPairDerivationSecret);\n\n this.#router = config.router;\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 router: config.router,\n emitEvent: this.emitEvent.bind(this),\n logger: this.#logger,\n });\n\n const registryAddresses: Record<number, Address> = {};\n for (const chain of config.chains) {\n if (chain.registryAddress) {\n registryAddresses[chain.id] = chain.registryAddress;\n }\n }\n this.registry = new WrappersRegistry({\n provider: this.provider,\n registryAddresses,\n registryTTL: config.registryTTL,\n });\n this.#registryAddresses = registryAddresses;\n this.#registryTTL = config.registryTTL;\n\n // CredentialService is always constructed (with optional signer) so\n // public-decrypt / encryption flows and pre-wallet-connect construction\n // work; permit-signing methods require a signer and throw without one.\n this.#credentialService = new CredentialService({\n router: config.router,\n signer: config.signer,\n transportKeyPairTTL: config.transportKeyPairTTL,\n permitTTL: config.permitTTL,\n scope: config.transportKeyPairScope,\n derivationSecret,\n storage: this.storage,\n permitStorage: config.permitStorage,\n logger: this.#logger,\n emitEvent: this.emitEvent.bind(this),\n });\n if (config.signer) {\n this.#decryptionService = new DecryptionService({\n cache: this.#cachingService,\n credentialService: this.#credentialService,\n delegationService: this.#delegationService,\n router: config.router,\n emitEvent: this.emitEvent.bind(this),\n });\n }\n this.#encryptionService = new EncryptionService({\n router: config.router,\n emitEvent: this.emitEvent.bind(this),\n });\n this.#lifecycleService = new LifecycleService({\n signer: config.signer,\n router: config.router,\n cachingService: this.#cachingService,\n credentialService: this.#credentialService,\n logger: this.#logger,\n });\n this.#offlineService = new OfflineService({\n provider: this.provider,\n router: config.router,\n encryption: this.#encryptionService,\n emitEvent: (input, tokenAddress) => this.emitEvent(input, tokenAddress),\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 emitEvent: this.emitEvent.bind(this),\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 router: config.router,\n decryptionService: this.#decryptionService,\n });\n this.offline = new Offline(this.#offlineService, this.#credentialService);\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 * The single-chain relayer backend for the **currently active** chain.\n */\n get relayer(): RelayerSDK {\n return this.#router.relayer;\n }\n\n /**\n * Emit a structured SDK event into the unified SDK event stream.\n *\n * Listener exceptions are caught and logged so that a misbehaving subscriber\n * can never corrupt SDK operations.\n *\n * Application code should subscribe via the `onEvent` config option, never\n * call this directly.\n *\n * @internal\n */\n emitEvent(input: ZamaSDKEventInput, tokenAddress?: Address): void {\n try {\n this.#onEvent({ ...input, tokenAddress, timestamp: Date.now() } as ZamaSDKEvent);\n } catch (error) {\n this.#logger.warn(`${input.type} event listener silently failed`, { error });\n }\n }\n\n /**\n * Create a {@link WrappersRegistry} instance bound to this SDK's provider.\n * Inherits the registry addresses derived from the SDK's chain configs, so\n * the result is consistent with {@link ZamaSDK.registry}.\n *\n * @param registryAddresses - Optional per-chain overrides for this registry instance.\n * @returns A {@link WrappersRegistry} instance.\n *\n * @example\n * ```ts\n * // Addresses resolved from the SDK's chain configs\n * const registry = sdk.createWrappersRegistry();\n *\n * // Hardhat or custom chain — override per chain for this registry instance\n * const registry = sdk.createWrappersRegistry({ [31337]: \"0xYourRegistry\" });\n *\n * const pairs = await registry.getTokenPairs();\n * ```\n */\n createWrappersRegistry(registryAddresses?: Record<number, Address>): WrappersRegistry {\n return new WrappersRegistry({\n provider: this.provider,\n registryAddresses: { ...this.#registryAddresses, ...registryAddresses },\n registryTTL: this.#registryTTL,\n });\n }\n\n /**\n * Encrypt one or more plaintext values into FHE ciphertexts.\n *\n * @param params - Typed FHE inputs, the target contract address, and the user address.\n * @returns External encrypted values and the input proof for on-chain submission.\n * @throws if FHE encryption fails. {@link EncryptionFailedError}\n *\n * @example\n * ```ts\n * const { encryptedValues, inputProof } = await sdk.encrypt({\n * values: [{ value: 1000n, type: \"euint64\" }],\n * contractAddress: \"0xToken\",\n * userAddress: \"0xUser\",\n * });\n * ```\n */\n async encrypt(params: EncryptParams, options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">) {\n return this.#encryptionService.encryptValues(params, options);\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 * Release the SDK-owned resources: signer lifecycle subscriptions and the\n * relayer backend's resources, an encrypt worker included. Call this when the\n * SDK instance is being replaced (e.g. React provider unmount or a Strict Mode\n * remount). Work already in flight runs to completion, and the instance stays\n * usable: the next encryption spawns a fresh worker.\n */\n dispose(): void {\n this.#lifecycleService.dispose();\n this.#router.dispose();\n }\n\n /**\n * {@link dispose} plus the signer's own disposal. Call this when the SDK is no\n * longer needed (e.g. on shutdown). Work already in flight runs to completion.\n */\n terminate(): void {\n this.dispose();\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 releasing the relayer's resources.\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"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","names":["ZamaError","ZamaError","ZamaErrorCode","ZamaError","ZamaErrorCode","ZamaError","ZamaErrorCode","DecryptionFailedError","NoCiphertextError","RelayerRequestFailedError","SigningRejectedError","SigningFailedError","RpcRateLimitError","InvalidTransportKeyPairError","RevokedKmsContextError","UnifiedDecryptionUnsupportedError","isInvalidTransportKeyPairMessage","isRevokedKmsContextError","isUnifiedDecryptionUnsupportedMessage","isNotEntitledMessage","parseHandleFromMessage","hasStructuredRpcRateLimitSignal","extractRetryAfter","extractHttpStatus","isRpcRateLimitError","isRelayerError","isRelayerTimeoutError","ZamaError","extractHttpStatus","isRelayerTimeoutError","isRelayerError","RelayerRequestFailedError","extractRetryAfter","EncryptionFailedError","buildZamaConfig","#signer","#provider","#cachingService","#credentialService","#delegationService","#logger","#emitEvent","requireConfigured","ZamaSDKEvents","#requireCredentialService","requireChainAlignment","#failPermit","#clearDecryptCacheForRequester","requireAlignedWalletAccount","swallow","#requireSigner","checksum","#signer","#provider","#delegationService","requireConfigured","#requireSigner","requireAlignedWalletAccount","#signer","#provider","#router","#decryptionService","requireConfigured","#requireDecryptionService","requireAlignedWalletAccount","#offlineService","#credentialService","checksum","z","hex","Token","SignerNotConfiguredError","#getUnderlying","#isPayable","isPayableTokenContract","allowanceContract","requireAlignedWalletAccount","balanceOfContract","ZamaError","ERC20ReadFailedError","toError","InsufficientERC20BalanceError","#shieldViaTransferAndCall","#shieldViaApproveAndWrap","#requireSigner","InsufficientAllowanceError","wrapContract","#ensureAllowance","approveContract","swallow","#finalizeUnshield","TransactionRevertedError","#extractUnwrapRequestId","#isUnwrapRequestConsumed","#clearStoredPendingUnshield","#isPendingUnshieldConsumed","EncryptionFailedError","unwrapContract","isEncryptedValueZero","DecryptionFailedError","unwrapFromBalanceContract","requireChainAlignment","finalizeUnwrapContract","unwrapRequesterContract","zeroAddress","#underlying","#underlyingPromise","underlyingContract","ZamaSDKEvents","z","checksummedAddress","#storage","#logger","#decryptNamespace","#decryptKeysNamespace","#buildStorageKey","#indexWriteQueue","#addToIndex","#doDelete","#doClearForRequester","#doClearAll","#readIndex","DecryptionFailedError","checksum","permissionCovers","#cache","#credentialService","#delegationService","#router","#emitEvent","#decrypt","#withPropagationRetry","#assertAllDelegationsActive","#setHandleResult","isFatalBatchError","#missingBatchItem","#toZamaError","pLimit","#decryptValues","isInvalidTransportKeyPairMessage","isEncryptedValueZero","isRpcRateLimitError","#rpcRateLimitError","chunkHandlesByBitBudget","ZamaSDKEvents","#runDecryptRequests","RevokedKmsContextError","SigningFailedError","ZamaError","toError","#decryptRequest","DecryptionFailedError","RpcRateLimitError","extractRetryAfter","InvalidationTimestampTooLowError","InvalidationTimestampInFutureError","#router","#provider","#emitEvent","#logger","#warnIfWildcardAlreadyCoversDelegate","#submitAclTransaction","#needsBlockTimestamp","#resolveStatus","submitTransaction","#throwAclRevertIfMatched","TransactionRevertedError","#router","#emitEvent","ZamaSDKEvents","toError","#signer","#router","#cachingService","#credentialService","#logger","#walletAccountListeners","#unsubscribeSigner","#handleWalletAccountChange","swallow","z","checksummedAddress","unixSeconds","hex","#provider","#router","#encryption","parseSchema","ConfigurationError","#buildCalldata","#buildConfidentialTransfer","#buildConfidentialTransferFrom","#buildSetOperator","#buildUnwrap","#buildUnwrapAll","#buildFinalizeUnwrap","#buildApproveUnderlying","#buildWrap","#buildTransferAndCall","#buildDelegateDecryption","#buildRevokeDelegation","unhandled","EncryptionFailedError","confidentialTransferContract","confidentialTransferFromContract","setOperatorContract","unwrapContract","confidentialBalanceOfContract","unwrapFromBalanceContract","finalizeUnwrapContract","approveContract","wrapContract","ConfigurationError","parseSchema","DerivationSecretSchema","DerivationSecretHolder","#router","#registryTTL","#registryAddresses","#onEvent","#logger","#cachingService","#lifecycleService","#encryptionService","#decryptionService","#credentialService","#delegationService","#offlineService","WrappersRegistry","CredentialService","Token"],"sources":["../../src/errors/match.ts","../../src/errors/entitlement.ts","../../src/errors/delegation.ts","../../src/errors/revert.ts","../../src/errors/unshield.ts","../../src/errors/decrypt.ts","../../src/errors/encrypt.ts","../../src/abi/erc1363.abi.ts","../../src/contracts/erc1363.ts","../../src/abi/acl.abi.ts","../../src/contracts/acl.ts","../../src/contracts/constants.ts","../../src/config/create.ts","../../src/utils/hex.ts","../../src/events/onchain-events.ts","../../src/namespaces/permits.ts","../../src/namespaces/delegations.ts","../../src/namespaces/decryption.ts","../../src/namespaces/offline.ts","../../src/storage/chrome-session-storage.ts","../../src/token/pending-unshield.ts","../../src/token/wrapped-token.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/schemas/offline.ts","../../src/services/offline-service.ts","../../src/zama-sdk.ts"],"sourcesContent":["import { ZamaError } from \"./base\";\nimport type { ZamaErrorCode } from \"./base\";\nimport type { ChainMismatchError } from \"./chain\";\nimport type {\n KeyWrappingError,\n NoCiphertextError,\n PreparedPermitChainMismatchError,\n PreparedPermitExpiredError,\n TransportKeyPairChangedError,\n TransportKeyPairExpiredError,\n InvalidTransportKeyPairError,\n RevokedKmsContextError,\n UnifiedPermitNotSupportedError,\n UnifiedDecryptionUnsupportedError,\n InvalidationTimestampTooLowError,\n InvalidationTimestampInFutureError,\n} from \"./credential\";\nimport type {\n AclPausedError,\n DelegationContractIsSelfError,\n DelegationCooldownError,\n DelegationDelegateEqualsContractError,\n DelegationDelegateCannotBeWildcardError,\n DelegationExpirationTooSoonError,\n DelegationExpiredError,\n DelegationExpiryUnchangedError,\n DelegationNotFoundError,\n DelegationNotPropagatedError,\n DelegationSelfNotAllowedError,\n} from \"./delegation\";\nimport type {\n DecryptionFailedError,\n EncryptionFailedError,\n EncryptOffloadUnavailableError,\n} from \"./encryption\";\nimport type {\n BalanceCheckUnavailableError,\n ERC20ReadFailedError,\n InsufficientAllowanceError,\n InsufficientConfidentialBalanceError,\n InsufficientERC20BalanceError,\n} from \"./balance\";\nimport type { ConfigurationError, RelayerRequestFailedError } from \"./relayer\";\nimport type { NotEntitledError } from \"./entitlement\";\nimport type { RpcRateLimitError } from \"./rpc\";\nimport type {\n SignerNotConfiguredError,\n WalletAccountNotReadyError,\n WalletNotConnectedError,\n} from \"./signer\";\nimport type { SigningFailedError, SigningRejectedError } from \"./signing\";\nimport type { TransactionRevertedError } from \"./transaction\";\nimport type { UnshieldAlreadyFinalizedError } from \"./unshield\";\n\n/**\n * Maps each {@link ZamaErrorCode} to the error class thrown with that code, so\n * {@link matchZamaError} handlers receive the matched subtype instead of the base\n * `ZamaError`.\n */\nexport interface ErrorForCode {\n /** Thrown for {@link ZamaErrorCode.SigningRejected}. */\n [ZamaErrorCode.SigningRejected]: SigningRejectedError;\n /** Thrown for {@link ZamaErrorCode.SigningFailed}. */\n [ZamaErrorCode.SigningFailed]: SigningFailedError;\n /** Thrown for {@link ZamaErrorCode.EncryptionFailed}. */\n [ZamaErrorCode.EncryptionFailed]: EncryptionFailedError;\n /** Thrown for {@link ZamaErrorCode.DecryptionFailed}. */\n [ZamaErrorCode.DecryptionFailed]: DecryptionFailedError;\n /** Thrown for {@link ZamaErrorCode.EncryptOffloadUnavailable}. */\n [ZamaErrorCode.EncryptOffloadUnavailable]: EncryptOffloadUnavailableError;\n /** Thrown for {@link ZamaErrorCode.TransactionReverted}. */\n [ZamaErrorCode.TransactionReverted]: TransactionRevertedError;\n /** Thrown for {@link ZamaErrorCode.TransportKeyPairExpired}. */\n [ZamaErrorCode.TransportKeyPairExpired]: TransportKeyPairExpiredError;\n /** Thrown for {@link ZamaErrorCode.InvalidTransportKeyPair}. */\n [ZamaErrorCode.InvalidTransportKeyPair]: InvalidTransportKeyPairError;\n /** Thrown for {@link ZamaErrorCode.RevokedKmsContext}. */\n [ZamaErrorCode.RevokedKmsContext]: RevokedKmsContextError;\n /** Thrown for {@link ZamaErrorCode.NoCiphertext}. */\n [ZamaErrorCode.NoCiphertext]: NoCiphertextError;\n /** Thrown for {@link ZamaErrorCode.RelayerRequestFailed}. */\n [ZamaErrorCode.RelayerRequestFailed]: RelayerRequestFailedError;\n /** Thrown for {@link ZamaErrorCode.NotEntitled}. */\n [ZamaErrorCode.NotEntitled]: NotEntitledError;\n /** Thrown for {@link ZamaErrorCode.RpcRateLimited}. */\n [ZamaErrorCode.RpcRateLimited]: RpcRateLimitError;\n /** Thrown for {@link ZamaErrorCode.Configuration}. */\n [ZamaErrorCode.Configuration]: ConfigurationError;\n /** Thrown for {@link ZamaErrorCode.DelegationSelfNotAllowed}. */\n [ZamaErrorCode.DelegationSelfNotAllowed]: DelegationSelfNotAllowedError;\n /** Thrown for {@link ZamaErrorCode.DelegationCooldown}. */\n [ZamaErrorCode.DelegationCooldown]: DelegationCooldownError;\n /** Thrown for {@link ZamaErrorCode.DelegationNotFound}. */\n [ZamaErrorCode.DelegationNotFound]: DelegationNotFoundError;\n /** Thrown for {@link ZamaErrorCode.DelegationExpired}. */\n [ZamaErrorCode.DelegationExpired]: DelegationExpiredError;\n /** Thrown for {@link ZamaErrorCode.InsufficientConfidentialBalance}. */\n [ZamaErrorCode.InsufficientConfidentialBalance]: InsufficientConfidentialBalanceError;\n /** Thrown for {@link ZamaErrorCode.InsufficientERC20Balance}. */\n [ZamaErrorCode.InsufficientERC20Balance]: InsufficientERC20BalanceError;\n /** Thrown for {@link ZamaErrorCode.InsufficientAllowance}. */\n [ZamaErrorCode.InsufficientAllowance]: InsufficientAllowanceError;\n /** Thrown for {@link ZamaErrorCode.BalanceCheckUnavailable}. */\n [ZamaErrorCode.BalanceCheckUnavailable]: BalanceCheckUnavailableError;\n /** Thrown for {@link ZamaErrorCode.ERC20ReadFailed}. */\n [ZamaErrorCode.ERC20ReadFailed]: ERC20ReadFailedError;\n /** Thrown for {@link ZamaErrorCode.DelegationExpiryUnchanged}. */\n [ZamaErrorCode.DelegationExpiryUnchanged]: DelegationExpiryUnchangedError;\n /** Thrown for {@link ZamaErrorCode.DelegationDelegateEqualsContract}. */\n [ZamaErrorCode.DelegationDelegateEqualsContract]: DelegationDelegateEqualsContractError;\n /** Thrown for {@link ZamaErrorCode.DelegationDelegateCannotBeWildcard}. */\n [ZamaErrorCode.DelegationDelegateCannotBeWildcard]: DelegationDelegateCannotBeWildcardError;\n /** Thrown for {@link ZamaErrorCode.DelegationContractIsSelf}. */\n [ZamaErrorCode.DelegationContractIsSelf]: DelegationContractIsSelfError;\n /** Thrown for {@link ZamaErrorCode.AclPaused}. */\n [ZamaErrorCode.AclPaused]: AclPausedError;\n /** Thrown for {@link ZamaErrorCode.DelegationExpirationTooSoon}. */\n [ZamaErrorCode.DelegationExpirationTooSoon]: DelegationExpirationTooSoonError;\n /** Thrown for {@link ZamaErrorCode.DelegationNotPropagated}. */\n [ZamaErrorCode.DelegationNotPropagated]: DelegationNotPropagatedError;\n /** Thrown for {@link ZamaErrorCode.ChainMismatch}. */\n [ZamaErrorCode.ChainMismatch]: ChainMismatchError;\n /** Thrown for {@link ZamaErrorCode.SignerNotConfigured}. */\n [ZamaErrorCode.SignerNotConfigured]: SignerNotConfiguredError;\n /** Thrown for {@link ZamaErrorCode.WalletNotConnected}. */\n [ZamaErrorCode.WalletNotConnected]: WalletNotConnectedError;\n /** Thrown for {@link ZamaErrorCode.WalletAccountNotReady}. */\n [ZamaErrorCode.WalletAccountNotReady]: WalletAccountNotReadyError;\n /** Thrown for {@link ZamaErrorCode.KeyWrappingFailed}. */\n [ZamaErrorCode.KeyWrappingFailed]: KeyWrappingError;\n /** Thrown for {@link ZamaErrorCode.TransportKeyPairChanged}. */\n [ZamaErrorCode.TransportKeyPairChanged]: TransportKeyPairChangedError;\n /** Thrown for {@link ZamaErrorCode.PreparedPermitChainMismatch}. */\n [ZamaErrorCode.PreparedPermitChainMismatch]: PreparedPermitChainMismatchError;\n /** Thrown for {@link ZamaErrorCode.PreparedPermitExpired}. */\n [ZamaErrorCode.PreparedPermitExpired]: PreparedPermitExpiredError;\n /** Thrown for {@link ZamaErrorCode.UnifiedPermitNotSupported}. */\n [ZamaErrorCode.UnifiedPermitNotSupported]: UnifiedPermitNotSupportedError;\n /** Thrown for {@link ZamaErrorCode.UnifiedDecryptionUnsupported}. */\n [ZamaErrorCode.UnifiedDecryptionUnsupported]: UnifiedDecryptionUnsupportedError;\n /** Thrown for {@link ZamaErrorCode.InvalidationTimestampTooLow}. */\n [ZamaErrorCode.InvalidationTimestampTooLow]: InvalidationTimestampTooLowError;\n /** Thrown for {@link ZamaErrorCode.InvalidationTimestampInFuture}. */\n [ZamaErrorCode.InvalidationTimestampInFuture]: InvalidationTimestampInFutureError;\n /** Thrown for {@link ZamaErrorCode.UnshieldAlreadyFinalized}. */\n [ZamaErrorCode.UnshieldAlreadyFinalized]: UnshieldAlreadyFinalizedError;\n}\n\n/**\n * Pattern-match on a {@link ZamaError} by its error code. Each handler receives the\n * error class for its code, so subclass fields are available without a cast.\n * Falls through to the `_` wildcard handler if no specific handler matches.\n * Returns `undefined` if the error is not a `ZamaError` and no `_` handler is provided.\n *\n * @example\n * ```ts\n * matchZamaError(error, {\n * SIGNING_REJECTED: () => toast(\"Please approve in wallet\"),\n * INSUFFICIENT_CONFIDENTIAL_BALANCE: (e) => toast(`Need ${e.requested}, have ${e.available}`),\n * RELAYER_REQUEST_FAILED: (e) => toast(`Relayer failed (${e.statusCode})`),\n * _: () => toast(\"Unknown error\"),\n * });\n * ```\n */\nexport function matchZamaError<R>(\n error: unknown,\n handlers: { [K in ZamaErrorCode]?: (error: ErrorForCode[K]) => R } & {\n _?: (error: unknown) => R;\n },\n): R | undefined {\n if (error instanceof ZamaError) {\n // `error.code` narrows the handler at runtime; the cast bridges the per-code param types.\n const handler = handlers[error.code] as ((error: ZamaError) => R) | undefined;\n if (handler) {\n return handler(error);\n }\n }\n return handlers._?.(error);\n}\n","import { ZamaError, ZamaErrorCode } from \"./base\";\n\n/**\n * The signer (or delegator) lacks ACL permission to decrypt the encrypted value —\n * `persistAllowed` returned `false`. Terminal and **non-retryable**: the fix is\n * an on-chain grant (`FHE.allow`), or for indexers, to wait for a backfill once\n * the grant lands. Distinct from transient failures like {@link RpcRateLimitError}.\n *\n * @example\n * ```ts\n * try {\n * await sdk.decryption.decryptValues([{ encryptedValue, contractAddress }]);\n * } catch (e) {\n * if (e instanceof NotEntitledError) {\n * // don't retry — wait for an ACL grant / backfill\n * }\n * }\n * ```\n */\nexport class NotEntitledError extends ZamaError {\n /** The encrypted value the actor is not entitled to decrypt. */\n readonly encryptedValue: string;\n /** The contract the encrypted value belongs to. */\n readonly contractAddress: string;\n /** The actor (signer or delegator) that lacks ACL permission. */\n readonly account: string;\n\n constructor(\n args: { encryptedValue: string; contractAddress: string; account: string },\n options?: ErrorOptions,\n ) {\n super(\n ZamaErrorCode.NotEntitled,\n `Account ${args.account} is not entitled to decrypt encrypted value ${args.encryptedValue} ` +\n `on contract ${args.contractAddress}. This is not a transient failure — ` +\n `the account needs an on-chain ACL grant before it can decrypt this encrypted value.`,\n options,\n );\n this.name = \"NotEntitledError\";\n this.encryptedValue = args.encryptedValue;\n this.contractAddress = args.contractAddress;\n this.account = args.account;\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/** Delegate address cannot be the wildcard address — it's only valid as `contractAddress`. */\nexport class DelegationDelegateCannotBeWildcardError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationDelegateCannotBeWildcard, message, options);\n this.name = \"DelegationDelegateCannotBeWildcardError\";\n }\n}\n\n/** Contract address cannot be the sender address. */\nexport class DelegationContractIsSelfError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationContractIsSelf, message, options);\n this.name = \"DelegationContractIsSelfError\";\n }\n}\n\n/** The ACL contract is paused. */\nexport class AclPausedError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.AclPaused, message, options);\n this.name = \"AclPausedError\";\n }\n}\n\n/** Expiration date is too soon (must be at least 1 hour in the future). */\nexport class DelegationExpirationTooSoonError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationExpirationTooSoon, message, options);\n this.name = \"DelegationExpirationTooSoonError\";\n }\n}\n\n/**\n * Delegation exists on L1 but hasn't propagated to the gateway yet.\n *\n * After calling `delegateForUserDecryption()`, the delegation is recorded on-chain\n * immediately. However, the gateway (deployed on Arbitrum) must sync this state\n * via cross-chain event propagation, which usually completes within ~10 blocks\n * (a few seconds).\n *\n * Calling `decryptBalanceAs` during this window will fail because the gateway's\n * `isHandleDelegatedForUserDecryption()` check reads from its own synced copy\n * of the ACL state, which hasn't been updated yet.\n *\n * **You rarely need to handle this directly:** the delegated-decrypt path rides\n * out the propagation window with a bounded internal retry (~30s), so a decrypt\n * issued right after the grant simply waits for sync. This error only surfaces\n * if the window outlasts the retry budget, or when retries are disabled via\n * `waitForPropagation: false`.\n *\n * **Note:** This error is raised as a best-effort heuristic — when a delegated\n * decryption receives an HTTP 500 from the relayer, the most likely cause is a\n * propagation delay. However, the same status code can occur if the gateway or\n * relayer experiences an unrelated internal error.\n */\nexport class DelegationNotPropagatedError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.DelegationNotPropagated, message, options);\n this.name = \"DelegationNotPropagatedError\";\n }\n}\n","/**\n * Extract the decoded custom error name from a viem ContractFunctionRevertedError,\n * or `null` when the error carries no structured revert data.\n * @internal\n */\nexport function 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","import { keccak256, toBytes, type Hex } from \"viem\";\nimport type { EncryptedValue } from \"../relayer/types\";\nimport { ZamaError, ZamaErrorCode } from \"./base\";\nimport { extractRevertErrorName } from \"./revert\";\n\n/** Structured details identifying the consumed unwrap request. */\nexport interface UnshieldAlreadyFinalizedDetails {\n /** Transaction hash of the original unwrap request. */\n readonly unwrapTxHash: Hex;\n /** Request identifier from the `UnwrapRequested` event. */\n readonly unwrapRequestId: EncryptedValue;\n}\n\n/**\n * The unwrap request was already finalized on-chain: the underlying ERC-20\n * tokens were delivered and there is nothing left to resume. The SDK clears\n * the persisted pending-unshield pointer before throwing, so treat this as a\n * success signal: refresh balances and dismiss any \"resume unshield\" prompt.\n */\nexport class UnshieldAlreadyFinalizedError extends ZamaError {\n /** Transaction hash of the original unwrap request. */\n readonly unwrapTxHash: Hex;\n /** Request identifier from the `UnwrapRequested` event. */\n readonly unwrapRequestId: EncryptedValue;\n\n constructor(message: string, details: UnshieldAlreadyFinalizedDetails, options?: ErrorOptions) {\n super(ZamaErrorCode.UnshieldAlreadyFinalized, message, options);\n this.name = \"UnshieldAlreadyFinalizedError\";\n this.unwrapTxHash = details.unwrapTxHash;\n this.unwrapRequestId = details.unwrapRequestId;\n }\n}\n\nconst INVALID_UNWRAP_REQUEST = \"InvalidUnwrapRequest\";\nconst INVALID_UNWRAP_REQUEST_SELECTOR = keccak256(\n toBytes(`${INVALID_UNWRAP_REQUEST}(bytes32)`),\n).slice(0, 10);\n\n/**\n * True if `error` (or anything on its `cause` chain) is the wrapper's\n * `InvalidUnwrapRequest` custom revert. Prefers viem's structured\n * `cause.data.errorName`, falling back to message matching on the error name\n * and the raw 4-byte selector for non-viem providers.\n * @internal\n */\nexport function isInvalidUnwrapRequestRevert(error: unknown): boolean {\n for (let current = error; current instanceof Error; current = current.cause) {\n if (extractRevertErrorName(current) === INVALID_UNWRAP_REQUEST) {\n return true;\n }\n if (\n current.message.includes(INVALID_UNWRAP_REQUEST) ||\n current.message.includes(INVALID_UNWRAP_REQUEST_SELECTOR)\n ) {\n return true;\n }\n }\n return false;\n}\n","import type { ZamaError } from \"./base\";\nimport { DecryptionFailedError } from \"./encryption\";\nimport {\n InvalidTransportKeyPairError,\n NoCiphertextError,\n RevokedKmsContextError,\n UnifiedDecryptionUnsupportedError,\n} from \"./credential\";\nimport { RelayerRequestFailedError } from \"./relayer\";\nimport { DelegationNotPropagatedError } from \"./delegation\";\nimport { NotEntitledError } from \"./entitlement\";\nimport { RpcRateLimitError } from \"./rpc\";\nimport { SigningRejectedError, SigningFailedError } from \"./signing\";\nimport {\n extractHttpStatus,\n extractRetryAfter,\n hasStructuredRpcRateLimitSignal,\n isInvalidTransportKeyPairMessage,\n isNotEntitledMessage,\n isRelayerError,\n isRelayerTimeoutError,\n isRevokedKmsContextError,\n isRpcRateLimitError,\n isUnifiedDecryptionUnsupportedMessage,\n parseHandleFromMessage,\n} from \"../utils/error\";\n\n/**\n * Context the caller supplies so a not-entitled / delegation failure can be\n * mapped precisely. The request context (`contractAddress` / `account`) is not\n * present on the raw error, so it is injected here.\n */\nexport interface DecryptErrorContext {\n isDelegated?: boolean;\n contractAddress?: string;\n /** The ACL actor (signer, or delegator for delegated decrypt). */\n account?: string;\n}\n\n/**\n * Every typed SDK error `wrapDecryptError` may see on its way in (from a prior\n * classification, a worker rethrow, or a caller-level retry) and must pass\n * through unchanged rather than collapse into terminal `DecryptionFailedError`.\n * A single source of truth for the early-return check below and for the\n * `errors.test.ts` \"every typed cause passes through unchanged\" test — so a\n * class dropped from this array is caught by that test instead of silently\n * falling through to the generic fallback.\n *\n * This is a fixed, decrypt-scoped subset of the taxonomy maintained by hand\n * (unlike {@link RETRYABLE_BY_CODE} in `base.ts`, it has no `Complete<>` tie\n * to `ZamaErrorCode`) — a new decrypt-path error class must be added here\n * explicitly, since there's no compiler check forcing it.\n */\nexport const DECRYPT_PASSTHROUGH_ERROR_TYPES = [\n DecryptionFailedError,\n NoCiphertextError,\n RelayerRequestFailedError,\n DelegationNotPropagatedError,\n SigningRejectedError,\n SigningFailedError,\n NotEntitledError,\n RpcRateLimitError,\n InvalidTransportKeyPairError,\n RevokedKmsContextError,\n UnifiedDecryptionUnsupportedError,\n] as const;\n\n/**\n * The single decryption-error classifier. Maps a caught error to the right typed\n * SDK error: not-entitled (ACL), consumer RPC rate-limit, NoCiphertext (400),\n * DelegationNotPropagated (delegated 500 *or* a delegated ACL denial, which is\n * transient), RelayerRequestFailed (other HTTP), or the generic DecryptionFailed\n * fallback.\n *\n * Errors that are already typed SDK errors are returned as-is so callers can\n * still match the original cause. All structured signals (codes, status, cause\n * chain) are read from the error itself.\n */\nexport function wrapDecryptError(\n error: unknown,\n fallbackMessage: string,\n ctx: DecryptErrorContext = {},\n): ZamaError {\n if (DECRYPT_PASSTHROUGH_ERROR_TYPES.some((ErrorType) => error instanceof ErrorType)) {\n return error as ZamaError;\n }\n\n const message = error instanceof Error ? error.message : fallbackMessage;\n\n // Stale transport key pair the relayer can't re-derive (post KMS/TKMS rotation).\n // Typed so the decrypt path can evict the vault entry and regenerate on retry.\n if (error instanceof Error && isInvalidTransportKeyPairMessage(error.message)) {\n return new InvalidTransportKeyPairError(error.message, { cause: error });\n }\n\n // The permit's KMS context was revoked on-chain (InvalidKmsContext revert).\n // Typed so the decrypt path can evict the dead permit, re-grant, and retry once.\n if (isRevokedKmsContextError(error)) {\n return new RevokedKmsContextError(\n \"The permit's KMS context has been revoked on-chain, so the permit is no longer usable. \" +\n \"The SDK evicts the permit and re-grants automatically; if this error surfaced, the retry \" +\n \"failed the same way. The on-chain validity check is cached for up to 15 minutes, so a \" +\n \"just-revoked context can keep failing across that window. Retry after the window; the \" +\n \"SDK re-runs the recovery on the next decrypt, no manual cleanup is needed.\",\n { cause: error },\n );\n }\n\n // A stored V2/wildcard permit's scope is needed for this decrypt, but this\n // relayer instance hasn't deployed /v3/user-decrypt yet — distinct from\n // UnifiedPermitNotSupportedError (signing-time, chain hasn't upgraded).\n if (error instanceof Error && isUnifiedDecryptionUnsupportedMessage(error.message)) {\n return new UnifiedDecryptionUnsupportedError(\n \"This account's stored permit for this scope is a wildcard (V2) permit, but the connected \" +\n \"relayer does not yet support unified decryption (/v3/user-decrypt). Grant a specific-\" +\n \"contract permit instead (sdk.permits.grantPermit([...])), or retry once the relayer upgrades.\",\n { cause: error },\n );\n }\n\n // Actor not entitled (ACL). The relayer throws a message-only Error; the handle\n // is parseable from it and the contract/account come from the request context\n // the caller holds.\n if (error instanceof Error && isNotEntitledMessage(error.message)) {\n // On the delegated path the \"not entitled\" verdict comes from the\n // *delegator's* `persistAllowed` L1 read, which has no staleness tolerance:\n // it returns false *transiently* when the delegation has just landed or the\n // consumer's RPC serves a lagging block. Terminal `NotEntitledError` (\"never\n // retry\") would be the wrong signal for that propagation window, so — mirroring\n // the delegated-500 branch below — surface the retryable\n // `DelegationNotPropagatedError` instead. A direct signer denial (non-\n // delegated) stays terminal `NotEntitledError`.\n if (ctx.isDelegated) {\n return new DelegationNotPropagatedError(\n \"Delegated decryption was denied by the on-chain ACL check. \" +\n \"This is most commonly caused by the delegation not having propagated yet, or by the \" +\n \"RPC node serving a stale block. Propagation usually completes within ~10 blocks (a few \" +\n \"seconds) and the SDK retries across that window; seeing this means it did not sync in time. \" +\n \"Retry shortly (and prefer a fresh, low-lag RPC endpoint). If it persists, the delegator may \" +\n \"genuinely lack the on-chain ACL grant.\",\n { cause: error },\n );\n }\n return new NotEntitledError(\n {\n encryptedValue: parseHandleFromMessage(error.message) ?? \"\",\n contractAddress: ctx.contractAddress ?? \"\",\n account: ctx.account ?? \"\",\n },\n { cause: error },\n );\n }\n\n // Consumer's RPC provider throttling an on-chain read. An unambiguous\n // structured signal (-32005 / viem `status: 429`) wins over any HTTP status;\n // relayer-origin errors are `@fhevm/sdk` `Relayer*` classes and are excluded by\n // `isRelayerError`, staying RelayerRequestFailedError below.\n if (hasStructuredRpcRateLimitSignal(error)) {\n return new RpcRateLimitError(message, { cause: error, retryAfter: extractRetryAfter(error) });\n }\n\n const statusCode = extractHttpStatus(error);\n\n // A message-only throttle (\"Too Many Requests\" / \"rate limit\") is trusted only\n // when no HTTP status is present — otherwise the status classification (e.g. a\n // relayer error whose body mentions a rate limit) takes precedence.\n if (statusCode === undefined && isRpcRateLimitError(error)) {\n return new RpcRateLimitError(message, { cause: error, retryAfter: extractRetryAfter(error) });\n }\n\n if (statusCode === 400) {\n return new NoCiphertextError(\n error instanceof Error ? error.message : \"No ciphertext for this account\",\n { cause: error },\n );\n }\n\n if (ctx.isDelegated && statusCode === 500) {\n return new DelegationNotPropagatedError(\n \"Delegated decryption failed with a server error. \" +\n \"This is most commonly caused by the delegation not having propagated to the gateway yet. \" +\n \"Cross-chain sync usually completes within ~10 blocks (a few seconds) and the SDK retries \" +\n \"across that window; seeing this means it did not sync in time — retry shortly. \" +\n \"If the error persists, the gateway or relayer may be experiencing an unrelated issue.\",\n { cause: error },\n );\n }\n\n if (isRelayerError(error) || statusCode !== undefined) {\n return new RelayerRequestFailedError(message, statusCode, {\n cause: error,\n retryAfter: extractRetryAfter(error),\n // A relayer timeout carries no HTTP status but is safe to retry; force\n // `retryable` so it isn't misclassified as terminal. Other relayer errors\n // fall back to the status-based default (429 → retryable).\n retryable: isRelayerTimeoutError(error) || undefined,\n });\n }\n\n return new DecryptionFailedError(fallbackMessage, { cause: error });\n}\n","import {\n extractHttpStatus,\n extractRetryAfter,\n isRelayerError,\n isRelayerTimeoutError,\n} 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 `@fhevm/sdk` relayer origin or HTTP\n * status code and return the appropriate typed SDK error. Relayer transport\n * failures without a status, plus HTTP failures from the relayer or an\n * intermediary such as Cloudflare/Kong, surface as\n * {@link RelayerRequestFailedError} instead of collapsing into a generic\n * {@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 relayer's HTTP status may surface as `status` or `statusCode` anywhere in\n * the cause chain; {@link extractHttpStatus} walks the chain for either, mirroring\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 // A relayer timeout carries no HTTP status but is safe to retry — surface it as\n // a retryable RelayerRequestFailedError rather than a terminal EncryptionFailed.\n const isTimeout = isRelayerTimeoutError(error);\n\n if (statusCode !== undefined || isRelayerError(error)) {\n return new RelayerRequestFailedError(\n error instanceof Error ? error.message : fallbackMessage,\n statusCode,\n { cause: error, retryAfter: extractRetryAfter(error), retryable: isTimeout || undefined },\n );\n }\n\n return new EncryptionFailedError(fallbackMessage, { cause: error });\n}\n","// DO NOT EDIT: generated by `pnpm abi:build` from\n// contracts/out/IERC1363.sol/IERC1363.json.\n// Regenerate after `pnpm contracts:build`; `pnpm abi:check` enforces this in CI.\nexport const erc1363Abi = [\n {\n type: \"function\",\n name: \"allowance\",\n inputs: [\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"approve\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"approveAndCall\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"approveAndCall\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"balanceOf\",\n inputs: [{ name: \"account\", type: \"address\", internalType: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"supportsInterface\",\n inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"totalSupply\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"transfer\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferAndCall\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferAndCall\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFrom\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFromAndCall\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFromAndCall\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"event\",\n name: \"Approval\",\n inputs: [\n { name: \"owner\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"spender\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n ],\n anonymous: false,\n },\n {\n type: \"event\",\n name: \"Transfer\",\n inputs: [\n { name: \"from\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"to\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n ],\n anonymous: false,\n },\n] as const;\n","import type { Address, Hex } from \"viem\";\nimport { erc1363Abi } from \"../abi/erc1363.abi\";\n\n/**\n * Returns the contract config for an ERC-1363 `transferAndCall`.\n *\n * @param tokenAddress - The ERC-20 token to transfer from (the underlying, not the wrapper).\n * @param to - The recipient of the ERC-20 transfer. In `Token.shield`, this is\n * the wrapper contract whose `onTransferReceived` callback mints\n * confidential tokens to the address encoded in `data`.\n * @param amount - The amount to transfer.\n * @param data - Raw 20-byte recipient address for shield-to-other (decoded by\n * the wrapper as `address(bytes20(data))`). Empty `0x` for self-shield —\n * the wrapper falls back to `from`.\n */\nexport function transferAndCallContract(\n tokenAddress: Address,\n to: Address,\n amount: bigint,\n data: Hex = \"0x\",\n) {\n return {\n address: tokenAddress,\n abi: erc1363Abi,\n functionName: \"transferAndCall\",\n args: [to, amount, data],\n } as const;\n}\n","// DO NOT EDIT: generated by `pnpm abi:build` from\n// contracts/out/IACLExtended.sol/IACLExtended.json.\n// Regenerate after `pnpm contracts:build`; `pnpm abi:check` enforces this in CI.\nexport const aclAbi = [\n {\n type: \"function\",\n name: \"allow\",\n inputs: [\n { name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"account\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"allowForDecryption\",\n inputs: [{ name: \"handlesList\", type: \"bytes32[]\", internalType: \"bytes32[]\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"allowTransient\",\n inputs: [\n { name: \"ciphertext\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"account\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"cleanTransientStorage\",\n inputs: [],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"delegateForUserDecryption\",\n inputs: [\n { name: \"delegate\", type: \"address\", internalType: \"address\" },\n { name: \"contractAddress\", type: \"address\", internalType: \"address\" },\n { name: \"expirationDate\", type: \"uint64\", internalType: \"uint64\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"getUserDecryptionDelegationExpirationDate\",\n inputs: [\n { name: \"delegator\", type: \"address\", internalType: \"address\" },\n { name: \"delegate\", type: \"address\", internalType: \"address\" },\n { name: \"contractAddress\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint64\", internalType: \"uint64\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"invalidateDecryptionSignaturesBefore\",\n inputs: [{ name: \"timestamp\", type: \"uint256\", internalType: \"uint256\" }],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"isAccountDenied\",\n inputs: [{ name: \"account\", type: \"address\", internalType: \"address\" }],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"isAllowed\",\n inputs: [\n { name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"account\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"isAllowedForDecryption\",\n inputs: [{ name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" }],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"isHandleDelegatedForUserDecryption\",\n inputs: [\n { name: \"delegator\", type: \"address\", internalType: \"address\" },\n { name: \"delegate\", type: \"address\", internalType: \"address\" },\n { name: \"contractAddress\", type: \"address\", internalType: \"address\" },\n { name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"multicall\",\n inputs: [{ name: \"data\", type: \"bytes[]\", internalType: \"bytes[]\" }],\n outputs: [{ name: \"results\", type: \"bytes[]\", internalType: \"bytes[]\" }],\n stateMutability: \"payable\",\n },\n {\n type: \"function\",\n name: \"persistAllowed\",\n inputs: [\n { name: \"handle\", type: \"bytes32\", internalType: \"bytes32\" },\n { name: \"account\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"revokeDelegationForUserDecryption\",\n inputs: [\n { name: \"delegate\", type: \"address\", internalType: \"address\" },\n { name: \"contractAddress\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [],\n stateMutability: \"nonpayable\",\n },\n] as const;\n","import type { Address } from \"viem\";\nimport { aclAbi } from \"../abi/acl.abi\";\n\n/**\n * Returns the contract config to delegate user decryption rights.\n *\n * @example\n * ```ts\n * const txHash = await signer.writeContract(\n * delegateForUserDecryptionContract(aclAddress, delegateAddress, contractAddress, expirationDate),\n * );\n * ```\n */\nexport function delegateForUserDecryptionContract(\n aclAddress: Address,\n delegateAddress: Address,\n contractAddress: Address,\n expirationDate: bigint,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"delegateForUserDecryption\",\n args: [delegateAddress, contractAddress, expirationDate],\n } as const;\n}\n\n/**\n * Returns the contract config to revoke a user decryption delegation.\n *\n * @example\n * ```ts\n * const txHash = await signer.writeContract(\n * revokeDelegationContract(aclAddress, delegateAddress, contractAddress),\n * );\n * ```\n */\nexport function revokeDelegationContract(\n aclAddress: Address,\n delegateAddress: Address,\n contractAddress: Address,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"revokeDelegationForUserDecryption\",\n args: [delegateAddress, contractAddress],\n } as const;\n}\n\n/**\n * Returns the contract config to invalidate every decryption signature signed\n * by `msg.sender` before `timestamp` (`0n` resolves to now on-chain).\n *\n * @example\n * ```ts\n * const txHash = await signer.writeContract(\n * invalidateDecryptionSignaturesBeforeContract(aclAddress, 0n),\n * );\n * ```\n */\nexport function invalidateDecryptionSignaturesBeforeContract(\n aclAddress: Address,\n timestamp: bigint,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"invalidateDecryptionSignaturesBefore\",\n args: [timestamp],\n } as const;\n}\n\n/**\n * Returns the contract config to read the delegation expiry date.\n *\n * @example\n * ```ts\n * const expiry = await provider.readContract(\n * getDelegationExpiryContract(aclAddress, delegatorAddress, delegateAddress, contractAddress),\n * );\n * ```\n */\nexport function getDelegationExpiryContract(\n aclAddress: Address,\n delegatorAddress: Address,\n delegateAddress: Address,\n contractAddress: Address,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"getUserDecryptionDelegationExpirationDate\",\n args: [delegatorAddress, delegateAddress, contractAddress],\n } as const;\n}\n\n/**\n * Returns the contract config to check if a specific handle is delegated.\n *\n * @example\n * ```ts\n * const isDelegated = await provider.readContract(\n * isHandleDelegatedContract(aclAddress, delegatorAddress, delegateAddress, contractAddress, handle),\n * );\n * ```\n */\nexport function isHandleDelegatedContract(\n aclAddress: Address,\n delegatorAddress: Address,\n delegateAddress: Address,\n contractAddress: Address,\n handle: `0x${string}`,\n) {\n return {\n address: aclAddress,\n abi: aclAbi,\n functionName: \"isHandleDelegatedForUserDecryption\",\n args: [delegatorAddress, delegateAddress, contractAddress, handle],\n } as const;\n}\n","/** uint64 max — represents a permanent (no-expiry) delegation. */\nexport const MAX_UINT64 = 2n ** 64n - 1n;\n\n// Duplicated rather than imported: @fhevm/sdk computes the same value\n// internally but doesn't export it from any public entry point.\n/**\n * `contractAddress` covering every confidential contract with a single\n * delegation.\n */\nexport const WILDCARD_CONTRACT = \"0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF\" as const;\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 { 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","/**\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/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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 /** Event name discriminant. */\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 { getAddress, type Address, type Hex } from \"viem\";\nimport type { CredentialService } from \"../credentials/credential-service\";\nimport type { PreparedPermit } from \"../credentials/types\";\nimport type { WildcardPermit } from \"../credentials/utils\";\nimport { requireConfigured } from \"../errors\";\nimport type { PermitOperation, ZamaSDKEventInput } from \"../events/sdk-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport { checksum } from \"../schemas/primitives\";\nimport type { CachingService } from \"../services/caching-service\";\nimport type { DelegationService } from \"../services/delegation-service\";\nimport type { GenericLogger, GenericProvider, GenericSigner, TransactionResult } from \"../types\";\nimport { swallow } from \"../utils\";\nimport { requireAlignedWalletAccount, requireChainAlignment } from \"../utils/alignment\";\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 *\n * When `transportKeyPairScope` is configured (opt-in shared-tenant scope for B2B2C/WaaS\n * operators), {@link clear} and {@link revokePermits} stay signer-level only — they never\n * touch the shared key pair. {@link revokeTransportKeyPair} is the distinct,\n * operator-level operation for that.\n */\nexport class Permits {\n readonly #signer: GenericSigner | undefined;\n readonly #provider: GenericProvider;\n readonly #cachingService: CachingService;\n readonly #credentialService: CredentialService | undefined;\n readonly #delegationService: DelegationService;\n readonly #logger: GenericLogger;\n readonly #emitEvent: (input: ZamaSDKEventInput) => void;\n\n /** @internal */\n constructor(opts: {\n signer: GenericSigner | undefined;\n provider: GenericProvider;\n cachingService: CachingService;\n credentialService: CredentialService | undefined;\n delegationService: DelegationService;\n logger: GenericLogger;\n emitEvent: (input: ZamaSDKEventInput) => void;\n }) {\n this.#signer = opts.signer;\n this.#provider = opts.provider;\n this.#cachingService = opts.cachingService;\n this.#credentialService = opts.credentialService;\n this.#delegationService = opts.delegationService;\n this.#logger = opts.logger;\n this.#emitEvent = opts.emitEvent;\n }\n\n #requireSigner(operation: string): GenericSigner {\n return requireConfigured(this.#signer, operation);\n }\n\n #requireCredentialService(operation: string): CredentialService {\n return requireConfigured(this.#credentialService, operation);\n }\n\n /**\n * Emit a {@link ZamaSDKEvents.PermitError} event for a pre-flight guard\n * failure (no signer/CredentialService configured, chain mismatch) and\n * rethrow the same error unchanged. These guards run in this namespace\n * layer, before {@link CredentialService} (and its own equivalent choke\n * point) is ever reached, so without this they'd be invisible to `onEvent`\n * regardless of what CredentialService itself emits.\n *\n * Only for the pre-flight guards below — never wrap a delegated\n * `CredentialService` call in this, since that call already emits\n * internally on failure; doing it here too would double-emit.\n */\n #failPermit(operation: PermitOperation, error: unknown): never {\n this.#emitEvent({\n type: ZamaSDKEvents.PermitError,\n operation,\n error: error instanceof Error ? error : new Error(String(error)),\n });\n throw error;\n }\n\n /**\n * Sign and store an EIP-712 permit authorizing 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 * Pass {@link WILDCARD_PERMIT} instead of an address list to request a V2\n * permissive permit covering every contract, present and future — an\n * explicit opt-in, not something a large address list implies. A stolen\n * wildcard permit decrypts anything the signer owns until it expires, so\n * prefer a specific contract list unless the caller genuinely needs\n * unbounded coverage.\n *\n * @param contracts - Contract addresses to authorize, or {@link WILDCARD_PERMIT}.\n * @throws if `transportKeyPairDerivationSecret` is configured and the keypair fails to wrap or\n * unwrap. {@link KeyWrappingError}\n */\n async grantPermit(contracts: Address[] | WildcardPermit): Promise<void> {\n if (Array.isArray(contracts) && contracts.length === 0) {\n return;\n }\n let service: CredentialService;\n try {\n service = this.#requireCredentialService(\"grantPermit\");\n await requireChainAlignment(\"grantPermit\", this.#signer, this.#provider);\n } catch (error) {\n this.#failPermit(\"grantPermit\", error);\n }\n await service.grantPermit(contracts);\n }\n\n /**\n * Sign and store an EIP-712 delegation permit authorizing decryption on\n * behalf of `delegator`. Same idempotence/chunking/wildcard semantics as\n * {@link grantPermit}.\n *\n * @param delegator - The address that delegated decryption rights to the connected signer.\n * @param contracts - Contract addresses to authorize, or {@link WILDCARD_PERMIT}.\n * @throws if `transportKeyPairDerivationSecret` is configured and the keypair fails to wrap or\n * unwrap. {@link KeyWrappingError}\n */\n async grantDelegationPermit(\n delegator: Address,\n contracts: Address[] | WildcardPermit,\n ): Promise<void> {\n if (Array.isArray(contracts) && contracts.length === 0) {\n return;\n }\n let service: CredentialService;\n try {\n service = this.#requireCredentialService(\"grantDelegationPermit\");\n await requireChainAlignment(\"grantDelegationPermit\", this.#signer, this.#provider);\n } catch (error) {\n this.#failPermit(\"grantDelegationPermit\", error);\n }\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, or when `transportKeyPairDerivationSecret` is configured and the stored keypair\n * fails to unwrap. Does not swallow other errors (e.g. a failing storage backend), which\n * propagate normally.\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. Never throws when the stored keypair\n * fails to unwrap, reporting no permit instead; other errors still propagate.\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 * Not for pre-warming a shared `transportKeyPairScope`: this call's wallet-account\n * precondition doesn't conceptually apply to a scope-wide key, and would silently\n * no-op precisely when an operator is most likely to be calling it (no end-user\n * connected yet). Use {@link warmTransportKeyPairScope} instead.\n *\n * @throws if `transportKeyPairDerivationSecret` is configured and the keypair fails to wrap or\n * unwrap. {@link KeyWrappingError}\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 * Offline permit flow, phase 2: verify and persist the signature an\n * out-of-process signer produced for a `sdk.offline.preparePermit` payload.\n *\n * No wallet account required: the permit is scoped by `prepared.signerAddress`\n * (and `prepared.delegatorAddress`, if present), not a connected signer.\n *\n * @param prepared - The payload `sdk.offline.preparePermit` returned.\n * @param signature - The `eth_signTypedData_v4` signature over `prepared.eip712`.\n * V2 permits also accept a variable-length ERC-1271 (smart-wallet) blob.\n * @throws if `prepared` doesn't match the `PreparedPermit` shape (e.g. it crossed a\n * process boundary and was corrupted). {@link ConfigurationError}\n * @throws if the chain embedded in `prepared.eip712` doesn't match the active chain. {@link PreparedPermitChainMismatchError}\n * @throws if the permit's validity window has already elapsed. {@link PreparedPermitExpiredError}\n * @throws if the transport key pair changed since prepare. {@link TransportKeyPairChangedError}\n * @throws if the signature is invalid or malformed. {@link SigningFailedError}\n */\n async registerPermit(prepared: PreparedPermit, signature: Hex): Promise<void> {\n let service: CredentialService;\n try {\n service = this.#requireCredentialService(\"registerPermit\");\n } catch (error) {\n this.#failPermit(\"registerPermit\", error);\n }\n await service.registerPermit(prepared, signature);\n await this.#clearDecryptCacheForRequester(prepared.signerAddress);\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 this.#clearDecryptCacheForRequester(signerAddress);\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 this.#clearDecryptCacheForRequester(signerAddress);\n }\n }\n\n async #clearDecryptCacheForRequester(signerAddress: Address): Promise<void> {\n await swallow(\n \"clear decrypt cache\",\n () => this.#cachingService.clearForRequester(signerAddress),\n this.#logger,\n );\n }\n\n /**\n * Revoke the shared transport key pair for `transportKeyPairScope`. Storage-only,\n * operator-level action: no wallet account or signer needs to be connected.\n *\n * Deletes the shared key pair; every permit in the scope embeds its public key, so\n * they're all treated as stale on next access. Signer-level {@link clear} never does\n * this — it only ever wipes the calling signer's own permits.\n *\n * Not best-effort, unlike most credential-store writes: a storage failure rejects\n * instead of being logged and swallowed. This is the primitive an operator reaches\n * for on suspected key compromise — a resolved promise must mean the key pair is\n * actually gone.\n *\n * Stops the SDK from reissuing or reusing the deleted key — does not revoke any\n * permit already issued under it. A permit is a self-contained, bearer-style EIP-712\n * signature the relayer accepts independently of this SDK; one exfiltrated alongside\n * the key remains usable until its own `permitTTL` expiry regardless of this call.\n *\n * @param scopeId - Must match the configured `transportKeyPairScope`, as a guard\n * against revoking the wrong scope by mistake.\n * @throws if no scope is configured, or `scopeId` doesn't match it. {@link ConfigurationError}\n * @throws if the underlying storage delete fails.\n */\n async revokeTransportKeyPair(scopeId: string): Promise<void> {\n const service = this.#requireCredentialService(\"revokeTransportKeyPair\");\n await service.revokeTransportKeyPair(scopeId);\n }\n\n /**\n * Warm the shared transport key pair for `transportKeyPairScope` — the pre-warm\n * counterpart to {@link revokeTransportKeyPair}. Storage-only, operator-level action:\n * no wallet account or signer needs to be connected. Prefer this over\n * {@link warmTransportKeyPair} for a scoped key pair: unlike that method, this never\n * silently no-ops for lack of a connected wallet, because a scope-wide key was never\n * tied to one in the first place.\n *\n * @param scopeId - Must match the configured `transportKeyPairScope`, as a guard\n * against warming the wrong scope by mistake.\n * @throws if no scope is configured, or `scopeId` doesn't match it. {@link ConfigurationError}\n * @throws if `transportKeyPairDerivationSecret` is configured and the keypair fails to wrap or\n * unwrap. {@link KeyWrappingError}\n */\n async warmTransportKeyPairScope(scopeId: string): Promise<void> {\n const service = this.#requireCredentialService(\"warmTransportKeyPairScope\");\n await service.warmTransportKeyPairScope(scopeId);\n }\n\n /**\n * Invalidate every decryption signature signed before `timestamp`, via\n * `ACL.invalidateDecryptionSignaturesBefore`. The KMS Connector rejects\n * any decryption request whose permit predates the new cutoff — the\n * recourse when a permissive/wildcard permit or its signing key is\n * compromised, or on a multisig (ERC-1271/Safe) owner rotation. Call this\n * on every multisig signer rotation and on suspected signing-key compromise.\n *\n * On success, this signer's locally-stored permits for the current chain\n * are cleared automatically — they would now only fail against the KMS\n * Connector.\n *\n * @param timestamp - Oldest timestamp that remains valid. Omit to invalidate\n * everything up to now.\n * @throws if no signer is configured. {@link SignerNotConfiguredError}\n * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n * @throws if `timestamp` is not strictly later than the account's current\n * cutoff. {@link InvalidationTimestampTooLowError}\n * @throws if `timestamp` is in the future. {@link InvalidationTimestampInFutureError}\n * @throws if the invalidation transaction reverts for any other reason. {@link TransactionRevertedError}\n */\n async invalidateDecryptionSignatures(timestamp?: Date): Promise<TransactionResult> {\n const service = this.#requireCredentialService(\"invalidateDecryptionSignatures\");\n const signer = this.#requireSigner(\"invalidateDecryptionSignatures\");\n const account = await requireAlignedWalletAccount(\n \"invalidateDecryptionSignatures\",\n this.#signer,\n this.#provider,\n );\n const signerAddress = checksum(account.address);\n const result = await this.#delegationService.invalidateDecryptionSignaturesBefore(\n signer,\n timestamp,\n );\n // Only after the write lands: local permits stay usable if it reverted.\n await service.clearPermitsAfterInvalidation(signerAddress);\n await this.#clearDecryptCacheForRequester(getAddress(account.address));\n return result;\n }\n}\n","import type { Address } from \"viem\";\nimport type { DelegationService, DelegationStatus } from \"../services/delegation-service\";\nimport type { GenericProvider, GenericSigner, TransactionResult } from \"../types\";\nimport { requireAlignedWalletAccount } from \"../utils/alignment\";\nimport { requireConfigured } from \"../errors\";\n\n/**\n * Public namespace for on-chain decryption-delegation management.\n *\n * Exposed as `sdk.delegations`. Owns the SDK-level guards (signer requirement, chain\n * alignment, delegator address resolution from the wallet account) and delegates the\n * actual work to the internal {@link DelegationService}.\n *\n * Delegation operations write to the host chain ACL; after a delegation is mined,\n * the gateway syncs the ACL state via cross-chain event propagation — usually\n * within ~10 blocks (a few seconds). Delegated decryption rides out that window\n * with a bounded internal retry, so callers can decrypt right after granting.\n */\nexport class Delegations {\n readonly #signer: GenericSigner | undefined;\n readonly #provider: GenericProvider;\n readonly #delegationService: DelegationService;\n\n /** @internal */\n constructor(opts: {\n signer: GenericSigner | undefined;\n provider: GenericProvider;\n delegationService: DelegationService;\n }) {\n this.#signer = opts.signer;\n this.#provider = opts.provider;\n this.#delegationService = opts.delegationService;\n }\n\n #requireSigner(operation: string): GenericSigner {\n return requireConfigured(this.#signer, operation);\n }\n\n /**\n * Delegate decryption rights for a confidential contract to another address.\n * Calls `ACL.delegateForUserDecryption()` on-chain.\n *\n * The delegation is recorded on L1 immediately, but the gateway must sync the\n * ACL state via cross-chain event propagation — usually within ~10 blocks (a\n * few seconds). You do not need to wait: delegated decryption rides out that\n * window with a bounded internal retry, so you can decrypt right after this\n * resolves.\n *\n * @param contractAddress - The confidential contract address to delegate on, or\n * {@link WILDCARD_CONTRACT} to cover every contract with a single delegation.\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 is the wildcard address. {@link DelegationDelegateCannotBeWildcardError}\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 /**\n * Get activity and expiry together in a single on-chain read, instead of\n * calling {@link isActive} and {@link getExpiry} separately.\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 `{ isActive, expiryTimestamp }` — activity and the raw expiry timestamp together.\n */\n async getStatus(params: {\n contractAddress: Address;\n delegatorAddress: Address;\n delegateAddress: Address;\n }): Promise<DelegationStatus> {\n return this.#delegationService.getStatus(params);\n }\n}\n","import type { Address } from \"viem\";\nimport { requireConfigured, wrapDecryptError } from \"../errors\";\nimport type { EncryptedInput } from \"../query/user-decrypt\";\nimport type { ChainRouter } from \"../chains/router\";\nimport type {\n ClearValue,\n DecryptPublicValuesResult,\n EncryptedValue,\n FhevmRelayerOptions,\n} from \"../relayer/types\";\nimport type {\n BatchDecryptResult,\n DecryptionService,\n DelegatedDecryptOptions,\n} from \"../services/decryption-service\";\nimport type { GenericProvider, GenericSigner } from \"../types\";\nimport { requireAlignedWalletAccount } from \"../utils/alignment\";\nimport { assertNonNullable } from \"../utils\";\n\n/**\n * Public namespace for FHE decryption — the canonical way to decrypt.\n *\n * Exposed as `sdk.decryption`. Prefer these methods over the low-level\n * `sdk.relayer.decryptValues` / `decryptPublicValues`: they\n * assemble the credential bundle (transport key pair, EIP-712 permit) for you,\n * cache results, and wrap relayer errors. Reach for `sdk.relayer.*` only when\n * you must control credential assembly by hand.\n *\n * Owns the SDK-level guards (signer requirement on\n * `decryptValues` and `delegatedDecryptValues`, empty-array\n * short-circuit on `decryptPublicValues`, relayer error wrapping) and delegates the\n * actual work to the internal {@link DecryptionService} or the relayer directly for\n * `decryptPublicValues`.\n *\n * **Mixed signer requirement:** `decryptValues` and\n * `delegatedDecryptValues` need a configured signer; `decryptPublicValues`\n * does not. Each method documents its requirement in its JSDoc.\n *\n * **Request chunking:** decrypt requests are split internally to stay under\n * the relayer's 2048-cleartext-bit per-request budget — callers never need to\n * size batches themselves.\n */\nexport class Decryption {\n readonly #signer: GenericSigner | undefined;\n readonly #provider: GenericProvider;\n readonly #router: ChainRouter;\n readonly #decryptionService: DecryptionService | undefined;\n\n /** @internal */\n constructor(opts: {\n signer: GenericSigner | undefined;\n provider: GenericProvider;\n router: ChainRouter;\n decryptionService: DecryptionService | undefined;\n }) {\n this.#signer = opts.signer;\n this.#provider = opts.provider;\n this.#router = opts.router;\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 * @param options - Per-call `signal` and `timeout` forwarded to the relayer round-trip.\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 options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\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.decryptValues(encryptedInput, account.address, options);\n }\n\n /**\n * Decrypt one or more FHE encrypted values using delegated credentials.\n *\n * Mirrors {@link decryptValues} with delegated credentials — same caching and\n * zero-value short-circuit. Before reading from cache or calling the relayer,\n * every non-zero encrypted value's contract must have an active delegation from the\n * delegator to the connected signer; missing or expired delegations fail fast.\n *\n * @param encryptedInputs - FHE encrypted values paired with their contract addresses.\n * @param delegatorAddress - The address that granted delegation rights.\n * @param accountAddress - Address used as the cache key's \"requester\"\n * dimension. Defaults to `delegatorAddress`. Pass the actual account address\n * when decrypting on behalf of someone whose balance is stored under a\n * different address (e.g. `decryptBalanceAs` with an explicit `accountAddress`).\n * @param options - Delegated-decrypt options. By default the call rides out the\n * gateway propagation window ({@link DelegatedDecryptOptions.waitForPropagation});\n * pass `{ waitForPropagation: false }` to fail fast instead.\n * @returns Map of encrypted value → clear-text value.\n *\n * @example\n * ```ts\n * const values = await sdk.decryption.delegatedDecryptValues([\n * { encryptedValue: balance, contractAddress: tokenAddr },\n * ], delegatorAddr);\n * console.log(values[balance]); // 1000n\n * ```\n */\n async delegatedDecryptValues(\n encryptedInputs: EncryptedInput[],\n delegatorAddress: Address,\n accountAddress: Address = delegatorAddress,\n options?: DelegatedDecryptOptions,\n ): Promise<Record<EncryptedValue, ClearValue>> {\n const service = this.#requireDecryptionService(\"delegatedDecryptValues\");\n const account = await requireAlignedWalletAccount(\n \"delegatedDecryptValues\",\n this.#signer,\n this.#provider,\n );\n return service.delegatedDecryptValues(\n encryptedInputs,\n delegatorAddress,\n account.address,\n accountAddress,\n options,\n );\n }\n\n /**\n * Publicly decrypt one or more FHE encrypted values.\n *\n * Signer-independent: works without a configured signer.\n * Returns the decryption proof alongside the clear-text values so callers\n * can submit on-chain finalization transactions (e.g. `finalizeUnwrap`).\n *\n * @param encryptedValues - FHE encrypted values to decrypt publicly.\n * @param options - Per-call `signal` and `timeout` forwarded to the relayer round-trip.\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(\n encryptedValues: EncryptedValue[],\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<DecryptPublicValuesResult> {\n if (encryptedValues.length === 0) {\n return { clearValues: {}, decryptionProof: \"0x\", abiEncodedClearValues: \"0x\" };\n }\n\n try {\n const result = await this.#router.relayer.decryptPublicValuesWithSignatures({\n encryptedValues,\n options,\n });\n const clearValues: Record<EncryptedValue, ClearValue> = {};\n result.checkSignaturesArgs.handlesList.forEach((handle, i) => {\n assertNonNullable(result.clearValues[i], `result.clearValues[${i}]`);\n clearValues[handle] = result.clearValues[i].value;\n });\n return {\n clearValues,\n abiEncodedClearValues: result.checkSignaturesArgs.abiEncodedCleartexts,\n decryptionProof: result.checkSignaturesArgs.decryptionProof,\n };\n } catch (error) {\n throw wrapDecryptError(error, \"Public decryption failed\");\n }\n }\n\n /**\n * Batch-decrypt delegated encrypted values with per-entry error isolation.\n *\n * Attempts a single batch request first. If the batch fails with a non-fatal\n * error (e.g. one entry is invalid), falls back to per-entry decryption so\n * healthy entries still resolve. Each item in the result carries either a\n * decrypted value or an error — callers decide how to surface partial failures.\n *\n * @param encryptedInputs - FHE encrypted values paired with their contract addresses.\n * @param delegatorAddress - The address that granted delegation rights.\n * @param accountAddress - The account on whose behalf decryption is performed. Defaults to `delegatorAddress`.\n * @param maxConcurrency - Maximum parallel decrypt calls during per-entry fallback.\n * @param waitForPropagation - Ride out the gateway propagation window on the\n * initial batch attempt (default `true`). See {@link DelegatedDecryptOptions.waitForPropagation}.\n * @returns Per-entry results, each with a value or an error.\n * @throws if no signer is configured. {@link SignerNotConfiguredError}\n * @throws if signer and provider are on different chains. {@link ChainMismatchError}\n * @throws A failure that affects the whole session (rejected signature, RPC\n * rate limit, revoked KMS context) rejects the call instead of landing in a\n * per-entry error.\n *\n * @example\n * ```ts\n * const result = await sdk.decryption.delegatedBatchDecryptValues({\n * encryptedInputs: [\n * { encryptedValue: encryptedValue1, contractAddress: tokenA },\n * { encryptedValue: encryptedValue2, contractAddress: tokenB },\n * ],\n * delegatorAddress: \"0xDelegator\",\n * maxConcurrency: 5,\n * });\n * for (const item of result.items) {\n * if (item.error) console.error(item.encryptedValue, item.error);\n * else console.log(item.encryptedValue, item.value);\n * }\n * ```\n */\n async delegatedBatchDecryptValues({\n encryptedInputs,\n delegatorAddress,\n accountAddress = delegatorAddress,\n maxConcurrency,\n waitForPropagation,\n }: {\n encryptedInputs: EncryptedInput[];\n delegatorAddress: Address;\n accountAddress?: Address;\n maxConcurrency?: number;\n } & DelegatedDecryptOptions): Promise<BatchDecryptResult> {\n const service = this.#requireDecryptionService(\"delegatedBatchDecryptValues\");\n const account = await requireAlignedWalletAccount(\n \"delegatedBatchDecryptValues\",\n this.#signer,\n this.#provider,\n );\n return service.delegatedBatchDecryptHandlesAs({\n encryptedInputs,\n delegatorAddress,\n delegateAddress: account.address,\n accountAddress,\n maxConcurrency,\n waitForPropagation,\n });\n }\n}\n","import type { CredentialService } from \"../credentials/credential-service\";\nimport type { PreparedPermit, PreparePermitRequest } from \"../credentials/types\";\nimport type { OfflineService } from \"../services/offline-service\";\nimport type {\n PreparedFor,\n PrepareOptions,\n PrepareTransactionRequest,\n TransactionKind,\n} from \"../types\";\n\n/**\n * Namespace for the offline-signing pipeline —\n * `prepare → [external sign + self-publish]` — for institutional custody, HSM\n * ceremonies, and policy-engine workflows where signing runs out-of-process and\n * cannot happen synchronously in a single Promise.\n */\nexport class Offline {\n readonly #offlineService: OfflineService;\n readonly #credentialService: CredentialService;\n\n /** @internal */\n constructor(offlineService: OfflineService, credentialService: CredentialService) {\n this.#offlineService = offlineService;\n this.#credentialService = credentialService;\n }\n\n /**\n * Build an RLP-encoded unsigned transaction for the given request. The\n * caller signs it externally — via an HSM ceremony, an out-of-process\n * custodian, or any signer holding the key — and broadcasts the signed bytes\n * through its own channel.\n *\n * Signer-optional: works without a configured signer (canonical shape for\n * cross-process custody — the back-end signer service consumes\n * `prepared.unsignedTx` and returns signed bytes).\n *\n * @remarks\n * `request.from` is only a declaration — the SDK does not prove the caller\n * controls it, and an EIP-1559 unsigned tx carries no `from` field at all\n * (the on-chain sender is whichever key signs the bytes). Point `from` at\n * the account the custodian will sign with; custodians enforce key-control\n * at sign time — a signing request for a key the credential can't use fails\n * there — so a mismatched `from` cannot make the custodian sign from an\n * account you don't control. Verifying control of `from` up front is still\n * the application's responsibility.\n */\n prepare<K extends TransactionKind>(\n request: Extract<PrepareTransactionRequest, { kind: K }>,\n options?: PrepareOptions,\n ): Promise<PreparedFor<K>> {\n return this.#offlineService.prepare(request, options);\n }\n\n /**\n * Build the offline-signing payload for a decryption permit: the unsigned\n * EIP-712 typed data plus everything `sdk.permits.registerPermit` needs to\n * verify and persist the signature an out-of-process signer returns for it.\n *\n * Not a `prepare()` transaction kind: a permit is not a transaction —\n * nothing is broadcast, and registering the signature is a local operation,\n * not a relayer round-trip.\n *\n * Signer-optional, like {@link prepare}: `request.signer` is an explicit\n * address, not a connected wallet account. Building the typed data still\n * reads the chain's KMS signers context on-chain — signer-offline, not\n * network-offline.\n *\n * One permit per call: unlike `sdk.permits.grantPermit`, this never widens\n * an existing permit or chunks over 10 contracts — `request.contracts` maps\n * to exactly one signature.\n *\n * @throws if `request.contracts` is empty or exceeds 10 addresses, `request.delegator`\n * equals `request.signer`, or `request.durationDays` exceeds the V1 permit maximum\n * of 365 days. {@link ConfigurationError}\n * @throws if a concurrent `permits.revokeTransportKeyPair()` rotates the transport key\n * pair while this call is generating one. {@link TransportKeyPairChangedError}\n */\n preparePermit(request: PreparePermitRequest): Promise<PreparedPermit> {\n return this.#credentialService.preparePermit(request);\n }\n}\n","import type { GenericStorage } from \"../types\";\n\n/** Minimal chrome.storage.session typings (avoids depending on @types/chrome). */\ndeclare const chrome: {\n storage: {\n session: {\n get(key: string): Promise<Record<string, unknown>>;\n set(items: Record<string, unknown>): Promise<void>;\n remove(key: string): Promise<void>;\n };\n };\n};\n\n/**\n * {@link GenericStorage} backed by `chrome.storage.session`.\n *\n * Use this in MV3 web extensions so the wallet signature survives\n * service worker restarts and is shared across popup, background,\n * and content script contexts.\n *\n * @example\n * ```ts\n * import { ZamaSDK, indexedDBStorage, chromeSessionStorage } from \"@zama-fhe/sdk\";\n * import { createConfig } from \"@zama-fhe/sdk/viem\";\n *\n * const config = createConfig({\n * chains: [mySepolia],\n * publicClient,\n * walletClient,\n * relayers: { [mySepolia.id]: web() },\n * storage: indexedDBStorage, // encrypted transport key pair — persistent\n * permitStorage: chromeSessionStorage, // signed permits — ephemeral\n * });\n * const sdk = new ZamaSDK(config);\n * ```\n */\nexport class ChromeSessionStorage implements GenericStorage {\n /**\n * Retrieve a value by key.\n * @returns The stored value, or `null` if the key does not exist.\n */\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 /** Store a value under the given key, overwriting any existing entry. */\n async set(key: string, value: unknown): Promise<void> {\n await chrome.storage.session.set({ [key]: value });\n }\n\n /** Remove the entry for the given key (no-op if absent). */\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","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/types\";\n\nconst STORAGE_PREFIX = \"zama:pending-unshield:\";\nconst CURRENT_VERSION = 1;\n\n/**\n * Persisted state for an in-progress unshield request.\n * Used to resume an interrupted unshield after page reload.\n *\n * @internal\n */\nexport interface PendingUnshieldRequest {\n /** Transaction hash of the original unwrap call. */\n readonly unwrapTxHash: Hex;\n /**\n * Request identifier from the `UnwrapRequested` event.\n * Always populated for entries persisted by this SDK version; pass it as\n * `unwrapRequestId` to `finalizeUnwrap`. Absent only when re-loading a\n * pending unshield serialized by an older SDK version that did not\n * record this field — in that case pass the `encryptedAmount` from the\n * `UnwrapRequested` event to `finalizeUnwrap` instead.\n */\n readonly unwrapRequestId?: EncryptedValue;\n}\n\ninterface StoredPendingUnshieldRequest extends PendingUnshieldRequest {\n readonly version: typeof CURRENT_VERSION;\n}\n\nfunction storageKey(wrapperAddress: Address): string {\n return `${STORAGE_PREFIX}${checksum(wrapperAddress)}`;\n}\n\nconst PendingUnshieldRequestSchema = z.union([\n z.pipe(\n hex,\n z.transform((unwrapTxHash: Hex) => ({ unwrapTxHash })),\n ),\n z.pipe(\n z.object({\n version: z.literal(CURRENT_VERSION),\n unwrapTxHash: hex,\n unwrapRequestId: z.optional(hex),\n }),\n z.transform(\n ({\n unwrapTxHash,\n unwrapRequestId,\n }: {\n version: typeof CURRENT_VERSION;\n unwrapTxHash: Hex;\n unwrapRequestId?: Hex;\n }) => ({ unwrapTxHash, unwrapRequestId }),\n ),\n ),\n]);\n\n/**\n * Persist the unwrap tx hash so an interrupted unshield can be resumed later\n * (e.g. after a page reload).\n *\n * @internal\n */\nexport async function savePendingUnshield(\n storage: GenericStorage,\n wrapperAddress: Address,\n unwrapTxHash: Hex,\n unwrapRequestId?: EncryptedValue,\n): Promise<void> {\n if (unwrapRequestId === undefined) {\n await storage.set(storageKey(wrapperAddress), unwrapTxHash);\n return;\n }\n\n await storage.set(storageKey(wrapperAddress), {\n version: CURRENT_VERSION,\n unwrapTxHash,\n unwrapRequestId,\n } satisfies StoredPendingUnshieldRequest);\n}\n\n/**\n * Load a previously saved unwrap tx hash, or `null` if none exists.\n *\n * @internal\n */\nexport async function loadPendingUnshield(\n storage: GenericStorage,\n wrapperAddress: Address,\n): Promise<Hex | null> {\n const request = await loadPendingUnshieldRequest(storage, wrapperAddress);\n return request?.unwrapTxHash ?? null;\n}\n\n/**\n * Load a previously saved unwrap request, including `unwrapRequestId` when available.\n *\n * `resumeUnshield()` only needs `unwrapTxHash`: it reloads the transaction receipt and\n * rediscovers the right finalize input from the emitted `UnwrapRequested` event.\n * Use `unwrapRequestId` directly only for custom flows that call `finalizeUnwrap()`\n * without reloading the original unwrap receipt.\n *\n * @internal\n */\nexport async function loadPendingUnshieldRequest(\n storage: GenericStorage,\n wrapperAddress: Address,\n): Promise<PendingUnshieldRequest | null> {\n const key = storageKey(wrapperAddress);\n const value = await storage.get<Hex | StoredPendingUnshieldRequest>(key);\n if (value === null || value === undefined) {\n return null;\n }\n const parsed = PendingUnshieldRequestSchema.safeParse(value);\n if (!parsed.success) {\n await storage.delete(key);\n return null;\n }\n return parsed.data as PendingUnshieldRequest;\n}\n\n/**\n * Clear the saved unwrap tx hash after a successful finalization.\n *\n * @internal\n */\nexport async function clearPendingUnshield(\n storage: GenericStorage,\n wrapperAddress: Address,\n): Promise<void> {\n await storage.delete(storageKey(wrapperAddress));\n}\n","import { getAddress, zeroAddress, type Address, type Hex } from \"viem\";\nimport {\n allowanceContract,\n approveContract,\n balanceOfContract,\n finalizeUnwrapContract,\n isPayableTokenContract,\n transferAndCallContract,\n underlyingContract,\n unwrapContract,\n unwrapFromBalanceContract,\n unwrapRequesterContract,\n wrapContract,\n} from \"../contracts\";\nimport {\n DecryptionFailedError,\n ERC20ReadFailedError,\n EncryptionFailedError,\n InsufficientAllowanceError,\n InsufficientERC20BalanceError,\n SignerNotConfiguredError,\n TransactionRevertedError,\n UnshieldAlreadyFinalizedError,\n ZamaError,\n} from \"../errors\";\nimport { isInvalidUnwrapRequestRevert } from \"../errors/unshield\";\nimport { findUnwrapRequested } from \"../events/onchain-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { EncryptedValue } from \"../relayer/types\";\nimport type {\n GenericSigner,\n ShieldCallbacks,\n ShieldOptions,\n TransactionResult,\n UnshieldCallbacks,\n UnshieldOptions,\n UnwrapResult,\n WrapOptions,\n} from \"../types\";\nimport type { RawLog } from \"../types/transaction\";\nimport { toError } from \"../utils\";\nimport { requireAlignedWalletAccount, requireChainAlignment } from \"../utils/alignment\";\nimport { assertBigint, assertNonNullable } from \"../utils/assertions\";\nimport { isEncryptedValueZero } from \"../utils/handles\";\nimport { swallow } from \"../utils/swallow\";\nimport {\n clearPendingUnshield,\n loadPendingUnshieldRequest,\n savePendingUnshield,\n type PendingUnshieldRequest,\n} from \"./pending-unshield\";\nimport { Token } from \"./token\";\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 /**\n * Wrap already-approved underlying ERC-20 into confidential tokens.\n *\n * Escape hatch for splitting shield across two signatures: call\n * {@link approveUnderlying} first, then `wrap`. Most callers should use\n * {@link shield}, which routes and orchestrates approval automatically.\n *\n * Validates the ERC-20 balance and the allowance granted to this wrapper\n * (public reads, no signing) and fails early with a clear error.\n *\n * @param amount - The plaintext amount to wrap.\n * @param options - Optional `to` recipient and `onWrapSubmitted` callback.\n * @returns The transaction hash and mined receipt.\n * @throws if reading the ERC-20 balance or allowance fails. {@link ERC20ReadFailedError}\n * @throws if the ERC-20 balance is less than `amount`. {@link InsufficientERC20BalanceError}\n * @throws if the allowance granted to the wrapper is less than `amount`. {@link InsufficientAllowanceError}\n *\n * @example\n * ```ts\n * await wrappedToken.approveUnderlying(1000n);\n * await wrappedToken.wrap(1000n);\n * ```\n */\n async wrap(amount: bigint, options?: WrapOptions): Promise<TransactionResult> {\n this.#requireSigner(\"wrap\");\n const account = await requireAlignedWalletAccount(\"wrap\", this.sdk.signer, this.sdk.provider);\n const underlying = await this.#getUnderlying();\n const userAddress = getAddress(account.address);\n\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 wrap 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 let allowance: bigint;\n try {\n allowance = await this.sdk.provider.readContract(\n allowanceContract(underlying, userAddress, this.address),\n );\n } catch (error) {\n if (error instanceof ZamaError) {\n throw error;\n }\n throw new ERC20ReadFailedError(\n `Could not read ERC-20 allowance for wrap validation (token: ${underlying})`,\n { cause: toError(error) },\n );\n }\n if (allowance < amount) {\n throw new InsufficientAllowanceError(\n `Insufficient allowance for wrap: requested ${amount}, approved ${allowance}. Call approveUnderlying() first (token: ${underlying}).`,\n { requested: amount, available: allowance, token: underlying },\n );\n }\n\n const recipient = options?.to ? getAddress(options.to) : userAddress;\n return this.submitTransaction({\n operation: \"wrap\",\n config: wrapContract(this.address, recipient, amount),\n onSubmitted: options?.onWrapSubmitted,\n });\n }\n\n async #shieldViaApproveAndWrap(\n amount: bigint,\n userAddress: Address,\n options?: ShieldOptions,\n ): Promise<TransactionResult> {\n this.#requireSigner(\"shield\");\n const strategy = options?.approvalStrategy ?? \"exact\";\n if (strategy !== \"skip\") {\n await this.#ensureAllowance(amount, strategy === \"max\", options);\n }\n const recipient = options?.to ? getAddress(options.to) : userAddress;\n return this.submitTransaction({\n operation: \"shield:approveAndWrap\",\n config: wrapContract(this.address, recipient, amount),\n onSubmitted: options?.onShieldSubmitted,\n });\n }\n\n /**\n * Approve this wrapper contract to spend the underlying ERC-20.\n * Defaults to max uint256. Resets to zero first if there's an existing\n * non-zero allowance (required by tokens like USDT).\n *\n * @param amount - Optional approval amount. Defaults to max uint256.\n * @returns The transaction hash and mined receipt.\n *\n * @example\n * ```ts\n * await wrappedToken.approveUnderlying(); // max approval\n * await wrappedToken.approveUnderlying(1000n); // exact amount\n * ```\n */\n async approveUnderlying(amount?: bigint): Promise<TransactionResult> {\n this.#requireSigner(\"approveUnderlying\");\n const account = await requireAlignedWalletAccount(\n \"approveUnderlying\",\n this.sdk.signer,\n this.sdk.provider,\n );\n const underlying = await this.#getUnderlying();\n const userAddress = getAddress(account.address);\n\n const approvalAmount = amount ?? 2n ** 256n - 1n;\n\n if (approvalAmount > 0n) {\n const currentAllowance = await this.sdk.provider.readContract(\n allowanceContract(underlying, userAddress, this.address),\n );\n\n if (currentAllowance > 0n) {\n await this.submitTransaction({\n operation: \"approveUnderlying:reset\",\n config: approveContract(underlying, this.address, 0n),\n });\n }\n }\n\n return this.submitTransaction({\n operation: \"approveUnderlying\",\n config: approveContract(underlying, this.address, approvalAmount),\n });\n }\n\n // UNSHIELD (confidential → ERC-20)\n\n /**\n * Unshield a specific amount and finalize in one call.\n * Orchestrates: unshield → wait for receipt → parse event → finalize.\n *\n * By default, the SDK validates the confidential balance before submitting.\n * Set `skipBalanceCheck: true` to bypass this validation (e.g. for smart wallets).\n *\n * @param amount - The plaintext amount to unshield.\n * @param options - Optional: `skipBalanceCheck` (default `false`), callbacks.\n * @returns The finalize transaction hash and mined receipt.\n *\n * @example\n * ```ts\n * const txHash = await wrappedToken.unshield(500n);\n * ```\n */\n async unshield(amount: bigint, options?: UnshieldOptions): Promise<TransactionResult> {\n const {\n skipBalanceCheck = false,\n onUnwrapSubmitted,\n onFinalizing,\n onFinalizeSubmitted,\n } = options ?? {};\n\n if (!skipBalanceCheck) {\n await this.assertConfidentialBalance(amount);\n }\n\n const callbacks: UnshieldCallbacks = { onFinalizing, onFinalizeSubmitted };\n const operationId = crypto.randomUUID();\n const unwrapResult = await this.unwrap(amount);\n void swallow(\n \"unshield: onUnwrapSubmitted\",\n () => onUnwrapSubmitted?.(unwrapResult.txHash),\n this.sdk.logger,\n );\n // Reuse the id `unwrap()` already decoded — no second receipt fetch or decode.\n return this.#finalizeUnshield(\n unwrapResult.unwrapRequestId,\n unwrapResult.txHash,\n operationId,\n callbacks,\n );\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 // Reuse the id `unwrapAll()` already decoded — no second receipt fetch or decode.\n return this.#finalizeUnshield(\n unwrapResult.unwrapRequestId,\n unwrapResult.txHash,\n operationId,\n callbacks,\n );\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 * @throws if the unwrap request was already finalized on-chain; the persisted\n * pending-unshield state is cleared first. {@link UnshieldAlreadyFinalizedError}\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 // The only entry point that starts from a bare hash, so it's the only one\n // that has to fetch the receipt and decode the id from chain.\n let receipt;\n try {\n receipt = await this.sdk.provider.waitForTransactionReceipt(unwrapTxHash);\n } catch (error) {\n if (error instanceof ZamaError) {\n throw error;\n }\n throw new TransactionRevertedError(\"Failed to get unwrap receipt\", { cause: error });\n }\n const unwrapRequestId = this.#extractUnwrapRequestId(receipt.logs);\n if (await this.#isUnwrapRequestConsumed(unwrapRequestId)) {\n await this.#clearStoredPendingUnshield(\"resumeUnshield\");\n throw new UnshieldAlreadyFinalizedError(\n \"Nothing to resume: the unwrap request was already finalized on-chain and the funds were delivered.\",\n { unwrapTxHash, unwrapRequestId },\n );\n }\n return this.#finalizeUnshield(unwrapRequestId, unwrapTxHash, crypto.randomUUID(), callbacks);\n }\n\n /**\n * Return the unwrap tx hash of an unshield that was interrupted between its\n * two phases, or `null` if none is pending for this wrapper.\n *\n * The SDK persists this automatically when {@link unshield}/{@link unshieldAll}\n * submit phase 1, and clears it once phase 2 finalizes. Use the returned hash\n * to surface a \"resume\" affordance, then pass it to {@link resumeUnshield}.\n * Resuming is intentionally caller-driven — auto-resuming on load would fire a\n * wallet transaction unprompted.\n *\n * The pointer is verified on-chain before it is reported: if the unwrap\n * request was already finalized (e.g. the tab closed before the SDK could\n * clear storage), the stale pointer is cleared and `null` is returned. When\n * the verification read fails, the pointer is returned unverified: a\n * network error never deletes recovery state.\n *\n * @returns The pending unwrap tx hash, or `null`.\n *\n * @example\n * ```ts\n * const unwrapTxHash = await wrappedToken.getPendingUnshield();\n * if (unwrapTxHash) await wrappedToken.resumeUnshield(unwrapTxHash);\n * ```\n */\n async getPendingUnshield(): Promise<Hex | null> {\n const pending = await loadPendingUnshieldRequest(this.sdk.storage, this.address);\n if (!pending) {\n return null;\n }\n if (await this.#isPendingUnshieldConsumed(pending)) {\n await this.#clearStoredPendingUnshield(\"getPendingUnshield\");\n return null;\n }\n return pending.unwrapTxHash;\n }\n\n // UNSHIELD LOW-LEVEL PRIMITIVES\n\n /**\n * Request an unwrap for a specific amount. Encrypts the amount first.\n * Pass the result's `unwrapRequestId` to {@link finalizeUnwrap} once the\n * request is processed on-chain.\n *\n * @param amount - The plaintext amount to unwrap (encrypted automatically).\n * @returns The tx hash, mined receipt, and the `unwrapRequestId` for `finalizeUnwrap`.\n *\n * @example\n * ```ts\n * const result = await wrappedToken.unwrap(500n);\n * await wrappedToken.finalizeUnwrap(result.unwrapRequestId);\n * ```\n */\n async unwrap(amount: bigint): Promise<UnwrapResult> {\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 const result = await this.submitTransaction({\n operation: \"unwrap\",\n config: unwrapContract(this.address, userAddress, userAddress, encryptedAmount, inputProof),\n });\n\n return { ...result, unwrapRequestId: this.#extractUnwrapRequestId(result.receipt.logs) };\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 tx hash, mined receipt, and the `unwrapRequestId` for `finalizeUnwrap`.\n * @throws if the balance is zero. {@link DecryptionFailedError}\n *\n * @example\n * ```ts\n * const result = await wrappedToken.unwrapAll();\n * await wrappedToken.finalizeUnwrap(result.unwrapRequestId);\n * ```\n */\n async unwrapAll(): Promise<UnwrapResult> {\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 const result = await this.submitTransaction({\n operation: \"unwrapAll\",\n config: unwrapFromBalanceContract(this.address, userAddress, userAddress, encryptedValue),\n });\n\n return { ...result, unwrapRequestId: this.#extractUnwrapRequestId(result.receipt.logs) };\n }\n\n /**\n * Complete an unwrap by fetching the public decryption proof and finalizing.\n * Call this once the unwrap request has been processed on-chain.\n *\n * @param unwrapRequestId - The `unwrapRequestId` from an {@link UnwrapResult}\n * (`result.unwrapRequestId`) returned by {@link unwrap} / {@link unwrapAll},\n * or one decoded from an `UnwrapRequested` event (e.g. when finalizing\n * across sessions).\n * @returns The transaction hash and mined receipt.\n *\n * @example\n * ```ts\n * const { unwrapRequestId } = await wrappedToken.unwrap(500n);\n * await wrappedToken.finalizeUnwrap(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 /**\n * Decode the `unwrapRequestId` from an unwrap/unshield receipt's logs.\n * Only logs emitted by this wrapper count: a caller-supplied tx hash from a\n * different wrapper must fail here, not decode a foreign request id. Logs\n * without an emitter address (older custom adapters) are kept.\n * Throws when no matching `UnwrapRequested` event is found.\n */\n #extractUnwrapRequestId(logs: readonly RawLog[]): EncryptedValue {\n const ownLogs = logs.filter(\n (log) => log.address === undefined || getAddress(log.address) === this.address,\n );\n const event = findUnwrapRequested(ownLogs);\n if (!event) {\n throw new TransactionRevertedError(\n \"No UnwrapRequested event from this wrapper found in the unwrap receipt\",\n );\n }\n return event.unwrapRequestId;\n }\n\n /**\n * True only when the unwrap request is definitely gone. `unwrapRequester`\n * returns the zero address once finalize deletes the request, and the id\n * always comes from the unwrap tx's own `UnwrapRequested` event, so zero can\n * only mean \"already finalized\". A failed read returns `false`: the check\n * fails open, so a network error never heals recovery state.\n */\n async #isUnwrapRequestConsumed(unwrapRequestId: EncryptedValue): Promise<boolean> {\n try {\n const requester = await this.sdk.provider.readContract(\n unwrapRequesterContract(this.address, unwrapRequestId),\n );\n return requester === zeroAddress;\n } catch {\n return false;\n }\n }\n\n /**\n * Consumed-request check for a persisted pointer; legacy hash-only entries\n * re-derive the request id from the unwrap receipt.\n */\n async #isPendingUnshieldConsumed(pending: PendingUnshieldRequest): Promise<boolean> {\n let unwrapRequestId = pending.unwrapRequestId;\n if (unwrapRequestId === undefined) {\n try {\n const receipt = await this.sdk.provider.waitForTransactionReceipt(pending.unwrapTxHash);\n unwrapRequestId = this.#extractUnwrapRequestId(receipt.logs);\n } catch {\n return false;\n }\n }\n return this.#isUnwrapRequestConsumed(unwrapRequestId);\n }\n\n async #clearStoredPendingUnshield(operation: string): Promise<void> {\n await swallow(\n `${operation}: clearPendingUnshield`,\n () => clearPendingUnshield(this.sdk.storage, this.address),\n this.sdk.logger,\n );\n }\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 /**\n * Phase 2 of unshield, shared by {@link unshield}/{@link unshieldAll} (which\n * pass the id `unwrap`/`unwrapAll` already decoded) and {@link resumeUnshield}\n * (which decoded it from a fetched receipt). Persists the unwrap hash for\n * recovery, finalizes, then clears the persisted state.\n */\n async #finalizeUnshield(\n unwrapRequestId: EncryptedValue,\n unwrapTxHash: Hex,\n operationId: string,\n callbacks: UnshieldCallbacks | undefined,\n ): Promise<TransactionResult> {\n this.emit({ type: ZamaSDKEvents.UnshieldPhase1Submitted, txHash: unwrapTxHash, operationId });\n await swallow(\n \"unshield: savePendingUnshield\",\n () => savePendingUnshield(this.sdk.storage, this.address, unwrapTxHash, unwrapRequestId),\n this.sdk.logger,\n );\n this.emit({ type: ZamaSDKEvents.UnshieldPhase2Started, operationId });\n void swallow(\"unshield: onFinalizing\", () => callbacks?.onFinalizing?.(), this.sdk.logger);\n let finalizeResult: TransactionResult;\n try {\n finalizeResult = await this.finalizeUnwrap(unwrapRequestId);\n } catch (error) {\n // The id comes from this wrapper's own UnwrapRequested event and the only\n // transition to \"gone\" is a successful finalize, so this revert means a\n // concurrent finalize won the race (second tab, double click, third\n // party). The funds arrived; heal.\n if (!isInvalidUnwrapRequestRevert(error)) {\n throw error;\n }\n await this.#clearStoredPendingUnshield(\"unshield\");\n throw new UnshieldAlreadyFinalizedError(\n \"The unwrap request was finalized concurrently — the funds were already delivered.\",\n { unwrapTxHash, unwrapRequestId },\n { cause: error },\n );\n }\n this.emit({\n type: ZamaSDKEvents.UnshieldPhase2Submitted,\n txHash: finalizeResult.txHash,\n operationId,\n });\n void swallow(\n \"unshield: onFinalizeSubmitted\",\n () => callbacks?.onFinalizeSubmitted?.(finalizeResult.txHash),\n this.sdk.logger,\n );\n // Phase 2 landed: the persisted recovery state is no longer needed.\n await this.#clearStoredPendingUnshield(\"unshield\");\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 { getAddress, type Address } from \"viem\";\nimport { z } from \"zod/mini\";\nimport type { ClearValue, EncryptedValue } from \"../relayer/types\";\nimport { checksummedAddress } from \"../schemas/primitives\";\nimport type { GenericLogger, GenericStorage } from \"../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 *\n * @internal\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, Hex } from \"viem\";\nimport { DecryptionFailedError } from \"../errors\";\nimport { checksum } from \"../schemas/primitives\";\nimport { permissionCovers } from \"./permissions\";\nimport type {\n Permission,\n SerializedTransportKeyPairWithPermissions,\n SerializedPermit,\n} from \"./types\";\n\n/**\n * The minimal permit material the decrypt seam needs. Delegation is already\n * encoded in the self-contained `serializedPermit`, so a delegated decrypt and\n * a normal decrypt resolve to the same shape — there is no separate delegated\n * variant.\n */\nexport interface ResolvedPermit {\n privateKey: Hex;\n publicKey: Hex;\n serializedPermit: SerializedPermit;\n}\n\n/**\n * Resolve the signed permit covering `contractAddress` from previously granted\n * credentials. Works uniformly for direct and delegated decryption: the\n * `@fhevm/sdk` signed permit bakes the delegator (if any) into its EIP-712\n * payload, so the decrypt call needs nothing beyond the transport key pair and\n * the serialized permit.\n *\n * @throws if no stored permit covers `contractAddress`. {@link DecryptionFailedError}\n */\nexport function resolvePermit(\n credentials: SerializedTransportKeyPairWithPermissions,\n contractAddress: Address,\n): ResolvedPermit {\n const permission = findPermissionFor(credentials, contractAddress);\n if (!permission) {\n throw new DecryptionFailedError(`No permit covers contract ${contractAddress} after allow()`);\n }\n return {\n privateKey: credentials.keypair.privateKey,\n publicKey: credentials.keypair.publicKey,\n serializedPermit: permission.serializedPermit,\n };\n}\n\nfunction findPermissionFor(\n credentials: SerializedTransportKeyPairWithPermissions,\n contractAddress: Address,\n): Permission | undefined {\n const target = checksum(contractAddress);\n return credentials.permissions.find((permission) => permissionCovers(permission, target));\n}\n","import type { ParseTransportKeyPairReturnType } from \"@fhevm/sdk/actions/chain\";\nimport type { DecryptValuesReturnType } from \"@fhevm/sdk/actions/decrypt\";\nimport { getAddress, type Address } from \"viem\";\nimport type { ChainRouter } from \"../chains/router\";\nimport type { CredentialService } from \"../credentials/credential-service\";\nimport { resolvePermit } from \"../credentials/decrypt-permit\";\nimport type { SerializedTransportKeyPairWithPermissions } from \"../credentials/types\";\nimport {\n type DecryptErrorContext,\n DecryptionFailedError,\n DelegationNotPropagatedError,\n isFatalBatchError,\n RevokedKmsContextError,\n RpcRateLimitError,\n SigningFailedError,\n wrapDecryptError,\n ZamaError,\n} from \"../errors\";\nimport type { ZamaSDKEventInput } from \"../events/sdk-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { EncryptedInput } from \"../query/user-decrypt\";\nimport type { ClearValue, EncryptedValue, FhevmRelayerOptions } from \"../relayer/types\";\nimport { pLimit } from \"../utils/concurrency\";\nimport { chunkHandlesByBitBudget, isEncryptedValueZero } from \"../utils/handles\";\nimport {\n extractRetryAfter,\n isInvalidTransportKeyPairMessage,\n isRpcRateLimitError,\n toError,\n} from \"../utils\";\nimport type { CachingService } from \"./caching-service\";\nimport type { DelegationService } from \"./delegation-service\";\n\n/**\n * How long the delegated-decrypt path keeps retrying while a freshly granted\n * delegation propagates to the gateway. Propagation usually completes within\n * ~10 blocks (a few seconds); this ceiling absorbs a briefly lagging gateway\n * without turning a genuine outage into a long hang.\n */\nconst DELEGATION_PROPAGATION_RETRY_BUDGET_MS = 30_000;\n/** Delay between propagation retries. */\nconst DELEGATION_PROPAGATION_RETRY_INTERVAL_MS = 2_000;\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\n/** Options shared by the delegated-decrypt entry points. */\nexport interface DelegatedDecryptOptions {\n /**\n * Ride out the gateway propagation window: when a just-granted delegation\n * has not yet synced, the delegated decrypt is retried (bounded, ~30s) until\n * it lands instead of throwing {@link DelegationNotPropagatedError}. Defaults\n * to `true`. Pass `false` to fail fast on the first not-propagated response.\n */\n waitForPropagation?: boolean;\n}\n\ninterface DecryptionStrategy {\n requesterAddress: Address;\n /**\n * Delegator whose permit scope this decrypt reads; undefined on the direct\n * path. The single delegation discriminator: it also selects the delegated\n * error classification and the ACL actor (delegator, or the requester when\n * direct).\n */\n delegator?: Address;\n validate?: (contractAddresses: readonly Address[]) => Promise<void>;\n errorMessage: string;\n}\n\n/** One decrypt-relayer request: a contract's handles chunked to the bit budget. */\ninterface DecryptRequest {\n contractAddress: Address;\n encryptedValues: EncryptedValue[];\n}\n\n/** Tracks the evict-and-regrant allowance across retried decrypt attempts. */\ninterface RecoveryBudget {\n spent: boolean;\n}\n\n/** Per-handle outcome of a batch decrypt: the decrypted value, or a per-item error. */\nexport interface BatchDecryptItem {\n /** The encrypted value (handle) being decrypted. */\n encryptedValue: EncryptedValue;\n /** Address of the contract the handle belongs to. */\n contractAddress: Address;\n /** Decrypted clear value; set when this item succeeded. */\n value?: ClearValue;\n /** Error for this item; set when this item failed. */\n error?: ZamaError;\n}\n\n/** Result of a batch decrypt: one entry per requested handle, in input order. */\nexport interface BatchDecryptResult {\n /** Per-handle outcomes. */\n items: BatchDecryptItem[];\n}\n\n/** @internal */\nexport class DecryptionService {\n readonly #cache: CachingService;\n readonly #credentialService: CredentialService;\n readonly #delegationService: DelegationService;\n readonly #router: ChainRouter;\n readonly #emitEvent: (input: ZamaSDKEventInput) => void;\n\n constructor({\n cache,\n credentialService,\n delegationService,\n router,\n emitEvent,\n }: {\n cache: CachingService;\n credentialService: CredentialService;\n delegationService: DelegationService;\n router: ChainRouter;\n emitEvent: (input: ZamaSDKEventInput) => void;\n }) {\n this.#cache = cache;\n this.#credentialService = credentialService;\n this.#delegationService = delegationService;\n this.#router = router;\n this.#emitEvent = emitEvent;\n }\n\n async decryptValues(\n handles: EncryptedInput[],\n signerAddress: Address,\n opts?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<Record<EncryptedValue, ClearValue>> {\n const normalizedSigner = getAddress(signerAddress);\n return this.#decrypt(\n handles,\n { requesterAddress: normalizedSigner, errorMessage: \"Failed to decrypt encrypted values\" },\n opts,\n );\n }\n\n async delegatedDecryptValues(\n encryptedInputs: EncryptedInput[],\n delegatorAddress: Address,\n delegateAddress: Address,\n accountAddress: Address,\n opts?: DelegatedDecryptOptions,\n ): Promise<Record<EncryptedValue, ClearValue>> {\n const normalizedDelegator = getAddress(delegatorAddress);\n const normalizedDelegate = getAddress(delegateAddress);\n // One evict-and-regrant across the whole propagation-retry loop, not one\n // per attempt: each retry would otherwise re-arm the recovery and spend a\n // fresh wallet prompt per 2s attempt while the upstream validity cache\n // keeps serving the revoked context.\n const recovery: RecoveryBudget = { spent: false };\n return this.#withPropagationRetry(opts?.waitForPropagation ?? true, () =>\n this.#decrypt(\n encryptedInputs,\n {\n requesterAddress: getAddress(accountAddress),\n delegator: normalizedDelegator,\n validate: (contractAddresses) =>\n this.#assertAllDelegationsActive(contractAddresses, {\n delegatorAddress: normalizedDelegator,\n delegateAddress: normalizedDelegate,\n }),\n errorMessage: \"Failed to decrypt delegated encrypted values\",\n },\n undefined,\n recovery,\n ),\n );\n }\n\n /**\n * Absorb the gateway propagation window on the delegated path: retry `attempt`\n * (bounded by {@link DELEGATION_PROPAGATION_RETRY_BUDGET_MS}) while it fails\n * with a transient {@link DelegationNotPropagatedError}. Every other error —\n * including a missing/expired grant surfaced by the pre-check — throws\n * immediately, and passing `waitForPropagation: false` disables the retry so\n * the first not-propagated response propagates unchanged.\n */\n async #withPropagationRetry<T>(\n waitForPropagation: boolean,\n attempt: () => Promise<T>,\n ): Promise<T> {\n // Fixed-interval polling across the budget: e.g. 30s / 2s = 15 gaps, so 16\n // attempts. Bounded (no open-ended loop) and deterministic under fake timers.\n const maxAttempts =\n Math.floor(\n DELEGATION_PROPAGATION_RETRY_BUDGET_MS / DELEGATION_PROPAGATION_RETRY_INTERVAL_MS,\n ) + 1;\n let lastError: unknown;\n for (let i = 0; i < maxAttempts; i++) {\n try {\n return await attempt();\n } catch (error) {\n lastError = error;\n const canRetry =\n i < maxAttempts - 1 &&\n waitForPropagation &&\n error instanceof DelegationNotPropagatedError;\n if (!canRetry) {\n throw error;\n }\n await sleep(DELEGATION_PROPAGATION_RETRY_INTERVAL_MS);\n }\n }\n throw lastError;\n }\n\n async delegatedBatchDecryptHandlesAs({\n encryptedInputs,\n delegatorAddress,\n delegateAddress,\n accountAddress,\n maxConcurrency = 5,\n waitForPropagation = true,\n }: {\n encryptedInputs: EncryptedInput[];\n delegatorAddress: Address;\n delegateAddress: Address;\n accountAddress: Address;\n maxConcurrency?: number;\n waitForPropagation?: boolean;\n }): Promise<BatchDecryptResult> {\n const items: BatchDecryptItem[] = encryptedInputs.map((h) => ({\n encryptedValue: h.encryptedValue,\n contractAddress: getAddress(h.contractAddress),\n }));\n if (items.length === 0) {\n return { items };\n }\n const normalizedAccount = getAddress(accountAddress);\n\n try {\n const decrypted = await this.delegatedDecryptValues(\n items.map(({ encryptedValue, contractAddress }) => ({ encryptedValue, contractAddress })),\n delegatorAddress,\n delegateAddress,\n normalizedAccount,\n { waitForPropagation },\n );\n for (const item of items) {\n this.#setHandleResult(item, decrypted);\n }\n return { items };\n } catch (error) {\n if (isFatalBatchError(error)) {\n throw error;\n }\n if (items.length === 1) {\n const [item = this.#missingBatchItem()] = items;\n item.error = this.#toZamaError(error, \"Failed to decrypt delegated encrypted values\", {\n isDelegated: true,\n contractAddress: item.contractAddress,\n account: getAddress(delegatorAddress),\n });\n return { items };\n }\n }\n\n // `pLimit` cannot cancel calls that already started. The shared flag stops\n // the queued items from starting once a fatal error (e.g. an RPC rate\n // limit) is seen, instead of re-hitting the failing endpoint.\n let aborted = false;\n let fatal: unknown;\n await pLimit(\n items.map((item) => async () => {\n if (aborted) {\n return;\n }\n try {\n // The batch attempt above already rode out the propagation window for\n // the whole set; fail fast here so a still-unsynced delegation records\n // a per-item error instead of each item re-spending the full budget.\n const decrypted = await this.delegatedDecryptValues(\n [{ encryptedValue: item.encryptedValue, contractAddress: item.contractAddress }],\n delegatorAddress,\n delegateAddress,\n normalizedAccount,\n { waitForPropagation: false },\n );\n this.#setHandleResult(item, decrypted);\n } catch (error) {\n if (isFatalBatchError(error)) {\n aborted = true;\n fatal ??= error;\n return;\n }\n item.error = this.#toZamaError(error, \"Failed to decrypt delegated encrypted values\", {\n isDelegated: true,\n contractAddress: item.contractAddress,\n account: getAddress(delegatorAddress),\n });\n }\n }),\n maxConcurrency,\n );\n\n if (fatal !== undefined) {\n throw fatal;\n }\n\n return { items };\n }\n\n /**\n * Run a user (or delegated-user) decrypt for one contract: rebuild the\n * `@fhevm/sdk` transport key pair and signed permit from the resolved permit,\n * then decrypt. The delegation, if any, is encoded in the permit — both paths\n * share this call. Returns the positional clear values for `encryptedValues`.\n */\n async #decryptValues(\n credentials: SerializedTransportKeyPairWithPermissions,\n contractAddress: Address,\n encryptedValues: EncryptedValue[],\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<DecryptValuesReturnType> {\n const permit = resolvePermit(credentials, contractAddress);\n let transportKeyPair: ParseTransportKeyPairReturnType;\n try {\n transportKeyPair = await this.#router.relayer.parseTransportKeyPair({\n publicKey: permit.publicKey,\n privateKey: permit.privateKey,\n tkmsVersion: credentials.keypair.tkmsVersion,\n });\n } catch (error) {\n // Stale key pair the relayer can't re-derive (post KMS/TKMS rotation):\n // evict it so the next resolveCredentials regenerates and re-signs.\n // wrapDecryptError maps the raw message to InvalidTransportKeyPairError.\n if (error instanceof Error && isInvalidTransportKeyPairMessage(error.message)) {\n await this.#credentialService.evictTransportKeyPair();\n }\n throw error;\n }\n const signedPermit = await this.#router.relayer.parseSignedDecryptionPermit({\n transportKeyPair,\n serializedPermit: permit.serializedPermit,\n });\n return this.#router.relayer.decryptValues({\n transportKeyPair,\n signedPermit,\n encryptedValues,\n contractAddress,\n options,\n });\n }\n\n async #decrypt(\n handles: EncryptedInput[],\n strategy: DecryptionStrategy,\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n recovery: RecoveryBudget = { spent: false },\n ): Promise<Record<EncryptedValue, ClearValue>> {\n if (handles.length === 0) {\n return {};\n }\n\n const normalized = handles.map((h) => ({\n encryptedValue: h.encryptedValue,\n contractAddress: getAddress(h.contractAddress),\n }));\n const result: Record<EncryptedValue, ClearValue> = {};\n const nonZero: EncryptedInput[] = [];\n\n for (const h of normalized) {\n if (isEncryptedValueZero(h.encryptedValue)) {\n result[h.encryptedValue] = 0n;\n } else {\n nonZero.push(h);\n }\n }\n\n if (nonZero.length === 0) {\n return result;\n }\n\n const allContracts = Array.from(new Set(normalized.map((h) => h.contractAddress)));\n const nonZeroContracts = Array.from(new Set(nonZero.map((h) => h.contractAddress)));\n if (strategy.validate) {\n try {\n await strategy.validate(nonZeroContracts);\n } catch (error) {\n // The delegation pre-check makes on-chain reads too; classify a throttled\n // RPC here as well so delegated decrypt branches deterministically.\n if (isRpcRateLimitError(error)) {\n throw this.#rpcRateLimitError(error, \"the delegation pre-check\");\n }\n throw error;\n }\n }\n\n const uncached: EncryptedInput[] = [];\n for (const h of nonZero) {\n const cached = await this.#cache.get(\n strategy.requesterAddress,\n h.contractAddress,\n h.encryptedValue,\n );\n if (cached !== null) {\n result[h.encryptedValue] = cached;\n } else {\n uncached.push(h);\n }\n }\n\n if (uncached.length === 0) {\n return result;\n }\n\n let credentials = await this.#credentialService.grantPermit(allContracts, strategy.delegator);\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 // Split each contract's handles to stay under the relayer's per-request\n // cleartext-bit budget — a contract with many/wide handles becomes\n // several relayer calls instead of one oversized, rejected call.\n const requests: DecryptRequest[] = [];\n for (const [contractAddress, encryptedValues] of byContract) {\n for (const chunk of chunkHandlesByBitBudget(encryptedValues)) {\n requests.push({ contractAddress, encryptedValues: chunk });\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 try {\n await this.#runDecryptRequests(strategy, credentials, requests, result, options);\n } catch (error) {\n if (!(error instanceof RevokedKmsContextError) || recovery.spent) {\n throw error;\n }\n // Identify the permits this attempt used: if they are already gone from\n // the store, a sibling decrypt recovered the scope and re-signing would\n // cost a second prompt for nothing.\n const staleSignatures = credentials.permissions.map((p) => p.serializedPermit.signature);\n // Re-grant under the current context and retry the still-unresolved\n // chunks once; a second revoked failure surfaces instead of looping\n // into the upstream 15-minute validity cache. Spent is set before\n // awaiting so a failing re-grant cannot re-arm the budget.\n recovery.spent = true;\n try {\n credentials = await this.#credentialService.recoverPermits(\n allContracts,\n strategy.delegator,\n staleSignatures,\n );\n } catch (recoveryError) {\n // A re-grant the signer cannot complete must not mask the revocation:\n // the caller's remedy is a new permit, not a signing fix. A user\n // rejecting the prompt stays a rejection.\n if (recoveryError instanceof SigningFailedError) {\n throw new RevokedKmsContextError(\n \"The permit's KMS context has been revoked on-chain and the automatic re-grant \" +\n \"failed, so the decrypt cannot proceed. Establish a new permit for this scope \" +\n \"and retry.\",\n { cause: recoveryError },\n );\n }\n throw recoveryError;\n }\n await this.#runDecryptRequests(\n strategy,\n credentials,\n requests.filter(({ encryptedValues }) =>\n encryptedValues.some((encryptedValue) => result[encryptedValue] === undefined),\n ),\n result,\n options,\n );\n }\n\n const uncachedResult: Record<EncryptedValue, ClearValue> = {};\n for (const encryptedValue of uncachedEncryptedValues) {\n const value = result[encryptedValue];\n if (value !== undefined) {\n uncachedResult[encryptedValue] = value;\n }\n }\n this.#emitEvent({\n type: ZamaSDKEvents.DecryptEnd,\n durationMs: Date.now() - t0,\n encryptedValues: uncachedEncryptedValues,\n result: uncachedResult,\n });\n return result;\n } catch (error) {\n // Per-contract failures are already classified into a typed ZamaError whose\n // `cause` is the original failure; surface that original in the observability\n // event so monitoring keeps the root-cause message.\n const original =\n error instanceof ZamaError && error.cause instanceof Error ? error.cause : error;\n this.#emitEvent({\n type: ZamaSDKEvents.DecryptError,\n error: toError(original),\n durationMs: Date.now() - t0,\n encryptedValues: uncachedEncryptedValues,\n });\n // The per-contract wrap above already classified these; this is a passthrough\n // for them plus a fallback for any non-contract failure (e.g. caching).\n throw wrapDecryptError(error, strategy.errorMessage, {\n isDelegated: strategy.delegator !== undefined,\n });\n }\n }\n\n /**\n * Fan the decrypt requests out (bounded concurrency), writing clear values\n * into `result` and the cache as each settles. Every request is settled\n * before anything is thrown: pLimit rejects on the first settled failure\n * while siblings are still in flight, which would let a sibling's earlier\n * failure hide a revoked-context revert from the recovery decision and let\n * the retry race workers still writing into `result`. Among the settled\n * failures, a {@link RevokedKmsContextError} is surfaced in preference to\n * whichever happened to settle first, so the self-heal always sees it.\n */\n async #runDecryptRequests(\n strategy: DecryptionStrategy,\n credentials: SerializedTransportKeyPairWithPermissions,\n requests: DecryptRequest[],\n result: Record<EncryptedValue, ClearValue>,\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<void> {\n const outcomes = await pLimit(\n requests.map(({ contractAddress, encryptedValues }) => async (): Promise<unknown> => {\n try {\n await this.#decryptRequest(\n strategy,\n credentials,\n contractAddress,\n encryptedValues,\n result,\n options,\n );\n return undefined;\n } catch (error) {\n return error;\n }\n }),\n 5,\n );\n const failures = outcomes.filter((outcome) => outcome !== undefined);\n if (failures.length > 0) {\n throw failures.find((failure) => failure instanceof RevokedKmsContextError) ?? failures[0];\n }\n }\n\n /** Decrypt one contract's chunk of handles into `result` (and the cache). */\n async #decryptRequest(\n strategy: DecryptionStrategy,\n credentials: SerializedTransportKeyPairWithPermissions,\n contractAddress: Address,\n encryptedValues: EncryptedValue[],\n result: Record<EncryptedValue, ClearValue>,\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<void> {\n // Classify per contract so a not-entitled / relayer failure carries the\n // exact contract + ACL actor. Already-typed errors pass straight through.\n let decrypted: DecryptValuesReturnType;\n try {\n decrypted = await this.#decryptValues(credentials, contractAddress, encryptedValues, options);\n } catch (error) {\n throw wrapDecryptError(error, strategy.errorMessage, {\n isDelegated: strategy.delegator !== undefined,\n contractAddress,\n account: strategy.delegator ?? strategy.requesterAddress,\n });\n }\n\n // `decryptValues` returns clear values positionally aligned with the\n // requested `encryptedValues`; zip them back into the handle→value map.\n for (let i = 0; i < encryptedValues.length; i++) {\n const encryptedValue = encryptedValues[i];\n const value = decrypted[i]?.value;\n if (encryptedValue === undefined || value === undefined) {\n continue;\n }\n result[encryptedValue] = value;\n await this.#cache.set(strategy.requesterAddress, contractAddress, encryptedValue, value);\n }\n\n const missing = encryptedValues.filter(\n (encryptedValue) => result[encryptedValue] === undefined,\n );\n if (missing.length > 0) {\n throw new DecryptionFailedError(\n `${strategy.errorMessage}: relayer returned no clear value for ${missing.length} of ${encryptedValues.length} handle(s) on ${contractAddress}`,\n {\n cause: new AggregateError(\n missing.map(\n (encryptedValue) =>\n new DecryptionFailedError(\n `No clear value for handle ${encryptedValue} on ${contractAddress}`,\n ),\n ),\n `${missing.length} handle(s) missing a clear value on ${contractAddress}`,\n ),\n },\n );\n }\n }\n\n /** Build an `RpcRateLimitError` for a throttled on-chain read. */\n #rpcRateLimitError(error: unknown, context: string): RpcRateLimitError {\n return new RpcRateLimitError(`RPC provider rate-limited ${context}; retry with backoff.`, {\n cause: error,\n retryAfter: extractRetryAfter(error),\n });\n }\n\n #setHandleResult(item: BatchDecryptItem, decrypted: Record<EncryptedValue, ClearValue>): void {\n const value = decrypted[item.encryptedValue];\n if (value === undefined) {\n item.error = new DecryptionFailedError(\n `Batch delegated decryption returned no value for encrypted value ${item.encryptedValue} on contract ${item.contractAddress}`,\n );\n return;\n }\n item.value = value;\n }\n\n #toZamaError(error: unknown, fallbackMessage: string, ctx?: DecryptErrorContext): ZamaError {\n return error instanceof ZamaError ? error : wrapDecryptError(error, fallbackMessage, ctx);\n }\n\n #missingBatchItem(): never {\n throw new DecryptionFailedError(\"Batch delegated decryption invariant failed: missing item\");\n }\n\n async #assertAllDelegationsActive(\n contractAddresses: readonly Address[],\n { delegatorAddress, delegateAddress }: { delegatorAddress: Address; delegateAddress: Address },\n ): Promise<void> {\n const inactive = await this.#delegationService.findInactiveDelegations(\n contractAddresses,\n delegatorAddress,\n delegateAddress,\n );\n if (inactive.size === 0) {\n return;\n }\n for (const error of inactive.values()) {\n throw error;\n }\n }\n}\n","import type { ZamaError } from \"./base\";\nimport { InvalidationTimestampInFutureError, InvalidationTimestampTooLowError } from \"./credential\";\nimport { extractRevertErrorName } from \"./revert\";\nimport {\n AclPausedError,\n DelegationContractIsSelfError,\n DelegationCooldownError,\n DelegationDelegateCannotBeWildcardError,\n DelegationDelegateEqualsContractError,\n DelegationExpirationTooSoonError,\n DelegationExpiryUnchangedError,\n DelegationNotFoundError,\n DelegationSelfNotAllowedError,\n} from \"./delegation\";\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 DelegateCannotBeWildcard: (cause) =>\n new DelegationDelegateCannotBeWildcardError(\n \"Delegate address cannot be the wildcard address; it can only be used 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 InvalidationTimestampTooLow: (cause) =>\n new InvalidationTimestampTooLowError(\n \"The invalidation cutoff must be strictly later than the account's current one. \" +\n \"Pass a later timestamp, or omit it to use the current block timestamp.\",\n { cause },\n ),\n InvalidationTimestampInTheFuture: (cause) =>\n new InvalidationTimestampInFutureError(\n \"The invalidation cutoff cannot be in the future. Pass a timestamp no later than \" +\n \"now, or omit it to use the current block timestamp.\",\n { cause },\n ),\n} satisfies Record<string, (cause: unknown) => ZamaError>;\n\nfunction isAclRevertName(name: string): name is keyof typeof ACL_ERROR_MAP {\n return Object.hasOwn(ACL_ERROR_MAP, name);\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 invalidateDecryptionSignaturesBeforeContract,\n MAX_UINT64,\n revokeDelegationContract,\n WILDCARD_CONTRACT,\n} from \"../contracts\";\nimport {\n DelegationDelegateCannotBeWildcardError,\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 { ChainRouter } from \"../chains/router\";\nimport type {\n GenericLogger,\n GenericProvider,\n GenericSigner,\n TransactionResult,\n WriteContractConfig,\n} from \"../types\";\nimport { submitTransaction } from \"../utils/submit-transaction\";\n\ntype AclTransactionOperation = Extract<\n TransactionOperation,\n \"delegateDecryption\" | \"revokeDelegation\" | \"invalidateDecryptionSignatures\"\n>;\n\n/** Delegation activity and expiry, resolved from the active contract or wildcard grant. */\nexport interface DelegationStatus {\n /** Whether the delegation is currently active (exists and not expired). */\n isActive: boolean;\n /** Unix timestamp (seconds) when the delegation expires; `0n` if none exists. */\n expiryTimestamp: bigint;\n}\n\n/** @internal */\nexport class DelegationService {\n readonly #router: ChainRouter;\n readonly #provider: GenericProvider;\n readonly #emitEvent: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;\n readonly #logger: GenericLogger;\n\n constructor({\n provider,\n router,\n emitEvent = () => {},\n logger,\n }: {\n provider: GenericProvider;\n router: ChainRouter;\n logger: GenericLogger;\n emitEvent?: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;\n }) {\n this.#provider = provider;\n this.#router = router;\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 === getAddress(WILDCARD_CONTRACT)) {\n throw new DelegationDelegateCannotBeWildcardError(\n \"Delegate address cannot be the wildcard address; it can only be used as the contract address.\",\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 = this.#router.relayer.chain.aclContractAddress;\n const expDate = expirationDate\n ? BigInt(Math.floor(expirationDate.getTime() / 1000))\n : MAX_UINT64;\n\n let currentExpiry: bigint;\n try {\n currentExpiry = await this.getDelegationExpiry({\n contractAddress: normalizedContract,\n delegatorAddress: normalizedDelegator,\n delegateAddress: normalizedDelegate,\n });\n } catch (error) {\n this.#logger.warn(\"delegateDecryption: pre-flight expiry check failed\", { error });\n currentExpiry = -1n;\n }\n if (currentExpiry === expDate) {\n throw new DelegationExpiryUnchangedError(\n `The new expiration date (${expDate}) is the same as the current one. No on-chain change needed.`,\n );\n }\n\n if (normalizedContract !== getAddress(WILDCARD_CONTRACT)) {\n await this.#warnIfWildcardAlreadyCoversDelegate({\n contractAddress: normalizedContract,\n delegatorAddress: normalizedDelegator,\n delegateAddress: normalizedDelegate,\n });\n }\n\n return this.#submitAclTransaction({\n operation: \"delegateDecryption\",\n signer,\n contractAddress: normalizedContract,\n config: delegateForUserDecryptionContract(\n acl,\n normalizedDelegate,\n normalizedContract,\n expDate,\n ),\n });\n }\n\n async revokeDelegation(\n signer: GenericSigner,\n {\n contractAddress,\n delegateAddress,\n delegatorAddress,\n }: { contractAddress: Address; delegateAddress: Address; delegatorAddress: Address },\n ): Promise<TransactionResult> {\n const normalizedContract = getAddress(contractAddress);\n const normalizedDelegate = getAddress(delegateAddress);\n const normalizedDelegator = getAddress(delegatorAddress);\n const acl = this.#router.relayer.chain.aclContractAddress;\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: normalizedContract,\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 return (await this.getStatus(params)).isActive;\n }\n\n /**\n * Resolve activity and expiry, falling back to the delegate's {@link WILDCARD_CONTRACT}\n * grant when the per-contract row isn't active — the raw expiry getter is a per-contract\n * read, so a wildcard-only grant would otherwise read as \"no delegation\" for every contract.\n */\n async getStatus(params: {\n contractAddress: Address;\n delegatorAddress: Address;\n delegateAddress: Address;\n }): Promise<DelegationStatus> {\n const normalizedContract = getAddress(params.contractAddress);\n const isWildcardQuery = normalizedContract === WILDCARD_CONTRACT;\n\n const [contractExpiry, wildcardExpiry] = await Promise.all([\n this.getDelegationExpiry(params),\n isWildcardQuery\n ? Promise.resolve(0n)\n : this.getDelegationExpiry({ ...params, contractAddress: WILDCARD_CONTRACT }),\n ]);\n\n const now =\n this.#needsBlockTimestamp(contractExpiry) || this.#needsBlockTimestamp(wildcardExpiry)\n ? await this.#provider.getBlockTimestamp()\n : undefined;\n\n const contractStatus = this.#resolveStatus(contractExpiry, now);\n if (contractStatus.isActive) {\n return contractStatus;\n }\n const wildcardStatus = this.#resolveStatus(wildcardExpiry, now);\n if (wildcardStatus.isActive) {\n return wildcardStatus;\n }\n return contractExpiry >= wildcardExpiry ? contractStatus : wildcardStatus;\n }\n\n /**\n * Advisory only — mixing wildcard and per-contract delegations to the same\n * delegate is valid on-chain, so this never blocks the write.\n */\n async #warnIfWildcardAlreadyCoversDelegate(params: {\n contractAddress: Address;\n delegatorAddress: Address;\n delegateAddress: Address;\n }): Promise<void> {\n try {\n const { isActive } = await this.getStatus({ ...params, contractAddress: WILDCARD_CONTRACT });\n if (isActive) {\n this.#logger.warn(\n `delegateDecryption: ${params.delegateAddress} already holds an active wildcard ` +\n `delegation from ${params.delegatorAddress}; this grant for ${params.contractAddress} is redundant.`,\n );\n }\n } catch (error) {\n this.#logger.warn(\"delegateDecryption: wildcard redundancy check failed\", { error });\n }\n }\n\n #needsBlockTimestamp(expiryTimestamp: bigint): boolean {\n return expiryTimestamp !== 0n && expiryTimestamp !== MAX_UINT64;\n }\n\n #resolveStatus(expiryTimestamp: bigint, now: bigint | undefined): DelegationStatus {\n if (expiryTimestamp === 0n) {\n return { isActive: false, expiryTimestamp };\n }\n if (expiryTimestamp === MAX_UINT64) {\n return { isActive: true, expiryTimestamp };\n }\n return { isActive: now !== undefined && expiryTimestamp > now, expiryTimestamp };\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 = this.#router.relayer.chain.aclContractAddress;\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 /** The confidential contract the write is scoped to; omitted for account-wide writes. */\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 /**\n * Invalidate every decryption signature this signer produced before\n * `timestamp`, via `ACL.invalidateDecryptionSignaturesBefore`.\n *\n * @param timestamp - Oldest timestamp that remains valid. Omit to let the chain\n * resolve the cutoff from the current block timestamp, avoiding client clock skew.\n */\n async invalidateDecryptionSignaturesBefore(\n signer: GenericSigner,\n timestamp?: Date,\n ): Promise<TransactionResult> {\n const acl = this.#router.relayer.chain.aclContractAddress;\n const cutoff = timestamp ? BigInt(Math.floor(timestamp.getTime() / 1000)) : 0n;\n return this.#submitAclTransaction({\n operation: \"invalidateDecryptionSignatures\",\n signer,\n config: invalidateDecryptionSignaturesBeforeContract(acl, cutoff),\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 { isActive, expiryTimestamp } = await this.getStatus({\n contractAddress: normalizedContract,\n delegatorAddress: normalizedDelegator,\n delegateAddress: normalizedDelegate,\n });\n if (isActive) {\n return;\n }\n if (expiryTimestamp === 0n) {\n throw new DelegationNotFoundError(\n `No active delegation from ${normalizedDelegator} to ${normalizedDelegate} for ${normalizedContract}`,\n );\n }\n throw new DelegationExpiredError(\n `Delegation from ${normalizedDelegator} to ${normalizedDelegate} for ${normalizedContract} has expired`,\n );\n }\n}\n","import { getAddress } from \"viem\";\nimport type { ChainRouter } from \"../chains/router\";\nimport { wrapEncryptError } from \"../errors\";\nimport type { ZamaSDKEventInput } from \"../events/sdk-events\";\nimport { ZamaSDKEvents } from \"../events/sdk-events\";\nimport type { EncryptParams, EncryptResult, FhevmRelayerOptions } from \"../relayer/types\";\nimport { toError } from \"../utils\";\n\nexport class EncryptionService {\n readonly #router: ChainRouter;\n readonly #emitEvent: (\n input: ZamaSDKEventInput,\n tokenAddress?: EncryptParams[\"contractAddress\"],\n ) => void;\n\n constructor({\n router,\n emitEvent,\n }: {\n router: ChainRouter;\n emitEvent: (input: ZamaSDKEventInput, tokenAddress?: EncryptParams[\"contractAddress\"]) => void;\n }) {\n this.#router = router;\n this.#emitEvent = emitEvent;\n }\n\n async encryptValues(\n params: EncryptParams,\n options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">,\n ): Promise<EncryptResult> {\n const t0 = Date.now();\n const normalizedContractAddress = getAddress(params.contractAddress);\n try {\n this.#emitEvent({ type: ZamaSDKEvents.EncryptStart }, normalizedContractAddress);\n const result = await this.#router.relayer.encryptValues({ ...params, options });\n this.#emitEvent(\n { type: ZamaSDKEvents.EncryptEnd, durationMs: Date.now() - t0 },\n normalizedContractAddress,\n );\n return result;\n } catch (error) {\n this.#emitEvent(\n { type: ZamaSDKEvents.EncryptError, error: toError(error), durationMs: Date.now() - t0 },\n normalizedContractAddress,\n );\n throw wrapEncryptError(error, \"Encryption failed\");\n }\n }\n}\n","import type { CredentialService } from \"../credentials/credential-service\";\nimport type { ChainRouter } from \"../chains/router\";\nimport type {\n GenericLogger,\n GenericSigner,\n WalletAccountChange,\n WalletAccountListener,\n} from \"../types\";\nimport { swallow } from \"../utils\";\nimport type { CachingService } from \"./caching-service\";\n\nexport type LifecycleServiceOptions = {\n signer?: GenericSigner;\n router: ChainRouter;\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 #router: ChainRouter;\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.#router = opts.router;\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 router on next.chainId. Downstream\n // keypair warming (driven by listeners — see ZamaProvider) therefore\n // dispatches against the wallet chain rather than chains[0]. Switching to a\n // chain with no configured backend does not throw here — the router tracks\n // it and the next relayer op surfaces a ConfigurationError — so `swallow`\n // is defensive only. It suspends one microtask for error containment, not\n // for I/O; ChainRouter.switchChain is synchronous.\n const nextChainId = next?.chainId;\n if (nextChainId !== undefined) {\n await swallow(\n \"switch relayer chain\",\n () => this.#router.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","import { size } from \"viem\";\nimport { z } from \"zod/mini\";\nimport type {\n ApproveUnderlyingRequest,\n ConfidentialTransferFromRequest,\n ConfidentialTransferRequest,\n DelegateDecryptionRequest,\n FinalizeUnwrapRequest,\n PrepareOptions,\n PrepareTransactionRequest,\n RevokeDelegationRequest,\n SetOperatorRequest,\n TransferAndCallRequest,\n UnwrapAllRequest,\n UnwrapRequest,\n WrapRequest,\n WriteContractConfig,\n} from \"../types\";\nimport { checksummedAddress, hex, unixSeconds } from \"./primitives\";\n\n/**\n * {@link ConfidentialTransferRequest} schema.\n * @internal\n */\nexport const confidentialTransferRequest = z.object({\n kind: z.literal(\"ConfidentialTransfer\"),\n from: checksummedAddress,\n token: checksummedAddress,\n to: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<ConfidentialTransferRequest>;\n\n/**\n * {@link ConfidentialTransferFromRequest} schema.\n * @internal\n */\nexport const confidentialTransferFromRequest = z.object({\n kind: z.literal(\"ConfidentialTransferFrom\"),\n from: checksummedAddress,\n token: checksummedAddress,\n owner: checksummedAddress,\n to: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<ConfidentialTransferFromRequest>;\n\n/**\n * {@link SetOperatorRequest} schema. `until` is a required unix timestamp\n * (seconds); pass `0 < until < now` to revoke.\n * @internal\n */\nexport const setOperatorRequest = z.object({\n kind: z.literal(\"SetOperator\"),\n from: checksummedAddress,\n token: checksummedAddress,\n operator: checksummedAddress,\n until: unixSeconds,\n}) satisfies z.ZodMiniType<SetOperatorRequest>;\n\n/**\n * {@link UnwrapRequest} schema.\n * @internal\n */\nexport const unwrapRequest = z.object({\n kind: z.literal(\"Unwrap\"),\n from: checksummedAddress,\n token: checksummedAddress,\n to: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<UnwrapRequest>;\n\n/**\n * {@link UnwrapAllRequest} schema.\n * @internal\n */\nexport const unwrapAllRequest = z.object({\n kind: z.literal(\"UnwrapAll\"),\n from: checksummedAddress,\n token: checksummedAddress,\n to: checksummedAddress,\n}) satisfies z.ZodMiniType<UnwrapAllRequest>;\n\n/**\n * {@link FinalizeUnwrapRequest} schema.\n * @internal\n */\nexport const finalizeUnwrapRequest = z.object({\n kind: z.literal(\"FinalizeUnwrap\"),\n from: checksummedAddress,\n wrapper: checksummedAddress,\n unwrapRequestIdOrAmount: hex,\n}) satisfies z.ZodMiniType<FinalizeUnwrapRequest>;\n\n/**\n * {@link ApproveUnderlyingRequest} schema.\n * @internal\n */\nexport const approveUnderlyingRequest = z.object({\n kind: z.literal(\"ApproveUnderlying\"),\n from: checksummedAddress,\n underlying: checksummedAddress,\n spender: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<ApproveUnderlyingRequest>;\n\n/**\n * {@link WrapRequest} schema.\n * @internal\n */\nexport const wrapRequest = z.object({\n kind: z.literal(\"Wrap\"),\n from: checksummedAddress,\n wrapper: checksummedAddress,\n to: checksummedAddress,\n amount: z.bigint(),\n}) satisfies z.ZodMiniType<WrapRequest>;\n\n/**\n * `TransferAndCall` recipient payload: `0x` (self-shield to the sender) or a\n * raw 20-byte address. The wrapper's receiver hook does\n * `to = data.length < 20 ? from : address(bytes20(data))`, so any other\n * non-empty value (e.g. a 32-byte ABI-encoded address) is truncated to its\n * first 20 bytes — minting the shielded funds to a garbage address. Reject\n * those rather than let the funds go astray; omit for a self-shield.\n */\nconst recipientData = hex.check(\n z.refine(\n (data) => data === \"0x\" || size(data) === 20,\n 'TransferAndCall.recipientData must be \"0x\" (self-shield to the sender) or a raw 20-byte address, ' +\n \"not a 32-byte ABI-encoded value the wrapper would truncate to a garbage address\",\n ),\n);\n\n/**\n * {@link TransferAndCallRequest} schema. `recipientData` is 20 raw bytes or `0x`.\n * @internal\n */\nexport const transferAndCallRequest = z.object({\n kind: z.literal(\"TransferAndCall\"),\n from: checksummedAddress,\n underlying: checksummedAddress,\n wrapper: checksummedAddress,\n amount: z.bigint(),\n recipientData: z.optional(recipientData),\n}) satisfies z.ZodMiniType<TransferAndCallRequest>;\n\n/**\n * {@link DelegateDecryptionRequest} schema. Input takes an optional\n * `expirationDate` (a `Date`); the parsed output is the on-chain `uint64`\n * expiry — seconds since epoch, or `MAX_UINT64` (\"permanent\") when omitted —\n * so callers never hand-roll the encoding.\n *\n * The ≥1h-in-the-future expiry check and the self/contract guards live in the\n * `#buildDelegateDecryption` builder (they throw domain-specific delegation\n * errors this schema can't).\n * @internal\n */\nexport const delegateDecryptionRequest = z.object({\n kind: z.literal(\"DelegateDecryption\"),\n from: checksummedAddress,\n contractAddress: checksummedAddress,\n delegateAddress: checksummedAddress,\n expirationDate: z.optional(z.date()),\n}) satisfies z.ZodMiniType<DelegateDecryptionRequest>;\n\n/**\n * {@link RevokeDelegationRequest} schema.\n * @internal\n */\nexport const revokeDelegationRequest = z.object({\n kind: z.literal(\"RevokeDelegation\"),\n from: checksummedAddress,\n contractAddress: checksummedAddress,\n delegateAddress: checksummedAddress,\n}) satisfies z.ZodMiniType<RevokeDelegationRequest>;\n\n/**\n * Discriminated union (on `kind`) of every offline `prepare` request. Backs\n * both the {@link PrepareTransactionRequest} type and the runtime validation\n * in `OfflineService.prepare`.\n * @internal\n */\nexport const prepareTransactionRequest = z.discriminatedUnion(\"kind\", [\n confidentialTransferRequest,\n confidentialTransferFromRequest,\n setOperatorRequest,\n unwrapRequest,\n unwrapAllRequest,\n finalizeUnwrapRequest,\n approveUnderlyingRequest,\n wrapRequest,\n transferAndCallRequest,\n delegateDecryptionRequest,\n revokeDelegationRequest,\n]) satisfies z.ZodMiniType<PrepareTransactionRequest>;\n\n/**\n * {@link PrepareFees} schema. `maxFeePerGas` and `maxPriorityFeePerGas` live in\n * one object so they can only be supplied together — pinning a cap (the total\n * fee) while the tip is estimated can produce a tip above the cap and fail\n * serialization. Both legs are validated as `bigint` so a JS caller (no\n * compiler) can't slip a `number` into the frozen, signed payload.\n * @internal\n */\nexport const fees = z.strictObject({ maxFeePerGas: z.bigint(), maxPriorityFeePerGas: z.bigint() });\n\n/**\n * {@link PrepareOptions} schema. All fields are optional; omitted ones fall\n * back to the provider's live chain-state defaults.\n * @internal\n */\nexport const prepareOptions = z.object({\n nonce: z.optional(z.int().check(z.nonnegative())),\n gasLimit: z.optional(z.bigint()),\n fees: z.optional(fees),\n}) satisfies z.ZodMiniType<PrepareOptions>;\n\n/**\n * `WriteContractConfig` schema. `abi` and `args` are validated only as\n * arrays — their element shapes are the ABI-typed `TAbi`/`TFunctionName`\n * generics the runtime can't check — so this guards the structural envelope\n * (address, function name, the two arrays, optional `value`/`gas`) a provider's\n * tx-builder consumes.\n * @internal\n */\nexport const writeContractConfig = z.object({\n address: checksummedAddress,\n abi: z.array(z.unknown()),\n functionName: z.string(),\n args: z.array(z.unknown()),\n value: z.optional(z.bigint()),\n gas: z.optional(z.bigint()),\n}) satisfies z.ZodMiniType<WriteContractConfig>;\n\n/**\n * Schema for the argument object of `GenericProvider.prepareTransaction`:\n * the originating `from` wallet, the write-contract `calldata`, and the\n * optional chain-state overrides. Extends {@link prepareOptions} so the\n * `nonce`/`gasLimit`/`fees` legs stay in lockstep with the per-call overrides.\n *\n * `from` is EIP-55 checksummed on parse (the custodian keys off it), so the\n * validated output can flow straight into the prepared handoff.\n * @internal\n */\nexport const prepareTransactionParams = z.extend(prepareOptions, {\n from: checksummedAddress,\n calldata: writeContractConfig,\n});\n","import type { Address } from \"viem\";\nimport type { ChainRouter } from \"../chains/router\";\nimport {\n approveContract,\n confidentialBalanceOfContract,\n confidentialTransferContract,\n confidentialTransferFromContract,\n delegateForUserDecryptionContract,\n finalizeUnwrapContract,\n MAX_UINT64,\n revokeDelegationContract,\n setOperatorContract,\n transferAndCallContract,\n unwrapContract,\n unwrapFromBalanceContract,\n wrapContract,\n} from \"../contracts\";\nimport {\n ConfigurationError,\n DelegationDelegateEqualsContractError,\n DelegationExpirationTooSoonError,\n DelegationSelfNotAllowedError,\n EncryptionFailedError,\n wrapDecryptError,\n} from \"../errors\";\nimport type { ZamaSDKEventInput } from \"../events/sdk-events\";\nimport {\n approveUnderlyingRequest,\n confidentialTransferFromRequest,\n confidentialTransferRequest,\n delegateDecryptionRequest,\n finalizeUnwrapRequest,\n prepareOptions,\n prepareTransactionParams,\n revokeDelegationRequest,\n setOperatorRequest,\n transferAndCallRequest,\n unwrapAllRequest,\n unwrapRequest,\n wrapRequest,\n} from \"../schemas/offline\";\nimport type {\n ApproveUnderlyingRequest,\n ConfidentialTransferFromRequest,\n ConfidentialTransferRequest,\n DelegateDecryptionRequest,\n FinalizeUnwrapRequest,\n GenericProvider,\n PreparedFor,\n PrepareOptions,\n PrepareTransactionRequest,\n RevokeDelegationRequest,\n SetOperatorRequest,\n TransactionKind,\n TransferAndCallRequest,\n UnwrapAllRequest,\n UnwrapRequest,\n WrapRequest,\n} from \"../types\";\nimport { assertBigint } from \"../utils/assertions\";\nimport { parseSchema } from \"../validation\";\nimport type { EncryptionService } from \"./encryption-service\";\n\n/**\n * Configuration for {@link OfflineService}.\n *\n * @internal\n */\nexport interface OfflineServiceConfig {\n readonly provider: GenericProvider;\n readonly router: ChainRouter;\n readonly encryption: EncryptionService;\n readonly emitEvent: (input: ZamaSDKEventInput, tokenAddress?: Address) => void;\n}\n\n/**\n * Offline-signing pipeline. Builds an RLP-encoded unsigned transaction that\n * the caller signs **and** publishes out-of-process — for institutional\n * custody, HSM ceremonies, and policy-engine workflows where signing cannot\n * happen synchronously in a single Promise.\n *\n * Atomic call sites ({@link Token.confidentialTransfer}, etc.) keep their\n * `signer.writeContract` path; this service is the parallel route where the\n * caller signs `prepared.unsignedTx` externally (HSM, custody API, policy\n * engine) and publishes the signed bytes through its own channel.\n *\n * Owned by {@link ZamaSDK}.\n *\n * @internal\n */\nexport class OfflineService {\n readonly #provider: GenericProvider;\n readonly #router: ChainRouter;\n readonly #encryption: EncryptionService;\n\n constructor(config: OfflineServiceConfig) {\n this.#provider = config.provider;\n this.#router = config.router;\n this.#encryption = config.encryption;\n }\n\n // ── prepare ─────────────────────────────────────────────────────────────\n\n /**\n * Build the offline-signing payload for the given transaction request:\n * an RLP-encoded unsigned transaction the caller signs externally (an HSM,\n * custody API, or any out-of-process signer) and publishes through its own\n * channel.\n *\n * Decryption permits are not transactions — acquire them via\n * `sdk.permits.grantPermit`, which signs with the configured signer\n * (including an out-of-process custody signer).\n */\n async prepare<K extends TransactionKind>(\n request: Extract<PrepareTransactionRequest, { kind: K }>,\n options?: PrepareOptions,\n ): Promise<PreparedFor<K>> {\n if (options) {\n options = parseSchema(prepareOptions, options);\n }\n\n // The prepared tx's contract addresses and encrypted inputs are bound to\n // the SDK's configured chain; if the provider is on a different chain it\n // would bake that chain's id into a tx carrying wrong-chain addresses.\n // No signer here (offline is signer-less), so guard router vs provider\n // directly rather than through requireChainAlignment.\n const providerChainId = await this.#provider.getChainId();\n const expectedChainId = this.#router.chain.id;\n if (providerChainId !== expectedChainId) {\n throw new ConfigurationError(\n `Offline.prepare: provider is on chain ${providerChainId} but the SDK is configured for chain ${expectedChainId}. ` +\n `The prepared transaction's contract addresses and encrypted inputs are bound to chain ${expectedChainId} — point the provider at the same chain.`,\n );\n }\n\n const calldata = await this.#buildCalldata(request);\n const params = {\n calldata,\n from: request.from,\n nonce: options?.nonce,\n gasLimit: options?.gasLimit,\n fees: options?.fees,\n };\n const parsed = parseSchema(prepareTransactionParams, params);\n const unsignedTx = await this.#provider.prepareTransaction(parsed);\n return { kind: request.kind, unsignedTx, from: parsed.from } satisfies PreparedFor<K>;\n }\n\n // ── internals ──────────────────────────────────────────────────────────\n\n async #buildCalldata(\n request: PrepareTransactionRequest,\n ): Promise<{\n readonly address: Address;\n readonly abi: readonly unknown[];\n readonly functionName: string;\n readonly args: readonly unknown[];\n }> {\n switch (request.kind) {\n case \"ConfidentialTransfer\":\n return this.#buildConfidentialTransfer(request);\n case \"ConfidentialTransferFrom\":\n return this.#buildConfidentialTransferFrom(request);\n case \"SetOperator\":\n return this.#buildSetOperator(request);\n case \"Unwrap\":\n return this.#buildUnwrap(request);\n case \"UnwrapAll\":\n return this.#buildUnwrapAll(request);\n case \"FinalizeUnwrap\":\n return this.#buildFinalizeUnwrap(request);\n case \"ApproveUnderlying\":\n return this.#buildApproveUnderlying(request);\n case \"Wrap\":\n return this.#buildWrap(request);\n case \"TransferAndCall\":\n return this.#buildTransferAndCall(request);\n case \"DelegateDecryption\":\n return this.#buildDelegateDecryption(request);\n case \"RevokeDelegation\":\n return this.#buildRevokeDelegation(request);\n default: {\n const unhandled: { kind: string } = request;\n throw new ConfigurationError(\n `OfflineService.prepare: unsupported transaction kind '${unhandled.kind}'.`,\n );\n }\n }\n }\n\n async #buildConfidentialTransfer(\n request: ConfidentialTransferRequest,\n ): Promise<ReturnType<typeof confidentialTransferContract>> {\n request = parseSchema(confidentialTransferRequest, request);\n const { encryptedValues, inputProof } = await this.#encryption.encryptValues({\n values: [{ value: request.amount, type: \"euint64\" }],\n contractAddress: request.token,\n userAddress: request.from,\n });\n const handle = encryptedValues[0];\n if (!handle) {\n throw new EncryptionFailedError(\"Encryption returned no handles for ConfidentialTransfer\");\n }\n return confidentialTransferContract(request.token, request.to, handle, inputProof);\n }\n\n async #buildConfidentialTransferFrom(\n request: ConfidentialTransferFromRequest,\n ): Promise<ReturnType<typeof confidentialTransferFromContract>> {\n request = parseSchema(confidentialTransferFromRequest, request);\n // The encrypted input's proof binds to the tx sender (fhevm verifies it\n // against `msg.sender`), which for `transferFrom` is the operator == the\n // `from` wallet that signs and broadcasts — not the `owner` being debited.\n const { encryptedValues, inputProof } = await this.#encryption.encryptValues({\n values: [{ value: request.amount, type: \"euint64\" }],\n contractAddress: request.token,\n userAddress: request.from,\n });\n const handle = encryptedValues[0];\n if (!handle) {\n throw new EncryptionFailedError(\n \"Encryption returned no handles for ConfidentialTransferFrom\",\n );\n }\n return confidentialTransferFromContract(\n request.token,\n request.owner,\n request.to,\n handle,\n inputProof,\n );\n }\n\n #buildSetOperator(request: SetOperatorRequest): ReturnType<typeof setOperatorContract> {\n request = parseSchema(setOperatorRequest, request);\n return setOperatorContract(request.token, request.operator, request.until);\n }\n\n async #buildUnwrap(request: UnwrapRequest): Promise<ReturnType<typeof unwrapContract>> {\n request = parseSchema(unwrapRequest, request);\n const { encryptedValues, inputProof } = await this.#encryption.encryptValues({\n values: [{ value: request.amount, type: \"euint64\" }],\n contractAddress: request.token,\n userAddress: request.from,\n });\n const handle = encryptedValues[0];\n if (!handle) {\n throw new EncryptionFailedError(\"Encryption returned no handles for Unwrap\");\n }\n return unwrapContract(request.token, request.from, request.to, handle, inputProof);\n }\n\n async #buildUnwrapAll(\n request: UnwrapAllRequest,\n ): Promise<ReturnType<typeof unwrapFromBalanceContract>> {\n request = parseSchema(unwrapAllRequest, request);\n const balanceHandle = await this.#provider.readContract(\n confidentialBalanceOfContract(request.token, request.from),\n );\n return unwrapFromBalanceContract(request.token, request.from, request.to, balanceHandle);\n }\n\n async #buildFinalizeUnwrap(\n request: FinalizeUnwrapRequest,\n ): Promise<ReturnType<typeof finalizeUnwrapContract>> {\n request = parseSchema(finalizeUnwrapRequest, request);\n const decrypted = await this.#router.relayer\n .decryptPublicValuesWithSignatures({ encryptedValues: [request.unwrapRequestIdOrAmount] })\n .catch((error: unknown) => {\n throw wrapDecryptError(error, \"Public decryption failed during FinalizeUnwrap\");\n });\n const raw = decrypted.clearValues[0]?.value;\n assertBigint(raw, \"FinalizeUnwrap: decryptPublicValuesWithSignatures(handle).clearValue\");\n return finalizeUnwrapContract(\n request.wrapper,\n request.unwrapRequestIdOrAmount,\n raw,\n decrypted.checkSignaturesArgs.decryptionProof,\n );\n }\n\n #buildApproveUnderlying(request: ApproveUnderlyingRequest): ReturnType<typeof approveContract> {\n request = parseSchema(approveUnderlyingRequest, request);\n return approveContract(request.underlying, request.spender, request.amount);\n }\n\n #buildWrap(request: WrapRequest): ReturnType<typeof wrapContract> {\n request = parseSchema(wrapRequest, request);\n return wrapContract(request.wrapper, request.to, request.amount);\n }\n\n #buildTransferAndCall(\n request: TransferAndCallRequest,\n ): ReturnType<typeof transferAndCallContract> {\n request = parseSchema(transferAndCallRequest, request);\n return transferAndCallContract(\n request.underlying,\n request.wrapper,\n request.amount,\n request.recipientData,\n );\n }\n\n #buildDelegateDecryption(\n request: DelegateDecryptionRequest,\n ): ReturnType<typeof delegateForUserDecryptionContract> {\n request = parseSchema(delegateDecryptionRequest, request);\n // Expiry ≥1h out: an expiry under 1h lands already-expired (or nearly so),\n // and the offline payload is signed/broadcast later, eating into that\n // margin further. Checked against the pre-parse `Date` (the schema\n // transforms it into the on-chain uint64 below).\n if (request.expirationDate && request.expirationDate.getTime() < Date.now() + 3_600_000) {\n throw new DelegationExpirationTooSoonError(\n \"Expiration date must be at least 1 hour in the future\",\n );\n }\n if (request.delegateAddress === request.from) {\n throw new DelegationSelfNotAllowedError(\n \"Cannot delegate to yourself (delegate === msg.sender).\",\n );\n }\n if (request.delegateAddress === request.contractAddress) {\n throw new DelegationDelegateEqualsContractError(\n `Delegate address cannot be the same as the contract address (${request.contractAddress}).`,\n );\n }\n const expirationDate = request.expirationDate\n ? BigInt(Math.floor(request.expirationDate.getTime() / 1000))\n : MAX_UINT64;\n return delegateForUserDecryptionContract(\n this.#router.chain.aclContractAddress,\n request.delegateAddress,\n request.contractAddress,\n expirationDate,\n );\n }\n\n #buildRevokeDelegation(\n request: RevokeDelegationRequest,\n ): ReturnType<typeof revokeDelegationContract> {\n request = parseSchema(revokeDelegationRequest, request);\n return revokeDelegationContract(\n this.#router.chain.aclContractAddress,\n request.delegateAddress,\n request.contractAddress,\n );\n }\n}\n","import type { Address } from \"viem\";\nimport type { ChainRouter } from \"./chains/router\";\nimport type { ZamaConfig } from \"./config/types\";\nimport { CredentialService } from \"./credentials/credential-service\";\nimport { DerivationSecretHolder } from \"./credentials/keypair-wrapping\";\nimport { DerivationSecretSchema } from \"./credentials/schemas\";\nimport { ConfigurationError } from \"./errors\";\nimport type { ZamaSDKEvent, ZamaSDKEventInput, ZamaSDKEventListener } from \"./events/sdk-events\";\nimport { Decryption } from \"./namespaces/decryption\";\nimport { Delegations } from \"./namespaces/delegations\";\nimport { Offline } from \"./namespaces/offline\";\nimport { Permits } from \"./namespaces/permits\";\nimport type { EncryptParams, FhevmRelayerOptions, RelayerSDK } from \"./relayer/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 { OfflineService } from \"./services/offline-service\";\nimport { Token } from \"./token/token\";\nimport { WrappedToken } from \"./token/wrapped-token\";\nimport type {\n GenericLogger,\n GenericProvider,\n GenericSigner,\n GenericStorage,\n WalletAccountListener,\n} from \"./types\";\nimport { parseSchema } from \"./validation\";\nimport { WrappersRegistry } from \"./wrappers-registry\";\n\n/** Instance-level options that are deliberately not part of the shareable config object. */\nexport interface ZamaSDKOptions {\n /**\n * Encrypts the transport key pair's private half at rest. Headless environments only\n * (CLI tools, servers, agents); the constructor rejects it in browser contexts. Supply\n * at least 32 random bytes, or a string of at least 64 characters, from a CSPRNG or\n * secrets manager. The SDK copies a Uint8Array secret and zeroizes its own copy after\n * key import; it never touches your buffer, so zeroize yours after construction.\n * The SDK never persists or exposes this value. Omit for the default:\n * plaintext at rest, security delegated to the storage backend.\n */\n transportKeyPairDerivationSecret?: string | Uint8Array;\n}\n\n/**\n * Omitting the option means cleartext-at-rest by choice; passing it as `undefined` means the\n * caller asked for wrapping and the value went missing, so it must fail instead of downgrading.\n */\nfunction assertDerivationSecretNotUnset(options: ZamaSDKOptions): void {\n if (\n !Object.hasOwn(options, \"transportKeyPairDerivationSecret\") ||\n options.transportKeyPairDerivationSecret !== undefined\n ) {\n return;\n }\n throw new ConfigurationError(\n \"transportKeyPairDerivationSecret was passed as undefined, which usually means the environment variable it reads is unset (e.g. process.env.ZAMA_DERIVATION_SECRET). Supply the secret, or omit the option entirely to persist transport key pairs in cleartext on purpose.\",\n );\n}\n\n/**\n * Wrapping only helps where no platform keystore protects the store, which is the headless\n * case. `importScripts` catches a browser worker, where `window` and `document` are absent.\n */\nfunction assertDerivationSecretHeadless(secret: string | Uint8Array | undefined): void {\n if (secret === undefined) {\n return;\n }\n const { importScripts } = globalThis as { importScripts?: unknown };\n const headless =\n typeof window === \"undefined\" &&\n typeof document === \"undefined\" &&\n typeof importScripts !== \"function\";\n if (headless) {\n return;\n }\n throw new ConfigurationError(\n \"transportKeyPairDerivationSecret is supported in headless environments only (CLI tools, servers, agents). Remove the option: an environment with a platform keystore, or one that ships a bundle, must delegate at-rest security of the transport key pair to the storage backend.\",\n );\n}\n\n/**\n * Copies a `Uint8Array` secret so the holder only ever zeroizes the SDK's own buffer, and\n * a caller zeroizing theirs cannot corrupt later wraps. Strings are immutable, so no copy.\n */\nfunction derivationSecretHolder(\n secret: string | Uint8Array | undefined,\n): DerivationSecretHolder | undefined {\n if (secret === undefined) {\n return undefined;\n }\n const parsed = parseSchema(DerivationSecretSchema, secret);\n return new DerivationSecretHolder(typeof parsed === \"string\" ? parsed : new Uint8Array(parsed));\n}\n\n/**\n * ZamaSDK — composes a RelayerSDK with contract abstraction.\n *\n * Exposes domain namespaces for permits, delegations, decryption, offline\n * signing, and tokens, plus an unchanged registry, a top-level `encrypt`, and\n * lifecycle methods. Internal `*Service` classes do the work; the namespace\n * classes own SDK-level guards (chain alignment, signer requirement, event\n * emission).\n */\nexport class ZamaSDK {\n readonly #router: ChainRouter;\n /** Read-only chain access used for all contract reads. */\n readonly provider: GenericProvider;\n /** Wallet signer used for write operations, or `undefined` when the SDK is read-only. */\n readonly signer: GenericSigner | undefined;\n /** Storage for cached permits and transport key pairs. */\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 /** Offline-signing pipeline: `prepare` builds an unsigned tx the caller signs and broadcasts out-of-process — for HSM, policy-engine, and cross-process custody workflows. */\n readonly offline: Offline;\n readonly #registryTTL: number;\n readonly #registryAddresses: Record<number, Address>;\n readonly #onEvent: ZamaSDKEventListener;\n readonly #logger: GenericLogger;\n readonly #cachingService: CachingService;\n readonly #lifecycleService: LifecycleService;\n readonly #encryptionService: EncryptionService;\n readonly #decryptionService: DecryptionService | undefined;\n readonly #credentialService: CredentialService;\n readonly #delegationService: DelegationService;\n readonly #offlineService: OfflineService;\n\n constructor(config: ZamaConfig, options: ZamaSDKOptions = {}) {\n assertDerivationSecretNotUnset(options);\n assertDerivationSecretHeadless(options.transportKeyPairDerivationSecret);\n // Constructor-local on purpose: neither the raw secret nor the holder may become a field.\n const derivationSecret = derivationSecretHolder(options.transportKeyPairDerivationSecret);\n\n this.#router = config.router;\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 router: config.router,\n emitEvent: this.emitEvent.bind(this),\n logger: this.#logger,\n });\n\n const registryAddresses: Record<number, Address> = {};\n for (const chain of config.chains) {\n if (chain.registryAddress) {\n registryAddresses[chain.id] = chain.registryAddress;\n }\n }\n this.registry = new WrappersRegistry({\n provider: this.provider,\n registryAddresses,\n registryTTL: config.registryTTL,\n });\n this.#registryAddresses = registryAddresses;\n this.#registryTTL = config.registryTTL;\n\n // CredentialService is always constructed (with optional signer) so\n // public-decrypt / encryption flows and pre-wallet-connect construction\n // work; permit-signing methods require a signer and throw without one.\n this.#credentialService = new CredentialService({\n router: config.router,\n signer: config.signer,\n transportKeyPairTTL: config.transportKeyPairTTL,\n permitTTL: config.permitTTL,\n scope: config.transportKeyPairScope,\n derivationSecret,\n storage: this.storage,\n permitStorage: config.permitStorage,\n logger: this.#logger,\n emitEvent: this.emitEvent.bind(this),\n });\n if (config.signer) {\n this.#decryptionService = new DecryptionService({\n cache: this.#cachingService,\n credentialService: this.#credentialService,\n delegationService: this.#delegationService,\n router: config.router,\n emitEvent: this.emitEvent.bind(this),\n });\n }\n this.#encryptionService = new EncryptionService({\n router: config.router,\n emitEvent: this.emitEvent.bind(this),\n });\n this.#lifecycleService = new LifecycleService({\n signer: config.signer,\n router: config.router,\n cachingService: this.#cachingService,\n credentialService: this.#credentialService,\n logger: this.#logger,\n });\n this.#offlineService = new OfflineService({\n provider: this.provider,\n router: config.router,\n encryption: this.#encryptionService,\n emitEvent: (input, tokenAddress) => this.emitEvent(input, tokenAddress),\n });\n\n this.permits = new Permits({\n signer: this.signer,\n provider: this.provider,\n cachingService: this.#cachingService,\n credentialService: this.#credentialService,\n delegationService: this.#delegationService,\n logger: this.#logger,\n emitEvent: this.emitEvent.bind(this),\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 router: config.router,\n decryptionService: this.#decryptionService,\n });\n this.offline = new Offline(this.#offlineService, this.#credentialService);\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 * The single-chain relayer backend for the **currently active** chain.\n */\n get relayer(): RelayerSDK {\n return this.#router.relayer;\n }\n\n /**\n * Emit a structured SDK event into the unified SDK event stream.\n *\n * Listener exceptions are caught and logged so that a misbehaving subscriber\n * can never corrupt SDK operations.\n *\n * Application code should subscribe via the `onEvent` config option, never\n * call this directly.\n *\n * @internal\n */\n emitEvent(input: ZamaSDKEventInput, tokenAddress?: Address): void {\n try {\n this.#onEvent({ ...input, tokenAddress, timestamp: Date.now() } as ZamaSDKEvent);\n } catch (error) {\n this.#logger.warn(`${input.type} event listener silently failed`, { error });\n }\n }\n\n /**\n * Create a {@link WrappersRegistry} instance bound to this SDK's provider.\n * Inherits the registry addresses derived from the SDK's chain configs, so\n * the result is consistent with {@link ZamaSDK.registry}.\n *\n * @param registryAddresses - Optional per-chain overrides for this registry instance.\n * @returns A {@link WrappersRegistry} instance.\n *\n * @example\n * ```ts\n * // Addresses resolved from the SDK's chain configs\n * const registry = sdk.createWrappersRegistry();\n *\n * // Hardhat or custom chain — override per chain for this registry instance\n * const registry = sdk.createWrappersRegistry({ [31337]: \"0xYourRegistry\" });\n *\n * const pairs = await registry.getTokenPairs();\n * ```\n */\n createWrappersRegistry(registryAddresses?: Record<number, Address>): WrappersRegistry {\n return new WrappersRegistry({\n provider: this.provider,\n registryAddresses: { ...this.#registryAddresses, ...registryAddresses },\n registryTTL: this.#registryTTL,\n });\n }\n\n /**\n * Encrypt one or more plaintext values into FHE ciphertexts.\n *\n * @param params - Typed FHE inputs, the target contract address, and the user address.\n * @returns External encrypted values and the input proof for on-chain submission.\n * @throws if FHE encryption fails. {@link EncryptionFailedError}\n *\n * @example\n * ```ts\n * const { encryptedValues, inputProof } = await sdk.encrypt({\n * values: [{ value: 1000n, type: \"euint64\" }],\n * contractAddress: \"0xToken\",\n * userAddress: \"0xUser\",\n * });\n * ```\n */\n async encrypt(params: EncryptParams, options?: Pick<FhevmRelayerOptions, \"signal\" | \"timeout\">) {\n return this.#encryptionService.encryptValues(params, options);\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 * Release the SDK-owned resources: signer lifecycle subscriptions and the\n * relayer backend's resources, an encrypt worker included. Call this when the\n * SDK instance is being replaced (e.g. React provider unmount or a Strict Mode\n * remount). Work already in flight runs to completion, and the instance stays\n * usable: the next encryption spawns a fresh worker.\n */\n dispose(): void {\n this.#lifecycleService.dispose();\n this.#router.dispose();\n }\n\n /**\n * {@link dispose} plus the signer's own disposal. Call this when the SDK is no\n * longer needed (e.g. on shutdown). Work already in flight runs to completion.\n */\n terminate(): void {\n this.dispose();\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 releasing the relayer's resources.\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"],"mappings":"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"}