@zama-fhe/sdk 3.7.0-beta.7 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/base-signer.cjs +1 -1
- package/dist/cjs/base-signer.cjs.map +1 -1
- package/dist/cjs/erc165.cjs +1 -1
- package/dist/cjs/erc165.cjs.map +1 -1
- package/dist/cjs/fhevm-relayer.cjs +1 -1
- package/dist/cjs/fhevm-relayer.cjs.map +1 -1
- package/dist/cjs/index.cjs +1 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/telemetry.cjs +1 -1
- package/dist/cjs/telemetry.cjs.map +1 -1
- package/dist/cjs/token.cjs +1 -1
- package/dist/cjs/token.cjs.map +1 -1
- package/dist/cjs/vaults/index.cjs +1 -1
- package/dist/cjs/web/index.cjs +1 -1
- package/dist/cjs/wrapped-token.cjs +1 -1
- package/dist/esm/base-signer-b1ff2VPI.js +2 -0
- package/dist/esm/base-signer-b1ff2VPI.js.map +1 -0
- package/dist/esm/cleartext/index.js +1 -1
- package/dist/esm/{cleartext-BLXvNZte.js → cleartext-CiE1gO7Y.js} +2 -2
- package/dist/esm/{cleartext-BLXvNZte.js.map → cleartext-CiE1gO7Y.js.map} +1 -1
- package/dist/esm/erc165-BAd2z3ay.js +2 -0
- package/dist/esm/erc165-BAd2z3ay.js.map +1 -0
- package/dist/esm/ethers/index.js +1 -1
- package/dist/esm/fhevm-relayer-DXLb4mIw.js +8 -0
- package/dist/esm/{fhevm-relayer-DhaBR8Kb.js.map → fhevm-relayer-DXLb4mIw.js.map} +1 -1
- package/dist/esm/{index-DHMs4ZRb.d.ts → index-BKMce5ya.d.ts} +2 -2
- package/dist/esm/{decryption-q0ODuDDS.d.ts → index-CpQK8U4F.d.ts} +2 -6
- package/dist/esm/index.d.ts +3 -4
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/node/index.js +1 -1
- package/dist/esm/query/index.d.ts +2 -3
- package/dist/esm/query/index.js +1 -1
- package/dist/esm/telemetry-Dll0Swdj.js +2 -0
- package/dist/esm/{telemetry-XTn27hkl.js.map → telemetry-Dll0Swdj.js.map} +1 -1
- package/dist/esm/token-CTvEGQmH.js +2 -0
- package/dist/esm/token-CTvEGQmH.js.map +1 -0
- package/dist/esm/vaults/index.d.ts +1 -2
- package/dist/esm/vaults/index.js +1 -1
- package/dist/esm/viem/index.js +1 -1
- package/dist/esm/web/index.d.ts +16 -1
- package/dist/esm/web/index.js +1 -1
- package/dist/esm/wrapped-token-IDUEFpZx.js +2 -0
- package/dist/esm/{wrapped-token-3usJd0oi.js.map → wrapped-token-IDUEFpZx.js.map} +1 -1
- package/package.json +1 -15
- package/dist/cjs/fatal-batch.cjs +0 -2
- package/dist/cjs/fatal-batch.cjs.map +0 -1
- package/dist/cjs/internal/index.cjs +0 -2
- package/dist/cjs/internal/index.cjs.map +0 -1
- package/dist/cjs/signing.cjs +0 -2
- package/dist/cjs/signing.cjs.map +0 -1
- package/dist/esm/base-signer-CNHZZnr2.js +0 -2
- package/dist/esm/base-signer-CNHZZnr2.js.map +0 -1
- package/dist/esm/encrypt-worker-client-CKTlhAGI.d.ts +0 -19
- package/dist/esm/erc165-B8gx2luK.js +0 -2
- package/dist/esm/erc165-B8gx2luK.js.map +0 -1
- package/dist/esm/fatal-batch-BiiS7KdS.js +0 -2
- package/dist/esm/fatal-batch-BiiS7KdS.js.map +0 -1
- package/dist/esm/fhevm-relayer-DhaBR8Kb.js +0 -8
- package/dist/esm/index-B09m_e9L.d.ts +0 -1
- package/dist/esm/internal/index.d.ts +0 -26
- package/dist/esm/internal/index.js +0 -2
- package/dist/esm/internal/index.js.map +0 -1
- package/dist/esm/signing-C6nbPCyd.js +0 -2
- package/dist/esm/signing-C6nbPCyd.js.map +0 -1
- package/dist/esm/telemetry-XTn27hkl.js +0 -2
- package/dist/esm/token-g6sinwTx.js +0 -2
- package/dist/esm/token-g6sinwTx.js.map +0 -1
- package/dist/esm/wrapped-token-3usJd0oi.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrapped-token-3usJd0oi.js","names":["#getUnderlying","#isPayable","#shieldViaTransferAndCall","#shieldViaApproveAndWrap","#requireSigner","#ensureAllowance","#unwrap","#finalizeUnshield","#extractUnwrapRequestId","#isUnwrapRequestConsumed","#clearStoredPendingUnshield","#isPendingUnshieldConsumed","#finalizeUnwrap","#underlying","#underlyingPromise"],"sources":["../../src/errors/revert.ts","../../src/errors/unshield.ts","../../src/abi/erc1363.abi.ts","../../src/contracts/erc1363.ts","../../src/utils/hex.ts","../../src/events/log-decoding.ts","../../src/events/onchain-events.ts","../../src/token/pending-unshield.ts","../../src/token/wrapped-token.ts"],"sourcesContent":["/**\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","// DO NOT EDIT: generated by `pnpm abi:build` from\n// contracts/out/IERC1363.sol/IERC1363.json.\n// Regenerate after `pnpm contracts:build`; `pnpm abi:check` enforces this in CI.\nexport const erc1363Abi = [\n {\n type: \"function\",\n name: \"allowance\",\n inputs: [\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"approve\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"approveAndCall\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"approveAndCall\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"balanceOf\",\n inputs: [{ name: \"account\", type: \"address\", internalType: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"supportsInterface\",\n inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"totalSupply\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"transfer\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferAndCall\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferAndCall\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFrom\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFromAndCall\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFromAndCall\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"event\",\n name: \"Approval\",\n inputs: [\n { name: \"owner\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"spender\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n ],\n anonymous: false,\n },\n {\n type: \"event\",\n name: \"Transfer\",\n inputs: [\n { name: \"from\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"to\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n ],\n anonymous: false,\n },\n] as const;\n","import type { Address, Hex } from \"viem\";\nimport { erc1363Abi } from \"../abi/erc1363.abi\";\n\n/**\n * Returns the contract config for an ERC-1363 `transferAndCall`.\n *\n * @param tokenAddress - The ERC-20 token to transfer from (the underlying, not the wrapper).\n * @param to - The recipient of the ERC-20 transfer. In `Token.shield`, this is\n * the wrapper contract whose `onTransferReceived` callback mints\n * confidential tokens to the address encoded in `data`.\n * @param amount - The amount to transfer.\n * @param data - Raw 20-byte recipient address for shield-to-other (decoded by\n * the wrapper as `address(bytes20(data))`). Empty `0x` for self-shield —\n * the wrapper falls back to `from`.\n */\nexport function transferAndCallContract(\n tokenAddress: Address,\n to: Address,\n amount: bigint,\n data: Hex = \"0x\",\n) {\n return {\n address: tokenAddress,\n abi: erc1363Abi,\n functionName: \"transferAndCall\",\n args: [to, amount, data],\n } as const;\n}\n","import type { 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 * Primitives for decoding raw EVM logs without an ABI decoder.\n *\n * @internal\n */\n\nimport { getAddress, keccak256, toBytes, type Address, type Hex } from \"viem\";\nimport type { EncryptedValue } from \"../relayer/types\";\nimport { prefixHex } from \"../utils\";\n\n/** Hashes the canonical signature — `Joined(uint256,address,bytes32)`, not the declaration with parameter names. */\nexport function eventTopic(signature: string): Hex {\n return keccak256(toBytes(signature));\n}\n\nexport function topicToAddress(topic: Hex): Address {\n return getAddress(prefixHex(topic.slice(-40)));\n}\n\nexport function topicToBytes32(topic: Hex): EncryptedValue {\n // EVM topics are already 32-byte 0x-prefixed hex — cast directly\n return topic as EncryptedValue;\n}\n\nexport function 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\nexport function wordToAddress(data: Hex, index: number): Address {\n return getAddress(prefixHex(wordAt(data, index).slice(-40)));\n}\n\nexport function wordToBigInt(data: Hex, index: number): bigint {\n return BigInt(\"0x\" + wordAt(data, index));\n}\n\nexport function 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 * 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 type { Address } from \"viem\";\nimport type { RawLog } from \"../types/transaction\";\nimport {\n eventTopic,\n topicToAddress,\n topicToBytes32,\n wordToAddress,\n wordToBigInt,\n wordToBytes32,\n} from \"./log-decoding\";\nexport type { RawLog } from \"../types/transaction\";\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// 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 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 type { TelemetryOperation } from \"../telemetry\";\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, \"unshield\");\n }\n\n const callbacks: UnshieldCallbacks = { onFinalizing, onFinalizeSubmitted };\n const operationId = crypto.randomUUID();\n const unwrapResult = await this.#unwrap(amount, \"unshield\");\n void swallow(\n \"unshield: onUnwrapSubmitted\",\n () => onUnwrapSubmitted?.(unwrapResult.txHash),\n this.sdk.logger,\n );\n // Reuse the id the unwrap already decoded — no second receipt fetch or decode.\n return this.#finalizeUnshield(\n unwrapResult.unwrapRequestId,\n unwrapResult.txHash,\n operationId,\n callbacks,\n \"unshield\",\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 \"unshield-all\",\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(\n unwrapRequestId,\n unwrapTxHash,\n crypto.randomUUID(),\n callbacks,\n \"resume-unshield\",\n );\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 return this.#unwrap(amount, \"unwrap\");\n }\n\n async #unwrap(amount: bigint, telemetryOperation: TelemetryOperation): 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\" }], contractAddress: this.address, userAddress },\n { operation: telemetryOperation },\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 return this.#finalizeUnwrap(unwrapRequestId, \"finalize-unwrap\");\n }\n\n async #finalizeUnwrap(\n unwrapRequestId: EncryptedValue,\n telemetryOperation: TelemetryOperation,\n ): 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 operation: telemetryOperation,\n });\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 telemetryOperation: TelemetryOperation,\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, telemetryOperation);\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"wrapped-token-IDUEFpZx.js","names":["#getUnderlying","#isPayable","#shieldViaTransferAndCall","#shieldViaApproveAndWrap","#requireSigner","#ensureAllowance","#unwrap","#finalizeUnshield","#extractUnwrapRequestId","#isUnwrapRequestConsumed","#clearStoredPendingUnshield","#isPendingUnshieldConsumed","#finalizeUnwrap","#underlying","#underlyingPromise"],"sources":["../../src/errors/revert.ts","../../src/errors/unshield.ts","../../src/abi/erc1363.abi.ts","../../src/contracts/erc1363.ts","../../src/utils/hex.ts","../../src/events/log-decoding.ts","../../src/events/onchain-events.ts","../../src/token/pending-unshield.ts","../../src/token/wrapped-token.ts"],"sourcesContent":["/**\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","// DO NOT EDIT: generated by `pnpm abi:build` from\n// contracts/out/IERC1363.sol/IERC1363.json.\n// Regenerate after `pnpm contracts:build`; `pnpm abi:check` enforces this in CI.\nexport const erc1363Abi = [\n {\n type: \"function\",\n name: \"allowance\",\n inputs: [\n { name: \"owner\", type: \"address\", internalType: \"address\" },\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n ],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"approve\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"approveAndCall\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"approveAndCall\",\n inputs: [\n { name: \"spender\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"balanceOf\",\n inputs: [{ name: \"account\", type: \"address\", internalType: \"address\" }],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"supportsInterface\",\n inputs: [{ name: \"interfaceId\", type: \"bytes4\", internalType: \"bytes4\" }],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"totalSupply\",\n inputs: [],\n outputs: [{ name: \"\", type: \"uint256\", internalType: \"uint256\" }],\n stateMutability: \"view\",\n },\n {\n type: \"function\",\n name: \"transfer\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferAndCall\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferAndCall\",\n inputs: [\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFrom\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFromAndCall\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n { name: \"data\", type: \"bytes\", internalType: \"bytes\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"function\",\n name: \"transferFromAndCall\",\n inputs: [\n { name: \"from\", type: \"address\", internalType: \"address\" },\n { name: \"to\", type: \"address\", internalType: \"address\" },\n { name: \"value\", type: \"uint256\", internalType: \"uint256\" },\n ],\n outputs: [{ name: \"\", type: \"bool\", internalType: \"bool\" }],\n stateMutability: \"nonpayable\",\n },\n {\n type: \"event\",\n name: \"Approval\",\n inputs: [\n { name: \"owner\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"spender\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n ],\n anonymous: false,\n },\n {\n type: \"event\",\n name: \"Transfer\",\n inputs: [\n { name: \"from\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"to\", type: \"address\", indexed: true, internalType: \"address\" },\n { name: \"value\", type: \"uint256\", indexed: false, internalType: \"uint256\" },\n ],\n anonymous: false,\n },\n] as const;\n","import type { Address, Hex } from \"viem\";\nimport { erc1363Abi } from \"../abi/erc1363.abi\";\n\n/**\n * Returns the contract config for an ERC-1363 `transferAndCall`.\n *\n * @param tokenAddress - The ERC-20 token to transfer from (the underlying, not the wrapper).\n * @param to - The recipient of the ERC-20 transfer. In `Token.shield`, this is\n * the wrapper contract whose `onTransferReceived` callback mints\n * confidential tokens to the address encoded in `data`.\n * @param amount - The amount to transfer.\n * @param data - Raw 20-byte recipient address for shield-to-other (decoded by\n * the wrapper as `address(bytes20(data))`). Empty `0x` for self-shield —\n * the wrapper falls back to `from`.\n */\nexport function transferAndCallContract(\n tokenAddress: Address,\n to: Address,\n amount: bigint,\n data: Hex = \"0x\",\n) {\n return {\n address: tokenAddress,\n abi: erc1363Abi,\n functionName: \"transferAndCall\",\n args: [to, amount, data],\n } as const;\n}\n","import type { 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 * Primitives for decoding raw EVM logs without an ABI decoder.\n *\n * @internal\n */\n\nimport { getAddress, keccak256, toBytes, type Address, type Hex } from \"viem\";\nimport type { EncryptedValue } from \"../relayer/types\";\nimport { prefixHex } from \"../utils\";\n\n/** Hashes the canonical signature — `Joined(uint256,address,bytes32)`, not the declaration with parameter names. */\nexport function eventTopic(signature: string): Hex {\n return keccak256(toBytes(signature));\n}\n\nexport function topicToAddress(topic: Hex): Address {\n return getAddress(prefixHex(topic.slice(-40)));\n}\n\nexport function topicToBytes32(topic: Hex): EncryptedValue {\n // EVM topics are already 32-byte 0x-prefixed hex — cast directly\n return topic as EncryptedValue;\n}\n\nexport function 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\nexport function wordToAddress(data: Hex, index: number): Address {\n return getAddress(prefixHex(wordAt(data, index).slice(-40)));\n}\n\nexport function wordToBigInt(data: Hex, index: number): bigint {\n return BigInt(\"0x\" + wordAt(data, index));\n}\n\nexport function 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 * 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 type { Address } from \"viem\";\nimport type { RawLog } from \"../types/transaction\";\nimport {\n eventTopic,\n topicToAddress,\n topicToBytes32,\n wordToAddress,\n wordToBigInt,\n wordToBytes32,\n} from \"./log-decoding\";\nexport type { RawLog } from \"../types/transaction\";\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// 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 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 type { TelemetryOperation } from \"../telemetry\";\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, \"unshield\");\n }\n\n const callbacks: UnshieldCallbacks = { onFinalizing, onFinalizeSubmitted };\n const operationId = crypto.randomUUID();\n const unwrapResult = await this.#unwrap(amount, \"unshield\");\n void swallow(\n \"unshield: onUnwrapSubmitted\",\n () => onUnwrapSubmitted?.(unwrapResult.txHash),\n this.sdk.logger,\n );\n // Reuse the id the unwrap already decoded — no second receipt fetch or decode.\n return this.#finalizeUnshield(\n unwrapResult.unwrapRequestId,\n unwrapResult.txHash,\n operationId,\n callbacks,\n \"unshield\",\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 \"unshield-all\",\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(\n unwrapRequestId,\n unwrapTxHash,\n crypto.randomUUID(),\n callbacks,\n \"resume-unshield\",\n );\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 return this.#unwrap(amount, \"unwrap\");\n }\n\n async #unwrap(amount: bigint, telemetryOperation: TelemetryOperation): 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\" }], contractAddress: this.address, userAddress },\n { operation: telemetryOperation },\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 return this.#finalizeUnwrap(unwrapRequestId, \"finalize-unwrap\");\n }\n\n async #finalizeUnwrap(\n unwrapRequestId: EncryptedValue,\n telemetryOperation: TelemetryOperation,\n ): 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 operation: telemetryOperation,\n });\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 telemetryOperation: TelemetryOperation,\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, telemetryOperation);\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"],"mappings":"wfAKA,SAAgB,EAAuB,EAA+B,CACpE,GAAI,EAAE,aAAiB,OACrB,OAAO,KAET,IAAM,EAAQ,EAAM,MACpB,GAAI,OAAO,GAAU,WAAY,GAAkB,EAAE,SAAU,GAC7D,OAAO,KAET,GAAM,CAAE,QAAS,EAIjB,OAHI,OAAO,GAAS,WAAY,GAAiB,EAAE,cAAe,GACzD,KAEF,OAAO,EAAK,WAAc,SAAW,EAAK,UAAY,IAC/D,CCCA,IAAa,EAAb,cAAmD,CAAU,CAE3D,aAEA,gBAEA,YAAY,EAAiB,EAA0C,EAAwB,CAC7F,MAAM,EAAc,yBAA0B,EAAS,CAAO,EAC9D,KAAK,KAAO,gCACZ,KAAK,aAAe,EAAQ,aAC5B,KAAK,gBAAkB,EAAQ,eACjC,CACF,EAEA,MAAM,EAAyB,uBACzB,EAAkC,EACtC,EAAQ,GAAG,EAAuB,UAAU,CAC9C,CAAC,CAAC,MAAM,EAAG,EAAE,EASb,SAAgB,EAA6B,EAAyB,CACpE,IAAK,IAAI,EAAU,EAAO,aAAmB,MAAO,EAAU,EAAQ,MAIpE,GAHI,EAAuB,CAAO,IAAM,GAItC,EAAQ,QAAQ,SAAS,CAAsB,GAC/C,EAAQ,QAAQ,SAAS,CAA+B,EAExD,MAAO,GAGX,MAAO,EACT,CCvDA,MAAa,EAAa,CACxB,CACE,KAAM,WACN,KAAM,YACN,OAAQ,CACN,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,EAC1D,CAAE,KAAM,UAAW,KAAM,UAAW,aAAc,SAAU,CAC9D,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,UAAW,aAAc,SAAU,CAAC,EAChE,gBAAiB,MACnB,EACA,CACE,KAAM,WACN,KAAM,UACN,OAAQ,CACN,CAAE,KAAM,UAAW,KAAM,UAAW,aAAc,SAAU,EAC5D,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,CAC5D,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,iBACN,OAAQ,CACN,CAAE,KAAM,UAAW,KAAM,UAAW,aAAc,SAAU,EAC5D,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,CAC5D,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,iBACN,OAAQ,CACN,CAAE,KAAM,UAAW,KAAM,UAAW,aAAc,SAAU,EAC5D,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,EAC1D,CAAE,KAAM,OAAQ,KAAM,QAAS,aAAc,OAAQ,CACvD,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,YACN,OAAQ,CAAC,CAAE,KAAM,UAAW,KAAM,UAAW,aAAc,SAAU,CAAC,EACtE,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,UAAW,aAAc,SAAU,CAAC,EAChE,gBAAiB,MACnB,EACA,CACE,KAAM,WACN,KAAM,oBACN,OAAQ,CAAC,CAAE,KAAM,cAAe,KAAM,SAAU,aAAc,QAAS,CAAC,EACxE,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,MACnB,EACA,CACE,KAAM,WACN,KAAM,cACN,OAAQ,CAAC,EACT,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,UAAW,aAAc,SAAU,CAAC,EAChE,gBAAiB,MACnB,EACA,CACE,KAAM,WACN,KAAM,WACN,OAAQ,CACN,CAAE,KAAM,KAAM,KAAM,UAAW,aAAc,SAAU,EACvD,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,CAC5D,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,kBACN,OAAQ,CACN,CAAE,KAAM,KAAM,KAAM,UAAW,aAAc,SAAU,EACvD,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,CAC5D,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,kBACN,OAAQ,CACN,CAAE,KAAM,KAAM,KAAM,UAAW,aAAc,SAAU,EACvD,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,EAC1D,CAAE,KAAM,OAAQ,KAAM,QAAS,aAAc,OAAQ,CACvD,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,eACN,OAAQ,CACN,CAAE,KAAM,OAAQ,KAAM,UAAW,aAAc,SAAU,EACzD,CAAE,KAAM,KAAM,KAAM,UAAW,aAAc,SAAU,EACvD,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,CAC5D,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,sBACN,OAAQ,CACN,CAAE,KAAM,OAAQ,KAAM,UAAW,aAAc,SAAU,EACzD,CAAE,KAAM,KAAM,KAAM,UAAW,aAAc,SAAU,EACvD,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,EAC1D,CAAE,KAAM,OAAQ,KAAM,QAAS,aAAc,OAAQ,CACvD,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,WACN,KAAM,sBACN,OAAQ,CACN,CAAE,KAAM,OAAQ,KAAM,UAAW,aAAc,SAAU,EACzD,CAAE,KAAM,KAAM,KAAM,UAAW,aAAc,SAAU,EACvD,CAAE,KAAM,QAAS,KAAM,UAAW,aAAc,SAAU,CAC5D,EACA,QAAS,CAAC,CAAE,KAAM,GAAI,KAAM,OAAQ,aAAc,MAAO,CAAC,EAC1D,gBAAiB,YACnB,EACA,CACE,KAAM,QACN,KAAM,WACN,OAAQ,CACN,CAAE,KAAM,QAAS,KAAM,UAAW,QAAS,GAAM,aAAc,SAAU,EACzE,CAAE,KAAM,UAAW,KAAM,UAAW,QAAS,GAAM,aAAc,SAAU,EAC3E,CAAE,KAAM,QAAS,KAAM,UAAW,QAAS,GAAO,aAAc,SAAU,CAC5E,EACA,UAAW,EACb,EACA,CACE,KAAM,QACN,KAAM,WACN,OAAQ,CACN,CAAE,KAAM,OAAQ,KAAM,UAAW,QAAS,GAAM,aAAc,SAAU,EACxE,CAAE,KAAM,KAAM,KAAM,UAAW,QAAS,GAAM,aAAc,SAAU,EACtE,CAAE,KAAM,QAAS,KAAM,UAAW,QAAS,GAAO,aAAc,SAAU,CAC5E,EACA,UAAW,EACb,CACF,ECxIA,SAAgB,EACd,EACA,EACA,EACA,EAAY,KACZ,CACA,MAAO,CACL,QAAS,EACT,IAAK,EACL,aAAc,kBACd,KAAM,CAAC,EAAI,EAAQ,CAAI,CACzB,CACF,CCvBA,SAAgB,EAAU,EAAoB,CAC5C,OAAQ,EAAM,WAAW,IAAI,EAAI,EAAQ,KAAK,GAChD,CCKA,SAAgB,EAAW,EAAwB,CACjD,OAAO,EAAU,EAAQ,CAAS,CAAC,CACrC,CAEA,SAAgB,EAAe,EAAqB,CAClD,OAAO,EAAW,EAAU,EAAM,MAAM,GAAG,CAAC,CAAC,CAC/C,CAEA,SAAgB,EAAe,EAA4B,CAEzD,OAAO,CACT,CAEA,SAAgB,EAAO,EAAW,EAAuB,CAEvD,IAAM,EAAQ,EAAI,EAAQ,GACpB,EAAO,EAAK,MAAM,EAAO,EAAQ,EAAE,EACzC,OAAO,EAAK,SAAW,GAAK,EAAO,EAAK,OAAO,GAAI,GAAG,CACxD,CAEA,SAAgB,EAAc,EAAW,EAAwB,CAC/D,OAAO,EAAW,EAAU,EAAO,EAAM,CAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAC7D,CAEA,SAAgB,EAAa,EAAW,EAAuB,CAC7D,OAAO,OAAO,KAAO,EAAO,EAAM,CAAK,CAAC,CAC1C,CAEA,SAAgB,EAAc,EAAW,EAA+B,CAEtE,OAAO,EAAU,EAAO,EAAM,CAAK,CAAC,CACtC,CChBA,MAAa,EAAS,CAEpB,qBAAsB,EAAW,+CAA+C,EAEhF,KAAM,EAAW,+BAA+B,EAEhD,gBAAiB,EAAW,0CAA0C,EAEtE,gBAAiB,EAAW,iDAAiD,CAC/E,EA2EA,SAAgB,EAA2B,EAA+C,CAQxF,OAPI,EAAI,OAAO,KAAO,EAAO,sBAGzB,EAAI,OAAO,OAAS,EACf,KAGF,CACL,UAAW,uBACX,KAAM,EAAe,EAAI,OAAO,EAAG,EACnC,GAAI,EAAe,EAAI,OAAO,EAAG,EACjC,gBAAiB,EAAe,EAAI,OAAO,EAAG,CAChD,CACF,CAOA,SAAgB,EAAW,EAA+B,CAQxD,OAPI,EAAI,OAAO,KAAO,EAAO,MAGzB,EAAI,OAAO,OAAS,EACf,KAGF,CACL,UAAW,OACX,GAAI,EAAe,EAAI,OAAO,EAAG,EACjC,cAAe,EAAa,EAAI,KAAM,CAAC,EACvC,uBAAwB,EAAc,EAAI,KAAM,CAAC,CACnD,CACF,CAKA,SAAgB,EAAsB,EAA0C,CAQ9E,OAPI,EAAI,OAAO,KAAO,EAAO,iBAGzB,EAAI,OAAO,OAAS,EACf,KAGF,CACL,UAAW,kBACX,SAAU,EAAe,EAAI,OAAO,EAAG,EACvC,gBAAiB,EAAe,EAAI,OAAO,EAAG,EAC9C,gBAAiB,EAAc,EAAI,KAAM,CAAC,CAC5C,CACF,CAKA,SAAgB,EAAsB,EAA0C,CAQ9E,OAPI,EAAI,OAAO,KAAO,EAAO,iBAGzB,EAAI,OAAO,OAAS,EACf,KAGF,CACL,UAAW,kBACX,SAAU,EAAe,EAAI,OAAO,EAAG,EACvC,gBAAiB,EAAe,EAAI,OAAO,EAAG,EAC9C,gBAAiB,EAAc,EAAI,KAAM,CAAC,EAC1C,gBAAiB,EAAa,EAAI,KAAM,CAAC,CAC3C,CACF,CAiBA,SAAgB,EAAmB,EAAkC,CACnE,OACE,EAA2B,CAAG,GAC9B,EAAW,CAAG,GACd,EAAsB,CAAG,GACzB,EAAsB,CAAG,CAE7B,CAUA,SAAgB,GAAoB,EAAyC,CAC3E,IAAM,EAAyB,CAAC,EAChC,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAQ,EAAmB,CAAG,EAChC,GACF,EAAO,KAAK,CAAK,CAErB,CACA,OAAO,CACT,CAWA,SAAgB,EAAoB,EAAsD,CACxF,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAQ,EAAsB,CAAG,EACvC,GAAI,EACF,OAAO,CAEX,CACA,OAAO,IACT,CAWA,SAAgB,GAAS,EAA2C,CAClE,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAQ,EAAW,CAAG,EAC5B,GAAI,EACF,OAAO,CAEX,CACA,OAAO,IACT,CAOA,MAAa,GAAe,CAC1B,EAAO,qBACP,EAAO,KACP,EAAO,gBACP,EAAO,eACT,EAUa,EAAY,CAEvB,2BAA4B,EAC1B,0EACF,EAEA,mCAAoC,EAClC,2EACF,CACF,EAqDA,SAAgB,EACd,EACwC,CAQxC,OAPI,EAAI,OAAO,KAAO,EAAU,4BAG5B,EAAI,OAAO,OAAS,EACf,KAGF,CACL,UAAW,6BACX,UAAW,EAAe,EAAI,OAAO,EAAG,EACxC,SAAU,EAAe,EAAI,OAAO,EAAG,EACvC,gBAAiB,EAAc,EAAI,KAAM,CAAC,EAC1C,kBAAmB,EAAa,EAAI,KAAM,CAAC,EAC3C,kBAAmB,EAAa,EAAI,KAAM,CAAC,EAC3C,kBAAmB,EAAa,EAAI,KAAM,CAAC,CAC7C,CACF,CAQA,SAAgB,EACd,EACgD,CAQhD,OAPI,EAAI,OAAO,KAAO,EAAU,oCAG5B,EAAI,OAAO,OAAS,EACf,KAGF,CACL,UAAW,qCACX,UAAW,EAAe,EAAI,OAAO,EAAG,EACxC,SAAU,EAAe,EAAI,OAAO,EAAG,EACvC,gBAAiB,EAAc,EAAI,KAAM,CAAC,EAC1C,kBAAmB,EAAa,EAAI,KAAM,CAAC,EAC3C,kBAAmB,EAAa,EAAI,KAAM,CAAC,CAC7C,CACF,CAKA,SAAgB,EAAe,EAA8B,CAC3D,OAAO,EAAiC,CAAG,GAAK,EAAyC,CAAG,CAC9F,CAKA,SAAgB,GAAgB,EAAqC,CACnE,IAAM,EAAqB,CAAC,EAC5B,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAQ,EAAe,CAAG,EAC5B,GACF,EAAO,KAAK,CAAK,CAErB,CACA,OAAO,CACT,CAKA,SAAgB,GACd,EACwC,CACxC,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAQ,EAAiC,CAAG,EAClD,GAAI,EACF,OAAO,CAEX,CACA,OAAO,IACT,CAKA,SAAgB,GACd,EACgD,CAChD,IAAK,IAAM,KAAO,EAAM,CACtB,IAAM,EAAQ,EAAyC,CAAG,EAC1D,GAAI,EACF,OAAO,CAEX,CACA,OAAO,IACT,CAOA,MAAa,GAAa,CACxB,EAAU,2BACV,EAAU,kCACZ,ECtaA,SAAS,EAAW,EAAiC,CACnD,MAAO,yBAAoB,GAAS,CAAc,GACpD,CAEA,MAAM,GAA+B,EAAE,MAAM,CAC3C,EAAE,KACA,EACA,EAAE,UAAW,IAAuB,CAAE,cAAa,EAAE,CACvD,EACA,EAAE,KACA,EAAE,OAAO,CACP,QAAS,EAAE,QAAQ,CAAe,EAClC,aAAc,EACd,gBAAiB,EAAE,SAAS,CAAG,CACjC,CAAC,EACD,EAAE,WACC,CACC,eACA,sBAKK,CAAE,eAAc,iBAAgB,EACzC,CACF,CACF,CAAC,EAQD,eAAsB,GACpB,EACA,EACA,EACA,EACe,CACf,GAAI,IAAoB,IAAA,GAAW,CACjC,MAAM,EAAQ,IAAI,EAAW,CAAc,EAAG,CAAY,EAC1D,MACF,CAEA,MAAM,EAAQ,IAAI,EAAW,CAAc,EAAG,CAC5C,QAAS,EACT,eACA,iBACF,CAAwC,CAC1C,CAyBA,eAAsB,GACpB,EACA,EACwC,CACxC,IAAM,EAAM,EAAW,CAAc,EAC/B,EAAQ,MAAM,EAAQ,IAAwC,CAAG,EACvE,GAAI,GAAU,KACZ,OAAO,KAET,IAAM,EAAS,GAA6B,UAAU,CAAK,EAK3D,OAJK,EAAO,QAIL,EAAO,MAHZ,MAAM,EAAQ,OAAO,CAAG,EACjB,KAGX,CAOA,eAAsB,GACpB,EACA,EACe,CACf,MAAM,EAAQ,OAAO,EAAW,CAAc,CAAC,CACjD,CCtEA,IAAa,GAAb,cAAkC,EAAM,CACtC,GACA,GAA8C,KAC9C,GAA6B,KAG7B,GAAe,EAAkC,CAC/C,GAAI,CAEF,OADA,EAAkB,KAAK,IAAI,OAAQ,yBAAyB,EACrD,KAAK,IAAI,MAClB,OAAS,EAAO,CACd,MAAM,IAAI,EAAyB,EAAW,CAAE,OAAM,CAAC,CACzD,CACF,CASA,MAAM,YAA+B,CACnC,OAAO,KAAKA,GAAe,CAC7B,CAQA,MAAM,WAA8B,CAClC,GAAI,KAAKC,KAAe,KACtB,OAAO,KAAKA,GAEd,GAAI,CACF,IAAM,EAAa,MAAM,KAAKD,GAAe,EAC7C,KAAKC,GAAa,MAAM,KAAK,IAAI,SAAS,aAAa,GAAuB,CAAU,CAAC,CAC3F,MAAQ,CACN,KAAKA,GAAa,EACpB,CACA,OAAO,KAAKA,EACd,CASA,MAAM,UAAU,EAAiC,CAC/C,IAAM,EAAa,MAAM,KAAKD,GAAe,EAC7C,OAAO,KAAK,IAAI,SAAS,aACvB,EAAkB,EAAY,EAAW,CAAK,EAAG,KAAK,OAAO,CAC/D,CACF,CAiCA,MAAM,OAAO,EAAgB,EAAqD,CAChF,IAAM,EAAU,MAAM,EAA4B,SAAU,KAAK,IAAI,OAAQ,KAAK,IAAI,QAAQ,EAExF,EAAiB,MAAM,KAAK,UAAU,EACtC,EAAa,MAAM,KAAKA,GAAe,EACvC,EAAc,EAAW,EAAQ,OAAO,EAG1C,EACJ,GAAI,CACF,EAAe,MAAM,KAAK,IAAI,SAAS,aACrC,EAAkB,EAAY,CAAW,CAC3C,CACF,OAAS,EAAO,CAId,MAHI,aAAiB,EACb,EAEF,IAAI,EACR,+DAA+D,EAAW,GAC1E,CAAE,MAAO,EAAQ,CAAK,CAAE,CAC1B,CACF,CACA,GAAI,EAAe,EACjB,MAAM,IAAI,EACR,0CAA0C,EAAO,cAAc,EAAa,WAAW,EAAW,GAClG,CAAE,UAAW,EAAQ,UAAW,EAAc,MAAO,CAAW,CAClE,EAMF,OAHI,EACK,KAAKE,GAA0B,EAAQ,EAAY,EAAa,CAAO,EAEzE,KAAKC,GAAyB,EAAQ,EAAa,CAAO,CACnE,CAEA,KAAMD,GACJ,EACA,EACA,EACA,EAC4B,CAC5B,KAAKE,GAAe,QAAQ,EAC5B,IAAM,EAAY,GAAS,GAAK,EAAW,EAAQ,EAAE,EAAI,EAKnD,EAAY,IAAc,EAAc,KAAO,EAErD,OAAO,KAAK,kBAAkB,CAC5B,UAAW,yBACX,OAAQ,EAAwB,EAAY,KAAK,QAAS,EAAQ,CAAI,EACtE,YAAa,GAAS,iBACxB,CAAC,CACH,CAyBA,MAAM,KAAK,EAAgB,EAAmD,CAC5E,KAAKA,GAAe,MAAM,EAC1B,IAAM,EAAU,MAAM,EAA4B,OAAQ,KAAK,IAAI,OAAQ,KAAK,IAAI,QAAQ,EACtF,EAAa,MAAM,KAAKJ,GAAe,EACvC,EAAc,EAAW,EAAQ,OAAO,EAE1C,EACJ,GAAI,CACF,EAAe,MAAM,KAAK,IAAI,SAAS,aACrC,EAAkB,EAAY,CAAW,CAC3C,CACF,OAAS,EAAO,CAId,MAHI,aAAiB,EACb,EAEF,IAAI,EACR,6DAA6D,EAAW,GACxE,CAAE,MAAO,EAAQ,CAAK,CAAE,CAC1B,CACF,CACA,GAAI,EAAe,EACjB,MAAM,IAAI,EACR,0CAA0C,EAAO,cAAc,EAAa,WAAW,EAAW,GAClG,CAAE,UAAW,EAAQ,UAAW,EAAc,MAAO,CAAW,CAClE,EAGF,IAAI,EACJ,GAAI,CACF,EAAY,MAAM,KAAK,IAAI,SAAS,aAClC,EAAkB,EAAY,EAAa,KAAK,OAAO,CACzD,CACF,OAAS,EAAO,CAId,MAHI,aAAiB,EACb,EAEF,IAAI,EACR,+DAA+D,EAAW,GAC1E,CAAE,MAAO,EAAQ,CAAK,CAAE,CAC1B,CACF,CACA,GAAI,EAAY,EACd,MAAM,IAAI,GACR,8CAA8C,EAAO,aAAa,EAAU,2CAA2C,EAAW,IAClI,CAAE,UAAW,EAAQ,UAAW,EAAW,MAAO,CAAW,CAC/D,EAGF,IAAM,EAAY,GAAS,GAAK,EAAW,EAAQ,EAAE,EAAI,EACzD,OAAO,KAAK,kBAAkB,CAC5B,UAAW,OACX,OAAQ,EAAa,KAAK,QAAS,EAAW,CAAM,EACpD,YAAa,GAAS,eACxB,CAAC,CACH,CAEA,KAAMG,GACJ,EACA,EACA,EAC4B,CAC5B,KAAKC,GAAe,QAAQ,EAC5B,IAAM,EAAW,GAAS,kBAAoB,QAC1C,IAAa,QACf,MAAM,KAAKC,GAAiB,EAAQ,IAAa,MAAO,CAAO,EAEjE,IAAM,EAAY,GAAS,GAAK,EAAW,EAAQ,EAAE,EAAI,EACzD,OAAO,KAAK,kBAAkB,CAC5B,UAAW,wBACX,OAAQ,EAAa,KAAK,QAAS,EAAW,CAAM,EACpD,YAAa,GAAS,iBACxB,CAAC,CACH,CAgBA,MAAM,kBAAkB,EAA6C,CACnE,KAAKD,GAAe,mBAAmB,EACvC,IAAM,EAAU,MAAM,EACpB,oBACA,KAAK,IAAI,OACT,KAAK,IAAI,QACX,EACM,EAAa,MAAM,KAAKJ,GAAe,EACvC,EAAc,EAAW,EAAQ,OAAO,EAExC,EAAiB,GAAU,IAAM,KAAO,GAe9C,OAbI,EAAiB,IAKf,MAJ2B,KAAK,IAAI,SAAS,aAC/C,EAAkB,EAAY,EAAa,KAAK,OAAO,CACzD,EAEuB,IACrB,MAAM,KAAK,kBAAkB,CAC3B,UAAW,0BACX,OAAQ,EAAgB,EAAY,KAAK,QAAS,EAAE,CACtD,CAAC,EAIE,KAAK,kBAAkB,CAC5B,UAAW,oBACX,OAAQ,EAAgB,EAAY,KAAK,QAAS,CAAc,CAClE,CAAC,CACH,CAoBA,MAAM,SAAS,EAAgB,EAAuD,CACpF,GAAM,CACJ,mBAAmB,GACnB,oBACA,eACA,uBACE,GAAW,CAAC,EAEX,GACH,MAAM,KAAK,0BAA0B,EAAQ,UAAU,EAGzD,IAAM,EAA+B,CAAE,eAAc,qBAAoB,EACnE,EAAc,OAAO,WAAW,EAChC,EAAe,MAAM,KAAKM,GAAQ,EAAQ,UAAU,EAO1D,OANA,EACE,kCACM,IAAoB,EAAa,MAAM,EAC7C,KAAK,IAAI,MACX,EAEO,KAAKC,GACV,EAAa,gBACb,EAAa,OACb,EACA,EACA,UACF,CACF,CAeA,MAAM,YAAY,EAA2D,CAC3E,IAAM,EAAc,OAAO,WAAW,EAChC,EAAe,MAAM,KAAK,UAAU,EAO1C,OANA,EACE,qCACM,GAAW,oBAAoB,EAAa,MAAM,EACxD,KAAK,IAAI,MACX,EAEO,KAAKA,GACV,EAAa,gBACb,EAAa,OACb,EACA,EACA,cACF,CACF,CAkBA,MAAM,eACJ,EACA,EAC4B,CAG5B,IAAI,EACJ,GAAI,CACF,EAAU,MAAM,KAAK,IAAI,SAAS,0BAA0B,CAAY,CAC1E,OAAS,EAAO,CAId,MAHI,aAAiB,EACb,EAEF,IAAI,EAAyB,+BAAgC,CAAE,MAAO,CAAM,CAAC,CACrF,CACA,IAAM,EAAkB,KAAKC,GAAwB,EAAQ,IAAI,EACjE,GAAI,MAAM,KAAKC,GAAyB,CAAe,EAErD,MADA,MAAM,KAAKC,GAA4B,gBAAgB,EACjD,IAAI,EACR,qGACA,CAAE,eAAc,iBAAgB,CAClC,EAEF,OAAO,KAAKH,GACV,EACA,EACA,OAAO,WAAW,EAClB,EACA,iBACF,CACF,CA0BA,MAAM,oBAA0C,CAC9C,IAAM,EAAU,MAAM,GAA2B,KAAK,IAAI,QAAS,KAAK,OAAO,EAQ/E,OAPK,EAGD,MAAM,KAAKI,GAA2B,CAAO,GAC/C,MAAM,KAAKD,GAA4B,oBAAoB,EACpD,MAEF,EAAQ,aANN,IAOX,CAkBA,MAAM,OAAO,EAAuC,CAClD,OAAO,KAAKJ,GAAQ,EAAQ,QAAQ,CACtC,CAEA,KAAMA,GAAQ,EAAgB,EAA+D,CAC3F,KAAKF,GAAe,QAAQ,EAE5B,IAAM,EAAc,GAAW,MADT,EAA4B,SAAU,KAAK,IAAI,OAAQ,KAAK,IAAI,QAAQ,EAAA,CACvD,OAAO,EAExC,CAAE,kBAAiB,cAAe,MAAM,KAAK,IAAI,QACrD,CAAE,OAAQ,CAAC,CAAE,MAAO,EAAQ,KAAM,SAAU,CAAC,EAAG,gBAAiB,KAAK,QAAS,aAAY,EAC3F,CAAE,UAAW,CAAmB,CAClC,EAEM,CAAC,GAAmB,EAC1B,GAAI,CAAC,EACH,MAAM,IAAI,EAAsB,yCAAyC,EAG3E,IAAM,EAAS,MAAM,KAAK,kBAAkB,CAC1C,UAAW,SACX,OAAQ,EAAe,KAAK,QAAS,EAAa,EAAa,EAAiB,CAAU,CAC5F,CAAC,EAED,MAAO,CAAE,GAAG,EAAQ,gBAAiB,KAAKI,GAAwB,EAAO,QAAQ,IAAI,CAAE,CACzF,CAgBA,MAAM,WAAmC,CACvC,KAAKJ,GAAe,WAAW,EAM/B,IAAM,EAAc,GAAW,MALT,EACpB,YACA,KAAK,IAAI,OACT,KAAK,IAAI,QACX,EAAA,CACuC,OAAO,EACxC,EAAiB,MAAM,KAAK,0BAA0B,CAAW,EAEvE,GAAI,GAAqB,CAAc,EACrC,MAAM,IAAI,EAAsB,kCAAkC,EAGpE,IAAM,EAAS,MAAM,KAAK,kBAAkB,CAC1C,UAAW,YACX,OAAQ,EAA0B,KAAK,QAAS,EAAa,EAAa,CAAc,CAC1F,CAAC,EAED,MAAO,CAAE,GAAG,EAAQ,gBAAiB,KAAKI,GAAwB,EAAO,QAAQ,IAAI,CAAE,CACzF,CAkBA,MAAM,eAAe,EAA6D,CAChF,OAAO,KAAKI,GAAgB,EAAiB,iBAAiB,CAChE,CAEA,KAAMA,GACJ,EACA,EAC4B,CAC5B,KAAKR,GAAe,gBAAgB,EACpC,MAAM,EAAsB,iBAAkB,KAAK,IAAI,OAAQ,KAAK,IAAI,QAAQ,EAChF,IAAM,EAAS,MAAM,KAAK,IAAI,WAAW,oBAAoB,CAAC,CAAe,EAAG,CAC9E,UAAW,CACb,CAAC,EACK,EAAa,EAAO,YAAY,GAEtC,OADA,EAAa,EAAY,4BAA4B,EAC9C,KAAK,kBAAkB,CAC5B,UAAW,iBACX,OAAQ,GACN,KAAK,QACL,EACA,EACA,EAAO,eACT,CACF,CAAC,CACH,CAWA,GAAwB,EAAyC,CAI/D,IAAM,EAAQ,EAHE,EAAK,OAClB,GAAQ,EAAI,UAAY,IAAA,IAAa,EAAW,EAAI,OAAO,IAAM,KAAK,OAEjC,CAAC,EACzC,GAAI,CAAC,EACH,MAAM,IAAI,EACR,wEACF,EAEF,OAAO,EAAM,eACf,CASA,KAAMK,GAAyB,EAAmD,CAChF,GAAI,CAIF,OAAO,MAHiB,KAAK,IAAI,SAAS,aACxC,GAAwB,KAAK,QAAS,CAAe,CACvD,IACqB,EACvB,MAAQ,CACN,MAAO,EACT,CACF,CAMA,KAAME,GAA2B,EAAmD,CAClF,IAAI,EAAkB,EAAQ,gBAC9B,GAAI,IAAoB,IAAA,GACtB,GAAI,CACF,IAAM,EAAU,MAAM,KAAK,IAAI,SAAS,0BAA0B,EAAQ,YAAY,EACtF,EAAkB,KAAKH,GAAwB,EAAQ,IAAI,CAC7D,MAAQ,CACN,MAAO,EACT,CAEF,OAAO,KAAKC,GAAyB,CAAe,CACtD,CAEA,KAAMC,GAA4B,EAAkC,CAClE,MAAM,EACJ,GAAG,EAAU,4BACP,GAAqB,KAAK,IAAI,QAAS,KAAK,OAAO,EACzD,KAAK,IAAI,MACX,CACF,CAEA,KAAMV,IAAmC,CAiBvC,OAhBI,KAAKa,KAAgB,IAAA,IAGzB,AACE,KAAKC,KAAqB,KAAK,IAAI,SAChC,aAAa,EAAmB,KAAK,OAAO,CAAC,CAAC,CAC9C,KAAM,IACL,KAAKD,GAAc,EACnB,KAAKC,GAAqB,KACnB,EACR,CAAC,CACD,MAAO,GAAU,CAEhB,KADA,MAAKA,GAAqB,KACpB,CACR,CAAC,EAEE,KAAKA,IAfH,KAAKD,EAgBhB,CAQA,KAAMN,GACJ,EACA,EACA,EACA,EACA,EAC4B,CAC5B,KAAK,KAAK,CAAE,KAAM,EAAc,wBAAyB,OAAQ,EAAc,aAAY,CAAC,EAC5F,MAAM,EACJ,oCACM,GAAoB,KAAK,IAAI,QAAS,KAAK,QAAS,EAAc,CAAe,EACvF,KAAK,IAAI,MACX,EACA,KAAK,KAAK,CAAE,KAAM,EAAc,sBAAuB,aAAY,CAAC,EACpE,EAAa,6BAAgC,GAAW,eAAe,EAAG,KAAK,IAAI,MAAM,EACzF,IAAI,EACJ,GAAI,CACF,EAAiB,MAAM,KAAKK,GAAgB,EAAiB,CAAkB,CACjF,OAAS,EAAO,CASd,MAJK,EAA6B,CAAK,GAGvC,MAAM,KAAKF,GAA4B,UAAU,EAC3C,IAAI,EACR,oFACA,CAAE,eAAc,iBAAgB,EAChC,CAAE,MAAO,CAAM,CACjB,GAPQ,CAQV,CAaA,OAZA,KAAK,KAAK,CACR,KAAM,EAAc,wBACpB,OAAQ,EAAe,OACvB,aACF,CAAC,EACD,EACE,oCACM,GAAW,sBAAsB,EAAe,MAAM,EAC5D,KAAK,IAAI,MACX,EAEA,MAAM,KAAKA,GAA4B,UAAU,EAC1C,CACT,CAEA,KAAML,GACJ,EACA,EACA,EACe,CACf,KAAKD,GAAe,mBAAmB,EACvC,IAAM,EAAa,MAAM,KAAKJ,GAAe,EAMvC,EAAc,GAAW,MALT,EACpB,oBACA,KAAK,IAAI,OACT,KAAK,IAAI,QACX,EAAA,CACuC,OAAO,EACxC,EAAY,MAAM,KAAK,IAAI,SAAS,aACxC,EAAkB,EAAY,EAAa,KAAK,OAAO,CACzD,EAEA,GAAI,GAAa,EACf,OAME,EAAY,IACd,MAAM,KAAK,kBAAkB,CAC3B,UAAW,0BACX,OAAQ,EAAgB,EAAY,KAAK,QAAS,EAAE,CACtD,CAAC,EAGH,IAAM,EAAiB,EAAc,IAAM,KAAO,GAAK,EAEvD,MAAM,KAAK,kBAAkB,CAC3B,UAAW,oBACX,OAAQ,EAAgB,EAAY,KAAK,QAAS,CAAc,EAChE,YAAa,GAAW,mBAC1B,CAAC,CACH,CACF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zama-fhe/sdk",
|
|
3
|
-
"version": "3.7.0
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"description": "TypeScript SDK for Zama fhEVM confidential smart contracts",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"blockchain",
|
|
@@ -62,9 +62,6 @@
|
|
|
62
62
|
],
|
|
63
63
|
"vaults": [
|
|
64
64
|
"./dist/esm/vaults/index.d.ts"
|
|
65
|
-
],
|
|
66
|
-
"internal": [
|
|
67
|
-
"./dist/esm/internal/index.d.ts"
|
|
68
65
|
]
|
|
69
66
|
}
|
|
70
67
|
},
|
|
@@ -171,17 +168,6 @@
|
|
|
171
168
|
"./encrypt.worker.js": "./dist/esm/encrypt.worker.js",
|
|
172
169
|
"./package.json": {
|
|
173
170
|
"default": "./package.json"
|
|
174
|
-
},
|
|
175
|
-
"./internal": {
|
|
176
|
-
"import": {
|
|
177
|
-
"types": "./dist/esm/internal/index.d.ts",
|
|
178
|
-
"default": "./dist/esm/internal/index.js"
|
|
179
|
-
},
|
|
180
|
-
"require": {
|
|
181
|
-
"types": "./dist/esm/internal/index.d.ts",
|
|
182
|
-
"default": "./dist/cjs/internal/index.cjs"
|
|
183
|
-
},
|
|
184
|
-
"default": "./dist/esm/internal/index.js"
|
|
185
171
|
}
|
|
186
172
|
},
|
|
187
173
|
"publishConfig": {
|
package/dist/cjs/fatal-batch.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("./relayer.cjs"),t=require("./signing.cjs");var n=class extends e.r{retryAfter;constructor(t,n){let{retryAfter:r,...i}=n??{};super(e.i.RpcRateLimited,t,i),this.name=`RpcRateLimitError`,this.retryAfter=r}};const r={[e.i.SigningRejected]:t.n,[e.i.SigningFailed]:t.t,[e.i.Configuration]:e.t,[e.i.RpcRateLimited]:n,[e.i.KeyWrappingFailed]:t.a,[e.i.RevokedKmsContext]:t.l};function i(e){return Object.values(r).some(t=>e instanceof t)}Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return r}});
|
|
2
|
-
//# sourceMappingURL=fatal-batch.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"fatal-batch.cjs","names":["ZamaError","ZamaErrorCode","ZamaErrorCode","SigningRejectedError","SigningFailedError","ConfigurationError","KeyWrappingError","RevokedKmsContextError"],"sources":["../../src/errors/rpc.ts","../../src/errors/fatal-batch.ts"],"sourcesContent":["import { ZamaError, ZamaErrorCode } from \"./base\";\n\n/**\n * The consumer's RPC provider rate-limited an on-chain read the SDK performs\n * during decryption (e.g. the ACL check) — HTTP 429 or JSON-RPC `-32005`. An\n * RPC-endpoint problem, **not** a decryption/entitlement failure, and safe to\n * **retry**. Kept distinct from the relayer's own back-pressure\n * ({@link RelayerRequestFailedError}).\n *\n * Backoff for chain RPC is owned by the consumer's transport: viem/ethers\n * already honor the `Retry-After` header and retry internally before this error\n * surfaces, so it is configured on the transport you pass via `chain.network`\n * (not re-implemented here).\n *\n * @example\n * ```ts\n * try {\n * await sdk.decryption.decryptValues([{ encryptedValue, contractAddress }]);\n * } catch (e) {\n * if (e instanceof RpcRateLimitError) {\n * // back off and retry; consider a higher-throughput RPC endpoint\n * }\n * }\n * ```\n */\nexport class RpcRateLimitError extends ZamaError {\n /**\n * Suggested delay before retrying, in **seconds**, when a numeric `retryAfter`\n * is present on the error. Usually `undefined` for chain RPC: the `Retry-After`\n * header is consumed by the consumer's viem/ethers transport (which owns the\n * backoff), not surfaced here — see the class doc.\n */\n readonly retryAfter: number | undefined;\n\n constructor(message: string, options?: ErrorOptions & { retryAfter?: number }) {\n const { retryAfter, ...errorOptions } = options ?? {};\n super(ZamaErrorCode.RpcRateLimited, message, errorOptions);\n this.name = \"RpcRateLimitError\";\n this.retryAfter = retryAfter;\n }\n}\n","import { ZamaErrorCode, type ZamaError } from \"./base\";\nimport { KeyWrappingError, RevokedKmsContextError } from \"./credential\";\nimport { ConfigurationError } from \"./relayer\";\nimport { RpcRateLimitError } from \"./rpc\";\nimport { SigningRejectedError, SigningFailedError } from \"./signing\";\n\nexport const fatalBatchErrors = {\n [ZamaErrorCode.SigningRejected]: SigningRejectedError,\n [ZamaErrorCode.SigningFailed]: SigningFailedError,\n [ZamaErrorCode.Configuration]: ConfigurationError,\n [ZamaErrorCode.RpcRateLimited]: RpcRateLimitError,\n [ZamaErrorCode.KeyWrappingFailed]: KeyWrappingError,\n [ZamaErrorCode.RevokedKmsContext]: RevokedKmsContextError,\n} satisfies Partial<Record<ZamaErrorCode, new (message: string) => ZamaError>>;\n\n/** Systemic failures abort a batch because retrying each item would repeat the same failure. */\nexport function isFatalBatchError(error: unknown): boolean {\n return Object.values(fatalBatchErrors).some((Constructor) => error instanceof Constructor);\n}\n"],"mappings":"4DAyBA,IAAa,EAAb,cAAuCA,EAAAA,CAAU,CAO/C,WAEA,YAAY,EAAiB,EAAkD,CAC7E,GAAM,CAAE,aAAY,GAAG,GAAiB,GAAW,CAAC,EACpD,MAAMC,EAAAA,EAAc,eAAgB,EAAS,CAAY,EACzD,KAAK,KAAO,oBACZ,KAAK,WAAa,CACpB,CACF,EClCA,MAAa,EAAmB,EAC7BC,EAAAA,EAAc,iBAAkBC,EAAAA,GAChCD,EAAAA,EAAc,eAAgBE,EAAAA,GAC9BF,EAAAA,EAAc,eAAgBG,EAAAA,GAC9BH,EAAAA,EAAc,gBAAiB,GAC/BA,EAAAA,EAAc,mBAAoBI,EAAAA,GAClCJ,EAAAA,EAAc,mBAAoBK,EAAAA,CACrC,EAGA,SAAgB,EAAkB,EAAyB,CACzD,OAAO,OAAO,OAAO,CAAgB,CAAC,CAAC,KAAM,GAAgB,aAAiB,CAAW,CAC3F"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});const e=require("../fhevm-relayer.cjs"),t=require("../relayer.cjs"),n=require("../fatal-batch.cjs").t;function r(e,r,i){let a=n[e],o=a?new a(r):new t.r(e,r,e===t.i.RelayerRequestFailed?{retryable:i.retryable}:void 0);return o.retryable&&t.y(i.retryAfter)?Object.assign(o,{retryAfter:i.retryAfter}):o}function i(e,t){return e.onWalletAccountChange(t)}exports.reviveZamaError=r,exports.subscribeWalletAccountChanges=i,exports.toFhevmAuth=e.n;
|
|
2
|
-
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["fatalBatchErrors","ZamaError","ZamaErrorCode","isValidRetryAfterSeconds"],"sources":["../../../src/errors/revive.ts","../../../src/internal/wallet-events.ts"],"sourcesContent":["import { isValidRetryAfterSeconds } from \"../utils/error\";\nimport { ZamaError, ZamaErrorCode } from \"./base\";\nimport { fatalBatchErrors } from \"./fatal-batch\";\n\nconst callbackErrors: Partial<Record<ZamaErrorCode, new (message: string) => ZamaError>> =\n fatalBatchErrors;\n\n/** Restores callback failures whose class identity controls batch termination. */\nexport function reviveZamaError(\n code: ZamaErrorCode,\n message: string,\n options: { retryable: boolean; retryAfter?: number },\n): ZamaError {\n const Constructor = callbackErrors[code];\n const error = Constructor\n ? new Constructor(message)\n : new ZamaError(\n code,\n message,\n code === ZamaErrorCode.RelayerRequestFailed ? { retryable: options.retryable } : undefined,\n );\n if (error.retryable && isValidRetryAfterSeconds(options.retryAfter)) {\n return Object.assign(error, { retryAfter: options.retryAfter });\n }\n return error;\n}\n","import type { WalletAccountListener } from \"../types/signer\";\nimport type { ZamaSDK } from \"../zama-sdk\";\n\n/** Subscribe after the SDK's wallet cleanup, through the internal integration entry point. */\nexport function subscribeWalletAccountChanges(\n sdk: ZamaSDK,\n listener: WalletAccountListener,\n): () => void {\n return sdk.onWalletAccountChange(listener);\n}\n"],"mappings":"uIAIM,8BACJA,CAAAA,CAAAA,EAGF,SAAgB,EACd,EACA,EACA,EACW,CACX,IAAM,EAAc,EAAe,GAC7B,EAAQ,EACV,IAAI,EAAY,CAAO,EACvB,IAAIC,EAAAA,EACF,EACA,EACA,IAASC,EAAAA,EAAc,qBAAuB,CAAE,UAAW,EAAQ,SAAU,EAAI,IAAA,EACnF,EAIJ,OAHI,EAAM,WAAaC,EAAAA,EAAyB,EAAQ,UAAU,EACzD,OAAO,OAAO,EAAO,CAAE,WAAY,EAAQ,UAAW,CAAC,EAEzD,CACT,CCrBA,SAAgB,EACd,EACA,EACY,CACZ,OAAO,EAAI,sBAAsB,CAAQ,CAC3C"}
|
package/dist/cjs/signing.cjs
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const e=require("./relayer.cjs");var t=class extends e.r{constructor(t,n){super(e.i.TransportKeyPairExpired,t,n),this.name=`TransportKeyPairExpiredError`}},n=class extends e.r{constructor(t,n){super(e.i.InvalidTransportKeyPair,t,n),this.name=`InvalidTransportKeyPairError`}},r=class extends e.r{constructor(t,n){super(e.i.RevokedKmsContext,t,n),this.name=`RevokedKmsContextError`}},i=class extends e.r{constructor(t,n){super(e.i.NoCiphertext,t,n),this.name=`NoCiphertextError`}},a=class extends e.r{constructor(t,n){super(e.i.KeyWrappingFailed,t,n),this.name=`KeyWrappingError`}},o=class extends e.r{constructor(t,n){super(e.i.TransportKeyPairChanged,t,n),this.name=`TransportKeyPairChangedError`}},s=class extends e.r{preparedChainId;activeChainId;constructor({preparedChainId:t,activeChainId:n},r){super(e.i.PreparedPermitChainMismatch,`registerPermit: prepared.chainId (${t}) does not match the active chain (${n}). Register the permit while the SDK is configured for the chain it was prepared for.`,r),this.name=`PreparedPermitChainMismatchError`,this.preparedChainId=t,this.activeChainId=n}},c=class extends e.r{constructor(t,n){super(e.i.PreparedPermitExpired,t,n),this.name=`PreparedPermitExpiredError`}},l=class extends e.r{operation;rpcCode;walletErrorName;constructor(t,n){let{operation:r,rpcCode:i,walletErrorName:a,...o}=n??{};super(e.i.SigningRejected,t,o),this.name=`SigningRejectedError`,this.operation=r,this.rpcCode=i,this.walletErrorName=a}},u=class extends e.r{operation;rpcCode;walletErrorName;constructor(t,n){let{operation:r,rpcCode:i,walletErrorName:a,...o}=n??{};super(e.i.SigningFailed,t,o),this.name=`SigningFailedError`,this.operation=r,this.rpcCode=i,this.walletErrorName=a}};function d(t,r){if(t instanceof e.r)return t;let{operation:i}=r,a=typeof t==`object`&&!!t&&`code`in t&&t.code===4001,o=t instanceof Error?t.message:String(t),s=o.toLowerCase(),c=s.includes(`user rejected`)||s.includes(`user denied`),d=`${i}: ${o}`;return a||c?new l(d,{cause:t,operation:i,rpcCode:e.l(t),walletErrorName:e.u(t)}):e.p(o)?new n(d,{cause:t}):new u(d,{cause:t,operation:i,rpcCode:e.l(t),walletErrorName:e.u(t)})}Object.defineProperty(exports,"a",{enumerable:!0,get:function(){return a}}),Object.defineProperty(exports,"c",{enumerable:!0,get:function(){return c}}),Object.defineProperty(exports,"d",{enumerable:!0,get:function(){return t}}),Object.defineProperty(exports,"i",{enumerable:!0,get:function(){return n}}),Object.defineProperty(exports,"l",{enumerable:!0,get:function(){return r}}),Object.defineProperty(exports,"n",{enumerable:!0,get:function(){return l}}),Object.defineProperty(exports,"o",{enumerable:!0,get:function(){return i}}),Object.defineProperty(exports,"r",{enumerable:!0,get:function(){return d}}),Object.defineProperty(exports,"s",{enumerable:!0,get:function(){return s}}),Object.defineProperty(exports,"t",{enumerable:!0,get:function(){return u}}),Object.defineProperty(exports,"u",{enumerable:!0,get:function(){return o}});
|
|
2
|
-
//# sourceMappingURL=signing.cjs.map
|
package/dist/cjs/signing.cjs.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"signing.cjs","names":["ZamaError","ZamaErrorCode","ZamaError","ZamaErrorCode","extractRpcErrorCode","extractWalletErrorName","isInvalidTransportKeyPairMessage"],"sources":["../../src/errors/credential.ts","../../src/errors/signing.ts"],"sourcesContent":["import { ZamaError, ZamaErrorCode } from \"./base\";\n\n/** Transport key pair has expired and needs regeneration. */\nexport class TransportKeyPairExpiredError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.TransportKeyPairExpired, message, options);\n this.name = \"TransportKeyPairExpiredError\";\n }\n}\n\n/** Relayer rejected the transport key pair (stale, expired, or malformed). */\nexport class InvalidTransportKeyPairError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.InvalidTransportKeyPair, message, options);\n this.name = \"InvalidTransportKeyPairError\";\n }\n}\n\n/**\n * The permit's KMS context has been revoked on-chain, so the permit (and every\n * other permit signed under that context) is permanently unusable. The SDK\n * already tried to self-heal before surfacing this. Check `cause` to tell why\n * it failed: a `SigningFailedError` means the configured signer could not\n * produce a new permit, waiting will not help, establish a new permit with a\n * working signer. Any other cause means the retry hit the same revoked\n * context, typically because the upstream validity check caches a stale\n * \"valid\" verdict for up to 15 minutes; wait out that window and retry.\n */\nexport class RevokedKmsContextError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.RevokedKmsContext, message, options);\n this.name = \"RevokedKmsContextError\";\n }\n}\n\n/** No FHE ciphertext exists for this account (never shielded). */\nexport class NoCiphertextError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.NoCiphertext, message, options);\n this.name = \"NoCiphertextError\";\n }\n}\n\n/**\n * Wrapping or unwrapping the transport private key with `transportKeyPairDerivationSecret` failed:\n * a scoped entry that fails to unwrap may belong to a peer using a different secret, so it fails\n * loudly instead of silently regenerating and clobbering that peer's entry, or the underlying\n * WebCrypto operation itself failed (e.g. `crypto.subtle` unavailable in this environment).\n */\nexport class KeyWrappingError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.KeyWrappingFailed, message, options);\n this.name = \"KeyWrappingError\";\n }\n}\n\n/**\n * The transport key pair changed between `preparePermit` and `registerPermit`\n * (expired, evicted, or rotated in between). The prepared EIP-712 payload was\n * signed against the old key pair's public key — registering it under a\n * different one would persist a permit bound to the wrong key. Call\n * `preparePermit` again to rebind the signature request to the current key pair.\n */\nexport class TransportKeyPairChangedError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.TransportKeyPairChanged, message, options);\n this.name = \"TransportKeyPairChangedError\";\n }\n}\n\n/**\n * A prepared permit's `chainId` doesn't match the chain `registerPermit` is\n * running against. The EIP-712 payload's domain is bound to the chain it was\n * prepared for; registering it under a different chain would persist a permit\n * whose signed payload disagrees with its storage scope.\n */\nexport class PreparedPermitChainMismatchError extends ZamaError {\n /** Chain ID the permit was prepared for. */\n readonly preparedChainId: number;\n /** Chain ID `registerPermit` is currently running against. */\n readonly activeChainId: number;\n\n constructor(\n { preparedChainId, activeChainId }: { preparedChainId: number; activeChainId: number },\n options?: ErrorOptions,\n ) {\n super(\n ZamaErrorCode.PreparedPermitChainMismatch,\n `registerPermit: prepared.chainId (${preparedChainId}) does not match the active chain ` +\n `(${activeChainId}). Register the permit while the SDK is configured for the chain it was prepared for.`,\n options,\n );\n this.name = \"PreparedPermitChainMismatchError\";\n this.preparedChainId = preparedChainId;\n this.activeChainId = activeChainId;\n }\n}\n\n/** A prepared permit's validity window elapsed before its signature was registered. */\nexport class PreparedPermitExpiredError extends ZamaError {\n constructor(message: string, options?: ErrorOptions) {\n super(ZamaErrorCode.PreparedPermitExpired, message, options);\n this.name = \"PreparedPermitExpiredError\";\n }\n}\n","import {\n extractRpcErrorCode,\n extractWalletErrorName,\n isInvalidTransportKeyPairMessage,\n} from \"../utils/error\";\nimport { ZamaError, ZamaErrorCode } from \"./base\";\nimport { InvalidTransportKeyPairError } from \"./credential\";\n\n/**\n * Diagnostic metadata attached to a signing-failure error, on top of the\n * inherited `cause`. All optional and best-effort: `operation` comes from the\n * caller, `rpcCode`/`walletErrorName` are extracted from the wallet's raw\n * error by {@link wrapSigningError}.\n */\nexport interface SigningErrorMetadata {\n /** Name of the SDK operation that was signing when the wallet/provider failed (e.g. \"grantPermit\"). */\n operation?: string;\n /** JSON-RPC / EIP-1193 numeric error code found in the failure's cause chain, if any. */\n rpcCode?: number;\n /** `name` of the error class the wallet/provider library threw (e.g. viem's `InvalidParamsRpcError`). */\n walletErrorName?: string;\n}\n\n/** User rejected the wallet signature prompt. */\nexport class SigningRejectedError extends ZamaError {\n /** Name of the SDK operation that was signing when the user rejected. */\n readonly operation: string | undefined;\n /** JSON-RPC / EIP-1193 numeric error code found in the failure's cause chain, if any. */\n readonly rpcCode: number | undefined;\n /** `name` of the error class the wallet/provider library threw. */\n readonly walletErrorName: string | undefined;\n\n constructor(message: string, options?: ErrorOptions & SigningErrorMetadata) {\n const { operation, rpcCode, walletErrorName, ...errorOptions } = options ?? {};\n super(ZamaErrorCode.SigningRejected, message, errorOptions);\n this.name = \"SigningRejectedError\";\n this.operation = operation;\n this.rpcCode = rpcCode;\n this.walletErrorName = walletErrorName;\n }\n}\n\n/** Wallet signature failed for a reason other than rejection. */\nexport class SigningFailedError extends ZamaError {\n /** Name of the SDK operation that was signing when the wallet/provider failed. */\n readonly operation: string | undefined;\n /** JSON-RPC / EIP-1193 numeric error code found in the failure's cause chain, if any. */\n readonly rpcCode: number | undefined;\n /** `name` of the error class the wallet/provider library threw. */\n readonly walletErrorName: string | undefined;\n\n constructor(message: string, options?: ErrorOptions & SigningErrorMetadata) {\n const { operation, rpcCode, walletErrorName, ...errorOptions } = options ?? {};\n super(ZamaErrorCode.SigningFailed, message, errorOptions);\n this.name = \"SigningFailedError\";\n this.operation = operation;\n this.rpcCode = rpcCode;\n this.walletErrorName = walletErrorName;\n }\n}\n\n/**\n * Classify a caught signing error into {@link SigningRejectedError},\n * {@link SigningFailedError}, or {@link InvalidTransportKeyPairError} and\n * return it rather than throw (mirroring {@link wrapDecryptError}/\n * {@link wrapEncryptError}), so a caller can emit an observability event\n * carrying the classified error before throwing it themselves. Enriches the\n * result with `rpcCode`/`walletErrorName` extracted from `error`'s cause\n * chain, and passes an already-typed `ZamaError` through unchanged.\n */\nexport function wrapSigningError(error: unknown, context: { operation: string }): ZamaError {\n if (error instanceof ZamaError) {\n return error;\n }\n const { operation } = context;\n const hasCode4001 =\n typeof error === \"object\" && error !== null && \"code\" in error && error.code === 4001;\n const originalMsg = error instanceof Error ? error.message : String(error);\n const lowerMsg = originalMsg.toLowerCase();\n const hasRejectionMessage =\n lowerMsg.includes(\"user rejected\") || lowerMsg.includes(\"user denied\");\n const fullMessage = `${operation}: ${originalMsg}`;\n if (hasCode4001 || hasRejectionMessage) {\n return new SigningRejectedError(fullMessage, {\n cause: error,\n operation,\n rpcCode: extractRpcErrorCode(error),\n walletErrorName: extractWalletErrorName(error),\n });\n }\n // A stale transport key pair the relayer can't re-derive (post-rotation) is\n // not a signing failure per se — surface it as the typed, self-heal signal so\n // the caller can evict the vault entry and regenerate.\n if (isInvalidTransportKeyPairMessage(originalMsg)) {\n return new InvalidTransportKeyPairError(fullMessage, { cause: error });\n }\n return new SigningFailedError(fullMessage, {\n cause: error,\n operation,\n rpcCode: extractRpcErrorCode(error),\n walletErrorName: extractWalletErrorName(error),\n });\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{p as e,r as t,t as n}from"./relayer-C3jVhqSK.js";import{a as r,c as i,r as a,s as o,u as s}from"./signing-C6nbPCyd.js";import{B as c,F as l,L as u,P as d,d as f,f as p,j as m,m as h,p as g}from"./erc165-B8gx2luK.js";import{r as _}from"./applied-runtime-3fzqBC2V.js";import{a as v,i as ee,n as y,o as te,r as b,s as x,t as S}from"./primitives-Cym-3HKa.js";import{t as C}from"./validation-ClSvPh6P.js";import{a as ne,i as re,n as ie,o as ae,r as oe,s as se,t as ce}from"./wrappers-registry-Cm3JJeqx.js";import{a as le,c as ue,d as de,l as w,n as T,o as E,s as D,u as fe}from"./chains-iPpnjXql.js";import{getAddress as O,toBytes as k,toHex as A,zeroAddress as pe}from"viem";import{hasFhevmRuntimeConfig as me,setFhevmRuntimeConfig as he}from"@fhevm/sdk/viem";import{z as j}from"zod/mini";var M=class{#e=null;#t=null;#n;#r;#i;constructor(e=`CredentialStore`,t=1,n=`credentials`){this.#n=e,this.#r=t,this.#i=n}#a(){return this.#e?Promise.resolve(this.#e):(this.#t||=new Promise((e,t)=>{let n=indexedDB.open(this.#n,this.#r);n.onupgradeneeded=()=>{let e=n.result;e.objectStoreNames.contains(this.#i)||e.createObjectStore(this.#i,{keyPath:`key`})},n.onsuccess=()=>{this.#e=n.result,this.#t=null,this.#e.onversionchange=()=>{this.#e?.close(),this.#e=null,this.#t=null},this.#e.onclose=()=>{this.#e=null,this.#t=null},e(this.#e)},n.onerror=()=>{this.#e=null,this.#t=null,t(n.error)}}),this.#t)}async#o(e,t){let n=await this.#a();return new Promise((r,i)=>{let a=n.transaction(this.#i,e);a.onabort=()=>i(a.error??Error(`Transaction aborted`));let o=t(a.objectStore(this.#i));e===`readonly`?o.onsuccess=()=>r(o.result):a.oncomplete=()=>r(o.result),o.onerror=()=>i(o.error)})}async get(e){return(await this.#o(`readonly`,t=>t.get(e)))?.value??null}async set(e,t){await this.#o(`readwrite`,n=>n.put({key:e,value:t}))}async delete(e){await this.#o(`readwrite`,t=>t.delete(e))}async clear(){await this.#o(`readwrite`,e=>e.clear())}};const ge=new M;var N=class{#e=new Map;async get(e){return this.#e.get(e)??null}async set(e,t){this.#e.set(e,t)}async delete(e){this.#e.delete(e)}};const _e=new N;function ve(){return typeof window<`u`?new M(`CredentialStore`):new N}function ye(e=ve(),t=e){return{storage:e,permitStorage:t}}function be(e,t,r){let i=e.map(e=>e.id),a=[...new Set(i.filter((e,t)=>i.indexOf(e)!==t))];if(a.length>0)throw new n(`Duplicate chain id(s) [${a.join(`, `)}] in the chains array. Each chain id must appear only once. Note: hardhat and anvil are aliases (both use 31337).`);let o=Object.keys(t).map(Number).filter(e=>!i.includes(e));o.length>0&&r.warn(`Relayer entries for chain(s) [${o.join(`, `)}] are ignored: those chains are not in the chains array. Add the chain config to use them, or drop the relayer entries.`);let s=new Map;for(let r of e){let e=t[r.id];if(!e)throw new n(`Chain ${r.id} has no relayer configured. Add a relayer entry: relayers: { [${r.id}]: web() }`);s.set(r.id,{chain:r,relayerConfig:e})}return s}var xe=class{#e;#t;#n;constructor(e,t,r,i){if(e.length===0)throw new n(`At least one chain is required.`);this.#e=new Map(e.map(e=>[e.id,e])),this.#n=e[0].id;let a=new Map;for(let[n,{relayerConfig:o,chain:s}]of be(e,t,r))a.set(n,o.createRelayer(s,r,i));this.#t=a}get chains(){return[...this.#e.values()]}get chain(){let e=this.#e.get(this.#n);if(e===void 0)throw new n(`Chain ${this.#n} is not configured. Add it to the chains array.`);return e}switchChain(e){this.#n=e}dispose(){for(let e of new Set(this.#t.values()))e.dispose?.()}get relayer(){let e=this.#t.get(this.chain.id);if(e===void 0)throw new n(`No relayer configured for chain ${this.#n}. Add it to the relayers object.`);return e}};const P={version:1,info:`zama-sdk-keypair-wrapping-v1`,ivLengthBytes:12,tagLengthBytes:16};function F(e){return new Uint8Array(e)}function Se(e){return F(new TextEncoder().encode(JSON.stringify([e.publicKey,e.createdAt,e.expiresAt,e.tkmsVersion??null])))}function Ce(e){return typeof e==`string`?new TextEncoder().encode(e):F(e)}var we=class{#e;#t;constructor(e){this.#e=e}async baseKey(){return this.#t??=this.#n(this.#e),this.#t}async#n(e){let t=Ce(e),n=await crypto.subtle.importKey(`raw`,t,`HKDF`,!1,[`deriveKey`]);return t.fill(0),e instanceof Uint8Array&&e.fill(0),this.#e=void 0,n}};async function I(e,t){let n=await e.baseKey();return crypto.subtle.deriveKey({name:`HKDF`,hash:`SHA-256`,salt:new TextEncoder().encode(t),info:new TextEncoder().encode(P.info)},n,{name:`AES-GCM`,length:256},!1,[`encrypt`,`decrypt`])}async function Te(e,t,n,r){let i=await I(t,n),a=crypto.getRandomValues(new Uint8Array(P.ivLengthBytes)),o=await crypto.subtle.encrypt({name:`AES-GCM`,iv:a,additionalData:Se(r)},i,F(k(e)));return{wrappedPrivateKey:A(new Uint8Array(o)),iv:A(a)}}async function Ee(e,t,n,r){let i=await I(t,n),a=await crypto.subtle.decrypt({name:`AES-GCM`,iv:F(k(e.iv)),additionalData:Se(r)},i,F(k(e.wrappedPrivateKey)));return A(new Uint8Array(a))}function De(e){return typeof e==`object`&&!!e&&`name`in e&&e.name===`OperationError`}const L=86400;function R(){return Math.floor(Date.now()/1e3)}function z(e){return[...new Set(e.map(S))].sort()}function Oe(e){let{chainId:t}=e.domain;return typeof t==`bigint`?{...e,domain:{...e.domain,chainId:t.toString()}}:e}const B=`transportKeyPairTTL must be a positive integer number of seconds`,V=`permitTTL must be a positive integer number of days`,H=`transportKeyPairScope must be a non-empty string`,U=`transportKeyPairDerivationSecret must be a Uint8Array of at least 32 bytes or a string of at least 64 characters (256 bits of entropy): source it from a CSPRNG or secrets manager, not a human-memorable passphrase`,ke=365*L,Ae=j.int({error:B}).check(j.positive({error:B}),j.maximum(ke,`transportKeyPairTTL must not exceed the fhevm ACL maximum of ${ke}s (365 days)`)),je=j.int({error:V}).check(j.positive({error:V}),j.maximum(365,`permitTTL must not exceed the V1 permit maximum of 365 days`)),Me=j.string({error:H}).check(j.minLength(1,H)),Ne=j.union([j.string({error:U}).check(j.minLength(64,U)),j.instanceof(Uint8Array,{error:U}).check(j.refine(e=>e.byteLength>=32,{error:U}))],{error:U}),Pe=j.object({publicKey:b,privateKey:b,createdAt:x,expiresAt:te,tkmsVersion:j.optional(j.string())}),W=j.object({domain:j.record(j.string(),j.unknown()),primaryType:j.optional(j.string()),types:j.record(j.string(),j.array(j.object({name:j.string(),type:j.string()}))),message:j.record(j.string(),j.unknown())}),G=j.object({version:j.int().check(j.positive()),eip712:W,signature:b,signerAddress:y}),K=j.object({keypairPublicKey:b,contractAddresses:j.array(y).check(j.maxLength(10)),serializedPermit:G,startTimestamp:x,durationDays:v}),Fe=j.array(K),Ie=j.array(j.string()),Le=j.object({version:j.literal(1),eip712:W,signerAddress:y}),Re=`iv must be a ${P.ivLengthBytes}-byte hex string`,ze=`wrappedPrivateKey must be a whole number of bytes and at least ${P.tagLengthBytes} bytes (the AES-GCM authentication tag)`;function Be(e){return(e.length-2)/2}const Ve=j.object({wrappingVersion:j.literal(P.version,{error:`wrappingVersion must be a wrapping scheme this SDK can read`}),publicKey:b,wrappedPrivateKey:b.check(j.refine(e=>e.length%2==0&&Be(e)>=P.tagLengthBytes,{error:ze})),iv:b.check(j.refine(e=>Be(e)===P.ivLengthBytes,{error:Re})),createdAt:x,expiresAt:te,tkmsVersion:j.optional(j.string())});function He(e){let t={publicKey:e.publicKey,createdAt:e.createdAt,expiresAt:e.expiresAt};return e.tkmsVersion&&(t.tkmsVersion=e.tkmsVersion),t}const q={version:P.version,schema:Ve,async encode(e,t,n){let{wrappedPrivateKey:r,iv:i}=await Te(e.privateKey,t,n,He(e)),a={wrappingVersion:P.version,publicKey:e.publicKey,wrappedPrivateKey:r,iv:i,createdAt:e.createdAt,expiresAt:e.expiresAt};return e.tkmsVersion&&(a.tkmsVersion=e.tkmsVersion),a},async decode(e,t,n){let r=await Ee({wrappedPrivateKey:e.wrappedPrivateKey,iv:e.iv},t,n,He(e)),i={publicKey:e.publicKey,privateKey:r,createdAt:e.createdAt,expiresAt:e.expiresAt};return e.tkmsVersion&&(i.tkmsVersion=e.tkmsVersion),i}},Ue=new Map([[q.version,q]]),We=q;function Ge(e){let t=e;return t.wrappingVersion!==void 0||t.wrappedPrivateKey!==void 0&&t.iv!==void 0}function Ke(e){if(typeof e!=`object`||!e||!Ge(e)){let t=Pe.safeParse(e);return t.success?{kind:`plaintext`,keyPair:t.data}:{kind:`unrecognized`}}let t=e.wrappingVersion,n=typeof t==`number`?Ue.get(t):void 0;if(n===void 0)return{kind:`unsupported-version`,version:t};let r=n.schema.safeParse(e);if(!r.success)return{kind:`corrupt-wrapped`};let i=r.data;return{kind:`wrapped`,expiresAt:i.expiresAt,decode:(e,t)=>n.decode(i,e,t)}}function qe(e,t,n){return We.encode(e,t,n)}function Je(e){return`keypair:${e}`}function J(e){return`keypair:scope:${e}`}function Y(e){return`permits:${e.signerAddress}:${e.chainId}:${e.delegatorAddress}`}function X(e){return`permits-index:${e}`}function Z(e){return`scope:${e}`}function Ye(e,t){return{"wrapped-without-secret":`Transport key pair for scope "${t}" is wrapped, but this instance has no transportKeyPairDerivationSecret configured. Every instance sharing this scope must use the same transportKeyPairDerivationSecret; once they do, call permits.revokeTransportKeyPair() to rotate the entry.`,"unwrapped-under-secret":`Transport key pair for scope "${t}" is stored unwrapped, but this instance is configured with a transportKeyPairDerivationSecret. A peer instance sharing this scope is running without the secret: configure the same transportKeyPairDerivationSecret everywhere, then call permits.revokeTransportKeyPair() to migrate the scope to a wrapped entry.`,"unwrap-failed":`Transport key pair for scope "${t}" failed to unwrap. This usually means another instance created it with a different transportKeyPairDerivationSecret: every instance sharing this scope must use the same secret. It can also mean the stored entry is corrupted.`,"corrupt-wrapped":`Transport key pair for scope "${t}" is wrapped but structurally invalid: the stored iv or ciphertext is not a shape this wrapping scheme can produce. This usually means the stored entry is corrupted, or instances sharing this scope are running mismatched wrapping-scheme versions.`}[e]}const Xe={"unwrapped-under-secret":`unwrapped transport key pair entry found while a transportKeyPairDerivationSecret is configured`,"unwrap-failed":`transport key pair entry failed to unwrap (wrong transportKeyPairDerivationSecret?)`,"corrupt-wrapped":`structurally invalid wrapped transport key pair entry`};function Ze(e,t){let n=typeof e==`number`?`wrappingVersion ${e}`:`no wrappingVersion this build recognizes`;return`Transport key pair ${t===void 0?`for this signer`:`for scope "${t}"`} was written under a wrapping scheme this SDK build cannot read (${n}). The entry is preserved instead of regenerated, since an instance that understands the scheme may still be using it: ${t===void 0?`run a build that supports it, or call permits.clear() to discard the entry deliberately`:`run a build that supports it everywhere, or call permits.revokeTransportKeyPair() to rotate the scope`}.`}var Qe=class{#e;#t;#n;#r;#i;#a;#o=new Map;#s=new Map;constructor(e){this.#e=e.generator,this.#t=e.storage,this.#n=e.ttl,this.#r=e.logger,this.#i=e.scope,this.#a=e.derivationSecret}#c(e){return this.#i===void 0?`signer:${e}`:Z(this.#i)}#l(e){return this.#i===void 0?Je(e):J(this.#i)}async readStored(e){return this.#u(this.#l(e),this.#c(e))}async#u(e,t){let n=await this.#t.get(e);if(n==null)return null;let i=Ke(n);if(i.kind===`unsupported-version`)throw this.#f(e,Ze(i.version,this.#i));if(i.kind===`unrecognized`)return await this.#m(e,`malformed transport key pair entry`),null;let a=this.#a;if(a===void 0)return i.kind===`plaintext`?await this.#p(e,i.keyPair.expiresAt)?null:i.keyPair:this.#d(e,`wrapped-without-secret`);if(i.kind===`plaintext`)return this.#d(e,`unwrapped-under-secret`);if(i.kind===`corrupt-wrapped`)return this.#d(e,`corrupt-wrapped`);if(await this.#p(e,i.expiresAt))return null;try{return await i.decode(a,t)}catch(t){if(!De(t))throw this.#r.error(`transport key pair unwrap failed unexpectedly`,{key:e,error:t}),new r(`Transport key pair unwrap failed unexpectedly.`,{cause:t});return this.#d(e,`unwrap-failed`,t)}}async#d(e,t,n){if(this.#i!==void 0)throw this.#f(e,Ye(t,this.#i),n);if(t===`wrapped-without-secret`)throw this.#f(e,`Transport key pair for this signer is wrapped, but this instance has no transportKeyPairDerivationSecret configured. Configure the same transportKeyPairDerivationSecret the entry was written with. To downgrade to plaintext at rest on purpose, discard the stored entry first by calling permits.clear(), then run without the secret.`,n);let r=Xe[t];return this.#r.warn(r,{key:e}),await this.#m(e,r),null}#f(e,t,n){return this.#r.error(t,{key:e}),new r(t,{cause:n})}async#p(e,t){return R()<t?!1:(await this.#m(e,`expired transport key pair entry`),!0)}async#m(e,t){this.#r.debug(`discarding transport key pair entry`,{key:e,reason:t}),await m(`delete transport key pair entry`,()=>this.#t.delete(e),this.#r)}async getOrCreate(e,t){return this.#h(this.#l(e),this.#c(e),{strict:t?.strict})}async#h(e,t,n){let i=n?.strict??!1,a=`${e}::${i}`,o=this.#o.get(a);if(o)return o;let c=this.#s.get(e)??0,l=(async()=>{let n=await this.#u(e,t);if(n!==null)return n;let a=await this.#e(),o=R(),l=o+this.#n,u={publicKey:a.publicKey,privateKey:a.privateKey,createdAt:o,expiresAt:l};a.tkmsVersion&&(u.tkmsVersion=a.tkmsVersion);let d=u;if(this.#a!==void 0)try{d=await qe(u,this.#a,t)}catch(t){let n=`Failed to wrap the transport private key for at-rest storage.`;throw this.#r.error(n,{key:e,error:t}),new r(n,{cause:t})}if((this.#s.get(e)??0)===c)i?await this.#t.set(e,d):await m(`persist transport key pair`,()=>this.#t.set(e,d),this.#r);else if(i)throw new s(`The transport key pair was rotated while it was being generated, so the freshly generated key pair could not be persisted. Retry.`);return u})().finally(()=>{this.#o.delete(a)});return this.#o.set(a,l),l}async clear(e){let t=Je(e);await m(`delete transport key pair entry`,()=>this.#t.delete(t),this.#r)}async evict(e){let t=this.#l(e);await m(`evict transport key pair entry`,()=>this.#t.delete(t),this.#r)}async clearScope(){if(this.#i===void 0)return;let e=J(this.#i);this.#s.set(e,(this.#s.get(e)??0)+1),await this.#t.delete(e)}async warmScope(){this.#i!==void 0&&await this.#h(J(this.#i),Z(this.#i),{strict:!0})}};function $e(e){return C(Le,e)}function et(e,t){let n=new Set(e.flatMap(e=>e.contractAddresses));return t.filter(e=>!n.has(e))}function tt(e){let t=[];for(let n=0;n<e.length;n+=10)t.push(e.slice(n,n+10));return t}function nt(e,t,n){return e.filter(e=>e.keypairPublicKey===t&&n<e.startTimestamp+e.durationDays*86400)}function rt(e,t){let n=new Set(t);return e.filter(e=>!e.contractAddresses.some(e=>n.has(e)))}function it(e,t){return[...new Set([...e,...t])].sort()}function at(e,t,n){let r=new Set(n),i=e.filter(e=>new Set([...e.contractAddresses,...t]).size<=10);if(i.length===0)return null;function a(e){return e.contractAddresses.reduce((e,t)=>e+ +!!r.has(t),0)}let o=Math.max(...i.map(a));return i.filter(e=>a(e)===o).reduce((e,t)=>t.startTimestamp>e.startTimestamp?t:e)}var ot=class{#e;#t;constructor(e){this.#e=e.storage,this.#t=e.logger}async list(e){let t=Y(e),n=await this.#e.get(t);if(n==null)return[];let r=Fe.safeParse(n);return r.success?r.data:(await this.clearScope(e),[])}async listUsableAndPrune(e,t){let n=await this.list(e),r=nt(n,t,Math.floor(Date.now()/1e3));return r.length!==n.length&&(r.length===0?await this.clearScope(e):await m(`update permit entry`,()=>this.#e.set(Y(e),r),this.#t)),r}async append(e,t){if(t.length===0)return;let n=t.map(e=>K.parse(e)),r=await this.list(e);await this.#e.set(Y(e),[...r,...n]),await this.#r(e)}async replace(e,t,n){let r=K.parse(n),i=(await this.list(e)).filter(e=>e.serializedPermit.signature!==t);await this.#e.set(Y(e),[...i,r]),await this.#r(e)}async deletePermitsTouching(e,t){let n=await this.list(e);if(n.length===0)return;let r=rt(n,t);r.length===0?await this.clearScope(e):await this.#e.set(Y(e),r)}async clearScope(e){await this.#a(Y(e)),await this.#i(e)}async clearAllForSigner(e){let t=X(e),n=await this.#n(t);await Promise.all(n.map(e=>this.#a(e))),await m(`delete permit index`,()=>this.#e.delete(t),this.#t)}async#n(e){let t=await this.#e.get(e);if(t==null)return[];let n=Ie.safeParse(t);return n.success?n.data:(await m(`delete permit index`,()=>this.#e.delete(e),this.#t),[])}async#r(e){let t=X(e.signerAddress),n=Y(e),r=await this.#n(t);r.includes(n)||await this.#e.set(t,[...r,n])}async#i(e){let t=X(e.signerAddress),n=Y(e),r=await this.#n(t),i=r.filter(e=>e!==n);i.length!==r.length&&(i.length===0?await m(`delete permit index`,()=>this.#e.delete(t),this.#t):await m(`update permit index`,()=>this.#e.set(t,i),this.#t))}async#a(e){await m(`delete permit entry`,()=>this.#e.delete(e),this.#t)}};async function st(e,t,n){let r=e.get(t);if(r!==void 0)return r;let i=await n();return e.set(t,i),i}var ct=class{#e;#t;#n;#r;#i;#a;#o;#s;#c=new Map;constructor(e){this.#e=new Qe({generator:async()=>{let t=e.router.relayer,n=await t.generateTransportKeyPair();return t.serializeTransportKeyPair({transportKeyPair:n})},storage:e.storage,ttl:e.transportKeyPairTTL,logger:e.logger,scope:e.scope,derivationSecret:e.derivationSecret}),this.#t=new ot({storage:e.permitStorage??e.storage,logger:e.logger}),this.#n=e.router,this.#r=e.signer,this.#i=e.permitTTL,this.#a=e.logger,this.#o=e.emitEvent,this.#s=e.scope}#l(e){if(!this.#r)throw new u(e);return this.#r}#u(e,t,n=``){let r=a(t,{operation:e});return n&&(r.message=n+r.message),this.#o({type:l.PermitError,operation:e,error:r}),r}async grantPermit(e,t){let n=t===void 0?`grantPermit`:`grantDelegationPermit`,r,i,a;try{r=S(this.#l(`grantPermit`).requireWalletAccount(`grantPermit`).address),i=z(e),a=this.#f(r,t)}catch(e){throw this.#u(n,e)}let o=await this.#e.getOrCreate(r);if(i.length===0)return{keypair:o,permissions:[]};let s;try{s=await this.#t.listUsableAndPrune(a,o.publicKey)}catch(e){throw this.#u(n,e)}let c=et(s,i);if(c.length>0){let e=at(s,c,i);if(e!==null){let t=it(e.contractAddresses,c),n=await this.#p({chunk:t,keypair:o,scope:a});await m(`replace permit`,()=>this.#t.replace(a,e.serializedPermit.signature,n),this.#a),s[s.indexOf(e)]=n}else for(let e of tt(c)){let t=await this.#p({chunk:e,keypair:o,scope:a});s.push(t),await m(`persist permit`,()=>this.#t.append(a,[t]),this.#a)}}let l=new Set(i);return{keypair:o,permissions:s.filter(e=>e.contractAddresses.some(e=>l.has(e)))}}async preparePermit(e){let t=z(e.contracts).length;if(t>10)throw new n(`preparePermit: request.contracts must not exceed 10 addresses (got ${t}). Use batchPreparePermits to split them across permits.`);let[r]=await this.batchPreparePermits(e);return d(r,`batchPreparePermits result`),r}async batchPreparePermits(e){let t=S(e.signer),r=z(e.contracts);if(r.length===0)throw new n(`request.contracts must not be empty.`);let i=e.delegator?S(e.delegator):void 0;if(i!==void 0&&i===t)throw new n(`request.delegator must differ from request.signer: self-delegation is not allowed.`);let a=e.durationDays===void 0?this.#i:C(je,e.durationDays),o=this.#n.relayer,s=await this.#e.getOrCreate(t,{strict:!0}),c=await o.parseTransportKeyPair(s),l=R();return Promise.all(tt(r).map(async e=>({version:1,eip712:Oe(W.parse(await o.createUnsignedLegacyDecryptionPermitEip712({transportKeyPair:c,contractAddresses:e,startTimestamp:l,durationSeconds:a*L,...i&&{delegatorAddress:i}}))),signerAddress:t})))}async batchRegisterPermits(e){if(e.length===0)throw new n(`permits must not be empty.`);let t={relayer:this.#n.relayer,activeChainId:this.#n.chain.id,storedKeyPairs:new Map,transportKeyPairs:new Map},r=[];for(let[n,{prepared:i,signature:a}]of e.entries()){let o=e.length>1?`permits[${n}]: `:``;r.push(await this.#d(i,a,t,o))}for(let{scope:e,permission:t}of r)await m(`replace permit`,()=>this.#t.replace(e,t.serializedPermit.signature,t),this.#a)}async#d(e,t,{relayer:r,activeChainId:a,storedKeyPairs:c,transportKeyPairs:l},u){let d;try{d=$e(e)}catch(e){throw this.#u(`registerPermit`,e,u)}let{domain:f,message:p}=d.eip712,m=Number(f.chainId);if(m!==a)throw this.#u(`registerPermit`,new o({preparedChainId:m,activeChainId:a}),u);let h=Number(p.startTimestamp),g=Number(p.durationDays);if(R()>=h+g*86400)throw this.#u(`registerPermit`,new i(`registerPermit: the prepared permit's validity window (starting ${h}, ${g}d) has already elapsed. Prepare the permit again.`),u);let _=d.signerAddress,v=await st(c,_,()=>this.#e.readStored(_));if(v===null||v.publicKey!==p.publicKey)throw new s(`${u}registerPermit: the transport key pair changed since the permit was prepared. Prepare it again to rebind the signature request to the current key pair.`);try{let e=await st(l,_,()=>r.parseTransportKeyPair(v)),i=await r.parseSignedDecryptionPermit({serializedPermit:{version:d.version,eip712:d.eip712,signature:t,signerAddress:_},transportKeyPair:e});if(i.version!==1)throw new n(`registerPermit: expected a V1 signed permit, got version ${i.version}.`);let o=C(G,await r.serializeSignedDecryptionPermit({signedPermit:i})),s={keypairPublicKey:v.publicKey,contractAddresses:z(i.eip712.message.contractAddresses),serializedPermit:o,startTimestamp:Number(i.eip712.message.startTimestamp),durationDays:Number(i.eip712.message.durationDays)};return{scope:{signerAddress:_,chainId:a,delegatorAddress:S(i.encryptedDataOwnerAddress)},permission:s}}catch(e){throw this.#u(`registerPermit`,e,u)}}async hasPermit(e,t){if(e.length===0)return!0;let n=this.#r?.walletAccount.getSnapshot();if(!n)return!1;let i=S(n.address),a;try{a=await this.#e.readStored(i)}catch(e){if(!(e instanceof r))throw e;return!1}if(a===null)return!1;let o=this.#f(i,t);return et(await this.#t.listUsableAndPrune(o,a.publicKey),z(e)).length===0}async revokePermits(e){let t=S(this.#l(`revokePermits`).requireWalletAccount(`revokePermits`).address);if(e===void 0){await this.#t.clearAllForSigner(t);return}let n=z(e);n.length!==0&&await this.#t.deletePermitsTouching(this.#f(t),n)}#f(e,t){return{signerAddress:e,chainId:this.#n.chain.id,delegatorAddress:t?S(t):e}}async clearCredentials(){let e=S(this.#l(`clearCredentials`).requireWalletAccount(`clearCredentials`).address);await this.#e.clear(e),await this.#t.clearAllForSigner(e)}async revokeTransportKeyPair(e){if(this.#s===void 0)throw new n(`revokeTransportKeyPair() requires a transportKeyPairScope to be configured on this SDK instance — there is no shared key pair to revoke.`);if(e!==this.#s)throw new n(`revokeTransportKeyPair("${e}") does not match the configured scope ("${this.#s}").`);await this.#e.clearScope()}async warmTransportKeyPair(e){await this.#e.getOrCreate(S(e))}async warmTransportKeyPairScope(e){if(this.#s===void 0)throw new n(`warmTransportKeyPairScope() requires a transportKeyPairScope to be configured on this SDK instance — there is no shared key pair to warm.`);if(e!==this.#s)throw new n(`warmTransportKeyPairScope("${e}") does not match the configured scope ("${this.#s}").`);await this.#e.warmScope()}async handleWalletAccountChange(e,t){let n=e?S(e.address):void 0;n!==(t?S(t.address):void 0)&&n&&(await this.#e.clear(n),await this.#t.clearAllForSigner(n))}async#p(n){let{chunk:r,keypair:i,scope:a}=n,o=R(),s=a.delegatorAddress!==a.signerAddress,c=this.#n.relayer;try{let e={transportKeyPair:await c.parseTransportKeyPair(i),contractAddresses:r,startTimestamp:o,durationSeconds:this.#i*L,signerAddress:a.signerAddress,signer:this.#l(`signPermit`)},t=s?await c.signDecryptionPermit({...e,delegatorAddress:a.delegatorAddress}):await c.signDecryptionPermit(e),n=C(G,await c.serializeSignedDecryptionPermit({signedPermit:t}));return{keypairPublicKey:i.publicKey,contractAddresses:r,serializedPermit:n,startTimestamp:o,durationDays:this.#i}}catch(n){let r=s?`grantDelegationPermit`:`grantPermit`;throw!(n instanceof t)&&n instanceof Error&&e(n.message)&&await this.#e.evict(a.signerAddress),this.#u(r,n)}}async evictTransportKeyPair(){let e=this.#r?.walletAccount.getSnapshot();e&&await this.#e.evict(S(e.address))}async recoverPermits(e,t,n){let r=this.#l(`recoverPermits`).requireWalletAccount(`recoverPermits`),i=this.#f(S(r.address),t),a=Y(i),o=this.#c.get(a);if(o)return await o,this.grantPermit(e,t);let s=await this.#m(i),c=this.#c.get(a);if(c)return await c,this.grantPermit(e,t);if(s===null)return this.grantPermit(e,t);let l=new Set(n??[]);if(l.size>0&&!s.some(e=>l.has(e.serializedPermit.signature)))return this.grantPermit(e,t);let u=s.filter(e=>!l.has(e.serializedPermit.signature)),d=s.flatMap(e=>e.contractAddresses),f=this.#h(i,d,e,u,t).finally(()=>{this.#c.delete(a)});return this.#c.set(a,f),await f,this.grantPermit(e,t)}async#m(e){try{return await this.#t.list(e)}catch(e){return this.#a.warn(`read permits for recovery failed`,{error:e}),null}}async#h(e,t,n,r,i){await m(`evict revoked permits`,()=>this.#t.clearScope(e),this.#a);try{await this.grantPermit(it(t,z(n)),i)}catch(t){throw r.length>0&&await m(`restore surviving permits`,async()=>{let t=await this.#t.list(e),n=new Set(t.map(e=>e.serializedPermit.signature)),i=r.filter(e=>!n.has(e.serializedPermit.signature));i.length>0&&await this.#t.append(e,i)},this.#a),t}}},lt=class{#e;#t=`[zama-sdk]`;constructor(e){this.#e=e}error(e,t){this.#e?.error(`${this.#t} ${e}`,t)}warn(e,t){this.#e?.warn(`${this.#t} ${e}`,t)}info(e,t){this.#e?.info(`${this.#t} ${e}`,t)}debug(e,t){this.#e?.debug(`${this.#t} ${e}`,t)}warnAlways(e){console.warn(`${this.#t} ${e}`),this.warn(e)}};const ut={[D.id]:D.registryAddress,[ue.id]:ue.registryAddress,[fe.id]:fe.registryAddress,[w.id]:w.registryAddress,[le.id]:le.registryAddress,[E.id]:E.registryAddress,[de.id]:de.registryAddress,[T.id]:T.registryAddress},dt=j.record(j.string().check(j.regex(/^\d+$/,`expected numeric chain id key`)),y),ft=ee,Q=300*1e3;var pt=class{provider;#e;#t;#n=new Map;constructor(e){this.provider=e.provider,this.#e=Object.assign({},ut,C(j.optional(dt),e.registryAddresses)),this.#t=C(ft,e.registryTTL??86400)*1e3}getAddress(e){return this.#e[e]}#r(e){let t=this.#n.get(e);if(t){if(Date.now()>=t.expiresAt){this.#n.delete(e);return}return t.data}}#i(e,t,n=this.#t){return this.#n.set(e,{data:t,expiresAt:Date.now()+n}),t}refresh(){this.#n.clear()}get ttlMs(){return this.#t}async getRegistryAddress(){let e=await this.provider.getChainId(),t=this.#e[e];if(!t)throw new n(`No wrappers registry address configured for chain ${e}.\nPass a registryAddresses entry for this chain.`);return O(t)}async listPairs(e={}){let t=e.page??1,r=e.pageSize??100,i=e.metadata??!1;if(t<1)throw new n(`page must be >= 1, got ${t}`);if(r<1)throw new n(`pageSize must be >= 1, got ${r}`);let a=await this.getRegistryAddress(),o=`total:${a}`,s=this.#r(o);if(s===void 0){let e=await this.provider.readContract(ne(a));s=this.#i(o,Number(e))}let c=BigInt((t-1)*r),l=c+BigInt(r)>BigInt(s)?BigInt(s):c+BigInt(r);if(c>=BigInt(s))return{items:[],total:s,page:t,pageSize:r};let u=`slice:${a}:${c}:${l}`,d=this.#r(u);if(d===void 0){let e=await this.provider.readContract(ae(a,c,l));d=this.#i(u,[...e])}if(!i)return{items:d,total:s,page:t,pageSize:r};let f=`metadata:${a}:${c}:${l}`,p=this.#r(f);if(p===void 0){let e=await Promise.allSettled(d.map(e=>this.#a(e))),t=e.some(e=>e.status===`rejected`),n=e.map((e,t)=>e.status===`fulfilled`?e.value:Object.assign({},d[t],{metadataFailed:!0,underlying:{name:`Unknown`,symbol:`???`,decimals:0,totalSupply:0n},confidential:{name:`Unknown`,symbol:`???`,decimals:0}}));p=this.#i(f,n,t?Q:void 0)}return{items:p,total:s,page:t,pageSize:r}}async#a(e){let[t,n,r,i,a,o,s]=await Promise.all([this.provider.readContract(g(e.tokenAddress)),this.provider.readContract(h(e.tokenAddress)),this.provider.readContract(f(e.tokenAddress)),this.provider.readContract(p(e.tokenAddress)),this.provider.readContract(g(e.confidentialTokenAddress)),this.provider.readContract(h(e.confidentialTokenAddress)),this.provider.readContract(f(e.confidentialTokenAddress))]);return{...e,underlying:{name:t,symbol:n,decimals:r,totalSupply:i},confidential:{name:a,symbol:o,decimals:s}}}async getConfidentialToken(e){let t=await this.getRegistryAddress(),n=O(e),r=`ct:${t}:${n}`,i=this.#r(r);if(i!==void 0)return i;let[a,o]=await this.provider.readContract(ce(t,n));return o===pe?this.#i(r,null,Q):this.#i(r,{confidentialTokenAddress:o,isValid:a})}async getUnderlyingToken(e){let t=await this.getRegistryAddress(),n=O(e),r=`ut:${t}:${n}`,i=this.#r(r);if(i!==void 0)return i;let[a,o]=await this.provider.readContract(ie(t,n));return o===pe?this.#i(r,null,Q):this.#i(r,{tokenAddress:o,isValid:a})}async getTokenPairs(){let e=await this.getRegistryAddress();return this.provider.readContract(re(e))}async getTokenPairsLength(){let e=await this.getRegistryAddress();return this.provider.readContract(ne(e))}async getTokenPairsSlice(e,t){let n=await this.getRegistryAddress();return this.provider.readContract(ae(n,e,t))}async getTokenPair(e){let t=await this.getRegistryAddress();return this.provider.readContract(oe(t,e))}async getConfidentialTokenAddress(e){let t=await this.getRegistryAddress();return this.provider.readContract(ce(t,O(e)))}async getTokenAddress(e){let t=await this.getRegistryAddress();return this.provider.readContract(ie(t,O(e)))}async isConfidentialTokenValid(e){let t=await this.getRegistryAddress();return this.provider.readContract(se(t,O(e)))}};function mt(e,t,n){let r=new lt(n.logger),i=n.logger,a={wasmAssetLoadMode:`auto`,moduleVersions:`auto`,logger:{error:(e,t)=>i?.error(e,{cause:t}),warn:e=>i?.warn(e),debug:e=>i?.debug(e)},...n.runtime};if(me()){let e=`runtime configuration is already set and cannot be changed.`;n.runtime===void 0?r.debug(e):r.warn(e)}else he(a),_(a);let{storage:o,permitStorage:s}=ye(n.storage,n.permitStorage),c=n.telemetry===!1?void 0:{layer:`core`},l=new xe(n.chains,n.relayers,r,c);return{chains:n.chains,router:l,provider:t,signer:e,storage:o,permitStorage:s,transportKeyPairTTL:C(Ae,n.transportKeyPairTTL??2592e3),permitTTL:C(je,n.permitTTL??30),transportKeyPairScope:n.transportKeyPairScope===void 0?void 0:C(Me,n.transportKeyPairScope),registryTTL:C(ft,n.registryTTL??86400),logger:r,onEvent:n.onEvent,telemetry:c}}function ht(e,t){return e?.address===t?.address&&e?.chainId===t?.chainId}var $=class{#e=new Set;#t;#n;constructor(e){this.#t=e,this.#n=e!==void 0}getSnapshot(){return this.#t}isReady(){return this.#n}setSnapshot(e){this.#n=!0;let t=this.#t;ht(t,e)||(this.#t=e,this.#r({previous:t,next:e}))}subscribe(e){this.#e.add(e);let t=this.#t;return t&&e({previous:void 0,next:t}),()=>{this.#e.delete(e)}}#r(e){for(let t of this.#e)t(e)}};function gt(e){return new $(e)}var _t=class{walletAccount;#e=!1;constructor(e){this.walletAccount=new $(e)}requireWalletAccount(e){let t=this.walletAccount.getSnapshot();if(!t)throw new c(e);return t}dispose(){this.#e||(this.#e=!0,this.onDispose())}[Symbol.dispose](){this.dispose()}onDispose(){}};export{ut as a,$e as c,N as d,_e as f,mt as i,Ne as l,ge as m,$ as n,pt as o,M as p,gt as r,ct as s,_t as t,we as u};
|
|
2
|
-
//# sourceMappingURL=base-signer-CNHZZnr2.js.map
|