From b1c15254b5cefd1246bf65635b6f4a690d1d1029 Mon Sep 17 00:00:00 2001 From: JoeGruff Date: Tue, 25 Apr 2023 18:43:45 +0900 Subject: [PATCH] actions: Add ledger backend functions. --- app/actions/LedgerActions.js | 235 +++++++++++++++++++++++++++++++ app/helpers/ledger.js | 176 +++++++++++++++++++++++ package.json | 2 + test/unit/helpers/ledger.spec.js | 67 +++++++++ yarn.lock | 233 ++++++++++++++++++++++++++++-- 5 files changed, 700 insertions(+), 13 deletions(-) create mode 100644 app/actions/LedgerActions.js create mode 100644 app/helpers/ledger.js create mode 100644 test/unit/helpers/ledger.spec.js diff --git a/app/actions/LedgerActions.js b/app/actions/LedgerActions.js new file mode 100644 index 0000000000..2626460838 --- /dev/null +++ b/app/actions/LedgerActions.js @@ -0,0 +1,235 @@ +import TransportNodeHid from "@ledgerhq/hw-transport-node-hid-singleton"; +import { createTransaction } from "@ledgerhq/hw-app-btc/lib/createTransaction"; +import Btc from "@ledgerhq/hw-app-btc"; +import * as ledgerHelpers from "../helpers/ledger"; +import { wallet } from "wallet-preload-shim"; +import { publishTransactionAttempt } from "./ControlActions"; +import { hexToBytes } from "helpers"; +import { getTxFromInputs } from "../actions/TransactionActions"; +import { + SIGNTX_ATTEMPT, + SIGNTX_FAILED, + SIGNTX_SUCCESS +} from "./ControlActions"; + +import * as selectors from "selectors"; +import * as cfgConstants from "constants/config"; + +export const LDG_LEDGER_ENABLED = "LDG_LEDGER_ENABLED"; +export const LDG_WALLET_CLOSED = "LDG_WALLET_CLOSED"; + +const coin = "decred"; +// This is an error's message when an app is open but we are trying to get +// device info. +const DEVICE_ON_DASHBOARD_EXPECTED = "DeviceOnDashboardExpected" + +// enableLedger only sets a value in the config. Ledger connections are made +// per action then dropped. +export const enableLedger = () => (dispatch, getState) => { + const walletName = selectors.getWalletName(getState()); + + if (walletName) { + const config = wallet.getWalletCfg( + selectors.isTestNet(getState()), + walletName + ); + config.set(cfgConstants.LEDGER, true); + } + + dispatch({ type: LDG_LEDGER_ENABLED }); + + connect()(dispatch, getState); +}; + +export const LDG_CONNECT_ATTEMPT = "LDG_CONNECT_ATTEMPT"; +export const LDG_CONNECT_FAILED = "LDG_CONNECT_FAILED"; +export const LDG_CONNECT_SUCCESS = "LDG_CONNECT_SUCCESS"; + +async function connect(dispatch, getState) { + dispatch({ type: LDG_CONNECT_ATTEMPT }); + try { + // If unable to connect, a timeout error will occur. + await deviceRun(dispatch, getState, async (transport) => {}) + } catch (error) { + dispatch({ type: LDG_CONNECT_FAILED }); + throw error + } + dispatch({ type: LDG_CONNECT_SUCCESS }); + return device; +} + +export const LDG_LEDGER_DISABLED = "LDG_LEDGER_DISABLED"; + +// disableLedger disables ledger integration for the current wallet. Note +// that it does **not** disable in the config, so the wallet will restart as a +// ledger wallet next time it's opened. +export const disableLedger = () => (dispatch) => { + dispatch({ type: LDG_LEDGER_DISABLED }); +}; + +export const LDG_NOCONNECTEDDEVICE = "LDG_NOCONNECTEDDEVICE"; + +export const alertNoConnectedDevice = () => (dispatch) => { + dispatch({ type: LDG_NOCONNECTEDDEVICE }); +}; + +// deviceRun is the main function for executing ledger operations. This handles +// cleanup for cancellations and device disconnections during mid-operation (eg: +// someone disconnected ledger while it was waiting for a pin input). +// In general, fn itself shouldn't handle errors, letting this function handle +// the common cases, which are then propagated up the call stack into fn's +// parent. +async function deviceRun(dispatch, getState, fn) { + const timoutErr = new Error("timeout waiting for transport") + const handleError = (error) => { + if (error === timeoutErr) { + alertNoConnectedDevice()(dispatch); + } + return error; + }; + + try { + // TODO: Enable on mainnet. + const isTestnet = selectors.isTestNet(getState()); + if (!isTestnet) + throw "ledger is currently under development and should only be used on testnet"; + + const pWithTransport = new Promise(async (resolve, reject) => { + resolve(await TransportNodeHid.create()) + }) + + let timeout; + const pTimeout = new Promise((resolve, reject) => { + timeout = setTimeout(() => {reject(timeoutErr)}, 2000) + }) + + // Creating the transport will wait indefinitely. Timeout if it does not + // connect in a couple seconds. + let res; + await Promise.race([pWithTransport, pTimeout]).then( async (t) => { + clearTimeout(timeout) + res = await fn(t) + }).catch((err) => { + throw err + }) + + return res; + } catch (error) { + throw handleError(error); + } +} + +// checkLedgerIsDcrwallet verifies whether the wallet currently running on +// dcrwallet (presumably a watch only wallet created from a ledger provided +// xpub) is the same wallet as the one of the currently connected ledger. This +// function throws an error if they are not the same. +// This is useful for making sure, prior to performing some wallet related +// function such as transaction signing, that ledger will correctly perform the +// operation. +// Note that this might trigger pin/passphrase modals, depending on the current +// ledger configuration. +// The way the check is performed is by generating the first address from the +// ledger wallet and then validating this address agains dcrwallet, ensuring +// this is an owned address at the appropriate branch/index. +// This check is only valid for a single session (ie, a single execution of +// `deviceRun`) as the physical device might change between sessions. +const checkLedgerIsDcrwallet = () => async (dispatch, getState) => { + const { + grpc: { walletService } + } = getState(); + + const path = ledgerHelpers.addressPath(0, 0); + const payload = await deviceRun(dispatch, getState, async (transport) => { + const btc = new Btc({ transport, currency: coin }); + const res = await btc.getWalletPublicKey(path, { + verify: false + }); + return res; + }); + const addr = payload.bitcoinAddress; + + const addrValidResp = await wallet.validateAddress(walletService, addr); + if (!addrValidResp.isValid) + throw "Ledger provided an invalid address " + addr; + + if (!addrValidResp.isMine) + throw "Ledger and dcrwallet not running from the same extended public key"; + + if (addrValidResp.index !== 0) throw "Wallet replied with wrong index."; +}; + +export const signTransactionAttemptLedger = + (rawUnsigTx) => async (dispatch, getState) => { + dispatch({ type: SIGNTX_ATTEMPT }); + + const { + grpc: { walletService } + } = getState(); + const chainParams = selectors.chainParams(getState()); + + try { + const decodedUnsigTxResp = wallet.decodeRawTransaction( + Buffer.from(rawUnsigTx, "hex"), + chainParams + ); + const getInputs = (tx) => { + return async () => { + return await dispatch(getTxFromInputs(tx)); + }; + }; + const arg = await ledgerHelpers.signArgs( + decodedUnsigTxResp, + wallet, + walletService, + getInputs + ); + + const signedRaw = await deviceRun( + dispatch, + getState, + async (transport) => { + await dispatch(checkLedgerIsDcrwallet()); + + const res = await createTransaction(transport, arg); + return res; + } + ); + + dispatch({ type: SIGNTX_SUCCESS }); + dispatch(publishTransactionAttempt(hexToBytes(signedRaw))); + } catch (error) { + dispatch({ error, type: SIGNTX_FAILED }); + } + }; + +export const LDG_GETWALLETCREATIONMASTERPUBKEY_ATTEMPT = + "LDG_GETWALLETCREATIONMASTERPUBKEY_ATTEMPT"; +export const LDG_GETWALLETCREATIONMASTERPUBKEY_FAILED = + "LDG_GETWALLETCREATIONMASTERPUBKEY_FAILED"; +export const LDG_GETWALLETCREATIONMASTERPUBKEY_SUCCESS = + "LDG_GETWALLETCREATIONMASTERPUBKEY_SUCCESS"; + +export const getWalletCreationMasterPubKey = + () => async (dispatch, getState) => { + dispatch({ type: LDG_GETWALLETCREATIONMASTERPUBKEY_ATTEMPT }); + try { + const payload = await deviceRun(dispatch, getState, async (transport) => { + const btc = new Btc({ transport, currency: "decred" }); + const res = await btc.getWalletPublicKey("44'/42'/0'", { + verify: false + }); + return res; + }); + const hdpk = ledgerHelpers.pubkeyToHDPubkey( + payload.publicKey, + payload.chainCode + ); + + dispatch({ type: LDG_GETWALLETCREATIONMASTERPUBKEY_SUCCESS }); + + return hdpk; + } catch (error) { + dispatch({ error, type: LDG_GETWALLETCREATIONMASTERPUBKEY_FAILED }); + throw error; + } + }; diff --git a/app/helpers/ledger.js b/app/helpers/ledger.js new file mode 100644 index 0000000000..cfc9862ce7 --- /dev/null +++ b/app/helpers/ledger.js @@ -0,0 +1,176 @@ +import { hexToBytes, strHashToRaw } from "helpers"; +import * as secp256k1 from "secp256k1"; +import { default as blake } from "blake-hash"; +import * as bs58 from "bs58"; +import toBuffer from "typedarray-to-buffer"; + +export function addressPath(branch, index) { + const prefix = "44'/42'/0'/"; + const i = (index || 0).toString(); + const b = (branch || 0).toString(); + return prefix + b + "/" + i; +} + +export function pubkeyToHDPubkey(pubkey, chainCode, isTestnet) { + const pk = secp256k1.publicKeyConvert(hexToBytes(pubkey), true); // from uncompressed to compressed + const cc = hexToBytes(chainCode); + let hdPublicKeyID = hexToBytes("02fda926"); // dpub + if (isTestnet) { + hdPublicKeyID = hexToBytes("043587d1"); // tpub + } + const parentFP = hexToBytes("00000000"); // not true but we dont know the fingerprint + const childNum = hexToBytes("80000000"); // always first hardened child + const depth = 2; // account is depth 2 + const buff = new Uint8Array(78); // 4 network identifier + 1 depth + 4 parent fingerprint + 4 child number + 32 chain code + 33 compressed public key + let i = 0; + buff.set(hdPublicKeyID, i); + i += 4; + buff[i] = depth; + i += 1; + buff.set(parentFP, i); + i += 4; + buff.set(childNum, i); + i += 4; + buff.set(cc, i); + i += 32; + buff.set(pk, i); + const firstPass = blake("blake256").update(Buffer.from(buff)).digest(); + const secondPass = blake("blake256").update(firstPass).digest(); + const fullSerialize = Buffer.concat([ + Buffer.from(buff), + secondPass.slice(0, 4) + ]); + return bs58.encode(fullSerialize); +} + +function writeUint16LE(n) { + const buff = new Buffer(2); + buff.writeUInt16LE(n, 0); + return buff; +} + +function writeUint32LE(n) { + const buff = new Buffer(4); + buff.writeUInt32LE(n, 0); + return buff; +} + +/* global BigInt */ +function writeUint64LE(n) { + const buff = new Buffer(8); + buff.writeBigUInt64LE(BigInt(n), 0); + return buff; +} + +function inputToTx(tx) { + const inputs = []; + for (const inp of tx.inputsList) { + const sequence = writeUint32LE(inp.sequence); + const tree = new Uint8Array(1); + tree[0] = inp.tree; + const prevout = new Uint8Array(36); + prevout.set(strHashToRaw(inp.previousTransactionHash), 0); + prevout.set(writeUint32LE(inp.previousTransactionIndex), 32); + const input = { + prevout: toBuffer(prevout), + script: toBuffer(new Uint8Array(25)), + sequence: sequence, + tree: toBuffer(tree) + }; + inputs.push(input); + } + const outputs = []; + for (const out of tx.outputsList) { + const output = { + amount: writeUint64LE(out.value), + script: Buffer.from(out.script, "hex") + }; + outputs.push(output); + } + return { + version: writeUint32LE(tx.version), // Pretty sure this is a uint16 but ledger does not want that. + inputs: inputs, + outputs: outputs, + locktime: writeUint32LE(tx.lockTime), + nExpiryHeight: writeUint32LE(tx.expiry) + }; +} + +function createPrefix(tx) { + const numOuts = tx.outputsList.length; + if (numOuts > 2) { + throw "more than two outputs is not expected"; + } + let buffLen = 1; + for (const out of tx.outputsList) { + buffLen += 11 + out.script.length / 2; // script in hex atm + } + const buff = new Uint8Array(buffLen); // 1 varInt + ( 8 value + 2 tx version + 1 varInt + (23/25?) variable script length) * number of outputs + let i = 0; + buff[i] = numOuts; + i += 1; + for (const out of tx.outputsList) { + buff.set(writeUint64LE(out.value), i); + i += 8; + buff.set(writeUint16LE(out.version), i); + i += 2; + // TODO: Clean this up for production? Should use smarter logic to get varInts. + buff[i] = out.script.length / 2; // varInt for 23/25 bytes + i += 1; + buff.set(Buffer.from(out.script, "hex"), i); + i += out.script.length / 2; + } + return toBuffer(buff); +} + +export async function signArg(txHex, wallet, walletService, getTxFromInputs) { + const tx = await wallet.decodeTransaction(walletService, txHex); + const inputTxs = await getTxFromInputs(tx); + const inputs = []; + const paths = []; + let i = 0; + for (const inp of inputTxs) { + const prevOut = inputToTx(inp); + const idx = tx.inputsList[i].previousTransactionIndex; + inputs.push([prevOut, idx]); + const addrs = inp.outputsList[idx].addressesList; + if (addrs.length != 1) throw "unexpected spending from multisig"; + const val = await wallet.validateAddress(walletService, addrs[0]); + const acct = val.getAccountNumber().toString(); + const branch = val.getIsInternal() ? "1" : "0"; + const index = val.getIndex().toString(); + paths.push("44'/42'/" + acct + "'/" + branch + "/" + index); + i++; + } + let changePath = null; + for (const out of tx.outputsList) { + if (out.addressesList.length != 1) { + continue; + } + const addr = out.addressesList[0]; + const val = await wallet.validateAddress(walletService, addr); + if (!val.getIsInternal()) { + continue; + } // assume the internal address is change + const acct = val.getAccountNumber().toString(); + const index = val.getIndex().toString(); + changePath = "44'/42'/" + acct + "'/1/" + index; + break; + } + + return { + inputs: inputs, + associatedKeysets: paths, + changePath: changePath, + outputScriptHex: createPrefix(tx), + lockTime: tx.lockTime, + sigHashType: 1, // SIGHASH_ALL + segwit: false, + expiryHeight: writeUint32LE(tx.expiry), + useTrustedInputForSegwit: false, + additionals: ["decred"], + onDeviceStreaming: () => {}, + onDeviceSignatureGranted: () => {}, + onDeviceSignatureRequested: () => {} + }; +} diff --git a/package.json b/package.json index c19e3c54ec..324f05440f 100644 --- a/package.json +++ b/package.json @@ -273,6 +273,8 @@ "@formatjs/intl-utils": "^1.6.0", "@grpc/grpc-js": "1.7.3", "@hot-loader/react-dom": "16.14.0", + "@ledgerhq/hw-app-btc": "^10.0.2", + "@ledgerhq/hw-transport-node-hid-singleton": "^6.28.11", "@peculiar/webcrypto": "1.4.1", "@xstate/react": "^0.8.1", "blake-hash": "^2.0.0", diff --git a/test/unit/helpers/ledger.spec.js b/test/unit/helpers/ledger.spec.js new file mode 100644 index 0000000000..fcdb7e8905 --- /dev/null +++ b/test/unit/helpers/ledger.spec.js @@ -0,0 +1,67 @@ +import { addressPath, pubkeyToHDPubkey, signArg } from "helpers/ledger"; + +test("test ledger address path", () => { + expect(addressPath(1, 2)).toStrictEqual("44'/42'/0'/1/2"); +}); + +test("test ledger pubkey to hd key", () => { + // testnet + expect(pubkeyToHDPubkey("043e3e8802449f60621bebed4fcb296c781b63df429e45b1201fda6d4ec6a172445ffe4f6a5032de88cd1ba4397c9a397fe9522d76e12306c8f38b8fa61d4bdc33", + "7271b9c5a3dbf281efdab76250d978f178782e33b354b131c0b817459c98bdc3", true)).toStrictEqual("tpubVmYdgyojvygmmGAKaWc8qCzFGafGFVNhGr44tra11QGak5GwMsVibCtkdvxYfg27XgHGvtN6j9kt9p8cewEChPM5HBqaeQGMS1E4WgSY271"); + // mainet + expect(pubkeyToHDPubkey("043e3e8802449f60621bebed4fcb296c781b63df429e45b1201fda6d4ec6a172445ffe4f6a5032de88cd1ba4397c9a397fe9522d76e12306c8f38b8fa61d4bdc33", + "7271b9c5a3dbf281efdab76250d978f178782e33b354b131c0b817459c98bdc3", false)).toStrictEqual("dpubZCmMrtFLzkfwgoEsrkwMkAH5i49zt3yGkEuwe4nQBEsnuFz8erXctxL4ehVtDBnDqYXKJEKpCygt7qt298XHpEHko3vDtuvE2z8NzLkPZTo"); +}); + +class mockValidateAddress { + constructor(accountNumber, isInternal, index) { + this.accountNumber = accountNumber; + this.isInternal = isInternal; + this.index = index; + } + getAccountNumber() { + return this.accountNumber; + } + getIndex() { + return this.index; + } + getIsInternal() { + return this.isInternal; + } +} + +class mockWallet { + constructor(decodeTransaction, validateAddress) { + this.dt = decodeTransaction; + this.vaArray = validateAddress; + this.vaN = -1; + } + decodeTransaction() { + return this.dt; + } + validateAddress() { + this.vaN += 1; + return this.vaArray[this.vaN]; + } +} + +function getTxFromInputsFn (inputs) { + return function () { + return inputs; + }; +} + +test("test ledger constructing arg to sign", async () => { + const txHex = "0100000001c63b60df16c2f13950d7a2f3d406bedd8ae9dc007964dd3a077fcafc7c340b3f0100000000ffffffff02340782060000000000001976a9148848f6d82e4b221317ff067b3a8094c40fa604f988aca08601000000000000001976a9140262bb5374203f86fa733efbce84ab51450a5f2988ac000000000000000001b69783060000000000000000ffffffff00"; + const validateAddreassA = new mockValidateAddress(0, true, 46); // input + const validateAddreassB = new mockValidateAddress(0, false, 0); // output 0 + const validateAddreassC = new mockValidateAddress(0, true, 51); // output 1 + const mockGetTxFromInputs = getTxFromInputsFn([{ "transactionHash": "c63b60df16c2f13950d7a2f3d406bedd8ae9dc007964dd3a077fcafc7c340b3f", "version": 1, "lockTime": 0, "expiry": 0, "transactionType": 0, "inputsList": [{ "previousTransactionHash": "8225d7548e74455f99ebe1138180be9bc6c9f8538c0ee524adc1507e5637fe2e", "previousTransactionIndex": 1, "tree": 0, "sequence": 4294967295, "amountIn": 0, "blockHeight": 0, "blockIndex": 4294967295, "signatureScript": "47304402205bf2c3da69ef5975928ad2b0d0e6f2aa5c23dc53a24a231fa0ac607d44dcef4a02203f21f9d44d0ddb0fc2baf11bf37c07125cc5dd9955962d8ae7551f037c57f8ba01210207b61cb64e5229caaee985c2c63a542155693aaba209ccf461e5d93685ad6f4b", "signatureScriptAsm": "304402205bf2c3da69ef5975928ad2b0d0e6f2aa5c23dc53a24a231fa0ac607d44dcef4a02203f21f9d44d0ddb0fc2baf11bf37c07125cc5dd9955962d8ae7551f037c57f8ba01 0207b61cb64e5229caaee985c2c63a542155693aaba209ccf461e5d93685ad6f4b" }], "outputsList": [{ "value": 100000, "index": 0, "version": 0, "script": "76a9140262bb5374203f86fa733efbce84ab51450a5f2988ac", "scriptAsm": "OP_DUP OP_HASH160 0262bb5374203f86fa733efbce84ab51450a5f29 OP_EQUALVERIFY OP_CHECKSIG", "requiredSignatures": 1, "scriptClass": 2, "addressesList": ["TsREk6wnD45SU9NoVg4wxcGdZomKhqfshQK"], "commitmentAmount": 0 }, { "value": 109287350, "index": 1, "version": 0, "script": "76a9144124949612dfe1cb06a94cb66a2f290793bf63ac88ac", "scriptAsm": "OP_DUP OP_HASH160 4124949612dfe1cb06a94cb66a2f290793bf63ac OP_EQUALVERIFY OP_CHECKSIG", "requiredSignatures": 1, "scriptClass": 2, "addressesList": ["TsWxaDgS5hA4y8rsZ3e1Dz36G2tVcWWnYmZ"], "commitmentAmount": 0 }] }]); + const mw = new mockWallet( + { "transactionHash": "5a7cda0fb9861a26066cc505bc10d3ba76270c37b49626afcaa47b53602cebe4", "version": 1, "lockTime": 0, "expiry": 0, "transactionType": 0, "inputsList": [{ "previousTransactionHash": "3f0b347cfcca7f073add647900dce98addbe06d4f3a2d75039f1c216df603bc6", "previousTransactionIndex": 1, "tree": 0, "sequence": 4294967295, "amountIn": 109287350, "blockHeight": 0, "blockIndex": 4294967295, "signatureScript": "", "signatureScriptAsm": "" }], "outputsList": [{ "value": 109184820, "index": 0, "version": 0, "script": "76a9148848f6d82e4b221317ff067b3a8094c40fa604f988ac", "scriptAsm": "OP_DUP OP_HASH160 8848f6d82e4b221317ff067b3a8094c40fa604f9 OP_EQUALVERIFY OP_CHECKSIG", "requiredSignatures": 1, "scriptClass": 2, "addressesList": ["TsdSjnHwSfVvJHVJVusbWCmQHhBjY1XHAGU"], "commitmentAmount": 0 }, { "value": 100000, "index": 1, "version": 0, "script": "76a9140262bb5374203f86fa733efbce84ab51450a5f2988ac", "scriptAsm": "OP_DUP OP_HASH160 0262bb5374203f86fa733efbce84ab51450a5f29 OP_EQUALVERIFY OP_CHECKSIG", "requiredSignatures": 1, "scriptClass": 2, "addressesList": ["TsREk6wnD45SU9NoVg4wxcGdZomKhqfshQK"], "commitmentAmount": 0 }] }, + [validateAddreassA, validateAddreassB, validateAddreassC] + ); + const want = { "inputs": [[{ "version": { "type": "Buffer", "data": [1, 0, 0, 0] }, "inputs": [{ "prevout": { "type": "Buffer", "data": [46, 254, 55, 86, 126, 80, 193, 173, 36, 229, 14, 140, 83, 248, 201, 198, 155, 190, 128, 129, 19, 225, 235, 153, 95, 69, 116, 142, 84, 215, 37, 130, 1, 0, 0, 0] }, "script": { "type": "Buffer", "data": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] }, "sequence": { "type": "Buffer", "data": [255, 255, 255, 255] }, "tree": { "type": "Buffer", "data": [0] } }], "outputs": [{ "amount": { "type": "Buffer", "data": [160, 134, 1, 0, 0, 0, 0, 0] }, "script": { "type": "Buffer", "data": [118, 169, 20, 2, 98, 187, 83, 116, 32, 63, 134, 250, 115, 62, 251, 206, 132, 171, 81, 69, 10, 95, 41, 136, 172] } }, { "amount": { "type": "Buffer", "data": [182, 151, 131, 6, 0, 0, 0, 0] }, "script": { "type": "Buffer", "data": [118, 169, 20, 65, 36, 148, 150, 18, 223, 225, 203, 6, 169, 76, 182, 106, 47, 41, 7, 147, 191, 99, 172, 136, 172] } }], "locktime": { "type": "Buffer", "data": [0, 0, 0, 0] }, "nExpiryHeight": { "type": "Buffer", "data": [0, 0, 0, 0] } }, 1]], "associatedKeysets": ["44'/42'/0'/1/46"], "changePath": "44'/42'/0'/1/51", "outputScriptHex": { "type": "Buffer", "data": [2, 52, 7, 130, 6, 0, 0, 0, 0, 0, 0, 25, 118, 169, 20, 136, 72, 246, 216, 46, 75, 34, 19, 23, 255, 6, 123, 58, 128, 148, 196, 15, 166, 4, 249, 136, 172, 160, 134, 1, 0, 0, 0, 0, 0, 0, 0, 25, 118, 169, 20, 2, 98, 187, 83, 116, 32, 63, 134, 250, 115, 62, 251, 206, 132, 171, 81, 69, 10, 95, 41, 136, 172] }, "lockTime": 0, "sigHashType": 1, "segwit": false, "expiryHeight": { "type": "Buffer", "data": [0, 0, 0, 0] }, "useTrustedInputForSegwit": false, "additionals": ["decred"] }; + const data = await signArg(txHex, mw, null, mockGetTxFromInputs); + expect(JSON.stringify(data)).toStrictEqual(JSON.stringify(want)); +}); diff --git a/yarn.lock b/yarn.lock index 1fba9f958b..c0a220ffae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1742,6 +1742,78 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@ledgerhq/devices@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@ledgerhq/devices/-/devices-8.0.2.tgz#8086e9be0185f4925fa611d4d71dc9c141b9b089" + integrity sha512-Qnc9hgGae4YNr/4NUU/5l3xGc5fx6t2k1su6ASu4wsV/p49xmaU/iBO6PtFHqb3QCwsrkieXASU932Ac2WTw0g== + dependencies: + "@ledgerhq/errors" "^6.12.5" + "@ledgerhq/logs" "^6.10.1" + rxjs "6" + semver "^7.3.5" + +"@ledgerhq/errors@^6.12.5": + version "6.12.5" + resolved "https://registry.yarnpkg.com/@ledgerhq/errors/-/errors-6.12.5.tgz#f112b548ab3c4f21bb7fbe77e6cb62998a050992" + integrity sha512-wQlDyKD2lG4hiFmSPvWfuzhbH8wxWG4ugesM17HdZgxUt8g0SluwaBfFJ7Nx0Ym44VIhbsGMUzyBp0hHyCkVqA== + +"@ledgerhq/hw-app-btc@^10.0.2": + version "10.0.2" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-btc/-/hw-app-btc-10.0.2.tgz#56636114f5837a7b9f9ea0961edbce1440cb8cc2" + integrity sha512-jhSgAVQMHAxPZydr8N9h5jHpgBp17FNmOJHpBuEJ3zAdPhS1XXMtUFV+ewg+4d45LD9geP29xgYGACNmFl1Upw== + dependencies: + "@ledgerhq/hw-transport" "^6.28.3" + "@ledgerhq/logs" "^6.10.1" + bip32-path "^0.4.2" + bitcoinjs-lib "^5.2.0" + bs58 "^4.0.1" + bs58check "^2.1.2" + invariant "^2.2.4" + ripemd160 "2" + semver "^7.3.5" + sha.js "2" + tiny-secp256k1 "1.1.6" + varuint-bitcoin "1.1.2" + +"@ledgerhq/hw-transport-node-hid-noevents@^6.27.14": + version "6.27.14" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-noevents/-/hw-transport-node-hid-noevents-6.27.14.tgz#eeb14146e0007163516da73f6dd8afc3ec17bcbf" + integrity sha512-zTckColH6+WRi2ZXdgzjwI+fV6Hfo7+Xf+fC2qAjWZBs8H9h288oXnbaNU2hJQqrKGygN5Y9Qne470dhlRiqqQ== + dependencies: + "@ledgerhq/devices" "^8.0.2" + "@ledgerhq/errors" "^6.12.5" + "@ledgerhq/hw-transport" "^6.28.3" + "@ledgerhq/logs" "^6.10.1" + node-hid "^2.1.2" + +"@ledgerhq/hw-transport-node-hid-singleton@^6.28.11": + version "6.28.11" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-node-hid-singleton/-/hw-transport-node-hid-singleton-6.28.11.tgz#0a503078e837130e1fb6bd0e9c1a99d279c76430" + integrity sha512-W39kgrhPI5Wq2CNyjfwLP9Kj+OUZ4AfNU8NavqKo3jQAkhW6Ke2gAR9TZYYncUZPAEdDeNKRfPXbTFpkZ34weQ== + dependencies: + "@ledgerhq/devices" "^8.0.2" + "@ledgerhq/errors" "^6.12.5" + "@ledgerhq/hw-transport" "^6.28.3" + "@ledgerhq/hw-transport-node-hid-noevents" "^6.27.14" + "@ledgerhq/logs" "^6.10.1" + lodash "^4.17.21" + node-hid "^2.1.2" + usb "2.5.1" + +"@ledgerhq/hw-transport@^6.28.3": + version "6.28.3" + resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-6.28.3.tgz#1108ceb8bfb9dc949f6178b17dd1bcb76dba11f0" + integrity sha512-YFPh9n51V4TfPZov7iAUbtez0cyNEVR1+49RG8tYvmsmk8ihvya2rR90U8KO2MnrT2jR4k2rlgQ3IcZJO9dBcw== + dependencies: + "@ledgerhq/devices" "^8.0.2" + "@ledgerhq/errors" "^6.12.5" + events "^3.3.0" + +"@ledgerhq/logs@^6.10.1": + version "6.10.1" + resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-6.10.1.tgz#5bd16082261d7364eabb511c788f00937dac588d" + integrity sha512-z+ILK8Q3y+nfUl43ctCPuR4Y2bIxk/ooCQFwZxhtci1EhAtMDzMAx2W25qx8G1PPL9UUOdnUax19+F0OjXoj4w== + "@malept/cross-spawn-promise@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz#504af200af6b98e198bce768bc1730c6936ae01d" @@ -2444,6 +2516,11 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-18.11.9.tgz#02d013de7058cea16d36168ef2fc653464cfbad4" integrity sha512-CRpX21/kGdzjOpFsZSkcrXMGIBWMGNIHXXBVFSH+ggkftxg+XYP20TESbh+zFvFj3EQOl5byk0HTRn1IL6hbqg== +"@types/node@10.12.18": + version "10.12.18" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" + integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== + "@types/node@^16.11.26": version "16.18.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-16.18.3.tgz#d7f7ba828ad9e540270f01ce00d391c54e6e0abc" @@ -2565,6 +2642,11 @@ resolved "https://registry.yarnpkg.com/@types/verror/-/verror-1.10.6.tgz#3e600c62d210c5826460858f84bcbb65805460bb" integrity sha512-NNm+gdePAX1VGvPcGZCDKQZKYSiAWigKhKaz5KF94hG6f2s8de9Ow5+7AbXoeKxL8gavZfk4UquSAygOF2duEQ== +"@types/w3c-web-usb@1.0.6": + version "1.0.6" + resolved "https://registry.yarnpkg.com/@types/w3c-web-usb/-/w3c-web-usb-1.0.6.tgz#5d8560d0d9f585ffc80865bc773db7bc975b680c" + integrity sha512-cSjhgrr8g4KbPnnijAr/KJDNKa/bBa+ixYkywFRvrhvi9n1WEl7yYbtRyzE6jqNQiSxxJxoAW3STaOQwJHndaw== + "@types/ws@^7.2.0": version "7.4.7" resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" @@ -3505,6 +3587,11 @@ bchaddrjs@^0.5.2: cashaddrjs "0.4.4" stream-browserify "^3.0.0" +bech32@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/bech32/-/bech32-1.1.4.tgz#e38c9f37bf179b8eb16ae3a772b40c356d4832e9" + integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ== + bech32@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bech32/-/bech32-2.0.0.tgz#078d3686535075c8c79709f054b1b226a133b355" @@ -3530,7 +3617,7 @@ bignumber.js@^9.0.0, bignumber.js@^9.0.1: resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.1.0.tgz#8d340146107fe3a6cb8d40699643c302e8773b62" integrity sha512-4LwHK4nfDOraBCtst+wOWIHbu1vhvAPJK8g8nROd4iuc3PSEjWif/qwbkh8jwCJz6yDBvtU4KPynETgrfh7y3A== -bindings@^1.3.0: +bindings@^1.3.0, bindings@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== @@ -3542,18 +3629,62 @@ bindings@~1.2.1: resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.2.1.tgz#14ad6113812d2d37d72e67b4cacb4bb726505f11" integrity sha512-u4cBQNepWxYA55FunZSM7wMi55yQaN0otnhhilNoWHq0MfOfJeQx0v0mRRpolGOExPjZcl6FtB0BB8Xkb88F0g== -bip66@^1.1.5: +bip174@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/bip174/-/bip174-2.1.0.tgz#cd3402581feaa5116f0f00a0eaee87a5843a2d30" + integrity sha512-lkc0XyiX9E9KiVAS1ZiOqK1xfiwvf4FXDDdkDq5crcDzOq+xGytY+14qCsqz7kCiy8rpN1CRNfacRhf9G3JNSA== + +bip32-path@^0.4.2: + version "0.4.2" + resolved "https://registry.yarnpkg.com/bip32-path/-/bip32-path-0.4.2.tgz#5db0416ad6822712f077836e2557b8697c0c7c99" + integrity sha512-ZBMCELjJfcNMkz5bDuJ1WrYvjlhEF5k6mQ8vUr4N7MbVRsXei7ZOg8VhhwMfNiW68NWmLkgkc6WvTickrLGprQ== + +bip32@^2.0.4: + version "2.0.6" + resolved "https://registry.yarnpkg.com/bip32/-/bip32-2.0.6.tgz#6a81d9f98c4cd57d05150c60d8f9e75121635134" + 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" + +bip66@^1.1.0, bip66@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" integrity sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw== dependencies: safe-buffer "^5.0.1" -bitcoin-ops@^1.3.0, bitcoin-ops@^1.4.1: +bitcoin-ops@^1.3.0, bitcoin-ops@^1.4.0, bitcoin-ops@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz#e45de620398e22fd4ca6023de43974ff42240278" integrity sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow== +bitcoinjs-lib@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/bitcoinjs-lib/-/bitcoinjs-lib-5.2.0.tgz#caf8b5efb04274ded1b67e0706960b93afb9d332" + 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" + typeforce "^1.11.3" + varuint-bitcoin "^1.0.4" + wif "^2.0.1" + bl@^4.0.3, bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -3767,7 +3898,7 @@ bs58@^4.0.0, bs58@^4.0.1: dependencies: base-x "^3.0.2" -bs58check@2.1.2, bs58check@<3.0.0, bs58check@^2.1.1, bs58check@^2.1.2: +bs58check@2.1.2, bs58check@<3.0.0, bs58check@^2.0.0, bs58check@^2.1.1, bs58check@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-2.1.2.tgz#53b018291228d82a5aa08e7d796fdafda54aebfc" integrity sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA== @@ -4606,7 +4737,7 @@ create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0: ripemd160 "^2.0.1" sha.js "^2.4.0" -create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.0, create-hmac@^1.1.3, create-hmac@^1.1.4, create-hmac@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== @@ -7356,6 +7487,13 @@ intl-messageformat@^7.8.4: intl-format-cache "^4.2.21" intl-messageformat-parser "^3.6.4" +invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + ip@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ip/-/ip-2.0.0.tgz#4cf4ab182fee2314c75ede1276f8c80b479936da" @@ -9037,6 +9175,11 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== +merkle-lib@^2.0.10: + version "2.0.10" + resolved "https://registry.yarnpkg.com/merkle-lib/-/merkle-lib-2.0.10.tgz#82b8dbae75e27a7785388b73f9d7725d0f6f3326" + integrity sha512-XrNQvUbn1DL5hKNe46Ccs+Tu3/PYOlrcZILuGUhb95oKBPjc/nmIC8D462PQkipVDGKRvwhn+QFg2cCdIvmDJA== + methods@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" @@ -9459,6 +9602,13 @@ node-abi@^3.0.0: dependencies: semver "^7.3.5" +node-abi@^3.3.0: + version "3.40.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.40.0.tgz#51d8ed44534f70ff1357dfbc3a89717b1ceac1b4" + integrity sha512-zNy02qivjjRosswoYmPi8hIKJRr8MpQyeKT6qlcq/OnOgA3Rhoae+IYOqsM9V5+JnHWmxKnWOT2GxvtqdtOCXA== + dependencies: + semver "^7.3.5" + node-addon-api@^1.6.3: version "1.7.2" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.2.tgz#3df30b95720b53c24e59948b49532b662444f54d" @@ -9469,11 +9619,16 @@ node-addon-api@^2.0.0: resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.2.tgz#432cfa82962ce494b132e9d72a15b29f71ff5d32" integrity sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA== -node-addon-api@^3.0.0, node-addon-api@^3.1.0: +node-addon-api@^3.0.0, node-addon-api@^3.0.2, node-addon-api@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-3.2.1.tgz#81325e0a2117789c0128dab65e7e38f07ceba161" integrity sha512-mmcei9JghVNDYydghQmeDX8KoAm0FAiYyIcUt/N4nhyAipB17pllZQDOJD2fotxABnt4Mdz+dKTO7eftLg4d0A== +node-addon-api@^4.2.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-4.3.0.tgz#52a1a0b475193e0928e98e0426a0d1254782b77f" + integrity sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ== + node-api-version@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/node-api-version/-/node-api-version-0.1.4.tgz#1ed46a485e462d55d66b5aa1fe2821720dedf080" @@ -9509,6 +9664,15 @@ node-gyp@^9.0.0: tar "^6.1.2" which "^2.0.2" +node-hid@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/node-hid/-/node-hid-2.1.2.tgz#3145fa86ed4336a402a71e9f372c54213b88797c" + integrity sha512-qhCyQqrPpP93F/6Wc/xUR7L8mAJW0Z6R7HMQV8jCHHksAxNDe/4z4Un/H9CpLOT+5K39OPyt9tIQlavxWES3lg== + dependencies: + bindings "^1.5.0" + node-addon-api "^3.0.2" + prebuild-install "^7.1.1" + node-int64@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/node-int64/-/node-int64-0.4.0.tgz#87a9065cdb355d3182d8f94ce11188b825c68a3b" @@ -10632,6 +10796,24 @@ prebuild-install@^5.3.4: tunnel-agent "^0.6.0" which-pm-runs "^1.0.0" +prebuild-install@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.1.tgz#de97d5b34a70a0c81334fd24641f2a1702352e45" + integrity sha512-jAXscXWMcCK8GgCoHOfIr0ODh5ai8mj63L2nWrjuAgXE6tDyYGnx4/8o/rCgU+B4JSyZBKbeZqzhtwtC3ovxjw== + dependencies: + detect-libc "^2.0.0" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^1.0.1" + node-abi "^3.3.0" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + precinct@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/precinct/-/precinct-7.1.0.tgz#a0311e0b59029647eaf57c2d30b8efa9c85d129a" @@ -11743,7 +11925,7 @@ rimraf@~2.6.2: dependencies: glob "^7.1.3" -ripemd160@^2.0.0, ripemd160@^2.0.1: +ripemd160@2, ripemd160@^2.0.0, ripemd160@^2.0.1: version "2.0.2" resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== @@ -11844,6 +12026,13 @@ runtypes@^6.5.1: resolved "https://registry.yarnpkg.com/runtypes/-/runtypes-6.6.0.tgz#48e353d8b0f641ab5ec5d80fa96dd7bd41ea3281" integrity sha512-ddM7sgB3fyboDlBzEYFQ04L674sKjbs4GyW2W32N/5Ae47NRd/GyMASPC2PFw8drPHYGEcZ0mZ26r5RcB8msfQ== +rxjs@6: + version "6.6.7" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.6.7.tgz#90ac018acabf491bf65044235d5863c4dab804c9" + integrity sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ== + dependencies: + tslib "^1.9.0" + safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@^5.2.0, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -12075,7 +12264,7 @@ setprototypeof@1.2.0: resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.2.0.tgz#66c9a24a73f9fc28cbe66b09fed3d33dcaf1b424" integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw== -sha.js@^2.4.0, sha.js@^2.4.8: +sha.js@2, sha.js@^2.4.0, sha.js@^2.4.8: version "2.4.11" resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== @@ -12165,6 +12354,15 @@ simple-get@^3.0.3: once "^1.3.1" simple-concat "^1.0.0" +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed" @@ -12851,7 +13049,7 @@ tiny-invariant@^1.0.2: resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.3.1.tgz#8560808c916ef02ecfd55e66090df23a4b7aa642" integrity sha512-AD5ih2NlSssTCwsMznbvwMZpJ1cbhkGd2uueNxzv2jDlEeZdU04JQfRnggJQ8DrcVBGjAsCKwFBbDlVNtEMlzw== -tiny-secp256k1@^1.1.6: +tiny-secp256k1@1.1.6, tiny-secp256k1@^1.1.1, tiny-secp256k1@^1.1.3, tiny-secp256k1@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/tiny-secp256k1/-/tiny-secp256k1-1.1.6.tgz#7e224d2bee8ab8283f284e40e6b4acb74ffe047c" integrity sha512-FmqJZGduTyvsr2cF3375fqGHUovSwDi/QytexX1Se4BPuPZpTE5Ftp5fg+EFSuEf3lhZqgCRjEG3ydUQ/aNiwA== @@ -13009,7 +13207,7 @@ tsconfig-paths@^3.10.1: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^1.8.1: +tslib@^1.8.1, tslib@^1.9.0: version "1.14.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== @@ -13112,7 +13310,7 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== -typeforce@^1.18.0: +typeforce@^1.11.3, typeforce@^1.11.5, typeforce@^1.18.0: version "1.18.0" resolved "https://registry.yarnpkg.com/typeforce/-/typeforce-1.18.0.tgz#d7416a2c5845e085034d70fcc5b6cc4a90edbfdc" integrity sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g== @@ -13359,6 +13557,15 @@ url@^0.11.0: punycode "1.3.2" querystring "0.2.0" +usb@2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/usb/-/usb-2.5.1.tgz#27550f078a785144fbc19b5f6664742a066b961f" + integrity sha512-/VNr4wUL32KVqyrVJ1HGBhDEvklhouVh+8ehIGKv6FsOKz6MWlkYLLAEyXbRo72HXhhiFNj6bwz6L+bIk8F0Yw== + dependencies: + "@types/w3c-web-usb" "1.0.6" + node-addon-api "^4.2.0" + node-gyp-build "^4.3.0" + use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" @@ -13434,7 +13641,7 @@ value-equal@^1.0.1: resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== -varuint-bitcoin@^1.1.2: +varuint-bitcoin@1.1.2, varuint-bitcoin@^1.0.4, varuint-bitcoin@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-1.1.2.tgz#e76c138249d06138b480d4c5b40ef53693e24e92" integrity sha512-4EVb+w4rx+YfVM32HQX42AbbT7/1f5zwAYhIujKXKk8NQK+JfRVl3pqT3hjNn/L+RstigmGGKVwHA/P0wgITZw== @@ -13747,7 +13954,7 @@ widest-line@^3.1.0: dependencies: string-width "^4.0.0" -wif@^2.0.6: +wif@^2.0.1, wif@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/wif/-/wif-2.0.6.tgz#08d3f52056c66679299726fade0d432ae74b4704" integrity sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==