diff --git a/.github/workflows/npm-typescript.yml b/.github/workflows/npm-typescript.yml index e1e97e733..c950491a1 100644 --- a/.github/workflows/npm-typescript.yml +++ b/.github/workflows/npm-typescript.yml @@ -19,7 +19,7 @@ jobs: - uses: actions/setup-node@v3 with: - node-version: "14.x" + node-version: "18.x" registry-url: "https://registry.npmjs.org" cache: "yarn" cache-dependency-path: typescript/yarn.lock diff --git a/typescript/README.adoc b/typescript/README.adoc index 36fadc0c0..9d518ab76 100644 --- a/typescript/README.adoc +++ b/typescript/README.adoc @@ -14,8 +14,8 @@ toc::[] Please make sure you have the following prerequisites installed on your machine: -- https://nodejs.org[Node.js] >14.17.4 -- https://yarnpkg.com[Yarn] >1.22.10 +- https://nodejs.org[Node.js] >=16 +- https://yarnpkg.com[Yarn] >=1.22.19 === Install dependencies diff --git a/typescript/package.json b/typescript/package.json index bc3627f9d..b7cc037e9 100644 --- a/typescript/package.json +++ b/typescript/package.json @@ -1,6 +1,6 @@ { "name": "@keep-network/tbtc-v2.ts", - "version": "1.4.0-dev", + "version": "2.0.0-dev", "license": "MIT", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -16,7 +16,9 @@ "dev": "tsc --project tsconfig.build.json --watch" }, "files": [ - "dist" + "dist/", + "src/", + "typechain/" ], "config": { "contracts": "./node_modules/@keep-network/ecdsa/artifacts/WalletRegistry.json ./node_modules/@keep-network/tbtc-v2/artifacts/{Bridge,TBTCVault,TBTC}.json" diff --git a/typescript/scripts/README.adoc b/typescript/scripts/README.adoc index b057d463a..da1ad4bdb 100644 --- a/typescript/scripts/README.adoc +++ b/typescript/scripts/README.adoc @@ -12,8 +12,8 @@ toc::[] Please make sure you have the following prerequisites installed on your machine: -- https://nodejs.org[Node.js] >14.18.0 -- https://yarnpkg.com[Yarn] >1.22.19 +- https://nodejs.org[Node.js] >=16 +- https://yarnpkg.com[Yarn] >=1.22.19 tBTCv2 system prerequisite is that you can refund your BTC only if it was not used for minting tBTC and after `refundLocktime` has passed. diff --git a/typescript/src/lib/bitcoin/address.ts b/typescript/src/lib/bitcoin/address.ts index fb41e8221..02149b8b4 100644 --- a/typescript/src/lib/bitcoin/address.ts +++ b/typescript/src/lib/bitcoin/address.ts @@ -5,13 +5,13 @@ import { BitcoinNetwork, toBitcoinJsLibNetwork } from "./network" /** * Creates the Bitcoin address from the public key. Supports SegWit (P2WPKH) and * Legacy (P2PKH) formats. - * @param publicKey - Public key used to derive the Bitcoin address. - * @param bitcoinNetwork - Target Bitcoin network. - * @param witness - Flag to determine address format: true for SegWit (P2WPKH) + * @param publicKey Compressed public key used to derive the Bitcoin address. + * @param bitcoinNetwork Target Bitcoin network. + * @param witness Flag to determine address format: true for SegWit (P2WPKH) * and false for Legacy (P2PKH). Default is true. * @returns The derived Bitcoin address. */ -export function publicKeyToAddress( +function publicKeyToAddress( publicKey: Hex, bitcoinNetwork: BitcoinNetwork, witness: boolean = true diff --git a/typescript/src/lib/bitcoin/csuint.ts b/typescript/src/lib/bitcoin/csuint.ts index e0576e176..e32dc8932 100644 --- a/typescript/src/lib/bitcoin/csuint.ts +++ b/typescript/src/lib/bitcoin/csuint.ts @@ -14,6 +14,10 @@ function read(varLenData: Hex): { value: number byteLength: number } { + if (varLenData.toString().length == 0) { + throw new Error("Empty variable length data argument") + } + // The varLenData is prefixed with the compact size uint. According to the docs // (https://developer.bitcoin.org/reference/transactions.html#compactsize-unsigned-integers) // a compact size uint can be 1, 3, 5 or 9 bytes. To determine the exact length, @@ -26,12 +30,12 @@ function read(varLenData: Hex): { case "fe": case "fd": { throw new Error( - "support for 3, 5 and 9 bytes compact size uints is not implemented yet" + "Support for 3, 5 and 9 bytes compact size uints is not implemented yet" ) } default: { // The discriminant tells the compact size uint is 1 byte. That means - // the discriminant represent the value itself. + // the discriminant represents the value itself. return { value: parseInt(discriminant, 16), byteLength: 1, diff --git a/typescript/src/lib/bitcoin/ecdsa-key.ts b/typescript/src/lib/bitcoin/ecdsa-key.ts index 3dd1507b8..8ffbd9955 100644 --- a/typescript/src/lib/bitcoin/ecdsa-key.ts +++ b/typescript/src/lib/bitcoin/ecdsa-key.ts @@ -41,18 +41,13 @@ function compressPublicKey(publicKey: string | Hex): string { // The Y coordinate is the next 32 bytes. const publicKeyY = publicKey.substring(64) - let prefix: string - if (BigNumber.from(`0x${publicKeyY}`).mod(2).eq(0)) { - prefix = "02" - } else { - prefix = "03" - } + const prefix = BigNumber.from(`0x${publicKeyY}`).mod(2).eq(0) ? "02" : "03" return `${prefix}${publicKeyX}` } /** - * Utility functions allowing to perform Bitcoin ECDSA public keys. + * Utility functions allowing to perform operations on Bitcoin ECDSA public keys. */ export const BitcoinPublicKeyUtils = { isCompressedPublicKey, @@ -61,8 +56,8 @@ export const BitcoinPublicKeyUtils = { /** * Creates a Bitcoin key pair based on the given private key. - * @param privateKey Private key in the WIF format that should be used to create - * the key pair. + * @param privateKey Private key that should be used to create the key pair. + * Should be passed in the WIF format. * @param bitcoinNetwork Bitcoin network the given key pair is relevant for. * @returns Bitcoin key pair. */ @@ -78,7 +73,7 @@ function createKeyPair( } /** - * Utility functions allowing to perform Bitcoin ECDSA public keys. + * Utility functions allowing to perform operations on Bitcoin ECDSA private keys. */ export const BitcoinPrivateKeyUtils = { createKeyPair, diff --git a/typescript/src/lib/bitcoin/hash.ts b/typescript/src/lib/bitcoin/hash.ts index c92876aaf..3299d1df9 100644 --- a/typescript/src/lib/bitcoin/hash.ts +++ b/typescript/src/lib/bitcoin/hash.ts @@ -2,8 +2,8 @@ import { BigNumber, utils } from "ethers" import { Hex } from "../utils" /** - * Computes the HASH160 for the given text. - * @param text - Text the HASH160 is computed for. + * Computes the HASH160 (i.e. RIPEMD160(SHA256(text))) for the given text. + * @param text Text the HASH160 is computed for. * @returns 20-byte-long hash. */ function computeHash160(text: Hex): Hex { @@ -28,7 +28,7 @@ function computeHash256(text: Hex): Hex { /** * Converts a hash in hex string in little endian to a BigNumber. - * @param hash - Hash in hex-string format. + * @param hash Hash in hex-string format. * @returns BigNumber representation of the hash. */ function hashLEToBigNumber(hash: Hex): BigNumber { diff --git a/typescript/src/lib/bitcoin/header.ts b/typescript/src/lib/bitcoin/header.ts index 06531d933..99faa237a 100644 --- a/typescript/src/lib/bitcoin/header.ts +++ b/typescript/src/lib/bitcoin/header.ts @@ -147,7 +147,9 @@ export function validateBitcoinHeadersChain( if ( !previousBlockHeaderHash.equals(currentHeader.previousBlockHeaderHash) ) { - throw new Error("Invalid headers chain") + throw new Error( + `Invalid headers chain; problem with header index: ${index}` + ) } } diff --git a/typescript/src/lib/bitcoin/tx.ts b/typescript/src/lib/bitcoin/tx.ts index a61d1f37e..2ad886155 100644 --- a/typescript/src/lib/bitcoin/tx.ts +++ b/typescript/src/lib/bitcoin/tx.ts @@ -185,7 +185,7 @@ export function extractBitcoinRawTxVectors( /** * Converts Bitcoin specific locktime value to a number. The number represents - * either a block height or an Unix timestamp depending on the value. + * either a block height or a Unix timestamp, depending on the value. * * If the number is less than 500 000 000 it is a block height. * If the number is greater or equal 500 000 000 it is a Unix timestamp. diff --git a/typescript/test/lib/bitcoin.test.ts b/typescript/test/lib/bitcoin.test.ts index 25dade9b5..b04831493 100644 --- a/typescript/test/lib/bitcoin.test.ts +++ b/typescript/test/lib/bitcoin.test.ts @@ -776,8 +776,16 @@ describe("Bitcoin", () => { const { read } = BitcoinCompactSizeUint describe("read", () => { + context("when the compact size uint is empty", () => { + it("should throw", () => { + expect(() => { + return read(Hex.from("")) + }).to.throw("Empty variable length data argument") + }) + }) + context("when the compact size uint is 1-byte", () => { - it("should return the the uint value and byte length", () => { + it("should return the uint value and byte length", () => { expect(read(Hex.from("bb"))).to.be.eql({ value: 187, byteLength: 1, @@ -788,7 +796,7 @@ describe("Bitcoin", () => { context("when the compact size uint is 3-byte", () => { it("should throw", () => { expect(() => read(Hex.from("fd0302"))).to.throw( - "support for 3, 5 and 9 bytes compact size uints is not implemented yet" + "Support for 3, 5 and 9 bytes compact size uints is not implemented yet" ) }) }) @@ -796,7 +804,7 @@ describe("Bitcoin", () => { context("when the compact size uint is 5-byte", () => { it("should throw", () => { expect(() => read(Hex.from("fe703a0f00"))).to.throw( - "support for 3, 5 and 9 bytes compact size uints is not implemented yet" + "Support for 3, 5 and 9 bytes compact size uints is not implemented yet" ) }) }) @@ -806,7 +814,7 @@ describe("Bitcoin", () => { expect(() => { return read(Hex.from("ff57284e56dab40000")) }).to.throw( - "support for 3, 5 and 9 bytes compact size uints is not implemented yet" + "Support for 3, 5 and 9 bytes compact size uints is not implemented yet" ) }) })