@quip.network/quip-swap-sdk 0.1.0-beta.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/LICENSE +235 -0
- package/README.md +124 -0
- package/dist/index.d.ts +3136 -0
- package/dist/index.js +2596 -0
- package/dist/index.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/types.ts","../src/errors.ts","../src/assets.ts","../src/terms.ts","../src/windows.ts","../src/hashing.ts","../src/secrets.ts","../src/deployments.ts","../src/address.json","../src/gas.ts","../src/client.ts","../src/generated/omnibusAbi.ts","../src/events.ts","../src/receipts.ts","../src/approvals.ts","../src/buffers.ts","../src/workflows/sameChain.ts","../src/workflows/crossChain.ts"],"sourcesContent":["/**\n * Core protocol types mirroring `src/TermsLib.sol` and\n * `src/interfaces/IOmnibus.sol` exactly.\n *\n * Every Solidity integer (`uint256`, token ids, amounts, chain ids,\n * timestamps, fees) is represented as `bigint` — never `number` — because\n * `uint256` exceeds `Number.MAX_SAFE_INTEGER`.\n */\nimport type {Address, Hex} from 'viem'\n\n/**\n * The type of asset in a swap leg.\n *\n * Mirrors the Solidity `enum AssetType` (encoded as `uint8` in the ABI).\n * The numeric values MUST match the Solidity declaration order — they are\n * part of the terms digest, so a mismatch breaks hash agreement with the\n * contract.\n *\n * @see TermsLib (enum AssetType)\n */\nexport enum AssetType {\n /** Native chain currency (ETH on mainnet, etc.). */\n Native = 0,\n /** An ERC-20 fungible token. */\n ERC20 = 1,\n /** An ERC-721 non-fungible token (one specific token id). */\n ERC721 = 2,\n /** An ERC-1155 semi-fungible token (a quantity of one token id). */\n ERC1155 = 3,\n}\n\n/**\n * Lifecycle state of a hashlock in the Omnibus contract.\n *\n * Mirrors the Solidity `enum LockState`. Valid transitions (enforced\n * on-chain by `Omnibus._advanceLockTo`):\n *\n * ```text\n * Unused -> Free (first same-chain commit)\n * Unused -> Committed (cross-chain local commit)\n * Free -> Committed (second same-chain commit, other side)\n * Free -> Spent (reclaim of a half-committed same-chain swap)\n * Committed -> Spent (claim or reclaim)\n * ```\n *\n * @see IOmnibus (enum LockState), Omnibus._advanceLockTo\n */\nexport enum LockState {\n /** Default — the lock has never been used. */\n Unused = 0,\n /** Same-chain only: one party has committed, waiting for the counterparty. */\n Free = 1,\n /** Ready for claim (same-chain: both committed; cross-chain: the single local commit). */\n Committed = 2,\n /** Terminal — claimed or reclaimed. */\n Spent = 3,\n}\n\n/**\n * An asset to be transferred as part of a swap.\n *\n * Mirrors the Solidity `struct Asset` field-for-field. All four fields are\n * part of the terms digest, so canonical field values matter: two assets\n * that move the same tokens but differ in any field produce different\n * digests and therefore different swaps.\n *\n * @see TermsLib (struct Asset)\n */\nexport interface Asset {\n /** The kind of asset; encoded as `uint8` in the ABI. */\n readonly assetType: AssetType\n /** Token contract address; MUST be the zero address for {@link AssetType.Native}. */\n readonly target: Address\n /**\n * Token id; used by ERC-721 and ERC-1155 and MUST be `0n` for Native and\n * ERC-20 (the contract rejects a non-zero id for ERC-20 with\n * `InvalidERC20Asset`). Token id `0n` is explicitly VALID for ERC-721 and\n * ERC-1155.\n */\n readonly id: bigint\n /**\n * Quantity in the token's base units (wei for native). MUST be greater\n * than zero for every asset type — including ERC-721, where the SDK\n * canonicalizes the value to `1n` (see {@link erc721Asset}).\n */\n readonly amount: bigint\n}\n\n/**\n * The terms for a single party (one \"leg\") of an Omnibus swap.\n *\n * Mirrors the Solidity `struct Terms` field-for-field. A swap consists of\n * two `Terms` whose lifecycle timestamps strictly interleave (see\n * {@link validateTermPairing}); the side with the earlier\n * `commitmentDeadline` is the PROPOSER and commits first.\n *\n * @see TermsLib (struct Terms)\n */\nexport interface Terms {\n /**\n * The chain id where THIS side's assets are held and escrowed. The two\n * sides may name different chains (cross-chain swap) or the same chain\n * (same-chain swap). Must be non-zero.\n */\n readonly chainId: bigint\n /**\n * The address that receives this side's own assets back if the swap is\n * reclaimed instead of claimed. Must be non-zero.\n */\n readonly reclaimRecipient: Address\n /**\n * The address that receives the COUNTERPARTY's assets when the swap is\n * claimed — not this side's own assets. Must be non-zero.\n */\n readonly recipient: Address\n /**\n * Unix timestamp (seconds) at and after which this side may no longer\n * commit. Also the instant the counterparty-taker's commit window opens\n * when this side proposes. Must be non-zero.\n */\n readonly commitmentDeadline: bigint\n /**\n * Unix timestamp (seconds) at and after which claiming gated by this\n * side's claim schedule is forbidden. Must be strictly greater than\n * `commitmentDeadline`.\n */\n readonly claimDeadline: bigint\n /**\n * Unix timestamp (seconds) at and after which this side's escrowed assets\n * may be reclaimed to `reclaimRecipient`. Must be strictly greater than\n * `claimDeadline`.\n */\n readonly reclaimRelease: bigint\n /** The assets this side escrows. Must be non-empty and each asset valid. */\n readonly assets: readonly Asset[]\n}\n\n/** A 32-byte hex value (`0x` + 64 hex chars), e.g. a secret, lock, or digest. */\nexport type Hex32 = Hex\n\n/**\n * A freshly generated hashlock pair.\n *\n * Secrecy lifecycle:\n * - `lock` may be shared freely — it is published on-chain at commit time.\n * - `secret` MUST remain private until the holder claims; the `Claim` event\n * reveals it publicly.\n * - Revealing the secret early lets anyone in the proposer-claim window\n * claim, compromising a cross-chain flow.\n * - Losing the secret makes claiming impossible; the assets can then only\n * be recovered via reclaim after `reclaimRelease`.\n */\nexport interface SecretLockPair {\n /** The 32-byte preimage. Keep private until claim. */\n readonly secret: Hex32\n /** `keccak256(secret)` — safe to share. */\n readonly lock: Hex32\n}\n","/**\n * SDK error type and contract custom-error decoding.\n *\n * Every error the SDK raises is a {@link QuipSwapError} carrying a stable\n * machine-readable `code`. Errors that originate from a reverted contract\n * call additionally carry the decoded Solidity custom-error name in\n * `contractErrorName`, and the original Viem error is always preserved in\n * `cause` — never discarded.\n */\nimport {BaseError, ContractFunctionRevertedError} from 'viem'\n\n/**\n * Stable machine-readable SDK error codes.\n *\n * Codes prefixed with contract semantics (e.g. `CONTRACT_REVERT`) wrap an\n * on-chain revert; the rest are produced by SDK-side preflight validation\n * BEFORE any transaction is sent. SDK validation mirrors but never replaces\n * contract enforcement.\n */\nexport type QuipSwapErrorCode =\n // asset / terms structural validation (mirrors TermsLib.validateAsset / validateTerms)\n | 'ZERO_AMOUNT'\n | 'INVALID_NATIVE_ASSET'\n | 'INVALID_ERC20_ASSET'\n | 'INVALID_ERC721_ASSET'\n | 'INVALID_ERC1155_ASSET'\n | 'INVALID_ASSET_TYPE'\n | 'EMPTY_ASSETS'\n | 'ZERO_ADDRESS_RECIPIENT'\n | 'ZERO_DEADLINE'\n | 'DISORDERED_DEADLINES'\n | 'ZERO_CHAIN_ID'\n // pairing / window validation (mirrors TermsLib.validateTermPairing / enforceWithin)\n | 'INVALID_RANGE'\n | 'WINDOW_VIOLATED'\n // secrets and hex inputs\n | 'INVALID_HEX32'\n // client preflight\n | 'CHAIN_ID_MISMATCH'\n | 'NOT_QUIP_WALLET'\n | 'MISSING_WALLET_CLIENT'\n | 'MISSING_ACCOUNT'\n | 'TERMS_NOT_ON_CHAIN'\n // lock-state preflight (preflight equivalents of the contract's\n // InvalidLockState / InvalidLockAdvancement / TermsAlreadyPosted)\n | 'INVALID_LOCK_STATE'\n | 'TERMS_ALREADY_POSTED'\n // transaction preparation (gas estimation + balance preflight)\n | 'GAS_ESTIMATION_FAILED'\n | 'BALANCE_TOO_LOW'\n // cross-chain schedule validation\n | 'SECRET_HOLDER_NOT_PROPOSER'\n | 'INSUFFICIENT_BUFFER'\n // deployments\n | 'UNKNOWN_DEPLOYMENT'\n // receipts / events\n | 'TRANSACTION_REVERTED'\n | 'EVENT_NOT_FOUND'\n // wrapped on-chain revert (see contractErrorName for the Solidity error)\n | 'CONTRACT_REVERT'\n\n/**\n * Structured details carried by every {@link QuipSwapError}.\n */\nexport interface QuipSwapErrorDetails {\n /** Stable machine-readable code; safe to branch on. */\n readonly code: QuipSwapErrorCode\n /** Human-readable explanation with remediation guidance. */\n readonly message: string\n /**\n * The decoded Solidity custom-error name (e.g. `CallerNotQuipWallet`,\n * `WindowViolated`) when the error wraps an on-chain revert and the error\n * was decodable from the Omnibus ABI.\n */\n readonly contractErrorName?: string\n /** The original underlying error (e.g. the Viem error), never discarded. */\n readonly cause?: unknown\n /** Additional structured context (offending values, window bounds, ...). */\n readonly details?: unknown\n}\n\n/**\n * The error class thrown by every SDK function.\n *\n * @example\n * ```ts\n * try {\n * await client.commit({lock, party, counterparty})\n * } catch (err) {\n * if (err instanceof QuipSwapError && err.code === 'CONTRACT_REVERT') {\n * // a contract revert; err.contractErrorName names the Solidity error\n * // (e.g. 'IncorrectNativeAmountReceived', 'CallerNotQuipWallet')\n * }\n * }\n * ```\n */\nexport class QuipSwapError extends Error implements QuipSwapErrorDetails {\n override readonly name = 'QuipSwapError'\n readonly code: QuipSwapErrorCode\n readonly contractErrorName?: string\n override readonly cause?: unknown\n readonly details?: unknown\n\n constructor(args: QuipSwapErrorDetails) {\n super(args.message)\n this.code = args.code\n if (args.contractErrorName !== undefined) this.contractErrorName = args.contractErrorName\n if (args.cause !== undefined) this.cause = args.cause\n if (args.details !== undefined) this.details = args.details\n }\n}\n\n/**\n * Extracts the decoded Solidity custom-error name from a Viem error, if any.\n *\n * Viem decodes custom errors against the contract ABI during\n * `simulateContract` / `readContract`; this helper walks the error chain\n * (structured decoding — no parsing of human-readable strings) and returns\n * e.g. `\"CallerNotQuipWallet\"` or `\"WindowViolated\"`.\n *\n * @param error - Any error thrown by a Viem contract action.\n * @returns The custom error name, or `undefined` when the revert could not\n * be decoded (e.g. an out-of-ABI token error with no registered ABI).\n */\nexport function extractContractErrorName(error: unknown): string | undefined {\n if (error instanceof BaseError) {\n const revert = error.walk(e => e instanceof ContractFunctionRevertedError)\n if (revert instanceof ContractFunctionRevertedError) {\n return revert.data?.errorName ?? revert.signature\n }\n }\n return undefined\n}\n\n/**\n * Wraps an error thrown by a Viem contract action into a\n * {@link QuipSwapError} with code `CONTRACT_REVERT`, preserving the original\n * error in `cause` and the decoded custom-error name (when available) in\n * `contractErrorName`.\n *\n * @param error - The original error thrown by Viem.\n * @param context - Short description of the operation that failed.\n * @returns A `QuipSwapError` wrapping the original error.\n */\nexport function wrapContractError(error: unknown, context: string): QuipSwapError {\n const contractErrorName = extractContractErrorName(error)\n const suffix = contractErrorName !== undefined ? ` (contract error: ${contractErrorName})` : ''\n return new QuipSwapError({\n code: 'CONTRACT_REVERT',\n message: `${context} reverted${suffix}`,\n ...(contractErrorName !== undefined ? {contractErrorName} : {}),\n cause: error,\n })\n}\n","/**\n * Asset builders and structural validation.\n *\n * The validation rules transcribe `TermsLib.validateAsset` exactly; the one\n * deliberate divergence (ERC-721 amount canonicalization) is marked with\n * `SDK-STRICTER-THAN-CONTRACT` below.\n */\nimport {isAddress, zeroAddress} from 'viem'\nimport type {Address} from 'viem'\nimport {QuipSwapError} from './errors.js'\nimport {AssetType} from './types.js'\nimport type {Asset, Terms} from './types.js'\n\n/**\n * Builds a native-currency asset (ETH or the chain's equivalent).\n *\n * Canonical fields enforced — mirrors the contract's native-asset rule:\n * `target` must be the zero address and `id` must be `0`, otherwise the\n * contract reverts with `InvalidNativeAsset`.\n *\n * @param amount - Amount of native currency in wei; must be `> 0n`.\n * @returns A canonical, frozen `Asset` with `assetType: Native`.\n * @throws QuipSwapError `ZERO_AMOUNT` if `amount` is zero or negative.\n * @see TermsLib.validateAsset\n * @example\n * ```ts\n * const oneEth = nativeAsset(10n ** 18n)\n * ```\n */\nexport function nativeAsset(amount: bigint): Asset {\n if (amount <= 0n) {\n throw new QuipSwapError({\n code: 'ZERO_AMOUNT',\n message: 'Native asset amount must be greater than zero (contract: ZeroAmount)',\n details: {amount},\n })\n }\n return Object.freeze({assetType: AssetType.Native, target: zeroAddress, id: 0n, amount})\n}\n\n/**\n * Builds an ERC-20 asset.\n *\n * The id is fixed at `0n`: the contract REJECTS a non-zero id for ERC-20\n * with `InvalidERC20Asset` (the id field is meaningless for fungible\n * tokens but is still hashed into the terms digest).\n *\n * @param target - The ERC-20 token contract address; must be non-zero.\n * @param amount - Token amount in the token's base units; must be `> 0n`.\n * @returns A canonical, frozen `Asset` with `assetType: ERC20` and `id: 0n`.\n * @throws QuipSwapError `INVALID_ERC20_ASSET` if `target` is the zero address\n * or not a valid address; `ZERO_AMOUNT` if `amount <= 0n`.\n * @see TermsLib.validateAsset\n * @example\n * ```ts\n * const usdc = erc20Asset('0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', 1_000_000n)\n * ```\n */\nexport function erc20Asset(target: Address, amount: bigint): Asset {\n assertTokenTarget(target, 'INVALID_ERC20_ASSET', 'ERC-20')\n if (amount <= 0n) {\n throw new QuipSwapError({\n code: 'ZERO_AMOUNT',\n message: 'ERC-20 asset amount must be greater than zero (contract: ZeroAmount)',\n details: {target, amount},\n })\n }\n return Object.freeze({assetType: AssetType.ERC20, target, id: 0n, amount})\n}\n\n/**\n * Builds an ERC-721 asset for one specific NFT.\n *\n * Token id `0n` is explicitly VALID — do not pre-filter it out; the\n * contract permits id 0 for ERC-721 (see the comment in\n * `TermsLib.validateAsset`).\n *\n * SDK-STRICTER-THAN-CONTRACT: the amount is canonicalized to `1n`. The\n * contract only enforces `amount != 0`, but the amount is hashed into the\n * terms digest while the transfer always moves exactly the one NFT\n * identified by `tokenId` — so two different amounts would yield two\n * different digests describing the same effective transfer. Canonicalizing\n * to `1n` (matching the repository's `AssetHelper.makeERC721`) prevents\n * that ambiguity. Validation of externally supplied assets\n * ({@link validateAsset}) follows the contract and accepts any non-zero\n * amount.\n *\n * @param target - The ERC-721 token contract address; must be non-zero.\n * @param tokenId - The NFT's token id; `0n` is valid.\n * @returns A canonical, frozen `Asset` with `assetType: ERC721` and `amount: 1n`.\n * @throws QuipSwapError `INVALID_ERC721_ASSET` if `target` is the zero\n * address or not a valid address.\n * @see TermsLib.validateAsset\n * @example\n * ```ts\n * const punk = erc721Asset('0xb47e3cd837dDF8e4c57F05d70Ab865de6e193BBB', 42n)\n * // punk.amount === 1n always\n * ```\n */\nexport function erc721Asset(target: Address, tokenId: bigint): Asset {\n assertTokenTarget(target, 'INVALID_ERC721_ASSET', 'ERC-721')\n if (tokenId < 0n) {\n throw new QuipSwapError({\n code: 'INVALID_ERC721_ASSET',\n message: 'ERC-721 token id must be non-negative',\n details: {target, tokenId},\n })\n }\n return Object.freeze({assetType: AssetType.ERC721, target, id: tokenId, amount: 1n})\n}\n\n/**\n * Builds an ERC-1155 asset (a quantity of one token id).\n *\n * Token id `0n` is explicitly VALID, mirroring the contract.\n *\n * @param target - The ERC-1155 token contract address; must be non-zero.\n * @param tokenId - The token id; `0n` is valid.\n * @param amount - Quantity of the token id; must be `> 0n`.\n * @returns A canonical, frozen `Asset` with `assetType: ERC1155`.\n * @throws QuipSwapError `INVALID_ERC1155_ASSET` if `target` is invalid;\n * `ZERO_AMOUNT` if `amount <= 0n`.\n * @see TermsLib.validateAsset\n * @example\n * ```ts\n * const gameItems = erc1155Asset('0x495f947276749Ce646f68AC8c248420045cb7b5e', 7n, 25n)\n * ```\n */\nexport function erc1155Asset(target: Address, tokenId: bigint, amount: bigint): Asset {\n assertTokenTarget(target, 'INVALID_ERC1155_ASSET', 'ERC-1155')\n if (tokenId < 0n) {\n throw new QuipSwapError({\n code: 'INVALID_ERC1155_ASSET',\n message: 'ERC-1155 token id must be non-negative',\n details: {target, tokenId},\n })\n }\n if (amount <= 0n) {\n throw new QuipSwapError({\n code: 'ZERO_AMOUNT',\n message: 'ERC-1155 asset amount must be greater than zero (contract: ZeroAmount)',\n details: {target, tokenId, amount},\n })\n }\n return Object.freeze({assetType: AssetType.ERC1155, target, id: tokenId, amount})\n}\n\n/**\n * Validates an asset object received from an untrusted source (JSON, an\n * API, a database, another application).\n *\n * This is a faithful transcription of `TermsLib.validateAsset`:\n *\n * ```solidity\n * if (asset.amount == 0) revert ZeroAmount();\n * if (isNative && (!isZeroTarget || !isZeroId)) revert InvalidNativeAsset();\n * if (isERC20 && (isZeroTarget || !isZeroId)) revert InvalidERC20Asset();\n * // ERC721/ERC1155 token id 0 is valid; only a zero target is rejected\n * if (isERC721 && isZeroTarget) revert InvalidERC721Asset();\n * if (isERC1155 && isZeroTarget) revert InvalidERC1155Asset();\n * ```\n *\n * Unlike {@link erc721Asset}, this accepts any non-zero ERC-721 amount,\n * matching the contract exactly (validation must not be stricter than the\n * contract for objects that may already exist in committed terms).\n *\n * @param asset - The asset to validate.\n * @throws QuipSwapError `ZERO_AMOUNT` | `INVALID_NATIVE_ASSET` |\n * `INVALID_ERC20_ASSET` | `INVALID_ERC721_ASSET` | `INVALID_ERC1155_ASSET`\n * | `INVALID_ASSET_TYPE`, each naming the matching contract error.\n * @see TermsLib.validateAsset\n * @example\n * ```ts\n * validateAsset(JSON.parse(payload, bigintReviver)) // throws on bad input\n * ```\n */\nexport function validateAsset(asset: Asset): void {\n if (\n asset.assetType !== AssetType.Native &&\n asset.assetType !== AssetType.ERC20 &&\n asset.assetType !== AssetType.ERC721 &&\n asset.assetType !== AssetType.ERC1155\n ) {\n // the contract cannot receive an out-of-range enum (ABI decoding reverts);\n // the SDK surfaces the same condition as a structured error\n throw new QuipSwapError({\n code: 'INVALID_ASSET_TYPE',\n message: `Unknown asset type ${String(asset.assetType)}; expected 0 (Native), 1 (ERC20), 2 (ERC721), or 3 (ERC1155)`,\n details: {asset},\n })\n }\n if (asset.amount <= 0n) {\n throw new QuipSwapError({\n code: 'ZERO_AMOUNT',\n message: 'Asset amount must be greater than zero for every asset type (contract: ZeroAmount)',\n details: {asset},\n })\n }\n if (!isAddress(asset.target, {strict: false})) {\n throw new QuipSwapError({\n code: assetTypeErrorCode(asset.assetType),\n message: `Asset target ${String(asset.target)} is not a valid address`,\n details: {asset},\n })\n }\n\n const isZeroTarget = asset.target.toLowerCase() === zeroAddress\n const isZeroId = asset.id === 0n\n\n if (asset.assetType === AssetType.Native && (!isZeroTarget || !isZeroId)) {\n throw new QuipSwapError({\n code: 'INVALID_NATIVE_ASSET',\n message: 'Native asset must have zero target and zero id (contract: InvalidNativeAsset)',\n details: {asset},\n })\n }\n if (asset.assetType === AssetType.ERC20 && (isZeroTarget || !isZeroId)) {\n throw new QuipSwapError({\n code: 'INVALID_ERC20_ASSET',\n message: 'ERC-20 asset must have a non-zero target and id 0 (contract: InvalidERC20Asset)',\n details: {asset},\n })\n }\n // ERC721/ERC1155: token id 0 is valid; only a zero target is rejected\n if (asset.assetType === AssetType.ERC721 && isZeroTarget) {\n throw new QuipSwapError({\n code: 'INVALID_ERC721_ASSET',\n message: 'ERC-721 asset must have a non-zero target (contract: InvalidERC721Asset)',\n details: {asset},\n })\n }\n if (asset.assetType === AssetType.ERC1155 && isZeroTarget) {\n throw new QuipSwapError({\n code: 'INVALID_ERC1155_ASSET',\n message: 'ERC-1155 asset must have a non-zero target (contract: InvalidERC1155Asset)',\n details: {asset},\n })\n }\n}\n\n/** Maps an asset type to its type-specific validation error code. */\nfunction assetTypeErrorCode(\n assetType: AssetType,\n): 'INVALID_NATIVE_ASSET' | 'INVALID_ERC20_ASSET' | 'INVALID_ERC721_ASSET' | 'INVALID_ERC1155_ASSET' {\n switch (assetType) {\n case AssetType.Native:\n return 'INVALID_NATIVE_ASSET'\n case AssetType.ERC20:\n return 'INVALID_ERC20_ASSET'\n case AssetType.ERC721:\n return 'INVALID_ERC721_ASSET'\n case AssetType.ERC1155:\n return 'INVALID_ERC1155_ASSET'\n }\n}\n\n/** Throws the given code when `target` is missing, malformed, or the zero address. */\nfunction assertTokenTarget(\n target: Address,\n code: 'INVALID_ERC20_ASSET' | 'INVALID_ERC721_ASSET' | 'INVALID_ERC1155_ASSET',\n label: string,\n): void {\n if (!isAddress(target, {strict: false}) || target.toLowerCase() === zeroAddress) {\n throw new QuipSwapError({\n code,\n message: `${label} asset target must be a non-zero contract address`,\n details: {target},\n })\n }\n}\n\n/**\n * Sums the native amounts in a side's terms — the amount of wei the\n * committer must escrow (before the commitment fee).\n *\n * Transcribes `TermsLib.totalNative`: only assets with\n * `assetType === Native` contribute; all other types are ignored.\n *\n * The exact commit transaction value is\n * `totalNative(party) + commitmentFee`, checked by the contract for strict\n * equality (`IncorrectNativeAmountReceived`) — see\n * {@link OmnibusClient.commit}, which re-reads the fee immediately before\n * simulating.\n *\n * @param terms - The side's terms (only `assets` is read).\n * @returns The sum of all native-asset amounts in wei (`0n` when none).\n * @see TermsLib.totalNative\n * @example\n * ```ts\n * totalNative({...terms, assets: [nativeAsset(5n), erc20Asset(token, 100n)]}) // 5n\n * ```\n */\nexport function totalNative(terms: Pick<Terms, 'assets'>): bigint {\n let total = 0n\n for (const asset of terms.assets) {\n if (asset.assetType === AssetType.Native) total += asset.amount\n }\n return total\n}\n","/**\n * Terms construction, structural validation, and pairing validation.\n *\n * Transcribes `TermsLib.validateTerms`, `TermsLib.validateTermPairing`, and\n * `TermsLib.proposedByParty`.\n */\nimport {isAddress, zeroAddress} from 'viem'\nimport type {Address} from 'viem'\nimport {validateAsset} from './assets.js'\nimport {QuipSwapError} from './errors.js'\nimport type {Asset, Terms} from './types.js'\n\n/** Input shape for {@link createTerms}; identical to {@link Terms}. */\nexport interface CreateTermsArgs {\n /** Chain id where this side's assets live; must be `> 0n`. */\n readonly chainId: bigint\n /** Receives this side's own assets on reclaim; non-zero. */\n readonly reclaimRecipient: Address\n /** Receives the COUNTERPARTY's assets on claim; non-zero. */\n readonly recipient: Address\n /** Unix seconds; commitment forbidden at/after this instant; non-zero. */\n readonly commitmentDeadline: bigint\n /** Unix seconds; strictly after `commitmentDeadline`. */\n readonly claimDeadline: bigint\n /** Unix seconds; strictly after `claimDeadline`. */\n readonly reclaimRelease: bigint\n /** Non-empty list of structurally valid assets. */\n readonly assets: readonly Asset[]\n}\n\n/**\n * Builds and validates a {@link Terms} object.\n *\n * The returned object is frozen (including a defensive copy of the asset\n * array) so later mutation of caller-supplied inputs cannot desynchronize a\n * digest already shared with a counterparty.\n *\n * @param args - The seven Terms fields; see {@link CreateTermsArgs} for\n * units and constraints.\n * @returns A frozen, structurally valid `Terms`.\n * @throws QuipSwapError - every code listed on {@link validateTerms}.\n * @see TermsLib.validateTerms\n * @example\n * ```ts\n * const terms = createTerms({\n * chainId: 8453n,\n * reclaimRecipient: wallet,\n * recipient: wallet,\n * commitmentDeadline: now + 600n,\n * claimDeadline: now + 1800n,\n * reclaimRelease: now + 3600n,\n * assets: [nativeAsset(10n ** 18n)],\n * })\n * ```\n */\nexport function createTerms(args: CreateTermsArgs): Terms {\n // defensive copy: never mutate or alias the caller's array\n const terms: Terms = Object.freeze({\n chainId: args.chainId,\n reclaimRecipient: args.reclaimRecipient,\n recipient: args.recipient,\n commitmentDeadline: args.commitmentDeadline,\n claimDeadline: args.claimDeadline,\n reclaimRelease: args.reclaimRelease,\n assets: Object.freeze([...args.assets]),\n })\n validateTerms(terms)\n return terms\n}\n\n/**\n * Structurally validates one side's terms.\n *\n * Exact transcription of `TermsLib.validateTerms`:\n *\n * ```solidity\n * if (terms.assets.length == 0) revert EmptyAssets();\n * if (reclaimRecipient == 0 || recipient == 0) revert ZeroAddressRecipient();\n * if (terms.commitmentDeadline == 0) revert ZeroDeadline();\n * if (!(commitmentDeadline < claimDeadline && claimDeadline < reclaimRelease))\n * revert DisordedDeadlines();\n * enforceNonZeroChainId(terms); validateAssets(terms);\n * ```\n *\n * Deliberately does NOT check that deadlines are in the future: freshness\n * is enforced per-action by the half-open windows\n * (see {@link validateCommitWindow}). The taker legitimately commits AFTER\n * the proposer's commitment deadline has elapsed — `Omnibus.commit`\n * validates BOTH sides' terms, so a freshness check here would wrongly\n * reject the proposer's already-elapsed deadline during the taker's commit.\n *\n * @param terms - The terms to validate (e.g. parsed from JSON or an API).\n * @throws QuipSwapError `EMPTY_ASSETS` | `ZERO_ADDRESS_RECIPIENT` |\n * `ZERO_DEADLINE` | `DISORDERED_DEADLINES` | `ZERO_CHAIN_ID`, plus every\n * asset-level code from {@link validateAsset}.\n * @see TermsLib.validateTerms\n * @example\n * ```ts\n * validateTerms(termsFromCounterparty) // throws before any tx is built\n * ```\n */\nexport function validateTerms(terms: Terms): void {\n if (terms.assets.length === 0) {\n throw new QuipSwapError({\n code: 'EMPTY_ASSETS',\n message: 'Terms must contain at least one asset (contract: EmptyAssets)',\n })\n }\n if (!isRecipientAddress(terms.reclaimRecipient) || !isRecipientAddress(terms.recipient)) {\n throw new QuipSwapError({\n code: 'ZERO_ADDRESS_RECIPIENT',\n message:\n 'Both recipient and reclaimRecipient must be valid non-zero addresses (contract: ZeroAddressRecipient)',\n details: {recipient: terms.recipient, reclaimRecipient: terms.reclaimRecipient},\n })\n }\n if (terms.commitmentDeadline === 0n) {\n throw new QuipSwapError({\n code: 'ZERO_DEADLINE',\n message: 'commitmentDeadline must be non-zero (contract: ZeroDeadline)',\n })\n }\n // lifecycle deadlines must be STRICTLY increasing: commitment < claim < reclaim\n if (!(terms.commitmentDeadline < terms.claimDeadline && terms.claimDeadline < terms.reclaimRelease)) {\n throw new QuipSwapError({\n code: 'DISORDERED_DEADLINES',\n message:\n 'Lifecycle timestamps must satisfy commitmentDeadline < claimDeadline < reclaimRelease, strictly ' +\n '(contract: DisordedDeadlines)',\n details: {\n commitmentDeadline: terms.commitmentDeadline,\n claimDeadline: terms.claimDeadline,\n reclaimRelease: terms.reclaimRelease,\n },\n })\n }\n if (terms.chainId <= 0n) {\n throw new QuipSwapError({\n code: 'ZERO_CHAIN_ID',\n message: 'chainId must be greater than zero (contract: ZeroChainId)',\n details: {chainId: terms.chainId},\n })\n }\n for (const asset of terms.assets) validateAsset(asset)\n}\n\n/** True when the value is a well-formed, non-zero address. */\nfunction isRecipientAddress(value: Address): boolean {\n return isAddress(value, {strict: false}) && value.toLowerCase() !== zeroAddress\n}\n\n/**\n * Validates that two sides' lifecycle timestamps strictly interleave.\n *\n * Exact transcription of `TermsLib.validateTermPairing`. Exactly one of\n * the two chains must hold (every comparison strict — equal timestamps\n * anywhere are rejected):\n *\n * ```text\n * A proposes: A.commitmentDeadline < B.commitmentDeadline < A.claimDeadline\n * < B.claimDeadline < A.reclaimRelease < B.reclaimRelease\n * B proposes: the same chain with A and B swapped\n * ```\n *\n * The proposer is the side with the smaller `commitmentDeadline` and\n * commits first. The interleaving is what bounds each side's risk — in a\n * cross-chain swap it guarantees the taker a reaction buffer after the\n * secret is revealed (see {@link validateCrossChainSchedule}).\n *\n * @param a - One side's terms.\n * @param b - The other side's terms.\n * @throws QuipSwapError `DISORDERED_DEADLINES` when neither interleaving\n * holds (contract: DisordedDeadlines).\n * @see TermsLib.validateTermPairing\n * @example\n * ```ts\n * validateTermPairing(aliceTerms, bobTerms) // throws if the schedule is invalid\n * ```\n */\nexport function validateTermPairing(a: Terms, b: Terms): void {\n const aProposes =\n a.commitmentDeadline < b.commitmentDeadline &&\n b.commitmentDeadline < a.claimDeadline &&\n a.claimDeadline < b.claimDeadline &&\n b.claimDeadline < a.reclaimRelease &&\n a.reclaimRelease < b.reclaimRelease\n\n const bProposes =\n b.commitmentDeadline < a.commitmentDeadline &&\n a.commitmentDeadline < b.claimDeadline &&\n b.claimDeadline < a.claimDeadline &&\n a.claimDeadline < b.reclaimRelease &&\n b.reclaimRelease < a.reclaimRelease\n\n if (!(aProposes || bProposes)) {\n throw new QuipSwapError({\n code: 'DISORDERED_DEADLINES',\n message:\n \"The two sides' lifecycle timestamps must strictly interleave \" +\n '(proposer.commit < taker.commit < proposer.claim < taker.claim < proposer.reclaim < taker.reclaim; ' +\n 'contract: DisordedDeadlines)',\n details: {a: lifecycleOf(a), b: lifecycleOf(b)},\n })\n }\n}\n\n/** Extracts just the three lifecycle timestamps for error reporting. */\nfunction lifecycleOf(terms: Terms): Record<string, bigint> {\n return {\n commitmentDeadline: terms.commitmentDeadline,\n claimDeadline: terms.claimDeadline,\n reclaimRelease: terms.reclaimRelease,\n }\n}\n\n/**\n * Identifies which side of a pairing proposed.\n *\n * Transcribes `TermsLib.proposedByParty`: the proposer is the side with\n * the smaller `commitmentDeadline` (it commits first). Only meaningful\n * after {@link validateTermPairing} has passed, which guarantees the\n * commitment deadlines are strictly ordered and never equal.\n *\n * @param party - The first side's terms.\n * @param counterparty - The second side's terms.\n * @returns `'party'` if `party` proposed, `'counterparty'` otherwise.\n * @see TermsLib.proposedByParty\n * @example\n * ```ts\n * if (proposedBy(mine, theirs) === 'party') {\n * // I commit first, in [0, mine.commitmentDeadline)\n * }\n * ```\n */\nexport function proposedBy(party: Terms, counterparty: Terms): 'party' | 'counterparty' {\n return party.commitmentDeadline < counterparty.commitmentDeadline ? 'party' : 'counterparty'\n}\n","/**\n * Half-open timing-window math.\n *\n * The protocol partitions the swap timeline into HALF-OPEN windows\n * `[lower, upper)` and the contract enforces, per action, that\n * `block.timestamp` falls in the right one (`TermsLib.enforceWithin`).\n * The exclusive upper bound is deliberate: adjacent windows share a\n * boundary (one window's upper is the next window's lower), and exclusivity\n * guarantees exactly one window accepts the shared instant. Never treat the\n * upper bound as inclusive.\n *\n * All helpers are pure and take an explicit timestamp — they never read the\n * local wall clock, because the contract judges windows against\n * `block.timestamp`, not the client's clock. Off-chain window validation is\n * a preflight convenience; it never replaces on-chain enforcement.\n */\nimport {QuipSwapError} from './errors.js'\nimport {proposedBy} from './terms.js'\nimport type {Terms} from './types.js'\n\n/** `type(uint256).max` — the open upper bound of the reclaim window. */\nexport const MAX_UINT256 = (1n << 256n) - 1n\n\n/**\n * A half-open time window `[lower, upper)` in Unix seconds.\n */\nexport interface TimeWindow {\n /** Inclusive lower bound (Unix seconds). */\n readonly lower: bigint\n /** EXCLUSIVE upper bound (Unix seconds); `MAX_UINT256` means unbounded. */\n readonly upper: bigint\n}\n\n/**\n * Asserts `timestamp` lies within the half-open window `[lower, upper)`.\n *\n * Exact transcription of `TermsLib.enforceWithin`:\n *\n * ```solidity\n * if (lower >= upper) revert InvalidRange();\n * if (lower > timestamp || upper <= timestamp) revert WindowViolated();\n * ```\n *\n * The upper bound is EXCLUSIVE: `timestamp === upper` is rejected.\n *\n * @param lower - Inclusive lower bound (Unix seconds).\n * @param upper - Exclusive upper bound (Unix seconds).\n * @param timestamp - The instant to test (pass the chain's `block.timestamp`).\n * @throws QuipSwapError `INVALID_RANGE` when `lower >= upper` (degenerate\n * window — contract: InvalidRange); `WINDOW_VIOLATED` when the timestamp\n * is before `lower` or at/after `upper` (contract: WindowViolated).\n * @see TermsLib.enforceWithin\n * @example\n * ```ts\n * enforceWithin(0n, 1000n, 999n) // ok\n * enforceWithin(0n, 1000n, 1000n) // throws WINDOW_VIOLATED (upper exclusive)\n * ```\n */\nexport function enforceWithin(lower: bigint, upper: bigint, timestamp: bigint): void {\n if (lower >= upper) {\n throw new QuipSwapError({\n code: 'INVALID_RANGE',\n message: `Degenerate window: lower (${lower}) must be strictly less than upper (${upper}) (contract: InvalidRange)`,\n details: {lower, upper, timestamp},\n })\n }\n if (lower > timestamp || upper <= timestamp) {\n throw new QuipSwapError({\n code: 'WINDOW_VIOLATED',\n message:\n `Timestamp ${timestamp} is outside the half-open window [${lower}, ${upper}) ` +\n '(contract: WindowViolated; the upper bound is exclusive)',\n details: {lower, upper, timestamp},\n })\n }\n}\n\n/**\n * Non-throwing variant of {@link enforceWithin}.\n *\n * @param window - The half-open window to test.\n * @param timestamp - The instant to test (Unix seconds).\n * @returns `true` iff `window.lower <= timestamp < window.upper` and the\n * window is non-degenerate.\n */\nexport function isWithinWindow(window: TimeWindow, timestamp: bigint): boolean {\n return window.lower < window.upper && window.lower <= timestamp && timestamp < window.upper\n}\n\n/**\n * The proposer's commit window: `[0, proposer.commitmentDeadline)`.\n *\n * Enforced by `Omnibus.commit` via\n * `enforceWithin(0, party.commitmentDeadline, block.timestamp)` on the\n * proposer path.\n *\n * @param proposer - The proposer's terms (the side with the earlier `commitmentDeadline`).\n * @returns The half-open commit window for the proposer.\n * @see Omnibus.commit\n */\nexport function proposerCommitWindow(proposer: Terms): TimeWindow {\n return {lower: 0n, upper: proposer.commitmentDeadline}\n}\n\n/**\n * The taker's commit window:\n * `[proposer.commitmentDeadline, taker.commitmentDeadline)`.\n *\n * The taker can only commit AFTER the proposer's commitment deadline has\n * elapsed — enforced by `Omnibus.commit` via\n * `enforceWithin(counterparty.commitmentDeadline, party.commitmentDeadline, block.timestamp)`.\n * A taker commit attempted while the proposer's window is still open\n * reverts with `WindowViolated`.\n *\n * @param taker - The taker's terms.\n * @param proposer - The proposer's terms.\n * @returns The half-open commit window for the taker.\n * @see Omnibus.commit\n */\nexport function takerCommitWindow(taker: Terms, proposer: Terms): TimeWindow {\n return {lower: proposer.commitmentDeadline, upper: taker.commitmentDeadline}\n}\n\n/**\n * The proposer's claim window:\n * `[taker.commitmentDeadline, proposer.claimDeadline)`.\n *\n * Enforced by `Omnibus.claim` when the claimant role is the proposer:\n * `enforceWithin(counterparty.commitmentDeadline, party.claimDeadline, block.timestamp)`.\n *\n * @param proposer - The proposer's terms.\n * @param taker - The taker's terms.\n * @returns The half-open claim window for the proposer (secret holder).\n * @see Omnibus.claim\n */\nexport function proposerClaimWindow(proposer: Terms, taker: Terms): TimeWindow {\n return {lower: taker.commitmentDeadline, upper: proposer.claimDeadline}\n}\n\n/**\n * The taker's claim window:\n * `[proposer.claimDeadline, proposer.reclaimRelease)`.\n *\n * Enforced by `Omnibus.claim` when the claimant role is the taker:\n * `enforceWithin(counterparty.claimDeadline, counterparty.reclaimRelease, block.timestamp)`\n * (the counterparty is the proposer on this path). The width of this\n * window, `proposer.reclaimRelease - proposer.claimDeadline`, is the\n * taker's post-reveal reaction buffer in a cross-chain swap.\n *\n * @param proposer - The proposer's terms (the claim is gated on the PROPOSER's schedule).\n * @returns The half-open claim window for the taker.\n * @see Omnibus.claim\n */\nexport function takerClaimWindow(proposer: Terms): TimeWindow {\n return {lower: proposer.claimDeadline, upper: proposer.reclaimRelease}\n}\n\n/**\n * The reclaim window for one leg: `[leg.reclaimRelease, +infinity)`.\n *\n * Enforced by `Omnibus.reclaim` via\n * `enforceWithin(party.reclaimRelease, type(uint256).max, block.timestamp)`.\n * Reclaim never closes once open.\n *\n * @param leg - The terms of the leg being reclaimed.\n * @returns The half-open reclaim window (upper bound `MAX_UINT256`).\n * @see Omnibus.reclaim\n */\nexport function reclaimWindow(leg: Terms): TimeWindow {\n return {lower: leg.reclaimRelease, upper: MAX_UINT256}\n}\n\n/**\n * Validates that `currentTimestamp` lies inside the commit window for the\n * role `party` plays in the pairing — exactly the check `Omnibus.commit`\n * performs:\n *\n * - `party` is the proposer: `[0, party.commitmentDeadline)`\n * - `party` is the taker: `[counterparty.commitmentDeadline, party.commitmentDeadline)`\n *\n * @param party - The committing side's terms.\n * @param counterparty - The other side's terms.\n * @param currentTimestamp - The chain's current `block.timestamp` (Unix\n * seconds) — pass an explicit value; this helper never reads a clock.\n * @throws QuipSwapError `WINDOW_VIOLATED` | `INVALID_RANGE` as in\n * {@link enforceWithin}.\n * @see Omnibus.commit\n * @example\n * ```ts\n * const block = await publicClient.getBlock()\n * validateCommitWindow(myTerms, theirTerms, block.timestamp)\n * ```\n */\nexport function validateCommitWindow(party: Terms, counterparty: Terms, currentTimestamp: bigint): void {\n if (proposedBy(party, counterparty) === 'party') {\n enforceWithin(0n, party.commitmentDeadline, currentTimestamp)\n } else {\n // taker path: the proposer's (counterparty's) deadline must have elapsed\n enforceWithin(counterparty.commitmentDeadline, party.commitmentDeadline, currentTimestamp)\n }\n}\n\n/**\n * Validates that `currentTimestamp` lies inside the claim window for the\n * role `party` plays — exactly the check `Omnibus.claim` performs:\n *\n * - `party` is the proposer: `[counterparty.commitmentDeadline, party.claimDeadline)`\n * - `party` is the taker: `[counterparty.claimDeadline, counterparty.reclaimRelease)`\n *\n * @param party - The claimant role's terms (the side the claimant acts for).\n * @param counterparty - The other side's terms (the leg being claimed).\n * @param currentTimestamp - The chain's current `block.timestamp` (Unix seconds).\n * @throws QuipSwapError `WINDOW_VIOLATED` | `INVALID_RANGE` as in\n * {@link enforceWithin}.\n * @see Omnibus.claim\n */\nexport function validateClaimWindow(party: Terms, counterparty: Terms, currentTimestamp: bigint): void {\n if (proposedBy(party, counterparty) === 'party') {\n enforceWithin(counterparty.commitmentDeadline, party.claimDeadline, currentTimestamp)\n } else {\n enforceWithin(counterparty.claimDeadline, counterparty.reclaimRelease, currentTimestamp)\n }\n}\n\n/**\n * Validates that `currentTimestamp` has reached the reclaim window of the\n * leg being reclaimed — exactly the check `Omnibus.reclaim` performs:\n * `[party.reclaimRelease, type(uint256).max)`.\n *\n * @param party - The terms of the leg being reclaimed.\n * @param currentTimestamp - The chain's current `block.timestamp` (Unix seconds).\n * @throws QuipSwapError `WINDOW_VIOLATED` when the release has not elapsed.\n * @see Omnibus.reclaim\n */\nexport function validateReclaimWindow(party: Terms, currentTimestamp: bigint): void {\n enforceWithin(party.reclaimRelease, MAX_UINT256, currentTimestamp)\n}\n","/**\n * Solidity-exact hashing and ABI encoding.\n *\n * These functions are byte-for-byte transcriptions of\n * `TermsLib.digestTerms`, `TermsLib.digestTermsCanonically`, and\n * `Omnibus._generateLock`. ANY deviation here breaks hash agreement with\n * the contract — and across chains, since both legs of a cross-chain swap\n * derive the same canonical digest independently. Correctness is proven by\n * differential tests against the Solidity harnesses (the harness is the\n * oracle), not assumed.\n */\nimport {concat, encodeAbiParameters, isHex, keccak256} from 'viem'\nimport {QuipSwapError} from './errors.js'\nimport type {Hex32, Terms} from './types.js'\n\n/**\n * The ABI parameter description of the `Asset[]` array — the SINGLE source\n * of truth for the Asset tuple shape in the SDK. `assetType` is a Solidity\n * enum, encoded as `uint8` in the ABI.\n *\n * @see TermsLib (struct Asset)\n */\nexport const assetArrayAbiParameter = {\n name: 'assets',\n type: 'tuple[]',\n components: [\n {name: 'assetType', type: 'uint8'},\n {name: 'target', type: 'address'},\n {name: 'id', type: 'uint256'},\n {name: 'amount', type: 'uint256'},\n ],\n} as const\n\n/**\n * The ABI parameter description of the full `Terms` tuple — the SINGLE\n * source of truth for the Terms shape. Used to decode the `Commitment`\n * event's `party` field back into a typed {@link Terms}.\n *\n * Note: {@link digestTerms} does NOT use this tuple — the contract hashes\n * `abi.encode(field1, ..., field7)` (seven separate top-level values), not\n * `abi.encode(struct)`; for a single dynamic struct argument those two\n * encodings differ by a leading offset word.\n *\n * @see TermsLib (struct Terms), IOmnibus.Commitment\n */\nexport const termsAbiParameter = {\n name: 'terms',\n type: 'tuple',\n components: [\n {name: 'chainId', type: 'uint256'},\n {name: 'reclaimRecipient', type: 'address'},\n {name: 'recipient', type: 'address'},\n {name: 'commitmentDeadline', type: 'uint256'},\n {name: 'claimDeadline', type: 'uint256'},\n {name: 'reclaimRelease', type: 'uint256'},\n assetArrayAbiParameter,\n ],\n} as const\n\n/**\n * The seven top-level ABI parameters hashed by `TermsLib.digestTerms`, in\n * the exact order the contract encodes them.\n */\nconst termsDigestAbiParameters = [\n {name: 'chainId', type: 'uint256'},\n {name: 'reclaimRecipient', type: 'address'},\n {name: 'recipient', type: 'address'},\n {name: 'commitmentDeadline', type: 'uint256'},\n {name: 'claimDeadline', type: 'uint256'},\n {name: 'reclaimRelease', type: 'uint256'},\n assetArrayAbiParameter,\n] as const\n\n/**\n * Computes the digest of a single side's terms.\n *\n * Exact transcription of `TermsLib.digestTerms`:\n *\n * ```solidity\n * digest = EfficientHashLib.hash( // keccak256(bytes)\n * abi.encode(\n * terms.chainId, terms.reclaimRecipient, terms.recipient,\n * terms.commitmentDeadline, terms.claimDeadline, terms.reclaimRelease,\n * terms.assets\n * )\n * );\n * ```\n *\n * Standard (head/tail) ABI encoding of SEVEN top-level values — not packed\n * encoding, and not the encoding of a single `Terms` struct. The asset\n * order matters: reordering assets changes the digest.\n *\n * @param terms - The side's terms.\n * @returns The 32-byte digest used for `posted` tracking and canonical ordering.\n * @see TermsLib.digestTerms\n * @example\n * ```ts\n * const digest = digestTerms(aliceTerms)\n * const isPosted = await client.posted(lock, digest)\n * ```\n */\nexport function digestTerms(terms: Terms): Hex32 {\n return keccak256(\n encodeAbiParameters(termsDigestAbiParameters, [\n terms.chainId,\n terms.reclaimRecipient,\n terms.recipient,\n terms.commitmentDeadline,\n terms.claimDeadline,\n terms.reclaimRelease,\n // readonly Asset[] is structurally compatible with the tuple components\n terms.assets.map(a => ({assetType: a.assetType, target: a.target, id: a.id, amount: a.amount})),\n ]),\n )\n}\n\n/**\n * Computes the canonical digest of a terms pair, identical regardless of\n * which side is passed first.\n *\n * Exact transcription of `TermsLib.digestTermsCanonically`:\n * 1. Digest each side independently with {@link digestTerms}.\n * 2. Compare the two digests as unsigned 256-bit integers — NOT as strings\n * (string comparison is locale/casing-sensitive and does not match\n * Solidity's `uint256(a) < uint256(b)`).\n * 3. Concatenate the raw 32-byte values, smaller digest first.\n * 4. keccak256 the 64-byte concatenation (matching\n * `EfficientHashLib.hash(bytes32, bytes32)`).\n *\n * This is the value stored in `Omnibus.termsHash[lock]`; both chains of a\n * cross-chain swap must derive it identically.\n *\n * @param party - One side's terms (order does not matter).\n * @param counterparty - The other side's terms.\n * @returns The canonical 32-byte digest of the pair.\n * @see TermsLib.digestTermsCanonically\n * @example\n * ```ts\n * digestTermsCanonically(a, b) === digestTermsCanonically(b, a) // always true\n * ```\n */\nexport function digestTermsCanonically(party: Terms, counterparty: Terms): Hex32 {\n const partyDigest = digestTerms(party)\n const counterpartyDigest = digestTerms(counterparty)\n // canonical ordering: numerically smaller digest first (unsigned-bigint compare)\n return BigInt(partyDigest) < BigInt(counterpartyDigest)\n ? keccak256(concat([partyDigest, counterpartyDigest]))\n : keccak256(concat([counterpartyDigest, partyDigest]))\n}\n\n/**\n * Derives the hashlock from a secret.\n *\n * Exact transcription of `Omnibus._generateLock`: keccak256 over the raw\n * 32-byte secret (matching `EfficientHashLib.hash(bytes32)` — no length\n * prefix, no ABI encoding).\n *\n * @param secret - A 32-byte hex preimage (`0x` + 64 hex chars). Validated\n * before hashing — externally supplied secrets of the wrong length would\n * otherwise silently produce a lock that can never be claimed.\n * @returns The 32-byte lock, `keccak256(secret)`.\n * @throws QuipSwapError `INVALID_HEX32` if `secret` is not exactly 32 bytes\n * of valid hex.\n * @see Omnibus._generateLock\n * @example\n * ```ts\n * const lock = generateLock('0x' + '11'.repeat(32) as Hex32)\n * ```\n */\nexport function generateLock(secret: Hex32): Hex32 {\n assertHex32(secret, 'secret')\n return keccak256(secret)\n}\n\n/**\n * Asserts a value is exactly 32 bytes of valid hex (`0x` + 64 hex chars).\n *\n * @param value - The value to check.\n * @param label - Name used in the error message (e.g. `\"secret\"`, `\"lock\"`).\n * @throws QuipSwapError `INVALID_HEX32` when malformed or the wrong length.\n */\nexport function assertHex32(value: string, label: string): asserts value is Hex32 {\n if (!isHex(value, {strict: true}) || value.length !== 66) {\n // do not echo the value itself: it may be a secret and must never be logged\n throw new QuipSwapError({\n code: 'INVALID_HEX32',\n message: `${label} must be a 0x-prefixed 32-byte hex string (66 chars total); received ${\n typeof value === 'string' ? `${value.length} chars` : typeof value\n }`,\n })\n }\n}\n","/**\n * Cryptographically secure secret generation for hashlocks.\n *\n * Secrecy lifecycle (applies to every secret produced or accepted here):\n * - The LOCK may be shared freely; it is published on-chain at commit.\n * - The SECRET must remain private until the holder claims — the on-chain\n * `Claim` event then reveals it publicly.\n * - Revealing the secret early compromises a cross-chain flow: anyone can\n * claim once they hold the secret inside an open claim window.\n * - Losing the secret makes claiming impossible; escrowed assets are then\n * only recoverable via reclaim after `reclaimRelease`.\n *\n * The SDK never logs or prints secrets, and error messages never echo\n * secret values.\n */\nimport {bytesToHex} from 'viem'\nimport {assertHex32, generateLock} from './hashing.js'\nimport type {Hex32, SecretLockPair} from './types.js'\n\n/**\n * Generates a fresh 32-byte secret and its lock.\n *\n * Uses `crypto.getRandomValues` (the runtime's CSPRNG — available in\n * browsers, Node.js >= 19, and Bun). Never uses `Math.random()`,\n * timestamps, counters, or any other predictable source: a guessable\n * secret lets an attacker claim the counterparty's escrowed assets.\n *\n * @returns A {@link SecretLockPair} where `lock === generateLock(secret)`.\n * Keep `secret` private until claim; `lock` is safe to share.\n * @see Omnibus._generateLock\n * @example\n * ```ts\n * const {secret, lock} = generateSecret()\n * // share `lock` with the counterparty; keep `secret` private\n * ```\n */\nexport function generateSecret(): SecretLockPair {\n const bytes = new Uint8Array(32)\n // SECURITY: CSPRNG only. globalThis.crypto exists in all supported runtimes.\n globalThis.crypto.getRandomValues(bytes)\n const secret = bytesToHex(bytes) as Hex32\n return Object.freeze({secret, lock: generateLock(secret)})\n}\n\n/**\n * Validates an externally supplied secret and derives its lock.\n *\n * Use this instead of {@link generateLock} when the secret comes from\n * storage or another process and you want the validated pair back.\n *\n * @param secret - A 0x-prefixed 32-byte hex string.\n * @returns The validated {@link SecretLockPair}.\n * @throws QuipSwapError `INVALID_HEX32` if the secret is malformed or not\n * exactly 32 bytes (the error never echoes the supplied value).\n * @example\n * ```ts\n * const pair = secretToPair(loadSecretFromVault())\n * ```\n */\nexport function secretToPair(secret: string): SecretLockPair {\n assertHex32(secret, 'secret')\n return Object.freeze({secret, lock: generateLock(secret)})\n}\n","/**\n * Typed deployment registry for verified Omnibus deployments.\n *\n * Omnibus is deployed via CREATE3 through the canonical Deployer contract\n * (`script/DeployOmnibus.s.sol`, using solady's `CREATE3.deployDeterministic`).\n * The address derives only from (Deployer contract, salt) — neither\n * chain-specific nor dependent on the broadcasting EOA — so a single\n * deployment has the SAME address on every chain. The registry therefore ships\n * ONE canonical address ({@link OMNIBUS_CREATE3_ADDRESS}) gated to the chain\n * ids where it has been VERIFIED-deployed, plus the existing per-chain override.\n *\n * The address DATA is the single source of truth in `address.json` (imported\n * below). `script/VerifyOmnibus.s.sol` (run `make verify-omnibus`) asserts\n * `address.json` matches the address predicted from (Deployer, salt) — pure\n * offline math, not an on-chain semantic check. A chain id is added to that\n * file's `chains` array ONLY after the deployed contract is confirmed on-chain\n * for it. This module derives its constants from that JSON; activating a\n * deployment is a data-only edit.\n *\n * Derivation is deterministic, but the SDK ships a VERIFIED constant rather\n * than deriving the address at runtime: a CREATE3 address ignores init code,\n * so the contract actually sitting at the computed address must be confirmed\n * to be the correct two-argument-constructor Omnibus\n * (`constructor(address initialOwner, address quipFactory)`) before it is\n * trusted. A derived-but-unverified address is never returned.\n *\n * Until the canonical address is filled in and chains are enabled, the\n * registry is empty and `resolveDeployment` throws `UNKNOWN_DEPLOYMENT` for\n * every chain without an override — exactly as before. Addresses are never\n * invented or guessed.\n */\nimport {isAddress, zeroAddress} from 'viem'\nimport type {Address} from 'viem'\nimport addressData from './address.json'\nimport {QuipSwapError} from './errors.js'\n\n/** A verified Omnibus deployment on one chain. */\nexport interface OmnibusDeployment {\n /** The chain id the deployment lives on. */\n readonly chainId: bigint\n /** The Omnibus singleton address on that chain. */\n readonly omnibusAddress: Address\n}\n\n/**\n * The canonical CREATE3 Omnibus address, sourced from `address.json`.\n *\n * CREATE3 (via the canonical Deployer contract) derives the address from\n * (Deployer contract, salt) — both chain-independent — so a single Omnibus\n * deployed via `script/DeployOmnibus.s.sol` has the SAME address on every\n * chain.\n *\n * ⚠️ Currently the zero PLACEHOLDER (`address.json`). To activate: set\n * `omnibusAddress` in `address.json` to the real deployed address, run\n * `make verify-omnibus` (offline: confirms it matches the predicted\n * (Deployer, salt) address), confirm on-chain that the correct Omnibus sits\n * there for each target chain (CREATE3 addresses ignore init code, so\n * semantic verification is mandatory), and add those chain ids to `chains`.\n * No code change required.\n */\nexport const OMNIBUS_CREATE3_ADDRESS = addressData.omnibusAddress as Address\n\n/**\n * Chain ids on which {@link OMNIBUS_CREATE3_ADDRESS} is verified-deployed,\n * sourced from `address.json`'s `chains` array. EMPTY until deployments are\n * confirmed — while empty, {@link resolveDeployment} behaves exactly as the\n * old empty-registry version (throws for every chain without an override).\n * A chain id is added ONLY after `make verify-omnibus` passes on it.\n */\nconst VERIFIED_DEPLOYMENT_CHAINS: ReadonlySet<bigint> = new Set<bigint>(\n addressData.chains.map(chainId => BigInt(chainId)),\n)\n\n/**\n * Built-in verified deployments, keyed by chain id. Derived from\n * {@link OMNIBUS_CREATE3_ADDRESS} + {@link VERIFIED_DEPLOYMENT_CHAINS} so\n * there is a single source of truth. EMPTY until the placeholder address is\n * replaced and chains are enabled (identical behavior to the prior empty\n * registry while empty).\n */\nexport const knownDeployments: ReadonlyMap<bigint, OmnibusDeployment> = new Map(\n [...VERIFIED_DEPLOYMENT_CHAINS].map(chainId => [chainId, {chainId, omnibusAddress: OMNIBUS_CREATE3_ADDRESS}]),\n)\n\n/**\n * Resolves the Omnibus address for a chain.\n *\n * Resolution order: an explicit `override` wins; otherwise the built-in\n * {@link knownDeployments} registry is consulted.\n *\n * @param chainId - The target chain id.\n * @param override - Optional application-supplied deployment for this chain.\n * @returns The resolved deployment.\n * @throws QuipSwapError `UNKNOWN_DEPLOYMENT` when no verified deployment\n * exists and no override was provided, or when the override is malformed\n * or names a different chain.\n * @example\n * ```ts\n * const {omnibusAddress} = resolveDeployment(8453n, {\n * chainId: 8453n,\n * omnibusAddress: '0x...', // your verified deployment\n * })\n * ```\n */\nexport function resolveDeployment(chainId: bigint, override?: OmnibusDeployment): OmnibusDeployment {\n if (override !== undefined) {\n if (!isAddress(override.omnibusAddress, {strict: false}) || override.omnibusAddress.toLowerCase() === zeroAddress) {\n throw new QuipSwapError({\n code: 'UNKNOWN_DEPLOYMENT',\n message: `Deployment override for chain ${chainId} has an invalid omnibusAddress`,\n details: {override},\n })\n }\n if (override.chainId !== chainId) {\n throw new QuipSwapError({\n code: 'UNKNOWN_DEPLOYMENT',\n message: `Deployment override names chain ${override.chainId} but chain ${chainId} was requested`,\n details: {override, chainId},\n })\n }\n return override\n }\n const known = knownDeployments.get(chainId)\n if (known === undefined) {\n throw new QuipSwapError({\n code: 'UNKNOWN_DEPLOYMENT',\n message:\n `No verified Omnibus deployment is known for chain ${chainId} and no override was provided. ` +\n 'Supply {chainId, omnibusAddress} explicitly. Addresses are never guessed: a CREATE3 address ignores ' +\n 'init code, so a deployment must be verified on-chain before it is trusted (run `make verify-omnibus`).',\n details: {chainId},\n })\n }\n return known\n}\n","{\n \"_comment\": \"Verified Omnibus deployments. 'omnibusAddress' is the canonical CREATE3 address derived from (Deployer contract, salt); 'chains' lists chain ids where it is VERIFIED-deployed (verify with `make verify-omnibus`). Empty/placeholder until a real deployment is confirmed; while empty, the SDK resolves no built-in address and requires an override.\",\n \"omnibusAddress\": \"0x07b74fb3805f75E669488F64E9a27E74E08fC9e0\",\n \"chains\": [84532]\n}\n","/**\n * Gas estimation, safety-buffered gas limits, fee overrides, and the\n * balance preflight shared by every write method.\n *\n * Why a buffer at all: unused gas is refunded, so over-providing the gas\n * LIMIT costs nothing at execution. Its purpose is preventing out-of-gas\n * failures from state drift between estimation and inclusion — which\n * matters in this protocol because writes happen inside closing time\n * windows, and an OOG'd claim near a window boundary may be unrecoverable.\n *\n * `prepareTx` replaces the previous `simulateContract` step: viem's\n * `estimateContractGas` executes the call node-side, so contract reverts\n * still surface BEFORE submission (decoded into `CONTRACT_REVERT` with\n * `contractErrorName`), and the returned estimate feeds the buffered gas\n * limit. The balance preflight runs FIRST and checks the bare call value\n * only — gas funding is deliberately not preflighted.\n */\nimport {BaseError, ContractFunctionRevertedError} from 'viem'\nimport type {Abi, Address, PublicClient} from 'viem'\nimport {QuipSwapError, wrapContractError} from './errors.js'\n\n/** Default gas-limit safety multiplier: a 20% margin over the node's estimate. */\nexport const DEFAULT_GAS_MULTIPLIER = 1.2\n/** Multiplier floor; anything below 1.0 risks out-of-gas by construction. */\nexport const MIN_GAS_MULTIPLIER = 1.0\n/** Multiplier ceiling; caps the damage of a misconfigured value. */\nexport const MAX_GAS_MULTIPLIER = 2.0\n\n/**\n * Per-transaction options accepted by every write method (`commit`,\n * `claim`, `reclaim`, and all `admin.*` writes). All fields optional;\n * everything unset falls back to viem's automatic behavior.\n */\nexport interface TxOptions {\n /**\n * Explicit gas limit. When set, THREE things are skipped: (a) gas\n * estimation, (b) the safety multiplier, and (c) the pre-submission\n * revert check — because `estimateContractGas` is also what catches a\n * would-be revert before broadcast, and it does not run. The protocol\n * preflights still run, but a call that would revert is signed and\n * broadcast anyway and burns its gas. Use an explicit `gas` only when the\n * call is known to succeed (e.g. replaying a previously simulated call)\n * and you accept on-chain revert risk; leave `gas` unset to keep the\n * revert check, and use {@link TxOptions.gasMultiplier} if you only want\n * to tune the buffer.\n */\n readonly gas?: bigint\n /**\n * Gas-limit safety multiplier: `gas = floor(estimate * multiplier)`,\n * computed with bigint-safe 3-decimal math (never a bigint×float\n * multiplication). Defaults to {@link DEFAULT_GAS_MULTIPLIER}; clamped\n * to [{@link MIN_GAS_MULTIPLIER}, {@link MAX_GAS_MULTIPLIER}];\n * non-finite values fall back to the MIN (no buffer).\n */\n readonly gasMultiplier?: number\n /** EIP-1559 total fee ceiling per gas, in wei (exclusive with `gasPrice`). */\n readonly maxFeePerGas?: bigint\n /** EIP-1559 priority tip per gas, in wei (exclusive with `gasPrice`). */\n readonly maxPriorityFeePerGas?: bigint\n /** Legacy gas price, in wei, for non-EIP-1559 chains (exclusive with the two fields above). */\n readonly gasPrice?: bigint\n /** Pin the transaction nonce; by default viem fetches the next nonce. */\n readonly nonce?: number\n /**\n * Skips the stage-1 BALANCE preflight ONLY (the bare-call-value check\n * that runs before gas estimation; see {@link preflightBalanceCheck}).\n * The protocol preflights (windows, pairing, chain id, lock state) ALWAYS\n * run — they are correctness checks, not robustness checks.\n */\n readonly skipPreflightChecks?: boolean\n}\n\n/**\n * Resolves the effective gas multiplier from {@link TxOptions}.\n *\n * Rules (deterministic, inspectable by tests and callers):\n * - unset → {@link DEFAULT_GAS_MULTIPLIER}\n * - non-finite (`NaN`, `±Infinity`) → {@link MIN_GAS_MULTIPLIER} (no buffer)\n * - otherwise clamped into [{@link MIN_GAS_MULTIPLIER}, {@link MAX_GAS_MULTIPLIER}]\n *\n * @param opts - The caller's transaction options (only `gasMultiplier` is read).\n * @returns The clamped multiplier that {@link applyGasMultiplier} will use.\n */\nexport function resolveGasMultiplier(opts: TxOptions = {}): number {\n const requested = opts.gasMultiplier ?? DEFAULT_GAS_MULTIPLIER\n if (!Number.isFinite(requested)) return MIN_GAS_MULTIPLIER\n return Math.min(MAX_GAS_MULTIPLIER, Math.max(MIN_GAS_MULTIPLIER, requested))\n}\n\n/**\n * Applies the resolved safety multiplier to a gas estimate.\n *\n * Bigint-safe and deterministic: the multiplier is rounded to exactly\n * 3 decimal places by integer scaling — a bigint is never multiplied by a\n * float, so large estimates cannot pick up float round-trip drift:\n *\n * ```ts\n * const scaled = Math.round(multiplier * 1000)\n * gas = (estimate * BigInt(scaled)) / 1000n\n * ```\n *\n * @param estimate - The node's gas estimate (from `estimateContractGas`).\n * @param opts - Transaction options; see {@link resolveGasMultiplier}.\n * @returns The buffered gas limit, `floor(estimate * multiplier)`.\n */\nexport function applyGasMultiplier(estimate: bigint, opts: TxOptions = {}): bigint {\n const scaled = Math.round(resolveGasMultiplier(opts) * 1000)\n return (estimate * BigInt(scaled)) / 1000n\n}\n\n/**\n * The fee fields forwarded to `writeContract` — containing ONLY the fields\n * the caller explicitly set, so viem's automatic fee pricing keeps working\n * for everything unset. `undefined` fee fields are never passed through.\n */\nexport interface FeeOverrides {\n readonly maxFeePerGas?: bigint\n readonly maxPriorityFeePerGas?: bigint\n readonly gasPrice?: bigint\n}\n\n/**\n * Builds the {@link FeeOverrides} object from caller options.\n *\n * @param opts - Transaction options.\n * @returns An object with only the explicitly-set fee fields present.\n */\nexport function buildFeeOverrides(opts: TxOptions = {}): FeeOverrides {\n return {\n ...(opts.maxFeePerGas !== undefined ? {maxFeePerGas: opts.maxFeePerGas} : {}),\n ...(opts.maxPriorityFeePerGas !== undefined ? {maxPriorityFeePerGas: opts.maxPriorityFeePerGas} : {}),\n ...(opts.gasPrice !== undefined ? {gasPrice: opts.gasPrice} : {}),\n }\n}\n\n/** The contract call being prepared (the exact params `estimateContractGas` receives). */\nexport interface PrepareTxContractParams {\n readonly address: Address\n readonly abi: Abi\n readonly functionName: string\n readonly args?: readonly unknown[]\n /** Native value attached to the call (payable functions only). */\n readonly value?: bigint\n /** The sender address — estimation and the balance preflight both use it. */\n readonly account: Address\n}\n\n/** Arguments for {@link prepareTx}. */\nexport interface PrepareTxArgs {\n readonly publicClient: PublicClient\n readonly contractParams: PrepareTxContractParams\n /**\n * The total native value the sender must pay for the call itself, in wei\n * — for commit exactly `totalNative(party) + commitmentFee`; `0n` for\n * claim/reclaim/admin. The balance preflight checks this bare value only\n * (gas funding is deliberately not preflighted — see\n * {@link preflightBalanceCheck}); value-less calls skip the check.\n */\n readonly totalValue: bigint\n readonly opts?: TxOptions\n}\n\n/** The prepared transaction fields, ready to spread into `writeContract`. */\nexport interface PreparedTx {\n /** The gas limit to submit with (buffered unless `opts.gas` was set). */\n readonly gas: bigint\n /** Only the caller's explicitly-set fee fields (see {@link FeeOverrides}). */\n readonly fees: FeeOverrides\n /** Present only when the caller pinned a nonce. */\n readonly nonce?: number\n}\n\n/** True when the error chain contains a decodable contract revert. */\nfunction isContractRevert(error: unknown): boolean {\n return error instanceof BaseError && error.walk(e => e instanceof ContractFunctionRevertedError) !== null\n}\n\n/**\n * Throws `BALANCE_TOO_LOW` if the account's balance is below `required`.\n *\n * No-op when `required <= 0n` — value-less calls (claim/reclaim/admin)\n * have no balance preflight; their send-time funds failures are mapped to\n * `BALANCE_TOO_LOW` in `submitWrite` (see client.ts). Only the bare call\n * value is checked: gas funding is deliberately NOT preflighted (it is the\n * wallet application's concern in the WalletConnect flow).\n *\n * @param publicClient - The Viem public client to read the balance through.\n * @param account - The sender whose balance is checked.\n * @param required - The native value (wei) the call itself must carry.\n * @throws QuipSwapError `BALANCE_TOO_LOW` (with `{required, balance}` in\n * details) when the balance cannot cover `required`.\n */\nexport async function preflightBalanceCheck(\n publicClient: PublicClient,\n account: Address,\n required: bigint,\n): Promise<void> {\n if (required <= 0n) return\n const balance = await publicClient.getBalance({address: account})\n if (balance < required) {\n throw new QuipSwapError({\n code: 'BALANCE_TOO_LOW',\n message: `Sender ${account} holds ${balance} wei but the call requires ${required} wei of value`,\n details: {required, balance},\n })\n }\n}\n\n/**\n * Prepares a write: balance preflight, then gas estimation (or an explicit\n * limit) with the safety multiplier.\n *\n * Stage order:\n * 1. **Balance preflight** (unless `opts.skipPreflightChecks`) — BEFORE\n * estimation, bare `totalValue` only ({@link preflightBalanceCheck}).\n * Running it first fixes a masking bug by construction: any sender\n * reaching estimation already covers the value, and viem attaches no\n * gas price to `eth_estimateGas`, so the node cannot fail estimation on\n * funds — insufficient funds can no longer masquerade as\n * `GAS_ESTIMATION_FAILED`.\n * 2. **Gas** — explicit `opts.gas` is used verbatim (no estimation, no\n * multiplier, and therefore NO pre-submission revert check). Otherwise\n * `publicClient.estimateContractGas` runs the call node-side, so a\n * contract revert surfaces HERE, decoded into a\n * `CONTRACT_REVERT` error with `contractErrorName` — this stage is the\n * pre-submission revert check that replaced `simulateContract` — and\n * the estimate is buffered by {@link applyGasMultiplier}.\n *\n * @param args - See {@link PrepareTxArgs}.\n * @returns The {@link PreparedTx} to spread into `writeContract`.\n * @throws QuipSwapError `BALANCE_TOO_LOW` (with `{required, balance}` in\n * details) when the sender cannot cover the call value;\n * `CONTRACT_REVERT` (with `contractErrorName`) when the call would\n * revert; `GAS_ESTIMATION_FAILED` when estimation fails for a non-revert\n * reason (network error, bad params).\n * @example\n * ```ts\n * const prepared = await prepareTx({publicClient, contractParams, totalValue: 0n, opts})\n * await walletClient.writeContract({...contractParams, gas: prepared.gas, ...prepared.fees})\n * ```\n */\nexport async function prepareTx(args: PrepareTxArgs): Promise<PreparedTx> {\n const {publicClient, contractParams, totalValue, opts = {}} = args\n\n // Stage 1: balance — BEFORE estimation, bare totalValue only. This is\n // the one stage skipPreflightChecks disables. Running it first fixes a\n // masking bug by construction: any sender reaching estimation already\n // covers the value, and viem attaches no gas price to eth_estimateGas,\n // so the node cannot fail estimation on funds — insufficient funds can\n // no longer masquerade as GAS_ESTIMATION_FAILED.\n if (opts.skipPreflightChecks !== true) {\n await preflightBalanceCheck(publicClient, contractParams.account, totalValue)\n }\n\n // Stage 2: gas — explicit opts.gas is used verbatim (no estimation, no\n // multiplier, and therefore no pre-submission revert check); otherwise\n // estimate (contract reverts surface here, decoded — this is the\n // pre-submission revert check) and buffer.\n let gas: bigint\n if (opts.gas !== undefined) {\n gas = opts.gas\n } else {\n let estimate: bigint\n try {\n estimate = await publicClient.estimateContractGas({\n address: contractParams.address,\n abi: contractParams.abi,\n functionName: contractParams.functionName,\n args: (contractParams.args ?? []) as unknown[],\n account: contractParams.account,\n ...(contractParams.value !== undefined ? {value: contractParams.value} : {}),\n // dynamic functionName + optional payable value cannot satisfy viem's\n // conditional parameter types statically; the runtime shape is\n // exercised by the mocked-client and Anvil integration suites\n } as unknown as Parameters<PublicClient['estimateContractGas']>[0])\n } catch (error) {\n if (isContractRevert(error)) {\n // the call would revert on-chain — same signal simulateContract gave\n throw wrapContractError(error, `Estimating gas for ${contractParams.functionName}`)\n }\n throw new QuipSwapError({\n code: 'GAS_ESTIMATION_FAILED',\n message:\n `Gas estimation for ${contractParams.functionName} failed for a non-revert reason ` +\n '(network error or invalid request); see cause',\n cause: error,\n })\n }\n gas = applyGasMultiplier(estimate, opts)\n }\n\n return {gas, fees: buildFeeOverrides(opts), ...(opts.nonce !== undefined ? {nonce: opts.nonce} : {})}\n}\n","/**\n * The Omnibus SDK client: typed reads, preflighted writes, and admin\n * operations against one deployed Omnibus contract.\n *\n * Design rules:\n * - Accepts EXISTING Viem clients — browser wallets, local private-key\n * accounts, backends, hardware-wallet transports, and (in production)\n * clients whose sender is a QuipWallet contract. The SDK never takes\n * custody of private keys, raw RPC URLs, or a specific wallet impl.\n * - Every write runs the protocol preflights first, then `prepareTx`\n * (a balance preflight on the bare call value, then node-side gas\n * estimation — which surfaces would-be reverts before submission — with\n * a safety-buffered gas limit), then `writeContract`. Nothing is sent\n * blind.\n * - Every write preflights the same conditions the contract enforces, so\n * integration failures surface as actionable errors BEFORE a transaction\n * exists. Preflight mirrors but never replaces on-chain enforcement.\n * - User operations (`commit`/`claim`/`reclaim`) and owner administration\n * (`admin.*`) are exposed on separate namespaces so they cannot be\n * confused.\n */\nimport {BaseError, InsufficientFundsError} from 'viem'\nimport type {Address, Hash, PublicClient, WalletClient} from 'viem'\nimport {totalNative} from './assets.js'\nimport {QuipSwapError, wrapContractError} from './errors.js'\nimport {prepareTx} from './gas.js'\nimport type {TxOptions} from './gas.js'\nimport {omnibusAbi} from './generated/omnibusAbi.js'\nimport {assertHex32, digestTerms, digestTermsCanonically, generateLock} from './hashing.js'\nimport {proposedBy, validateTermPairing, validateTerms} from './terms.js'\nimport {waitForOmnibusReceipt} from './receipts.js'\nimport type {OmnibusReceipt, WaitOptions} from './receipts.js'\nimport {LockState} from './types.js'\nimport type {Hex32, Terms} from './types.js'\nimport {validateClaimWindow, validateCommitWindow, validateReclaimWindow} from './windows.js'\n\n/**\n * Minimal `IQuipFactory` surface consumed by the SDK — exactly what the\n * Omnibus `onlyQuipWallet` modifier reads.\n *\n * @see IQuipFactory.vaultIdOf\n */\nexport const quipFactoryAbi = [\n {\n type: 'function',\n name: 'vaultIdOf',\n stateMutability: 'view',\n inputs: [{name: 'wallet', type: 'address'}],\n outputs: [{name: 'vaultId', type: 'bytes32'}],\n },\n] as const\n\n/** Arguments for {@link createOmnibusClient}. */\nexport interface CreateOmnibusClientArgs {\n /** The deployed Omnibus contract address (see {@link resolveDeployment}). */\n readonly address: Address\n /** A Viem public client connected to the chain the contract lives on. */\n readonly publicClient: PublicClient\n /**\n * A Viem wallet client for writes. Optional: a read-only client works\n * without one, and writes then fail with `MISSING_WALLET_CLIENT`. In\n * production the COMMIT sender must be a QuipWallet contract; claim and\n * reclaim may be sent by any account.\n */\n readonly walletClient?: WalletClient\n}\n\n/** Arguments for {@link OmnibusClient.commit}. */\nexport interface CommitArgs {\n /** The hashlock (`generateLock(secret)`); the proposer generates the secret. */\n readonly lock: Hex32\n /** The committing side's terms — the sender acts for this side. */\n readonly party: Terms\n /** The other side's terms. */\n readonly counterparty: Terms\n /**\n * When `true` (default), preflight additionally reads the lock's\n * on-chain state: a `Spent` or `Committed` lock rejects with\n * `INVALID_LOCK_STATE` (no commit can advance from those states), and a\n * `Free` lock requires the canonical `termsHash` to match\n * (`TERMS_NOT_ON_CHAIN` otherwise) and the committing side to not\n * already be posted (`TERMS_ALREADY_POSTED` otherwise — the second\n * same-chain commit must post the OTHER side). Costs three extra\n * parallel reads; with the flag off, gas estimation still catches every\n * case as a decoded `CONTRACT_REVERT`.\n */\n readonly verifyOnChainState?: boolean\n}\n\n/** Arguments for {@link OmnibusClient.claim}. */\nexport interface ClaimArgs {\n /** The 32-byte preimage of the lock. Sending it on-chain reveals it publicly. */\n readonly secret: Hex32\n /** The claimant role's terms (the side the claimant acts for). */\n readonly party: Terms\n /** The other side's terms — the leg being claimed; must be local. */\n readonly counterparty: Terms\n /**\n * When `true` (default), preflight additionally verifies on-chain state\n * in one parallel read batch: `lockState(lock)` must be `Committed`\n * (`INVALID_LOCK_STATE` otherwise, with the actual state and likely\n * cause), `termsHash(lock)` must equal the canonical digest, and the\n * counterparty's side must be `posted` (`TERMS_NOT_ON_CHAIN` otherwise).\n * Costs three extra parallel reads; disable only if you have just\n * verified the state yourself — estimation still catches everything.\n */\n readonly verifyOnChainState?: boolean\n}\n\n/** Arguments for {@link OmnibusClient.reclaim}. */\nexport interface ReclaimArgs {\n /** The hashlock identifying the swap. */\n readonly lock: Hex32\n /** The terms of the leg being reclaimed (must be local to this chain). */\n readonly party: Terms\n /** The other side's terms. */\n readonly counterparty: Terms\n /**\n * When `true` (default), preflight additionally verifies on-chain state\n * in one parallel read batch: `lockState(lock)` must be `Free` or\n * `Committed` (`INVALID_LOCK_STATE` otherwise — `Unused` was never\n * committed, `Spent` was already settled), `termsHash(lock)` must equal\n * the canonical digest, and the party's side must be `posted`\n * (`TERMS_NOT_ON_CHAIN` otherwise).\n */\n readonly verifyOnChainState?: boolean\n}\n\n/** Owner-only administrative operations (Ownable2Step). */\nexport interface OmnibusAdmin {\n /**\n * Sets the commitment fee. Owner only; reverts `FeeExceedsMax` above\n * `MAX_FEE`, `OwnableUnauthorizedAccount` for non-owners.\n *\n * @param newFee - The new fee in wei; must be `<= MAX_FEE`.\n * @param opts - Optional per-transaction gas/fee/nonce options.\n * @returns The transaction hash.\n * @throws QuipSwapError `MISSING_WALLET_CLIENT` | `CONTRACT_REVERT` |\n * `GAS_ESTIMATION_FAILED` | `BALANCE_TOO_LOW`.\n * @see Omnibus.setCommitmentFee\n */\n setCommitmentFee(newFee: bigint, opts?: TxOptions): Promise<Hash>\n /**\n * Withdraws all accrued fees to `to`. Owner only. Escrowed swap native is\n * NOT withdrawable — only accrued fees.\n *\n * @param to - The recipient of the accrued fees.\n * @param opts - Optional per-transaction gas/fee/nonce options.\n * @returns The transaction hash.\n * @throws QuipSwapError `MISSING_WALLET_CLIENT` | `CONTRACT_REVERT` |\n * `GAS_ESTIMATION_FAILED` | `BALANCE_TOO_LOW`.\n * @see Omnibus.withdrawFees\n */\n withdrawFees(to: Address, opts?: TxOptions): Promise<Hash>\n /**\n * Starts the two-step ownership transfer (Ownable2Step): the new owner\n * must later call {@link acceptOwnership}.\n *\n * @param newOwner - The proposed new owner.\n * @param opts - Optional per-transaction gas/fee/nonce options.\n * @returns The transaction hash.\n * @see Ownable2Step.transferOwnership\n */\n transferOwnership(newOwner: Address, opts?: TxOptions): Promise<Hash>\n /**\n * Completes a pending two-step ownership transfer; must be sent by the\n * pending owner.\n *\n * @param opts - Optional per-transaction gas/fee/nonce options.\n * @returns The transaction hash.\n * @see Ownable2Step.acceptOwnership\n */\n acceptOwnership(opts?: TxOptions): Promise<Hash>\n}\n\n/**\n * A typed client bound to one deployed Omnibus contract.\n *\n * Created by {@link createOmnibusClient}. Read methods mirror the\n * contract's getters one-to-one; write methods preflight, estimate gas\n * with a safety buffer, and submit. Write methods return the transaction\n * HASH only — pair them with {@link OmnibusClient.waitForReceipt} to\n * confirm success and decode events (it scopes decoding to this client's\n * Omnibus address automatically).\n */\nexport interface OmnibusClient {\n /** The Omnibus contract address this client is bound to. */\n readonly address: Address\n /** The underlying public client (exposed for receipt/event helpers). */\n readonly publicClient: PublicClient\n\n // ---- reads ----\n\n /** Reads the contract version. @see Omnibus.VERSION */\n getVersion(): Promise<bigint>\n /** Reads the maximum settable commitment fee in wei. @see Omnibus.MAX_FEE */\n getMaxFee(): Promise<bigint>\n /** Reads the QuipFactory address whose registry gates commit. @see Omnibus.QUIP_FACTORY */\n getQuipFactory(): Promise<Address>\n /** Reads the current commitment fee in wei. @see Omnibus.commitmentFee */\n getCommitmentFee(): Promise<bigint>\n /** Reads the withdrawable accrued fees in wei. @see Omnibus.accruedFees */\n getAccruedFees(): Promise<bigint>\n /** Reads a lock's lifecycle state. @see Omnibus.lockState */\n getLockState(lock: Hex32): Promise<LockState>\n /** Reads the canonical terms digest bound to a lock (zero if none). @see Omnibus.termsHash */\n getTermsHash(lock: Hex32): Promise<Hex32>\n /** Reads whether a side's terms digest was posted for a lock. @see Omnibus.posted */\n getPosted(lock: Hex32, termsDigest: Hex32): Promise<boolean>\n /** Reads the current owner. @see Ownable.owner */\n getOwner(): Promise<Address>\n /** Reads the pending owner of an in-flight two-step transfer. @see Ownable2Step.pendingOwner */\n getPendingOwner(): Promise<Address>\n /**\n * Checks whether `account` passes the `onlyQuipWallet` gate: reads\n * `vaultIdOf(account)` on the contract's `QUIP_FACTORY` and reports\n * whether it is non-zero. Only factory-deployed QuipWallets can commit;\n * `commit` runs this as a preflight and rejects with `NOT_QUIP_WALLET`.\n *\n * @param account - The would-be commit sender (the QuipWallet contract\n * address, NOT its owner's EOA).\n * @returns `true` iff `vaultIdOf(account)` is non-zero (the account can commit).\n * @see Omnibus.commit (onlyQuipWallet), IQuipFactory.vaultIdOf\n */\n isQuipWallet(account: Address): Promise<boolean>\n\n // ---- writes (preflight → estimate+buffer → write; hash returned, NOT finality) ----\n\n /**\n * Commits the sender's side of a swap. QuipWallet-gated and payable.\n *\n * The contract gates commit with `onlyQuipWallet`\n * (`QUIP_FACTORY.vaultIdOf(msg.sender) != 0`), so the SDK preflights the\n * gate via {@link OmnibusClient.isQuipWallet} and rejects a non-wallet\n * sender with `NOT_QUIP_WALLET` BEFORE any estimation round-trip — this is\n * the most likely integration failure. The committer must be the QuipWallet\n * CONTRACT address, never its owner's EOA.\n *\n * Preflight (in order, all before any transaction exists):\n * 1. Both terms structurally valid; 2. pairing strictly interleaves;\n * 3. `party.chainId` matches the connected chain (`counterparty.chainId`\n * may differ — cross-chain); 4. the sender passes the QuipWallet gate\n * (`vaultIdOf != 0`); 5. the chain's current timestamp is inside the\n * sender's commit window — proposer `[0, party.commitmentDeadline)`,\n * taker `[counterparty.commitmentDeadline, party.commitmentDeadline)`\n * (the taker's window OPENS only when the proposer's deadline\n * elapses); 6. unless `verifyOnChainState` is disabled, the lock's\n * on-chain state permits this commit (see\n * {@link CommitArgs.verifyOnChainState}); 7. the fee is re-read;\n * 8. `msg.value` is computed as exactly\n * `totalNative(party) + commitmentFee` — the contract checks strict\n * equality (`IncorrectNativeAmountReceived`), so over- and\n * underpayment both revert; 9. the balance preflight runs (bare\n * `msg.value` only — gas funding is not preflighted); 10. gas is\n * estimated node-side (a would-be revert surfaces here, decoded) and\n * buffered by the safety multiplier; 11. submit.\n *\n * Unused gas is refunded, so the default 1.2x buffer costs nothing at\n * execution; it exists to prevent out-of-gas failures from state drift\n * between estimation and inclusion — which matters here because writes\n * happen inside closing time windows.\n *\n * @remarks\n * ⚠️ ASSET-LOSS RISK (cross-chain takers). If you are the TAKER in a\n * cross-chain swap and you commit before the PROPOSER has actually\n * committed on their chain, the proposer — who holds the secret — can\n * claim your escrowed leg while never funding their own, and your assets\n * are gone. The contract enforces the same-chain *window* ordering (the\n * taker cannot commit until the proposer's commitment deadline has passed)\n * and the same-chain lock-state guards prevent a taker-first commit from\n * ever draining the taker — but it CANNOT protect you cross-chain (your\n * chain cannot read the proposer's chain), where a taker-first commit\n * against an uncommitted proposer loses your funds. Before a cross-chain\n * taker commit, verify the\n * proposer's commitment yourself with\n * {@link verifyRemoteCommitment} against the proposer's chain and apply\n * your own confirmation depth; only then call `commit`. See the\n * \"Security & risks\" section of USAGE.md.\n *\n * @param args - See {@link CommitArgs}.\n * @param opts - Optional per-transaction gas/fee/nonce options\n * ({@link TxOptions}); `skipPreflightChecks` skips ONLY the balance\n * check, never the protocol preflights.\n * @returns The transaction hash (not finality — wait for the receipt).\n * @throws QuipSwapError `MISSING_WALLET_CLIENT` | `MISSING_ACCOUNT` |\n * structural codes from {@link validateTerms} | `DISORDERED_DEADLINES`\n * | `CHAIN_ID_MISMATCH` | `NOT_QUIP_WALLET` | `WINDOW_VIOLATED` |\n * `INVALID_LOCK_STATE` | `TERMS_ALREADY_POSTED` | `TERMS_NOT_ON_CHAIN` |\n * `GAS_ESTIMATION_FAILED` | `BALANCE_TOO_LOW` | `CONTRACT_REVERT`.\n * @see Omnibus.commit (onlyQuipWallet)\n * @example\n * ```ts\n * const hash = await client.commit({lock, party: myTerms, counterparty: theirTerms})\n * const result = await client.waitForReceipt(hash) // address-scoped decoding\n * ```\n */\n commit(args: CommitArgs, opts?: TxOptions): Promise<Hash>\n\n /**\n * Claims a swap by revealing the secret. PERMISSIONLESS — the contract\n * allows anyone holding the secret to claim; the SDK adds no caller\n * restriction. The transaction makes the secret PUBLIC.\n *\n * Same-chain note: when `party.chainId == counterparty.chainId`, one\n * claim settles BOTH legs (counterparty's assets to `party.recipient`,\n * party's assets to `counterparty.recipient`).\n *\n * Preflight: secret is valid 32-byte hex; both terms valid and paired;\n * `counterparty.chainId` matches the connected chain (the CLAIMED leg is\n * local; `party.chainId` may be remote in a cross-chain claim); the\n * timestamp is inside the claimant role's window; unless disabled, the\n * lock is `Committed` and its `termsHash`/`posted` state matches (see\n * {@link ClaimArgs.verifyOnChainState}); then balance preflight,\n * estimate+buffer gas (the pre-submission revert check), submit.\n *\n * @param args - See {@link ClaimArgs}.\n * @param opts - Optional per-transaction gas/fee/nonce options.\n * @returns The transaction hash (not finality).\n * @throws QuipSwapError `INVALID_HEX32` | structural/pairing codes |\n * `CHAIN_ID_MISMATCH` | `WINDOW_VIOLATED` | `INVALID_LOCK_STATE` |\n * `TERMS_NOT_ON_CHAIN` | `MISSING_WALLET_CLIENT` |\n * `GAS_ESTIMATION_FAILED` | `BALANCE_TOO_LOW` | `CONTRACT_REVERT`.\n * @see Omnibus.claim\n */\n claim(args: ClaimArgs, opts?: TxOptions): Promise<Hash>\n\n /**\n * Reclaims escrowed assets after the local leg's `reclaimRelease`.\n * PERMISSIONLESS — assets always go to the terms' `reclaimRecipient`\n * regardless of caller, so the SDK adds no caller restriction.\n *\n * Dual-leg note: when the counterparty leg is also local and the lock is\n * `Committed`, one reclaim returns BOTH legs to their respective\n * `reclaimRecipient` addresses and emits two `Reclaimed` events. Reclaim\n * is also valid from `Free` (a half-committed same-chain swap).\n *\n * Preflight: terms valid and paired; `party.chainId` matches the\n * connected chain; current timestamp `>= party.reclaimRelease`; unless\n * disabled, the lock is `Free` or `Committed` and its\n * `termsHash`/`posted` state matches (see\n * {@link ReclaimArgs.verifyOnChainState}); then balance preflight,\n * estimate+buffer gas (the pre-submission revert check), submit.\n *\n * @param args - See {@link ReclaimArgs}.\n * @param opts - Optional per-transaction gas/fee/nonce options.\n * @returns The transaction hash (not finality).\n * @throws QuipSwapError structural/pairing codes | `CHAIN_ID_MISMATCH` |\n * `WINDOW_VIOLATED` | `INVALID_LOCK_STATE` | `TERMS_NOT_ON_CHAIN` |\n * `MISSING_WALLET_CLIENT` | `GAS_ESTIMATION_FAILED` |\n * `BALANCE_TOO_LOW` | `CONTRACT_REVERT`.\n * @see Omnibus.reclaim\n */\n reclaim(args: ReclaimArgs, opts?: TxOptions): Promise<Hash>\n\n /**\n * Waits for a write's receipt, verifies success, and decodes the Omnibus\n * events — scoped to THIS client's Omnibus address, so a same-signature\n * event from another contract in the same transaction is never decoded as\n * genuine. This is the preferred way to confirm a `commit`/`claim`/\n * `reclaim`; you do not pass the address again.\n *\n * @param hash - The transaction hash returned by a write method.\n * @param options - Confirmation count and timeout ({@link WaitOptions});\n * `address` is always set to this client's Omnibus address, so you do\n * not pass it.\n * @returns The typed {@link OmnibusReceipt} with address-scoped events.\n * @throws QuipSwapError `TRANSACTION_REVERTED` | `CONTRACT_REVERT`.\n * @see waitForOmnibusReceipt\n * @example\n * ```ts\n * const hash = await client.commit({lock, party, counterparty})\n * const {commitments} = await client.waitForReceipt(hash, {confirmations: 3})\n * ```\n */\n waitForReceipt(hash: Hash, options?: WaitOptions): Promise<OmnibusReceipt>\n\n /** Owner-only operations, namespaced to avoid mixing with user flows. */\n readonly admin: OmnibusAdmin\n}\n\n/** Convert SDK Terms (readonly) into the mutable tuple shape viem encodes. */\nfunction toAbiTerms(terms: Terms) {\n return {\n chainId: terms.chainId,\n reclaimRecipient: terms.reclaimRecipient,\n recipient: terms.recipient,\n commitmentDeadline: terms.commitmentDeadline,\n claimDeadline: terms.claimDeadline,\n reclaimRelease: terms.reclaimRelease,\n assets: terms.assets.map(a => ({assetType: a.assetType, target: a.target, id: a.id, amount: a.amount})),\n }\n}\n\n/** Human-readable name of a lock state for error messages. */\nfunction lockStateName(state: LockState): string {\n return LockState[state] ?? `unknown(${state})`\n}\n\n/**\n * Creates a typed {@link OmnibusClient} bound to one deployed Omnibus.\n *\n * @param args - The contract address plus existing Viem clients; see\n * {@link CreateOmnibusClientArgs}. No private keys, RPC URLs, or\n * provider-specific objects are accepted — bring your own Viem clients.\n * @returns The client; see {@link OmnibusClient} for every method.\n * @example\n * ```ts\n * import {createPublicClient, createWalletClient, custom, http} from 'viem'\n *\n * const publicClient = createPublicClient({transport: http(rpcUrl)})\n * const walletClient = createWalletClient({transport: custom(window.ethereum)})\n * const client = createOmnibusClient({address: omnibusAddress, publicClient, walletClient})\n * const fee = await client.getCommitmentFee()\n * ```\n */\nexport function createOmnibusClient(args: CreateOmnibusClientArgs): OmnibusClient {\n const {address, publicClient, walletClient} = args\n const contract = {address, abi: omnibusAbi} as const\n\n /** Cached QUIP_FACTORY address — immutable on-chain, safe to cache per client. */\n let quipFactoryAddress: Address | undefined\n\n async function getQuipFactory(): Promise<Address> {\n if (quipFactoryAddress === undefined) {\n const factory = await read<Address>('QUIP_FACTORY')\n quipFactoryAddress = factory\n return factory\n }\n return quipFactoryAddress\n }\n\n /** Typed read with revert wrapping. */\n async function read<T>(functionName: string, fnArgs: readonly unknown[] = []): Promise<T> {\n try {\n return (await publicClient.readContract({\n ...contract,\n functionName,\n args: fnArgs as unknown[],\n } as Parameters<PublicClient['readContract']>[0])) as T\n } catch (error) {\n throw wrapContractError(error, `Reading ${functionName}`)\n }\n }\n\n /** Resolves the wallet client + account or throws actionable errors. */\n function requireWallet(): {wallet: WalletClient; sender: Address} {\n if (walletClient === undefined) {\n throw new QuipSwapError({\n code: 'MISSING_WALLET_CLIENT',\n message: 'This operation submits a transaction; create the client with a walletClient to use it',\n })\n }\n const account = walletClient.account\n if (account === undefined) {\n throw new QuipSwapError({\n code: 'MISSING_ACCOUNT',\n message: 'The wallet client has no account; hoist an account onto the wallet client',\n })\n }\n return {wallet: walletClient, sender: account.address}\n }\n\n /** The chain's current block timestamp — windows are judged against this, not the local clock. */\n async function chainTimestamp(): Promise<bigint> {\n const block = await publicClient.getBlock()\n return block.timestamp\n }\n\n // The onlyQuipWallet gate: QUIP_FACTORY.vaultIdOf(account) != bytes32(0).\n // commit() preflights this so a non-wallet sender fails as NOT_QUIP_WALLET.\n async function isQuipWallet(account: Address): Promise<boolean> {\n const factory = await getQuipFactory()\n try {\n const vaultId = await publicClient.readContract({\n address: factory,\n abi: quipFactoryAbi,\n functionName: 'vaultIdOf',\n args: [account],\n })\n return BigInt(vaultId) !== 0n\n } catch (error) {\n throw wrapContractError(error, 'Reading vaultIdOf from QUIP_FACTORY')\n }\n }\n\n /**\n * One parallel batch of the three on-chain lock reads every\n * `verifyOnChainState` preflight uses — a single round of reads, no\n * sequential extra latency.\n */\n async function readLockBatch(\n lock: Hex32,\n postedDigest: Hex32,\n ): Promise<{state: LockState; onChainTermsHash: Hex32; isPosted: boolean}> {\n const [state, onChainTermsHash, isPosted] = await Promise.all([\n read<number>('lockState', [lock]),\n read<Hex32>('termsHash', [lock]),\n read<boolean>('posted', [lock, postedDigest]),\n ])\n return {state: state as LockState, onChainTermsHash, isPosted}\n }\n\n /** Throws TERMS_NOT_ON_CHAIN when the on-chain termsHash disagrees with the supplied pairing. */\n function checkTermsHash(lock: Hex32, onChainTermsHash: Hex32, party: Terms, counterparty: Terms): void {\n const expected = digestTermsCanonically(party, counterparty)\n if (onChainTermsHash.toLowerCase() !== expected.toLowerCase()) {\n throw new QuipSwapError({\n code: 'TERMS_NOT_ON_CHAIN',\n message:\n 'The on-chain termsHash for this lock does not match the canonical digest of the supplied terms ' +\n '(contract would revert TermsMismatch)',\n details: {lock, onChainTermsHash, expected},\n })\n }\n }\n\n /** Throws TERMS_NOT_ON_CHAIN when the required side has not been posted for the lock. */\n function checkPosted(lock: Hex32, isPosted: boolean): void {\n if (!isPosted) {\n throw new QuipSwapError({\n code: 'TERMS_NOT_ON_CHAIN',\n message:\n \"The required side's terms have not been posted for this lock (contract would revert TermsNotPosted)\",\n details: {lock},\n })\n }\n }\n\n /**\n * Claim preflight against on-chain state: the lock must be `Committed`\n * (`Omnibus._enforceCommittedLock`), the termsHash must bind this exact\n * pairing, and the claimed (counterparty) side must be posted.\n *\n * Deliberately NOT checked: `posted(lock, digestTerms(party))`. The\n * contract's party-side `_enforcePosted` in `claim` runs only when\n * `party.chainId == block.chainid` — unreachable in a cross-chain claim\n * (the claimant's own leg is on the other chain by definition). For\n * same-chain swaps, `Committed` is reachable only via\n * Unused→Free→Committed where the second commit must match the same\n * canonical termsHash and post the not-yet-posted side, so Committed\n * (same-chain) provably implies BOTH sides are posted. With the\n * `Committed` check above in place, a party-side posted read can never\n * fire — zero information content, so it is skipped. (The counterparty\n * read below is, strictly, also implied; it is KEPT because it costs no\n * extra latency inside the Promise.all and, since the three reads are\n * not atomic, it localizes which value disagrees under an RPC race or a\n * violated invariant instead of leaving a confusing revert.)\n */\n async function verifyClaimState(lock: Hex32, party: Terms, counterparty: Terms): Promise<void> {\n const {state, onChainTermsHash, isPosted} = await readLockBatch(lock, digestTerms(counterparty))\n if (state !== LockState.Committed) {\n const cause =\n state === LockState.Unused\n ? 'nothing has been committed under this lock on this chain — either the swap was never committed here, or the supplied secret is not the preimage for this swap (a wrong secret derives a different lock)'\n : state === LockState.Free\n ? 'the counterparty has not committed yet (same-chain swap is half-committed)'\n : 'the lock was already claimed or reclaimed'\n throw new QuipSwapError({\n code: 'INVALID_LOCK_STATE',\n message:\n `Cannot claim: lock state is ${lockStateName(state)} but claim requires Committed — ${cause} ` +\n '(contract would revert InvalidLockState)',\n details: {lock, lockState: state, required: 'Committed'},\n })\n }\n checkTermsHash(lock, onChainTermsHash, party, counterparty)\n checkPosted(lock, isPosted)\n }\n\n /**\n * Reclaim preflight against on-chain state: `_advanceLockTo` permits\n * only Free→Spent and Committed→Spent, so the lock must be `Free` or\n * `Committed`; the termsHash must bind this pairing; and the reclaimed\n * (party) side must be posted.\n */\n async function verifyReclaimState(lock: Hex32, party: Terms, counterparty: Terms): Promise<void> {\n const {state, onChainTermsHash, isPosted} = await readLockBatch(lock, digestTerms(party))\n if (state !== LockState.Free && state !== LockState.Committed) {\n const cause =\n state === LockState.Unused\n ? 'nothing has been committed under this lock on this chain'\n : 'the lock was already claimed or reclaimed'\n throw new QuipSwapError({\n code: 'INVALID_LOCK_STATE',\n message:\n `Cannot reclaim: lock state is ${lockStateName(state)} but reclaim requires Free or Committed — ` +\n `${cause} (contract would revert InvalidLockAdvancement)`,\n details: {lock, lockState: state, required: 'Free or Committed'},\n })\n }\n checkTermsHash(lock, onChainTermsHash, party, counterparty)\n checkPosted(lock, isPosted)\n }\n\n /**\n * Commit preflight against on-chain state: `Spent`/`Committed` can never\n * accept another commit; a `Free` lock (second same-chain commit) must\n * carry the same canonical termsHash and must NOT already have the\n * committing side posted — the second commit posts the OTHER side\n * (`Omnibus.commit`: `if (posted[lock][partyDigest]) revert\n * TermsAlreadyPosted()`); `Unused` needs nothing extra.\n */\n async function verifyCommitState(lock: Hex32, party: Terms, counterparty: Terms): Promise<void> {\n // all three reads go out in one parallel batch; the Free-only checks\n // simply ignore the extra values for other states\n const {state, onChainTermsHash, isPosted} = await readLockBatch(lock, digestTerms(party))\n if (state === LockState.Spent || state === LockState.Committed) {\n throw new QuipSwapError({\n code: 'INVALID_LOCK_STATE',\n message:\n `Cannot commit: lock state is ${lockStateName(state)} and no commit can advance from it ` +\n '(contract would revert InvalidLockAdvancement)',\n details: {lock, lockState: state, required: 'Unused or Free'},\n })\n }\n if (state === LockState.Free) {\n checkTermsHash(lock, onChainTermsHash, party, counterparty)\n if (isPosted) {\n throw new QuipSwapError({\n code: 'TERMS_ALREADY_POSTED',\n message:\n \"This side's terms are already posted for the lock; the second same-chain commit must post the \" +\n 'OTHER side (contract would revert TermsAlreadyPosted)',\n details: {lock, partyDigest: digestTerms(party)},\n })\n }\n }\n // Unused: no extra requirement\n }\n\n /**\n * Shared write path: prepare (balance preflight on the bare call value,\n * then node-side gas estimation — a would-be revert surfaces here\n * decoded — with the safety multiplier applied) and submit with the\n * prepared gas/fees/nonce.\n */\n async function submitWrite(params: {\n wallet: WalletClient\n sender: Address\n functionName: string\n args: readonly unknown[]\n value?: bigint\n opts: TxOptions | undefined\n context: string\n }): Promise<Hash> {\n const prepared = await prepareTx({\n publicClient,\n contractParams: {\n address,\n abi: omnibusAbi,\n functionName: params.functionName,\n args: params.args,\n ...(params.value !== undefined ? {value: params.value} : {}),\n account: params.sender,\n },\n totalValue: params.value ?? 0n,\n ...(params.opts !== undefined ? {opts: params.opts} : {}),\n })\n try {\n return await params.wallet.writeContract({\n ...contract,\n functionName: params.functionName,\n args: params.args as unknown[],\n account: params.wallet.account ?? params.sender,\n chain: params.wallet.chain ?? publicClient.chain ?? null,\n ...(params.value !== undefined ? {value: params.value} : {}),\n gas: prepared.gas,\n ...prepared.fees,\n ...(prepared.nonce !== undefined ? {nonce: prepared.nonce} : {}),\n // dynamic functionName + optional payable value cannot satisfy viem's\n // conditional parameter types statically; the runtime shape is\n // exercised by the mocked-client and Anvil integration suites\n } as unknown as Parameters<WalletClient['writeContract']>[0])\n } catch (error) {\n // value-less calls (claim/reclaim/admin) carry no balance preflight,\n // so a gas-unfunded sender's failure surfaces at SEND time — map it\n // to BALANCE_TOO_LOW instead of mislabeling it CONTRACT_REVERT\n if (error instanceof BaseError && error.walk(e => e instanceof InsufficientFundsError) !== null) {\n throw new QuipSwapError({\n code: 'BALANCE_TOO_LOW',\n message: `Sender cannot cover gas for ${params.functionName}; fund the account and retry`,\n cause: error,\n })\n }\n throw wrapContractError(error, params.context)\n }\n }\n\n const admin: OmnibusAdmin = {\n async setCommitmentFee(newFee: bigint, opts?: TxOptions): Promise<Hash> {\n const {wallet, sender} = requireWallet()\n return submitWrite({wallet, sender, functionName: 'setCommitmentFee', args: [newFee], opts, context: 'setCommitmentFee'})\n },\n async withdrawFees(to: Address, opts?: TxOptions): Promise<Hash> {\n const {wallet, sender} = requireWallet()\n return submitWrite({wallet, sender, functionName: 'withdrawFees', args: [to], opts, context: 'withdrawFees'})\n },\n async transferOwnership(newOwner: Address, opts?: TxOptions): Promise<Hash> {\n const {wallet, sender} = requireWallet()\n return submitWrite({\n wallet,\n sender,\n functionName: 'transferOwnership',\n args: [newOwner],\n opts,\n context: 'transferOwnership',\n })\n },\n async acceptOwnership(opts?: TxOptions): Promise<Hash> {\n const {wallet, sender} = requireWallet()\n return submitWrite({wallet, sender, functionName: 'acceptOwnership', args: [], opts, context: 'acceptOwnership'})\n },\n }\n\n return {\n address,\n publicClient,\n getVersion: () => read('VERSION'),\n getMaxFee: () => read('MAX_FEE'),\n getQuipFactory,\n getCommitmentFee: () => read('commitmentFee'),\n getAccruedFees: () => read('accruedFees'),\n getLockState: async (lock: Hex32) => {\n assertHex32(lock, 'lock')\n const state = await read<number>('lockState', [lock])\n return state as LockState\n },\n getTermsHash: (lock: Hex32) => {\n assertHex32(lock, 'lock')\n return read('termsHash', [lock])\n },\n getPosted: (lock: Hex32, termsDigest: Hex32) => {\n assertHex32(lock, 'lock')\n assertHex32(termsDigest, 'termsDigest')\n return read('posted', [lock, termsDigest])\n },\n getOwner: () => read('owner'),\n getPendingOwner: () => read('pendingOwner'),\n\n isQuipWallet,\n\n // confirm a write and decode events, always scoped to this client's\n // Omnibus address (the client knows the right address for its chain)\n waitForReceipt: (hash: Hash, options: WaitOptions = {}) =>\n waitForOmnibusReceipt(publicClient, hash, {...options, address}),\n\n // @audit-ok\n async commit({lock, party, counterparty, verifyOnChainState = true}: CommitArgs, opts?: TxOptions): Promise<Hash> {\n assertHex32(lock, 'lock')\n const {wallet, sender} = requireWallet()\n\n // 1-2. structural + pairing validation (mirrors the contract's order)\n validateTerms(party)\n validateTerms(counterparty)\n validateTermPairing(party, counterparty)\n\n // 3. only the LOCAL side's chainId must match; the counterparty may be remote\n const connectedChainId = BigInt(await publicClient.getChainId())\n if (party.chainId !== connectedChainId) {\n throw new QuipSwapError({\n code: 'CHAIN_ID_MISMATCH',\n message:\n `party.chainId (${party.chainId}) does not match the connected chain (${connectedChainId}); ` +\n \"commit must be sent on the chain holding the party's assets (contract: ChainIdMismatch)\",\n details: {partyChainId: party.chainId, connectedChainId},\n })\n }\n\n // 4. QuipWallet gate — only factory-deployed QuipWallets can commit\n // (Omnibus.commit is onlyQuipWallet). Preflight it here, before the\n // estimation round-trip, since a non-wallet sender is the most likely\n // integration failure; surfaces as NOT_QUIP_WALLET with a clear cause.\n if (!(await isQuipWallet(sender))) {\n throw new QuipSwapError({\n code: 'NOT_QUIP_WALLET',\n message:\n `Sender ${sender} is not a factory-deployed QuipWallet (QUIP_FACTORY.vaultIdOf is zero); ` +\n 'only QuipWallet contracts can commit (contract: CallerNotQuipWallet). The committer must be the ' +\n \"QuipWallet CONTRACT address — never substitute the wallet owner's EOA\",\n details: {sender},\n })\n }\n\n // 5. role-aware commit window; surfaces \"taker too early\" clearly\n const timestamp = await chainTimestamp()\n try {\n validateCommitWindow(party, counterparty, timestamp)\n } catch (error) {\n if (\n error instanceof QuipSwapError &&\n error.code === 'WINDOW_VIOLATED' &&\n proposedBy(party, counterparty) === 'counterparty' &&\n timestamp < counterparty.commitmentDeadline\n ) {\n throw new QuipSwapError({\n code: 'WINDOW_VIOLATED',\n message:\n `Taker commit window has not opened yet: it opens at the proposer's commitmentDeadline ` +\n `(${counterparty.commitmentDeadline}) and the chain time is ${timestamp}. Wait for the proposer's ` +\n 'deadline to elapse before committing',\n details: {opensAt: counterparty.commitmentDeadline, timestamp},\n cause: error,\n })\n }\n throw error\n }\n\n // 6. lock-state preflight (Spent/Committed cannot accept a commit;\n // Free requires matching termsHash and an un-posted party side)\n if (verifyOnChainState) {\n await verifyCommitState(lock, party, counterparty)\n }\n\n // 7-8. SECURITY: re-read the fee immediately before estimating — the\n // owner can change it, and the contract checks msg.value for EXACT\n // equality (IncorrectNativeAmountReceived); a stale fee bricks the tx\n // in either direction (under- AND overpayment revert)\n const fee = await read<bigint>('commitmentFee')\n const value = totalNative(party) + fee\n\n // 9-11. balance preflight + estimate (revert check) + buffer + submit\n return submitWrite({\n wallet,\n sender,\n functionName: 'commit',\n args: [lock, toAbiTerms(party), toAbiTerms(counterparty)],\n value,\n opts,\n context: 'commit',\n })\n },\n\n async claim(\n {secret, party, counterparty, verifyOnChainState = true}: ClaimArgs,\n opts?: TxOptions,\n ): Promise<Hash> {\n // 1-2. validate the secret and derive the lock from it\n assertHex32(secret, 'secret')\n const lock = generateLock(secret)\n const {wallet, sender} = requireWallet()\n\n // 3. structural + pairing validation\n validateTerms(party)\n validateTerms(counterparty)\n validateTermPairing(party, counterparty)\n\n // 4. the CLAIMED leg (counterparty) must be local; party may be remote\n const connectedChainId = BigInt(await publicClient.getChainId())\n if (counterparty.chainId !== connectedChainId) {\n throw new QuipSwapError({\n code: 'CHAIN_ID_MISMATCH',\n message:\n `counterparty.chainId (${counterparty.chainId}) does not match the connected chain ` +\n `(${connectedChainId}); claim must be sent on the chain holding the counterparty's assets ` +\n '(contract: ChainIdMismatch)',\n details: {counterpartyChainId: counterparty.chainId, connectedChainId},\n })\n }\n\n // 5. role-aware claim window\n const timestamp = await chainTimestamp()\n validateClaimWindow(party, counterparty, timestamp)\n\n // 6. optional on-chain state verification (lockState + termsHash + posted)\n if (verifyOnChainState) {\n await verifyClaimState(lock, party, counterparty)\n }\n\n // 7-9. balance preflight + estimate (revert check) + buffer + submit.\n // NOTE: claim is permissionless — any sender with the secret may\n // claim; no caller check is added here\n return submitWrite({\n wallet,\n sender,\n functionName: 'claim',\n args: [secret, toAbiTerms(party), toAbiTerms(counterparty)],\n opts,\n context: 'claim',\n })\n },\n\n async reclaim(\n {lock, party, counterparty, verifyOnChainState = true}: ReclaimArgs,\n opts?: TxOptions,\n ): Promise<Hash> {\n assertHex32(lock, 'lock')\n const {wallet, sender} = requireWallet()\n\n // 1. structural + pairing validation\n validateTerms(party)\n validateTerms(counterparty)\n validateTermPairing(party, counterparty)\n\n // 2. the reclaimed leg must be local\n const connectedChainId = BigInt(await publicClient.getChainId())\n if (party.chainId !== connectedChainId) {\n throw new QuipSwapError({\n code: 'CHAIN_ID_MISMATCH',\n message:\n `party.chainId (${party.chainId}) does not match the connected chain (${connectedChainId}); ` +\n \"reclaim must be sent on the chain holding the party's assets (contract: ChainIdMismatch)\",\n details: {partyChainId: party.chainId, connectedChainId},\n })\n }\n\n // 3. reclaim window: [party.reclaimRelease, +inf). NOTE: reclaim is\n // permissionless and pays reclaimRecipient regardless of caller\n const timestamp = await chainTimestamp()\n validateReclaimWindow(party, timestamp)\n\n // 4. optional on-chain state verification (lockState + termsHash + posted)\n if (verifyOnChainState) {\n await verifyReclaimState(lock, party, counterparty)\n }\n\n // 5-7. balance preflight + estimate (revert check) + buffer + submit\n return submitWrite({\n wallet,\n sender,\n functionName: 'reclaim',\n args: [lock, toAbiTerms(party), toAbiTerms(counterparty)],\n opts,\n context: 'reclaim',\n })\n },\n\n admin,\n }\n}\n","/**\n * Omnibus contract ABI.\n *\n * AUTO-GENERATED by scripts/generate-abi.ts from out/Omnibus.sol/Omnibus.json.\n * Do not edit by hand — run `forge build && bun run generate:abi` instead.\n *\n * Exported `as const` so Viem can infer typed function arguments, return\n * values, event shapes, and custom error names directly from this object.\n */\nexport const omnibusAbi = [\n {\n \"type\": \"constructor\",\n \"inputs\": [\n {\n \"name\": \"initialOwner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"quipFactory\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"receive\",\n \"stateMutability\": \"payable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"MAX_FEE\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"QUIP_FACTORY\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"contract IQuipFactory\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"VERSION\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"acceptOwnership\",\n \"inputs\": [],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"accruedFees\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"claim\",\n \"inputs\": [\n {\n \"name\": \"secret\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"party\",\n \"type\": \"tuple\",\n \"internalType\": \"struct Terms\",\n \"components\": [\n {\n \"name\": \"chainId\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRecipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"commitmentDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"claimDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRelease\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"assets\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct Asset[]\",\n \"components\": [\n {\n \"name\": \"assetType\",\n \"type\": \"uint8\",\n \"internalType\": \"enum AssetType\"\n },\n {\n \"name\": \"target\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"id\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"amount\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ]\n }\n ]\n },\n {\n \"name\": \"counterparty\",\n \"type\": \"tuple\",\n \"internalType\": \"struct Terms\",\n \"components\": [\n {\n \"name\": \"chainId\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRecipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"commitmentDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"claimDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRelease\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"assets\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct Asset[]\",\n \"components\": [\n {\n \"name\": \"assetType\",\n \"type\": \"uint8\",\n \"internalType\": \"enum AssetType\"\n },\n {\n \"name\": \"target\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"id\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"amount\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ]\n }\n ]\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"commit\",\n \"inputs\": [\n {\n \"name\": \"lock\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"party\",\n \"type\": \"tuple\",\n \"internalType\": \"struct Terms\",\n \"components\": [\n {\n \"name\": \"chainId\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRecipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"commitmentDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"claimDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRelease\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"assets\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct Asset[]\",\n \"components\": [\n {\n \"name\": \"assetType\",\n \"type\": \"uint8\",\n \"internalType\": \"enum AssetType\"\n },\n {\n \"name\": \"target\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"id\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"amount\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ]\n }\n ]\n },\n {\n \"name\": \"counterparty\",\n \"type\": \"tuple\",\n \"internalType\": \"struct Terms\",\n \"components\": [\n {\n \"name\": \"chainId\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRecipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"commitmentDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"claimDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRelease\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"assets\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct Asset[]\",\n \"components\": [\n {\n \"name\": \"assetType\",\n \"type\": \"uint8\",\n \"internalType\": \"enum AssetType\"\n },\n {\n \"name\": \"target\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"id\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"amount\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ]\n }\n ]\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"payable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"commitmentFee\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"lockState\",\n \"inputs\": [\n {\n \"name\": \"lock\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"state\",\n \"type\": \"uint8\",\n \"internalType\": \"enum LockState\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"onERC1155BatchReceived\",\n \"inputs\": [\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"\",\n \"type\": \"uint256[]\",\n \"internalType\": \"uint256[]\"\n },\n {\n \"name\": \"\",\n \"type\": \"uint256[]\",\n \"internalType\": \"uint256[]\"\n },\n {\n \"name\": \"\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes4\",\n \"internalType\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"pure\"\n },\n {\n \"type\": \"function\",\n \"name\": \"onERC1155Received\",\n \"inputs\": [\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes4\",\n \"internalType\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"pure\"\n },\n {\n \"type\": \"function\",\n \"name\": \"onERC721Received\",\n \"inputs\": [\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"\",\n \"type\": \"bytes\",\n \"internalType\": \"bytes\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bytes4\",\n \"internalType\": \"bytes4\"\n }\n ],\n \"stateMutability\": \"pure\"\n },\n {\n \"type\": \"function\",\n \"name\": \"owner\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"pendingOwner\",\n \"inputs\": [],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"posted\",\n \"inputs\": [\n {\n \"name\": \"lock\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"termsDigest\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"isPosted\",\n \"type\": \"bool\",\n \"internalType\": \"bool\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"reclaim\",\n \"inputs\": [\n {\n \"name\": \"lock\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"party\",\n \"type\": \"tuple\",\n \"internalType\": \"struct Terms\",\n \"components\": [\n {\n \"name\": \"chainId\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRecipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"commitmentDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"claimDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRelease\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"assets\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct Asset[]\",\n \"components\": [\n {\n \"name\": \"assetType\",\n \"type\": \"uint8\",\n \"internalType\": \"enum AssetType\"\n },\n {\n \"name\": \"target\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"id\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"amount\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ]\n }\n ]\n },\n {\n \"name\": \"counterparty\",\n \"type\": \"tuple\",\n \"internalType\": \"struct Terms\",\n \"components\": [\n {\n \"name\": \"chainId\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRecipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"commitmentDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"claimDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRelease\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"assets\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct Asset[]\",\n \"components\": [\n {\n \"name\": \"assetType\",\n \"type\": \"uint8\",\n \"internalType\": \"enum AssetType\"\n },\n {\n \"name\": \"target\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"id\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"amount\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ]\n }\n ]\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"renounceOwnership\",\n \"inputs\": [],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"setCommitmentFee\",\n \"inputs\": [\n {\n \"name\": \"newFee\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"supportsInterface\",\n \"inputs\": [\n {\n \"name\": \"interfaceId\",\n \"type\": \"bytes4\",\n \"internalType\": \"bytes4\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"\",\n \"type\": \"bool\",\n \"internalType\": \"bool\"\n }\n ],\n \"stateMutability\": \"pure\"\n },\n {\n \"type\": \"function\",\n \"name\": \"termsHash\",\n \"inputs\": [\n {\n \"name\": \"lock\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"outputs\": [\n {\n \"name\": \"canonicalDigest\",\n \"type\": \"bytes32\",\n \"internalType\": \"bytes32\"\n }\n ],\n \"stateMutability\": \"view\"\n },\n {\n \"type\": \"function\",\n \"name\": \"transferOwnership\",\n \"inputs\": [\n {\n \"name\": \"newOwner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"function\",\n \"name\": \"withdrawFees\",\n \"inputs\": [\n {\n \"name\": \"to\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ],\n \"outputs\": [],\n \"stateMutability\": \"nonpayable\"\n },\n {\n \"type\": \"event\",\n \"name\": \"Claim\",\n \"inputs\": [\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"lock\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"secret\",\n \"type\": \"bytes32\",\n \"indexed\": false,\n \"internalType\": \"bytes32\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"Commitment\",\n \"inputs\": [\n {\n \"name\": \"lock\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"party\",\n \"type\": \"tuple\",\n \"indexed\": false,\n \"internalType\": \"struct Terms\",\n \"components\": [\n {\n \"name\": \"chainId\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRecipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"commitmentDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"claimDeadline\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"reclaimRelease\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"assets\",\n \"type\": \"tuple[]\",\n \"internalType\": \"struct Asset[]\",\n \"components\": [\n {\n \"name\": \"assetType\",\n \"type\": \"uint8\",\n \"internalType\": \"enum AssetType\"\n },\n {\n \"name\": \"target\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n },\n {\n \"name\": \"id\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"amount\",\n \"type\": \"uint256\",\n \"internalType\": \"uint256\"\n }\n ]\n }\n ]\n },\n {\n \"name\": \"committer\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"FeeUpdated\",\n \"inputs\": [\n {\n \"name\": \"oldFee\",\n \"type\": \"uint256\",\n \"indexed\": false,\n \"internalType\": \"uint256\"\n },\n {\n \"name\": \"newFee\",\n \"type\": \"uint256\",\n \"indexed\": false,\n \"internalType\": \"uint256\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"FeesWithdrawn\",\n \"inputs\": [\n {\n \"name\": \"to\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"amount\",\n \"type\": \"uint256\",\n \"indexed\": false,\n \"internalType\": \"uint256\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"OwnershipTransferStarted\",\n \"inputs\": [\n {\n \"name\": \"previousOwner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"newOwner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"OwnershipTransferred\",\n \"inputs\": [\n {\n \"name\": \"previousOwner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"newOwner\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"event\",\n \"name\": \"Reclaimed\",\n \"inputs\": [\n {\n \"name\": \"caller\",\n \"type\": \"address\",\n \"indexed\": false,\n \"internalType\": \"address\"\n },\n {\n \"name\": \"lock\",\n \"type\": \"bytes32\",\n \"indexed\": true,\n \"internalType\": \"bytes32\"\n },\n {\n \"name\": \"recipient\",\n \"type\": \"address\",\n \"indexed\": true,\n \"internalType\": \"address\"\n }\n ],\n \"anonymous\": false\n },\n {\n \"type\": \"error\",\n \"name\": \"CallerNotQuipWallet\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"ChainIdMismatch\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"DisordedDeadlines\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"EmptyAssets\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"FeeExceedsMax\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"IncorrectNativeAmountReceived\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidERC1155Asset\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidERC20Asset\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidERC721Asset\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidLockAdvancement\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidLockState\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidNativeAsset\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"InvalidRange\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"OwnableInvalidOwner\",\n \"inputs\": [\n {\n \"name\": \"owner\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n },\n {\n \"type\": \"error\",\n \"name\": \"OwnableUnauthorizedAccount\",\n \"inputs\": [\n {\n \"name\": \"account\",\n \"type\": \"address\",\n \"internalType\": \"address\"\n }\n ]\n },\n {\n \"type\": \"error\",\n \"name\": \"TermsAlreadyPosted\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"TermsMismatch\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"TermsNotPosted\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"UnexpectedAmountReceived\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"WindowViolated\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"ZeroAddressRecipient\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"ZeroAmount\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"ZeroChainId\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"ZeroDeadline\",\n \"inputs\": []\n },\n {\n \"type\": \"error\",\n \"name\": \"ZeroQuipFactory\",\n \"inputs\": []\n }\n] as const\n","/**\n * Typed decoding and query helpers for all active Omnibus events:\n *\n * ```solidity\n * event Commitment(bytes32 indexed lock, Terms party, address indexed committer);\n * event Claim(address recipient, bytes32 indexed lock, bytes32 secret);\n * event Reclaimed(address caller, bytes32 indexed lock, address indexed recipient);\n * event FeeUpdated(uint256 oldFee, uint256 newFee);\n * event FeesWithdrawn(address indexed to, uint256 amount);\n * ```\n *\n * Operational caveats every consumer must respect:\n * - Observing an event ONCE is not finality: logs can be duplicated by\n * RPC providers and removed/re-emitted across chain reorganizations.\n * Apply your own confirmation policy before treating a log as final.\n * - `Reclaimed` is legitimately emitted TWICE in one transaction when a\n * reclaim settles both legs locally — helpers return arrays.\n * - `Claim.secret` lives in event DATA (not a topic): the lock is the only\n * filterable topic, and the secret becomes public the moment the event\n * is emitted.\n */\nimport {parseEventLogs} from 'viem'\nimport type {Address, BlockNumber, BlockTag, Log, PublicClient} from 'viem'\nimport {QuipSwapError} from './errors.js'\nimport {generateLock} from './hashing.js'\nimport {omnibusAbi} from './generated/omnibusAbi.js'\nimport {AssetType} from './types.js'\nimport type {Hex32, Terms} from './types.js'\n\n/** A decoded `Commitment` event. */\nexport interface CommitmentEvent {\n /** The hashlock the commitment is bound to (indexed topic). */\n readonly lock: Hex32\n /** The committing side's FULL terms, recovered from event data. */\n readonly party: Terms\n /** The QuipWallet that committed (indexed topic). */\n readonly committer: Address\n /** Block number the log was found in (`null` for pending logs). */\n readonly blockNumber: bigint | null\n /** Transaction hash the log was found in (`null` for pending logs). */\n readonly transactionHash: Hex32 | null\n /** Log index within the block (`null` for pending logs). */\n readonly logIndex: number | null\n}\n\n/** A decoded `Claim` event. The `secret` field is public once emitted. */\nexport interface ClaimEvent {\n /** The address that called `claim` (event data, NOT the asset recipient per se). */\n readonly recipient: Address\n /** The hashlock that was claimed (indexed topic — the only filterable field). */\n readonly lock: Hex32\n /** The revealed 32-byte preimage. Public from this moment on. */\n readonly secret: Hex32\n readonly blockNumber: bigint | null\n readonly transactionHash: Hex32 | null\n readonly logIndex: number | null\n}\n\n/** A decoded `Reclaimed` event. Two may appear in a single transaction. */\nexport interface ReclaimedEvent {\n /** The address that called `reclaim` (permissionless — any account). */\n readonly caller: Address\n /** The hashlock that was reclaimed (indexed topic). */\n readonly lock: Hex32\n /** The `reclaimRecipient` that received this leg's assets (indexed topic). */\n readonly recipient: Address\n readonly blockNumber: bigint | null\n readonly transactionHash: Hex32 | null\n readonly logIndex: number | null\n}\n\n/** Narrow a decoded uint8 to the {@link AssetType} enum, rejecting out-of-range values. */\nfunction toAssetType(value: number): AssetType {\n if (value === 0 || value === 1 || value === 2 || value === 3) return value as AssetType\n throw new QuipSwapError({\n code: 'INVALID_ASSET_TYPE',\n message: `Decoded asset type ${value} is out of range`,\n })\n}\n\n/** Shape of the Terms tuple as viem decodes it from the ABI. */\ninterface DecodedTermsTuple {\n readonly chainId: bigint\n readonly reclaimRecipient: Address\n readonly recipient: Address\n readonly commitmentDeadline: bigint\n readonly claimDeadline: bigint\n readonly reclaimRelease: bigint\n readonly assets: readonly {\n readonly assetType: number\n readonly target: Address\n readonly id: bigint\n readonly amount: bigint\n }[]\n}\n\n/** Convert a viem-decoded Terms tuple into the SDK's typed, frozen {@link Terms}. */\nfunction toTerms(decoded: DecodedTermsTuple): Terms {\n return Object.freeze({\n chainId: decoded.chainId,\n reclaimRecipient: decoded.reclaimRecipient,\n recipient: decoded.recipient,\n commitmentDeadline: decoded.commitmentDeadline,\n claimDeadline: decoded.claimDeadline,\n reclaimRelease: decoded.reclaimRelease,\n assets: Object.freeze(\n decoded.assets.map(a =>\n Object.freeze({assetType: toAssetType(a.assetType), target: a.target, id: a.id, amount: a.amount}),\n ),\n ),\n })\n}\n\n/**\n * Decodes every `Commitment` event in a list of logs (e.g. from a receipt\n * or `getLogs`), recovering the committing side's full typed {@link Terms}\n * from event data — this is how a coordinator reconstructs a side's terms\n * from chain history without an off-chain channel.\n *\n * Non-`Commitment` logs are skipped, not errors.\n *\n * NOTE: a raw ABI decoder — it does NOT verify `log.address`, so it decodes\n * any `Commitment`-shaped log in `logs`. Scope `logs` to the known Omnibus\n * deployment first (prefer `client.waitForReceipt` /\n * `waitForOmnibusReceipt(..., {address})`, or the address-scoped\n * {@link getCommitmentEvents}).\n *\n * @param logs - Pre-scoped logs (a receipt's `logs` array or a `getLogs` result).\n * @returns All decoded `Commitment` events, in log order.\n * @see IOmnibus.Commitment\n * @example\n * ```ts\n * // PREFERRED: client.waitForReceipt scopes decoding to the Omnibus address\n * const {commitments} = await client.waitForReceipt(hash)\n * commitments[0]?.party.assets // typed Asset[]\n *\n * // low-level: only on logs ALREADY scoped to the Omnibus address\n * const scoped = receipt.logs.filter(l => l.address.toLowerCase() === omnibus.toLowerCase())\n * const [commitment] = decodeCommitmentEvents(scoped)\n * ```\n */\nexport function decodeCommitmentEvents(logs: readonly Log[]): CommitmentEvent[] {\n const parsed = parseEventLogs({abi: omnibusAbi, eventName: 'Commitment', logs: logs as Log[], strict: true})\n return parsed.map(log => ({\n lock: log.args.lock,\n party: toTerms(log.args.party),\n committer: log.args.committer,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n logIndex: log.logIndex,\n }))\n}\n\n/**\n * Decodes every `Claim` event in a list of logs.\n *\n * The `secret` field is the revealed preimage: in a cross-chain swap this\n * is how the taker (or a relayer) learns the secret after the proposer\n * claims — watch the counterparty chain for `Claim` on the shared lock and\n * extract `secret`.\n *\n * NOTE: This helper does NOT filter by Omnibus contract address — it decodes\n * any log in `logs` whose shape matches the `Claim` ABI. Callers passing\n * unscoped logs (e.g. a full receipt or a broad `getLogs` result) may pick up\n * unrelated contracts. {@link extractRevealedSecret} inherits this behavior\n * and can then return a spoofed secret if a non-Omnibus log mimics `Claim`.\n * Prefer {@link getClaimEvents} / {@link watchClaimEvents} (address-scoped)\n * or pre-filter `logs` to the known Omnibus deployment before decoding.\n *\n * @param logs - Raw logs to scan; non-`Claim` logs are skipped.\n * @returns All decoded `Claim` events, in log order.\n * @see IOmnibus.Claim\n * @example\n * ```ts\n * // PREFERRED: client.waitForReceipt scopes decoding to the Omnibus address\n * const {claims} = await client.waitForReceipt(hash)\n * const secret = extractSecretFromClaims(claims, lock) // verified + scoped\n *\n * // low-level: only on logs ALREADY scoped to the Omnibus address\n * const scoped = receipt.logs.filter(l => l.address.toLowerCase() === omnibus.toLowerCase())\n * const someClaim = decodeClaimEvents(scoped)[0]?.secret // now public on-chain\n * ```\n */\nexport function decodeClaimEvents(logs: readonly Log[]): ClaimEvent[] {\n const parsed = parseEventLogs({abi: omnibusAbi, eventName: 'Claim', logs: logs as Log[], strict: true})\n return parsed.map(log => ({\n recipient: log.args.recipient,\n lock: log.args.lock,\n secret: log.args.secret,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n logIndex: log.logIndex,\n }))\n}\n\n/**\n * Extracts the revealed secret for a specific lock from a list of logs.\n *\n * Verifies the cryptographic relationship before returning: a `Claim` event\n * is accepted only when both its indexed `lock` equals the requested lock\n * AND `generateLock(event.secret)` hashes back to that lock. This rejects a\n * same-shaped fake `Claim(lock, wrongSecret)` whose `secret` does not\n * actually open the lock.\n *\n * Idempotent by construction: duplicate `Claim` logs for the same lock\n * carry the same secret (the lock is `keccak256(secret)`, so only one\n * preimage can ever satisfy it), so processing the same event twice\n * returns the same value.\n *\n * SECURITY: this does NOT filter by `log.address` — it inherits the\n * raw-log/address behavior of the decoders. Scope `logs` to the correct\n * Omnibus address first (prefer `client.waitForReceipt`,\n * `waitForOmnibusReceipt(..., {address})`, or the address-scoped\n * `getClaimEvents`/`watchClaimEvents`), or extract from an already-scoped\n * decoded {@link ClaimEvent} array via {@link extractSecretFromClaims}.\n *\n * @param logs - Raw logs to scan (receipt logs or a `getLogs` result).\n * @param lock - The lock whose secret to extract.\n * @returns The 32-byte secret, or `undefined` when no `Claim` for the lock\n * carries a secret that hashes to it.\n * @see IOmnibus.Claim, Omnibus._generateLock\n * @example\n * ```ts\n * // prefer scoped claims; only use raw logs you have already address-scoped\n * const secret = extractRevealedSecret(scopedChainBLogs, lock)\n * if (secret) await chainAClient.claim({secret, party: bobTerms, counterparty: aliceTerms})\n * ```\n */\nexport function extractRevealedSecret(logs: readonly Log[], lock: Hex32): Hex32 | undefined {\n return extractSecretFromClaims(decodeClaimEvents(logs), lock)\n}\n\n/**\n * Extracts the revealed secret for a lock from already-decoded `Claim`\n * events — the safe, address-scoped path (the events typically come from\n * {@link OmnibusReceipt.claims}, which `client.waitForReceipt` /\n * `waitForOmnibusReceipt(..., {address})` already filter by `log.address`).\n *\n * Like {@link extractRevealedSecret} it verifies `generateLock(secret)`\n * hashes back to the requested lock, so a fake `Claim(lock, wrongSecret)`\n * is ignored.\n *\n * @param claims - Decoded `Claim` events (e.g. `receipt.claims`).\n * @param lock - The lock whose secret to extract.\n * @returns The 32-byte secret, or `undefined` when none matches.\n * @see IOmnibus.Claim, Omnibus._generateLock\n * @example\n * ```ts\n * const receipt = await aliceOnB.waitForReceipt(claimHash)\n * const secret = extractSecretFromClaims(receipt.claims, lock)\n * ```\n */\nexport function extractSecretFromClaims(claims: readonly ClaimEvent[], lock: Hex32): Hex32 | undefined {\n const lockLower = lock.toLowerCase()\n for (const event of claims) {\n if (event.lock.toLowerCase() !== lockLower) continue\n // verify the secret actually opens the lock — rejects a same-shaped fake\n if (generateLock(event.secret).toLowerCase() !== lockLower) continue\n return event.secret\n }\n return undefined\n}\n\n/**\n * Decodes every `Reclaimed` event in a list of logs.\n *\n * IMPORTANT: one reclaim transaction can legitimately emit TWO `Reclaimed`\n * events — when the counterparty leg is local and the lock was `Committed`,\n * both legs return to their respective `reclaimRecipient` addresses in one\n * call. Always handle the array, never assume a single event.\n *\n * NOTE: a raw ABI decoder — it does NOT verify `log.address`. Scope `logs`\n * to the known Omnibus deployment first (prefer `client.waitForReceipt` /\n * `waitForOmnibusReceipt(..., {address})`, or {@link getReclaimedEvents}).\n *\n * @param logs - Pre-scoped logs to scan; non-`Reclaimed` logs are skipped.\n * @returns All decoded `Reclaimed` events, in log order.\n * @see IOmnibus.Reclaimed, Omnibus.reclaim\n */\nexport function decodeReclaimedEvents(logs: readonly Log[]): ReclaimedEvent[] {\n const parsed = parseEventLogs({abi: omnibusAbi, eventName: 'Reclaimed', logs: logs as Log[], strict: true})\n return parsed.map(log => ({\n caller: log.args.caller,\n lock: log.args.lock,\n recipient: log.args.recipient,\n blockNumber: log.blockNumber,\n transactionHash: log.transactionHash,\n logIndex: log.logIndex,\n }))\n}\n\n/** Common arguments for historical event queries. */\nexport interface EventQueryArgs {\n /** The Viem public client to query through. */\n readonly publicClient: PublicClient\n /** The Omnibus contract address — always filter by contract address. */\n readonly address: Address\n /** Restrict results to one lock (indexed topic) when provided. */\n readonly lock?: Hex32\n /** Inclusive starting block; supply a deployment block to bound the scan. */\n readonly fromBlock?: BlockNumber | BlockTag\n /** Inclusive ending block. */\n readonly toBlock?: BlockNumber | BlockTag\n}\n\n/**\n * Queries historical `Commitment` events via `publicClient.getLogs`.\n *\n * Reorg caveat: a log returned here reflects the chain at query time only.\n * Re-query (or compare block hashes) after your confirmation depth before\n * acting on it.\n *\n * @param args - See {@link EventQueryArgs}.\n * @returns Decoded events in chain order.\n * @example\n * ```ts\n * const history = await getCommitmentEvents({publicClient, address, lock})\n * ```\n */\nexport async function getCommitmentEvents(args: EventQueryArgs): Promise<CommitmentEvent[]> {\n const logs = await getOmnibusLogs(args, 'Commitment')\n return decodeCommitmentEvents(logs)\n}\n\n/**\n * Queries historical `Claim` events via `publicClient.getLogs`.\n *\n * @param args - See {@link EventQueryArgs}.\n * @returns Decoded events in chain order. Apply your confirmation policy\n * before treating a revealed secret's claim as settled.\n */\nexport async function getClaimEvents(args: EventQueryArgs): Promise<ClaimEvent[]> {\n const logs = await getOmnibusLogs(args, 'Claim')\n return decodeClaimEvents(logs)\n}\n\n/**\n * Queries historical `Reclaimed` events via `publicClient.getLogs`.\n *\n * @param args - See {@link EventQueryArgs}.\n * @returns Decoded events in chain order (possibly two per transaction).\n */\nexport async function getReclaimedEvents(args: EventQueryArgs): Promise<ReclaimedEvent[]> {\n const logs = await getOmnibusLogs(args, 'Reclaimed')\n return decodeReclaimedEvents(logs)\n}\n\n/** Shared `getLogs` plumbing: contract-address filter + optional lock topic. */\nasync function getOmnibusLogs(\n args: EventQueryArgs,\n eventName: 'Commitment' | 'Claim' | 'Reclaimed',\n): Promise<Log[]> {\n const event = omnibusAbi.find(\n (entry): entry is Extract<(typeof omnibusAbi)[number], {type: 'event'}> =>\n entry.type === 'event' && entry.name === eventName,\n )\n /* v8 ignore next 3 -- the generated ABI always contains all three events */\n if (event === undefined) {\n throw new QuipSwapError({code: 'EVENT_NOT_FOUND', message: `Event ${eventName} missing from generated ABI`})\n }\n return (await args.publicClient.getLogs({\n address: args.address,\n event,\n ...(args.lock !== undefined ? {args: {lock: args.lock}} : {}),\n ...(args.fromBlock !== undefined ? {fromBlock: args.fromBlock} : {}),\n ...(args.toBlock !== undefined ? {toBlock: args.toBlock} : {}),\n } as Parameters<PublicClient['getLogs']>[0])) as Log[]\n}\n\n/**\n * Watches for live `Claim` events on a lock — the cross-chain coordinator's\n * tool for learning the revealed secret promptly.\n *\n * This is an OPTIONAL convenience; the SDK never requires a permanently\n * running watcher. The callback may fire more than once for the same claim\n * (duplicates, reorg re-emission) — {@link extractRevealedSecret}'s\n * idempotence makes acting on duplicates safe.\n *\n * @param args - Query args plus the callback.\n * @param args.onClaim - Invoked with each decoded `Claim` event observed.\n * @returns The unwatch function from Viem; call it to stop watching.\n * @example\n * ```ts\n * const stop = watchClaimEvents({publicClient, address, lock, onClaim: e => use(e.secret)})\n * ```\n */\nexport function watchClaimEvents(\n args: Omit<EventQueryArgs, 'fromBlock' | 'toBlock'> & {readonly onClaim: (event: ClaimEvent) => void},\n): () => void {\n return args.publicClient.watchContractEvent({\n address: args.address,\n abi: omnibusAbi,\n eventName: 'Claim',\n ...(args.lock !== undefined ? {args: {lock: args.lock}} : {}),\n onLogs: logs => {\n for (const event of decodeClaimEvents(logs as Log[])) args.onClaim(event)\n },\n })\n}\n","/**\n * Receipt helpers.\n *\n * A returned transaction hash is NOT confirmation: the transaction may\n * still be pending, may revert, or may be dropped/replaced. These helpers\n * wait for a receipt, check `status`, and decode the relevant Omnibus\n * events into typed results.\n *\n * Address-scoped decoding: when `options.address` is supplied, only logs\n * emitted by that address are decoded — preventing another contract in the\n * same transaction from emitting an Omnibus-shaped `Commitment`/`Claim`/\n * `Reclaimed` event that the receipt helper would otherwise decode as\n * genuine. Prefer the client-bound {@link OmnibusClient.waitForReceipt},\n * which passes the client's Omnibus address automatically. Omitting\n * `address` keeps the legacy raw behavior (decode every matching log) for\n * backward compatibility, but is NOT recommended for security-sensitive\n * flows.\n *\n * Submission ({@link OmnibusClient.commit} et al.) and receipt waiting are\n * deliberately separate so the application chooses its own confirmation\n * count, timeout, retry, and finality policy per call.\n */\nimport type {Address, Hash, Log, PublicClient, TransactionReceipt} from 'viem'\nimport {QuipSwapError, wrapContractError} from './errors.js'\nimport {decodeClaimEvents, decodeCommitmentEvents, decodeReclaimedEvents} from './events.js'\nimport type {ClaimEvent, CommitmentEvent, ReclaimedEvent} from './events.js'\n\n/** Options forwarded to `publicClient.waitForTransactionReceipt`, plus address scoping. */\nexport interface WaitOptions {\n /**\n * The expected Omnibus contract address. When set, only logs emitted by\n * this address are decoded into `commitments`/`claims`/`reclaims` — the\n * defense against same-signature events from other contracts in the same\n * transaction. Omitting it decodes every matching log (legacy behavior;\n * not recommended). {@link OmnibusClient.waitForReceipt} fills this in.\n */\n readonly address?: Address\n /** Number of confirmations to wait for (default: the client's default, 1). */\n readonly confirmations?: number\n /** Milliseconds to wait before giving up. */\n readonly timeout?: number\n}\n\n/**\n * Returns only the logs emitted by `address` (case-insensitive). When\n * `address` is undefined, returns `logs` unchanged (legacy raw behavior).\n */\nfunction filterLogsByAddress(logs: readonly Log[], address?: Address): readonly Log[] {\n if (address === undefined) return logs\n const expected = address.toLowerCase()\n return logs.filter(log => log.address.toLowerCase() === expected)\n}\n\n/** A successful, decoded Omnibus transaction result. */\nexport interface OmnibusReceipt {\n /** The transaction hash that was waited on. */\n readonly transactionHash: Hash\n /** The full Viem receipt (status is guaranteed `'success'`). */\n readonly receipt: TransactionReceipt\n /** Decoded `Commitment` events emitted by the transaction (0 or 1). */\n readonly commitments: readonly CommitmentEvent[]\n /** Decoded `Claim` events emitted by the transaction (0 or 1). */\n readonly claims: readonly ClaimEvent[]\n /** Decoded `Reclaimed` events (0, 1, or 2 — dual-leg reclaims emit two). */\n readonly reclaims: readonly ReclaimedEvent[]\n}\n\n/**\n * Waits for a transaction receipt, verifies it succeeded, and decodes all\n * Omnibus events it emitted.\n *\n * @param publicClient - The Viem public client to poll through.\n * @param hash - The transaction hash returned by a write method.\n * @param options - `address` (strongly recommended — scopes decoding to the\n * Omnibus deployment; see {@link WaitOptions}), plus confirmation count\n * and timeout. Pick confirmations per your finality policy — one\n * confirmation on a reorg-prone chain is weak evidence.\n * @returns The typed {@link OmnibusReceipt}; `commitments`/`claims`/\n * `reclaims` contain only events from `options.address` when supplied.\n * @throws QuipSwapError `TRANSACTION_REVERTED` when the receipt status is\n * `'reverted'`; `CONTRACT_REVERT` (with `cause`) when waiting itself\n * fails (timeout, replacement, RPC error).\n * @example\n * ```ts\n * // prefer client.waitForReceipt; standalone form must pass the address:\n * const hash = await client.commit({lock, party, counterparty})\n * const {commitments} = await waitForOmnibusReceipt(publicClient, hash, {\n * address: omnibusAddress,\n * confirmations: 3,\n * })\n * console.log(commitments[0]?.lock)\n * ```\n */\nexport async function waitForOmnibusReceipt(\n publicClient: PublicClient,\n hash: Hash,\n options: WaitOptions = {},\n): Promise<OmnibusReceipt> {\n let receipt: TransactionReceipt\n try {\n receipt = await publicClient.waitForTransactionReceipt({\n hash,\n ...(options.confirmations !== undefined ? {confirmations: options.confirmations} : {}),\n ...(options.timeout !== undefined ? {timeout: options.timeout} : {}),\n })\n } catch (error) {\n throw wrapContractError(error, `Waiting for receipt of ${hash}`)\n }\n\n if (receipt.status !== 'success') {\n throw new QuipSwapError({\n code: 'TRANSACTION_REVERTED',\n message: `Transaction ${hash} was mined but reverted`,\n details: {receipt},\n })\n }\n\n // scope to the expected Omnibus address (when given) BEFORE decoding, so a\n // same-signature event from another contract in this tx is never decoded\n // as a genuine Omnibus event\n const logs = filterLogsByAddress(receipt.logs, options.address)\n\n return {\n transactionHash: hash,\n receipt,\n commitments: decodeCommitmentEvents(logs),\n claims: decodeClaimEvents(logs),\n reclaims: decodeReclaimedEvents(logs),\n }\n}\n","/**\n * Approval inspection and planning for non-native assets.\n *\n * The committer is `msg.sender` of the commit transaction — in production a\n * QuipWallet CONTRACT (never its owner's EOA; see the QuipWallet gate on\n * `Omnibus.commit`). Assets must belong to that wallet and approvals must\n * be issued BY that wallet, so every check here asks: \"can the Omnibus\n * contract pull this asset from the committing wallet?\"\n *\n * Fee-on-transfer caveat: `Omnibus.commit` reconciles received balances\n * (`TermsLib.transferAssetsNoNative`). If an ERC-20/ERC-1155 delivers less\n * than the declared amount (fee-on-transfer, deflationary), commit reverts\n * with `UnexpectedAmountReceived` EVEN IF the approval plan is fully\n * satisfied. A satisfied plan is necessary, not sufficient.\n */\nimport type {Address, PublicClient, WalletClient} from 'viem'\nimport {QuipSwapError, wrapContractError} from './errors.js'\nimport {AssetType} from './types.js'\nimport type {Terms} from './types.js'\n\n/** Minimal ERC-20 surface used for approval planning. */\nconst erc20Abi = [\n {\n type: 'function',\n name: 'allowance',\n stateMutability: 'view',\n inputs: [\n {name: 'owner', type: 'address'},\n {name: 'spender', type: 'address'},\n ],\n outputs: [{name: '', type: 'uint256'}],\n },\n {\n type: 'function',\n name: 'approve',\n stateMutability: 'nonpayable',\n inputs: [\n {name: 'spender', type: 'address'},\n {name: 'amount', type: 'uint256'},\n ],\n outputs: [{name: '', type: 'bool'}],\n },\n] as const\n\n/** Minimal ERC-721 surface used for approval planning. */\nconst erc721Abi = [\n {\n type: 'function',\n name: 'getApproved',\n stateMutability: 'view',\n inputs: [{name: 'tokenId', type: 'uint256'}],\n outputs: [{name: '', type: 'address'}],\n },\n {\n type: 'function',\n name: 'isApprovedForAll',\n stateMutability: 'view',\n inputs: [\n {name: 'owner', type: 'address'},\n {name: 'operator', type: 'address'},\n ],\n outputs: [{name: '', type: 'bool'}],\n },\n {\n type: 'function',\n name: 'approve',\n stateMutability: 'nonpayable',\n inputs: [\n {name: 'to', type: 'address'},\n {name: 'tokenId', type: 'uint256'},\n ],\n outputs: [],\n },\n {\n type: 'function',\n name: 'setApprovalForAll',\n stateMutability: 'nonpayable',\n inputs: [\n {name: 'operator', type: 'address'},\n {name: 'approved', type: 'bool'},\n ],\n outputs: [],\n },\n] as const\n\n/** Minimal ERC-1155 surface used for approval planning. */\nconst erc1155Abi = [\n {\n type: 'function',\n name: 'isApprovedForAll',\n stateMutability: 'view',\n inputs: [\n {name: 'account', type: 'address'},\n {name: 'operator', type: 'address'},\n ],\n outputs: [{name: '', type: 'bool'}],\n },\n {\n type: 'function',\n name: 'setApprovalForAll',\n stateMutability: 'nonpayable',\n inputs: [\n {name: 'operator', type: 'address'},\n {name: 'approved', type: 'bool'},\n ],\n outputs: [],\n },\n] as const\n\n/** ERC-20 approval status for one token (amounts aggregated across asset entries). */\nexport interface Erc20ApprovalItem {\n readonly kind: 'erc20'\n /** The token contract. */\n readonly token: Address\n /** Sum of every asset entry for this token in the terms. */\n readonly requiredAllowance: bigint\n /** `allowance(committer, omnibus)` at plan time. */\n readonly currentAllowance: bigint\n /** `currentAllowance >= requiredAllowance`. */\n readonly satisfied: boolean\n}\n\n/** ERC-721 approval status for one specific token id. */\nexport interface Erc721ApprovalItem {\n readonly kind: 'erc721'\n readonly token: Address\n readonly tokenId: bigint\n /** `getApproved(tokenId) == omnibus`. */\n readonly tokenApproved: boolean\n /** `isApprovedForAll(committer, omnibus)`. */\n readonly operatorApproved: boolean\n /** Either single-token or operator approval suffices. */\n readonly satisfied: boolean\n}\n\n/** ERC-1155 approval status for one token contract (operator approval covers all ids). */\nexport interface Erc1155ApprovalItem {\n readonly kind: 'erc1155'\n readonly token: Address\n /** `isApprovedForAll(committer, omnibus)`. */\n readonly operatorApproved: boolean\n readonly satisfied: boolean\n}\n\n/** One entry of an {@link ApprovalPlan}. */\nexport type ApprovalItem = Erc20ApprovalItem | Erc721ApprovalItem | Erc1155ApprovalItem\n\n/** The result of {@link planApprovals}. */\nexport interface ApprovalPlan {\n /** The wallet whose assets will be pulled (the commit sender). */\n readonly committer: Address\n /** The Omnibus contract that must be able to pull them. */\n readonly omnibusAddress: Address\n /** One item per (token / token+id) requiring approval; empty if all-native. */\n readonly items: readonly ApprovalItem[]\n /** True iff every item is satisfied. */\n readonly satisfied: boolean\n}\n\n/** Arguments for {@link planApprovals}. */\nexport interface PlanApprovalsArgs {\n /** Public client on the chain where `terms.chainId` points. */\n readonly publicClient: PublicClient\n /** The deployed Omnibus address (the spender/operator to check for). */\n readonly omnibusAddress: Address\n /**\n * The committing wallet — the QuipWallet CONTRACT address that will send\n * the commit transaction, NOT its owner's EOA.\n */\n readonly committer: Address\n /** The side's terms whose assets will be escrowed. */\n readonly terms: Terms\n}\n\n/**\n * Inspects on-chain approvals for every non-native asset in a side's terms\n * and returns a typed plan describing what is missing.\n *\n * Checks performed (mirroring what `TermsLib.transferAssetsNoNative` will\n * need at commit time):\n * - ERC-20: `allowance(committer, omnibus) >= sum(required amounts)` —\n * multiple entries of the same token are AGGREGATED.\n * - ERC-721: `getApproved(tokenId) == omnibus` OR\n * `isApprovedForAll(committer, omnibus)`.\n * - ERC-1155: `isApprovedForAll(committer, omnibus)`.\n *\n * Native assets need no approval (they ride along as `msg.value`).\n *\n * Note: nonstandard ERC-20s exist (missing return values, fee-on-transfer).\n * A satisfied plan does not guarantee commit success for fee-on-transfer\n * tokens — the contract reverts with `UnexpectedAmountReceived` when less\n * than the declared amount arrives.\n *\n * @param args - See {@link PlanApprovalsArgs}.\n * @returns The typed {@link ApprovalPlan}.\n * @throws QuipSwapError `CONTRACT_REVERT` when an allowance/approval read\n * itself reverts (e.g. a non-token target address).\n * @see TermsLib.transferAssetsNoNative\n * @example\n * ```ts\n * const plan = await planApprovals({publicClient, omnibusAddress, committer: quipWallet, terms})\n * for (const item of plan.items.filter(i => !i.satisfied)) {\n * const hash = await submitApproval({publicClient, walletClient, omnibusAddress, item, erc20Mode: 'exact'})\n * }\n * ```\n */\nexport async function planApprovals(args: PlanApprovalsArgs): Promise<ApprovalPlan> {\n const {publicClient, omnibusAddress, committer, terms} = args\n\n // aggregate ERC-20 requirements per token: the contract pulls each asset\n // entry separately, so the allowance must cover the SUM\n const erc20Required = new Map<string, {token: Address; amount: bigint}>()\n // one ERC-721 check per (token, id); one ERC-1155 check per token\n const erc721Items: {token: Address; tokenId: bigint}[] = []\n const erc1155Tokens = new Map<string, Address>()\n\n for (const asset of terms.assets) {\n if (asset.assetType === AssetType.Native) continue\n if (asset.assetType === AssetType.ERC20) {\n const key = asset.target.toLowerCase()\n const existing = erc20Required.get(key)\n erc20Required.set(key, {token: asset.target, amount: (existing?.amount ?? 0n) + asset.amount})\n } else if (asset.assetType === AssetType.ERC721) {\n erc721Items.push({token: asset.target, tokenId: asset.id})\n } else {\n erc1155Tokens.set(asset.target.toLowerCase(), asset.target)\n }\n }\n\n const items: ApprovalItem[] = []\n try {\n for (const {token, amount} of erc20Required.values()) {\n const currentAllowance = await publicClient.readContract({\n address: token,\n abi: erc20Abi,\n functionName: 'allowance',\n args: [committer, omnibusAddress],\n })\n items.push({\n kind: 'erc20',\n token,\n requiredAllowance: amount,\n currentAllowance,\n satisfied: currentAllowance >= amount,\n })\n }\n for (const {token, tokenId} of erc721Items) {\n const [approvedAddress, operatorApproved] = await Promise.all([\n publicClient.readContract({address: token, abi: erc721Abi, functionName: 'getApproved', args: [tokenId]}),\n publicClient.readContract({\n address: token,\n abi: erc721Abi,\n functionName: 'isApprovedForAll',\n args: [committer, omnibusAddress],\n }),\n ])\n const tokenApproved = approvedAddress.toLowerCase() === omnibusAddress.toLowerCase()\n items.push({\n kind: 'erc721',\n token,\n tokenId,\n tokenApproved,\n operatorApproved,\n satisfied: tokenApproved || operatorApproved,\n })\n }\n for (const token of erc1155Tokens.values()) {\n const operatorApproved = await publicClient.readContract({\n address: token,\n abi: erc1155Abi,\n functionName: 'isApprovedForAll',\n args: [committer, omnibusAddress],\n })\n items.push({kind: 'erc1155', token, operatorApproved, satisfied: operatorApproved})\n }\n } catch (error) {\n throw wrapContractError(error, 'Reading token approvals')\n }\n\n return {committer, omnibusAddress, items, satisfied: items.every(item => item.satisfied)}\n}\n\n/**\n * ERC-20 approval sizing. The choice is explicit because it is a real\n * trade-off the application must own:\n * - `'exact'` approves only the required amount (safer: a compromised or\n * buggy spender can take at most the swap amount; costs one approval per\n * swap).\n * - `'unlimited'` approves `type(uint256).max` (convenient: one approval\n * forever; risk: the spender can pull ANY future balance).\n *\n * The SDK never defaults to unlimited.\n */\nexport type Erc20ApprovalMode = 'exact' | 'unlimited'\n\n/** Arguments for {@link submitApproval}. */\nexport interface SubmitApprovalArgs {\n /** Public client used for simulation. */\n readonly publicClient: PublicClient\n /** Wallet client of the COMMITTER (the wallet that owns the assets). */\n readonly walletClient: WalletClient\n /** The Omnibus address to approve as spender/operator. */\n readonly omnibusAddress: Address\n /** The unsatisfied plan item to fix. */\n readonly item: ApprovalItem\n /** REQUIRED for ERC-20 items: exact or unlimited (see {@link Erc20ApprovalMode}). */\n readonly erc20Mode?: Erc20ApprovalMode\n /**\n * For ERC-721 items: `'token'` approves only the specific token id\n * (default — least privilege); `'operator'` grants `setApprovalForAll`.\n */\n readonly erc721Mode?: 'token' | 'operator'\n}\n\nconst MAX_UINT256 = (1n << 256n) - 1n\n\n/**\n * Simulates and submits the approval transaction that satisfies one\n * unsatisfied {@link ApprovalItem}.\n *\n * Always simulates before writing (`simulateContract` → `writeContract`)\n * so approval failures surface as decoded errors, not burned gas. Nothing\n * is auto-approved: the application explicitly invokes this per item.\n *\n * @param args - See {@link SubmitApprovalArgs}.\n * @returns The transaction hash. Wait for its receipt before re-planning —\n * a hash alone does not mean the approval landed.\n * @throws QuipSwapError `MISSING_ACCOUNT` when the wallet client has no\n * account; `INVALID_RANGE` (mode missing for ERC-20); `CONTRACT_REVERT`\n * when simulation/submission fails.\n * @example\n * ```ts\n * const hash = await submitApproval({\n * publicClient, walletClient, omnibusAddress,\n * item: unsatisfiedItem, erc20Mode: 'exact',\n * })\n * await publicClient.waitForTransactionReceipt({hash})\n * ```\n */\nexport async function submitApproval(args: SubmitApprovalArgs): Promise<`0x${string}`> {\n const {publicClient, walletClient, omnibusAddress, item} = args\n const account = walletClient.account\n if (account === undefined) {\n throw new QuipSwapError({\n code: 'MISSING_ACCOUNT',\n message: 'The wallet client must have an account to submit an approval',\n })\n }\n\n try {\n if (item.kind === 'erc20') {\n if (args.erc20Mode === undefined) {\n throw new QuipSwapError({\n code: 'INVALID_RANGE',\n message:\n \"ERC-20 approvals require an explicit erc20Mode ('exact' or 'unlimited'); the SDK never defaults to unlimited\",\n })\n }\n const amount = args.erc20Mode === 'exact' ? item.requiredAllowance : MAX_UINT256\n const {request} = await publicClient.simulateContract({\n address: item.token,\n abi: erc20Abi,\n functionName: 'approve',\n args: [omnibusAddress, amount],\n account,\n })\n return await walletClient.writeContract(request)\n }\n\n if (item.kind === 'erc721') {\n if ((args.erc721Mode ?? 'token') === 'token') {\n const {request} = await publicClient.simulateContract({\n address: item.token,\n abi: erc721Abi,\n functionName: 'approve',\n args: [omnibusAddress, item.tokenId],\n account,\n })\n return await walletClient.writeContract(request)\n }\n const {request} = await publicClient.simulateContract({\n address: item.token,\n abi: erc721Abi,\n functionName: 'setApprovalForAll',\n args: [omnibusAddress, true],\n account,\n })\n return await walletClient.writeContract(request)\n }\n\n // erc1155: operator approval is the only mechanism the standard offers\n const {request} = await publicClient.simulateContract({\n address: item.token,\n abi: erc1155Abi,\n functionName: 'setApprovalForAll',\n args: [omnibusAddress, true],\n account,\n })\n return await walletClient.writeContract(request)\n } catch (error) {\n if (error instanceof QuipSwapError) throw error\n throw wrapContractError(error, `Approving ${item.kind} ${item.token}`)\n }\n}\n","/**\n * Schedule buffer defaults and the shared gap-size check.\n *\n * A swap's six lifecycle timestamps must do two distinct things:\n * - **ORDER** — strictly interleave (proposer first at every stage). The\n * contract enforces this on every commit (`TermsLib.validateTermPairing`),\n * and the SDK mirrors it in `validateTermPairing`.\n * - **SIZE** — leave enough wall-clock time between adjacent stages for each\n * party to act and react. The contract does NOT check gap size, so the SDK\n * is the ONLY place a dangerously tight window can be caught.\n *\n * This module owns the SIZE check. The gaps protect the action/reaction\n * windows against chain finality, reorg risk, RPC outages, network\n * congestion, and relayer latency — most critically the taker's post-reveal\n * reaction buffer (`proposer.reclaimRelease - proposer.claimDeadline`).\n *\n * The {@link DEFAULT_BUFFERS} presets are conservative STARTING POINTS keyed\n * to a chain's finality profile, not authoritative values — tune them to the\n * chains you actually operate on.\n */\nimport {QuipSwapError} from './errors.js'\nimport type {Terms} from './types.js'\n\n/**\n * Suggested minimum-buffer presets (seconds) by chain-finality profile.\n * Starting points to tune to your chains, NOT authoritative values.\n *\n * - `fastL2` (~5 min): fast-finality L2s with low reorg risk.\n * - `standard` (~30 min): general-purpose default.\n * - `conservativeL1` (~1 hr): congested or deep-reorg-risk L1s.\n */\nexport const DEFAULT_BUFFERS = {\n /** ~5 min — fast-finality L2s. */\n fastL2: 300n,\n /** ~30 min — general default. */\n standard: 1800n,\n /** ~1 hr — congested / deep-reorg-risk L1s. */\n conservativeL1: 3600n,\n} as const\n\n/**\n * Default minimum buffer applied to CROSS-CHAIN schedules when the caller\n * supplies none. A conservative starting point ({@link DEFAULT_BUFFERS}.standard,\n * ~30 min) — tune to your chains; overriding BELOW it can expose users to\n * missed windows and lost funds under congestion/reorgs.\n */\nexport const DEFAULT_CROSS_CHAIN_BUFFER_SECONDS = DEFAULT_BUFFERS.standard\n\n/**\n * Default minimum buffer applied to SAME-CHAIN schedules when the caller\n * supplies none. Same conservative starting point as the cross-chain default\n * ({@link DEFAULT_BUFFERS}.standard, ~30 min) but a SEPARATE constant so the\n * two modes can be tuned independently later without touching call sites.\n */\nexport const DEFAULT_SAME_CHAIN_BUFFER_SECONDS = DEFAULT_BUFFERS.standard\n\n/**\n * Validates that every adjacent gap in a pairing's interleaved six-timestamp\n * schedule is at least `minimumBufferSeconds`. This is the gap-SIZE check\n * (distinct from interleaving ORDER, validated by `validateTermPairing`);\n * the contract never checks size, so this is the only enforcement point.\n *\n * The schedule order checked is: `proposer.commitmentDeadline`,\n * `taker.commitmentDeadline`, `proposer.claimDeadline`, `taker.claimDeadline`,\n * `proposer.reclaimRelease`, `taker.reclaimRelease`. Callers must pass terms\n * whose roles are already normalized (proposer = smaller `commitmentDeadline`).\n *\n * @param proposerTerms - The proposer's leg (smaller `commitmentDeadline`).\n * @param takerTerms - The taker's leg.\n * @param minimumBufferSeconds - The minimum acceptable gap (seconds) between\n * every adjacent pair of schedule timestamps.\n * @returns `{minimumGapSeconds}` — the smallest adjacent gap in the schedule.\n * @throws QuipSwapError `INSUFFICIENT_BUFFER` when any adjacent gap is below\n * `minimumBufferSeconds` (details carry the offending pair and the gap).\n * @see TermsLib.validateTermPairing (the ORDER check this complements)\n * @example\n * ```ts\n * const {minimumGapSeconds} = checkScheduleBuffers(proposer, taker, 1800n)\n * ```\n */\nexport function checkScheduleBuffers(\n proposerTerms: Terms,\n takerTerms: Terms,\n minimumBufferSeconds: bigint,\n): {minimumGapSeconds: bigint} {\n // the six interleaved timestamps, in schedule order\n const sequence: readonly [string, bigint][] = [\n ['proposer.commitmentDeadline', proposerTerms.commitmentDeadline],\n ['taker.commitmentDeadline', takerTerms.commitmentDeadline],\n ['proposer.claimDeadline', proposerTerms.claimDeadline],\n ['taker.claimDeadline', takerTerms.claimDeadline],\n ['proposer.reclaimRelease', proposerTerms.reclaimRelease],\n ['taker.reclaimRelease', takerTerms.reclaimRelease],\n ]\n\n let minimumGapSeconds: bigint | undefined\n for (let i = 1; i < sequence.length; i++) {\n const [prevName, prev] = sequence[i - 1] as [string, bigint]\n const [nextName, next] = sequence[i] as [string, bigint]\n const gap = next - prev\n if (gap < minimumBufferSeconds) {\n throw new QuipSwapError({\n code: 'INSUFFICIENT_BUFFER',\n message:\n `Gap between ${prevName} (${prev}) and ${nextName} (${next}) is ${gap}s, below the required ` +\n `minimum of ${minimumBufferSeconds}s. Every adjacent gap — especially the taker's post-reveal ` +\n 'reaction buffer (proposer.reclaimRelease - proposer.claimDeadline) — must cover finality, reorg ' +\n 'risk, RPC outages, congestion, and relayer latency',\n details: {prevName, prev, nextName, next, gap, minimumBufferSeconds},\n })\n }\n if (minimumGapSeconds === undefined || gap < minimumGapSeconds) minimumGapSeconds = gap\n }\n\n return {minimumGapSeconds: minimumGapSeconds ?? 0n}\n}\n","/**\n * Same-chain swap workflow helpers.\n *\n * Roles: the PROPOSER is the side with the earlier schedule (smaller\n * `commitmentDeadline`) and commits first; the TAKER commits second. The\n * SECRET HOLDER must be the proposer: only the proposer can claim in the\n * first claim window, so giving the secret to the taker would invert the\n * protocol's risk model.\n *\n * The happy path (all windows half-open `[lower, upper)`):\n *\n * ```text\n * 1. Build both sides' terms with a strictly interleaved schedule.\n * 2. The proposer generates the secret and lock.\n * 3. Proposer commits in [0, proposer.commitmentDeadline) -> lock Free\n * 4. WAIT: the taker's window opens only at proposer.commitmentDeadline.\n * 5. Taker commits in [proposer.commit, taker.commit) -> lock Committed\n * (the taker posts the OTHER side; re-posting reverts TermsAlreadyPosted)\n * 6. Anyone with the secret claims in [taker.commit, proposer.claim)\n * — ONE claim settles BOTH legs -> lock Spent\n * ```\n *\n * Unhappy paths: reclaim from `Free` (only the proposer committed) is valid\n * once the proposer's `reclaimRelease` passes; reclaim from `Committed`\n * returns BOTH legs in one transaction when the counterparty leg is local.\n *\n * These helpers never hide wallet signing, never auto-approve, and never\n * submit transactions on their own — every transaction is an explicit\n * application call. Status inspection combines actual on-chain state\n * (`lockState`, `posted`, `termsHash`) with the current window.\n *\n * Schedule validation — including gap-SIZE buffers — happens in\n * {@link planSameChainSwap}. The contract checks interleaving ORDER but\n * never gap size, so this is the only place a dangerously tight same-chain\n * window is caught. There is nothing forcing it (unlike the cross-chain\n * flow's reaction handoff), so BOTH parties should run `planSameChainSwap`\n * on their own terms before acting — it is per-party self-protection.\n */\nimport {DEFAULT_SAME_CHAIN_BUFFER_SECONDS, checkScheduleBuffers} from '../buffers.js'\nimport {digestTerms, digestTermsCanonically} from '../hashing.js'\nimport {proposedBy, validateTermPairing, validateTerms} from '../terms.js'\nimport {LockState} from '../types.js'\nimport type {Hex32, Terms} from '../types.js'\nimport {\n isWithinWindow,\n proposerClaimWindow,\n proposerCommitWindow,\n reclaimWindow,\n takerClaimWindow,\n takerCommitWindow,\n} from '../windows.js'\nimport type {TimeWindow} from '../windows.js'\nimport type {OmnibusClient} from '../client.js'\nimport {QuipSwapError} from '../errors.js'\n\n/**\n * A validated same-chain swap plan with both sides normalized into\n * proposer/taker roles and all five action windows precomputed.\n */\nexport interface SameChainSwapPlan {\n /** The proposer's terms (earlier schedule; commits first; holds the secret). */\n readonly proposerTerms: Terms\n /** The taker's terms (later schedule; commits second). */\n readonly takerTerms: Terms\n /** The canonical trade digest stored in `termsHash[lock]` on commit. */\n readonly canonicalDigest: Hex32\n /** The proposer side's single-terms digest (its `posted` key). */\n readonly proposerDigest: Hex32\n /** The taker side's single-terms digest (its `posted` key). */\n readonly takerDigest: Hex32\n /** `[0, proposer.commitmentDeadline)`. */\n readonly proposerCommitWindow: TimeWindow\n /** `[proposer.commitmentDeadline, taker.commitmentDeadline)`. */\n readonly takerCommitWindow: TimeWindow\n /** `[taker.commitmentDeadline, proposer.claimDeadline)` — one claim settles both legs. */\n readonly claimWindow: TimeWindow\n /** `[proposer.reclaimRelease, +inf)` for the proposer's leg. */\n readonly proposerReclaimWindow: TimeWindow\n /** `[taker.reclaimRelease, +inf)` for the taker's leg. */\n readonly takerReclaimWindow: TimeWindow\n}\n\n/**\n * Validates a same-chain pairing and assembles a {@link SameChainSwapPlan}.\n *\n * Validates structure, interleaving (ORDER), that both sides name the SAME\n * chain, AND the gap-SIZE buffers between adjacent schedule timestamps.\n * Accepts the two sides in either order; roles are derived from the\n * schedule (`proposedBy`). Use {@link validateCrossChainSchedule} for\n * cross-chain swaps.\n *\n * The CONTRACT does not check buffer sizes — it only enforces interleaving\n * order — so this is the ONLY place a dangerously tight same-chain window is\n * caught. And nothing forces it (unlike the cross-chain reaction handoff):\n * BOTH parties should call `planSameChainSwap` on their own terms before\n * acting. It is per-party self-protection, not a shared gate.\n *\n * @param a - One side's terms.\n * @param b - The other side's terms.\n * @param opts - Optional. `minimumBufferSeconds` sets the minimum acceptable\n * gap (seconds) between every adjacent pair of schedule timestamps;\n * defaults to {@link DEFAULT_SAME_CHAIN_BUFFER_SECONDS} when omitted.\n * Overriding BELOW the default may let dangerously tight windows through —\n * only do so if you understand your chain's finality.\n * @returns The normalized plan with windows and digests precomputed.\n * @throws QuipSwapError - structural codes from {@link validateTerms};\n * `DISORDERED_DEADLINES` for a non-interleaved schedule;\n * `CHAIN_ID_MISMATCH` when the sides name different chains;\n * `INSUFFICIENT_BUFFER` when any adjacent gap is below the minimum.\n * @see TermsLib.validateTermPairing, checkScheduleBuffers\n * @example\n * ```ts\n * const plan = planSameChainSwap(aliceTerms, bobTerms) // default buffer\n * // proposer commits first:\n * await client.commit({lock, party: plan.proposerTerms, counterparty: plan.takerTerms})\n * ```\n */\nexport function planSameChainSwap(\n a: Terms,\n b: Terms,\n opts?: {readonly minimumBufferSeconds?: bigint},\n): SameChainSwapPlan {\n validateTerms(a)\n validateTerms(b)\n validateTermPairing(a, b)\n if (a.chainId !== b.chainId) {\n throw new QuipSwapError({\n code: 'CHAIN_ID_MISMATCH',\n message: `Same-chain plan requires both sides on one chain; got ${a.chainId} and ${b.chainId}`,\n details: {aChainId: a.chainId, bChainId: b.chainId},\n })\n }\n const [proposerTerms, takerTerms] = proposedBy(a, b) === 'party' ? [a, b] : [b, a]\n // gap-SIZE buffer check (the contract never does this) — the new protection\n checkScheduleBuffers(proposerTerms, takerTerms, opts?.minimumBufferSeconds ?? DEFAULT_SAME_CHAIN_BUFFER_SECONDS)\n return {\n proposerTerms,\n takerTerms,\n canonicalDigest: digestTermsCanonically(proposerTerms, takerTerms),\n proposerDigest: digestTerms(proposerTerms),\n takerDigest: digestTerms(takerTerms),\n proposerCommitWindow: proposerCommitWindow(proposerTerms),\n takerCommitWindow: takerCommitWindow(takerTerms, proposerTerms),\n claimWindow: proposerClaimWindow(proposerTerms, takerTerms),\n proposerReclaimWindow: reclaimWindow(proposerTerms),\n takerReclaimWindow: reclaimWindow(takerTerms),\n }\n}\n\n/**\n * Application-level swap status — deliberately SEPARATE from the Solidity\n * {@link LockState}: the chain knows four states, but an application also\n * needs to know which window is open and which side has posted.\n */\nexport type SameChainSwapStatus =\n /** Nothing committed; the proposer's commit window is open. */\n | 'awaiting-proposer-commit'\n /**\n * Nothing committed and the proposer's window has closed. The swap can\n * no longer COMPLETE (the proposer can never commit, so the lock can\n * never reach Committed) — but the contract will still accept a\n * taker-first commit in `[proposer.commitmentDeadline,\n * taker.commitmentDeadline)`: `Omnibus.commit` checks only the window,\n * not that the proposer actually committed (verifying the counterparty's\n * commitment is the committer's duty, per the contract comments). Such a\n * commit is pointless and self-harming — it moves the lock Unused→Free\n * and strands the taker's assets until `taker.reclaimRelease` (reclaim\n * from Free). Treat this status as terminal and do NOT commit into it.\n */\n | 'proposer-commit-expired'\n /** Proposer committed (lock Free); the taker's window has not opened yet. */\n | 'awaiting-taker-window'\n /** Proposer committed (lock Free); the taker's window is open. */\n | 'awaiting-taker-commit'\n /** Only the proposer committed and the taker's window closed; awaiting the proposer's reclaimRelease. */\n | 'half-committed-expired'\n /** Both committed before the taker's commitment deadline; the proposer-claim window has not opened yet. */\n | 'awaiting-claim-window'\n /** Both committed; the claim window is open — the secret holder should claim. */\n | 'claimable'\n /** Both committed; the proposer-claim window closed (taker-claim window may run until proposer.reclaimRelease). */\n | 'late-claimable'\n /** Both committed; no claim landed and a leg's reclaim window is open. */\n | 'reclaimable'\n /** Lock Free and the proposer's reclaim window is open (reclaim-from-Free). */\n | 'reclaimable-from-free'\n /** Terminal: the lock is Spent (claimed or reclaimed). */\n | 'settled'\n\n/** The full status report returned by {@link getSameChainSwapStatus}. */\nexport interface SameChainSwapStatusReport {\n /** The application-level status (see {@link SameChainSwapStatus}). */\n readonly status: SameChainSwapStatus\n /** The raw on-chain {@link LockState} the status was derived from. */\n readonly lockState: LockState\n /** Whether the proposer's side is posted on-chain. */\n readonly proposerPosted: boolean\n /** Whether the taker's side is posted on-chain. */\n readonly takerPosted: boolean\n /** The chain timestamp the report was computed at. */\n readonly timestamp: bigint\n}\n\n/**\n * Inspects a same-chain swap's status from ACTUAL on-chain state\n * (`lockState`, `posted`) combined with the current block timestamp.\n *\n * @param client - An {@link OmnibusClient} on the swap's chain.\n * @param lock - The swap's hashlock.\n * @param plan - The plan from {@link planSameChainSwap}.\n * @returns A {@link SameChainSwapStatusReport}; never throws on unexpected\n * state combinations — the raw fields are included so the application can\n * inspect them.\n * @example\n * ```ts\n * const {status} = await getSameChainSwapStatus(client, lock, plan)\n * if (status === 'claimable') await client.claim({secret, party: plan.proposerTerms, counterparty: plan.takerTerms})\n * ```\n */\nexport async function getSameChainSwapStatus(\n client: OmnibusClient,\n lock: Hex32,\n plan: SameChainSwapPlan,\n): Promise<SameChainSwapStatusReport> {\n const [state, proposerPosted, takerPosted, block] = await Promise.all([\n client.getLockState(lock),\n client.getPosted(lock, plan.proposerDigest),\n client.getPosted(lock, plan.takerDigest),\n client.publicClient.getBlock(),\n ])\n const timestamp = block.timestamp\n\n let status: SameChainSwapStatus\n switch (state) {\n case LockState.Unused:\n status = isWithinWindow(plan.proposerCommitWindow, timestamp)\n ? 'awaiting-proposer-commit'\n : 'proposer-commit-expired'\n break\n case LockState.Free:\n if (isWithinWindow(plan.proposerReclaimWindow, timestamp)) {\n // reclaim from Free: a half-committed swap is recoverable once the\n // committed leg's release passes (Free -> Spent is a valid transition)\n status = 'reclaimable-from-free'\n } else if (timestamp < plan.takerCommitWindow.lower) {\n status = 'awaiting-taker-window'\n } else if (isWithinWindow(plan.takerCommitWindow, timestamp)) {\n status = 'awaiting-taker-commit'\n } else {\n status = 'half-committed-expired'\n }\n break\n case LockState.Committed:\n if (isWithinWindow(plan.claimWindow, timestamp)) {\n status = 'claimable'\n } else if (isWithinWindow(plan.proposerReclaimWindow, timestamp)) {\n status = 'reclaimable'\n } else if (timestamp >= plan.proposerTerms.claimDeadline) {\n // between proposer.claimDeadline and proposer.reclaimRelease the\n // taker-role claim path is still open (it settles both legs too)\n status = 'late-claimable'\n } else {\n // Committed before taker.commitmentDeadline: the taker committed\n // early in its window; the proposer-claim window opens at\n // taker.commitmentDeadline\n status = 'awaiting-claim-window'\n }\n break\n case LockState.Spent:\n status = 'settled'\n break\n }\n\n return {status, lockState: state, proposerPosted, takerPosted, timestamp}\n}\n","/**\n * Cross-chain swap workflow helpers.\n *\n * A cross-chain swap is NOT atomic: it is a coordinated flow across two\n * independent EVM chains. The strictly interleaved six-timestamp schedule\n * plus one MANDATORY off-chain check are what bound each side's risk.\n *\n * Roles and timing are identical to the same-chain flow — one shared\n * schedule — but each leg lives on its own chain and each local commit\n * moves that chain's lock `Unused -> Committed` directly (no `Free` state\n * cross-chain). With Alice the proposer/secret holder on Chain A and Bob\n * the taker on Chain B:\n *\n * ```text\n * 1. Alice generates the secret and lock.\n * 2. Alice commits her leg on Chain A in [0, alice.commitmentDeadline).\n * 3. Bob VERIFIES ALICE'S CHAIN-A COMMITMENT OFF-CHAIN (mandatory — the\n * Chain B contract cannot see Chain A), then commits on Chain B in\n * [alice.commitmentDeadline, bob.commitmentDeadline).\n * 4. Alice claims Bob's leg ON CHAIN B in [bob.commitmentDeadline,\n * alice.claimDeadline) — claim(secret, party=alice, counterparty=bob).\n * The Chain B Claim event reveals the secret.\n * 5. Bob (or a relayer) extracts the secret from the Chain B Claim event.\n * 6. Bob claims Alice's leg ON CHAIN A in [alice.claimDeadline,\n * alice.reclaimRelease) — claim(secret, party=bob, counterparty=alice).\n * 7. Both locks are Spent.\n * ```\n *\n * THE SECRET HOLDER MUST BE THE PROPOSER. If the secret holder were the\n * taker, the windows would let them claim the counterparty's leg while\n * retaining the option to let their own leg expire — the cross-chain\n * \"free option\" the interleaving exists to prevent (see\n * `test/attack/CrossChainFreeOption.t.sol`).\n */\nimport {DEFAULT_CROSS_CHAIN_BUFFER_SECONDS, checkScheduleBuffers} from '../buffers.js'\nimport {QuipSwapError} from '../errors.js'\nimport {digestTerms, digestTermsCanonically, generateLock} from '../hashing.js'\nimport {proposedBy, validateTermPairing, validateTerms} from '../terms.js'\nimport {LockState} from '../types.js'\nimport type {Hex32, Terms} from '../types.js'\nimport type {OmnibusClient} from '../client.js'\n\n/** Arguments for {@link validateCrossChainSchedule}. */\nexport interface ValidateCrossChainScheduleArgs {\n /**\n * The SECRET HOLDER's leg. The secret holder must be the proposer (the\n * side with the smaller `commitmentDeadline`); anything else is the\n * free-option misconfiguration and is rejected.\n */\n readonly proposerTerms: Terms\n /** The counterparty's (taker's) leg, on the other chain. */\n readonly takerTerms: Terms\n /**\n * Minimum acceptable gap, in SECONDS, between EVERY pair of adjacent\n * timestamps in the interleaved schedule — including the taker's\n * post-reveal reaction buffer\n * (`proposer.reclaimRelease - proposer.claimDeadline`).\n *\n * Optional: defaults to {@link DEFAULT_CROSS_CHAIN_BUFFER_SECONDS} when\n * omitted. Choose it from chain finality, reorg risk, RPC reliability,\n * network congestion, relayer responsiveness, and your operational safety\n * margin (the {@link DEFAULT_BUFFERS} presets are starting points). A\n * value comfortable on a fast-finality L2 may be recklessly small on a\n * congested L1. Overriding BELOW the default can expose users to missed\n * windows and lost funds under congestion/reorgs — only do so if you\n * understand your chains' finality.\n */\n readonly minimumBufferSeconds?: bigint\n}\n\n/** The validated cross-chain schedule summary. */\nexport interface CrossChainSchedule {\n /** The proposer's (secret holder's) leg. */\n readonly proposerTerms: Terms\n /** The taker's leg. */\n readonly takerTerms: Terms\n /**\n * The taker's post-reveal reaction buffer in seconds:\n * `proposer.reclaimRelease - proposer.claimDeadline` — the gap between\n * the latest possible secret reveal (the proposer-claim window closes at\n * `proposer.claimDeadline`) and the close of the taker's claim window\n * (`proposer.reclaimRelease`). This is the taker's time to observe the\n * revealed secret and land their own claim.\n */\n readonly reactionBufferSeconds: bigint\n /** The smallest gap between any two adjacent schedule timestamps, in seconds. */\n readonly minimumGapSeconds: bigint\n}\n\n/**\n * Validates a cross-chain swap schedule before any transaction is sent.\n *\n * Checks, in order:\n * 1. Both terms are structurally valid and the pairing strictly\n * interleaves (the contract enforces this on BOTH chains; the SDK\n * rejects bad pairings before any gas is spent).\n * 2. The secret holder's leg (`proposerTerms`) actually IS the proposer —\n * rejecting the free-option role mis-assignment.\n * 3. The two legs are on DIFFERENT chains (use {@link planSameChainSwap}\n * otherwise).\n * 4. Every gap between adjacent timestamps in the interleaved schedule —\n * including the reaction buffer — is at least `minimumBufferSeconds`\n * (defaults to {@link DEFAULT_CROSS_CHAIN_BUFFER_SECONDS} when omitted).\n *\n * This validates the SCHEDULE only (interleaving, roles, buffers) and reads\n * no chain — it is NOT proof that any party has committed. A taker must\n * still run {@link verifyRemoteCommitment} against the proposer's chain\n * before committing; a valid schedule alone does not make a commit safe.\n *\n * @param args - See {@link ValidateCrossChainScheduleArgs}; parameter names\n * are protocol roles (`proposerTerms`/`takerTerms`), not call-site roles.\n * @returns The {@link CrossChainSchedule} summary (buffers included).\n * @throws QuipSwapError - structural codes; `DISORDERED_DEADLINES`;\n * `SECRET_HOLDER_NOT_PROPOSER` when the roles are inverted;\n * `CHAIN_ID_MISMATCH` when both legs share a chain;\n * `INSUFFICIENT_BUFFER` when any adjacent gap is below the minimum.\n * @see TermsLib.validateTermPairing, test/attack/CrossChainFreeOption.t.sol\n * @example\n * ```ts\n * const schedule = validateCrossChainSchedule({\n * proposerTerms: aliceTermsOnChainA, // Alice holds the secret\n * takerTerms: bobTermsOnChainB,\n * // minimumBufferSeconds omitted → DEFAULT_CROSS_CHAIN_BUFFER_SECONDS;\n * // or pass an explicit margin, e.g. DEFAULT_BUFFERS.conservativeL1\n * })\n * ```\n */\nexport function validateCrossChainSchedule(args: ValidateCrossChainScheduleArgs): CrossChainSchedule {\n const {proposerTerms, takerTerms} = args\n const minimumBufferSeconds = args.minimumBufferSeconds ?? DEFAULT_CROSS_CHAIN_BUFFER_SECONDS\n validateTerms(proposerTerms)\n validateTerms(takerTerms)\n validateTermPairing(proposerTerms, takerTerms)\n\n // SECURITY: the secret holder must be the proposer. proposedBy returns\n // 'party' iff the first argument has the smaller commitmentDeadline.\n if (proposedBy(proposerTerms, takerTerms) !== 'party') {\n throw new QuipSwapError({\n code: 'SECRET_HOLDER_NOT_PROPOSER',\n message:\n \"The secret holder's leg must be the proposer (smaller commitmentDeadline). A secret-holding taker \" +\n 'could claim the counterparty leg while letting its own leg expire — the cross-chain free option. ' +\n 'Swap the role assignment or rebuild the schedule',\n details: {\n proposerCommitmentDeadline: proposerTerms.commitmentDeadline,\n takerCommitmentDeadline: takerTerms.commitmentDeadline,\n },\n })\n }\n\n if (proposerTerms.chainId === takerTerms.chainId) {\n throw new QuipSwapError({\n code: 'CHAIN_ID_MISMATCH',\n message: `Cross-chain schedule requires the two legs on different chains; both are on ${proposerTerms.chainId}`,\n details: {chainId: proposerTerms.chainId},\n })\n }\n\n // gap-SIZE check across the interleaved schedule (shared with the\n // same-chain validator); throws INSUFFICIENT_BUFFER on a too-tight gap\n const {minimumGapSeconds} = checkScheduleBuffers(proposerTerms, takerTerms, minimumBufferSeconds)\n\n return {\n proposerTerms,\n takerTerms,\n // reactionBuffer = proposer.reclaimRelease - proposer.claimDeadline\n reactionBufferSeconds: proposerTerms.reclaimRelease - proposerTerms.claimDeadline,\n minimumGapSeconds,\n }\n}\n\n/** The result of {@link verifyRemoteCommitment}. */\nexport interface RemoteCommitmentStatus {\n /** True iff the remote lock is `Committed` AND the remote side's terms are posted. */\n readonly committed: boolean\n /** The remote lock's state. */\n readonly lockState: LockState\n /** Whether the remote (proposer) side's terms digest is posted for the lock. */\n readonly proposerPosted: boolean\n /** Whether the on-chain canonical termsHash matches the supplied pairing. */\n readonly termsHashMatches: boolean\n}\n\n/**\n * The taker's MANDATORY pre-commit check: verifies on the PROPOSER's chain\n * that the proposer's commitment has actually taken effect.\n *\n * ⚠️ Skipping this before a cross-chain TAKER commit is the single most\n * dangerous mistake you can make with this SDK. If the taker commits and\n * the proposer never committed, the proposer (who holds the secret) can\n * claim the taker's escrowed leg while risking nothing — the taker loses\n * its funds. The contract states the obligation explicitly (`Omnibus.commit`:\n * \"the party MUST ensure the commitment from the counterparty has taken\n * effect especially if the swap is cross-chain\") but CANNOT enforce it\n * cross-chain, because the taker's chain cannot read the proposer's chain.\n *\n * Not spoofable: this reads on-chain STORAGE (`lockState` / `posted` /\n * `termsHash`), not events, so a forged log cannot fake a commitment. But\n * the result is POINT-IN-TIME — a reorg can undo a young commit — so apply\n * your own confirmation depth (re-check after N blocks) before relying on a\n * `true` result.\n *\n * Chain-agnostic: pass a client bound to the PROPOSER's chain for a\n * cross-chain swap (the case that matters); passing the local client for a\n * same-chain swap merely duplicates a guard the contract already enforces.\n *\n * @param remoteClient - An {@link OmnibusClient} bound to the PROPOSER's chain.\n * @param lock - The shared hashlock.\n * @param proposerTerms - The proposer's (remote) leg.\n * @param takerTerms - The taker's (local) leg.\n * @returns A {@link RemoteCommitmentStatus}; commit only when `committed`\n * is true and your confirmation policy is satisfied.\n * @see Omnibus.commit\n * @example\n * ```ts\n * const status = await verifyRemoteCommitment(chainAClient, lock, aliceTerms, bobTerms)\n * if (status.committed) await chainBClient.commit({lock, party: bobTerms, counterparty: aliceTerms})\n * ```\n */\nexport async function verifyRemoteCommitment(\n remoteClient: OmnibusClient,\n lock: Hex32,\n proposerTerms: Terms,\n takerTerms: Terms,\n): Promise<RemoteCommitmentStatus> {\n const [state, proposerPosted, onChainTermsHash] = await Promise.all([\n remoteClient.getLockState(lock),\n remoteClient.getPosted(lock, digestTerms(proposerTerms)),\n remoteClient.getTermsHash(lock),\n ])\n const termsHashMatches =\n onChainTermsHash.toLowerCase() === digestTermsCanonically(proposerTerms, takerTerms).toLowerCase()\n return {\n // cross-chain local commits move Unused -> Committed directly\n committed: state === LockState.Committed && proposerPosted && termsHashMatches,\n lockState: state,\n proposerPosted,\n termsHashMatches,\n }\n}\n\n/**\n * Derives the lock from a secret for cross-chain coordination — re-export\n * of {@link generateLock} under a workflow-centric name so coordinators\n * depend only on this module.\n *\n * @param secret - The proposer's 32-byte secret.\n * @returns The shared lock used on BOTH chains.\n * @throws QuipSwapError `INVALID_HEX32` for malformed secrets.\n * @see Omnibus._generateLock\n */\nexport function deriveSharedLock(secret: Hex32): Hex32 {\n return generateLock(secret)\n}\n"],"mappings":"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","names":["AssetType","LockState","isAddress","zeroAddress","isAddress","zeroAddress","isAddress","zeroAddress","isAddress","zeroAddress","BaseError","ContractFunctionRevertedError","BaseError","ContractFunctionRevertedError","BaseError","BaseError","MAX_UINT256","request"]}
|