diff --git a/.github/workflows/main_ci.yml b/.github/workflows/main_ci.yml index e9ba67bb2..2e197b4e6 100644 --- a/.github/workflows/main_ci.yml +++ b/.github/workflows/main_ci.yml @@ -8,6 +8,9 @@ on: permissions: contents: read + pages: write + id-token: write + jobs: ################## @@ -124,3 +127,31 @@ jobs: cache: 'npm' - run: npm ci - run: npm run lint:tests + + build-doc: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@ec3a7ce113134d7a93b817d10a8272cb61118579 # v2 + - uses: actions/setup-node@eeb10cff27034e7acf239c5d29f62154018672fd # v3 + with: + node-version: 'lts/*' + registry-url: https://registry.npmjs.org/ + cache: 'npm' + - run: npm ci + - run: npm run doc + - name: Upload artifact + uses: actions/upload-pages-artifact@v2 + with: + path: ./docs + + deploy-doc: + if: github.ref == 'refs/heads/master' + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build-doc + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v2 diff --git a/.gitignore b/.gitignore index d6ceb6b58..c1733a6e0 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ npm-debug.log test/*.js test/integration/*.js !test/ts-node-register.js +docs diff --git a/CHANGELOG.md b/CHANGELOG.md index d0485f0e8..91ed0dae5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -331,8 +331,8 @@ Ideally you shoud not have to directly access `HDNode` internals for general usa __added__ - `ECPair.prototype.getNetwork` -- `HDNode.prototype.getNetwork`, wraps the underyling keyPair's `getNetwork` method -- `HDNode.prototype.getPublicKeyBuffer`, wraps the underyling keyPair's `getPublicKeyBuffer` method +- `HDNode.prototype.getNetwork`, wraps the underlying keyPair's `getNetwork` method +- `HDNode.prototype.getPublicKeyBuffer`, wraps the underlying keyPair's `getPublicKeyBuffer` method - `HDNode.prototype.sign`, wraps the underlying keyPair's `sign` method - `HDNode.prototype.verify`, wraps the underlying keyPair's `verify` method diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c1df5e090..7797c92d2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,8 +14,8 @@ We are always accepting of pull requests, but we do adhere to specific standards GitHub is the preferred method of communication between members. Otherwise, in order of preference: -* bitcoinjs.slack.com -* #bitcoinjs-dev on Freenode IRC +* #bitcoinjs-dev:matrix.org on Matrix (A part of the #bitcoinjs-space:matrix.org "Space") +* #bitcoinjs on libera.chat IRC ## Workflow diff --git a/README.md b/README.md index 01a45733b..ba3700948 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ Mistakes and bugs happen, but with your help in resolving and reporting [issues] - Friendly, with a strong and helpful community, ready to answer questions. ## Documentation -Presently, we do not have any formal documentation other than our [examples](#examples), please [ask for help](https://github.com/bitcoinjs/bitcoinjs-lib/issues/new) if our examples aren't enough to guide you. +Visit our [documentation](https://bitcoinjs.github.io/bitcoinjs-lib/) to explore the available resources. We're continually enhancing our documentation with additional features for an enriched experience. If you need further guidance beyond what our [examples](#examples) offer, don't hesitate to [ask for help](https://github.com/bitcoinjs/bitcoinjs-lib/issues/new). We're here to assist you. You can find a [Web UI](https://bitcoincore.tech/apps/bitcoinjs-ui/index.html) that covers most of the `psbt.ts`, `transaction.ts` and `p2*.ts` APIs [here](https://bitcoincore.tech/apps/bitcoinjs-ui/index.html). diff --git a/package-lock.json b/package-lock.json index cb00c5608..c02f958ed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -47,6 +47,8 @@ "rimraf": "^2.6.3", "tiny-secp256k1": "^2.2.0", "ts-node": "^8.3.0", + "typedoc": "^0.25.1", + "typedoc-plugin-bitcoinjs-runcase": "^1.0.1", "typescript": "^4.4.4" }, "engines": { @@ -67,17 +69,89 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "dependencies": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/code-frame/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "node_modules/@babel/code-frame/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/code-frame/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/code-frame/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/compat-data": { "version": "7.20.5", "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.20.5.tgz", @@ -127,13 +201,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", - "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "dependencies": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "engines": { @@ -182,34 +257,34 @@ } }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "dependencies": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" @@ -259,30 +334,30 @@ } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "dependencies": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true, "engines": { "node": ">=6.9.0" @@ -312,13 +387,13 @@ } }, "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "engines": { @@ -397,9 +472,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", - "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -409,33 +484,33 @@ } }, "node_modules/@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", - "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.5", - "@babel/types": "^7.20.5", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -453,13 +528,13 @@ } }, "node_modules/@babel/types": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", - "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1047,6 +1122,12 @@ "node": ">=8" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -2720,6 +2801,12 @@ "node": ">=6" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -2788,6 +2875,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -2800,6 +2899,12 @@ "node": ">=10" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmmirror.com/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -2830,6 +2935,18 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -3553,6 +3670,31 @@ "safe-buffer": "^5.1.0" } }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, "node_modules/readable-stream": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", @@ -3749,6 +3891,15 @@ } ] }, + "node_modules/scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, + "dependencies": { + "loose-envify": "^1.1.0" + } + }, "node_modules/semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", @@ -3813,6 +3964,18 @@ "node": ">=8" } }, + "node_modules/shiki": { + "version": "0.14.4", + "resolved": "https://registry.npmmirror.com/shiki/-/shiki-0.14.4.tgz", + "integrity": "sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -4170,6 +4333,58 @@ "is-typedarray": "^1.0.0" } }, + "node_modules/typedoc": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.1.tgz", + "integrity": "sha512-c2ye3YUtGIadxN2O6YwPEXgrZcvhlZ6HlhWZ8jQRNzwLPn2ylhdGqdR8HbyDRyALP8J6lmSANILCkkIdNPFxqA==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" + } + }, + "node_modules/typedoc-plugin-bitcoinjs-runcase": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-bitcoinjs-runcase/-/typedoc-plugin-bitcoinjs-runcase-1.0.1.tgz", + "integrity": "sha512-tqbnCCP2ku2egGjwn0G0bRNeSH/lh3FT7khrpyYdx1kDu8rjKlyqJX7yPgEj4biBHJATJnQGxp3cKmYG0wv5uw==", + "dev": true, + "dependencies": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, + "node_modules/typedoc/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/typeforce": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", @@ -4255,6 +4470,18 @@ "safe-buffer": "^5.1.1" } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -4461,12 +4688,71 @@ } }, "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", + "version": "7.22.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", + "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", "dev": true, "requires": { - "@babel/highlight": "^7.18.6" + "@babel/highlight": "^7.22.13", + "chalk": "^2.4.2" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "@babel/compat-data": { @@ -4507,13 +4793,14 @@ } }, "@babel/generator": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.20.5.tgz", - "integrity": "sha512-jl7JY2Ykn9S0yj4DQP82sYvPU+T3g0HFcWTqDLqiuA9tGRNIj9VfbtXGAYTTkyNEnQk1jkMGOdYka8aG/lulCA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", + "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", "dev": true, "requires": { - "@babel/types": "^7.20.5", + "@babel/types": "^7.23.0", "@jridgewell/gen-mapping": "^0.3.2", + "@jridgewell/trace-mapping": "^0.3.17", "jsesc": "^2.5.1" }, "dependencies": { @@ -4551,28 +4838,28 @@ } }, "@babel/helper-environment-visitor": { - "version": "7.18.9", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.18.9.tgz", - "integrity": "sha512-3r/aACDJ3fhQ/EVgFy0hpj8oHyHpQc+LPtJoY9SzTThAsStm4Ptegq92vqKoE3vD706ZVFWITnMnxucw+S9Ipg==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", + "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", "dev": true }, "@babel/helper-function-name": { - "version": "7.19.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.19.0.tgz", - "integrity": "sha512-WAwHBINyrpqywkUH0nTnNgI5ina5TFn85HKS0pbPDfxFfhyR/aNQEn4hGi1P1JyT//I0t4OgXUlofzWILRvS5w==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", + "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", "dev": true, "requires": { - "@babel/template": "^7.18.10", - "@babel/types": "^7.19.0" + "@babel/template": "^7.22.15", + "@babel/types": "^7.23.0" } }, "@babel/helper-hoist-variables": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.18.6.tgz", - "integrity": "sha512-UlJQPkFqFULIcyW5sbzgbkxn2FKRgwWiRexcuaR8RNJRy8+LLveqPjwZV/bwrLZCN0eUHD/x8D0heK1ozuoo6Q==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", + "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-module-imports": { @@ -4610,24 +4897,24 @@ } }, "@babel/helper-split-export-declaration": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.18.6.tgz", - "integrity": "sha512-bde1etTx6ZyTmobl9LLMMQsaizFVZrquTEHOqKeQESMKo4PlObf+8+JA25ZsIpZhT/WEd39+vOdLXAFG/nELpA==", + "version": "7.22.6", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", + "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", "dev": true, "requires": { - "@babel/types": "^7.18.6" + "@babel/types": "^7.22.5" } }, "@babel/helper-string-parser": { - "version": "7.19.4", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.19.4.tgz", - "integrity": "sha512-nHtDoQcuqFmwYNYPz3Rah5ph2p8PFeFCsZk9A/48dPc/rGocJ5J3hAAZ7pb76VWX3fZKu+uEr/FhH5jLx7umrw==", + "version": "7.22.5", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", + "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", "dev": true }, "@babel/helper-validator-identifier": { - "version": "7.19.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.19.1.tgz", - "integrity": "sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", + "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", "dev": true }, "@babel/helper-validator-option": { @@ -4648,13 +4935,13 @@ } }, "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.22.20", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.20.tgz", + "integrity": "sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", + "@babel/helper-validator-identifier": "^7.22.20", + "chalk": "^2.4.2", "js-tokens": "^4.0.0" }, "dependencies": { @@ -4717,36 +5004,36 @@ } }, "@babel/parser": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.20.5.tgz", - "integrity": "sha512-r27t/cy/m9uKLXQNWWebeCUHgnAZq0CpG1OwKRxzJMP1vpSU4bSIK2hq+/cp0bQxetkXx38n09rNu8jVkcK/zA==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", + "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", "dev": true }, "@babel/template": { - "version": "7.18.10", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.18.10.tgz", - "integrity": "sha512-TI+rCtooWHr3QJ27kJxfjutghu44DLnasDMwpDqCXVTal9RLp3RSYNh4NdBrRP2cQAoG9A8juOQl6P6oZG4JxA==", + "version": "7.22.15", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", + "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", "dev": true, "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/parser": "^7.18.10", - "@babel/types": "^7.18.10" + "@babel/code-frame": "^7.22.13", + "@babel/parser": "^7.22.15", + "@babel/types": "^7.22.15" } }, "@babel/traverse": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.20.5.tgz", - "integrity": "sha512-WM5ZNN3JITQIq9tFZaw1ojLU3WgWdtkxnhM1AegMS+PvHjkM5IXjmYEGY7yukz5XS4sJyEf2VzWjI8uAavhxBQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.18.6", - "@babel/generator": "^7.20.5", - "@babel/helper-environment-visitor": "^7.18.9", - "@babel/helper-function-name": "^7.19.0", - "@babel/helper-hoist-variables": "^7.18.6", - "@babel/helper-split-export-declaration": "^7.18.6", - "@babel/parser": "^7.20.5", - "@babel/types": "^7.20.5", + "version": "7.23.2", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", + "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.22.13", + "@babel/generator": "^7.23.0", + "@babel/helper-environment-visitor": "^7.22.20", + "@babel/helper-function-name": "^7.23.0", + "@babel/helper-hoist-variables": "^7.22.5", + "@babel/helper-split-export-declaration": "^7.22.6", + "@babel/parser": "^7.23.0", + "@babel/types": "^7.23.0", "debug": "^4.1.0", "globals": "^11.1.0" }, @@ -4760,13 +5047,13 @@ } }, "@babel/types": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.20.5.tgz", - "integrity": "sha512-c9fst/h2/dcF7H+MJKZ2T0KjEQ8hY/BNnDk/H3XY8C4Aw/eWQXWn/lWntHF9ooUBnGmEvbfGrTgLWc+um0YDUg==", + "version": "7.23.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", + "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", "dev": true, "requires": { - "@babel/helper-string-parser": "^7.19.4", - "@babel/helper-validator-identifier": "^7.19.1", + "@babel/helper-string-parser": "^7.22.5", + "@babel/helper-validator-identifier": "^7.22.20", "to-fast-properties": "^2.0.0" } }, @@ -5170,6 +5457,12 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true }, + "ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmmirror.com/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -6416,6 +6709,12 @@ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true }, + "jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6469,6 +6768,15 @@ "is-unicode-supported": "^0.1.0" } }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dev": true, + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, "lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -6478,6 +6786,12 @@ "yallist": "^4.0.0" } }, + "lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmmirror.com/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, "make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", @@ -6501,6 +6815,12 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "marked": { + "version": "4.3.0", + "resolved": "https://registry.npmmirror.com/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -7052,6 +7372,25 @@ "safe-buffer": "^5.1.0" } }, + "react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-dom": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.2.0.tgz", + "integrity": "sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.0" + } + }, "readable-stream": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", @@ -7185,6 +7524,15 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" }, + "scheduler": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.0.tgz", + "integrity": "sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==", + "dev": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, "semver": { "version": "7.3.8", "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", @@ -7234,6 +7582,18 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "shiki": { + "version": "0.14.4", + "resolved": "https://registry.npmmirror.com/shiki/-/shiki-0.14.4.tgz", + "integrity": "sha512-IXCRip2IQzKwxArNNq1S+On4KPML3Yyn8Zzs/xRgcgOWIr8ntIK3IKzjFPfjy/7kt9ZMjc+FItfqHRBg8b6tNQ==", + "dev": true, + "requires": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -7500,6 +7860,48 @@ "is-typedarray": "^1.0.0" } }, + "typedoc": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.1.tgz", + "integrity": "sha512-c2ye3YUtGIadxN2O6YwPEXgrZcvhlZ6HlhWZ8jQRNzwLPn2ylhdGqdR8HbyDRyALP8J6lmSANILCkkIdNPFxqA==", + "dev": true, + "requires": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmmirror.com/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmmirror.com/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, + "typedoc-plugin-bitcoinjs-runcase": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typedoc-plugin-bitcoinjs-runcase/-/typedoc-plugin-bitcoinjs-runcase-1.0.1.tgz", + "integrity": "sha512-tqbnCCP2ku2egGjwn0G0bRNeSH/lh3FT7khrpyYdx1kDu8rjKlyqJX7yPgEj4biBHJATJnQGxp3cKmYG0wv5uw==", + "dev": true, + "requires": { + "react": "^18.2.0", + "react-dom": "^18.2.0" + } + }, "typeforce": { "version": "1.18.0", "resolved": "https://registry.npmjs.org/typeforce/-/typeforce-1.18.0.tgz", @@ -7556,6 +7958,18 @@ "safe-buffer": "^5.1.1" } }, + "vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmmirror.com/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmmirror.com/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", diff --git a/package.json b/package.json index 485afdbf8..13c845713 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "coverage-report": "npm run build && npm run nobuild:coverage-report", "coverage-html": "npm run build && npm run nobuild:coverage-html", "coverage": "npm run build && npm run nobuild:coverage", + "doc": "typedoc", "format": "npm run prettier -- --write", "formatjs": "npm run prettierjs -- --write", "format:ci": "npm run prettier -- --check && npm run prettierjs -- --check", @@ -87,6 +88,7 @@ "rimraf": "^2.6.3", "tiny-secp256k1": "^2.2.0", "ts-node": "^8.3.0", + "typedoc": "^0.25.1", "typescript": "^4.4.4" }, "license": "MIT" diff --git a/src/address.d.ts b/src/address.d.ts index be0e00a61..6b5bc9c2a 100644 --- a/src/address.d.ts +++ b/src/address.d.ts @@ -1,17 +1,51 @@ /// +/** + * bitcoin address decode and encode tools, include base58、bech32 and output script + * + * networks support bitcoin、bitcoin testnet and bitcoin regtest + * + * addresses support P2PKH、P2SH、P2WPKH、P2WSH、P2TR and so on + * + * @packageDocumentation + */ import { Network } from './networks'; +/** base58check decode result */ export interface Base58CheckResult { + /** address hash */ hash: Buffer; + /** address version: 0x00 for P2PKH, 0x05 for P2SH */ version: number; } +/** bech32 decode result */ export interface Bech32Result { + /** address version: 0x00 for P2WPKH、P2WSH, 0x01 for P2TR*/ version: number; + /** address prefix: bc for P2WPKH、P2WSH、P2TR */ prefix: string; + /** address data:20 bytes for P2WPKH, 32 bytes for P2WSH、P2TR */ data: Buffer; } +/** + * decode address with base58 specification, return address version and address hash if valid + */ export declare function fromBase58Check(address: string): Base58CheckResult; +/** + * decode address with bech32 specification, return address version、address prefix and address data if valid + */ export declare function fromBech32(address: string): Bech32Result; +/** + * encode address hash to base58 address with version + */ export declare function toBase58Check(hash: Buffer, version: number): string; +/** + * encode address hash to bech32 address with version and prefix + */ export declare function toBech32(data: Buffer, version: number, prefix: string): string; +/** + * decode address from output script with network, return address if matched + */ export declare function fromOutputScript(output: Buffer, network?: Network): string; +/** + * encodes address to output script with network, return output script if address matched + */ export declare function toOutputScript(address: string, network?: Network): Buffer; diff --git a/src/address.js b/src/address.js index ada8042af..ad3ceeb1a 100644 --- a/src/address.js +++ b/src/address.js @@ -41,6 +41,9 @@ function _toFutureSegwitAddress(output, network) { console.warn(FUTURE_SEGWIT_VERSION_WARNING); return toBech32(data, version, network.bech32); } +/** + * decode address with base58 specification, return address version and address hash if valid + */ function fromBase58Check(address) { const payload = Buffer.from(bs58check.decode(address)); // TODO: 4.0.0, move to "toOutputScript" @@ -51,6 +54,9 @@ function fromBase58Check(address) { return { version, hash }; } exports.fromBase58Check = fromBase58Check; +/** + * decode address with bech32 specification, return address version、address prefix and address data if valid + */ function fromBech32(address) { let result; let version; @@ -73,6 +79,9 @@ function fromBech32(address) { }; } exports.fromBech32 = fromBech32; +/** + * encode address hash to base58 address with version + */ function toBase58Check(hash, version) { (0, types_1.typeforce)( (0, types_1.tuple)(types_1.Hash160bit, types_1.UInt8), @@ -84,6 +93,9 @@ function toBase58Check(hash, version) { return bs58check.encode(payload); } exports.toBase58Check = toBase58Check; +/** + * encode address hash to bech32 address with version and prefix + */ function toBech32(data, version, prefix) { const words = bech32_1.bech32.toWords(data); words.unshift(version); @@ -92,6 +104,9 @@ function toBech32(data, version, prefix) { : bech32_1.bech32m.encode(prefix, words); } exports.toBech32 = toBech32; +/** + * decode address from output script with network, return address if matched + */ function fromOutputScript(output, network) { // TODO: Network network = network || networks.bitcoin; @@ -116,6 +131,9 @@ function fromOutputScript(output, network) { throw new Error(bscript.toASM(output) + ' has no matching Address'); } exports.fromOutputScript = fromOutputScript; +/** + * encodes address to output script with network, return output script if address matched + */ function toOutputScript(address, network) { network = network || networks.bitcoin; let decodeBase58; diff --git a/src/bufferutils.d.ts b/src/bufferutils.d.ts index b1d89665b..b76bae0e3 100644 --- a/src/bufferutils.d.ts +++ b/src/bufferutils.d.ts @@ -2,7 +2,20 @@ import * as varuint from 'varuint-bitcoin'; export { varuint }; export declare function readUInt64LE(buffer: Buffer, offset: number): number; +/** + * Writes a 64-bit unsigned integer in little-endian format to the specified buffer at the given offset. + * + * @param buffer - The buffer to write the value to. + * @param value - The 64-bit unsigned integer value to write. + * @param offset - The offset in the buffer where the value should be written. + * @returns The new offset after writing the value. + */ export declare function writeUInt64LE(buffer: Buffer, value: number, offset: number): number; +/** + * Reverses the order of bytes in a buffer. + * @param buffer - The buffer to reverse. + * @returns A new buffer with the bytes reversed. + */ export declare function reverseBuffer(buffer: Buffer): Buffer; export declare function cloneBuffer(buffer: Buffer): Buffer; /** diff --git a/src/bufferutils.js b/src/bufferutils.js index 0f7fd10f4..cf11f02b4 100644 --- a/src/bufferutils.js +++ b/src/bufferutils.js @@ -30,6 +30,14 @@ function readUInt64LE(buffer, offset) { return b + a; } exports.readUInt64LE = readUInt64LE; +/** + * Writes a 64-bit unsigned integer in little-endian format to the specified buffer at the given offset. + * + * @param buffer - The buffer to write the value to. + * @param value - The 64-bit unsigned integer value to write. + * @param offset - The offset in the buffer where the value should be written. + * @returns The new offset after writing the value. + */ function writeUInt64LE(buffer, value, offset) { verifuint(value, 0x001fffffffffffff); buffer.writeInt32LE(value & -1, offset); @@ -37,6 +45,11 @@ function writeUInt64LE(buffer, value, offset) { return offset + 8; } exports.writeUInt64LE = writeUInt64LE; +/** + * Reverses the order of bytes in a buffer. + * @param buffer - The buffer to reverse. + * @returns A new buffer with the bytes reversed. + */ function reverseBuffer(buffer) { if (buffer.length < 1) return buffer; let j = buffer.length - 1; diff --git a/src/crypto.d.ts b/src/crypto.d.ts index 1a465dad1..6692df1ee 100644 --- a/src/crypto.d.ts +++ b/src/crypto.d.ts @@ -10,6 +10,9 @@ type TaggedHashPrefixes = { [key in TaggedHashPrefix]: Buffer; }; /** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ +/** + * Defines the tagged hash prefixes used in the crypto module. + */ export declare const TAGGED_HASH_PREFIXES: TaggedHashPrefixes; export declare function taggedHash(prefix: TaggedHashPrefix, data: Buffer): Buffer; export {}; diff --git a/src/crypto.js b/src/crypto.js index af1224d25..a7a5936d9 100644 --- a/src/crypto.js +++ b/src/crypto.js @@ -9,6 +9,12 @@ exports.taggedHash = exports.sha1 = exports.ripemd160 = void 0; +/** + * A module for hashing functions. + * include ripemd160、sha1、sha256、hash160、hash256、taggedHash + * + * @packageDocumentation + */ const ripemd160_1 = require('@noble/hashes/ripemd160'); const sha1_1 = require('@noble/hashes/sha1'); const sha256_1 = require('@noble/hashes/sha256'); @@ -48,6 +54,9 @@ exports.TAGS = [ 'KeyAgg coefficient', ]; /** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ +/** + * Defines the tagged hash prefixes used in the crypto module. + */ exports.TAGGED_HASH_PREFIXES = { 'BIP0340/challenge': Buffer.from([ 123, 181, 45, 122, 159, 239, 88, 50, 62, 177, 191, 122, 64, 125, 179, 130, diff --git a/src/ecc_lib.d.ts b/src/ecc_lib.d.ts index 201ebb5cf..abb750a32 100644 --- a/src/ecc_lib.d.ts +++ b/src/ecc_lib.d.ts @@ -1,3 +1,17 @@ import { TinySecp256k1Interface } from './types'; +/** + * Initializes the ECC library with the provided instance. + * If `eccLib` is `undefined`, the library will be cleared. + * If `eccLib` is a new instance, it will be verified before setting it as the active library. + * + * @param eccLib The instance of the ECC library to initialize. + */ export declare function initEccLib(eccLib: TinySecp256k1Interface | undefined): void; +/** + * Retrieves the ECC Library instance. + * Throws an error if the ECC Library is not provided. + * You must call initEccLib() with a valid TinySecp256k1Interface instance before calling this function. + * @returns The ECC Library instance. + * @throws Error if the ECC Library is not provided. + */ export declare function getEccLib(): TinySecp256k1Interface; diff --git a/src/ecc_lib.js b/src/ecc_lib.js index eaa8a5327..22202da98 100644 --- a/src/ecc_lib.js +++ b/src/ecc_lib.js @@ -2,6 +2,13 @@ Object.defineProperty(exports, '__esModule', { value: true }); exports.getEccLib = exports.initEccLib = void 0; const _ECCLIB_CACHE = {}; +/** + * Initializes the ECC library with the provided instance. + * If `eccLib` is `undefined`, the library will be cleared. + * If `eccLib` is a new instance, it will be verified before setting it as the active library. + * + * @param eccLib The instance of the ECC library to initialize. + */ function initEccLib(eccLib) { if (!eccLib) { // allow clearing the library @@ -13,6 +20,13 @@ function initEccLib(eccLib) { } } exports.initEccLib = initEccLib; +/** + * Retrieves the ECC Library instance. + * Throws an error if the ECC Library is not provided. + * You must call initEccLib() with a valid TinySecp256k1Interface instance before calling this function. + * @returns The ECC Library instance. + * @throws Error if the ECC Library is not provided. + */ function getEccLib() { if (!_ECCLIB_CACHE.eccLib) throw new Error( @@ -22,6 +36,11 @@ function getEccLib() { } exports.getEccLib = getEccLib; const h = hex => Buffer.from(hex, 'hex'); +/** + * Verifies the ECC functionality. + * + * @param ecc - The TinySecp256k1Interface object. + */ function verifyEcc(ecc) { assert(typeof ecc.isXOnlyPoint === 'function'); assert( diff --git a/src/index.d.ts b/src/index.d.ts index 420979ffe..3655f4560 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -5,11 +5,15 @@ import * as payments from './payments'; import * as script from './script'; export { address, crypto, networks, payments, script }; export { Block } from './block'; +/** @hidden */ export { TaggedHashPrefix } from './crypto'; export { Psbt, PsbtTxInput, PsbtTxOutput, Signer, SignerAsync, HDSigner, HDSignerAsync, } from './psbt'; +/** @hidden */ export { OPS as opcodes } from './ops'; export { Transaction } from './transaction'; +/** @hidden */ export { Network } from './networks'; +/** @hidden */ export { Payment, PaymentCreator, PaymentOpts, Stack, StackElement, } from './payments'; export { Input as TxInput, Output as TxOutput } from './transaction'; export { initEccLib } from './ecc_lib'; diff --git a/src/index.js b/src/index.js index 4159064bd..c742ceef6 100644 --- a/src/index.js +++ b/src/index.js @@ -35,6 +35,7 @@ Object.defineProperty(exports, 'Psbt', { return psbt_1.Psbt; }, }); +/** @hidden */ var ops_1 = require('./ops'); Object.defineProperty(exports, 'opcodes', { enumerable: true, diff --git a/src/merkle.d.ts b/src/merkle.d.ts index d602201b9..a911ca525 100644 --- a/src/merkle.d.ts +++ b/src/merkle.d.ts @@ -1,2 +1,10 @@ /// +/** + * Calculates the Merkle root of an array of buffers using a specified digest function. + * + * @param values - The array of buffers. + * @param digestFn - The digest function used to calculate the hash of the concatenated buffers. + * @returns The Merkle root as a buffer. + * @throws {TypeError} If the values parameter is not an array or the digestFn parameter is not a function. + */ export declare function fastMerkleRoot(values: Buffer[], digestFn: (b: Buffer) => Buffer): Buffer; diff --git a/src/merkle.js b/src/merkle.js index e93f9cab6..c326c53af 100644 --- a/src/merkle.js +++ b/src/merkle.js @@ -1,6 +1,14 @@ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); exports.fastMerkleRoot = void 0; +/** + * Calculates the Merkle root of an array of buffers using a specified digest function. + * + * @param values - The array of buffers. + * @param digestFn - The digest function used to calculate the hash of the concatenated buffers. + * @returns The Merkle root as a buffer. + * @throws {TypeError} If the values parameter is not an array or the digestFn parameter is not a function. + */ function fastMerkleRoot(values, digestFn) { if (!Array.isArray(values)) throw TypeError('Expected values Array'); if (typeof digestFn !== 'function') diff --git a/src/networks.d.ts b/src/networks.d.ts index d5590fd1b..f9b020d9e 100644 --- a/src/networks.d.ts +++ b/src/networks.d.ts @@ -1,3 +1,8 @@ +/** + * Represents a Bitcoin network configuration,including messagePrefix, bech32, bip32, pubKeyHash, scriptHash, wif. + * Support bitcoin、bitcoin testnet and bitcoin regtest. + * @packageDocumentation + */ export interface Network { messagePrefix: string; bech32: string; @@ -10,7 +15,16 @@ interface Bip32 { public: number; private: number; } +/** + * Represents the Bitcoin network configuration. + */ export declare const bitcoin: Network; +/** + * Represents the regtest network configuration. + */ export declare const regtest: Network; +/** + * Represents the testnet network configuration. + */ export declare const testnet: Network; export {}; diff --git a/src/networks.js b/src/networks.js index ea710f8a2..75cdf30cc 100644 --- a/src/networks.js +++ b/src/networks.js @@ -1,17 +1,49 @@ 'use strict'; +// https://en.bitcoin.it/wiki/List_of_address_prefixes +// Dogecoin BIP32 is a proposed standard: https://bitcointalk.org/index.php?topic=409731 Object.defineProperty(exports, '__esModule', { value: true }); exports.testnet = exports.regtest = exports.bitcoin = void 0; +/** + * Represents the Bitcoin network configuration. + */ exports.bitcoin = { + /** + * The message prefix used for signing Bitcoin messages. + */ messagePrefix: '\x18Bitcoin Signed Message:\n', + /** + * The Bech32 prefix used for Bitcoin addresses. + */ bech32: 'bc', + /** + * The BIP32 key prefixes for Bitcoin. + */ bip32: { + /** + * The public key prefix for BIP32 extended public keys. + */ public: 0x0488b21e, + /** + * The private key prefix for BIP32 extended private keys. + */ private: 0x0488ade4, }, + /** + * The prefix for Bitcoin public key hashes. + */ pubKeyHash: 0x00, + /** + * The prefix for Bitcoin script hashes. + */ scriptHash: 0x05, + /** + * The prefix for Bitcoin Wallet Import Format (WIF) private keys. + */ wif: 0x80, }; +/** + * Represents the regtest network configuration. + */ exports.regtest = { messagePrefix: '\x18Bitcoin Signed Message:\n', bech32: 'bcrt', @@ -23,6 +55,9 @@ exports.regtest = { scriptHash: 0xc4, wif: 0xef, }; +/** + * Represents the testnet network configuration. + */ exports.testnet = { messagePrefix: '\x18Bitcoin Signed Message:\n', bech32: 'tb', diff --git a/src/payments/bip341.d.ts b/src/payments/bip341.d.ts index fe9ecf0d9..676021e4c 100644 --- a/src/payments/bip341.d.ts +++ b/src/payments/bip341.d.ts @@ -21,6 +21,13 @@ interface TweakedPublicKey { * and calculating merkle inclusion proofs when constructing a control block. */ export type HashTree = HashLeaf | HashBranch; +/** + * Calculates the root hash from a given control block and leaf hash. + * @param controlBlock - The control block buffer. + * @param leafHash - The leaf hash buffer. + * @returns The root hash buffer. + * @throws {TypeError} If the control block length is less than 33. + */ export declare function rootHashFromPath(controlBlock: Buffer, leafHash: Buffer): Buffer; /** * Build a hash tree of merkle nodes from the scripts binary tree. diff --git a/src/payments/bip341.js b/src/payments/bip341.js index 35609d788..926af6bf2 100644 --- a/src/payments/bip341.js +++ b/src/payments/bip341.js @@ -17,6 +17,13 @@ const types_1 = require('../types'); exports.LEAF_VERSION_TAPSCRIPT = 0xc0; exports.MAX_TAPTREE_DEPTH = 128; const isHashBranch = ht => 'left' in ht && 'right' in ht; +/** + * Calculates the root hash from a given control block and leaf hash. + * @param controlBlock - The control block buffer. + * @param leafHash - The leaf hash buffer. + * @returns The root hash buffer. + * @throws {TypeError} If the control block length is less than 33. + */ function rootHashFromPath(controlBlock, leafHash) { if (controlBlock.length < 33) throw new TypeError( diff --git a/src/payments/embed.d.ts b/src/payments/embed.d.ts index 76a9ed28f..d5f5785e1 100644 --- a/src/payments/embed.d.ts +++ b/src/payments/embed.d.ts @@ -1,2 +1,9 @@ import { Payment, PaymentOpts } from './index'; +/** + * Embeds data in a Bitcoin payment. + * @param a - The payment object. + * @param opts - Optional payment options. + * @returns The modified payment object. + * @throws {TypeError} If there is not enough data or if the output is invalid. + */ export declare function p2data(a: Payment, opts?: PaymentOpts): Payment; diff --git a/src/payments/embed.js b/src/payments/embed.js index a465c0815..92bbb572f 100644 --- a/src/payments/embed.js +++ b/src/payments/embed.js @@ -7,6 +7,13 @@ const types_1 = require('../types'); const lazy = require('./lazy'); const OPS = bscript.OPS; // output: OP_RETURN ... +/** + * Embeds data in a Bitcoin payment. + * @param a - The payment object. + * @param opts - Optional payment options. + * @returns The modified payment object. + * @throws {TypeError} If there is not enough data or if the output is invalid. + */ function p2data(a, opts) { if (!a.data && !a.output) throw new TypeError('Not enough data'); opts = Object.assign({ validate: true }, opts || {}); diff --git a/src/payments/index.d.ts b/src/payments/index.d.ts index 57a0369b8..8eafc319e 100644 --- a/src/payments/index.d.ts +++ b/src/payments/index.d.ts @@ -1,4 +1,11 @@ /// +/** + * Represents a payment object, which is used to create a payment. + * + * Supports P2PKH、P2SH、P2WPKH、P2WSH、P2TR and so on + * + * @packageDocumentation + */ import { Network } from '../networks'; import { Taptree } from '../types'; import { p2data as embed } from './embed'; diff --git a/src/payments/p2ms.d.ts b/src/payments/p2ms.d.ts index 199e02915..ff761c1fc 100644 --- a/src/payments/p2ms.d.ts +++ b/src/payments/p2ms.d.ts @@ -1,2 +1,9 @@ import { Payment, PaymentOpts } from './index'; +/** + * Represents a function that creates a Pay-to-Multisig (P2MS) payment object. + * @param a - The payment object. + * @param opts - Optional payment options. + * @returns The created payment object. + * @throws {TypeError} If the provided data is not valid. + */ export declare function p2ms(a: Payment, opts?: PaymentOpts): Payment; diff --git a/src/payments/p2ms.js b/src/payments/p2ms.js index 0fb57bb41..dfa0c8dd7 100644 --- a/src/payments/p2ms.js +++ b/src/payments/p2ms.js @@ -9,6 +9,13 @@ const OPS = bscript.OPS; const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1 // input: OP_0 [signatures ...] // output: m [pubKeys ...] n OP_CHECKMULTISIG +/** + * Represents a function that creates a Pay-to-Multisig (P2MS) payment object. + * @param a - The payment object. + * @param opts - Optional payment options. + * @returns The created payment object. + * @throws {TypeError} If the provided data is not valid. + */ function p2ms(a, opts) { if ( !a.input && diff --git a/src/payments/p2pk.d.ts b/src/payments/p2pk.d.ts index d7e824d6c..862ea90df 100644 --- a/src/payments/p2pk.d.ts +++ b/src/payments/p2pk.d.ts @@ -1,2 +1,10 @@ import { Payment, PaymentOpts } from './index'; +/** + * Creates a pay-to-public-key (P2PK) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2PK payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ export declare function p2pk(a: Payment, opts?: PaymentOpts): Payment; diff --git a/src/payments/p2pk.js b/src/payments/p2pk.js index 284953045..cd6702f53 100644 --- a/src/payments/p2pk.js +++ b/src/payments/p2pk.js @@ -8,6 +8,14 @@ const lazy = require('./lazy'); const OPS = bscript.OPS; // input: {signature} // output: {pubKey} OP_CHECKSIG +/** + * Creates a pay-to-public-key (P2PK) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2PK payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ function p2pk(a, opts) { if (!a.input && !a.output && !a.pubkey && !a.input && !a.signature) throw new TypeError('Not enough data'); diff --git a/src/payments/p2pkh.d.ts b/src/payments/p2pkh.d.ts index a33eeb030..1c5b76b5b 100644 --- a/src/payments/p2pkh.d.ts +++ b/src/payments/p2pkh.d.ts @@ -1,2 +1,10 @@ import { Payment, PaymentOpts } from './index'; +/** + * Creates a Pay-to-Public-Key-Hash (P2PKH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2PKH payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ export declare function p2pkh(a: Payment, opts?: PaymentOpts): Payment; diff --git a/src/payments/p2pkh.js b/src/payments/p2pkh.js index 16e293d59..bc35e878e 100644 --- a/src/payments/p2pkh.js +++ b/src/payments/p2pkh.js @@ -10,6 +10,14 @@ const bs58check = require('bs58check'); const OPS = bscript.OPS; // input: {signature} {pubkey} // output: OP_DUP OP_HASH160 {hash160(pubkey)} OP_EQUALVERIFY OP_CHECKSIG +/** + * Creates a Pay-to-Public-Key-Hash (P2PKH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2PKH payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ function p2pkh(a, opts) { if (!a.address && !a.hash && !a.output && !a.pubkey && !a.input) throw new TypeError('Not enough data'); diff --git a/src/payments/p2sh.d.ts b/src/payments/p2sh.d.ts index bb76772e7..c82d040cc 100644 --- a/src/payments/p2sh.d.ts +++ b/src/payments/p2sh.d.ts @@ -1,2 +1,10 @@ import { Payment, PaymentOpts } from './index'; +/** + * Creates a Pay-to-Script-Hash (P2SH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2SH payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ export declare function p2sh(a: Payment, opts?: PaymentOpts): Payment; diff --git a/src/payments/p2sh.js b/src/payments/p2sh.js index 66e56b6c8..1386966be 100644 --- a/src/payments/p2sh.js +++ b/src/payments/p2sh.js @@ -11,6 +11,14 @@ const OPS = bscript.OPS; // input: [redeemScriptSig ...] {redeemScript} // witness: // output: OP_HASH160 {hash160(redeemScript)} OP_EQUAL +/** + * Creates a Pay-to-Script-Hash (P2SH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2SH payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ function p2sh(a, opts) { if (!a.address && !a.hash && !a.output && !a.redeem && !a.input) throw new TypeError('Not enough data'); diff --git a/src/payments/p2tr.d.ts b/src/payments/p2tr.d.ts index 350ed0ffc..97b2e0eb2 100644 --- a/src/payments/p2tr.d.ts +++ b/src/payments/p2tr.d.ts @@ -1,2 +1,10 @@ import { Payment, PaymentOpts } from './index'; +/** + * Creates a Pay-to-Taproot (P2TR) payment object. + * + * @param a - The payment object containing the necessary data for P2TR. + * @param opts - Optional payment options. + * @returns The P2TR payment object. + * @throws {TypeError} If the provided data is invalid or insufficient. + */ export declare function p2tr(a: Payment, opts?: PaymentOpts): Payment; diff --git a/src/payments/p2tr.js b/src/payments/p2tr.js index bc0ab45c7..33fedb464 100644 --- a/src/payments/p2tr.js +++ b/src/payments/p2tr.js @@ -13,6 +13,14 @@ const address_1 = require('../address'); const OPS = bscript.OPS; const TAPROOT_WITNESS_VERSION = 0x01; const ANNEX_PREFIX = 0x50; +/** + * Creates a Pay-to-Taproot (P2TR) payment object. + * + * @param a - The payment object containing the necessary data for P2TR. + * @param opts - Optional payment options. + * @returns The P2TR payment object. + * @throws {TypeError} If the provided data is invalid or insufficient. + */ function p2tr(a, opts) { if ( !a.address && diff --git a/src/payments/p2wpkh.d.ts b/src/payments/p2wpkh.d.ts index 360939119..5108e2912 100644 --- a/src/payments/p2wpkh.d.ts +++ b/src/payments/p2wpkh.d.ts @@ -1,2 +1,10 @@ import { Payment, PaymentOpts } from './index'; +/** + * Creates a pay-to-witness-public-key-hash (p2wpkh) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The p2wpkh payment object. + * @throws {TypeError} If the required data is missing or invalid. + */ export declare function p2wpkh(a: Payment, opts?: PaymentOpts): Payment; diff --git a/src/payments/p2wpkh.js b/src/payments/p2wpkh.js index 168e08f19..1c6073e9b 100644 --- a/src/payments/p2wpkh.js +++ b/src/payments/p2wpkh.js @@ -12,6 +12,14 @@ const EMPTY_BUFFER = Buffer.alloc(0); // witness: {signature} {pubKey} // input: <> // output: OP_0 {pubKeyHash} +/** + * Creates a pay-to-witness-public-key-hash (p2wpkh) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The p2wpkh payment object. + * @throws {TypeError} If the required data is missing or invalid. + */ function p2wpkh(a, opts) { if (!a.address && !a.hash && !a.output && !a.pubkey && !a.witness) throw new TypeError('Not enough data'); diff --git a/src/payments/p2wsh.d.ts b/src/payments/p2wsh.d.ts index d9ae925e8..4169a30de 100644 --- a/src/payments/p2wsh.d.ts +++ b/src/payments/p2wsh.d.ts @@ -1,2 +1,10 @@ import { Payment, PaymentOpts } from './index'; +/** + * Creates a Pay-to-Witness-Script-Hash (P2WSH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2WSH payment object. + * @throws {TypeError} If the required data is missing or invalid. + */ export declare function p2wsh(a: Payment, opts?: PaymentOpts): Payment; diff --git a/src/payments/p2wsh.js b/src/payments/p2wsh.js index b4adebd8e..a3422e50a 100644 --- a/src/payments/p2wsh.js +++ b/src/payments/p2wsh.js @@ -24,6 +24,14 @@ function chunkHasUncompressedPubkey(chunk) { // input: <> // witness: [redeemScriptSig ...] {redeemScript} // output: OP_0 {sha256(redeemScript)} +/** + * Creates a Pay-to-Witness-Script-Hash (P2WSH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2WSH payment object. + * @throws {TypeError} If the required data is missing or invalid. + */ function p2wsh(a, opts) { if (!a.address && !a.hash && !a.output && !a.redeem && !a.witness) throw new TypeError('Not enough data'); diff --git a/src/psbt.d.ts b/src/psbt.d.ts index de7bbb3d4..d350ca12b 100644 --- a/src/psbt.d.ts +++ b/src/psbt.d.ts @@ -24,6 +24,7 @@ export type ValidateSigFunction = (pubkey: Buffer, msghash: Buffer, signature: B * There are 6 roles that this class fulfills. (Explained in BIP174) * * Creator: This can be done with `new Psbt()` + * * Updater: This can be done with `psbt.addInput(input)`, `psbt.addInputs(inputs)`, * `psbt.addOutput(output)`, `psbt.addOutputs(outputs)` when you are looking to * add new inputs and outputs to the PSBT, and `psbt.updateGlobal(itemObject)`, @@ -34,20 +35,24 @@ export type ValidateSigFunction = (pubkey: Buffer, msghash: Buffer, signature: B * data for updateOutput. * For a list of what attributes should be what types. Check the bip174 library. * Also, check the integration tests for some examples of usage. + * * Signer: There are a few methods. signAllInputs and signAllInputsAsync, which will search all input * information for your pubkey or pubkeyhash, and only sign inputs where it finds * your info. Or you can explicitly sign a specific input with signInput and * signInputAsync. For the async methods you can create a SignerAsync object * and use something like a hardware wallet to sign with. (You must implement this) + * * Combiner: psbts can be combined easily with `psbt.combine(psbt2, psbt3, psbt4 ...)` * the psbt calling combine will always have precedence when a conflict occurs. * Combine checks if the internal bitcoin transaction is the same, so be sure that * all sequences, version, locktime, etc. are the same before combining. + * * Input Finalizer: This role is fairly important. Not only does it need to construct * the input scriptSigs and witnesses, but it SHOULD verify the signatures etc. * Before running `psbt.finalizeAllInputs()` please run `psbt.validateSignaturesOfAllInputs()` * Running any finalize method will delete any data in the input(s) that are no longer * needed due to the finalized scripts containing the information. + * * Transaction Extractor: This role will perform some checks before returning a * Transaction object. Such as fee rate not being larger than maximumFeeRate etc. */ diff --git a/src/psbt.js b/src/psbt.js index 71c3589f0..227e29304 100644 --- a/src/psbt.js +++ b/src/psbt.js @@ -34,6 +34,7 @@ const DEFAULT_OPTS = { * There are 6 roles that this class fulfills. (Explained in BIP174) * * Creator: This can be done with `new Psbt()` + * * Updater: This can be done with `psbt.addInput(input)`, `psbt.addInputs(inputs)`, * `psbt.addOutput(output)`, `psbt.addOutputs(outputs)` when you are looking to * add new inputs and outputs to the PSBT, and `psbt.updateGlobal(itemObject)`, @@ -44,20 +45,24 @@ const DEFAULT_OPTS = { * data for updateOutput. * For a list of what attributes should be what types. Check the bip174 library. * Also, check the integration tests for some examples of usage. + * * Signer: There are a few methods. signAllInputs and signAllInputsAsync, which will search all input * information for your pubkey or pubkeyhash, and only sign inputs where it finds * your info. Or you can explicitly sign a specific input with signInput and * signInputAsync. For the async methods you can create a SignerAsync object * and use something like a hardware wallet to sign with. (You must implement this) + * * Combiner: psbts can be combined easily with `psbt.combine(psbt2, psbt3, psbt4 ...)` * the psbt calling combine will always have precedence when a conflict occurs. * Combine checks if the internal bitcoin transaction is the same, so be sure that * all sequences, version, locktime, etc. are the same before combining. + * * Input Finalizer: This role is fairly important. Not only does it need to construct * the input scriptSigs and witnesses, but it SHOULD verify the signatures etc. * Before running `psbt.finalizeAllInputs()` please run `psbt.validateSignaturesOfAllInputs()` * Running any finalize method will delete any data in the input(s) that are no longer * needed due to the finalized scripts containing the information. + * * Transaction Extractor: This role will perform some checks before returning a * Transaction object. Such as fee rate not being larger than maximumFeeRate etc. */ @@ -85,7 +90,7 @@ class Psbt { __NON_WITNESS_UTXO_BUF_CACHE: [], __TX_IN_CACHE: {}, __TX: this.data.globalMap.unsignedTx.tx, - // Psbt's predecesor (TransactionBuilder - now removed) behavior + // Psbt's predecessor (TransactionBuilder - now removed) behavior // was to not confirm input values before signing. // Even though we highly encourage people to get // the full parent transaction to verify values, the ability to @@ -1262,7 +1267,7 @@ function getHashForSig(inputIndex, input, cache, forValidate, sighashTypes) { console.warn( 'Warning: Signing non-segwit inputs without the full parent transaction ' + 'means there is a chance that a miner could feed you incorrect information ' + - "to trick you into paying large fees. This behavior is the same as Psbt's predecesor " + + "to trick you into paying large fees. This behavior is the same as Psbt's predecessor " + '(TransactionBuilder - now removed) when signing non-segwit scripts. You are not ' + 'able to export this Psbt with toBuffer|toBase64|toHex since it is not ' + 'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' + diff --git a/src/psbt/bip371.js b/src/psbt/bip371.js index 61196ead2..2b53171e0 100644 --- a/src/psbt/bip371.js +++ b/src/psbt/bip371.js @@ -265,6 +265,14 @@ function checkMixedTaprootAndNonTaprootOutputFields( `Cannot use both taproot and non-taproot fields.`, ); } +/** + * Checks if the tap leaf is part of the tap tree for the given input data. + * Throws an error if the tap leaf is not part of the tap tree. + * @param inputData - The original PsbtInput data. + * @param newInputData - The new PsbtInput data. + * @param action - The action being performed. + * @throws {Error} - If the tap leaf is not part of the tap tree. + */ function checkIfTapLeafInTree(inputData, newInputData, action) { if (newInputData.tapMerkleRoot) { const newLeafsInTree = (newInputData.tapLeafScript || []).every(l => @@ -287,6 +295,12 @@ function checkIfTapLeafInTree(inputData, newInputData, action) { ); } } +/** + * Checks if a TapLeafScript is present in a Merkle tree. + * @param tapLeaf The TapLeafScript to check. + * @param merkleRoot The Merkle root of the tree. If not provided, the function assumes the TapLeafScript is present. + * @returns A boolean indicating whether the TapLeafScript is present in the tree. + */ function isTapLeafInTree(tapLeaf, merkleRoot) { if (!merkleRoot) return true; const leafHash = (0, bip341_1.tapleafHash)({ @@ -299,6 +313,13 @@ function isTapLeafInTree(tapLeaf, merkleRoot) { ); return rootHash.equals(merkleRoot); } +/** + * Sorts the signatures in the input's tapScriptSig array based on their position in the tapLeaf script. + * + * @param input - The PsbtInput object. + * @param tapLeaf - The TapLeafScript object. + * @returns An array of sorted signatures as Buffers. + */ function sortSignatures(input, tapLeaf) { const leafHash = (0, bip341_1.tapleafHash)({ output: tapLeaf.script, @@ -310,6 +331,12 @@ function sortSignatures(input, tapLeaf) { .sort((t1, t2) => t2.positionInScript - t1.positionInScript) .map(t => t.signature); } +/** + * Adds the position of a public key in a script to a TapScriptSig object. + * @param script The script in which to find the position of the public key. + * @param tss The TapScriptSig object to add the position to. + * @returns A TapScriptSigWitPosition object with the added position. + */ function addPubkeyPositionInScript(script, tss) { return Object.assign( { @@ -340,6 +367,14 @@ function findTapLeafToFinalize(input, inputIndex, leafHashToFinalize) { ); return tapLeaf; } +/** + * Determines whether a TapLeafScript can be finalized. + * + * @param leaf - The TapLeafScript to check. + * @param tapScriptSig - The array of TapScriptSig objects. + * @param hash - The optional hash to compare with the leaf hash. + * @returns A boolean indicating whether the TapLeafScript can be finalized. + */ function canFinalizeLeaf(leaf, tapScriptSig, hash) { const leafHash = (0, bip341_1.tapleafHash)({ output: leaf.script, @@ -351,6 +386,12 @@ function canFinalizeLeaf(leaf, tapScriptSig, hash) { tapScriptSig.find(tss => tss.leafHash.equals(leafHash)) !== undefined ); } +/** + * Checks if the given PsbtInput or PsbtOutput has non-taproot fields. + * Non-taproot fields include redeemScript, witnessScript, and bip32Derivation. + * @param io The PsbtInput or PsbtOutput to check. + * @returns A boolean indicating whether the given input or output has non-taproot fields. + */ function hasNonTaprootFields(io) { return ( io && diff --git a/src/psbt/psbtutils.d.ts b/src/psbt/psbtutils.d.ts index db5f0b516..3e7b2a393 100644 --- a/src/psbt/psbtutils.d.ts +++ b/src/psbt/psbtutils.d.ts @@ -7,13 +7,49 @@ export declare const isP2WPKH: (script: Buffer) => boolean; export declare const isP2WSHScript: (script: Buffer) => boolean; export declare const isP2SHScript: (script: Buffer) => boolean; export declare const isP2TR: (script: Buffer) => boolean; +/** + * Converts a witness stack to a script witness. + * @param witness The witness stack to convert. + * @returns The script witness as a Buffer. + */ +/** + * Converts a witness stack to a script witness. + * @param witness The witness stack to convert. + * @returns The converted script witness. + */ export declare function witnessStackToScriptWitness(witness: Buffer[]): Buffer; +/** + * Finds the position of a public key in a script. + * @param pubkey The public key to search for. + * @param script The script to search in. + * @returns The index of the public key in the script, or -1 if not found. + * @throws {Error} If there is an unknown script error. + */ export declare function pubkeyPositionInScript(pubkey: Buffer, script: Buffer): number; +/** + * Checks if a public key is present in a script. + * @param pubkey The public key to check. + * @param script The script to search in. + * @returns A boolean indicating whether the public key is present in the script. + */ export declare function pubkeyInScript(pubkey: Buffer, script: Buffer): boolean; +/** + * Checks if an input contains a signature for a specific action. + * @param input - The input to check. + * @param action - The action to check for. + * @returns A boolean indicating whether the input contains a signature for the specified action. + */ export declare function checkInputForSig(input: PsbtInput, action: string): boolean; type SignatureDecodeFunc = (buffer: Buffer) => { signature: Buffer; hashType: number; }; +/** + * Determines if a given action is allowed for a signature block. + * @param signature - The signature block. + * @param signatureDecodeFn - The function used to decode the signature. + * @param action - The action to be checked. + * @returns True if the action is allowed, false otherwise. + */ export declare function signatureBlocksAction(signature: Buffer, signatureDecodeFn: SignatureDecodeFunc, action: string): boolean; export {}; diff --git a/src/psbt/psbtutils.js b/src/psbt/psbtutils.js index 2e8bd435a..ea5f1d719 100644 --- a/src/psbt/psbtutils.js +++ b/src/psbt/psbtutils.js @@ -35,6 +35,16 @@ exports.isP2WPKH = isPaymentFactory(payments.p2wpkh); exports.isP2WSHScript = isPaymentFactory(payments.p2wsh); exports.isP2SHScript = isPaymentFactory(payments.p2sh); exports.isP2TR = isPaymentFactory(payments.p2tr); +/** + * Converts a witness stack to a script witness. + * @param witness The witness stack to convert. + * @returns The script witness as a Buffer. + */ +/** + * Converts a witness stack to a script witness. + * @param witness The witness stack to convert. + * @returns The converted script witness. + */ function witnessStackToScriptWitness(witness) { let buffer = Buffer.allocUnsafe(0); function writeSlice(slice) { @@ -58,6 +68,13 @@ function witnessStackToScriptWitness(witness) { return buffer; } exports.witnessStackToScriptWitness = witnessStackToScriptWitness; +/** + * Finds the position of a public key in a script. + * @param pubkey The public key to search for. + * @param script The script to search in. + * @returns The index of the public key in the script, or -1 if not found. + * @throws {Error} If there is an unknown script error. + */ function pubkeyPositionInScript(pubkey, script) { const pubkeyHash = (0, crypto_1.hash160)(pubkey); const pubkeyXOnly = pubkey.slice(1, 33); // slice before calling? @@ -73,10 +90,22 @@ function pubkeyPositionInScript(pubkey, script) { }); } exports.pubkeyPositionInScript = pubkeyPositionInScript; +/** + * Checks if a public key is present in a script. + * @param pubkey The public key to check. + * @param script The script to search in. + * @returns A boolean indicating whether the public key is present in the script. + */ function pubkeyInScript(pubkey, script) { return pubkeyPositionInScript(pubkey, script) !== -1; } exports.pubkeyInScript = pubkeyInScript; +/** + * Checks if an input contains a signature for a specific action. + * @param input - The input to check. + * @param action - The action to check for. + * @returns A boolean indicating whether the input contains a signature for the specified action. + */ function checkInputForSig(input, action) { const pSigs = extractPartialSigs(input); return pSigs.some(pSig => @@ -84,6 +113,13 @@ function checkInputForSig(input, action) { ); } exports.checkInputForSig = checkInputForSig; +/** + * Determines if a given action is allowed for a signature block. + * @param signature - The signature block. + * @param signatureDecodeFn - The function used to decode the signature. + * @param action - The action to be checked. + * @returns True if the action is allowed, false otherwise. + */ function signatureBlocksAction(signature, signatureDecodeFn, action) { const { hashType } = signatureDecodeFn(signature); const whitelist = []; @@ -106,6 +142,16 @@ function signatureBlocksAction(signature, signatureDecodeFn, action) { return false; } exports.signatureBlocksAction = signatureBlocksAction; +/** + * Extracts the signatures from a PsbtInput object. + * If the input has partial signatures, it returns an array of the signatures. + * If the input does not have partial signatures, it checks if it has a finalScriptSig or finalScriptWitness. + * If it does, it extracts the signatures from the final scripts and returns them. + * If none of the above conditions are met, it returns an empty array. + * + * @param input - The PsbtInput object from which to extract the signatures. + * @returns An array of signatures extracted from the PsbtInput object. + */ function extractPartialSigs(input) { let pSigs = []; if ((input.partialSig || []).length === 0) { @@ -116,6 +162,14 @@ function extractPartialSigs(input) { } return pSigs.map(p => p.signature); } +/** + * Retrieves the partial signatures (Psigs) from the input's final scripts. + * Psigs are extracted from both the final scriptSig and final scriptWitness of the input. + * Only canonical script signatures are considered. + * + * @param input - The PsbtInput object representing the input. + * @returns An array of PartialSig objects containing the extracted Psigs. + */ function getPsigsFromInputFinalScripts(input) { const scriptItems = !input.finalScriptSig ? [] diff --git a/src/push_data.d.ts b/src/push_data.d.ts index 07c2f918d..068456148 100644 --- a/src/push_data.d.ts +++ b/src/push_data.d.ts @@ -1,6 +1,27 @@ /// +/** + * Calculates the encoding length of a number used for push data in Bitcoin transactions. + * @param i The number to calculate the encoding length for. + * @returns The encoding length of the number. + */ export declare function encodingLength(i: number): number; +/** + * Encodes a number into a buffer using a variable-length encoding scheme. + * The encoded buffer is written starting at the specified offset. + * Returns the size of the encoded buffer. + * + * @param buffer - The buffer to write the encoded data into. + * @param num - The number to encode. + * @param offset - The offset at which to start writing the encoded buffer. + * @returns The size of the encoded buffer. + */ export declare function encode(buffer: Buffer, num: number, offset: number): number; +/** + * Decodes a buffer and returns information about the opcode, number, and size. + * @param buffer - The buffer to decode. + * @param offset - The offset within the buffer to start decoding. + * @returns An object containing the opcode, number, and size, or null if decoding fails. + */ export declare function decode(buffer: Buffer, offset: number): { opcode: number; number: number; diff --git a/src/push_data.js b/src/push_data.js index 16b6147b5..2d3683769 100644 --- a/src/push_data.js +++ b/src/push_data.js @@ -2,10 +2,25 @@ Object.defineProperty(exports, '__esModule', { value: true }); exports.decode = exports.encode = exports.encodingLength = void 0; const ops_1 = require('./ops'); +/** + * Calculates the encoding length of a number used for push data in Bitcoin transactions. + * @param i The number to calculate the encoding length for. + * @returns The encoding length of the number. + */ function encodingLength(i) { return i < ops_1.OPS.OP_PUSHDATA1 ? 1 : i <= 0xff ? 2 : i <= 0xffff ? 3 : 5; } exports.encodingLength = encodingLength; +/** + * Encodes a number into a buffer using a variable-length encoding scheme. + * The encoded buffer is written starting at the specified offset. + * Returns the size of the encoded buffer. + * + * @param buffer - The buffer to write the encoded data into. + * @param num - The number to encode. + * @param offset - The offset at which to start writing the encoded buffer. + * @returns The size of the encoded buffer. + */ function encode(buffer, num, offset) { const size = encodingLength(num); // ~6 bit @@ -27,6 +42,12 @@ function encode(buffer, num, offset) { return size; } exports.encode = encode; +/** + * Decodes a buffer and returns information about the opcode, number, and size. + * @param buffer - The buffer to decode. + * @param offset - The offset within the buffer to start decoding. + * @returns An object containing the opcode, number, and size, or null if decoding fails. + */ function decode(buffer, offset) { const opcode = buffer.readUInt8(offset); let num; diff --git a/src/script.d.ts b/src/script.d.ts index fd5964b89..ffc8c89bb 100644 --- a/src/script.d.ts +++ b/src/script.d.ts @@ -6,10 +6,34 @@ import * as scriptSignature from './script_signature'; export { OPS }; export declare function isPushOnly(value: Stack): boolean; export declare function countNonPushOnlyOPs(value: Stack): number; +/** + * Compiles an array of chunks into a Buffer. + * + * @param chunks - The array of chunks to compile. + * @returns The compiled Buffer. + * @throws Error if the compilation fails. + */ export declare function compile(chunks: Buffer | Stack): Buffer; export declare function decompile(buffer: Buffer | Array): Array | null; +/** + * Converts the given chunks into an ASM (Assembly) string representation. + * If the chunks parameter is a Buffer, it will be decompiled into a Stack before conversion. + * @param chunks - The chunks to convert into ASM. + * @returns The ASM string representation of the chunks. + */ export declare function toASM(chunks: Buffer | Array): string; +/** + * Converts an ASM string to a Buffer. + * @param asm The ASM string to convert. + * @returns The converted Buffer. + */ export declare function fromASM(asm: string): Buffer; +/** + * Converts the given chunks into a stack of buffers. + * + * @param chunks - The chunks to convert. + * @returns The stack of buffers. + */ export declare function toStack(chunks: Buffer | Array): Buffer[]; export declare function isCanonicalPubKey(buffer: Buffer): boolean; export declare function isDefinedHashType(hashType: number): boolean; diff --git a/src/script.js b/src/script.js index 6ed7ba20a..be2805190 100644 --- a/src/script.js +++ b/src/script.js @@ -14,6 +14,10 @@ exports.signature = exports.isPushOnly = exports.OPS = void 0; +/** + * Script tools, including decompile, compile, toASM, fromASM, toStack, isCanonicalPubKey, isCanonicalScriptSignature + * @packageDocumentation + */ const bip66 = require('./bip66'); const ops_1 = require('./ops'); Object.defineProperty(exports, 'OPS', { @@ -62,6 +66,13 @@ function chunksIsArray(buf) { function singleChunkIsBuffer(buf) { return Buffer.isBuffer(buf); } +/** + * Compiles an array of chunks into a Buffer. + * + * @param chunks - The array of chunks to compile. + * @returns The compiled Buffer. + * @throws Error if the compilation fails. + */ function compile(chunks) { // TODO: remove me if (chunksIsBuffer(chunks)) return chunks; @@ -137,6 +148,12 @@ function decompile(buffer) { return chunks; } exports.decompile = decompile; +/** + * Converts the given chunks into an ASM (Assembly) string representation. + * If the chunks parameter is a Buffer, it will be decompiled into a Stack before conversion. + * @param chunks - The chunks to convert into ASM. + * @returns The ASM string representation of the chunks. + */ function toASM(chunks) { if (chunksIsBuffer(chunks)) { chunks = decompile(chunks); @@ -155,6 +172,11 @@ function toASM(chunks) { .join(' '); } exports.toASM = toASM; +/** + * Converts an ASM string to a Buffer. + * @param asm The ASM string to convert. + * @returns The converted Buffer. + */ function fromASM(asm) { typeforce(types.String, asm); return compile( @@ -168,6 +190,12 @@ function fromASM(asm) { ); } exports.fromASM = fromASM; +/** + * Converts the given chunks into a stack of buffers. + * + * @param chunks - The chunks to convert. + * @returns The stack of buffers. + */ function toStack(chunks) { chunks = decompile(chunks); typeforce(isPushOnly, chunks); diff --git a/src/script_number.d.ts b/src/script_number.d.ts index 015bb8943..90f09c55a 100644 --- a/src/script_number.d.ts +++ b/src/script_number.d.ts @@ -1,3 +1,19 @@ /// +/** + * Decodes a script number from a buffer. + * + * @param buffer - The buffer containing the script number. + * @param maxLength - The maximum length of the script number. Defaults to 4. + * @param minimal - Whether the script number should be minimal. Defaults to true. + * @returns The decoded script number. + * @throws {TypeError} If the script number overflows the maximum length. + * @throws {Error} If the script number is not minimally encoded when minimal is true. + */ export declare function decode(buffer: Buffer, maxLength?: number, minimal?: boolean): number; +/** + * Encodes a number into a Buffer using a specific format. + * + * @param _number - The number to encode. + * @returns The encoded number as a Buffer. + */ export declare function encode(_number: number): Buffer; diff --git a/src/script_number.js b/src/script_number.js index 8220a1043..2691b41e6 100644 --- a/src/script_number.js +++ b/src/script_number.js @@ -1,6 +1,16 @@ 'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); exports.encode = exports.decode = void 0; +/** + * Decodes a script number from a buffer. + * + * @param buffer - The buffer containing the script number. + * @param maxLength - The maximum length of the script number. Defaults to 4. + * @param minimal - Whether the script number should be minimal. Defaults to true. + * @returns The decoded script number. + * @throws {TypeError} If the script number overflows the maximum length. + * @throws {Error} If the script number is not minimally encoded when minimal is true. + */ function decode(buffer, maxLength, minimal) { maxLength = maxLength || 4; minimal = minimal === undefined ? true : minimal; @@ -43,6 +53,12 @@ function scriptNumSize(i) { ? 1 : 0; } +/** + * Encodes a number into a Buffer using a specific format. + * + * @param _number - The number to encode. + * @returns The encoded number as a Buffer. + */ function encode(_number) { let value = Math.abs(_number); const size = scriptNumSize(value); diff --git a/src/script_signature.d.ts b/src/script_signature.d.ts index 2057dd99f..b9034a816 100644 --- a/src/script_signature.d.ts +++ b/src/script_signature.d.ts @@ -3,6 +3,19 @@ interface ScriptSignature { signature: Buffer; hashType: number; } +/** + * Decodes a buffer into a ScriptSignature object. + * @param buffer - The buffer to decode. + * @returns The decoded ScriptSignature object. + * @throws Error if the hashType is invalid. + */ export declare function decode(buffer: Buffer): ScriptSignature; +/** + * Encodes a signature and hash type into a buffer. + * @param signature - The signature to encode. + * @param hashType - The hash type to encode. + * @returns The encoded buffer. + * @throws Error if the hashType is invalid. + */ export declare function encode(signature: Buffer, hashType: number): Buffer; export {}; diff --git a/src/script_signature.js b/src/script_signature.js index eb252ceb4..61624b630 100644 --- a/src/script_signature.js +++ b/src/script_signature.js @@ -6,6 +6,11 @@ const script_1 = require('./script'); const types = require('./types'); const { typeforce } = types; const ZERO = Buffer.alloc(1, 0); +/** + * Converts a buffer to a DER-encoded buffer. + * @param x - The buffer to be converted. + * @returns The DER-encoded buffer. + */ function toDER(x) { let i = 0; while (x[i] === 0) ++i; @@ -14,6 +19,13 @@ function toDER(x) { if (x[0] & 0x80) return Buffer.concat([ZERO, x], 1 + x.length); return x; } +/** + * Converts a DER-encoded signature to a buffer. + * If the first byte of the input buffer is 0x00, it is skipped. + * The resulting buffer is 32 bytes long, filled with zeros if necessary. + * @param x - The DER-encoded signature. + * @returns The converted buffer. + */ function fromDER(x) { if (x[0] === 0x00) x = x.slice(1); const buffer = Buffer.alloc(32, 0); @@ -22,6 +34,12 @@ function fromDER(x) { return buffer; } // BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed) +/** + * Decodes a buffer into a ScriptSignature object. + * @param buffer - The buffer to decode. + * @returns The decoded ScriptSignature object. + * @throws Error if the hashType is invalid. + */ function decode(buffer) { const hashType = buffer.readUInt8(buffer.length - 1); if (!(0, script_1.isDefinedHashType)(hashType)) { @@ -34,6 +52,13 @@ function decode(buffer) { return { signature, hashType }; } exports.decode = decode; +/** + * Encodes a signature and hash type into a buffer. + * @param signature - The signature to encode. + * @param hashType - The hash type to encode. + * @returns The encoded buffer. + * @throws Error if the hashType is invalid. + */ function encode(signature, hashType) { typeforce( { diff --git a/src/transaction.d.ts b/src/transaction.d.ts index 613706b67..118fa57f1 100644 --- a/src/transaction.d.ts +++ b/src/transaction.d.ts @@ -10,6 +10,9 @@ export interface Input { sequence: number; witness: Buffer[]; } +/** + * Represents a Bitcoin transaction. + */ export declare class Transaction { static readonly DEFAULT_SEQUENCE = 4294967295; static readonly SIGHASH_DEFAULT = 0; diff --git a/src/transaction.js b/src/transaction.js index ade4582cf..2b74f3788 100644 --- a/src/transaction.js +++ b/src/transaction.js @@ -38,6 +38,9 @@ const BLANK_OUTPUT = { function isOutput(out) { return out.value !== undefined; } +/** + * Represents a Bitcoin transaction. + */ class Transaction { constructor() { this.version = 1; diff --git a/src/types.d.ts b/src/types.d.ts index 5b32ab9de..b08a1fb6f 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,6 +1,17 @@ /// export declare const typeforce: any; +/** + * Checks if two arrays of Buffers are equal. + * @param a - The first array of Buffers. + * @param b - The second array of Buffers. + * @returns True if the arrays are equal, false otherwise. + */ export declare function stacksEqual(a: Buffer[], b: Buffer[]): boolean; +/** + * Checks if the given value is a valid elliptic curve point. + * @param p - The value to check. + * @returns True if the value is a valid elliptic curve point, false otherwise. + */ export declare function isPoint(p: Buffer | number | undefined | null): boolean; export declare function UInt31(value: number): boolean; export declare function BIP32Path(value: string): boolean; diff --git a/src/types.js b/src/types.js index 337badd34..5bcd54c81 100644 --- a/src/types.js +++ b/src/types.js @@ -37,6 +37,12 @@ const EC_P = buffer_1.Buffer.from( 'fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f', 'hex', ); +/** + * Checks if two arrays of Buffers are equal. + * @param a - The first array of Buffers. + * @param b - The second array of Buffers. + * @returns True if the arrays are equal, false otherwise. + */ function stacksEqual(a, b) { if (a.length !== b.length) return false; return a.every((x, i) => { @@ -44,6 +50,11 @@ function stacksEqual(a, b) { }); } exports.stacksEqual = stacksEqual; +/** + * Checks if the given value is a valid elliptic curve point. + * @param p - The value to check. + * @returns True if the value is a valid elliptic curve point, false otherwise. + */ function isPoint(p) { if (!buffer_1.Buffer.isBuffer(p)) return false; if (p.length < 33) return false; diff --git a/test/integration/transactions.spec.ts b/test/integration/transactions.spec.ts index 264d99a2f..2754ee226 100644 --- a/test/integration/transactions.spec.ts +++ b/test/integration/transactions.spec.ts @@ -126,7 +126,7 @@ describe('bitcoinjs-lib (transactions with psbt)', () => { // (in)(5e4 + 7e4) - (out)(8e4 + 1e4) = (fee)3e4 = 30000, this is the miner fee // Let's show a new feature with PSBT. - // We can have multiple signers sign in parrallel and combine them. + // We can have multiple signers sign in parallel and combine them. // (this is not necessary, but a nice feature) // encode to send out to the signers diff --git a/test/transaction.spec.ts b/test/transaction.spec.ts index bf62acedf..991557ba3 100644 --- a/test/transaction.spec.ts +++ b/test/transaction.spec.ts @@ -350,7 +350,7 @@ describe('Transaction', () => { }); describe('setWitness', () => { - it('only accepts a a witness stack (Array of Buffers)', () => { + it('only accepts a witness stack (Array of Buffers)', () => { assert.throws(() => { (new Transaction().setWitness as any)(0, 'foobar'); }, /Expected property "1" of type \[Buffer], got String "foobar"/); diff --git a/ts_src/address.ts b/ts_src/address.ts index ce224fd11..cbd03da1f 100644 --- a/ts_src/address.ts +++ b/ts_src/address.ts @@ -1,3 +1,12 @@ +/** + * bitcoin address decode and encode tools, include base58、bech32 and output script + * + * networks support bitcoin、bitcoin testnet and bitcoin regtest + * + * addresses support P2PKH、P2SH、P2WPKH、P2WSH、P2TR and so on + * + * @packageDocumentation + */ import { Network } from './networks'; import * as networks from './networks'; import * as payments from './payments'; @@ -5,14 +14,22 @@ import * as bscript from './script'; import { typeforce, tuple, Hash160bit, UInt8 } from './types'; import { bech32, bech32m } from 'bech32'; import * as bs58check from 'bs58check'; + +/** base58check decode result */ export interface Base58CheckResult { + /** address hash */ hash: Buffer; + /** address version: 0x00 for P2PKH, 0x05 for P2SH */ version: number; } +/** bech32 decode result */ export interface Bech32Result { + /** address version: 0x00 for P2WPKH、P2WSH, 0x01 for P2TR*/ version: number; + /** address prefix: bc for P2WPKH、P2WSH、P2TR */ prefix: string; + /** address data:20 bytes for P2WPKH, 32 bytes for P2WSH、P2TR */ data: Buffer; } @@ -52,6 +69,9 @@ function _toFutureSegwitAddress(output: Buffer, network: Network): string { return toBech32(data, version, network.bech32); } +/** + * decode address with base58 specification, return address version and address hash if valid + */ export function fromBase58Check(address: string): Base58CheckResult { const payload = Buffer.from(bs58check.decode(address)); @@ -65,6 +85,9 @@ export function fromBase58Check(address: string): Base58CheckResult { return { version, hash }; } +/** + * decode address with bech32 specification, return address version、address prefix and address data if valid + */ export function fromBech32(address: string): Bech32Result { let result; let version; @@ -90,6 +113,9 @@ export function fromBech32(address: string): Bech32Result { }; } +/** + * encode address hash to base58 address with version + */ export function toBase58Check(hash: Buffer, version: number): string { typeforce(tuple(Hash160bit, UInt8), arguments); @@ -100,6 +126,9 @@ export function toBase58Check(hash: Buffer, version: number): string { return bs58check.encode(payload); } +/** + * encode address hash to bech32 address with version and prefix + */ export function toBech32( data: Buffer, version: number, @@ -113,6 +142,9 @@ export function toBech32( : bech32m.encode(prefix, words); } +/** + * decode address from output script with network, return address if matched + */ export function fromOutputScript(output: Buffer, network?: Network): string { // TODO: Network network = network || networks.bitcoin; @@ -139,6 +171,9 @@ export function fromOutputScript(output: Buffer, network?: Network): string { throw new Error(bscript.toASM(output) + ' has no matching Address'); } +/** + * encodes address to output script with network, return output script if address matched + */ export function toOutputScript(address: string, network?: Network): Buffer { network = network || networks.bitcoin; diff --git a/ts_src/bufferutils.ts b/ts_src/bufferutils.ts index 901d72a48..b73ce1502 100644 --- a/ts_src/bufferutils.ts +++ b/ts_src/bufferutils.ts @@ -23,6 +23,14 @@ export function readUInt64LE(buffer: Buffer, offset: number): number { return b + a; } +/** + * Writes a 64-bit unsigned integer in little-endian format to the specified buffer at the given offset. + * + * @param buffer - The buffer to write the value to. + * @param value - The 64-bit unsigned integer value to write. + * @param offset - The offset in the buffer where the value should be written. + * @returns The new offset after writing the value. + */ export function writeUInt64LE( buffer: Buffer, value: number, @@ -35,6 +43,11 @@ export function writeUInt64LE( return offset + 8; } +/** + * Reverses the order of bytes in a buffer. + * @param buffer - The buffer to reverse. + * @returns A new buffer with the bytes reversed. + */ export function reverseBuffer(buffer: Buffer): Buffer { if (buffer.length < 1) return buffer; let j = buffer.length - 1; diff --git a/ts_src/crypto.ts b/ts_src/crypto.ts index e3b876961..223305a11 100644 --- a/ts_src/crypto.ts +++ b/ts_src/crypto.ts @@ -1,3 +1,9 @@ +/** + * A module for hashing functions. + * include ripemd160、sha1、sha256、hash160、hash256、taggedHash + * + * @packageDocumentation + */ import { ripemd160 as _ripemd160 } from '@noble/hashes/ripemd160'; import { sha1 as _sha1 } from '@noble/hashes/sha1'; import { sha256 as _sha256 } from '@noble/hashes/sha256'; @@ -38,6 +44,9 @@ type TaggedHashPrefixes = { [key in TaggedHashPrefix]: Buffer; }; /** An object mapping tags to their tagged hash prefix of [SHA256(tag) | SHA256(tag)] */ +/** + * Defines the tagged hash prefixes used in the crypto module. + */ export const TAGGED_HASH_PREFIXES: TaggedHashPrefixes = { 'BIP0340/challenge': Buffer.from([ 123, 181, 45, 122, 159, 239, 88, 50, 62, 177, 191, 122, 64, 125, 179, 130, diff --git a/ts_src/ecc_lib.ts b/ts_src/ecc_lib.ts index eb4c59eeb..fbd1fcdb8 100644 --- a/ts_src/ecc_lib.ts +++ b/ts_src/ecc_lib.ts @@ -2,6 +2,13 @@ import { TinySecp256k1Interface } from './types'; const _ECCLIB_CACHE: { eccLib?: TinySecp256k1Interface } = {}; +/** + * Initializes the ECC library with the provided instance. + * If `eccLib` is `undefined`, the library will be cleared. + * If `eccLib` is a new instance, it will be verified before setting it as the active library. + * + * @param eccLib The instance of the ECC library to initialize. + */ export function initEccLib(eccLib: TinySecp256k1Interface | undefined): void { if (!eccLib) { // allow clearing the library @@ -13,6 +20,13 @@ export function initEccLib(eccLib: TinySecp256k1Interface | undefined): void { } } +/** + * Retrieves the ECC Library instance. + * Throws an error if the ECC Library is not provided. + * You must call initEccLib() with a valid TinySecp256k1Interface instance before calling this function. + * @returns The ECC Library instance. + * @throws Error if the ECC Library is not provided. + */ export function getEccLib(): TinySecp256k1Interface { if (!_ECCLIB_CACHE.eccLib) throw new Error( @@ -23,6 +37,11 @@ export function getEccLib(): TinySecp256k1Interface { const h = (hex: string): Buffer => Buffer.from(hex, 'hex'); +/** + * Verifies the ECC functionality. + * + * @param ecc - The TinySecp256k1Interface object. + */ function verifyEcc(ecc: TinySecp256k1Interface): void { assert(typeof ecc.isXOnlyPoint === 'function'); assert( diff --git a/ts_src/index.ts b/ts_src/index.ts index 64c4294c2..4b4041152 100644 --- a/ts_src/index.ts +++ b/ts_src/index.ts @@ -7,6 +7,7 @@ import * as script from './script'; export { address, crypto, networks, payments, script }; export { Block } from './block'; +/** @hidden */ export { TaggedHashPrefix } from './crypto'; export { Psbt, @@ -17,10 +18,12 @@ export { HDSigner, HDSignerAsync, } from './psbt'; +/** @hidden */ export { OPS as opcodes } from './ops'; export { Transaction } from './transaction'; - +/** @hidden */ export { Network } from './networks'; +/** @hidden */ export { Payment, PaymentCreator, diff --git a/ts_src/merkle.ts b/ts_src/merkle.ts index 8ff8c3f8c..206f8fcd0 100644 --- a/ts_src/merkle.ts +++ b/ts_src/merkle.ts @@ -1,3 +1,11 @@ +/** + * Calculates the Merkle root of an array of buffers using a specified digest function. + * + * @param values - The array of buffers. + * @param digestFn - The digest function used to calculate the hash of the concatenated buffers. + * @returns The Merkle root as a buffer. + * @throws {TypeError} If the values parameter is not an array or the digestFn parameter is not a function. + */ export function fastMerkleRoot( values: Buffer[], digestFn: (b: Buffer) => Buffer, diff --git a/ts_src/networks.ts b/ts_src/networks.ts index e66b08c30..9aa465d70 100644 --- a/ts_src/networks.ts +++ b/ts_src/networks.ts @@ -1,5 +1,11 @@ // https://en.bitcoin.it/wiki/List_of_address_prefixes // Dogecoin BIP32 is a proposed standard: https://bitcointalk.org/index.php?topic=409731 + +/** + * Represents a Bitcoin network configuration,including messagePrefix, bech32, bip32, pubKeyHash, scriptHash, wif. + * Support bitcoin、bitcoin testnet and bitcoin regtest. + * @packageDocumentation + */ export interface Network { messagePrefix: string; bech32: string; @@ -14,17 +20,47 @@ interface Bip32 { private: number; } +/** + * Represents the Bitcoin network configuration. + */ export const bitcoin: Network = { + /** + * The message prefix used for signing Bitcoin messages. + */ messagePrefix: '\x18Bitcoin Signed Message:\n', + /** + * The Bech32 prefix used for Bitcoin addresses. + */ bech32: 'bc', + /** + * The BIP32 key prefixes for Bitcoin. + */ bip32: { + /** + * The public key prefix for BIP32 extended public keys. + */ public: 0x0488b21e, + /** + * The private key prefix for BIP32 extended private keys. + */ private: 0x0488ade4, }, + /** + * The prefix for Bitcoin public key hashes. + */ pubKeyHash: 0x00, + /** + * The prefix for Bitcoin script hashes. + */ scriptHash: 0x05, + /** + * The prefix for Bitcoin Wallet Import Format (WIF) private keys. + */ wif: 0x80, }; +/** + * Represents the regtest network configuration. + */ export const regtest: Network = { messagePrefix: '\x18Bitcoin Signed Message:\n', bech32: 'bcrt', @@ -36,6 +72,9 @@ export const regtest: Network = { scriptHash: 0xc4, wif: 0xef, }; +/** + * Represents the testnet network configuration. + */ export const testnet: Network = { messagePrefix: '\x18Bitcoin Signed Message:\n', bech32: 'tb', diff --git a/ts_src/payments/bip341.ts b/ts_src/payments/bip341.ts index 40793779f..af9b1f171 100644 --- a/ts_src/payments/bip341.ts +++ b/ts_src/payments/bip341.ts @@ -34,6 +34,13 @@ const isHashBranch = (ht: HashTree): ht is HashBranch => */ export type HashTree = HashLeaf | HashBranch; +/** + * Calculates the root hash from a given control block and leaf hash. + * @param controlBlock - The control block buffer. + * @param leafHash - The leaf hash buffer. + * @returns The root hash buffer. + * @throws {TypeError} If the control block length is less than 33. + */ export function rootHashFromPath( controlBlock: Buffer, leafHash: Buffer, diff --git a/ts_src/payments/embed.ts b/ts_src/payments/embed.ts index 1d9a82807..aef14e1b7 100644 --- a/ts_src/payments/embed.ts +++ b/ts_src/payments/embed.ts @@ -7,6 +7,13 @@ import * as lazy from './lazy'; const OPS = bscript.OPS; // output: OP_RETURN ... +/** + * Embeds data in a Bitcoin payment. + * @param a - The payment object. + * @param opts - Optional payment options. + * @returns The modified payment object. + * @throws {TypeError} If there is not enough data or if the output is invalid. + */ export function p2data(a: Payment, opts?: PaymentOpts): Payment { if (!a.data && !a.output) throw new TypeError('Not enough data'); opts = Object.assign({ validate: true }, opts || {}); diff --git a/ts_src/payments/index.ts b/ts_src/payments/index.ts index ca72f72cb..bd1ac0d84 100644 --- a/ts_src/payments/index.ts +++ b/ts_src/payments/index.ts @@ -1,3 +1,10 @@ +/** + * Represents a payment object, which is used to create a payment. + * + * Supports P2PKH、P2SH、P2WPKH、P2WSH、P2TR and so on + * + * @packageDocumentation + */ import { Network } from '../networks'; import { Taptree } from '../types'; import { p2data as embed } from './embed'; diff --git a/ts_src/payments/p2ms.ts b/ts_src/payments/p2ms.ts index 8ba33479c..ffbf0155b 100644 --- a/ts_src/payments/p2ms.ts +++ b/ts_src/payments/p2ms.ts @@ -9,6 +9,13 @@ const OP_INT_BASE = OPS.OP_RESERVED; // OP_1 - 1 // input: OP_0 [signatures ...] // output: m [pubKeys ...] n OP_CHECKMULTISIG +/** + * Represents a function that creates a Pay-to-Multisig (P2MS) payment object. + * @param a - The payment object. + * @param opts - Optional payment options. + * @returns The created payment object. + * @throws {TypeError} If the provided data is not valid. + */ export function p2ms(a: Payment, opts?: PaymentOpts): Payment { if ( !a.input && diff --git a/ts_src/payments/p2pk.ts b/ts_src/payments/p2pk.ts index 7273f53fb..c6c83b35d 100644 --- a/ts_src/payments/p2pk.ts +++ b/ts_src/payments/p2pk.ts @@ -7,6 +7,14 @@ const OPS = bscript.OPS; // input: {signature} // output: {pubKey} OP_CHECKSIG +/** + * Creates a pay-to-public-key (P2PK) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2PK payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ export function p2pk(a: Payment, opts?: PaymentOpts): Payment { if (!a.input && !a.output && !a.pubkey && !a.input && !a.signature) throw new TypeError('Not enough data'); diff --git a/ts_src/payments/p2pkh.ts b/ts_src/payments/p2pkh.ts index 4947c832a..2873a6ebe 100644 --- a/ts_src/payments/p2pkh.ts +++ b/ts_src/payments/p2pkh.ts @@ -9,6 +9,14 @@ const OPS = bscript.OPS; // input: {signature} {pubkey} // output: OP_DUP OP_HASH160 {hash160(pubkey)} OP_EQUALVERIFY OP_CHECKSIG +/** + * Creates a Pay-to-Public-Key-Hash (P2PKH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2PKH payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ export function p2pkh(a: Payment, opts?: PaymentOpts): Payment { if (!a.address && !a.hash && !a.output && !a.pubkey && !a.input) throw new TypeError('Not enough data'); diff --git a/ts_src/payments/p2sh.ts b/ts_src/payments/p2sh.ts index f4a07c55d..2f5f936c6 100644 --- a/ts_src/payments/p2sh.ts +++ b/ts_src/payments/p2sh.ts @@ -16,6 +16,14 @@ const OPS = bscript.OPS; // input: [redeemScriptSig ...] {redeemScript} // witness: // output: OP_HASH160 {hash160(redeemScript)} OP_EQUAL +/** + * Creates a Pay-to-Script-Hash (P2SH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2SH payment object. + * @throws {TypeError} If the required data is not provided or if the data is invalid. + */ export function p2sh(a: Payment, opts?: PaymentOpts): Payment { if (!a.address && !a.hash && !a.output && !a.redeem && !a.input) throw new TypeError('Not enough data'); diff --git a/ts_src/payments/p2tr.ts b/ts_src/payments/p2tr.ts index b92d76cc3..c1140b715 100644 --- a/ts_src/payments/p2tr.ts +++ b/ts_src/payments/p2tr.ts @@ -25,6 +25,14 @@ const OPS = bscript.OPS; const TAPROOT_WITNESS_VERSION = 0x01; const ANNEX_PREFIX = 0x50; +/** + * Creates a Pay-to-Taproot (P2TR) payment object. + * + * @param a - The payment object containing the necessary data for P2TR. + * @param opts - Optional payment options. + * @returns The P2TR payment object. + * @throws {TypeError} If the provided data is invalid or insufficient. + */ export function p2tr(a: Payment, opts?: PaymentOpts): Payment { if ( !a.address && diff --git a/ts_src/payments/p2wpkh.ts b/ts_src/payments/p2wpkh.ts index a4497fece..997cb6292 100644 --- a/ts_src/payments/p2wpkh.ts +++ b/ts_src/payments/p2wpkh.ts @@ -12,6 +12,14 @@ const EMPTY_BUFFER = Buffer.alloc(0); // witness: {signature} {pubKey} // input: <> // output: OP_0 {pubKeyHash} +/** + * Creates a pay-to-witness-public-key-hash (p2wpkh) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The p2wpkh payment object. + * @throws {TypeError} If the required data is missing or invalid. + */ export function p2wpkh(a: Payment, opts?: PaymentOpts): Payment { if (!a.address && !a.hash && !a.output && !a.pubkey && !a.witness) throw new TypeError('Not enough data'); diff --git a/ts_src/payments/p2wsh.ts b/ts_src/payments/p2wsh.ts index 41cefe686..bd9339277 100644 --- a/ts_src/payments/p2wsh.ts +++ b/ts_src/payments/p2wsh.ts @@ -25,6 +25,14 @@ function chunkHasUncompressedPubkey(chunk: StackElement): boolean { // input: <> // witness: [redeemScriptSig ...] {redeemScript} // output: OP_0 {sha256(redeemScript)} +/** + * Creates a Pay-to-Witness-Script-Hash (P2WSH) payment object. + * + * @param a - The payment object containing the necessary data. + * @param opts - Optional payment options. + * @returns The P2WSH payment object. + * @throws {TypeError} If the required data is missing or invalid. + */ export function p2wsh(a: Payment, opts?: PaymentOpts): Payment { if (!a.address && !a.hash && !a.output && !a.redeem && !a.witness) throw new TypeError('Not enough data'); diff --git a/ts_src/psbt.ts b/ts_src/psbt.ts index a69dc1e08..a44646592 100644 --- a/ts_src/psbt.ts +++ b/ts_src/psbt.ts @@ -92,6 +92,7 @@ const DEFAULT_OPTS: PsbtOpts = { * There are 6 roles that this class fulfills. (Explained in BIP174) * * Creator: This can be done with `new Psbt()` + * * Updater: This can be done with `psbt.addInput(input)`, `psbt.addInputs(inputs)`, * `psbt.addOutput(output)`, `psbt.addOutputs(outputs)` when you are looking to * add new inputs and outputs to the PSBT, and `psbt.updateGlobal(itemObject)`, @@ -102,20 +103,24 @@ const DEFAULT_OPTS: PsbtOpts = { * data for updateOutput. * For a list of what attributes should be what types. Check the bip174 library. * Also, check the integration tests for some examples of usage. + * * Signer: There are a few methods. signAllInputs and signAllInputsAsync, which will search all input * information for your pubkey or pubkeyhash, and only sign inputs where it finds * your info. Or you can explicitly sign a specific input with signInput and * signInputAsync. For the async methods you can create a SignerAsync object * and use something like a hardware wallet to sign with. (You must implement this) + * * Combiner: psbts can be combined easily with `psbt.combine(psbt2, psbt3, psbt4 ...)` * the psbt calling combine will always have precedence when a conflict occurs. * Combine checks if the internal bitcoin transaction is the same, so be sure that * all sequences, version, locktime, etc. are the same before combining. + * * Input Finalizer: This role is fairly important. Not only does it need to construct * the input scriptSigs and witnesses, but it SHOULD verify the signatures etc. * Before running `psbt.finalizeAllInputs()` please run `psbt.validateSignaturesOfAllInputs()` * Running any finalize method will delete any data in the input(s) that are no longer * needed due to the finalized scripts containing the information. + * * Transaction Extractor: This role will perform some checks before returning a * Transaction object. Such as fee rate not being larger than maximumFeeRate etc. */ @@ -151,7 +156,7 @@ export class Psbt { __NON_WITNESS_UTXO_BUF_CACHE: [], __TX_IN_CACHE: {}, __TX: (this.data.globalMap.unsignedTx as PsbtTransaction).tx, - // Psbt's predecesor (TransactionBuilder - now removed) behavior + // Psbt's predecessor (TransactionBuilder - now removed) behavior // was to not confirm input values before signing. // Even though we highly encourage people to get // the full parent transaction to verify values, the ability to @@ -1673,7 +1678,7 @@ function getHashForSig( console.warn( 'Warning: Signing non-segwit inputs without the full parent transaction ' + 'means there is a chance that a miner could feed you incorrect information ' + - "to trick you into paying large fees. This behavior is the same as Psbt's predecesor " + + "to trick you into paying large fees. This behavior is the same as Psbt's predecessor " + '(TransactionBuilder - now removed) when signing non-segwit scripts. You are not ' + 'able to export this Psbt with toBuffer|toBase64|toHex since it is not ' + 'BIP174 compliant.\n*********************\nPROCEED WITH CAUTION!\n' + diff --git a/ts_src/psbt/bip371.ts b/ts_src/psbt/bip371.ts index 375d35cc6..752265b0b 100644 --- a/ts_src/psbt/bip371.ts +++ b/ts_src/psbt/bip371.ts @@ -337,6 +337,14 @@ function checkMixedTaprootAndNonTaprootOutputFields( ); } +/** + * Checks if the tap leaf is part of the tap tree for the given input data. + * Throws an error if the tap leaf is not part of the tap tree. + * @param inputData - The original PsbtInput data. + * @param newInputData - The new PsbtInput data. + * @param action - The action being performed. + * @throws {Error} - If the tap leaf is not part of the tap tree. + */ function checkIfTapLeafInTree( inputData: PsbtInput, newInputData: PsbtInput, @@ -364,6 +372,12 @@ function checkIfTapLeafInTree( } } +/** + * Checks if a TapLeafScript is present in a Merkle tree. + * @param tapLeaf The TapLeafScript to check. + * @param merkleRoot The Merkle root of the tree. If not provided, the function assumes the TapLeafScript is present. + * @returns A boolean indicating whether the TapLeafScript is present in the tree. + */ function isTapLeafInTree(tapLeaf: TapLeafScript, merkleRoot?: Buffer): boolean { if (!merkleRoot) return true; @@ -376,6 +390,13 @@ function isTapLeafInTree(tapLeaf: TapLeafScript, merkleRoot?: Buffer): boolean { return rootHash.equals(merkleRoot); } +/** + * Sorts the signatures in the input's tapScriptSig array based on their position in the tapLeaf script. + * + * @param input - The PsbtInput object. + * @param tapLeaf - The TapLeafScript object. + * @returns An array of sorted signatures as Buffers. + */ function sortSignatures(input: PsbtInput, tapLeaf: TapLeafScript): Buffer[] { const leafHash = tapleafHash({ output: tapLeaf.script, @@ -389,6 +410,12 @@ function sortSignatures(input: PsbtInput, tapLeaf: TapLeafScript): Buffer[] { .map(t => t.signature) as Buffer[]; } +/** + * Adds the position of a public key in a script to a TapScriptSig object. + * @param script The script in which to find the position of the public key. + * @param tss The TapScriptSig object to add the position to. + * @returns A TapScriptSigWitPosition object with the added position. + */ function addPubkeyPositionInScript( script: Buffer, tss: TapScriptSig, @@ -427,6 +454,14 @@ function findTapLeafToFinalize( return tapLeaf; } +/** + * Determines whether a TapLeafScript can be finalized. + * + * @param leaf - The TapLeafScript to check. + * @param tapScriptSig - The array of TapScriptSig objects. + * @param hash - The optional hash to compare with the leaf hash. + * @returns A boolean indicating whether the TapLeafScript can be finalized. + */ function canFinalizeLeaf( leaf: TapLeafScript, tapScriptSig: TapScriptSig[], @@ -443,6 +478,12 @@ function canFinalizeLeaf( ); } +/** + * Checks if the given PsbtInput or PsbtOutput has non-taproot fields. + * Non-taproot fields include redeemScript, witnessScript, and bip32Derivation. + * @param io The PsbtInput or PsbtOutput to check. + * @returns A boolean indicating whether the given input or output has non-taproot fields. + */ function hasNonTaprootFields(io: PsbtInput | PsbtOutput): boolean { return ( io && diff --git a/ts_src/psbt/psbtutils.ts b/ts_src/psbt/psbtutils.ts index 173e0215c..19cf33e5b 100644 --- a/ts_src/psbt/psbtutils.ts +++ b/ts_src/psbt/psbtutils.ts @@ -23,6 +23,16 @@ export const isP2WSHScript = isPaymentFactory(payments.p2wsh); export const isP2SHScript = isPaymentFactory(payments.p2sh); export const isP2TR = isPaymentFactory(payments.p2tr); +/** + * Converts a witness stack to a script witness. + * @param witness The witness stack to convert. + * @returns The script witness as a Buffer. + */ +/** + * Converts a witness stack to a script witness. + * @param witness The witness stack to convert. + * @returns The converted script witness. + */ export function witnessStackToScriptWitness(witness: Buffer[]): Buffer { let buffer = Buffer.allocUnsafe(0); @@ -53,6 +63,13 @@ export function witnessStackToScriptWitness(witness: Buffer[]): Buffer { return buffer; } +/** + * Finds the position of a public key in a script. + * @param pubkey The public key to search for. + * @param script The script to search in. + * @returns The index of the public key in the script, or -1 if not found. + * @throws {Error} If there is an unknown script error. + */ export function pubkeyPositionInScript(pubkey: Buffer, script: Buffer): number { const pubkeyHash = hash160(pubkey); const pubkeyXOnly = pubkey.slice(1, 33); // slice before calling? @@ -70,10 +87,22 @@ export function pubkeyPositionInScript(pubkey: Buffer, script: Buffer): number { }); } +/** + * Checks if a public key is present in a script. + * @param pubkey The public key to check. + * @param script The script to search in. + * @returns A boolean indicating whether the public key is present in the script. + */ export function pubkeyInScript(pubkey: Buffer, script: Buffer): boolean { return pubkeyPositionInScript(pubkey, script) !== -1; } +/** + * Checks if an input contains a signature for a specific action. + * @param input - The input to check. + * @param action - The action to check for. + * @returns A boolean indicating whether the input contains a signature for the specified action. + */ export function checkInputForSig(input: PsbtInput, action: string): boolean { const pSigs = extractPartialSigs(input); return pSigs.some(pSig => @@ -85,6 +114,13 @@ type SignatureDecodeFunc = (buffer: Buffer) => { signature: Buffer; hashType: number; }; +/** + * Determines if a given action is allowed for a signature block. + * @param signature - The signature block. + * @param signatureDecodeFn - The function used to decode the signature. + * @param action - The action to be checked. + * @returns True if the action is allowed, false otherwise. + */ export function signatureBlocksAction( signature: Buffer, signatureDecodeFn: SignatureDecodeFunc, @@ -110,6 +146,16 @@ export function signatureBlocksAction( return false; } +/** + * Extracts the signatures from a PsbtInput object. + * If the input has partial signatures, it returns an array of the signatures. + * If the input does not have partial signatures, it checks if it has a finalScriptSig or finalScriptWitness. + * If it does, it extracts the signatures from the final scripts and returns them. + * If none of the above conditions are met, it returns an empty array. + * + * @param input - The PsbtInput object from which to extract the signatures. + * @returns An array of signatures extracted from the PsbtInput object. + */ function extractPartialSigs(input: PsbtInput): Buffer[] { let pSigs: PartialSig[] = []; if ((input.partialSig || []).length === 0) { @@ -121,6 +167,14 @@ function extractPartialSigs(input: PsbtInput): Buffer[] { return pSigs.map(p => p.signature); } +/** + * Retrieves the partial signatures (Psigs) from the input's final scripts. + * Psigs are extracted from both the final scriptSig and final scriptWitness of the input. + * Only canonical script signatures are considered. + * + * @param input - The PsbtInput object representing the input. + * @returns An array of PartialSig objects containing the extracted Psigs. + */ function getPsigsFromInputFinalScripts(input: PsbtInput): PartialSig[] { const scriptItems = !input.finalScriptSig ? [] diff --git a/ts_src/push_data.ts b/ts_src/push_data.ts index 56bb02ab2..ade5f82f9 100644 --- a/ts_src/push_data.ts +++ b/ts_src/push_data.ts @@ -1,9 +1,24 @@ import { OPS } from './ops'; +/** + * Calculates the encoding length of a number used for push data in Bitcoin transactions. + * @param i The number to calculate the encoding length for. + * @returns The encoding length of the number. + */ export function encodingLength(i: number): number { return i < OPS.OP_PUSHDATA1 ? 1 : i <= 0xff ? 2 : i <= 0xffff ? 3 : 5; } +/** + * Encodes a number into a buffer using a variable-length encoding scheme. + * The encoded buffer is written starting at the specified offset. + * Returns the size of the encoded buffer. + * + * @param buffer - The buffer to write the encoded data into. + * @param num - The number to encode. + * @param offset - The offset at which to start writing the encoded buffer. + * @returns The size of the encoded buffer. + */ export function encode(buffer: Buffer, num: number, offset: number): number { const size = encodingLength(num); @@ -30,6 +45,12 @@ export function encode(buffer: Buffer, num: number, offset: number): number { return size; } +/** + * Decodes a buffer and returns information about the opcode, number, and size. + * @param buffer - The buffer to decode. + * @param offset - The offset within the buffer to start decoding. + * @returns An object containing the opcode, number, and size, or null if decoding fails. + */ export function decode( buffer: Buffer, offset: number, diff --git a/ts_src/script.ts b/ts_src/script.ts index 4f246fe7a..54ee98fde 100644 --- a/ts_src/script.ts +++ b/ts_src/script.ts @@ -1,3 +1,7 @@ +/** + * Script tools, including decompile, compile, toASM, fromASM, toStack, isCanonicalPubKey, isCanonicalScriptSignature + * @packageDocumentation + */ import * as bip66 from './bip66'; import { OPS, REVERSE_OPS } from './ops'; import { Stack } from './payments'; @@ -50,6 +54,13 @@ function singleChunkIsBuffer(buf: number | Buffer): buf is Buffer { return Buffer.isBuffer(buf); } +/** + * Compiles an array of chunks into a Buffer. + * + * @param chunks - The array of chunks to compile. + * @returns The compiled Buffer. + * @throws Error if the compilation fails. + */ export function compile(chunks: Buffer | Stack): Buffer { // TODO: remove me if (chunksIsBuffer(chunks)) return chunks; @@ -147,6 +158,12 @@ export function decompile( return chunks; } +/** + * Converts the given chunks into an ASM (Assembly) string representation. + * If the chunks parameter is a Buffer, it will be decompiled into a Stack before conversion. + * @param chunks - The chunks to convert into ASM. + * @returns The ASM string representation of the chunks. + */ export function toASM(chunks: Buffer | Array): string { if (chunksIsBuffer(chunks)) { chunks = decompile(chunks) as Stack; @@ -167,6 +184,11 @@ export function toASM(chunks: Buffer | Array): string { .join(' '); } +/** + * Converts an ASM string to a Buffer. + * @param asm The ASM string to convert. + * @returns The converted Buffer. + */ export function fromASM(asm: string): Buffer { typeforce(types.String, asm); @@ -182,6 +204,12 @@ export function fromASM(asm: string): Buffer { ); } +/** + * Converts the given chunks into a stack of buffers. + * + * @param chunks - The chunks to convert. + * @returns The stack of buffers. + */ export function toStack(chunks: Buffer | Array): Buffer[] { chunks = decompile(chunks) as Stack; typeforce(isPushOnly, chunks); diff --git a/ts_src/script_number.ts b/ts_src/script_number.ts index a4c502fc9..1ad20e2ff 100644 --- a/ts_src/script_number.ts +++ b/ts_src/script_number.ts @@ -1,3 +1,13 @@ +/** + * Decodes a script number from a buffer. + * + * @param buffer - The buffer containing the script number. + * @param maxLength - The maximum length of the script number. Defaults to 4. + * @param minimal - Whether the script number should be minimal. Defaults to true. + * @returns The decoded script number. + * @throws {TypeError} If the script number overflows the maximum length. + * @throws {Error} If the script number is not minimally encoded when minimal is true. + */ export function decode( buffer: Buffer, maxLength?: number, @@ -50,6 +60,12 @@ function scriptNumSize(i: number): number { : 0; } +/** + * Encodes a number into a Buffer using a specific format. + * + * @param _number - The number to encode. + * @returns The encoded number as a Buffer. + */ export function encode(_number: number): Buffer { let value = Math.abs(_number); const size = scriptNumSize(value); diff --git a/ts_src/script_signature.ts b/ts_src/script_signature.ts index f10ed86b7..571720607 100644 --- a/ts_src/script_signature.ts +++ b/ts_src/script_signature.ts @@ -4,6 +4,11 @@ import * as types from './types'; const { typeforce } = types; const ZERO = Buffer.alloc(1, 0); +/** + * Converts a buffer to a DER-encoded buffer. + * @param x - The buffer to be converted. + * @returns The DER-encoded buffer. + */ function toDER(x: Buffer): Buffer { let i = 0; while (x[i] === 0) ++i; @@ -13,6 +18,13 @@ function toDER(x: Buffer): Buffer { return x; } +/** + * Converts a DER-encoded signature to a buffer. + * If the first byte of the input buffer is 0x00, it is skipped. + * The resulting buffer is 32 bytes long, filled with zeros if necessary. + * @param x - The DER-encoded signature. + * @returns The converted buffer. + */ function fromDER(x: Buffer): Buffer { if (x[0] === 0x00) x = x.slice(1); const buffer = Buffer.alloc(32, 0); @@ -27,6 +39,12 @@ interface ScriptSignature { } // BIP62: 1 byte hashType flag (only 0x01, 0x02, 0x03, 0x81, 0x82 and 0x83 are allowed) +/** + * Decodes a buffer into a ScriptSignature object. + * @param buffer - The buffer to decode. + * @returns The decoded ScriptSignature object. + * @throws Error if the hashType is invalid. + */ export function decode(buffer: Buffer): ScriptSignature { const hashType = buffer.readUInt8(buffer.length - 1); if (!isDefinedHashType(hashType)) { @@ -41,6 +59,13 @@ export function decode(buffer: Buffer): ScriptSignature { return { signature, hashType }; } +/** + * Encodes a signature and hash type into a buffer. + * @param signature - The signature to encode. + * @param hashType - The hash type to encode. + * @returns The encoded buffer. + * @throws Error if the hashType is invalid. + */ export function encode(signature: Buffer, hashType: number): Buffer { typeforce( { diff --git a/ts_src/transaction.ts b/ts_src/transaction.ts index 39b975545..665583ec5 100644 --- a/ts_src/transaction.ts +++ b/ts_src/transaction.ts @@ -60,6 +60,9 @@ export interface Input { witness: Buffer[]; } +/** + * Represents a Bitcoin transaction. + */ export class Transaction { static readonly DEFAULT_SEQUENCE = 0xffffffff; static readonly SIGHASH_DEFAULT = 0x00; diff --git a/ts_src/types.ts b/ts_src/types.ts index 937805617..971b42363 100644 --- a/ts_src/types.ts +++ b/ts_src/types.ts @@ -8,6 +8,12 @@ const EC_P = NBuffer.from( 'hex', ); +/** + * Checks if two arrays of Buffers are equal. + * @param a - The first array of Buffers. + * @param b - The second array of Buffers. + * @returns True if the arrays are equal, false otherwise. + */ export function stacksEqual(a: Buffer[], b: Buffer[]): boolean { if (a.length !== b.length) return false; @@ -16,6 +22,11 @@ export function stacksEqual(a: Buffer[], b: Buffer[]): boolean { }); } +/** + * Checks if the given value is a valid elliptic curve point. + * @param p - The value to check. + * @returns True if the value is a valid elliptic curve point, false otherwise. + */ export function isPoint(p: Buffer | number | undefined | null): boolean { if (!NBuffer.isBuffer(p)) return false; if (p.length < 33) return false; diff --git a/typedoc.json b/typedoc.json new file mode 100644 index 000000000..041e85042 --- /dev/null +++ b/typedoc.json @@ -0,0 +1,17 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "name": "bitcoinjs-lib", + "entryPoints": ["./ts_src"], + "out": "docs", + "searchCategoryBoosts": { + "Component": 2, + "Model": 1.2 + }, + "searchGroupBoosts": { + "Classes": 1.5 + }, + "visibilityFilters": {}, + "hideGenerator": true, + "excludePrivate": true, + "includeVersion": true +} \ No newline at end of file