diff --git a/lib/consts/Types.ts b/lib/consts/Types.ts index ea9f927..96e3202 100644 --- a/lib/consts/Types.ts +++ b/lib/consts/Types.ts @@ -59,3 +59,5 @@ export type SwapTree = { claimLeaf: Tapleaf; refundLeaf: Tapleaf; }; + +export type LiquidSwapTree = SwapTree & { covenantClaimLeaf?: Tapleaf }; diff --git a/lib/liquid/consts/Types.ts b/lib/liquid/consts/Types.ts index ec2ccf9..f61bee3 100644 --- a/lib/liquid/consts/Types.ts +++ b/lib/liquid/consts/Types.ts @@ -1,9 +1,7 @@ import { BIP32Interface } from 'bip32'; import { ECPairInterface } from 'ecpair'; import { Transaction, TxOutput } from 'liquidjs-lib'; -import { RefundDetails, SwapTree, Tapleaf } from '../../consts/Types'; - -export type LiquidSwapTree = SwapTree & { covenantClaimLeaf?: Tapleaf }; +import { LiquidSwapTree, RefundDetails } from '../../consts/Types'; export type LiquidRefundDetails = Omit & TxOutput & { diff --git a/lib/liquid/swap/ReverseSwapTree.ts b/lib/liquid/swap/ReverseSwapTree.ts index 0bbd9cb..f492f25 100644 --- a/lib/liquid/swap/ReverseSwapTree.ts +++ b/lib/liquid/swap/ReverseSwapTree.ts @@ -2,13 +2,12 @@ import ops from '@boltz/bitcoin-ops'; import { crypto, script } from 'bitcoinjs-lib'; import { reverseBuffer } from 'liquidjs-lib/src/bufferutils'; import { getHexBuffer } from '../../Utils'; -import { Tapleaf } from '../../consts/Types'; +import { LiquidSwapTree, Tapleaf } from '../../consts/Types'; import bitcoinReverseSwapTree from '../../swap/ReverseSwapTree'; import { leafVersionLiquid } from '../../swap/TaprootUtils'; -import { assignTreeProbabilities, sortTree } from '../TreeSort'; +import { assignTreeProbabilities, sortTree } from '../../swap/TreeSort'; import { getScriptIntrospectionValues } from '../Utils'; import liquidOps from '../consts/Ops'; -import { LiquidSwapTree } from '../consts/Types'; enum Feature { ClaimCovenant, diff --git a/lib/liquid/swap/TaprootUtils.ts b/lib/liquid/swap/TaprootUtils.ts index a265079..2d068e4 100644 --- a/lib/liquid/swap/TaprootUtils.ts +++ b/lib/liquid/swap/TaprootUtils.ts @@ -3,10 +3,8 @@ import { Taptree, isTapleaf } from 'bitcoinjs-lib/src/types'; import { Transaction, TxOutput } from 'liquidjs-lib'; import { HashTree, - TaprootLeaf, findScriptPath as liquidFindScriptPath, tapLeafHash as liquidTapLeafHash, - toHashTree as liquidToHashTree, } from 'liquidjs-lib/src/bip341'; import { taggedHash } from 'liquidjs-lib/src/crypto'; import { Network } from 'liquidjs-lib/src/networks'; @@ -44,24 +42,27 @@ export const hashForWitnessV1 = ( export const tapLeafHash = (leaf: Tapleaf) => liquidTapLeafHash(convertLeaf(leaf)); +export const tapBranchHash = (a: Buffer, b: Buffer) => + taggedHash('TapBranch/elements', Buffer.concat([a, b])); + export const tapTweakHash = (publicKey: Buffer, tweak: Buffer) => taggedHash('TapTweak/elements', Buffer.concat([toXOnly(publicKey), tweak])); -export const toHashTree = (tree: Taptree): HashTree => { - const leafs: TaprootLeaf[] = []; +export function toHashTree(scriptTree: Taptree): HashTree { + if (isTapleaf(scriptTree)) { + return { hash: tapLeafHash(scriptTree as Tapleaf) }; + } - const convertToLeafs = (tree: Taptree) => { - if (isTapleaf(tree)) { - leafs.push(convertLeaf(tree as Tapleaf)); - } else { - convertToLeafs(tree[0]); - convertToLeafs(tree[1]); - } - }; - convertToLeafs(tree); + const hashes = [toHashTree(scriptTree[0]), toHashTree(scriptTree[1])]; + hashes.sort((a, b) => a.hash.compare(b.hash)); + const [left, right] = hashes; - return liquidToHashTree(leafs); -}; + return { + hash: tapBranchHash(left.hash, right.hash), + left, + right, + }; +} export const tweakMusig = (musig: Musig, tree: Taptree): Buffer => toXOnly( diff --git a/lib/swap/SwapTreeSerializer.ts b/lib/swap/SwapTreeSerializer.ts index 3258d01..a025412 100644 --- a/lib/swap/SwapTreeSerializer.ts +++ b/lib/swap/SwapTreeSerializer.ts @@ -1,6 +1,6 @@ import { getHexBuffer, getHexString } from '../Utils'; -import { SwapTree, Tapleaf } from '../consts/Types'; -import { swapLeafsToTree } from './TaprootUtils'; +import { LiquidSwapTree, SwapTree, Tapleaf } from '../consts/Types'; +import { assignTreeProbabilities, sortTree } from './TreeSort'; type SerializedLeaf = { version: number; @@ -12,6 +12,10 @@ type SerializedTree = { refundLeaf: SerializedLeaf; }; +type SerializedLiquidSwapTree = SerializedTree & { + covenantClaimLeaf?: SerializedLeaf; +}; + const serializeLeaf = (leaf: Tapleaf): SerializedLeaf => ({ version: leaf.version, output: getHexString(leaf.output), @@ -22,24 +26,38 @@ const deserializeLeaf = (leaf: SerializedLeaf): Tapleaf => ({ output: getHexBuffer(leaf.output), }); -export const serializeSwapTree = (tree: SwapTree): SerializedTree => ({ - claimLeaf: serializeLeaf(tree.claimLeaf), - refundLeaf: serializeLeaf(tree.refundLeaf), -}); +export const serializeSwapTree = ( + tree: LiquidSwapTree, +): SerializedTree | SerializedLiquidSwapTree => { + const res: SerializedLiquidSwapTree = { + claimLeaf: serializeLeaf(tree.claimLeaf), + refundLeaf: serializeLeaf(tree.refundLeaf), + }; + + if (tree.covenantClaimLeaf !== undefined) { + res.covenantClaimLeaf = serializeLeaf(tree.covenantClaimLeaf); + } + + return res; +}; export const deserializeSwapTree = ( - tree: string | SerializedTree, -): SwapTree => { + tree: string | SerializedTree | LiquidSwapTree, +): SwapTree | LiquidSwapTree => { const parsed = typeof tree === 'string' ? JSON.parse(tree) : tree; - const res = { + const res: Omit = { claimLeaf: deserializeLeaf(parsed.claimLeaf), refundLeaf: deserializeLeaf(parsed.refundLeaf), + covenantClaimLeaf: + parsed.covenantClaimLeaf !== undefined + ? deserializeLeaf(parsed.covenantClaimLeaf) + : undefined, }; return { ...res, - tree: swapLeafsToTree(res.claimLeaf, res.refundLeaf), + tree: sortTree(assignTreeProbabilities(res)), }; }; diff --git a/lib/liquid/TreeSort.ts b/lib/swap/TreeSort.ts similarity index 77% rename from lib/liquid/TreeSort.ts rename to lib/swap/TreeSort.ts index 9f9b231..dc7c055 100644 --- a/lib/liquid/TreeSort.ts +++ b/lib/swap/TreeSort.ts @@ -1,5 +1,4 @@ -import { Tapleaf } from '../consts/Types'; -import { LiquidSwapTree } from './consts/Types'; +import { LiquidSwapTree } from '../consts/Types'; type ProbabilityNode = { probability: number; value: T }; @@ -29,9 +28,18 @@ const subSortTree = (nodes: ProbabilityNode[]): TreeNode => { export const sortTree = (nodes: ProbabilityNode[]): TreeNode => subSortTree(nodes.sort((a, b) => b.probability - a.probability)); -export const assignTreeProbabilities = ( - tree: Omit, -): ProbabilityNode[] => { +export const assignTreeProbabilities = ( + tree: Omit< + Record, T | undefined> & { + covenantClaimLeaf?: T; + }, + 'tree' + >, +): ProbabilityNode[] => { + if (tree.claimLeaf === undefined || tree.refundLeaf === undefined) { + throw 'invalid tree'; + } + if (tree.covenantClaimLeaf) { return [ { diff --git a/package-lock.json b/package-lock.json index 24c446e..bc96eec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "boltz-core", - "version": "2.1.0", + "version": "2.1.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "boltz-core", - "version": "2.1.0", + "version": "2.1.1", "license": "AGPL-3.0", "dependencies": { "@boltz/bitcoin-ops": "^2.0.0", @@ -24,17 +24,17 @@ "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@typechain/ethers-v6": "^0.5.1", "@types/jest": "^29.5.12", - "@types/node": "^20.11.16", + "@types/node": "^20.11.18", "@types/ws": "^8.5.10", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "@typescript-eslint/parser": "^6.21.0", + "@typescript-eslint/eslint-plugin": "^7.0.1", + "@typescript-eslint/parser": "^7.0.1", "bip174": "^2.1.1", "cross-os": "^1.5.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.3", + "eslint-plugin-jest": "^27.8.0", "eslint-plugin-node": "^11.1.0", - "ethers": "^6.10.0", + "ethers": "^6.11.1", "git-cliff": "^1.4.0", "jest": "^29.7.0", "prettier": "^3.2.5", @@ -63,9 +63,9 @@ } }, "node_modules/@adraffy/ens-normalize": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.0.tgz", - "integrity": "sha512-nA9XHtlAkYfJxY7bce8DcN7eKxWWCWkU+1GR9d+U6MbNpfwQp8TI7vqOsBsMcHoT4mBu2kypKoSKnghEzOOq5Q==", + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", "dev": true }, "node_modules/@ampproject/remapping": { @@ -1553,9 +1553,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.16", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.16.tgz", - "integrity": "sha512-gKb0enTmRCzXSSUJDq6/sPcqrfCv2mkkG6Jt/clpn5eiCbKTY+SgZUxo+p8ZKMof5dCp9vHQUAB7wOUTod22wQ==", + "version": "20.11.18", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.18.tgz", + "integrity": "sha512-ABT5VWnnYneSBcNWYSCuR05M826RoMyMSGiFivXGx6ZUIsXb9vn4643IEwkg2zbEOSgAiSogtapN2fgc4mAPlw==", "dependencies": { "undici-types": "~5.26.4" } @@ -1612,16 +1612,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", - "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.1.tgz", + "integrity": "sha512-OLvgeBv3vXlnnJGIAgCLYKjgMEU+wBGj07MQ/nxAaON+3mLzX7mJbhRYrVGiVvFiXtwFlkcBa/TtmglHy0UbzQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/type-utils": "6.21.0", - "@typescript-eslint/utils": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/type-utils": "7.0.1", + "@typescript-eslint/utils": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -1637,8 +1637,8 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", - "eslint": "^7.0.0 || ^8.0.0" + "@typescript-eslint/parser": "^7.0.0", + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1647,13 +1647,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1664,9 +1664,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1677,13 +1677,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1705,17 +1705,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", "semver": "^7.5.4" }, "engines": { @@ -1726,16 +1726,16 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1786,15 +1786,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", - "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.0.1.tgz", + "integrity": "sha512-8GcRRZNzaHxKzBPU3tKtFNing571/GwPBeCvmAUw0yBtfE2XVd0zFKJIMSWkHJcPQi0ekxjIts6L/rrZq5cxGQ==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4" }, "engines": { @@ -1805,7 +1805,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1814,13 +1814,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1831,9 +1831,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1844,13 +1844,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1872,12 +1872,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -1945,13 +1945,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", - "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.0.1.tgz", + "integrity": "sha512-YtT9UcstTG5Yqy4xtLiClm1ZpM/pWVGFnkAa90UfdkkZsR1eP2mR/1jbHeYp8Ay1l1JHPyGvoUYR6o3On5Nhmw==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "6.21.0", - "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/typescript-estree": "7.0.1", + "@typescript-eslint/utils": "7.0.1", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -1963,7 +1963,7 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" }, "peerDependenciesMeta": { "typescript": { @@ -1972,13 +1972,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", - "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.0.1.tgz", + "integrity": "sha512-v7/T7As10g3bcWOOPAcbnMDuvctHzCFYCG/8R4bK4iYzdFqsZTbXGln0cZNVcwQcwewsYU2BJLay8j0/4zOk4w==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0" + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -1989,9 +1989,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", - "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.0.1.tgz", + "integrity": "sha512-uJDfmirz4FHib6ENju/7cz9SdMSkeVvJDK3VcMFvf/hAShg8C74FW+06MaQPODHfDJp/z/zHfgawIJRjlu0RLg==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2002,13 +2002,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", - "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.1.tgz", + "integrity": "sha512-SO9wHb6ph0/FN5OJxH4MiPscGah5wjOd0RRpaLvuBv9g8565Fgu0uMySFEPqwPHiQU90yzJ2FjRYKGrAhS1xig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/visitor-keys": "6.21.0", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/visitor-keys": "7.0.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2030,17 +2030,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", - "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.0.1.tgz", + "integrity": "sha512-oe4his30JgPbnv+9Vef1h48jm0S6ft4mNwi9wj7bX10joGn07QRfqIqFHoMiajrtoU88cIhXf8ahwgrcbNLgPA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.21.0", - "@typescript-eslint/types": "6.21.0", - "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/scope-manager": "7.0.1", + "@typescript-eslint/types": "7.0.1", + "@typescript-eslint/typescript-estree": "7.0.1", "semver": "^7.5.4" }, "engines": { @@ -2051,16 +2051,16 @@ "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^8.56.0" } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "6.21.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", - "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.1.tgz", + "integrity": "sha512-hwAgrOyk++RTXrP4KzCg7zB2U0xt7RUU0ZdMSCsqF3eKUwkdXUMyTb0qdCuji7VIbcpG62kKTU9M1J1c9UpFBw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/types": "7.0.1", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -3622,9 +3622,9 @@ } }, "node_modules/eslint-plugin-jest": { - "version": "27.6.3", - "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.6.3.tgz", - "integrity": "sha512-+YsJFVH6R+tOiO3gCJon5oqn4KWc+mDq2leudk8mrp8RFubLOo9CVyi3cib4L7XMpxExmkmBZQTPDYVBzgpgOA==", + "version": "27.8.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-27.8.0.tgz", + "integrity": "sha512-347hVFiu4ZKMYl5xFp0X81gLNwBdno0dl0CMpUMjwuAux9X/M2a7z+ab2VHmPL6XCT87q8nv1vaVzhIO4TE/hw==", "dev": true, "dependencies": { "@typescript-eslint/utils": "^5.10.0" @@ -3633,7 +3633,7 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" }, "peerDependencies": { - "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0", + "@typescript-eslint/eslint-plugin": "^5.0.0 || ^6.0.0 || ^7.0.0", "eslint": "^7.0.0 || ^8.0.0", "jest": "*" }, @@ -3916,9 +3916,9 @@ } }, "node_modules/ethers": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.10.0.tgz", - "integrity": "sha512-nMNwYHzs6V1FR3Y4cdfxSQmNgZsRj1RiTU25JwvnJLmyzw9z3SKxNc2XKDuiXXo/v9ds5Mp9m6HBabgYQQ26tA==", + "version": "6.11.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.11.1.tgz", + "integrity": "sha512-mxTAE6wqJQAbp5QAe/+o+rXOID7Nw91OZXvgpjDa1r4fAbq2Nu314oEZSbjoRLacuCzs7kUC3clEvkCQowffGg==", "dev": true, "funding": [ { @@ -3931,7 +3931,7 @@ } ], "dependencies": { - "@adraffy/ens-normalize": "1.10.0", + "@adraffy/ens-normalize": "1.10.1", "@noble/curves": "1.2.0", "@noble/hashes": "1.3.2", "@types/node": "18.15.13", @@ -7040,12 +7040,12 @@ } }, "node_modules/ts-api-utils": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", - "integrity": "sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.1.tgz", + "integrity": "sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==", "dev": true, "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" diff --git a/package.json b/package.json index 1f11308..589b112 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "boltz-core", - "version": "2.1.0", + "version": "2.1.1", "description": "Core library of Boltz", "main": "dist/lib/Boltz.js", "scripts": { @@ -64,17 +64,17 @@ "@trivago/prettier-plugin-sort-imports": "^4.3.0", "@typechain/ethers-v6": "^0.5.1", "@types/jest": "^29.5.12", - "@types/node": "^20.11.16", + "@types/node": "^20.11.18", "@types/ws": "^8.5.10", - "@typescript-eslint/eslint-plugin": "^6.21.0", - "@typescript-eslint/parser": "^6.21.0", + "@typescript-eslint/eslint-plugin": "^7.0.1", + "@typescript-eslint/parser": "^7.0.1", "bip174": "^2.1.1", "cross-os": "^1.5.0", "eslint": "^8.56.0", "eslint-plugin-import": "^2.29.1", - "eslint-plugin-jest": "^27.6.3", + "eslint-plugin-jest": "^27.8.0", "eslint-plugin-node": "^11.1.0", - "ethers": "^6.10.0", + "ethers": "^6.11.1", "git-cliff": "^1.4.0", "jest": "^29.7.0", "prettier": "^3.2.5", diff --git a/test/unit/liquid/swap/TaprootUtils.spec.ts b/test/unit/liquid/swap/TaprootUtils.spec.ts index 6100c9f..eeb9c8c 100644 --- a/test/unit/liquid/swap/TaprootUtils.spec.ts +++ b/test/unit/liquid/swap/TaprootUtils.spec.ts @@ -58,6 +58,12 @@ describe('TaprootUtils', () => { expect(hashTree).toMatchSnapshot(); }); + test('should convert netsted taproot tree to hash tree', () => { + const hashTree = toHashTree([taptree, taptree]); + expect(hashTree).toBeDefined(); + expect(hashTree).toMatchSnapshot(); + }); + test('should tweak Musig', async () => { const secp = await zkp(); const ourMusigKey = ECPair.makeRandom(); diff --git a/test/unit/liquid/swap/__snapshots__/TaprootUtils.spec.ts.snap b/test/unit/liquid/swap/__snapshots__/TaprootUtils.spec.ts.snap index 16e4d15..f463620 100644 --- a/test/unit/liquid/swap/__snapshots__/TaprootUtils.spec.ts.snap +++ b/test/unit/liquid/swap/__snapshots__/TaprootUtils.spec.ts.snap @@ -1,5 +1,281 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`TaprootUtils should convert netsted taproot tree to hash tree 1`] = ` +{ + "hash": { + "data": [ + 38, + 228, + 93, + 103, + 9, + 119, + 162, + 250, + 250, + 132, + 14, + 171, + 7, + 6, + 123, + 30, + 38, + 185, + 236, + 21, + 133, + 90, + 234, + 61, + 243, + 228, + 164, + 37, + 250, + 171, + 22, + 105, + ], + "type": "Buffer", + }, + "left": { + "hash": { + "data": [ + 183, + 85, + 121, + 159, + 174, + 151, + 56, + 244, + 93, + 34, + 165, + 195, + 58, + 58, + 235, + 182, + 252, + 187, + 41, + 203, + 71, + 55, + 190, + 204, + 220, + 216, + 175, + 121, + 55, + 230, + 110, + 202, + ], + "type": "Buffer", + }, + "left": { + "hash": { + "data": [ + 156, + 21, + 208, + 30, + 80, + 233, + 79, + 202, + 96, + 183, + 18, + 16, + 29, + 201, + 213, + 92, + 241, + 161, + 125, + 199, + 185, + 215, + 253, + 81, + 162, + 18, + 84, + 29, + 216, + 112, + 63, + 47, + ], + "type": "Buffer", + }, + }, + "right": { + "hash": { + "data": [ + 214, + 199, + 128, + 229, + 173, + 226, + 45, + 20, + 21, + 0, + 119, + 252, + 154, + 50, + 126, + 138, + 134, + 144, + 180, + 204, + 181, + 248, + 104, + 162, + 39, + 139, + 222, + 26, + 212, + 66, + 140, + 179, + ], + "type": "Buffer", + }, + }, + }, + "right": { + "hash": { + "data": [ + 183, + 85, + 121, + 159, + 174, + 151, + 56, + 244, + 93, + 34, + 165, + 195, + 58, + 58, + 235, + 182, + 252, + 187, + 41, + 203, + 71, + 55, + 190, + 204, + 220, + 216, + 175, + 121, + 55, + 230, + 110, + 202, + ], + "type": "Buffer", + }, + "left": { + "hash": { + "data": [ + 156, + 21, + 208, + 30, + 80, + 233, + 79, + 202, + 96, + 183, + 18, + 16, + 29, + 201, + 213, + 92, + 241, + 161, + 125, + 199, + 185, + 215, + 253, + 81, + 162, + 18, + 84, + 29, + 216, + 112, + 63, + 47, + ], + "type": "Buffer", + }, + }, + "right": { + "hash": { + "data": [ + 214, + 199, + 128, + 229, + 173, + 226, + 45, + 20, + 21, + 0, + 119, + 252, + 154, + 50, + 126, + 138, + 134, + 144, + 180, + 204, + 181, + 248, + 104, + 162, + 39, + 139, + 222, + 26, + 212, + 66, + 140, + 179, + ], + "type": "Buffer", + }, + }, + }, +} +`; + exports[`TaprootUtils should convert taproot tree to hash tree 1`] = ` { "hash": { @@ -40,46 +316,6 @@ exports[`TaprootUtils should convert taproot tree to hash tree 1`] = ` "type": "Buffer", }, "left": { - "hash": { - "data": [ - 214, - 199, - 128, - 229, - 173, - 226, - 45, - 20, - 21, - 0, - 119, - 252, - 154, - 50, - 126, - 138, - 134, - 144, - 180, - 204, - 181, - 248, - 104, - 162, - 39, - 139, - 222, - 26, - 212, - 66, - 140, - 179, - ], - "type": "Buffer", - }, - "scriptHex": undefined, - }, - "right": { "hash": { "data": [ 156, @@ -117,7 +353,45 @@ exports[`TaprootUtils should convert taproot tree to hash tree 1`] = ` ], "type": "Buffer", }, - "scriptHex": undefined, + }, + "right": { + "hash": { + "data": [ + 214, + 199, + 128, + 229, + 173, + 226, + 45, + 20, + 21, + 0, + 119, + 252, + 154, + 50, + 126, + 138, + 134, + 144, + 180, + 204, + 181, + 248, + 104, + 162, + 39, + 139, + 222, + 26, + 212, + 66, + 140, + 179, + ], + "type": "Buffer", + }, }, } `; diff --git a/test/unit/swap/SwapTreeSerializer.spec.ts b/test/unit/swap/SwapTreeSerializer.spec.ts index 1ec1241..38547b1 100644 --- a/test/unit/swap/SwapTreeSerializer.spec.ts +++ b/test/unit/swap/SwapTreeSerializer.spec.ts @@ -1,4 +1,6 @@ import { getHexBuffer } from '../../../lib/Utils'; +import { Feature, Networks, reverseSwapTree } from '../../../lib/liquid'; +import { p2trOutput } from '../../../lib/swap/Scripts'; import swapTree from '../../../lib/swap/SwapTree'; import { deserializeSwapTree, @@ -7,51 +9,84 @@ import { import { ECPair } from '../Utils'; describe('SwapTreeSerializer', () => { + const preimageHash = getHexBuffer( + 'a8aca40d423f00ec0a69b1b815169d7412a747e08e5669e80b3106e82975908a', + ); + const claimPublicKey = ECPair.fromPrivateKey( + getHexBuffer( + '4cffad3235065eff2959eabeb36cccaed698bc5a009d43f2ca1ce2d251599f85', + ), + ).publicKey; + const refundPublicKey = ECPair.fromPrivateKey( + getHexBuffer( + 'eb4036423cd9ae6eaa44eb7203047c613aa2c6f52153b6783d53fa4e19173af1', + ), + ).publicKey; + const timeoutBlockHeight = 123; + const createTree = (isLiquid: boolean) => swapTree( isLiquid, - getHexBuffer( - 'a8aca40d423f00ec0a69b1b815169d7412a747e08e5669e80b3106e82975908a', - ), - ECPair.fromPrivateKey( - getHexBuffer( - '4cffad3235065eff2959eabeb36cccaed698bc5a009d43f2ca1ce2d251599f85', - ), - ).publicKey, - ECPair.fromPrivateKey( - getHexBuffer( - 'eb4036423cd9ae6eaa44eb7203047c613aa2c6f52153b6783d53fa4e19173af1', - ), - ).publicKey, - 123, + preimageHash, + claimPublicKey, + refundPublicKey, + timeoutBlockHeight, + ); + + const createTreeWithCovenant = () => + reverseSwapTree( + preimageHash, + claimPublicKey, + refundPublicKey, + timeoutBlockHeight, + [ + { + type: Feature.ClaimCovenant, + expectedAmount: 100_000, + assetHash: Networks.liquidRegtest.assetHash, + outputScript: p2trOutput(claimPublicKey), + }, + ], ); test.each` isLiquid ${false} ${true} - `('should serialize swap trees (isLiquid: $isLiquid)', ({ isLiquid }) => { + `('should serialize swap tree (isLiquid: $isLiquid)', ({ isLiquid }) => { const serialized = serializeSwapTree(createTree(isLiquid)); expect(serialized).toMatchSnapshot(); }); + test('should serialize swap tree with covenant', () => { + const serialized = serializeSwapTree(createTreeWithCovenant()); + expect(serialized).toMatchSnapshot(); + }); + test.each` isLiquid ${false} ${true} - `('should deserialize swap trees (isLiquid: $isLiquid)', ({ isLiquid }) => { + `('should deserialize swap tree (isLiquid: $isLiquid)', ({ isLiquid }) => { const tree = createTree(isLiquid); const serialized = serializeSwapTree(tree); expect(deserializeSwapTree(serialized)).toEqual(tree); }); + test('should deserialize swap tree with covenant', () => { + const tree = createTreeWithCovenant(); + + const serialized = serializeSwapTree(tree); + expect(deserializeSwapTree(serialized)).toEqual(tree); + }); + test.each` isLiquid ${false} ${true} `( - 'should deserialize stringified swap trees (isLiquid: $isLiquid)', + 'should deserialize string swap trees (isLiquid: $isLiquid)', ({ isLiquid }) => { const tree = createTree(isLiquid); diff --git a/test/unit/liquid/TreeSort.spec.ts b/test/unit/swap/TreeSort.spec.ts similarity index 95% rename from test/unit/liquid/TreeSort.spec.ts rename to test/unit/swap/TreeSort.spec.ts index a31264f..98ca4c3 100644 --- a/test/unit/liquid/TreeSort.spec.ts +++ b/test/unit/swap/TreeSort.spec.ts @@ -1,9 +1,6 @@ -import { - assignTreeProbabilities, - sortTree, -} from '../../../lib/liquid/TreeSort'; -import { LiquidSwapTree } from '../../../lib/liquid/consts/Types'; +import { LiquidSwapTree } from '../../../lib/consts/Types'; import { createLeaf } from '../../../lib/swap/TaprootUtils'; +import { assignTreeProbabilities, sortTree } from '../../../lib/swap/TreeSort'; describe('TreeSort', () => { test.each` diff --git a/test/unit/swap/__snapshots__/SwapTreeSerializer.spec.ts.snap b/test/unit/swap/__snapshots__/SwapTreeSerializer.spec.ts.snap index a6e5626..d944f22 100644 --- a/test/unit/swap/__snapshots__/SwapTreeSerializer.spec.ts.snap +++ b/test/unit/swap/__snapshots__/SwapTreeSerializer.spec.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`SwapTreeSerializer should serialize swap trees (isLiquid: false) 1`] = ` +exports[`SwapTreeSerializer should serialize swap tree (isLiquid: false) 1`] = ` { "claimLeaf": { "output": "a914124b4a204760441dc802c445d4987ba1bd967e6d882083d1d7b47cd4163db23e633b81a3a6906a99a99e5acbbe4df29172f42621668cac", @@ -13,7 +13,7 @@ exports[`SwapTreeSerializer should serialize swap trees (isLiquid: false) 1`] = } `; -exports[`SwapTreeSerializer should serialize swap trees (isLiquid: true) 1`] = ` +exports[`SwapTreeSerializer should serialize swap tree (isLiquid: true) 1`] = ` { "claimLeaf": { "output": "a914124b4a204760441dc802c445d4987ba1bd967e6d882083d1d7b47cd4163db23e633b81a3a6906a99a99e5acbbe4df29172f42621668cac", @@ -25,3 +25,20 @@ exports[`SwapTreeSerializer should serialize swap trees (isLiquid: true) 1`] = ` }, } `; + +exports[`SwapTreeSerializer should serialize swap tree with covenant 1`] = ` +{ + "claimLeaf": { + "output": "82012088a914124b4a204760441dc802c445d4987ba1bd967e6d882083d1d7b47cd4163db23e633b81a3a6906a99a99e5acbbe4df29172f42621668cac", + "version": 196, + }, + "covenantClaimLeaf": { + "output": "82012088a914124b4a204760441dc802c445d4987ba1bd967e6d8800d151882083d1d7b47cd4163db23e633b81a3a6906a99a99e5acbbe4df29172f42621668c8800ce51882025b251070e29ca19043cf33ccd7324e2ddab03ecc4ae0b5e77c4fc0e5cf6c95a8800cf7508a08601000000000087", + "version": 196, + }, + "refundLeaf": { + "output": "2010154f49ec6656fd70d28abd9bbb71633da124eda324b1bf2b28dd9686915087ad017bb1", + "version": 196, + }, +} +`;