├── .github └── workflows │ └── main_ci.yml ├── .gitignore ├── .mocharc.json ├── .npm-audit-whitelister.json ├── .prettierrc.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── fixup.cjs ├── package-lock.json ├── package.json ├── src ├── cjs │ ├── ecpair.cjs │ ├── ecpair.d.ts │ ├── index.cjs │ ├── index.d.ts │ ├── networks.cjs │ ├── networks.d.ts │ ├── testecc.cjs │ ├── testecc.d.ts │ ├── types.cjs │ └── types.d.ts └── esm │ ├── ecpair.js │ ├── index.js │ ├── networks.js │ ├── testecc.js │ └── types.js ├── test ├── ecpair.spec.ts ├── fixtures │ └── ecpair.json └── tsconfig.json ├── ts_src ├── ecpair.ts ├── index.ts ├── networks.ts ├── testecc.ts └── types.ts ├── tsconfig.base.json ├── tsconfig.cjs.json ├── tsconfig.json └── tslint.json /.github/workflows/main_ci.yml: -------------------------------------------------------------------------------- 1 | name: Run Tests 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | 9 | jobs: 10 | unit: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v4 15 | with: 16 | node-version: 20 17 | registry-url: https://registry.npmjs.org/ 18 | - run: npm ci 19 | - run: npm run unit 20 | coverage: 21 | runs-on: ubuntu-latest 22 | steps: 23 | - uses: actions/checkout@v3 24 | - uses: actions/setup-node@v4 25 | with: 26 | node-version: 20 27 | registry-url: https://registry.npmjs.org/ 28 | - run: npm ci 29 | - run: npm run coverage 30 | format: 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v3 34 | - uses: actions/setup-node@v4 35 | with: 36 | node-version: 20 37 | registry-url: https://registry.npmjs.org/ 38 | - run: npm ci 39 | - run: npm run format:ci 40 | gitdiff: 41 | runs-on: ubuntu-latest 42 | steps: 43 | - uses: actions/checkout@v3 44 | - uses: actions/setup-node@v4 45 | with: 46 | node-version: 20 47 | registry-url: https://registry.npmjs.org/ 48 | - run: npm ci 49 | - run: npm run gitdiff:ci 50 | lint: 51 | runs-on: ubuntu-latest 52 | steps: 53 | - uses: actions/checkout@v3 54 | - uses: actions/setup-node@v4 55 | with: 56 | node-version: 20 57 | registry-url: https://registry.npmjs.org/ 58 | - run: npm ci 59 | - run: npm run lint 60 | lint-tests: 61 | runs-on: ubuntu-latest 62 | steps: 63 | - uses: actions/checkout@v3 64 | - uses: actions/setup-node@v4 65 | with: 66 | node-version: 20 67 | registry-url: https://registry.npmjs.org/ 68 | - run: npm ci 69 | - run: npm run lint:tests 70 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | .nyc_output 4 | npm-debug.log 5 | test/*.js 6 | !test/ts-node-register.js 7 | -------------------------------------------------------------------------------- /.mocharc.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/mocharc.json", 3 | "require": "tsx" 4 | } 5 | -------------------------------------------------------------------------------- /.npm-audit-whitelister.json: -------------------------------------------------------------------------------- 1 | [] -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all" 4 | } 5 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Refer to Bitcoinjs-lib 2 | 3 | [Please refer to bitcoinjs-lib CONTRIBUTING for a guide on how to contribute by clicking here.](https://github.com/bitcoinjs/bitcoinjs-lib/blob/master/CONTRIBUTING.md) 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2011-2021 bitcoinjs-lib contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ecpair 2 | [![Github CI](https://github.com/bitcoinjs/ecpair/actions/workflows/main_ci.yml/badge.svg)](https://github.com/bitcoinjs/ecpair/actions/workflows/main_ci.yml) [![NPM](https://img.shields.io/npm/v/ecpair.svg)](https://www.npmjs.org/package/ecpair) [![code style: prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat-square)](https://github.com/prettier/prettier) 3 | 4 | A library for managing SECP256k1 keypairs written in TypeScript with transpiled JavaScript committed to git. 5 | 6 | **Note** `ECPair`.makeRandom() uses the `crypto.getRandomValues` if there is no custom `rng` function provided. This API currently is still an experimental feature as of Node.js 18.19.0. To work around this you can do one of the following: 7 | 1. Use a polyfill for crypto.getRandomValues() 8 | 2. Use the `--experimental-global-webcrypto` flag when running node.js. 9 | 3. Pass in a custom rng function to generate random values. 10 | 11 | ## Example 12 | 13 | TypeScript 14 | 15 | ``` typescript 16 | import { Signer, SignerAsync, ECPairInterface, ECPairFactory, ECPairAPI, TinySecp256k1Interface } from 'ecpair'; 17 | import * as crypto from 'crypto'; 18 | 19 | // You need to provide the ECC library. The ECC library must implement 20 | // all the methods of the `TinySecp256k1Interface` interface. 21 | const tinysecp: TinySecp256k1Interface = require('tiny-secp256k1'); 22 | const ECPair: ECPairAPI = ECPairFactory(tinysecp); 23 | 24 | // You don't need to explicitly write ECPairInterface, but just to show 25 | // that the keyPair implements the interface this example includes it. 26 | 27 | // From WIF 28 | const keyPair1: ECPairInterface = ECPair.fromWIF('KynD8ZKdViVo5W82oyxvE18BbG6nZPVQ8Td8hYbwU94RmyUALUik'); 29 | // Random private key 30 | const keyPair2 = ECPair.fromPrivateKey(crypto.randomBytes(32)); 31 | // OR (uses randombytes library, compatible with browser) 32 | const keyPair3 = ECPair.makeRandom(); 33 | // OR use your own custom random buffer generator BE CAREFUL!!!! 34 | const customRandomBufferFunc = (size: number): Buffer => crypto.randomBytes(size); 35 | const keyPair4 = ECPair.makeRandom({ rng: customRandomBufferFunc }); 36 | // From pubkey (33 or 65 byte DER format public key) 37 | const keyPair5 = ECPair.fromPublicKey(keyPair1.publicKey); 38 | 39 | // Pass a custom network 40 | const network = {}; // Your custom network object here 41 | ECPair.makeRandom({ network }); 42 | ECPair.fromPrivateKey(crypto.randomBytes(32), { network }); 43 | ECPair.fromPublicKey(keyPair1.publicKey, { network }); 44 | // fromWIF will check the WIF version against the network you pass in 45 | // pass in multiple networks if you are not sure 46 | ECPair.fromWIF('wif key...', network); 47 | const network2 = {}; // Your custom network object here 48 | const network3 = {}; // Your custom network object here 49 | ECPair.fromWIF('wif key...', [network, network2, network3]); 50 | ``` 51 | 52 | ## LICENSE [MIT](LICENSE) 53 | Written and tested by [bitcoinjs-lib](https://github.com/bitcoinjs/bitcoinjs-lib) contributors since 2014. 54 | -------------------------------------------------------------------------------- /fixup.cjs: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | 4 | const updateRequires = (filePath) => { 5 | let content = fs.readFileSync(filePath, 'utf8'); 6 | //replace local imports eg. require('./ecpair') to require('ecpair.cjs') 7 | content = content.replace(/require\('\.\/([^']*)'\)/g, "require('./$1.cjs')"); 8 | 9 | fs.writeFileSync(filePath, content, 'utf8'); 10 | }; 11 | 12 | const updateImports = (filePath) => { 13 | let content = fs.readFileSync(filePath, 'utf8'); 14 | //replace local imports eg. from './types'; to from './types.js'; 15 | content = content.replace(/from '\.\/([^']*)'/g, "from './$1.js'"); 16 | 17 | fs.writeFileSync(filePath, content, 'utf8'); 18 | }; 19 | 20 | const processFiles = (dir) => { 21 | fs.readdirSync(dir).forEach((file) => { 22 | const filePath = path.join(dir, file); 23 | if (fs.lstatSync(filePath).isDirectory()) { 24 | processFiles(filePath); 25 | } else if (filePath.endsWith('.cjs')) { 26 | updateRequires(filePath); 27 | } else if (filePath.endsWith('.js')) { 28 | updateImports(filePath); 29 | } 30 | }); 31 | }; 32 | 33 | const dir = path.join(__dirname, 'src'); 34 | processFiles(dir); 35 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ecpair", 3 | "version": "3.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "ecpair", 9 | "version": "3.0.0", 10 | "license": "MIT", 11 | "dependencies": { 12 | "uint8array-tools": "^0.0.8", 13 | "valibot": "^0.37.0", 14 | "wif": "^5.0.0" 15 | }, 16 | "devDependencies": { 17 | "@types/create-hash": "^1.2.2", 18 | "@types/mocha": "^5.2.7", 19 | "@types/node": "^20.14.2", 20 | "@types/wif": "^2.0.2", 21 | "c8": "^10.1.2", 22 | "mocha": "^10.7.3", 23 | "prettier": "^3.3.3", 24 | "rimraf": "^2.6.3", 25 | "tiny-secp256k1": "^2.2.3", 26 | "tslint": "^6.1.3", 27 | "tsx": "^4.16.5", 28 | "typescript": "^5.0.4" 29 | }, 30 | "engines": { 31 | "node": ">=18.0.0" 32 | } 33 | }, 34 | "node_modules/@babel/code-frame": { 35 | "version": "7.15.8", 36 | "dev": true, 37 | "license": "MIT", 38 | "dependencies": { 39 | "@babel/highlight": "^7.14.5" 40 | }, 41 | "engines": { 42 | "node": ">=6.9.0" 43 | } 44 | }, 45 | "node_modules/@babel/helper-validator-identifier": { 46 | "version": "7.15.7", 47 | "dev": true, 48 | "license": "MIT", 49 | "engines": { 50 | "node": ">=6.9.0" 51 | } 52 | }, 53 | "node_modules/@babel/highlight": { 54 | "version": "7.14.5", 55 | "dev": true, 56 | "license": "MIT", 57 | "dependencies": { 58 | "@babel/helper-validator-identifier": "^7.14.5", 59 | "chalk": "^2.0.0", 60 | "js-tokens": "^4.0.0" 61 | }, 62 | "engines": { 63 | "node": ">=6.9.0" 64 | } 65 | }, 66 | "node_modules/@bcoe/v8-coverage": { 67 | "version": "0.2.3", 68 | "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", 69 | "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", 70 | "dev": true 71 | }, 72 | "node_modules/@esbuild/aix-ppc64": { 73 | "version": "0.23.1", 74 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.1.tgz", 75 | "integrity": "sha512-6VhYk1diRqrhBAqpJEdjASR/+WVRtfjpqKuNw11cLiaWpAT/Uu+nokB+UJnevzy/P9C/ty6AOe0dwueMrGh/iQ==", 76 | "cpu": [ 77 | "ppc64" 78 | ], 79 | "dev": true, 80 | "optional": true, 81 | "os": [ 82 | "aix" 83 | ], 84 | "engines": { 85 | "node": ">=18" 86 | } 87 | }, 88 | "node_modules/@esbuild/android-arm": { 89 | "version": "0.23.1", 90 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.1.tgz", 91 | "integrity": "sha512-uz6/tEy2IFm9RYOyvKl88zdzZfwEfKZmnX9Cj1BHjeSGNuGLuMD1kR8y5bteYmwqKm1tj8m4cb/aKEorr6fHWQ==", 92 | "cpu": [ 93 | "arm" 94 | ], 95 | "dev": true, 96 | "optional": true, 97 | "os": [ 98 | "android" 99 | ], 100 | "engines": { 101 | "node": ">=18" 102 | } 103 | }, 104 | "node_modules/@esbuild/android-arm64": { 105 | "version": "0.23.1", 106 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.1.tgz", 107 | "integrity": "sha512-xw50ipykXcLstLeWH7WRdQuysJqejuAGPd30vd1i5zSyKK3WE+ijzHmLKxdiCMtH1pHz78rOg0BKSYOSB/2Khw==", 108 | "cpu": [ 109 | "arm64" 110 | ], 111 | "dev": true, 112 | "optional": true, 113 | "os": [ 114 | "android" 115 | ], 116 | "engines": { 117 | "node": ">=18" 118 | } 119 | }, 120 | "node_modules/@esbuild/android-x64": { 121 | "version": "0.23.1", 122 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.1.tgz", 123 | "integrity": "sha512-nlN9B69St9BwUoB+jkyU090bru8L0NA3yFvAd7k8dNsVH8bi9a8cUAUSEcEEgTp2z3dbEDGJGfP6VUnkQnlReg==", 124 | "cpu": [ 125 | "x64" 126 | ], 127 | "dev": true, 128 | "optional": true, 129 | "os": [ 130 | "android" 131 | ], 132 | "engines": { 133 | "node": ">=18" 134 | } 135 | }, 136 | "node_modules/@esbuild/darwin-arm64": { 137 | "version": "0.23.1", 138 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.1.tgz", 139 | "integrity": "sha512-YsS2e3Wtgnw7Wq53XXBLcV6JhRsEq8hkfg91ESVadIrzr9wO6jJDMZnCQbHm1Guc5t/CdDiFSSfWP58FNuvT3Q==", 140 | "cpu": [ 141 | "arm64" 142 | ], 143 | "dev": true, 144 | "optional": true, 145 | "os": [ 146 | "darwin" 147 | ], 148 | "engines": { 149 | "node": ">=18" 150 | } 151 | }, 152 | "node_modules/@esbuild/darwin-x64": { 153 | "version": "0.23.1", 154 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.1.tgz", 155 | "integrity": "sha512-aClqdgTDVPSEGgoCS8QDG37Gu8yc9lTHNAQlsztQ6ENetKEO//b8y31MMu2ZaPbn4kVsIABzVLXYLhCGekGDqw==", 156 | "cpu": [ 157 | "x64" 158 | ], 159 | "dev": true, 160 | "optional": true, 161 | "os": [ 162 | "darwin" 163 | ], 164 | "engines": { 165 | "node": ">=18" 166 | } 167 | }, 168 | "node_modules/@esbuild/freebsd-arm64": { 169 | "version": "0.23.1", 170 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.1.tgz", 171 | "integrity": "sha512-h1k6yS8/pN/NHlMl5+v4XPfikhJulk4G+tKGFIOwURBSFzE8bixw1ebjluLOjfwtLqY0kewfjLSrO6tN2MgIhA==", 172 | "cpu": [ 173 | "arm64" 174 | ], 175 | "dev": true, 176 | "optional": true, 177 | "os": [ 178 | "freebsd" 179 | ], 180 | "engines": { 181 | "node": ">=18" 182 | } 183 | }, 184 | "node_modules/@esbuild/freebsd-x64": { 185 | "version": "0.23.1", 186 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.1.tgz", 187 | "integrity": "sha512-lK1eJeyk1ZX8UklqFd/3A60UuZ/6UVfGT2LuGo3Wp4/z7eRTRYY+0xOu2kpClP+vMTi9wKOfXi2vjUpO1Ro76g==", 188 | "cpu": [ 189 | "x64" 190 | ], 191 | "dev": true, 192 | "optional": true, 193 | "os": [ 194 | "freebsd" 195 | ], 196 | "engines": { 197 | "node": ">=18" 198 | } 199 | }, 200 | "node_modules/@esbuild/linux-arm": { 201 | "version": "0.23.1", 202 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.1.tgz", 203 | "integrity": "sha512-CXXkzgn+dXAPs3WBwE+Kvnrf4WECwBdfjfeYHpMeVxWE0EceB6vhWGShs6wi0IYEqMSIzdOF1XjQ/Mkm5d7ZdQ==", 204 | "cpu": [ 205 | "arm" 206 | ], 207 | "dev": true, 208 | "optional": true, 209 | "os": [ 210 | "linux" 211 | ], 212 | "engines": { 213 | "node": ">=18" 214 | } 215 | }, 216 | "node_modules/@esbuild/linux-arm64": { 217 | "version": "0.23.1", 218 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.1.tgz", 219 | "integrity": "sha512-/93bf2yxencYDnItMYV/v116zff6UyTjo4EtEQjUBeGiVpMmffDNUyD9UN2zV+V3LRV3/on4xdZ26NKzn6754g==", 220 | "cpu": [ 221 | "arm64" 222 | ], 223 | "dev": true, 224 | "optional": true, 225 | "os": [ 226 | "linux" 227 | ], 228 | "engines": { 229 | "node": ">=18" 230 | } 231 | }, 232 | "node_modules/@esbuild/linux-ia32": { 233 | "version": "0.23.1", 234 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.1.tgz", 235 | "integrity": "sha512-VTN4EuOHwXEkXzX5nTvVY4s7E/Krz7COC8xkftbbKRYAl96vPiUssGkeMELQMOnLOJ8k3BY1+ZY52tttZnHcXQ==", 236 | "cpu": [ 237 | "ia32" 238 | ], 239 | "dev": true, 240 | "optional": true, 241 | "os": [ 242 | "linux" 243 | ], 244 | "engines": { 245 | "node": ">=18" 246 | } 247 | }, 248 | "node_modules/@esbuild/linux-loong64": { 249 | "version": "0.23.1", 250 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.1.tgz", 251 | "integrity": "sha512-Vx09LzEoBa5zDnieH8LSMRToj7ir/Jeq0Gu6qJ/1GcBq9GkfoEAoXvLiW1U9J1qE/Y/Oyaq33w5p2ZWrNNHNEw==", 252 | "cpu": [ 253 | "loong64" 254 | ], 255 | "dev": true, 256 | "optional": true, 257 | "os": [ 258 | "linux" 259 | ], 260 | "engines": { 261 | "node": ">=18" 262 | } 263 | }, 264 | "node_modules/@esbuild/linux-mips64el": { 265 | "version": "0.23.1", 266 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.1.tgz", 267 | "integrity": "sha512-nrFzzMQ7W4WRLNUOU5dlWAqa6yVeI0P78WKGUo7lg2HShq/yx+UYkeNSE0SSfSure0SqgnsxPvmAUu/vu0E+3Q==", 268 | "cpu": [ 269 | "mips64el" 270 | ], 271 | "dev": true, 272 | "optional": true, 273 | "os": [ 274 | "linux" 275 | ], 276 | "engines": { 277 | "node": ">=18" 278 | } 279 | }, 280 | "node_modules/@esbuild/linux-ppc64": { 281 | "version": "0.23.1", 282 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.1.tgz", 283 | "integrity": "sha512-dKN8fgVqd0vUIjxuJI6P/9SSSe/mB9rvA98CSH2sJnlZ/OCZWO1DJvxj8jvKTfYUdGfcq2dDxoKaC6bHuTlgcw==", 284 | "cpu": [ 285 | "ppc64" 286 | ], 287 | "dev": true, 288 | "optional": true, 289 | "os": [ 290 | "linux" 291 | ], 292 | "engines": { 293 | "node": ">=18" 294 | } 295 | }, 296 | "node_modules/@esbuild/linux-riscv64": { 297 | "version": "0.23.1", 298 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.1.tgz", 299 | "integrity": "sha512-5AV4Pzp80fhHL83JM6LoA6pTQVWgB1HovMBsLQ9OZWLDqVY8MVobBXNSmAJi//Csh6tcY7e7Lny2Hg1tElMjIA==", 300 | "cpu": [ 301 | "riscv64" 302 | ], 303 | "dev": true, 304 | "optional": true, 305 | "os": [ 306 | "linux" 307 | ], 308 | "engines": { 309 | "node": ">=18" 310 | } 311 | }, 312 | "node_modules/@esbuild/linux-s390x": { 313 | "version": "0.23.1", 314 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.1.tgz", 315 | "integrity": "sha512-9ygs73tuFCe6f6m/Tb+9LtYxWR4c9yg7zjt2cYkjDbDpV/xVn+68cQxMXCjUpYwEkze2RcU/rMnfIXNRFmSoDw==", 316 | "cpu": [ 317 | "s390x" 318 | ], 319 | "dev": true, 320 | "optional": true, 321 | "os": [ 322 | "linux" 323 | ], 324 | "engines": { 325 | "node": ">=18" 326 | } 327 | }, 328 | "node_modules/@esbuild/linux-x64": { 329 | "version": "0.23.1", 330 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.1.tgz", 331 | "integrity": "sha512-EV6+ovTsEXCPAp58g2dD68LxoP/wK5pRvgy0J/HxPGB009omFPv3Yet0HiaqvrIrgPTBuC6wCH1LTOY91EO5hQ==", 332 | "cpu": [ 333 | "x64" 334 | ], 335 | "dev": true, 336 | "optional": true, 337 | "os": [ 338 | "linux" 339 | ], 340 | "engines": { 341 | "node": ">=18" 342 | } 343 | }, 344 | "node_modules/@esbuild/netbsd-x64": { 345 | "version": "0.23.1", 346 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.1.tgz", 347 | "integrity": "sha512-aevEkCNu7KlPRpYLjwmdcuNz6bDFiE7Z8XC4CPqExjTvrHugh28QzUXVOZtiYghciKUacNktqxdpymplil1beA==", 348 | "cpu": [ 349 | "x64" 350 | ], 351 | "dev": true, 352 | "optional": true, 353 | "os": [ 354 | "netbsd" 355 | ], 356 | "engines": { 357 | "node": ">=18" 358 | } 359 | }, 360 | "node_modules/@esbuild/openbsd-arm64": { 361 | "version": "0.23.1", 362 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.1.tgz", 363 | "integrity": "sha512-3x37szhLexNA4bXhLrCC/LImN/YtWis6WXr1VESlfVtVeoFJBRINPJ3f0a/6LV8zpikqoUg4hyXw0sFBt5Cr+Q==", 364 | "cpu": [ 365 | "arm64" 366 | ], 367 | "dev": true, 368 | "optional": true, 369 | "os": [ 370 | "openbsd" 371 | ], 372 | "engines": { 373 | "node": ">=18" 374 | } 375 | }, 376 | "node_modules/@esbuild/openbsd-x64": { 377 | "version": "0.23.1", 378 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.1.tgz", 379 | "integrity": "sha512-aY2gMmKmPhxfU+0EdnN+XNtGbjfQgwZj43k8G3fyrDM/UdZww6xrWxmDkuz2eCZchqVeABjV5BpildOrUbBTqA==", 380 | "cpu": [ 381 | "x64" 382 | ], 383 | "dev": true, 384 | "optional": true, 385 | "os": [ 386 | "openbsd" 387 | ], 388 | "engines": { 389 | "node": ">=18" 390 | } 391 | }, 392 | "node_modules/@esbuild/sunos-x64": { 393 | "version": "0.23.1", 394 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.1.tgz", 395 | "integrity": "sha512-RBRT2gqEl0IKQABT4XTj78tpk9v7ehp+mazn2HbUeZl1YMdaGAQqhapjGTCe7uw7y0frDi4gS0uHzhvpFuI1sA==", 396 | "cpu": [ 397 | "x64" 398 | ], 399 | "dev": true, 400 | "optional": true, 401 | "os": [ 402 | "sunos" 403 | ], 404 | "engines": { 405 | "node": ">=18" 406 | } 407 | }, 408 | "node_modules/@esbuild/win32-arm64": { 409 | "version": "0.23.1", 410 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.1.tgz", 411 | "integrity": "sha512-4O+gPR5rEBe2FpKOVyiJ7wNDPA8nGzDuJ6gN4okSA1gEOYZ67N8JPk58tkWtdtPeLz7lBnY6I5L3jdsr3S+A6A==", 412 | "cpu": [ 413 | "arm64" 414 | ], 415 | "dev": true, 416 | "optional": true, 417 | "os": [ 418 | "win32" 419 | ], 420 | "engines": { 421 | "node": ">=18" 422 | } 423 | }, 424 | "node_modules/@esbuild/win32-ia32": { 425 | "version": "0.23.1", 426 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.1.tgz", 427 | "integrity": "sha512-BcaL0Vn6QwCwre3Y717nVHZbAa4UBEigzFm6VdsVdT/MbZ38xoj1X9HPkZhbmaBGUD1W8vxAfffbDe8bA6AKnQ==", 428 | "cpu": [ 429 | "ia32" 430 | ], 431 | "dev": true, 432 | "optional": true, 433 | "os": [ 434 | "win32" 435 | ], 436 | "engines": { 437 | "node": ">=18" 438 | } 439 | }, 440 | "node_modules/@esbuild/win32-x64": { 441 | "version": "0.23.1", 442 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.1.tgz", 443 | "integrity": "sha512-BHpFFeslkWrXWyUPnbKm+xYYVYruCinGcftSBaa8zoF9hZO4BcSCFUvHVTtzpIY6YzUnYtuEhZ+C9iEXjxnasg==", 444 | "cpu": [ 445 | "x64" 446 | ], 447 | "dev": true, 448 | "optional": true, 449 | "os": [ 450 | "win32" 451 | ], 452 | "engines": { 453 | "node": ">=18" 454 | } 455 | }, 456 | "node_modules/@isaacs/cliui": { 457 | "version": "8.0.2", 458 | "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", 459 | "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", 460 | "dev": true, 461 | "dependencies": { 462 | "string-width": "^5.1.2", 463 | "string-width-cjs": "npm:string-width@^4.2.0", 464 | "strip-ansi": "^7.0.1", 465 | "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", 466 | "wrap-ansi": "^8.1.0", 467 | "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" 468 | }, 469 | "engines": { 470 | "node": ">=12" 471 | } 472 | }, 473 | "node_modules/@isaacs/cliui/node_modules/ansi-regex": { 474 | "version": "6.0.1", 475 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", 476 | "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", 477 | "dev": true, 478 | "engines": { 479 | "node": ">=12" 480 | }, 481 | "funding": { 482 | "url": "https://github.com/chalk/ansi-regex?sponsor=1" 483 | } 484 | }, 485 | "node_modules/@isaacs/cliui/node_modules/ansi-styles": { 486 | "version": "6.2.1", 487 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", 488 | "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", 489 | "dev": true, 490 | "engines": { 491 | "node": ">=12" 492 | }, 493 | "funding": { 494 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 495 | } 496 | }, 497 | "node_modules/@isaacs/cliui/node_modules/emoji-regex": { 498 | "version": "9.2.2", 499 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", 500 | "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", 501 | "dev": true 502 | }, 503 | "node_modules/@isaacs/cliui/node_modules/string-width": { 504 | "version": "5.1.2", 505 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", 506 | "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", 507 | "dev": true, 508 | "dependencies": { 509 | "eastasianwidth": "^0.2.0", 510 | "emoji-regex": "^9.2.2", 511 | "strip-ansi": "^7.0.1" 512 | }, 513 | "engines": { 514 | "node": ">=12" 515 | }, 516 | "funding": { 517 | "url": "https://github.com/sponsors/sindresorhus" 518 | } 519 | }, 520 | "node_modules/@isaacs/cliui/node_modules/strip-ansi": { 521 | "version": "7.1.0", 522 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", 523 | "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", 524 | "dev": true, 525 | "dependencies": { 526 | "ansi-regex": "^6.0.1" 527 | }, 528 | "engines": { 529 | "node": ">=12" 530 | }, 531 | "funding": { 532 | "url": "https://github.com/chalk/strip-ansi?sponsor=1" 533 | } 534 | }, 535 | "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { 536 | "version": "8.1.0", 537 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", 538 | "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", 539 | "dev": true, 540 | "dependencies": { 541 | "ansi-styles": "^6.1.0", 542 | "string-width": "^5.0.1", 543 | "strip-ansi": "^7.0.1" 544 | }, 545 | "engines": { 546 | "node": ">=12" 547 | }, 548 | "funding": { 549 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 550 | } 551 | }, 552 | "node_modules/@istanbuljs/schema": { 553 | "version": "0.1.3", 554 | "dev": true, 555 | "license": "MIT", 556 | "engines": { 557 | "node": ">=8" 558 | } 559 | }, 560 | "node_modules/@jridgewell/resolve-uri": { 561 | "version": "3.1.2", 562 | "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", 563 | "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", 564 | "dev": true, 565 | "engines": { 566 | "node": ">=6.0.0" 567 | } 568 | }, 569 | "node_modules/@jridgewell/sourcemap-codec": { 570 | "version": "1.5.0", 571 | "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", 572 | "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", 573 | "dev": true 574 | }, 575 | "node_modules/@jridgewell/trace-mapping": { 576 | "version": "0.3.25", 577 | "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", 578 | "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", 579 | "dev": true, 580 | "dependencies": { 581 | "@jridgewell/resolve-uri": "^3.1.0", 582 | "@jridgewell/sourcemap-codec": "^1.4.14" 583 | } 584 | }, 585 | "node_modules/@noble/hashes": { 586 | "version": "1.5.0", 587 | "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.5.0.tgz", 588 | "integrity": "sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==", 589 | "engines": { 590 | "node": "^14.21.3 || >=16" 591 | }, 592 | "funding": { 593 | "url": "https://paulmillr.com/funding/" 594 | } 595 | }, 596 | "node_modules/@pkgjs/parseargs": { 597 | "version": "0.11.0", 598 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 599 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 600 | "dev": true, 601 | "optional": true, 602 | "engines": { 603 | "node": ">=14" 604 | } 605 | }, 606 | "node_modules/@types/create-hash": { 607 | "version": "1.2.6", 608 | "resolved": "https://registry.npmjs.org/@types/create-hash/-/create-hash-1.2.6.tgz", 609 | "integrity": "sha512-/VIViZZAK3rAFvfGbWmcLaxwKfmU213W/XL2cr5VE0ac44jE5ky7+sHl54OJhd+bTz7sqi+Ev//8RU1F/S/ZJQ==", 610 | "dev": true, 611 | "dependencies": { 612 | "@types/node": "*" 613 | } 614 | }, 615 | "node_modules/@types/istanbul-lib-coverage": { 616 | "version": "2.0.6", 617 | "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", 618 | "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", 619 | "dev": true 620 | }, 621 | "node_modules/@types/mocha": { 622 | "version": "5.2.7", 623 | "dev": true, 624 | "license": "MIT" 625 | }, 626 | "node_modules/@types/node": { 627 | "version": "20.16.5", 628 | "resolved": "https://registry.npmjs.org/@types/node/-/node-20.16.5.tgz", 629 | "integrity": "sha512-VwYCweNo3ERajwy0IUlqqcyZ8/A7Zwa9ZP3MnENWcB11AejO+tLy3pu850goUW2FC/IJMdZUfKpX/yxL1gymCA==", 630 | "dev": true, 631 | "dependencies": { 632 | "undici-types": "~6.19.2" 633 | } 634 | }, 635 | "node_modules/@types/wif": { 636 | "version": "2.0.2", 637 | "dev": true, 638 | "license": "MIT", 639 | "dependencies": { 640 | "@types/node": "*" 641 | } 642 | }, 643 | "node_modules/ansi-colors": { 644 | "version": "4.1.3", 645 | "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", 646 | "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", 647 | "dev": true, 648 | "engines": { 649 | "node": ">=6" 650 | } 651 | }, 652 | "node_modules/ansi-regex": { 653 | "version": "5.0.1", 654 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 655 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 656 | "dev": true, 657 | "engines": { 658 | "node": ">=8" 659 | } 660 | }, 661 | "node_modules/ansi-styles": { 662 | "version": "3.2.1", 663 | "dev": true, 664 | "license": "MIT", 665 | "dependencies": { 666 | "color-convert": "^1.9.0" 667 | }, 668 | "engines": { 669 | "node": ">=4" 670 | } 671 | }, 672 | "node_modules/anymatch": { 673 | "version": "3.1.3", 674 | "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", 675 | "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", 676 | "dev": true, 677 | "dependencies": { 678 | "normalize-path": "^3.0.0", 679 | "picomatch": "^2.0.4" 680 | }, 681 | "engines": { 682 | "node": ">= 8" 683 | } 684 | }, 685 | "node_modules/argparse": { 686 | "version": "1.0.10", 687 | "dev": true, 688 | "license": "MIT", 689 | "dependencies": { 690 | "sprintf-js": "~1.0.2" 691 | } 692 | }, 693 | "node_modules/balanced-match": { 694 | "version": "1.0.2", 695 | "dev": true, 696 | "license": "MIT" 697 | }, 698 | "node_modules/base-x": { 699 | "version": "5.0.0", 700 | "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.0.tgz", 701 | "integrity": "sha512-sMW3VGSX1QWVFA6l8U62MLKz29rRfpTlYdCqLdpLo1/Yd4zZwSbnUaDfciIAowAqvq7YFnWq9hrhdg1KYgc1lQ==" 702 | }, 703 | "node_modules/binary-extensions": { 704 | "version": "2.3.0", 705 | "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", 706 | "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", 707 | "dev": true, 708 | "engines": { 709 | "node": ">=8" 710 | }, 711 | "funding": { 712 | "url": "https://github.com/sponsors/sindresorhus" 713 | } 714 | }, 715 | "node_modules/brace-expansion": { 716 | "version": "1.1.11", 717 | "dev": true, 718 | "license": "MIT", 719 | "dependencies": { 720 | "balanced-match": "^1.0.0", 721 | "concat-map": "0.0.1" 722 | } 723 | }, 724 | "node_modules/braces": { 725 | "version": "3.0.3", 726 | "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", 727 | "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", 728 | "dev": true, 729 | "dependencies": { 730 | "fill-range": "^7.1.1" 731 | }, 732 | "engines": { 733 | "node": ">=8" 734 | } 735 | }, 736 | "node_modules/browser-stdout": { 737 | "version": "1.3.1", 738 | "dev": true, 739 | "license": "ISC" 740 | }, 741 | "node_modules/bs58": { 742 | "version": "6.0.0", 743 | "resolved": "https://registry.npmjs.org/bs58/-/bs58-6.0.0.tgz", 744 | "integrity": "sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw==", 745 | "dependencies": { 746 | "base-x": "^5.0.0" 747 | } 748 | }, 749 | "node_modules/bs58check": { 750 | "version": "4.0.0", 751 | "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-4.0.0.tgz", 752 | "integrity": "sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g==", 753 | "dependencies": { 754 | "@noble/hashes": "^1.2.0", 755 | "bs58": "^6.0.0" 756 | } 757 | }, 758 | "node_modules/builtin-modules": { 759 | "version": "1.1.1", 760 | "dev": true, 761 | "license": "MIT", 762 | "engines": { 763 | "node": ">=0.10.0" 764 | } 765 | }, 766 | "node_modules/c8": { 767 | "version": "10.1.2", 768 | "resolved": "https://registry.npmjs.org/c8/-/c8-10.1.2.tgz", 769 | "integrity": "sha512-Qr6rj76eSshu5CgRYvktW0uM0CFY0yi4Fd5D0duDXO6sYinyopmftUiJVuzBQxQcwQLor7JWDVRP+dUfCmzgJw==", 770 | "dev": true, 771 | "dependencies": { 772 | "@bcoe/v8-coverage": "^0.2.3", 773 | "@istanbuljs/schema": "^0.1.3", 774 | "find-up": "^5.0.0", 775 | "foreground-child": "^3.1.1", 776 | "istanbul-lib-coverage": "^3.2.0", 777 | "istanbul-lib-report": "^3.0.1", 778 | "istanbul-reports": "^3.1.6", 779 | "test-exclude": "^7.0.1", 780 | "v8-to-istanbul": "^9.0.0", 781 | "yargs": "^17.7.2", 782 | "yargs-parser": "^21.1.1" 783 | }, 784 | "bin": { 785 | "c8": "bin/c8.js" 786 | }, 787 | "engines": { 788 | "node": ">=18" 789 | }, 790 | "peerDependencies": { 791 | "monocart-coverage-reports": "^2" 792 | }, 793 | "peerDependenciesMeta": { 794 | "monocart-coverage-reports": { 795 | "optional": true 796 | } 797 | } 798 | }, 799 | "node_modules/c8/node_modules/brace-expansion": { 800 | "version": "2.0.1", 801 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 802 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 803 | "dev": true, 804 | "dependencies": { 805 | "balanced-match": "^1.0.0" 806 | } 807 | }, 808 | "node_modules/c8/node_modules/foreground-child": { 809 | "version": "3.3.0", 810 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", 811 | "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", 812 | "dev": true, 813 | "dependencies": { 814 | "cross-spawn": "^7.0.0", 815 | "signal-exit": "^4.0.1" 816 | }, 817 | "engines": { 818 | "node": ">=14" 819 | }, 820 | "funding": { 821 | "url": "https://github.com/sponsors/isaacs" 822 | } 823 | }, 824 | "node_modules/c8/node_modules/glob": { 825 | "version": "10.4.5", 826 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", 827 | "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", 828 | "dev": true, 829 | "dependencies": { 830 | "foreground-child": "^3.1.0", 831 | "jackspeak": "^3.1.2", 832 | "minimatch": "^9.0.4", 833 | "minipass": "^7.1.2", 834 | "package-json-from-dist": "^1.0.0", 835 | "path-scurry": "^1.11.1" 836 | }, 837 | "bin": { 838 | "glob": "dist/esm/bin.mjs" 839 | }, 840 | "funding": { 841 | "url": "https://github.com/sponsors/isaacs" 842 | } 843 | }, 844 | "node_modules/c8/node_modules/minimatch": { 845 | "version": "9.0.5", 846 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", 847 | "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", 848 | "dev": true, 849 | "dependencies": { 850 | "brace-expansion": "^2.0.1" 851 | }, 852 | "engines": { 853 | "node": ">=16 || 14 >=14.17" 854 | }, 855 | "funding": { 856 | "url": "https://github.com/sponsors/isaacs" 857 | } 858 | }, 859 | "node_modules/c8/node_modules/signal-exit": { 860 | "version": "4.1.0", 861 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", 862 | "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", 863 | "dev": true, 864 | "engines": { 865 | "node": ">=14" 866 | }, 867 | "funding": { 868 | "url": "https://github.com/sponsors/isaacs" 869 | } 870 | }, 871 | "node_modules/c8/node_modules/test-exclude": { 872 | "version": "7.0.1", 873 | "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-7.0.1.tgz", 874 | "integrity": "sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==", 875 | "dev": true, 876 | "dependencies": { 877 | "@istanbuljs/schema": "^0.1.2", 878 | "glob": "^10.4.1", 879 | "minimatch": "^9.0.4" 880 | }, 881 | "engines": { 882 | "node": ">=18" 883 | } 884 | }, 885 | "node_modules/chalk": { 886 | "version": "2.4.2", 887 | "dev": true, 888 | "license": "MIT", 889 | "dependencies": { 890 | "ansi-styles": "^3.2.1", 891 | "escape-string-regexp": "^1.0.5", 892 | "supports-color": "^5.3.0" 893 | }, 894 | "engines": { 895 | "node": ">=4" 896 | } 897 | }, 898 | "node_modules/chalk/node_modules/supports-color": { 899 | "version": "5.5.0", 900 | "dev": true, 901 | "license": "MIT", 902 | "dependencies": { 903 | "has-flag": "^3.0.0" 904 | }, 905 | "engines": { 906 | "node": ">=4" 907 | } 908 | }, 909 | "node_modules/chokidar": { 910 | "version": "3.6.0", 911 | "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", 912 | "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", 913 | "dev": true, 914 | "dependencies": { 915 | "anymatch": "~3.1.2", 916 | "braces": "~3.0.2", 917 | "glob-parent": "~5.1.2", 918 | "is-binary-path": "~2.1.0", 919 | "is-glob": "~4.0.1", 920 | "normalize-path": "~3.0.0", 921 | "readdirp": "~3.6.0" 922 | }, 923 | "engines": { 924 | "node": ">= 8.10.0" 925 | }, 926 | "funding": { 927 | "url": "https://paulmillr.com/funding/" 928 | }, 929 | "optionalDependencies": { 930 | "fsevents": "~2.3.2" 931 | } 932 | }, 933 | "node_modules/cliui": { 934 | "version": "8.0.1", 935 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 936 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 937 | "dev": true, 938 | "dependencies": { 939 | "string-width": "^4.2.0", 940 | "strip-ansi": "^6.0.1", 941 | "wrap-ansi": "^7.0.0" 942 | }, 943 | "engines": { 944 | "node": ">=12" 945 | } 946 | }, 947 | "node_modules/color-convert": { 948 | "version": "1.9.3", 949 | "dev": true, 950 | "license": "MIT", 951 | "dependencies": { 952 | "color-name": "1.1.3" 953 | } 954 | }, 955 | "node_modules/color-name": { 956 | "version": "1.1.3", 957 | "dev": true, 958 | "license": "MIT" 959 | }, 960 | "node_modules/commander": { 961 | "version": "2.20.3", 962 | "dev": true, 963 | "license": "MIT" 964 | }, 965 | "node_modules/concat-map": { 966 | "version": "0.0.1", 967 | "dev": true, 968 | "license": "MIT" 969 | }, 970 | "node_modules/cross-spawn": { 971 | "version": "7.0.3", 972 | "dev": true, 973 | "license": "MIT", 974 | "dependencies": { 975 | "path-key": "^3.1.0", 976 | "shebang-command": "^2.0.0", 977 | "which": "^2.0.1" 978 | }, 979 | "engines": { 980 | "node": ">= 8" 981 | } 982 | }, 983 | "node_modules/cross-spawn/node_modules/which": { 984 | "version": "2.0.2", 985 | "dev": true, 986 | "license": "ISC", 987 | "dependencies": { 988 | "isexe": "^2.0.0" 989 | }, 990 | "bin": { 991 | "node-which": "bin/node-which" 992 | }, 993 | "engines": { 994 | "node": ">= 8" 995 | } 996 | }, 997 | "node_modules/debug": { 998 | "version": "4.3.7", 999 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", 1000 | "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", 1001 | "dev": true, 1002 | "dependencies": { 1003 | "ms": "^2.1.3" 1004 | }, 1005 | "engines": { 1006 | "node": ">=6.0" 1007 | }, 1008 | "peerDependenciesMeta": { 1009 | "supports-color": { 1010 | "optional": true 1011 | } 1012 | } 1013 | }, 1014 | "node_modules/diff": { 1015 | "version": "5.2.0", 1016 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", 1017 | "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", 1018 | "dev": true, 1019 | "engines": { 1020 | "node": ">=0.3.1" 1021 | } 1022 | }, 1023 | "node_modules/eastasianwidth": { 1024 | "version": "0.2.0", 1025 | "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", 1026 | "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", 1027 | "dev": true 1028 | }, 1029 | "node_modules/emoji-regex": { 1030 | "version": "8.0.0", 1031 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1032 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1033 | "dev": true 1034 | }, 1035 | "node_modules/esbuild": { 1036 | "version": "0.23.1", 1037 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.1.tgz", 1038 | "integrity": "sha512-VVNz/9Sa0bs5SELtn3f7qhJCDPCF5oMEl5cO9/SSinpE9hbPVvxbd572HH5AKiP7WD8INO53GgfDDhRjkylHEg==", 1039 | "dev": true, 1040 | "hasInstallScript": true, 1041 | "bin": { 1042 | "esbuild": "bin/esbuild" 1043 | }, 1044 | "engines": { 1045 | "node": ">=18" 1046 | }, 1047 | "optionalDependencies": { 1048 | "@esbuild/aix-ppc64": "0.23.1", 1049 | "@esbuild/android-arm": "0.23.1", 1050 | "@esbuild/android-arm64": "0.23.1", 1051 | "@esbuild/android-x64": "0.23.1", 1052 | "@esbuild/darwin-arm64": "0.23.1", 1053 | "@esbuild/darwin-x64": "0.23.1", 1054 | "@esbuild/freebsd-arm64": "0.23.1", 1055 | "@esbuild/freebsd-x64": "0.23.1", 1056 | "@esbuild/linux-arm": "0.23.1", 1057 | "@esbuild/linux-arm64": "0.23.1", 1058 | "@esbuild/linux-ia32": "0.23.1", 1059 | "@esbuild/linux-loong64": "0.23.1", 1060 | "@esbuild/linux-mips64el": "0.23.1", 1061 | "@esbuild/linux-ppc64": "0.23.1", 1062 | "@esbuild/linux-riscv64": "0.23.1", 1063 | "@esbuild/linux-s390x": "0.23.1", 1064 | "@esbuild/linux-x64": "0.23.1", 1065 | "@esbuild/netbsd-x64": "0.23.1", 1066 | "@esbuild/openbsd-arm64": "0.23.1", 1067 | "@esbuild/openbsd-x64": "0.23.1", 1068 | "@esbuild/sunos-x64": "0.23.1", 1069 | "@esbuild/win32-arm64": "0.23.1", 1070 | "@esbuild/win32-ia32": "0.23.1", 1071 | "@esbuild/win32-x64": "0.23.1" 1072 | } 1073 | }, 1074 | "node_modules/escalade": { 1075 | "version": "3.1.1", 1076 | "dev": true, 1077 | "license": "MIT", 1078 | "engines": { 1079 | "node": ">=6" 1080 | } 1081 | }, 1082 | "node_modules/escape-string-regexp": { 1083 | "version": "1.0.5", 1084 | "dev": true, 1085 | "license": "MIT", 1086 | "engines": { 1087 | "node": ">=0.8.0" 1088 | } 1089 | }, 1090 | "node_modules/esprima": { 1091 | "version": "4.0.1", 1092 | "dev": true, 1093 | "license": "BSD-2-Clause", 1094 | "bin": { 1095 | "esparse": "bin/esparse.js", 1096 | "esvalidate": "bin/esvalidate.js" 1097 | }, 1098 | "engines": { 1099 | "node": ">=4" 1100 | } 1101 | }, 1102 | "node_modules/fill-range": { 1103 | "version": "7.1.1", 1104 | "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", 1105 | "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", 1106 | "dev": true, 1107 | "dependencies": { 1108 | "to-regex-range": "^5.0.1" 1109 | }, 1110 | "engines": { 1111 | "node": ">=8" 1112 | } 1113 | }, 1114 | "node_modules/find-up": { 1115 | "version": "5.0.0", 1116 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", 1117 | "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", 1118 | "dev": true, 1119 | "dependencies": { 1120 | "locate-path": "^6.0.0", 1121 | "path-exists": "^4.0.0" 1122 | }, 1123 | "engines": { 1124 | "node": ">=10" 1125 | }, 1126 | "funding": { 1127 | "url": "https://github.com/sponsors/sindresorhus" 1128 | } 1129 | }, 1130 | "node_modules/flat": { 1131 | "version": "5.0.2", 1132 | "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", 1133 | "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", 1134 | "dev": true, 1135 | "bin": { 1136 | "flat": "cli.js" 1137 | } 1138 | }, 1139 | "node_modules/fs.realpath": { 1140 | "version": "1.0.0", 1141 | "dev": true, 1142 | "license": "ISC" 1143 | }, 1144 | "node_modules/fsevents": { 1145 | "version": "2.3.3", 1146 | "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", 1147 | "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", 1148 | "dev": true, 1149 | "hasInstallScript": true, 1150 | "optional": true, 1151 | "os": [ 1152 | "darwin" 1153 | ], 1154 | "engines": { 1155 | "node": "^8.16.0 || ^10.6.0 || >=11.0.0" 1156 | } 1157 | }, 1158 | "node_modules/function-bind": { 1159 | "version": "1.1.1", 1160 | "dev": true, 1161 | "license": "MIT" 1162 | }, 1163 | "node_modules/get-caller-file": { 1164 | "version": "2.0.5", 1165 | "dev": true, 1166 | "license": "ISC", 1167 | "engines": { 1168 | "node": "6.* || 8.* || >= 10.*" 1169 | } 1170 | }, 1171 | "node_modules/get-tsconfig": { 1172 | "version": "4.8.0", 1173 | "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.8.0.tgz", 1174 | "integrity": "sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==", 1175 | "dev": true, 1176 | "dependencies": { 1177 | "resolve-pkg-maps": "^1.0.0" 1178 | }, 1179 | "funding": { 1180 | "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" 1181 | } 1182 | }, 1183 | "node_modules/glob": { 1184 | "version": "7.1.3", 1185 | "dev": true, 1186 | "license": "ISC", 1187 | "dependencies": { 1188 | "fs.realpath": "^1.0.0", 1189 | "inflight": "^1.0.4", 1190 | "inherits": "2", 1191 | "minimatch": "^3.0.4", 1192 | "once": "^1.3.0", 1193 | "path-is-absolute": "^1.0.0" 1194 | }, 1195 | "engines": { 1196 | "node": "*" 1197 | } 1198 | }, 1199 | "node_modules/glob-parent": { 1200 | "version": "5.1.2", 1201 | "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", 1202 | "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", 1203 | "dev": true, 1204 | "dependencies": { 1205 | "is-glob": "^4.0.1" 1206 | }, 1207 | "engines": { 1208 | "node": ">= 6" 1209 | } 1210 | }, 1211 | "node_modules/has": { 1212 | "version": "1.0.3", 1213 | "dev": true, 1214 | "license": "MIT", 1215 | "dependencies": { 1216 | "function-bind": "^1.1.1" 1217 | }, 1218 | "engines": { 1219 | "node": ">= 0.4.0" 1220 | } 1221 | }, 1222 | "node_modules/has-flag": { 1223 | "version": "3.0.0", 1224 | "dev": true, 1225 | "license": "MIT", 1226 | "engines": { 1227 | "node": ">=4" 1228 | } 1229 | }, 1230 | "node_modules/he": { 1231 | "version": "1.2.0", 1232 | "dev": true, 1233 | "license": "MIT", 1234 | "bin": { 1235 | "he": "bin/he" 1236 | } 1237 | }, 1238 | "node_modules/html-escaper": { 1239 | "version": "2.0.2", 1240 | "dev": true, 1241 | "license": "MIT" 1242 | }, 1243 | "node_modules/inflight": { 1244 | "version": "1.0.6", 1245 | "dev": true, 1246 | "license": "ISC", 1247 | "dependencies": { 1248 | "once": "^1.3.0", 1249 | "wrappy": "1" 1250 | } 1251 | }, 1252 | "node_modules/inherits": { 1253 | "version": "2.0.4", 1254 | "dev": true, 1255 | "license": "ISC" 1256 | }, 1257 | "node_modules/is-binary-path": { 1258 | "version": "2.1.0", 1259 | "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", 1260 | "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", 1261 | "dev": true, 1262 | "dependencies": { 1263 | "binary-extensions": "^2.0.0" 1264 | }, 1265 | "engines": { 1266 | "node": ">=8" 1267 | } 1268 | }, 1269 | "node_modules/is-core-module": { 1270 | "version": "2.8.0", 1271 | "dev": true, 1272 | "license": "MIT", 1273 | "dependencies": { 1274 | "has": "^1.0.3" 1275 | }, 1276 | "funding": { 1277 | "url": "https://github.com/sponsors/ljharb" 1278 | } 1279 | }, 1280 | "node_modules/is-extglob": { 1281 | "version": "2.1.1", 1282 | "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", 1283 | "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", 1284 | "dev": true, 1285 | "engines": { 1286 | "node": ">=0.10.0" 1287 | } 1288 | }, 1289 | "node_modules/is-fullwidth-code-point": { 1290 | "version": "3.0.0", 1291 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1292 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 1293 | "dev": true, 1294 | "engines": { 1295 | "node": ">=8" 1296 | } 1297 | }, 1298 | "node_modules/is-glob": { 1299 | "version": "4.0.3", 1300 | "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", 1301 | "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", 1302 | "dev": true, 1303 | "dependencies": { 1304 | "is-extglob": "^2.1.1" 1305 | }, 1306 | "engines": { 1307 | "node": ">=0.10.0" 1308 | } 1309 | }, 1310 | "node_modules/is-number": { 1311 | "version": "7.0.0", 1312 | "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", 1313 | "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", 1314 | "dev": true, 1315 | "engines": { 1316 | "node": ">=0.12.0" 1317 | } 1318 | }, 1319 | "node_modules/is-plain-obj": { 1320 | "version": "2.1.0", 1321 | "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", 1322 | "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", 1323 | "dev": true, 1324 | "engines": { 1325 | "node": ">=8" 1326 | } 1327 | }, 1328 | "node_modules/is-unicode-supported": { 1329 | "version": "0.1.0", 1330 | "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", 1331 | "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", 1332 | "dev": true, 1333 | "engines": { 1334 | "node": ">=10" 1335 | }, 1336 | "funding": { 1337 | "url": "https://github.com/sponsors/sindresorhus" 1338 | } 1339 | }, 1340 | "node_modules/isexe": { 1341 | "version": "2.0.0", 1342 | "dev": true, 1343 | "license": "ISC" 1344 | }, 1345 | "node_modules/istanbul-lib-coverage": { 1346 | "version": "3.2.0", 1347 | "dev": true, 1348 | "license": "BSD-3-Clause", 1349 | "engines": { 1350 | "node": ">=8" 1351 | } 1352 | }, 1353 | "node_modules/istanbul-lib-report": { 1354 | "version": "3.0.1", 1355 | "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", 1356 | "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", 1357 | "dev": true, 1358 | "dependencies": { 1359 | "istanbul-lib-coverage": "^3.0.0", 1360 | "make-dir": "^4.0.0", 1361 | "supports-color": "^7.1.0" 1362 | }, 1363 | "engines": { 1364 | "node": ">=10" 1365 | } 1366 | }, 1367 | "node_modules/istanbul-lib-report/node_modules/has-flag": { 1368 | "version": "4.0.0", 1369 | "dev": true, 1370 | "license": "MIT", 1371 | "engines": { 1372 | "node": ">=8" 1373 | } 1374 | }, 1375 | "node_modules/istanbul-lib-report/node_modules/make-dir": { 1376 | "version": "4.0.0", 1377 | "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", 1378 | "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", 1379 | "dev": true, 1380 | "dependencies": { 1381 | "semver": "^7.5.3" 1382 | }, 1383 | "engines": { 1384 | "node": ">=10" 1385 | }, 1386 | "funding": { 1387 | "url": "https://github.com/sponsors/sindresorhus" 1388 | } 1389 | }, 1390 | "node_modules/istanbul-lib-report/node_modules/semver": { 1391 | "version": "7.6.3", 1392 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", 1393 | "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", 1394 | "dev": true, 1395 | "bin": { 1396 | "semver": "bin/semver.js" 1397 | }, 1398 | "engines": { 1399 | "node": ">=10" 1400 | } 1401 | }, 1402 | "node_modules/istanbul-lib-report/node_modules/supports-color": { 1403 | "version": "7.2.0", 1404 | "dev": true, 1405 | "license": "MIT", 1406 | "dependencies": { 1407 | "has-flag": "^4.0.0" 1408 | }, 1409 | "engines": { 1410 | "node": ">=8" 1411 | } 1412 | }, 1413 | "node_modules/istanbul-reports": { 1414 | "version": "3.1.7", 1415 | "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", 1416 | "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", 1417 | "dev": true, 1418 | "dependencies": { 1419 | "html-escaper": "^2.0.0", 1420 | "istanbul-lib-report": "^3.0.0" 1421 | }, 1422 | "engines": { 1423 | "node": ">=8" 1424 | } 1425 | }, 1426 | "node_modules/jackspeak": { 1427 | "version": "3.4.3", 1428 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", 1429 | "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", 1430 | "dev": true, 1431 | "dependencies": { 1432 | "@isaacs/cliui": "^8.0.2" 1433 | }, 1434 | "funding": { 1435 | "url": "https://github.com/sponsors/isaacs" 1436 | }, 1437 | "optionalDependencies": { 1438 | "@pkgjs/parseargs": "^0.11.0" 1439 | } 1440 | }, 1441 | "node_modules/js-tokens": { 1442 | "version": "4.0.0", 1443 | "dev": true, 1444 | "license": "MIT" 1445 | }, 1446 | "node_modules/js-yaml": { 1447 | "version": "3.13.1", 1448 | "dev": true, 1449 | "license": "MIT", 1450 | "dependencies": { 1451 | "argparse": "^1.0.7", 1452 | "esprima": "^4.0.0" 1453 | }, 1454 | "bin": { 1455 | "js-yaml": "bin/js-yaml.js" 1456 | } 1457 | }, 1458 | "node_modules/locate-path": { 1459 | "version": "6.0.0", 1460 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", 1461 | "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", 1462 | "dev": true, 1463 | "dependencies": { 1464 | "p-locate": "^5.0.0" 1465 | }, 1466 | "engines": { 1467 | "node": ">=10" 1468 | }, 1469 | "funding": { 1470 | "url": "https://github.com/sponsors/sindresorhus" 1471 | } 1472 | }, 1473 | "node_modules/log-symbols": { 1474 | "version": "4.1.0", 1475 | "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", 1476 | "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", 1477 | "dev": true, 1478 | "dependencies": { 1479 | "chalk": "^4.1.0", 1480 | "is-unicode-supported": "^0.1.0" 1481 | }, 1482 | "engines": { 1483 | "node": ">=10" 1484 | }, 1485 | "funding": { 1486 | "url": "https://github.com/sponsors/sindresorhus" 1487 | } 1488 | }, 1489 | "node_modules/log-symbols/node_modules/ansi-styles": { 1490 | "version": "4.3.0", 1491 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1492 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1493 | "dev": true, 1494 | "dependencies": { 1495 | "color-convert": "^2.0.1" 1496 | }, 1497 | "engines": { 1498 | "node": ">=8" 1499 | }, 1500 | "funding": { 1501 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 1502 | } 1503 | }, 1504 | "node_modules/log-symbols/node_modules/chalk": { 1505 | "version": "4.1.2", 1506 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1507 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1508 | "dev": true, 1509 | "dependencies": { 1510 | "ansi-styles": "^4.1.0", 1511 | "supports-color": "^7.1.0" 1512 | }, 1513 | "engines": { 1514 | "node": ">=10" 1515 | }, 1516 | "funding": { 1517 | "url": "https://github.com/chalk/chalk?sponsor=1" 1518 | } 1519 | }, 1520 | "node_modules/log-symbols/node_modules/color-convert": { 1521 | "version": "2.0.1", 1522 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1523 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1524 | "dev": true, 1525 | "dependencies": { 1526 | "color-name": "~1.1.4" 1527 | }, 1528 | "engines": { 1529 | "node": ">=7.0.0" 1530 | } 1531 | }, 1532 | "node_modules/log-symbols/node_modules/color-name": { 1533 | "version": "1.1.4", 1534 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1535 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1536 | "dev": true 1537 | }, 1538 | "node_modules/log-symbols/node_modules/has-flag": { 1539 | "version": "4.0.0", 1540 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1541 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1542 | "dev": true, 1543 | "engines": { 1544 | "node": ">=8" 1545 | } 1546 | }, 1547 | "node_modules/log-symbols/node_modules/supports-color": { 1548 | "version": "7.2.0", 1549 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1550 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1551 | "dev": true, 1552 | "dependencies": { 1553 | "has-flag": "^4.0.0" 1554 | }, 1555 | "engines": { 1556 | "node": ">=8" 1557 | } 1558 | }, 1559 | "node_modules/lru-cache": { 1560 | "version": "10.4.3", 1561 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", 1562 | "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", 1563 | "dev": true 1564 | }, 1565 | "node_modules/minimatch": { 1566 | "version": "3.0.4", 1567 | "dev": true, 1568 | "license": "ISC", 1569 | "dependencies": { 1570 | "brace-expansion": "^1.1.7" 1571 | }, 1572 | "engines": { 1573 | "node": "*" 1574 | } 1575 | }, 1576 | "node_modules/minimist": { 1577 | "version": "1.2.5", 1578 | "dev": true, 1579 | "license": "MIT" 1580 | }, 1581 | "node_modules/minipass": { 1582 | "version": "7.1.2", 1583 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", 1584 | "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", 1585 | "dev": true, 1586 | "engines": { 1587 | "node": ">=16 || 14 >=14.17" 1588 | } 1589 | }, 1590 | "node_modules/mkdirp": { 1591 | "version": "0.5.5", 1592 | "dev": true, 1593 | "license": "MIT", 1594 | "dependencies": { 1595 | "minimist": "^1.2.5" 1596 | }, 1597 | "bin": { 1598 | "mkdirp": "bin/cmd.js" 1599 | } 1600 | }, 1601 | "node_modules/mocha": { 1602 | "version": "10.7.3", 1603 | "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.7.3.tgz", 1604 | "integrity": "sha512-uQWxAu44wwiACGqjbPYmjo7Lg8sFrS3dQe7PP2FQI+woptP4vZXSMcfMyFL/e1yFEeEpV4RtyTpZROOKmxis+A==", 1605 | "dev": true, 1606 | "dependencies": { 1607 | "ansi-colors": "^4.1.3", 1608 | "browser-stdout": "^1.3.1", 1609 | "chokidar": "^3.5.3", 1610 | "debug": "^4.3.5", 1611 | "diff": "^5.2.0", 1612 | "escape-string-regexp": "^4.0.0", 1613 | "find-up": "^5.0.0", 1614 | "glob": "^8.1.0", 1615 | "he": "^1.2.0", 1616 | "js-yaml": "^4.1.0", 1617 | "log-symbols": "^4.1.0", 1618 | "minimatch": "^5.1.6", 1619 | "ms": "^2.1.3", 1620 | "serialize-javascript": "^6.0.2", 1621 | "strip-json-comments": "^3.1.1", 1622 | "supports-color": "^8.1.1", 1623 | "workerpool": "^6.5.1", 1624 | "yargs": "^16.2.0", 1625 | "yargs-parser": "^20.2.9", 1626 | "yargs-unparser": "^2.0.0" 1627 | }, 1628 | "bin": { 1629 | "_mocha": "bin/_mocha", 1630 | "mocha": "bin/mocha.js" 1631 | }, 1632 | "engines": { 1633 | "node": ">= 14.0.0" 1634 | } 1635 | }, 1636 | "node_modules/mocha/node_modules/argparse": { 1637 | "version": "2.0.1", 1638 | "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", 1639 | "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", 1640 | "dev": true 1641 | }, 1642 | "node_modules/mocha/node_modules/brace-expansion": { 1643 | "version": "2.0.1", 1644 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 1645 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 1646 | "dev": true, 1647 | "dependencies": { 1648 | "balanced-match": "^1.0.0" 1649 | } 1650 | }, 1651 | "node_modules/mocha/node_modules/cliui": { 1652 | "version": "7.0.4", 1653 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", 1654 | "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", 1655 | "dev": true, 1656 | "dependencies": { 1657 | "string-width": "^4.2.0", 1658 | "strip-ansi": "^6.0.0", 1659 | "wrap-ansi": "^7.0.0" 1660 | } 1661 | }, 1662 | "node_modules/mocha/node_modules/escape-string-regexp": { 1663 | "version": "4.0.0", 1664 | "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", 1665 | "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", 1666 | "dev": true, 1667 | "engines": { 1668 | "node": ">=10" 1669 | }, 1670 | "funding": { 1671 | "url": "https://github.com/sponsors/sindresorhus" 1672 | } 1673 | }, 1674 | "node_modules/mocha/node_modules/glob": { 1675 | "version": "8.1.0", 1676 | "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", 1677 | "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", 1678 | "deprecated": "Glob versions prior to v9 are no longer supported", 1679 | "dev": true, 1680 | "dependencies": { 1681 | "fs.realpath": "^1.0.0", 1682 | "inflight": "^1.0.4", 1683 | "inherits": "2", 1684 | "minimatch": "^5.0.1", 1685 | "once": "^1.3.0" 1686 | }, 1687 | "engines": { 1688 | "node": ">=12" 1689 | }, 1690 | "funding": { 1691 | "url": "https://github.com/sponsors/isaacs" 1692 | } 1693 | }, 1694 | "node_modules/mocha/node_modules/js-yaml": { 1695 | "version": "4.1.0", 1696 | "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", 1697 | "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", 1698 | "dev": true, 1699 | "dependencies": { 1700 | "argparse": "^2.0.1" 1701 | }, 1702 | "bin": { 1703 | "js-yaml": "bin/js-yaml.js" 1704 | } 1705 | }, 1706 | "node_modules/mocha/node_modules/minimatch": { 1707 | "version": "5.1.6", 1708 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", 1709 | "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", 1710 | "dev": true, 1711 | "dependencies": { 1712 | "brace-expansion": "^2.0.1" 1713 | }, 1714 | "engines": { 1715 | "node": ">=10" 1716 | } 1717 | }, 1718 | "node_modules/mocha/node_modules/y18n": { 1719 | "version": "5.0.8", 1720 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 1721 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 1722 | "dev": true, 1723 | "engines": { 1724 | "node": ">=10" 1725 | } 1726 | }, 1727 | "node_modules/mocha/node_modules/yargs": { 1728 | "version": "16.2.0", 1729 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", 1730 | "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", 1731 | "dev": true, 1732 | "dependencies": { 1733 | "cliui": "^7.0.2", 1734 | "escalade": "^3.1.1", 1735 | "get-caller-file": "^2.0.5", 1736 | "require-directory": "^2.1.1", 1737 | "string-width": "^4.2.0", 1738 | "y18n": "^5.0.5", 1739 | "yargs-parser": "^20.2.2" 1740 | }, 1741 | "engines": { 1742 | "node": ">=10" 1743 | } 1744 | }, 1745 | "node_modules/mocha/node_modules/yargs-parser": { 1746 | "version": "20.2.9", 1747 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", 1748 | "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", 1749 | "dev": true, 1750 | "engines": { 1751 | "node": ">=10" 1752 | } 1753 | }, 1754 | "node_modules/ms": { 1755 | "version": "2.1.3", 1756 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", 1757 | "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", 1758 | "dev": true 1759 | }, 1760 | "node_modules/normalize-path": { 1761 | "version": "3.0.0", 1762 | "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", 1763 | "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", 1764 | "dev": true, 1765 | "engines": { 1766 | "node": ">=0.10.0" 1767 | } 1768 | }, 1769 | "node_modules/once": { 1770 | "version": "1.4.0", 1771 | "dev": true, 1772 | "license": "ISC", 1773 | "dependencies": { 1774 | "wrappy": "1" 1775 | } 1776 | }, 1777 | "node_modules/p-locate": { 1778 | "version": "5.0.0", 1779 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", 1780 | "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", 1781 | "dev": true, 1782 | "dependencies": { 1783 | "p-limit": "^3.0.2" 1784 | }, 1785 | "engines": { 1786 | "node": ">=10" 1787 | }, 1788 | "funding": { 1789 | "url": "https://github.com/sponsors/sindresorhus" 1790 | } 1791 | }, 1792 | "node_modules/p-locate/node_modules/p-limit": { 1793 | "version": "3.1.0", 1794 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", 1795 | "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", 1796 | "dev": true, 1797 | "dependencies": { 1798 | "yocto-queue": "^0.1.0" 1799 | }, 1800 | "engines": { 1801 | "node": ">=10" 1802 | }, 1803 | "funding": { 1804 | "url": "https://github.com/sponsors/sindresorhus" 1805 | } 1806 | }, 1807 | "node_modules/package-json-from-dist": { 1808 | "version": "1.0.0", 1809 | "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz", 1810 | "integrity": "sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw==", 1811 | "dev": true 1812 | }, 1813 | "node_modules/path-exists": { 1814 | "version": "4.0.0", 1815 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1816 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 1817 | "dev": true, 1818 | "engines": { 1819 | "node": ">=8" 1820 | } 1821 | }, 1822 | "node_modules/path-is-absolute": { 1823 | "version": "1.0.1", 1824 | "dev": true, 1825 | "license": "MIT", 1826 | "engines": { 1827 | "node": ">=0.10.0" 1828 | } 1829 | }, 1830 | "node_modules/path-key": { 1831 | "version": "3.1.1", 1832 | "dev": true, 1833 | "license": "MIT", 1834 | "engines": { 1835 | "node": ">=8" 1836 | } 1837 | }, 1838 | "node_modules/path-parse": { 1839 | "version": "1.0.7", 1840 | "dev": true, 1841 | "license": "MIT" 1842 | }, 1843 | "node_modules/path-scurry": { 1844 | "version": "1.11.1", 1845 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", 1846 | "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", 1847 | "dev": true, 1848 | "dependencies": { 1849 | "lru-cache": "^10.2.0", 1850 | "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" 1851 | }, 1852 | "engines": { 1853 | "node": ">=16 || 14 >=14.18" 1854 | }, 1855 | "funding": { 1856 | "url": "https://github.com/sponsors/isaacs" 1857 | } 1858 | }, 1859 | "node_modules/picomatch": { 1860 | "version": "2.3.1", 1861 | "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", 1862 | "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", 1863 | "dev": true, 1864 | "engines": { 1865 | "node": ">=8.6" 1866 | }, 1867 | "funding": { 1868 | "url": "https://github.com/sponsors/jonschlinkert" 1869 | } 1870 | }, 1871 | "node_modules/prettier": { 1872 | "version": "3.3.3", 1873 | "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", 1874 | "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", 1875 | "dev": true, 1876 | "bin": { 1877 | "prettier": "bin/prettier.cjs" 1878 | }, 1879 | "engines": { 1880 | "node": ">=14" 1881 | }, 1882 | "funding": { 1883 | "url": "https://github.com/prettier/prettier?sponsor=1" 1884 | } 1885 | }, 1886 | "node_modules/randombytes": { 1887 | "version": "2.1.0", 1888 | "dev": true, 1889 | "license": "MIT", 1890 | "dependencies": { 1891 | "safe-buffer": "^5.1.0" 1892 | } 1893 | }, 1894 | "node_modules/readdirp": { 1895 | "version": "3.6.0", 1896 | "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", 1897 | "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", 1898 | "dev": true, 1899 | "dependencies": { 1900 | "picomatch": "^2.2.1" 1901 | }, 1902 | "engines": { 1903 | "node": ">=8.10.0" 1904 | } 1905 | }, 1906 | "node_modules/require-directory": { 1907 | "version": "2.1.1", 1908 | "dev": true, 1909 | "license": "MIT", 1910 | "engines": { 1911 | "node": ">=0.10.0" 1912 | } 1913 | }, 1914 | "node_modules/resolve": { 1915 | "version": "1.20.0", 1916 | "dev": true, 1917 | "license": "MIT", 1918 | "dependencies": { 1919 | "is-core-module": "^2.2.0", 1920 | "path-parse": "^1.0.6" 1921 | }, 1922 | "funding": { 1923 | "url": "https://github.com/sponsors/ljharb" 1924 | } 1925 | }, 1926 | "node_modules/resolve-pkg-maps": { 1927 | "version": "1.0.0", 1928 | "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", 1929 | "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", 1930 | "dev": true, 1931 | "funding": { 1932 | "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" 1933 | } 1934 | }, 1935 | "node_modules/rimraf": { 1936 | "version": "2.7.1", 1937 | "dev": true, 1938 | "license": "ISC", 1939 | "dependencies": { 1940 | "glob": "^7.1.3" 1941 | }, 1942 | "bin": { 1943 | "rimraf": "bin.js" 1944 | } 1945 | }, 1946 | "node_modules/safe-buffer": { 1947 | "version": "5.2.1", 1948 | "dev": true, 1949 | "funding": [ 1950 | { 1951 | "type": "github", 1952 | "url": "https://github.com/sponsors/feross" 1953 | }, 1954 | { 1955 | "type": "patreon", 1956 | "url": "https://www.patreon.com/feross" 1957 | }, 1958 | { 1959 | "type": "consulting", 1960 | "url": "https://feross.org/support" 1961 | } 1962 | ], 1963 | "license": "MIT" 1964 | }, 1965 | "node_modules/semver": { 1966 | "version": "5.7.1", 1967 | "dev": true, 1968 | "license": "ISC", 1969 | "bin": { 1970 | "semver": "bin/semver" 1971 | } 1972 | }, 1973 | "node_modules/serialize-javascript": { 1974 | "version": "6.0.2", 1975 | "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", 1976 | "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", 1977 | "dev": true, 1978 | "dependencies": { 1979 | "randombytes": "^2.1.0" 1980 | } 1981 | }, 1982 | "node_modules/shebang-command": { 1983 | "version": "2.0.0", 1984 | "dev": true, 1985 | "license": "MIT", 1986 | "dependencies": { 1987 | "shebang-regex": "^3.0.0" 1988 | }, 1989 | "engines": { 1990 | "node": ">=8" 1991 | } 1992 | }, 1993 | "node_modules/shebang-regex": { 1994 | "version": "3.0.0", 1995 | "dev": true, 1996 | "license": "MIT", 1997 | "engines": { 1998 | "node": ">=8" 1999 | } 2000 | }, 2001 | "node_modules/sprintf-js": { 2002 | "version": "1.0.3", 2003 | "dev": true, 2004 | "license": "BSD-3-Clause" 2005 | }, 2006 | "node_modules/string-width": { 2007 | "version": "4.2.3", 2008 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2009 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2010 | "dev": true, 2011 | "dependencies": { 2012 | "emoji-regex": "^8.0.0", 2013 | "is-fullwidth-code-point": "^3.0.0", 2014 | "strip-ansi": "^6.0.1" 2015 | }, 2016 | "engines": { 2017 | "node": ">=8" 2018 | } 2019 | }, 2020 | "node_modules/string-width-cjs": { 2021 | "name": "string-width", 2022 | "version": "4.2.3", 2023 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2024 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2025 | "dev": true, 2026 | "dependencies": { 2027 | "emoji-regex": "^8.0.0", 2028 | "is-fullwidth-code-point": "^3.0.0", 2029 | "strip-ansi": "^6.0.1" 2030 | }, 2031 | "engines": { 2032 | "node": ">=8" 2033 | } 2034 | }, 2035 | "node_modules/strip-ansi": { 2036 | "version": "6.0.1", 2037 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2038 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2039 | "dev": true, 2040 | "dependencies": { 2041 | "ansi-regex": "^5.0.1" 2042 | }, 2043 | "engines": { 2044 | "node": ">=8" 2045 | } 2046 | }, 2047 | "node_modules/strip-ansi-cjs": { 2048 | "name": "strip-ansi", 2049 | "version": "6.0.1", 2050 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2051 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2052 | "dev": true, 2053 | "dependencies": { 2054 | "ansi-regex": "^5.0.1" 2055 | }, 2056 | "engines": { 2057 | "node": ">=8" 2058 | } 2059 | }, 2060 | "node_modules/strip-json-comments": { 2061 | "version": "3.1.1", 2062 | "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", 2063 | "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", 2064 | "dev": true, 2065 | "engines": { 2066 | "node": ">=8" 2067 | }, 2068 | "funding": { 2069 | "url": "https://github.com/sponsors/sindresorhus" 2070 | } 2071 | }, 2072 | "node_modules/supports-color": { 2073 | "version": "8.1.1", 2074 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", 2075 | "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", 2076 | "dev": true, 2077 | "dependencies": { 2078 | "has-flag": "^4.0.0" 2079 | }, 2080 | "engines": { 2081 | "node": ">=10" 2082 | }, 2083 | "funding": { 2084 | "url": "https://github.com/chalk/supports-color?sponsor=1" 2085 | } 2086 | }, 2087 | "node_modules/supports-color/node_modules/has-flag": { 2088 | "version": "4.0.0", 2089 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 2090 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 2091 | "dev": true, 2092 | "engines": { 2093 | "node": ">=8" 2094 | } 2095 | }, 2096 | "node_modules/tiny-secp256k1": { 2097 | "version": "2.2.3", 2098 | "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.3.tgz", 2099 | "integrity": "sha512-SGcL07SxcPN2nGKHTCvRMkQLYPSoeFcvArUSCYtjVARiFAWU44cCIqYS0mYAU6nY7XfvwURuTIGo2Omt3ZQr0Q==", 2100 | "dev": true, 2101 | "dependencies": { 2102 | "uint8array-tools": "0.0.7" 2103 | }, 2104 | "engines": { 2105 | "node": ">=14.0.0" 2106 | } 2107 | }, 2108 | "node_modules/tiny-secp256k1/node_modules/uint8array-tools": { 2109 | "version": "0.0.7", 2110 | "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.7.tgz", 2111 | "integrity": "sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==", 2112 | "dev": true, 2113 | "engines": { 2114 | "node": ">=14.0.0" 2115 | } 2116 | }, 2117 | "node_modules/to-regex-range": { 2118 | "version": "5.0.1", 2119 | "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", 2120 | "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", 2121 | "dev": true, 2122 | "dependencies": { 2123 | "is-number": "^7.0.0" 2124 | }, 2125 | "engines": { 2126 | "node": ">=8.0" 2127 | } 2128 | }, 2129 | "node_modules/tslib": { 2130 | "version": "1.14.1", 2131 | "dev": true, 2132 | "license": "0BSD" 2133 | }, 2134 | "node_modules/tslint": { 2135 | "version": "6.1.3", 2136 | "dev": true, 2137 | "license": "Apache-2.0", 2138 | "dependencies": { 2139 | "@babel/code-frame": "^7.0.0", 2140 | "builtin-modules": "^1.1.1", 2141 | "chalk": "^2.3.0", 2142 | "commander": "^2.12.1", 2143 | "diff": "^4.0.1", 2144 | "glob": "^7.1.1", 2145 | "js-yaml": "^3.13.1", 2146 | "minimatch": "^3.0.4", 2147 | "mkdirp": "^0.5.3", 2148 | "resolve": "^1.3.2", 2149 | "semver": "^5.3.0", 2150 | "tslib": "^1.13.0", 2151 | "tsutils": "^2.29.0" 2152 | }, 2153 | "bin": { 2154 | "tslint": "bin/tslint" 2155 | }, 2156 | "engines": { 2157 | "node": ">=4.8.0" 2158 | }, 2159 | "peerDependencies": { 2160 | "typescript": ">=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >=3.0.0-dev || >= 3.1.0-dev || >= 3.2.0-dev || >= 4.0.0-dev" 2161 | } 2162 | }, 2163 | "node_modules/tslint/node_modules/diff": { 2164 | "version": "4.0.2", 2165 | "dev": true, 2166 | "license": "BSD-3-Clause", 2167 | "engines": { 2168 | "node": ">=0.3.1" 2169 | } 2170 | }, 2171 | "node_modules/tsutils": { 2172 | "version": "2.29.0", 2173 | "dev": true, 2174 | "license": "MIT", 2175 | "dependencies": { 2176 | "tslib": "^1.8.1" 2177 | }, 2178 | "peerDependencies": { 2179 | "typescript": ">=2.1.0 || >=2.1.0-dev || >=2.2.0-dev || >=2.3.0-dev || >=2.4.0-dev || >=2.5.0-dev || >=2.6.0-dev || >=2.7.0-dev || >=2.8.0-dev || >=2.9.0-dev || >= 3.0.0-dev || >= 3.1.0-dev" 2180 | } 2181 | }, 2182 | "node_modules/tsx": { 2183 | "version": "4.19.0", 2184 | "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.19.0.tgz", 2185 | "integrity": "sha512-bV30kM7bsLZKZIOCHeMNVMJ32/LuJzLVajkQI/qf92J2Qr08ueLQvW00PUZGiuLPP760UINwupgUj8qrSCPUKg==", 2186 | "dev": true, 2187 | "dependencies": { 2188 | "esbuild": "~0.23.0", 2189 | "get-tsconfig": "^4.7.5" 2190 | }, 2191 | "bin": { 2192 | "tsx": "dist/cli.mjs" 2193 | }, 2194 | "engines": { 2195 | "node": ">=18.0.0" 2196 | }, 2197 | "optionalDependencies": { 2198 | "fsevents": "~2.3.3" 2199 | } 2200 | }, 2201 | "node_modules/typescript": { 2202 | "version": "5.5.4", 2203 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz", 2204 | "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==", 2205 | "devOptional": true, 2206 | "bin": { 2207 | "tsc": "bin/tsc", 2208 | "tsserver": "bin/tsserver" 2209 | }, 2210 | "engines": { 2211 | "node": ">=14.17" 2212 | } 2213 | }, 2214 | "node_modules/uint8array-tools": { 2215 | "version": "0.0.8", 2216 | "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.8.tgz", 2217 | "integrity": "sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g==", 2218 | "engines": { 2219 | "node": ">=14.0.0" 2220 | } 2221 | }, 2222 | "node_modules/undici-types": { 2223 | "version": "6.19.8", 2224 | "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", 2225 | "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", 2226 | "dev": true 2227 | }, 2228 | "node_modules/v8-to-istanbul": { 2229 | "version": "9.3.0", 2230 | "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", 2231 | "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", 2232 | "dev": true, 2233 | "dependencies": { 2234 | "@jridgewell/trace-mapping": "^0.3.12", 2235 | "@types/istanbul-lib-coverage": "^2.0.1", 2236 | "convert-source-map": "^2.0.0" 2237 | }, 2238 | "engines": { 2239 | "node": ">=10.12.0" 2240 | } 2241 | }, 2242 | "node_modules/v8-to-istanbul/node_modules/convert-source-map": { 2243 | "version": "2.0.0", 2244 | "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", 2245 | "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", 2246 | "dev": true 2247 | }, 2248 | "node_modules/valibot": { 2249 | "version": "0.37.0", 2250 | "resolved": "https://registry.npmjs.org/valibot/-/valibot-0.37.0.tgz", 2251 | "integrity": "sha512-FQz52I8RXgFgOHym3XHYSREbNtkgSjF9prvMFH1nBsRyfL6SfCzoT1GuSDTlbsuPubM7/6Kbw0ZMQb8A+V+VsQ==", 2252 | "peerDependencies": { 2253 | "typescript": ">=5" 2254 | }, 2255 | "peerDependenciesMeta": { 2256 | "typescript": { 2257 | "optional": true 2258 | } 2259 | } 2260 | }, 2261 | "node_modules/wif": { 2262 | "version": "5.0.0", 2263 | "resolved": "https://registry.npmjs.org/wif/-/wif-5.0.0.tgz", 2264 | "integrity": "sha512-iFzrC/9ne740qFbNjTZ2FciSRJlHIXoxqk/Y5EnE08QOXu1WjJyCCswwDTYbohAOEnlCtLaAAQBhyaLRFh2hMA==", 2265 | "dependencies": { 2266 | "bs58check": "^4.0.0" 2267 | } 2268 | }, 2269 | "node_modules/workerpool": { 2270 | "version": "6.5.1", 2271 | "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", 2272 | "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", 2273 | "dev": true 2274 | }, 2275 | "node_modules/wrap-ansi": { 2276 | "version": "7.0.0", 2277 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2278 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2279 | "dev": true, 2280 | "dependencies": { 2281 | "ansi-styles": "^4.0.0", 2282 | "string-width": "^4.1.0", 2283 | "strip-ansi": "^6.0.0" 2284 | }, 2285 | "engines": { 2286 | "node": ">=10" 2287 | }, 2288 | "funding": { 2289 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2290 | } 2291 | }, 2292 | "node_modules/wrap-ansi-cjs": { 2293 | "name": "wrap-ansi", 2294 | "version": "7.0.0", 2295 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2296 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2297 | "dev": true, 2298 | "dependencies": { 2299 | "ansi-styles": "^4.0.0", 2300 | "string-width": "^4.1.0", 2301 | "strip-ansi": "^6.0.0" 2302 | }, 2303 | "engines": { 2304 | "node": ">=10" 2305 | }, 2306 | "funding": { 2307 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 2308 | } 2309 | }, 2310 | "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { 2311 | "version": "4.3.0", 2312 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2313 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2314 | "dev": true, 2315 | "dependencies": { 2316 | "color-convert": "^2.0.1" 2317 | }, 2318 | "engines": { 2319 | "node": ">=8" 2320 | }, 2321 | "funding": { 2322 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2323 | } 2324 | }, 2325 | "node_modules/wrap-ansi-cjs/node_modules/color-convert": { 2326 | "version": "2.0.1", 2327 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2328 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2329 | "dev": true, 2330 | "dependencies": { 2331 | "color-name": "~1.1.4" 2332 | }, 2333 | "engines": { 2334 | "node": ">=7.0.0" 2335 | } 2336 | }, 2337 | "node_modules/wrap-ansi-cjs/node_modules/color-name": { 2338 | "version": "1.1.4", 2339 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2340 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2341 | "dev": true 2342 | }, 2343 | "node_modules/wrap-ansi/node_modules/ansi-styles": { 2344 | "version": "4.3.0", 2345 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 2346 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 2347 | "dev": true, 2348 | "dependencies": { 2349 | "color-convert": "^2.0.1" 2350 | }, 2351 | "engines": { 2352 | "node": ">=8" 2353 | }, 2354 | "funding": { 2355 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 2356 | } 2357 | }, 2358 | "node_modules/wrap-ansi/node_modules/color-convert": { 2359 | "version": "2.0.1", 2360 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 2361 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 2362 | "dev": true, 2363 | "dependencies": { 2364 | "color-name": "~1.1.4" 2365 | }, 2366 | "engines": { 2367 | "node": ">=7.0.0" 2368 | } 2369 | }, 2370 | "node_modules/wrap-ansi/node_modules/color-name": { 2371 | "version": "1.1.4", 2372 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 2373 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 2374 | "dev": true 2375 | }, 2376 | "node_modules/wrappy": { 2377 | "version": "1.0.2", 2378 | "dev": true, 2379 | "license": "ISC" 2380 | }, 2381 | "node_modules/yargs": { 2382 | "version": "17.7.2", 2383 | "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", 2384 | "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", 2385 | "dev": true, 2386 | "dependencies": { 2387 | "cliui": "^8.0.1", 2388 | "escalade": "^3.1.1", 2389 | "get-caller-file": "^2.0.5", 2390 | "require-directory": "^2.1.1", 2391 | "string-width": "^4.2.3", 2392 | "y18n": "^5.0.5", 2393 | "yargs-parser": "^21.1.1" 2394 | }, 2395 | "engines": { 2396 | "node": ">=12" 2397 | } 2398 | }, 2399 | "node_modules/yargs-parser": { 2400 | "version": "21.1.1", 2401 | "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", 2402 | "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", 2403 | "dev": true, 2404 | "engines": { 2405 | "node": ">=12" 2406 | } 2407 | }, 2408 | "node_modules/yargs-unparser": { 2409 | "version": "2.0.0", 2410 | "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", 2411 | "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", 2412 | "dev": true, 2413 | "dependencies": { 2414 | "camelcase": "^6.0.0", 2415 | "decamelize": "^4.0.0", 2416 | "flat": "^5.0.2", 2417 | "is-plain-obj": "^2.1.0" 2418 | }, 2419 | "engines": { 2420 | "node": ">=10" 2421 | } 2422 | }, 2423 | "node_modules/yargs-unparser/node_modules/camelcase": { 2424 | "version": "6.3.0", 2425 | "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", 2426 | "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", 2427 | "dev": true, 2428 | "engines": { 2429 | "node": ">=10" 2430 | }, 2431 | "funding": { 2432 | "url": "https://github.com/sponsors/sindresorhus" 2433 | } 2434 | }, 2435 | "node_modules/yargs-unparser/node_modules/decamelize": { 2436 | "version": "4.0.0", 2437 | "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", 2438 | "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", 2439 | "dev": true, 2440 | "engines": { 2441 | "node": ">=10" 2442 | }, 2443 | "funding": { 2444 | "url": "https://github.com/sponsors/sindresorhus" 2445 | } 2446 | }, 2447 | "node_modules/yargs/node_modules/y18n": { 2448 | "version": "5.0.8", 2449 | "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", 2450 | "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", 2451 | "dev": true, 2452 | "engines": { 2453 | "node": ">=10" 2454 | } 2455 | }, 2456 | "node_modules/yocto-queue": { 2457 | "version": "0.1.0", 2458 | "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", 2459 | "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", 2460 | "dev": true, 2461 | "engines": { 2462 | "node": ">=10" 2463 | }, 2464 | "funding": { 2465 | "url": "https://github.com/sponsors/sindresorhus" 2466 | } 2467 | } 2468 | } 2469 | } 2470 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ecpair", 3 | "version": "3.0.0", 4 | "description": "Client-side Bitcoin JavaScript library ECPair", 5 | "type": "module", 6 | "main": "src/cjs/index.cjs", 7 | "module": "src/esm/index.js", 8 | "types": "src/cjs/index.d.ts", 9 | "exports": { 10 | ".": { 11 | "require": "./src/cjs/index.cjs", 12 | "import": "./src/esm/index.js", 13 | "types": "./src/cjs/index.d.ts" 14 | } 15 | }, 16 | "engines": { 17 | "node": ">=20.0.0" 18 | }, 19 | "keywords": [ 20 | "bitcoinjs", 21 | "bitcoin", 22 | "browserify", 23 | "javascript", 24 | "bitcoinjs" 25 | ], 26 | "scripts": { 27 | "audit": "NPM_AUDIT_IGNORE_DEV=1 NPM_AUDIT_IGNORE_LEVEL=low npm-audit-whitelister .npm-audit-whitelister.json", 28 | "build": "npm run clean && tsc -p ./tsconfig.json && tsc -p tsconfig.cjs.json && npm run formatjs", 29 | "postbuild": "find src/cjs -type f -name \"*.js\" -exec bash -c 'mv \"$0\" \"${0%.js}.cjs\"' {} \\; && chmod +x ./fixup.cjs && node fixup.cjs", 30 | "clean": "rimraf src", 31 | "clean:jstests": "rimraf 'test/**/*.js'", 32 | "coverage-report": "npm run build && npm run nobuild:coverage-report", 33 | "coverage-html": "npm run build && npm run nobuild:coverage-html", 34 | "coverage": "npm run build && npm run nobuild:coverage", 35 | "format": "npm run prettier -- --write", 36 | "formatjs": "npm run prettierjs -- --write", 37 | "format:ci": "npm run prettier -- --check && npm run prettierjs -- --check", 38 | "gitdiff:ci": "npm run build && git diff --exit-code", 39 | "lint": "tslint -p tsconfig.json -c tslint.json", 40 | "lint:tests": "tslint -p test/tsconfig.json -c tslint.json", 41 | "mocha:ts": "mocha --recursive", 42 | "nobuild:coverage-report": "c8 report --reporter=lcov", 43 | "nobuild:coverage-html": "c8 report --reporter=html", 44 | "nobuild:coverage": "c8 --check-coverage --exclude='**/*.cjs' --branches 90 --functions 90 --lines 90 npm run unit", 45 | "nobuild:unit": "npm run mocha:ts -- 'test/*.ts'", 46 | "prettier": "prettier \"ts_src/**/*.ts\" \"test/**/*.ts\" --ignore-path ./.prettierignore", 47 | "prettierjs": "prettier \"src/**/*.js\" --ignore-path ./.prettierignore", 48 | "test": "npm run build && npm run format:ci && npm run lint && npm run nobuild:coverage", 49 | "unit": "npm run build && npm run nobuild:unit" 50 | }, 51 | "repository": { 52 | "type": "git", 53 | "url": "https://github.com/bitcoinjs/ecpair.git" 54 | }, 55 | "files": [ 56 | "src" 57 | ], 58 | "dependencies": { 59 | "uint8array-tools": "^0.0.8", 60 | "valibot": "^0.37.0", 61 | "wif": "^5.0.0" 62 | }, 63 | "devDependencies": { 64 | "@types/create-hash": "^1.2.2", 65 | "@types/mocha": "^5.2.7", 66 | "@types/node": "^20.14.2", 67 | "@types/wif": "^2.0.2", 68 | "c8": "^10.1.2", 69 | "mocha": "^10.7.3", 70 | "prettier": "^3.3.3", 71 | "rimraf": "^2.6.3", 72 | "tiny-secp256k1": "^2.2.3", 73 | "tslint": "^6.1.3", 74 | "tsx": "^4.16.5", 75 | "typescript": "^5.0.4" 76 | }, 77 | "license": "MIT" 78 | } 79 | -------------------------------------------------------------------------------- /src/cjs/ecpair.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var __createBinding = 3 | (this && this.__createBinding) || 4 | (Object.create 5 | ? function (o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | var desc = Object.getOwnPropertyDescriptor(m, k); 8 | if ( 9 | !desc || 10 | ('get' in desc ? !m.__esModule : desc.writable || desc.configurable) 11 | ) { 12 | desc = { 13 | enumerable: true, 14 | get: function () { 15 | return m[k]; 16 | }, 17 | }; 18 | } 19 | Object.defineProperty(o, k2, desc); 20 | } 21 | : function (o, m, k, k2) { 22 | if (k2 === undefined) k2 = k; 23 | o[k2] = m[k]; 24 | }); 25 | var __setModuleDefault = 26 | (this && this.__setModuleDefault) || 27 | (Object.create 28 | ? function (o, v) { 29 | Object.defineProperty(o, 'default', { enumerable: true, value: v }); 30 | } 31 | : function (o, v) { 32 | o['default'] = v; 33 | }); 34 | var __importStar = 35 | (this && this.__importStar) || 36 | function (mod) { 37 | if (mod && mod.__esModule) return mod; 38 | var result = {}; 39 | if (mod != null) 40 | for (var k in mod) 41 | if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) 42 | __createBinding(result, mod, k); 43 | __setModuleDefault(result, mod); 44 | return result; 45 | }; 46 | Object.defineProperty(exports, '__esModule', { value: true }); 47 | exports.networks = void 0; 48 | exports.ECPairFactory = ECPairFactory; 49 | const networks = __importStar(require('./networks.cjs')); 50 | exports.networks = networks; 51 | const types = __importStar(require('./types.cjs')); 52 | const wif = __importStar(require('wif')); 53 | const testecc_1 = require('./testecc.cjs'); 54 | const v = __importStar(require('valibot')); 55 | const tools = __importStar(require('uint8array-tools')); 56 | const ECPairOptionsSchema = v.optional( 57 | v.object({ 58 | compressed: v.optional(v.boolean()), 59 | network: v.optional(types.NetworkSchema), 60 | // https://github.com/fabian-hiller/valibot/issues/243#issuecomment-2182514063 61 | rng: v.optional( 62 | v.pipe( 63 | v.instance(Function), 64 | v.transform((func) => { 65 | return (arg) => { 66 | const parsedArg = v.parse(v.optional(v.number()), arg); 67 | const returnedValue = func(parsedArg); 68 | const parsedReturn = v.parse(v.instance(Uint8Array), returnedValue); 69 | return parsedReturn; 70 | }; 71 | }), 72 | ), 73 | ), 74 | }), 75 | ); 76 | const toXOnly = (pubKey) => 77 | pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33); 78 | function ECPairFactory(ecc) { 79 | (0, testecc_1.testEcc)(ecc); 80 | function isPoint(maybePoint) { 81 | return ecc.isPoint(maybePoint); 82 | } 83 | function fromPrivateKey(buffer, options) { 84 | v.parse(types.Buffer256Bit, buffer); 85 | if (!ecc.isPrivate(buffer)) 86 | throw new TypeError('Private key not in range [1, n)'); 87 | v.parse(ECPairOptionsSchema, options); 88 | return new ECPair(buffer, undefined, options); 89 | } 90 | function fromPublicKey(buffer, options) { 91 | if (!ecc.isPoint(buffer)) { 92 | throw new Error('Point not on the curve'); 93 | } 94 | v.parse(ECPairOptionsSchema, options); 95 | return new ECPair(undefined, buffer, options); 96 | } 97 | function fromWIF(wifString, network) { 98 | const decoded = wif.decode(wifString); 99 | const version = decoded.version; 100 | // list of networks? 101 | if (Array.isArray(network)) { 102 | network = network 103 | .filter((x) => { 104 | return version === x.wif; 105 | }) 106 | .pop(); 107 | if (!network) throw new Error('Unknown network version'); 108 | // otherwise, assume a network object (or default to bitcoin) 109 | } else { 110 | network = network || networks.bitcoin; 111 | if (version !== network.wif) throw new Error('Invalid network version'); 112 | } 113 | return fromPrivateKey(decoded.privateKey, { 114 | compressed: decoded.compressed, 115 | network: network, 116 | }); 117 | } 118 | /** 119 | * Generates a random ECPairInterface. 120 | * 121 | * Uses `crypto.getRandomValues` under the hood for options.rng function, which is still an experimental feature as of Node.js 18.19.0. To work around this you can do one of the following: 122 | * 1. Use a polyfill for crypto.getRandomValues() 123 | * 2. Use the `--experimental-global-webcrypto` flag when running node.js. 124 | * 3. Pass in a custom rng function to generate random values. 125 | * 126 | * @param {ECPairOptions} options - Options for the ECPairInterface. 127 | * @return {ECPairInterface} A random ECPairInterface. 128 | */ 129 | function makeRandom(options) { 130 | v.parse(ECPairOptionsSchema, options); 131 | if (options === undefined) options = {}; 132 | const rng = 133 | options.rng || ((size) => crypto.getRandomValues(new Uint8Array(size))); 134 | let d; 135 | do { 136 | d = rng(32); 137 | v.parse(types.Buffer256Bit, d); 138 | } while (!ecc.isPrivate(d)); 139 | return fromPrivateKey(d, options); 140 | } 141 | class ECPair { 142 | __D; 143 | __Q; 144 | compressed; 145 | network; 146 | lowR; 147 | constructor(__D, __Q, options) { 148 | this.__D = __D; 149 | this.__Q = __Q; 150 | this.lowR = false; 151 | if (options === undefined) options = {}; 152 | this.compressed = 153 | options.compressed === undefined ? true : options.compressed; 154 | this.network = options.network || networks.bitcoin; 155 | if (__Q !== undefined) this.__Q = ecc.pointCompress(__Q, this.compressed); 156 | } 157 | get privateKey() { 158 | return this.__D; 159 | } 160 | get publicKey() { 161 | if (!this.__Q) { 162 | // It is not possible for both `__Q` and `__D` to be `undefined` at the same time. 163 | // The factory methods guard for this. 164 | const p = ecc.pointFromScalar(this.__D, this.compressed); 165 | // It is not possible for `p` to be null. 166 | // `fromPrivateKey()` checks that `__D` is a valid scalar. 167 | this.__Q = p; 168 | } 169 | return this.__Q; 170 | } 171 | toWIF() { 172 | if (!this.__D) throw new Error('Missing private key'); 173 | return wif.encode({ 174 | compressed: this.compressed, 175 | privateKey: this.__D, 176 | version: this.network.wif, 177 | }); 178 | } 179 | tweak(t) { 180 | if (this.privateKey) return this.tweakFromPrivateKey(t); 181 | return this.tweakFromPublicKey(t); 182 | } 183 | sign(hash, lowR) { 184 | if (!this.__D) throw new Error('Missing private key'); 185 | if (lowR === undefined) lowR = this.lowR; 186 | if (lowR === false) { 187 | return ecc.sign(hash, this.__D); 188 | } else { 189 | let sig = ecc.sign(hash, this.__D); 190 | const extraData = new Uint8Array(32); 191 | let counter = 0; 192 | // if first try is lowR, skip the loop 193 | // for second try and on, add extra entropy counting up 194 | while (sig[0] > 0x7f) { 195 | counter++; 196 | tools.writeUInt32(extraData, 0, counter, 'LE'); 197 | sig = ecc.sign(hash, this.__D, extraData); 198 | } 199 | return sig; 200 | } 201 | } 202 | signSchnorr(hash) { 203 | if (!this.privateKey) throw new Error('Missing private key'); 204 | if (!ecc.signSchnorr) 205 | throw new Error('signSchnorr not supported by ecc library'); 206 | return ecc.signSchnorr(hash, this.privateKey); 207 | } 208 | verify(hash, signature) { 209 | return ecc.verify(hash, this.publicKey, signature); 210 | } 211 | verifySchnorr(hash, signature) { 212 | if (!ecc.verifySchnorr) 213 | throw new Error('verifySchnorr not supported by ecc library'); 214 | return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature); 215 | } 216 | tweakFromPublicKey(t) { 217 | const xOnlyPubKey = toXOnly(this.publicKey); 218 | const tweakedPublicKey = ecc.xOnlyPointAddTweak(xOnlyPubKey, t); 219 | if (!tweakedPublicKey || tweakedPublicKey.xOnlyPubkey === null) 220 | throw new Error('Cannot tweak public key!'); 221 | const parityByte = Uint8Array.from([ 222 | tweakedPublicKey.parity === 0 ? 0x02 : 0x03, 223 | ]); 224 | return fromPublicKey( 225 | tools.concat([parityByte, tweakedPublicKey.xOnlyPubkey]), 226 | { 227 | network: this.network, 228 | compressed: this.compressed, 229 | }, 230 | ); 231 | } 232 | tweakFromPrivateKey(t) { 233 | const hasOddY = 234 | this.publicKey[0] === 3 || 235 | (this.publicKey[0] === 4 && (this.publicKey[64] & 1) === 1); 236 | const privateKey = hasOddY 237 | ? ecc.privateNegate(this.privateKey) 238 | : this.privateKey; 239 | const tweakedPrivateKey = ecc.privateAdd(privateKey, t); 240 | if (!tweakedPrivateKey) throw new Error('Invalid tweaked private key!'); 241 | return fromPrivateKey(tweakedPrivateKey, { 242 | network: this.network, 243 | compressed: this.compressed, 244 | }); 245 | } 246 | } 247 | return { 248 | isPoint, 249 | fromPrivateKey, 250 | fromPublicKey, 251 | fromWIF, 252 | makeRandom, 253 | }; 254 | } 255 | -------------------------------------------------------------------------------- /src/cjs/ecpair.d.ts: -------------------------------------------------------------------------------- 1 | import { Network } from './networks'; 2 | import * as networks from './networks'; 3 | export { networks }; 4 | import * as v from 'valibot'; 5 | declare const ECPairOptionsSchema: v.OptionalSchema, never>; 7 | readonly network: v.OptionalSchema, v.InstanceSchema], undefined>; 9 | readonly bech32: v.StringSchema; 10 | readonly bip32: v.ObjectSchema<{ 11 | readonly public: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 12 | readonly private: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 13 | }, undefined>; 14 | readonly pubKeyHash: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 15 | readonly scriptHash: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 16 | readonly wif: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 17 | }, undefined>, never>; 18 | readonly rng: v.OptionalSchema, v.TransformAction Uint8Array>]>, never>; 19 | }, undefined>, never>; 20 | type ECPairOptions = v.InferOutput; 21 | export interface Signer { 22 | publicKey: Uint8Array; 23 | network?: any; 24 | sign(hash: Uint8Array, lowR?: boolean): Uint8Array; 25 | } 26 | export interface SignerAsync { 27 | publicKey: Uint8Array; 28 | network?: any; 29 | sign(hash: Uint8Array, lowR?: boolean): Promise; 30 | } 31 | export interface ECPairInterface extends Signer { 32 | compressed: boolean; 33 | network: Network; 34 | lowR: boolean; 35 | privateKey?: Uint8Array; 36 | toWIF(): string; 37 | tweak(t: Uint8Array): ECPairInterface; 38 | verify(hash: Uint8Array, signature: Uint8Array): boolean; 39 | verifySchnorr(hash: Uint8Array, signature: Uint8Array): boolean; 40 | signSchnorr(hash: Uint8Array): Uint8Array; 41 | } 42 | export interface ECPairAPI { 43 | isPoint(maybePoint: any): boolean; 44 | fromPrivateKey(buffer: Uint8Array, options?: ECPairOptions): ECPairInterface; 45 | fromPublicKey(buffer: Uint8Array, options?: ECPairOptions): ECPairInterface; 46 | fromWIF(wifString: string, network?: Network | Network[]): ECPairInterface; 47 | makeRandom(options?: ECPairOptions): ECPairInterface; 48 | } 49 | export interface TinySecp256k1Interface { 50 | isPoint(p: Uint8Array): boolean; 51 | pointCompress(p: Uint8Array, compressed?: boolean): Uint8Array; 52 | isPrivate(d: Uint8Array): boolean; 53 | pointFromScalar(d: Uint8Array, compressed?: boolean): Uint8Array | null; 54 | xOnlyPointAddTweak(p: Uint8Array, tweak: Uint8Array): XOnlyPointAddTweakResult | null; 55 | privateAdd(d: Uint8Array, tweak: Uint8Array): Uint8Array | null; 56 | privateNegate(d: Uint8Array): Uint8Array; 57 | sign(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array; 58 | signSchnorr?(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array; 59 | verify(h: Uint8Array, Q: Uint8Array, signature: Uint8Array, strict?: boolean): boolean; 60 | verifySchnorr?(h: Uint8Array, Q: Uint8Array, signature: Uint8Array): boolean; 61 | } 62 | interface XOnlyPointAddTweakResult { 63 | parity: 1 | 0; 64 | xOnlyPubkey: Uint8Array; 65 | } 66 | export declare function ECPairFactory(ecc: TinySecp256k1Interface): ECPairAPI; 67 | -------------------------------------------------------------------------------- /src/cjs/index.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | exports.networks = exports.ECPairFactory = exports.default = void 0; 4 | var ecpair_1 = require('./ecpair.cjs'); 5 | Object.defineProperty(exports, 'default', { 6 | enumerable: true, 7 | get: function () { 8 | return ecpair_1.ECPairFactory; 9 | }, 10 | }); 11 | Object.defineProperty(exports, 'ECPairFactory', { 12 | enumerable: true, 13 | get: function () { 14 | return ecpair_1.ECPairFactory; 15 | }, 16 | }); 17 | Object.defineProperty(exports, 'networks', { 18 | enumerable: true, 19 | get: function () { 20 | return ecpair_1.networks; 21 | }, 22 | }); 23 | -------------------------------------------------------------------------------- /src/cjs/index.d.ts: -------------------------------------------------------------------------------- 1 | export { ECPairFactory as default, ECPairFactory, type Signer, type SignerAsync, type ECPairAPI, type ECPairInterface, type TinySecp256k1Interface, networks, } from './ecpair'; 2 | -------------------------------------------------------------------------------- /src/cjs/networks.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | exports.testnet = exports.bitcoin = void 0; 4 | exports.bitcoin = { 5 | messagePrefix: '\x18Bitcoin Signed Message:\n', 6 | bech32: 'bc', 7 | bip32: { 8 | public: 0x0488b21e, 9 | private: 0x0488ade4, 10 | }, 11 | pubKeyHash: 0x00, 12 | scriptHash: 0x05, 13 | wif: 0x80, 14 | }; 15 | exports.testnet = { 16 | messagePrefix: '\x18Bitcoin Signed Message:\n', 17 | bech32: 'tb', 18 | bip32: { 19 | public: 0x043587cf, 20 | private: 0x04358394, 21 | }, 22 | pubKeyHash: 0x6f, 23 | scriptHash: 0xc4, 24 | wif: 0xef, 25 | }; 26 | -------------------------------------------------------------------------------- /src/cjs/networks.d.ts: -------------------------------------------------------------------------------- 1 | import * as v from 'valibot'; 2 | import { NetworkSchema } from './types'; 3 | export type Network = v.InferOutput; 4 | export declare const bitcoin: Network; 5 | export declare const testnet: Network; 6 | -------------------------------------------------------------------------------- /src/cjs/testecc.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | Object.defineProperty(exports, '__esModule', { value: true }); 3 | exports.testEcc = testEcc; 4 | const h = (hex) => Buffer.from(hex, 'hex'); 5 | function testEcc(ecc) { 6 | assert( 7 | ecc.isPoint( 8 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 9 | ), 10 | ); 11 | assert( 12 | !ecc.isPoint( 13 | h('030000000000000000000000000000000000000000000000000000000000000005'), 14 | ), 15 | ); 16 | assert( 17 | ecc.isPrivate( 18 | h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 19 | ), 20 | ); 21 | // order - 1 22 | assert( 23 | ecc.isPrivate( 24 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 25 | ), 26 | ); 27 | // 0 28 | assert( 29 | !ecc.isPrivate( 30 | h('0000000000000000000000000000000000000000000000000000000000000000'), 31 | ), 32 | ); 33 | // order 34 | assert( 35 | !ecc.isPrivate( 36 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'), 37 | ), 38 | ); 39 | // order + 1 40 | assert( 41 | !ecc.isPrivate( 42 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142'), 43 | ), 44 | ); 45 | // 1 + 0 == 1 46 | assert( 47 | Buffer.from( 48 | ecc.privateAdd( 49 | h('0000000000000000000000000000000000000000000000000000000000000001'), 50 | h('0000000000000000000000000000000000000000000000000000000000000000'), 51 | ), 52 | ).equals( 53 | h('0000000000000000000000000000000000000000000000000000000000000001'), 54 | ), 55 | ); 56 | // -3 + 3 == 0 57 | assert( 58 | ecc.privateAdd( 59 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e'), 60 | h('0000000000000000000000000000000000000000000000000000000000000003'), 61 | ) === null, 62 | ); 63 | assert( 64 | Buffer.from( 65 | ecc.privateAdd( 66 | h('e211078564db65c3ce7704f08262b1f38f1ef412ad15b5ac2d76657a63b2c500'), 67 | h('b51fbb69051255d1becbd683de5848242a89c229348dd72896a87ada94ae8665'), 68 | ), 69 | ).equals( 70 | h('9730c2ee69edbb958d42db7460bafa18fef9d955325aec99044c81c8282b0a24'), 71 | ), 72 | ); 73 | assert( 74 | Buffer.from( 75 | ecc.privateNegate( 76 | h('0000000000000000000000000000000000000000000000000000000000000001'), 77 | ), 78 | ).equals( 79 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 80 | ), 81 | ); 82 | assert( 83 | Buffer.from( 84 | ecc.privateNegate( 85 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e'), 86 | ), 87 | ).equals( 88 | h('0000000000000000000000000000000000000000000000000000000000000003'), 89 | ), 90 | ); 91 | assert( 92 | Buffer.from( 93 | ecc.privateNegate( 94 | h('b1121e4088a66a28f5b6b0f5844943ecd9f610196d7bb83b25214b60452c09af'), 95 | ), 96 | ).equals( 97 | h('4eede1bf775995d70a494f0a7bb6bc11e0b8cccd41cce8009ab1132c8b0a3792'), 98 | ), 99 | ); 100 | assert( 101 | Buffer.from( 102 | ecc.pointCompress( 103 | h( 104 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 105 | ), 106 | true, 107 | ), 108 | ).equals( 109 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 110 | ), 111 | ); 112 | assert( 113 | Buffer.from( 114 | ecc.pointCompress( 115 | h( 116 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 117 | ), 118 | false, 119 | ), 120 | ).equals( 121 | h( 122 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 123 | ), 124 | ), 125 | ); 126 | assert( 127 | Buffer.from( 128 | ecc.pointCompress( 129 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 130 | true, 131 | ), 132 | ).equals( 133 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 134 | ), 135 | ); 136 | assert( 137 | Buffer.from( 138 | ecc.pointCompress( 139 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 140 | false, 141 | ), 142 | ).equals( 143 | h( 144 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 145 | ), 146 | ), 147 | ); 148 | assert( 149 | Buffer.from( 150 | ecc.pointFromScalar( 151 | h('b1121e4088a66a28f5b6b0f5844943ecd9f610196d7bb83b25214b60452c09af'), 152 | ), 153 | ).equals( 154 | h('02b07ba9dca9523b7ef4bd97703d43d20399eb698e194704791a25ce77a400df99'), 155 | ), 156 | ); 157 | assert( 158 | ecc.xOnlyPointAddTweak( 159 | h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 160 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 161 | ) === null, 162 | ); 163 | let xOnlyRes = ecc.xOnlyPointAddTweak( 164 | h('1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b'), 165 | h('a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac'), 166 | ); 167 | assert( 168 | Buffer.from(xOnlyRes.xOnlyPubkey).equals( 169 | h('e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf'), 170 | ) && xOnlyRes.parity === 1, 171 | ); 172 | xOnlyRes = ecc.xOnlyPointAddTweak( 173 | h('2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991'), 174 | h('823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47'), 175 | ); 176 | assert( 177 | Buffer.from(xOnlyRes.xOnlyPubkey).equals( 178 | h('9534f8dc8c6deda2dc007655981c78b49c5d96c778fbf363462a11ec9dfd948c'), 179 | ) && xOnlyRes.parity === 0, 180 | ); 181 | assert( 182 | Buffer.from( 183 | ecc.sign( 184 | h('5e9f0a0d593efdcf78ac923bc3313e4e7d408d574354ee2b3288c0da9fbba6ed'), 185 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 186 | ), 187 | ).equals( 188 | h( 189 | '54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5', 190 | ), 191 | ), 192 | ); 193 | assert( 194 | ecc.verify( 195 | h('5e9f0a0d593efdcf78ac923bc3313e4e7d408d574354ee2b3288c0da9fbba6ed'), 196 | h('0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 197 | h( 198 | '54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5', 199 | ), 200 | ), 201 | ); 202 | if (ecc.signSchnorr) { 203 | assert( 204 | Buffer.from( 205 | ecc.signSchnorr( 206 | h('7e2d58d8b3bcdf1abadec7829054f90dda9805aab56c77333024b9d0a508b75c'), 207 | h('c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b14e5c9'), 208 | h('c87aa53824b4d7ae2eb035a2b5bbbccc080e76cdc6d1692c4b0b62d798e6d906'), 209 | ), 210 | ).equals( 211 | h( 212 | '5831aaeed7b44bb74e5eab94ba9d4294c49bcf2a60728d8b4c200f50dd313c1bab745879a5ad954a72c45a91c3a51d3c7adea98d82f8481e0e1e03674a6f3fb7', 213 | ), 214 | ), 215 | ); 216 | } 217 | if (ecc.verifySchnorr) { 218 | assert( 219 | ecc.verifySchnorr( 220 | h('7e2d58d8b3bcdf1abadec7829054f90dda9805aab56c77333024b9d0a508b75c'), 221 | h('dd308afec5777e13121fa72b9cc1b7cc0139715309b086c960e18fd969774eb8'), 222 | h( 223 | '5831aaeed7b44bb74e5eab94ba9d4294c49bcf2a60728d8b4c200f50dd313c1bab745879a5ad954a72c45a91c3a51d3c7adea98d82f8481e0e1e03674a6f3fb7', 224 | ), 225 | ), 226 | ); 227 | } 228 | } 229 | function assert(bool) { 230 | if (!bool) throw new Error('ecc library invalid'); 231 | } 232 | -------------------------------------------------------------------------------- /src/cjs/testecc.d.ts: -------------------------------------------------------------------------------- 1 | import { TinySecp256k1Interface } from './ecpair'; 2 | export declare function testEcc(ecc: TinySecp256k1Interface): void; 3 | -------------------------------------------------------------------------------- /src/cjs/types.cjs: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | var __createBinding = 3 | (this && this.__createBinding) || 4 | (Object.create 5 | ? function (o, m, k, k2) { 6 | if (k2 === undefined) k2 = k; 7 | var desc = Object.getOwnPropertyDescriptor(m, k); 8 | if ( 9 | !desc || 10 | ('get' in desc ? !m.__esModule : desc.writable || desc.configurable) 11 | ) { 12 | desc = { 13 | enumerable: true, 14 | get: function () { 15 | return m[k]; 16 | }, 17 | }; 18 | } 19 | Object.defineProperty(o, k2, desc); 20 | } 21 | : function (o, m, k, k2) { 22 | if (k2 === undefined) k2 = k; 23 | o[k2] = m[k]; 24 | }); 25 | var __setModuleDefault = 26 | (this && this.__setModuleDefault) || 27 | (Object.create 28 | ? function (o, v) { 29 | Object.defineProperty(o, 'default', { enumerable: true, value: v }); 30 | } 31 | : function (o, v) { 32 | o['default'] = v; 33 | }); 34 | var __importStar = 35 | (this && this.__importStar) || 36 | function (mod) { 37 | if (mod && mod.__esModule) return mod; 38 | var result = {}; 39 | if (mod != null) 40 | for (var k in mod) 41 | if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) 42 | __createBinding(result, mod, k); 43 | __setModuleDefault(result, mod); 44 | return result; 45 | }; 46 | Object.defineProperty(exports, '__esModule', { value: true }); 47 | exports.Buffer256Bit = exports.NetworkSchema = void 0; 48 | const v = __importStar(require('valibot')); 49 | const Uint32Schema = v.pipe( 50 | v.number(), 51 | v.integer(), 52 | v.minValue(0), 53 | v.maxValue(0xffffffff), 54 | ); 55 | const Uint8Schema = v.pipe( 56 | v.number(), 57 | v.integer(), 58 | v.minValue(0), 59 | v.maxValue(0xff), 60 | ); 61 | exports.NetworkSchema = v.object({ 62 | messagePrefix: v.union([v.string(), v.instance(Uint8Array)]), 63 | bech32: v.string(), 64 | bip32: v.object({ 65 | public: Uint32Schema, 66 | private: Uint32Schema, 67 | }), 68 | pubKeyHash: Uint8Schema, 69 | scriptHash: Uint8Schema, 70 | wif: Uint8Schema, 71 | }); 72 | exports.Buffer256Bit = v.pipe(v.instance(Uint8Array), v.length(32)); 73 | -------------------------------------------------------------------------------- /src/cjs/types.d.ts: -------------------------------------------------------------------------------- 1 | import * as v from 'valibot'; 2 | export declare const NetworkSchema: v.ObjectSchema<{ 3 | readonly messagePrefix: v.UnionSchema<[v.StringSchema, v.InstanceSchema], undefined>; 4 | readonly bech32: v.StringSchema; 5 | readonly bip32: v.ObjectSchema<{ 6 | readonly public: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 7 | readonly private: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 8 | }, undefined>; 9 | readonly pubKeyHash: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 10 | readonly scriptHash: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 11 | readonly wif: v.SchemaWithPipe<[v.NumberSchema, v.IntegerAction, v.MinValueAction, v.MaxValueAction]>; 12 | }, undefined>; 13 | export declare const Buffer256Bit: v.SchemaWithPipe<[v.InstanceSchema, v.LengthAction]>; 14 | -------------------------------------------------------------------------------- /src/esm/ecpair.js: -------------------------------------------------------------------------------- 1 | import * as networks from './networks.js'; 2 | import * as types from './types.js'; 3 | import * as wif from 'wif'; 4 | import { testEcc } from './testecc.js'; 5 | export { networks }; 6 | import * as v from 'valibot'; 7 | import * as tools from 'uint8array-tools'; 8 | const ECPairOptionsSchema = v.optional( 9 | v.object({ 10 | compressed: v.optional(v.boolean()), 11 | network: v.optional(types.NetworkSchema), 12 | // https://github.com/fabian-hiller/valibot/issues/243#issuecomment-2182514063 13 | rng: v.optional( 14 | v.pipe( 15 | v.instance(Function), 16 | v.transform((func) => { 17 | return (arg) => { 18 | const parsedArg = v.parse(v.optional(v.number()), arg); 19 | const returnedValue = func(parsedArg); 20 | const parsedReturn = v.parse(v.instance(Uint8Array), returnedValue); 21 | return parsedReturn; 22 | }; 23 | }), 24 | ), 25 | ), 26 | }), 27 | ); 28 | const toXOnly = (pubKey) => 29 | pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33); 30 | export function ECPairFactory(ecc) { 31 | testEcc(ecc); 32 | function isPoint(maybePoint) { 33 | return ecc.isPoint(maybePoint); 34 | } 35 | function fromPrivateKey(buffer, options) { 36 | v.parse(types.Buffer256Bit, buffer); 37 | if (!ecc.isPrivate(buffer)) 38 | throw new TypeError('Private key not in range [1, n)'); 39 | v.parse(ECPairOptionsSchema, options); 40 | return new ECPair(buffer, undefined, options); 41 | } 42 | function fromPublicKey(buffer, options) { 43 | if (!ecc.isPoint(buffer)) { 44 | throw new Error('Point not on the curve'); 45 | } 46 | v.parse(ECPairOptionsSchema, options); 47 | return new ECPair(undefined, buffer, options); 48 | } 49 | function fromWIF(wifString, network) { 50 | const decoded = wif.decode(wifString); 51 | const version = decoded.version; 52 | // list of networks? 53 | if (Array.isArray(network)) { 54 | network = network 55 | .filter((x) => { 56 | return version === x.wif; 57 | }) 58 | .pop(); 59 | if (!network) throw new Error('Unknown network version'); 60 | // otherwise, assume a network object (or default to bitcoin) 61 | } else { 62 | network = network || networks.bitcoin; 63 | if (version !== network.wif) throw new Error('Invalid network version'); 64 | } 65 | return fromPrivateKey(decoded.privateKey, { 66 | compressed: decoded.compressed, 67 | network: network, 68 | }); 69 | } 70 | /** 71 | * Generates a random ECPairInterface. 72 | * 73 | * Uses `crypto.getRandomValues` under the hood for options.rng function, which is still an experimental feature as of Node.js 18.19.0. To work around this you can do one of the following: 74 | * 1. Use a polyfill for crypto.getRandomValues() 75 | * 2. Use the `--experimental-global-webcrypto` flag when running node.js. 76 | * 3. Pass in a custom rng function to generate random values. 77 | * 78 | * @param {ECPairOptions} options - Options for the ECPairInterface. 79 | * @return {ECPairInterface} A random ECPairInterface. 80 | */ 81 | function makeRandom(options) { 82 | v.parse(ECPairOptionsSchema, options); 83 | if (options === undefined) options = {}; 84 | const rng = 85 | options.rng || ((size) => crypto.getRandomValues(new Uint8Array(size))); 86 | let d; 87 | do { 88 | d = rng(32); 89 | v.parse(types.Buffer256Bit, d); 90 | } while (!ecc.isPrivate(d)); 91 | return fromPrivateKey(d, options); 92 | } 93 | class ECPair { 94 | __D; 95 | __Q; 96 | compressed; 97 | network; 98 | lowR; 99 | constructor(__D, __Q, options) { 100 | this.__D = __D; 101 | this.__Q = __Q; 102 | this.lowR = false; 103 | if (options === undefined) options = {}; 104 | this.compressed = 105 | options.compressed === undefined ? true : options.compressed; 106 | this.network = options.network || networks.bitcoin; 107 | if (__Q !== undefined) this.__Q = ecc.pointCompress(__Q, this.compressed); 108 | } 109 | get privateKey() { 110 | return this.__D; 111 | } 112 | get publicKey() { 113 | if (!this.__Q) { 114 | // It is not possible for both `__Q` and `__D` to be `undefined` at the same time. 115 | // The factory methods guard for this. 116 | const p = ecc.pointFromScalar(this.__D, this.compressed); 117 | // It is not possible for `p` to be null. 118 | // `fromPrivateKey()` checks that `__D` is a valid scalar. 119 | this.__Q = p; 120 | } 121 | return this.__Q; 122 | } 123 | toWIF() { 124 | if (!this.__D) throw new Error('Missing private key'); 125 | return wif.encode({ 126 | compressed: this.compressed, 127 | privateKey: this.__D, 128 | version: this.network.wif, 129 | }); 130 | } 131 | tweak(t) { 132 | if (this.privateKey) return this.tweakFromPrivateKey(t); 133 | return this.tweakFromPublicKey(t); 134 | } 135 | sign(hash, lowR) { 136 | if (!this.__D) throw new Error('Missing private key'); 137 | if (lowR === undefined) lowR = this.lowR; 138 | if (lowR === false) { 139 | return ecc.sign(hash, this.__D); 140 | } else { 141 | let sig = ecc.sign(hash, this.__D); 142 | const extraData = new Uint8Array(32); 143 | let counter = 0; 144 | // if first try is lowR, skip the loop 145 | // for second try and on, add extra entropy counting up 146 | while (sig[0] > 0x7f) { 147 | counter++; 148 | tools.writeUInt32(extraData, 0, counter, 'LE'); 149 | sig = ecc.sign(hash, this.__D, extraData); 150 | } 151 | return sig; 152 | } 153 | } 154 | signSchnorr(hash) { 155 | if (!this.privateKey) throw new Error('Missing private key'); 156 | if (!ecc.signSchnorr) 157 | throw new Error('signSchnorr not supported by ecc library'); 158 | return ecc.signSchnorr(hash, this.privateKey); 159 | } 160 | verify(hash, signature) { 161 | return ecc.verify(hash, this.publicKey, signature); 162 | } 163 | verifySchnorr(hash, signature) { 164 | if (!ecc.verifySchnorr) 165 | throw new Error('verifySchnorr not supported by ecc library'); 166 | return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature); 167 | } 168 | tweakFromPublicKey(t) { 169 | const xOnlyPubKey = toXOnly(this.publicKey); 170 | const tweakedPublicKey = ecc.xOnlyPointAddTweak(xOnlyPubKey, t); 171 | if (!tweakedPublicKey || tweakedPublicKey.xOnlyPubkey === null) 172 | throw new Error('Cannot tweak public key!'); 173 | const parityByte = Uint8Array.from([ 174 | tweakedPublicKey.parity === 0 ? 0x02 : 0x03, 175 | ]); 176 | return fromPublicKey( 177 | tools.concat([parityByte, tweakedPublicKey.xOnlyPubkey]), 178 | { 179 | network: this.network, 180 | compressed: this.compressed, 181 | }, 182 | ); 183 | } 184 | tweakFromPrivateKey(t) { 185 | const hasOddY = 186 | this.publicKey[0] === 3 || 187 | (this.publicKey[0] === 4 && (this.publicKey[64] & 1) === 1); 188 | const privateKey = hasOddY 189 | ? ecc.privateNegate(this.privateKey) 190 | : this.privateKey; 191 | const tweakedPrivateKey = ecc.privateAdd(privateKey, t); 192 | if (!tweakedPrivateKey) throw new Error('Invalid tweaked private key!'); 193 | return fromPrivateKey(tweakedPrivateKey, { 194 | network: this.network, 195 | compressed: this.compressed, 196 | }); 197 | } 198 | } 199 | return { 200 | isPoint, 201 | fromPrivateKey, 202 | fromPublicKey, 203 | fromWIF, 204 | makeRandom, 205 | }; 206 | } 207 | -------------------------------------------------------------------------------- /src/esm/index.js: -------------------------------------------------------------------------------- 1 | export { ECPairFactory as default, ECPairFactory, networks } from './ecpair.js'; 2 | -------------------------------------------------------------------------------- /src/esm/networks.js: -------------------------------------------------------------------------------- 1 | export const bitcoin = { 2 | messagePrefix: '\x18Bitcoin Signed Message:\n', 3 | bech32: 'bc', 4 | bip32: { 5 | public: 0x0488b21e, 6 | private: 0x0488ade4, 7 | }, 8 | pubKeyHash: 0x00, 9 | scriptHash: 0x05, 10 | wif: 0x80, 11 | }; 12 | export const testnet = { 13 | messagePrefix: '\x18Bitcoin Signed Message:\n', 14 | bech32: 'tb', 15 | bip32: { 16 | public: 0x043587cf, 17 | private: 0x04358394, 18 | }, 19 | pubKeyHash: 0x6f, 20 | scriptHash: 0xc4, 21 | wif: 0xef, 22 | }; 23 | -------------------------------------------------------------------------------- /src/esm/testecc.js: -------------------------------------------------------------------------------- 1 | const h = (hex) => Buffer.from(hex, 'hex'); 2 | export function testEcc(ecc) { 3 | assert( 4 | ecc.isPoint( 5 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 6 | ), 7 | ); 8 | assert( 9 | !ecc.isPoint( 10 | h('030000000000000000000000000000000000000000000000000000000000000005'), 11 | ), 12 | ); 13 | assert( 14 | ecc.isPrivate( 15 | h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 16 | ), 17 | ); 18 | // order - 1 19 | assert( 20 | ecc.isPrivate( 21 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 22 | ), 23 | ); 24 | // 0 25 | assert( 26 | !ecc.isPrivate( 27 | h('0000000000000000000000000000000000000000000000000000000000000000'), 28 | ), 29 | ); 30 | // order 31 | assert( 32 | !ecc.isPrivate( 33 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'), 34 | ), 35 | ); 36 | // order + 1 37 | assert( 38 | !ecc.isPrivate( 39 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142'), 40 | ), 41 | ); 42 | // 1 + 0 == 1 43 | assert( 44 | Buffer.from( 45 | ecc.privateAdd( 46 | h('0000000000000000000000000000000000000000000000000000000000000001'), 47 | h('0000000000000000000000000000000000000000000000000000000000000000'), 48 | ), 49 | ).equals( 50 | h('0000000000000000000000000000000000000000000000000000000000000001'), 51 | ), 52 | ); 53 | // -3 + 3 == 0 54 | assert( 55 | ecc.privateAdd( 56 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e'), 57 | h('0000000000000000000000000000000000000000000000000000000000000003'), 58 | ) === null, 59 | ); 60 | assert( 61 | Buffer.from( 62 | ecc.privateAdd( 63 | h('e211078564db65c3ce7704f08262b1f38f1ef412ad15b5ac2d76657a63b2c500'), 64 | h('b51fbb69051255d1becbd683de5848242a89c229348dd72896a87ada94ae8665'), 65 | ), 66 | ).equals( 67 | h('9730c2ee69edbb958d42db7460bafa18fef9d955325aec99044c81c8282b0a24'), 68 | ), 69 | ); 70 | assert( 71 | Buffer.from( 72 | ecc.privateNegate( 73 | h('0000000000000000000000000000000000000000000000000000000000000001'), 74 | ), 75 | ).equals( 76 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 77 | ), 78 | ); 79 | assert( 80 | Buffer.from( 81 | ecc.privateNegate( 82 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e'), 83 | ), 84 | ).equals( 85 | h('0000000000000000000000000000000000000000000000000000000000000003'), 86 | ), 87 | ); 88 | assert( 89 | Buffer.from( 90 | ecc.privateNegate( 91 | h('b1121e4088a66a28f5b6b0f5844943ecd9f610196d7bb83b25214b60452c09af'), 92 | ), 93 | ).equals( 94 | h('4eede1bf775995d70a494f0a7bb6bc11e0b8cccd41cce8009ab1132c8b0a3792'), 95 | ), 96 | ); 97 | assert( 98 | Buffer.from( 99 | ecc.pointCompress( 100 | h( 101 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 102 | ), 103 | true, 104 | ), 105 | ).equals( 106 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 107 | ), 108 | ); 109 | assert( 110 | Buffer.from( 111 | ecc.pointCompress( 112 | h( 113 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 114 | ), 115 | false, 116 | ), 117 | ).equals( 118 | h( 119 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 120 | ), 121 | ), 122 | ); 123 | assert( 124 | Buffer.from( 125 | ecc.pointCompress( 126 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 127 | true, 128 | ), 129 | ).equals( 130 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 131 | ), 132 | ); 133 | assert( 134 | Buffer.from( 135 | ecc.pointCompress( 136 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 137 | false, 138 | ), 139 | ).equals( 140 | h( 141 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 142 | ), 143 | ), 144 | ); 145 | assert( 146 | Buffer.from( 147 | ecc.pointFromScalar( 148 | h('b1121e4088a66a28f5b6b0f5844943ecd9f610196d7bb83b25214b60452c09af'), 149 | ), 150 | ).equals( 151 | h('02b07ba9dca9523b7ef4bd97703d43d20399eb698e194704791a25ce77a400df99'), 152 | ), 153 | ); 154 | assert( 155 | ecc.xOnlyPointAddTweak( 156 | h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 157 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 158 | ) === null, 159 | ); 160 | let xOnlyRes = ecc.xOnlyPointAddTweak( 161 | h('1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b'), 162 | h('a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac'), 163 | ); 164 | assert( 165 | Buffer.from(xOnlyRes.xOnlyPubkey).equals( 166 | h('e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf'), 167 | ) && xOnlyRes.parity === 1, 168 | ); 169 | xOnlyRes = ecc.xOnlyPointAddTweak( 170 | h('2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991'), 171 | h('823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47'), 172 | ); 173 | assert( 174 | Buffer.from(xOnlyRes.xOnlyPubkey).equals( 175 | h('9534f8dc8c6deda2dc007655981c78b49c5d96c778fbf363462a11ec9dfd948c'), 176 | ) && xOnlyRes.parity === 0, 177 | ); 178 | assert( 179 | Buffer.from( 180 | ecc.sign( 181 | h('5e9f0a0d593efdcf78ac923bc3313e4e7d408d574354ee2b3288c0da9fbba6ed'), 182 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 183 | ), 184 | ).equals( 185 | h( 186 | '54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5', 187 | ), 188 | ), 189 | ); 190 | assert( 191 | ecc.verify( 192 | h('5e9f0a0d593efdcf78ac923bc3313e4e7d408d574354ee2b3288c0da9fbba6ed'), 193 | h('0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 194 | h( 195 | '54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5', 196 | ), 197 | ), 198 | ); 199 | if (ecc.signSchnorr) { 200 | assert( 201 | Buffer.from( 202 | ecc.signSchnorr( 203 | h('7e2d58d8b3bcdf1abadec7829054f90dda9805aab56c77333024b9d0a508b75c'), 204 | h('c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b14e5c9'), 205 | h('c87aa53824b4d7ae2eb035a2b5bbbccc080e76cdc6d1692c4b0b62d798e6d906'), 206 | ), 207 | ).equals( 208 | h( 209 | '5831aaeed7b44bb74e5eab94ba9d4294c49bcf2a60728d8b4c200f50dd313c1bab745879a5ad954a72c45a91c3a51d3c7adea98d82f8481e0e1e03674a6f3fb7', 210 | ), 211 | ), 212 | ); 213 | } 214 | if (ecc.verifySchnorr) { 215 | assert( 216 | ecc.verifySchnorr( 217 | h('7e2d58d8b3bcdf1abadec7829054f90dda9805aab56c77333024b9d0a508b75c'), 218 | h('dd308afec5777e13121fa72b9cc1b7cc0139715309b086c960e18fd969774eb8'), 219 | h( 220 | '5831aaeed7b44bb74e5eab94ba9d4294c49bcf2a60728d8b4c200f50dd313c1bab745879a5ad954a72c45a91c3a51d3c7adea98d82f8481e0e1e03674a6f3fb7', 221 | ), 222 | ), 223 | ); 224 | } 225 | } 226 | function assert(bool) { 227 | if (!bool) throw new Error('ecc library invalid'); 228 | } 229 | -------------------------------------------------------------------------------- /src/esm/types.js: -------------------------------------------------------------------------------- 1 | import * as v from 'valibot'; 2 | const Uint32Schema = v.pipe( 3 | v.number(), 4 | v.integer(), 5 | v.minValue(0), 6 | v.maxValue(0xffffffff), 7 | ); 8 | const Uint8Schema = v.pipe( 9 | v.number(), 10 | v.integer(), 11 | v.minValue(0), 12 | v.maxValue(0xff), 13 | ); 14 | export const NetworkSchema = v.object({ 15 | messagePrefix: v.union([v.string(), v.instance(Uint8Array)]), 16 | bech32: v.string(), 17 | bip32: v.object({ 18 | public: Uint32Schema, 19 | private: Uint32Schema, 20 | }), 21 | pubKeyHash: Uint8Schema, 22 | scriptHash: Uint8Schema, 23 | wif: Uint8Schema, 24 | }); 25 | export const Buffer256Bit = v.pipe(v.instance(Uint8Array), v.length(32)); 26 | -------------------------------------------------------------------------------- /test/ecpair.spec.ts: -------------------------------------------------------------------------------- 1 | import * as assert from 'assert'; 2 | import { createHash } from 'crypto'; 3 | import { beforeEach, describe, it } from 'mocha'; 4 | import { ECPairFactory, networks as NETWORKS } from '..'; 5 | import type { ECPairInterface, TinySecp256k1Interface } from '..'; 6 | import fixtures from './fixtures/ecpair.json'; 7 | import * as tinysecp from 'tiny-secp256k1'; 8 | import * as tools from 'uint8array-tools'; 9 | 10 | const ECPair = ECPairFactory(tinysecp); 11 | 12 | const NETWORKS_LIST = Object.values(NETWORKS); 13 | const ZERO = Buffer.alloc(32, 0); 14 | const ONE = Buffer.from( 15 | '0000000000000000000000000000000000000000000000000000000000000001', 16 | 'hex', 17 | ); 18 | const GROUP_ORDER = Buffer.from( 19 | 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141', 20 | 'hex', 21 | ); 22 | const GROUP_ORDER_LESS_1 = Buffer.from( 23 | 'fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140', 24 | 'hex', 25 | ); 26 | 27 | function sha256(buffer: Buffer): Buffer { 28 | return createHash('sha256').update(buffer).digest(); 29 | } 30 | 31 | function tapTweakHash(pubKey: Buffer, h?: Buffer): Buffer { 32 | const data = Buffer.concat(h ? [pubKey, h] : [pubKey]); 33 | const tagHash = sha256(Buffer.from('TapTweak')); 34 | const tag = Buffer.concat([tagHash, tagHash]); 35 | return sha256(Buffer.concat([tag, data])); 36 | } 37 | 38 | describe('ECPair', () => { 39 | describe('getPublicKey', () => { 40 | let keyPair: ECPairInterface; 41 | 42 | beforeEach(() => { 43 | keyPair = ECPair.fromPrivateKey(ONE); 44 | }); 45 | 46 | it('calls pointFromScalar lazily', () => { 47 | assert.strictEqual((keyPair as any).__Q, undefined); 48 | 49 | // .publicKey forces the memoization 50 | assert.strictEqual( 51 | tools.toHex(keyPair.publicKey), 52 | '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 53 | ); 54 | assert.strictEqual( 55 | tools.toHex((keyPair as any).__Q), 56 | '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 57 | ); 58 | }); 59 | }); 60 | 61 | describe('fromPrivateKey', () => { 62 | it('defaults to compressed', () => { 63 | const keyPair = ECPair.fromPrivateKey(ONE); 64 | 65 | assert.strictEqual(keyPair.compressed, true); 66 | }); 67 | 68 | it('supports the uncompressed option', () => { 69 | const keyPair = ECPair.fromPrivateKey(ONE, { 70 | compressed: false, 71 | }); 72 | 73 | assert.strictEqual(keyPair.compressed, false); 74 | }); 75 | 76 | it('supports the network option', () => { 77 | const keyPair = ECPair.fromPrivateKey(ONE, { 78 | compressed: false, 79 | network: NETWORKS.testnet, 80 | }); 81 | 82 | assert.strictEqual(keyPair.network, NETWORKS.testnet); 83 | }); 84 | 85 | fixtures.valid.forEach((f) => { 86 | it('derives public key for ' + f.WIF, () => { 87 | const d = Buffer.from(f.d, 'hex'); 88 | const keyPair = ECPair.fromPrivateKey(d, { 89 | compressed: f.compressed, 90 | }); 91 | 92 | assert.strictEqual(tools.toHex(keyPair.publicKey), f.Q); 93 | }); 94 | }); 95 | 96 | fixtures.invalid.fromPrivateKey.forEach((f) => { 97 | it('throws ' + f.exception, () => { 98 | const d = Buffer.from(f.d, 'hex'); 99 | assert.throws(() => { 100 | ECPair.fromPrivateKey(d, (f as any).options); 101 | }, new RegExp(f.exception)); 102 | }); 103 | }); 104 | }); 105 | 106 | describe('fromPublicKey', () => { 107 | fixtures.invalid.fromPublicKey.forEach((f) => { 108 | it('throws ' + f.exception, () => { 109 | const Q = Buffer.from(f.Q, 'hex'); 110 | assert.throws(() => { 111 | ECPair.fromPublicKey(Q, (f as any).options); 112 | }, new RegExp(f.exception)); 113 | }); 114 | }); 115 | }); 116 | 117 | describe('fromWIF', () => { 118 | fixtures.valid.forEach((f) => { 119 | it('imports ' + f.WIF + ' (' + f.network + ')', () => { 120 | const network = (NETWORKS as any)[f.network]; 121 | const keyPair = ECPair.fromWIF(f.WIF, network); 122 | 123 | assert.strictEqual(tools.toHex(keyPair.privateKey!), f.d); 124 | assert.strictEqual(keyPair.compressed, f.compressed); 125 | assert.strictEqual(keyPair.network, network); 126 | }); 127 | }); 128 | 129 | fixtures.valid.forEach((f) => { 130 | it('imports ' + f.WIF + ' (via list of networks)', () => { 131 | const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST); 132 | 133 | assert.strictEqual(tools.toHex(keyPair.privateKey!), f.d); 134 | assert.strictEqual(keyPair.compressed, f.compressed); 135 | assert.strictEqual(keyPair.network, (NETWORKS as any)[f.network]); 136 | }); 137 | }); 138 | 139 | fixtures.invalid.fromWIF.forEach((f) => { 140 | it('throws on ' + f.WIF, () => { 141 | assert.throws(() => { 142 | const networks = f.network 143 | ? (NETWORKS as any)[f.network] 144 | : NETWORKS_LIST; 145 | 146 | ECPair.fromWIF(f.WIF, networks); 147 | }, new RegExp(f.exception)); 148 | }); 149 | }); 150 | }); 151 | 152 | describe('toWIF', () => { 153 | fixtures.valid.forEach((f) => { 154 | it('exports ' + f.WIF, () => { 155 | const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST); 156 | const result = keyPair.toWIF(); 157 | assert.strictEqual(result, f.WIF); 158 | }); 159 | }); 160 | it('throws if no private key is found', () => { 161 | assert.throws(() => { 162 | const keyPair = ECPair.makeRandom(); 163 | delete (keyPair as any).__D; 164 | keyPair.toWIF(); 165 | }, /Missing private key/); 166 | }); 167 | it('throws if from public key only', () => { 168 | assert.throws(() => { 169 | const publicKey = Buffer.from( 170 | '0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798', 171 | 'hex', 172 | ); 173 | const keyPair = ECPair.fromPublicKey(publicKey); 174 | keyPair.toWIF(); 175 | }, /Missing private key/); 176 | }); 177 | }); 178 | 179 | describe('makeRandom', () => { 180 | const d = Buffer.alloc(32, 4); 181 | const exWIF = 'KwMWvwRJeFqxYyhZgNwYuYjbQENDAPAudQx5VEmKJrUZcq6aL2pv'; 182 | 183 | describe('uses crypto.getRandomBytes as RNG', () => { 184 | it('generates a ECPair', () => { 185 | const originalFn = crypto.getRandomValues; 186 | // @ts-ignore 187 | crypto.getRandomValues = (): Buffer => { 188 | return d; 189 | }; 190 | 191 | const keyPair = ECPair.makeRandom(); 192 | assert.strictEqual(keyPair.toWIF(), exWIF); 193 | crypto.getRandomValues = originalFn; 194 | }); 195 | }); 196 | 197 | it('allows a custom RNG to be used', () => { 198 | const keyPair = ECPair.makeRandom({ 199 | rng: (size?: number): Uint8Array => { 200 | return d.slice(0, size); 201 | }, 202 | }); 203 | 204 | assert.strictEqual(keyPair.toWIF(), exWIF); 205 | }); 206 | 207 | it('retains the same defaults as ECPair constructor', () => { 208 | const keyPair = ECPair.makeRandom(); 209 | 210 | assert.strictEqual(keyPair.compressed, true); 211 | assert.strictEqual(keyPair.network, NETWORKS.bitcoin); 212 | }); 213 | 214 | it('supports the options parameter', () => { 215 | const keyPair = ECPair.makeRandom({ 216 | compressed: false, 217 | network: NETWORKS.testnet, 218 | }); 219 | 220 | assert.strictEqual(keyPair.compressed, false); 221 | assert.strictEqual(keyPair.network, NETWORKS.testnet); 222 | }); 223 | 224 | it('throws if d is bad length', () => { 225 | function rng(): Buffer { 226 | return Buffer.alloc(28); 227 | } 228 | 229 | assert.throws(() => { 230 | ECPair.makeRandom({ rng }); 231 | }, /ValiError: Invalid length: Expected 32 but received 28/); 232 | }); 233 | 234 | it('loops until d is within interval [1, n) : 1', () => { 235 | let counter = 0; 236 | const rng = () => { 237 | if (counter++ === 0) return ZERO; 238 | return ONE; 239 | }; 240 | 241 | const keyPair = ECPair.makeRandom({ rng }); 242 | assert.strictEqual(keyPair.privateKey!, ONE); 243 | }); 244 | 245 | it('loops until d is within interval [1, n) : n - 1', () => { 246 | let counter = 0; 247 | const rng = () => { 248 | if (counter++ === 0) return ZERO; // <1 249 | if (counter++ === 1) return GROUP_ORDER; // >n-1 250 | return GROUP_ORDER_LESS_1; // n-1 251 | }; 252 | 253 | const keyPair = ECPair.makeRandom({ rng }); 254 | 255 | assert.strictEqual(keyPair.privateKey!, GROUP_ORDER_LESS_1); 256 | }); 257 | }); 258 | 259 | describe('tweak', () => { 260 | fixtures.valid.forEach((f) => { 261 | it('tweaks private and public key for ' + f.WIF, () => { 262 | const network = (NETWORKS as any)[f.network]; 263 | const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST); 264 | const hash = tapTweakHash(Buffer.from(keyPair.publicKey.slice(1, 33))); 265 | 266 | const tweakedKeyPair = keyPair.tweak(hash); 267 | assert.strictEqual(tweakedKeyPair.toWIF(), f.tweak); 268 | 269 | const Q = Buffer.from(f.Q, 'hex'); 270 | const pubOnlyKeyPair = ECPair.fromPublicKey(Q, { 271 | network, 272 | compressed: f.compressed, 273 | }); 274 | const tweakedPubOnlyKeyPair = pubOnlyKeyPair.tweak(hash); 275 | 276 | assert.deepStrictEqual( 277 | tweakedKeyPair.publicKey, 278 | tweakedPubOnlyKeyPair.publicKey, 279 | ); 280 | }); 281 | }); 282 | }); 283 | 284 | describe('.network', () => { 285 | fixtures.valid.forEach((f) => { 286 | it('returns ' + f.network + ' for ' + f.WIF, () => { 287 | const network = (NETWORKS as any)[f.network]; 288 | const keyPair = ECPair.fromWIF(f.WIF, NETWORKS_LIST); 289 | 290 | assert.strictEqual(keyPair.network, network); 291 | }); 292 | }); 293 | }); 294 | 295 | describe('tinysecp wrappers', () => { 296 | let keyPair: ECPairInterface; 297 | let hash: Buffer; 298 | let signature: Buffer; 299 | 300 | beforeEach(() => { 301 | hash = ZERO; 302 | signature = Buffer.alloc(64, 1); 303 | const mockSign = (h: any, d: any) => { 304 | if (h === hash) { 305 | assert.strictEqual(h, hash); 306 | return signature; 307 | } 308 | return tinysecp.sign(h, d); 309 | }; 310 | 311 | const mockSignSchnorr = (h: any, d: any, e: any) => { 312 | if (h === hash) { 313 | assert.strictEqual(h, hash); 314 | return signature; 315 | } 316 | return tinysecp.signSchnorr(h, d, e); 317 | }; 318 | 319 | const mockVerify = (h: any, Q: any, sig: any) => { 320 | if (h === hash && sig === signature) { 321 | assert.strictEqual(h, hash); 322 | return true; 323 | } 324 | return tinysecp.verify(h, Q, sig); 325 | }; 326 | 327 | const mockVerifySchnorr = (h: any, Q: any, sig: any) => { 328 | if (h === hash && sig === signature) { 329 | assert.strictEqual(h, hash); 330 | return true; 331 | } 332 | return tinysecp.verifySchnorr(h, Q, sig); 333 | }; 334 | 335 | // @ts-ignore 336 | keyPair = ECPairFactory({ 337 | ...tinysecp, 338 | sign: mockSign, 339 | signSchnorr: mockSignSchnorr, 340 | verify: mockVerify, 341 | verifySchnorr: mockVerifySchnorr, 342 | }).makeRandom(); 343 | }); 344 | 345 | describe('signing', () => { 346 | it('wraps tinysecp.sign', () => { 347 | assert.deepStrictEqual(keyPair.sign(hash), signature); 348 | }); 349 | 350 | it('throws if no private key is found', () => { 351 | delete (keyPair as any).__D; 352 | 353 | assert.throws(() => { 354 | keyPair.sign(hash); 355 | }, /Missing private key/); 356 | }); 357 | }); 358 | 359 | describe('schnorr signing', () => { 360 | it('creates signature', () => { 361 | const kP = ECPair.fromPrivateKey(ONE, { 362 | compressed: false, 363 | }); 364 | const h = Buffer.alloc(32, 2); 365 | const schnorrsig = Buffer.from( 366 | 'cde43b67d4326fa6ff1b40711615b692a997e193cc512f3a40e5cd4a5c9be18ca871296fa967f4dc13634c70d965223d637546a0b519050bae82c76d3ae627ff', 367 | 'hex', 368 | ); 369 | 370 | assert.deepStrictEqual( 371 | tools.toHex(kP.signSchnorr(h)), 372 | schnorrsig.toString('hex'), 373 | ); 374 | }); 375 | 376 | it('wraps tinysecp.signSchnorr', () => { 377 | assert.deepStrictEqual(keyPair.signSchnorr(hash), signature); 378 | }); 379 | 380 | it('throws if no private key is found', () => { 381 | delete (keyPair as any).__D; 382 | 383 | assert.throws(() => { 384 | keyPair.signSchnorr(hash); 385 | }, /Missing private key/); 386 | }); 387 | 388 | it('throws if signSchnorr() not found', () => { 389 | assert.throws(() => { 390 | keyPair = ECPairFactory({ 391 | ...tinysecp, 392 | signSchnorr: null, 393 | } as unknown as TinySecp256k1Interface).makeRandom(); 394 | keyPair.signSchnorr(hash); 395 | }, /signSchnorr not supported by ecc library/); 396 | }); 397 | }); 398 | 399 | describe('verify', () => { 400 | it('wraps tinysecp.verify', () => { 401 | assert.strictEqual(keyPair.verify(hash, signature), true); 402 | }); 403 | }); 404 | 405 | describe('schnorr verify', () => { 406 | it('checks signature', () => { 407 | const kP = ECPair.fromPrivateKey(ONE, { 408 | compressed: false, 409 | }); 410 | const h = Buffer.alloc(32, 2); 411 | const schnorrsig = Buffer.from( 412 | '4bc68cbd7c0b769b2dff262e9971756da7ab78402ed6f710c3788ce815e9c06a011bab7a527e33c6a1df0dad5ed05a04b8f3be656d8578502fef07f8215d37db', 413 | 'hex', 414 | ); 415 | 416 | assert.strictEqual(kP.verifySchnorr(h, schnorrsig), true); 417 | }); 418 | 419 | it('wraps tinysecp.verifySchnorr', () => { 420 | assert.strictEqual(keyPair.verifySchnorr(hash, signature), true); 421 | }); 422 | 423 | it('throws if verifySchnorr() not found', () => { 424 | assert.throws(() => { 425 | keyPair = ECPairFactory({ 426 | ...tinysecp, 427 | verifySchnorr: null, 428 | } as unknown as TinySecp256k1Interface).makeRandom(); 429 | keyPair.verifySchnorr(hash, signature); 430 | }, /verifySchnorr not supported by ecc library/); 431 | }); 432 | }); 433 | }); 434 | 435 | describe('optional low R signing', () => { 436 | const sig = Buffer.from( 437 | '95a6619140fca3366f1d3b013b0367c4f86e39508a50fdce' + 438 | 'e5245fbb8bd60aa6086449e28cf15387cf9f85100bfd0838624ca96759e59f65c10a00' + 439 | '16b86f5229', 440 | 'hex', 441 | ); 442 | const sigLowR = Buffer.from( 443 | '6a2660c226e8055afad317eeba918a304be79208d505' + 444 | '3bc5ea4a5e4c5892b4a061c717c5284ae5202d721c0e49b4717b79966280906b1d3b52' + 445 | '95d1fdde963c35', 446 | 'hex', 447 | ); 448 | const lowRKeyPair = ECPair.fromWIF( 449 | 'L3nThUzbAwpUiBAjR5zCu66ybXSPMr2zZ3ikp' + 'ScpTPiYTxBynfZu', 450 | ); 451 | const dataToSign = Buffer.from( 452 | 'b6c5c548a7f6164c8aa7af5350901626ebd69f9ae' + '2c1ecf8871f5088ec204cfe', 453 | 'hex', 454 | ); 455 | 456 | it('signs with normal R by default', () => { 457 | const signed = lowRKeyPair.sign(dataToSign); 458 | assert.deepStrictEqual(sig, Buffer.from(signed)); 459 | }); 460 | 461 | it('signs with low R when true is passed', () => { 462 | const signed = lowRKeyPair.sign(dataToSign, true); 463 | assert.deepStrictEqual(sigLowR, Buffer.from(signed)); 464 | }); 465 | }); 466 | }); 467 | -------------------------------------------------------------------------------- /test/fixtures/ecpair.json: -------------------------------------------------------------------------------- 1 | { 2 | "valid": [ 3 | { 4 | "d": "0000000000000000000000000000000000000000000000000000000000000001", 5 | "Q": "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 6 | "compressed": true, 7 | "network": "bitcoin", 8 | "address": "1BgGZ9tcN4rm9KBzDn7KprQz87SZ26SAMH", 9 | "WIF": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sVHnoWn", 10 | "tweak": "KyGComs4RrHnqnn5ku3WxA6CVFmHJV61bm8V36Uu4WMsRjjdeAVr" 11 | }, 12 | { 13 | "d": "0000000000000000000000000000000000000000000000000000000000000001", 14 | "Q": "0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8", 15 | "compressed": false, 16 | "network": "bitcoin", 17 | "address": "1EHNa6Q4Jz2uvNExL497mE43ikXhwF6kZm", 18 | "WIF": "5HpHagT65TZzG1PH3CSu63k8DbpvD8s5ip4nEB3kEsreAnchuDf", 19 | "tweak": "5JH8fEnnBcdtAhH74buE8WhbmvBwSiFjH2qpb1LTkPWehzrbBaF" 20 | }, 21 | { 22 | "d": "2bfe58ab6d9fd575bdc3a624e4825dd2b375d64ac033fbc46ea79dbab4f69a3e", 23 | "Q": "02b80011a883a0fd621ad46dfc405df1e74bf075cbaf700fd4aebef6e96f848340", 24 | "compressed": true, 25 | "network": "bitcoin", 26 | "address": "1MasfEKgSiaSeri2C6kgznaqBNtyrZPhNq", 27 | "WIF": "KxhEDBQyyEFymvfJD96q8stMbJMbZUb6D1PmXqBWZDU2WvbvVs9o", 28 | "tweak": "KwUyUow4TNzozBuaxR5VAQRw99PFQqYZXFn5ZN7Cm2FPeRvXwoAD" 29 | }, 30 | { 31 | "d": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b", 32 | "Q": "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34", 33 | "compressed": true, 34 | "network": "bitcoin", 35 | "address": "1LwwMWdSEMHJ2dMhSvAHZ3g95tG2UBv9jg", 36 | "WIF": "KzrA86mCVMGWnLGBQu9yzQa32qbxb5dvSK4XhyjjGAWSBKYX4rHx", 37 | "tweak": "L4LVynF3Ra6tpU14rMjx2bjNTbKpathPA1KcKVch8UpuGJgHakpw" 38 | }, 39 | { 40 | "d": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b", 41 | "Q": "044289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34cec320a0565fb7caf11b1ca2f445f9b7b012dda5718b3cface369ee3a034ded6", 42 | "compressed": false, 43 | "network": "bitcoin", 44 | "address": "1zXcfvKCLgsFdJDYPuqpu1sF3q92tnnUM", 45 | "WIF": "5JdxzLtFPHNe7CAL8EBC6krdFv9pwPoRo4e3syMZEQT9srmK8hh", 46 | "tweak": "5KRotqK8oMBrMGdievBdwHUj23Lfsj5AYwuFM3rmtYE7rmwTEsf" 47 | }, 48 | { 49 | "d": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b", 50 | "Q": "024289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34", 51 | "compressed": true, 52 | "network": "testnet", 53 | "address": "n1TteZiR3NiYojqKAV8fNxtTwsrjM7kVdj", 54 | "WIF": "cRD9b1m3vQxmwmjSoJy7Mj56f4uNFXjcWMCzpQCEmHASS4edEwXv", 55 | "tweak": "cUhVShEtrdo9yuULEmZ5PvES5pdEFLo5E3U5Rv5CdbUuX3pgcvk2" 56 | }, 57 | { 58 | "d": "6c4313b03f2e7324d75e642f0ab81b734b724e13fec930f309e222470236d66b", 59 | "Q": "044289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34cec320a0565fb7caf11b1ca2f445f9b7b012dda5718b3cface369ee3a034ded6", 60 | "compressed": false, 61 | "network": "testnet", 62 | "address": "mgWUuj1J1N882jmqFxtDepEC73Rr22E9GU", 63 | "WIF": "92Qba5hnyWSn5Ffcka56yMQauaWY6ZLd91Vzxbi4a9CCetaHtYj", 64 | "tweak": "93CSUa8gPaFzKL91HG5Yot2gfhhP2tcMttmCRgDHEGyAdoiN1CE" 65 | }, 66 | { 67 | "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140", 68 | "Q": "0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798", 69 | "compressed": true, 70 | "network": "bitcoin", 71 | "address": "1GrLCmVQXoyJXaPJQdqssNqwxvha1eUo2E", 72 | "WIF": "L5oLkpV3aqBjhki6LmvChTCV6odsp4SXM6FfU2Gppt5kFLaHLuZ9", 73 | "tweak": "KyGComs4RrHnqnn5ku3WxA6CVFmHJV61bm8V36Uu4WMsRjjdeAVr" 74 | } 75 | ], 76 | "invalid": { 77 | "fromPrivateKey": [ 78 | { 79 | "exception": "Private key not in range \\[1, n\\)", 80 | "d": "0000000000000000000000000000000000000000000000000000000000000000" 81 | }, 82 | { 83 | "exception": "Private key not in range \\[1, n\\)", 84 | "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141" 85 | }, 86 | { 87 | "exception": "Private key not in range \\[1, n\\)", 88 | "d": "fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142" 89 | }, 90 | { 91 | "exception": "ValiError: Invalid type: Expected boolean but received 2", 92 | "d": "0000000000000000000000000000000000000000000000000000000000000001", 93 | "options": { 94 | "compressed": 2 95 | } 96 | }, 97 | { 98 | "exception": "ValiError: Invalid type: Expected string | Uint8Array but received undefined", 99 | "d": "0000000000000000000000000000000000000000000000000000000000000001", 100 | "options": { 101 | "network": {} 102 | } 103 | } 104 | ], 105 | "fromPublicKey": [ 106 | { 107 | "exception": "Error: Point not on the curve", 108 | "Q": "", 109 | "options": {} 110 | }, 111 | { 112 | "exception": "ValiError: Invalid type: Expected string | Uint8Array but received undefined", 113 | "Q": "044289801366bcee6172b771cf5a7f13aaecd237a0b9a1ff9d769cabc2e6b70a34cec320a0565fb7caf11b1ca2f445f9b7b012dda5718b3cface369ee3a034ded6", 114 | "options": { 115 | "network": {} 116 | } 117 | }, 118 | { 119 | "description": "Bad X coordinate (== P)", 120 | "exception": "Error: Point not on the curve", 121 | "Q": "040000000000000000000000000000000000000000000000000000000000000001fffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f", 122 | "options": {} 123 | } 124 | ], 125 | "fromWIF": [ 126 | { 127 | "exception": "Invalid network version", 128 | "network": "bitcoin", 129 | "WIF": "92Qba5hnyWSn5Ffcka56yMQauaWY6ZLd91Vzxbi4a9CCetaHtYj" 130 | }, 131 | { 132 | "exception": "Unknown network version", 133 | "WIF": "brQnSed3Fia1w9VcbbS6ZGDgJ6ENkgwuQY2LS7pEC5bKHD1fMF" 134 | }, 135 | { 136 | "exception": "Invalid compression flag", 137 | "WIF": "KwDiBf89QgGbjEhKnhXJuH7LrciVrZi3qYjgd9M7rFU73sfZr2ym" 138 | }, 139 | { 140 | "exception": "Invalid WIF length", 141 | "WIF": "3tq8Vmhh9SN5XhjTGSWgx8iKk59XbKG6UH4oqpejRuJhfYD" 142 | }, 143 | { 144 | "exception": "Invalid WIF length", 145 | "WIF": "38uMpGARR2BJy5p4dNFKYg9UsWNoBtkpbdrXDjmfvz8krCtw3T1W92ZDSR" 146 | } 147 | ] 148 | } 149 | } 150 | -------------------------------------------------------------------------------- /test/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "module": "NodeNext", 5 | "rootDir": "./", 6 | "moduleResolution": "NodeNext", 7 | "baseUrl": "./", 8 | "resolveJsonModule": true, 9 | "esModuleInterop": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "strict": true, 12 | "skipLibCheck": true 13 | }, 14 | "include": ["**/*.spec.ts"] 15 | } 16 | -------------------------------------------------------------------------------- /ts_src/ecpair.ts: -------------------------------------------------------------------------------- 1 | import { Network } from './networks'; 2 | import * as networks from './networks'; 3 | import * as types from './types'; 4 | import * as wif from 'wif'; 5 | import { testEcc } from './testecc'; 6 | export { networks }; 7 | import * as v from 'valibot'; 8 | import * as tools from 'uint8array-tools'; 9 | 10 | const ECPairOptionsSchema = v.optional( 11 | v.object({ 12 | compressed: v.optional(v.boolean()), 13 | network: v.optional(types.NetworkSchema), 14 | // https://github.com/fabian-hiller/valibot/issues/243#issuecomment-2182514063 15 | rng: v.optional( 16 | v.pipe( 17 | v.instance(Function), 18 | v.transform((func) => { 19 | return (arg?: number) => { 20 | const parsedArg = v.parse(v.optional(v.number()), arg); 21 | const returnedValue = func(parsedArg); 22 | const parsedReturn = v.parse(v.instance(Uint8Array), returnedValue); 23 | return parsedReturn; 24 | }; 25 | }), 26 | ), 27 | ), 28 | }), 29 | ); 30 | 31 | type ECPairOptions = v.InferOutput; 32 | 33 | const toXOnly = (pubKey: Uint8Array) => 34 | pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33); 35 | 36 | export interface Signer { 37 | publicKey: Uint8Array; 38 | network?: any; 39 | sign(hash: Uint8Array, lowR?: boolean): Uint8Array; 40 | } 41 | 42 | export interface SignerAsync { 43 | publicKey: Uint8Array; 44 | network?: any; 45 | sign(hash: Uint8Array, lowR?: boolean): Promise; 46 | } 47 | 48 | export interface ECPairInterface extends Signer { 49 | compressed: boolean; 50 | network: Network; 51 | lowR: boolean; 52 | privateKey?: Uint8Array; 53 | toWIF(): string; 54 | tweak(t: Uint8Array): ECPairInterface; 55 | verify(hash: Uint8Array, signature: Uint8Array): boolean; 56 | verifySchnorr(hash: Uint8Array, signature: Uint8Array): boolean; 57 | signSchnorr(hash: Uint8Array): Uint8Array; 58 | } 59 | 60 | export interface ECPairAPI { 61 | isPoint(maybePoint: any): boolean; 62 | fromPrivateKey(buffer: Uint8Array, options?: ECPairOptions): ECPairInterface; 63 | fromPublicKey(buffer: Uint8Array, options?: ECPairOptions): ECPairInterface; 64 | fromWIF(wifString: string, network?: Network | Network[]): ECPairInterface; 65 | makeRandom(options?: ECPairOptions): ECPairInterface; 66 | } 67 | 68 | export interface TinySecp256k1Interface { 69 | isPoint(p: Uint8Array): boolean; 70 | pointCompress(p: Uint8Array, compressed?: boolean): Uint8Array; 71 | isPrivate(d: Uint8Array): boolean; 72 | pointFromScalar(d: Uint8Array, compressed?: boolean): Uint8Array | null; 73 | xOnlyPointAddTweak( 74 | p: Uint8Array, 75 | tweak: Uint8Array, 76 | ): XOnlyPointAddTweakResult | null; 77 | 78 | privateAdd(d: Uint8Array, tweak: Uint8Array): Uint8Array | null; 79 | privateNegate(d: Uint8Array): Uint8Array; 80 | 81 | sign(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array; 82 | signSchnorr?(h: Uint8Array, d: Uint8Array, e?: Uint8Array): Uint8Array; 83 | 84 | verify( 85 | h: Uint8Array, 86 | Q: Uint8Array, 87 | signature: Uint8Array, 88 | strict?: boolean, 89 | ): boolean; 90 | verifySchnorr?(h: Uint8Array, Q: Uint8Array, signature: Uint8Array): boolean; 91 | } 92 | 93 | interface XOnlyPointAddTweakResult { 94 | parity: 1 | 0; 95 | xOnlyPubkey: Uint8Array; 96 | } 97 | 98 | export function ECPairFactory(ecc: TinySecp256k1Interface): ECPairAPI { 99 | testEcc(ecc); 100 | function isPoint(maybePoint: any): boolean { 101 | return ecc.isPoint(maybePoint); 102 | } 103 | 104 | function fromPrivateKey( 105 | buffer: Uint8Array, 106 | options?: ECPairOptions, 107 | ): ECPairInterface { 108 | v.parse(types.Buffer256Bit, buffer); 109 | if (!ecc.isPrivate(buffer)) 110 | throw new TypeError('Private key not in range [1, n)'); 111 | v.parse(ECPairOptionsSchema, options); 112 | 113 | return new ECPair(buffer, undefined, options); 114 | } 115 | 116 | function fromPublicKey( 117 | buffer: Uint8Array, 118 | options?: ECPairOptions, 119 | ): ECPairInterface { 120 | if (!ecc.isPoint(buffer)) { 121 | throw new Error('Point not on the curve'); 122 | } 123 | v.parse(ECPairOptionsSchema, options); 124 | return new ECPair(undefined, buffer, options); 125 | } 126 | 127 | function fromWIF( 128 | wifString: string, 129 | network?: Network | Network[], 130 | ): ECPairInterface { 131 | const decoded = wif.decode(wifString); 132 | const version = decoded.version; 133 | 134 | // list of networks? 135 | if (Array.isArray(network)) { 136 | network = network 137 | .filter((x: Network) => { 138 | return version === x.wif; 139 | }) 140 | .pop() as Network; 141 | 142 | if (!network) throw new Error('Unknown network version'); 143 | 144 | // otherwise, assume a network object (or default to bitcoin) 145 | } else { 146 | network = network || networks.bitcoin; 147 | 148 | if (version !== (network as Network).wif) 149 | throw new Error('Invalid network version'); 150 | } 151 | 152 | return fromPrivateKey(decoded.privateKey, { 153 | compressed: decoded.compressed, 154 | network: network as Network, 155 | }); 156 | } 157 | 158 | /** 159 | * Generates a random ECPairInterface. 160 | * 161 | * Uses `crypto.getRandomValues` under the hood for options.rng function, which is still an experimental feature as of Node.js 18.19.0. To work around this you can do one of the following: 162 | * 1. Use a polyfill for crypto.getRandomValues() 163 | * 2. Use the `--experimental-global-webcrypto` flag when running node.js. 164 | * 3. Pass in a custom rng function to generate random values. 165 | * 166 | * @param {ECPairOptions} options - Options for the ECPairInterface. 167 | * @return {ECPairInterface} A random ECPairInterface. 168 | */ 169 | function makeRandom(options?: ECPairOptions): ECPairInterface { 170 | v.parse(ECPairOptionsSchema, options); 171 | if (options === undefined) options = {}; 172 | const rng = 173 | options.rng || 174 | ((size: any) => crypto.getRandomValues(new Uint8Array(size))); 175 | 176 | let d; 177 | do { 178 | d = rng(32); 179 | v.parse(types.Buffer256Bit, d); 180 | } while (!ecc.isPrivate(d)); 181 | 182 | return fromPrivateKey(d, options); 183 | } 184 | 185 | class ECPair implements ECPairInterface { 186 | compressed: boolean; 187 | network: Network; 188 | lowR: boolean; 189 | 190 | constructor( 191 | private __D?: Uint8Array, 192 | private __Q?: Uint8Array, 193 | options?: ECPairOptions, 194 | ) { 195 | this.lowR = false; 196 | if (options === undefined) options = {}; 197 | this.compressed = 198 | options.compressed === undefined ? true : options.compressed; 199 | this.network = options.network || networks.bitcoin; 200 | 201 | if (__Q !== undefined) this.__Q = ecc.pointCompress(__Q, this.compressed); 202 | } 203 | 204 | get privateKey(): Uint8Array | undefined { 205 | return this.__D; 206 | } 207 | 208 | get publicKey(): Uint8Array { 209 | if (!this.__Q) { 210 | // It is not possible for both `__Q` and `__D` to be `undefined` at the same time. 211 | // The factory methods guard for this. 212 | const p = ecc.pointFromScalar(this.__D!, this.compressed)!; 213 | // It is not possible for `p` to be null. 214 | // `fromPrivateKey()` checks that `__D` is a valid scalar. 215 | this.__Q = p; 216 | } 217 | 218 | return this.__Q; 219 | } 220 | 221 | toWIF(): string { 222 | if (!this.__D) throw new Error('Missing private key'); 223 | return wif.encode({ 224 | compressed: this.compressed, 225 | privateKey: this.__D, 226 | version: this.network.wif, 227 | }); 228 | } 229 | 230 | tweak(t: Uint8Array): ECPairInterface { 231 | if (this.privateKey) return this.tweakFromPrivateKey(t); 232 | return this.tweakFromPublicKey(t); 233 | } 234 | 235 | sign(hash: Uint8Array, lowR?: boolean): Uint8Array { 236 | if (!this.__D) throw new Error('Missing private key'); 237 | if (lowR === undefined) lowR = this.lowR; 238 | if (lowR === false) { 239 | return ecc.sign(hash, this.__D); 240 | } else { 241 | let sig = ecc.sign(hash, this.__D); 242 | const extraData = new Uint8Array(32); 243 | let counter = 0; 244 | // if first try is lowR, skip the loop 245 | // for second try and on, add extra entropy counting up 246 | while (sig[0] > 0x7f) { 247 | counter++; 248 | tools.writeUInt32(extraData, 0, counter, 'LE'); 249 | sig = ecc.sign(hash, this.__D, extraData); 250 | } 251 | return sig; 252 | } 253 | } 254 | 255 | signSchnorr(hash: Uint8Array): Uint8Array { 256 | if (!this.privateKey) throw new Error('Missing private key'); 257 | if (!ecc.signSchnorr) 258 | throw new Error('signSchnorr not supported by ecc library'); 259 | return ecc.signSchnorr(hash, this.privateKey); 260 | } 261 | 262 | verify(hash: Uint8Array, signature: Uint8Array): boolean { 263 | return ecc.verify(hash, this.publicKey, signature); 264 | } 265 | 266 | verifySchnorr(hash: Uint8Array, signature: Uint8Array): boolean { 267 | if (!ecc.verifySchnorr) 268 | throw new Error('verifySchnorr not supported by ecc library'); 269 | return ecc.verifySchnorr(hash, this.publicKey.subarray(1, 33), signature); 270 | } 271 | 272 | private tweakFromPublicKey(t: Uint8Array): ECPairInterface { 273 | const xOnlyPubKey = toXOnly(this.publicKey); 274 | const tweakedPublicKey = ecc.xOnlyPointAddTweak(xOnlyPubKey, t); 275 | if (!tweakedPublicKey || tweakedPublicKey.xOnlyPubkey === null) 276 | throw new Error('Cannot tweak public key!'); 277 | const parityByte = Uint8Array.from([ 278 | tweakedPublicKey.parity === 0 ? 0x02 : 0x03, 279 | ]); 280 | return fromPublicKey( 281 | tools.concat([parityByte, tweakedPublicKey.xOnlyPubkey]), 282 | { 283 | network: this.network, 284 | compressed: this.compressed, 285 | }, 286 | ); 287 | } 288 | 289 | private tweakFromPrivateKey(t: Uint8Array): ECPairInterface { 290 | const hasOddY = 291 | this.publicKey[0] === 3 || 292 | (this.publicKey[0] === 4 && (this.publicKey[64] & 1) === 1); 293 | const privateKey = hasOddY 294 | ? ecc.privateNegate(this.privateKey!) 295 | : this.privateKey; 296 | 297 | const tweakedPrivateKey = ecc.privateAdd(privateKey!, t); 298 | if (!tweakedPrivateKey) throw new Error('Invalid tweaked private key!'); 299 | 300 | return fromPrivateKey(tweakedPrivateKey, { 301 | network: this.network, 302 | compressed: this.compressed, 303 | }); 304 | } 305 | } 306 | 307 | return { 308 | isPoint, 309 | fromPrivateKey, 310 | fromPublicKey, 311 | fromWIF, 312 | makeRandom, 313 | }; 314 | } 315 | -------------------------------------------------------------------------------- /ts_src/index.ts: -------------------------------------------------------------------------------- 1 | export { 2 | ECPairFactory as default, 3 | ECPairFactory, 4 | type Signer, 5 | type SignerAsync, 6 | type ECPairAPI, 7 | type ECPairInterface, 8 | type TinySecp256k1Interface, 9 | networks, 10 | } from './ecpair'; 11 | -------------------------------------------------------------------------------- /ts_src/networks.ts: -------------------------------------------------------------------------------- 1 | // https://en.bitcoin.it/wiki/List_of_address_prefixes 2 | import * as v from 'valibot'; 3 | import { NetworkSchema } from './types'; 4 | 5 | export type Network = v.InferOutput; 6 | 7 | export const bitcoin: Network = { 8 | messagePrefix: '\x18Bitcoin Signed Message:\n', 9 | bech32: 'bc', 10 | bip32: { 11 | public: 0x0488b21e, 12 | private: 0x0488ade4, 13 | }, 14 | pubKeyHash: 0x00, 15 | scriptHash: 0x05, 16 | wif: 0x80, 17 | }; 18 | 19 | export const testnet: Network = { 20 | messagePrefix: '\x18Bitcoin Signed Message:\n', 21 | bech32: 'tb', 22 | bip32: { 23 | public: 0x043587cf, 24 | private: 0x04358394, 25 | }, 26 | pubKeyHash: 0x6f, 27 | scriptHash: 0xc4, 28 | wif: 0xef, 29 | }; 30 | -------------------------------------------------------------------------------- /ts_src/testecc.ts: -------------------------------------------------------------------------------- 1 | import { TinySecp256k1Interface } from './ecpair'; 2 | 3 | const h = (hex: string): Buffer => Buffer.from(hex, 'hex'); 4 | 5 | export function testEcc(ecc: TinySecp256k1Interface): void { 6 | assert( 7 | ecc.isPoint( 8 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 9 | ), 10 | ); 11 | assert( 12 | !ecc.isPoint( 13 | h('030000000000000000000000000000000000000000000000000000000000000005'), 14 | ), 15 | ); 16 | assert( 17 | ecc.isPrivate( 18 | h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 19 | ), 20 | ); 21 | // order - 1 22 | assert( 23 | ecc.isPrivate( 24 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 25 | ), 26 | ); 27 | // 0 28 | assert( 29 | !ecc.isPrivate( 30 | h('0000000000000000000000000000000000000000000000000000000000000000'), 31 | ), 32 | ); 33 | // order 34 | assert( 35 | !ecc.isPrivate( 36 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141'), 37 | ), 38 | ); 39 | // order + 1 40 | assert( 41 | !ecc.isPrivate( 42 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364142'), 43 | ), 44 | ); 45 | // 1 + 0 == 1 46 | assert( 47 | Buffer.from( 48 | ecc.privateAdd( 49 | h('0000000000000000000000000000000000000000000000000000000000000001'), 50 | h('0000000000000000000000000000000000000000000000000000000000000000'), 51 | )!, 52 | ).equals( 53 | h('0000000000000000000000000000000000000000000000000000000000000001'), 54 | ), 55 | ); 56 | // -3 + 3 == 0 57 | assert( 58 | ecc.privateAdd( 59 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e'), 60 | h('0000000000000000000000000000000000000000000000000000000000000003'), 61 | ) === null, 62 | ); 63 | assert( 64 | Buffer.from( 65 | ecc.privateAdd( 66 | h('e211078564db65c3ce7704f08262b1f38f1ef412ad15b5ac2d76657a63b2c500'), 67 | h('b51fbb69051255d1becbd683de5848242a89c229348dd72896a87ada94ae8665'), 68 | )!, 69 | ).equals( 70 | h('9730c2ee69edbb958d42db7460bafa18fef9d955325aec99044c81c8282b0a24'), 71 | ), 72 | ); 73 | assert( 74 | Buffer.from( 75 | ecc.privateNegate( 76 | h('0000000000000000000000000000000000000000000000000000000000000001'), 77 | ), 78 | ).equals( 79 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 80 | ), 81 | ); 82 | assert( 83 | Buffer.from( 84 | ecc.privateNegate( 85 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd036413e'), 86 | ), 87 | ).equals( 88 | h('0000000000000000000000000000000000000000000000000000000000000003'), 89 | ), 90 | ); 91 | assert( 92 | Buffer.from( 93 | ecc.privateNegate( 94 | h('b1121e4088a66a28f5b6b0f5844943ecd9f610196d7bb83b25214b60452c09af'), 95 | ), 96 | ).equals( 97 | h('4eede1bf775995d70a494f0a7bb6bc11e0b8cccd41cce8009ab1132c8b0a3792'), 98 | ), 99 | ); 100 | assert( 101 | Buffer.from( 102 | ecc.pointCompress( 103 | h( 104 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 105 | ), 106 | true, 107 | )!, 108 | ).equals( 109 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 110 | ), 111 | ); 112 | assert( 113 | Buffer.from( 114 | ecc.pointCompress( 115 | h( 116 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 117 | ), 118 | false, 119 | )!, 120 | ).equals( 121 | h( 122 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 123 | ), 124 | ), 125 | ); 126 | assert( 127 | Buffer.from( 128 | ecc.pointCompress( 129 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 130 | true, 131 | )!, 132 | ).equals( 133 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 134 | ), 135 | ); 136 | assert( 137 | Buffer.from( 138 | ecc.pointCompress( 139 | h('0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 140 | false, 141 | )!, 142 | ).equals( 143 | h( 144 | '0479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8', 145 | ), 146 | ), 147 | ); 148 | assert( 149 | Buffer.from( 150 | ecc.pointFromScalar( 151 | h('b1121e4088a66a28f5b6b0f5844943ecd9f610196d7bb83b25214b60452c09af'), 152 | )!, 153 | ).equals( 154 | h('02b07ba9dca9523b7ef4bd97703d43d20399eb698e194704791a25ce77a400df99'), 155 | ), 156 | ); 157 | 158 | assert( 159 | ecc.xOnlyPointAddTweak( 160 | h('79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 161 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 162 | ) === null, 163 | ); 164 | 165 | let xOnlyRes = ecc.xOnlyPointAddTweak( 166 | h('1617d38ed8d8657da4d4761e8057bc396ea9e4b9d29776d4be096016dbd2509b'), 167 | h('a8397a935f0dfceba6ba9618f6451ef4d80637abf4e6af2669fbc9de6a8fd2ac'), 168 | ); 169 | assert( 170 | Buffer.from(xOnlyRes!.xOnlyPubkey).equals( 171 | h('e478f99dab91052ab39a33ea35fd5e6e4933f4d28023cd597c9a1f6760346adf'), 172 | ) && xOnlyRes!.parity === 1, 173 | ); 174 | 175 | xOnlyRes = ecc.xOnlyPointAddTweak( 176 | h('2c0b7cf95324a07d05398b240174dc0c2be444d96b159aa6c7f7b1e668680991'), 177 | h('823c3cd2142744b075a87eade7e1b8678ba308d566226a0056ca2b7a76f86b47'), 178 | ); 179 | assert( 180 | Buffer.from(xOnlyRes!.xOnlyPubkey).equals( 181 | h('9534f8dc8c6deda2dc007655981c78b49c5d96c778fbf363462a11ec9dfd948c'), 182 | ) && xOnlyRes!.parity === 0, 183 | ); 184 | 185 | assert( 186 | Buffer.from( 187 | ecc.sign( 188 | h('5e9f0a0d593efdcf78ac923bc3313e4e7d408d574354ee2b3288c0da9fbba6ed'), 189 | h('fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364140'), 190 | )!, 191 | ).equals( 192 | h( 193 | '54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5', 194 | ), 195 | ), 196 | ); 197 | assert( 198 | ecc.verify( 199 | h('5e9f0a0d593efdcf78ac923bc3313e4e7d408d574354ee2b3288c0da9fbba6ed'), 200 | h('0379be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798'), 201 | h( 202 | '54c4a33c6423d689378f160a7ff8b61330444abb58fb470f96ea16d99d4a2fed07082304410efa6b2943111b6a4e0aaa7b7db55a07e9861d1fb3cb1f421044a5', 203 | ), 204 | ), 205 | ); 206 | if (ecc.signSchnorr) { 207 | assert( 208 | Buffer.from( 209 | ecc.signSchnorr( 210 | h('7e2d58d8b3bcdf1abadec7829054f90dda9805aab56c77333024b9d0a508b75c'), 211 | h('c90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b14e5c9'), 212 | h('c87aa53824b4d7ae2eb035a2b5bbbccc080e76cdc6d1692c4b0b62d798e6d906'), 213 | )!, 214 | ).equals( 215 | h( 216 | '5831aaeed7b44bb74e5eab94ba9d4294c49bcf2a60728d8b4c200f50dd313c1bab745879a5ad954a72c45a91c3a51d3c7adea98d82f8481e0e1e03674a6f3fb7', 217 | ), 218 | ), 219 | ); 220 | } 221 | if (ecc.verifySchnorr) { 222 | assert( 223 | ecc.verifySchnorr( 224 | h('7e2d58d8b3bcdf1abadec7829054f90dda9805aab56c77333024b9d0a508b75c'), 225 | h('dd308afec5777e13121fa72b9cc1b7cc0139715309b086c960e18fd969774eb8'), 226 | h( 227 | '5831aaeed7b44bb74e5eab94ba9d4294c49bcf2a60728d8b4c200f50dd313c1bab745879a5ad954a72c45a91c3a51d3c7adea98d82f8481e0e1e03674a6f3fb7', 228 | ), 229 | ), 230 | ); 231 | } 232 | } 233 | 234 | function assert(bool: boolean): void { 235 | if (!bool) throw new Error('ecc library invalid'); 236 | } 237 | -------------------------------------------------------------------------------- /ts_src/types.ts: -------------------------------------------------------------------------------- 1 | import * as v from 'valibot'; 2 | 3 | const Uint32Schema = v.pipe( 4 | v.number(), 5 | v.integer(), 6 | v.minValue(0), 7 | v.maxValue(0xffffffff), 8 | ); 9 | 10 | const Uint8Schema = v.pipe( 11 | v.number(), 12 | v.integer(), 13 | v.minValue(0), 14 | v.maxValue(0xff), 15 | ); 16 | 17 | export const NetworkSchema = v.object({ 18 | messagePrefix: v.union([v.string(), v.instance(Uint8Array)]), 19 | bech32: v.string(), 20 | bip32: v.object({ 21 | public: Uint32Schema, 22 | private: Uint32Schema, 23 | }), 24 | pubKeyHash: Uint8Schema, 25 | scriptHash: Uint8Schema, 26 | wif: Uint8Schema, 27 | }); 28 | 29 | export const Buffer256Bit = v.pipe(v.instance(Uint8Array), v.length(32)); 30 | -------------------------------------------------------------------------------- /tsconfig.base.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNEXT", 4 | "module": "commonjs", 5 | "outDir": "./src", 6 | "rootDir": "./ts_src", 7 | "types": ["node"], 8 | "allowJs": false, 9 | "strict": true, 10 | "noImplicitAny": true, 11 | "strictNullChecks": true, 12 | "strictFunctionTypes": true, 13 | "strictBindCallApply": true, 14 | "strictPropertyInitialization": true, 15 | "noImplicitThis": true, 16 | "alwaysStrict": true, 17 | "noUnusedLocals": true, 18 | "noUnusedParameters": true, 19 | "skipLibCheck": true 20 | }, 21 | "include": ["ts_src/**/*.ts"], 22 | "exclude": ["**/*.spec.ts", "node_modules/**/*"] 23 | } 24 | -------------------------------------------------------------------------------- /tsconfig.cjs.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "declaration": true, 5 | "emitDeclarationOnly": false, 6 | "esModuleInterop": true, 7 | "outDir": "src/cjs", 8 | "module": "commonjs" 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig.base.json", 3 | "compilerOptions": { 4 | "outDir": "src/esm", 5 | "esModuleInterop": true, 6 | "resolveJsonModule": true, 7 | "module": "ESNext", 8 | "moduleResolution": "Node" 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "defaultSeverity": "error", 3 | "extends": ["tslint:recommended"], 4 | "rules": { 5 | "array-type": false, 6 | "arrow-parens": false, 7 | "curly": false, 8 | "indent": [ 9 | true, 10 | "spaces", 11 | 2 12 | ], 13 | "interface-name": [false], 14 | "match-default-export-name": true, 15 | "max-classes-per-file": [false], 16 | "member-access": [true, "no-public"], 17 | "no-bitwise": false, 18 | "no-console": false, 19 | "no-empty": [true, "allow-empty-catch"], 20 | "no-implicit-dependencies": [true, "dev"], 21 | "no-return-await": true, 22 | "no-var-requires": false, 23 | "no-unused-expression": false, 24 | "object-literal-sort-keys": false, 25 | "quotemark": [true, "single", "avoid-escape"], 26 | "typedef": [ 27 | true, 28 | "call-signature", 29 | "property-declaration" 30 | ], 31 | "variable-name": [ 32 | true, 33 | "ban-keywords", 34 | "check-format", 35 | "allow-leading-underscore", 36 | "allow-pascal-case" 37 | ] 38 | }, 39 | "rulesDirectory": [] 40 | } 41 | --------------------------------------------------------------------------------