From 127a5c7148bacc9a543f8335168c043c36afc1cf Mon Sep 17 00:00:00 2001 From: Dhairya Majmudar <124715224+DhairyaMajmudar@users.noreply.github.com> Date: Thu, 10 Oct 2024 19:42:27 +0530 Subject: [PATCH 1/2] [Test]: Jest to Vitest migration `caravan-psbt` package (#133) --- README.md | 16 ++++++ package-lock.json | 49 ++----------------- packages/caravan-bitcoin/package.json | 1 + .../src/__tests__/client.test.ts | 11 +---- .../src/__tests__/wallet.test.ts | 2 - packages/caravan-psbt/jest.config.ts | 14 ------ packages/caravan-psbt/jest.setup.ts | 1 - packages/caravan-psbt/package.json | 12 ++--- .../src/{ => __tests__}/functions.test.ts | 2 +- .../src/{ => __tests__}/psbtv0/psbt.test.ts | 8 +-- .../src/{ => __tests__}/psbtv0/utils.test.ts | 2 +- .../src/{ => __tests__}/psbtv2/psbtv2.test.ts | 44 ++++++++++++----- packages/caravan-psbt/src/psbtv0/psbt.ts | 2 +- packages/caravan-psbt/tsconfig.json | 9 +--- vitest.config.ts | 2 +- 15 files changed, 65 insertions(+), 110 deletions(-) delete mode 100644 packages/caravan-psbt/jest.config.ts delete mode 100644 packages/caravan-psbt/jest.setup.ts rename packages/caravan-psbt/src/{ => __tests__}/functions.test.ts (95%) rename packages/caravan-psbt/src/{ => __tests__}/psbtv0/psbt.test.ts (98%) rename packages/caravan-psbt/src/{ => __tests__}/psbtv0/utils.test.ts (82%) rename packages/caravan-psbt/src/{ => __tests__}/psbtv2/psbtv2.test.ts (99%) diff --git a/README.md b/README.md index 8b742e43..194e636d 100644 --- a/README.md +++ b/README.md @@ -309,6 +309,22 @@ import { BlockchainClient, ClientType } from "@caravan/clients"; ``` - Note that now not only if you make a change to `caravan/coordinator` the changes will be reflected almost instantly in the app, but you can also make a change to the dependencies and everything will rebuild (technically turborepo only rebuilds what is necessary, caching the rest). Add a console.log to the `getFeeEstimate` in the `BlockchainClient` app and see for yourself! +## Testing + +Caravan monorepo uses [vitest](https://vitest.dev) testing framework to test different pacakges within it. + +- For running the test suite runners hit below command in terminal + +```bash +turbo run test +``` + +**Editing test suite files:** Test suite files can be found in `__tests__` folder, every pacakge share a common vitest config file which manages test suiter runner environment. + +In some files if environment is needed to be changed specifically, it can done by adding control comments at top of the file [docs reference](https://vitest.dev/guide/environment#environments-for-specific-files) + + + ## Troubleshooting - you might see an error "The request '...' failed to resolve only because it was resolved as fully specified" Webpack has an [issue](https://github.com/webpack/webpack/issues/11467#issuecomment-691873586) by default diff --git a/package-lock.json b/package-lock.json index a5ace851..7549761d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20363,9 +20363,9 @@ } }, "node_modules/react-silence/node_modules/@types/react": { - "version": "16.14.60", - "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.60.tgz", - "integrity": "sha512-wIFmnczGsTcgwCBeIYOuy2mdXEiKZ5znU/jNOnMZPQyCcIxauMGWlX0TNG4lZ7NxRKj7YUIZRneJQSSdB2jKgg==", + "version": "16.14.61", + "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.61.tgz", + "integrity": "sha512-CK3zd17pDWAEMnN5TdzwQJQlto2dK/lb0WZsI74owWgQ8PR60WRk0sCeBxLWuSuuqqDZKqeUcxod/8yECqrP/g==", "dev": true, "dependencies": { "@types/prop-types": "*", @@ -26112,6 +26112,7 @@ "lint-staged": "^13.1.2", "mocha": "^10.2.0", "prettier": "^3.2.5", + "react-silence": "^1.0.4", "tsup": "^7.2.0", "typescript": "^4.1.3" }, @@ -27970,16 +27971,10 @@ "@caravan/eslint-config": "*", "@caravan/multisig": "*", "@caravan/typescript-config": "*", - "@inrupt/jest-jsdom-polyfills": "^3.2.1", - "@jest/globals": "^29.7.0", - "@types/jest": "^29.5.12", "eslint-plugin-prettier": "^5.1.3", - "jest": "^29.4.1", "jsdom": "24.0.0", "jsdom-global": "3.0.2", "lodash": "^4.17.21", - "react-silence": "^1.0.4", - "ts-jest": "^29.1.2", "ts-node": "^10.9.2", "tsup": "^7.2.0", "typescript": "^5.2.2" @@ -28044,16 +28039,6 @@ "dev": true, "peer": true }, - "packages/caravan-psbt/node_modules/@types/jest": { - "version": "29.5.12", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.12.tgz", - "integrity": "sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==", - "dev": true, - "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" - } - }, "packages/caravan-psbt/node_modules/acorn": { "version": "8.11.3", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", @@ -28496,32 +28481,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/caravan-psbt/node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "packages/caravan-psbt/node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "packages/caravan-psbt/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", diff --git a/packages/caravan-bitcoin/package.json b/packages/caravan-bitcoin/package.json index 9cb771d2..d2d1906e 100644 --- a/packages/caravan-bitcoin/package.json +++ b/packages/caravan-bitcoin/package.json @@ -58,6 +58,7 @@ "lint-staged": "^13.1.2", "mocha": "^10.2.0", "prettier": "^3.2.5", + "react-silence": "^1.0.4", "tsup": "^7.2.0", "typescript": "^4.1.3" }, diff --git a/packages/caravan-clients/src/__tests__/client.test.ts b/packages/caravan-clients/src/__tests__/client.test.ts index aa1bf1d4..0464e271 100644 --- a/packages/caravan-clients/src/__tests__/client.test.ts +++ b/packages/caravan-clients/src/__tests__/client.test.ts @@ -10,16 +10,7 @@ import * as bitcoind from "../bitcoind"; import * as wallet from "../wallet"; import BigNumber from "bignumber.js"; -import { - vi, - beforeEach, - afterEach, - Mocked, - MockInstance, - describe, - it, - expect, -} from "vitest"; +import { Mocked, MockInstance } from "vitest"; import axios from "axios"; vi.mock("axios"); diff --git a/packages/caravan-clients/src/__tests__/wallet.test.ts b/packages/caravan-clients/src/__tests__/wallet.test.ts index dde04fb3..bdf34614 100644 --- a/packages/caravan-clients/src/__tests__/wallet.test.ts +++ b/packages/caravan-clients/src/__tests__/wallet.test.ts @@ -6,8 +6,6 @@ import { bitcoindListUnspent, } from "../wallet"; -import { beforeEach, afterEach, vi, describe, it, expect } from "vitest"; - import * as bitcoind from "../bitcoind"; import BigNumber from "bignumber.js"; diff --git a/packages/caravan-psbt/jest.config.ts b/packages/caravan-psbt/jest.config.ts deleted file mode 100644 index d2c20cba..00000000 --- a/packages/caravan-psbt/jest.config.ts +++ /dev/null @@ -1,14 +0,0 @@ -import type { JestConfigWithTsJest } from "ts-jest"; - -const config: JestConfigWithTsJest = { - extensionsToTreatAsEsm: [".ts"], - verbose: true, - preset: "ts-jest/presets/default-esm", - testEnvironment: "node", - testPathIgnorePatterns: ["./lib"], - transform: {}, - setupFiles: ["/jest.setup.ts"], - moduleDirectories: ["node_modules", ""], -}; - -export default config; diff --git a/packages/caravan-psbt/jest.setup.ts b/packages/caravan-psbt/jest.setup.ts deleted file mode 100644 index b0bd26f6..00000000 --- a/packages/caravan-psbt/jest.setup.ts +++ /dev/null @@ -1 +0,0 @@ -import "@inrupt/jest-jsdom-polyfills"; diff --git a/packages/caravan-psbt/package.json b/packages/caravan-psbt/package.json index 4b713eab..f0a2a8d8 100644 --- a/packages/caravan-psbt/package.json +++ b/packages/caravan-psbt/package.json @@ -28,11 +28,11 @@ "scripts": { "build": "tsup src/index.ts --format cjs,esm --dts", "dev": "npm run build -- --watch", - "test": "NODE_OPTIONS=--experimental-vm-modules npx jest src", "lint": "eslint src", "ci": "npm run lint && npm run test", - "test:watch": "npm run test -- --watch", - "test:debug": "node --inspect-brk ../../node_modules/.bin/jest --runInBand" + "test": "vitest --watch=false src", + "test:watch": "vitest --watch src", + "test:debug": "node --inspect-brk vitest --runInBand" }, "keywords": [ "bitcoin", @@ -54,16 +54,10 @@ "@caravan/eslint-config": "*", "@caravan/multisig": "*", "@caravan/typescript-config": "*", - "@inrupt/jest-jsdom-polyfills": "^3.2.1", - "@jest/globals": "^29.7.0", - "@types/jest": "^29.5.12", "eslint-plugin-prettier": "^5.1.3", - "jest": "^29.4.1", "jsdom": "24.0.0", "jsdom-global": "3.0.2", "lodash": "^4.17.21", - "react-silence": "^1.0.4", - "ts-jest": "^29.1.2", "ts-node": "^10.9.2", "tsup": "^7.2.0", "typescript": "^5.2.2" diff --git a/packages/caravan-psbt/src/functions.test.ts b/packages/caravan-psbt/src/__tests__/functions.test.ts similarity index 95% rename from packages/caravan-psbt/src/functions.test.ts rename to packages/caravan-psbt/src/__tests__/functions.test.ts index fabb23b5..d0618420 100644 --- a/packages/caravan-psbt/src/functions.test.ts +++ b/packages/caravan-psbt/src/__tests__/functions.test.ts @@ -1,4 +1,4 @@ -import { bufferize } from "./functions"; +import { bufferize } from "../functions"; describe("bufferize", () => { it("should return a buffer when given a hex string", () => { diff --git a/packages/caravan-psbt/src/psbtv0/psbt.test.ts b/packages/caravan-psbt/src/__tests__/psbtv0/psbt.test.ts similarity index 98% rename from packages/caravan-psbt/src/psbtv0/psbt.test.ts rename to packages/caravan-psbt/src/__tests__/psbtv0/psbt.test.ts index 4204d912..186eafd8 100644 --- a/packages/caravan-psbt/src/psbtv0/psbt.test.ts +++ b/packages/caravan-psbt/src/__tests__/psbtv0/psbt.test.ts @@ -1,7 +1,3 @@ -/** - * @jest-environment jsdom - */ - import { generateMultisigFromHex, P2WSH, @@ -12,9 +8,9 @@ import { getUnsignedMultisigPsbtV0, validateMultisigPsbtSignature, translatePSBT, -} from "./psbt"; +} from "../../psbtv0/psbt"; import _ from "lodash"; -import { psbtArgsFromFixture } from "./utils"; +import { psbtArgsFromFixture } from "../../psbtv0/utils"; describe("getUnsignedMultisigPsbtV0", () => { TEST_FIXTURES.transactions diff --git a/packages/caravan-psbt/src/psbtv0/utils.test.ts b/packages/caravan-psbt/src/__tests__/psbtv0/utils.test.ts similarity index 82% rename from packages/caravan-psbt/src/psbtv0/utils.test.ts rename to packages/caravan-psbt/src/__tests__/psbtv0/utils.test.ts index ae3072ac..909872a1 100644 --- a/packages/caravan-psbt/src/psbtv0/utils.test.ts +++ b/packages/caravan-psbt/src/__tests__/psbtv0/utils.test.ts @@ -1,4 +1,4 @@ -import { autoLoadPSBT } from "./utils"; +import { autoLoadPSBT } from "../../psbtv0/utils"; describe("autoLoadPSBT", () => { it("should fail if you don't send a String", () => { diff --git a/packages/caravan-psbt/src/psbtv2/psbtv2.test.ts b/packages/caravan-psbt/src/__tests__/psbtv2/psbtv2.test.ts similarity index 99% rename from packages/caravan-psbt/src/psbtv2/psbtv2.test.ts rename to packages/caravan-psbt/src/__tests__/psbtv2/psbtv2.test.ts index 05e97595..e5de13a8 100644 --- a/packages/caravan-psbt/src/psbtv2/psbtv2.test.ts +++ b/packages/caravan-psbt/src/__tests__/psbtv2/psbtv2.test.ts @@ -1,8 +1,6 @@ -import { PsbtV2, getPsbtVersionNumber } from "./"; -import { test, jest } from "@jest/globals"; -import { silenceDescribe } from "react-silence"; +import { PsbtV2, getPsbtVersionNumber } from "../../psbtv2"; -import { KeyType, PsbtGlobalTxModifiableBits } from "./types"; +import { KeyType, PsbtGlobalTxModifiableBits } from "../../psbtv2/types"; const BIP_370_VECTORS_INVALID_PSBT = [ // Case: PSBTv0 but with PSBT_GLOBAL_VERSION set to 2. @@ -723,7 +721,14 @@ const BIP_174_VECTORS_VALID_PSBT = [ ]; describe("PsbtV2", () => { - silenceDescribe("error", "warn"); + beforeAll(() => { + vi.spyOn(console, "error").mockImplementation(() => {}); + vi.spyOn(console, "warn").mockImplementation(() => {}); + }); + + afterAll(() => { + vi.restoreAllMocks(); + }); test.each(BIP_370_VECTORS_INVALID_PSBT)( "Throws with BIP0370 test vectors. $case", @@ -895,9 +900,9 @@ describe("PsbtV2.isReadyForSigner", () => { }); it("Returns not ready for Signer when the psbt has already finalized inputs", () => { - jest - .spyOn(psbt, "isReadyForTransactionExtractor", "get") - .mockReturnValue(true); + vi.spyOn(psbt, "isReadyForTransactionExtractor", "get").mockReturnValue( + true, + ); expect(psbt.isReadyForSigner).toBe(false); }); @@ -1066,7 +1071,15 @@ describe("PsbtV2.nLockTime", () => { }); describe("PsbtV2.FromV0", () => { - silenceDescribe("error", "warn"); + beforeAll(() => { + vi.spyOn(console, "error").mockImplementation(() => {}); + vi.spyOn(console, "warn").mockImplementation(() => {}); + }); + + // Restore console methods + afterAll(() => { + vi.restoreAllMocks(); + }); test.each(BIP_174_VECTORS_INVALID_PSBT)( "Throws with BIP0174 test vectors. $case", @@ -1161,13 +1174,20 @@ describe("getPsbtVersionNumber", () => { }); describe("PsbtV2.addPartialSig", () => { - silenceDescribe("error", "warn"); + beforeAll(() => { + vi.spyOn(console, "error").mockImplementation(() => {}); + vi.spyOn(console, "warn").mockImplementation(() => {}); + }); + // Restore console methods + afterAll(() => { + vi.restoreAllMocks(); + }); let psbt; beforeEach(() => { psbt = new PsbtV2(); - psbt.handleSighashType = jest.fn(); + psbt.handleSighashType = vi.fn(); // This has to be added so inputs can be added else addSig will fail since // the input at the index does not exist. psbt.PSBT_GLOBAL_TX_MODIFIABLE = ["INPUTS"]; @@ -1229,7 +1249,7 @@ describe("PsbtV2.removePartialSig", () => { beforeEach(() => { psbt = new PsbtV2(); - psbt.handleSighashType = jest.fn(); + psbt.handleSighashType = vi.fn(); // This has to be added so inputs can be added else removeSig will fail // since the input at the index does not exist. psbt.PSBT_GLOBAL_TX_MODIFIABLE = ["INPUTS"]; diff --git a/packages/caravan-psbt/src/psbtv0/psbt.ts b/packages/caravan-psbt/src/psbtv0/psbt.ts index 9959ba60..dc86efd8 100644 --- a/packages/caravan-psbt/src/psbtv0/psbt.ts +++ b/packages/caravan-psbt/src/psbtv0/psbt.ts @@ -19,7 +19,7 @@ import { GlobalXpub } from "bip174/src/lib/interfaces.js"; // be sorted out and simplified then we can use the primary module with wasm import * as ecc from "../../vendor/tiny-secp256k1-asmjs/lib/index.js"; import * as bitcoin from "bitcoinjs-lib-v6"; -import { bufferize } from "src/functions"; +import { bufferize } from "../functions"; import BigNumber from "bignumber.js"; import { reverseBuffer } from "bitcoinjs-lib-v6/src/bufferutils.js"; import { autoLoadPSBT } from "./utils"; diff --git a/packages/caravan-psbt/tsconfig.json b/packages/caravan-psbt/tsconfig.json index 9a6082a3..addbeeda 100644 --- a/packages/caravan-psbt/tsconfig.json +++ b/packages/caravan-psbt/tsconfig.json @@ -2,14 +2,9 @@ "extends": "@caravan/typescript-config/base.json", "compilerOptions": { "baseUrl": ".", - "types": [ - "node", - "jest" - ], + "types": ["node", "vitest/globals"], "paths": { - "src/*": [ - "./src/*" - ] + "src/*": ["./src/*"] } } } diff --git a/vitest.config.ts b/vitest.config.ts index a72a2292..f6b75af9 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -6,6 +6,6 @@ export default defineConfig({ test: { include: ["./**/*.test.ts"], globals: true, - environment: "jsdom", + environment: "node", }, }); From 130e309d49e06a044111011f5ff5b1726b345628 Mon Sep 17 00:00:00 2001 From: Mrigesh Thakur <96632943+Legend101Zz@users.noreply.github.com> Date: Thu, 10 Oct 2024 21:21:38 +0530 Subject: [PATCH 2/2] refactor(tests): Migrate `caravan-bitcoin` tests from Jest to Vitest (#135) * refactor(tests): Migrate `caravan-bitcoin` tests from Jest to Vitest - Convert test suite to use Vitest syntax and APIs - Reorganising to test directory - Resolve empty test suite issues in convertExtendedPublicKey tests * fixes : Review fixes done --- packages/caravan-bitcoin/jest.config.js | 188 ---------------- packages/caravan-bitcoin/package.json | 4 +- .../src/{ => __tests__}/addresses.test.ts | 6 +- .../{ => __tests__}/block_explorer.test.ts | 24 +- .../src/{ => __tests__}/braid.test.ts | 48 ++-- .../src/{ => __tests__}/fees.test.ts | 49 ++--- .../src/{ => __tests__}/inputs.test.ts | 56 ++--- .../src/{ => __tests__}/keys.test.ts | 205 +++++++++--------- .../src/{ => __tests__}/multisig.test.ts | 32 +-- .../src/{ => __tests__}/networks.test.ts | 6 +- .../src/{ => __tests__}/outputs.test.ts | 48 ++-- .../src/{ => __tests__}/p2sh.test.ts | 4 +- .../src/{ => __tests__}/p2sh_p2wsh.test.ts | 4 +- .../src/{ => __tests__}/p2wsh.test.ts | 4 +- .../src/{ => __tests__}/paths.test.ts | 44 ++-- .../src/{ => __tests__}/psbt.test.ts | 62 +++--- .../src/{ => __tests__}/psbtv2.test.ts | 35 ++- .../src/{ => __tests__}/script.test.ts | 8 +- .../src/__tests__/signatures.test.ts | 62 ++++++ .../src/{ => __tests__}/transactions.test.ts | 18 +- .../src/{ => __tests__}/utils.test.ts | 6 +- .../caravan-bitcoin/src/signatures.test.ts | 43 ---- packages/caravan-bitcoin/tsconfig.json | 5 +- 23 files changed, 399 insertions(+), 562 deletions(-) delete mode 100644 packages/caravan-bitcoin/jest.config.js rename packages/caravan-bitcoin/src/{ => __tests__}/addresses.test.ts (96%) rename packages/caravan-bitcoin/src/{ => __tests__}/block_explorer.test.ts (84%) rename packages/caravan-bitcoin/src/{ => __tests__}/braid.test.ts (88%) rename packages/caravan-bitcoin/src/{ => __tests__}/fees.test.ts (88%) rename packages/caravan-bitcoin/src/{ => __tests__}/inputs.test.ts (94%) rename packages/caravan-bitcoin/src/{ => __tests__}/keys.test.ts (87%) rename packages/caravan-bitcoin/src/{ => __tests__}/multisig.test.ts (92%) rename packages/caravan-bitcoin/src/{ => __tests__}/networks.test.ts (93%) rename packages/caravan-bitcoin/src/{ => __tests__}/outputs.test.ts (86%) rename packages/caravan-bitcoin/src/{ => __tests__}/p2sh.test.ts (80%) rename packages/caravan-bitcoin/src/{ => __tests__}/p2sh_p2wsh.test.ts (81%) rename packages/caravan-bitcoin/src/{ => __tests__}/p2wsh.test.ts (97%) rename packages/caravan-bitcoin/src/{ => __tests__}/paths.test.ts (93%) rename packages/caravan-bitcoin/src/{ => __tests__}/psbt.test.ts (97%) rename packages/caravan-bitcoin/src/{ => __tests__}/psbtv2.test.ts (99%) rename packages/caravan-bitcoin/src/{ => __tests__}/script.test.ts (84%) create mode 100644 packages/caravan-bitcoin/src/__tests__/signatures.test.ts rename packages/caravan-bitcoin/src/{ => __tests__}/transactions.test.ts (97%) rename packages/caravan-bitcoin/src/{ => __tests__}/utils.test.ts (99%) delete mode 100644 packages/caravan-bitcoin/src/signatures.test.ts diff --git a/packages/caravan-bitcoin/jest.config.js b/packages/caravan-bitcoin/jest.config.js deleted file mode 100644 index b301498c..00000000 --- a/packages/caravan-bitcoin/jest.config.js +++ /dev/null @@ -1,188 +0,0 @@ -// For a detailed explanation regarding each configuration property, visit: -// https://jestjs.io/docs/en/configuration.html - -module.exports = { - // All imported modules in your tests should be mocked automatically - // automock: false, - - // Stop running tests after `n` failures - // bail: 0, - - // Respect "browser" field in package.json when resolving modules - // browser: false, - - // The directory where Jest should store its cached dependency information - // cacheDirectory: "/tmp/jest_rs", - - // Automatically clear mock calls and instances between every test - clearMocks: true, - - // Indicates whether the coverage information should be collected while executing the test - // collectCoverage: false, - - // An array of glob patterns indicating a set of files for which coverage information should be collected - // collectCoverageFrom: null, - - // The directory where Jest should output its coverage files - coverageDirectory: "coverage", - - // An array of regexp pattern strings used to skip coverage collection - // coveragePathIgnorePatterns: [ - // "/node_modules/" - // ], - - // A list of reporter names that Jest uses when writing coverage reports - // coverageReporters: [ - // "json", - // "text", - // "lcov", - // "clover" - // ], - - // An object that configures minimum threshold enforcement for coverage results - // coverageThreshold: null, - - // A path to a custom dependency extractor - // dependencyExtractor: null, - - // Make calling deprecated APIs throw helpful error messages - // errorOnDeprecated: false, - - // Force coverage collection from ignored files using an array of glob patterns - // forceCoverageMatch: [], - - // A path to a module which exports an async function that is triggered once before all test suites - // globalSetup: null, - - // A path to a module which exports an async function that is triggered once after all test suites - // globalTeardown: null, - - // A set of global variables that need to be available in all test environments - // globals: {}, - - // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers. - // maxWorkers: "50%", - - // An array of directory names to be searched recursively up from the requiring module's location - // moduleDirectories: [ - // "node_modules" - // ], - - // An array of file extensions your modules use - // moduleFileExtensions: [ - // "js", - // "json", - // "jsx", - // "ts", - // "tsx", - // "node" - // ], - - // A map from regular expressions to module names that allow to stub out resources with a single module - // moduleNameMapper: {}, - - // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader - // modulePathIgnorePatterns: [], - - // Activates notifications for test results - // notify: false, - - // An enum that specifies notification mode. Requires { notify: true } - // notifyMode: "failure-change", - - // A preset that is used as a base for Jest's configuration - // preset: null, - - // Run tests from one or more projects - // projects: null, - - // Use this configuration option to add custom reporters to Jest - // reporters: undefined, - - // Automatically reset mock state between every test - // resetMocks: false, - - // Reset the module registry before running each individual test - // resetModules: false, - - // A path to a custom resolver - // resolver: null, - - // Automatically restore mock state between every test - // restoreMocks: false, - - // The root directory that Jest should scan for tests and modules within - // rootDir: null, - - // A list of paths to directories that Jest should use to search for files in - // roots: [ - // "" - // ], - - // Allows you to use a custom runner instead of Jest's default test runner - // runner: "jest-runner", - - // The paths to modules that run some code to configure or set up the testing environment before each test - // setupFiles: [], - - // A list of paths to modules that run some code to configure or set up the testing framework before each test - // setupFilesAfterEnv: [], - - // A list of paths to snapshot serializer modules Jest should use for snapshot testing - // snapshotSerializers: [], - - // The test environment that will be used for testing - testEnvironment: "node", - - // Options that will be passed to the testEnvironment - // testEnvironmentOptions: {}, - - // Adds a location field to test results - // testLocationInResults: false, - - // The glob patterns Jest uses to detect test files - // testMatch: [ - // "**/__tests__/**/*.[jt]s?(x)", - // "**/?(*.)+(spec|test).[tj]s?(x)" - // ], - - // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped - // testPathIgnorePatterns: [ - // "/node_modules/" - // ], - - // The regexp pattern or array of patterns that Jest uses to detect test files - // testRegex: [], - - // This option allows the use of a custom results processor - // testResultsProcessor: null, - - // This option allows use of a custom test runner - // testRunner: "jasmine2", - - // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href - // testURL: "http://localhost", - - // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout" - // timers: "real", - - // A map from regular expressions to paths to transformers - // transform: null, - - // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation - // transformIgnorePatterns: [ - // "/node_modules/" - // ], - - // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them - // unmockedModulePathPatterns: undefined, - - // Indicates whether each individual test should be reported during the run - // verbose: null, - - // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode - // watchPathIgnorePatterns: [], - - // Whether to use watchman for file crawling - // watchman: true, -}; diff --git a/packages/caravan-bitcoin/package.json b/packages/caravan-bitcoin/package.json index d2d1906e..875de7af 100644 --- a/packages/caravan-bitcoin/package.json +++ b/packages/caravan-bitcoin/package.json @@ -67,8 +67,8 @@ "dev": "npm run build -- --watch", "lint": "eslint src/ --ext .ts", "ci": "npm run lint && npm run test", - "test": "jest src", - "test:watch": "jest --watch src" + "test": "vitest --watch=false src", + "test:watch": "vitest --watch src" }, "bin": {}, "dependencies": { diff --git a/packages/caravan-bitcoin/src/addresses.test.ts b/packages/caravan-bitcoin/src/__tests__/addresses.test.ts similarity index 96% rename from packages/caravan-bitcoin/src/addresses.test.ts rename to packages/caravan-bitcoin/src/__tests__/addresses.test.ts index b79a8252..439189be 100644 --- a/packages/caravan-bitcoin/src/addresses.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/addresses.test.ts @@ -1,6 +1,6 @@ -import { validateAddress } from "./addresses"; -import * as multisig from "./multisig"; -import { Network } from "./networks"; +import { validateAddress } from "../addresses"; +import * as multisig from "../multisig"; +import { Network } from "../networks"; const P2PKH = "P2PKH"; const P2TR = "P2TR"; diff --git a/packages/caravan-bitcoin/src/block_explorer.test.ts b/packages/caravan-bitcoin/src/__tests__/block_explorer.test.ts similarity index 84% rename from packages/caravan-bitcoin/src/block_explorer.test.ts rename to packages/caravan-bitcoin/src/__tests__/block_explorer.test.ts index 2e5610bf..f9e1dfdf 100644 --- a/packages/caravan-bitcoin/src/block_explorer.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/block_explorer.test.ts @@ -3,14 +3,14 @@ import { blockExplorerAPIURL, blockExplorerTransactionURL, blockExplorerAddressURL, -} from "./block_explorer"; -import { Network } from "./networks"; +} from "../block_explorer"; +import { Network } from "../networks"; describe("block_explorer", () => { describe("blockExplorerURL", () => { it("should properly return the base mainnet block explorer url for empty path", () => { expect(blockExplorerURL("", Network.MAINNET)).toBe( - "https://mempool.space" + "https://mempool.space", ); }); @@ -18,13 +18,13 @@ describe("block_explorer", () => { const path = "/block/00000000000000000011341d69792271766e4683e29b3ea169eacc59bde10a57"; expect(blockExplorerURL(path, Network.MAINNET)).toBe( - `https://mempool.space${path}` + `https://mempool.space${path}`, ); }); it("should properly return the base testnet block explorer url for empty path", () => { expect(blockExplorerURL("", Network.TESTNET)).toBe( - "https://mempool.space/testnet" + "https://mempool.space/testnet", ); }); @@ -32,7 +32,7 @@ describe("block_explorer", () => { const path = "/tx/4f0ef69f88829bd2f6b7793e32dd8bfcfbc87ddb9a2de3d8ef3f2aabbaff0be3"; expect(blockExplorerURL(path, Network.TESTNET)).toBe( - `https://mempool.space/testnet${path}` + `https://mempool.space/testnet${path}`, ); }); }); @@ -42,7 +42,7 @@ describe("block_explorer", () => { const path = "/tx/1814a10fb22e9551a17a94a1e68971e19b4f59eaf1689e0af85b97929b3b9ae0"; expect(blockExplorerAPIURL(path, Network.MAINNET)).toBe( - `https://mempool.space/api${path}` + `https://mempool.space/api${path}`, ); }); @@ -50,7 +50,7 @@ describe("block_explorer", () => { const path = "/tx/4f0ef69f88829bd2f6b7793e32dd8bfcfbc87ddb9a2de3d8ef3f2aabbaff0be3"; expect(blockExplorerAPIURL(path, Network.TESTNET)).toBe( - `https://mempool.space/testnet/api${path}` + `https://mempool.space/testnet/api${path}`, ); }); }); @@ -60,7 +60,7 @@ describe("block_explorer", () => { const path = "1814a10fb22e9551a17a94a1e68971e19b4f59eaf1689e0af85b97929b3b9ae0"; expect(blockExplorerTransactionURL(path, Network.MAINNET)).toBe( - `https://mempool.space/tx/${path}` + `https://mempool.space/tx/${path}`, ); }); @@ -68,7 +68,7 @@ describe("block_explorer", () => { const path = "4f0ef69f88829bd2f6b7793e32dd8bfcfbc87ddb9a2de3d8ef3f2aabbaff0be3"; expect(blockExplorerTransactionURL(path, Network.TESTNET)).toBe( - `https://mempool.space/testnet/tx/${path}` + `https://mempool.space/testnet/tx/${path}`, ); }); }); @@ -77,14 +77,14 @@ describe("block_explorer", () => { it("should properly return the mainnet block explorer address url for a given path", () => { const path = "39YqNoLULDpbjmeCTdGJ42DQhrQLzRcMdX"; expect(blockExplorerAddressURL(path, Network.MAINNET)).toBe( - `https://mempool.space/address/${path}` + `https://mempool.space/address/${path}`, ); }); it("should properly return the testnet block explorer address url for a given path", () => { const path = "2N16oE62ZjAPup985dFBQYAuy5zpDraH7Hk"; expect(blockExplorerAddressURL(path, Network.TESTNET)).toBe( - `https://mempool.space/testnet/address/${path}` + `https://mempool.space/testnet/address/${path}`, ); }); }); diff --git a/packages/caravan-bitcoin/src/braid.test.ts b/packages/caravan-bitcoin/src/__tests__/braid.test.ts similarity index 88% rename from packages/caravan-bitcoin/src/braid.test.ts rename to packages/caravan-bitcoin/src/__tests__/braid.test.ts index adb888af..d556138e 100644 --- a/packages/caravan-bitcoin/src/braid.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/braid.test.ts @@ -1,4 +1,4 @@ -import { TEST_FIXTURES } from "./fixtures"; +import { TEST_FIXTURES } from "../fixtures"; import { Braid, braidAddressType, @@ -15,7 +15,7 @@ import { generatePublicKeysAtIndex, generatePublicKeysAtPath, validateBip32PathForBraid, -} from "./braid"; +} from "../braid"; const BRAIDS = TEST_FIXTURES.braids; const MULTISIGS = TEST_FIXTURES.multisigs; @@ -63,16 +63,16 @@ describe("braids", () => { extendedPublicKeys, requiredSigners, index, - }) + }), ); expect(braidNetwork(defaultBraid)).toBe(BRAIDS[0].network); expect(braidAddressType(defaultBraid)).toBe(BRAIDS[0].addressType); expect(braidExtendedPublicKeys(defaultBraid)).toBe( - BRAIDS[0].extendedPublicKeys + BRAIDS[0].extendedPublicKeys, ); expect(braidRequiredSigners(defaultBraid)).toBe( - BRAIDS[0].requiredSigners + BRAIDS[0].requiredSigners, ); expect(braidIndex(defaultBraid)).toBe(BRAIDS[0].index); @@ -83,7 +83,7 @@ describe("braids", () => { extendedPublicKeys, requiredSigners, index, - }) + }), ).toStrictEqual(defaultBraid); }); @@ -111,76 +111,76 @@ describe("braids", () => { }); expect(generatePublicKeysAtIndex(stringBraid, 0)).toEqual( - pubKeySets.index[0] + pubKeySets.index[0], ); }); it("should generate pubkeys at an index", () => { expect(generatePublicKeysAtIndex(defaultBraid, 0)).toEqual( - pubKeySets.index[0] + pubKeySets.index[0], ); expect(generatePublicKeysAtIndex(defaultBraid, 1)).toEqual( - pubKeySets.index[1] + pubKeySets.index[1], ); expect(generatePublicKeysAtIndex(defaultBraid, 48349)).toEqual( - pubKeySets.index[48349] + pubKeySets.index[48349], ); }); it("should generate pubkeys at path", () => { expect(generatePublicKeysAtPath(defaultBraid, "0/0")).toEqual( - pubKeySets.path["0/0"] + pubKeySets.path["0/0"], ); expect(generatePublicKeysAtPath(defaultBraid, "m/0/0")).toEqual( - pubKeySets.path["0/0"] + pubKeySets.path["0/0"], ); }); it("should fail to generate pubkeys at path", () => { expect(() => generatePublicKeysAtPath(defaultBraid, "1/0")).toThrow( - /Cannot derive paths outside of the braid's index/i + /Cannot derive paths outside of the braid's index/i, ); expect(() => - generatePublicKeysAtPath(defaultBraid, "48349/0/0/0") + generatePublicKeysAtPath(defaultBraid, "48349/0/0/0"), ).toThrow(/Cannot derive paths outside of the braid's index/i); }); it("should generate getBip32Derivation at index", () => { expect(generateBip32DerivationByIndex(defaultBraid, 0)).toEqual( - bip32Derivations.index[0] + bip32Derivations.index[0], ); expect(generateBip32DerivationByIndex(defaultBraid, 1)).toEqual( - bip32Derivations.index[1] + bip32Derivations.index[1], ); expect(generateBip32DerivationByIndex(defaultBraid, 48349)).toEqual( - bip32Derivations.index[48349] + bip32Derivations.index[48349], ); }); it("should generate getBip32Derivation at path", () => { expect(generateBip32DerivationByPath(defaultBraid, "0/0")).toEqual( - bip32Derivations.path["0/0"] + bip32Derivations.path["0/0"], ); }); it("should fail to generate getBip32Derivation at path", () => { expect(() => generateBip32DerivationByPath(defaultBraid, "1/0")).toThrow( - /Cannot derive paths outside of the braid's index/i + /Cannot derive paths outside of the braid's index/i, ); expect(() => - generateBip32DerivationByPath(defaultBraid, "48349/0/0/0") + generateBip32DerivationByPath(defaultBraid, "48349/0/0/0"), ).toThrow(/Cannot derive paths outside of the braid's index/i); }); it("should generate braid-aware multisig at index 0", () => { expect(deriveMultisigByIndex(defaultBraid, 0)).toEqual( - expect.objectContaining(MULTISIGS[0].braidAwareMultisig) + expect.objectContaining(MULTISIGS[0].braidAwareMultisig), ); }); it("should generate braid-aware multisig at path 0/0", () => { expect(deriveMultisigByPath(defaultBraid, "0/0")).toEqual( - expect.objectContaining(MULTISIGS[0].braidAwareMultisig) + expect.objectContaining(MULTISIGS[0].braidAwareMultisig), ); }); @@ -198,8 +198,8 @@ describe("braids", () => { addressType, extendedPublicKeys, requiredSigners, - index - ) + index, + ), ).toStrictEqual(defaultBraid); }); diff --git a/packages/caravan-bitcoin/src/fees.test.ts b/packages/caravan-bitcoin/src/__tests__/fees.test.ts similarity index 88% rename from packages/caravan-bitcoin/src/fees.test.ts rename to packages/caravan-bitcoin/src/__tests__/fees.test.ts index 205fa6a2..84327652 100644 --- a/packages/caravan-bitcoin/src/fees.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/fees.test.ts @@ -1,6 +1,5 @@ import BigNumber from "bignumber.js"; - -import { FeeValidationError } from "./types"; +import { FeeValidationError } from "../types"; import { validateFeeRate, validateFee, @@ -8,10 +7,10 @@ import { estimateMultisigTransactionFeeRate, checkFeeError, checkFeeRateError, -} from "./fees"; -import { P2SH } from "./p2sh"; -import { P2SH_P2WSH } from "./p2sh_p2wsh"; -import { P2WSH } from "./p2wsh"; +} from "../fees"; +import { P2SH } from "../p2sh"; +import { P2SH_P2WSH } from "../p2sh_p2wsh"; +import { P2WSH } from "../p2wsh"; describe("fees", () => { describe("validateFeeRate", () => { @@ -19,7 +18,7 @@ describe("fees", () => { BigNumber.DEBUG = true; const feeRateSatsPerVbyte = null; expect(checkFeeRateError(feeRateSatsPerVbyte)).toBe( - FeeValidationError.INVALID_FEE_RATE + FeeValidationError.INVALID_FEE_RATE, ); expect(validateFeeRate(feeRateSatsPerVbyte)).toMatch(/invalid fee rate/i); BigNumber.DEBUG = false; @@ -28,7 +27,7 @@ describe("fees", () => { it("should return an error and message for an unparseable fee rate", () => { const feeRateSatsPerVbyte = "foo"; expect(checkFeeRateError(feeRateSatsPerVbyte)).toBe( - FeeValidationError.INVALID_FEE_RATE + FeeValidationError.INVALID_FEE_RATE, ); expect(validateFeeRate(feeRateSatsPerVbyte)).toMatch(/invalid fee rate/i); }); @@ -36,10 +35,10 @@ describe("fees", () => { it("should return an error and message for a negative fee rate", () => { const feeRateSatsPerVbyte = -1; expect(checkFeeRateError(feeRateSatsPerVbyte)).toBe( - FeeValidationError.FEE_RATE_CANNOT_BE_NEGATIVE + FeeValidationError.FEE_RATE_CANNOT_BE_NEGATIVE, ); expect(validateFeeRate(feeRateSatsPerVbyte)).toMatch( - /cannot be negative/i + /cannot be negative/i, ); }); @@ -52,7 +51,7 @@ describe("fees", () => { it("should return an error and message when the fee rate is too high", () => { const feeRateSatsPerVbyte = 10000; expect(checkFeeRateError(feeRateSatsPerVbyte)).toBe( - FeeValidationError.FEE_RATE_TOO_HIGH + FeeValidationError.FEE_RATE_TOO_HIGH, ); expect(validateFeeRate(feeRateSatsPerVbyte)).toMatch(/too high/i); }); @@ -72,7 +71,7 @@ describe("fees", () => { const feeSats = null; const inputsTotalSats = 1000000; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.INVALID_FEE + FeeValidationError.INVALID_FEE, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch(/invalid fee/i); BigNumber.DEBUG = false; @@ -83,10 +82,10 @@ describe("fees", () => { const feeSats = 10000; const inputsTotalSats = null; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.INVALID_INPUT_AMOUNT + FeeValidationError.INVALID_INPUT_AMOUNT, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch( - /invalid total input amount/i + /invalid total input amount/i, ); BigNumber.DEBUG = false; }); @@ -95,7 +94,7 @@ describe("fees", () => { const feeSats = "foo"; const inputsTotalSats = 1000000; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.INVALID_FEE + FeeValidationError.INVALID_FEE, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch(/invalid fee/i); }); @@ -104,10 +103,10 @@ describe("fees", () => { const feeSats = 10000; const inputsTotalSats = "foo"; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.INVALID_INPUT_AMOUNT + FeeValidationError.INVALID_INPUT_AMOUNT, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch( - /invalid total input amount/i + /invalid total input amount/i, ); }); @@ -115,10 +114,10 @@ describe("fees", () => { const feeSats = -1; const inputsTotalSats = 1000000; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.FEE_CANNOT_BE_NEGATIVE + FeeValidationError.FEE_CANNOT_BE_NEGATIVE, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch( - /cannot be negative/i + /cannot be negative/i, ); }); @@ -126,10 +125,10 @@ describe("fees", () => { const feeSats = 10000; const inputsTotalSats = -1; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.INPUT_AMOUNT_MUST_BE_POSITIVE + FeeValidationError.INPUT_AMOUNT_MUST_BE_POSITIVE, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch( - /must be positive/i + /must be positive/i, ); }); @@ -137,10 +136,10 @@ describe("fees", () => { const feeSats = 10000; const inputsTotalSats = 0; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.INPUT_AMOUNT_MUST_BE_POSITIVE + FeeValidationError.INPUT_AMOUNT_MUST_BE_POSITIVE, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch( - /must be positive/i + /must be positive/i, ); }); @@ -155,7 +154,7 @@ describe("fees", () => { const feeSats = 2500001; const inputsTotalSats = 10000000; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.FEE_TOO_HIGH + FeeValidationError.FEE_TOO_HIGH, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch(/too high/i); }); @@ -164,7 +163,7 @@ describe("fees", () => { const feeSats = 100001; const inputsTotalSats = 100000; expect(checkFeeError(feeSats, inputsTotalSats)).toBe( - FeeValidationError.FEE_TOO_HIGH + FeeValidationError.FEE_TOO_HIGH, ); expect(validateFee(feeSats, inputsTotalSats)).toMatch(/too high/i); }); diff --git a/packages/caravan-bitcoin/src/inputs.test.ts b/packages/caravan-bitcoin/src/__tests__/inputs.test.ts similarity index 94% rename from packages/caravan-bitcoin/src/inputs.test.ts rename to packages/caravan-bitcoin/src/__tests__/inputs.test.ts index 7fb22608..efc17927 100644 --- a/packages/caravan-bitcoin/src/inputs.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/inputs.test.ts @@ -4,7 +4,7 @@ import { validateMultisigInput, validateTransactionID, validateTransactionIndex, -} from "./inputs"; +} from "../inputs"; const VALID_TXID = "65e7ef764030dabfb46e3ae1c357b0666d0dda722c9809fb73245d6d68665284"; @@ -51,7 +51,7 @@ describe("inputs", () => { describe("validateMultisigInputs", () => { it("should return an error message with no inputs", () => { expect(validateMultisigInputs([])).toMatch( - /At least one input.+required/i + /At least one input.+required/i, ); }); @@ -60,7 +60,7 @@ describe("inputs", () => { validateMultisigInputs([ { txid: VALID_TXID, index: 0 }, { txid: VALID_TXID, index: 1, multisig: true }, - ]) + ]), ).toMatch(/not have a multisig.+property/i); }); @@ -69,7 +69,7 @@ describe("inputs", () => { validateMultisigInputs([ { txid: VALID_TXID, index: 0, multisig: true }, { txid: VALID_TXID, index: 0, multisig: true }, - ]) + ]), ).toMatch(/duplicate input/i); }); @@ -78,7 +78,7 @@ describe("inputs", () => { validateMultisigInputs([ { txid: VALID_TXID, index: 0, multisig: true }, { txid: VALID_TXID, index: 1, multisig: true }, - ]) + ]), ).toEqual(""); }); }); @@ -86,31 +86,31 @@ describe("inputs", () => { describe("validateMultisigInput", () => { it("should return an error message for a missing txid", () => { expect(validateMultisigInput({ index: 0, multisig: true })).toMatch( - /does not have.+txid/i + /does not have.+txid/i, ); }); it("should return an error message for an invalid txid", () => { expect( - validateMultisigInput({ index: 0, multisig: true, txid: "hi there" }) + validateMultisigInput({ index: 0, multisig: true, txid: "hi there" }), ).toMatch(/txid is invalid/i); }); it("should return an error message for a missing index", () => { expect( - validateMultisigInput({ txid: VALID_TXID, multisig: true }) + validateMultisigInput({ txid: VALID_TXID, multisig: true }), ).toMatch(/does not have.+index/i); }); it("should return an error message for an invalid index", () => { expect( - validateMultisigInput({ txid: VALID_TXID, index: -1, multisig: true }) + validateMultisigInput({ txid: VALID_TXID, index: -1, multisig: true }), ).toMatch(/index cannot be negative/i); }); it("should return an error message for a missing multisig", () => { expect(validateMultisigInput({ txid: VALID_TXID, index: 0 })).toMatch( - /does not have.+multisig/i + /does not have.+multisig/i, ); }); }); @@ -118,7 +118,7 @@ describe("inputs", () => { describe("validateBraidAwareMultisigInputs", () => { it("should return an error message with no inputs", () => { expect(validateMultisigInputs([], true)).toMatch( - /At least one input.+required/i + /At least one input.+required/i, ); }); @@ -133,8 +133,8 @@ describe("inputs", () => { multisig: { braidDetails: true, bip32Derivation: [] }, }, ], - true - ) + true, + ), ).toMatch(/not have a multisig.+property/i); }); @@ -145,8 +145,8 @@ describe("inputs", () => { { txid: VALID_TXID, index: 0, multisig: { braidDetails: true } }, { txid: VALID_TXID, index: 0, multisig: { braidDetails: true } }, ], - true - ) + true, + ), ).toMatch(/duplicate input/i); }); @@ -154,10 +154,10 @@ describe("inputs", () => { expect( validateMultisigInputs( [{ txid: VALID_TXID, index: 0, multisig: true }], - true - ) + true, + ), ).toMatch( - /input cannot be traced back to its set of extended public keys/i + /input cannot be traced back to its set of extended public keys/i, ); }); @@ -168,8 +168,8 @@ describe("inputs", () => { { txid: VALID_TXID, index: 0, multisig: { braidDetails: true } }, { txid: VALID_TXID, index: 1, multisig: { braidDetails: true } }, ], - true - ) + true, + ), ).toEqual(""); }); }); @@ -179,8 +179,8 @@ describe("inputs", () => { expect( validateMultisigInputs( [{ index: 0, multisig: { braidDetails: true } }], - true - ) + true, + ), ).toMatch(/does not have.+txid/i); }); @@ -188,7 +188,7 @@ describe("inputs", () => { expect( validateMultisigInputs([ { index: 0, multisig: { braidDetails: true }, txid: "hi there" }, - ]) + ]), ).toMatch(/txid is invalid/i); }); @@ -196,8 +196,8 @@ describe("inputs", () => { expect( validateMultisigInputs( [{ txid: VALID_TXID, multisig: { braidDetails: true } }], - true - ) + true, + ), ).toMatch(/does not have.+index/i); }); @@ -205,14 +205,14 @@ describe("inputs", () => { expect( validateMultisigInputs( [{ txid: VALID_TXID, index: -1, multisig: { braidDetails: true } }], - true - ) + true, + ), ).toMatch(/index cannot be negative/i); }); it("should return an error message for a missing multisig", () => { expect( - validateMultisigInputs([{ txid: VALID_TXID, index: 0 }], true) + validateMultisigInputs([{ txid: VALID_TXID, index: 0 }], true), ).toMatch(/does not have.+multisig/i); }); }); diff --git a/packages/caravan-bitcoin/src/keys.test.ts b/packages/caravan-bitcoin/src/__tests__/keys.test.ts similarity index 87% rename from packages/caravan-bitcoin/src/keys.test.ts rename to packages/caravan-bitcoin/src/__tests__/keys.test.ts index baa793c8..6a2249bc 100644 --- a/packages/caravan-bitcoin/src/keys.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/keys.test.ts @@ -18,16 +18,16 @@ import { extendedPublicKeyRootFingerprint, validateExtendedPublicKeyForNetwork, getMaskedDerivation, -} from "./keys"; +} from "../keys"; -import { Network } from "./networks"; +import { Network } from "../networks"; -import { TEST_FIXTURES } from "./fixtures"; +import { TEST_FIXTURES } from "../fixtures"; -import { P2SH } from "./p2sh"; -import { P2SH_P2WSH } from "./p2sh_p2wsh"; -import { P2WSH } from "./p2wsh"; -import { KeyPrefix } from "./types"; +import { P2SH } from "../p2sh"; +import { P2SH_P2WSH } from "../p2sh_p2wsh"; +import { P2WSH } from "../p2wsh"; +import { KeyPrefix } from "../types"; const NODES = TEST_FIXTURES.keys.open_source.nodes; const extendedPubKeyNode = NODES["m/45'/0'/0'"]; @@ -41,31 +41,31 @@ describe("keys", () => { it("returns an error message when the prefix does not match the network", () => { expect( - validateExtendedPublicKeyForNetwork("foobar", Network.TESTNET) + validateExtendedPublicKeyForNetwork("foobar", Network.TESTNET), ).toMatch(/must begin with/i); expect( - validateExtendedPublicKeyForNetwork("tpub", Network.MAINNET) + validateExtendedPublicKeyForNetwork("tpub", Network.MAINNET), ).toMatch(/must begin with/i); expect( - validateExtendedPublicKeyForNetwork(validTpub, Network.MAINNET) + validateExtendedPublicKeyForNetwork(validTpub, Network.MAINNET), ).toMatch(/must begin with/i); expect( - validateExtendedPublicKeyForNetwork(validXpub, Network.TESTNET) + validateExtendedPublicKeyForNetwork(validXpub, Network.TESTNET), ).toMatch(/must begin with/i); expect( - validateExtendedPublicKeyForNetwork(validXpub, Network.REGTEST) + validateExtendedPublicKeyForNetwork(validXpub, Network.REGTEST), ).toMatch(/must begin with/i); }); it("returns an empty string when the value is valid", () => { expect( - validateExtendedPublicKeyForNetwork(validTpub, Network.TESTNET) + validateExtendedPublicKeyForNetwork(validTpub, Network.TESTNET), ).toBe(""); expect( - validateExtendedPublicKeyForNetwork(validTpub, Network.REGTEST) + validateExtendedPublicKeyForNetwork(validTpub, Network.REGTEST), ).toBe(""); expect( - validateExtendedPublicKeyForNetwork(validXpub, Network.MAINNET) + validateExtendedPublicKeyForNetwork(validXpub, Network.MAINNET), ).toBe(""); }); }); @@ -78,56 +78,56 @@ describe("keys", () => { it("returns an error message on an empty value", () => { expect(validateExtendedPublicKey(undefined, Network.TESTNET)).toMatch( - /cannot be blank/i + /cannot be blank/i, ); expect(validateExtendedPublicKey("", Network.TESTNET)).toMatch( - /cannot be blank/i + /cannot be blank/i, ); expect(validateExtendedPublicKey(null, Network.TESTNET)).toMatch( - /cannot be blank/i + /cannot be blank/i, ); }); it("returns an error message when the prefix does not match the network", () => { expect(validateExtendedPublicKey("foobar", Network.TESTNET)).toMatch( - /must begin with/i + /must begin with/i, ); expect(validateExtendedPublicKey("tpub", Network.MAINNET)).toMatch( - /must begin with/i + /must begin with/i, ); expect(validateExtendedPublicKey(validTpub, Network.MAINNET)).toMatch( - /must begin with/i + /must begin with/i, ); expect(validateExtendedPublicKey(validXpub, Network.TESTNET)).toMatch( - /must begin with/i + /must begin with/i, ); }); it("returns an error message when the value is too short", () => { expect(validateExtendedPublicKey("tpub123", Network.TESTNET)).toMatch( - /is too short/i + /is too short/i, ); expect(validateExtendedPublicKey("xpub123", Network.MAINNET)).toMatch( - /is too short/i + /is too short/i, ); }); it("returns an error message when the value is too short", () => { expect(validateExtendedPublicKey("tpub123", Network.TESTNET)).toMatch( - /is too short/i + /is too short/i, ); expect(validateExtendedPublicKey("xpub123", Network.MAINNET)).toMatch( - /is too short/i + /is too short/i, ); }); it("returns an error message when the value is not valid", () => { // they both have 'n' in them expect( - validateExtendedPublicKey(validTpub.replace("n", "p"), Network.TESTNET) + validateExtendedPublicKey(validTpub.replace("n", "p"), Network.TESTNET), ).toMatch(/invalid/i); expect( - validateExtendedPublicKey(validXpub.replace("n", "p"), Network.MAINNET) + validateExtendedPublicKey(validXpub.replace("n", "p"), Network.MAINNET), ).toMatch(/invalid/i); }); @@ -156,7 +156,7 @@ describe("keys", () => { it("returns an error message on an invalid value", () => { expect(validatePublicKey(invalidPublicKey)).toMatch( - /invalid public key/i + /invalid public key/i, ); }); @@ -186,13 +186,13 @@ describe("keys", () => { it("returns an error message on a valid uncompressed public key used for P2SH-P2WSH", () => { expect(validatePublicKey(uncompressedPublicKey, P2SH_P2WSH)).toBe( - "P2SH-P2WSH does not support uncompressed public keys." + "P2SH-P2WSH does not support uncompressed public keys.", ); }); it("returns an error message on a valid uncompressed public key used for P2WSH", () => { expect(validatePublicKey(uncompressedPublicKey, P2WSH)).toBe( - "P2WSH does not support uncompressed public keys." + "P2WSH does not support uncompressed public keys.", ); }); @@ -202,7 +202,7 @@ describe("keys", () => { it("returns an error message on an invalid value used for P2SH", () => { expect(validatePublicKey(invalidPublicKey, P2SH)).toMatch( - /invalid public key/i + /invalid public key/i, ); }); }); @@ -211,31 +211,31 @@ describe("keys", () => { it("compresses public keys", () => { expect( compressPublicKey( - "04b32dc780fba98db25b4b72cf2b69da228f5e10ca6aa8f46eabe7f9fe22c994ee6e43c09d025c2ad322382347ec0f69b4e78d8e23c8ff9aa0dd0cb93665ae83d5" - ) + "04b32dc780fba98db25b4b72cf2b69da228f5e10ca6aa8f46eabe7f9fe22c994ee6e43c09d025c2ad322382347ec0f69b4e78d8e23c8ff9aa0dd0cb93665ae83d5", + ), ).toBe( - "03b32dc780fba98db25b4b72cf2b69da228f5e10ca6aa8f46eabe7f9fe22c994ee" + "03b32dc780fba98db25b4b72cf2b69da228f5e10ca6aa8f46eabe7f9fe22c994ee", ); expect( compressPublicKey( - "04f7946511e5f5c2697ed1a6c7f1fb7cfa6c03c74ac123b3d2d0c19ad25899baa6bd72af01ea2a58460fe34c2a2d48527f91da977a45a224f50028d937feb68660" - ) + "04f7946511e5f5c2697ed1a6c7f1fb7cfa6c03c74ac123b3d2d0c19ad25899baa6bd72af01ea2a58460fe34c2a2d48527f91da977a45a224f50028d937feb68660", + ), ).toBe( - "02f7946511e5f5c2697ed1a6c7f1fb7cfa6c03c74ac123b3d2d0c19ad25899baa6" + "02f7946511e5f5c2697ed1a6c7f1fb7cfa6c03c74ac123b3d2d0c19ad25899baa6", ); expect( compressPublicKey( - "04d87003b52cc497a6ca9a72fd610bcbfb2fe1430ffc4c9d89c2b25b501e04d677ee43c602a902993757d479d89b004f70a944de6db953594be98f397921b20162" - ) + "04d87003b52cc497a6ca9a72fd610bcbfb2fe1430ffc4c9d89c2b25b501e04d677ee43c602a902993757d479d89b004f70a944de6db953594be98f397921b20162", + ), ).toBe( - "02d87003b52cc497a6ca9a72fd610bcbfb2fe1430ffc4c9d89c2b25b501e04d677" + "02d87003b52cc497a6ca9a72fd610bcbfb2fe1430ffc4c9d89c2b25b501e04d677", ); expect( compressPublicKey( - "040354bd30fed4d431ee2acb51391128c72af8ee2bec8a303d977a40c85ba82e7b0456f8717352c5cb95fef87671109a66243e0b6d4917b3c33eb6aa5f33e5c09d" - ) + "040354bd30fed4d431ee2acb51391128c72af8ee2bec8a303d977a40c85ba82e7b0456f8717352c5cb95fef87671109a66243e0b6d4917b3c33eb6aa5f33e5c09d", + ), ).toBe( - "030354bd30fed4d431ee2acb51391128c72af8ee2bec8a303d977a40c85ba82e7b" + "030354bd30fed4d431ee2acb51391128c72af8ee2bec8a303d977a40c85ba82e7b", ); }); }); @@ -246,11 +246,11 @@ describe("keys", () => { deriveChildPublicKey( NODES["m/45'/0'/0'"].xpub, "m/0/0", - Network.MAINNET - ) + Network.MAINNET, + ), ).toBe(NODES["m/45'/0'/0'/0/0"].pub); expect( - deriveChildPublicKey(NODES["m/45'/0'/0'"].xpub, "0/0", Network.MAINNET) + deriveChildPublicKey(NODES["m/45'/0'/0'"].xpub, "0/0", Network.MAINNET), ).toBe(NODES["m/45'/0'/0'/0/0"].pub); }); @@ -259,11 +259,11 @@ describe("keys", () => { deriveChildPublicKey( NODES["m/45'/0'/0'"].tpub, "m/0/0", - Network.TESTNET - ) + Network.TESTNET, + ), ).toBe(NODES["m/45'/0'/0'/0/0"].pub); expect( - deriveChildPublicKey(NODES["m/45'/0'/0'"].tpub, "0/0", Network.TESTNET) + deriveChildPublicKey(NODES["m/45'/0'/0'"].tpub, "0/0", Network.TESTNET), ).toBe(NODES["m/45'/0'/0'/0/0"].pub); }); @@ -272,14 +272,14 @@ describe("keys", () => { deriveChildPublicKey( NODES["m/45'/0'/0'"].xpub, "m/99'", - Network.MAINNET + Network.MAINNET, ); }).toThrow(/missing private key/i); expect(() => { deriveChildPublicKey( NODES["m/45'/0'/0'"].xpub, "m/99'/0/0", - Network.MAINNET + Network.MAINNET, ); }).toThrow(/missing private key/i); }); @@ -289,14 +289,14 @@ describe("keys", () => { deriveChildPublicKey( NODES["m/45'/0'/0'"].xpub, "m/0/0", - Network.TESTNET + Network.TESTNET, ); }).toThrow(/invalid network/i); expect(() => { deriveChildPublicKey( NODES["m/45'/0'/0'"].tpub, "m/0/0", - Network.MAINNET + Network.MAINNET, ); }).toThrow(/invalid network/i); }); @@ -308,15 +308,15 @@ describe("keys", () => { deriveChildExtendedPublicKey( NODES["m/45'/0'/0'"].xpub, "m/0/0", - Network.MAINNET - ) + Network.MAINNET, + ), ).toBe(NODES["m/45'/0'/0'/0/0"].xpub); expect( deriveChildExtendedPublicKey( NODES["m/45'/0'/0'"].xpub, "0/0", - Network.MAINNET - ) + Network.MAINNET, + ), ).toBe(NODES["m/45'/0'/0'/0/0"].xpub); }); @@ -325,15 +325,15 @@ describe("keys", () => { deriveChildExtendedPublicKey( NODES["m/45'/0'/0'"].tpub, "m/0/0", - Network.TESTNET - ) + Network.TESTNET, + ), ).toBe(NODES["m/45'/0'/0'/0/0"].tpub); expect( deriveChildExtendedPublicKey( NODES["m/45'/0'/0'"].tpub, "0/0", - Network.TESTNET - ) + Network.TESTNET, + ), ).toBe(NODES["m/45'/0'/0'/0/0"].tpub); }); @@ -342,14 +342,14 @@ describe("keys", () => { deriveChildExtendedPublicKey( NODES["m/45'/0'/0'"].xpub, "m/99'", - Network.MAINNET + Network.MAINNET, ); }).toThrow(/missing private key/i); expect(() => { deriveChildExtendedPublicKey( NODES["m/45'/0'/0'"].xpub, "m/99'/0/0", - Network.MAINNET + Network.MAINNET, ); }).toThrow(/missing private key/i); }); @@ -359,14 +359,14 @@ describe("keys", () => { deriveChildExtendedPublicKey( NODES["m/45'/0'/0'"].xpub, "m/0/0", - Network.TESTNET + Network.TESTNET, ); }).toThrow(/invalid network/i); expect(() => { deriveChildExtendedPublicKey( NODES["m/45'/0'/0'"].tpub, "m/0/0", - Network.MAINNET + Network.MAINNET, ); }).toThrow(/invalid network/i); }); @@ -390,31 +390,40 @@ describe("keys", () => { describe("convertExtendedPublicKey", () => { it(`should fail to convert`, () => { expect(() => convertExtendedPublicKey("tpub", "xpub")).toThrow( - /Unable to convert extended/ + /Unable to convert extended/, ); }); - Object.keys(EXTENDED_PUBLIC_KEY_VERSIONS).forEach((_convertTo) => { - const convertTo = _convertTo as KeyPrefix; - describe(`Test converting to ${convertTo}`, () => { - Object.keys(EXTENDED_PUBLIC_KEY_VERSIONS).forEach((convertFrom) => { - if ( - convertFrom === convertTo || - !extendedPubKeyNode[convertFrom] || - !extendedPubKeyNode[convertTo] - ) { - return; - } - it(`should properly convert extended public key from ${convertFrom} to ${convertTo}`, () => { - const converted = convertExtendedPublicKey( - extendedPubKeyNode[convertFrom], - convertTo - ); - expect(converted).toBe(extendedPubKeyNode[convertTo]); - }); - }); - }); - }); + /** + * NOTE: vitest's `test.each()` treats empty describe + * blocks as errors, in contrast to jest which just ignores + * them. Using flatMap instead of forEach avoids + * potentially creating empty describe blocks for key types + * not present in extended pubkey nodes + */ + const validConversions = Object.keys(EXTENDED_PUBLIC_KEY_VERSIONS) + .flatMap((convertTo) => + Object.keys(EXTENDED_PUBLIC_KEY_VERSIONS).map((convertFrom) => ({ + convertTo, + convertFrom, + })), + ) + .filter( + ({ convertTo, convertFrom }) => + convertFrom !== convertTo && + extendedPubKeyNode[convertFrom] && + extendedPubKeyNode[convertTo as KeyPrefix], + ); + test.each(validConversions)( + "should properly convert extended public key from $convertFrom to $convertTo", + ({ convertFrom, convertTo }) => { + const converted = convertExtendedPublicKey( + extendedPubKeyNode[convertFrom], + convertTo as KeyPrefix, + ); + expect(converted).toBe(extendedPubKeyNode[convertTo as KeyPrefix]); + }, + ); }); describe("isKeyCompressed", () => { @@ -423,7 +432,7 @@ describe("keys", () => { "0487cb4929c287665fbda011b1afbebb0e691a5ee11ee9a561fcd6adba266afe03f7c55f784242305cfd8252076d038b0f3c92836754308d06b097d11e37bc0907"; expect(isKeyCompressed(uncompressedPubkey)).toBeFalsy(); expect( - isKeyCompressed(compressPublicKey(uncompressedPubkey)) + isKeyCompressed(compressPublicKey(uncompressedPubkey)), ).toBeTruthy(); const uncompressedPubkeyBuffer = Buffer.from(uncompressedPubkey, "hex"); @@ -476,7 +485,7 @@ describe("keys", () => { "0487cb4929c287665fbda011b1afbebb0e691a5ee11ee9a561fcd6adba266afe03f7c55f784242305cfd8252076d038b0f3c92836754308d06b097d11e37bc0907"; } const derivedXpub = ExtendedPublicKey.fromBase58( - deriveExtendedPublicKey(path, pubToUse, chaincode, parentFingerprint) + deriveExtendedPublicKey(path, pubToUse, chaincode, parentFingerprint), ); derivedXpub.setRootFingerprint(rootFingerprint); const derivedTpub = ExtendedPublicKey.fromBase58( @@ -485,11 +494,11 @@ describe("keys", () => { pubToUse, chaincode, parentFingerprint, - Network.TESTNET - ) + Network.TESTNET, + ), ); expect(extendedPublicKeyRootFingerprint(derivedXpub)).toEqual( - rootFingerprint + rootFingerprint, ); expect(extendedPublicKeyRootFingerprint(derivedTpub)).toBe(null); } @@ -528,14 +537,14 @@ describe("keys", () => { pub, chaincode, parentFingerprint, - Network.MAINNET + Network.MAINNET, ); const derivedTpub = deriveExtendedPublicKey( path, pub, chaincode, parentFingerprint, - Network.TESTNET + Network.TESTNET, ); expect(derivedXpub).toEqual(xpub); expect(derivedTpub).toEqual(tpub); @@ -597,12 +606,12 @@ describe("keys", () => { // test decoding (same as fromBase58) const decodedXpub = ExtendedPublicKey.decode(bs58check.decode(xpub)); const decodedTestnetXpub = ExtendedPublicKey.decode( - bs58check.decode(tpub) + bs58check.decode(tpub), ); expect(decodedXpub.version).toEqual(EXTENDED_PUBLIC_KEY_VERSIONS.xpub); expect(decodedTestnetXpub.version).toEqual( - EXTENDED_PUBLIC_KEY_VERSIONS.tpub + EXTENDED_PUBLIC_KEY_VERSIONS.tpub, ); expect(decodedXpub.parentFingerprint).toEqual(parentFingerprint); expect(decodedTestnetXpub.parentFingerprint).toEqual(parentFingerprint); @@ -642,7 +651,7 @@ describe("keys", () => { bip32Path: vect.path, }); expect(actual).toEqual(vect.path); - } + }, ); }); }); diff --git a/packages/caravan-bitcoin/src/multisig.test.ts b/packages/caravan-bitcoin/src/__tests__/multisig.test.ts similarity index 92% rename from packages/caravan-bitcoin/src/multisig.test.ts rename to packages/caravan-bitcoin/src/__tests__/multisig.test.ts index 49d08727..d9fe1a5c 100644 --- a/packages/caravan-bitcoin/src/multisig.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/multisig.test.ts @@ -1,6 +1,6 @@ -import { P2SH } from "./p2sh"; -import { P2WSH } from "./p2wsh"; -import { scriptToHex } from "./script"; +import { P2SH } from "../p2sh"; +import { P2WSH } from "../p2wsh"; +import { scriptToHex } from "../script"; import { generateMultisigFromHex, generateMultisigFromPublicKeys, @@ -13,9 +13,9 @@ import { multisigPublicKeys, multisigAddress, multisigBraidDetails, -} from "./multisig"; -import { TEST_FIXTURES } from "./fixtures"; -import { braidConfig } from "./braid"; +} from "../multisig"; +import { TEST_FIXTURES } from "../fixtures"; +import { braidConfig } from "../braid"; const MULTISIGS = TEST_FIXTURES.multisigs; @@ -27,7 +27,7 @@ describe("multisig", () => { badone.network, badone.type, 2, - ...badone.publicKeys + ...badone.publicKeys, ); expect(badMultisig).toBe(null); @@ -37,14 +37,14 @@ describe("multisig", () => { test.network, test.type, 2, - ...test.publicKeys + ...test.publicKeys, ); expect(multisigAddressType(multisig)).toEqual(test.type); expect(multisigRequiredSigners(multisig)).toEqual(2); expect(multisigTotalSigners(multisig)).toEqual(2); expect(multisigPublicKeys(multisig)).toEqual(test.publicKeys); expect(scriptToHex(multisigScript(multisig))).toEqual( - test.type === P2SH ? test.redeemScriptHex : test.witnessScriptHex + test.type === P2SH ? test.redeemScriptHex : test.witnessScriptHex, ); }); }); @@ -56,14 +56,14 @@ describe("multisig", () => { const multisig = generateMultisigFromHex( test.network, test.type, - test.type === P2SH ? test.redeemScriptHex : test.witnessScriptHex + test.type === P2SH ? test.redeemScriptHex : test.witnessScriptHex, ); expect(multisigAddressType(multisig)).toEqual(test.type); expect(multisigRequiredSigners(multisig)).toEqual(2); expect(multisigTotalSigners(multisig)).toEqual(2); expect(multisigPublicKeys(multisig)).toEqual(test.publicKeys); expect(scriptToHex(multisigScript(multisig))).toEqual( - test.multisigScriptHex + test.multisigScriptHex, ); }); }); @@ -97,7 +97,7 @@ describe("multisig", () => { MULTISIGS.forEach((test) => { it(`returns the multisig script for a ${test.network} 2-of-2 ${test.type} address`, () => { expect(scriptToHex(multisigScript(test.braidAwareMultisig))).toEqual( - test.multisigScriptHex + test.multisigScriptHex, ); }); }); @@ -112,7 +112,7 @@ describe("multisig", () => { } else { it(`returns the redeem script for a ${test.network} 2-of-2 ${test.type} address`, () => { expect( - scriptToHex(multisigRedeemScript(test.braidAwareMultisig)) + scriptToHex(multisigRedeemScript(test.braidAwareMultisig)), ).toEqual(test.redeemScriptHex); }); } @@ -128,7 +128,7 @@ describe("multisig", () => { } else { it(`returns the witness script for a ${test.network} 2-of-2 ${test.type} address`, () => { expect( - scriptToHex(multisigWitnessScript(test.braidAwareMultisig)) + scriptToHex(multisigWitnessScript(test.braidAwareMultisig)), ).toEqual(test.witnessScriptHex); }); } @@ -139,7 +139,7 @@ describe("multisig", () => { MULTISIGS.forEach((test) => { it(`returns the public keys for a ${test.network} 2-of-2 ${test.type} address`, () => { expect(multisigPublicKeys(test.braidAwareMultisig)).toEqual( - test.publicKeys + test.publicKeys, ); }); }); @@ -162,7 +162,7 @@ describe("multisig", () => { MULTISIGS.forEach((test) => { it(`returns the braidDetails for a ${test.network} 2-of-2 ${test.type} address`, () => { expect(multisigBraidDetails(test.braidAwareMultisig)).toBe( - braidConfig(test.braidDetails) + braidConfig(test.braidDetails), ); }); }); diff --git a/packages/caravan-bitcoin/src/networks.test.ts b/packages/caravan-bitcoin/src/__tests__/networks.test.ts similarity index 93% rename from packages/caravan-bitcoin/src/networks.test.ts rename to packages/caravan-bitcoin/src/__tests__/networks.test.ts index 76aa4396..ff5e9a12 100644 --- a/packages/caravan-bitcoin/src/networks.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/networks.test.ts @@ -3,7 +3,7 @@ import { networkLabel, networkData, getNetworkFromPrefix, -} from "./networks"; +} from "../networks"; import { networks } from "bitcoinjs-lib-v5"; @@ -27,10 +27,10 @@ describe("networks", () => { describe("getNetworkFromPrefix", () => { it("throws error on unknown prefix", () => { expect(() => getNetworkFromPrefix("foo")).toThrow( - /Unrecognized extended public key prefix/i + /Unrecognized extended public key prefix/i, ); expect(() => getNetworkFromPrefix("kpub")).toThrow( - /Unrecognized extended public key prefix/i + /Unrecognized extended public key prefix/i, ); }); it("returns testnet for testnet prefixes, case insensitive", () => { diff --git a/packages/caravan-bitcoin/src/outputs.test.ts b/packages/caravan-bitcoin/src/__tests__/outputs.test.ts similarity index 86% rename from packages/caravan-bitcoin/src/outputs.test.ts rename to packages/caravan-bitcoin/src/__tests__/outputs.test.ts index 61545644..db784184 100644 --- a/packages/caravan-bitcoin/src/outputs.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/outputs.test.ts @@ -2,8 +2,8 @@ import { validateOutputs, validateOutput, validateOutputAmount, -} from "./outputs"; -import { Network } from "./networks"; +} from "../outputs"; +import { Network } from "../networks"; import BigNumber from "bignumber.js"; describe("outputs", () => { @@ -12,7 +12,7 @@ describe("outputs", () => { describe("validateOutputs", () => { it("should return an error message if no outputs", () => { expect(validateOutputs(Network.TESTNET, [])).toMatch( - /At least one output is required/i + /At least one output is required/i, ); }); @@ -21,7 +21,7 @@ describe("outputs", () => { validateOutputs(Network.TESTNET, [ { address: validAddress, amountSats: 1000 }, { address: "foo", amountSats: 1000 }, - ]) + ]), ).toMatch(/invalid.+address/i); }); @@ -29,7 +29,7 @@ describe("outputs", () => { expect( validateOutputs(Network.TESTNET, [ { address: validAddress, amountSats: 1000 }, - ]) + ]), ).toEqual(""); }); }); @@ -37,7 +37,7 @@ describe("outputs", () => { describe("validateOutput", () => { it("should return an error message for a missing amount", () => { expect( - validateOutput(Network.TESTNET, { address: validAddress }) + validateOutput(Network.TESTNET, { address: validAddress }), ).toMatch(/does not have.+amountSats/i); }); @@ -47,7 +47,7 @@ describe("outputs", () => { validateOutput(Network.TESTNET, { address: validAddress, amountSats: "foo", - }) + }), ).toMatch(/invalid output amount/i); BigNumber.DEBUG = false; }); @@ -57,19 +57,19 @@ describe("outputs", () => { validateOutput(Network.TESTNET, { address: validAddress, amountSats: "foo", - }) + }), ).toMatch(/invalid output amount/i); }); it("should return an error message for a missing address", () => { expect(validateOutput(Network.TESTNET, { amountSats: 10000 })).toMatch( - /does not have.+address/i + /does not have.+address/i, ); }); it("should return an error message for an invalid address", () => { expect( - validateOutput(Network.TESTNET, { amountSats: 10000, address: "foo" }) + validateOutput(Network.TESTNET, { amountSats: 10000, address: "foo" }), ).toMatch(/invalid.+address/i); }); @@ -78,7 +78,7 @@ describe("outputs", () => { validateOutput(Network.TESTNET, { amountSats: 10000, address: validAddress, - }) + }), ).toEqual(""); }); }); @@ -90,20 +90,20 @@ describe("outputs", () => { it("should return an error message for a negative output amount", () => { expect(validateOutputAmount(-10000)).toMatch( - /output amount must be positive/i + /output amount must be positive/i, ); }); it("should return an error message for a zero output amount", () => { expect(validateOutputAmount(0)).toMatch( - /output amount must be positive/i + /output amount must be positive/i, ); }); it("should return an error message when the output is too small", () => { expect(validateOutputAmount(100)).toMatch(/output amount is too small/i); expect(validateOutputAmount(800, undefined, new BigNumber(1000))).toMatch( - /output amount is too small/i + /output amount is too small/i, ); }); @@ -115,7 +115,7 @@ describe("outputs", () => { it("should return an error message for an unparseable inputTotalSats amount", () => { BigNumber.DEBUG = true; expect(validateOutputAmount(1000, "foo")).toMatch( - /invalid total input amount/i + /invalid total input amount/i, ); BigNumber.DEBUG = false; @@ -123,52 +123,52 @@ describe("outputs", () => { it("should return an error message for an unparseable output amount", () => { expect(validateOutputAmount("foo", 100000)).toMatch( - /invalid output amount/i + /invalid output amount/i, ); }); it("should return an error message for a negative output amount", () => { expect(validateOutputAmount(-10000, 100000)).toMatch( - /output amount must be positive/i + /output amount must be positive/i, ); }); it("should return an error message for a zero output amount", () => { expect(validateOutputAmount(0, 100000)).toMatch( - /output amount must be positive/i + /output amount must be positive/i, ); }); it("should return an error message when the output is too small", () => { expect(validateOutputAmount(100, 100000)).toMatch( - /output amount is too small/i + /output amount is too small/i, ); expect(validateOutputAmount(800, 100000, new BigNumber(1000))).toMatch( - /output amount is too small/i + /output amount is too small/i, ); }); it("should return an error message for an unparseable total input amount", () => { expect(validateOutputAmount(100000, "foo")).toMatch( - /invalid total input amount/i + /invalid total input amount/i, ); }); it("should return an error message for a negative total input amount", () => { expect(validateOutputAmount(100000, -1000000)).toMatch( - /total input amount must be positive/i + /total input amount must be positive/i, ); }); it("should return an error message for a zero total input amount", () => { expect(validateOutputAmount(100000, 0)).toMatch( - /total input amount must be positive/i + /total input amount must be positive/i, ); }); it("should return an error message when the output is larger than the total input amount", () => { expect(validateOutputAmount(100001, 100000)).toMatch( - /output amount is too large/i + /output amount is too large/i, ); }); diff --git a/packages/caravan-bitcoin/src/p2sh.test.ts b/packages/caravan-bitcoin/src/__tests__/p2sh.test.ts similarity index 80% rename from packages/caravan-bitcoin/src/p2sh.test.ts rename to packages/caravan-bitcoin/src/__tests__/p2sh.test.ts index d07492a4..494e7ff2 100644 --- a/packages/caravan-bitcoin/src/p2sh.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/p2sh.test.ts @@ -1,4 +1,4 @@ -import { estimateMultisigP2SHTransactionVSize } from "./p2sh"; +import { estimateMultisigP2SHTransactionVSize } from "../p2sh"; describe("p2sh", () => { describe("estimateMultisigP2SHTransactionVSize", () => { @@ -9,7 +9,7 @@ describe("p2sh", () => { numOutputs: 2, m: 2, n: 3, - }) + }), ).toBe(391); }); }); diff --git a/packages/caravan-bitcoin/src/p2sh_p2wsh.test.ts b/packages/caravan-bitcoin/src/__tests__/p2sh_p2wsh.test.ts similarity index 81% rename from packages/caravan-bitcoin/src/p2sh_p2wsh.test.ts rename to packages/caravan-bitcoin/src/__tests__/p2sh_p2wsh.test.ts index 098452a3..dfaceb8f 100644 --- a/packages/caravan-bitcoin/src/p2sh_p2wsh.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/p2sh_p2wsh.test.ts @@ -1,4 +1,4 @@ -import { estimateMultisigP2SH_P2WSHTransactionVSize } from "./p2sh_p2wsh"; +import { estimateMultisigP2SH_P2WSHTransactionVSize } from "../p2sh_p2wsh"; describe("p2sh_p2wsh", () => { describe("estimateMultisigP2SH_P2WSHTransactionVSize", () => { @@ -9,7 +9,7 @@ describe("p2sh_p2wsh", () => { numOutputs: 2, m: 3, n: 5, - }) + }), ).toBe(444); // actual value from bitcoin core for P2PKH out }); }); diff --git a/packages/caravan-bitcoin/src/p2wsh.test.ts b/packages/caravan-bitcoin/src/__tests__/p2wsh.test.ts similarity index 97% rename from packages/caravan-bitcoin/src/p2wsh.test.ts rename to packages/caravan-bitcoin/src/__tests__/p2wsh.test.ts index f2b147e9..3a994307 100644 --- a/packages/caravan-bitcoin/src/p2wsh.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/p2wsh.test.ts @@ -3,7 +3,7 @@ import { getRedeemScriptSize, getWitnessSize, calculateBase, -} from "./p2wsh"; +} from "../p2wsh"; describe("p2wsh", () => { describe("estimateMultisigP2WSHTransactionVSize", () => { @@ -14,7 +14,7 @@ describe("p2wsh", () => { numOutputs: 2, m: 2, n: 3, - }) + }), ).toBe(202); // actual value from bitcoin core for P2PKH out }); const vsize = estimateMultisigP2WSHTransactionVSize({ diff --git a/packages/caravan-bitcoin/src/paths.test.ts b/packages/caravan-bitcoin/src/__tests__/paths.test.ts similarity index 93% rename from packages/caravan-bitcoin/src/paths.test.ts rename to packages/caravan-bitcoin/src/__tests__/paths.test.ts index 1e5bdbe5..10badde5 100644 --- a/packages/caravan-bitcoin/src/paths.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/paths.test.ts @@ -8,11 +8,11 @@ import { multisigBIP32Path, getParentBIP32Path, getRelativeBIP32Path, -} from "./paths"; -import { P2SH } from "./p2sh"; -import { P2SH_P2WSH } from "./p2sh_p2wsh"; -import { P2WSH } from "./p2wsh"; -import { Network } from "./networks"; +} from "../paths"; +import { P2SH } from "../p2sh"; +import { P2SH_P2WSH } from "../p2sh_p2wsh"; +import { P2WSH } from "../p2wsh"; +import { Network } from "../networks"; describe("paths", () => { describe("hardenedBIP32Index", () => { @@ -62,7 +62,7 @@ describe("paths", () => { it("returns an error message when a derivation index is too high", () => { expect(validateBIP32Path("m/4294967296")).toMatch(/index is too high/i); expect(validateBIP32Path("m/45'/2147483648'/0")).toMatch( - /index is too high/i + /index is too high/i, ); }); @@ -79,7 +79,7 @@ describe("paths", () => { expect(validateBIP32Path("m/45'/0")).toEqual(""); expect(validateBIP32Path("m/45'/0'", { mode: "hardened" })).toEqual(""); expect(validateBIP32Path("m/45'/0", { mode: "hardened" })).toMatch( - /fully-hardened/i + /fully-hardened/i, ); expect(validateBIP32Path("m/45'/0'", { mode: "hardened" })).toEqual(""); }); @@ -88,7 +88,7 @@ describe("paths", () => { expect(validateBIP32Path("m/45'/0")).toEqual(""); expect(validateBIP32Path("m/45/0", { mode: "unhardened" })).toEqual(""); expect(validateBIP32Path("m/45'/0", { mode: "unhardened" })).toMatch( - /cannot include hardened/i + /cannot include hardened/i, ); }); }); @@ -111,7 +111,7 @@ describe("paths", () => { it("returns an error message when the index is too high", () => { expect( - validateBIP32Index("85899345929999999999999999999999999999") + validateBIP32Index("85899345929999999999999999999999999999"), ).toMatch(/Invalid BIP32 index/i); expect(validateBIP32Index("4294967296")).toMatch(/index is too high/i); expect(validateBIP32Index("2147483648'")).toMatch(/index is too high/i); @@ -133,10 +133,10 @@ describe("paths", () => { expect(validateBIP32Index("45'", { mode: "hardened" })).toEqual(""); expect(validateBIP32Index("2147483648", { mode: "hardened" })).toEqual( - "" + "", ); expect(validateBIP32Index("45", { mode: "hardened" })).toMatch( - /must be hardened/i + /must be hardened/i, ); }); @@ -145,10 +145,10 @@ describe("paths", () => { expect(validateBIP32Index("45")).toEqual(""); expect(validateBIP32Index("45", { mode: "unhardened" })).toEqual(""); expect(validateBIP32Index("45'", { mode: "unhardened" })).toMatch( - /cannot be hardened/i + /cannot be hardened/i, ); expect(validateBIP32Index("2147483648", { mode: "unhardened" })).toMatch( - /cannot be hardened/i + /cannot be hardened/i, ); }); }); @@ -158,16 +158,16 @@ describe("paths", () => { expect(multisigBIP32Root(P2SH, Network.MAINNET)).toEqual("m/45'/0'/0'"); expect(multisigBIP32Root(P2SH, Network.TESTNET)).toEqual("m/45'/1'/0'"); expect(multisigBIP32Root(P2SH_P2WSH, Network.MAINNET)).toEqual( - "m/48'/0'/0'/1'" + "m/48'/0'/0'/1'", ); expect(multisigBIP32Root(P2SH_P2WSH, Network.TESTNET)).toEqual( - "m/48'/1'/0'/1'" + "m/48'/1'/0'/1'", ); expect(multisigBIP32Root(P2WSH, Network.MAINNET)).toEqual( - "m/48'/0'/0'/2'" + "m/48'/0'/0'/2'", ); expect(multisigBIP32Root(P2WSH, Network.TESTNET)).toEqual( - "m/48'/1'/0'/2'" + "m/48'/1'/0'/2'", ); }); @@ -190,16 +190,16 @@ describe("paths", () => { it("returns a BIP32 path with the correct root for each combination of address type, network, and relative path", () => { expect(multisigBIP32Path(P2SH, Network.MAINNET, "1")).toEqual( - "m/45'/0'/0'/1" + "m/45'/0'/0'/1", ); expect(multisigBIP32Path(P2SH, Network.TESTNET, "1'/2'")).toEqual( - "m/45'/1'/0'/1'/2'" + "m/45'/1'/0'/1'/2'", ); expect(multisigBIP32Path(P2SH_P2WSH, Network.MAINNET, "0")).toEqual( - "m/48'/0'/0'/1'/0" + "m/48'/0'/0'/1'/0", ); expect(multisigBIP32Path(P2WSH, Network.TESTNET, "3")).toEqual( - "m/48'/1'/0'/2'/3" + "m/48'/1'/0'/2'/3", ); }); @@ -238,7 +238,7 @@ describe("paths", () => { expect(getRelativeBIP32Path("m/45'", "foo")).toMatch(/is invalid/i); expect(getRelativeBIP32Path("m/45'", "/45")).toMatch(/is invalid/i); expect(getRelativeBIP32Path("m/44'", "m/45'")).toMatch( - /bip32Path does not start with the chroot/i + /bip32Path does not start with the chroot/i, ); const validPaths = [ "m/45'", diff --git a/packages/caravan-bitcoin/src/psbt.test.ts b/packages/caravan-bitcoin/src/__tests__/psbt.test.ts similarity index 97% rename from packages/caravan-bitcoin/src/psbt.test.ts rename to packages/caravan-bitcoin/src/__tests__/psbt.test.ts index 82c12109..4fdb1a8a 100644 --- a/packages/caravan-bitcoin/src/psbt.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/psbt.test.ts @@ -6,14 +6,14 @@ import { psbtInputFormatter, psbtOutputFormatter, translatePSBT, -} from "./psbt"; -import { ROOT_FINGERPRINT, TEST_FIXTURES } from "./fixtures"; +} from "../psbt"; +import { ROOT_FINGERPRINT, TEST_FIXTURES } from "../fixtures"; import { generateMultisigFromHex, generateMultisigFromPublicKeys, -} from "./multisig"; -import { braidConfig } from "./braid"; -import { P2WSH } from "./p2wsh"; +} from "../multisig"; +import { braidConfig } from "../braid"; +import { P2WSH } from "../p2wsh"; const MULTISIGS = TEST_FIXTURES.multisigs; const TRANSACTIONS = TEST_FIXTURES.transactions; @@ -27,7 +27,7 @@ describe("psbt", () => { const input = MULTISIGS[0].utxos[0]; input.bip32Path = null; expect(psbtInputFormatter(input).bip32Derivation).toEqual( - MULTISIGS[0].bip32Derivation + MULTISIGS[0].bip32Derivation, ); }); }); @@ -41,11 +41,11 @@ describe("psbt", () => { MULTISIGS[0].network, MULTISIGS[0].type, 2, - ...changePublicKeys + ...changePublicKeys, ); if (changeMultisig) { (changeMultisig as any).braidDetails = braidConfig( - MULTISIGS[0].changeBraidDetails + MULTISIGS[0].changeBraidDetails, ); (changeMultisig as any).bip32Derivation = MULTISIGS[0].changeBip32Derivation; @@ -53,7 +53,7 @@ describe("psbt", () => { output.multisig = changeMultisig; expect(MULTISIGS[0].transaction.outputs[1]).toEqual( - expect.objectContaining(psbtOutputFormatter(output)) + expect.objectContaining(psbtOutputFormatter(output)), ); }); }); @@ -68,8 +68,8 @@ describe("psbt", () => { { xfp: ROOT_FINGERPRINT, path: "m/45'/1'/100'", - } - ) + }, + ), ).toThrow(/Unsupported addressType/i); }); @@ -95,7 +95,7 @@ describe("psbt", () => { multisig: generateMultisigFromHex( tx.network, tx.format, - ms.redeemScriptHex + ms.redeemScriptHex, ), })); expect(unchainedInputs).toEqual(expectedInputs); @@ -111,7 +111,7 @@ describe("psbt", () => { expect(unchainedOutputs).toEqual(expectedOutputs); expect(bip32Derivations.map((b32d) => b32d.path)).toEqual( - tx.bip32Paths + tx.bip32Paths, ); } }); @@ -125,8 +125,8 @@ describe("psbt", () => { { xfp: ROOT_FINGERPRINT, path: "m/45'/1'/100'", - } - ) + }, + ), ).toBeNull(); }); @@ -143,7 +143,7 @@ describe("psbt", () => { describe("addSignaturesToPSBT", () => { // Function expects Buffers but our fixtures are hex strings const signaturesAsBuffers = tx.signature.map((sig) => - Buffer.from(sig, "hex") + Buffer.from(sig, "hex"), ); const signingPubKeyBuffer = Buffer.from(ms.publicKey, "hex"); const pubKeys = Array(signaturesAsBuffers.length).fill(signingPubKeyBuffer); @@ -153,7 +153,7 @@ describe("psbt", () => { tx.network, tx.psbt, pubKeys, - signaturesAsBuffers + signaturesAsBuffers, ); expect(psbtWithSignature).toEqual(ms.psbtOrderedPartiallySigned); @@ -161,7 +161,7 @@ describe("psbt", () => { it("throws validation error when trying to add valid signatures to the wrong pubkey", () => { const wrongPubKeys = Array(signaturesAsBuffers.length).fill( - Buffer.from(ms.publicKeys[1], "hex") + Buffer.from(ms.publicKeys[1], "hex"), ); expect(() => @@ -169,14 +169,14 @@ describe("psbt", () => { tx.network, tx.psbt, wrongPubKeys, - signaturesAsBuffers - ) + signaturesAsBuffers, + ), ).toThrow(/invalid signature/i); }); it("should return null with non-string PSBT input", () => { expect( - addSignaturesToPSBT(tx.network, [], pubKeys, signaturesAsBuffers) + addSignaturesToPSBT(tx.network, [], pubKeys, signaturesAsBuffers), ).toBeNull(); }); }); @@ -216,7 +216,7 @@ describe("psbt", () => { it("should return null if you send in a blank PSBT", () => { expect( - parseSignaturesFromPSBT("cHNidP8BAAoCAAAAAAAAAAAAAAAA") + parseSignaturesFromPSBT("cHNidP8BAAoCAAAAAAAAAAAAAAAA"), ).toBeNull(); }); @@ -232,7 +232,7 @@ describe("psbt", () => { ], }; expect( - parseSignaturesFromPSBT(singleInputB64PSBT_partiallySigned) + parseSignaturesFromPSBT(singleInputB64PSBT_partiallySigned), ).toEqual(oneSetOneInput); }); @@ -244,7 +244,7 @@ describe("psbt", () => { ], }; expect( - parseSignaturesFromPSBT(multiInputB64PSBT_partiallySigned) + parseSignaturesFromPSBT(multiInputB64PSBT_partiallySigned), ).toEqual(oneSetTwoInputs); }); @@ -258,7 +258,7 @@ describe("psbt", () => { ], }; expect(parseSignaturesFromPSBT(singleInputB64PSBT_fullySigned)).toEqual( - twoSetsOneInput + twoSetsOneInput, ); }); @@ -274,7 +274,7 @@ describe("psbt", () => { ], }; expect(parseSignaturesFromPSBT(multiInputB64PSBT_fullySigned)).toEqual( - twoSetsTwoInputs + twoSetsTwoInputs, ); }); }); @@ -286,7 +286,7 @@ describe("psbt", () => { it("should return null if you send in a blank PSBT", () => { expect( - parseSignatureArrayFromPSBT("cHNidP8BAAoCAAAAAAAAAAAAAAAA") + parseSignatureArrayFromPSBT("cHNidP8BAAoCAAAAAAAAAAAAAAAA"), ).toBeNull(); }); @@ -300,7 +300,7 @@ describe("psbt", () => { "3045022100fd9862cc751bd99f4b77b7d80f86701ba67e667912b2497f83f0d67d95c976ed02205ae2c4f01a361498709a5605baee70b985a9882c55ad022a8fed71e588f1350601", ]; expect( - parseSignatureArrayFromPSBT(singleInputHexPSBT_partiallySigned) + parseSignatureArrayFromPSBT(singleInputHexPSBT_partiallySigned), ).toEqual(oneSetOneInput); }); @@ -310,7 +310,7 @@ describe("psbt", () => { "3045022100a41cd24ac399c24449334d0a46906626de003e2b88a9c37e46f2cb0cbfbac0f602203c7524ec1c8f12d535a2212632865da1bef43bbe81c1b20ead12b6cbf7f44f9a01", ]; expect( - parseSignatureArrayFromPSBT(multiInputHexPSBT_partiallySigned) + parseSignatureArrayFromPSBT(multiInputHexPSBT_partiallySigned), ).toEqual(oneSetTwoInputs); }); @@ -324,7 +324,7 @@ describe("psbt", () => { ], ]; expect( - parseSignatureArrayFromPSBT(singleInputHexPSBT_fullySigned) + parseSignatureArrayFromPSBT(singleInputHexPSBT_fullySigned), ).toEqual(twoSetsOneInput); }); @@ -340,7 +340,7 @@ describe("psbt", () => { ], ]; expect( - parseSignatureArrayFromPSBT(multiInputHexPSBT_fullySigned) + parseSignatureArrayFromPSBT(multiInputHexPSBT_fullySigned), ).toEqual(twoSetsTwoInputs); }); }); diff --git a/packages/caravan-bitcoin/src/psbtv2.test.ts b/packages/caravan-bitcoin/src/__tests__/psbtv2.test.ts similarity index 99% rename from packages/caravan-bitcoin/src/psbtv2.test.ts rename to packages/caravan-bitcoin/src/__tests__/psbtv2.test.ts index 540ce9bc..c168b8bc 100644 --- a/packages/caravan-bitcoin/src/psbtv2.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/psbtv2.test.ts @@ -1,5 +1,4 @@ -import { PsbtV2, getPsbtVersionNumber } from "./psbtv2"; -import { test } from "@jest/globals"; +import { PsbtV2, getPsbtVersionNumber } from "../psbtv2"; import { silenceDescribe } from "react-silence"; const BIP_370_VECTORS_INVALID_PSBT = [ @@ -930,14 +929,14 @@ describe("PsbtV2.FromV0", () => { expect(t).toThrow(); } } - } + }, ); it("Throws with valid psbtv0 with PSBT_GLOBAL_TX_VERSION=1 when disallowing txnv1", () => { const t = () => PsbtV2.FromV0( "cHNidP8BAMUBAAAAA4RSZmhtXSRz+wmYLHLaDW1msFfD4TputL/aMEB27+dlAQAAAAD/////KgI+xaBWgfS8tWueRYhPYlqWZY4doW+ALhAuMaganq4BAAAAAP////9ErmEIocbg7uZe38fpG3ICYmN2nLh3FKmd1F24+8FD8gAAAAAA/////wIGcwQAAAAAABepFOO6EVG3Xv+/etxGc8g8j+7D3cNnh28dAAAAAAAAF6kUw01jpnIIZgcEkKjLJExr3Hzi+hOHAAAAAAABAPcCAAAAAAEBSckS0OXkb275MwOMf7fh1mXbmuVrZ/pX/kw0dqlc+VQAAAAAFxYAFADi94+YelpEk88GKZTb3knQQKki/v///wJjFBgAAAAAABepFMerbRAxgKSBgYR9NXMuk+DOmrBzh6CGAQAAAAAAF6kUhHkHLVpVDuCQC1r35wr1dVJ6h52HAkcwRAIgL1OHUuQItIF+d1HvJD7uZ9IkLKIGHo5snyKHMkfxCo0CIFtGIjFO/XM/EvxlV7wvMj/yy8FgStl6NRgH4b6Ah1vIASEC6SM19uyxhi8O6guZKX8hvbm+uaHo9BETeI9a3TBsqfzumxgAAQRHUiECqFE9mTGJbV06/IBjFI23XYhR/R/EGxCYuipqdm21Y9QhA5ON0Jvz3Snd9B8mSFisz6QLMwyY4O0nyvd3NPrAATm6Uq4iBgKoUT2ZMYltXTr8gGMUjbddiFH9H8QbEJi6Kmp2bbVj1Bj1fsZdLQAAgAEAAIBkAACAAAAAAAAAAAAiBgOTjdCb890p3fQfJkhYrM+kCzMMmODtJ8r3dzT6wAE5uhgAAAABLQAAgAEAAIBkAACAAAAAAAAAAAAAAQD3AgAAAAABAQF0Xh2qKMFwXb9z7dGD5e+RrQkY2XrT4uwsabVICG9NAAAAABcWABQrC1IrqH2xZGiYEYhgRJ/LLGna4/7///8CMpZCAAAAAAAXqRQPiU9+O3C4dB+DDgZrbvUIqfdHnYeghgEAAAAAABepFIR5By1aVQ7gkAta9+cK9XVSeoedhwJHMEQCIC3Ih+XWI72XSWgoXpyBZc+p+s2UPK8PhHLnrO9jL7lDAiBcYENAYeak5FNg07PJAanB3RSLON1sliPNj6JndYfmMgEhAjZlOGkv+5Yi51oF3CAE2F76DrwnuZlh5pTYj57eK1fK5JsYAAEER1IhAqhRPZkxiW1dOvyAYxSNt12IUf0fxBsQmLoqanZttWPUIQOTjdCb890p3fQfJkhYrM+kCzMMmODtJ8r3dzT6wAE5ulKuIgYCqFE9mTGJbV06/IBjFI23XYhR/R/EGxCYuipqdm21Y9QY9X7GXS0AAIABAACAZAAAgAAAAAAAAAAAIgYDk43Qm/PdKd30HyZIWKzPpAszDJjg7SfK93c0+sABOboYAAAAAS0AAIABAACAZAAAgAAAAAAAAAAAAAEA9wIAAAAAAQHl1qD/xfg4epDEY79hSuU2CbcpiMRK/GpXfyJma8lxpwAAAAAXFgAUKDhkidFbHN39JFtQa4/y2QmxjTb+////AqCGAQAAAAAAF6kUhHkHLVpVDuCQC1r35wr1dVJ6h52Hhs4YBQAAAAAXqRTS+wqJWOVdTGw/9Y+XD9u6MAbsB4cCRzBEAiAHpxhuavuT3nSbOpBdHHQ39HD5cJXqQQU4tqwz0VqUeAIgWmYRjH3C4U1zJaEi6wAh9U4dvV37j9VrJT+jeCcWrz0BIQP1lRzMzwCWTVTu+ngoCuCD4PDwzGOC/Sez+/3+2o3Sx7KbGAABBEdSIQKoUT2ZMYltXTr8gGMUjbddiFH9H8QbEJi6Kmp2bbVj1CEDk43Qm/PdKd30HyZIWKzPpAszDJjg7SfK93c0+sABObpSriIGAqhRPZkxiW1dOvyAYxSNt12IUf0fxBsQmLoqanZttWPUGPV+xl0tAACAAQAAgGQAAIAAAAAAAAAAACIGA5ON0Jvz3Snd9B8mSFisz6QLMwyY4O0nyvd3NPrAATm6GAAAAAEtAACAAQAAgGQAAIAAAAAAAAAAAAAAAQBHUiECGgSXRxIDRfqQF/tC2P89T7HS70yAVGhyxdpRO6vVFYUhA6AAld9INn7SHlxu3VCvQ1IxG/Bg6xAEJct69DMaoarQUq4iAgIaBJdHEgNF+pAX+0LY/z1PsdLvTIBUaHLF2lE7q9UVhRgAAAABLQAAgAEAAIBkAACAAQAAAAAAAAAiAgOgAJXfSDZ+0h5cbt1Qr0NSMRvwYOsQBCXLevQzGqGq0Bj1fsZdLQAAgAEAAIBkAACAAQAAAAAAAAAA", - false + false, ); expect(t).toThrow(); }); @@ -951,13 +950,13 @@ describe("PsbtV2.FromV0", () => { expect(t).not.toThrow(); } } - } + }, ); test.each( BIP_174_VECTORS_VALID_PSBT.filter( - (vect) => vect.inputs !== undefined && vect.outputs !== undefined - ) + (vect) => vect.inputs !== undefined && vect.outputs !== undefined, + ), )("Returns proper input and output counts. $case", (vect) => { const psbt = PsbtV2.FromV0(vect.hex, true); expect(psbt.PSBT_GLOBAL_INPUT_COUNT).toBe(vect.inputs); @@ -965,7 +964,7 @@ describe("PsbtV2.FromV0", () => { }); test.each( - BIP_174_VECTORS_VALID_PSBT.filter((vect) => vect.partialSigs !== undefined) + BIP_174_VECTORS_VALID_PSBT.filter((vect) => vect.partialSigs !== undefined), )("Sets partialSigs when they are present. $case", (vect) => { const psbt = PsbtV2.FromV0(vect.hex, true); const partialSigs = psbt.PSBT_IN_PARTIAL_SIG; @@ -1009,7 +1008,7 @@ describe("getPsbtVersionNumber", () => { (vect) => { const version = getPsbtVersionNumber(vect.psbt); expect(version).toEqual(vect.expected); - } + }, ); }); @@ -1018,7 +1017,7 @@ describe("PsbtV2.addPartialSig", () => { beforeEach(() => { psbt = new PsbtV2(); - psbt.handleSighashType = jest.fn(); + psbt.handleSighashType = vi.fn(); // This has to be added so inputs can be added else addSig will fail since // the input at the index does not exist. psbt.PSBT_GLOBAL_TX_MODIFIABLE = ["INPUTS"]; @@ -1031,14 +1030,14 @@ describe("PsbtV2.addPartialSig", () => { psbt.addInput({ previousTxId: Buffer.from([0x00]), outputIndex: 0 }); expect(() => addSig(0)).toThrow( - "PsbtV2.addPartialSig() missing argument pubkey" + "PsbtV2.addPartialSig() missing argument pubkey", ); expect(() => addSig(0, Buffer.from([0x00]))).toThrow( - "PsbtV2.addPartialSig() missing argument sig" + "PsbtV2.addPartialSig() missing argument sig", ); addSig(0, Buffer.from([0x00]), Buffer.from([0x00])); expect(() => addSig(0, Buffer.from([0x00]), Buffer.from([0x00]))).toThrow( - "PsbtV2 already has a signature for this input with this pubkey" + "PsbtV2 already has a signature for this input with this pubkey", ); }); @@ -1075,7 +1074,7 @@ describe("PsbtV2.removePartialSig", () => { beforeEach(() => { psbt = new PsbtV2(); - psbt.handleSighashType = jest.fn(); + psbt.handleSighashType = vi.fn(); // This has to be added so inputs can be added else removeSig will fail // since the input at the index does not exist. psbt.PSBT_GLOBAL_TX_MODIFIABLE = ["INPUTS"]; @@ -1088,7 +1087,7 @@ describe("PsbtV2.removePartialSig", () => { psbt.addInput({ previousTxId: Buffer.from([0x00]), outputIndex: 0 }); expect(() => removeSig(0, Buffer.from([0x00]))).toThrow( - "PsbtV2 input has no signature from pubkey 00" + "PsbtV2 input has no signature from pubkey 00", ); }); @@ -1175,7 +1174,7 @@ describe("PsbtV2.handleSighashType (private)", () => { (vect) => { psbt.handleSighashType(vect.value); expect(psbt.PSBT_GLOBAL_TX_MODIFIABLE).toEqual(vect.expectedModifiable); - } + }, ); }); @@ -1237,8 +1236,8 @@ describe("PsbtV2.isModifiable (private)", () => { expect(psbt.isModifiable(["OUTPUTS"])).toBe(vect.outputsExpected); expect(psbt.isModifiable(["OUTPUTS", "INPUTS"])).toBe(vect.bothExpected); expect(psbt.isModifiable(["SIGHASH_SINGLE"])).toBe( - vect.sighashSingleExpected + vect.sighashSingleExpected, ); - } + }, ); }); diff --git a/packages/caravan-bitcoin/src/script.test.ts b/packages/caravan-bitcoin/src/__tests__/script.test.ts similarity index 84% rename from packages/caravan-bitcoin/src/script.test.ts rename to packages/caravan-bitcoin/src/__tests__/script.test.ts index 57b742b8..b9eaba31 100644 --- a/packages/caravan-bitcoin/src/script.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/script.test.ts @@ -1,5 +1,5 @@ -import { scriptToOps, scriptToHex } from "./script"; -import { TEST_FIXTURES } from "./fixtures"; +import { scriptToOps, scriptToHex } from "../script"; +import { TEST_FIXTURES } from "../fixtures"; describe("scripts", () => { describe("scriptToOps", () => { @@ -8,7 +8,7 @@ describe("scripts", () => { if ("multisig" in test) { expect(scriptToOps(test.multisig)).toEqual(test.scriptOps); expect(scriptToOps(test.multisigScript)).toEqual( - test.multisigScriptOps + test.multisigScriptOps, ); } else { throw Error("does not contain a multisig"); @@ -23,7 +23,7 @@ describe("scripts", () => { if ("multisig" in test) { expect(scriptToHex(test.multisig)).toEqual(test.scriptHex); expect(scriptToHex(test.multisigScript)).toEqual( - test.multisigScriptHex + test.multisigScriptHex, ); } else { throw Error("does not contain a multisig"); diff --git a/packages/caravan-bitcoin/src/__tests__/signatures.test.ts b/packages/caravan-bitcoin/src/__tests__/signatures.test.ts new file mode 100644 index 00000000..270dd103 --- /dev/null +++ b/packages/caravan-bitcoin/src/__tests__/signatures.test.ts @@ -0,0 +1,62 @@ +import { validateMultisigSignature } from "../signatures"; +import { TEST_FIXTURES } from "../fixtures"; + +// FIXME: transactionbuilder is deprecating, but we know this. remove this after addressing. +// Mock console.warn +beforeAll(() => { + console.warn = vi.fn(); +}); + +describe("signatures", () => { + describe("validateMultisigSignature", () => { + it("throws an error on an invalid signature", () => { + const fixture = TEST_FIXTURES.transactions[0]; + expect(() => { + validateMultisigSignature( + fixture.network, + fixture.inputs, + fixture.outputs, + 0, + "", + ); + }).toThrow(/is too short/i); + expect(() => { + validateMultisigSignature( + fixture.network, + fixture.inputs, + fixture.outputs, + 0, + "foobar", + ); + }).toThrow(/is too short/i); + }); + + TEST_FIXTURES.transactions.forEach((fixture) => { + describe(`validating signature for a transaction which ${fixture.description}`, () => { + it("returns the public key corresponding to a valid input signature", () => { + fixture.inputs.forEach((input, inputIndex) => { + const publicKey = validateMultisigSignature( + fixture.network, + fixture.inputs, + fixture.outputs, + inputIndex, + fixture.signature[inputIndex], + ); + expect(publicKey).toEqual(fixture.publicKeys[inputIndex]); + }); + }); + + it("returns false for a valid signature for a different input", () => { + const publicKey = validateMultisigSignature( + fixture.network, + fixture.inputs, + fixture.outputs, + 0, + fixture.signature[1], + ); + expect(publicKey).toEqual(false); + }); + }); + }); + }); +}); diff --git a/packages/caravan-bitcoin/src/transactions.test.ts b/packages/caravan-bitcoin/src/__tests__/transactions.test.ts similarity index 97% rename from packages/caravan-bitcoin/src/transactions.test.ts rename to packages/caravan-bitcoin/src/__tests__/transactions.test.ts index 77b23d67..36d80a45 100644 --- a/packages/caravan-bitcoin/src/transactions.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/transactions.test.ts @@ -1,21 +1,21 @@ -import { generateMultisigFromHex } from "./multisig"; +import { generateMultisigFromHex } from "../multisig"; import { unsignedMultisigTransaction, signedMultisigTransaction, unsignedMultisigPSBT, unsignedTransactionObjectFromPSBT, -} from "./transactions"; -import { toHexString } from "./utils"; -import { P2SH } from "./p2sh"; -import { networkData, Network } from "./networks"; -import { TEST_FIXTURES } from "./fixtures"; -import { P2WSH } from "./p2wsh"; -import { P2SH_P2WSH } from "./p2sh_p2wsh"; +} from "../transactions"; +import { toHexString } from "../utils"; +import { P2SH } from "../p2sh"; +import { networkData, Network } from "../networks"; +import { TEST_FIXTURES } from "../fixtures"; +import { P2WSH } from "../p2wsh"; +import { P2SH_P2WSH } from "../p2sh_p2wsh"; import { address } from "bitcoinjs-lib-v5"; // FIXME: transactionbuilder is deprecating, but we know this. remove this after addressing. -console.warn = jest.fn(); +console.warn = vi.fn(); describe("transactions", () => { describe("unsignedMultisigTransaction", () => { diff --git a/packages/caravan-bitcoin/src/utils.test.ts b/packages/caravan-bitcoin/src/__tests__/utils.test.ts similarity index 99% rename from packages/caravan-bitcoin/src/utils.test.ts rename to packages/caravan-bitcoin/src/__tests__/utils.test.ts index 38198445..0a710e62 100644 --- a/packages/caravan-bitcoin/src/utils.test.ts +++ b/packages/caravan-bitcoin/src/__tests__/utils.test.ts @@ -5,7 +5,7 @@ import { satoshisToBitcoins, bitcoinsToSatoshis, hash160, -} from "./utils"; +} from "../utils"; describe("utils", () => { describe("validBase64", () => { @@ -122,11 +122,11 @@ describe("utils", () => { it("should take a buffer and hash it with sha256 and ripemd160", () => { const val = Buffer.from( "a2bc6de234a4b2fe10fe582f29c39de52b8161624ef310ca6cccff5d6d7d591a", - "hex" + "hex", ); const expected = Buffer.from( "d06d0dadca1f9cf3aedd5514e0669c2fffa7bc81", - "hex" + "hex", ); expect(hash160(val)).toEqual(expected); }); diff --git a/packages/caravan-bitcoin/src/signatures.test.ts b/packages/caravan-bitcoin/src/signatures.test.ts deleted file mode 100644 index de23aa63..00000000 --- a/packages/caravan-bitcoin/src/signatures.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { - validateMultisigSignature, -} from './signatures'; -import { - TEST_FIXTURES, -} from "./fixtures"; - -// FIXME: transactionbuilder is deprecating, but we know this. remove this after addressing. -console.warn = jest.fn(); - -describe('signatures', () => { - - describe('validateMultisigSignature', () => { - - it("throws an error on an invalid signature", () => { - const fixture = TEST_FIXTURES.transactions[0]; - expect(() => { validateMultisigSignature(fixture.network, fixture.inputs, fixture.outputs, 0, ""); }).toThrow(/is too short/i); - expect(() => { validateMultisigSignature(fixture.network, fixture.inputs, fixture.outputs, 0, "foobar"); }).toThrow(/is too short/i); - }); - - TEST_FIXTURES.transactions.forEach((fixture) => { - - describe(`validating signature for a transaction which ${fixture.description}`, () => { - - it("returns the public key corresponding to a valid input signature", () => { - fixture.inputs.forEach((input, inputIndex) => { - const publicKey = validateMultisigSignature(fixture.network, fixture.inputs, fixture.outputs, inputIndex, fixture.signature[inputIndex]); - expect(publicKey).toEqual(fixture.publicKeys[inputIndex]); - }); - }); - - it("returns false for a valid signature for a different input", () => { - const publicKey = validateMultisigSignature(fixture.network, fixture.inputs, fixture.outputs, 0, fixture.signature[1]); - expect(publicKey).toEqual(false); - }); - - }); - - }); - - }); - -}); diff --git a/packages/caravan-bitcoin/tsconfig.json b/packages/caravan-bitcoin/tsconfig.json index 66d43cf0..4aaa49be 100644 --- a/packages/caravan-bitcoin/tsconfig.json +++ b/packages/caravan-bitcoin/tsconfig.json @@ -17,8 +17,7 @@ // Ensure that Babel can safely transpile files in the TypeScript project "isolatedModules": true, "outDir": "lib", + "types": ["vitest/globals"] }, - "include": [ - "src" - ], + "include": ["src"] }