diff --git a/package-lock.json b/package-lock.json index 40f8459fb..6439f7d7f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,7 @@ "b64-to-blob": "^1.2.19", "bignumber.js": "^9.1.2", "bip39": "^3.1.0", - "bitcoinjs-lib": "^5.2.0", + "bitcoinjs-lib": "6.1.5", "buffer": "^6.0.3", "bytebuffer": "^5.0.1", "coininfo": "^5.2.1", @@ -33,6 +33,7 @@ "deepmerge": "^4.3.1", "detect-browser": "^5.3.0", "dompurify": "^3.0.5", + "ecpair": "^2.1.0", "ed2curve": "^0.3.0", "emoji-mart": "^5.5.2", "file-saver": "^2.0.5", @@ -62,6 +63,7 @@ "stream-http": "^3.2.0", "stylefire": "^7.0.3", "throttle-promise": "^1.0.4", + "tiny-secp256k1": "^2.2.3", "tweetnacl": "^1.0.3", "visibilityjs": "^2.0.2", "vue": "^3.3.4", @@ -109,6 +111,8 @@ "vite": "^4.4.9", "vite-plugin-electron": "^0.14.1", "vite-plugin-pwa": "^0.16.5", + "vite-plugin-top-level-await": "^1.3.1", + "vite-plugin-wasm": "^3.2.2", "vitest": "^0.34.5", "vue-cli-plugin-i18n": "^2.3.2", "vue-cli-plugin-vuetify": "~2.5.8", @@ -3808,6 +3812,23 @@ } } }, + "node_modules/@rollup/plugin-virtual": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-virtual/-/plugin-virtual-3.0.2.tgz", + "integrity": "sha512-10monEYsBp3scM4/ND4LNH5Rxvh3e/cVeL3jWTgZ2SrQ+BmUoQcopVQvnaMcOnykb1VkxUFuDAN+0FnpTFRy2A==", + "dev": true, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, "node_modules/@rollup/pluginutils": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.0.2.tgz", @@ -3929,6 +3950,216 @@ "sourcemap-codec": "^1.4.8" } }, + "node_modules/@swc/core": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.3.95.tgz", + "integrity": "sha512-PMrNeuqIusq9DPDooV3FfNEbZuTu5jKAc04N3Hm6Uk2Fl49cqElLFQ4xvl4qDmVDz97n3n/C1RE0/f6WyGPEiA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "@swc/counter": "^0.1.1", + "@swc/types": "^0.1.5" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/swc" + }, + "optionalDependencies": { + "@swc/core-darwin-arm64": "1.3.95", + "@swc/core-darwin-x64": "1.3.95", + "@swc/core-linux-arm-gnueabihf": "1.3.95", + "@swc/core-linux-arm64-gnu": "1.3.95", + "@swc/core-linux-arm64-musl": "1.3.95", + "@swc/core-linux-x64-gnu": "1.3.95", + "@swc/core-linux-x64-musl": "1.3.95", + "@swc/core-win32-arm64-msvc": "1.3.95", + "@swc/core-win32-ia32-msvc": "1.3.95", + "@swc/core-win32-x64-msvc": "1.3.95" + }, + "peerDependencies": { + "@swc/helpers": "^0.5.0" + }, + "peerDependenciesMeta": { + "@swc/helpers": { + "optional": true + } + } + }, + "node_modules/@swc/core-darwin-arm64": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.3.95.tgz", + "integrity": "sha512-VAuBAP3MNetO/yBIBzvorUXq7lUBwhfpJxYViSxyluMwtoQDhE/XWN598TWMwMl1ZuImb56d7eUsuFdjgY7pJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-darwin-x64": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.3.95.tgz", + "integrity": "sha512-20vF2rvUsN98zGLZc+dsEdHvLoCuiYq/1B+TDeE4oolgTFDmI1jKO+m44PzWjYtKGU9QR95sZ6r/uec0QC5O4Q==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm-gnueabihf": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.3.95.tgz", + "integrity": "sha512-oEudEM8PST1MRNGs+zu0cx5i9uP8TsLE4/L9HHrS07Ck0RJ3DCj3O2fU832nmLe2QxnAGPwBpSO9FntLfOiWEQ==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-gnu": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.3.95.tgz", + "integrity": "sha512-pIhFI+cuC1aYg+0NAPxwT/VRb32f2ia8oGxUjQR6aJg65gLkUYQzdwuUmpMtFR2WVf7WVFYxUnjo4UyMuyh3ng==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-arm64-musl": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.3.95.tgz", + "integrity": "sha512-ZpbTr+QZDT4OPJfjPAmScqdKKaT+wGurvMU5AhxLaf85DuL8HwUwwlL0n1oLieLc47DwIJEMuKQkYhXMqmJHlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-gnu": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.3.95.tgz", + "integrity": "sha512-n9SuHEFtdfSJ+sHdNXNRuIOVprB8nbsz+08apKfdo4lEKq6IIPBBAk5kVhPhkjmg2dFVHVo4Tr/OHXM1tzWCCw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-linux-x64-musl": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.3.95.tgz", + "integrity": "sha512-L1JrVlsXU3LC0WwmVnMK9HrOT2uhHahAoPNMJnZQpc18a0paO9fqifPG8M/HjNRffMUXR199G/phJsf326UvVg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-arm64-msvc": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.3.95.tgz", + "integrity": "sha512-YaP4x/aZbUyNdqCBpC2zL8b8n58MEpOUpmOIZK6G1SxGi+2ENht7gs7+iXpWPc0sy7X3YPKmSWMAuui0h8lgAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-ia32-msvc": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.3.95.tgz", + "integrity": "sha512-w0u3HI916zT4BC/57gOd+AwAEjXeUlQbGJ9H4p/gzs1zkSHtoDQghVUNy3n/ZKp9KFod/95cA8mbVF9t1+6epQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/core-win32-x64-msvc": { + "version": "1.3.95", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.3.95.tgz", + "integrity": "sha512-5RGnMt0S6gg4Gc6QtPUJ3Qs9Un4sKqccEzgH/tj7V/DVTJwKdnBKxFZfgQ34OR2Zpz7zGOn889xwsFVXspVWNA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=10" + } + }, + "node_modules/@swc/counter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@swc/counter/-/counter-0.1.2.tgz", + "integrity": "sha512-9F4ys4C74eSTEUNndnER3VJ15oru2NumfQxS8geE+f3eB5xvfxpWyqE5XlVnxb/R14uoXi6SLbBwwiDSkv+XEw==", + "dev": true + }, + "node_modules/@swc/types": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.5.tgz", + "integrity": "sha512-myfUej5naTBWnqOCc/MdVOLVjXUXtIA+NpDrDBKJtLLg2shUjBu3cZmB/85RyitKc55+lUUyl7oRfLOvkr2hsw==", + "dev": true + }, "node_modules/@szmarczak/http-timer": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", @@ -5560,9 +5791,9 @@ ] }, "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz", + "integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==" }, "node_modules/big-integer": { "version": "1.6.51", @@ -5599,44 +5830,14 @@ "node": ">=8" } }, - "node_modules/bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dependencies": { - "file-uri-to-path": "1.0.0" - } - }, "node_modules/bip174": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.0.tgz", - "integrity": "sha512-lkc0XyiX9E9KiVAS1ZiOqK1xfiwvf4FXDDdkDq5crcDzOq+xGytY+14qCsqz7kCiy8rpN1CRNfacRhf9G3JNSA==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bip174/-/bip174-2.1.1.tgz", + "integrity": "sha512-mdFV5+/v0XyNYXjBS6CQPLo9ekCx4gtKZFnJm5PMto7Fs9hTTDpkkzOB7/FtluRI6JbUUAu+snTYfJRgHLZbZQ==", "engines": { "node": ">=8.0.0" } }, - "node_modules/bip32": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/bip32/-/bip32-2.0.6.tgz", - "integrity": "sha512-HpV5OMLLGTjSVblmrtYRfFFKuQB+GArM0+XP8HGWfJ5vxYBqo+DesvJwOdC2WJ3bCkZShGf0QIfoIpeomVzVdA==", - "dependencies": { - "@types/node": "10.12.18", - "bs58check": "^2.1.1", - "create-hash": "^1.2.0", - "create-hmac": "^1.1.7", - "tiny-secp256k1": "^1.1.3", - "typeforce": "^1.11.5", - "wif": "^2.0.6" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/bip32/node_modules/@types/node": { - "version": "10.12.18", - "resolved": "https://registry.npmjs.org/@types/node/-/node-10.12.18.tgz", - "integrity": "sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==" - }, "node_modules/bip39": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/bip39/-/bip39-3.1.0.tgz", @@ -5645,44 +5846,44 @@ "@noble/hashes": "^1.2.0" } }, - "node_modules/bip66": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/bip66/-/bip66-1.1.5.tgz", - "integrity": "sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, - "node_modules/bitcoin-ops": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz", - "integrity": "sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow==" - }, "node_modules/bitcoinjs-lib": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-5.2.0.tgz", - "integrity": "sha512-5DcLxGUDejgNBYcieMIUfjORtUeNWl828VWLHJGVKZCb4zIS1oOySTUr0LGmcqJBQgTBz3bGbRQla4FgrdQEIQ==", - "dependencies": { - "bech32": "^1.1.2", - "bip174": "^2.0.1", - "bip32": "^2.0.4", - "bip66": "^1.1.0", - "bitcoin-ops": "^1.4.0", - "bs58check": "^2.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.3", - "merkle-lib": "^2.0.10", - "pushdata-bitcoin": "^1.0.1", - "randombytes": "^2.0.1", - "tiny-secp256k1": "^1.1.1", + "version": "6.1.5", + "resolved": "https://registry.npmjs.org/bitcoinjs-lib/-/bitcoinjs-lib-6.1.5.tgz", + "integrity": "sha512-yuf6xs9QX/E8LWE2aMJPNd0IxGofwfuVOiYdNUESkc+2bHHVKjhJd8qewqapeoolh9fihzHGoDCB5Vkr57RZCQ==", + "dependencies": { + "@noble/hashes": "^1.2.0", + "bech32": "^2.0.0", + "bip174": "^2.1.1", + "bs58check": "^3.0.1", "typeforce": "^1.11.3", - "varuint-bitcoin": "^1.0.4", - "wif": "^2.0.1" + "varuint-bitcoin": "^1.1.2" }, "engines": { "node": ">=8.0.0" } }, + "node_modules/bitcoinjs-lib/node_modules/base-x": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/base-x/-/base-x-4.0.0.tgz", + "integrity": "sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw==" + }, + "node_modules/bitcoinjs-lib/node_modules/bs58": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bs58/-/bs58-5.0.0.tgz", + "integrity": "sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ==", + "dependencies": { + "base-x": "^4.0.0" + } + }, + "node_modules/bitcoinjs-lib/node_modules/bs58check": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/bs58check/-/bs58check-3.0.1.tgz", + "integrity": "sha512-hjuuJvoWEybo7Hn/0xOrczQKKEKD63WguEjlhLExYs2wUBcebDC1jDNK17eEAD2lYfw82d5ASC1d7K3SWszjaQ==", + "dependencies": { + "@noble/hashes": "^1.2.0", + "bs58": "^5.0.0" + } + }, "node_modules/bl": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", @@ -7591,6 +7792,19 @@ "wcwidth": ">=1.0.1" } }, + "node_modules/ecpair": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ecpair/-/ecpair-2.1.0.tgz", + "integrity": "sha512-cL/mh3MtJutFOvFc27GPZE2pWL3a3k4YvzUWEOvilnfZVlH3Jwgx/7d6tlD7/75tNk8TG2m+7Kgtz0SI1tWcqw==", + "dependencies": { + "randombytes": "^2.1.0", + "typeforce": "^1.18.0", + "wif": "^2.0.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/ed2curve": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/ed2curve/-/ed2curve-0.3.0.tgz", @@ -8853,11 +9067,6 @@ "resolved": "https://registry.npmjs.org/file-saver/-/file-saver-2.0.5.tgz", "integrity": "sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA==" }, - "node_modules/file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" - }, "node_modules/filelist": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", @@ -10908,11 +11117,6 @@ "node": ">= 8" } }, - "node_modules/merkle-lib": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/merkle-lib/-/merkle-lib-2.0.10.tgz", - "integrity": "sha512-XrNQvUbn1DL5hKNe46Ccs+Tu3/PYOlrcZILuGUhb95oKBPjc/nmIC8D462PQkipVDGKRvwhn+QFg2cCdIvmDJA==" - }, "node_modules/micromatch": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", @@ -11195,11 +11399,6 @@ "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", "dev": true }, - "node_modules/nan": { - "version": "2.17.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.17.0.tgz", - "integrity": "sha512-2ZTgtl0nJsO0KQCjEpxcIr5D+Yv90plTitZt9JBfQvVJDS5seMl3FOvsh3+9CoYWXf/1l5OaZzzF6nDm4cagaQ==" - }, "node_modules/nanoid": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", @@ -12092,14 +12291,6 @@ "node": ">=6" } }, - "node_modules/pushdata-bitcoin": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/pushdata-bitcoin/-/pushdata-bitcoin-1.0.1.tgz", - "integrity": "sha512-hw7rcYTJRAl4olM8Owe8x0fBuJJ+WGbMhQuLWOXEMN3PxPCKQHRkhfL+XG0+iXUmSHjkMmb3Ba55Mt21cZc9kQ==", - "dependencies": { - "bitcoin-ops": "^1.3.0" - } - }, "node_modules/qrcode": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.3.tgz", @@ -13961,26 +14152,16 @@ } }, "node_modules/tiny-secp256k1": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz", - "integrity": "sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA==", - "hasInstallScript": true, + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/tiny-secp256k1/-/tiny-secp256k1-2.2.3.tgz", + "integrity": "sha512-SGcL07SxcPN2nGKHTCvRMkQLYPSoeFcvArUSCYtjVARiFAWU44cCIqYS0mYAU6nY7XfvwURuTIGo2Omt3ZQr0Q==", "dependencies": { - "bindings": "^1.3.0", - "bn.js": "^4.11.8", - "create-hmac": "^1.1.7", - "elliptic": "^6.4.0", - "nan": "^2.13.2" + "uint8array-tools": "0.0.7" }, "engines": { - "node": ">=6.0.0" + "node": ">=14.0.0" } }, - "node_modules/tiny-secp256k1/node_modules/bn.js": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", - "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" - }, "node_modules/tinybench": { "version": "2.5.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", @@ -14286,6 +14467,14 @@ "node": ">=8" } }, + "node_modules/uint8array-tools": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/uint8array-tools/-/uint8array-tools-0.0.7.tgz", + "integrity": "sha512-vrrNZJiusLWoFWBqz5Y5KMCgP9W9hnjZHzZiZRT8oNAkq3d5Z5Oe76jAvVVSRh4U8GGR90N2X1dWtrhvx6L8UQ==", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/unbox-primitive": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", @@ -14678,6 +14867,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/vite-plugin-top-level-await": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/vite-plugin-top-level-await/-/vite-plugin-top-level-await-1.3.1.tgz", + "integrity": "sha512-55M1h4NAwkrpxPNOJIBzKZFihqLUzIgnElLSmPNPMR2Fn9+JHKaNg3sVX1Fq+VgvuBksQYxiD3OnwQAUu7kaPQ==", + "dev": true, + "dependencies": { + "@rollup/plugin-virtual": "^3.0.1", + "@swc/core": "^1.3.10", + "uuid": "^9.0.0" + }, + "peerDependencies": { + "vite": ">=2.8" + } + }, + "node_modules/vite-plugin-wasm": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/vite-plugin-wasm/-/vite-plugin-wasm-3.2.2.tgz", + "integrity": "sha512-cdbBUNR850AEoMd5nvLmnyeq63CSfoP1ctD/L2vLk/5+wsgAPlAVAzUK5nGKWO/jtehNlrSSHLteN+gFQw7VOA==", + "dev": true, + "peerDependencies": { + "vite": "^2 || ^3 || ^4" + } + }, "node_modules/vitest": { "version": "0.34.5", "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.34.5.tgz", diff --git a/package.json b/package.json index 259e6b845..3f611047f 100644 --- a/package.json +++ b/package.json @@ -36,7 +36,7 @@ "b64-to-blob": "^1.2.19", "bignumber.js": "^9.1.2", "bip39": "^3.1.0", - "bitcoinjs-lib": "^5.2.0", + "bitcoinjs-lib": "6.1.5", "buffer": "^6.0.3", "bytebuffer": "^5.0.1", "coininfo": "^5.2.1", @@ -46,6 +46,7 @@ "deepmerge": "^4.3.1", "detect-browser": "^5.3.0", "dompurify": "^3.0.5", + "ecpair": "^2.1.0", "ed2curve": "^0.3.0", "emoji-mart": "^5.5.2", "file-saver": "^2.0.5", @@ -75,6 +76,7 @@ "stream-http": "^3.2.0", "stylefire": "^7.0.3", "throttle-promise": "^1.0.4", + "tiny-secp256k1": "^2.2.3", "tweetnacl": "^1.0.3", "visibilityjs": "^2.0.2", "vue": "^3.3.4", @@ -122,6 +124,8 @@ "vite": "^4.4.9", "vite-plugin-electron": "^0.14.1", "vite-plugin-pwa": "^0.16.5", + "vite-plugin-top-level-await": "^1.3.1", + "vite-plugin-wasm": "^3.2.2", "vitest": "^0.34.5", "vue-cli-plugin-i18n": "^2.3.2", "vue-cli-plugin-vuetify": "~2.5.8", diff --git a/src/lib/bitcoin/btc-base-api.js b/src/lib/bitcoin/btc-base-api.js index 34af8898b..44a4f01cf 100644 --- a/src/lib/bitcoin/btc-base-api.js +++ b/src/lib/bitcoin/btc-base-api.js @@ -7,17 +7,22 @@ import BigNumber from '../bignumber' import { isPositiveNumber } from '@/lib/numericHelpers' import { CryptosInfo } from '../constants' -const getUnique = values => { +import { ECPairFactory } from 'ecpair' +import * as tinysecp from 'tiny-secp256k1' + +const ECPairAPI = ECPairFactory(tinysecp) + +const getUnique = (values) => { const map = values.reduce((m, v) => { m[v] = 1 return m - }, { }) + }, {}) return Object.keys(map) } -const createClient = url => { +const createClient = (url) => { const client = axios.create({ baseURL: url }) - client.interceptors.response.use(null, error => { + client.interceptors.response.use(null, (error) => { if (error.response && Number(error.response.status) >= 500) { console.error('Request failed', error) } @@ -26,10 +31,10 @@ const createClient = url => { return client } -export function getAccount (crypto, passphrase) { +export function getAccount(crypto, passphrase) { const network = networks[crypto] const pwHash = bitcoin.crypto.sha256(Buffer.from(passphrase)) - const keyPair = bitcoin.ECPair.fromPrivateKey(pwHash, { network }) + const keyPair = ECPairAPI.fromPrivateKey(pwHash, { network }) return { network, @@ -39,21 +44,21 @@ export function getAccount (crypto, passphrase) { } export default class BtcBaseApi { - constructor (crypto, passphrase) { + constructor(crypto, passphrase) { const account = getAccount(crypto, passphrase) this._network = account.network this._keyPair = account.keyPair this._address = account.address - this._clients = { } + this._clients = {} this._crypto = crypto } - get multiplier () { + get multiplier() { return 1e8 } - get address () { + get address() { return this._address } @@ -67,7 +72,7 @@ export default class BtcBaseApi { * @abstract * @returns {Promise} */ - getBalance () { + getBalance() { return Promise.resolve(0) } @@ -78,16 +83,22 @@ export default class BtcBaseApi { * @param {number} fee transaction fee (coins, not satoshis) * @returns {Promise<{hex: string, txid: string}>} */ - createTransaction (address = '', amount = 0, fee) { - return this.getUnspents().then(unspents => { - const hex = this._buildTransaction(address, amount, unspents, fee) + async createTransaction(address = '', amount = 0, fee) { + const unspents = await this.getUnspents() - let txid = bitcoin.crypto.sha256(Buffer.from(hex, 'hex')) - txid = bitcoin.crypto.sha256(Buffer.from(txid)) - txid = txid.toString('hex').match(/.{2}/g).reverse().join('') + // populate unspents with full transaction in HEX + for (const unspent of unspents) { + const txHex = await this._get(`/tx/${unspent.txid}/hex`) + unspent.txHex = txHex + } - return { hex, txid } - }) + const hex = this._buildTransaction(address, amount, unspents, fee) + + let txid = bitcoin.crypto.sha256(Buffer.from(hex, 'hex')) + txid = bitcoin.crypto.sha256(Buffer.from(txid)) + txid = txid.toString('hex').match(/.{2}/g).reverse().join('') + + return { hex, txid } } /** @@ -95,7 +106,7 @@ export default class BtcBaseApi { * @abstract * @param {string} txHex raw transaction as a HEX literal */ - sendTransaction (txHex) { + sendTransaction(txHex) { return Promise.resolve('') } @@ -105,7 +116,7 @@ export default class BtcBaseApi { * @param {*} txid transaction ID * @returns {Promise} */ - getTransaction (txid) { + getTransaction(txid) { return Promise.resolve(null) } @@ -115,7 +126,7 @@ export default class BtcBaseApi { * @param {any} options crypto-specific options * @returns {Promise<{hasMore: boolean, items: Array}>} */ - getTransactions (options) { + getTransactions(options) { return Promise.resolve({ hasMore: false, items: [] }) } @@ -124,7 +135,7 @@ export default class BtcBaseApi { * @abstract * @returns {Promise>} */ - getUnspents () { + getUnspents() { return Promise.resolve([]) } @@ -136,43 +147,58 @@ export default class BtcBaseApi { * @param {number} fee transaction fee in primary units (BTC, DOGE, DASH, etc) * @returns {string} */ - _buildTransaction (address, amount, unspents, fee) { + _buildTransaction(address, amount, unspents, fee) { amount = new BigNumber(amount).times(this.multiplier).toNumber() amount = Math.floor(amount) - const txb = new bitcoin.TransactionBuilder(this._network) + const txb = new bitcoin.Psbt({ + network: this._network + }) txb.setVersion(1) const target = amount + new BigNumber(fee).times(this.multiplier).toNumber() let transferAmount = 0 let inputs = 0 - unspents.forEach(tx => { + unspents.forEach((tx) => { const amt = Math.floor(tx.amount) if (transferAmount < target) { - txb.addInput(tx.txid, tx.vout) + txb.addInput({ + hash: tx.txid, + index: tx.vout, + nonWitnessUtxo: Buffer.from(tx.txHex, 'hex') + }) transferAmount += amt inputs++ } }) - txb.addOutput(bitcoin.address.toOutputScript(address, this._network), amount) + txb.addOutput({ + address, + value: amount + }) // This is a necessary step // If we'll not add a change to output, it will burn in hell const change = transferAmount - target if (isPositiveNumber(change)) { - txb.addOutput(this._address, change) + txb.addOutput({ + address: this._address, + value: change + }) } for (let i = 0; i < inputs; ++i) { - txb.sign(i, this._keyPair) + txb.signInput(i, this._keyPair) } - return txb.build().toHex() + txb.finalizeAllInputs() + const tx = txb.extractTransaction() + + return tx.toHex() } /** Picks a client for a random API endpoint */ - _getClient () { + _getClient() { const url = getEnpointUrl(this._crypto) if (!this._clients[url]) { this._clients[url] = createClient(url) @@ -180,19 +206,23 @@ export default class BtcBaseApi { return this._clients[url] } - _mapTransaction (tx) { + _mapTransaction(tx) { // Remove курьи txs like "possibleDoubleSpend" and txs without info if (tx.possibleDoubleSpend || (!tx.txid && !tx.time && !tx.valueIn && !tx.vin)) return const addressField = tx.vin[0].address ? 'address' : 'addr' - const senders = getUnique(tx.vin.map(input => input[addressField])).filter(sender => sender !== undefined && sender !== 'undefined') + const senders = getUnique(tx.vin.map((input) => input[addressField])).filter( + (sender) => sender !== undefined && sender !== 'undefined' + ) const direction = senders.includes(this._address) ? 'from' : 'to' - const recipients = getUnique(tx.vout.reduce((list, out) => { - list.push(...out.scriptPubKey.addresses) - return list - }, [])).filter(recipient => recipient !== undefined && recipient !== 'undefined') + const recipients = getUnique( + tx.vout.reduce((list, out) => { + list.push(...out.scriptPubKey.addresses) + return list + }, []) + ).filter((recipient) => recipient !== undefined && recipient !== 'undefined') if (direction === 'from') { // Disregard our address for an outgoing transaction unless it's the only address (i.e. we're sending to ourselves) @@ -218,8 +248,13 @@ export default class BtcBaseApi { // Calculate amount from outputs: // * for the outgoing transactions take outputs that DO NOT target us // * for the incoming transactions take outputs that DO target us - const amount = tx.vout.reduce((sum, t) => - ((direction === 'to') === (t.scriptPubKey.addresses.includes(this._address)) ? sum + Number(t.value) : sum), 0) + const amount = tx.vout.reduce( + (sum, t) => + (direction === 'to') === t.scriptPubKey.addresses.includes(this._address) + ? sum + Number(t.value) + : sum, + 0 + ) const confirmations = tx.confirmations const timestamp = tx.time ? tx.time * 1000 : undefined diff --git a/vite-base.config.ts b/vite-base.config.ts index 8b023fe28..25b1304da 100644 --- a/vite-base.config.ts +++ b/vite-base.config.ts @@ -1,5 +1,7 @@ import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' +import wasm from 'vite-plugin-wasm' +import topLevelAwait from 'vite-plugin-top-level-await' import path from 'path' import autoprefixer from 'autoprefixer' import inject from '@rollup/plugin-inject' @@ -11,6 +13,8 @@ import { excludeBip39Wordlists } from './vite-config/rollup/excludeBip39Wordlist export default defineConfig({ plugins: [ + wasm(), + topLevelAwait(), vue(), commonjs(), inject({