From e181f594340046db11349b54267253c5c7a478b6 Mon Sep 17 00:00:00 2001 From: highlander Date: Mon, 9 Mar 2026 16:48:09 -0600 Subject: [PATCH 1/3] chore: remove hdwallet-native and hdwallet-native-vault packages Remove unused native wallet packages that caused FIO type build errors. Fix pre-existing TypeScript errors (ethers import, ArrayBuffer casts). Clean up all native references from integration tests. --- integration/package.json | 1 - integration/src/bitcoin/bitcoin.ts | 13 - integration/src/fio/fio.ts | 424 ----- integration/src/fio/index.ts | 7 - integration/src/fio/tx01.unsigned.json | 35 - integration/src/fio/tx02.signed.json | 0 integration/src/integration.ts | 14 +- integration/src/wallets/native.ts | 518 ------ package.json | 2 +- .../src/transport.ts | 2 +- .../hdwallet-keepkey-webusb/src/transport.ts | 2 +- packages/hdwallet-keepkey/src/ethereum.ts | 23 +- packages/hdwallet-keepkey/src/transport.ts | 2 +- packages/hdwallet-native-vault/.npmignore | 4 - packages/hdwallet-native-vault/jest.config.js | 6 - packages/hdwallet-native-vault/package.json | 31 - .../src/deterministicGetRandomValues.test.ts | 61 - .../hdwallet-native-vault/src/index.test.ts | 222 --- packages/hdwallet-native-vault/src/index.ts | 19 - .../hdwallet-native-vault/src/mapVault.ts | 87 - .../hdwallet-native-vault/src/rawVault.ts | 273 ---- .../src/test/mockVault.skip.ts | 145 -- packages/hdwallet-native-vault/src/types.ts | 68 - packages/hdwallet-native-vault/src/util.ts | 83 - packages/hdwallet-native-vault/src/vault.ts | 198 --- packages/hdwallet-native-vault/tsconfig.json | 10 - packages/hdwallet-native/.npmignore | 4 - .../__mocks__/@shapeshiftoss/hdwallet-core.ts | 8 - packages/hdwallet-native/__mocks__/mswMock.ts | 62 - .../__mocks__/untouchableMock.ts | 47 - packages/hdwallet-native/jest.config.js | 4 - packages/hdwallet-native/package.json | 59 - packages/hdwallet-native/src/adapter.test.ts | 29 - packages/hdwallet-native/src/adapter.ts | 53 - packages/hdwallet-native/src/arkeo.test.ts | 88 -- packages/hdwallet-native/src/arkeo.ts | 99 -- packages/hdwallet-native/src/bitcoin.test.ts | 481 ------ packages/hdwallet-native/src/bitcoin.ts | 388 ----- packages/hdwallet-native/src/cosmos.test.ts | 92 -- packages/hdwallet-native/src/cosmos.ts | 100 -- .../src/crypto/CryptoHelper.test.ts | 212 --- .../src/crypto/CryptoHelper.ts | 174 -- .../src/crypto/EncryptedWallet.test.ts | 180 --- .../src/crypto/EncryptedWallet.ts | 141 -- .../src/crypto/classes/cipherString.test.ts | 63 - .../src/crypto/classes/cipherString.ts | 61 - .../src/crypto/classes/encryptedObject.ts | 33 - .../src/crypto/classes/encryptionType.ts | 6 - .../src/crypto/classes/index.ts | 4 - .../crypto/classes/symmetricCryptoKey.test.ts | 43 - .../src/crypto/classes/symmetricCryptoKey.ts | 33 - .../src/crypto/engines/index.ts | 2 - .../src/crypto/engines/types.ts | 26 - .../src/crypto/engines/web-crypto.test.ts | 157 -- .../src/crypto/engines/web-crypto.ts | 64 - packages/hdwallet-native/src/crypto/index.ts | 3 - .../src/crypto/isolation/adapters/bip32.ts | 167 -- .../src/crypto/isolation/adapters/bitcoin.ts | 98 -- .../src/crypto/isolation/adapters/cosmos.ts | 27 - .../crypto/isolation/adapters/cosmosDirect.ts | 58 - .../src/crypto/isolation/adapters/ethereum.ts | 99 -- .../src/crypto/isolation/adapters/fio.ts | 52 - .../src/crypto/isolation/adapters/index.ts | 6 - .../src/crypto/isolation/core/bip32/index.ts | 31 - .../crypto/isolation/core/bip32/interfaces.ts | 20 - .../src/crypto/isolation/core/bip32/types.ts | 16 - .../src/crypto/isolation/core/bip39/index.ts | 1 - .../crypto/isolation/core/bip39/interfaces.ts | 6 - .../isolation/core/digest/algorithms.ts | 57 - .../isolation/core/digest/index.test.ts | 39 - .../src/crypto/isolation/core/digest/index.ts | 2 - .../src/crypto/isolation/core/digest/types.ts | 113 -- .../src/crypto/isolation/core/index.ts | 15 - .../crypto/isolation/core/secp256k1/index.ts | 2 - .../isolation/core/secp256k1/interfaces.ts | 58 - .../crypto/isolation/core/secp256k1/types.ts | 317 ---- .../crypto/isolation/engines/default/bip32.ts | 186 --- .../crypto/isolation/engines/default/bip39.ts | 45 - .../isolation/engines/default/index.test.ts | 78 - .../crypto/isolation/engines/default/index.ts | 3 - .../isolation/engines/default/revocable.ts | 126 -- .../crypto/isolation/engines/dummy/bip32.ts | 118 -- .../crypto/isolation/engines/dummy/bip39.ts | 72 - .../isolation/engines/dummy/index.test.ts | 93 -- .../crypto/isolation/engines/dummy/index.ts | 3 - .../crypto/isolation/engines/dummy/types.ts | 22 - .../src/crypto/isolation/engines/index.ts | 2 - .../src/crypto/isolation/index.ts | 3 - .../src/crypto/isolation/types.ts | 163 -- .../hdwallet-native/src/crypto/utils.test.ts | 38 - packages/hdwallet-native/src/crypto/utils.ts | 17 - packages/hdwallet-native/src/ethereum.test.ts | 296 ---- packages/hdwallet-native/src/ethereum.ts | 149 -- packages/hdwallet-native/src/fio.test.ts | 281 ---- packages/hdwallet-native/src/fio.ts | 272 ---- packages/hdwallet-native/src/index.test.ts | 11 - packages/hdwallet-native/src/index.ts | 3 - packages/hdwallet-native/src/kava.test.ts | 76 - packages/hdwallet-native/src/kava.ts | 90 -- .../hdwallet-native/src/mayachain.test.ts | 88 -- packages/hdwallet-native/src/mayachain.ts | 100 -- packages/hdwallet-native/src/modules.d.ts | 116 -- packages/hdwallet-native/src/native.test.ts | 506 ------ packages/hdwallet-native/src/native.ts | 455 ------ packages/hdwallet-native/src/networks.test.ts | 29 - packages/hdwallet-native/src/networks.ts | 196 --- packages/hdwallet-native/src/osmosis.test.ts | 92 -- packages/hdwallet-native/src/osmosis.ts | 99 -- packages/hdwallet-native/src/secret.test.ts | 74 - packages/hdwallet-native/src/secret.ts | 95 -- packages/hdwallet-native/src/terra.test.ts | 74 - packages/hdwallet-native/src/terra.ts | 90 -- .../hdwallet-native/src/thorchain.test.ts | 88 -- packages/hdwallet-native/src/thorchain.ts | 100 -- packages/hdwallet-native/src/util.test.ts | 21 - packages/hdwallet-native/src/util.ts | 31 - packages/hdwallet-native/tsconfig.json | 11 - tsconfig.json | 3 +- yarn.lock | 1399 +---------------- 119 files changed, 85 insertions(+), 11879 deletions(-) delete mode 100644 integration/src/fio/fio.ts delete mode 100644 integration/src/fio/index.ts delete mode 100644 integration/src/fio/tx01.unsigned.json delete mode 100644 integration/src/fio/tx02.signed.json delete mode 100644 integration/src/wallets/native.ts delete mode 100644 packages/hdwallet-native-vault/.npmignore delete mode 100644 packages/hdwallet-native-vault/jest.config.js delete mode 100644 packages/hdwallet-native-vault/package.json delete mode 100644 packages/hdwallet-native-vault/src/deterministicGetRandomValues.test.ts delete mode 100644 packages/hdwallet-native-vault/src/index.test.ts delete mode 100644 packages/hdwallet-native-vault/src/index.ts delete mode 100644 packages/hdwallet-native-vault/src/mapVault.ts delete mode 100644 packages/hdwallet-native-vault/src/rawVault.ts delete mode 100644 packages/hdwallet-native-vault/src/test/mockVault.skip.ts delete mode 100644 packages/hdwallet-native-vault/src/types.ts delete mode 100644 packages/hdwallet-native-vault/src/util.ts delete mode 100644 packages/hdwallet-native-vault/src/vault.ts delete mode 100644 packages/hdwallet-native-vault/tsconfig.json delete mode 100644 packages/hdwallet-native/.npmignore delete mode 100644 packages/hdwallet-native/__mocks__/@shapeshiftoss/hdwallet-core.ts delete mode 100644 packages/hdwallet-native/__mocks__/mswMock.ts delete mode 100644 packages/hdwallet-native/__mocks__/untouchableMock.ts delete mode 100644 packages/hdwallet-native/jest.config.js delete mode 100644 packages/hdwallet-native/package.json delete mode 100644 packages/hdwallet-native/src/adapter.test.ts delete mode 100644 packages/hdwallet-native/src/adapter.ts delete mode 100644 packages/hdwallet-native/src/arkeo.test.ts delete mode 100644 packages/hdwallet-native/src/arkeo.ts delete mode 100644 packages/hdwallet-native/src/bitcoin.test.ts delete mode 100644 packages/hdwallet-native/src/bitcoin.ts delete mode 100644 packages/hdwallet-native/src/cosmos.test.ts delete mode 100644 packages/hdwallet-native/src/cosmos.ts delete mode 100644 packages/hdwallet-native/src/crypto/CryptoHelper.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/CryptoHelper.ts delete mode 100644 packages/hdwallet-native/src/crypto/EncryptedWallet.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/EncryptedWallet.ts delete mode 100644 packages/hdwallet-native/src/crypto/classes/cipherString.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/classes/cipherString.ts delete mode 100644 packages/hdwallet-native/src/crypto/classes/encryptedObject.ts delete mode 100644 packages/hdwallet-native/src/crypto/classes/encryptionType.ts delete mode 100644 packages/hdwallet-native/src/crypto/classes/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/classes/symmetricCryptoKey.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/classes/symmetricCryptoKey.ts delete mode 100644 packages/hdwallet-native/src/crypto/engines/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/engines/types.ts delete mode 100644 packages/hdwallet-native/src/crypto/engines/web-crypto.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/engines/web-crypto.ts delete mode 100644 packages/hdwallet-native/src/crypto/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/adapters/bip32.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/adapters/bitcoin.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/adapters/cosmos.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/adapters/cosmosDirect.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/adapters/ethereum.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/adapters/fio.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/adapters/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/bip32/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/bip32/interfaces.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/bip32/types.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/bip39/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/bip39/interfaces.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/digest/algorithms.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/digest/index.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/digest/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/digest/types.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/secp256k1/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/secp256k1/interfaces.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/core/secp256k1/types.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/default/bip32.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/default/bip39.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/default/index.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/default/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/default/revocable.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/dummy/bip32.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/dummy/bip39.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/dummy/index.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/dummy/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/dummy/types.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/engines/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/index.ts delete mode 100644 packages/hdwallet-native/src/crypto/isolation/types.ts delete mode 100644 packages/hdwallet-native/src/crypto/utils.test.ts delete mode 100644 packages/hdwallet-native/src/crypto/utils.ts delete mode 100644 packages/hdwallet-native/src/ethereum.test.ts delete mode 100644 packages/hdwallet-native/src/ethereum.ts delete mode 100644 packages/hdwallet-native/src/fio.test.ts delete mode 100644 packages/hdwallet-native/src/fio.ts delete mode 100644 packages/hdwallet-native/src/index.test.ts delete mode 100644 packages/hdwallet-native/src/index.ts delete mode 100644 packages/hdwallet-native/src/kava.test.ts delete mode 100644 packages/hdwallet-native/src/kava.ts delete mode 100644 packages/hdwallet-native/src/mayachain.test.ts delete mode 100644 packages/hdwallet-native/src/mayachain.ts delete mode 100644 packages/hdwallet-native/src/modules.d.ts delete mode 100644 packages/hdwallet-native/src/native.test.ts delete mode 100644 packages/hdwallet-native/src/native.ts delete mode 100644 packages/hdwallet-native/src/networks.test.ts delete mode 100644 packages/hdwallet-native/src/networks.ts delete mode 100644 packages/hdwallet-native/src/osmosis.test.ts delete mode 100644 packages/hdwallet-native/src/osmosis.ts delete mode 100644 packages/hdwallet-native/src/secret.test.ts delete mode 100644 packages/hdwallet-native/src/secret.ts delete mode 100644 packages/hdwallet-native/src/terra.test.ts delete mode 100644 packages/hdwallet-native/src/terra.ts delete mode 100644 packages/hdwallet-native/src/thorchain.test.ts delete mode 100644 packages/hdwallet-native/src/thorchain.ts delete mode 100644 packages/hdwallet-native/src/util.test.ts delete mode 100644 packages/hdwallet-native/src/util.ts delete mode 100644 packages/hdwallet-native/tsconfig.json diff --git a/integration/package.json b/integration/package.json index 134388d6..ec4e6971 100644 --- a/integration/package.json +++ b/integration/package.json @@ -4,7 +4,6 @@ "@keepkey/hdwallet-keepkey": "1.53.16", "@keepkey/hdwallet-keepkey-nodewebusb": "1.53.16", "@keepkey/hdwallet-keepkey-tcp": "1.53.16", - "@keepkey/hdwallet-native": "1.53.16", "fast-json-stable-stringify": "^2.1.0", "msw": "^0.27.1", "whatwg-fetch": "^3.6.2" diff --git a/integration/src/bitcoin/bitcoin.ts b/integration/src/bitcoin/bitcoin.ts index e788ea68..8cc94c5d 100644 --- a/integration/src/bitcoin/bitcoin.ts +++ b/integration/src/bitcoin/bitcoin.ts @@ -1,5 +1,4 @@ import * as core from "@keepkey/hdwallet-core"; -import * as native from "@keepkey/hdwallet-native"; import { each } from "../utils"; @@ -360,10 +359,6 @@ export function bitcoinTests(get: () => { wallet: core.HDWallet; info: core.HDWa async () => { if (!wallet) return; - // not implemented for native - if (native.isNative(wallet)) { - return; - } const res = wallet.btcSignMessage({ addressNList: core.bip32ToAddressNList("m/44'/0'/0'/0/0"), @@ -386,10 +381,6 @@ export function bitcoinTests(get: () => { wallet: core.HDWallet; info: core.HDWa async () => { if (!wallet) return; - // not implemented for native - if (native.isNative(wallet)) { - return; - } const res = await wallet.btcVerifyMessage({ address: "1FH6ehAd5ZFXCM1cLGzHxK1s4dGdq1JusM", @@ -409,10 +400,6 @@ export function bitcoinTests(get: () => { wallet: core.HDWallet; info: core.HDWa async () => { if (!wallet) return; - // not implemented for native - if (native.isNative(wallet)) { - return; - } const res = await wallet.btcVerifyMessage({ address: "1FH6ehAd5ZFXCM1cLGzHxK1s4dGdq1JusM", diff --git a/integration/src/fio/fio.ts b/integration/src/fio/fio.ts deleted file mode 100644 index ebdd92e6..00000000 --- a/integration/src/fio/fio.ts +++ /dev/null @@ -1,424 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -// TODO: Use these test TXs for something? -// import * as tx01_unsigned from "./tx01.unsigned.json"; -// import * as tx02_signed from "./tx02.signed.json"; - -const MNEMONIC12_NOPIN_NOPASSPHRASE = "alcohol woman abuse must during monitor noble actual mixed trade anger aisle"; -const MNEMONIC12_NOPIN_NOPASSPHRASE2 = "all all all all all all all all all all all all"; - -const TIMEOUT = 60 * 1000; - -export function fioTests(get: () => { wallet: core.HDWallet; info: core.HDWalletInfo; wallet2: core.HDWallet }): void { - let wallet: core.FioWallet & core.HDWallet; - let wallet2: core.FioWallet & core.HDWallet; - - describe("Fio", () => { - beforeAll(async () => { - const { wallet: w, wallet2: w2 } = get(); - if (core.supportsFio(w)) wallet = w; - if (core.supportsFio(w2)) wallet2 = w2; - }); - - beforeEach(async () => { - if (!wallet) return; - if (!wallet2) return; - await wallet.wipe(); - await wallet.loadDevice({ - mnemonic: MNEMONIC12_NOPIN_NOPASSPHRASE, - label: "test", - skipChecksum: true, - }); - await wallet2.wipe(); - await wallet2.loadDevice({ - mnemonic: MNEMONIC12_NOPIN_NOPASSPHRASE2, - label: "test2", - skipChecksum: true, - }); - }, TIMEOUT); - - /* - Get FIO Address - - */ - test( - "fioGetAddress()", - async () => { - if (!wallet) return; - await expect( - wallet.fioGetAddress({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - showDisplay: false, - }) - ).resolves.toEqual("FIO6iLE1J4zb2SyDGTH9d6UL9Qm6hhqRce27QvP8AKxVLASGhtm7z"); - - if (!wallet2) return; - await expect( - wallet2.fioGetAddress({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - showDisplay: false, - }) - ).resolves.toEqual("FIO5NSKecB4CcMpUxtpHzG4u43SmcGMAjRbxyG38rE4HPegGpaHu9"); - }, - TIMEOUT - ); - - /* - Transfer FIO tokens - - */ - test( - "fioSignTransferTokenTx()", - async () => { - if (!wallet) return; - const res = await wallet.fioSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - actions: [ - { - account: "fio.token", - name: "trnsfiopubky", - data: { - payee_public_key: "FIO7MpYCsLfjPGgXg8Sv7usGAw6RnFV3W6HTz1UP6HvodNXSAZiDp", - amount: "1000000000", - max_fee: 800000000000, - tpid: "", - }, - }, - ], - }); - - expect(res).toHaveProperty("signature"); - expect(res).toHaveProperty("serialized"); - }, - TIMEOUT - ); - - /* - Add pubkey to FIO account - - */ - test( - "fioSignAddPubAddressTx()", - async () => { - if (!wallet) return; - const res = await wallet.fioSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - actions: [ - { - account: "fio.address", - name: "addaddress", - data: { - fio_address: "test@shapeshift", - public_addresses: [ - { - chain_code: "ETH", - token_code: "ETH", - public_address: "0x3f2329c9adfbccd9a84f52c906e936a42da18cb8", - }, - ], - max_fee: 800000000000, - tpid: "", - }, - }, - ], - }); - - expect(res).toHaveProperty("signature"); - expect(res).toHaveProperty("serialized"); - }, - TIMEOUT - ); - - /* - Register FIO address - - */ - test( - "fioSignRegisterFioAddressTx()", - async () => { - if (!wallet) return; - const res = await wallet.fioSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - actions: [ - { - account: "fio.address", - name: "regaddress", - data: { - fio_address: "test@shapeshift", - owner_fio_public_key: "FIO7MpYCsLfjPGgXg8Sv7usGAw6RnFV3W6HTz1UP6HvodNXSAZiDp", - max_fee: 800000000000, - tpid: "", - }, - }, - ], - }); - - expect(res).toHaveProperty("signature"); - expect(res).toHaveProperty("serialized"); - }, - TIMEOUT - ); - - /* - Create payment request - - */ - test( - "fioSignNewFundsRequestTx()", - async () => { - if (!wallet) return; - - const res = await wallet.fioSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - actions: [ - { - account: "fio.reqobt", - name: "newfundsreq", - data: { - payer_fio_address: "highlander@scatter", - payee_fio_address: "test@shapeshift", - content: core.mustBeDefined( - await wallet.fioEncryptRequestContent({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - content: { - payee_public_address: "test@shapeshift", - amount: "1", - chain_code: "FIO", - token_code: "FIO", - memo: "memo", - hash: "hash", - offline_url: "offline_url", - }, - publicKey: "FIO6Lxx7BTA8zbgPuqn4QidNNdTCHisXU7RpxJxLwxAka7NV7SoBW", - contentType: core.FioEncryptionContentType.REQUEST, - }) - ), - max_fee: 800000000000, - tpid: "", - }, - }, - ], - }); - - expect(res).toHaveProperty("signature"); - expect(res).toHaveProperty("serialized"); - }, - TIMEOUT - ); - - /* - Accept payment request - - */ - test( - "fioRecordObtDataTx()", - async () => { - if (!wallet) return; - - const res = await wallet.fioSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - actions: [ - { - account: "fio.reqobt", - name: "recordobt", - data: { - payee_fio_address: "test@shapeshift", - payer_fio_address: "highlander@scatter", - content: core.mustBeDefined( - await wallet.fioEncryptRequestContent({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - content: { - payee_public_address: "test@shapeshift", - payer_public_address: "highlander@scatter", - amount: "1", - chain_code: "FIO", - token_code: "FIO", - memo: "memo", - hash: "hash", - status: "", - obt_id: "", - offline_url: "offline_url", - }, - publicKey: "FIO6iLE1J4zb2SyDGTH9d6UL9Qm6hhqRce27QvP8AKxVLASGhtm7z", - contentType: core.FioEncryptionContentType.OBT, - }) - ), - fio_request_id: "17501", - max_fee: 800000000000, - tpid: "", - actor: "", - }, - }, - ], - }); - - expect(res).toHaveProperty("signature"); - expect(res).toHaveProperty("serialized"); - }, - TIMEOUT - ); - - /* - Reject payment request - - */ - test( - "fioRejectFundsRequestTx()", - async () => { - if (!wallet) return; - - const res = await wallet.fioSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - actions: [ - { - account: "fio.reqobt", - name: "rejectfndreq", - data: { - fio_request_id: "17501", - max_fee: 800000000000, - tpid: "", - }, - }, - ], - }); - - expect(res).toHaveProperty("signature"); - expect(res).toHaveProperty("serialized"); - }, - TIMEOUT - ); - - /* - Register FIO domain - - */ - test( - "fioSignRegisterDomainTx()", - async () => { - if (!wallet) return; - const res = await wallet.fioSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - actions: [ - { - account: "fio.address", - name: "regdomain", - data: { - fio_domain: "fox", - owner_fio_public_key: "FIO7MpYCsLfjPGgXg8Sv7usGAw6RnFV3W6HTz1UP6HvodNXSAZiDp", - max_fee: 800000000000, - tpid: "", - }, - }, - ], - }); - - expect(res).toHaveProperty("signature"); - expect(res).toHaveProperty("serialized"); - }, - TIMEOUT - ); - - /* - Encrypt/decrypt request content object - - */ - test( - "fioEncryptDecryptRequestContent()", - async () => { - if (!wallet) return; - if (!wallet2) return; - const originalContent = { - payee_public_address: "purse.alice", - amount: "1", - chain_code: "FIO", - token_code: "FIO", - memo: "memo", - hash: "hash", - offline_url: "offline_url", - }; - const walletPk = core.mustBeDefined( - await wallet.fioGetAddress({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - showDisplay: false, - }) - ); - const wallet2Pk = core.mustBeDefined( - await wallet2.fioGetAddress({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - showDisplay: false, - }) - ); - - const encryptedContent = core.mustBeDefined( - await wallet.fioEncryptRequestContent({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - content: originalContent, - publicKey: wallet2Pk, - contentType: core.FioEncryptionContentType.REQUEST, - }) - ); - const decryptedContent = core.mustBeDefined( - await wallet2.fioDecryptRequestContent({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - content: encryptedContent, - publicKey: walletPk, - contentType: core.FioEncryptionContentType.REQUEST, - }) - ); - expect(originalContent).toEqual(decryptedContent); - }, - TIMEOUT - ); - - test( - "fioEncryptDecryptObtContent()", - async () => { - if (!wallet) return; - if (!wallet2) return; - const originalContent = { - payee_public_address: "purse.alice", - payer_public_address: "purse.bob", - amount: "1", - chain_code: "FIO", - token_code: "FIO", - status: "status", - obt_id: "0x12345", - memo: "memo", - hash: "hash", - offline_url: "offline_url", - }; - const walletPk = core.mustBeDefined( - await wallet.fioGetAddress({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - showDisplay: false, - }) - ); - const wallet2Pk = core.mustBeDefined( - await wallet2.fioGetAddress({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - showDisplay: false, - }) - ); - - const encryptedContent = core.mustBeDefined( - await wallet.fioEncryptRequestContent({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - content: originalContent, - publicKey: wallet2Pk, - contentType: core.FioEncryptionContentType.OBT, - }) - ); - const decryptedContent = core.mustBeDefined( - await wallet2.fioDecryptRequestContent({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - content: encryptedContent, - publicKey: walletPk, - contentType: core.FioEncryptionContentType.OBT, - }) - ); - expect(originalContent).toEqual(decryptedContent); - }, - TIMEOUT - ); - }); -} diff --git a/integration/src/fio/index.ts b/integration/src/fio/index.ts deleted file mode 100644 index d183b937..00000000 --- a/integration/src/fio/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import { fioTests as tests } from "./fio"; - -export function fioTests(get: () => { wallet: core.HDWallet; info: core.HDWalletInfo; wallet2: core.HDWallet }): void { - tests(get); -} diff --git a/integration/src/fio/tx01.unsigned.json b/integration/src/fio/tx01.unsigned.json deleted file mode 100644 index 1c9bd039..00000000 --- a/integration/src/fio/tx01.unsigned.json +++ /dev/null @@ -1,35 +0,0 @@ -{ - "expiration": "2018-07-14T07:43:28", - "ref_block_num": "blockInfo.block_num & 0xffff", - "ref_block_prefix": "blockInfo.ref_block_prefix", - "actions": [ - { - "account": "fio.address", - "name": "addaddress", - "authorization": [ - { - "actor": "user.account", - "permission": "active" - } - ], - "data": { - "fio_address": "user.address", - "public_addresses": [ - { - "chain_code": "BCH", - "token_code": "BCH", - "public_address": "bitcoincash:qzf8zha74ahdh9j0xnwlffdn0zuyaslx3c90q7n9g9" - }, - { - "chain_code": "DASH", - "token_code": "DASH", - "public_address": "XyCyPKzTWvW2XdcYjPaPXGQDCGk946ywEv" - } - ], - "max_fee": 600000000, - "tpid": "rewards@wallet", - "actor": "user.account" - } - } - ] -} diff --git a/integration/src/fio/tx02.signed.json b/integration/src/fio/tx02.signed.json deleted file mode 100644 index e69de29b..00000000 diff --git a/integration/src/integration.ts b/integration/src/integration.ts index f8bedbaa..3346eccd 100644 --- a/integration/src/integration.ts +++ b/integration/src/integration.ts @@ -1,12 +1,10 @@ import * as core from "@keepkey/hdwallet-core"; import * as keepkey from "@keepkey/hdwallet-keepkey"; -import * as native from "@keepkey/hdwallet-native"; import { btcTests } from "./bitcoin"; import { cosmosTests } from "./cosmos"; import { eosTests } from "./eos"; import { ethTests } from "./ethereum"; -import { fioTests } from "./fio"; import { kavaTests } from "./kava"; import { mayachainTests } from "./mayachain"; import { osmosisTests } from "./osmosis"; @@ -42,7 +40,7 @@ export function integration(suite: WalletSuite): void { }); it("has only one vendor", () => { - expect((keepkey.isKeepKey(wallet) ? 1 : 0) + (native.isNative(wallet) ? 1 : 0)).toEqual(1); + expect(keepkey.isKeepKey(wallet) ? 1 : 0).toEqual(1); }); }); @@ -70,16 +68,6 @@ export function integration(suite: WalletSuite): void { eosTests(() => ({ wallet, info })); }); - describe("FioWallet", () => { - let wallet2: core.HDWallet; - beforeAll(async () => { - wallet = await suite.createWallet("Fio"); - wallet2 = await suite.createWallet("Fio"); - }); - - fioTests(() => ({ wallet, info, wallet2 })); - }); - describe("CosmosWallet", () => { beforeAll(async () => { wallet = await suite.createWallet("Cosmos"); diff --git a/integration/src/wallets/native.ts b/integration/src/wallets/native.ts deleted file mode 100644 index 905cbf65..00000000 --- a/integration/src/wallets/native.ts +++ /dev/null @@ -1,518 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as native from "@keepkey/hdwallet-native"; -import * as _ from "lodash"; - -// TODO: clean this up -// eslint-disable-next-line jest/no-mocks-import -import mswMock from "../../../packages/hdwallet-native/__mocks__/mswMock"; - -const mnemonic = "all all all all all all all all all all all all"; -const deviceId = "native-test"; - -export function name(): string { - return "Native"; -} - -export function createInfo(): core.HDWalletInfo { - return native.info(); -} - -export async function setupMswMocks() { - const fioMocks = { - get: { - "https://fio.eu.eosamsterdam.net/v1/chain/get_info": { - server_version: "0b30e123", - chain_id: "21dcae42c0182200e93f954a074011f9048a7624c6fe81d3c9541a614a88bd1c", - head_block_num: 61842307, - last_irreversible_block_num: 61841978, - last_irreversible_block_id: "03afa23a114cfee7ef1c7ca90e270422fe37396080738ece42391d9ef31440e8", - head_block_id: "03afa38300f285879d00fe0f2f659f7a4b09d134dcd678ad12fc788dccf67952", - head_block_time: "2021-03-18T00:05:14.000", - head_block_producer: "aloha3joooqd", - virtual_block_cpu_limit: 200000000, - virtual_block_net_limit: 1048576000, - block_cpu_limit: 199900, - block_net_limit: 1048576, - server_version_string: "v2.0.0", - fork_db_head_block_num: 61842307, - fork_db_head_block_id: "03afa38300f285879d00fe0f2f659f7a4b09d134dcd678ad12fc788dccf67952", - }, - }, - post: { - "https://fio.eu.eosamsterdam.net/v1/chain/get_block": { - timestamp: "2021-03-18T00:02:29.500", - producer: "sweidrpkehv2", - confirmed: 0, - previous: "03afa2397459431ac5325ceefccfc17168d96efa07198221a48dc7339e4cc265", - transaction_mroot: "0000000000000000000000000000000000000000000000000000000000000000", - action_mroot: "5ceb022b440279ec9943e07564aadfa82a3fadfccc9531510ae60c8d6e035d4e", - schedule_version: 73, - new_producers: null, - header_extensions: [], - producer_signature: - "SIG_K1_KAJ9KUhQ94GWqPGmZ13rzHYbaR7kB3f4xaK73G24EEU82fMjboJTtBxZWk65Qdcy3iQimgeJ6bUWaSsU7kmmMMMFwb2fmR", - transactions: [], - block_extensions: [], - id: "03afa23a114cfee7ef1c7ca90e270422fe37396080738ece42391d9ef31440e8", - block_num: 61841978, - ref_block_prefix: 2843483375, - }, - "https://fio.eu.eosamsterdam.net/v1/chain/get_pub_address": (body: any) => { - body = JSON.stringify(body); - switch (body) { - case '{"fio_address":"highlander@scatter","chain_code":"FIO","token_code":"FIO"}': - return { - public_address: "FIO6Lxx7BTA8zbgPuqn4QidNNdTCHisXU7RpxJxLwxAka7NV7SoBW", - }; - case '{"fio_address":"test@shapeshift","chain_code":"FIO","token_code":"FIO"}': - return { - public_address: "FIO6iLE1J4zb2SyDGTH9d6UL9Qm6hhqRce27QvP8AKxVLASGhtm7z", - }; - default: - throw new Error(`unrecognized get_pub_address call: ${body}`); - } - }, - "https://fio.eu.eosamsterdam.net/v1/chain/get_raw_abi": (body: any) => { - body = JSON.stringify(body); - switch (body) { - case '{"account_name":"fio.address"}': - return { - account_name: "fio.address", - code_hash: "183b0410eb9d6071ca741a94da36502eab4d808ac60a6432cae1329ca86c2a64", - abi_hash: "0dca0ca50be70bb04a84c2494e3eecdf72c083498a3acdbe0ed7ebc4a89d8ad9", - abi: "DmVvc2lvOjphYmkvMS4wABMHZmlvbmFtZQAJAmlkBnVpbnQ2NARuYW1lBnN0cmluZwhuYW1laGFzaAd1aW50MTI4BmRvbWFpbgZzdHJpbmcKZG9tYWluaGFzaAd1aW50MTI4CmV4cGlyYXRpb24GdWludDY0DW93bmVyX2FjY291bnQEbmFtZQlhZGRyZXNzZXMOdG9rZW5wdWJhZGRyW10XYnVuZGxlZWxpZ2libGVjb3VudGRvd24GdWludDY0BmRvbWFpbgAGAmlkBnVpbnQ2NARuYW1lBnN0cmluZwpkb21haW5oYXNoB3VpbnQxMjgHYWNjb3VudARuYW1lCWlzX3B1YmxpYwV1aW50OApleHBpcmF0aW9uBnVpbnQ2NAplb3Npb19uYW1lAAMHYWNjb3VudARuYW1lCWNsaWVudGtleQZzdHJpbmcHa2V5aGFzaAd1aW50MTI4CnJlZ2FkZHJlc3MABQtmaW9fYWRkcmVzcwZzdHJpbmcUb3duZXJfZmlvX3B1YmxpY19rZXkGc3RyaW5nB21heF9mZWUFaW50NjQFYWN0b3IEbmFtZQR0cGlkBnN0cmluZwx0b2tlbnB1YmFkZHIAAwp0b2tlbl9jb2RlBnN0cmluZwpjaGFpbl9jb2RlBnN0cmluZw5wdWJsaWNfYWRkcmVzcwZzdHJpbmcKYWRkYWRkcmVzcwAFC2Zpb19hZGRyZXNzBnN0cmluZxBwdWJsaWNfYWRkcmVzc2VzDnRva2VucHViYWRkcltdB21heF9mZWUFaW50NjQFYWN0b3IEbmFtZQR0cGlkBnN0cmluZwpyZW1hZGRyZXNzAAULZmlvX2FkZHJlc3MGc3RyaW5nEHB1YmxpY19hZGRyZXNzZXMOdG9rZW5wdWJhZGRyW10HbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lBHRwaWQGc3RyaW5nCnJlbWFsbGFkZHIABAtmaW9fYWRkcmVzcwZzdHJpbmcHbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lBHRwaWQGc3RyaW5nCXJlZ2RvbWFpbgAFCmZpb19kb21haW4Gc3RyaW5nFG93bmVyX2Zpb19wdWJsaWNfa2V5BnN0cmluZwdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUEdHBpZAZzdHJpbmcLcmVuZXdkb21haW4ABApmaW9fZG9tYWluBnN0cmluZwdtYXhfZmVlBWludDY0BHRwaWQGc3RyaW5nBWFjdG9yBG5hbWUMcmVuZXdhZGRyZXNzAAQLZmlvX2FkZHJlc3MGc3RyaW5nB21heF9mZWUFaW50NjQEdHBpZAZzdHJpbmcFYWN0b3IEbmFtZQxzZXRkb21haW5wdWIABQpmaW9fZG9tYWluBnN0cmluZwlpc19wdWJsaWMEaW50OAdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUEdHBpZAZzdHJpbmcLYnVybmV4cGlyZWQAAAtkZWNyY291bnRlcgACC2Zpb19hZGRyZXNzBnN0cmluZwRzdGVwBWludDMyCmJpbmQyZW9zaW8AAwdhY2NvdW50BG5hbWUKY2xpZW50X2tleQZzdHJpbmcIZXhpc3RpbmcEYm9vbAtidXJuYWRkcmVzcwAEC2Zpb19hZGRyZXNzBnN0cmluZwdtYXhfZmVlBWludDY0BHRwaWQGc3RyaW5nBWFjdG9yBG5hbWUKeGZlcmRvbWFpbgAFCmZpb19kb21haW4Gc3RyaW5nGG5ld19vd25lcl9maW9fcHVibGljX2tleQZzdHJpbmcHbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lBHRwaWQGc3RyaW5nC3hmZXJhZGRyZXNzAAULZmlvX2FkZHJlc3MGc3RyaW5nGG5ld19vd25lcl9maW9fcHVibGljX2tleQZzdHJpbmcHbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lBHRwaWQGc3RyaW5nCmFkZGJ1bmRsZXMABQtmaW9fYWRkcmVzcwZzdHJpbmcLYnVuZGxlX3NldHMFaW50NjQHbWF4X2ZlZQVpbnQ2NAR0cGlkBnN0cmluZwVhY3RvcgRuYW1lDwCuylNTdJFKC2RlY3Jjb3VudGVyAAAAxuqmZJi6CnJlZ2FkZHJlc3MAAADG6qZkUjIKYWRkYWRkcmVzcwAAAMbqpmSkugpyZW1hZGRyZXNzAADATcnEaKS6CnJlbWFsbGFkZHIAAACYzkiamLoJcmVnZG9tYWluAACmM5Imrqa6C3JlbmV3ZG9tYWluAICxuikZrqa6DHJlbmV3YWRkcmVzcwAAkrqudjWvPgtidXJuZXhwaXJlZABwdJ3OSJqywgxzZXRkb21haW5wdWIAAAB1mCqRpjsKYmluZDJlb3NpbwAAMFY3JTOvPgtidXJuYWRkcmVzcwAAwHRG0nTV6gp4ZmVyZG9tYWluAAAwVjclc9XqC3hmZXJhZGRyZXNzAAAAVjFNfVIyCmFkZGJ1bmRsZXMAAwAAAFhJM6lbA2k2NAECaWQBBnN0cmluZwdmaW9uYW1lAAAAAE9nJE0DaTY0AQJpZAEGc3RyaW5nBmRvbWFpbgBANTJPTREyA2k2NAEHYWNjb3VudAEGdWludDY0CmVvc2lvX25hbWUAAAAA=", - }; - case '{"account_name":"fio.fee"}': - return { - account_name: "fio.fee", - code_hash: "564c5023ddd4916517fad8cf0fda502a1a8cd64af32f8a4a4c45b6d6ee60cda4", - abi_hash: "63370fe617c23b9ffd714cf33ec3e67cfc4695dfcc9830c6aff8dbd9a6b3c56f", - abi: "DmVvc2lvOjphYmkvMS4wAA4JY3JlYXRlZmVlAAMJZW5kX3BvaW50BnN0cmluZwR0eXBlBWludDY0CnN1Zl9hbW91bnQFaW50NjQIZmVldmFsdWUAAgllbmRfcG9pbnQGc3RyaW5nBXZhbHVlBWludDY0C2ZlZXZhbHVlX3RzAAMJZW5kX3BvaW50BnN0cmluZwV2YWx1ZQVpbnQ2NAl0aW1lc3RhbXAGdWludDY0CnNldGZlZXZvdGUAAwpmZWVfcmF0aW9zCmZlZXZhbHVlW10HbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lCmJ1bmRsZXZvdGUAAxRidW5kbGVkX3RyYW5zYWN0aW9ucwVpbnQ2NAdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUKc2V0ZmVlbXVsdAADCm11bHRpcGxpZXIHZmxvYXQ2NAdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUMbWFuZGF0b3J5ZmVlAAMJZW5kX3BvaW50BnN0cmluZwdhY2NvdW50BG5hbWUHbWF4X2ZlZQVpbnQ2NAtieXRlbWFuZGZlZQAECWVuZF9wb2ludAZzdHJpbmcHYWNjb3VudARuYW1lB21heF9mZWUFaW50NjQIYnl0ZXNpemUFaW50NjQLY29tcHV0ZWZlZXMAAAZmaW9mZWUABgZmZWVfaWQGdWludDY0CWVuZF9wb2ludAZzdHJpbmcOZW5kX3BvaW50X2hhc2gHdWludDEyOAR0eXBlBnVpbnQ2NApzdWZfYW1vdW50BnVpbnQ2NA12b3Rlc19wZW5kaW5nBWJvb2wkCGZlZXZvdGVyAAMTYmxvY2tfcHJvZHVjZXJfbmFtZQRuYW1lDmZlZV9tdWx0aXBsaWVyB2Zsb2F0NjQRbGFzdHZvdGV0aW1lc3RhbXAGdWludDY0B2ZlZXZvdGUABgJpZAZ1aW50NjQTYmxvY2tfcHJvZHVjZXJfbmFtZQRuYW1lCWVuZF9wb2ludAZzdHJpbmcOZW5kX3BvaW50X2hhc2gHdWludDEyOApzdWZfYW1vdW50BnVpbnQ2NBFsYXN0dm90ZXRpbWVzdGFtcAZ1aW50NjQIZmVldm90ZTIABAJpZAZ1aW50NjQTYmxvY2tfcHJvZHVjZXJfbmFtZQRuYW1lCGZlZXZvdGVzDWZlZXZhbHVlX3RzW10RbGFzdHZvdGV0aW1lc3RhbXAGdWludDY0C2J1bmRsZXZvdGVyAAMTYmxvY2tfcHJvZHVjZXJfbmFtZQRuYW1lEmJ1bmRsZWRidm90ZW51bWJlcgZ1aW50NjQRbGFzdHZvdGV0aW1lc3RhbXAGdWludDY0BwAAUGqpbNRFCWNyZWF0ZWZlZQAAgMp0K7WywgpzZXRmZWV2b3RlAACAynSrmKY+CmJ1bmRsZXZvdGUAAECOWiq1ssIKc2V0ZmVlbXVsdACg1PKXZpOmkQxtYW5kYXRvcnlmZWUAAJRaaRqpsj8LYnl0ZW1hbmRmZWUAALBSS2VdJUULY29tcHV0ZWZlZXMABYCvynSrmKY+A2k2NAETYmxvY2tfcHJvZHVjZXJfbmFtZQEGdWludDY0C2J1bmRsZXZvdGVyAAAAACu1qFsDaTY0AQZmZWVfaWQBBnVpbnQ2NAZmaW9mZWUAAMBXZbqVWgNpNjQBE2Jsb2NrX3Byb2R1Y2VyX25hbWUBBnVpbnQ2NAhmZWV2b3RlcgAAAFhlupVaA2k2NAETYmxvY2tfcHJvZHVjZXJfbmFtZQEGdWludDY0B2ZlZXZvdGUAABBYZbqVWgNpNjQBE2Jsb2NrX3Byb2R1Y2VyX25hbWUBBnVpbnQ2NAhmZWV2b3RlMgAAAAA==", - }; - case '{"account_name":"fio.reqobt"}': - return { - account_name: "fio.reqobt", - code_hash: "cd54f179eb5913984af88cc589ec527396041bd63e2094ffb143c483e2f0c1da", - abi_hash: "93118de6229f77f4213dc948674c4e11d462f573db821204224a73628b942ffd", - abi: "DmVvc2lvOjphYmkvMS4wAAoKZmlvcmVxY3R4dAANDmZpb19yZXF1ZXN0X2lkBnVpbnQ2NBFwYXllcl9maW9fYWRkcmVzcwd1aW50MTI4EXBheWVlX2Zpb19hZGRyZXNzB3VpbnQxMjgZcGF5ZXJfZmlvX2FkZHJlc3NfaGV4X3N0cgZzdHJpbmcZcGF5ZWVfZmlvX2FkZHJlc3NfaGV4X3N0cgZzdHJpbmcbcGF5ZXJfZmlvX2FkZHJlc3Nfd2l0aF90aW1lB3VpbnQxMjgbcGF5ZWVfZmlvX2FkZHJlc3Nfd2l0aF90aW1lB3VpbnQxMjgHY29udGVudAZzdHJpbmcKdGltZV9zdGFtcAZ1aW50NjQOcGF5ZXJfZmlvX2FkZHIGc3RyaW5nDnBheWVlX2Zpb19hZGRyBnN0cmluZwlwYXllcl9rZXkGc3RyaW5nCXBheWVlX2tleQZzdHJpbmcOcmVjb3Jkb2J0X2luZm8ADQJpZAZ1aW50NjQRcGF5ZXJfZmlvX2FkZHJlc3MHdWludDEyOBFwYXllZV9maW9fYWRkcmVzcwd1aW50MTI4GXBheWVyX2Zpb19hZGRyZXNzX2hleF9zdHIGc3RyaW5nGXBheWVlX2Zpb19hZGRyZXNzX2hleF9zdHIGc3RyaW5nG3BheWVyX2Zpb19hZGRyZXNzX3dpdGhfdGltZQd1aW50MTI4G3BheWVlX2Zpb19hZGRyZXNzX3dpdGhfdGltZQd1aW50MTI4B2NvbnRlbnQGc3RyaW5nCnRpbWVfc3RhbXAGdWludDY0DnBheWVyX2Zpb19hZGRyBnN0cmluZw5wYXllZV9maW9fYWRkcgZzdHJpbmcJcGF5ZXJfa2V5BnN0cmluZwlwYXllZV9rZXkGc3RyaW5nCWZpb3JlcXN0cwAFAmlkBnVpbnQ2NA5maW9fcmVxdWVzdF9pZAZ1aW50NjQGc3RhdHVzBnVpbnQ2NAhtZXRhZGF0YQZzdHJpbmcKdGltZV9zdGFtcAZ1aW50NjQMZmlvdHJ4dF9pbmZvAA8CaWQGdWludDY0DmZpb19yZXF1ZXN0X2lkBnVpbnQ2NBJwYXllcl9maW9fYWRkcl9oZXgHdWludDEyOBJwYXllZV9maW9fYWRkcl9oZXgHdWludDEyOA1maW9fZGF0YV90eXBlBXVpbnQ4CHJlcV90aW1lBnVpbnQ2NA5wYXllcl9maW9fYWRkcgZzdHJpbmcOcGF5ZWVfZmlvX2FkZHIGc3RyaW5nCXBheWVyX2tleQZzdHJpbmcJcGF5ZWVfa2V5BnN0cmluZw1wYXllcl9hY2NvdW50BG5hbWUNcGF5ZWVfYWNjb3VudARuYW1lC3JlcV9jb250ZW50BnN0cmluZwtvYnRfY29udGVudAZzdHJpbmcIb2J0X3RpbWUGdWludDY0Cm1pZ3JsZWRnZXIABwJpZAZ1aW50NjQIYmVnaW5vYnQFaW50NjQKY3VycmVudG9idAVpbnQ2NAdiZWdpbnJxBWludDY0CWN1cnJlbnRycQVpbnQ2NApjdXJyZW50c3RhBWludDY0CmlzRmluaXNoZWQEaW50OAdtaWdydHJ4AAIGYW1vdW50BWludDE2BWFjdG9yBnN0cmluZwlyZWNvcmRvYnQABw5maW9fcmVxdWVzdF9pZAZzdHJpbmcRcGF5ZXJfZmlvX2FkZHJlc3MGc3RyaW5nEXBheWVlX2Zpb19hZGRyZXNzBnN0cmluZwdjb250ZW50BnN0cmluZwdtYXhfZmVlBWludDY0BWFjdG9yBnN0cmluZwR0cGlkBnN0cmluZwtuZXdmdW5kc3JlcQAGEXBheWVyX2Zpb19hZGRyZXNzBnN0cmluZxFwYXllZV9maW9fYWRkcmVzcwZzdHJpbmcHY29udGVudAZzdHJpbmcHbWF4X2ZlZQVpbnQ2NAVhY3RvcgZzdHJpbmcEdHBpZAZzdHJpbmcMcmVqZWN0Zm5kcmVxAAQOZmlvX3JlcXVlc3RfaWQGc3RyaW5nB21heF9mZWUFaW50NjQFYWN0b3IGc3RyaW5nBHRwaWQGc3RyaW5nDGNhbmNlbGZuZHJlcQAEDmZpb19yZXF1ZXN0X2lkBnN0cmluZwdtYXhfZmVlBWludDY0BWFjdG9yBnN0cmluZwR0cGlkBnN0cmluZwUAAACg33yZkwdtaWdydHJ4AAAAyIemS5G6CXJlY29yZG9idAAArLo4Tb24mgtuZXdmdW5kc3JlcQBg1U1zZaSeugxyZWplY3RmbmRyZXEAYNVNc0WFpkEMY2FuY2VsZm5kcmVxAAUAcO4ZWXWpWwNpNjQBDmZpb19yZXF1ZXN0X2lkAQZ1aW50NjQKZmlvcmVxY3R4dAAAzoemS5G6A2k2NAECaWQBBnVpbnQ2NA5yZWNvcmRvYnRfaW5mbwAAxhlbdalbA2k2NAECaWQBBnVpbnQ2NAlmaW9yZXFzdHMAAMA495upWwNpNjQBAmlkAQZ1aW50NjQMZmlvdHJ4dF9pbmZvAPBVLKl4mZMDaTY0AQJpZAEGdWludDY0Cm1pZ3JsZWRnZXIAAAAA=", - }; - case '{"account_name":"fio.token"}': - return { - account_name: "fio.token", - code_hash: "f20c3d91844682c1ac035fee1509f1c91a934122e372ac6df45594bb3f3f171e", - abi_hash: "b368fbc363f0da588eea9c943b75caadffb881dcb4dc4f283bfee7a86c97850f", - abi: "DmVvc2lvOjphYmkvMS4xAAoHYWNjb3VudAABB2JhbGFuY2UFYXNzZXQGY3JlYXRlAAEObWF4aW11bV9zdXBwbHkFYXNzZXQOY3VycmVuY3lfc3RhdHMAAwZzdXBwbHkFYXNzZXQKbWF4X3N1cHBseQVhc3NldAZpc3N1ZXIEbmFtZQVpc3N1ZQADAnRvBG5hbWUIcXVhbnRpdHkFYXNzZXQEbWVtbwZzdHJpbmcLbG9ja3BlcmlvZHMAAghkdXJhdGlvbgVpbnQ2NAdwZXJjZW50B2Zsb2F0NjQHbWludGZpbwACAnRvBG5hbWUGYW1vdW50BnVpbnQ2NAZyZXRpcmUAAghxdWFudGl0eQVhc3NldARtZW1vBnN0cmluZwh0cmFuc2ZlcgAEBGZyb20EbmFtZQJ0bwRuYW1lCHF1YW50aXR5BWFzc2V0BG1lbW8Gc3RyaW5nDHRybnNmaW9wdWJreQAFEHBheWVlX3B1YmxpY19rZXkGc3RyaW5nBmFtb3VudAVpbnQ2NAdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUEdHBpZAZzdHJpbmcLdHJuc2xvY3Rva3MABxBwYXllZV9wdWJsaWNfa2V5BnN0cmluZwhjYW5fdm90ZQVpbnQzMgdwZXJpb2RzDWxvY2twZXJpb2RzW10GYW1vdW50BWludDY0B21heF9mZWUFaW50NjQFYWN0b3IEbmFtZQR0cGlkBnN0cmluZwcAAAAAqGzURQZjcmVhdGUAAAAAAAClMXYFaXNzdWUAAAAAgLqVp5MHbWludGZpbwAAAAAAqOuyugZyZXRpcmUAAAAAVy08zc0IdHJhbnNmZXIA4OHRlbqF580MdHJuc2Zpb3B1Ymt5AAAwpBnRiOfNC3RybnNsb2N0b2tzAAIAAAA4T00RMgNpNjQAAAdhY2NvdW50AAAAAACQTcYDaTY0AAAOY3VycmVuY3lfc3RhdHMAAAAA=", - }; - case '{"account_name":"eosio"}': - return { - account_name: "eosio", - code_hash: "bf2cf9c963c483263e279d1a2f3f968a65a5c6db86af99bb9e5d7a2d2840cc12", - abi_hash: "ead7a5cf52addda442d99acf5a35494f235330392b02c4ced3d4a09dd5a7602d", - abi: "DmVvc2lvOjphYmkvMS4xADcIYWJpX2hhc2gAAgVvd25lcgRuYW1lBGhhc2gLY2hlY2tzdW0yNTYJYWRkYWN0aW9uAAMGYWN0aW9uBG5hbWUIY29udHJhY3QGc3RyaW5nBWFjdG9yBG5hbWUMYWRkZ2VubG9ja2VkAAQFb3duZXIEbmFtZQdwZXJpb2RzDWxvY2twZXJpb2RzW10HY2Fudm90ZQRib29sBmFtb3VudAVpbnQ2NAlhZGRsb2NrZWQAAwVvd25lcgRuYW1lBmFtb3VudAVpbnQ2NAhsb2NrdHlwZQVpbnQxNglhdXRob3JpdHkABAl0aHJlc2hvbGQGdWludDMyBGtleXMMa2V5X3dlaWdodFtdCGFjY291bnRzGXBlcm1pc3Npb25fbGV2ZWxfd2VpZ2h0W10Fd2FpdHMNd2FpdF93ZWlnaHRbXQxibG9ja19oZWFkZXIACAl0aW1lc3RhbXAGdWludDMyCHByb2R1Y2VyBG5hbWUJY29uZmlybWVkBnVpbnQxNghwcmV2aW91cwtjaGVja3N1bTI1NhF0cmFuc2FjdGlvbl9tcm9vdAtjaGVja3N1bTI1NgxhY3Rpb25fbXJvb3QLY2hlY2tzdW0yNTYQc2NoZWR1bGVfdmVyc2lvbgZ1aW50MzINbmV3X3Byb2R1Y2VycxJwcm9kdWNlcl9zY2hlZHVsZT8VYmxvY2tjaGFpbl9wYXJhbWV0ZXJzABETbWF4X2Jsb2NrX25ldF91c2FnZQZ1aW50NjQadGFyZ2V0X2Jsb2NrX25ldF91c2FnZV9wY3QGdWludDMyGW1heF90cmFuc2FjdGlvbl9uZXRfdXNhZ2UGdWludDMyHmJhc2VfcGVyX3RyYW5zYWN0aW9uX25ldF91c2FnZQZ1aW50MzIQbmV0X3VzYWdlX2xlZXdheQZ1aW50MzIjY29udGV4dF9mcmVlX2Rpc2NvdW50X25ldF91c2FnZV9udW0GdWludDMyI2NvbnRleHRfZnJlZV9kaXNjb3VudF9uZXRfdXNhZ2VfZGVuBnVpbnQzMhNtYXhfYmxvY2tfY3B1X3VzYWdlBnVpbnQzMhp0YXJnZXRfYmxvY2tfY3B1X3VzYWdlX3BjdAZ1aW50MzIZbWF4X3RyYW5zYWN0aW9uX2NwdV91c2FnZQZ1aW50MzIZbWluX3RyYW5zYWN0aW9uX2NwdV91c2FnZQZ1aW50MzIYbWF4X3RyYW5zYWN0aW9uX2xpZmV0aW1lBnVpbnQzMh5kZWZlcnJlZF90cnhfZXhwaXJhdGlvbl93aW5kb3cGdWludDMyFW1heF90cmFuc2FjdGlvbl9kZWxheQZ1aW50MzIWbWF4X2lubGluZV9hY3Rpb25fc2l6ZQZ1aW50MzIXbWF4X2lubGluZV9hY3Rpb25fZGVwdGgGdWludDE2E21heF9hdXRob3JpdHlfZGVwdGgGdWludDE2CmJ1cm5hY3Rpb24AAQtmaW9hZGRyaGFzaAd1aW50MTI4C2NhbmNlbGRlbGF5AAIOY2FuY2VsaW5nX2F1dGgQcGVybWlzc2lvbl9sZXZlbAZ0cnhfaWQLY2hlY2tzdW0yNTYLY3JhdXRvcHJveHkAAgVwcm94eQRuYW1lBW93bmVyBG5hbWUKZGVsZXRlYXV0aAADB2FjY291bnQEbmFtZQpwZXJtaXNzaW9uBG5hbWUHbWF4X2ZlZQZ1aW50NjQSZW9zaW9fZ2xvYmFsX3N0YXRlFWJsb2NrY2hhaW5fcGFyYW1ldGVycwsdbGFzdF9wcm9kdWNlcl9zY2hlZHVsZV91cGRhdGUUYmxvY2tfdGltZXN0YW1wX3R5cGUYbGFzdF9wZXJ2b3RlX2J1Y2tldF9maWxsCnRpbWVfcG9pbnQOcGVydm90ZV9idWNrZXQFaW50NjQPcGVyYmxvY2tfYnVja2V0BWludDY0E3RvdGFsX3VucGFpZF9ibG9ja3MGdWludDMyD3RvdGFsX3ZvdGVkX2ZpbwVpbnQ2NBV0aHJlc2hfdm90ZWRfZmlvX3RpbWUKdGltZV9wb2ludBtsYXN0X3Byb2R1Y2VyX3NjaGVkdWxlX3NpemUGdWludDE2GnRvdGFsX3Byb2R1Y2VyX3ZvdGVfd2VpZ2h0B2Zsb2F0NjQPbGFzdF9uYW1lX2Nsb3NlFGJsb2NrX3RpbWVzdGFtcF90eXBlD2xhc3RfZmVlX3VwZGF0ZRRibG9ja190aW1lc3RhbXBfdHlwZRNlb3Npb19nbG9iYWxfc3RhdGUyAAMObGFzdF9ibG9ja19udW0UYmxvY2tfdGltZXN0YW1wX3R5cGUcdG90YWxfcHJvZHVjZXJfdm90ZXBheV9zaGFyZQdmbG9hdDY0CHJldmlzaW9uBXVpbnQ4E2Vvc2lvX2dsb2JhbF9zdGF0ZTMAAhZsYXN0X3ZwYXlfc3RhdGVfdXBkYXRlCnRpbWVfcG9pbnQcdG90YWxfdnBheV9zaGFyZV9jaGFuZ2VfcmF0ZQdmbG9hdDY0BmluY3JhbQACCWFjY291bnRtbgRuYW1lBmFtb3VudAVpbnQ2NAxpbmhpYml0dW5sY2sAAgVvd25lcgRuYW1lBXZhbHVlBnVpbnQzMgRpbml0AAIHdmVyc2lvbgl2YXJ1aW50MzIEY29yZQZzeW1ib2wKa2V5X3dlaWdodAACA2tleQpwdWJsaWNfa2V5BndlaWdodAZ1aW50MTYIbGlua2F1dGgABQdhY2NvdW50BG5hbWUEY29kZQRuYW1lBHR5cGUEbmFtZQtyZXF1aXJlbWVudARuYW1lB21heF9mZWUGdWludDY0GGxvY2tlZF90b2tlbl9ob2xkZXJfaW5mbwAHBW93bmVyBG5hbWUSdG90YWxfZ3JhbnRfYW1vdW50BnVpbnQ2NBV1bmxvY2tlZF9wZXJpb2RfY291bnQGdWludDMyCmdyYW50X3R5cGUGdWludDMyEWluaGliaXRfdW5sb2NraW5nBnVpbnQzMhdyZW1haW5pbmdfbG9ja2VkX2Ftb3VudAZ1aW50NjQJdGltZXN0YW1wBnVpbnQzMhJsb2NrZWRfdG9rZW5zX2luZm8ACAJpZAVpbnQ2NA1vd25lcl9hY2NvdW50BG5hbWULbG9ja19hbW91bnQFaW50NjQRcGF5b3V0c19wZXJmb3JtZWQFaW50MzIIY2FuX3ZvdGUFaW50MzIHcGVyaW9kcw1sb2NrcGVyaW9kc1tdFXJlbWFpbmluZ19sb2NrX2Ftb3VudAVpbnQ2NAl0aW1lc3RhbXAGdWludDMyC2xvY2twZXJpb2RzAAIIZHVyYXRpb24FaW50NjQHcGVyY2VudAdmbG9hdDY0Cm5ld2FjY291bnQABAdjcmVhdG9yBG5hbWUEbmFtZQRuYW1lBW93bmVyCWF1dGhvcml0eQZhY3RpdmUJYXV0aG9yaXR5B29uYmxvY2sAAQZoZWFkZXIMYmxvY2tfaGVhZGVyB29uZXJyb3IAAglzZW5kZXJfaWQHdWludDEyOAhzZW50X3RyeAVieXRlcxBwZXJtaXNzaW9uX2xldmVsAAIFYWN0b3IEbmFtZQpwZXJtaXNzaW9uBG5hbWUXcGVybWlzc2lvbl9sZXZlbF93ZWlnaHQAAgpwZXJtaXNzaW9uEHBlcm1pc3Npb25fbGV2ZWwGd2VpZ2h0BnVpbnQxNg1wcm9kdWNlcl9pbmZvAAwCaWQGdWludDY0BW93bmVyBG5hbWULZmlvX2FkZHJlc3MGc3RyaW5nC2FkZHJlc3NoYXNoB3VpbnQxMjgLdG90YWxfdm90ZXMHZmxvYXQ2NBNwcm9kdWNlcl9wdWJsaWNfa2V5CnB1YmxpY19rZXkJaXNfYWN0aXZlBGJvb2wDdXJsBnN0cmluZw11bnBhaWRfYmxvY2tzBnVpbnQzMg9sYXN0X2NsYWltX3RpbWUKdGltZV9wb2ludAxsYXN0X2JwY2xhaW0GdWludDMyCGxvY2F0aW9uBnVpbnQxNgxwcm9kdWNlcl9rZXkAAg1wcm9kdWNlcl9uYW1lBG5hbWURYmxvY2tfc2lnbmluZ19rZXkKcHVibGljX2tleRFwcm9kdWNlcl9zY2hlZHVsZQACB3ZlcnNpb24GdWludDMyCXByb2R1Y2Vycw5wcm9kdWNlcl9rZXlbXQtyZWdwcm9kdWNlcgAGC2Zpb19hZGRyZXNzBnN0cmluZwtmaW9fcHViX2tleQZzdHJpbmcDdXJsBnN0cmluZwhsb2NhdGlvbgZ1aW50MTYFYWN0b3IEbmFtZQdtYXhfZmVlBWludDY0CHJlZ3Byb3h5AAMLZmlvX2FkZHJlc3MGc3RyaW5nBWFjdG9yBG5hbWUHbWF4X2ZlZQVpbnQ2NAlyZW1hY3Rpb24AAgZhY3Rpb24EbmFtZQVhY3RvcgRuYW1lCnJlc2V0Y2xhaW0AAQhwcm9kdWNlcgRuYW1lC3JtdnByb2R1Y2VyAAEIcHJvZHVjZXIEbmFtZQZzZXRhYmkAAgdhY2NvdW50BG5hbWUDYWJpBWJ5dGVzDHNldGF1dG9wcm94eQACBXByb3h5BG5hbWUFb3duZXIEbmFtZQdzZXRjb2RlAAQHYWNjb3VudARuYW1lBnZtdHlwZQV1aW50OAl2bXZlcnNpb24FdWludDgEY29kZQVieXRlcwlzZXRwYXJhbXMAAQZwYXJhbXMVYmxvY2tjaGFpbl9wYXJhbWV0ZXJzB3NldHByaXYAAgdhY2NvdW50BG5hbWUHaXNfcHJpdgV1aW50OA10b3BfcHJvZF9pbmZvAAEIcHJvZHVjZXIEbmFtZQp1bmxpbmthdXRoAAMHYWNjb3VudARuYW1lBGNvZGUEbmFtZQR0eXBlBG5hbWUMdW5sb2NrdG9rZW5zAAEFYWN0b3IEbmFtZQl1bnJlZ3Byb2QAAwtmaW9fYWRkcmVzcwZzdHJpbmcFYWN0b3IEbmFtZQdtYXhfZmVlBWludDY0CnVucmVncHJveHkAAwtmaW9fYWRkcmVzcwZzdHJpbmcFYWN0b3IEbmFtZQdtYXhfZmVlBWludDY0CnVwZGF0ZWF1dGgABQdhY2NvdW50BG5hbWUKcGVybWlzc2lvbgRuYW1lBnBhcmVudARuYW1lBGF1dGgJYXV0aG9yaXR5B21heF9mZWUGdWludDY0C3VwZGF0ZXBvd2VyAAIFdm90ZXIEbmFtZQp1cGRhdGVvbmx5BGJvb2wLdXBkbGJwY2xhaW0AAQhwcm9kdWNlcgRuYW1lCXVwZGxvY2tlZAACBW93bmVyBG5hbWUPYW1vdW50cmVtYWluaW5nBnVpbnQ2NAx1cGR0cmV2aXNpb24AAQhyZXZpc2lvbgV1aW50OA51c2VyX3Jlc291cmNlcwAEBW93bmVyBG5hbWUKbmV0X3dlaWdodAVhc3NldApjcHVfd2VpZ2h0BWFzc2V0CXJhbV9ieXRlcwVpbnQ2NAx2b3RlcHJvZHVjZXIABAlwcm9kdWNlcnMIc3RyaW5nW10LZmlvX2FkZHJlc3MGc3RyaW5nBWFjdG9yBG5hbWUHbWF4X2ZlZQVpbnQ2NAl2b3RlcHJveHkABAVwcm94eQZzdHJpbmcLZmlvX2FkZHJlc3MGc3RyaW5nBWFjdG9yBG5hbWUHbWF4X2ZlZQVpbnQ2NAp2b3Rlcl9pbmZvAAwCaWQGdWludDY0CmZpb2FkZHJlc3MGc3RyaW5nC2FkZHJlc3NoYXNoB3VpbnQxMjgFb3duZXIEbmFtZQVwcm94eQRuYW1lCXByb2R1Y2VycwZuYW1lW10QbGFzdF92b3RlX3dlaWdodAdmbG9hdDY0E3Byb3hpZWRfdm90ZV93ZWlnaHQHZmxvYXQ2NAhpc19wcm94eQRib29sDWlzX2F1dG9fcHJveHkEYm9vbAlyZXNlcnZlZDIGdWludDMyCXJlc2VydmVkMwVhc3NldAt3YWl0X3dlaWdodAACCHdhaXRfc2VjBnVpbnQzMgZ3ZWlnaHQGdWludDE2IwAAmNRlZFIyCWFkZGFjdGlvbgCQFEQ0TsVSMgxhZGRnZW5sb2NrZWQAAABICiIaUzIJYWRkbG9ja2VkAADApC4jM68+CmJ1cm5hY3Rpb24AALyJKkWFpkELY2FuY2VsZGVsYXkAAHynt9KszUULY3JhdXRvcHJveHkAAEDL2qisokoKZGVsZXRlYXV0aAAAAAAASHPRdAZpbmNyYW0AAFGcOrvj2nQMaW5oaWJpdHVubGNrAAAAAAAAkN10BGluaXQAAAAALWsDp4sIbGlua2F1dGgAAECemiJkuJoKbmV3YWNjb3VudAAAAAAAIhrPpAdvbmJsb2NrAAAAAODSe9WkB29uZXJyb3IAAK5COtFbmboLcmVncHJvZHVjZXIAAAAAvtNbmboIcmVncHJveHkAAACY1GVkpLoJcmVtYWN0aW9uAACAdCairLC6CnJlc2V0Y2xhaW0AAK5COtFbt7wLcm12cHJvZHVjZXIAAAAAALhjssIGc2V0YWJpAOA7vZVmbbLCDHNldGF1dG9wcm94eQAAAABAJYqywgdzZXRjb2RlAAAAwNJcU7PCCXNldHBhcmFtcwAAAABgu1uzwgdzZXRwcml2AABAy9rA6eLUCnVubGlua2F1dGgAgKeCNENE49QMdW5sb2NrdG9rZW5zAAAASPRWpu7UCXVucmVncHJvZAAAgO/0Vqbu1Ap1bnJlZ3Byb3h5AABAy9qobFLVCnVwZGF0ZWF1dGgAAK7itKpsUtULdXBkYXRlcG93ZXIAAKQzEdUTU9ULdXBkbGJwY2xhaW0AAABICiIaU9UJdXBkbG9ja2VkADCpw26rm1PVDHVwZHRyZXZpc2lvbgBwFdKJ3qoy3Qx2b3RlcHJvZHVjZXIAAADwnd6qMt0Jdm90ZXByb3h5AAoAAACgYdPcMQNpNjQAAAhhYmlfaGFzaAAAAABEc2hkA2k2NAAAEmVvc2lvX2dsb2JhbF9zdGF0ZQAAAEBEc2hkA2k2NAAAE2Vvc2lvX2dsb2JhbF9zdGF0ZTIAAABgRHNoZANpNjQAABNlb3Npb19nbG9iYWxfc3RhdGUzgKeCNCcFEY0DaTY0AAAYbG9ja2VkX3Rva2VuX2hvbGRlcl9pbmZvAACeCtIMEY0DaTY0AAASbG9ja2VkX3Rva2Vuc19pbmZvAADAVyGd6K0DaTY0AAANcHJvZHVjZXJfaW5mbwAAADjRWyvNA2k2NAAADXRvcF9wcm9kX2luZm8AAAAAq3sV1gNpNjQAAA51c2VyX3Jlc291cmNlcwAAAADgqzLdA2k2NAAACnZvdGVyX2luZm8AAAAA=", - }; - case '{"account_name":"eosio.msig"}': - return { - account_name: "eosio.msig", - code_hash: "f9eaecc20eeea9705e5e5a81777244281a4770e8ff8b377d76d032ad3163ca81", - abi_hash: "a72cfc8faf3a10267d6b842f47b7d983889831b956b2c41e09f7044e338876de", - abi: "DmVvc2lvOjphYmkvMS4xABAGYWN0aW9uAAQHYWNjb3VudARuYW1lBG5hbWUEbmFtZQ1hdXRob3JpemF0aW9uEnBlcm1pc3Npb25fbGV2ZWxbXQRkYXRhBWJ5dGVzCGFwcHJvdmFsAAIFbGV2ZWwQcGVybWlzc2lvbl9sZXZlbAR0aW1lCnRpbWVfcG9pbnQOYXBwcm92YWxzX2luZm8ABAd2ZXJzaW9uBXVpbnQ4DXByb3Bvc2FsX25hbWUEbmFtZRNyZXF1ZXN0ZWRfYXBwcm92YWxzCmFwcHJvdmFsW10ScHJvdmlkZWRfYXBwcm92YWxzCmFwcHJvdmFsW10HYXBwcm92ZQAFCHByb3Bvc2VyBG5hbWUNcHJvcG9zYWxfbmFtZQRuYW1lBWxldmVsEHBlcm1pc3Npb25fbGV2ZWwHbWF4X2ZlZQZ1aW50NjQNcHJvcG9zYWxfaGFzaAxjaGVja3N1bTI1NiQGY2FuY2VsAAQIcHJvcG9zZXIEbmFtZQ1wcm9wb3NhbF9uYW1lBG5hbWUIY2FuY2VsZXIEbmFtZQdtYXhfZmVlBnVpbnQ2NARleGVjAAQIcHJvcG9zZXIEbmFtZQ1wcm9wb3NhbF9uYW1lBG5hbWUHbWF4X2ZlZQZ1aW50NjQIZXhlY3V0ZXIEbmFtZQlleHRlbnNpb24AAgR0eXBlBnVpbnQxNgRkYXRhBWJ5dGVzCmludmFsaWRhdGUAAgdhY2NvdW50BG5hbWUHbWF4X2ZlZQZ1aW50NjQMaW52YWxpZGF0aW9uAAIHYWNjb3VudARuYW1lFmxhc3RfaW52YWxpZGF0aW9uX3RpbWUKdGltZV9wb2ludBJvbGRfYXBwcm92YWxzX2luZm8AAw1wcm9wb3NhbF9uYW1lBG5hbWUTcmVxdWVzdGVkX2FwcHJvdmFscxJwZXJtaXNzaW9uX2xldmVsW10ScHJvdmlkZWRfYXBwcm92YWxzEnBlcm1pc3Npb25fbGV2ZWxbXRBwZXJtaXNzaW9uX2xldmVsAAIFYWN0b3IEbmFtZQpwZXJtaXNzaW9uBG5hbWUIcHJvcG9zYWwAAg1wcm9wb3NhbF9uYW1lBG5hbWUScGFja2VkX3RyYW5zYWN0aW9uBWJ5dGVzB3Byb3Bvc2UABQhwcm9wb3NlcgRuYW1lDXByb3Bvc2FsX25hbWUEbmFtZQlyZXF1ZXN0ZWQScGVybWlzc2lvbl9sZXZlbFtdB21heF9mZWUGdWludDY0A3RyeAt0cmFuc2FjdGlvbgt0cmFuc2FjdGlvbhJ0cmFuc2FjdGlvbl9oZWFkZXIDFGNvbnRleHRfZnJlZV9hY3Rpb25zCGFjdGlvbltdB2FjdGlvbnMIYWN0aW9uW10WdHJhbnNhY3Rpb25fZXh0ZW5zaW9ucwtleHRlbnNpb25bXRJ0cmFuc2FjdGlvbl9oZWFkZXIABgpleHBpcmF0aW9uDnRpbWVfcG9pbnRfc2VjDXJlZl9ibG9ja19udW0GdWludDE2EHJlZl9ibG9ja19wcmVmaXgGdWludDMyE21heF9uZXRfdXNhZ2Vfd29yZHMJdmFydWludDMyEG1heF9jcHVfdXNhZ2VfbXMFdWludDgJZGVsYXlfc2VjCXZhcnVpbnQzMgl1bmFwcHJvdmUABAhwcm9wb3NlcgRuYW1lDXByb3Bvc2FsX25hbWUEbmFtZQVsZXZlbBBwZXJtaXNzaW9uX2xldmVsB21heF9mZWUGdWludDY0BgAAAEBtems1B2FwcHJvdmUAAAAAAESFpkEGY2FuY2VsAAAAAAAAgFRXBGV4ZWMAAIDKJrlo9nQKaW52YWxpZGF0ZQAAAABAYVrprQdwcm9wb3NlAAAAUJveWs3UCXVuYXBwcm92ZQAEAADA0Wx6azUDaTY0AAASb2xkX2FwcHJvdmFsc19pbmZvAIDA0Wx6azUDaTY0AAAOYXBwcm92YWxzX2luZm8AAAAA4Gj2dANpNjQAAAxpbnZhbGlkYXRpb24AAADRYFrprQNpNjQAAAhwcm9wb3NhbAAAAAA==", - }; - default: - throw new Error(`unrecognized get_raw_abi call: ${body}`); - } - }, - }, - }; - - return mswMock(fioMocks).startServer(); -} - -export async function createWallet(): Promise { - await setupMswMocks(); - const wallet = new native.NativeHDWallet({ mnemonic, deviceId }); - await wallet.initialize(); - return wallet; -} - -export function selfTest(get: () => core.HDWallet): void { - let wallet: native.NativeHDWallet; - - beforeAll(async () => { - const w = get() as native.NativeHDWallet; - - if (native.isNative(w) && core.supportsBTC(w) && core.supportsETH(w)) { - wallet = w; - } else { - throw new Error("Wallet is not native"); - } - }); - - it("supports Ethereum mainnet", async () => { - if (!wallet) return; - expect(await wallet.ethSupportsNetwork()).toEqual(true); - }); - - it("does not support Native ShapeShift", async () => { - if (!wallet) return; - expect(wallet.ethSupportsNativeShapeShift()).toEqual(false); - expect(wallet.btcSupportsNativeShapeShift()).toEqual(false); - }); - - it("does not support Secure Transfer", async () => { - if (!wallet) return; - expect(await wallet.ethSupportsSecureTransfer()).toEqual(false); - expect(await wallet.btcSupportsSecureTransfer()).toEqual(false); - }); - - it("supports bip44 accounts", async () => { - if (!wallet) return; - expect(wallet.supportsBip44Accounts()).toEqual(true); - }); - - it("uses correct eth bip44 paths", () => { - if (!wallet) return; - [0, 1, 3, 27].forEach((account) => { - const paths = core.mustBeDefined( - wallet.ethGetAccountPaths({ - coin: "Ethereum", - accountIdx: account, - }) - ); - expect(paths).toEqual([ - { - addressNList: core.bip32ToAddressNList(`m/44'/60'/${account}'/0/0`), - hardenedPath: core.bip32ToAddressNList(`m/44'/60'/${account}'`), - relPath: [0, 0], - description: "Native", - }, - ]); - paths.forEach((path) => { - expect( - wallet.describePath({ - coin: "Ethereum", - path: path.addressNList, - }).isKnown - ).toBeTruthy(); - }); - }); - }); - - it("uses correct btc bip44 paths", () => { - if (!wallet) return; - - const paths = wallet.btcGetAccountPaths({ - coin: "Litecoin", - accountIdx: 3, - }); - - expect(paths).toEqual([ - { - addressNList: [2147483692, 2147483650, 2147483651], - scriptType: core.BTCInputScriptType.SpendAddress, - coin: "Litecoin", - }, - { - addressNList: [2147483697, 2147483650, 2147483651], - scriptType: core.BTCInputScriptType.SpendP2SHWitness, - coin: "Litecoin", - }, - { - addressNList: [2147483732, 2147483650, 2147483651], - scriptType: core.BTCInputScriptType.SpendWitness, - coin: "Litecoin", - }, - ]); - }); - - // eslint-disable-next-line jest/no-disabled-tests - it.skip("supports ethNextAccountPath", () => { - if (!wallet) return; - - const paths = core.mustBeDefined( - wallet.ethGetAccountPaths({ - coin: "Ethereum", - accountIdx: 5, - }) - ); - - expect( - paths - .map((path) => core.mustBeDefined(wallet.ethNextAccountPath(path))) - .map((path) => - wallet.describePath({ - ...path, - coin: "Ethereum", - path: path.addressNList, - }) - ) - ).toEqual([ - { - accountIdx: 6, - coin: "Ethereum", - isKnown: true, - verbose: "Ethereum Account #6", - wholeAccount: true, - isPrefork: false, - }, - ]); - }); - - it("supports btcNextAccountPath", () => { - if (!wallet) return; - - const paths = core.mustBeDefined( - wallet.btcGetAccountPaths({ - coin: "Litecoin", - accountIdx: 3, - }) - ); - - expect( - paths - .map((path) => core.mustBeDefined(wallet.btcNextAccountPath(path))) - .map((path) => - wallet.describePath({ - ...path, - path: path.addressNList, - }) - ) - ).toEqual([ - { - accountIdx: 4, - coin: "Litecoin", - isKnown: true, - scriptType: "p2pkh", - verbose: "Litecoin Account #4 (Legacy)", - wholeAccount: true, - isPrefork: false, - }, - { - accountIdx: 4, - coin: "Litecoin", - isKnown: true, - scriptType: "p2sh-p2wpkh", - verbose: "Litecoin Account #4", - wholeAccount: true, - isPrefork: false, - }, - { - accountIdx: 4, - coin: "Litecoin", - isKnown: true, - scriptType: "p2wpkh", - verbose: "Litecoin Account #4 (Segwit)", - wholeAccount: true, - isPrefork: false, - }, - ]); - }); - - it("returns true for supportsBip44Accounts", () => { - expect(wallet.supportsBip44Accounts()).toBe(true); - }); - - it("can describe a Bitcoin path", () => { - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/0'/0'/0/0"), - coin: "Bitcoin", - scriptType: core.BTCInputScriptType.SpendAddress, - }) - ).toEqual({ - verbose: "Bitcoin Account #0, Address #0 (Legacy)", - coin: "Bitcoin", - isKnown: true, - scriptType: core.BTCInputScriptType.SpendAddress, - accountIdx: 0, - addressIdx: 0, - wholeAccount: false, - isChange: false, - isPrefork: false, - }); - }); - - it("can describe a Bitcoin bech32 path", () => { - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/84'/0'/0'/0/0"), - coin: "Bitcoin", - scriptType: core.BTCInputScriptType.Bech32, - }) - ).toEqual({ - verbose: "Bitcoin Account #0, Address #0 (Segwit Native)", - coin: "Bitcoin", - isKnown: true, - scriptType: core.BTCInputScriptType.Bech32, - accountIdx: 0, - addressIdx: 0, - wholeAccount: false, - isChange: false, - isPrefork: false, - }); - }); - - it("can describe Bitcoin Change Addresses", () => { - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/0'/7'/1/5"), - coin: "Bitcoin", - scriptType: core.BTCInputScriptType.SpendAddress, - }) - ).toEqual({ - verbose: "Bitcoin Account #7, Change Address #5 (Legacy)", - coin: "Bitcoin", - isKnown: true, - scriptType: core.BTCInputScriptType.SpendAddress, - accountIdx: 7, - addressIdx: 5, - wholeAccount: false, - isChange: true, - isPrefork: false, - }); - }); - - // eslint-disable-next-line jest/no-disabled-tests - it.skip("can describe prefork BitcoinCash", () => { - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/0'/0'/0/0"), - coin: "BitcoinCash", - scriptType: core.BTCInputScriptType.SpendAddress, - }) - ).toEqual({ - verbose: "BitcoinCash Account #0, Address #0 (Prefork)", - coin: "BitcoinCash", - isKnown: true, - scriptType: core.BTCInputScriptType.SpendAddress, - accountIdx: 0, - addressIdx: 0, - wholeAccount: false, - isChange: false, - isPrefork: true, - }); - }); - - // eslint-disable-next-line jest/no-disabled-tests - it.skip("can describe prefork Segwit Native BTG", () => { - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/84'/0'/0'/0/0"), - coin: "BitcoinGold", - scriptType: core.BTCInputScriptType.SpendWitness, - }) - ).toEqual({ - verbose: "BitcoinGold Account #0, Address #0 (Prefork, Segwit Native)", - coin: "BitcoinGold", - isKnown: true, - scriptType: core.BTCInputScriptType.SpendWitness, - accountIdx: 0, - addressIdx: 0, - wholeAccount: false, - isChange: false, - isPrefork: true, - }); - }); - - // eslint-disable-next-line jest/no-disabled-tests - it.skip("can describe prefork paths", () => { - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/0'/7'/1/5"), - coin: "BitcoinCash", - scriptType: core.BTCInputScriptType.SpendAddress, - }) - ).toEqual({ - accountIdx: 7, - addressIdx: 5, - coin: "BitcoinCash", - isChange: true, - isKnown: true, - isPrefork: true, - scriptType: "p2pkh", - verbose: "BitcoinCash Account #7, Change Address #5 (Prefork)", - wholeAccount: false, - }); - }); - - it("can describe ETH paths", () => { - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - coin: "Ethereum", - }) - ).toEqual({ - verbose: "Ethereum Account #0", - coin: "Ethereum", - isKnown: true, - accountIdx: 0, - wholeAccount: true, - isPrefork: false, - }); - - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/60'/3'/0/0"), - coin: "Ethereum", - }) - ).toEqual({ - verbose: "Ethereum Account #3", - coin: "Ethereum", - isKnown: true, - accountIdx: 3, - wholeAccount: true, - isPrefork: false, - }); - - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/60'/0'/0/3"), - coin: "Ethereum", - }) - ).toEqual({ - verbose: "m/44'/60'/0'/0/3", - coin: "Ethereum", - isKnown: false, - }); - }); - - it("can describe Fio paths", () => { - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - coin: "Fio", - }) - ).toEqual({ - verbose: "Fio Account #0", - coin: "Fio", - isKnown: true, - accountIdx: 0, - wholeAccount: true, - isPrefork: false, - }); - - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/235'/3'/0/0"), - coin: "Fio", - }) - ).toEqual({ - verbose: "Fio Account #3", - coin: "Fio", - isKnown: true, - accountIdx: 3, - wholeAccount: true, - isPrefork: false, - }); - - expect( - wallet.describePath({ - path: core.bip32ToAddressNList("m/44'/235'/0'/0/3"), - coin: "Fio", - }) - ).toEqual({ - verbose: "m/44'/235'/0'/0/3", - coin: "Fio", - isKnown: false, - }); - }); -} diff --git a/package.json b/package.json index 7a89743a..893e1a37 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "lint:fix": "yarn lint --fix", "lint:ts": "tsc --noEmit", "format": "prettier .", - "build": "yarn tsc --build && lerna run build --scope @keepkey/hdwallet-native-vault", + "build": "yarn tsc --build", "dev:all": "yarn tsc --build --watch", "dev:sandbox": "cd examples/sandbox && yarn dev", "docker:run:emulator": "docker run -p 5000:5000 kktech/kkemu:latest", diff --git a/packages/hdwallet-keepkey-nodewebusb/src/transport.ts b/packages/hdwallet-keepkey-nodewebusb/src/transport.ts index 4dee22b6..2a6e8954 100644 --- a/packages/hdwallet-keepkey-nodewebusb/src/transport.ts +++ b/packages/hdwallet-keepkey-nodewebusb/src/transport.ts @@ -71,7 +71,7 @@ export class TransportDelegate implements keepkey.TransportDelegate { async writeChunk(buf: Uint8Array, debugLink?: boolean): Promise { const result = await this.usbDevice.transferOut( debugLink ? 2 : 1, - buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) + buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer ); if (result.status !== "ok" || result.bytesWritten !== buf.length) throw new Error("bad write"); } diff --git a/packages/hdwallet-keepkey-webusb/src/transport.ts b/packages/hdwallet-keepkey-webusb/src/transport.ts index 8fb22c4b..6b3a6b87 100644 --- a/packages/hdwallet-keepkey-webusb/src/transport.ts +++ b/packages/hdwallet-keepkey-webusb/src/transport.ts @@ -68,7 +68,7 @@ export class TransportDelegate implements keepkey.TransportDelegate { async writeChunk(buf: Uint8Array, debugLink: boolean): Promise { await this.usbDevice.transferOut( debugLink ? 2 : 1, - buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) + buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength) as ArrayBuffer ); } diff --git a/packages/hdwallet-keepkey/src/ethereum.ts b/packages/hdwallet-keepkey/src/ethereum.ts index 46a407b2..36d088c3 100644 --- a/packages/hdwallet-keepkey/src/ethereum.ts +++ b/packages/hdwallet-keepkey/src/ethereum.ts @@ -6,11 +6,28 @@ import * as Types from "@keepkey/device-protocol/lib/types_pb"; import * as core from "@keepkey/hdwallet-core"; import { SignTypedDataVersion, TypedDataUtils } from "@metamask/eth-sig-util"; import * as eip55 from "eip55"; -import { arrayify, isBytes, isHexString } from "ethers/lib/utils.js"; - import { Transport } from "./transport"; import { toUTF8Array } from "./utils"; +function isHexString(value: string): boolean { + return typeof value === "string" && /^0x[0-9a-fA-F]*$/.test(value); +} + +function isBytes(value: unknown): value is Uint8Array { + if (value instanceof Uint8Array) return true; + if (!Array.isArray(value)) return false; + for (const v of value) { + if (typeof v !== "number" || v < 0 || v >= 256 || v % 1 !== 0) return false; + } + return true; +} + +function arrayify(value: string | Uint8Array): Uint8Array { + if (value instanceof Uint8Array) return value; + if (typeof value === "string") return core.arrayify(value); + throw new Error("invalid arrayify value"); +} + // eslint-disable-next-line @typescript-eslint/no-unused-vars export async function ethSupportsNetwork(chainId: number): Promise { return true; @@ -241,7 +258,7 @@ export async function ethVerifyMessage(transport: Transport, msg: core.ETHVerify const m = new Ethereum.EthereumVerifyMessage(); m.setAddress(core.arrayify(msg.address)); m.setSignature(core.arrayify(msg.signature)); - m.setMessage(isBytes(msg.message) ? arrayify(msg.message) : toUTF8Array(msg.message)); + m.setMessage(isBytes(msg.message) ? new Uint8Array(msg.message) : toUTF8Array(msg.message as string)); let event: core.Event; try { event = await transport.call(Messages.MessageType.MESSAGETYPE_ETHEREUMVERIFYMESSAGE, m, { diff --git a/packages/hdwallet-keepkey/src/transport.ts b/packages/hdwallet-keepkey/src/transport.ts index 16410a6d..49388997 100644 --- a/packages/hdwallet-keepkey/src/transport.ts +++ b/packages/hdwallet-keepkey/src/transport.ts @@ -115,7 +115,7 @@ export class Transport extends core.Transport { public async getFirmwareHash(firmware: Uint8Array): Promise { if (typeof window !== "undefined" && window?.crypto) { - return new Uint8Array(await window.crypto.subtle.digest({ name: "SHA-256" }, firmware)); + return new Uint8Array(await window.crypto.subtle.digest({ name: "SHA-256" }, firmware.buffer.slice(firmware.byteOffset, firmware.byteOffset + firmware.byteLength) as ArrayBuffer)); } const hash = crypto.createHash("sha256"); hash.update(firmware); diff --git a/packages/hdwallet-native-vault/.npmignore b/packages/hdwallet-native-vault/.npmignore deleted file mode 100644 index 1de8e7c0..00000000 --- a/packages/hdwallet-native-vault/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -* -!dist/** -!package.json -!yarn.lock \ No newline at end of file diff --git a/packages/hdwallet-native-vault/jest.config.js b/packages/hdwallet-native-vault/jest.config.js deleted file mode 100644 index 8a2e953e..00000000 --- a/packages/hdwallet-native-vault/jest.config.js +++ /dev/null @@ -1,6 +0,0 @@ -/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ -module.exports = { - preset: "ts-jest", - testPathIgnorePatterns: ["dist"], - setupFiles: ["fake-indexeddb/auto"], -}; diff --git a/packages/hdwallet-native-vault/package.json b/packages/hdwallet-native-vault/package.json deleted file mode 100644 index 1f169cd4..00000000 --- a/packages/hdwallet-native-vault/package.json +++ /dev/null @@ -1,31 +0,0 @@ -{ - "name": "@keepkey/hdwallet-native-vault", - "version": "1.53.16", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "main": "dist/index.js", - "source": "src/index.ts", - "types": "dist/index.d.ts", - "scripts": { - "build": "tsc --build", - "clean": "rm -rf dist node_modules tsconfig.tsbuildinfo", - "prepublishOnly": "yarn clean && yarn build" - }, - "dependencies": { - "@keepkey/hdwallet-native": "1.53.16", - "bip39": "^3.0.4", - "hash-wasm": "^4.9.0", - "idb-keyval": "^6.0.3", - "jose": "^4.3.5", - "p-lazy": "^3.1.0", - "type-assertions": "^1.1.0", - "uuid": "^8.3.2", - "web-encoding": "^1.1.0" - }, - "devDependencies": { - "@types/tiny-secp256k1": "^1.0.0", - "fake-indexeddb": "^3.1.7" - } -} diff --git a/packages/hdwallet-native-vault/src/deterministicGetRandomValues.test.ts b/packages/hdwallet-native-vault/src/deterministicGetRandomValues.test.ts deleted file mode 100644 index 9f3e15bc..00000000 --- a/packages/hdwallet-native-vault/src/deterministicGetRandomValues.test.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { AsyncCrypto } from "./types"; - -// (This is also used in index.test.ts) -// eslint-disable-next-line jest/no-export -export async function deterministicGetRandomValues(crypto: AsyncCrypto, seed: Uint8Array = new Uint8Array(32)) { - const rngSeed = await crypto.subtle.importKey( - "raw", - seed, - { - name: "HKDF", - }, - false, - ["deriveBits"] - ); - const rngCounter = new Uint32Array(1); - - return async function getRandomValues(array: T): Promise { - rngCounter[0]++; - if (array === null) return array; - const arrayBuf = Buffer.from(array.buffer, array.byteOffset, array.byteLength); - const randomBuf = Buffer.from( - await crypto.subtle.deriveBits( - { - name: "HKDF", - hash: "SHA-256", - salt: new Uint8Array(), - info: rngCounter, - }, - rngSeed, - array.byteLength * 8 - ) - ); - if (arrayBuf.byteLength !== randomBuf.byteLength) throw new Error("rng length mismatch"); - arrayBuf.fill(randomBuf); - return array; - }; -} - -describe("deterministicGetRandomValues", () => { - it("should return deterministic values", async () => { - const getRandomValues = await deterministicGetRandomValues(require("crypto").webcrypto as Crypto); - expect(await (await getRandomValues(Buffer.alloc(16))).toString("hex")).toMatchInlineSnapshot( - `"8f9c0a54715732f707f1361325aaf80a"` - ); - expect(await (await getRandomValues(Buffer.alloc(16))).toString("hex")).toMatchInlineSnapshot( - `"6e62a809bbbbb97532704ba8e607fa4f"` - ); - expect(await (await getRandomValues(Buffer.alloc(16))).toString("hex")).toMatchInlineSnapshot( - `"5f22ec6a1e7d693101db8dfcc6333434"` - ); - expect(await (await getRandomValues(Buffer.alloc(32))).toString("hex")).toMatchInlineSnapshot( - `"2e9a42cbe2c0e8922623c9d54617df2a7632fa893092a8c2f9c2ed0ac6254500"` - ); - expect(await (await getRandomValues(Buffer.alloc(32))).toString("hex")).toMatchInlineSnapshot( - `"d074ce162d9fc9b98881ec2367381056ecaac7a2445c9c981b3a3500175460b6"` - ); - expect(await (await getRandomValues(Buffer.alloc(32))).toString("hex")).toMatchInlineSnapshot( - `"42db59172fe5e5dda7afaebc3f1cd8e41bf38a40c77fa45e3aa1cc11f83e0335"` - ); - }); -}); diff --git a/packages/hdwallet-native-vault/src/index.test.ts b/packages/hdwallet-native-vault/src/index.test.ts deleted file mode 100644 index 3067989f..00000000 --- a/packages/hdwallet-native-vault/src/index.test.ts +++ /dev/null @@ -1,222 +0,0 @@ -import * as native from "@keepkey/hdwallet-native"; -import * as idb from "idb-keyval"; -// import * as jose from "jose"; -import * as uuid from "uuid"; - -import { GENERATE_MNEMONIC, Vault } from "."; -import { deterministicGetRandomValues } from "./deterministicGetRandomValues.test"; -import { RawVault } from "./rawVault"; -import { MockVault } from "./test/mockVault.skip"; -import { ISealableVaultFactory, IVault } from "./types"; -import { keyStoreUUID, vaultStoreUUID } from "./util"; - -const keyStore = idb.createStore(keyStoreUUID, "keyval"); -const vaultStore = idb.createStore(vaultStoreUUID, "keyval"); - -jest.setTimeout(30 * 1000); - -const realCrypto = require("crypto").webcrypto as Crypto; -let mockGetRandomValues: (array: T) => Promise; -async function resetGetRandomValues() { - mockGetRandomValues = await deterministicGetRandomValues(realCrypto); -} - -type ParametersExceptFirst = F extends (arg0: any, ...rest: infer R) => any ? R : never; -async function thereCanBeOnlyOne>( - factory: U, - ...args: ParametersExceptFirst -): Promise { - const ids = await factory.list(); - if (ids.length === 0) throw new Error("can't find a vault"); - if (ids.length > 1) throw new Error(`expected a single vault; found ${ids.length}: ${ids}`); - return await factory.open(ids[0], ...(args as any)); -} - -let prepareOnce: () => void; -const preparedOnce = new Promise((resolve) => (prepareOnce = resolve)).then(async () => { - await resetGetRandomValues(); - await RawVault.prepare({ - crypto: { - randomUUID: realCrypto.randomUUID, - subtle: realCrypto.subtle, - async getRandomValues(array: T): Promise { - return await mockGetRandomValues(array); - }, - }, - performance: require("perf_hooks").performance, - }); - await RawVault.defaultArgonParams; -}); - -// eslint-disable-next-line @typescript-eslint/no-shadow -function testVaultImpl(name: string, Vault: ISealableVaultFactory) { - // eslint-disable-next-line jest/valid-title - describe(name, () => { - beforeAll(async () => { - prepareOnce(); - await preparedOnce; - await Vault.prepare(); - for (const id of await Vault.list()) await Vault.delete(id); - }); - - beforeEach(async () => { - await resetGetRandomValues(); - }); - - it("should allow repeated calls to prepare() with no options", async () => { - await expect(Vault.prepare()).resolves.not.toThrow(); - await expect(Vault.prepare()).resolves.not.toThrow(); - }); - - it("should create a new vault", async () => { - expect((await Vault.list()).length).toBe(0); - - const vault = await Vault.create(); - await vault.setPassword("foobar"); - vault.set("foo", Promise.resolve("bar")); - vault.meta.set("name", "default"); - expect(vault.meta.get("name")).toBe("default"); - await vault.save(); - - expect((await Vault.list()).length).toBe(1); - expect(vault.meta.get("name")).toBe("default"); - - console.debug("keyStore", await idb.entries(keyStore)); - console.debug("vaultStore", await idb.entries(vaultStore)); - }); - - it("should open a vault", async () => { - const vaultIDs = await Vault.list(); - expect(vaultIDs.length).toBe(1); - const vault = await Vault.open(vaultIDs[0], "foobar"); - // console.debug(jose.decodeProtectedHeader((await idb.get(vaultIDs[0], vaultStore))!)); - // console.debug("entries", vault.entries()); - expect(await vault.get("foo")).toBe("bar"); - expect(uuid.validate(vault.id)).toBe(true); - expect(vault.meta.size).toBe(1); - expect(vault.meta.get("name")).toBe("default"); - }); - - it("should store a mnemonic", async () => { - const vault = await thereCanBeOnlyOne(Vault, "foobar"); - vault.set("#mnemonic", Promise.resolve("all all all all all all all all all all all all")); - await vault.save(); - const mnemonic = (await vault.get("#mnemonic")) as native.crypto.Isolation.Engines.Default.BIP39.Mnemonic; - expect(mnemonic).toBeInstanceOf(native.crypto.Isolation.Engines.Default.BIP39.Mnemonic); - expect( - await mnemonic - .toSeed() - .then((x) => x.toMasterKey()) - .then((x) => x.getPublicKey()) - .then((x) => Buffer.from(x).toString("hex")) - ).toMatchInlineSnapshot(`"03e3b30e8c21923752a408242e069941fedbaef7db7161f7e2c5f3fdafe7e25ddc"`); - }); - - it("should retrieve the mnemonic", async () => { - const vaultIDs = await Vault.list(); - expect(vaultIDs.length).toBe(1); - const vault = await Vault.open(vaultIDs[0], "foobar"); - const mnemonic = (await vault.get("#mnemonic")) as native.crypto.Isolation.Engines.Default.BIP39.Mnemonic; - expect(mnemonic).toBeInstanceOf(native.crypto.Isolation.Engines.Default.BIP39.Mnemonic); - expect( - await mnemonic - .toSeed() - .then((x) => x.toMasterKey()) - .then((x) => x.getPublicKey()) - .then((x) => Buffer.from(x).toString("hex")) - ).toMatchInlineSnapshot(`"03e3b30e8c21923752a408242e069941fedbaef7db7161f7e2c5f3fdafe7e25ddc"`); - }); - - it("should store metadata", async () => { - const vault = await thereCanBeOnlyOne(Vault, "foobar"); - vault.meta.set("bar", "baz"); - expect(vault.meta.get("bar")).toBe("baz"); - await vault.save(); - }); - - it("should retreive metadata from the vault instance", async () => { - const vault = await thereCanBeOnlyOne(Vault, "foobar"); - expect(vault.meta.get("bar")).toBe("baz"); - }); - - it("should retreive metadata with the static method", async () => { - const id = (await thereCanBeOnlyOne(Vault)).id; - expect((await Vault.meta(id))?.get("bar")).toBe("baz"); - }); - - describe("ISealable", () => { - it("should be unwrappable before being sealed", async () => { - const vault = await thereCanBeOnlyOne(Vault, "foobar", false); - expect(vault.sealed).toBe(false); - const unwrapped = vault.unwrap(); - expect(await unwrapped.get("#mnemonic")).toBe("all all all all all all all all all all all all"); - }); - - describe("the unwrapped vault", () => { - it("should expose the mnemonic via entries()", async () => { - const vault = await thereCanBeOnlyOne(Vault, "foobar", false); - const unwrapped = vault.unwrap(); - const entries = await Promise.all(Array.from(unwrapped.entries()).map(async ([k, v]) => [k, await v])); - expect(entries).toContainEqual(["#mnemonic", "all all all all all all all all all all all all"]); - }); - it("should expose the mnemonic via values()", async () => { - const vault = await thereCanBeOnlyOne(Vault, "foobar", false); - const unwrapped = vault.unwrap(); - const values = await Promise.all(Array.from(unwrapped.values())); - expect(values).toContain("all all all all all all all all all all all all"); - }); - }); - - it("should not be unwrappable after being sealed", async () => { - const vault = await thereCanBeOnlyOne(Vault, "foobar", false); - expect(vault.sealed).toBe(false); - vault.seal(); - expect(vault.sealed).toBe(true); - expect(() => vault.unwrap()).toThrowErrorMatchingInlineSnapshot(`"can't unwrap a sealed vault"`); - }); - }); - - it("should generate a fresh, random mnemonic when provided with the GENERATE_MNEMONIC magic", async () => { - const vault = await Vault.create("foobar", false); - expect(vault.id).toMatchInlineSnapshot(`"8f9c0a54-7157-42f7-87f1-361325aaf80a"`); - vault.set("#mnemonic", Promise.resolve(GENERATE_MNEMONIC)); - await vault.save(); - - const mnemonic = (await vault.get("#mnemonic")) as native.crypto.Isolation.Engines.Default.BIP39.Mnemonic; - expect(mnemonic).toBeInstanceOf(native.crypto.Isolation.Engines.Default.BIP39.Mnemonic); - expect( - await mnemonic - .toSeed() - .then((x) => x.toMasterKey()) - .then((x) => x.getPublicKey()) - .then((x) => Buffer.from(x).toString("hex")) - ).toMatchInlineSnapshot(`"02576bde4c55b05886e56eeeeff304006352f935b6dfc1c409f7eae521dbc5558e"`); - - const unwrappedMnemonic = (await vault.unwrap().get("#mnemonic")) as string; - expect(unwrappedMnemonic).toMatchInlineSnapshot( - `"hover best act jazz romance ritual six annual pottery coral write paddle"` - ); - }); - - it("should retrieve the random mnemonic generated by the GENERATE_MNEMONIC magic", async () => { - const vault = await Vault.open("8f9c0a54-7157-42f7-87f1-361325aaf80a", "foobar", false); - - const mnemonic = (await vault.get("#mnemonic")) as native.crypto.Isolation.Engines.Default.BIP39.Mnemonic; - expect(mnemonic).toBeInstanceOf(native.crypto.Isolation.Engines.Default.BIP39.Mnemonic); - expect( - await mnemonic - .toSeed() - .then((x) => x.toMasterKey()) - .then((x) => x.getPublicKey()) - .then((x) => Buffer.from(x).toString("hex")) - ).toMatchInlineSnapshot(`"02576bde4c55b05886e56eeeeff304006352f935b6dfc1c409f7eae521dbc5558e"`); - - expect(await vault.unwrap().get("#mnemonic")).toMatchInlineSnapshot( - `"hover best act jazz romance ritual six annual pottery coral write paddle"` - ); - }); - }); -} - -testVaultImpl("Vault", Vault); -testVaultImpl("MockVault", MockVault); diff --git a/packages/hdwallet-native-vault/src/index.ts b/packages/hdwallet-native-vault/src/index.ts deleted file mode 100644 index 317ff0ba..00000000 --- a/packages/hdwallet-native-vault/src/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { createMnemonic, crypto, entropyToMnemonic, GENERATE_MNEMONIC } from "./util"; -import { Vault } from "./vault"; - -export type { ISealableVaultFactory, IVault, IVaultFactory } from "./types"; -export { GENERATE_MNEMONIC } from "./util"; -export { Vault } from "./vault"; - -Vault.registerValueTransformer("#mnemonic", async (x: unknown) => { - if (x !== GENERATE_MNEMONIC) return x; - const entropy = await (await crypto).getRandomValues(Buffer.alloc(16)); - return entropyToMnemonic(entropy); -}); -Vault.registerValueWrapper("#mnemonic", async (x: unknown, addRevoker: (revoke: () => void) => void) => { - if (typeof x !== "string") throw new TypeError("#mnemonic must be a string"); - const out = await createMnemonic(x); - addRevoker(() => out.revoke?.()); - return out; -}); -Vault.extensionRegistrationComplete(); diff --git a/packages/hdwallet-native-vault/src/mapVault.ts b/packages/hdwallet-native-vault/src/mapVault.ts deleted file mode 100644 index db5cc41e..00000000 --- a/packages/hdwallet-native-vault/src/mapVault.ts +++ /dev/null @@ -1,87 +0,0 @@ -import * as ta from "type-assertions"; - -import { RawVault } from "./rawVault"; -import { IVaultBackedBy, IVaultFactory, VaultPrepareParams } from "./types"; -import { decoder, encoder, Revocable } from "./util"; - -ta.assert>>(); - -export class MapVault - extends Revocable(Map) - implements Map>, IVaultBackedBy]>> -{ - static async prepare(params?: VaultPrepareParams) { - return RawVault.prepare(params); - } - static async create(password?: string) { - return await MapVault.open(undefined, password); - } - static async open(id?: string, password?: string) { - await MapVault.prepare(); - return new MapVault(await RawVault.open(id, password)); - } - static list() { - return RawVault.list(); - } - static meta(id: string) { - return RawVault.meta(id); - } - static delete(id: string) { - return RawVault.delete(id); - } - - readonly #rawVault: RawVault; - - protected constructor(rawVault: RawVault) { - super(); - this.addRevoker(() => this.clear()); - this.addRevoker(() => this.#rawVault.revoke()); - this.#rawVault = rawVault; - } - - get id() { - return this.#rawVault.id; - } - get meta() { - return this.#rawVault.meta; - } - - async setPassword(password: string): Promise { - await this.#rawVault.setPassword(password); - return this; - } - - async load(deserializer: (_: Array<[string, unknown | Promise]>) => Promise) { - await this.#rawVault.load(async (x: Uint8Array): Promise => { - const obj = JSON.parse(decoder.decode(x)); - await deserializer(Object.entries(obj).map(([k, v]) => [k, Promise.resolve(v)])); - }); - return this; - } - - async save(serializer: () => Promise]>>) { - await this.#rawVault.save(async (): Promise => { - const payloadObj = ( - await Promise.all((await serializer()).map(async ([k, v]): Promise<[typeof k, unknown]> => [k, await v])) - ) - .sort((a, b) => { - if (a[0] < b[0]) return -1; - if (a[0] > b[0]) return 1; - return 0; - }) - .reduce((a, [k, v]) => ((a[k] = v), a), {} as Record); - return encoder.encode(JSON.stringify(payloadObj)); - }); - return this; - } - - async entriesAsync(): Promise> { - return await Promise.all( - Array.from(this.entries()).map(async ([k, v]): Promise<[typeof k, unknown]> => [k, await v]) - ); - } -} - -Object.freeze(MapVault); -Object.freeze(MapVault.prototype); -Object.freeze(Object.getPrototypeOf(MapVault)); diff --git a/packages/hdwallet-native-vault/src/rawVault.ts b/packages/hdwallet-native-vault/src/rawVault.ts deleted file mode 100644 index 146cf411..00000000 --- a/packages/hdwallet-native-vault/src/rawVault.ts +++ /dev/null @@ -1,273 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import { argon2id } from "hash-wasm"; -import * as idb from "idb-keyval"; -import * as jose from "jose"; -import * as ta from "type-assertions"; -import * as uuid from "uuid"; - -import { ArgonParams, IVaultBackedBy, IVaultFactory, VaultPrepareParams } from "./types"; -import { crypto, encoder, keyStoreUUID, Revocable, revocable, setCrypto, setPerformance, vaultStoreUUID } from "./util"; - -// This has to be outside the class so the static initializers for defaultArgonParams and #machineSeed can reference it. -let resolvers: - | Partial<{ - machineSeed: (_: CryptoKey) => void; - defaultArgonParams: (_: ArgonParams | PromiseLike) => void; - keyStore: (_: idb.UseStore) => void; - vaultStore: (_: idb.UseStore) => void; - }> - | undefined = {}; - -ta.assert>>(); - -export class RawVault extends Revocable(Object.freeze(class {})) implements IVaultBackedBy { - //#region static: prepare() - static readonly defaultArgonParams: Promise = new Promise( - (resolve) => resolvers && (resolvers.defaultArgonParams = resolve) - ); - - // Caching the machine seed also conveniently hides the inability of the fake-indexeddb package to store CryptoKey objects. - static readonly #machineSeed: Promise = new Promise( - (resolve) => resolvers && (resolvers.machineSeed = resolve) - ); - static readonly #keyStore: Promise = new Promise( - (resolve) => resolvers && (resolvers.keyStore = resolve) - ); - static readonly #vaultStore: Promise = new Promise( - (resolve) => resolvers && (resolvers.vaultStore = resolve) - ); - - static async prepare(params?: VaultPrepareParams) { - const currentResolvers = resolvers; - resolvers = undefined; - if (!currentResolvers) { - if (params) throw new Error("can't call prepare with a parameters object after vault is already prepared"); - return; - } - - setCrypto(params?.crypto ?? globalThis.crypto); - setPerformance(params?.performance ?? globalThis.performance); - - currentResolvers.keyStore?.(params?.keyStore ?? idb.createStore(keyStoreUUID, "keyval")); - currentResolvers.vaultStore?.(params?.vaultStore ?? idb.createStore(vaultStoreUUID, "keyval")); - currentResolvers.machineSeed?.( - (await idb.get("machineSeed", await RawVault.#keyStore)) ?? - (await (async () => { - const machineSeed = await ( - await crypto - ).subtle.importKey("raw", await (await crypto).getRandomValues(new Uint8Array(32)), "HKDF", false, [ - "deriveBits", - "deriveKey", - ]); - await idb.set("machineSeed", machineSeed, await RawVault.#keyStore); - return machineSeed; - })()) - ); - - currentResolvers.defaultArgonParams?.( - (await idb.get("defaultArgonParams", await RawVault.#keyStore)) ?? { - then: (onfulfilled, onrejected) => { - return (async () => { - // For more details on parameter selection, see: - // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-argon2-04#section-4 - const out: ArgonParams = { - parallelism: 1, - memorySize: 32 * 1024, - iterations: 16, - }; - - await idb.set("defaultArgonParams", out, await RawVault.#keyStore); - - return out; - })().then(onfulfilled, onrejected); - }, - } - ); - } - //#endregion - - static async #deriveVaultKey( - machineSeed: CryptoKey, - id: string, - argonParams: ArgonParams, - password: string, - // eslint-disable-next-line @typescript-eslint/no-unused-vars - addRevoker: (revoke: () => void) => void - ) { - const idBuf = encoder.encode(id); - - const argonSalt = new Uint8Array( - await ( - await crypto - ).subtle.deriveBits( - { - name: "HKDF", - hash: "SHA-256", - salt: idBuf, - info: encoder.encode("argonSalt"), - }, - machineSeed, - 128 - ) - ); - - const argonKey = await argon2id({ - ...argonParams, - password, - salt: argonSalt, - hashLength: 32, - outputType: "binary", - }); - - // It might make more logical sense to use the argon-derived key in the salt field, but both fields provide - // equivalent security, and using idBuf as the seed in both places permits some optimization by sharing - // the result of HDKF-Extract between both calculations. (This isn't done right now, and can't be done with - // the WebCrypto API as it is, but maybe we'll use something else some day.) - const vaultKey = await ( - await crypto - ).subtle.deriveKey( - { - name: "HKDF", - hash: "SHA-256", - salt: idBuf, - info: argonKey, - }, - machineSeed, - { - name: "AES-KW", - length: 256, - }, - false, - ["wrapKey", "unwrapKey"] - ); - - //TODO: Returning a revocable doesn't work here; WebCrypto in the browser complains about the proxy. Fix this. - return vaultKey; - // return revocable(vaultKey, addRevoker); - } - - //#region static: VaultFactory - static async create(password?: string) { - return await RawVault.open(undefined, password); - } - - static async open(id?: string, password?: string) { - await RawVault.prepare(); - - // eslint-disable-next-line @typescript-eslint/no-shadow - const factory = async (id: string, argonParams: Promise) => { - const vaultRevoker = new (Revocable(class {}))(); - const vault = revocable(new RawVault(id, argonParams), (x) => vaultRevoker.addRevoker(x)); - vault.addRevoker(() => vaultRevoker.revoke()); - return vault; - }; - - const out = await (async () => { - if (id !== undefined) { - const jwe = await idb.get(id, await RawVault.#vaultStore); - if (!jwe) throw new Error("can't find specified vault"); - const protectedHeader = jose.decodeProtectedHeader(jwe); - const argonParams = protectedHeader.argon as ArgonParams | undefined; - if (!argonParams) throw new Error("can't decode vault with missing argon parameters"); - - return await factory(id, Promise.resolve(argonParams)); - } else { - return await factory( - uuid.v4({ - random: await (await crypto).getRandomValues(new Uint8Array(16)), - }), - RawVault.defaultArgonParams - ); - } - })(); - if (password !== undefined) await out.setPassword(password); - return out; - } - - static async list(): Promise { - await RawVault.prepare(); - const out = (await idb.keys(await RawVault.#vaultStore)) - .filter((k) => typeof k === "string") - .map((k) => k as string); - return out; - } - - static async meta(id: string): Promise | undefined> { - await RawVault.prepare(); - const jwe = await idb.get(id, await RawVault.#vaultStore); - if (!jwe) return undefined; - const meta = jose.decodeProtectedHeader(jwe).meta; - if (!meta || !core.isIndexable(meta)) return undefined; - const out = new Map(); - Object.entries(meta).forEach(([k, v]) => out.set(k, v)); - return out; - } - - static async delete(id: string): Promise { - await RawVault.prepare(); - await idb.del(id, await RawVault.#vaultStore); - } - //#endregion - - readonly id: string; - readonly #argonParams: Promise>; - readonly meta: Map = new Map(); - - #key: CryptoKey | undefined; - - protected constructor(id: string, argonParams: Promise) { - super(); - this.id = id; - this.#argonParams = argonParams.then((x) => Object.freeze(JSON.parse(JSON.stringify(x)))); - } - - async setPassword(password: string): Promise { - this.#key = await RawVault.#deriveVaultKey( - await RawVault.#machineSeed, - this.id, - await this.#argonParams, - password, - (x) => this.addRevoker(x) - ); - return this; - } - - async load(deserialize: (_: Uint8Array) => Promise): Promise { - if (!this.#key) throw new Error("can't load vault until key is set"); - const jwe = await idb.get(this.id, await RawVault.#vaultStore); - if (!jwe) throw new Error("can't load missing vault"); - - const decryptResult = await jose.flattenedDecrypt(jwe, this.#key, { - keyManagementAlgorithms: ["A256KW"], - contentEncryptionAlgorithms: ["A256GCM"], - }); - this.meta.clear(); - const meta = decryptResult.protectedHeader?.meta; - if (core.isIndexable(meta)) { - Object.entries(meta).forEach(([k, v]) => this.meta.set(k, v)); - } - await deserialize(decryptResult.plaintext); - - return this; - } - - async save(serialize: () => Promise): Promise { - if (!this.#key) throw new Error("can't save vault until key is set"); - const payload = await serialize(); - //TODO: override the rng used by jose to calculate the CEK and IV with the dependency-injected one. - const jwe = await new jose.FlattenedEncrypt(payload) - .setProtectedHeader({ - alg: "A256KW", - enc: "A256GCM", - argon: await this.#argonParams, - meta: Array.from(this.meta.entries()).reduce((a, [k, v]) => ((a[k] = v), a), {} as Record), - }) - .encrypt(this.#key); - await idb.set(this.id, jwe, await RawVault.#vaultStore); - return this; - } -} - -Object.freeze(RawVault); -Object.freeze(RawVault.prototype); -Object.freeze(Object.getPrototypeOf(RawVault)); diff --git a/packages/hdwallet-native-vault/src/test/mockVault.skip.ts b/packages/hdwallet-native-vault/src/test/mockVault.skip.ts deleted file mode 100644 index b47d7b54..00000000 --- a/packages/hdwallet-native-vault/src/test/mockVault.skip.ts +++ /dev/null @@ -1,145 +0,0 @@ -/* This is intended to be used to test the tests. It should not be shipped or *shudder* actually used. */ -import * as core from "@keepkey/hdwallet-core"; -import * as native from "@keepkey/hdwallet-native"; -import * as bip39 from "bip39"; -import * as ta from "type-assertions"; -import * as uuid from "uuid"; - -import { ISealableVaultFactory, IVault, VaultPrepareParams } from "../types"; -import { crypto, GENERATE_MNEMONIC, Revocable, setCrypto, shadowedMap } from "../util"; - -ta.assert>>(); - -type MockVaultData = { - password: string; - data: Array<[string, unknown]>; - meta: Array<[string, unknown]>; -}; - -export class MockVault extends Revocable(Map) implements IVault, Map> { - static readonly data = new Map(); - static prepared = false; - - static async prepare(params?: VaultPrepareParams) { - if (params) { - if (this.prepared) throw new Error("can't call prepare with a parameters object after vault is already prepared"); - setCrypto(params.crypto ?? window.crypto); - } - this.prepared = true; - } - static async create(password?: string, sealed?: boolean): Promise { - return await MockVault.open(undefined, password, sealed); - } - static async open(id?: string, password?: string, sealed?: boolean): Promise { - await MockVault.prepare(); - id ??= uuid.v4({ - random: await (await crypto).getRandomValues(new Uint8Array(16)), - }); - const out = new MockVault(id, password, sealed); - if (id !== undefined && password !== undefined) await out.load(); - return out; - } - static async list() { - return Array.from(MockVault.data.keys()); - } - static async meta(id: string) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return MockVault.data.has(id) ? new Map(MockVault.data.get(id)!.meta) : undefined; - } - static async delete(id: string) { - MockVault.data.delete(id); - } - - readonly id: string; - readonly meta = new Map(); - - _password: string | undefined = undefined; - readonly _secrets = new Map(); - - protected constructor(id: string, password?: string, sealed = true) { - super(); - this.id = id; - this._password = password; - if (sealed) this.seal(); - } - - async setPassword(password: string): Promise { - this._password = password; - return this; - } - - async load() { - const data = MockVault.data.get(this.id); - if (!data) throw new Error("no such vault"); - if (this._password !== data.password) throw new Error("bad password"); - this.clear(); - this._secrets.clear(); - data.data.forEach(([k, v]) => this.set(k, v)); - this.meta.clear(); - data.meta.forEach(([k, v]) => this.meta.set(k, v)); - return this; - } - - async save() { - if (!this._password) throw new Error("can't save without password"); - const data = { - password: this._password, - data: await this._unwrap().entriesAsync(), - meta: Array.from(this.meta.entries()), - }; - MockVault.data.set(this.id, data); - return this; - } - - async entriesAsync(): Promise> { - return await Promise.all( - Array.from(this.entries()).map(async ([k, v]: [string, Promise]) => [k, await v] as [string, unknown]) - ); - } - - set(key: string, value: unknown | Promise): this { - if (!key.startsWith("#")) { - super.set(key, Promise.resolve(value)); - return this; - } - if (key === "#mnemonic") { - value = Promise.resolve(value).then(async (x) => { - if (x !== GENERATE_MNEMONIC) return x; - const entropy = await (await crypto).getRandomValues(Buffer.alloc(16)); - return bip39.entropyToMnemonic(entropy); - }); - } - this._secrets.set(key, Promise.resolve(value)); - super.set( - key, - (async () => { - switch (key) { - case "#mnemonic": - return await native.crypto.Isolation.Engines.Default.BIP39.Mnemonic.create((await value) as string); - default: - return core.untouchable(key); - } - })() - ); - return this; - } - - sealed = false; - seal() { - this.sealed = true; - } - unwrap() { - if (this.sealed) throw new Error("can't unwrap a sealed vault"); - return this._unwrap(); - } - _unwrap() { - return shadowedMap( - this, - (key: string) => { - return key.startsWith("#") ? this._secrets.get(key) : this.get(key); - }, - // eslint-disable-next-line @typescript-eslint/no-empty-function - () => {} - ); - } -} diff --git a/packages/hdwallet-native-vault/src/types.ts b/packages/hdwallet-native-vault/src/types.ts deleted file mode 100644 index 57d07265..00000000 --- a/packages/hdwallet-native-vault/src/types.ts +++ /dev/null @@ -1,68 +0,0 @@ -import type { IArgon2Options } from "hash-wasm"; -import type * as idb from "idb-keyval"; - -import type { Revocable } from "./util"; - -export type AsyncCrypto = Omit & { - getRandomValues< - T extends - | DataView - | Float32Array - | Float64Array - | Uint8ClampedArray - | Uint8Array - | Int8Array - | Int16Array - | Int32Array - | Uint16Array - | Uint32Array - | null - >( - array: T - ): T | Promise; -}; - -export type ArgonParams = Pick; - -export type VaultPrepareParams = Partial<{ - crypto: AsyncCrypto; - performance: Performance; - keyStore: idb.UseStore; - vaultStore: idb.UseStore; -}>; - -export interface IVaultFactory | IVault> { - readonly prepare: (params?: VaultPrepareParams) => Promise; - readonly create: (password?: string) => Promise; - readonly open: (id?: string, password?: string) => Promise; - readonly list: () => Promise; - readonly meta: (id: string) => Promise | undefined>; - readonly delete: (id: string) => Promise; -} - -export interface ISealableVaultFactory | IVault)> extends IVaultFactory { - readonly create: (password?: string, sealed?: boolean) => Promise; - readonly open: (id?: string, password?: string, sealed?: boolean) => Promise; -} - -export interface IVaultBackedBy { - readonly id: string; - readonly meta: Map; - setPassword(password: string): Promise; - load(deserialize: (_: T) => Promise): Promise; - save(serialize: () => Promise): Promise; -} - -export interface ISealable extends Revocable { - readonly sealed: boolean; - seal(): void; - unwrap(addRevoker?: (revoke: () => void) => void): this; -} - -export interface IVault extends Map>, ISealable, Revocable { - readonly id: string; - readonly meta: Map; - setPassword(password: string): Promise; - load(): Promise; - save(): Promise; -} diff --git a/packages/hdwallet-native-vault/src/util.ts b/packages/hdwallet-native-vault/src/util.ts deleted file mode 100644 index 4bfa3fcd..00000000 --- a/packages/hdwallet-native-vault/src/util.ts +++ /dev/null @@ -1,83 +0,0 @@ -import * as native from "@keepkey/hdwallet-native"; -import * as bip39 from "bip39"; -import PLazy from "p-lazy"; -import * as uuid from "uuid"; -import { TextDecoder, TextEncoder } from "web-encoding"; - -import { AsyncCrypto } from "./types"; - -const nativeEngines = PLazy.from(async () => { - return (await import("@keepkey/hdwallet-native")).crypto.Isolation.Engines; -}); - -export async function createMnemonic(mnemonic: string) { - return (await nativeEngines).Default.BIP39.Mnemonic.create(mnemonic); -} -export const entropyToMnemonic = bip39.entropyToMnemonic.bind(bip39); - -let cryptoResolver: ((x: AsyncCrypto) => void) | undefined; - -export function setCrypto(x: AsyncCrypto) { - if (!x) throw new Error("crypto module is required"); - if (!cryptoResolver) throw new Error("can only set crypto module once"); - cryptoResolver(x); - cryptoResolver = undefined; -} -export const crypto = new Promise((resolve) => (cryptoResolver = resolve)); - -let performanceResolver: ((x: Performance) => void) | undefined; -export function setPerformance(x: Performance) { - if (!x) throw new Error("performance module is required"); - if (!performanceResolver) throw new Error("can only set performance module once"); - performanceResolver(x); - performanceResolver = undefined; -} -export const performance = new Promise((resolve) => (performanceResolver = resolve)); - -export const uuidNamespace = uuid.v5("hdwallet-native-vault", uuid.NIL); -export const keyStoreUUID = uuid.v5("keyStore", uuidNamespace); -export const vaultStoreUUID = uuid.v5("vaultStore", uuidNamespace); -// Using a dynamic v4 UUID for GENERATE_MNEMONIC is slightly more correct and secure, but it could also be a v5 UUID: -// export const GENERATE_MNEMONIC = uuid.v5("GENERATE_MNEMONIC", uuidNamespace); -export const GENERATE_MNEMONIC = uuid.v4(); - -export type Revocable = native.crypto.Isolation.Engines.Default.Revocable; -export const Revocable = native.crypto.Isolation.Engines.Default.Revocable; -export const revocable = native.crypto.Isolation.Engines.Default.revocable; -export const decoder = new TextDecoder(); -export const encoder = new TextEncoder(); - -export function shadowedMap>( - map: T, - get: (key: K) => undefined | V, - addRevoker: (revoke: () => void) => void -): T { - const self = map; - const { proxy, revoke } = Proxy.revocable(self, { - get(t, p, r) { - switch (p) { - case "get": - return get.bind(self); - case "values": - return () => Array.from(self.keys()).map((k) => get(k)); - case "entries": - return () => Array.from(self.keys()).map((k) => [k, get(k)]); - case "entriesAsync": - return () => Promise.all(Array.from(self.keys()).map(async (k) => [k, await get(k)])); - case "forEach": - return (callbackFn: (v?: V, k?: K, m?: typeof self) => void, thisArg?: object) => { - for (const key of self.keys()) { - callbackFn.call(thisArg, get(key), key, self); - } - }; - default: { - const out = Reflect.get(t, p, r); - // if (!String(p).startsWith("_") && typeof out === "function") return out.bind(t); - return out; - } - } - }, - }); - addRevoker(revoke); - return proxy; -} diff --git a/packages/hdwallet-native-vault/src/vault.ts b/packages/hdwallet-native-vault/src/vault.ts deleted file mode 100644 index 5dfad754..00000000 --- a/packages/hdwallet-native-vault/src/vault.ts +++ /dev/null @@ -1,198 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as jose from "jose"; -import * as ta from "type-assertions"; - -import { MapVault } from "./mapVault"; -import { RawVault } from "./rawVault"; -import { ISealableVaultFactory, IVault, VaultPrepareParams } from "./types"; -import { crypto, decoder, encoder, Revocable, revocable, shadowedMap } from "./util"; - -export type ValueWrapper = (x: unknown, addRevoker: (revoke: () => void) => void) => Promise; -export type ValueTransformer = (x: unknown, addRevoker: (revoke: () => void) => void) => Promise; - -ta.assert>>(); - -export class Vault extends MapVault implements IVault { - //#region static - static async prepare(params?: VaultPrepareParams) { - return MapVault.prepare(params); - } - static async create(password?: string, sealed = true) { - return await Vault.open(undefined, password, sealed); - } - static async open(id?: string, password?: string, sealed = true) { - await Vault.prepare(); - - const out = new Vault(await RawVault.open(id, password)); - if (sealed) out.seal(); - if (id !== undefined && password !== undefined) await out.load(); - return out; - } - - static #isPrivateKey(key: string) { - return String(key).startsWith("#"); - } - - static #extensionRegistrationComplete = false; - static extensionRegistrationComplete() { - Vault.#extensionRegistrationComplete = true; - } - - static readonly #valueWrappers: Map = new Map(); - static registerValueWrapper(key: string, valueWrapper: ValueWrapper) { - if (Vault.#extensionRegistrationComplete) - throw new Error(`can't register value wrapper after registration is complete`); - if (!Vault.#isPrivateKey(key)) throw new TypeError(`can't set value wrapper for non-private key '${key}'`); - if (Vault.#valueWrappers.has(key)) throw new Error(`can't overwrite previously-set value wrapper for key '${key}'`); - Vault.#valueWrappers.set(key, valueWrapper); - } - static #wrapPrivateValue(key: string, value: unknown | Promise, addRevoker: (revoke: () => void) => void) { - if (!this.#isPrivateKey(key)) throw new TypeError(`can't wrap value with non-private key '${key}'`); - const valueWrapper = this.#valueWrappers.get(key); - // if (!valueWrapper) throw new Error(`private key '${key}' does not have a registered value wrapper`) - if (!valueWrapper) return core.untouchable(`no value wrapper registered for private key '${key}'`); - return (async () => await valueWrapper(await value, addRevoker))(); - } - - static readonly #valueTransformers: Map = new Map(); - static registerValueTransformer(key: string, valueTransformer: ValueTransformer) { - if (Vault.#extensionRegistrationComplete) - throw new Error(`can't register value transformer after registration is complete`); - if (!Vault.#isPrivateKey(key)) throw new TypeError(`can't set value transformer for non-private key '${key}'`); - if (Vault.#valueTransformers.has(key)) - throw new Error(`can't overwrite previously-set value transformer for key '${key}'`); - Vault.#valueTransformers.set(key, valueTransformer); - } - static #transformValue(key: string, value: unknown | Promise, addRevoker: (revoke: () => void) => void) { - const valueTransformer = this.#valueTransformers.get(key); - if (!valueTransformer) return value; - return (async () => await valueTransformer(await value, addRevoker))(); - } - //#endregion - - readonly #shieldingKey: Promise = (async () => { - const out = (await crypto).subtle.generateKey( - { - name: "AES-KW", - length: 256, - }, - false, - ["wrapKey", "unwrapKey"] - ); - return revocable(out, this.addRevoker.bind(this)); - })(); - - readonly #privateContents: Map>; - readonly #wrapperRevokers: Map void> = new Map(); - - protected constructor(rawVault: RawVault) { - super(rawVault); - this.#privateContents = revocable(new Map(), (x) => this.addRevoker(x)); - this.addRevoker(() => this.clear()); - } - - #revokeWrapperForValue(x: unknown) { - this.#wrapperRevokers.get(x)?.(); - this.#wrapperRevokers.delete(x); - } - - #revokeWrapperForKey(key: string) { - this.#revokeWrapperForValue(this.#privateContents.get(key)); - } - - clear() { - this.#privateContents.forEach((x) => this.#revokeWrapperForValue(x)); - this.#privateContents.clear(); - this.#wrapperRevokers.clear(); - super.clear(); - } - - delete(key: string) { - this.#revokeWrapperForKey(key); - this.#privateContents.delete(key); - return super.delete(key); - } - - set(key: string, value: unknown | Promise): this { - value = Vault.#transformValue(key, value, this.addRevoker.bind(this)); - if (!Vault.#isPrivateKey(key)) return super.set(key, value); - - this.#revokeWrapperForKey(key); - this.#privateContents.set( - key, - (async () => { - const payload = encoder.encode(JSON.stringify(await value)); - return new jose.FlattenedEncrypt(payload) - .setProtectedHeader({ - alg: "A256KW", - enc: "A256GCM", - }) - .encrypt(await this.#shieldingKey); - })() - ); - - const wrapperRevoker = new (Revocable(class {}))(); - const wrapper = Vault.#wrapPrivateValue(key, value, (x) => wrapperRevoker.addRevoker(x)); - this.#wrapperRevokers.set(key, () => wrapperRevoker.revoke()); - return super.set(key, wrapper); - } - - #getUnwrapped(key: string): undefined | unknown | Promise { - if (!Vault.#isPrivateKey(key)) return this.get(key); - const jwe = this.#privateContents.get(key); - if (!jwe) return undefined; - return (async () => { - const decryptResult = await jose.flattenedDecrypt(await jwe, await this.#shieldingKey, { - keyManagementAlgorithms: ["A256KW"], - contentEncryptionAlgorithms: ["A256GCM"], - }); - const out = JSON.parse(decoder.decode(decryptResult.plaintext)); - return out; - })(); - } - - #unwrap(addRevoker: (revoke: () => void) => void = (x) => this.addRevoker(x)) { - return shadowedMap(this, (x: string) => this.#getUnwrapped(x), addRevoker); - } - - #sealed = false; - seal() { - this.#sealed = true; - } - get sealed() { - return this.#sealed; - } - - unwrap(addRevoker?: (revoke: () => void) => void) { - if (this.#sealed) throw new Error("can't unwrap a sealed vault"); - return this.#unwrap((x) => { - this.addRevoker(x); - addRevoker?.(x); - }); - } - - async load() { - await super.load(async (entries) => { - this.clear(); - entries.forEach(([k, v]) => this.set(k, v)); - }); - return this; - } - - async save() { - const unwrappedRevoker = new (Revocable(class {}))(); - const unwrapped = this.#unwrap((x) => unwrappedRevoker.addRevoker(x)); - await super.save( - async () => - await Promise.all( - Array.from(unwrapped.entries()).map(async ([k, v]): Promise<[typeof k, typeof v]> => [k, await v]) - ) - ); - unwrappedRevoker.revoke(); - return this; - } -} - -Object.freeze(Vault); -Object.freeze(Vault.prototype); -Object.freeze(Object.getPrototypeOf(Vault)); diff --git a/packages/hdwallet-native-vault/tsconfig.json b/packages/hdwallet-native-vault/tsconfig.json deleted file mode 100644 index f2d80ddd..00000000 --- a/packages/hdwallet-native-vault/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "dist" - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "test", "**/*.test.ts"], - "references": [{ "path": "../hdwallet-core" }, { "path": "../hdwallet-native" }] -} diff --git a/packages/hdwallet-native/.npmignore b/packages/hdwallet-native/.npmignore deleted file mode 100644 index 1de8e7c0..00000000 --- a/packages/hdwallet-native/.npmignore +++ /dev/null @@ -1,4 +0,0 @@ -* -!dist/** -!package.json -!yarn.lock \ No newline at end of file diff --git a/packages/hdwallet-native/__mocks__/@shapeshiftoss/hdwallet-core.ts b/packages/hdwallet-native/__mocks__/@shapeshiftoss/hdwallet-core.ts deleted file mode 100644 index f24132d8..00000000 --- a/packages/hdwallet-native/__mocks__/@shapeshiftoss/hdwallet-core.ts +++ /dev/null @@ -1,8 +0,0 @@ -// This ensures that the module's exports are all writable, so that jest.spyOn() will work. -const actual = jest.requireActual("@keepkey/hdwallet-core"); -const mock: any = {}; -for (const key of Object.keys(Object.getOwnPropertyDescriptors(actual))) { - mock[key] = actual[key]; -} -module.exports = mock as typeof actual; -export {}; diff --git a/packages/hdwallet-native/__mocks__/mswMock.ts b/packages/hdwallet-native/__mocks__/mswMock.ts deleted file mode 100644 index ce1db919..00000000 --- a/packages/hdwallet-native/__mocks__/mswMock.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { rest } from "msw"; -import { setupServer } from "msw/node"; - -export = function newMswMock(handlers: Record> = {}) { - Object.values(handlers).forEach((x) => { - Object.entries(x).forEach(([k, v]) => { - x[k] = Object.assign( - jest.fn((...args: any[]) => (typeof v === "function" ? v(...args) : v)), - v - ); - }); - }); - - const processedHandlers = handlers as Record>; - - const self = jest.fn(); - return Object.assign(self, { - handlers: processedHandlers, - setupServer() { - return setupServer( - ...Object.entries(this.handlers) - .map(([method, mocks]) => - Object.entries(mocks).map(([k, v]) => { - return (rest as any)[method](k, (req: any, res: any, ctx: any) => { - const body = typeof req.body === "string" && req.body !== "" ? JSON.parse(req.body) : req.body; - if (body !== undefined && body !== "") { - self(method.toUpperCase(), k, body); - } else { - self(method.toUpperCase(), k); - } - let status = 200; - let out; - try { - out = v(body); - } catch (e) { - if (typeof e !== "number") throw e; - status = e; - out = {}; - } - return res(ctx.status(status), ctx.json(out)); - }); - }) - ) - .reduce((a, x) => a.concat(x), []) - ); - }, - startServer() { - this.setupServer().listen({ - onUnhandledRequest(req) { - self(req.method, req.url.href); - console.error("Unhandled request:", req.method, req.url.href); - throw new Error(`Unhandled ${req.method} request to ${req.url.href}`); - }, - }); - return this; - }, - clear() { - self.mockClear(); - Object.values(this.handlers).forEach((x) => Object.values(x).forEach((y) => y.mockClear())); - }, - }); -}; diff --git a/packages/hdwallet-native/__mocks__/untouchableMock.ts b/packages/hdwallet-native/__mocks__/untouchableMock.ts deleted file mode 100644 index c8f5a539..00000000 --- a/packages/hdwallet-native/__mocks__/untouchableMock.ts +++ /dev/null @@ -1,47 +0,0 @@ -function mockTraps(mock: () => unknown) { - return new Proxy( - {}, - { - get(_, propName) { - return (...args: any[]) => (mock(), (Reflect as any)[propName](...args)); - }, - } - ); -} - -function doMock(target: T) { - const mock = jest.fn(); - return [ - typeof target === "object" || typeof target === "function" ? new Proxy(target, mockTraps(mock)) : target, - mock, - ] as const; -} - -export function bind(obj: Record unknown>, prop: string, ...args: any[]) { - const mock = jest.fn(); - const [objProxy, objMock] = doMock(obj); - objMock.mockImplementation(() => mock()); - const argProxies = args.map((arg) => { - const [argProxy, argMock] = doMock(arg); - argMock.mockImplementation(() => mock()); - return argProxy; - }); - return [Function.prototype.bind.call(obj[prop], objProxy, ...argProxies), mock]; -} - -export function call(obj: Record unknown>, prop: string, ...args: any[]) { - expect(obj[prop]).toBeInstanceOf(Function); - const [fn, mock] = bind(obj, prop, ...args); - const out = fn(); - if ((typeof out === "object" || typeof out === "function") && "then" in out && out.then instanceof Function) { - return (async () => { - await out; // make sure the method under test has time to hit the tripwire - expect(mock).not.toHaveBeenCalled(); - return out; - })(); - } - expect(mock).not.toHaveBeenCalled(); - return out; -} - -export const mock = doMock; diff --git a/packages/hdwallet-native/jest.config.js b/packages/hdwallet-native/jest.config.js deleted file mode 100644 index b711350e..00000000 --- a/packages/hdwallet-native/jest.config.js +++ /dev/null @@ -1,4 +0,0 @@ -module.exports = { - preset: "ts-jest", - testPathIgnorePatterns: ["dist"], -}; diff --git a/packages/hdwallet-native/package.json b/packages/hdwallet-native/package.json deleted file mode 100644 index bf4583f2..00000000 --- a/packages/hdwallet-native/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "name": "@keepkey/hdwallet-native", - "version": "1.53.16", - "license": "MIT", - "publishConfig": { - "access": "public" - }, - "main": "dist/index.js", - "source": "src/index.ts", - "types": "dist/index.d.ts", - "scripts": { - "build": "tsc --build", - "clean": "rm -rf dist node_modules tsconfig.tsbuildinfo", - "prepublishOnly": "yarn clean && yarn build" - }, - "dependencies": { - "@keepkey/hdwallet-core": "1.53.16", - "@keepkey/proto-tx-builder": "^0.9.1", - "@shapeshiftoss/bitcoinjs-lib": "5.2.0-shapeshift.2", - "@shapeshiftoss/fiosdk": "1.2.1-shapeshift.6", - "@zxing/text-encoding": "^0.9.0", - "bchaddrjs": "^0.4.9", - "bech32": "^1.1.4", - "bignumber.js": "^9.0.1", - "bip32": "^2.0.5", - "bip39": "^3.0.2", - "crypto-js": "^4.0.0", - "eip-712": "^1.0.0", - "ethers": "5.7.2", - "eventemitter2": "^5.0.1", - "funtypes": "^3.0.1", - "lodash": "^4.17.21", - "node-fetch": "^2.6.1", - "p-lazy": "^3.1.0", - "scrypt-js": "^3.0.1", - "tendermint-tx-builder": "^1.0.9", - "tiny-secp256k1": "^1.1.6", - "web-encoding": "^1.1.0" - }, - "devDependencies": { - "@cosmjs/amino": "^0.28.13", - "@cosmjs/proto-signing": "^0.28.13", - "@cosmjs/stargate": "^0.28.13", - "@peculiar/webcrypto": "^1.4.3", - "@types/bchaddrjs": "^0.4.0", - "@types/big.js": "^6.0.2", - "@types/bs58": "^4.0.1", - "@types/bs58check": "^2.1.0", - "@types/crypto-js": "^4.0.0", - "@types/elliptic": "^6.4.12", - "@types/lodash": "^4.14.168", - "@types/node-fetch": "^2.5.10", - "@types/tiny-secp256k1": "^1.0.0", - "@types/wif": "^2.0.2", - "bs58": "^4.0.1", - "cosmjs-types": "^0.4.1", - "msw": "^0.27.1" - } -} diff --git a/packages/hdwallet-native/src/adapter.test.ts b/packages/hdwallet-native/src/adapter.test.ts deleted file mode 100644 index da62b7cf..00000000 --- a/packages/hdwallet-native/src/adapter.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import { NativeAdapter } from "./adapter"; -import { NativeHDWallet } from "./native"; - -describe("NativeAdapter", () => { - it("creates a unique wallet per deviceId", async () => { - const keyring = new core.Keyring(); - const adapter = NativeAdapter.useKeyring(keyring); - expect(await adapter.initialize()).toBe(0); - const wallet = await adapter.pairDevice("foobar"); - expect(wallet).toBeInstanceOf(NativeHDWallet); - expect(await adapter.pairDevice("foobar")).toBe(wallet); - }); - - it("won't pair if the deviceId isn't specified", async () => { - const keyring = new core.Keyring(); - const adapter = NativeAdapter.useKeyring(keyring); - expect(await adapter.pairDevice(undefined as any)).toBe(null); - }); - - it("won't pair if a non-native wallet with the same deviceId is present in the keyring", async () => { - const keyring = new core.Keyring(); - const adapter = NativeAdapter.useKeyring(keyring); - const dummyWallet = {}; - keyring.add(dummyWallet as any, "foobar"); - expect(await adapter.pairDevice("foobar")).toBe(null); - }); -}); diff --git a/packages/hdwallet-native/src/adapter.ts b/packages/hdwallet-native/src/adapter.ts deleted file mode 100644 index 6ce76e1a..00000000 --- a/packages/hdwallet-native/src/adapter.ts +++ /dev/null @@ -1,53 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as Isolation from "./crypto/isolation"; -import * as native from "./native"; - -export type NativeAdapterArgs = { - deviceId: string; -} & ( - | { - mnemonic?: string | Isolation.Core.BIP39.Mnemonic; - masterKey?: never; - } - | { - mnemonic?: never; - masterKey?: Isolation.Core.BIP32.Node; - } -); - -export class NativeAdapter { - keyring: core.Keyring; - - private constructor(keyring: core.Keyring) { - this.keyring = keyring; - } - - static useKeyring(keyring: core.Keyring) { - return new NativeAdapter(keyring); - } - - async initialize(): Promise { - return 0; - } - - async pairDevice(deviceId: string): Promise { - let wallet: core.HDWallet | null = this.keyring.get(deviceId); - if (!wallet && deviceId) { - // If a wallet with that ID hasn't been added to the keychain, then create it - wallet = await native.create({ deviceId }); - if (!native.isNative(wallet)) throw new Error("expected native wallet"); - this.keyring.add(wallet, deviceId); - this.keyring.decorateEvents(deviceId, wallet.events); - } - - if (wallet && native.isNative(wallet)) { - const id = await wallet.getDeviceID(); - this.keyring.emit([wallet.getVendor(), id, core.Events.CONNECT], id); - - return wallet; - } - - return null; - } -} diff --git a/packages/hdwallet-native/src/arkeo.test.ts b/packages/hdwallet-native/src/arkeo.test.ts deleted file mode 100644 index ed523dcd..00000000 --- a/packages/hdwallet-native/src/arkeo.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeArkeoWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - expect(await untouchable.call(info, "arkeoSupportsNetwork")).toBe(true); - expect(await untouchable.call(info, "arkeoSupportsSecureTransfer")).toBe(false); - expect(untouchable.call(info, "arkeoSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.arkeoGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "arkeoNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeArkeoWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - }); - - it("should generate a correct arkeo address", async () => { - expect(await wallet.arkeoGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0") })).toBe( - "arkeo1knuunh0lmwyrkjmrj7sky49uxk3peyzhpse9av" - ); - }); - - it("should generate another correct arkeo address", async () => { - expect(await wallet.arkeoGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/118'/1337'/123/4") })).toBe( - "arkeo14k4dnrrmxdch6nkvvuugsywrgmvlwrqspjur0w" - ); - }); - - it("should sign a transaction correctly", async () => { - const signed = await wallet.arkeoSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0"), - tx: { - msg: [ - { - type: "arkeo/BondProvider", - value: { - creator: "arkeo15cenya0tr7nm3tz2wn3h3zwkht2rxrq7r7z5sh", - provider: "arkeo15cenya0tr7nm3tz2wn3h3zwkht2rxrq7r7z5sh", - service: "test-service-string", - bond: "10000", - }, - }, - ], - fee: { - amount: [ - { - amount: "2291", - denom: "uarkeo", - }, - ], - gas: "91633", - }, - signatures: [], - memo: "foobar", - }, - chain_id: "arkeo-mainnet-1", - account_number: "97721", - sequence: "90", - }); - await expect(signed?.signatures?.length).toBe(1); - await expect(signed?.signatures?.[0]).toMatchInlineSnapshot( - `"nkq6+HHu7R2op3goq/UoyE6Ci4QyNFB8OFmNJRn0SSAHYKsl7J4AeItbuzZ+WapPhVdCbaAKlZoieQuAzHwW9A=="` - ); - }); -}); diff --git a/packages/hdwallet-native/src/arkeo.ts b/packages/hdwallet-native/src/arkeo.ts deleted file mode 100644 index 69665dea..00000000 --- a/packages/hdwallet-native/src/arkeo.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { StdTx } from "@cosmjs/amino"; -import { SignerData } from "@cosmjs/stargate"; -import * as core from "@keepkey/hdwallet-core"; -import * as bech32 from "bech32"; -import CryptoJS from "crypto-js"; -import PLazy from "p-lazy"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import * as util from "./util"; - -const ARKEO_CHAIN = "arkeo-mainnet-1"; - -const protoTxBuilder = PLazy.from(() => import("@keepkey/proto-tx-builder")); - -export function MixinNativeArkeoWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeArkeoWalletInfo extends Base implements core.ArkeoWalletInfo { - readonly _supportsArkeoInfo = true; - async arkeoSupportsNetwork(): Promise { - return true; - } - - async arkeoSupportsSecureTransfer(): Promise { - return false; - } - - arkeoSupportsNativeShapeShift(): boolean { - return false; - } - - arkeoGetAccountPaths(msg: core.ArkeoGetAccountPaths): Array { - const slip44 = core.slip44ByCoin("Arkeo"); - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - arkeoNextAccountPath(msg: core.ArkeoAccountPath): core.ArkeoAccountPath | undefined { - // Only support one account for now. - return undefined; - } - }; -} - -export function MixinNativeArkeoWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeArkeoWallet extends Base { - readonly _supportsArkeo = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async arkeoInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - arkeoWipe(): void { - this.#masterKey = undefined; - } - - arkeoBech32ify(address: ArrayLike, prefix: string): string { - const words = bech32.toWords(address); - return bech32.encode(prefix, words); - } - - createArkeoAddress(publicKey: string) { - const message = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey)); - const hash = CryptoJS.RIPEMD160(message as any).toString(); - const address = Buffer.from(hash, `hex`); - return this.arkeoBech32ify(address, `arkeo`); - } - - async arkeoGetAddress(msg: core.ArkeoGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "arkeo"); - return this.createArkeoAddress(keyPair.publicKey.toString("hex")); - }); - } - - async arkeoSignTx(msg: core.ArkeoSignTx): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "arkeo"); - const adapter = await Isolation.Adapters.CosmosDirect.create(keyPair.node, "arkeo"); - - const signerData: SignerData = { - sequence: Number(msg.sequence), - accountNumber: Number(msg.account_number), - chainId: ARKEO_CHAIN, - }; - return (await protoTxBuilder).sign(adapter.address, msg.tx as StdTx, adapter, signerData, "arkeo"); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/bitcoin.test.ts b/packages/hdwallet-native/src/bitcoin.test.ts deleted file mode 100644 index a8d3f708..00000000 --- a/packages/hdwallet-native/src/bitcoin.test.ts +++ /dev/null @@ -1,481 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import cloneDeep from "lodash/cloneDeep"; - -import * as native from "./native"; -import * as Networks from "./networks"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -function benchmarkTx( - inPath: string, - inScriptType: string, - inTxId: string, - inVout: number, - inAmount: string, - inputExtra: object, - outAddr: string, - outAmount: string, - outExtra: object = {} -): core.BTCSignTx { - return { - coin: "Bitcoin", - inputs: [ - { - addressNList: core.bip32ToAddressNList(inPath), - scriptType: inScriptType as any, - amount: inAmount, - vout: inVout, - txid: inTxId, - ...inputExtra, - } as any, - ], - outputs: [ - { - address: outAddr, - addressType: core.BTCOutputAddressType.Spend, - amount: outAmount, - isChange: false, - }, - ], - ...outExtra, - }; -} - -// Funding Tx: https://api.blockcypher.com/v1/btc/main/txs/350eebc1012ce2339b71b5fca317a0d174abc3a633684bc65a71845deb596539?includeHex=true -// Spending Tx: https://api.blockcypher.com/v1/btc/main/txs/1869cdbb3a86ab8b71a3e4a0d11135926b18f62bc0ebeb8e8a56635135616f00?includeHex=true -const BIP44_BENCHMARK_TX_INPUT_TXID = "350eebc1012ce2339b71b5fca317a0d174abc3a633684bc65a71845deb596539"; -const BIP44_BENCHMARK_TX_INPUT_HEX = - "0100000001ac941afec3d31edd772cf45647c2c97b25b1dbfbc0045a83ca3658942a155619010000006a47304402206c8e9ce1116842cb0ea8d1e2a07d930b3692ea36964251fc453cb0b51d281b5002203b493db783d69eaad775f3b0ee2a6855dffab3977fb68a3a34a1c067716f1fb2012103fa9122a96ca4223ab9518db03fb600bbb59de61dbd4b8ae587cd3e7b9f968764ffffffff02a0860100000000001976a914bc4c06f0e7da28b37ee22fc9c93e2bb7bd8f305c88ac20dac100000000001976a9143435bb2ebfe441f268fd5a7933f43f28d2a3dfe288ac00000000"; -const BIP44_BENCHMARK_TX_OUTPUT_ADDR = "1MCgrVZjXRJJJhi2Z6SR11GpRjCyvNjscY"; -const BIP44_BENCHMARK_TX_OUTPUT = - "0100000001396559eb5d84715ac64b6833a6c3ab74d1a017a3fcb5719b33e22c01c1eb0e35000000006a47304402203b727eb80b3bac3b23bb88e8a22a77eb5232dd4bf079cb1520769a1eca88d96302201e36cf5919f17eb61ef87b8e5f1dc684df98a42f58e815f002b7dcc6c665ee0d012103c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38cffffffff01b8820100000000001976a914dd985beff82366763a5d86dd8c61b98d3f79590b88ac00000000"; -const BIP44_BENCHMARK_TX_OUTPUT_SIG = BIP44_BENCHMARK_TX_OUTPUT.slice(86, 86 + 140); -const BIP44_BENCHMARK_TX = benchmarkTx( - "m/44'/0'/0'/0/0", - "p2pkh", - BIP44_BENCHMARK_TX_INPUT_TXID, - 0, - "100000", - { hex: BIP44_BENCHMARK_TX_INPUT_HEX }, - BIP44_BENCHMARK_TX_OUTPUT_ADDR, - "99000" -); - -// Funding Tx: https://api.blockcypher.com/v1/btc/main/txs/918f59f7144fa389f66b6776e3417e1ec356214e18684050237acc056d5efbc1?includeHex=true -// Spending Tx: https://api.blockcypher.com/v1/btc/main/txs/6e6ad85c99bfb6ed7c0fa3ec99af02dfcdb805aeda36674bbeb3960bfc6418ba?includeHex=true -const BIP49_BENCHMARK_TX_INPUT_TXID = "918f59f7144fa389f66b6776e3417e1ec356214e18684050237acc056d5efbc1"; -// (We're not using it but this is real on-chain data we don't want to lose track of) -// eslint-disable-next-line @typescript-eslint/no-unused-vars -const BIP49_BENCHMARK_TX_INPUT_HEX = - "01000000015c4813fb3e0203e3bfa21420d62f88d2f89d39a63fde0f6ef2b08c406bda5f7f000000006a47304402205c9c26e213470dcb1c6b9399cb6cfda2c2dfece806ef10d6e5a889e39bc2e201022027d07373261478c4c43fa7044d6128f48a496cb8c97b93e4460887c664e0ef960121022a6e02f34ea72544c24f96cde286916d162de1f448396c62943b72ea16e6fb47ffffffff028f8011f8000000001976a914d32f4064914d28c30f5b309a73435588e0161f7b88ac2a5d00000000000017a914c9e193b1af9e4349d2ee53b4190e2bd36e59719e8700000000"; -const BIP49_BENCHMARK_TX_OUTPUT_ADDR = "1EC9SktW9Y4kS4iW48idshNg9eNeBdY5Xi"; -const BIP49_BENCHMARK_TX_OUTPUT = - "01000000000101c1fb5e6d05cc7a23504068184e2156c31e7e41e376676bf689a34f14f7598f910100000017160014ef01be1e6c7709df95c0ed763aa3b845286bbe80ffffffff01a25c0000000000001976a91490b54270b8fb85ade07261e9edc99f96fd197de588ac02483045022100ee6c831ceb78d97d1e0c24d0de62a4e87494a436157a7f2291065523f3f673f9022055b24caa363a8c51a7ed9dce546e25aefbcf9af7a08f2ed63a3bf37c9978c167012102f770feae292b5b3f41d8c81220c2568cb73eb8042def35e648dfe048e4b41b1100000000"; -const BIP49_BENCHMARK_TX_OUTPUT_SIG = BIP49_BENCHMARK_TX_OUTPUT.slice(216, 216 + 144); -const BIP49_BENCHMARK_TX = benchmarkTx( - "m/49'/0'/0'/0/0", - "p2sh-p2wpkh", - BIP49_BENCHMARK_TX_INPUT_TXID, - 1, - "23850", - { - // Using tx.vout instead of hex tests another code path - /*hex: BIP49_BENCHMARK_TX_INPUT_HEX,*/ - tx: { - vout: [undefined, { scriptPubKey: { hex: "a914c9e193b1af9e4349d2ee53b4190e2bd36e59719e87" } }], - }, - }, - BIP49_BENCHMARK_TX_OUTPUT_ADDR, - "23714" -); - -// Funding Tx: https://api.blockcypher.com/v1/btc/main/txs/fa80a9949f1094119195064462f54d0e0eabd3139becd4514ae635b8c7fe3a46?includeHex=true -// Spending Tx: https://api.blockcypher.com/v1/btc/main/txs/7e58757f43015242c0efa29447bea4583336f2358fdff587b52bbe040ad8982a?includeHex=true -const BIP84_BENCHMARK_TX_INPUT_TXID = "fa80a9949f1094119195064462f54d0e0eabd3139becd4514ae635b8c7fe3a46"; -const BIP84_BENCHMARK_TX_INPUT_HEX = - "01000000000101360d7a720e95a6068678eb08e91b3a8a4774222c9f34becf57d0dc4329e0a686000000001716001495f41f5c0e0ec2c7fe27f0ac4bd59a5632a40b5fffffffff02d224000000000000160014ece6935b2a5a5b5ff997c87370b16fa10f16441088ba04000000000017a914dfe58cc93d35fb99e15436f47d3bbfce820328068702483045022100f312e8246e6a00d21fd762f12231c5fb7a20094a32940b9a84e28d712a5ced9b02203b9124d7a94aa7eb1e090ceda32e884511d7068b8d47593aa46537900e3e37d40121037e8bf05c6c7223cfba3ea484ecd61ee910ae38609ea89b4a4839beed2186b3fb00000000"; -const BIP84_BENCHMARK_TX_OUTPUT_ADDR = "36JkLACrdxARqXXffZk91V9W6SJvghKaVK"; -const BIP84_BENCHMARK_TX_OUTPUT = - "01000000000101463afec7b835e64a51d4ec9b13d3ab0e0e4df562440695911194109f94a980fa0000000000ffffffff01611900000000000017a91432a276261d6f084fa46917300b6be8848853211187024730440220200b1192c3d49338678bdb30678fa270720e7ff1de4f45d5340a0cb7fbf8f2de02202457250ae49f088fc9d9663db8c92db4606dc25b098874ed7bb548d3002c346f01210396070f2813933502e907c011ae7ba928683a9c2f0e888dae7ebd2c41120ee6b500000000"; -const BIP84_BENCHMARK_TX_OUTPUT_SIG = BIP84_BENCHMARK_TX_OUTPUT.slice(166, 166 + 142); -const BIP84_BENCHMARK_TX = benchmarkTx( - "m/84'/0'/0'/0/0", - "p2wpkh", - BIP84_BENCHMARK_TX_INPUT_TXID, - 0, - "9426", - { hex: BIP84_BENCHMARK_TX_INPUT_HEX }, - BIP84_BENCHMARK_TX_OUTPUT_ADDR, - "6497" -); - -// Funding Tx: https://api.blockcypher.com/v1/btc/main/txs/799a8923515e0303b15dda074b8341b2cf5efab946fce0d68a6614f32a8fc935?includeHex=true -// Spending Tx: https://api.blockcypher.com/v1/btc/main/txs/8841a6007c2a01376260c3dfa1469d5f215de310aaed72e0a300c88ecc9d11b9?includeHex=true -const OP_RETURN_BENCHMARK_TX_INPUT_TXID = "799a8923515e0303b15dda074b8341b2cf5efab946fce0d68a6614f32a8fc935"; -const OP_RETURN_BENCHMARK_TX_INPUT_HEX = - "01000000000102303a686b8bca00ebb484919f11addd3b2787cc26e1b2d3cd0f12af83623a3c210100000017160014838e24a1d99c435bde880e4dbc283c7ae1f7859cffffffff30b2fba7ee86f9de44bda798b70e7118e671e5ab8dc499da23b62156d46362510000000017160014e4540cd724d36d6dc3fa913f9fc4b476ff6aad13ffffffff023075000000000000160014ece6935b2a5a5b5ff997c87370b16fa10f1644104e0f00000000000017a9146d24979924837c0699c8abc91fe02907f2b992a48702483045022100ab0d3ad7fee9a20dac59fa70a4f6156ef9f725c841406ee722724e4d1084048302206a091bc9758b9205fc3c53f355e81c20d0d52cbaa17445865e56bd576c107eac012102cf98f208e8d659bd49127013a80d8ffb43931b8ebfad65fe0292ca48593ed31c02473044022070c0adba6d23521d8583d59769f7ec448c2188cc2bff6d16ab47ad02c10dc37e02204527a6c46f52782fe79e2a5964bafdd4ecd56c3d59e2bd42aaf907dcdef34a76012103c5412363b7a052398d213c79895f0d00f3237b86a354267697b75530664c0fce00000000"; -const OP_RETURN_BENCHMARK_TX_OUTPUT_ADDR = "38hU3uzGmB5ST37DW8SwvdhiWE7zvZPsyf"; -const OP_RETURN_BENCHMARK_TX_OUTPUT = - "0100000000010135c98f2af314668ad6e0fc46b9fa5ecfb241834b07da5db103035e5123899a790000000000ffffffff02a86100000000000017a9144cdeb0b5d429c2589fef2d6d088fce317f8dac44870000000000000000086a06666f6f62617202483045022100eb59a33fd25396ba5494aefb2a37be5c1956718815bd9404800ac274c2c937da02202a3b5e9796a1c8fc03be3a01bc0cdfb56b1002658b45abd7ca4a7d18bad3b9c101210396070f2813933502e907c011ae7ba928683a9c2f0e888dae7ebd2c41120ee6b500000000"; -const OP_RETURN_BENCHMARK_TX_OUTPUT_SIG = OP_RETURN_BENCHMARK_TX_OUTPUT.slice(200, 200 + 144); -const OP_RETURN_BENCHMARK_TX = benchmarkTx( - "m/84'/0'/0'/0/0", - "p2wpkh", - OP_RETURN_BENCHMARK_TX_INPUT_TXID, - 0, - "30000", - { hex: OP_RETURN_BENCHMARK_TX_INPUT_HEX }, - OP_RETURN_BENCHMARK_TX_OUTPUT_ADDR, - "25000", - { opReturnData: "foobar" } -); - -describe("NativeBTCWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - expect((info as any)["btcSupportsNetwork"]).not.toBeDefined(); - expect(await untouchable.call(info, "btcSupportsSecureTransfer")).toBe(false); - expect(untouchable.call(info, "btcSupportsNativeShapeShift")).toBe(false); - }); - - it("should return some dynamic metadata", async () => { - expect(await info.btcSupportsCoin("bitcoin")).toBe(true); - expect(await info.btcSupportsCoin("bitcoincash")).toBe(true); - expect(await info.btcSupportsScriptType("bitcoin", "p2pkh" as any)).toBe(true); - expect(await info.btcSupportsScriptType("bitcoin", "p2sh" as any)).toBe(true); - expect(await info.btcSupportsScriptType("bitcoin", "p2wpkh" as any)).toBe(true); - expect(await info.btcSupportsScriptType("bitcoin", "p2sh-p2wpkh" as any)).toBe(true); - expect(await info.btcSupportsScriptType("bitcoin", "bech32" as any)).toBe(true); - expect(await info.btcSupportsScriptType("bitcoin", "cashaddr" as any)).toBe(false); - expect(await info.btcSupportsScriptType("bitcoincash", "cashaddr" as any)).toBe(false); - expect(await info.btcSupportsScriptType("bitcoin", "foobar" as any)).toBe(false); - expect(await info.btcSupportsScriptType("foobar", "p2pkh" as any)).toBe(false); - }); - - it("should not do anything when btcIsSameAccount is called", async () => { - expect(untouchable.call(info, "btcIsSameAccount", [])).toBe(false); - }); - - it.each([ - [ - "an undefined scriptType", - "Bitcoin", - undefined, - 0, - [ - { - coin: "Bitcoin", - scriptType: "p2pkh", - addressNList: core.bip32ToAddressNList("m/44'/0'/0'"), - }, - { - coin: "Bitcoin", - scriptType: "p2sh-p2wpkh", - addressNList: core.bip32ToAddressNList("m/49'/0'/0'"), - }, - { - coin: "Bitcoin", - scriptType: "p2wpkh", - addressNList: core.bip32ToAddressNList("m/84'/0'/0'"), - }, - ], - ], - [ - "BIP44", - "Bitcoin", - "p2pkh", - 1337, - [ - { - coin: "Bitcoin", - scriptType: "p2pkh", - addressNList: core.bip32ToAddressNList("m/44'/0'/1337'"), - }, - ], - ], - [ - "BIP49", - "Bitcoin", - "p2sh-p2wpkh", - 1337, - [ - { - coin: "Bitcoin", - scriptType: "p2sh-p2wpkh", - addressNList: core.bip32ToAddressNList("m/49'/0'/1337'"), - }, - ], - ], - [ - "BIP84", - "Bitcoin", - "p2wpkh", - 1337, - [ - { - coin: "Bitcoin", - scriptType: "p2wpkh", - addressNList: core.bip32ToAddressNList("m/84'/0'/1337'"), - }, - ], - ], - ])("should return the correct account paths for %s", (_, coin, scriptType: any, accountIdx, out) => { - expect(info.btcGetAccountPaths({ coin, scriptType, accountIdx })).toMatchObject(out); - }); - - it("should not return any account paths for a bad coin type", () => { - expect( - info.btcGetAccountPaths({ - coin: "foobar", - accountIdx: 0, - }) - ).toMatchObject([]); - }); - - describe("btcNextAccountPath", () => { - it.each([ - ["BIP44", "Bitcoin", "p2pkh", "m/44'/0'/0'", "m/44'/0'/1'"], - ["BIP44", "Bitcoin", "p2pkh", "m/44'/0'/1337'", "m/44'/0'/1338'"], - ["BIP49", "Bitcoin", "p2sh-p2wpkh", "m/49'/0'/0'", "m/49'/0'/1'"], - ["BIP84", "Bitcoin", "p2wpkh", "m/84'/0'/0'", "m/84'/0'/1'"], - ["Bitcoin Cash", "BitcoinCash", "p2pkh", "m/44'/145'/1337'", "m/44'/145'/1338'"], - ])("should work for %s", (_, coin, scriptType: any, inPath, outPath) => { - expect( - info.btcNextAccountPath({ - coin, - scriptType, - addressNList: core.bip32ToAddressNList(inPath), - }) - ).toMatchObject({ - coin, - scriptType, - addressNList: core.bip32ToAddressNList(outPath), - }); - }); - - it.each([ - ["BIP44 with p2sh-p2wpkh scripts", "Bitcoin", "p2sh-p2wpkh", "m/44'/0'/0'"], - ["BIP44 with p2wpkh scripts", "Bitcoin", "p2wpkh", "m/44'/0'/0'"], - ["BIP49 with p2pkh scripts", "Bitcoin", "p2pkh", "m/49'/0'/0'"], - ["BIP49 with p2wpkh scripts", "Bitcoin", "p2wpkh", "m/49'/0'/0'"], - ["BIP84 with p2pkh scripts", "Bitcoin", "p2pkh", "m/84'/0'/0'"], - ["BIP84 with p2sh-p2wpkh scripts", "Bitcoin", "p2sh-p2wpkh", "m/84'/0'/0'"], - ["an unrecognized path", "Bitcoin", "p2pkh", "m/1337'/0'/0'"], - ["a lowercase coin name", "bitcoin", "p2pkh", "m/44'/0'/0'"], - ["a bad coin name", "foobar", "p2pkh", "m/44'/0'/0'"], - ["a bad script type name", "Bitcoin", "foobar", "m/44'/0'/0'"], - ])("should not work for %s", (_, coin, scriptType: any, path) => { - expect( - info.btcNextAccountPath({ - coin, - scriptType, - addressNList: core.bip32ToAddressNList(path), - }) - ).toBeUndefined(); - }); - }); -}); - -describe("NativeBTCWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - }); - - it.each([ - [ - "BIP44", - "Bitcoin", - "p2pkh", - [ - ["m/44'/0'/0'/0/0", "1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL"], - ["m/44'/0'/1337'/123/4", "12EgVaC3wL5rVczoMfTwJWpZ2v783cptjs"], - ], - ], - [ - "BIP49", - "Bitcoin", - "p2sh-p2wpkh", - [ - ["m/49'/0'/0'/0/0", "3L6TyTisPBmrDAj6RoKmDzNnj4eQi54gD2"], - ["m/49'/0'/1337'/123/4", "3CXezZxPpvNMriYWXUHYuxAByUXpANWMzb"], - ], - ], - [ - "BIP84", - "Bitcoin", - "p2wpkh", - [ - ["m/84'/0'/0'/0/0", "bc1qannfxke2tfd4l7vhepehpvt05y83v3qsf6nfkk"], - ["m/84'/0'/1337'/123/4", "bc1q9sjm947kn2hz84syykmem7dshvevm8xm5dkrpg"], - ], - ], - [ - "Bitcoin Cash", - "BitcoinCash", - // maybe "cashaddr" should work here, but it doesn't. - "p2pkh", - [ - ["m/44'/145'/0'/0/0", "bitcoincash:qr08q88p9etk89wgv05nwlrkm4l0urz4cyl36hh9sv"], - ["m/44'/145'/1337'/123/4", "bitcoincash:qzrgv3veuqtu9g345w3hz8kwx796ty6vuu7hqstryu"], - ], - ], - ])("should generate correct %s addresses", async (_, coin, scriptType: any, addrSpec) => { - for (const [path, addr] of addrSpec) { - expect(await wallet.btcGetAddress({ coin, scriptType, addressNList: core.bip32ToAddressNList(path) })).toBe(addr); - } - }); - - it("does not support p2sh addresses", async () => { - await expect( - wallet.btcGetAddress({ - coin: "Bitcoin", - scriptType: "p2sh" as any, - addressNList: core.bip32ToAddressNList("m/44'/0'/0'/0/0"), - }) - ).rejects.toThrowErrorMatchingInlineSnapshot(`"Not enough data"`); - }); - - it("should not generate addresses for bad script types", async () => { - const mock = jest.spyOn(Networks, "getNetwork").mockReturnValue(Networks.getNetwork("bitcoin", "p2pkh" as any)); - await expect( - wallet.btcGetAddress({ - coin: "Bitcoin", - scriptType: "foobar" as any, - addressNList: core.bip32ToAddressNList("m/44'/0'/0'/0/0"), - }) - ).rejects.toThrowError("no implementation for script type"); - mock.mockRestore(); - }); - - it("should sign a BIP44 transaction correctly", async () => { - const input = BIP44_BENCHMARK_TX; - const out = await wallet.btcSignTx(input); - expect(out?.signatures).toMatchObject([BIP44_BENCHMARK_TX_OUTPUT_SIG]); - expect(out?.serializedTx).toBe(BIP44_BENCHMARK_TX_OUTPUT); - }); - - it("should sign a BIP49 transaction correctly", async () => { - const input = BIP49_BENCHMARK_TX; - const out = await wallet.btcSignTx(input); - expect(out?.signatures).toMatchObject([BIP49_BENCHMARK_TX_OUTPUT_SIG]); - expect(out?.serializedTx).toBe(BIP49_BENCHMARK_TX_OUTPUT); - }); - - it("should sign a BIP84 transaction correctly", async () => { - const input = BIP84_BENCHMARK_TX; - const out = await wallet.btcSignTx(input); - - expect(out?.signatures).toMatchObject([BIP84_BENCHMARK_TX_OUTPUT_SIG]); - expect(out?.serializedTx).toBe(BIP84_BENCHMARK_TX_OUTPUT); - }); - - it("should sign a BIP84 transaction with an OP_RETURN message correctly", async () => { - const input = OP_RETURN_BENCHMARK_TX; - const out = await wallet.btcSignTx(input); - - expect(out?.signatures).toMatchObject([OP_RETURN_BENCHMARK_TX_OUTPUT_SIG]); - expect(out?.serializedTx).toBe(OP_RETURN_BENCHMARK_TX_OUTPUT); - }); - - it("should not sign a transaction without having the raw input transaction", async () => { - const input = cloneDeep(BIP44_BENCHMARK_TX); - delete (input.inputs[0] as any).hex; - await expect(wallet.btcSignTx(input)).rejects.toThrowError("must provide prev rawTx"); - }); - - it("should sign a transaction with a locktime correctly", async () => { - const input = { - locktime: 338841, - ...BIP44_BENCHMARK_TX, - }; - - const locktimeBuf = Buffer.alloc(4); - locktimeBuf.writeUInt32LE(input["locktime"]); - const locktimeHex = locktimeBuf.toString("hex"); - - const out = await wallet.btcSignTx(input); - const sigHex = - "3044022006e609c8a9bedb7088d46140ab5f54a1a2023bc49b44cdf8fa147a181974b39702203e159bd869d8ccc85468856d9165cfc5df1885a8d8f1ebeaaaa5b8211f6317af"; - expect(out?.signatures).toMatchObject([sigHex]); - expect(out?.serializedTx).toBe( - `${BIP44_BENCHMARK_TX_OUTPUT.slice(0, 86)}${sigHex}${BIP44_BENCHMARK_TX_OUTPUT.slice(-156, -8)}${locktimeHex}` - ); - }); - - it("should automatically set the output address for a transaction", async () => { - const input = { - ...BIP44_BENCHMARK_TX, - outputs: [ - { - addressNList: core.bip32ToAddressNList("m/44'/0'/0'/0/1"), - scriptType: core.BTCOutputScriptType.PayToAddress, - amount: "99000", - isChange: false, - }, - ], - }; - - const out = await wallet.btcSignTx(input as any); - - expect(out?.signatures[0]).toMatchInlineSnapshot( - `"3045022100b5971b81e1da04beec2ebe58b909953119b57490581de23e55721832b70c361a022038478c5a5036026fab419ccdae380143b6f14c379186dafa2a7e04735808aa1f"` - ); - expect(out?.serializedTx).toMatchInlineSnapshot( - `"0100000001396559eb5d84715ac64b6833a6c3ab74d1a017a3fcb5719b33e22c01c1eb0e35000000006b483045022100b5971b81e1da04beec2ebe58b909953119b57490581de23e55721832b70c361a022038478c5a5036026fab419ccdae380143b6f14c379186dafa2a7e04735808aa1f012103c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38cffffffff01b8820100000000001976a91402eea9ab5f88d829c501760bec348a5baa55cf3888ac00000000"` - ); - }); - - it("should not automatically set the output address for a transaction requesting an invalid scriptType", async () => { - const input = { - ...BIP44_BENCHMARK_TX, - outputs: [ - { - addressNList: core.bip32ToAddressNList("m/44'/0'/0'/0/1"), - scriptType: "foobar" as any, - amount: "99000", - isChange: false, - }, - ], - }; - - await expect(wallet.btcSignTx(input as any)).rejects.toThrowError("failed to add output"); - }); - - it("should not sign a transaction with the wrong key", async () => { - const input = cloneDeep(BIP44_BENCHMARK_TX); - input.inputs[0].addressNList = core.bip32ToAddressNList("m/44'/0'/1337'/123/4"); - - await expect(wallet.btcSignTx(input as any)).rejects.toThrowError("Can not sign for this input"); - }); - - it("doesn't support signing messages", async () => { - await expect( - wallet.btcSignMessage({ - coin: "Bitcoin", - addressNList: core.bip32ToAddressNList("m/44'/0'/0'/0/0"), - message: "foobar", - }) - ).rejects.toThrowError("not implemented"); - }); - - it("doesn't support verifying messages", async () => { - await expect( - wallet.btcVerifyMessage({ - coin: "Bitcoin", - address: "1JAd7XCBzGudGpJQSDSfpmJhiygtLQWaGL", - message: "foo", - signature: "bar", - }) - ).rejects.toThrowError("not implemented"); - }); -}); diff --git a/packages/hdwallet-native/src/bitcoin.ts b/packages/hdwallet-native/src/bitcoin.ts deleted file mode 100644 index 8cca927f..00000000 --- a/packages/hdwallet-native/src/bitcoin.ts +++ /dev/null @@ -1,388 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as bitcoin from "@shapeshiftoss/bitcoinjs-lib"; -import * as bchAddr from "bchaddrjs"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import { getNetwork } from "./networks"; -import * as util from "./util"; - -const supportedCoins = ["bitcoin", "dash", "digibyte", "dogecoin", "litecoin", "bitcoincash", "testnet"]; - -const segwit = ["p2wpkh", "p2sh-p2wpkh", "bech32"]; - -export type BTCScriptType = core.BTCInputScriptType | core.BTCOutputScriptType; - -type NonWitnessUtxo = Buffer; - -type WitnessUtxo = { - script: Buffer; - amount: number; -}; - -type UtxoData = NonWitnessUtxo | WitnessUtxo; - -type ScriptData = { - redeemScript?: Buffer; - witnessScript?: Buffer; -}; - -type BchInputData = { - sighashType?: number; -}; - -type InputData = UtxoData | ScriptData | BchInputData; - -export function MixinNativeBTCWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeBTCWalletInfo extends Base implements core.BTCWalletInfo { - readonly _supportsBTCInfo = true; - - btcSupportsCoinSync(coin: core.Coin): boolean { - return supportedCoins.includes(String(coin).toLowerCase()); - } - - async btcSupportsCoin(coin: core.Coin): Promise { - return this.btcSupportsCoinSync(coin); - } - - btcSupportsScriptTypeSync(coin: core.Coin, scriptType?: core.BTCInputScriptType): boolean { - if (!this.btcSupportsCoinSync(coin)) return false; - - switch (scriptType) { - case core.BTCInputScriptType.SpendMultisig: - case core.BTCInputScriptType.SpendAddress: - case core.BTCInputScriptType.SpendWitness: - case core.BTCInputScriptType.Bech32: - case core.BTCInputScriptType.SpendP2SHWitness: - return true; - default: - return false; - } - } - - async btcSupportsScriptType(coin: core.Coin, scriptType: core.BTCInputScriptType): Promise { - return this.btcSupportsScriptTypeSync(coin, scriptType); - } - - async btcSupportsSecureTransfer(): Promise { - return false; - } - - btcSupportsNativeShapeShift(): boolean { - return false; - } - - btcGetAccountPaths(msg: core.BTCGetAccountPaths): Array { - const slip44 = core.slip44ByCoin(msg.coin); - if (slip44 === undefined) return []; - const bip44 = core.legacyAccount(msg.coin, slip44, msg.accountIdx); - const bip49 = core.segwitAccount(msg.coin, slip44, msg.accountIdx); - const bip84 = core.segwitNativeAccount(msg.coin, slip44, msg.accountIdx); - - const coinPaths = { - bitcoin: [bip44, bip49, bip84], - bitcoincash: [bip44, bip49, bip84], - dash: [bip44], - digibyte: [bip44, bip49, bip84], - dogecoin: [bip44], - litecoin: [bip44, bip49, bip84], - testnet: [bip44, bip49, bip84], - } as Partial>>; - - let paths: Array = coinPaths[msg.coin.toLowerCase()] || []; - - if (msg.scriptType !== undefined) { - paths = paths.filter((path) => { - return path.scriptType === msg.scriptType; - }); - } - - return paths; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - btcIsSameAccount(msg: Array): boolean { - // TODO: support at some point - return false; - } - - btcNextAccountPath(msg: core.BTCAccountPath): core.BTCAccountPath | undefined { - const description = core.describeUTXOPath(msg.addressNList, msg.coin, msg.scriptType); - - if (!description.isKnown) { - return undefined; - } - - const addressNList = msg.addressNList; - - if ( - (addressNList[0] === 0x80000000 + 44 && msg.scriptType == core.BTCInputScriptType.SpendAddress) || - (addressNList[0] === 0x80000000 + 49 && msg.scriptType == core.BTCInputScriptType.SpendP2SHWitness) || - (addressNList[0] === 0x80000000 + 84 && msg.scriptType == core.BTCInputScriptType.SpendWitness) - ) { - addressNList[2] += 1; - return { - ...msg, - addressNList, - }; - } - - return undefined; - } - }; -} - -export function MixinNativeBTCWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeBTCWallet extends Base { - readonly _supportsBTC = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async btcInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - btcWipe(): void { - this.#masterKey = undefined; - } - - createPayment(pubkey: Buffer, scriptType?: BTCScriptType, network?: bitcoin.Network): bitcoin.Payment { - switch (scriptType) { - case "p2sh": - return bitcoin.payments.p2sh({ pubkey, network }); - case "p2pkh": - return bitcoin.payments.p2pkh({ pubkey, network }); - case "p2wpkh": - return bitcoin.payments.p2wpkh({ pubkey, network }); - case "p2sh-p2wpkh": - return bitcoin.payments.p2sh({ - redeem: bitcoin.payments.p2wpkh({ pubkey, network }), - network, - }); - case "bech32": - return bitcoin.payments.p2wsh({ - redeem: bitcoin.payments.p2wsh({ pubkey, network }), - network, - }); - default: - throw new Error(`no implementation for script type: ${scriptType}`); - } - } - - validateVoutOrdering(msg: core.BTCSignTxNative, tx: bitcoin.Transaction): boolean { - // From THORChain specification: - /* ignoreTx checks if we can already ignore a tx according to preset rules - - we expect array of "vout" for a BTC to have this format - OP_RETURN is mandatory only on inbound tx - vout:0 is our vault - vout:1 is any any change back to themselves - vout:2 is OP_RETURN (first 80 bytes) - vout:3 is OP_RETURN (next 80 bytes) - - Rules to ignore a tx are: - - vout:0 doesn't have coins (value) - - vout:0 doesn't have address - - count vouts > 4 - - count vouts with coins (value) > 2 - */ - - // Check that vout:0 contains the vault address - if (bitcoin.address.fromOutputScript(tx.outs[0].script) != msg.vaultAddress) { - console.error("Vout:0 does not contain vault address."); - return false; - } - - // TODO: Can we check and make sure vout:1 is our address? - - // Check and make sure vout:2 exists - if (tx.outs.length < 3) { - console.error("Not enough outputs found in transaction.", msg); - return false; - } - // Check and make sure vout:2 has OP_RETURN data - const opcode = bitcoin.script.decompile(tx.outs[2].script)?.[0]; - if (Object.keys(bitcoin.script.OPS).find((k) => bitcoin.script.OPS[k] === opcode) != "OP_RETURN") { - console.error("OP_RETURN output not found for transaction."); - return false; - } - - // Make sure vout:3 does not exist - if (tx.outs[3]) { - console.error("Illegal second op_return output found."); - return false; - } - - return true; - } - - async buildInput(coin: core.Coin, input: core.BTCSignTxInputNative): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - const { addressNList, amount, hex, scriptType } = input; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, addressNList, coin, scriptType); - - const isSegwit = !!scriptType && segwit.includes(scriptType); - const nonWitnessUtxo = hex && Buffer.from(hex, "hex"); - const witnessUtxo = input.tx && { - script: Buffer.from(input.tx.vout[input.vout].scriptPubKey.hex, "hex"), - value: Number(amount), - }; - const utxoData = isSegwit && witnessUtxo ? { witnessUtxo } : { nonWitnessUtxo }; - - if (!(utxoData.witnessUtxo || utxoData.nonWitnessUtxo)) { - throw new Error( - "failed to build input - must provide prev rawTx (segwit input can provide scriptPubKey hex and value instead)" - ); - } - - const { publicKey, network } = keyPair; - const payment = this.createPayment(publicKey, scriptType, network); - - const scriptData: ScriptData = {}; - switch (scriptType) { - case "p2sh-p2wpkh": - case "p2sh": - case "bech32": - scriptData.redeemScript = payment.redeem?.output; - break; - } - - const bchData: BchInputData = {}; - if (coin.toLowerCase() === "bitcoincash") { - bchData.sighashType = bitcoin.Transaction.SIGHASH_ALL | bitcoin.Transaction.SIGHASH_BITCOINCASHBIP143; - } - - return { - ...utxoData, - ...bchData, - ...scriptData, - }; - }); - } - - async btcGetAddress(msg: core.BTCGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - const { addressNList, coin, scriptType } = msg; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, addressNList, coin, scriptType); - const { address } = this.createPayment(keyPair.publicKey, scriptType, keyPair.network); - if (!address) return null; - return coin.toLowerCase() === "bitcoincash" ? bchAddr.toCashAddress(address) : address; - }); - } - - async btcSignTx(msg: core.BTCSignTxNative): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - const { coin, inputs, outputs, version, locktime } = msg; - - const psbt = new bitcoin.Psbt({ network: getNetwork(coin) }); - - psbt.setVersion(version ?? 1); - locktime && psbt.setLocktime(locktime); - - await Promise.all( - inputs.map(async (input) => { - try { - const inputData = await this.buildInput(coin, input); - - psbt.addInput({ - hash: input.txid, - index: input.vout, - ...inputData, - }); - } catch (e) { - throw new Error(`failed to add input: ${e}`); - } - }) - ); - - await Promise.all( - outputs.map(async (output) => { - try { - const { amount } = output; - - let address: string; - if (output.address !== undefined) { - address = output.address; - } else if (output.addressNList !== undefined) { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, output.addressNList, coin, output.scriptType); - const { publicKey, network } = keyPair; - const payment = this.createPayment(publicKey, output.scriptType, network); - if (!payment.address) throw new Error("could not get payment address"); - address = payment.address; - } else { - throw new Error("unsupported output type"); - } - - if (coin.toLowerCase() === "bitcoincash") { - address = bchAddr.toLegacyAddress(address); - } - - psbt.addOutput({ address, value: Number(amount) }); - } catch (e) { - throw new Error(`failed to add output: ${e}`); - } - }) - ); - - if (msg.opReturnData) { - const data = Buffer.from(msg.opReturnData, "utf-8"); - const embed = bitcoin.payments.embed({ data: [data] }); - const script = embed.output; - if (!script) throw new Error("unable to build OP_RETURN script"); - psbt.addOutput({ script, value: 0 }); - } - - await Promise.all( - inputs.map(async (input, idx) => { - try { - const { addressNList, scriptType } = input; - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, addressNList, coin, scriptType); - await psbt.signInputAsync(idx, keyPair); - } catch (e) { - throw new Error(`failed to sign input: ${e}`); - } - }) - ); - - psbt.finalizeAllInputs(); - - const tx = psbt.extractTransaction(true); - - // If this is a THORChain transaction, validate the vout ordering - if (msg.vaultAddress && !this.validateVoutOrdering(msg, tx)) { - throw new Error("Improper vout ordering for BTC Thorchain transaction"); - } - - const signatures = tx.ins.map((input) => { - if (input.witness.length > 0) { - return input.witness[0].toString("hex"); - } else { - const sigLen = input.script[0]; - return input.script.slice(1, sigLen).toString("hex"); - } - }); - - return { - signatures, - serializedTx: tx.toHex(), - }; - }); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - async btcSignMessage(msg: core.BTCSignMessage): Promise { - throw new Error("function not implemented"); - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - async btcVerifyMessage(msg: core.BTCVerifyMessage): Promise { - throw new Error("function not implemented"); - } - }; -} diff --git a/packages/hdwallet-native/src/cosmos.test.ts b/packages/hdwallet-native/src/cosmos.test.ts deleted file mode 100644 index 59baec61..00000000 --- a/packages/hdwallet-native/src/cosmos.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeCosmosWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - expect(await untouchable.call(info, "cosmosSupportsNetwork")).toBe(true); - expect(await untouchable.call(info, "cosmosSupportsSecureTransfer")).toBe(false); - expect(untouchable.call(info, "cosmosSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.cosmosGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "cosmosNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeCosmosWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - }); - - it("should generate a correct cosmos address", async () => { - expect(await wallet.cosmosGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0") })).toBe( - "cosmos1knuunh0lmwyrkjmrj7sky49uxk3peyzhzsvqqf" - ); - }); - - it("should generate another correct cosmos address", async () => { - expect(await wallet.cosmosGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/118'/1337'/123/4") })).toBe( - "cosmos14k4dnrrmxdch6nkvvuugsywrgmvlwrqszjfxjt" - ); - }); - - it("should sign a transaction correctly", async () => { - const signed = await wallet.cosmosSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0"), - tx: { - msg: [ - { - type: "cosmos-sdk/MsgSend", - value: { - from_address: "cosmos1knuunh0lmwyrkjmrj7sky49uxk3peyzhzsvqqf", - to_address: "cosmos1knuunh0lmwyrkjmrj7sky49uxk3peyzhzsvqqf", - amount: [ - { - denom: "uatom", - amount: "1000", - }, - ], - }, - }, - ], - fee: { - amount: [ - { - amount: "100", - denom: "uatom", - }, - ], - gas: "100000", - }, - signatures: [], - memo: "foobar", - }, - chain_id: "cosmoshub-4", - account_number: "16359", - sequence: "17", - }); - await expect(signed?.signatures?.length).toBe(1); - await expect(signed?.signatures?.[0]).toMatchInlineSnapshot( - `"B3KXc4pbANu4orFqVB9sWHXSqKXfU3oaH4rN7P3By9tmNEIw7+i8IBXMqaT1VDReehtK+krK02tDRhpFZIW7Iw=="` - ); - }); -}); diff --git a/packages/hdwallet-native/src/cosmos.ts b/packages/hdwallet-native/src/cosmos.ts deleted file mode 100644 index 3e62decc..00000000 --- a/packages/hdwallet-native/src/cosmos.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { StdTx } from "@cosmjs/amino"; -import type { SignerData } from "@cosmjs/stargate"; -import * as core from "@keepkey/hdwallet-core"; -import * as bech32 from "bech32"; -import CryptoJS from "crypto-js"; -import PLazy from "p-lazy"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import * as util from "./util"; - -const ATOM_CHAIN = "cosmoshub-4"; - -const protoTxBuilder = PLazy.from(() => import("@keepkey/proto-tx-builder")); - -export function MixinNativeCosmosWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeCosmosWalletInfo extends Base implements core.CosmosWalletInfo { - readonly _supportsCosmosInfo = true; - async cosmosSupportsNetwork(): Promise { - return true; - } - - async cosmosSupportsSecureTransfer(): Promise { - return false; - } - - cosmosSupportsNativeShapeShift(): boolean { - return false; - } - - cosmosGetAccountPaths(msg: core.CosmosGetAccountPaths): Array { - const slip44 = core.slip44ByCoin("Atom"); - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - cosmosNextAccountPath(msg: core.CosmosAccountPath): core.CosmosAccountPath | undefined { - // Only support one account for now. - return undefined; - } - }; -} - -export function MixinNativeCosmosWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeCosmosWallet extends Base { - readonly _supportsCosmos = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async cosmosInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - cosmosWipe(): void { - this.#masterKey = undefined; - } - - cosmosBech32ify(address: ArrayLike, prefix: string): string { - const words = bech32.toWords(address); - return bech32.encode(prefix, words); - } - - createCosmosAddress(publicKey: string) { - const message = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey)); - const hash = CryptoJS.RIPEMD160(message as any).toString(); - const address = Buffer.from(hash, `hex`); - return this.cosmosBech32ify(address, `cosmos`); - } - - async cosmosGetAddress(msg: core.CosmosGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "cosmos"); - return this.createCosmosAddress(keyPair.publicKey.toString("hex")); - }); - } - - async cosmosSignTx(msg: core.CosmosSignTx): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "cosmos"); - const adapter = await Isolation.Adapters.CosmosDirect.create(keyPair.node, "cosmos"); - - const signerData: SignerData = { - sequence: Number(msg.sequence), - accountNumber: Number(msg.account_number), - chainId: ATOM_CHAIN, - }; - - return (await protoTxBuilder).sign(adapter.address, msg.tx as StdTx, adapter, signerData); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/crypto/CryptoHelper.test.ts b/packages/hdwallet-native/src/crypto/CryptoHelper.test.ts deleted file mode 100644 index ec9600ec..00000000 --- a/packages/hdwallet-native/src/crypto/CryptoHelper.test.ts +++ /dev/null @@ -1,212 +0,0 @@ -/** - * @jest-environment jsdom - */ -import * as core from "@keepkey/hdwallet-core"; -import * as webcrypto from "@peculiar/webcrypto"; - -import { CipherString } from "./classes"; -import CryptoHelper from "./CryptoHelper"; -import { WebCryptoEngine } from "./engines"; -import * as utils from "./utils"; - -const PLAINTEXT_STRING = "totally random secret data"; -const ENCRYPTED_STRING = - "2.A/tC/OC0U/KN3XuAuz2L36lydOyr5x367tPSGSrPkvQ=|AAAAAAAAAAAAAAAAAAAAAA==|ZqR8HTeOg4+8mzcty10jVFZ5MqFFbn5bwEaqlL0c/Mg="; -const ENCRYPTED_EMPTY_STRING = - "2.7wpUO5ISHHdT1voBnjzyXQ==|AAAAAAAAAAAAAAAAAAAAAA==|02KQ8aQWWXUX7foOmf4T2W0XCFAk4OTKFQO+hRhlRcY="; - -const BAD_ARGS = [undefined, null, "encrypteddatastring", [1, 2, 3, 4, 5, 6], {}]; - -describe("CryptoHelpers", () => { - // Load shim to support running tests in node - globalThis.crypto = new webcrypto.Crypto(); - const engine = new WebCryptoEngine(); - const helper = new CryptoHelper(engine); - - describe("constructor", () => { - it("should require a CryptoEngine instances", () => { - expect(() => new CryptoHelper(undefined as any)).toThrow("Missing cryptography engine"); - }); - - it("should return a new instance", () => { - expect(new CryptoHelper(engine)).toBeInstanceOf(CryptoHelper); - }); - }); - - describe("aesEncrypt", () => { - it("should encrypt data with an hmac signature", async () => { - const randomMock = jest - .spyOn(global.crypto, "getRandomValues") - .mockImplementation((array) => array && new Uint8Array(array.byteLength).fill(0)); - const key = await helper.makeKey("password", "email"); - const encrypted = await helper.aesEncrypt(utils.fromUtf8ToArray(PLAINTEXT_STRING), key); - randomMock.mockRestore(); - - expect(encrypted.key).toEqual(key); - expect(encrypted.iv.byteLength).toBe(16); - expect(encrypted.mac.byteLength).toBe(32); - expect(encrypted.data.byteLength).toBe(32); - expect(encrypted.toString()).toEqual(ENCRYPTED_STRING); - }); - - it("should encrypt the empty string", async () => { - const randomMock = jest - .spyOn(global.crypto, "getRandomValues") - .mockImplementation((array) => array && new Uint8Array(array.byteLength).fill(0)); - const key = await helper.makeKey("password", "email"); - const encrypted = await helper.aesEncrypt(utils.fromUtf8ToArray(""), key); - randomMock.mockRestore(); - - expect(encrypted.key).toEqual(key); - expect(encrypted.iv.byteLength).toBe(16); - expect(encrypted.mac.byteLength).toBe(32); - expect(encrypted.data.byteLength).toBe(16); - expect(encrypted.toString()).toEqual(ENCRYPTED_EMPTY_STRING); - }); - - it.each([ - ["data", 0], - ["key", 1], - ])("should throw an error if %s is not the correct type", async (name, position) => { - const dummyArg = new Uint8Array(32).fill(0); - for (const arg of BAD_ARGS) { - const args = new Array(position).fill(dummyArg); - args.push(arg); - await expect((helper.aesEncrypt as any)(...(args as any))).rejects.toThrowError(`[${name}] is not of type`); - } - }); - - it("should work with ArrayBuffers", async () => { - const key = await helper.makeKey("password", "email"); - const encrypted = await helper.aesEncrypt(core.toArrayBuffer(utils.fromUtf8ToArray(PLAINTEXT_STRING)), key); - const decrypted = await helper.aesDecrypt(encrypted.data, encrypted.iv, encrypted.mac, key); - expect(utils.fromBufferToUtf8(decrypted)).toEqual(PLAINTEXT_STRING); - }); - - it("should work with Uint8Arrays", async () => { - const key = await helper.makeKey("password", "email"); - const encrypted = await helper.aesEncrypt(utils.fromUtf8ToArray(PLAINTEXT_STRING), key); - const decrypted = await helper.aesDecrypt( - new Uint8Array(encrypted.data), - new Uint8Array(encrypted.iv), - new Uint8Array(encrypted.mac), - key - ); - expect(utils.fromBufferToUtf8(decrypted)).toEqual(PLAINTEXT_STRING); - }); - }); - - describe("aesDecrypt", () => { - it("should decrypt data with an hmac signature", async () => { - const key = await helper.makeKey("password", "email"); - const encrypted = new CipherString(ENCRYPTED_STRING).toEncryptedObject(key); - const decrypted = await helper.aesDecrypt(encrypted.data, encrypted.iv, encrypted.mac, encrypted.key); - expect(utils.fromBufferToUtf8(decrypted)).toEqual(PLAINTEXT_STRING); - }); - - it("should fail if the data is incorrect", async () => { - const key = await helper.makeKey("password", "email"); - const encrypted = new CipherString(ENCRYPTED_STRING).toEncryptedObject(key); - const data = new Uint8Array(encrypted.data.byteLength).fill(0x80); - await expect(helper.aesDecrypt(data, encrypted.iv, encrypted.mac, encrypted.key)).rejects.toThrow( - "HMAC signature is not valid" - ); - }); - - it("should fail if the iv is incorrect", async () => { - const key = await helper.makeKey("password", "email"); - const encrypted = new CipherString(ENCRYPTED_STRING).toEncryptedObject(key); - const iv = new Uint8Array(encrypted.iv.byteLength).fill(0x80); - await expect(helper.aesDecrypt(encrypted.data, iv, encrypted.mac, encrypted.key)).rejects.toThrow( - "HMAC signature is not valid" - ); - }); - - it("should fail if the mac is incorrect", async () => { - const key = await helper.makeKey("password", "email"); - const encrypted = new CipherString(ENCRYPTED_STRING).toEncryptedObject(key); - const mac = new Uint8Array(encrypted.mac.byteLength).fill(0x80); - await expect(helper.aesDecrypt(encrypted.data, encrypted.iv, mac, encrypted.key)).rejects.toThrow( - "HMAC signature is not valid" - ); - }); - - it("should fail if the key is incorrect", async () => { - const key = await helper.makeKey("password2", "email"); - const encrypted = new CipherString(ENCRYPTED_STRING).toEncryptedObject(key); - await expect(helper.aesDecrypt(encrypted.data, encrypted.iv, encrypted.mac, encrypted.key)).rejects.toThrow( - "HMAC signature is not valid" - ); - }); - - it.each([ - ["data", 0], - ["iv", 1], - ["mac", 2], - ["key", 3], - ])("should throw an error if %s is not the correct type", async (name, position) => { - const dummyArg = new Uint8Array(32).fill(0); - for (const value of BAD_ARGS) { - const args = new Array(position).fill(dummyArg); - args.push(value); - await expect((helper.aesDecrypt as any)(...(args as any))).rejects.toThrowError(`[${name}] is not of type`); - } - }); - }); - - describe("compare", () => { - it("should return false if arrays are different sizes", async () => { - expect(await helper.compare(new Uint8Array(32), new Uint8Array(16))).toBe(false); - }); - - it("should return false if the hmac results are different sizes", async () => { - let i = 0; - const mock = jest.spyOn(engine, "hmac").mockImplementation(async () => { - return core.toArrayBuffer(new Uint8Array(++i * 16)); - }); - const result = await helper.compare(new Uint8Array(32), new Uint8Array(32)); - mock.mockRestore(); - await expect(result).toBe(false); - }); - - it("should return false if arrays are different", async () => { - const mac1 = new Uint8Array(16).fill(0); - const mac2 = new Uint8Array(16).fill(0); - mac2.set([1], 15); - expect(await helper.compare(mac1, mac2)).toBe(false); - }); - }); - - describe("makeKey", () => { - it.each([[undefined], [null], [""], [[1, 2, 3, 4, 5, 6]], [{}]])( - "should require a password (%o)", - async (param: any) => { - await expect(helper.makeKey(param, undefined as any)).rejects.toThrow("password"); - } - ); - - it.each([[undefined], [null], [""], [[1, 2, 3, 4, 5, 6]], [{}]])( - "should require an email (%o)", - async (param: any) => { - await expect(helper.makeKey("mypassword", param)).rejects.toThrow("email"); - } - ); - }); - - describe("deviceId", () => { - it("should return undefined if the wallet has not been initialized", async () => { - expect( - await helper.getDeviceId( - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about" - ) - ).toBe("40bdrat83JXH1jC8EnGPujqEtorp/J/ToNeAOoyMLPs="); - }); - - it.each([[undefined], [null], [""], [[1, 2, 3, 4, 5, 6]], [{}]])( - "should throw an error if invalid data is provided (%o)", - async (data: any) => { - await expect(helper.getDeviceId(data)).rejects.toThrow("Invalid data"); - } - ); - }); -}); diff --git a/packages/hdwallet-native/src/crypto/CryptoHelper.ts b/packages/hdwallet-native/src/crypto/CryptoHelper.ts deleted file mode 100644 index 10d50572..00000000 --- a/packages/hdwallet-native/src/crypto/CryptoHelper.ts +++ /dev/null @@ -1,174 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as bip39 from "bip39"; - -import { CipherString, EncryptedObject, SymmetricCryptoKey } from "./classes"; -import { CryptoEngine, DigestAlgorithm } from "./engines"; -import * as utils from "./utils"; - -/** - * This class is only intended to be used by the EncryptedWallet class - */ -export default class CryptoHelper { - readonly #engine: CryptoEngine; - - constructor(engine: CryptoEngine) { - if (!engine) { - throw new Error("Missing cryptography engine"); - } - this.#engine = engine; - } - - // Safely compare two values in a way that protects against timing attacks (Double HMAC Verification). - // ref: https://www.nccgroup.trust/us/about-us/newsroom-and-events/blog/2011/february/double-hmac-verification/ - // ref: https://paragonie.com/blog/2015/11/preventing-timing-attacks-on-string-comparison-with-double-hmac-strategy - async compare(a: ArrayBuffer, b: ArrayBuffer): Promise { - const macKey = await this.#engine.randomBytes(32); - - const mac1 = await this.#engine.hmac(a, macKey); - const mac2 = await this.#engine.hmac(b, macKey); - - if (mac1.byteLength !== mac2.byteLength) { - return false; - } - - const arr1 = new Uint8Array(mac1); - const arr2 = new Uint8Array(mac2); - for (let i = 0; i < arr2.length; i++) { - if (arr1[i] !== arr2[i]) { - return false; - } - } - - return true; - } - - async aesEncrypt(data: ArrayBuffer | Uint8Array, key: SymmetricCryptoKey): Promise { - if (data == null || !(data instanceof ArrayBuffer || data instanceof Uint8Array)) - throw new Error("Required parameter [data] is not of type ArrayBuffer or Uint8Array"); - if (data instanceof Uint8Array) data = core.toArrayBuffer(data); - if (key == null || key.encKey == null || key.macKey == null) - throw new Error("Required parameter [key] is not of type SymmetricCryptoKey"); - const iv = await this.#engine.randomBytes(16); - - const encData = await this.#engine.encrypt(data, key.encKey, iv); - - const macData = new Uint8Array(iv.byteLength + encData.byteLength); - macData.set(new Uint8Array(iv), 0); - macData.set(new Uint8Array(encData), iv.byteLength); - const mac = await this.#engine.hmac( - macData.buffer.slice(macData.byteOffset, macData.byteOffset + macData.byteLength), - key.macKey - ); - - return new EncryptedObject({ key, iv, data: encData, mac }); - } - - async aesDecrypt( - data: ArrayBuffer | Uint8Array, - iv: ArrayBuffer | Uint8Array, - mac: ArrayBuffer | Uint8Array, - key: SymmetricCryptoKey - ): Promise { - if (data == null || !(data instanceof ArrayBuffer || data instanceof Uint8Array)) - throw new Error("Required parameter [data] is not of type ArrayBuffer or Uint8Array"); - if (data instanceof Uint8Array) data = core.toArrayBuffer(data); - if (iv == null || !(iv instanceof ArrayBuffer || iv instanceof Uint8Array)) - throw new Error("Required parameter [iv] is not of type ArrayBuffer or Uint8Array"); - if (iv instanceof Uint8Array) iv = core.toArrayBuffer(iv); - if (mac == null || !(mac instanceof ArrayBuffer || mac instanceof Uint8Array)) - throw new Error("Required parameter [mac] is not of type ArrayBuffer or Uint8Array"); - if (mac instanceof Uint8Array) mac = core.toArrayBuffer(mac); - if (key == null || key.encKey == null || key.macKey == null) - throw new Error("Required parameter [key] is not of type SymmetricCryptoKey"); - - const macData = new Uint8Array(iv.byteLength + data.byteLength); - macData.set(new Uint8Array(iv), 0); - macData.set(new Uint8Array(data), iv.byteLength); - const computedMac = await this.#engine.hmac(core.toArrayBuffer(macData), key.macKey); - const macsMatch = await this.compare(mac, computedMac); - - if (!macsMatch) throw new Error("HMAC signature is not valid or data has been tampered with"); - - return this.#engine.decrypt(data, key.encKey, iv); - } - - // @see: https://tools.ietf.org/html/rfc5869 - async hkdfExpand(prk: ArrayBuffer, info: Uint8Array, size: number): Promise { - const hashLen = 32; // sha256 - const okm = new Uint8Array(size); - - let previousT = new Uint8Array(0); - - const n = Math.ceil(size / hashLen); - for (let i = 0; i < n; i++) { - const t = new Uint8Array(previousT.length + info.length + 1); - - t.set(previousT); - t.set(info, previousT.length); - t.set([i + 1], t.length - 1); - - previousT = new Uint8Array(await this.#engine.hmac(core.toArrayBuffer(t), prk)); - - okm.set(previousT, i * hashLen); - } - - return okm; - } - - async pbkdf2(password: string | ArrayBuffer, salt: string | ArrayBuffer, iterations: number): Promise { - password = typeof password !== "string" ? password : core.toArrayBuffer(utils.fromUtf8ToArray(password)); - salt = typeof salt !== "string" ? salt : core.toArrayBuffer(utils.fromUtf8ToArray(salt)); - - return this.#engine.pbkdf2(password, salt, { iterations, keyLen: 32 }); - } - - async makeKey(password: string, email: string): Promise { - if (!(password && email && typeof password === "string" && typeof email === "string")) { - throw new Error("A password and email are required to make a symmetric crypto key."); - } - - const salt = core.toArrayBuffer(utils.fromUtf8ToArray(email)); - // The same email/password MUST always generate the same encryption key, so - // scrypt parameters are hard-coded to ensure compatibility across implementations - const key = await this.#engine.scrypt(core.toArrayBuffer(utils.fromUtf8ToArray(password)), salt, { - iterations: 16384, - blockSize: 8, - parallelism: 1, - keyLength: 32, - }); - const hashKey = await this.pbkdf2(key, password, 1); - const stretchedKey = await this.hkdfExpand(key, utils.fromUtf8ToArray("enc"), 32); - const macKey = await this.hkdfExpand(key, utils.fromUtf8ToArray("mac"), 32); - - return new SymmetricCryptoKey(hashKey, stretchedKey, macKey); - } - - async decrypt(cipherString: CipherString, key: SymmetricCryptoKey): Promise { - const data = utils.fromB64ToArray(cipherString.data); - const iv = utils.fromB64ToArray(cipherString.iv); - const mac = utils.fromB64ToArray(cipherString.mac); - const decipher = await this.aesDecrypt(data, iv, mac, key); - - return utils.fromBufferToUtf8(decipher); - } - - // use entropyToMnemonic to generate mnemonic so we can utilize provided randomBytes function - async generateMnemonic(strength = 128): Promise { - const entropy = await this.#engine.randomBytes(strength / 8); - return bip39.entropyToMnemonic(Buffer.from(entropy)); - } - - /** - * Generates a base64 hash based on the provided data - * Should be used to calculate a device ID for the wallet based on the mnemonic - */ - async getDeviceId(data: string): Promise { - if (!(typeof data === "string" && data.length > 0)) throw new Error("Invalid data to hash"); - const digest = await this.#engine.digest( - DigestAlgorithm.SHA256, - await this.#engine.digest(DigestAlgorithm.SHA512, Buffer.from(data)) - ); - - return utils.fromBufferToB64(digest); - } -} diff --git a/packages/hdwallet-native/src/crypto/EncryptedWallet.test.ts b/packages/hdwallet-native/src/crypto/EncryptedWallet.test.ts deleted file mode 100644 index 8457ce7c..00000000 --- a/packages/hdwallet-native/src/crypto/EncryptedWallet.test.ts +++ /dev/null @@ -1,180 +0,0 @@ -/** - * @jest-environment jsdom - */ -import * as webcrypto from "@peculiar/webcrypto"; - -import { EncryptedWallet } from "./EncryptedWallet"; -import { WebCryptoEngine } from "./engines"; - -const PLAINTEXT_MNEMONIC = "boat garment fog other pony middle bronze ready grain betray load frame"; -const ENCRYPTED_MNEMONIC = - "2.Q1/C6FLg1MufcTAmEXEmQbuyPdjuXEGw3AP17sWhJ3Ws8Fcsl03XUDlC3zULVHY4+IU4lMtyjfnRNKlCF4Sy9OeUvS//i7JUCS6ieLAn5U8=|AAAAAAAAAAAAAAAAAAAAAA==|nuOb9GoiRhAkWRLLRqqDna05Jp03Botr3JF8A34SS3U="; - -const PLAINTEXT_MNEMONIC2 = - "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"; -const ENCRYPTED_MNEMONIC2 = - "2.1gm0swmYoZCc/T/U1aSGTsp0NgSQFtNT/N8U4nAgTWeJ28xpjlrGAjZwezW4vrwR8+TprSfaNCsh9lv1Nr19+/R3Ya2kj9obHhZZz1FL6qVY1dOdqfoaEWiqui54zlCb|AAAAAAAAAAAAAAAAAAAAAA==|R5969JYt8Y5CH55TFsafDVl8CXx8tv2ii2wjOMurdf4="; - -const ENCRYPTED_EMPTY_STRING = - "2.7wpUO5ISHHdT1voBnjzyXQ==|AAAAAAAAAAAAAAAAAAAAAA==|02KQ8aQWWXUX7foOmf4T2W0XCFAk4OTKFQO+hRhlRcY="; - -describe("EncryptedWallet", () => { - // Load shim to support running tests in node - globalThis.crypto = new webcrypto.Crypto(); - const engine = new WebCryptoEngine(); - - describe("constructor", () => { - it("should be instantiated", () => { - expect(new EncryptedWallet(engine)).toBeInstanceOf(EncryptedWallet); - }); - - it("should require a crypto engine", () => { - expect( - () => new EncryptedWallet(undefined as unknown as ConstructorParameters[0]) - ).toThrow("Missing"); - }); - }); - - describe("init", () => { - it("should generate a password hash and encrypted mnemonic from a given email and password", async () => { - const wallet = new EncryptedWallet(engine); - const result = await wallet.init("email", "password"); - - expect(result.email).toEqual("email"); - expect(result.passwordHash).toEqual("W/7DR3sIqcb8lnLXD/ToTS+imBVMTyPR7JMend9hxrM="); - expect(result.encryptedWallet).toBeUndefined(); - }); - - it.each([[], [null], [[1, 2, 3]], ""])( - "should not generate a password hash and encrypted mnemonic if no password is provided (%p)", - async (pw) => { - const wallet = new EncryptedWallet(engine); - await expect(wallet.init("email", pw as string)).rejects.toThrow("Invalid password"); - } - ); - - it.each([[], [null], [[1, 2, 3]], ""])( - "should not generate a password hash and encrypted mnemonic if no email is provided (%p)", - async (email) => { - const wallet = new EncryptedWallet(engine); - await expect(wallet.init(email as string, "password")).rejects.toThrow("Invalid email"); - } - ); - }); - - describe("encryptedWallet", () => { - it("should allow settings the encrypted wallet string", async () => { - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password"); - wallet.encryptedWallet = ENCRYPTED_MNEMONIC; - expect(wallet.encryptedWallet).toEqual(ENCRYPTED_MNEMONIC); - }); - - it("should throw an error", async () => { - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password"); - expect(() => (wallet.encryptedWallet = "")).toThrow("Invalid"); - }); - }); - - describe("createWallet", () => { - it("should hash password on construction", async () => { - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password"); - - expect(wallet.email).toEqual("email"); - expect(wallet.passwordHash).toEqual("W/7DR3sIqcb8lnLXD/ToTS+imBVMTyPR7JMend9hxrM="); - }); - - it("should create a new encrypted wallet", async () => { - const randomMock = jest - .spyOn(global.crypto, "getRandomValues") - .mockImplementation((array) => array && new Uint8Array(array.byteLength).fill(0)); - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password"); - await wallet.createWallet(PLAINTEXT_MNEMONIC2); - randomMock.mockRestore(); - - expect(wallet.encryptedWallet).toEqual(ENCRYPTED_MNEMONIC2); - }); - - it("should throw an error if the mnemonic is invalid", async () => { - const randomMock = jest.spyOn(require("bip39"), "validateMnemonic").mockReturnValue(false); - const wallet = new EncryptedWallet(engine); - const result = await wallet.init("email", "password"); - await expect(result.createWallet()).rejects.toThrow("Invalid mnemonic"); - randomMock.mockRestore(); - }); - - it("should require the wallet to be initialized", async () => { - const wallet = new EncryptedWallet(engine); - await expect(wallet.createWallet()).rejects.toThrow("not initialized"); - }); - }); - - describe("decrypt", () => { - it.each([ - [PLAINTEXT_MNEMONIC, ENCRYPTED_MNEMONIC], - [PLAINTEXT_MNEMONIC2, ENCRYPTED_MNEMONIC2], - ])("should decrypt a wallet with seed (%s)", async (PLAIN, ENCRYPTED) => { - const wallet = new EncryptedWallet(engine); - const result = await wallet.init("email", "password", ENCRYPTED); - - expect(await result.decrypt()).toEqual(PLAIN); - }); - - it("should require the wallet to be initialized", async () => { - const wallet = new EncryptedWallet(engine); - await expect(wallet.decrypt()).rejects.toThrow("not initialized"); - }); - - it("should require that the wallet has an encrypted wallet", async () => { - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password"); - await expect(wallet.decrypt()).rejects.toThrow("does not contain an encrypted wallet"); - }); - - it("should throw an error if the wallet cannot decrypt the wallet", async () => { - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password2", ENCRYPTED_MNEMONIC); - await expect(wallet.decrypt()).rejects.toThrow("signature is not valid"); - }); - - it("should throw an error if the decrypted mnemonic is the empty string", async () => { - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password", ENCRYPTED_EMPTY_STRING); - await expect(wallet.decrypt()).rejects.toThrow("Decryption failed"); - }); - }); - - describe("deviceId", () => { - it("should return undefined if the wallet has not been initialized", async () => { - const wallet = new EncryptedWallet(engine); - expect(wallet.deviceId).toBeUndefined(); - }); - - it("should return undefined if the wallet has not been decrypted", async () => { - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password", ENCRYPTED_MNEMONIC); - expect(wallet.deviceId).toBeUndefined(); - }); - - it("should return a base64 hash", async () => { - const wallet = new EncryptedWallet(engine); - await wallet.init("email", "password", ENCRYPTED_MNEMONIC); - await wallet.decrypt(); - expect(wallet.deviceId).toBe("0SUnRnGkhCt0T5qk5YmK10v5u+lgHiMMu1R76uD7kHE="); - }); - }); - - describe("reset", () => { - it("should remove all private data from the object", async () => { - const wallet = new EncryptedWallet(engine); - const result = await wallet.init("email", "password", ENCRYPTED_MNEMONIC); - result.reset(); - expect(result.encryptedWallet).toBeUndefined(); - expect(result.email).toBeUndefined(); - expect(result.passwordHash).toBeUndefined(); - }); - }); -}); diff --git a/packages/hdwallet-native/src/crypto/EncryptedWallet.ts b/packages/hdwallet-native/src/crypto/EncryptedWallet.ts deleted file mode 100644 index 0601b24a..00000000 --- a/packages/hdwallet-native/src/crypto/EncryptedWallet.ts +++ /dev/null @@ -1,141 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as bip39 from "bip39"; - -import { CipherString, SymmetricCryptoKey } from "./classes"; -import CryptoHelper from "./CryptoHelper"; -import { CryptoEngine } from "./engines"; -import * as utils from "./utils"; - -export class EncryptedWallet { - readonly #engine: CryptoEngine; - readonly #helper: CryptoHelper; - #deviceId: string | undefined; - #email: string | undefined; - #encryptedWallet: string | undefined; - #key: SymmetricCryptoKey | undefined; - #password: string | undefined; - - constructor(engine: CryptoEngine) { - if (!engine) { - throw new Error("Missing cryptography engine"); - } - this.#engine = engine; - this.#helper = new CryptoHelper(this.#engine); - } - - /** - * Whether or not the wallet has been initialized with an email and password - */ - get isInitialized() { - return Boolean(this.#email && this.#password && this.#key); - } - - /** - * The email provided to the `init` function - */ - get email() { - return this.#email; - } - - /** - * A hash derived from the email and password to be used for authentication - */ - get passwordHash() { - return this.#key?.hashKeyB64; - } - - /** - * A string representation of the encrypted seed phrase - */ - get encryptedWallet() { - return this.#encryptedWallet; - } - - /** - * Set the encrypted wallet by providing a string representation - * @throws {Error} throws if `wallet` is not a valid encrypted wallet string - */ - set encryptedWallet(wallet: string | undefined) { - if (wallet === undefined) throw new Error("Invalid cipher string"); - this.#encryptedWallet = new CipherString(wallet).encryptedString; - } - - /** - * Get an ID based on the mnemonic - * Calling `decrypt` will set this value after decryption is successful - */ - get deviceId() { - return this.#deviceId; - } - - /** - * Initialize the wallet with and email and password - * - * This cannot be done in the constructor because it performs async operations - */ - async init(email: string, password: string, encryptedWallet?: string): Promise { - if (!(email && typeof email === "string" && email.length > 0)) { - throw new Error("Invalid email address"); - } - if (!(password && typeof password === "string" && password.length > 0)) { - throw new Error("Invalid password"); - } - - this.#email = email.normalize("NFKC").trim().toLowerCase(); - this.#password = password.normalize("NFKC"); - this.#key = await this.#helper.makeKey(this.#password, this.#email); - - if (encryptedWallet) { - this.encryptedWallet = encryptedWallet; - } - - return this; - } - - /** - * Generate a new mnemonic and encrypt it with the email and password - */ - async createWallet(mnemonic?: string) { - if (!this.isInitialized) throw new Error("Wallet is not initialized"); - mnemonic = mnemonic ?? (await this.#helper.generateMnemonic()); - - if (!bip39.validateMnemonic(mnemonic)) { - throw new Error("Invalid mnemonic"); - } - - if (!this.#key) throw new Error("Wallet does not contain a key"); - this.#encryptedWallet = ( - await this.#helper.aesEncrypt(core.toArrayBuffer(utils.fromUtf8ToArray(mnemonic)), this.#key) - ).toString(); - - return this; - } - - /** - * Decrypt the encrypted wallet - * @throws {Error} if the wallet hasn't been initialized or doesn't have an encryptedWallet - */ - async decrypt(encryptedWallet = this.#encryptedWallet): Promise { - if (!this.isInitialized) throw new Error("Wallet is not initialized"); - if (!encryptedWallet) throw new Error("Wallet does not contain an encrypted wallet"); - if (!this.#key) throw new Error("Wallet does not contain a key"); - const decrypted = await this.#helper.decrypt(new CipherString(encryptedWallet), this.#key); - - if (typeof decrypted === "string" && decrypted.length > 0) { - this.#deviceId = await this.#helper.getDeviceId(decrypted); - return decrypted; - } - throw new Error("Decryption failed"); - } - - /** - * Clear all private data to allow it to be garbage collected - */ - reset() { - this.#deviceId = undefined; - this.#email = undefined; - this.#encryptedWallet = undefined; - this.#key = undefined; - this.#password = undefined; - } -} diff --git a/packages/hdwallet-native/src/crypto/classes/cipherString.test.ts b/packages/hdwallet-native/src/crypto/classes/cipherString.test.ts deleted file mode 100644 index 32bc0610..00000000 --- a/packages/hdwallet-native/src/crypto/classes/cipherString.test.ts +++ /dev/null @@ -1,63 +0,0 @@ -import { CipherString, EncryptedObject, EncryptionType, SymmetricCryptoKey } from "."; - -describe("CipherString", () => { - it.each([undefined, null, 0, [1, 2, 3], { data: "", iv: "", key: "" }, "", "abc|abc|abc"])( - "should throw an error if an invalid cipher is provided (%s)", - (cipher: any) => { - expect(() => new CipherString(cipher)).toThrow("Invalid cipher"); - } - ); - - it("should throw an error if an invalid encryption type is specified", () => { - const string = - "999.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=|AAAAAAAAAAAAAAAAAAAAAA==|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; - expect(() => new CipherString(string)).toThrow("Unsupported encryption method"); - }); - - it("should accept a properly formatted cipher string", () => { - const string = new CipherString("2.AAAA|AAAA|AAAA"); - expect(string.encryptionType).toEqual(2); - expect(string.data).toEqual("AAAA"); - expect(string.iv).toEqual("AAAA"); - expect(string.mac).toEqual("AAAA"); - expect(string.encryptedString).toEqual("2.AAAA|AAAA|AAAA"); - }); - - it("should accept an EncryptedObject", () => { - const buffer32 = new Uint8Array(32).fill(0); - const buffer16 = new Uint8Array(16).fill(0); - const encrypted = new EncryptedObject({ - data: buffer32, - iv: buffer16, - mac: buffer32, - key: new SymmetricCryptoKey(buffer32, buffer32, buffer32), - }); - const string = new CipherString(encrypted); - - expect(string.encryptionType).toEqual(EncryptionType.AesCbc256_HmacSha256_B64); - expect(string.data).toEqual("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); - expect(string.iv).toEqual("AAAAAAAAAAAAAAAAAAAAAA=="); - expect(string.mac).toEqual("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="); - expect(string.encryptedString).toEqual( - "2.AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=|AAAAAAAAAAAAAAAAAAAAAA==|AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=" - ); - }); - - it.each([ - ["key", "Invalid encryption object"], - ["data", "Encrypted data is missing"], - ["iv", "IV is missing"], - ["mac", "HMAC signature is missing"], - ])("should throw an error if an EncryptedObject with a missing %s is provided", (key, error) => { - const buffer32 = new Uint8Array(32).fill(0); - const buffer16 = new Uint8Array(16).fill(0); - const encrypted = new EncryptedObject({ - data: buffer32, - iv: buffer16, - mac: buffer32, - key: new SymmetricCryptoKey(buffer32, buffer32, buffer32), - }); - delete (encrypted as any)[key]; - expect(() => new CipherString(encrypted)).toThrow(error); - }); -}); diff --git a/packages/hdwallet-native/src/crypto/classes/cipherString.ts b/packages/hdwallet-native/src/crypto/classes/cipherString.ts deleted file mode 100644 index c9c004bf..00000000 --- a/packages/hdwallet-native/src/crypto/classes/cipherString.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - Copied from portis: packages/portis-crypto/src/models/cipherString.ts - */ -import { fromB64ToArray, fromBufferToB64 } from "../utils"; -import { EncryptedObject } from "./encryptedObject"; -import { EncryptionType } from "./encryptionType"; -import { SymmetricCryptoKey } from "./symmetricCryptoKey"; - -export class CipherString { - readonly encryptionType: EncryptionType = EncryptionType.AesCbc256_HmacSha256_B64; - data: string; - iv: string; - mac: string; - - constructor(cipher: string | EncryptedObject) { - let data: string | undefined, iv: string | undefined, mac: string | undefined; - if (typeof cipher === "string") { - try { - const header = cipher.split("."); - this.encryptionType = Number(header[0]); - [data, iv, mac] = header[1].split("|"); - } catch (e) { - throw new Error("Invalid cipher string"); - } - } else if (cipher instanceof EncryptedObject) { - try { - this.encryptionType = cipher.key.encType; - if (cipher.iv) iv = fromBufferToB64(cipher.iv); - if (cipher.data) data = fromBufferToB64(cipher.data); - if (cipher.mac) mac = fromBufferToB64(cipher.mac); - } catch { - throw new Error("Invalid encryption object"); - } - } else { - throw new Error("Invalid cipher data. You must provide a string or Encrypted Object"); - } - - if (!EncryptionType[this.encryptionType]) { - throw new Error("Unsupported encryption method"); - } - if (!data) throw new Error("Encrypted data is missing"); - this.data = data; - if (!iv) throw new Error("IV is missing"); - this.iv = iv; - if (!mac) throw new Error("HMAC signature is missing"); - this.mac = mac; - } - - get encryptedString() { - return `${this.encryptionType}.${[this.data, this.iv, this.mac].join("|")}`; - } - - toEncryptedObject(key: SymmetricCryptoKey): EncryptedObject { - return new EncryptedObject({ - data: fromB64ToArray(this.data), - iv: fromB64ToArray(this.iv), - mac: fromB64ToArray(this.mac), - key, - }); - } -} diff --git a/packages/hdwallet-native/src/crypto/classes/encryptedObject.ts b/packages/hdwallet-native/src/crypto/classes/encryptedObject.ts deleted file mode 100644 index c70c2501..00000000 --- a/packages/hdwallet-native/src/crypto/classes/encryptedObject.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copied from portis: packages/portis-crypto/src/models/encryptedObject.ts - */ -import { CipherString } from "./cipherString"; -import { SymmetricCryptoKey } from "./symmetricCryptoKey"; - -export class EncryptedObject { - key: SymmetricCryptoKey; - iv: ArrayBuffer; - data: ArrayBuffer; - mac: ArrayBuffer; - - constructor({ - key, - iv, - data, - mac, - }: { - key: SymmetricCryptoKey; - iv: ArrayBuffer; - data: ArrayBuffer; - mac: ArrayBuffer; - }) { - this.key = key; - this.iv = iv; - this.data = data; - this.mac = mac; - } - - toString() { - return new CipherString(this).encryptedString; - } -} diff --git a/packages/hdwallet-native/src/crypto/classes/encryptionType.ts b/packages/hdwallet-native/src/crypto/classes/encryptionType.ts deleted file mode 100644 index 78949438..00000000 --- a/packages/hdwallet-native/src/crypto/classes/encryptionType.ts +++ /dev/null @@ -1,6 +0,0 @@ -/* - Copied from portis: packages/portis-crypto/src/enums/encryptionType.ts - */ -export enum EncryptionType { - AesCbc256_HmacSha256_B64 = 2, -} diff --git a/packages/hdwallet-native/src/crypto/classes/index.ts b/packages/hdwallet-native/src/crypto/classes/index.ts deleted file mode 100644 index 9392e3a4..00000000 --- a/packages/hdwallet-native/src/crypto/classes/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export { CipherString } from "./cipherString"; -export { EncryptedObject } from "./encryptedObject"; -export { EncryptionType } from "./encryptionType"; -export { SymmetricCryptoKey } from "./symmetricCryptoKey"; diff --git a/packages/hdwallet-native/src/crypto/classes/symmetricCryptoKey.test.ts b/packages/hdwallet-native/src/crypto/classes/symmetricCryptoKey.test.ts deleted file mode 100644 index ce04dc3d..00000000 --- a/packages/hdwallet-native/src/crypto/classes/symmetricCryptoKey.test.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { EncryptionType } from "./encryptionType"; -import { SymmetricCryptoKey } from "./symmetricCryptoKey"; - -describe("symmetricCryptoKey", () => { - const key = new Uint8Array(32).fill(64); - const encKey = new Uint8Array(32).fill(128); - const macKey = new Uint8Array(32).fill(255); - const key64 = new Uint8Array(64); - key64.set(encKey, 0); - key64.set(macKey, 32); - - it.each([ - ["key", []], - ["encKey", [encKey]], - ["macKey", [encKey, encKey]], - ])("should require a parameter %s", (name: string, params: ArrayBuffer[]) => { - expect(() => new (SymmetricCryptoKey as any)(...params)).toThrow("Required parameter"); - }); - - it.each([ - ["key", [key64, encKey, macKey]], - ["encKey", [key, key64, macKey]], - ["macKey", [key, encKey, key64]], - ])("should throw an error if %s is not 32 bytes", (name: string, params: ArrayBuffer[]) => { - expect(() => new (SymmetricCryptoKey as any)(...params)).toThrow("Keys must be 32 bytes"); - }); - - it("should return an instance", () => { - const instance = new SymmetricCryptoKey(key, encKey, macKey); - expect(instance.hashKey).toEqual(key); - expect(instance.encKey).toEqual(encKey); - expect(instance.macKey).toEqual(macKey); - expect(instance.encType).toBe(EncryptionType.AesCbc256_HmacSha256_B64); - }); - - it("should provide keys in base64 format", () => { - const instance = new SymmetricCryptoKey(key, encKey, macKey); - expect(instance.hashKeyB64).toEqual("QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEA="); - expect(instance.encKeyB64).toEqual("gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIA="); - expect(instance.macKeyB64).toEqual("//////////////////////////////////////////8="); - expect(instance.encType).toBe(EncryptionType.AesCbc256_HmacSha256_B64); - }); -}); diff --git a/packages/hdwallet-native/src/crypto/classes/symmetricCryptoKey.ts b/packages/hdwallet-native/src/crypto/classes/symmetricCryptoKey.ts deleted file mode 100644 index f67eb69d..00000000 --- a/packages/hdwallet-native/src/crypto/classes/symmetricCryptoKey.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copied from portis: packages/portis-crypto/src/models/symmetricCryptoKey.ts - */ -import { fromBufferToB64 } from "../utils"; -import { EncryptionType } from "./encryptionType"; - -export class SymmetricCryptoKey { - hashKey: ArrayBuffer; - encKey: ArrayBuffer; - macKey: ArrayBuffer | null; - encType: EncryptionType = EncryptionType.AesCbc256_HmacSha256_B64; - - hashKeyB64: string; - encKeyB64: string; - macKeyB64: string; - - constructor(hashKey: ArrayBuffer, encKey: ArrayBuffer, mac: ArrayBuffer) { - if (hashKey == null) throw new Error("Required parameter [hashKey] was not provided"); - if (encKey == null) throw new Error("Required parameter [encKey] was not provided"); - if (mac == null) throw new Error("Required parameter [mac] was not provided"); - - if (hashKey.byteLength !== 32 || encKey.byteLength !== 32 || mac.byteLength !== 32) - throw new Error("Keys must be 32 bytes"); - - this.hashKey = hashKey; - this.encKey = encKey; - this.macKey = mac; - - this.hashKeyB64 = fromBufferToB64(this.hashKey); - this.encKeyB64 = fromBufferToB64(this.encKey); - this.macKeyB64 = fromBufferToB64(this.macKey); - } -} diff --git a/packages/hdwallet-native/src/crypto/engines/index.ts b/packages/hdwallet-native/src/crypto/engines/index.ts deleted file mode 100644 index 4403a6c2..00000000 --- a/packages/hdwallet-native/src/crypto/engines/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./types"; -export * from "./web-crypto"; diff --git a/packages/hdwallet-native/src/crypto/engines/types.ts b/packages/hdwallet-native/src/crypto/engines/types.ts deleted file mode 100644 index 45f151eb..00000000 --- a/packages/hdwallet-native/src/crypto/engines/types.ts +++ /dev/null @@ -1,26 +0,0 @@ -export interface Pbkdf2Params { - iterations: number; - keyLen?: number; -} - -export interface ScryptParams { - iterations: number; - blockSize: number; - parallelism: number; - keyLength: number; -} - -export enum DigestAlgorithm { - SHA256, - SHA512, -} - -export interface CryptoEngine { - decrypt(data: ArrayBuffer, key: ArrayBuffer, iv: ArrayBuffer): Promise; - digest(algorithm: DigestAlgorithm, data: ArrayBuffer): Promise; - encrypt(data: ArrayBuffer, key: ArrayBuffer, iv: ArrayBuffer): Promise; - hmac(value: ArrayBuffer, key: ArrayBuffer): Promise; - pbkdf2(password: ArrayBuffer, salt: ArrayBuffer, options?: Pbkdf2Params): Promise; - randomBytes(size: number): Promise; - scrypt(password: ArrayBuffer, salt: ArrayBuffer, params: ScryptParams): Promise; -} diff --git a/packages/hdwallet-native/src/crypto/engines/web-crypto.test.ts b/packages/hdwallet-native/src/crypto/engines/web-crypto.test.ts deleted file mode 100644 index 28be03aa..00000000 --- a/packages/hdwallet-native/src/crypto/engines/web-crypto.test.ts +++ /dev/null @@ -1,157 +0,0 @@ -/** - * @jest-environment jsdom - */ -import * as core from "@keepkey/hdwallet-core"; -import * as webcrypto from "@peculiar/webcrypto"; - -import CryptoHelper from "../CryptoHelper"; -import * as utils from "../utils"; -import { DigestAlgorithm } from "./index"; -import { WebCryptoEngine } from "./web-crypto"; - -describe("WebCryptoEngine JavaScript", () => { - // Load shim to support running tests in node - globalThis.crypto = new webcrypto.Crypto(); - - const engine = new WebCryptoEngine(); - const helper = new CryptoHelper(engine); - - it("should decrypt what it encrypts", async () => { - const data = core.toArrayBuffer(utils.fromUtf8ToArray("test all seed phrase words for to see this to work maybe")); - const key = core.toArrayBuffer(utils.fromUtf8ToArray("12345678901234561234567890123456")); - const iv = core.toArrayBuffer(utils.fromUtf8ToArray("1234567890123456")); - - const encrypted = await engine.encrypt(data, key, iv); - - const decrypted = utils.fromBufferToUtf8(await engine.decrypt(encrypted, key, iv)); - expect(decrypted).toEqual("test all seed phrase words for to see this to work maybe"); - }); - - it("should decrypt what it encrypts with random key", async () => { - const data = core.toArrayBuffer(utils.fromUtf8ToArray("test encrypted data")); - const key = await engine.randomBytes(32); - const iv = await engine.randomBytes(16); - - const encrypted = await engine.encrypt(data, key, iv); - const decrypted = await engine.decrypt(encrypted, key, iv); - expect(utils.fromBufferToUtf8(decrypted)).toEqual("test encrypted data"); - }); - - it("should generate a key from a password and email", async () => { - const key = await helper.makeKey("password", "email"); - expect(key.encKeyB64).toEqual("Ohkd7bfLczTp+zRe74f0raBkF3deLRWS4MvnIsYG7xQ="); - }); - - it("should generate a different key from a different password", async () => { - const key = await helper.makeKey("password2", "email"); - expect(key.encKeyB64).not.toEqual("Ohkd7bfLczTp+zRe74f0raBkF3deLRWS4MvnIsYG7xQ="); - }); - - it("should generate a different key from a different email", async () => { - const key = await helper.makeKey("password", "email2"); - expect(key.encKeyB64).not.toEqual("Ohkd7bfLczTp+zRe74f0raBkF3deLRWS4MvnIsYG7xQ="); - }); - - it("should generate a password hash from an encryption key and password", async () => { - const key = await helper.makeKey("password", "email"); - expect(key.hashKeyB64).toEqual("W/7DR3sIqcb8lnLXD/ToTS+imBVMTyPR7JMend9hxrM="); - }); - - it("should generate a different password hash from an encryption key and password", async () => { - const key = await helper.makeKey("password2", "email"); - const hash = await helper.pbkdf2(key.hashKey, "password2", 1); - expect(utils.fromBufferToB64(hash)).not.toEqual("W/7DR3sIqcb8lnLXD/ToTS+imBVMTyPR7JMend9hxrM="); - }); - - it("should encrypt a wallet with a password and email", async () => { - const key = await helper.makeKey("password", "email"); - - const mnemonic = utils.fromUtf8ToArray("all all all all all all all all all all all all"); - const iv = utils.fromB64ToArray("rnvfQhmCO27xxEk33ayinw=="); - const encrypted = await engine.encrypt(mnemonic, key.encKey, iv); - - expect(utils.fromBufferToB64(encrypted)).toEqual( - "FC2M6J3aqlavEne0Sl72Xyh3XB2RzxmNpy/zKNqu1ys+3Xe7pxyRQd+GRsLcf/Rf" - ); - }); - - it("should decrypt a wallet with a password and email", async () => { - const key = await helper.makeKey("password", "email"); - const encryptedData = utils.fromB64ToArray("FC2M6J3aqlavEne0Sl72Xyh3XB2RzxmNpy/zKNqu1ys+3Xe7pxyRQd+GRsLcf/Rf"); - const iv = utils.fromB64ToArray("rnvfQhmCO27xxEk33ayinw=="); - const decrypted = await engine.decrypt(encryptedData, key.encKey, iv); - - expect(utils.fromBufferToUtf8(decrypted)).toEqual("all all all all all all all all all all all all"); - }); - - it("should generate random bytes", async () => { - const bytes = await engine.randomBytes(32); - expect(bytes.byteLength).toBe(32); - - // Make sure we're not just returning an empty array of 0s - // It's very unlikely that a random set of 32 bytes will result in all 0s - const typedArray = new Uint8Array(bytes); - const sum = typedArray.reduce((acc, value) => acc + value, 0); - expect(sum).toBeGreaterThan(0); - }); - - it.each([ - [DigestAlgorithm.SHA256, "abc", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"], - [ - DigestAlgorithm.SHA256, - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1", - ], - [ - DigestAlgorithm.SHA512, - "abc", - "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", - ], - [ - DigestAlgorithm.SHA512, - "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445", - ], - ])("should produce a valid SHA hash (alg %s) for %s", async (alg, data: string, hash: string) => { - const dataBuffer = utils.fromUtf8ToArray(data); - const expected = core.toArrayBuffer(Buffer.from(hash, "hex")); - const result = await engine.digest(alg, dataBuffer); - expect(result).toEqual(expected); - }); -}); - -/* -To verify the web-crypto code is compatible with the mobile app, -the encrypted data used for these tests were generated by the mobile app - -The following was added to `App/context/Wallet/index.tsx` in the `useEffect` hook -that initializes the wallet: - - // ============ REMOVE ================= - const key = await makeKey('password', 'email') - console.log('key', key) - const hash = await hashPassword('password', key) - console.log('passwordHash', hash) - const stretchedKey = await stretchKey(key) - console.log('stretchedKey', stretchedKey) - const encryptedWallet = await encrypt( - 'all all all all all all all all all all all all', - stretchedKey - ) - console.log('encryptedWallet', encryptedWallet) - // ============ REMOVE ================= - -The result of that code was: - -unstretched key - {"encKey": {"data": [Array], "type": "Buffer"}, "encKeyB64": "Dh3RT7Uq4C5YVpsXBjCFnQZRnYiYEydLQPBgBLJ5MS8=", "encType": 0, "key": {"data": [Array], "type": "Buffer"}, "keyB64": "Dh3RT7Uq4C5YVpsXBjCFnQZRnYiYEydLQPBgBLJ5MS8=", "macKey": null, "macKeyB64": null} - -passwordHash - W/7DR3sIqcb8lnLXD/ToTS+imBVMTyPR7JMend9hxrM= - -stretchedKey - {"encKey": [], "encKeyB64": "Ohkd7bfLczTp+zRe74f0raBkF3deLRWS4MvnIsYG7xQ=", "encType": 2, "key": [], "keyB64": "Ohkd7bfLczTp+zRe74f0raBkF3deLRWS4MvnIsYG7xSisttHbNlnITu7dsitOKWy1L6ROQfr2tYZURsNXJcPbw==", "macKey": [], "macKeyB64": "orLbR2zZZyE7u3bIrTilstS+kTkH69rWGVEbDVyXD28="} - -encryptedWallet - {"data": "FC2M6J3aqlavEne0Sl72Xyh3XB2RzxmNpy/zKNqu1ys+3Xe7pxyRQd+GRsLcf/Rf", "encryptedString": "2.FC2M6J3aqlavEne0Sl72Xyh3XB2RzxmNpy/zKNqu1ys+3Xe7pxyRQd+GRsLcf/Rf|rnvfQhmCO27xxEk33ayinw==|kvwPLZpJtrTuob3xNVxSiePJ+newC7keI1DPGyUls/Y=", "encryptionType": 2, "iv": "rnvfQhmCO27xxEk33ayinw==", "mac": "kvwPLZpJtrTuob3xNVxSiePJ+newC7keI1DPGyUls/Y="} - */ diff --git a/packages/hdwallet-native/src/crypto/engines/web-crypto.ts b/packages/hdwallet-native/src/crypto/engines/web-crypto.ts deleted file mode 100644 index afb2900a..00000000 --- a/packages/hdwallet-native/src/crypto/engines/web-crypto.ts +++ /dev/null @@ -1,64 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as scryptJs from "scrypt-js"; - -import { CryptoEngine, DigestAlgorithm, ScryptParams } from "./types"; - -export class WebCryptoEngine implements CryptoEngine { - public async decrypt(data: ArrayBuffer, key: ArrayBuffer, iv: ArrayBuffer): Promise { - const impKey = await globalThis.crypto.subtle.importKey("raw", key, { name: "AES-CBC" }, false, ["decrypt"]); - return globalThis.crypto.subtle.decrypt({ name: "AES-CBC", iv }, impKey, data); - } - - public async digest(algorithm: DigestAlgorithm, data: ArrayBuffer): Promise { - const alg = algorithm === DigestAlgorithm.SHA512 ? "SHA-512" : "SHA-256"; - return globalThis.crypto.subtle.digest(alg, data); - } - - public async encrypt(data: ArrayBuffer, key: ArrayBuffer, iv: ArrayBuffer): Promise { - const impKey = await globalThis.crypto.subtle.importKey("raw", key, { name: "AES-CBC" }, false, ["encrypt"]); - return globalThis.crypto.subtle.encrypt({ name: "AES-CBC", iv }, impKey, data); - } - - public async hmac(value: ArrayBuffer, key: ArrayBuffer): Promise { - const signingAlgorithm = { - name: "HMAC", - hash: { name: "SHA-256" }, - }; - - const impKey = await globalThis.crypto.subtle.importKey("raw", key, signingAlgorithm, false, ["sign"]); - return globalThis.crypto.subtle.sign(signingAlgorithm, impKey, value); - } - - public async pbkdf2( - password: ArrayBuffer, - salt: ArrayBuffer, - options: Partial & Pick - ) { - const pbkdf2Params: Pbkdf2Params = { - name: "PBKDF2", - salt: new Uint8Array(salt), - hash: { name: "SHA-256" }, - ...options, - }; - - const impKey = await globalThis.crypto.subtle.importKey("raw", password, { name: "PBKDF2" }, false, ["deriveBits"]); - return globalThis.crypto.subtle.deriveBits(pbkdf2Params, impKey, 256); - } - - public async randomBytes(size: number): Promise { - return core.toArrayBuffer(globalThis.crypto.getRandomValues(new Uint8Array(size))); - } - - public async scrypt(password: ArrayBuffer, salt: ArrayBuffer, params: ScryptParams): Promise { - return core.toArrayBuffer( - await scryptJs.scrypt( - new Uint8Array(password), - new Uint8Array(salt), - params.iterations, - params.blockSize, - params.parallelism, - params.keyLength - ) - ); - } -} diff --git a/packages/hdwallet-native/src/crypto/index.ts b/packages/hdwallet-native/src/crypto/index.ts deleted file mode 100644 index 9e22d424..00000000 --- a/packages/hdwallet-native/src/crypto/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./EncryptedWallet"; -export * as engines from "./engines"; -export * as Isolation from "./isolation"; diff --git a/packages/hdwallet-native/src/crypto/isolation/adapters/bip32.ts b/packages/hdwallet-native/src/crypto/isolation/adapters/bip32.ts deleted file mode 100644 index 53aa1b47..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/adapters/bip32.ts +++ /dev/null @@ -1,167 +0,0 @@ -import { bip32ToAddressNList } from "@keepkey/hdwallet-core"; -import type { crypto as btccrypto, Network, SignerAsync } from "@shapeshiftoss/bitcoinjs-lib"; -import * as bip32 from "bip32"; -import bs58check from "bs58check"; -import PLazy from "p-lazy"; - -import { BIP32, IsolationError, SecP256K1 } from "../core"; -import { Path } from "../core/bip32/types"; -import { ECPairAdapter } from "./bitcoin"; - -let btccryptoInstance: typeof btccrypto | undefined; -const btccryptoReady = PLazy.from(async () => { - btccryptoInstance = (await import("@shapeshiftoss/bitcoinjs-lib")).crypto; -}); - -export type BIP32InterfaceAsync = Omit & - Pick & { - derive(index: number): Promise; - deriveHardened(index: number): Promise; - derivePath(path: string): Promise; - }; - -export class BIP32Adapter extends ECPairAdapter implements BIP32InterfaceAsync { - readonly node: BIP32.Node; - readonly _chainCode: BIP32.ChainCode; - readonly _publicKey: SecP256K1.CurvePoint; - readonly index: number; - readonly _parent?: BIP32Adapter; - readonly _children = new Map(); - readonly _explicitPath?: string; - _identifier?: Buffer; - _base58?: string; - - /** - * If you're inheriting from this class, be sure to call `await BIP32Adapter.prepare()` in your `create()` overload. - */ - protected constructor( - node: BIP32.Node, - chainCode: BIP32.ChainCode, - publicKey: SecP256K1.CurvePoint, - networkOrParent?: BIP32Adapter | Network, - index?: number - ) { - super(node, publicKey, networkOrParent instanceof BIP32Adapter ? networkOrParent.network : networkOrParent); - this.node = node; - this._chainCode = chainCode; - this._publicKey = publicKey; - this.index = index ?? 0; - if (networkOrParent instanceof BIP32Adapter) this._parent = networkOrParent; - if (node.explicitPath) { - Path.assert(node.explicitPath); - this._explicitPath = node.explicitPath; - } - } - - protected static async prepare(): Promise { - // Must await superclass's prepare() so it can do its lazy-loading. - await Promise.all([await btccryptoReady, ECPairAdapter.prepare()]); - } - - static async create( - isolatedNode: BIP32.Node, - networkOrParent?: BIP32Adapter | Network, - index?: number - ): Promise { - await this.prepare(); - return new BIP32Adapter( - isolatedNode, - await isolatedNode.getChainCode(), - await isolatedNode.getPublicKey(), - networkOrParent, - index - ); - } - - get depth(): number { - return this.path ? bip32ToAddressNList(this.path).length : 0; - } - get chainCode() { - return Buffer.from(this._chainCode) as Buffer & BIP32.ChainCode; - } - getChainCode() { - return this.chainCode; - } - get identifier() { - return (this._identifier = - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - this._identifier ?? btccryptoInstance!.hash160(Buffer.from(SecP256K1.CompressedPoint.from(this.publicKey)))); - } - get fingerprint() { - return this.identifier.slice(0, 4); - } - get parentFingerprint() { - return this._parent ? this._parent.fingerprint.readUInt32BE(0) : 0; - } - - get path(): string { - if (this._explicitPath) return this._explicitPath; - if (!this._parent) return ""; - let parentPath = this._parent.path ?? ""; - if (parentPath === "") parentPath = "m"; - const hardened = this.index >= 0x80000000; - const index = hardened ? this.index - 0x80000000 : this.index; - return `${parentPath}/${index}${hardened ? "'" : ""}`; - } - - get publicKey() { - return Buffer.from(SecP256K1.CompressedPoint.from(this._publicKey)) as Buffer & SecP256K1.CompressedPoint; - } - - getPublicKey() { - return this.publicKey; - } - - isNeutered() { - return false; - } - neutered() { - if (!this._base58) { - const xpub = Buffer.alloc(78); - xpub.writeUInt32BE(this.network.bip32.public, 0); - xpub.writeUInt8(this.depth, 4); - xpub.writeUInt32BE(this.parentFingerprint, 5); - xpub.writeUInt32BE(this.index, 9); - xpub.set(this.chainCode, 13); - xpub.set(this.publicKey, 45); - this._base58 = bs58check.encode(xpub); - } - return bip32.fromBase58(this._base58, this.network); - } - - toBase58(): never { - throw new IsolationError("xprv"); - } - - async derive(index: number): Promise { - let out = this._children.get(index); - if (!out) { - out = (await BIP32Adapter.create(await this.node.derive(index), this, index)) as this; - this._children.set(index, out); - } - return out; - } - async deriveHardened(index: number): Promise { - return await this.derive(index + 0x80000000); - } - - async derivePath(path: string): Promise { - /** - * If a non-root explicit path has been set, we cannot construct - * a full representation of the BIP32 key tree and therefore may - * only derive keys for nodes that are children of this one. - */ - if (this._explicitPath) { - if (!(path.startsWith(this._explicitPath) && path.length >= this._explicitPath.length)) { - throw new Error("path is not a child of this node"); - } - } - const ownPath = this.path; - if (path.startsWith(ownPath)) path = path.slice(ownPath.length); - if (path.startsWith("/")) path = path.slice(1); - if (/^m/.test(path) && this._parent) throw new Error("expected master, got child"); - return await BIP32.derivePath(this, path); - } -} - -export default BIP32Adapter; diff --git a/packages/hdwallet-native/src/crypto/isolation/adapters/bitcoin.ts b/packages/hdwallet-native/src/crypto/isolation/adapters/bitcoin.ts deleted file mode 100644 index 62ae6b27..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/adapters/bitcoin.ts +++ /dev/null @@ -1,98 +0,0 @@ -import type { crypto as bcrypto, ECPairInterface, Network, networks, SignerAsync } from "@shapeshiftoss/bitcoinjs-lib"; -import PLazy from "p-lazy"; - -import { IsolationError, SecP256K1 } from "../core"; -import { assertType, ByteArray } from "../types"; - -export type ECPairInterfaceAsync = Omit & Pick; - -let networksInstance: typeof networks | undefined; -const networksReady = PLazy.from(async () => { - networksInstance = (await import("@shapeshiftoss/bitcoinjs-lib")).networks; -}); - -export class ECPairAdapter implements SignerAsync, ECPairInterfaceAsync { - protected readonly _isolatedKey: SecP256K1.ECDSAKey; - readonly _publicKey: SecP256K1.CurvePoint; - readonly _network: Network | undefined; - compressed = false; - lowR = false; - - protected constructor(isolatedKey: SecP256K1.ECDSAKey, publicKey: SecP256K1.CurvePoint, network?: Network) { - this._isolatedKey = isolatedKey; - this._publicKey = publicKey; - this._network = network; - } - - /** - * If you're inheriting from this class, be sure to call `await ECPairAdapter.prepare()` in your `create()` overload. - */ - protected static async prepare() { - await networksReady; - } - - static async create(isolatedKey: SecP256K1.ECDSAKey, network?: Network): Promise { - await this.prepare(); - return new ECPairAdapter(isolatedKey, await isolatedKey.getPublicKey(), network); - } - - get network() { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this._network ?? networksInstance!.bitcoin; - } - - get ecdsaSign() { - return this._isolatedKey.ecdsaSign.bind(this._isolatedKey); - } - - get ecdh() { - const isolatedKey = this._isolatedKey as object as Record; - if (!("ecdh" in isolatedKey && typeof isolatedKey.ecdh === "function")) return undefined; - return isolatedKey.ecdh.bind(isolatedKey); - } - - get ecdhRaw() { - const isolatedKey = this._isolatedKey as object as Record; - if (!("ecdhRaw" in isolatedKey && typeof isolatedKey.ecdhRaw === "function")) return undefined; - return isolatedKey.ecdhRaw.bind(isolatedKey); - } - - async sign(hash: bcrypto.NonDigest | bcrypto.Digest<"hash256">, lowR?: boolean): Promise { - assertType(ByteArray(), hash); - - lowR = lowR ?? this.lowR; - const sig = await (async () => { - if (!hash.algorithm) { - assertType(ByteArray(32), hash); - return !lowR - ? await this._isolatedKey.ecdsaSign(null, hash) - : await SecP256K1.Signature.signCanonically(this._isolatedKey, null, hash); - } else { - return !lowR - ? await this._isolatedKey.ecdsaSign(hash.algorithm, hash.preimage) - : await SecP256K1.Signature.signCanonically(this._isolatedKey, hash.algorithm, hash.preimage); - } - })(); - return Buffer.from(sig); - } - get publicKey() { - return this.getPublicKey(); - } - getPublicKey() { - const publicKey = this._publicKey; - const key = this.compressed - ? SecP256K1.CompressedPoint.from(publicKey) - : SecP256K1.UncompressedPoint.from(publicKey); - return Buffer.from(key) as Buffer & SecP256K1.CurvePoint; - } - - toWIF(): never { - throw new IsolationError("WIF"); - } - verify(hash: Uint8Array, signature: Uint8Array) { - SecP256K1.Signature.assert(signature); - return SecP256K1.Signature.verify(signature, null, hash, this._publicKey); - } -} - -export default ECPairAdapter; diff --git a/packages/hdwallet-native/src/crypto/isolation/adapters/cosmos.ts b/packages/hdwallet-native/src/crypto/isolation/adapters/cosmos.ts deleted file mode 100644 index bef1385b..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/adapters/cosmos.ts +++ /dev/null @@ -1,27 +0,0 @@ -import * as Isolation from "../"; -import { SecP256K1 } from "../core"; - -export class WalletAdapter { - protected readonly _isolatedKey: SecP256K1.ECDSAKey | Isolation.Adapters.BIP32; - readonly _publicKey: SecP256K1.CurvePoint; - - protected constructor(isolatedKey: SecP256K1.ECDSAKey | Isolation.Adapters.BIP32, publicKey: SecP256K1.CurvePoint) { - this._isolatedKey = isolatedKey; - this._publicKey = publicKey; - } - - static async create(isolatedKey: SecP256K1.ECDSAKey | Isolation.Adapters.BIP32): Promise { - return new WalletAdapter(isolatedKey, await isolatedKey.getPublicKey()); - } - - get publicKey(): string { - return Buffer.from(this._publicKey).toString("hex"); - } - - async sign(signMessage: string): Promise { - const signBuf = Buffer.from(signMessage.normalize("NFKD"), "utf8"); - return Buffer.from(await this._isolatedKey.ecdsaSign("sha256", signBuf)); - } -} - -export default WalletAdapter; diff --git a/packages/hdwallet-native/src/crypto/isolation/adapters/cosmosDirect.ts b/packages/hdwallet-native/src/crypto/isolation/adapters/cosmosDirect.ts deleted file mode 100644 index dde687a7..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/adapters/cosmosDirect.ts +++ /dev/null @@ -1,58 +0,0 @@ -import type { AccountData, DirectSignResponse, OfflineDirectSigner } from "@cosmjs/proto-signing"; -import * as bech32 from "bech32"; -import type { SignDoc } from "cosmjs-types/cosmos/tx/v1beta1/tx"; -import PLazy from "p-lazy"; - -import { Digest, SecP256K1 } from "../core"; - -const cosmJsProtoSigning = PLazy.from(() => import("@cosmjs/proto-signing")); - -export class OfflineDirectSignerAdapter implements OfflineDirectSigner { - protected readonly _isolatedKey: SecP256K1.ECDSAKey; - protected readonly _pubkey: Uint8Array; - readonly address: string; - - protected constructor(isolatedKey: SecP256K1.ECDSAKey, pubkey: Uint8Array, address: string) { - this._isolatedKey = isolatedKey; - this._pubkey = pubkey; - this.address = address; - } - - static async create(isolatedKey: SecP256K1.ECDSAKey, prefix: string): Promise { - const pubkey = await isolatedKey.getPublicKey(); - const address = bech32.encode( - prefix, - bech32.toWords(Digest.Algorithms.ripemd160(Digest.Algorithms.sha256(await isolatedKey.getPublicKey()))) - ); - return new OfflineDirectSignerAdapter(isolatedKey, pubkey, address); - } - - async getAccounts(): Promise { - return [ - { - address: this.address, - algo: "secp256k1", - pubkey: this._pubkey, - }, - ]; - } - - async signDirect(signerAddress: string, signDoc: SignDoc): Promise { - if (signerAddress !== this.address) throw new Error("signerAddress mismatch"); - - const signBytes = (await cosmJsProtoSigning).makeSignBytes(signDoc); - const signatureBytes = await this._isolatedKey.ecdsaSign("sha256", signBytes); - return { - signed: signDoc, - signature: { - pub_key: { - type: "tendermint/PubKeySecp256k1", - value: Buffer.from(this._pubkey).toString("base64"), - }, - signature: Buffer.from(signatureBytes).toString("base64"), - }, - }; - } -} - -export default OfflineDirectSignerAdapter; diff --git a/packages/hdwallet-native/src/crypto/isolation/adapters/ethereum.ts b/packages/hdwallet-native/src/crypto/isolation/adapters/ethereum.ts deleted file mode 100644 index 94b99708..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/adapters/ethereum.ts +++ /dev/null @@ -1,99 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import { getMessage, TypedData } from "eip-712"; -import { BigNumber, BytesLike, providers, Signature, UnsignedTransaction } from "ethers"; -import { - arrayify, - computeAddress, - Deferrable, - getAddress, - joinSignature, - resolveProperties, - serializeTransaction, - splitSignature, -} from "ethers/lib/utils.js"; - -import { buildMessage } from "../../../util"; -import { Isolation } from "../.."; -import { SecP256K1 } from "../core"; - -function ethSigFromRecoverableSig(x: SecP256K1.RecoverableSignature): Signature { - const sig = SecP256K1.RecoverableSignature.sig(x); - const recoveryParam = SecP256K1.RecoverableSignature.recoveryParam(x); - return splitSignature(core.compatibleBufferConcat([sig, Buffer.from([recoveryParam])])); -} - -export class SignerAdapter { - protected readonly nodeAdapter: Isolation.Adapters.BIP32; - readonly provider?: providers.Provider; - - constructor(nodeAdapter: Isolation.Adapters.BIP32, provider?: providers.Provider) { - this.nodeAdapter = nodeAdapter; - this.provider = provider; - } - - // This throws (as allowed by ethers.Signer) to avoid having to return an object which is initialized asynchronously - // from a synchronous function. Because all the (other) methods on SignerAdapter are async, one could construct a - // wrapper that deferred its initialization and awaited it before calling through to a "real" method, but that's - // a lot of complexity just to implement this one method we don't actually use. - // eslint-disable-next-line @typescript-eslint/no-unused-vars - connect(_provider: providers.Provider): never { - throw new Error("changing providers on a SignerAdapter is unsupported"); - } - - async getAddress(addressNList: core.BIP32Path): Promise { - const nodeAdapter = await this.nodeAdapter.derivePath(core.addressNListToBIP32(addressNList)); - return computeAddress(SecP256K1.UncompressedPoint.from(nodeAdapter.getPublicKey())); - } - - async signDigest(digest: BytesLike, addressNList: core.BIP32Path): Promise { - const nodeAdapter = await this.nodeAdapter.derivePath(core.addressNListToBIP32(addressNList)); - const recoverableSig = await SecP256K1.RecoverableSignature.signCanonically( - nodeAdapter.node, - null, - digest instanceof Uint8Array ? digest : arrayify(digest) - ); - const sig = SecP256K1.RecoverableSignature.sig(recoverableSig); - const recoveryParam = SecP256K1.RecoverableSignature.recoveryParam(recoverableSig); - return splitSignature(core.compatibleBufferConcat([sig, Buffer.from([recoveryParam])])); - } - - async signTransaction( - transaction: Deferrable, - addressNList: core.BIP32Path - ): Promise { - const tx = await resolveProperties(transaction); - if (tx.from != null) { - if (getAddress(tx.from) !== (await this.getAddress(addressNList))) { - throw new Error("transaction from address mismatch"); - } - delete tx.from; - } - const unsignedTx: UnsignedTransaction = { - ...tx, - nonce: tx.nonce !== undefined ? BigNumber.from(tx.nonce).toNumber() : undefined, - }; - - const nodeAdapter = await this.nodeAdapter.derivePath(core.addressNListToBIP32(addressNList)); - const txBuf = arrayify(serializeTransaction(unsignedTx)); - const rawSig = await SecP256K1.RecoverableSignature.signCanonically(nodeAdapter.node, "keccak256", txBuf); - return serializeTransaction(unsignedTx, ethSigFromRecoverableSig(rawSig)); - } - - async signMessage(messageData: BytesLike, addressNList: core.BIP32Path): Promise { - const messageBuf = buildMessage(messageData); - const nodeAdapter = await this.nodeAdapter.derivePath(core.addressNListToBIP32(addressNList)); - const rawSig = await SecP256K1.RecoverableSignature.signCanonically(nodeAdapter.node, "keccak256", messageBuf); - return joinSignature(ethSigFromRecoverableSig(rawSig)); - } - - async signTypedData(typedData: TypedData, addressNList: core.BIP32Path): Promise { - const address = await this.getAddress(addressNList); - const messageArray = getMessage(typedData); - const nodeAdapter = await this.nodeAdapter.derivePath(core.addressNListToBIP32(addressNList)); - const rawSig = await SecP256K1.RecoverableSignature.signCanonically(nodeAdapter.node, "keccak256", messageArray); - const signature = joinSignature(ethSigFromRecoverableSig(rawSig)); - return { address, signature }; - } -} - -export default SignerAdapter; diff --git a/packages/hdwallet-native/src/crypto/isolation/adapters/fio.ts b/packages/hdwallet-native/src/crypto/isolation/adapters/fio.ts deleted file mode 100644 index 528b88dd..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/adapters/fio.ts +++ /dev/null @@ -1,52 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import { ExternalPrivateKey as FIOExternalPrivateKey } from "@shapeshiftoss/fiojs"; -import bs58 from "bs58"; - -import { SecP256K1 } from "../core"; -import * as Digest from "../core/digest"; -import { CurvePoint, RecoverableSignature } from "../core/secp256k1"; -import { checkType } from "../types"; - -function bs58FioEncode(raw: Uint8Array, keyType = ""): string { - const typeBuf = Buffer.from(keyType, "utf8"); - const checksum = Digest.Algorithms["ripemd160"](core.compatibleBufferConcat([raw, typeBuf])).slice(0, 4); - return bs58.encode(core.compatibleBufferConcat([raw, checksum])); -} - -type IsolatedKey = SecP256K1.ECDSAKey & SecP256K1.ECDHKey; -export class ExternalSignerAdapter implements FIOExternalPrivateKey { - protected readonly _isolatedKey: IsolatedKey; - readonly _publicKey: CurvePoint; - - protected constructor(isolatedKey: IsolatedKey, publicKey: CurvePoint) { - this._isolatedKey = isolatedKey; - this._publicKey = publicKey; - } - - static async create(isolatedKey: IsolatedKey): Promise { - return new ExternalSignerAdapter(isolatedKey, await isolatedKey.getPublicKey()); - } - - get publicKey(): string { - const raw = SecP256K1.CompressedPoint.from(this._publicKey); - return `FIO${bs58FioEncode(raw)}`; - } - - async sign(signBuf: Uint8Array): Promise { - const sig = await SecP256K1.RecoverableSignature.signCanonically(this._isolatedKey, "sha256", signBuf); - const fioSigBuf = core.compatibleBufferConcat([ - Buffer.from([RecoverableSignature.recoveryParam(sig) + 4 + 27]), - SecP256K1.RecoverableSignature.r(sig), - SecP256K1.RecoverableSignature.s(sig), - ]); - return `SIG_K1_${bs58FioEncode(fioSigBuf, "K1")}`; - } - - async getSharedSecret(publicKey: any): Promise { - return Buffer.from( - Digest.Algorithms["sha512"](await this._isolatedKey.ecdh(checkType(SecP256K1.CurvePoint, publicKey.toBuffer()))) - ); - } -} - -export default ExternalSignerAdapter; diff --git a/packages/hdwallet-native/src/crypto/isolation/adapters/index.ts b/packages/hdwallet-native/src/crypto/isolation/adapters/index.ts deleted file mode 100644 index 6085c7a9..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/adapters/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export { default as Bitcoin } from "./bitcoin"; -export { default as BIP32 } from "./bip32"; -export { default as Ethereum } from "./ethereum"; -export { default as FIO } from "./fio"; -export { default as Cosmos } from "./cosmos"; -export { default as CosmosDirect } from "./cosmosDirect"; diff --git a/packages/hdwallet-native/src/crypto/isolation/core/bip32/index.ts b/packages/hdwallet-native/src/crypto/isolation/core/bip32/index.ts deleted file mode 100644 index 58819f29..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/bip32/index.ts +++ /dev/null @@ -1,31 +0,0 @@ -export * from "./types"; -export * from "./interfaces"; - -import { Path } from "./types"; - -interface Derivable { - derive(index: number): Promise; -} - -export async function derivePath(node: T, path: Path): Promise { - // This logic is copied (almost) wholesale from the bip32 package. - Path.assert(path); - - let splitPath = path.split("/"); - if (splitPath[0] === "m") { - splitPath = splitPath.slice(1); - } - const endIndex = splitPath.lastIndexOf(""); - if (endIndex >= 0) splitPath = splitPath.slice(0, endIndex); - - return splitPath.reduce(async (prevHd: Promise, indexStr: string) => { - let index; - if (indexStr.slice(-1) === `'`) { - index = parseInt(indexStr.slice(0, -1), 10); - return (await prevHd).derive(index + 0x80000000); - } else { - index = parseInt(indexStr, 10); - return (await prevHd).derive(index); - } - }, Promise.resolve(node)); -} diff --git a/packages/hdwallet-native/src/crypto/isolation/core/bip32/interfaces.ts b/packages/hdwallet-native/src/crypto/isolation/core/bip32/interfaces.ts deleted file mode 100644 index aecd43fc..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/bip32/interfaces.ts +++ /dev/null @@ -1,20 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import { Revocable } from ".."; -import * as SecP256K1 from "../secp256k1"; -import { ChainCode } from "."; - -export interface Seed extends Partial { - toMasterKey(hmacKey?: string | Uint8Array): Promise; -} - -export interface Node extends Partial, SecP256K1.ECDSAKey, Partial { - readonly explicitPath?: string; - getPublicKey(): Promise; - getChainCode(): Promise; - derive(index: number): Promise; -} - -export function nodeSupportsECDH(x: T): x is T & SecP256K1.ECDHKey { - return core.isIndexable(x) && "ecdh" in x && typeof x.ecdh === "function"; -} diff --git a/packages/hdwallet-native/src/crypto/isolation/core/bip32/types.ts b/packages/hdwallet-native/src/crypto/isolation/core/bip32/types.ts deleted file mode 100644 index 7364860b..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/bip32/types.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { Static } from "funtypes"; - -import { BoundedString, ByteArray } from "../../types"; - -const chainCodeBase = ByteArray(32); -export type ChainCode = Static; -const chainCodeStatic = {}; -const chainCode = Object.assign(chainCodeBase, chainCodeStatic); -export const ChainCode: typeof chainCode = chainCode; - -// https://regex101.com/r/KwmgAp/1 -const pathBase = BoundedString(/^((m\/)?(\d+'?\/)*\d+'?)$|^(?![\s\S])/); -export type Path = Static; -const pathStatic = {}; -const path = Object.assign(pathBase, pathStatic); -export const Path: typeof path = path; diff --git a/packages/hdwallet-native/src/crypto/isolation/core/bip39/index.ts b/packages/hdwallet-native/src/crypto/isolation/core/bip39/index.ts deleted file mode 100644 index a427c734..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/bip39/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./interfaces"; diff --git a/packages/hdwallet-native/src/crypto/isolation/core/bip39/interfaces.ts b/packages/hdwallet-native/src/crypto/isolation/core/bip39/interfaces.ts deleted file mode 100644 index db765acc..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/bip39/interfaces.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { Revocable } from ".."; -import * as BIP32 from "../bip32"; - -export interface Mnemonic extends Partial { - toSeed(passphrase?: string): Promise; -} diff --git a/packages/hdwallet-native/src/crypto/isolation/core/digest/algorithms.ts b/packages/hdwallet-native/src/crypto/isolation/core/digest/algorithms.ts deleted file mode 100644 index 010cb792..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/digest/algorithms.ts +++ /dev/null @@ -1,57 +0,0 @@ -import CryptoJS from "crypto-js"; - -import { Algorithm, AlgorithmName } from "./types"; - -export const AlgorithmLength = { - sha1: 20, - ripemd160: 20, - hash160: 20, - sha256: 32, - hash256: 32, - keccak256: 32, - sha512: 64, -} as const; - -export function toWordArray(x: Uint8Array): CryptoJS.lib.WordArray { - // TODO: avoid this conversion - return CryptoJS.enc.Hex.parse(Buffer.from(x).toString("hex")); - // return (CryptoJS.lib.WordArray.create as unknown as (x: Uint8Array) => CryptoJS.lib.WordArray)(x); -} - -export function fromWordArray(x: CryptoJS.lib.WordArray): Uint8Array { - // TODO: avoid this conversion - return Buffer.from(CryptoJS.enc.Hex.stringify(x), "hex"); - // return Buffer.alloc(x.sigBytes).map((_, i) => (x.words[i >>> 2] >>> (32 - (((i + 1) & 0x03) << 3))) & 0xff); -} - -export function _initializeAlgorithms(register: (name: N, fn: Algorithm) => void) { - // Using an "any" return value overrides static type checking of the length of the digest. This - // is OK because there's no ambiguity as to what it should be and it will be checked at runtime. - - try { - // (Can't use a dynamic import here, because the return is needed synchronously; can't use a static import, - // because we need to fall back tp CryptoJS in browsers) - // eslint-disable-next-line @typescript-eslint/no-var-requires - const crypto = require("crypto"); - register("sha1", (x): any => crypto.createHash("sha1").update(x).digest()); - register("ripemd160", (x): any => crypto.createHash("ripemd160").update(x).digest()); - register("hash160", (x): any => - crypto.createHash("ripemd160").update(crypto.createHash("sha256").update(x).digest()).digest() - ); - register("sha256", (x): any => crypto.createHash("sha256").update(x).digest()); - register("hash256", (x): any => - crypto.createHash("sha256").update(crypto.createHash("sha256").update(x).digest()).digest() - ); - // register("keccak256", (x): any => crypto.createHash("sha3-256").update(x).digest()); - register("keccak256", (x): any => fromWordArray(CryptoJS.SHA3(toWordArray(x), { outputLength: 256 }))); - register("sha512", (x): any => crypto.createHash("sha512").update(x).digest()); - } catch { - register("sha1", (x): any => fromWordArray(CryptoJS.SHA1(toWordArray(x)))); - register("ripemd160", (x): any => fromWordArray(CryptoJS.RIPEMD160(toWordArray(x)))); - register("hash160", (x): any => fromWordArray(CryptoJS.RIPEMD160(CryptoJS.SHA256(toWordArray(x))))); - register("sha256", (x): any => fromWordArray(CryptoJS.SHA256(toWordArray(x)))); - register("hash256", (x): any => fromWordArray(CryptoJS.SHA256(CryptoJS.SHA256(toWordArray(x))))); - register("keccak256", (x): any => fromWordArray(CryptoJS.SHA3(toWordArray(x), { outputLength: 256 }))); - register("sha512", (x): any => fromWordArray(CryptoJS.SHA512(toWordArray(x)))); - } -} diff --git a/packages/hdwallet-native/src/crypto/isolation/core/digest/index.test.ts b/packages/hdwallet-native/src/crypto/isolation/core/digest/index.test.ts deleted file mode 100644 index c6037770..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/digest/index.test.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Algorithms } from "."; -import { fromWordArray, toWordArray } from "./algorithms"; - -describe("Digests", () => { - it("converts to/from WordArrays correctly", () => { - const inHex = "deadbeeffeedface"; - const input = Buffer.from(inHex, "hex"); - const foo = toWordArray(input); - const bar = fromWordArray(foo); - const output = Buffer.from(bar); - expect(output.toString("hex")).toEqual(inHex); - }); - it.each([ - ["SHA-1", "sha1", "616263", "a9993e364706816aba3e25717850c26c9cd0d89d"], - ["RIPEMD160", "ripemd160", "616263", "8eb208f7e05d987a9b044a8e98c6b087f15a0bfc"], - ["HASH160", "hash160", "616263", "bb1be98c142444d7a56aa3981c3942a978e4dc33"], - ["SHA-256", "sha256", "616263", "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"], - ["HASH256", "hash256", "616263", "4f8b42c22dd3729b519ba6f68d2da7cc5b2d606d05daed5ad5128cc03e6c6358"], - ["Keccak-256", "keccak256", "616263", "4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45"], - [ - "SHA-512", - "sha512", - "616263", - "ddaf35a193617abacc417349ae20413112e6fa4e89a97ea20a9eeee64b55d39a2192992a274fc1a836ba3c23a3feebbd454d4423643ce80e2a9ac94fa54ca49f", - ], - ] as const)("correctly implements %s", (_, algName, inHex, outHex) => { - const input = Buffer.from(inHex, "hex"); - console.time(algName); - const output = (() => { - for (let i = 0; ; i++) { - const foo = Algorithms[algName](input); - if (i === 1000) return foo; - } - })(); - console.timeEnd(algName); - expect(output.preimage).toEqual(input); - expect(Buffer.from(output).toString("hex")).toEqual(outHex); - }); -}); diff --git a/packages/hdwallet-native/src/crypto/isolation/core/digest/index.ts b/packages/hdwallet-native/src/crypto/isolation/core/digest/index.ts deleted file mode 100644 index 23823dbb..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/digest/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./types"; -export * from "./algorithms"; diff --git a/packages/hdwallet-native/src/crypto/isolation/core/digest/types.ts b/packages/hdwallet-native/src/crypto/isolation/core/digest/types.ts deleted file mode 100644 index d55e02b7..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/digest/types.ts +++ /dev/null @@ -1,113 +0,0 @@ -import { Contract, Enum, Literal, Never, Object as Obj, Runtype } from "funtypes"; - -import { ByteArray, NonNegativeInteger } from "../../types"; -import { checkType } from "../../types"; -import { _initializeAlgorithms, AlgorithmLength } from "./algorithms"; - -// These names come from the keys on the AlgorithmLength object. We'd prefer not -// to repeat them here, which means we have to build the Enum object in a way that -// type inference can't follow. Luckily, because the names are statically known, -// we can assert the type even though it can't be inferred. -function algorithmNameBase( - length?: L -): Enum<{ [N in AlgorithmName]: N }> { - return Enum( - `AlgorithmName(${length ?? ""})`, - Object.entries(AlgorithmLength) - .filter((x) => length === undefined || length === x[1]) - .map((x) => x[0]) - .reduce((a, x) => Object.assign(a, { [x]: x }), {}) - ) as any; -} -// This can't be inline (or use generic type bounds) because it needs to distributed over the members of a union type. -type algorithmNameInner = K extends keyof typeof AlgorithmLength - ? (typeof AlgorithmLength)[K] extends L - ? K - : never - : never; -// The generic parameter is optional, and will restrict the type to algorithm names whose entries on AlgorithmLength match the specified length. -export type AlgorithmName = L extends undefined - ? keyof typeof AlgorithmLength - : algorithmNameInner; -const algorithmNameStatic = { - forEach(callbackfn: (value: AlgorithmName, index: number, array: AlgorithmName[]) => void, thisarg?: any) { - (Object.keys(AlgorithmName().enumObject) as AlgorithmName[]).forEach(callbackfn, thisarg); - }, -}; -const algorithmName = Object.assign(algorithmNameBase, algorithmNameBase(), algorithmNameStatic); -export const AlgorithmName: typeof algorithmName = algorithmName; - -function specificUnverifiedDigest(name: N): Runtype> { - return Obj({ - preimage: ByteArray(), - algorithm: Literal(name), - }).And(ByteArray(AlgorithmLength[name])) as any; -} - -function unverifiedDigestBase(name?: N): Runtype> { - if (name !== undefined) return specificUnverifiedDigest(name); - return (Object.keys(AlgorithmName.enumObject) as AlgorithmName[]).reduce((a: Runtype, x: AlgorithmName) => { - return a.Or(specificUnverifiedDigest(x)); - }, Never as Runtype); -} -// This can't be inline (or use generic type bounds) because it needs to distributed over the members of a union type. -type unverifiedDigestInner = N extends keyof typeof AlgorithmLength - ? ByteArray<(typeof AlgorithmLength)[N]> & { preimage: ByteArray; algorithm: N } - : never; -// The generic parameter is optional, and will restrict the type to digests with matching length/name combinations. -type UnverifiedDigest = unverifiedDigestInner; -const unverifiedDigestStatic = {}; -const unverifiedDigest = Object.assign(unverifiedDigestBase, ByteArray, unverifiedDigestStatic); -// We need the UnverifiedDigest type to enable us to build the Algorithm contract without -// trying to recursively verify verified verifications. That said, it's not exported; only -// actual algorithm functions we're wrapping should be able to use it. -const UnverifiedDigest: typeof unverifiedDigest = unverifiedDigest; - -export type Digest = UnverifiedDigest; -const digestStatic = {}; - -// We use UnverifiedDigest instead of Digest in the contract because the result is implicitly trusted. -function algorithmBase(name: N) { - return Contract([ByteArray()], UnverifiedDigest(name)); -} -export type Algorithm = (_: ByteArray) => Digest; -const algorithmStatic = {}; -const algorithm = Object.assign(algorithmBase, algorithmStatic); -// This isn't exported; only the registration function below should be using it. -const Algorithm: typeof algorithm = algorithm; - -export const Algorithms = (() => { - const algorithms = {} as { - [Property in keyof typeof AlgorithmLength]: Algorithm; - }; - - _initializeAlgorithms((name: N, fn: Algorithm) => { - AlgorithmName.assert(name); - if (name in algorithms) throw new Error(`digest algorithm implementation already provided for ${name}`); - algorithms[name] = Algorithm(name).enforce((x: ByteArray) => { - const out = checkType(ByteArray<20 | 32 | 64>(AlgorithmLength[name]), fn(x)) as Partial>; - out.preimage = x; - out.algorithm = name; - return checkType(UnverifiedDigest(name), out); - }) as Algorithm; - }); - - Object.freeze(algorithms); - AlgorithmName.forEach((x) => { - if (!algorithms[x]) throw new Error(`digest algorithm implementation missing for ${x}`); - }); - - return algorithms; -})(); - -function digestBase(name?: AlgorithmName) { - return UnverifiedDigest(name).withConstraint( - (x) => - ByteArray.equal(x, Algorithms[x.algorithm](x.preimage)) || - `expected ${x} to equal the ${x.algorithm} digest of ${x.preimage}`, - { name: `Digest(${name})` } - ); -} - -const digest = Object.assign(digestBase, UnverifiedDigest, digestStatic); -export const Digest: typeof digest = digest; diff --git a/packages/hdwallet-native/src/crypto/isolation/core/index.ts b/packages/hdwallet-native/src/crypto/isolation/core/index.ts deleted file mode 100644 index 696c7fc9..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/index.ts +++ /dev/null @@ -1,15 +0,0 @@ -export * as BIP32 from "./bip32"; -export * as BIP39 from "./bip39"; -export * as Digest from "./digest"; -export * as SecP256K1 from "./secp256k1"; - -export class IsolationError extends Error { - constructor(name: string) { - super(`this key is isolated -- no ${name} for you!`); - } -} - -export interface Revocable { - revoke(): void; - addRevoker(revoke: () => void): void; -} diff --git a/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/index.ts b/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/index.ts deleted file mode 100644 index bafa71b5..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./interfaces"; -export * from "./types"; diff --git a/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/interfaces.ts b/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/interfaces.ts deleted file mode 100644 index b0d63569..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/interfaces.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { ByteArray, Uint32 } from "../../types"; -import * as Digest from "../digest"; -import { CurvePoint, RecoverableSignature, Signature } from "./types"; - -export interface ECDSAKey { - getPublicKey(): Promise; - - // Signatures MUST use a determinsitic nonce generation algorithm, which SHOULD be the one specified in RFC6979. The - // counter parameter is used to generate multiple distinct signatures over the same message, and SHOULD be included as - // additional entropy in the nonce generation algorithm (typically after convertion to a 32-byte big-endian integer). - // - // This can be used, for example, to find a signature whose r-value does not have the MSB set (i.e. a lowR signature), - // which can be encoded in DER format with one less byte. If an implementation does not support the use of the counter - // value, it MUST return undefined rather than perform a signing operation which ignores it. - ecdsaSign(digestAlgorithm: null, message: ByteArray<32>): Promise>; - ecdsaSign( - digestAlgorithm: null, - message: ByteArray<32>, - counter: Uint32 - ): Promise | undefined>; - ecdsaSign(digestAlgorithm: Digest.AlgorithmName<32>, message: Uint8Array): Promise>; - ecdsaSign( - digestAlgorithm: Digest.AlgorithmName<32>, - message: Uint8Array, - counter: Uint32 - ): Promise | undefined>; -} - -export interface ECDSARecoverableKey extends ECDSAKey { - ecdsaSignRecoverable(digestAlgorithm: null, message: ByteArray<32>): Promise>; - ecdsaSignRecoverable( - digestAlgorithm: null, - message: ByteArray<32>, - counter: Uint32 - ): Promise | undefined>; - ecdsaSignRecoverable( - digestAlgorithm: Digest.AlgorithmName<32>, - message: Uint8Array - ): Promise>; - ecdsaSignRecoverable( - digestAlgorithm: Digest.AlgorithmName<32>, - message: Uint8Array, - counter: Uint32 - ): Promise | undefined>; -} - -export interface ECDHKey { - getPublicKey(): Promise; - - // Calculates a shared secret field element according to the ECDH key-agreement scheme specified in SEC 1 section 3.3.2, - // encoded as a 32-byte big-endian integer. The output of this function is not uniformly distributed, and is not safe to - // use as a cryptographic key by itself. - // - // A key derivation function is required to convert the output into a usable key; a plain, unkeyed cryptographic hash - // function such as SHA-256 is typically used for this purpose. - ecdh(publicKey: CurvePoint, digestAlgorithm?: Digest.AlgorithmName<32>): Promise>>; - ecdhRaw?(publicKey: CurvePoint): Promise>; -} diff --git a/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/types.ts b/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/types.ts deleted file mode 100644 index 028b1ae0..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/core/secp256k1/types.ts +++ /dev/null @@ -1,317 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import { Literal, Object as Obj, Static, Union } from "funtypes"; -import PLazy from "p-lazy"; -import * as tinyecc from "tiny-secp256k1"; - -import { assertType, BigEndianInteger, ByteArray, checkType, safeBufferFrom, Uint32 } from "../../types"; -import * as Digest from "../digest"; -import { ECDSAKey, ECDSARecoverableKey } from "./interfaces"; - -const ethers = PLazy.from(() => import("ethers")); - -const _fieldElementBase = BigEndianInteger(32).withConstraint( - (x) => tinyecc.isPrivate(safeBufferFrom(x)) || `expected ${x} to be within the order of the curve`, - { name: "FieldElement" } -); -export type FieldElement = Static; -const _fieldElementStatic = {}; -const _fieldElement = Object.assign(_fieldElementBase, BigEndianInteger, _fieldElementStatic); -export const FieldElement: typeof _fieldElement = _fieldElement; - -const _uncompressedPointBase = ByteArray(65) - .And( - Obj({ - 0: Literal(0x04), - }) - ) - .withConstraint((p) => FieldElement.test(p.slice(1, 33)) || `expected ${p}.x to be within the order of the curve`, { - name: "UncompressedPoint.x", - }) - .withConstraint( - (p) => { - if (!FieldElement.test(p.slice(33, 65))) return `expected ${p}.y to be within the order of the curve`; - const pBuf = Buffer.from(p); - if (!ByteArray.equal(tinyecc.pointCompress(tinyecc.pointCompress(pBuf, true), false), pBuf)) - return `expected ${p} to be on the curve`; - return true; - }, - { name: "UncompressedPoint.y" } - ); -export type UncompressedPoint = Static; - -const _compressedPointBase = ByteArray(33) - .And( - Obj({ - 0: Literal(0x02).Or(Literal(0x03)), - }) - ) - .withConstraint((p) => FieldElement.test(p.slice(1)) || `expected ${p}.x to be within the order of the curve`, { - name: "CompressedPoint.x", - }); -export type CompressedPoint = Static; - -const _uncompressedPointStatic = { - from: (p: CurvePoint): UncompressedPoint => { - return p.length === 65 ? p : UncompressedPoint.fromCompressed(checkType(CompressedPoint, p)); - }, - fromCompressed: (p: CompressedPoint): UncompressedPoint => { - return checkType(UncompressedPoint, tinyecc.pointCompress(Buffer.from(p), false)); - }, - x: (p: UncompressedPoint): FieldElement => { - return checkType(FieldElement, p.slice(1, 33)); - }, - y: (p: UncompressedPoint): FieldElement => { - return checkType(FieldElement, p.slice(33, 65)); - }, - yIsOdd: (p: UncompressedPoint): boolean => { - return FieldElement.isOdd(UncompressedPoint.y(p)); - }, -}; -const _uncompressedPoint = Object.assign(_uncompressedPointBase, ByteArray, _uncompressedPointStatic); -export const UncompressedPoint: typeof _uncompressedPoint = _uncompressedPoint; - -const _compressedPointStatic = { - from: (p: CurvePoint): CompressedPoint => { - return p.length === 33 ? p : CompressedPoint.fromUncompressed(checkType(UncompressedPoint, p)); - }, - fromUncompressed: (p: UncompressedPoint): CompressedPoint => { - const out = new Uint8Array(33); - out[0] = UncompressedPoint.yIsOdd(p) ? 0x03 : 0x02; - out.set(UncompressedPoint.x(p), 1); - CompressedPoint.assert(out); - return out; - }, - x: (p: CompressedPoint): FieldElement => { - return checkType(FieldElement, p.slice(1)); - }, - yIsOdd: (p: CompressedPoint): boolean => { - return p[0] === 0x03; - }, -}; -const _compressedPoint = Object.assign(_compressedPointBase, ByteArray, _compressedPointStatic); -export const CompressedPoint: typeof _compressedPoint = _compressedPoint; - -const _curvePointBase = CompressedPoint.Or(UncompressedPoint); -export type CurvePoint = CompressedPoint | UncompressedPoint; -const _curvePointStatic = { - x: (p: CurvePoint): FieldElement => (p[0] === 0x04 ? UncompressedPoint.x(p) : CompressedPoint.x(p)), - yIsOdd: (p: CurvePoint): boolean => (p[0] === 0x04 ? UncompressedPoint.yIsOdd(p) : CompressedPoint.yIsOdd(p)), - // Equivalent to CompressedPoint.equal(CompressedPoint.from(lhs), CompressedPoint.from(rhs)), but avoids allocations - equal: (lhs: CurvePoint, rhs: CurvePoint) => - CurvePoint.yIsOdd(lhs) === CurvePoint.yIsOdd(rhs) && FieldElement.equal(CurvePoint.x(lhs), CurvePoint.x(rhs)), -}; -const _curvePoint = Object.assign(_curvePointBase, _curvePointStatic); -export const CurvePoint: typeof _curvePoint = _curvePoint; - -const _recoveryParamBase = Union(Literal(0), Literal(1), Literal(2), Literal(3)); -export type RecoveryParam = Static; -const _recoveryParamStatic = {}; -const _recoveryParam = Object.assign(_recoveryParamBase, _recoveryParamStatic); -export const RecoveryParam: typeof _recoveryParam = _recoveryParam; - -const _messageWithPreimageBase = ByteArray(32).And(Digest.Digest()); -export type MessageWithPreimage = Static; -const _messageWithPreimageStatic = {}; -const _messageWithPreimage = Object.assign(_messageWithPreimageBase, ByteArray, _messageWithPreimageStatic); -export const MessageWithPreimage: typeof _messageWithPreimage = _messageWithPreimage; - -const _messageBase = MessageWithPreimage.Or(ByteArray()); -export type Message = Static; -const _messageStatic = {}; -const _message = Object.assign(_messageBase, ByteArray, _messageWithPreimageStatic, _messageStatic); -export const Message: typeof _message = _message; - -const _signatureBase = ByteArray(64) - .withConstraint((x) => FieldElement.test(x.slice(0, 32)) || `expected ${x}.r to be within the order of the curve`, { - name: "Signature.r", - }) - .withConstraint((x) => FieldElement.test(x.slice(32, 64)) || `expected ${x}.s to be within the order of the curve`, { - name: "Signature.s", - }); -export type Signature = Static; -const _signatureStatic = { - r: (x: Signature): FieldElement => { - return checkType(FieldElement, x.slice(0, 32)); - }, - s: (x: Signature): FieldElement => { - return checkType(FieldElement, x.slice(32, 64)); - }, - isLowR: (x: Signature): boolean => { - return !FieldElement.isHigh(Signature.r(x)); - }, - isLowS: (x: Signature): boolean => { - return !FieldElement.isHigh(Signature.s(x)); - }, - isCanonical: (x: Signature): boolean => { - return Signature.isLowR(x) && Signature.isLowS(x); - }, - signCanonically: async ( - x: ECDSAKey, - digestAlgorithm: Digest.AlgorithmName<32> | null, - message: Uint8Array, - counter?: Uint32 - ): Promise => { - assertType(ByteArray(), message); - counter === undefined || Uint32.assert(counter); - for (let i = counter; i === undefined || i < (counter ?? 0) + 128; i = (i ?? -1) + 1) { - const sig = await (async () => { - if (digestAlgorithm === null) { - assertType(ByteArray(32), message); - return i === undefined - ? await x.ecdsaSign(digestAlgorithm, message) - : await x.ecdsaSign(digestAlgorithm, message, i); - } else { - return i === undefined - ? await x.ecdsaSign(digestAlgorithm, message) - : await x.ecdsaSign(digestAlgorithm, message, i); - } - })(); - if (sig === undefined) break; - //TODO: do integrated lowS correction - if (Signature.isCanonical(sig)) return sig; - } - // This is cryptographically impossible (2^-128 chance) if the key is implemented correctly. - throw new Error( - `Unable to generate canonical signature with public key ${x} over message ${message}; is your key implementation broken?` - ); - }, - verify: ( - x: Signature, - digestAlgorithm: Digest.AlgorithmName<32> | null, - message: Uint8Array, - publicKey: CurvePoint - ): boolean => { - const msgOrDigest = - digestAlgorithm === null - ? checkType(ByteArray(32), message) - : Digest.Algorithms[digestAlgorithm](checkType(ByteArray(), message)); - return tinyecc.verify(Buffer.from(msgOrDigest), Buffer.from(publicKey), Buffer.from(x)); - }, -}; -const _signature = Object.assign(_signatureBase, ByteArray, _signatureStatic); -export const Signature: typeof _signature = _signature; - -const _recoverableSignatureBase = ByteArray(65) - .And( - Obj({ - 64: RecoveryParam, - }) - ) - .withConstraint((x) => Signature.test(x.slice(0, 64)) || `expected ${x}.sig to be a valid signature`, { - name: "Signature", - }); -export type RecoverableSignature = Static; -const _recoverableSignatureStatic = { - from: (x: Signature, recoveryParam: RecoveryParam): RecoverableSignature => { - return checkType(RecoverableSignature, core.compatibleBufferConcat([x, new Uint8Array([recoveryParam])])); - }, - fromSignature: async ( - x: Signature, - digestAlgorithm: Digest.AlgorithmName<32> | null, - message: Uint8Array, - publicKey: CurvePoint - ): Promise => { - for (let recoveryParam: RecoveryParam = 0; recoveryParam < 4; recoveryParam++) { - const out = RecoverableSignature.from(x, recoveryParam); - if (!CurvePoint.equal(publicKey, await RecoverableSignature.recoverPublicKey(out, digestAlgorithm, message))) - continue; - return out; - } - throw new Error( - `couldn't find recovery parameter producing public key ${publicKey} for signature ${x} over message ${message}` - ); - }, - sig: (x: RecoverableSignature): Signature => checkType(Signature, x.slice(0, 64)), - recoveryParam: (x: RecoverableSignature): RecoveryParam => checkType(RecoveryParam, x[64]), - isLowRecoveryParam: (x: RecoverableSignature) => [0, 1].includes(RecoverableSignature.recoveryParam(x)), - isCanonical: (x: RecoverableSignature): boolean => - Signature.isCanonical(checkType(Signature, RecoverableSignature.sig(x))) && - RecoverableSignature.isLowRecoveryParam(x), - signCanonically: async ( - x: ECDSAKey, - digestAlgorithm: Digest.AlgorithmName<32> | null, - message: Uint8Array, - counter?: Uint32 - ): Promise => { - const publicKey = await x.getPublicKey(); - assertType(ByteArray(), message); - counter === undefined || Uint32.assert(counter); - - // eslint-disable-next-line @typescript-eslint/no-shadow - const isIndexable = (x: unknown): x is Record => - x !== null && ["object", "function"].includes(typeof x); - // eslint-disable-next-line @typescript-eslint/no-shadow - const isECDSARecoverableKey = (x: ECDSAKey): x is ECDSARecoverableKey => - isIndexable(x) && "ecdsaSignRecoverable" in x && typeof x.ecdsaSignRecoverable === "function"; - - const ecdsaSignRecoverable = isECDSARecoverableKey(x) - ? // eslint-disable-next-line @typescript-eslint/no-shadow - async (digestAlgorithm: Digest.AlgorithmName<32> | null, message: Uint8Array, counter?: Uint32) => { - if (digestAlgorithm === null) { - assertType(ByteArray(32), message); - return counter === undefined - ? await x.ecdsaSignRecoverable(digestAlgorithm, message) - : await x.ecdsaSignRecoverable(digestAlgorithm, message, counter); - } else { - return counter === undefined - ? await x.ecdsaSignRecoverable(digestAlgorithm, message) - : await x.ecdsaSignRecoverable(digestAlgorithm, message, counter); - } - } - : // eslint-disable-next-line @typescript-eslint/no-shadow - async (digestAlgorithm: Digest.AlgorithmName<32> | null, message: Uint8Array, counter?: Uint32) => { - const sig = await Signature.signCanonically(x, digestAlgorithm, message, counter); - if (sig === undefined) return undefined; - return await RecoverableSignature.fromSignature(sig, digestAlgorithm, message, publicKey); - }; - - // Technically, this may waste cycles; if Signature.signCanonically grinds the counter to find a canonical signature which then - // ends up to have a non-canonical recovery parameter, those values will all be re-ground. However, signatures can have - // non-canonical recovery parameters only with negligible probability, so optimization for that case would be silly. - for (let i = counter; i === undefined || i < (counter ?? 0) + 128; i = (i ?? -1) + 1) { - const recoverableSig = await ecdsaSignRecoverable(digestAlgorithm, message, i); - if (recoverableSig === undefined) break; - //TODO: do integrated lowS correction - if (RecoverableSignature.isCanonical(recoverableSig)) return recoverableSig; - } - // This is cryptographically impossible (2^-128 chance) if the key is implemented correctly. - throw new Error( - `Unable to generate canonical recoverable signature with public key ${Buffer.from(publicKey).toString( - "hex" - )} over message ${Buffer.from(message).toString("hex")}; is your key implementation broken?` - ); - }, - recoverPublicKey: async ( - x: RecoverableSignature, - digestAlgorithm: Digest.AlgorithmName<32> | null, - message: Uint8Array - ): Promise => { - // TODO: do this better - const msgOrDigest = - digestAlgorithm === null - ? checkType(ByteArray(32), message) - : Digest.Algorithms[digestAlgorithm](checkType(ByteArray(), message)); - const sig = RecoverableSignature.sig(x); - const recoveryParam = RecoverableSignature.recoveryParam(x); - const ethSig = core.compatibleBufferConcat([sig, Buffer.from([recoveryParam])]); - const ethRecovered = (await ethers).utils.recoverPublicKey( - msgOrDigest, - (await ethers).utils.splitSignature(ethSig) - ); - return checkType(UncompressedPoint, Buffer.from(ethRecovered.slice(2), "hex")); - }, - r: (x: RecoverableSignature): FieldElement => Signature.r(RecoverableSignature.sig(x)), - s: (x: RecoverableSignature): FieldElement => Signature.s(RecoverableSignature.sig(x)), - isLowR: (x: RecoverableSignature): boolean => Signature.isLowR(RecoverableSignature.sig(x)), - isLowS: (x: RecoverableSignature): boolean => Signature.isLowS(RecoverableSignature.sig(x)), - verify: ( - x: RecoverableSignature, - digestAlgorithm: Digest.AlgorithmName<32> | null, - message: Uint8Array, - publicKey: CurvePoint - ): boolean => { - return Signature.verify(RecoverableSignature.sig(x), digestAlgorithm, message, publicKey); - }, -}; -const _recoverableSignature = Object.assign(_recoverableSignatureBase, _recoverableSignatureStatic); -export const RecoverableSignature: typeof _recoverableSignature = _recoverableSignature; diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/default/bip32.ts b/packages/hdwallet-native/src/crypto/isolation/engines/default/bip32.ts deleted file mode 100644 index 7a69ee02..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/default/bip32.ts +++ /dev/null @@ -1,186 +0,0 @@ -import * as bip32crypto from "bip32/src/crypto"; -import * as tinyecc from "tiny-secp256k1"; -import { TextEncoder } from "web-encoding"; - -import { BIP32, Digest, SecP256K1 } from "../../core"; -import { assertType, ByteArray, checkType, safeBufferFrom, Uint32 } from "../../types"; -import { Revocable, revocable } from "./revocable"; - -export * from "../../core/bip32"; - -export class Node extends Revocable(class {}) implements BIP32.Node, SecP256K1.ECDSARecoverableKey, SecP256K1.ECDHKey { - readonly #privateKey: Buffer & ByteArray<32>; - readonly chainCode: Buffer & BIP32.ChainCode; - #publicKey: SecP256K1.CompressedPoint | undefined; - readonly explicitPath?: string; - // When running tests, this will keep us aware of any codepaths that don't pass in the preimage - static requirePreimage = typeof expect === "function"; - - protected constructor(privateKey: Uint8Array, chainCode: Uint8Array, explicitPath?: string) { - super(); - // We avoid handing the private key to any non-platform code -- including our type-checking machinery. - if (privateKey.length !== 32) throw new Error("bad private key length"); - this.#privateKey = safeBufferFrom(privateKey) as Buffer & ByteArray<32>; - this.addRevoker(() => this.#privateKey.fill(0)); - this.chainCode = safeBufferFrom(checkType(BIP32.ChainCode, chainCode)) as Buffer & BIP32.ChainCode; - this.explicitPath = explicitPath; - } - - static async create(privateKey: Uint8Array, chainCode: Uint8Array, explicitPath?: string): Promise { - const obj = new Node(privateKey, chainCode, explicitPath); - return revocable(obj, (x) => obj.addRevoker(x)); - } - - async getPublicKey(): Promise { - this.#publicKey = - this.#publicKey ?? checkType(SecP256K1.CompressedPoint, tinyecc.pointFromScalar(this.#privateKey, true)); - return this.#publicKey; - } - - async getChainCode() { - return this.chainCode; - } - - async ecdsaSign(digestAlgorithm: null, msg: ByteArray<32>, counter?: Uint32): Promise; - async ecdsaSign( - digestAlgorithm: Digest.AlgorithmName<32>, - msg: Uint8Array, - counter?: Uint32 - ): Promise; - async ecdsaSign( - digestAlgorithm: Digest.AlgorithmName<32> | null, - msg: Uint8Array, - counter?: Uint32 - ): Promise { - const recoverableSig = await (async () => { - if (digestAlgorithm === null) { - assertType(ByteArray(32), msg); - return await this.ecdsaSignRecoverable(digestAlgorithm, msg, counter); - } else { - return await this.ecdsaSignRecoverable(digestAlgorithm, msg, counter); - } - })(); - return SecP256K1.RecoverableSignature.sig(recoverableSig); - } - - async ecdsaSignRecoverable( - digestAlgorithm: null, - msg: ByteArray<32>, - counter?: Uint32 - ): Promise; - async ecdsaSignRecoverable( - digestAlgorithm: Digest.AlgorithmName<32>, - msg: Uint8Array, - counter?: Uint32 - ): Promise; - async ecdsaSignRecoverable( - digestAlgorithm: Digest.AlgorithmName<32> | null, - msg: Uint8Array, - counter?: Uint32 - ): Promise { - counter === undefined || Uint32.assert(counter); - digestAlgorithm === null || Digest.AlgorithmName(32).assert(digestAlgorithm); - - if (Node.requirePreimage && digestAlgorithm === null) throw TypeError("preimage required"); - - const msgOrDigest = - digestAlgorithm === null - ? checkType(ByteArray(32), msg) - : Digest.Algorithms[digestAlgorithm](checkType(ByteArray(), msg)); - const entropy = counter === undefined ? undefined : Buffer.alloc(32); - entropy?.writeUInt32BE(counter ?? 0, 24); - return await SecP256K1.RecoverableSignature.fromSignature( - checkType( - SecP256K1.Signature, - ( - tinyecc as typeof tinyecc & { - signWithEntropy: (message: Buffer, privateKey: Buffer, entropy?: Buffer) => Buffer; - } - ).signWithEntropy(Buffer.from(msgOrDigest), this.#privateKey, entropy) - ), - null, - msgOrDigest, - await this.getPublicKey() - ); - } - - async derive(index: Uint32): Promise { - Uint32.assert(index); - - const serP = Buffer.alloc(37); - if (index < 0x80000000) { - serP.set(SecP256K1.CompressedPoint.from(await this.getPublicKey()), 0); - } else { - serP.set(this.#privateKey, 1); - } - serP.writeUInt32BE(index, 33); - - const I = bip32crypto.hmacSHA512(this.chainCode, serP); - const IL = I.slice(0, 32); - const IR = I.slice(32, 64); - const ki = tinyecc.privateAdd(this.#privateKey, IL); - if (ki === null) throw new Error("ki is null; this should be cryptographically impossible"); - const out = await Node.create(ki, IR); - this.addRevoker(() => out.revoke?.()); - return out as this; - } - - async ecdh(publicKey: SecP256K1.CurvePoint, digestAlgorithm?: Digest.AlgorithmName<32>): Promise> { - SecP256K1.CurvePoint.assert(publicKey); - digestAlgorithm === undefined || Digest.AlgorithmName(32).assert(digestAlgorithm); - - return checkType(ByteArray(32), await this._ecdh(publicKey, digestAlgorithm)); - } - - async ecdhRaw(publicKey: SecP256K1.CurvePoint): Promise { - return checkType(SecP256K1.UncompressedPoint, await this._ecdh(publicKey, null)); - } - - private async _ecdh( - publicKey: SecP256K1.CurvePoint, - digestAlgorithm?: Digest.AlgorithmName<32> | null - ): Promise | SecP256K1.UncompressedPoint> { - SecP256K1.CurvePoint.assert(publicKey); - digestAlgorithm === undefined || digestAlgorithm === null || Digest.AlgorithmName(32).assert(digestAlgorithm); - - const sharedFieldElement = checkType( - SecP256K1.UncompressedPoint, - tinyecc.pointMultiply(Buffer.from(publicKey), this.#privateKey, false) - ); - if (digestAlgorithm === null) return sharedFieldElement; - - let out = SecP256K1.CurvePoint.x(sharedFieldElement); - if (digestAlgorithm !== undefined) out = Digest.Algorithms[digestAlgorithm](out); - return out; - } -} - -export class Seed extends Revocable(class {}) implements BIP32.Seed { - readonly #seed: Buffer; - - protected constructor(seed: Uint8Array) { - super(); - this.#seed = safeBufferFrom(seed); - this.addRevoker(() => this.#seed.fill(0)); - } - - static async create(seed: Uint8Array): Promise { - const obj = new Seed(seed); - return revocable(obj, (x) => obj.addRevoker(x)); - } - - async toMasterKey(hmacKey?: string | Uint8Array): Promise { - if (hmacKey !== undefined && typeof hmacKey !== "string" && !(hmacKey instanceof Uint8Array)) - throw new Error("bad hmacKey type"); - - // AFAIK all BIP32 implementations use the "Bitcoin seed" string for this derivation, even if they aren't otherwise Bitcoin-related - hmacKey = hmacKey ?? "Bitcoin seed"; - if (typeof hmacKey === "string") hmacKey = new TextEncoder().encode(hmacKey.normalize("NFKD")); - const I = safeBufferFrom(bip32crypto.hmacSHA512(safeBufferFrom(hmacKey), this.#seed)); - const IL = I.slice(0, 32); - const IR = I.slice(32, 64); - const out = await Node.create(IL, IR); - this.addRevoker(() => out.revoke?.()); - return out; - } -} diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/default/bip39.ts b/packages/hdwallet-native/src/crypto/isolation/engines/default/bip39.ts deleted file mode 100644 index f563e66a..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/default/bip39.ts +++ /dev/null @@ -1,45 +0,0 @@ -/// - -import { createSHA512, pbkdf2 } from "hash-wasm"; -import { TextEncoder } from "web-encoding"; - -import type { Seed as SeedType } from "../../core/bip32"; -import type { Mnemonic as Bip39Mnemonic } from "../../core/bip39"; -import { Seed } from "./bip32"; -import { Revocable, revocable } from "./revocable"; - -export * from "../../core/bip39"; - -export class Mnemonic extends Revocable(class {}) implements Bip39Mnemonic { - readonly #mnemonic: string; - - protected constructor(mnemonic: string) { - super(); - this.#mnemonic = mnemonic.normalize("NFKD"); - } - - static async create(mnemonic: string): Promise { - const obj = new Mnemonic(mnemonic); - return revocable(obj, (x) => obj.addRevoker(x)); - } - - async toSeed(passphrase?: string): Promise { - const mnemonic = this.#mnemonic; - const salt = new TextEncoder().encode(`mnemonic${passphrase ?? ""}`.normalize("NFKD")); - - const out = await Seed.create( - Buffer.from( - await pbkdf2({ - password: mnemonic, - salt, - iterations: 2048, - hashLength: 64, - hashFunction: createSHA512(), - outputType: "binary", - }) - ) - ); - this.addRevoker(() => out.revoke?.()); - return out; - } -} diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/default/index.test.ts b/packages/hdwallet-native/src/crypto/isolation/engines/default/index.test.ts deleted file mode 100644 index 7f99224e..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/default/index.test.ts +++ /dev/null @@ -1,78 +0,0 @@ -import * as Core from "../../core"; -import * as Default from "./"; - -describe("Isolation.Engines.Default", () => { - let mnemonic: Core.BIP39.Mnemonic; - let seed: Core.BIP32.Seed; - let masterKey: Core.BIP32.Node; - - it("can be loaded with a list of xpubs", async () => { - await expect( - (async () => { - mnemonic = await Default.BIP39.Mnemonic.create("all all all all all all all all all all all all"); - })() - ).resolves.not.toThrow(); - expect(mnemonic).toBeDefined(); - }); - - it("produces a seed", async () => { - await expect( - (async () => { - seed = await mnemonic.toSeed(); - })() - ).resolves.not.toThrow(); - expect(seed).toBeDefined(); - }); - - it("produces a master key", async () => { - masterKey = await seed.toMasterKey(); - const pk = await masterKey.getPublicKey(); - expect(Buffer.from(pk).toString("hex")).toEqual( - "03e3b30e8c21923752a408242e069941fedbaef7db7161f7e2c5f3fdafe7e25ddc" - ); - }); - - it.each([ - ["m/44'", "034d600165882b6faf32a3f1f2c4755eeb0f0486954718d46fd9621e8ca40ca6b6"], - ["m/44'/0'", "03dde722d51529c6744d45e1a5e644c6e27520bd8bc7278fbeb1f43094f3dce91a"], - ["m/44'/0'/0'", "03c8166eb40ac84088b618ec07c7cebadacee31c5f5b04a1e8c2a2f3e748eb2cdd"], - ["m/44'/0'/0'/0", "02d3f906cd22167506f94331fc879b1757695c9d9b09fbb1cd6bee9c7ee7019751"], - ["m/44'/0'/0'/0/0", "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c"], - ["m/44'/0'/0'/0/1", "02c651a011009e2c7e7b3ed2068857ca0a47cba35b73e06c32e3c06ef3aa67621d"], - ["m/44'/0'/0'/0/2", "03330236b68aa6fdcaca0ea72e11b360c84ed19a338509aa527b678a7ec9076882"], - ["m/44'/0'/0'/1", "0377d49f78af126571d0e995656ab0b12cf149a6761bfc3e75132813c7d9c1739f"], - ["m/44'/0'/0'/1/0", "035bc524b005abbf8c3f0c22a452d0b9c2ad43c4609b4b78c745b47f66120bb1a0"], - ["m/44'/0'/0'/1/1", "0203ae8dbf9f9b65f3922a4a855a7c5d7e7700b0f38477b9e047385eed1ba6e18c"], - ["m/44'/0'/0'/1/2", "03389aa9b8d59b776a93a26cf7ee3d9e0ad1b8f0440e778f5270785d12936dad3c"], - ["m/44'/60'", "026efeb8a29b3eedec94c5aca20a84ff4b98d57f9967856a21a64c8d127d863098"], - ["m/44'/60'/0'", "03d92dfaf121b2723d0e6dabb2637b2d9b2b3b2d8026ab901f2df3eea3f6d200c9"], - ["m/44'/60'/0'/0", "0217ebaac6b4c12d3c7e0fc21d8d53d89adf007ff7988840926032c89eb966a37c"], - ["m/44'/60'/0'/0/0", "03ad8e7eb4f3a7d1a409fa7bdc7b79d8840fe746d3fa9ee17fee4f84631ec1430b"], - ["m/49'", "02afb083c2e97455310c8591c6235c9ceb92dc32f4e40d146cd5b550e3bebbc74a"], - ["m/49'/0'", "039051bb3f5af2094a2b4ee31964b8d82b379604926b393b698314e098b6984bd0"], - ["m/49'/0'/0'", "0215a09870bbb713f1ba94d364e1e5bfcf9cdb5178d22efbca6ec17dc2c4f706cd"], - ["m/49'/0'/0'/0", "020ddd7e4206daf889a2c11920fcccbb60df383d4c5fcd982cd5c7d400fdd46c8e"], - ["m/49'/0'/0'/0/0", "02f770feae292b5b3f41d8c81220c2568cb73eb8042def35e648dfe048e4b41b11"], - ["m/49'/0'/0'/0/1", "02dc4843f2fbef594a8c41573ca7a91c968ced334c16c5200cc6a07e8dbba3bdb2"], - ["m/49'/0'/0'/0/2", "03eb2d79f0e0896f523a30d92f395e31c31d0196f2f36d8284145007e68d0563fa"], - ["m/49'/0'/0'/1", "02f7ff3aab4f9fd88190ac153bd0bcb26758a6b3b75480ddda8c0f43147fbbee95"], - ["m/49'/0'/0'/1/0", "03a961687895a78da9aef98eed8e1f2a3e91cfb69d2f3cf11cbd0bb1773d951928"], - ["m/49'/0'/0'/1/1", "03f459101133e88e5953ec0a128c3bc17d5e6e7e8dd035b4dbffad364774f1e710"], - ["m/49'/0'/0'/1/2", "036a7e2f1544eb4ddf1e3df4fedd4c8c0c39b988f3ac99e927f4a00fc5fddfc653"], - ["m/84'", "0225ee2bad1901cea8dca61028fa2c39f9bc6fe6fde7f06405c4cf1131e0ec91ae"], - ["m/84'/0'", "031c9a1c04f0c3b62c013e27ce7a6c7720ac669ee738aa4a6c9112f25d731b6c27"], - ["m/84'/0'/0'", "03e36a4f3fee21bfe83447b209d8de6da1ce1ae38f76bc2c00652dc5e0a8c5c0b5"], - ["m/84'/0'/0'/0", "025982bc036c5321d35d808ab872b2337438b1bb07d5544cf0a20e84327e05897f"], - ["m/84'/0'/0'/0/0", "0396070f2813933502e907c011ae7ba928683a9c2f0e888dae7ebd2c41120ee6b5"], - ["m/84'/0'/0'/0/1", "026b6039331b4d7bb2037fe72411a582e3d1993190731582bf04f18cc4249ea83e"], - ["m/84'/0'/0'/0/2", "03e4a361a06cdf253f7be2b00bb171e30f6f73ec06eb437d9842ec593c5ac0e499"], - ["m/84'/0'/0'/1", "03bc5bf5297765cd1675cd93667500529476502a413310afbfdeb04963e130ea3e"], - ["m/84'/0'/0'/1/0", "032ef68318c8f6aaa0adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b"], - ["m/84'/0'/0'/1/1", "02768afac47832d02e24c39ffcaa9bbd54be67460e38c255d97192cec5e4e25975"], - ["m/84'/0'/0'/1/2", "0245ac2db850ba9a1971741267a1849c72b91722e09cf71c9ff3754ff41f2a0419"], - ])("derives the key at %s", async (path: string, expectedPk: string) => { - const node = await Core.BIP32.derivePath(masterKey, path); - const pk = Buffer.from(await node.getPublicKey()).toString("hex"); - expect(pk).toEqual(expectedPk); - }); -}); diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/default/index.ts b/packages/hdwallet-native/src/crypto/isolation/engines/default/index.ts deleted file mode 100644 index d5996c19..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/default/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * as BIP32 from "./bip32"; -export * as BIP39 from "./bip39"; -export * from "./revocable"; diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/default/revocable.ts b/packages/hdwallet-native/src/crypto/isolation/engines/default/revocable.ts deleted file mode 100644 index 618f7c16..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/default/revocable.ts +++ /dev/null @@ -1,126 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -const _Set = Set; -const _freeze = Object.freeze.bind(Object); -const _revocable = Proxy.revocable.bind(Proxy); - -/* -Proxy handler invariants (per MDN): - apply - The target must be a callable itself. That is, it must be a function object. - construct - The result must be an Object. - defineProperty - A property cannot be added, if the target object is not extensible. - A property cannot be added as or modified to be non-configurable, if it does not exists as a non-configurable own property of the target object. - A property may not be non-configurable, if a corresponding configurable property of the target object exists. - If a property has a corresponding target object property then Object.defineProperty(target, prop, descriptor) will not throw an exception. - In strict mode, a false return value from the defineProperty() handler will throw a TypeError exception. - deleteProperty - A property cannot be deleted, if it exists as a non-configurable own property of the target object. - get - The value reported for a property must be the same as the value of the corresponding target object property if the target object property is a non-writable, non-configurable own data property. - The value reported for a property must be undefined if the corresponding target object property is a non-configurable own accessor property that has undefined as its [[Get]] attribute. - getOwnPropertyDescriptor - getOwnPropertyDescriptor() must return an object or undefined. - A property cannot be reported as non-existent, if it exists as a non-configurable own property of the target object. - A property cannot be reported as non-existent, if it exists as an own property of the target object and the target object is not extensible. - A property cannot be reported as existent, if it does not exists as an own property of the target object and the target object is not extensible. - A property cannot be reported as non-configurable, if it does not exists as an own property of the target object or if it exists as a configurable own property of the target object. - The result of Object.getOwnPropertyDescriptor(target) can be applied to the target object using Object.defineProperty() and will not throw an exception. - getPrototypeOf - getPrototypeOf() method must return an object or null. - If target is not extensible, Object.getPrototypeOf(proxy) method must return the same value as Object.getPrototypeOf(target). - has - A property cannot be reported as non-existent, if it exists as a non-configurable own property of the target object. - A property cannot be reported as non-existent, if it exists as an own property of the target object and the target object is not extensible. - isExtensible - Object.isExtensible(proxy) must return the same value as Object.isExtensible(target). - ownKeys - The result of ownKeys() must be an array. - The type of each array element is either a String or a Symbol. - The result List must contain the keys of all non-configurable own properties of the target object. - If the target object is not extensible, then the result List must contain all the keys of the own properties of the target object and no other values. - preventExtensions - Object.preventExtensions(proxy) only returns true if Object.isExtensible(proxy) is false. - set - Return true to indicate that assignment succeeded. - If the set() method returns false, and the assignment happened in strict-mode code, a TypeError will be thrown. - setPrototypeOf - If target is not extensible, the prototype parameter must be the same value as Object.getPrototypeOf(target). -*/ - -export const revocable = _freeze((x: T, addRevoker: (revoke: () => void) => void) => { - const universalProxyHandler = (pseudoTarget: object) => - new Proxy( - {}, - { - get(_, p) { - return (_t: any, p2: any, r: any) => { - switch (p) { - case "get": { - const out = Reflect.get(pseudoTarget, p2, r); - if (typeof out === "function") return out.bind(x); - return out; - } - case "getOwnPropertyDescriptor": { - const out = Reflect.getOwnPropertyDescriptor(pseudoTarget, p2); - if (out) out.configurable = true; - return out; - } - case "isExtensible": - return true; - case "preventExtensions": - return false; - default: - return (Reflect as any)[p](pseudoTarget, p2, r); - } - }; - }, - } - ); - const { proxy, revoke } = _revocable({} as T, universalProxyHandler(x)); - addRevoker(revoke); - return proxy; -}); - -export interface Revocable { - revoke(): void; - addRevoker(x: () => void): void; -} - -export const Revocable = _freeze((x: T) => { - const out = _freeze( - // eslint-disable-next-line @typescript-eslint/no-shadow - class Revocable extends x { - readonly #revokers: Set<() => void> = new _Set(); - #revoked = false; - - readonly revoke = () => { - this.#revoked = true; - this.#revokers.forEach((revoker) => { - try { - revoker(); - } catch { - // revoker errors get swallowed. - } - }); - this.#revokers.clear(); - }; - - readonly addRevoker = (revoker: () => void) => { - if (this.#revoked) { - try { - revoker(); - } catch { - // revoker errors get swallowed. - } - } else { - this.#revokers.add(revoker); - } - }; - } - ); - _freeze(out.prototype); - return out; -}); diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/bip32.ts b/packages/hdwallet-native/src/crypto/isolation/engines/dummy/bip32.ts deleted file mode 100644 index cda12f63..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/bip32.ts +++ /dev/null @@ -1,118 +0,0 @@ -import { toArrayBuffer } from "@keepkey/hdwallet-core"; -import * as bip32crypto from "bip32/src/crypto"; -import * as tinyecc from "tiny-secp256k1"; - -import { BIP32, Digest, SecP256K1 } from "../../core"; -import { ByteArray, checkType, safeBufferFrom, Uint32 } from "../../types"; -import { DummyEngineError, ParsedXpubTree } from "./types"; - -export * from "../../core/bip32"; - -export class Node implements BIP32.Node, SecP256K1.ECDSARecoverableKey, SecP256K1.ECDHKey { - readonly xpubTree: ParsedXpubTree; - - protected constructor(xpubTree: ParsedXpubTree) { - this.xpubTree = xpubTree; - } - - static async create(xpubTree: ParsedXpubTree): Promise { - return new Node(xpubTree); - } - - async getPublicKey(): Promise { - return this.xpubTree.publicKey; - } - - async getChainCode(): Promise { - return this.xpubTree.chainCode; - } - - async ecdsaSign(digestAlgorithm: null, msg: ByteArray<32>, counter?: Uint32): Promise; - async ecdsaSign( - digestAlgorithm: Digest.AlgorithmName<32>, - msg: Uint8Array, - counter?: Uint32 - ): Promise; - async ecdsaSign(): Promise { - throw new DummyEngineError(); - } - - async ecdsaSignRecoverable( - digestAlgorithm: null, - msg: ByteArray<32>, - counter?: Uint32 - ): Promise; - async ecdsaSignRecoverable( - digestAlgorithm: Digest.AlgorithmName<32>, - msg: Uint8Array, - counter?: Uint32 - ): Promise; - async ecdsaSignRecoverable(): Promise { - throw new DummyEngineError(); - } - - async derive(index: Uint32): Promise { - Uint32.assert(index); - const child = (() => { - const existingChild = this.xpubTree.children.get(index); - if (existingChild) return existingChild; - - if (index >= 0x80000000) throw new DummyEngineError(); - - const serP = Buffer.alloc(37); - serP.set(this.xpubTree.publicKey, 0); - serP.writeUInt32BE(index, 33); - const I = bip32crypto.hmacSHA512(safeBufferFrom(this.xpubTree.chainCode), serP); - const IL = I.slice(0, 32); - const IR = I.slice(32, 64); - const Ki = tinyecc.pointAddScalar(safeBufferFrom(this.xpubTree.publicKey), IL); - if (Ki === null) throw new Error("Ki is null; this should be cryptographically impossible"); - - const newChild = { - version: this.xpubTree.version, - depth: this.xpubTree.depth + 1, - parentFp: this.xpubTree.fingerprint, - childNum: index, - chainCode: checkType(BIP32.ChainCode, IR), - publicKey: checkType(SecP256K1.CompressedPoint, Ki), - fingerprint: new DataView(toArrayBuffer(Digest.Algorithms.hash160(Ki))).getUint32(0), - children: new Map(), - }; - - this.xpubTree.children.set(index, newChild); - return newChild; - })(); - const out = await Node.create(child); - return out as this; - } - - async ecdh(publicKey: SecP256K1.CurvePoint, digestAlgorithm?: Digest.AlgorithmName<32>): Promise>; - async ecdh(): Promise { - throw new DummyEngineError(); - } - - async ecdhRaw(publicKey: SecP256K1.CurvePoint): Promise; - async ecdhRaw(): Promise { - throw new DummyEngineError(); - } -} - -export class Seed implements BIP32.Seed { - readonly xpubTree: ParsedXpubTree; - - protected constructor(xpubTree: ParsedXpubTree) { - this.xpubTree = xpubTree; - } - - static async create(xpubTree: ParsedXpubTree): Promise { - return new Seed(xpubTree); - } - - toMasterKey(): Promise; - toMasterKey(hmacKey: string | Uint8Array): never; - async toMasterKey(hmacKey?: string | Uint8Array): Promise { - if (hmacKey !== undefined) throw new Error("bad hmacKey type"); - - return await Node.create(this.xpubTree); - } -} diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/bip39.ts b/packages/hdwallet-native/src/crypto/isolation/engines/dummy/bip39.ts deleted file mode 100644 index a85b9a0e..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/bip39.ts +++ /dev/null @@ -1,72 +0,0 @@ -import { toArrayBuffer } from "@keepkey/hdwallet-core"; -import * as bs58check from "bs58check"; - -import * as BIP32 from "../../core/bip32"; -import * as BIP39 from "../../core/bip39"; -import * as Digest from "../../core/digest"; -import * as SecP256K1 from "../../core/secp256k1"; -import { checkType } from "../../types"; -import * as BIP32Engine from "./bip32"; -import { ParsedXpubTree } from "./types"; - -export * from "../../core/bip39"; - -export class Mnemonic implements BIP39.Mnemonic { - readonly xpubTree: ParsedXpubTree; - - protected constructor(xpubTree: ParsedXpubTree) { - this.xpubTree = xpubTree; - } - - static async create(xpubList: string): Promise { - const parsedXpubs: ParsedXpubTree[] = xpubList.split(" ").map((xpub) => { - const xpubBuf = bs58check.decode(xpub); - if (xpubBuf.length !== 78) throw new Error("Isolation.Engine.Dummy.BIP39.create - Invalid xpub"); - const xpubView = new DataView(toArrayBuffer(xpubBuf)); - const pk = checkType(SecP256K1.CompressedPoint, xpubBuf.slice(45)); - return { - version: xpubView.getUint32(0), - depth: xpubView.getUint8(4), - parentFp: xpubView.getUint32(5), - childNum: xpubView.getUint32(9), - chainCode: checkType(BIP32.ChainCode, xpubBuf.slice(13, 45)), - publicKey: pk, - fingerprint: new DataView(toArrayBuffer(Digest.Algorithms.hash160(pk))).getUint32(0), - children: new Map(), - }; - }); - - const tree: ParsedXpubTree = (() => { - const rootXpubs = parsedXpubs.filter((x) => x.parentFp === 0x00000000); - if (rootXpubs.length === 0) throw new Error("can't find root xpub"); - if (rootXpubs.length > 1) throw new Error("more than one root xpub"); - return rootXpubs[0]; - })(); - - const xpubsByFp = parsedXpubs - .map((xpub) => { - return [xpub.fingerprint, xpub] as const; - }) - .reduce>((a, [k, v]) => { - if (k in a) throw new Error("key fingerprint collision"); - a[k] = v; - return a; - }, {}); - - for (const xpub of parsedXpubs.filter((x) => x !== tree)) { - if (!(xpub.parentFp in xpubsByFp)) throw new Error("found xpub, but not its parent"); - xpubsByFp[xpub.parentFp].children.set(xpub.childNum, xpub); - } - - return new Mnemonic(tree); - } - - toSeed(): Promise; - toSeed(passphrase: ""): Promise; - toSeed(passphrase: string): never; - async toSeed(passphrase?: string): Promise { - if (passphrase !== undefined && passphrase !== "") throw new Error("bad passphrase type"); - - return await BIP32Engine.Seed.create(this.xpubTree); - } -} diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/index.test.ts b/packages/hdwallet-native/src/crypto/isolation/engines/dummy/index.test.ts deleted file mode 100644 index cd24ef7e..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/index.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import * as Core from "../../core"; -import * as Dummy from "./"; - -describe("Isolation.Engines.Dummy", () => { - let mnemonic: Core.BIP39.Mnemonic; - let seed: Core.BIP32.Seed; - let masterKey: Core.BIP32.Node; - - it("can be loaded with a list of xpubs", async () => { - await expect( - (async () => { - mnemonic = await Dummy.BIP39.Mnemonic.create( - [ - "xpub661MyMwAqRbcFLgDU7wpcEVubSF7NkswwmXBUkDiGUW6uopeUMys4AqKXNgpfZKRTLnpKQgffd6a2c3J8JxLkF1AQN17Pm9QYHEqEfo1Rsx", // all seed root key - "xpub68Zyu13qjcQxDzLNfTYnUXtJuX2qJgnxP6osrcAvJGdo6bs9M2Adt2BunbwiYrZS5qpA1QKoMf3uqS2NHpbyZp4KMJxDrL58NTyvHXBeAv6", // all seed m/44' - "xpub6APRH5kELakva27TFbzpfhfsY3Jd4dRGo7NocHb63qWecSgK2dUkjWaYevJsCunicpdAkPg9fvHAdpSFMDCMCDMit8kiTM1w9QoGmfyVwDo", // all seed m/44'/0' - "xpub6BiVtCpG9fQPxnPmHXG8PhtzQdWC2Su4qWu6XW9tpWFYhxydCLJGrWBJZ5H6qTAHdPQ7pQhtpjiYZVZARo14qHiay2fvrX996oEP42u8wZy", // all seed m/44'/0'/0' - "xpub6APRH5kELakyDsZMmBU9HEoeRUzM9F8STp6ztXLPUJQLiXGrbsfACbngkw5vySPfa9vFs2p3kMsRPxhyDTLhKYEf5HLVfDcDuTTazgzvArk", // all seed m/44'/60' - "xpub6CNFa58kEQJu2hwMVoofpDEKVVSg6gfwqBqE2zHAianaUnQkrJzJJ42iLDp7Dmg2aP88qCKoFZ4jidk3tECdQuF4567NGHDfe7iBRwHxgke", // all seed m/44'/60'/0' - "xpub68Zyu13qjcQxUZiesSWiHJMqkg8G8Guft6MvDhwP72zSYXr9iKnNmDo7LxuSVwtpamrNwGQHkGDWoK8MAp3S9GW5fVxsjBY6AdvZc1hB7kK", // all seed m/49' - "xpub6AA5piovovuKytxa5QtBWAbixSjg7fbmu5gqs6QmvARrUMgewJV51roNH4M7GtvZmjBY1m5oAgAjoHivasewSh4S2H7LAikCyuhJxfHdSsK", // all seed m/49'/0' - "xpub6CVKsQYXc9awxgV1tWbG4foDvdcnieK2JkbpPEBKB5WwAPKBZ1mstLbKVB4ov7QzxzjaxNK6EfmNY5Jsk2cG26EVcEkycGW4tchT2dyUhrx", // all seed m/49'/0'/0' - "xpub68Zyu13qjcQz2DTzkBfLNCfsCTgT39rsUY9JT7MFvG3oEJvS8gUYwRX4RheUTFGZ6EtW4dFYhCdBX32GHJCodkQLAARjNsw4Drj1oDxvo9p", // all seed m/84' - "xpub69s3dQnszuX49hTwhNAQEMJyTcRQNZyhtKAqNgQXApquzXdR3fEjXg75ScXzMMMLkUjQnz2Giwt2L7vesiswkAYwzbHezaUXayU8Z81CW56", // all seed m/84'/0' - "xpub6DDUPHpUo4pcy43iJeZjbSVWGav1SMMmuWdMHiGtkK8rhKmfbomtkwW6GKs1GGAKehT6QRocrmda3WWxXawpjmwaUHfFRXuKrXSapdckEYF", // all seed m/84'/0'/0' - ].join(" ") - ); - })() - ).resolves.not.toThrow(); - expect(mnemonic).toBeDefined(); - }); - - it("produces a seed", async () => { - await expect( - (async () => { - seed = await mnemonic.toSeed(); - })() - ).resolves.not.toThrow(); - expect(seed).toBeDefined(); - }); - - it("produces a master key", async () => { - masterKey = await seed.toMasterKey(); - const pk = await masterKey.getPublicKey(); - expect(Buffer.from(pk).toString("hex")).toEqual( - "03e3b30e8c21923752a408242e069941fedbaef7db7161f7e2c5f3fdafe7e25ddc" - ); - }); - - it.each([ - ["m/44'", "034d600165882b6faf32a3f1f2c4755eeb0f0486954718d46fd9621e8ca40ca6b6"], - ["m/44'/0'", "03dde722d51529c6744d45e1a5e644c6e27520bd8bc7278fbeb1f43094f3dce91a"], - ["m/44'/0'/0'", "03c8166eb40ac84088b618ec07c7cebadacee31c5f5b04a1e8c2a2f3e748eb2cdd"], - ["m/44'/0'/0'/0", "02d3f906cd22167506f94331fc879b1757695c9d9b09fbb1cd6bee9c7ee7019751"], - ["m/44'/0'/0'/0/0", "03c6d9cc725bb7e19c026df03bf693ee1171371a8eaf25f04b7a58f6befabcd38c"], - ["m/44'/0'/0'/0/1", "02c651a011009e2c7e7b3ed2068857ca0a47cba35b73e06c32e3c06ef3aa67621d"], - ["m/44'/0'/0'/0/2", "03330236b68aa6fdcaca0ea72e11b360c84ed19a338509aa527b678a7ec9076882"], - ["m/44'/0'/0'/1", "0377d49f78af126571d0e995656ab0b12cf149a6761bfc3e75132813c7d9c1739f"], - ["m/44'/0'/0'/1/0", "035bc524b005abbf8c3f0c22a452d0b9c2ad43c4609b4b78c745b47f66120bb1a0"], - ["m/44'/0'/0'/1/1", "0203ae8dbf9f9b65f3922a4a855a7c5d7e7700b0f38477b9e047385eed1ba6e18c"], - ["m/44'/0'/0'/1/2", "03389aa9b8d59b776a93a26cf7ee3d9e0ad1b8f0440e778f5270785d12936dad3c"], - ["m/44'/60'", "026efeb8a29b3eedec94c5aca20a84ff4b98d57f9967856a21a64c8d127d863098"], - ["m/44'/60'/0'", "03d92dfaf121b2723d0e6dabb2637b2d9b2b3b2d8026ab901f2df3eea3f6d200c9"], - ["m/44'/60'/0'/0", "0217ebaac6b4c12d3c7e0fc21d8d53d89adf007ff7988840926032c89eb966a37c"], - ["m/44'/60'/0'/0/0", "03ad8e7eb4f3a7d1a409fa7bdc7b79d8840fe746d3fa9ee17fee4f84631ec1430b"], - ["m/49'", "02afb083c2e97455310c8591c6235c9ceb92dc32f4e40d146cd5b550e3bebbc74a"], - ["m/49'/0'", "039051bb3f5af2094a2b4ee31964b8d82b379604926b393b698314e098b6984bd0"], - ["m/49'/0'/0'", "0215a09870bbb713f1ba94d364e1e5bfcf9cdb5178d22efbca6ec17dc2c4f706cd"], - ["m/49'/0'/0'/0", "020ddd7e4206daf889a2c11920fcccbb60df383d4c5fcd982cd5c7d400fdd46c8e"], - ["m/49'/0'/0'/0/0", "02f770feae292b5b3f41d8c81220c2568cb73eb8042def35e648dfe048e4b41b11"], - ["m/49'/0'/0'/0/1", "02dc4843f2fbef594a8c41573ca7a91c968ced334c16c5200cc6a07e8dbba3bdb2"], - ["m/49'/0'/0'/0/2", "03eb2d79f0e0896f523a30d92f395e31c31d0196f2f36d8284145007e68d0563fa"], - ["m/49'/0'/0'/1", "02f7ff3aab4f9fd88190ac153bd0bcb26758a6b3b75480ddda8c0f43147fbbee95"], - ["m/49'/0'/0'/1/0", "03a961687895a78da9aef98eed8e1f2a3e91cfb69d2f3cf11cbd0bb1773d951928"], - ["m/49'/0'/0'/1/1", "03f459101133e88e5953ec0a128c3bc17d5e6e7e8dd035b4dbffad364774f1e710"], - ["m/49'/0'/0'/1/2", "036a7e2f1544eb4ddf1e3df4fedd4c8c0c39b988f3ac99e927f4a00fc5fddfc653"], - ["m/84'", "0225ee2bad1901cea8dca61028fa2c39f9bc6fe6fde7f06405c4cf1131e0ec91ae"], - ["m/84'/0'", "031c9a1c04f0c3b62c013e27ce7a6c7720ac669ee738aa4a6c9112f25d731b6c27"], - ["m/84'/0'/0'", "03e36a4f3fee21bfe83447b209d8de6da1ce1ae38f76bc2c00652dc5e0a8c5c0b5"], - ["m/84'/0'/0'/0", "025982bc036c5321d35d808ab872b2337438b1bb07d5544cf0a20e84327e05897f"], - ["m/84'/0'/0'/0/0", "0396070f2813933502e907c011ae7ba928683a9c2f0e888dae7ebd2c41120ee6b5"], - ["m/84'/0'/0'/0/1", "026b6039331b4d7bb2037fe72411a582e3d1993190731582bf04f18cc4249ea83e"], - ["m/84'/0'/0'/0/2", "03e4a361a06cdf253f7be2b00bb171e30f6f73ec06eb437d9842ec593c5ac0e499"], - ["m/84'/0'/0'/1", "03bc5bf5297765cd1675cd93667500529476502a413310afbfdeb04963e130ea3e"], - ["m/84'/0'/0'/1/0", "032ef68318c8f6aaa0adec0199c69901f0db7d3485eb38d9ad235221dc3d61154b"], - ["m/84'/0'/0'/1/1", "02768afac47832d02e24c39ffcaa9bbd54be67460e38c255d97192cec5e4e25975"], - ["m/84'/0'/0'/1/2", "0245ac2db850ba9a1971741267a1849c72b91722e09cf71c9ff3754ff41f2a0419"], - ])("derives the key at %s", async (path: string, expectedPk: string) => { - const node = await Core.BIP32.derivePath(masterKey, path); - const pk = Buffer.from(await node.getPublicKey()).toString("hex"); - expect(pk).toEqual(expectedPk); - }); -}); diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/index.ts b/packages/hdwallet-native/src/crypto/isolation/engines/dummy/index.ts deleted file mode 100644 index 4ac656ad..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * as BIP32 from "./bip32"; -export * as BIP39 from "./bip39"; -export { DummyEngineError } from "./types"; diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/types.ts b/packages/hdwallet-native/src/crypto/isolation/engines/dummy/types.ts deleted file mode 100644 index 3164004f..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/dummy/types.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { ChainCode } from "../../core/bip32"; -import { CompressedPoint } from "../../core/secp256k1"; - -export class DummyEngineError extends Error { - constructor() { - super("Isolation.Engines.Dummy - Invalid operation: private key not available"); - } -} - -export interface ParsedXpub { - version: number; - depth: number; - parentFp: number; - childNum: number; - chainCode: ChainCode; - publicKey: CompressedPoint; -} - -export type ParsedXpubTree = ParsedXpub & { - fingerprint: number; - children: Map; -}; diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/index.ts b/packages/hdwallet-native/src/crypto/isolation/engines/index.ts deleted file mode 100644 index 12f19188..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/engines/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * as Default from "./default"; -export * as Dummy from "./dummy"; diff --git a/packages/hdwallet-native/src/crypto/isolation/index.ts b/packages/hdwallet-native/src/crypto/isolation/index.ts deleted file mode 100644 index 83c2cad3..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * as Adapters from "./adapters"; -export * as Engines from "./engines"; -export * as Core from "./core"; diff --git a/packages/hdwallet-native/src/crypto/isolation/types.ts b/packages/hdwallet-native/src/crypto/isolation/types.ts deleted file mode 100644 index 7d91f6dd..00000000 --- a/packages/hdwallet-native/src/crypto/isolation/types.ts +++ /dev/null @@ -1,163 +0,0 @@ -import { - InstanceOf, - Literal, - Never, - Number as Num, - Object as Obj, - Runtype, - Static, - String as Str, - Unknown, -} from "funtypes"; - -const positive = Num.withConstraint((x) => x > 0 || `expected ${x} to be positive`, { name: "Positive" }); -export type Positive = Static; -export const Positive: typeof positive = positive; - -const negative = Num.withConstraint((x) => x < 0 || `expected ${x} to be negative`, { name: "Negative" }); -export type Negative = Static; -export const Negative: typeof negative = negative; - -const nonNegative = Num.withConstraint((x) => x >= 0 || `expected ${x} to be non-negative`, { name: "NonNegative" }); -export type NonNegative = Static; -export const NonNegative: typeof nonNegative = nonNegative; - -const nonPositive = Num.withConstraint((x) => x <= 0 || `expected ${x} to be non-positive`, { name: "NonPositive" }); -export type NonPositive = Static; -export const NonPositive: typeof nonPositive = nonPositive; - -export const integer = Num.withConstraint((x) => Number.isSafeInteger(x) || `expected ${x} to be an integer`, { - name: "Integer", -}); -export type Integer = Static; -export const Integer: typeof integer = integer; - -const positiveInteger = Integer.And(Positive); -export type PositiveInteger = Static; -export const PositiveInteger: typeof positiveInteger = positiveInteger; - -const negativeInteger = Integer.And(Negative); -export type NegativeInteger = Static; -export const NegativeInteger: typeof negativeInteger = negativeInteger; - -const nonPositiveInteger = Integer.And(NonPositive); -export type NonPositiveInteger = Static; -export const NonPositiveInteger: typeof nonPositiveInteger = nonPositiveInteger; - -const nonNegativeInteger = Integer.And(NonNegative); -export type NonNegativeInteger = Static; -export const NonNegativeInteger: typeof nonNegativeInteger = nonNegativeInteger; - -const uint = NonNegativeInteger.Or(Never); -export type Uint = Static; -export const Uint: typeof uint = uint; - -const uint32 = Num.withConstraint( - (x) => x === (x & 0xffffffff) >>> 0 || `expected ${x} to be an unsigned 32-bit integer.`, - { name: "Uint32" } -); -export type Uint32 = Static; -export const Uint32: typeof uint32 = uint32; - -const uint16 = Num.withConstraint((x) => x === (x & 0xffff) >>> 0 || `expected ${x} to be an unsigned 16-bit integer`, { - name: "Uint16", -}); -export type Uint16 = Static; -export const Uint16: typeof uint16 = uint16; - -const uint8 = Num.withConstraint((x) => x === (x & 0xff) >>> 0 || `expected ${x} to be an unsigned 8-bit integer`, { - name: "Uint8", -}); -export type Uint8 = Static; -export const Uint8: typeof uint8 = uint8; - -function boundedUintBase(max: T) { - return Object.assign( - Uint.withConstraint((x) => x <= max || `expected ${x} to be less than or equal to ${max}`, { - name: `BoundedUint(${max})`, - }), - { max } - ); -} -export type BoundedUint = Static & { max: T }; -const boundedUintStatic = {}; -const boundedUint = Object.assign(boundedUintBase, boundedUintStatic); -export const BoundedUint: typeof boundedUint = boundedUint; - -function boundedStringBase(regex: T) { - return Object.assign( - Str.withConstraint((x) => regex.test(x) || `expected ${x} to match regex ${regex}`, { - name: `BoundedString(${regex})`, - }), - { regex } - ); -} -export type BoundedString = Static & { regex: T }; -const boundedStringStatic = {}; -const boundedString = Object.assign(boundedStringBase, boundedStringStatic); -export const BoundedString: typeof boundedString = boundedString; - -export function assertType>(rt: T, value: unknown): asserts value is Static { - rt.assert(value); -} - -export function checkType>(rt: T, value: unknown): Static { - assertType(rt, value); - return value; -} - -// export function ParseWorkaround>(rt: U) { -// return Unknown.withParser({ -// test: rt, -// parse(value: any): Result { -// return (rt.test(value) ? {success: true, value} : rt.safeParse(value)); -// }, -// }) as unknown as U -// } - -type Ternary = T extends undefined ? V : unknown extends T ? V : U; -function byteArrayBase(length?: T) { - length === undefined || NonNegativeInteger.assert(length); - const indefinite = InstanceOf(Uint8Array); - const literalConstraint = length !== undefined ? Literal(length) : Unknown; - const definite = InstanceOf(Uint8Array).And( - Obj({ - length: literalConstraint as Literal, - }) - ); - return (length === undefined ? indefinite : definite) as Ternary; -} -export type ByteArray = Uint8Array & - (T extends undefined ? unknown : { length: T }); -const byteArrayStatic = { - equal(lhs: ByteArray, rhs: ByteArray): boolean { - const length = lhs.length; - if (length !== rhs.length) return false; - for (let i = 0; i < length; i++) { - if (lhs[i] !== rhs[i]) return false; - } - return true; - }, -}; -const byteArray = Object.assign(byteArrayBase, byteArrayStatic); -export const ByteArray: typeof byteArray = byteArray; - -function bigEndianIntegerBase(length?: T) { - return ByteArray(length); -} - -export type BigEndianInteger = ByteArray; -const bigEndianIntegerStatic = { - isHigh: (x: BigEndianInteger) => (x[0] & 0x80) !== 0, - isOdd: (x: BigEndianInteger) => (x[x.length - 1] & 1) === 1, -}; -const bigEndianInteger = Object.assign(bigEndianIntegerBase, ByteArray, bigEndianIntegerStatic); -export const BigEndianInteger: typeof bigEndianInteger = bigEndianInteger; - -export function safeBufferFrom( - input: ByteArray -): Buffer & ByteArray { - if (Buffer.isBuffer(input)) return input; - input = checkType(ByteArray(), input) as ByteArray; - return Buffer.alloc(input.byteLength).fill(input) as Buffer & ByteArray; -} diff --git a/packages/hdwallet-native/src/crypto/utils.test.ts b/packages/hdwallet-native/src/crypto/utils.test.ts deleted file mode 100644 index a78d968c..00000000 --- a/packages/hdwallet-native/src/crypto/utils.test.ts +++ /dev/null @@ -1,38 +0,0 @@ -import * as utils from "./utils"; - -describe("util", () => { - describe("fromUtf8ToArray", () => { - it("should convert a string to a Uint8Array", () => { - const result = utils.fromUtf8ToArray("my_Fancy-P$ssw0rd"); - expect(result).toBeInstanceOf(Uint8Array); - expect(result.length).toBe(17); - }); - }); - - describe("fromB64ToArray", () => { - it("should convert a base64 string to an Uint8Array", () => { - const array = new Uint8Array(32).fill(64); - const base64 = Buffer.from(array).toString("base64"); - const result = utils.fromB64ToArray(base64); - expect(result).toBeInstanceOf(Uint8Array); - expect(result.length).toBe(32); - expect(Buffer.from(array).equals(result)).toBe(true); - }); - }); - - describe("fromBufferToB64", () => { - it("should convert an Uint8Array to a base64 string", () => { - const array = new Uint8Array(32).fill(64); - const result = utils.fromBufferToB64(array); - expect(result).toEqual("QEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEA="); - }); - }); - - describe("fromBufferToUtf8", () => { - it("should convert an Uint8Array to a string", () => { - const array = new Uint8Array(16).fill(64); - const result = utils.fromBufferToUtf8(array); - expect(result).toEqual("@@@@@@@@@@@@@@@@"); - }); - }); -}); diff --git a/packages/hdwallet-native/src/crypto/utils.ts b/packages/hdwallet-native/src/crypto/utils.ts deleted file mode 100644 index 1f82bd89..00000000 --- a/packages/hdwallet-native/src/crypto/utils.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { TextDecoder, TextEncoder } from "web-encoding"; - -export function fromUtf8ToArray(str: string): Uint8Array { - return new TextEncoder().encode(str); -} - -export function fromBufferToB64(buffer: ArrayBuffer): string { - return Buffer.from(buffer).toString("base64"); -} - -export function fromBufferToUtf8(buffer: ArrayBuffer): string { - return new TextDecoder().decode(buffer); -} - -export function fromB64ToArray(str: string): Uint8Array { - return Buffer.from(str, "base64"); -} diff --git a/packages/hdwallet-native/src/ethereum.test.ts b/packages/hdwallet-native/src/ethereum.test.ts deleted file mode 100644 index fbb154cc..00000000 --- a/packages/hdwallet-native/src/ethereum.test.ts +++ /dev/null @@ -1,296 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import { parseTransaction } from "ethers/lib/utils.js"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeETHWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - expect(await untouchable.call(info, "ethSupportsNetwork")).toBe(true); - expect(await untouchable.call(info, "ethSupportsSecureTransfer")).toBe(false); - expect(untouchable.call(info, "ethSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.ethGetAccountPaths({ coin: "Ethereum", accountIdx: 0 }); - expect(paths).toMatchObject([ - { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - hardenedPath: core.bip32ToAddressNList("m/44'/60'/0'"), - relPath: [0, 0], - description: "Native", - }, - ]); - }); - - it("should return the correct account paths for other coin", async () => { - const avalanchePaths = info.ethGetAccountPaths({ coin: "Avalanche", accountIdx: 0 }); - expect(avalanchePaths).toMatchObject([ - { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - hardenedPath: core.bip32ToAddressNList("m/44'/60'/0'"), - relPath: [0, 0], - description: "Native", - }, - ]); - const optimismPaths = info.ethGetAccountPaths({ coin: "Optimism", accountIdx: 0 }); - expect(optimismPaths).toMatchObject([ - { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - hardenedPath: core.bip32ToAddressNList("m/44'/60'/0'"), - relPath: [0, 0], - description: "Native", - }, - ]); - const bscPaths = info.ethGetAccountPaths({ coin: "BnbSmartChain", accountIdx: 0 }); - expect(bscPaths).toMatchObject([ - { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - hardenedPath: core.bip32ToAddressNList("m/44'/60'/0'"), - relPath: [0, 0], - description: "Native", - }, - ]); - const polygonPaths = info.ethGetAccountPaths({ coin: "Polygon", accountIdx: 0 }); - expect(polygonPaths).toMatchObject([ - { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - hardenedPath: core.bip32ToAddressNList("m/44'/60'/0'"), - relPath: [0, 0], - description: "Native", - }, - ]); - const gnosisPaths = info.ethGetAccountPaths({ coin: "Gnosis", accountIdx: 0 }); - expect(gnosisPaths).toMatchObject([ - { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - hardenedPath: core.bip32ToAddressNList("m/44'/60'/0'"), - relPath: [0, 0], - description: "Native", - }, - ]); - const arbitrumPaths = info.ethGetAccountPaths({ coin: "Arbitrum", accountIdx: 0 }); - expect(arbitrumPaths).toMatchObject([ - { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - hardenedPath: core.bip32ToAddressNList("m/44'/60'/0'"), - relPath: [0, 0], - description: "Native", - }, - ]); - const arbitrumNovaPaths = info.ethGetAccountPaths({ coin: "ArbitrumNova", accountIdx: 0 }); - expect(arbitrumNovaPaths).toMatchObject([ - { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - hardenedPath: core.bip32ToAddressNList("m/44'/60'/0'"), - relPath: [0, 0], - description: "Native", - }, - ]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "ethNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeETHWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - }); - - it("should generate a correct ethereum address", async () => { - expect(await wallet.ethGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0") })).toBe( - "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8" - ); - }); - - it("should generate another correct ethereum address at account 1", async () => { - expect(await wallet.ethGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/60'/1'/0/0") })).toBe( - "0xeDe5D356020A0aA3DC3fCAf0d899b5c63d7eA4aa" - ); - }); - - it("should sign a legacy transaction correctly", async () => { - const sig = await wallet.ethSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - nonce: "0xDEADBEEF", - gasPrice: "0xDEADBEEF", - gasLimit: "0xDEADBEEF", - to: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF", - value: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF", - data: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF", - chainId: 1, - }); - // This is the output from tiny-secp256k1. - expect(sig).toMatchInlineSnapshot(` - Object { - "r": "0x7f21bb5a857db55c888355b2e48325062268ad62686fba56a4e57118f5783dda", - "s": "0x3e9893ed500842506a19288eb022b5f5b3cee6d1bbf6330f4304f60f8166f82a", - "serialized": "0xf88984deadbeef84deadbeef84deadbeef94deadbeefdeadbeefdeadbeefdeadbeefdeadbeef90deadbeefdeadbeefdeadbeefdeadbeef90deadbeefdeadbeefdeadbeefdeadbeef26a07f21bb5a857db55c888355b2e48325062268ad62686fba56a4e57118f5783ddaa03e9893ed500842506a19288eb022b5f5b3cee6d1bbf6330f4304f60f8166f82a", - "v": 38, - } - `); - // This is the output of the native library's own signing function. - /*expect(sig).toMatchInlineSnapshot(` - Object { - "r": "0xec482d7dfc3bfaf395b72dd1de692ab57c24134fb0bea39e986b16a4ad422d2f", - "s": "0x505506a0fb590d7ef63c24e9ae684eef608a6f48914d7cce762164d8c0a6fb29", - "serialized": "0xf88984deadbeef84deadbeef84deadbeef94deadbeefdeadbeefdeadbeefdeadbeefdeadbeef90deadbeefdeadbeefdeadbeefdeadbeef90deadbeefdeadbeefdeadbeefdeadbeef26a0ec482d7dfc3bfaf395b72dd1de692ab57c24134fb0bea39e986b16a4ad422d2fa0505506a0fb590d7ef63c24e9ae684eef608a6f48914d7cce762164d8c0a6fb29", - "v": 38, - } - `);*/ - expect(parseTransaction(sig!.serialized).from).toEqual("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"); - }); - - it("should sign a EIP-1559 transaction correctly", async () => { - const sig = await wallet.ethSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - nonce: "0xCAFEDEAD", - gasLimit: "0xCAFEDEAD", - maxFeePerGas: "0xCAFEDEAD", - maxPriorityFeePerGas: "0xCAFEDEAD", - to: "0xCAFEDEADCAFEDEADCAFEDEADCAFEDEADCAFEDEAD", - value: "0xCAFEDEADCAFEDEADCAFEDEADCAFEDEAD", - data: "0xCAFEDEADCAFEDEADCAFEDEADCAFEDEAD", - chainId: 1, - }); - console.debug("SIG: ", sig); - // This is the output from tiny-secp256k1. - expect(sig).toMatchInlineSnapshot(` - Object { - "r": "0x7a2efa71aa876ede546fdfa83054050b6249a8076297451b2a711e6b0f460234", - "s": "0x1880e95e79fed382b85077de63d83e787158c8a89839c786465139952cb04a74", - "serialized": "0x02f8900184cafedead84cafedead84cafedead84cafedead94cafedeadcafedeadcafedeadcafedeadcafedead90cafedeadcafedeadcafedeadcafedead90cafedeadcafedeadcafedeadcafedeadc080a07a2efa71aa876ede546fdfa83054050b6249a8076297451b2a711e6b0f460234a01880e95e79fed382b85077de63d83e787158c8a89839c786465139952cb04a74", - "v": 0, - } - `); - // This is the output of the native library's own signing function. - /*expect(sig).toMatchInlineSnapshot(` - Object { - "r": "0xec482d7dfc3bfaf395b72dd1de692ab57c24134fb0bea39e986b16a4ad422d2f", - "s": "0x505506a0fb590d7ef63c24e9ae684eef608a6f48914d7cce762164d8c0a6fb29", - "serialized": "0xf88984deadbeef84deadbeef84deadbeef94deadbeefdeadbeefdeadbeefdeadbeefdeadbeef90deadbeefdeadbeefdeadbeefdeadbeef90deadbeefdeadbeefdeadbeefdeadbeef26a0ec482d7dfc3bfaf395b72dd1de692ab57c24134fb0bea39e986b16a4ad422d2fa0505506a0fb590d7ef63c24e9ae684eef608a6f48914d7cce762164d8c0a6fb29", - "v": 38, - } - `);*/ - expect(parseTransaction(sig!.serialized).from).toEqual("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"); - }); - - describe("sign and verify message", () => { - it("should handle a utf8 message", async () => { - const message = "0x737570657220736563726574206d657373616765"; // super secret message - const result = await wallet.ethSignMessage({ - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - message, - }); - if (!result) throw new Error("failed to sign message"); - expect(result).toEqual({ - address: "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", - signature: - "0x05f51140905ffa33ffdc57f46b0b8d8fbb1d2a99f8cd843ca27893c01c31351c08b76d83dce412731c846e3b50649724415deb522d00950fbf4f2c1459c2b70b1b", - }); - const { address, signature } = result; - const valid = await wallet.ethVerifyMessage({ address, message, signature }); - expect(valid).toEqual(true); - }); - - it("should handle a hex encoded utf8 message", async () => { - const message = "0x737570657220736563726574206d657373616765"; - const result = await wallet.ethSignMessage({ - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - message, - }); - if (!result) throw new Error("failed to sign message"); - expect(result).toEqual({ - address: "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", - signature: - "0x05f51140905ffa33ffdc57f46b0b8d8fbb1d2a99f8cd843ca27893c01c31351c08b76d83dce412731c846e3b50649724415deb522d00950fbf4f2c1459c2b70b1b", - }); - const { address, signature } = result; - const valid = await wallet.ethVerifyMessage({ address, message, signature }); - expect(valid).toEqual(true); - }); - - it("should handle a keccak256 encoded message", async () => { - const message = "0x55d6a11839e2105c96a87f358961004575bae1fe5acd80e26a5eb7e361b20903"; - const result = await wallet.ethSignMessage({ - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - message, - }); - if (!result) throw new Error("failed to sign message"); - expect(result).toEqual({ - address: "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", - signature: - "0x4b4d22773b4a761a2f4cbafb3054830dd1ebaffdc166b4736cf98f1d3dbb0abe31590d32797f55a9b9e77bc46b262dde59eca27c866ad9bb4d83f488d8f208b61c", - }); - const { address, signature } = result; - const valid = await wallet.ethVerifyMessage({ address, message, signature }); - expect(valid).toEqual(true); - }); - - it("should handle a byte message", async () => { - const message = "0xcf8746d5aa75ecfd907eb3cae0aecf7f698a8bfe1f97eb2d77d6539e8991b0ea"; - const result = await wallet.ethSignMessage({ - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - message, - }); - if (!result) throw new Error("failed to sign message"); - expect(result).toEqual({ - address: "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", - signature: - "0x3509a531d2e47f2b6a796d69b91568ad9ad2276f4d17399660192ef8cd6580db70dc16b6941f5ba97be926f3717a71c001778da68f9c9771375beb3f3aaa8eb31b", - }); - const { address, signature } = result; - const valid = await wallet.ethVerifyMessage({ address, message, signature }); - expect(valid).toEqual(true); - }); - - it("should pass verification of a message signed with a different format", async () => { - const message = "0x737570657220736563726574206d657373616765"; // super secret message - expect( - await wallet.ethVerifyMessage({ - address: "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", - message, - signature: - "0x72d4baca0c1ca0eea587decb0177ded99fb50f62c4bd24d8595000d70e6383833eb0700fb6c96086154c2607b735ee1047ed4060211b32a52b43d827615b3e691c", - }) - ).toBe(true); - }); - - it("should fail verification of a mismatched message and signature", async () => { - expect( - await wallet.ethVerifyMessage({ - address: "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", - message: "super public message", - signature: - "0xd67ad52016d6fbc19fb9db81f32dd22cb67570b93b1c0e64ae30a4c2bc0b9c265c2d0f86906610d0cecac42ab90ee298a3474a5eb6d895aa7279d344f32aab191b", - }) - ).toBe(false); - }); - - it("should fail verification if the signature is invalid", async () => { - const message = "0x737570657220736563726574206d657373616765"; // super secret message - expect( - await wallet.ethVerifyMessage({ - address: "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", - message, - signature: - "deadbeef16d6fbc19fb9db81f32dd22cb67570b93b1c0e64ae30a4c2bc0b9c265c2d0f86906610d0cecac42ab90ee298a3474a5eb6d895aa7279d344f32aab191b", - }) - ).toBe(false); - }); - }); -}); diff --git a/packages/hdwallet-native/src/ethereum.ts b/packages/hdwallet-native/src/ethereum.ts deleted file mode 100644 index 649bda7c..00000000 --- a/packages/hdwallet-native/src/ethereum.ts +++ /dev/null @@ -1,149 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import { keccak256, parseTransaction, recoverAddress } from "ethers/lib/utils.js"; - -import * as Isolation from "./crypto/isolation"; -import SignerAdapter from "./crypto/isolation/adapters/ethereum"; -import { NativeHDWalletBase } from "./native"; -import { buildMessage } from "./util"; - -export function MixinNativeETHWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeETHWalletInfo extends Base implements core.ETHWalletInfo { - readonly _supportsETHInfo = true; - _chainId = 1; - - async ethSupportsNetwork(): Promise { - return true; - } - - async ethSupportsSecureTransfer(): Promise { - return false; - } - - ethSupportsNativeShapeShift(): boolean { - return false; - } - - async ethSupportsEIP1559(): Promise { - return true; - } - - ethGetAccountPaths(msg: core.ETHGetAccountPath): Array { - const slip44 = core.slip44ByCoin(msg.coin); - if (slip44 === undefined) return []; - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - hardenedPath: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx], - relPath: [0, 0], - description: "Native", - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - ethNextAccountPath(msg: core.ETHAccountPath): core.ETHAccountPath | undefined { - // Only support one account for now. - // the ethers library supports paths so it shouldnt be too hard if we decide multiple accounts are needed - return undefined; - } - }; -} - -export function MixinNativeETHWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeETHWallet extends Base { - readonly _supportsETH = true; - - #ethSigner: SignerAdapter | undefined; - - async ethInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - const nodeAdapter = await Isolation.Adapters.BIP32.create(masterKey); - - this.#ethSigner = new SignerAdapter(nodeAdapter); - } - - ethWipe() { - this.#ethSigner = undefined; - } - - async ethGetAddress(msg: core.ETHGetAddress): Promise { - if (msg.addressNList.length < 5) { - throw new Error(`path not supported length: ${msg.addressNList.length}`); - } - - return this.needsMnemonic(!!this.#ethSigner, () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return this.#ethSigner!.getAddress(msg.addressNList); - }); - } - - async ethSignTx(msg: core.ETHSignTx): Promise { - return this.needsMnemonic(!!this.#ethSigner, async () => { - const utx = { - to: msg.to, - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - from: await this.#ethSigner!.getAddress(msg.addressNList), - nonce: msg.nonce, - gasLimit: msg.gasLimit, - data: msg.data, - value: msg.value, - chainId: msg.chainId, - }; - const result: string = msg.maxFeePerGas - ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await this.#ethSigner!.signTransaction( - { - ...utx, - maxFeePerGas: msg.maxFeePerGas, - maxPriorityFeePerGas: msg.maxPriorityFeePerGas, - type: core.ETHTransactionType.ETH_TX_TYPE_EIP_1559, - }, - msg.addressNList - ) - : // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - await this.#ethSigner!.signTransaction( - { - ...utx, - gasPrice: msg.gasPrice, - type: core.ETHTransactionType.ETH_TX_TYPE_LEGACY, - }, - msg.addressNList - ); - - const decoded = parseTransaction(result); - return { - v: core.mustBeDefined(decoded.v), - r: core.mustBeDefined(decoded.r), - s: core.mustBeDefined(decoded.s), - serialized: result, - }; - }); - } - - async ethSignMessage(msg: core.ETHSignMessage): Promise { - return this.needsMnemonic(!!this.#ethSigner, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const result = await this.#ethSigner!.signMessage(msg.message, msg.addressNList); - return { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - address: await this.#ethSigner!.getAddress(msg.addressNList), - signature: result, - }; - }); - } - - async ethSignTypedData(msg: core.ETHSignTypedData): Promise { - return this.needsMnemonic(!!this.#ethSigner, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - return await this.#ethSigner!.signTypedData(msg.typedData, msg.addressNList); - }); - } - - async ethVerifyMessage({ address, message, signature }: core.ETHVerifyMessage): Promise { - if (!signature.startsWith("0x")) signature = `0x${signature}`; - const digest = keccak256(buildMessage(message)); - return recoverAddress(digest, signature) === address; - } - }; -} diff --git a/packages/hdwallet-native/src/fio.test.ts b/packages/hdwallet-native/src/fio.test.ts deleted file mode 100644 index 87d0cc53..00000000 --- a/packages/hdwallet-native/src/fio.test.ts +++ /dev/null @@ -1,281 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as fio from "@shapeshiftoss/fiosdk"; -import * as bs58 from "bs58"; -import * as tinyecc from "tiny-secp256k1"; - -import * as Isolation from "./crypto/isolation"; -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")({ - get: { - "https://fio.eu.eosamsterdam.net/v1/chain/get_info": { - server_version: "0b30e123", - chain_id: "21dcae42c0182200e93f954a074011f9048a7624c6fe81d3c9541a614a88bd1c", - head_block_num: 61842307, - last_irreversible_block_num: 61841978, - last_irreversible_block_id: "03afa23a114cfee7ef1c7ca90e270422fe37396080738ece42391d9ef31440e8", - head_block_id: "03afa38300f285879d00fe0f2f659f7a4b09d134dcd678ad12fc788dccf67952", - head_block_time: "2021-03-18T00:05:14.000", - head_block_producer: "aloha3joooqd", - virtual_block_cpu_limit: 200000000, - virtual_block_net_limit: 1048576000, - block_cpu_limit: 199900, - block_net_limit: 1048576, - server_version_string: "v2.0.0", - fork_db_head_block_num: 61842307, - fork_db_head_block_id: "03afa38300f285879d00fe0f2f659f7a4b09d134dcd678ad12fc788dccf67952", - }, - }, - post: { - "https://fio.eu.eosamsterdam.net/v1/chain/get_block": { - timestamp: "2021-03-18T00:02:29.500", - producer: "sweidrpkehv2", - confirmed: 0, - previous: "03afa2397459431ac5325ceefccfc17168d96efa07198221a48dc7339e4cc265", - transaction_mroot: "0000000000000000000000000000000000000000000000000000000000000000", - action_mroot: "5ceb022b440279ec9943e07564aadfa82a3fadfccc9531510ae60c8d6e035d4e", - schedule_version: 73, - new_producers: null, - header_extensions: [], - producer_signature: - "SIG_K1_KAJ9KUhQ94GWqPGmZ13rzHYbaR7kB3f4xaK73G24EEU82fMjboJTtBxZWk65Qdcy3iQimgeJ6bUWaSsU7kmmMMMFwb2fmR", - transactions: [], - block_extensions: [], - id: "03afa23a114cfee7ef1c7ca90e270422fe37396080738ece42391d9ef31440e8", - block_num: 61841978, - ref_block_prefix: 2843483375, - }, - "https://fio.eu.eosamsterdam.net/v1/chain/get_pub_address": (body: any) => { - body = JSON.stringify(body); - switch (body) { - case '{"fio_address":"highlander@scatter","chain_code":"FIO","token_code":"FIO"}': - return { - public_address: "FIO6Lxx7BTA8zbgPuqn4QidNNdTCHisXU7RpxJxLwxAka7NV7SoBW", - }; - case '{"fio_address":"test@shapeshift","chain_code":"FIO","token_code":"FIO"}': - return { - public_address: "FIO6iLE1J4zb2SyDGTH9d6UL9Qm6hhqRce27QvP8AKxVLASGhtm7z", - }; - default: - throw new Error(`unrecognized get_pub_address call: ${body}`); - } - }, - "https://fio.eu.eosamsterdam.net/v1/chain/get_raw_abi": (body: any) => { - body = JSON.stringify(body); - switch (body) { - case '{"account_name":"fio.address"}': - return { - account_name: "fio.address", - code_hash: "183b0410eb9d6071ca741a94da36502eab4d808ac60a6432cae1329ca86c2a64", - abi_hash: "0dca0ca50be70bb04a84c2494e3eecdf72c083498a3acdbe0ed7ebc4a89d8ad9", - abi: "DmVvc2lvOjphYmkvMS4wABMHZmlvbmFtZQAJAmlkBnVpbnQ2NARuYW1lBnN0cmluZwhuYW1laGFzaAd1aW50MTI4BmRvbWFpbgZzdHJpbmcKZG9tYWluaGFzaAd1aW50MTI4CmV4cGlyYXRpb24GdWludDY0DW93bmVyX2FjY291bnQEbmFtZQlhZGRyZXNzZXMOdG9rZW5wdWJhZGRyW10XYnVuZGxlZWxpZ2libGVjb3VudGRvd24GdWludDY0BmRvbWFpbgAGAmlkBnVpbnQ2NARuYW1lBnN0cmluZwpkb21haW5oYXNoB3VpbnQxMjgHYWNjb3VudARuYW1lCWlzX3B1YmxpYwV1aW50OApleHBpcmF0aW9uBnVpbnQ2NAplb3Npb19uYW1lAAMHYWNjb3VudARuYW1lCWNsaWVudGtleQZzdHJpbmcHa2V5aGFzaAd1aW50MTI4CnJlZ2FkZHJlc3MABQtmaW9fYWRkcmVzcwZzdHJpbmcUb3duZXJfZmlvX3B1YmxpY19rZXkGc3RyaW5nB21heF9mZWUFaW50NjQFYWN0b3IEbmFtZQR0cGlkBnN0cmluZwx0b2tlbnB1YmFkZHIAAwp0b2tlbl9jb2RlBnN0cmluZwpjaGFpbl9jb2RlBnN0cmluZw5wdWJsaWNfYWRkcmVzcwZzdHJpbmcKYWRkYWRkcmVzcwAFC2Zpb19hZGRyZXNzBnN0cmluZxBwdWJsaWNfYWRkcmVzc2VzDnRva2VucHViYWRkcltdB21heF9mZWUFaW50NjQFYWN0b3IEbmFtZQR0cGlkBnN0cmluZwpyZW1hZGRyZXNzAAULZmlvX2FkZHJlc3MGc3RyaW5nEHB1YmxpY19hZGRyZXNzZXMOdG9rZW5wdWJhZGRyW10HbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lBHRwaWQGc3RyaW5nCnJlbWFsbGFkZHIABAtmaW9fYWRkcmVzcwZzdHJpbmcHbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lBHRwaWQGc3RyaW5nCXJlZ2RvbWFpbgAFCmZpb19kb21haW4Gc3RyaW5nFG93bmVyX2Zpb19wdWJsaWNfa2V5BnN0cmluZwdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUEdHBpZAZzdHJpbmcLcmVuZXdkb21haW4ABApmaW9fZG9tYWluBnN0cmluZwdtYXhfZmVlBWludDY0BHRwaWQGc3RyaW5nBWFjdG9yBG5hbWUMcmVuZXdhZGRyZXNzAAQLZmlvX2FkZHJlc3MGc3RyaW5nB21heF9mZWUFaW50NjQEdHBpZAZzdHJpbmcFYWN0b3IEbmFtZQxzZXRkb21haW5wdWIABQpmaW9fZG9tYWluBnN0cmluZwlpc19wdWJsaWMEaW50OAdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUEdHBpZAZzdHJpbmcLYnVybmV4cGlyZWQAAAtkZWNyY291bnRlcgACC2Zpb19hZGRyZXNzBnN0cmluZwRzdGVwBWludDMyCmJpbmQyZW9zaW8AAwdhY2NvdW50BG5hbWUKY2xpZW50X2tleQZzdHJpbmcIZXhpc3RpbmcEYm9vbAtidXJuYWRkcmVzcwAEC2Zpb19hZGRyZXNzBnN0cmluZwdtYXhfZmVlBWludDY0BHRwaWQGc3RyaW5nBWFjdG9yBG5hbWUKeGZlcmRvbWFpbgAFCmZpb19kb21haW4Gc3RyaW5nGG5ld19vd25lcl9maW9fcHVibGljX2tleQZzdHJpbmcHbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lBHRwaWQGc3RyaW5nC3hmZXJhZGRyZXNzAAULZmlvX2FkZHJlc3MGc3RyaW5nGG5ld19vd25lcl9maW9fcHVibGljX2tleQZzdHJpbmcHbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lBHRwaWQGc3RyaW5nCmFkZGJ1bmRsZXMABQtmaW9fYWRkcmVzcwZzdHJpbmcLYnVuZGxlX3NldHMFaW50NjQHbWF4X2ZlZQVpbnQ2NAR0cGlkBnN0cmluZwVhY3RvcgRuYW1lDwCuylNTdJFKC2RlY3Jjb3VudGVyAAAAxuqmZJi6CnJlZ2FkZHJlc3MAAADG6qZkUjIKYWRkYWRkcmVzcwAAAMbqpmSkugpyZW1hZGRyZXNzAADATcnEaKS6CnJlbWFsbGFkZHIAAACYzkiamLoJcmVnZG9tYWluAACmM5Imrqa6C3JlbmV3ZG9tYWluAICxuikZrqa6DHJlbmV3YWRkcmVzcwAAkrqudjWvPgtidXJuZXhwaXJlZABwdJ3OSJqywgxzZXRkb21haW5wdWIAAAB1mCqRpjsKYmluZDJlb3NpbwAAMFY3JTOvPgtidXJuYWRkcmVzcwAAwHRG0nTV6gp4ZmVyZG9tYWluAAAwVjclc9XqC3hmZXJhZGRyZXNzAAAAVjFNfVIyCmFkZGJ1bmRsZXMAAwAAAFhJM6lbA2k2NAECaWQBBnN0cmluZwdmaW9uYW1lAAAAAE9nJE0DaTY0AQJpZAEGc3RyaW5nBmRvbWFpbgBANTJPTREyA2k2NAEHYWNjb3VudAEGdWludDY0CmVvc2lvX25hbWUAAAAA=", - }; - case '{"account_name":"fio.fee"}': - return { - account_name: "fio.fee", - code_hash: "564c5023ddd4916517fad8cf0fda502a1a8cd64af32f8a4a4c45b6d6ee60cda4", - abi_hash: "63370fe617c23b9ffd714cf33ec3e67cfc4695dfcc9830c6aff8dbd9a6b3c56f", - abi: "DmVvc2lvOjphYmkvMS4wAA4JY3JlYXRlZmVlAAMJZW5kX3BvaW50BnN0cmluZwR0eXBlBWludDY0CnN1Zl9hbW91bnQFaW50NjQIZmVldmFsdWUAAgllbmRfcG9pbnQGc3RyaW5nBXZhbHVlBWludDY0C2ZlZXZhbHVlX3RzAAMJZW5kX3BvaW50BnN0cmluZwV2YWx1ZQVpbnQ2NAl0aW1lc3RhbXAGdWludDY0CnNldGZlZXZvdGUAAwpmZWVfcmF0aW9zCmZlZXZhbHVlW10HbWF4X2ZlZQVpbnQ2NAVhY3RvcgRuYW1lCmJ1bmRsZXZvdGUAAxRidW5kbGVkX3RyYW5zYWN0aW9ucwVpbnQ2NAdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUKc2V0ZmVlbXVsdAADCm11bHRpcGxpZXIHZmxvYXQ2NAdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUMbWFuZGF0b3J5ZmVlAAMJZW5kX3BvaW50BnN0cmluZwdhY2NvdW50BG5hbWUHbWF4X2ZlZQVpbnQ2NAtieXRlbWFuZGZlZQAECWVuZF9wb2ludAZzdHJpbmcHYWNjb3VudARuYW1lB21heF9mZWUFaW50NjQIYnl0ZXNpemUFaW50NjQLY29tcHV0ZWZlZXMAAAZmaW9mZWUABgZmZWVfaWQGdWludDY0CWVuZF9wb2ludAZzdHJpbmcOZW5kX3BvaW50X2hhc2gHdWludDEyOAR0eXBlBnVpbnQ2NApzdWZfYW1vdW50BnVpbnQ2NA12b3Rlc19wZW5kaW5nBWJvb2wkCGZlZXZvdGVyAAMTYmxvY2tfcHJvZHVjZXJfbmFtZQRuYW1lDmZlZV9tdWx0aXBsaWVyB2Zsb2F0NjQRbGFzdHZvdGV0aW1lc3RhbXAGdWludDY0B2ZlZXZvdGUABgJpZAZ1aW50NjQTYmxvY2tfcHJvZHVjZXJfbmFtZQRuYW1lCWVuZF9wb2ludAZzdHJpbmcOZW5kX3BvaW50X2hhc2gHdWludDEyOApzdWZfYW1vdW50BnVpbnQ2NBFsYXN0dm90ZXRpbWVzdGFtcAZ1aW50NjQIZmVldm90ZTIABAJpZAZ1aW50NjQTYmxvY2tfcHJvZHVjZXJfbmFtZQRuYW1lCGZlZXZvdGVzDWZlZXZhbHVlX3RzW10RbGFzdHZvdGV0aW1lc3RhbXAGdWludDY0C2J1bmRsZXZvdGVyAAMTYmxvY2tfcHJvZHVjZXJfbmFtZQRuYW1lEmJ1bmRsZWRidm90ZW51bWJlcgZ1aW50NjQRbGFzdHZvdGV0aW1lc3RhbXAGdWludDY0BwAAUGqpbNRFCWNyZWF0ZWZlZQAAgMp0K7WywgpzZXRmZWV2b3RlAACAynSrmKY+CmJ1bmRsZXZvdGUAAECOWiq1ssIKc2V0ZmVlbXVsdACg1PKXZpOmkQxtYW5kYXRvcnlmZWUAAJRaaRqpsj8LYnl0ZW1hbmRmZWUAALBSS2VdJUULY29tcHV0ZWZlZXMABYCvynSrmKY+A2k2NAETYmxvY2tfcHJvZHVjZXJfbmFtZQEGdWludDY0C2J1bmRsZXZvdGVyAAAAACu1qFsDaTY0AQZmZWVfaWQBBnVpbnQ2NAZmaW9mZWUAAMBXZbqVWgNpNjQBE2Jsb2NrX3Byb2R1Y2VyX25hbWUBBnVpbnQ2NAhmZWV2b3RlcgAAAFhlupVaA2k2NAETYmxvY2tfcHJvZHVjZXJfbmFtZQEGdWludDY0B2ZlZXZvdGUAABBYZbqVWgNpNjQBE2Jsb2NrX3Byb2R1Y2VyX25hbWUBBnVpbnQ2NAhmZWV2b3RlMgAAAAA==", - }; - case '{"account_name":"fio.reqobt"}': - return { - account_name: "fio.reqobt", - code_hash: "cd54f179eb5913984af88cc589ec527396041bd63e2094ffb143c483e2f0c1da", - abi_hash: "93118de6229f77f4213dc948674c4e11d462f573db821204224a73628b942ffd", - abi: "DmVvc2lvOjphYmkvMS4wAAoKZmlvcmVxY3R4dAANDmZpb19yZXF1ZXN0X2lkBnVpbnQ2NBFwYXllcl9maW9fYWRkcmVzcwd1aW50MTI4EXBheWVlX2Zpb19hZGRyZXNzB3VpbnQxMjgZcGF5ZXJfZmlvX2FkZHJlc3NfaGV4X3N0cgZzdHJpbmcZcGF5ZWVfZmlvX2FkZHJlc3NfaGV4X3N0cgZzdHJpbmcbcGF5ZXJfZmlvX2FkZHJlc3Nfd2l0aF90aW1lB3VpbnQxMjgbcGF5ZWVfZmlvX2FkZHJlc3Nfd2l0aF90aW1lB3VpbnQxMjgHY29udGVudAZzdHJpbmcKdGltZV9zdGFtcAZ1aW50NjQOcGF5ZXJfZmlvX2FkZHIGc3RyaW5nDnBheWVlX2Zpb19hZGRyBnN0cmluZwlwYXllcl9rZXkGc3RyaW5nCXBheWVlX2tleQZzdHJpbmcOcmVjb3Jkb2J0X2luZm8ADQJpZAZ1aW50NjQRcGF5ZXJfZmlvX2FkZHJlc3MHdWludDEyOBFwYXllZV9maW9fYWRkcmVzcwd1aW50MTI4GXBheWVyX2Zpb19hZGRyZXNzX2hleF9zdHIGc3RyaW5nGXBheWVlX2Zpb19hZGRyZXNzX2hleF9zdHIGc3RyaW5nG3BheWVyX2Zpb19hZGRyZXNzX3dpdGhfdGltZQd1aW50MTI4G3BheWVlX2Zpb19hZGRyZXNzX3dpdGhfdGltZQd1aW50MTI4B2NvbnRlbnQGc3RyaW5nCnRpbWVfc3RhbXAGdWludDY0DnBheWVyX2Zpb19hZGRyBnN0cmluZw5wYXllZV9maW9fYWRkcgZzdHJpbmcJcGF5ZXJfa2V5BnN0cmluZwlwYXllZV9rZXkGc3RyaW5nCWZpb3JlcXN0cwAFAmlkBnVpbnQ2NA5maW9fcmVxdWVzdF9pZAZ1aW50NjQGc3RhdHVzBnVpbnQ2NAhtZXRhZGF0YQZzdHJpbmcKdGltZV9zdGFtcAZ1aW50NjQMZmlvdHJ4dF9pbmZvAA8CaWQGdWludDY0DmZpb19yZXF1ZXN0X2lkBnVpbnQ2NBJwYXllcl9maW9fYWRkcl9oZXgHdWludDEyOBJwYXllZV9maW9fYWRkcl9oZXgHdWludDEyOA1maW9fZGF0YV90eXBlBXVpbnQ4CHJlcV90aW1lBnVpbnQ2NA5wYXllcl9maW9fYWRkcgZzdHJpbmcOcGF5ZWVfZmlvX2FkZHIGc3RyaW5nCXBheWVyX2tleQZzdHJpbmcJcGF5ZWVfa2V5BnN0cmluZw1wYXllcl9hY2NvdW50BG5hbWUNcGF5ZWVfYWNjb3VudARuYW1lC3JlcV9jb250ZW50BnN0cmluZwtvYnRfY29udGVudAZzdHJpbmcIb2J0X3RpbWUGdWludDY0Cm1pZ3JsZWRnZXIABwJpZAZ1aW50NjQIYmVnaW5vYnQFaW50NjQKY3VycmVudG9idAVpbnQ2NAdiZWdpbnJxBWludDY0CWN1cnJlbnRycQVpbnQ2NApjdXJyZW50c3RhBWludDY0CmlzRmluaXNoZWQEaW50OAdtaWdydHJ4AAIGYW1vdW50BWludDE2BWFjdG9yBnN0cmluZwlyZWNvcmRvYnQABw5maW9fcmVxdWVzdF9pZAZzdHJpbmcRcGF5ZXJfZmlvX2FkZHJlc3MGc3RyaW5nEXBheWVlX2Zpb19hZGRyZXNzBnN0cmluZwdjb250ZW50BnN0cmluZwdtYXhfZmVlBWludDY0BWFjdG9yBnN0cmluZwR0cGlkBnN0cmluZwtuZXdmdW5kc3JlcQAGEXBheWVyX2Zpb19hZGRyZXNzBnN0cmluZxFwYXllZV9maW9fYWRkcmVzcwZzdHJpbmcHY29udGVudAZzdHJpbmcHbWF4X2ZlZQVpbnQ2NAVhY3RvcgZzdHJpbmcEdHBpZAZzdHJpbmcMcmVqZWN0Zm5kcmVxAAQOZmlvX3JlcXVlc3RfaWQGc3RyaW5nB21heF9mZWUFaW50NjQFYWN0b3IGc3RyaW5nBHRwaWQGc3RyaW5nDGNhbmNlbGZuZHJlcQAEDmZpb19yZXF1ZXN0X2lkBnN0cmluZwdtYXhfZmVlBWludDY0BWFjdG9yBnN0cmluZwR0cGlkBnN0cmluZwUAAACg33yZkwdtaWdydHJ4AAAAyIemS5G6CXJlY29yZG9idAAArLo4Tb24mgtuZXdmdW5kc3JlcQBg1U1zZaSeugxyZWplY3RmbmRyZXEAYNVNc0WFpkEMY2FuY2VsZm5kcmVxAAUAcO4ZWXWpWwNpNjQBDmZpb19yZXF1ZXN0X2lkAQZ1aW50NjQKZmlvcmVxY3R4dAAAzoemS5G6A2k2NAECaWQBBnVpbnQ2NA5yZWNvcmRvYnRfaW5mbwAAxhlbdalbA2k2NAECaWQBBnVpbnQ2NAlmaW9yZXFzdHMAAMA495upWwNpNjQBAmlkAQZ1aW50NjQMZmlvdHJ4dF9pbmZvAPBVLKl4mZMDaTY0AQJpZAEGdWludDY0Cm1pZ3JsZWRnZXIAAAAA=", - }; - case '{"account_name":"fio.token"}': - return { - account_name: "fio.token", - code_hash: "f20c3d91844682c1ac035fee1509f1c91a934122e372ac6df45594bb3f3f171e", - abi_hash: "b368fbc363f0da588eea9c943b75caadffb881dcb4dc4f283bfee7a86c97850f", - abi: "DmVvc2lvOjphYmkvMS4xAAoHYWNjb3VudAABB2JhbGFuY2UFYXNzZXQGY3JlYXRlAAEObWF4aW11bV9zdXBwbHkFYXNzZXQOY3VycmVuY3lfc3RhdHMAAwZzdXBwbHkFYXNzZXQKbWF4X3N1cHBseQVhc3NldAZpc3N1ZXIEbmFtZQVpc3N1ZQADAnRvBG5hbWUIcXVhbnRpdHkFYXNzZXQEbWVtbwZzdHJpbmcLbG9ja3BlcmlvZHMAAghkdXJhdGlvbgVpbnQ2NAdwZXJjZW50B2Zsb2F0NjQHbWludGZpbwACAnRvBG5hbWUGYW1vdW50BnVpbnQ2NAZyZXRpcmUAAghxdWFudGl0eQVhc3NldARtZW1vBnN0cmluZwh0cmFuc2ZlcgAEBGZyb20EbmFtZQJ0bwRuYW1lCHF1YW50aXR5BWFzc2V0BG1lbW8Gc3RyaW5nDHRybnNmaW9wdWJreQAFEHBheWVlX3B1YmxpY19rZXkGc3RyaW5nBmFtb3VudAVpbnQ2NAdtYXhfZmVlBWludDY0BWFjdG9yBG5hbWUEdHBpZAZzdHJpbmcLdHJuc2xvY3Rva3MABxBwYXllZV9wdWJsaWNfa2V5BnN0cmluZwhjYW5fdm90ZQVpbnQzMgdwZXJpb2RzDWxvY2twZXJpb2RzW10GYW1vdW50BWludDY0B21heF9mZWUFaW50NjQFYWN0b3IEbmFtZQR0cGlkBnN0cmluZwcAAAAAqGzURQZjcmVhdGUAAAAAAAClMXYFaXNzdWUAAAAAgLqVp5MHbWludGZpbwAAAAAAqOuyugZyZXRpcmUAAAAAVy08zc0IdHJhbnNmZXIA4OHRlbqF580MdHJuc2Zpb3B1Ymt5AAAwpBnRiOfNC3RybnNsb2N0b2tzAAIAAAA4T00RMgNpNjQAAAdhY2NvdW50AAAAAACQTcYDaTY0AAAOY3VycmVuY3lfc3RhdHMAAAAA=", - }; - case '{"account_name":"eosio"}': - return { - account_name: "eosio", - code_hash: "bf2cf9c963c483263e279d1a2f3f968a65a5c6db86af99bb9e5d7a2d2840cc12", - abi_hash: "ead7a5cf52addda442d99acf5a35494f235330392b02c4ced3d4a09dd5a7602d", - abi: "DmVvc2lvOjphYmkvMS4xADcIYWJpX2hhc2gAAgVvd25lcgRuYW1lBGhhc2gLY2hlY2tzdW0yNTYJYWRkYWN0aW9uAAMGYWN0aW9uBG5hbWUIY29udHJhY3QGc3RyaW5nBWFjdG9yBG5hbWUMYWRkZ2VubG9ja2VkAAQFb3duZXIEbmFtZQdwZXJpb2RzDWxvY2twZXJpb2RzW10HY2Fudm90ZQRib29sBmFtb3VudAVpbnQ2NAlhZGRsb2NrZWQAAwVvd25lcgRuYW1lBmFtb3VudAVpbnQ2NAhsb2NrdHlwZQVpbnQxNglhdXRob3JpdHkABAl0aHJlc2hvbGQGdWludDMyBGtleXMMa2V5X3dlaWdodFtdCGFjY291bnRzGXBlcm1pc3Npb25fbGV2ZWxfd2VpZ2h0W10Fd2FpdHMNd2FpdF93ZWlnaHRbXQxibG9ja19oZWFkZXIACAl0aW1lc3RhbXAGdWludDMyCHByb2R1Y2VyBG5hbWUJY29uZmlybWVkBnVpbnQxNghwcmV2aW91cwtjaGVja3N1bTI1NhF0cmFuc2FjdGlvbl9tcm9vdAtjaGVja3N1bTI1NgxhY3Rpb25fbXJvb3QLY2hlY2tzdW0yNTYQc2NoZWR1bGVfdmVyc2lvbgZ1aW50MzINbmV3X3Byb2R1Y2VycxJwcm9kdWNlcl9zY2hlZHVsZT8VYmxvY2tjaGFpbl9wYXJhbWV0ZXJzABETbWF4X2Jsb2NrX25ldF91c2FnZQZ1aW50NjQadGFyZ2V0X2Jsb2NrX25ldF91c2FnZV9wY3QGdWludDMyGW1heF90cmFuc2FjdGlvbl9uZXRfdXNhZ2UGdWludDMyHmJhc2VfcGVyX3RyYW5zYWN0aW9uX25ldF91c2FnZQZ1aW50MzIQbmV0X3VzYWdlX2xlZXdheQZ1aW50MzIjY29udGV4dF9mcmVlX2Rpc2NvdW50X25ldF91c2FnZV9udW0GdWludDMyI2NvbnRleHRfZnJlZV9kaXNjb3VudF9uZXRfdXNhZ2VfZGVuBnVpbnQzMhNtYXhfYmxvY2tfY3B1X3VzYWdlBnVpbnQzMhp0YXJnZXRfYmxvY2tfY3B1X3VzYWdlX3BjdAZ1aW50MzIZbWF4X3RyYW5zYWN0aW9uX2NwdV91c2FnZQZ1aW50MzIZbWluX3RyYW5zYWN0aW9uX2NwdV91c2FnZQZ1aW50MzIYbWF4X3RyYW5zYWN0aW9uX2xpZmV0aW1lBnVpbnQzMh5kZWZlcnJlZF90cnhfZXhwaXJhdGlvbl93aW5kb3cGdWludDMyFW1heF90cmFuc2FjdGlvbl9kZWxheQZ1aW50MzIWbWF4X2lubGluZV9hY3Rpb25fc2l6ZQZ1aW50MzIXbWF4X2lubGluZV9hY3Rpb25fZGVwdGgGdWludDE2E21heF9hdXRob3JpdHlfZGVwdGgGdWludDE2CmJ1cm5hY3Rpb24AAQtmaW9hZGRyaGFzaAd1aW50MTI4C2NhbmNlbGRlbGF5AAIOY2FuY2VsaW5nX2F1dGgQcGVybWlzc2lvbl9sZXZlbAZ0cnhfaWQLY2hlY2tzdW0yNTYLY3JhdXRvcHJveHkAAgVwcm94eQRuYW1lBW93bmVyBG5hbWUKZGVsZXRlYXV0aAADB2FjY291bnQEbmFtZQpwZXJtaXNzaW9uBG5hbWUHbWF4X2ZlZQZ1aW50NjQSZW9zaW9fZ2xvYmFsX3N0YXRlFWJsb2NrY2hhaW5fcGFyYW1ldGVycwsdbGFzdF9wcm9kdWNlcl9zY2hlZHVsZV91cGRhdGUUYmxvY2tfdGltZXN0YW1wX3R5cGUYbGFzdF9wZXJ2b3RlX2J1Y2tldF9maWxsCnRpbWVfcG9pbnQOcGVydm90ZV9idWNrZXQFaW50NjQPcGVyYmxvY2tfYnVja2V0BWludDY0E3RvdGFsX3VucGFpZF9ibG9ja3MGdWludDMyD3RvdGFsX3ZvdGVkX2ZpbwVpbnQ2NBV0aHJlc2hfdm90ZWRfZmlvX3RpbWUKdGltZV9wb2ludBtsYXN0X3Byb2R1Y2VyX3NjaGVkdWxlX3NpemUGdWludDE2GnRvdGFsX3Byb2R1Y2VyX3ZvdGVfd2VpZ2h0B2Zsb2F0NjQPbGFzdF9uYW1lX2Nsb3NlFGJsb2NrX3RpbWVzdGFtcF90eXBlD2xhc3RfZmVlX3VwZGF0ZRRibG9ja190aW1lc3RhbXBfdHlwZRNlb3Npb19nbG9iYWxfc3RhdGUyAAMObGFzdF9ibG9ja19udW0UYmxvY2tfdGltZXN0YW1wX3R5cGUcdG90YWxfcHJvZHVjZXJfdm90ZXBheV9zaGFyZQdmbG9hdDY0CHJldmlzaW9uBXVpbnQ4E2Vvc2lvX2dsb2JhbF9zdGF0ZTMAAhZsYXN0X3ZwYXlfc3RhdGVfdXBkYXRlCnRpbWVfcG9pbnQcdG90YWxfdnBheV9zaGFyZV9jaGFuZ2VfcmF0ZQdmbG9hdDY0BmluY3JhbQACCWFjY291bnRtbgRuYW1lBmFtb3VudAVpbnQ2NAxpbmhpYml0dW5sY2sAAgVvd25lcgRuYW1lBXZhbHVlBnVpbnQzMgRpbml0AAIHdmVyc2lvbgl2YXJ1aW50MzIEY29yZQZzeW1ib2wKa2V5X3dlaWdodAACA2tleQpwdWJsaWNfa2V5BndlaWdodAZ1aW50MTYIbGlua2F1dGgABQdhY2NvdW50BG5hbWUEY29kZQRuYW1lBHR5cGUEbmFtZQtyZXF1aXJlbWVudARuYW1lB21heF9mZWUGdWludDY0GGxvY2tlZF90b2tlbl9ob2xkZXJfaW5mbwAHBW93bmVyBG5hbWUSdG90YWxfZ3JhbnRfYW1vdW50BnVpbnQ2NBV1bmxvY2tlZF9wZXJpb2RfY291bnQGdWludDMyCmdyYW50X3R5cGUGdWludDMyEWluaGliaXRfdW5sb2NraW5nBnVpbnQzMhdyZW1haW5pbmdfbG9ja2VkX2Ftb3VudAZ1aW50NjQJdGltZXN0YW1wBnVpbnQzMhJsb2NrZWRfdG9rZW5zX2luZm8ACAJpZAVpbnQ2NA1vd25lcl9hY2NvdW50BG5hbWULbG9ja19hbW91bnQFaW50NjQRcGF5b3V0c19wZXJmb3JtZWQFaW50MzIIY2FuX3ZvdGUFaW50MzIHcGVyaW9kcw1sb2NrcGVyaW9kc1tdFXJlbWFpbmluZ19sb2NrX2Ftb3VudAVpbnQ2NAl0aW1lc3RhbXAGdWludDMyC2xvY2twZXJpb2RzAAIIZHVyYXRpb24FaW50NjQHcGVyY2VudAdmbG9hdDY0Cm5ld2FjY291bnQABAdjcmVhdG9yBG5hbWUEbmFtZQRuYW1lBW93bmVyCWF1dGhvcml0eQZhY3RpdmUJYXV0aG9yaXR5B29uYmxvY2sAAQZoZWFkZXIMYmxvY2tfaGVhZGVyB29uZXJyb3IAAglzZW5kZXJfaWQHdWludDEyOAhzZW50X3RyeAVieXRlcxBwZXJtaXNzaW9uX2xldmVsAAIFYWN0b3IEbmFtZQpwZXJtaXNzaW9uBG5hbWUXcGVybWlzc2lvbl9sZXZlbF93ZWlnaHQAAgpwZXJtaXNzaW9uEHBlcm1pc3Npb25fbGV2ZWwGd2VpZ2h0BnVpbnQxNg1wcm9kdWNlcl9pbmZvAAwCaWQGdWludDY0BW93bmVyBG5hbWULZmlvX2FkZHJlc3MGc3RyaW5nC2FkZHJlc3NoYXNoB3VpbnQxMjgLdG90YWxfdm90ZXMHZmxvYXQ2NBNwcm9kdWNlcl9wdWJsaWNfa2V5CnB1YmxpY19rZXkJaXNfYWN0aXZlBGJvb2wDdXJsBnN0cmluZw11bnBhaWRfYmxvY2tzBnVpbnQzMg9sYXN0X2NsYWltX3RpbWUKdGltZV9wb2ludAxsYXN0X2JwY2xhaW0GdWludDMyCGxvY2F0aW9uBnVpbnQxNgxwcm9kdWNlcl9rZXkAAg1wcm9kdWNlcl9uYW1lBG5hbWURYmxvY2tfc2lnbmluZ19rZXkKcHVibGljX2tleRFwcm9kdWNlcl9zY2hlZHVsZQACB3ZlcnNpb24GdWludDMyCXByb2R1Y2Vycw5wcm9kdWNlcl9rZXlbXQtyZWdwcm9kdWNlcgAGC2Zpb19hZGRyZXNzBnN0cmluZwtmaW9fcHViX2tleQZzdHJpbmcDdXJsBnN0cmluZwhsb2NhdGlvbgZ1aW50MTYFYWN0b3IEbmFtZQdtYXhfZmVlBWludDY0CHJlZ3Byb3h5AAMLZmlvX2FkZHJlc3MGc3RyaW5nBWFjdG9yBG5hbWUHbWF4X2ZlZQVpbnQ2NAlyZW1hY3Rpb24AAgZhY3Rpb24EbmFtZQVhY3RvcgRuYW1lCnJlc2V0Y2xhaW0AAQhwcm9kdWNlcgRuYW1lC3JtdnByb2R1Y2VyAAEIcHJvZHVjZXIEbmFtZQZzZXRhYmkAAgdhY2NvdW50BG5hbWUDYWJpBWJ5dGVzDHNldGF1dG9wcm94eQACBXByb3h5BG5hbWUFb3duZXIEbmFtZQdzZXRjb2RlAAQHYWNjb3VudARuYW1lBnZtdHlwZQV1aW50OAl2bXZlcnNpb24FdWludDgEY29kZQVieXRlcwlzZXRwYXJhbXMAAQZwYXJhbXMVYmxvY2tjaGFpbl9wYXJhbWV0ZXJzB3NldHByaXYAAgdhY2NvdW50BG5hbWUHaXNfcHJpdgV1aW50OA10b3BfcHJvZF9pbmZvAAEIcHJvZHVjZXIEbmFtZQp1bmxpbmthdXRoAAMHYWNjb3VudARuYW1lBGNvZGUEbmFtZQR0eXBlBG5hbWUMdW5sb2NrdG9rZW5zAAEFYWN0b3IEbmFtZQl1bnJlZ3Byb2QAAwtmaW9fYWRkcmVzcwZzdHJpbmcFYWN0b3IEbmFtZQdtYXhfZmVlBWludDY0CnVucmVncHJveHkAAwtmaW9fYWRkcmVzcwZzdHJpbmcFYWN0b3IEbmFtZQdtYXhfZmVlBWludDY0CnVwZGF0ZWF1dGgABQdhY2NvdW50BG5hbWUKcGVybWlzc2lvbgRuYW1lBnBhcmVudARuYW1lBGF1dGgJYXV0aG9yaXR5B21heF9mZWUGdWludDY0C3VwZGF0ZXBvd2VyAAIFdm90ZXIEbmFtZQp1cGRhdGVvbmx5BGJvb2wLdXBkbGJwY2xhaW0AAQhwcm9kdWNlcgRuYW1lCXVwZGxvY2tlZAACBW93bmVyBG5hbWUPYW1vdW50cmVtYWluaW5nBnVpbnQ2NAx1cGR0cmV2aXNpb24AAQhyZXZpc2lvbgV1aW50OA51c2VyX3Jlc291cmNlcwAEBW93bmVyBG5hbWUKbmV0X3dlaWdodAVhc3NldApjcHVfd2VpZ2h0BWFzc2V0CXJhbV9ieXRlcwVpbnQ2NAx2b3RlcHJvZHVjZXIABAlwcm9kdWNlcnMIc3RyaW5nW10LZmlvX2FkZHJlc3MGc3RyaW5nBWFjdG9yBG5hbWUHbWF4X2ZlZQVpbnQ2NAl2b3RlcHJveHkABAVwcm94eQZzdHJpbmcLZmlvX2FkZHJlc3MGc3RyaW5nBWFjdG9yBG5hbWUHbWF4X2ZlZQVpbnQ2NAp2b3Rlcl9pbmZvAAwCaWQGdWludDY0CmZpb2FkZHJlc3MGc3RyaW5nC2FkZHJlc3NoYXNoB3VpbnQxMjgFb3duZXIEbmFtZQVwcm94eQRuYW1lCXByb2R1Y2VycwZuYW1lW10QbGFzdF92b3RlX3dlaWdodAdmbG9hdDY0E3Byb3hpZWRfdm90ZV93ZWlnaHQHZmxvYXQ2NAhpc19wcm94eQRib29sDWlzX2F1dG9fcHJveHkEYm9vbAlyZXNlcnZlZDIGdWludDMyCXJlc2VydmVkMwVhc3NldAt3YWl0X3dlaWdodAACCHdhaXRfc2VjBnVpbnQzMgZ3ZWlnaHQGdWludDE2IwAAmNRlZFIyCWFkZGFjdGlvbgCQFEQ0TsVSMgxhZGRnZW5sb2NrZWQAAABICiIaUzIJYWRkbG9ja2VkAADApC4jM68+CmJ1cm5hY3Rpb24AALyJKkWFpkELY2FuY2VsZGVsYXkAAHynt9KszUULY3JhdXRvcHJveHkAAEDL2qisokoKZGVsZXRlYXV0aAAAAAAASHPRdAZpbmNyYW0AAFGcOrvj2nQMaW5oaWJpdHVubGNrAAAAAAAAkN10BGluaXQAAAAALWsDp4sIbGlua2F1dGgAAECemiJkuJoKbmV3YWNjb3VudAAAAAAAIhrPpAdvbmJsb2NrAAAAAODSe9WkB29uZXJyb3IAAK5COtFbmboLcmVncHJvZHVjZXIAAAAAvtNbmboIcmVncHJveHkAAACY1GVkpLoJcmVtYWN0aW9uAACAdCairLC6CnJlc2V0Y2xhaW0AAK5COtFbt7wLcm12cHJvZHVjZXIAAAAAALhjssIGc2V0YWJpAOA7vZVmbbLCDHNldGF1dG9wcm94eQAAAABAJYqywgdzZXRjb2RlAAAAwNJcU7PCCXNldHBhcmFtcwAAAABgu1uzwgdzZXRwcml2AABAy9rA6eLUCnVubGlua2F1dGgAgKeCNENE49QMdW5sb2NrdG9rZW5zAAAASPRWpu7UCXVucmVncHJvZAAAgO/0Vqbu1Ap1bnJlZ3Byb3h5AABAy9qobFLVCnVwZGF0ZWF1dGgAAK7itKpsUtULdXBkYXRlcG93ZXIAAKQzEdUTU9ULdXBkbGJwY2xhaW0AAABICiIaU9UJdXBkbG9ja2VkADCpw26rm1PVDHVwZHRyZXZpc2lvbgBwFdKJ3qoy3Qx2b3RlcHJvZHVjZXIAAADwnd6qMt0Jdm90ZXByb3h5AAoAAACgYdPcMQNpNjQAAAhhYmlfaGFzaAAAAABEc2hkA2k2NAAAEmVvc2lvX2dsb2JhbF9zdGF0ZQAAAEBEc2hkA2k2NAAAE2Vvc2lvX2dsb2JhbF9zdGF0ZTIAAABgRHNoZANpNjQAABNlb3Npb19nbG9iYWxfc3RhdGUzgKeCNCcFEY0DaTY0AAAYbG9ja2VkX3Rva2VuX2hvbGRlcl9pbmZvAACeCtIMEY0DaTY0AAASbG9ja2VkX3Rva2Vuc19pbmZvAADAVyGd6K0DaTY0AAANcHJvZHVjZXJfaW5mbwAAADjRWyvNA2k2NAAADXRvcF9wcm9kX2luZm8AAAAAq3sV1gNpNjQAAA51c2VyX3Jlc291cmNlcwAAAADgqzLdA2k2NAAACnZvdGVyX2luZm8AAAAA=", - }; - case '{"account_name":"eosio.msig"}': - return { - account_name: "eosio.msig", - code_hash: "f9eaecc20eeea9705e5e5a81777244281a4770e8ff8b377d76d032ad3163ca81", - abi_hash: "a72cfc8faf3a10267d6b842f47b7d983889831b956b2c41e09f7044e338876de", - abi: "DmVvc2lvOjphYmkvMS4xABAGYWN0aW9uAAQHYWNjb3VudARuYW1lBG5hbWUEbmFtZQ1hdXRob3JpemF0aW9uEnBlcm1pc3Npb25fbGV2ZWxbXQRkYXRhBWJ5dGVzCGFwcHJvdmFsAAIFbGV2ZWwQcGVybWlzc2lvbl9sZXZlbAR0aW1lCnRpbWVfcG9pbnQOYXBwcm92YWxzX2luZm8ABAd2ZXJzaW9uBXVpbnQ4DXByb3Bvc2FsX25hbWUEbmFtZRNyZXF1ZXN0ZWRfYXBwcm92YWxzCmFwcHJvdmFsW10ScHJvdmlkZWRfYXBwcm92YWxzCmFwcHJvdmFsW10HYXBwcm92ZQAFCHByb3Bvc2VyBG5hbWUNcHJvcG9zYWxfbmFtZQRuYW1lBWxldmVsEHBlcm1pc3Npb25fbGV2ZWwHbWF4X2ZlZQZ1aW50NjQNcHJvcG9zYWxfaGFzaAxjaGVja3N1bTI1NiQGY2FuY2VsAAQIcHJvcG9zZXIEbmFtZQ1wcm9wb3NhbF9uYW1lBG5hbWUIY2FuY2VsZXIEbmFtZQdtYXhfZmVlBnVpbnQ2NARleGVjAAQIcHJvcG9zZXIEbmFtZQ1wcm9wb3NhbF9uYW1lBG5hbWUHbWF4X2ZlZQZ1aW50NjQIZXhlY3V0ZXIEbmFtZQlleHRlbnNpb24AAgR0eXBlBnVpbnQxNgRkYXRhBWJ5dGVzCmludmFsaWRhdGUAAgdhY2NvdW50BG5hbWUHbWF4X2ZlZQZ1aW50NjQMaW52YWxpZGF0aW9uAAIHYWNjb3VudARuYW1lFmxhc3RfaW52YWxpZGF0aW9uX3RpbWUKdGltZV9wb2ludBJvbGRfYXBwcm92YWxzX2luZm8AAw1wcm9wb3NhbF9uYW1lBG5hbWUTcmVxdWVzdGVkX2FwcHJvdmFscxJwZXJtaXNzaW9uX2xldmVsW10ScHJvdmlkZWRfYXBwcm92YWxzEnBlcm1pc3Npb25fbGV2ZWxbXRBwZXJtaXNzaW9uX2xldmVsAAIFYWN0b3IEbmFtZQpwZXJtaXNzaW9uBG5hbWUIcHJvcG9zYWwAAg1wcm9wb3NhbF9uYW1lBG5hbWUScGFja2VkX3RyYW5zYWN0aW9uBWJ5dGVzB3Byb3Bvc2UABQhwcm9wb3NlcgRuYW1lDXByb3Bvc2FsX25hbWUEbmFtZQlyZXF1ZXN0ZWQScGVybWlzc2lvbl9sZXZlbFtdB21heF9mZWUGdWludDY0A3RyeAt0cmFuc2FjdGlvbgt0cmFuc2FjdGlvbhJ0cmFuc2FjdGlvbl9oZWFkZXIDFGNvbnRleHRfZnJlZV9hY3Rpb25zCGFjdGlvbltdB2FjdGlvbnMIYWN0aW9uW10WdHJhbnNhY3Rpb25fZXh0ZW5zaW9ucwtleHRlbnNpb25bXRJ0cmFuc2FjdGlvbl9oZWFkZXIABgpleHBpcmF0aW9uDnRpbWVfcG9pbnRfc2VjDXJlZl9ibG9ja19udW0GdWludDE2EHJlZl9ibG9ja19wcmVmaXgGdWludDMyE21heF9uZXRfdXNhZ2Vfd29yZHMJdmFydWludDMyEG1heF9jcHVfdXNhZ2VfbXMFdWludDgJZGVsYXlfc2VjCXZhcnVpbnQzMgl1bmFwcHJvdmUABAhwcm9wb3NlcgRuYW1lDXByb3Bvc2FsX25hbWUEbmFtZQVsZXZlbBBwZXJtaXNzaW9uX2xldmVsB21heF9mZWUGdWludDY0BgAAAEBtems1B2FwcHJvdmUAAAAAAESFpkEGY2FuY2VsAAAAAAAAgFRXBGV4ZWMAAIDKJrlo9nQKaW52YWxpZGF0ZQAAAABAYVrprQdwcm9wb3NlAAAAUJveWs3UCXVuYXBwcm92ZQAEAADA0Wx6azUDaTY0AAASb2xkX2FwcHJvdmFsc19pbmZvAIDA0Wx6azUDaTY0AAAOYXBwcm92YWxzX2luZm8AAAAA4Gj2dANpNjQAAAxpbnZhbGlkYXRpb24AAADRYFrprQNpNjQAAAhwcm9wb3NhbAAAAAA==", - }; - default: - throw new Error(`unrecognized get_raw_abi call: ${body}`); - } - }, - }, -}).startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeFioWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - expect(await untouchable.call(info, "fioSupportsNetwork")).toBe(true); - expect(await untouchable.call(info, "fioSupportsSecureTransfer")).toBe(false); - expect(untouchable.call(info, "fioSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.fioGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "fioNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeFioWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - }); - - describe("stuff that uses the network", () => { - afterEach(() => { - expect(mswMock.handlers.post["https://fio.eu.eosamsterdam.net/v1/chain/get_raw_abi"]).toHaveBeenCalledWith({ - account_name: "fio.address", - }); - expect(mswMock.handlers.post["https://fio.eu.eosamsterdam.net/v1/chain/get_raw_abi"]).toHaveBeenCalledWith({ - account_name: "fio.reqobt", - }); - expect(mswMock.handlers.post["https://fio.eu.eosamsterdam.net/v1/chain/get_raw_abi"]).toHaveBeenCalledWith({ - account_name: "fio.token", - }); - expect(mswMock.handlers.post["https://fio.eu.eosamsterdam.net/v1/chain/get_raw_abi"]).toHaveBeenCalledWith({ - account_name: "eosio", - }); - mswMock.clear(); - }); - - it("should generate a correct FIO address", async () => { - const address = await wallet.fioGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0") }); - expect(address).toBe("FIO5NSKecB4CcMpUxtpHzG4u43SmcGMAjRbxyG38rE4HPegGpaHu9"); - }); - - it("should generate another correct FIO address", async () => { - const address = await wallet.fioGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/235'/1337'/123/4") }); - expect(address).toBe("FIO8Pok1EBMsZWphhfUj2m3MXrxBZJq7erqyi7E1teAfZE18HyjK5"); - }); - - it("should generate a third correct FIO address", async () => { - const address = await wallet.fioGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/235'/1'/0/0") }); - expect(address).toMatchInlineSnapshot(`"FIO8HiUzsRDYo69AEmUk39f7h7nawTjn9msbX6oUY5wrX6ERCh3rA"`); - }); - - it("should expose the FIO SDK", async () => { - expect(await wallet.getFioSdk(core.bip32ToAddressNList("m/44'/235'/0'/0/0"))).toBeInstanceOf(fio.FIOSDK); - }); - - it("should sign a message", async () => { - const sig = await wallet.fioSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - actions: [ - { - account: "fio.address", - name: "addaddress", - data: { - fio_address: "FIO5NSKecB4CcMpUxtpHzG4u43SmcGMAjRbxyG38rE4HPegGpaHu9", - public_addresses: [ - { - chain_code: "foo", - token_code: "bar", - public_address: "baz", - }, - ], - max_fee: 0, - tpid: "FIO5NSKecB4CcMpUxtpHzG4u43SmcGMAjRbxyG38rE4HPegGpaHu9", - }, - }, - ], - }); - // This is the output of the native library's own signing function. - /*expect(sig).toMatchInlineSnapshot(` - Object { - "serialized": "ee9952603aa2ef1c7ca90000000001003056372503a85b0000c6eaa66452320180f2f085077460fd00000000a8ed323289013546494f354e534b6563423443634d7055787470487a4734753433536d63474d416a5262787947333872453448506567477061487539010362617203666f6f0362617a000000000000000080f2f085077460fd3546494f354e534b6563423443634d7055787470487a4734753433536d63474d416a526278794733387245344850656747706148753900", - "signature": "SIG_K1_JxgRLcqJHYjaqAhwHpsi8iGGkYVZRKMGT46xozonn2YwBF6vv3Jg7UZ95PsFKh9BFpHNTwhcLHhzyzhxdvw47zF12REeM2", - } - `);*/ - // This is the output from tiny-secp256k1. - expect(sig).toMatchInlineSnapshot(` - Object { - "serialized": "ee9952603aa2ef1c7ca90000000001003056372503a85b0000c6eaa66452320180f2f085077460fd00000000a8ed323289013546494f354e534b6563423443634d7055787470487a4734753433536d63474d416a5262787947333872453448506567477061487539010362617203666f6f0362617a000000000000000080f2f085077460fd3546494f354e534b6563423443634d7055787470487a4734753433536d63474d416a526278794733387245344850656747706148753900", - "signature": "SIG_K1_Kg5nEAYFbbTZGqKfsvAt1Jx4KwuRzmUiLRybv4tyJeHWwM17ch1SSW88rVcAv7m1V5EjqgCTbxLKCXUcqDofc1kqp3psmg", - } - `); - expect(mswMock).toHaveBeenCalledWith("GET", "https://fio.eu.eosamsterdam.net/v1/chain/get_info"); - expect(mswMock).toHaveBeenCalledWith("POST", "https://fio.eu.eosamsterdam.net/v1/chain/get_block", { - block_num_or_id: 61841978, - }); - - const chainId = Buffer.from( - mswMock.handlers.get["https://fio.eu.eosamsterdam.net/v1/chain/get_info"].chain_id, - "hex" - ); - const msgRaw = Buffer.concat([chainId, Buffer.from(sig!.serialized, "hex"), Buffer.alloc(32)]); - - const msgHash = Buffer.from(Isolation.Core.Digest.Algorithms["sha256"](msgRaw)); - const pubKey = bs58.decode("FIO5NSKecB4CcMpUxtpHzG4u43SmcGMAjRbxyG38rE4HPegGpaHu9".slice(3)).slice(0, -4); - const sigRaw = bs58.decode(sig!.signature.slice(7)).slice(1, -4); - expect(tinyecc.verify(msgHash, pubKey, sigRaw)).toBe(true); - }); - - it("should encrypt a request", async () => { - expect( - await wallet.fioEncryptRequestContent({ - addressNList: core.bip32ToAddressNList("m/44'/235'/0'/0/0"), - content: { - payee_public_address: "FIO5NSKecB4CcMpUxtpHzG4u43SmcGMAjRbxyG38rE4HPegGpaHu9", - amount: "1234", - chain_code: "foo", - token_code: "bar", - memo: "baz", - hash: "bash", - offline_url: "foobar", - }, - publicKey: "FIO8HiUzsRDYo69AEmUk39f7h7nawTjn9msbX6oUY5wrX6ERCh3rA", - contentType: core.FioEncryptionContentType.REQUEST, - iv: Buffer.from("deadbeefdeadbeefdeadbeefdeadbeef", "hex"), - } as any) - ).toMatchInlineSnapshot( - `"3q2+796tvu/erb7v3q2+7yeNoq+0I2pI2M5ylVEBuYkKwwHIJfKeuDZPp9bOLZNVbGtY7bfy/U9b7n316iuX1EQJHlIiHLOELx60jdWfF4A67x1T3WR8OW6lGBYCZDj8j50YbQM/oqcAIG5ND9MWK9U6Z2rcubAuZvQAcll1Jm4cIgVp49+ZxSKzEvH7Aasz"` - ); - }); - - it("should decrypt a request", async () => { - expect( - await wallet.fioDecryptRequestContent({ - addressNList: core.bip32ToAddressNList("m/44'/235'/1'/0/0"), - content: - "3q2+796tvu/erb7v3q2+7yeNoq+0I2pI2M5ylVEBuYkKwwHIJfKeuDZPp9bOLZNVbGtY7bfy/U9b7n316iuX1EQJHlIiHLOELx60jdWfF4A67x1T3WR8OW6lGBYCZDj8j50YbQM/oqcAIG5ND9MWK9U6Z2rcubAuZvQAcll1Jm4cIgVp49+ZxSKzEvH7Aasz", - publicKey: "FIO5NSKecB4CcMpUxtpHzG4u43SmcGMAjRbxyG38rE4HPegGpaHu9", - contentType: core.FioEncryptionContentType.REQUEST, - }) - ).toMatchInlineSnapshot(` - Object { - "amount": "1234", - "chain_code": "foo", - "hash": "bash", - "memo": "baz", - "offline_url": "foobar", - "payee_public_address": "FIO5NSKecB4CcMpUxtpHzG4u43SmcGMAjRbxyG38rE4HPegGpaHu9", - "token_code": "bar", - } - `); - }); - }); -}); diff --git a/packages/hdwallet-native/src/fio.ts b/packages/hdwallet-native/src/fio.ts deleted file mode 100644 index 4b9ebbae..00000000 --- a/packages/hdwallet-native/src/fio.ts +++ /dev/null @@ -1,272 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as fio from "@shapeshiftoss/fiosdk"; -import fetch, { RequestInfo, RequestInit } from "node-fetch"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; - -const fetchJson = async (uri: RequestInfo, opts?: RequestInit) => { - return fetch(uri, opts); -}; - -async function getKeyPair(masterKey: Isolation.Core.BIP32.Node, addressNList: number[]) { - const out = await addressNList.reduce(async (a, x) => (await a).derive(x), Promise.resolve(masterKey)); - if (!Isolation.Core.BIP32.nodeSupportsECDH(out)) throw new Error("fio requires keys that implement ECDH"); - return await Isolation.Adapters.FIO.create(out); -} - -export function MixinNativeFioWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeFioWalletInfo extends Base implements core.FioWalletInfo { - readonly _supportsFioInfo = true; - - async fioSupportsNetwork(): Promise { - return true; - } - - async fioSupportsSecureTransfer(): Promise { - return false; - } - - fioSupportsNativeShapeShift(): boolean { - return false; - } - - fioGetAccountPaths(msg: core.FioGetAccountPaths): Array { - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + 235, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - fioNextAccountPath(msg: core.FioAccountPath): core.FioAccountPath | undefined { - // Only support one account for now. - // the fioers library supports paths so it shouldnt be too hard if we decide multiple accounts are needed - return undefined; - } - }; -} - -export function MixinNativeFioWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeFioWallet extends Base { - readonly _supportsFio = true; - baseUrl = "https://fio.eu.eosamsterdam.net/v1/"; - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async fioInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - fioWipe(): void { - this.#masterKey = undefined; - } - - async getFioSdk(addressNList: core.BIP32Path): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const key = await getKeyPair(this.#masterKey!, addressNList); - const sdk = new fio.FIOSDK(key as any, key.publicKey, this.baseUrl, fetchJson); - sdk.setSignedTrxReturnOption(true); - return sdk; - }); - } - - async fioGetAddress(msg: core.FioGetAddress): Promise { - const sdk = await this.getFioSdk(msg.addressNList); - return sdk?.getFioPublicKey() ?? null; - } - - async fioSignTx(msg: core.FioSignTx): Promise { - const sdk = await this.getFioSdk(msg.addressNList); - if (!sdk) return null; - - const action = msg.actions[0]; - if (!action.account || !action.name || !action.data) throw new Error("account, name, and data required"); - - let genericAction = ""; - let genericActionParams: Record = {}; - switch (action.name) { - case "addaddress": { - genericAction = "addPublicAddresses"; - genericActionParams = { - fioAddress: action.data.fio_address, - publicAddresses: action.data.public_addresses, - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - }; - break; - } - case "newfundsreq": { - genericAction = "requestFunds"; - const payerPublicKey = (await sdk.getFioPublicAddress(action.data.payer_fio_address)).public_address; - const decryptedContent = core.mustBeDefined( - await this.fioDecryptRequestContent({ - contentType: core.Fio.ContentType.REQUEST, - content: action.data.content, - addressNList: msg.addressNList, - publicKey: payerPublicKey, - } as const) - ); - genericActionParams = { - payerFioAddress: action.data.payer_fio_address, - payeeFioAddress: action.data.payee_fio_address, - payeeTokenPublicAddress: decryptedContent.payee_public_address, - amount: decryptedContent.amount, - chainCode: decryptedContent.chain_code, - tokenCode: decryptedContent.token_code, - memo: decryptedContent.memo, - maxFee: action.data.max_fee, - payerFioPublicKey: null, - technologyProviderId: action.data.tpid, - hash: decryptedContent.hash, - offlineUrl: decryptedContent.offline_url, - }; - break; - } - case "recordobt": { - genericAction = "recordObtData"; - const payeePublicKey = (await sdk.getFioPublicAddress(action.data.payee_fio_address)).public_address; - const decryptedContent = core.mustBeDefined( - await this.fioDecryptRequestContent({ - contentType: core.Fio.ContentType.OBT, - content: action.data.content, - addressNList: msg.addressNList, - publicKey: payeePublicKey, - } as const) - ); - genericActionParams = { - fioRequestId: action.data.fio_request_id ? Number(action.data.fio_request_id) : null, - payerFioAddress: action.data.payer_fio_address, - payeeFioAddress: action.data.payee_fio_address, - payerTokenPublicAddress: decryptedContent.payer_public_address, - payeeTokenPublicAddress: decryptedContent.payee_public_address, - amount: decryptedContent.amount, - chainCode: decryptedContent.chain_code, - tokenCode: decryptedContent.token_code, - status: decryptedContent.status, - obtId: decryptedContent.obt_id, - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - payeeFioPublicKey: null, - memo: decryptedContent.memo, - hash: decryptedContent.hash, - offLineUrl: decryptedContent.offline_url, - }; - break; - } - case "regaddress": { - genericAction = "registerOwnerFioAddress"; - genericActionParams = { - fioAddress: action.data.fio_address, - ownerPublicKey: action.data.owner_fio_public_key, - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - }; - break; - } - case "regdomain": { - genericAction = "registerOwnerFioDomain"; - genericActionParams = { - fioDomain: action.data.fio_domain, - ownerPublicKey: action.data.owner_fio_public_key, - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - }; - break; - } - case "rejectfndreq": { - genericAction = "rejectFundsRequest"; - genericActionParams = { - fioRequestId: Number(action.data.fio_request_id), - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - }; - break; - } - case "renewaddress": { - genericAction = "renewFioAddress"; - genericActionParams = { - fioAddress: action.data.fio_address, - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - }; - break; - } - case "renewdomain": { - genericAction = "renewFioDomain"; - genericActionParams = { - fioDomain: action.data.fio_domain, - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - }; - break; - } - case "setdomainpub": { - genericAction = "setFioDomainVisibility"; - genericActionParams = { - fioDomain: action.data.fio_domain, - isPublic: action.data.is_public, - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - }; - break; - } - case "trnsfiopubky": { - genericAction = "transferTokens"; - genericActionParams = { - payeeFioPublicKey: action.data.payee_public_key, - amount: action.data.amount, - maxFee: action.data.max_fee, - technologyProviderId: action.data.tpid, - }; - break; - } - default: - throw new Error(`unsupported FIO action: ${JSON.stringify(action)}`); - } - - const res = await sdk.genericAction(genericAction, genericActionParams); - - return { - serialized: res.packed_trx, - signature: res.signatures[0], - }; - } - - async fioEncryptRequestContent( - msg: core.FioEncryptRequestContentMsg - ): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const privateKey = await getKeyPair(this.#masterKey!, msg.addressNList); - const sdk = core.mustBeDefined(await this.getFioSdk(msg.addressNList)); - return await sdk.transactions.getCipherContent( - msg.contentType, - msg.content, - privateKey, - msg.publicKey, - msg.iv && Buffer.from(msg.iv) - ); - }); - } - - async fioDecryptRequestContent( - msg: core.FioDecryptRequestContentMsg - ): Promise | null> { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const privateKey = await getKeyPair(this.#masterKey!, msg.addressNList); - const sdk = core.mustBeDefined(await this.getFioSdk(msg.addressNList)); - return await sdk.transactions.getUnCipherContent( - msg.contentType, - JSON.stringify(msg.content), - privateKey, - msg.publicKey - ); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/index.test.ts b/packages/hdwallet-native/src/index.test.ts deleted file mode 100644 index bab9b31b..00000000 --- a/packages/hdwallet-native/src/index.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import * as library from "./"; - -describe("Exports all expected classes", () => { - it("should export EncryptedWallet", () => { - expect(library.crypto.EncryptedWallet.name).toBe("EncryptedWallet"); - }); - - it("should export WebCryptoEngine", () => { - expect(library.crypto.engines.WebCryptoEngine.name).toBe("WebCryptoEngine"); - }); -}); diff --git a/packages/hdwallet-native/src/index.ts b/packages/hdwallet-native/src/index.ts deleted file mode 100644 index 62ae789a..00000000 --- a/packages/hdwallet-native/src/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./adapter"; -export * as crypto from "./crypto"; -export * from "./native"; diff --git a/packages/hdwallet-native/src/kava.test.ts b/packages/hdwallet-native/src/kava.test.ts deleted file mode 100644 index 9c7d9a2c..00000000 --- a/packages/hdwallet-native/src/kava.test.ts +++ /dev/null @@ -1,76 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeKavaWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - await expect(untouchable.call(info, "kavaSupportsNetwork")).resolves.toBe(true); - await expect(untouchable.call(info, "kavaSupportsSecureTransfer")).resolves.toBe(false); - expect(untouchable.call(info, "kavaSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.kavaGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/459'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "kavaNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeKavaWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - await expect(wallet.initialize()).resolves.toBe(true); - }); - - it("should generate a correct kava address", async () => { - await expect(wallet.kavaGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/459'/0'/0/0") })).resolves.toBe( - "kava1x9eec99f6m9d0nc3my4uyw55jefkcxj8dwxcpu" - ); - }); - - it("should generate another correct kava address", async () => { - await expect( - wallet.kavaGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/459'/1337'/123/4") }) - ).resolves.toBe("kava1yhys0syftn2f624lue6fsxyql74r3evvljchjt"); - }); - - it("does not support signing transactions", async () => { - const signed = await wallet.kavaSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/459'/0'/0/0"), - tx: { - msg: [{ type: "foo", value: "bar" }], - fee: { - amount: [{ denom: "foo", amount: "bar" }], - gas: "baz", - }, - signatures: null, - memo: "foobar", - }, - chain_id: "foobar", - account_number: "foo", - sequence: "bar", - }); - expect(signed?.signatures?.length).toBe(1); - expect(signed?.signatures?.[0].pub_key?.value).toMatchInlineSnapshot( - `"AlW0vIrn08ANEFwNKufFfnoU/1pTSjyzo8SMlPKoit3V"` - ); - expect(signed?.signatures?.[0].signature).toMatchInlineSnapshot( - `"77iUQFCVMfXvEj11YOEdMWOC4KDYxZzRz0WKzRFWnX18AwetdDh15be+iFsVgZ4RJFl2jj1JYoCGKrd9YN+Eew=="` - ); - }); -}); diff --git a/packages/hdwallet-native/src/kava.ts b/packages/hdwallet-native/src/kava.ts deleted file mode 100644 index 9192608f..00000000 --- a/packages/hdwallet-native/src/kava.ts +++ /dev/null @@ -1,90 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as bech32 from "bech32"; -import CryptoJS from "crypto-js"; -import * as txBuilder from "tendermint-tx-builder"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import * as util from "./util"; - -export function MixinNativeKavaWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeKavaWalletInfo extends Base implements core.KavaWalletInfo { - readonly _supportsKavaInfo = true; - - async kavaSupportsNetwork(): Promise { - return true; - } - - async kavaSupportsSecureTransfer(): Promise { - return false; - } - - kavaSupportsNativeShapeShift(): boolean { - return false; - } - - kavaGetAccountPaths(msg: core.KavaGetAccountPaths): Array { - const slip44 = core.slip44ByCoin("Kava"); - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - kavaNextAccountPath(msg: core.KavaAccountPath): core.KavaAccountPath | undefined { - // Only support one account for now. - return undefined; - } - }; -} - -export function MixinNativeKavaWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeKavaWallet extends Base { - readonly _supportsKava = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async kavaInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - kavaWipe(): void { - this.#masterKey = undefined; - } - - kavaBech32ify(address: ArrayLike, prefix: string): string { - const words = bech32.toWords(address); - return bech32.encode(prefix, words); - } - - createKavaAddress(publicKey: string) { - const message = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey)); - const hash = CryptoJS.RIPEMD160(message as any).toString(); - const address = Buffer.from(hash, `hex`); - return this.kavaBech32ify(address, `kava`); - } - - async kavaGetAddress(msg: core.KavaGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "kava"); - return this.createKavaAddress(keyPair.publicKey.toString("hex")); - }); - } - - async kavaSignTx(msg: core.KavaSignTx): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "kava"); - // @TODO: This needs to be fixed after the change to tendermint serialization - const adapter = await Isolation.Adapters.Cosmos.create(keyPair); - const result = await txBuilder.sign(msg.tx, adapter, msg.sequence, msg.account_number, msg.chain_id); - return txBuilder.createSignedTx(msg.tx, result); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/mayachain.test.ts b/packages/hdwallet-native/src/mayachain.test.ts deleted file mode 100644 index 34a8c727..00000000 --- a/packages/hdwallet-native/src/mayachain.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeMayachainWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - await expect(untouchable.call(info, "mayachainSupportsNetwork")).resolves.toBe(true); - await expect(untouchable.call(info, "mayachainSupportsSecureTransfer")).resolves.toBe(false); - expect(untouchable.call(info, "mayachainSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.mayachainGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/931'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "mayachainNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeThorchainWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - await expect(wallet.initialize()).resolves.toBe(true); - }); - - it("should generate a correct mayachain address", async () => { - await expect( - wallet.mayachainGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/931'/0'/0/0") }) - ).resolves.toBe("maya1ujumx36gj3jv33gcw49dfafdddza3kdcdxedts"); - }); - - it("should generate another correct mayachain address", async () => { - await expect( - wallet.mayachainGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/931'/1337'/123/4") }) - ).resolves.toBe("maya14hqwsy4qpwzsdk2l3h3q82eghg4ctaa385ck8c"); - }); - - it("should sign a transaction correctly", async () => { - const signed = await wallet.mayachainSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/931'/0'/0/0"), - tx: { - msg: [ - { - type: "mayachain/MsgSend", - value: { - from_address: "maya1ujumx36gj3jv33gcw49dfafdddza3kdcdxedts", - to_address: "maya14hqwsy4qpwzsdk2l3h3q82eghg4ctaa385ck8c", - amount: [ - { - denom: "cacao", - amount: "12345678", - }, - ], - }, - }, - ], - fee: { - amount: [], - gas: "1000000", - }, - memo: "hdwallet mayachain test", - signatures: [], - }, - chain_id: "mayachain-mainnet-v1", - account_number: "2722", - sequence: "11", - }); - - expect(signed?.signatures?.length).toBe(1); - expect(signed?.signatures?.[0]).toBe( - "JV+DawmfyQldwLBaLC8pe75bSaQSthH+BqHciZXZW3pzXHiZ3tFVawUgRhHPaoe38Au/pnsJMqG/LLYqGRnVlQ==" - ); - }); -}); diff --git a/packages/hdwallet-native/src/mayachain.ts b/packages/hdwallet-native/src/mayachain.ts deleted file mode 100644 index c99636b8..00000000 --- a/packages/hdwallet-native/src/mayachain.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { StdTx } from "@cosmjs/amino"; -import type { SignerData } from "@cosmjs/stargate"; -import * as core from "@keepkey/hdwallet-core"; -import * as bech32 from "bech32"; -import CryptoJS from "crypto-js"; -import PLazy from "p-lazy"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import * as util from "./util"; - -const MAYA_CHAIN = "mayachain-mainnet-v1"; - -const protoTxBuilder = PLazy.from(() => import("@keepkey/proto-tx-builder")); - -export function MixinNativeMayachainWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeMayachainWalletInfo extends Base implements core.MayachainWalletInfo { - readonly _supportsMayachainInfo = true; - async mayachainSupportsNetwork(): Promise { - return true; - } - - async mayachainSupportsSecureTransfer(): Promise { - return false; - } - - mayachainSupportsNativeShapeShift(): boolean { - return false; - } - - mayachainGetAccountPaths(msg: core.MayachainGetAccountPaths): Array { - const slip44 = core.slip44ByCoin("Mayachain"); - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - mayachainNextAccountPath(msg: core.MayachainAccountPath): core.MayachainAccountPath | undefined { - // Only support one account for now. - return undefined; - } - }; -} - -export function MixinNativeMayachainWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeMayachainWallet extends Base { - readonly _supportsMayachain = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async mayachainInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - mayachainWipe(): void { - this.#masterKey = undefined; - } - - mayachainBech32ify(address: ArrayLike, prefix: string): string { - const words = bech32.toWords(address); - return bech32.encode(prefix, words); - } - - createMayachainAddress(publicKey: string) { - const message = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey)); - const hash = CryptoJS.RIPEMD160(message as any).toString(); - const address = Buffer.from(hash, `hex`); - return this.mayachainBech32ify(address, `maya`); - } - - async mayachainGetAddress(msg: core.MayachainGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "mayachain"); - return this.createMayachainAddress(keyPair.publicKey.toString("hex")); - }); - } - - async mayachainSignTx(msg: core.MayachainSignTx): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "mayachain"); - const adapter = await Isolation.Adapters.CosmosDirect.create(keyPair.node, "maya"); - - const signerData: SignerData = { - sequence: Number(msg.sequence), - accountNumber: Number(msg.account_number), - chainId: MAYA_CHAIN, - }; - - return (await protoTxBuilder).sign(adapter.address, msg.tx as StdTx, adapter, signerData, "maya"); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/modules.d.ts b/packages/hdwallet-native/src/modules.d.ts deleted file mode 100644 index f436eb96..00000000 --- a/packages/hdwallet-native/src/modules.d.ts +++ /dev/null @@ -1,116 +0,0 @@ -/// - -declare module "ethereum-tx-decoder"; -declare module "@shapeshiftoss/fiojs/dist/ecc"; -declare module "bip32/src/crypto" { - export * from "bip32/types/crypto"; -} - -// These come from https://github.com/DefinitelyTyped/DefinitelyTyped/blob/7e1a46771ee0841d6c24219e0b138689512b6df6/types/tiny-secp256k1/index.d.ts, -// except for the additional definition of signWithEntropy() which is omitted in -// the DefinitelyTyped package. -declare module "tiny-secp256k1" { - // Type definitions for tiny-secp256k1 1.0 - // Project: https://github.com/bitcoinjs/tiny-secp256k1 - // Definitions by: Eduardo Henke - // Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped - /// - - /** - * Checks if A is a point in the curve - * @param A should be: - * encoded with a sequence tag of 0x02, 0x03 or 0x04 - * A.x is within [1...p - 1] - * A.y is within [1...p - 1] - */ - export function isPoint(A: Buffer): boolean; - - /** - * Returns false if the point is not compressed. - */ - export function isPointCompressed(A: Buffer): boolean; - - /** - * Checks if point is private key - * @param d should be: - * 256-bit - * within [1...order - 1] - */ - export function isPrivate(d: Buffer): boolean; - - /** - * Returns null if result is at infinity. - * @param A isPoint(A) should be true - * @param B isPoint(B) should be true - * @param compressed optional, if true compresses the resulting point - */ - export function pointAdd(A: Buffer, B: Buffer, compressed?: boolean): Buffer | null; - - /** - * Returns null if result is at infinity. - * @param A isPoint(A) should be true - * @param tweak should be within [1...order - 1] - * @param compressed optional, if true compresses the resulting point - */ - export function pointAddScalar(A: Buffer, tweak: Buffer, compressed?: boolean): Buffer | null; - - /** - * Compresses point A. - * @param A isPoint(A) should be true - * @param compressed if true compresses A - */ - export function pointCompress(A: Buffer, compressed: boolean): Buffer; - - /** - * Returns null if result is at infinity. - * @param d isPrivate(d) should be true - * @param compressed optional, if true compresses the resulting point - */ - export function pointFromScalar(d: Buffer, compressed?: boolean): Buffer | null; - - /** - * Returns null if result is at infinity. - * @param A isPoint(A) should be true - * @param tweak should be within [1...order - 1] - * @param compressed optional, if true compresses the resulting point - */ - export function pointMultiply(A: Buffer, tweak: Buffer, compressed?: boolean): Buffer | null; - - /** - * Returns null if result is equal to 0. - * @param d isPrivate(d) should be true - * @param tweak should be within [1...order - 1] - */ - export function privateAdd(d: Buffer, tweak: Buffer): Buffer | null; - - /** - * Returns null if result is equal to 0. - * @param d isPrivate(d) should be true - * @param tweak should be within [1...order - 1] - */ - export function privateSub(d: Buffer, tweak: Buffer): Buffer | null; - - /** - * Returns normalized signatures, each of (r, s) values are guaranteed to less than order / 2. Uses RFC6979. - * @param message should be 256-bit - * @param privateKey isPrivate(privateKey) should be true - */ - export function sign(message: Buffer, privateKey: Buffer): Buffer; - - /** - * Returns normalized signatures, each of (r, s) values are guaranteed to less than order / 2. Uses RFC6979. - * Adds e as Added Entropy to the deterministic k generation. - * @param message should be 256-bit - * @param privateKey isPrivate(privateKey) should be true - * @param entropy should be 256-bit - */ - export function signWithEntropy(message: Buffer, privateKey: Buffer, entropy: Buffer): Buffer; - - /** - * Returns false if any of (r, s) values are equal to 0, or if the signature is rejected. - * @param message should be 256-bit - * @param publicKey isPoint(publicKey) should be true - * @param signature signature should have all (r, s) values within range [0...order - 1] - */ - export function verify(message: Buffer, publicKey: Buffer, signature: Buffer): boolean; -} diff --git a/packages/hdwallet-native/src/native.test.ts b/packages/hdwallet-native/src/native.test.ts deleted file mode 100644 index 9314f19a..00000000 --- a/packages/hdwallet-native/src/native.test.ts +++ /dev/null @@ -1,506 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import { Node } from "./crypto/isolation/engines/default/bip32"; -import { fromB64ToArray } from "./crypto/utils"; -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const PRIVATE_KEY = "oe5ysT50Qkvnh1q9JwLULQuvK7flK664UkVA/srziyY="; // root private key generated from the 'all all all' seed -const CHAIN_CODE = "UBS48IuLdtYu2dXcWEAQDfUWmcwYvdSIAPM3VgRd0tI="; // root chain code generated from the 'all all all' seed - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeHDWalletInfo", () => { - it("should have correct metadata", () => { - const info = native.info(); - expect(info.getVendor()).toBe("Native"); - expect(info.hasOnDevicePinEntry()).toBe(false); - expect(info.hasOnDevicePassphrase()).toBe(false); - expect(info.hasOnDeviceDisplay()).toBe(false); - expect(info.hasOnDeviceRecovery()).toBe(false); - expect(info.supportsBip44Accounts()).toBe(true); - }); - it("should produce correct path descriptions", () => { - const info = native.info(); - expect(info.hasNativeShapeShift()).toBe(false); - [ - { - msg: { coin: "bitcoin", path: [1, 2, 3] }, - out: { coin: "bitcoin", verbose: "m/1/2/3", isKnown: false }, - }, - { - msg: { - coin: "bitcoin", - path: [44 + 0x80000000, 0 + 0x80000000, 0 + 0x80000000, 0, 0], - scriptType: core.BTCInputScriptType.SpendAddress, - }, - out: { coin: "bitcoin", verbose: "m/44'/0'/0'/0/0", isKnown: false }, - }, - { - msg: { - coin: "Bitcoin", - path: [44 + 0x80000000, 0 + 0x80000000, 0 + 0x80000000], - scriptType: core.BTCInputScriptType.SpendAddress, - }, - out: { coin: "Bitcoin", verbose: "Bitcoin Account #0 (Legacy)", isKnown: true, wholeAccount: true }, - }, - { - msg: { - coin: "Bitcoin", - path: [44 + 0x80000000, 0 + 0x80000000, 0 + 0x80000000, 0, 0], - scriptType: core.BTCInputScriptType.SpendAddress, - }, - out: { coin: "Bitcoin", verbose: "Bitcoin Account #0, Address #0 (Legacy)", isKnown: true }, - }, - { - msg: { coin: "dash", path: [1, 2, 3], scriptType: core.BTCInputScriptType.SpendWitness }, - out: { coin: "dash", verbose: "m/1/2/3", scriptType: core.BTCInputScriptType.SpendWitness, isKnown: false }, - }, - { - msg: { coin: "bitcoincash", path: [1, 2, 3] }, - out: { coin: "bitcoincash", verbose: "m/1/2/3", isKnown: false }, - }, - { - msg: { coin: "ethereum", path: [44 + 0x80000000, 60 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Ethereum", verbose: "Ethereum Account #0", isKnown: true }, - }, - { - msg: { coin: "atom", path: [44 + 0x80000000, 118 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Atom", verbose: "Cosmos Account #0", isKnown: true }, - }, - { - msg: { coin: "fio", path: [44 + 0x80000000, 235 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Fio", verbose: "Fio Account #0", isKnown: true }, - }, - { - msg: { coin: "rune", path: [44 + 0x80000000, 931 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Thorchain", verbose: "Thorchain Account #0", isKnown: true }, - }, - { - msg: { coin: "secret", path: [44 + 0x80000000, 529 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Secret", verbose: "Secret Account #0", isKnown: true }, - }, - { - msg: { coin: "luna", path: [44 + 0x80000000, 330 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Terra", verbose: "Terra Account #0", isKnown: true }, - }, - { - msg: { coin: "kava", path: [44 + 0x80000000, 459 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Kava", verbose: "Kava Account #0", isKnown: true }, - }, - { - msg: { coin: "Osmo", path: [44 + 0x80000000, 118 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Osmo", verbose: "Osmosis Account #0", isKnown: true }, - }, - { - msg: { coin: "cacao", path: [44 + 0x80000000, 931 + 0x80000000, 0 + 0x80000000, 0, 0] }, - out: { coin: "Mayachain", verbose: "Mayachain Account #0", isKnown: true }, - }, - ].forEach((x) => expect(info.describePath(x.msg)).toMatchObject(x.out)); - expect(() => info.describePath({ coin: "foobar", path: [1, 2, 3] })).toThrowError("Unsupported path"); - }); - it("should return true for supportsBip44Accounts", async () => { - expect(native.info().supportsBip44Accounts()).toBe(true); - }); -}); - -describe("NativeHDWallet", () => { - it("should keep mnemonic private", () => { - const wallet = native.create({ mnemonic: MNEMONIC, deviceId: "deviceId" }); - const json = JSON.stringify(wallet); - expect(json).not.toMatch(/mnemonic|all/); - expect(Object.getOwnPropertyNames(wallet).filter((p) => p.includes("mnemonic")).length).toBe(0); - expect(require("util").inspect(wallet, { showHidden: true }).includes("mnemonic")).toBe(false); - }); - - describe("loadDevice", () => { - it("should load wallet with a mnemonic", async () => { - const wallet = native.create({ deviceId: "native" }); - expect(await wallet.isInitialized()).toBe(false); - expect(await wallet.isLocked()).toBe(false); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - expect(await wallet.isInitialized()).toBe(true); - expect(await wallet.isLocked()).toBe(false); - const testCases: Array<{ in: any; out: any }> = [ - { - in: [{ coin: "bitcoin", addressNList: [] }], - out: [ - { - xpub: "xpub661MyMwAqRbcFLgDU7wpcEVubSF7NkswwmXBUkDiGUW6uopeUMys4AqKXNgpfZKRTLnpKQgffd6a2c3J8JxLkF1AQN17Pm9QYHEqEfo1Rsx", - }, - ], - }, - { - in: [{ coin: "bitcoin", addressNList: [1 + 0x80000000, 2 + 0x80000000] }], - out: [ - { - xpub: "xpub6A4ydEAik39rFLs1hcm6XiwpFN5XKEf9tdAZWK23tkXmSr8bHmfYyfVt2nTskZQj3yYydcST2DLUFq2iJAELtTVfW9UNnnK8zBi8bzFcQVB", - }, - ], - }, - // Note how this produces the same xpub as the path above. This is not intuitive behavior, and is probably a bug. - { - in: [{ coin: "bitcoin", addressNList: [1 + 0x80000000, 2 + 0x80000000, 3] }], - out: [ - { - xpub: "xpub6A4ydEAik39rFLs1hcm6XiwpFN5XKEf9tdAZWK23tkXmSr8bHmfYyfVt2nTskZQj3yYydcST2DLUFq2iJAELtTVfW9UNnnK8zBi8bzFcQVB", - }, - ], - }, - ]; - for (const params of testCases) { - expect(await wallet.getPublicKeys(params.in)).toStrictEqual(params.out); - } - }); - - it("should load wallet with a root node", async () => { - const node = await Node.create(fromB64ToArray(PRIVATE_KEY), fromB64ToArray(CHAIN_CODE)); - const wallet = native.create({ deviceId: "native", masterKey: node }); - expect(await wallet.isInitialized()).toBe(false); - expect(await wallet.isLocked()).toBe(false); - await wallet.loadDevice({ masterKey: node }); - expect(await wallet.initialize()).toBe(true); - expect(await wallet.isInitialized()).toBe(true); - expect(await wallet.isLocked()).toBe(false); - const testCases: Array<{ in: any; out: any }> = [ - { - in: [{ coin: "bitcoin", addressNList: [] }], - out: [ - { - xpub: "xpub661MyMwAqRbcFLgDU7wpcEVubSF7NkswwmXBUkDiGUW6uopeUMys4AqKXNgpfZKRTLnpKQgffd6a2c3J8JxLkF1AQN17Pm9QYHEqEfo1Rsx", - }, - ], - }, - { - in: [{ coin: "bitcoin", addressNList: [1 + 0x80000000, 2 + 0x80000000] }], - out: [ - { - xpub: "xpub6A4ydEAik39rFLs1hcm6XiwpFN5XKEf9tdAZWK23tkXmSr8bHmfYyfVt2nTskZQj3yYydcST2DLUFq2iJAELtTVfW9UNnnK8zBi8bzFcQVB", - }, - ], - }, - // Note how this produces the same xpub as the path above. This is not intuitive behavior, and is probably a bug. - { - in: [{ coin: "bitcoin", addressNList: [1 + 0x80000000, 2 + 0x80000000, 3] }], - out: [ - { - xpub: "xpub6A4ydEAik39rFLs1hcm6XiwpFN5XKEf9tdAZWK23tkXmSr8bHmfYyfVt2nTskZQj3yYydcST2DLUFq2iJAELtTVfW9UNnnK8zBi8bzFcQVB", - }, - ], - }, - ]; - for (const params of testCases) { - expect(await wallet.getPublicKeys(params.in)).toStrictEqual(params.out); - } - }); - - it("should load wallet with a non-root node", async () => { - /** NOTE: Private key and chain code for node at depth 2 was generated - * using 'alcohol' 'woman' 'abuse' seed. - */ - const PRIVATE_KEY_DEPTH_2 = "GNjTirvFO9+GTP2Mp+4tmJAWRhxVmgVopzGXLeGbsw4="; - const CHAIN_CODE_DEPTH_2 = "mMkqCbitsaueXWZf1q4d0zHRMBctdZFhid4z8c8v9II="; - const node = await Node.create( - fromB64ToArray(PRIVATE_KEY_DEPTH_2), - fromB64ToArray(CHAIN_CODE_DEPTH_2), - "m/44'/0'" - ); - const wallet = native.create({ deviceId: "native", masterKey: node }); - expect(await wallet.isInitialized()).toBe(false); - expect(await wallet.isLocked()).toBe(false); - await wallet.loadDevice({ masterKey: node }); - expect(await wallet.initialize()).toBe(true); - expect(await wallet.isInitialized()).toBe(true); - expect(await wallet.isLocked()).toBe(false); - - expect( - await wallet.btcGetAddress({ - coin: "bitcoin", - addressNList: [44 + 0x80000000, 0 + 0x80000000], - scriptType: core.BTCInputScriptType.SpendAddress, - }) - ).toStrictEqual("1Hvzdx2kSLHT93aTnEeDNDSo4DS1Wn3CML"); - }); - - it("should generate valid UTXO addresses when initialized with a non-root node", async () => { - /** NOTE: Private key and chain code for node at depth 2 was generated - * using 'alcohol' 'woman' 'abuse' seed. - */ - const PRIVATE_KEY_DEPTH_2 = "GNjTirvFO9+GTP2Mp+4tmJAWRhxVmgVopzGXLeGbsw4="; - const CHAIN_CODE_DEPTH_2 = "mMkqCbitsaueXWZf1q4d0zHRMBctdZFhid4z8c8v9II="; - - const node = await Node.create( - fromB64ToArray(PRIVATE_KEY_DEPTH_2), - fromB64ToArray(CHAIN_CODE_DEPTH_2), - "m/44'/0'" - ); - const wallet = native.create({ deviceId: "native", masterKey: node }); - expect(await wallet.isInitialized()).toBe(false); - expect(await wallet.isLocked()).toBe(false); - await wallet.loadDevice({ masterKey: node }); - expect(await wallet.initialize()).toBe(true); - expect(await wallet.isInitialized()).toBe(true); - expect(await wallet.isLocked()).toBe(false); - expect( - await wallet.btcGetAddress({ - coin: "bitcoin", - addressNList: [44 + 0x80000000, 0 + 0x80000000, 0 + 0x80000000, 0, 0], - scriptType: core.BTCInputScriptType.SpendAddress, - }) - ).toStrictEqual("1FH6ehAd5ZFXCM1cLGzHxK1s4dGdq1JusM"); - }); - - it("should generate valid Cosmos-SDK addresses when initialized with a non-root node", async () => { - /** NOTE: Private key and chain code for node at depth 2 was generated - * using 'alcohol' 'woman' 'abuse' seed. - */ - const PRIVATE_KEY_DEPTH_2 = "dbSElgfG40sz9QXOfAdw4CStHymWOj76YwCP/7J7gfg="; - const CHAIN_CODE_DEPTH_2 = "pBbxxP1ydHOWjGXtMOeeCMqvtiVpJlM0OQIJS3gsUcY="; - - const node = await Node.create( - fromB64ToArray(PRIVATE_KEY_DEPTH_2), - fromB64ToArray(CHAIN_CODE_DEPTH_2), - "m/44'/118'" - ); - const wallet = native.create({ deviceId: "native", masterKey: node }); - expect(await wallet.isInitialized()).toBe(false); - expect(await wallet.isLocked()).toBe(false); - await wallet.loadDevice({ masterKey: node }); - expect(await wallet.initialize()).toBe(true); - expect(await wallet.isInitialized()).toBe(true); - expect(await wallet.isLocked()).toBe(false); - expect( - await wallet.cosmosGetAddress({ - addressNList: [44 + 0x80000000, 118 + 0x80000000, 0 + 0x80000000, 0, 0], - }) - ).toStrictEqual("cosmos15cenya0tr7nm3tz2wn3h3zwkht2rxrq7q7h3dj"); - }); - - it("should generate valid EVM addresses when initialized with a non-root node", async () => { - /** NOTE: Private key and chain code for node at depth 2 was generated - * using 'alcohol' 'woman' 'abuse' seed. - */ - const PRIVATE_KEY_DEPTH_2 = "/z/nU3ZlAc3LMiIGaMzjPzGBKK55MXCv/NKLYnJ+4ZM="; - const CHAIN_CODE_DEPTH_2 = "c7sxhcAlFHGVnu0Ui5zJBvWAcuFddqFdX7eUHjd4Aw4="; - - const node = await Node.create( - fromB64ToArray(PRIVATE_KEY_DEPTH_2), - fromB64ToArray(CHAIN_CODE_DEPTH_2), - "m/44'/60'" - ); - const wallet = native.create({ deviceId: "native", masterKey: node }); - expect(await wallet.isInitialized()).toBe(false); - expect(await wallet.isLocked()).toBe(false); - await wallet.loadDevice({ masterKey: node }); - expect(await wallet.initialize()).toBe(true); - expect(await wallet.isInitialized()).toBe(true); - expect(await wallet.isLocked()).toBe(false); - expect( - await wallet.ethGetAddress({ - addressNList: [44 + 0x80000000, 60 + 0x80000000, 0 + 0x80000000, 0, 0], - }) - ).toStrictEqual("0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8"); - }); - - it("should throw when attempting to derive a key for a path that is not a child of the explicit path", async () => { - const node = await Node.create(fromB64ToArray(PRIVATE_KEY), fromB64ToArray(CHAIN_CODE), "m/44'/0'/0'"); - const wallet = native.create({ deviceId: "native", masterKey: node }); - expect(await wallet.isInitialized()).toBe(false); - expect(await wallet.isLocked()).toBe(false); - await wallet.loadDevice({ masterKey: node }); - expect(await wallet.initialize()).toBe(true); - expect(await wallet.isInitialized()).toBe(true); - expect(await wallet.isLocked()).toBe(false); - - const testCases: Array<{ in: any }> = [ - { - in: [ - { - coin: "bitcoin", - addressNList: [44 + 0x80000000, 0 + 0x80000000], - curve: "secp256k1", - }, - ], - }, - { - in: [ - { - coin: "bitcoin", - addressNList: [44 + 0x80000000, 60 + 0x80000000], - curve: "secp256k1", - }, - ], - }, - { - in: [ - { - coin: "bitcoin", - addressNList: [44 + 0x80000000, 0 + 0x80000000, 1 + 0x80000000], - curve: "secp256k1", - }, - ], - }, - { - in: [ - { - coin: "bitcoin", - addressNList: [44 + 0x80000000, 118 + 0x80000000, 0 + 0x80000000, 0, 0], - curve: "secp256k1", - }, - ], - }, - ]; - for (const params of testCases) { - await expect(wallet.getPublicKeys(params.in)).rejects.toThrowError("path is not a child of this node"); - } - }); - - it("should load wallet with a mnemonic and deviceId", async () => { - const wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC, deviceId: "0SUnRnGkhCt0T5qk5YmK10v5u+lgHiMMu1R76uD7kHE=" }); - expect(await wallet.initialize()).toBe(true); - expect(await wallet.getDeviceID()).toBe("0SUnRnGkhCt0T5qk5YmK10v5u+lgHiMMu1R76uD7kHE="); - }); - - it.each([[undefined], [null], [0], [[1, 2, 3]], [{}]])( - "should not update the deviceId if it's not a string (%o)", - async (param: any) => { - const wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC, deviceId: param }); - expect(await wallet.getDeviceID()).toBe("native"); - } - ); - - it("should throw an error when loadDevice is missing its parameters", async () => { - const wallet = native.create({ deviceId: "native" }); - await expect(wallet.loadDevice(undefined as any)).rejects.toThrow("Either [mnemonic] or [masterKey] is required"); - }); - - it.each([[undefined]])("should throw an error if mnemonic is not a string (%o)", async (param: any) => { - const wallet = native.create({ deviceId: "native" }); - await expect(wallet.loadDevice({ mnemonic: param })).rejects.toThrow( - "Either [mnemonic] or [masterKey] is required" - ); - }); - - it.each([[null], [0], [[1, 2, 3]], [{}], [""], ["all all all all all all"]])( - "should throw an error if mnemonic is not a string (%o)", - async (param: any) => { - const wallet = native.create({ deviceId: "native" }); - await expect(wallet.loadDevice({ mnemonic: param })).rejects.toThrow("Required property [mnemonic] is invalid"); - } - ); - it("should return true for supportsBip44Accounts", async () => { - const wallet = native.create({ deviceId: "native" }); - expect(wallet.supportsBip44Accounts()).toBe(true); - }); - }); - - it("should wipe if an error occurs during initialization", async () => { - expect.assertions(6); - const wallet = native.create({ deviceId: "native" }); - const masterKey = { - getChainCode: () => { - throw "mock error"; - }, - } as any; - const mocks = [ - jest.spyOn(console, "error").mockImplementationOnce((msg, error) => { - expect(msg).toMatch("NativeHDWallet:initialize:error"); - expect(error).toEqual("mock error"); - }), - jest.spyOn(wallet, "wipe"), - ]; - await wallet.loadDevice({ masterKey }); - expect(await wallet.initialize()).toBeFalsy(); - mocks.forEach((x) => { - expect(x).toHaveBeenCalled(); - x.mockRestore(); - }); - }); - - it("should have correct metadata", async () => { - const deviceId = "foobar"; - const wallet = native.create({ deviceId }); - expect(await wallet.getFeatures()).toEqual({}); - expect(await wallet.getDeviceID()).toEqual(deviceId); - expect(await wallet.getFirmwareVersion()).toEqual("Software"); - expect(await wallet.getModel()).toEqual("Native"); - expect(await wallet.getLabel()).toEqual("Native"); - }); - - it("should emit MNEMONIC_REQUIRED when initialized without a mnemonic", async () => { - const wallet = native.create({ deviceId: "native" }); - const mnemonicRequiredMock = jest.fn(({ message_type }) => { - expect(message_type).toBe(native.NativeEvents.MNEMONIC_REQUIRED); - }); - const readyMock = jest.fn(({ message_type }) => { - expect(message_type).toBe(native.NativeEvents.READY); - }); - wallet.events.addListener(native.NativeEvents.READY, readyMock); - wallet.events.addListener(native.NativeEvents.MNEMONIC_REQUIRED, mnemonicRequiredMock); - expect(await wallet.initialize()).toBe(null); - expect(mnemonicRequiredMock).toHaveBeenCalled(); - expect(readyMock).not.toHaveBeenCalled(); - }); - - it("should emit READY when initialized with a mnemonic", async () => { - const wallet = native.create({ deviceId: "native" }); - const mnemonicRequiredMock = jest.fn(({ message_type }) => { - expect(message_type).toBe(native.NativeEvents.MNEMONIC_REQUIRED); - }); - const readyMock = jest.fn(({ message_type }) => { - expect(message_type).toBe(native.NativeEvents.READY); - }); - wallet.events.addListener(native.NativeEvents.READY, readyMock); - wallet.events.addListener(native.NativeEvents.MNEMONIC_REQUIRED, mnemonicRequiredMock); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - expect(mnemonicRequiredMock).not.toHaveBeenCalled(); - expect(readyMock).toHaveBeenCalled(); - }); - - it("should emit MNEMONIC_REQUIRED when initialized after a wipe", async () => { - const wallet = native.create({ deviceId: "native" }); - const mock = jest.fn(); - wallet.events.addListener(native.NativeEvents.MNEMONIC_REQUIRED, mock); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - await wallet.wipe(); - expect(mock).not.toHaveBeenCalled(); - expect(await wallet.initialize()).toBe(null); - expect(mock).toHaveBeenCalled(); - }); - - it("should work with isNative", () => { - const wallet = native.create({ deviceId: "native" }); - expect(native.isNative(wallet)).toBe(true); - }); - - it("should respond to .ping()", async () => { - const wallet = native.create({ deviceId: "native" }); - expect(await wallet.ping({ msg: "pong" })).toEqual({ msg: "pong" }); - }); - - describe("nothing happens", () => { - const wallet = native.create({ deviceId: "native" }); - - it.each([ - ["clearSession"], - ["sendPin"], - ["sendPassphrase"], - ["sendCharacter"], - ["sendWord"], - ["cancel"], - ["reset"], - ["recover"], - ])("when %s is called", async (methodName) => { - expect(await untouchable.call(wallet, methodName)).toBe(undefined); - }); - }); -}); diff --git a/packages/hdwallet-native/src/native.ts b/packages/hdwallet-native/src/native.ts deleted file mode 100644 index 92ddc2aa..00000000 --- a/packages/hdwallet-native/src/native.ts +++ /dev/null @@ -1,455 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as bip39 from "bip39"; -import * as eventemitter2 from "eventemitter2"; -import isObject from "lodash/isObject"; - -import type { NativeAdapterArgs } from "./adapter"; -import { MixinNativeArkeoWallet, MixinNativeArkeoWalletInfo } from "./arkeo"; -import { MixinNativeBTCWallet, MixinNativeBTCWalletInfo } from "./bitcoin"; -import { MixinNativeCosmosWallet, MixinNativeCosmosWalletInfo } from "./cosmos"; -import * as Isolation from "./crypto/isolation"; -import { MixinNativeETHWallet, MixinNativeETHWalletInfo } from "./ethereum"; -import { MixinNativeFioWallet, MixinNativeFioWalletInfo } from "./fio"; -import { MixinNativeKavaWallet, MixinNativeKavaWalletInfo } from "./kava"; -import { MixinNativeMayachainWallet, MixinNativeMayachainWalletInfo } from "./mayachain"; -import { getNetwork } from "./networks"; -import { MixinNativeOsmosisWallet, MixinNativeOsmosisWalletInfo } from "./osmosis"; -import { MixinNativeSecretWallet, MixinNativeSecretWalletInfo } from "./secret"; -import { MixinNativeTerraWallet, MixinNativeTerraWalletInfo } from "./terra"; -import { MixinNativeThorchainWallet, MixinNativeThorchainWalletInfo } from "./thorchain"; - -export enum NativeEvents { - MNEMONIC_REQUIRED = "MNEMONIC_REQUIRED", - READY = "READY", -} - -function isMnemonicInterface(x: unknown): x is Isolation.Core.BIP39.Mnemonic { - return core.isIndexable(x) && typeof x.toSeed === "function"; -} - -type LoadDevice = Omit & { - // Set this if your deviceId is dependent on the mnemonic - deviceId?: string; -} & ( - | { - mnemonic: string | Isolation.Core.BIP39.Mnemonic; - masterKey?: never; - } - | { - mnemonic?: never; - masterKey: Isolation.Core.BIP32.Node; - } - ); - -export class NativeHDWalletInfoBase implements core.HDWalletInfo { - getVendor(): string { - return "Native"; - } - - hasOnDevicePinEntry(): boolean { - return false; - } - - hasOnDevicePassphrase(): boolean { - return false; - } - - hasOnDeviceDisplay(): boolean { - return false; - } - - hasOnDeviceRecovery(): boolean { - return false; - } - - hasNativeShapeShift(): boolean { - return false; - } - - public supportsBip44Accounts(): boolean { - return true; - } - - public supportsOfflineSigning(): boolean { - return true; - } - - public supportsBroadcast(): boolean { - return false; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - describePath(msg: core.DescribePath): core.PathDescription { - throw new Error("unreachable"); - } -} - -export class NativeHDWalletBase extends NativeHDWalletInfoBase { - readonly #events: eventemitter2.EventEmitter2; - - constructor() { - super(); - this.#events = new eventemitter2.EventEmitter2(); - } - - get events() { - return this.#events; - } - - /** - * Wrap a function call that needs a mnemonic seed - * Raise an event if the wallet hasn't been initialized with a mnemonic seed - */ - needsMnemonic(hasMnemonic: boolean, callback: () => T): T | null { - if (hasMnemonic) { - return callback(); - } - - this.#events.emit( - NativeEvents.MNEMONIC_REQUIRED, - core.makeEvent({ - message_type: NativeEvents.MNEMONIC_REQUIRED, - from_wallet: true, - }) - ); - - return null; - } -} - -class NativeHDWalletInfo - extends MixinNativeBTCWalletInfo( - MixinNativeFioWalletInfo( - MixinNativeETHWalletInfo( - MixinNativeCosmosWalletInfo( - MixinNativeThorchainWalletInfo( - MixinNativeSecretWalletInfo( - MixinNativeTerraWalletInfo( - MixinNativeKavaWalletInfo( - MixinNativeArkeoWalletInfo( - MixinNativeOsmosisWalletInfo(MixinNativeMayachainWalletInfo(NativeHDWalletBase)) - ) - ) - ) - ) - ) - ) - ) - ) - ) - implements core.HDWalletInfo -{ - describePath(msg: core.DescribePath): core.PathDescription { - switch (msg.coin.toLowerCase()) { - case "bitcoin": - case "bitcoincash": - case "dash": - case "digibyte": - case "dogecoin": - case "litecoin": - case "testnet": { - const unknown = core.unknownUTXOPath(msg.path, msg.coin, msg.scriptType); - - if (!msg.scriptType) return unknown; - if (!super.btcSupportsCoinSync(msg.coin)) return unknown; - if (!super.btcSupportsScriptTypeSync(msg.coin, msg.scriptType)) return unknown; - - return core.describeUTXOPath(msg.path, msg.coin, msg.scriptType); - } - case "ethereum": - return core.describeETHPath(msg.path); - case "atom": - return core.cosmosDescribePath(msg.path); - case "rune": - case "trune": - case "thorchain": - return core.thorchainDescribePath(msg.path); - case "secret": - case "scrt": - case "tscrt": - return core.secretDescribePath(msg.path); - case "luna": - case "terra": - case "tluna": - return core.terraDescribePath(msg.path); - case "kava": - case "tkava": - return core.kavaDescribePath(msg.path); - case "osmosis": - case "osmo": - return core.osmosisDescribePath(msg.path); - case "fio": - return core.fioDescribePath(msg.path); - case "arkeo": - return core.arkeoDescribePath(msg.path); - case "cacao": - case "scacao": - case "mayachain": - case "maya": - return core.mayachainDescribePath(msg.path); - default: - throw new Error("Unsupported path"); - } - } -} - -export class NativeHDWallet - extends MixinNativeBTCWallet( - MixinNativeFioWallet( - MixinNativeETHWallet( - MixinNativeCosmosWallet( - MixinNativeThorchainWallet( - MixinNativeSecretWallet( - MixinNativeTerraWallet( - MixinNativeKavaWallet( - MixinNativeOsmosisWallet(MixinNativeArkeoWallet(MixinNativeMayachainWallet(NativeHDWalletInfo))) - ) - ) - ) - ) - ) - ) - ) - ) - implements - core.HDWallet, - core.BTCWallet, - core.ETHWallet, - core.CosmosWallet, - core.OsmosisWallet, - core.FioWallet, - core.ThorchainWallet, - core.SecretWallet, - core.TerraWallet, - core.KavaWallet, - core.ArkeoWallet, - core.MayachainWallet -{ - readonly _supportsBTC = true; - readonly _supportsETH = true; - readonly _supportsCosmos = true; - readonly _supportsEthSwitchChain = false; - readonly _supportsAvalanche = true; - readonly _supportsOptimism = true; - readonly _supportsBSC = true; - readonly _supportsPolygon = true; - readonly _supportsGnosis = true; - readonly _supportsArbitrum = true; - readonly _supportsArbitrumNova = true; - readonly _supportsOsmosis = true; - readonly _supportsFio = true; - readonly _supportsThorchain = true; - readonly _supportsSecret = true; - readonly _supportsTerra = true; - readonly _supportsKava = true; - readonly _supportsArkeo = true; - readonly _supportsMayachain = true; - readonly _isNative = true; - - #deviceId: string; - #initialized = false; - #masterKey: Promise | undefined = undefined; - - constructor({ mnemonic, deviceId, masterKey }: NativeAdapterArgs) { - super(); - if (masterKey) { - this.#masterKey = Promise.resolve(masterKey); - } else if (mnemonic) { - this.#masterKey = (async () => { - const isolatedMnemonic = - typeof mnemonic === "string" ? await Isolation.Engines.Default.BIP39.Mnemonic.create(mnemonic) : mnemonic; - const seed = await isolatedMnemonic.toSeed(); - return await seed.toMasterKey(); - })(); - } - this.#deviceId = deviceId; - } - - async getFeatures(): Promise> { - return {}; - } - - async getDeviceID(): Promise { - return this.#deviceId; - } - - async getFirmwareVersion(): Promise { - return "Software"; - } - - async getModel(): Promise { - return "Native"; - } - - async getLabel(): Promise { - return "Native"; - } - - /* - * @see: https://github.com/satoshilabs/slips/blob/master/slip-0132.md - * to supports different styles of xpubs as can be defined by passing in a network to `fromSeed` - */ - async getPublicKeys(msg: Array): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const masterKey = await this.#masterKey!; - return await Promise.all( - msg.map(async (getPublicKey) => { - const { addressNList } = getPublicKey; - const network = getNetwork(getPublicKey.coin, getPublicKey.scriptType); - // TODO: return the xpub that's actually asked for, not the key of the hardened path - // It's done this way for hilarious historical reasons and will break ETH if fixed - const hardenedPath = core.hardenedPath(addressNList); - let node = await Isolation.Adapters.BIP32.create(masterKey, network); - if (hardenedPath.length > 0) node = await node.derivePath(core.addressNListToBIP32(hardenedPath)); - const xpub = node.neutered().toBase58(); - return { xpub }; - }) - ); - }); - } - - async isInitialized(): Promise { - return !!this.#initialized; - } - - async isLocked(): Promise { - return false; - } - - // eslint-disable-next-line @typescript-eslint/no-empty-function - async clearSession(): Promise {} - - async initialize(): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const masterKey = await this.#masterKey!; - try { - await Promise.all([ - super.btcInitializeWallet(masterKey), - super.ethInitializeWallet(masterKey), - super.cosmosInitializeWallet(masterKey), - super.osmosisInitializeWallet(masterKey), - super.fioInitializeWallet(masterKey), - super.thorchainInitializeWallet(masterKey), - super.secretInitializeWallet(masterKey), - super.terraInitializeWallet(masterKey), - super.kavaInitializeWallet(masterKey), - super.arkeoInitializeWallet(masterKey), - super.mayachainInitializeWallet(masterKey), - ]); - - this.#initialized = true; - } catch (e) { - console.error("NativeHDWallet:initialize:error", e); - this.#initialized = false; - await this.wipe(); - } - - return this.#initialized; - }); - } - - async ping(msg: core.Ping): Promise { - return { msg: msg.msg }; - } - - // eslint-disable-next-line @typescript-eslint/no-empty-function - async sendPin(): Promise {} - - // eslint-disable-next-line @typescript-eslint/no-empty-function - async sendPassphrase(): Promise {} - - // eslint-disable-next-line @typescript-eslint/no-empty-function - async sendCharacter(): Promise {} - - // eslint-disable-next-line @typescript-eslint/no-empty-function - async sendWord(): Promise {} - - // eslint-disable-next-line @typescript-eslint/no-empty-function - async cancel(): Promise {} - - async wipe(): Promise { - const oldMasterKey = this.#masterKey; - this.#initialized = false; - this.#masterKey = undefined; - - super.btcWipe(); - super.ethWipe(); - super.cosmosWipe(); - super.osmosisWipe(); - super.fioWipe(); - super.thorchainWipe(); - super.secretWipe(); - super.terraWipe(); - super.kavaWipe(); - super.arkeoWipe(); - super.mayachainWipe(); - - (await oldMasterKey)?.revoke?.(); - } - - // eslint-disable-next-line @typescript-eslint/no-empty-function - async reset(): Promise {} - - // eslint-disable-next-line @typescript-eslint/no-empty-function - async recover(): Promise {} - - async loadDevice(msg?: LoadDevice): Promise { - this.#masterKey = Promise.resolve( - await (async (mnemonic, masterKey) => { - if (masterKey !== undefined) { - return masterKey; - } else if (mnemonic !== undefined) { - const isolatedMnemonic = await (async () => { - if (isMnemonicInterface(mnemonic)) return mnemonic; - if (typeof mnemonic === "string" && bip39.validateMnemonic(mnemonic)) { - return await Isolation.Engines.Default.BIP39.Mnemonic.create(mnemonic); - } - throw new Error("Required property [mnemonic] is invalid"); - })(); - const seed = await isolatedMnemonic.toSeed(); - seed.addRevoker?.(() => isolatedMnemonic.revoke?.()); - const out = await seed.toMasterKey(); - out.addRevoker?.(() => seed.revoke?.()); - return out; - } - throw new Error("Either [mnemonic] or [masterKey] is required"); - })(msg?.mnemonic, msg?.masterKey) - ); - - if (typeof msg?.deviceId === "string") this.#deviceId = msg?.deviceId; - - this.#initialized = false; - await this.initialize(); - - // Once we've been seeded with a mnemonic we re-emit the connected event - this.events.emit( - NativeEvents.READY, - core.makeEvent({ - message_type: NativeEvents.READY, - from_wallet: true, - }) - ); - } - - async disconnect(): Promise { - await this.wipe(); - } -} - -export function isNative(wallet: core.HDWallet): wallet is NativeHDWallet { - return isObject(wallet) && (wallet as any)._isNative; -} - -export function info() { - return new NativeHDWalletInfo(); -} - -export function create(args: NativeAdapterArgs): NativeHDWallet { - return new NativeHDWallet(args); -} - -// This prevents any malicious code from overwriting the prototype -// to potentially steal the mnemonic when calling "loadDevice" -Object.freeze(Object.getPrototypeOf(NativeHDWallet)); diff --git a/packages/hdwallet-native/src/networks.test.ts b/packages/hdwallet-native/src/networks.test.ts deleted file mode 100644 index 1e780e07..00000000 --- a/packages/hdwallet-native/src/networks.test.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { getNetwork } from "./networks"; - -describe("getNetwork", () => { - it("should return the bitcoin network", () => { - expect(getNetwork("bitcoin")).toMatchObject({ - bech32: "bc", - pubKeyHash: 0x00, - scriptHash: 0x05, - wif: 0x80, - }); - }); - - it("should return the testnet network", () => { - expect(getNetwork("testnet")).toMatchObject({ - bech32: "tb", - pubKeyHash: 0x6f, - scriptHash: 0xc4, - wif: 0xef, - }); - }); - - it("should throw if asked for an unsupported network", () => { - expect(() => getNetwork("foobar")).toThrowError("foobar network not supported"); - }); - - it("should throw if asked for an unsupported script type", () => { - expect(() => getNetwork("bitcoin", "foobar" as any)).toThrowError("foobar not supported for bitcoin network"); - }); -}); diff --git a/packages/hdwallet-native/src/networks.ts b/packages/hdwallet-native/src/networks.ts deleted file mode 100644 index 14eaeef9..00000000 --- a/packages/hdwallet-native/src/networks.ts +++ /dev/null @@ -1,196 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as bitcoin from "@shapeshiftoss/bitcoinjs-lib"; - -import { BTCScriptType } from "./bitcoin"; - -type BIP32 = { - bip32: { - public: number; - private: number; - }; -}; - -type BIP32ByScriptType = Partial>; - -const bip32BTC: BIP32ByScriptType = { - p2sh: { - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - }, - p2pkh: { - bip32: { - public: 0x0488b21e, - private: 0x0488ade4, - }, - }, - "p2sh-p2wpkh": { - bip32: { - public: 0x049d7cb2, - private: 0x049d7878, - }, - }, - p2wpkh: { - bip32: { - public: 0x04b24746, - private: 0x04b2430c, - }, - }, -}; - -type NetworkDescription = { - base: Omit; -} & BIP32ByScriptType; - -type Networks = Record; - -const networks: Networks = { - bitcoin: { - base: { - messagePrefix: "\x18Bitcoin Signed Message:\n", - bech32: "bc", - pubKeyHash: 0x00, - scriptHash: 0x05, - wif: 0x80, - }, - ...bip32BTC, - }, - dash: { - base: { - messagePrefix: "unused", - bech32: "", - pubKeyHash: 0x4c, - scriptHash: 0x10, - wif: 0xcc, - }, - p2sh: bip32BTC.p2sh, - p2pkh: bip32BTC.p2pkh, - }, - digibyte: { - base: { - messagePrefix: "\x19Digibyte Signed Message:\n", - bech32: "dgb", - pubKeyHash: 0x1e, - scriptHash: 0x3f, - wif: 0x80, - }, - ...bip32BTC, - }, - dogecoin: { - base: { - messagePrefix: "\x19Dogecoin Signed Message:\n", - bech32: "", - pubKeyHash: 0x1e, - scriptHash: 0x16, - wif: 0x9e, - }, - p2sh: { - bip32: { - public: 0x02facafd, - private: 0x02fac398, - }, - }, - p2pkh: { - bip32: { - public: 0x02facafd, - private: 0x02fac398, - }, - }, - }, - litecoin: { - base: { - messagePrefix: "\x19Litecoin Signed Message:\n", - bech32: "ltc", - pubKeyHash: 0x30, - scriptHash: 0x32, - wif: 0xb0, - }, - p2sh: { - bip32: { - public: 0x019da462, - private: 0x019d9cfe, - }, - }, - p2pkh: { - bip32: { - public: 0x019da462, - private: 0x019d9cfe, - }, - }, - "p2sh-p2wpkh": { - bip32: { - public: 0x01b26ef6, - private: 0x01b26792, - }, - }, - p2wpkh: bip32BTC.p2wpkh, - }, - testnet: { - base: { - messagePrefix: "\x18Bitcoin Signed Message:\n", - bech32: "tb", - pubKeyHash: 0x6f, - scriptHash: 0xc4, - wif: 0xef, - }, - p2sh: { - bip32: { - public: 0x043587cf, - private: 0x04358394, - }, - }, - p2pkh: { - bip32: { - public: 0x043587cf, - private: 0x04358394, - }, - }, - "p2sh-p2wpkh": { - bip32: { - public: 0x044a5262, - private: 0x044a4e28, - }, - }, - p2wpkh: { - bip32: { - public: 0x045f1cf6, - private: 0x045f18bc, - }, - }, - }, -}; - -//TODO: all below are missing network data -for (const coin of [ - "bitcoincash", - "thorchain", - "secret", - "terra", - "kava", - "cardano", - "cosmos", - "osmosis", - "ethereum", - "arkeo", - "mayachain", -]) - networks[coin] = networks.bitcoin; - -export function getNetwork(coin: string, scriptType?: BTCScriptType): bitcoin.Network { - coin = coin.toLowerCase(); - scriptType = scriptType || core.BTCOutputScriptType.PayToMultisig; - - if (!(coin in networks)) throw new Error(`${coin} network not supported`); - const network = networks[coin]; - - const bip32 = network[scriptType as core.BTCOutputScriptType]; - if (!bip32) { - throw new Error(`${scriptType} not supported for ${coin} network`); - } - - return { - ...network.base, - ...bip32, - }; -} diff --git a/packages/hdwallet-native/src/osmosis.test.ts b/packages/hdwallet-native/src/osmosis.test.ts deleted file mode 100644 index db82d175..00000000 --- a/packages/hdwallet-native/src/osmosis.test.ts +++ /dev/null @@ -1,92 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeOsmosisWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - expect(await untouchable.call(info, "osmosisSupportsNetwork")).toBe(true); - expect(await untouchable.call(info, "osmosisSupportsSecureTransfer")).toBe(false); - expect(untouchable.call(info, "osmosisSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.osmosisGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "osmosisNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeOsmosisWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - expect(await wallet.initialize()).toBe(true); - }); - - it("should generate a correct osmosis address", async () => { - expect(await wallet.osmosisGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0") })).toBe( - "osmo1knuunh0lmwyrkjmrj7sky49uxk3peyzh2tlskm" - ); - }); - - it("should generate another correct osmosis address", async () => { - expect(await wallet.osmosisGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/118'/1337'/123/4") })).toBe( - "osmo14k4dnrrmxdch6nkvvuugsywrgmvlwrqs2f6kye" - ); - }); - - it("should sign a transaction correctly", async () => { - const signed = await wallet.osmosisSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/118'/0'/0/0"), - tx: { - msg: [ - { - type: "cosmos-sdk/MsgSend", - value: { - from_address: "osmo1knuunh0lmwyrkjmrj7sky49uxk3peyzh2tlskm", - to_address: "osmo1knuunh0lmwyrkjmrj7sky49uxk3peyzh2tlskm", - amount: [ - { - denom: "uosmo", - amount: "1000", - }, - ], - }, - }, - ], - fee: { - amount: [ - { - amount: "100", - denom: "uosmo", - }, - ], - gas: "100000", - }, - signatures: [], - memo: "foobar", - }, - chain_id: "osmosishub-4", - account_number: "95421", - sequence: "35", - }); - await expect(signed?.signatures?.length).toBe(1); - await expect(signed?.signatures?.[0]).toMatchInlineSnapshot( - `"m5wzNYyoP1UBsl4QI7cHDHCOcQ5AHBDbx4im19ip3icMJ+S/Ne2To34gNeUOaudlGP1Q7UGk5NNcXa7r1Us47A=="` - ); - }); -}); diff --git a/packages/hdwallet-native/src/osmosis.ts b/packages/hdwallet-native/src/osmosis.ts deleted file mode 100644 index 7aebadd6..00000000 --- a/packages/hdwallet-native/src/osmosis.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { StdTx } from "@cosmjs/amino"; -import { SignerData } from "@cosmjs/stargate"; -import * as core from "@keepkey/hdwallet-core"; -import * as bech32 from "bech32"; -import CryptoJS from "crypto-js"; -import PLazy from "p-lazy"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import * as util from "./util"; - -const OSMOSIS_CHAIN = "osmosis-1"; - -const protoTxBuilder = PLazy.from(() => import("@keepkey/proto-tx-builder")); - -export function MixinNativeOsmosisWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeOsmosisWalletInfo extends Base implements core.OsmosisWalletInfo { - readonly _supportsOsmosisInfo = true; - async osmosisSupportsNetwork(): Promise { - return true; - } - - async osmosisSupportsSecureTransfer(): Promise { - return false; - } - - osmosisSupportsNativeShapeShift(): boolean { - return false; - } - - osmosisGetAccountPaths(msg: core.OsmosisGetAccountPaths): Array { - const slip44 = core.slip44ByCoin("Osmo"); - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - osmosisNextAccountPath(msg: core.OsmosisAccountPath): core.OsmosisAccountPath | undefined { - // Only support one account for now. - return undefined; - } - }; -} - -export function MixinNativeOsmosisWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeOsmosisWallet extends Base { - readonly _supportsOsmosis = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async osmosisInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - osmosisWipe(): void { - this.#masterKey = undefined; - } - - osmosisBech32ify(address: ArrayLike, prefix: string): string { - const words = bech32.toWords(address); - return bech32.encode(prefix, words); - } - - createOsmosisAddress(publicKey: string) { - const message = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey)); - const hash = CryptoJS.RIPEMD160(message as any).toString(); - const address = Buffer.from(hash, `hex`); - return this.osmosisBech32ify(address, `osmo`); - } - - async osmosisGetAddress(msg: core.OsmosisGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "osmosis"); - return this.createOsmosisAddress(keyPair.publicKey.toString("hex")); - }); - } - - async osmosisSignTx(msg: core.OsmosisSignTx): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "osmosis"); - const adapter = await Isolation.Adapters.CosmosDirect.create(keyPair.node, "osmo"); - - const signerData: SignerData = { - sequence: Number(msg.sequence), - accountNumber: Number(msg.account_number), - chainId: OSMOSIS_CHAIN, - }; - return (await protoTxBuilder).sign(adapter.address, msg.tx as StdTx, adapter, signerData, "osmos"); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/secret.test.ts b/packages/hdwallet-native/src/secret.test.ts deleted file mode 100644 index c8d7dd32..00000000 --- a/packages/hdwallet-native/src/secret.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeSecretWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - await expect(untouchable.call(info, "secretSupportsNetwork")).resolves.toBe(true); - await expect(untouchable.call(info, "secretSupportsSecureTransfer")).resolves.toBe(false); - expect(untouchable.call(info, "secretSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.secretGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/529'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "secretNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeSecretWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - await expect(wallet.initialize()).resolves.toBe(true); - }); - - it("should generate a correct secret address", async () => { - await expect( - wallet.secretGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/529'/0'/0/0") }) - ).resolves.toBe("secret189wrfk2fsynjlz6jcn54wzdcud3a6k8vqa0ggu"); - }); - - it("should generate another correct secret address", async () => { - await expect( - wallet.secretGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/529'/1337'/123/4") }) - ).resolves.toBe("secret1wmmewcjt2s09r48ya8mtdfyy0rnnza20xnx6fs"); - }); - - it("should signing transactions", async () => { - const signed = await wallet.secretSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/529'/0'/0/0"), - tx: { - msg: [{ type: "foo", value: "bar" }], - fee: { - amount: [{ denom: "foo", amount: "bar" }], - gas: "baz", - }, - signatures: null, - memo: "foobar", - }, - chain_id: "foobar", - account_number: 123, - sequence: 456, - }); - expect(signed.signatures.length).toBe(1); - expect(signed.signatures[0].pub_key.value).toMatchInlineSnapshot(`"A2UVKphVsesrnAQEtX4K+qk8Z84wa5xD5mxzdPykAiyR"`); - expect(signed.signatures[0].signature).toMatchInlineSnapshot( - `"f4HKv09XvsGQn74y4MHL+M+wP/uBjHsIn5PwPfq7xMI7CJkS22Pxx7KlXpeUzCjiaSZvEEIuxbkd9J+Q4g86jg=="` - ); - }); -}); diff --git a/packages/hdwallet-native/src/secret.ts b/packages/hdwallet-native/src/secret.ts deleted file mode 100644 index 3a8e55e1..00000000 --- a/packages/hdwallet-native/src/secret.ts +++ /dev/null @@ -1,95 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as bech32 from "bech32"; -import CryptoJS from "crypto-js"; -import * as txBuilder from "tendermint-tx-builder"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import * as util from "./util"; - -export function MixinNativeSecretWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeSecretWalletInfo extends Base implements core.SecretWalletInfo { - readonly _supportsSecretInfo = true; - async secretSupportsNetwork(): Promise { - return true; - } - - async secretSupportsSecureTransfer(): Promise { - return false; - } - - secretSupportsNativeShapeShift(): boolean { - return false; - } - - secretGetAccountPaths(msg: core.SecretGetAccountPaths): Array { - const slip44 = core.slip44ByCoin("Secret"); - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - secretNextAccountPath(msg: core.SecretAccountPath): core.SecretAccountPath | undefined { - // Only support one account for now. - return undefined; - } - }; -} - -export function MixinNativeSecretWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeSecretWallet extends Base { - readonly _supportsSecret = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async secretInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - secretWipe(): void { - this.#masterKey = undefined; - } - - secretBech32ify(address: ArrayLike, prefix: string): string { - const words = bech32.toWords(address); - return bech32.encode(prefix, words); - } - - createSecretAddress(publicKey: string) { - const message = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey)); - const hash = CryptoJS.RIPEMD160(message as any).toString(); - const address = Buffer.from(hash, `hex`); - return this.secretBech32ify(address, `secret`); - } - - async secretGetAddress(msg: core.SecretGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "secret"); - return this.createSecretAddress(keyPair.publicKey.toString("hex")); - }); - } - - async secretSignTx(msg: core.SecretSignTx): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "secret"); - // @TODO: This needs to be fixed after the change to tendermint serialization - const adapter = await Isolation.Adapters.Cosmos.create(keyPair); - const result = await txBuilder.sign( - msg.tx, - adapter, - String(msg.sequence), - String(msg.account_number), - msg.chain_id - ); - return txBuilder.createSignedTx(msg.tx, result); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/terra.test.ts b/packages/hdwallet-native/src/terra.test.ts deleted file mode 100644 index ec8cdc09..00000000 --- a/packages/hdwallet-native/src/terra.test.ts +++ /dev/null @@ -1,74 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeTerraWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - await expect(untouchable.call(info, "terraSupportsNetwork")).resolves.toBe(true); - await expect(untouchable.call(info, "terraSupportsSecureTransfer")).resolves.toBe(false); - expect(untouchable.call(info, "terraSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.terraGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/330'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "terraNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeTerraWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - await expect(wallet.initialize()).resolves.toBe(true); - }); - - it("should generate a correct terra address", async () => { - await expect(wallet.terraGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/330'/0'/0/0") })).resolves.toBe( - "terra1f95csal3u6cyyj23ept3x7ap3u247npf8u2yhz" - ); - }); - - it("should generate another correct terra address", async () => { - await expect( - wallet.terraGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/330'/1337'/123/4") }) - ).resolves.toBe("terra153l3gzmg5xlr8aldndpcg7achjejre04azdf9q"); - }); - - it("does not support signing transactions", async () => { - const signed = await wallet.terraSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/330'/0'/0/0"), - tx: { - msg: [{ type: "foo", value: "bar" }], - fee: { - amount: [{ denom: "foo", amount: "bar" }], - gas: "baz", - }, - signatures: null, - memo: "foobar", - }, - chain_id: "foobar", - account_number: "foo", - sequence: "bar", - }); - expect(signed.signatures.length).toBe(1); - expect(signed.signatures[0].pub_key.value).toMatchInlineSnapshot(`"A6cAUgKWL3/P3nQY+j2fMUBaAW/QC/FGmQzTJ4nqXo0E"`); - expect(signed.signatures[0].signature).toMatchInlineSnapshot( - `"zUPR10sr2QwRa10fcb3z/KC6/mWuLq0iff5ImhylIJpqU1RSg49Jxbmvp07D3sWuY0fE5mcSdMWQXWJFw2zsWQ=="` - ); - }); -}); diff --git a/packages/hdwallet-native/src/terra.ts b/packages/hdwallet-native/src/terra.ts deleted file mode 100644 index 77299952..00000000 --- a/packages/hdwallet-native/src/terra.ts +++ /dev/null @@ -1,90 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import * as bech32 from "bech32"; -import CryptoJS from "crypto-js"; -import * as txBuilder from "tendermint-tx-builder"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import * as util from "./util"; - -export function MixinNativeTerraWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeTerraWalletInfo extends Base implements core.TerraWalletInfo { - readonly _supportsTerraInfo = true; - - async terraSupportsNetwork(): Promise { - return true; - } - - async terraSupportsSecureTransfer(): Promise { - return false; - } - - terraSupportsNativeShapeShift(): boolean { - return false; - } - - terraGetAccountPaths(msg: core.TerraGetAccountPaths): Array { - const slip44 = core.slip44ByCoin("Terra"); - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - terraNextAccountPath(msg: core.TerraAccountPath): core.TerraAccountPath | undefined { - // Only support one account for now. - return undefined; - } - }; -} - -export function MixinNativeTerraWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeTerraWallet extends Base { - readonly _supportsTerra = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async terraInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - terraWipe(): void { - this.#masterKey = undefined; - } - - terraBech32ify(address: ArrayLike, prefix: string): string { - const words = bech32.toWords(address); - return bech32.encode(prefix, words); - } - - createTerraAddress(publicKey: string) { - const message = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey)); - const hash = CryptoJS.RIPEMD160(message as any).toString(); - const address = Buffer.from(hash, `hex`); - return this.terraBech32ify(address, `terra`); - } - - async terraGetAddress(msg: core.TerraGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "terra"); - return this.createTerraAddress(keyPair.publicKey.toString("hex")); - }); - } - - async terraSignTx(msg: core.TerraSignTx): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "terra"); - // @TODO: This needs to be fixed after the change to tendermint serialization - const adapter = await Isolation.Adapters.Cosmos.create(keyPair); - const result = await txBuilder.sign(msg.tx, adapter, msg.sequence, msg.account_number, "terra"); - return txBuilder.createSignedTx(msg.tx, result); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/thorchain.test.ts b/packages/hdwallet-native/src/thorchain.test.ts deleted file mode 100644 index 5b0d4c6d..00000000 --- a/packages/hdwallet-native/src/thorchain.test.ts +++ /dev/null @@ -1,88 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; - -import * as native from "./native"; - -const MNEMONIC = "all all all all all all all all all all all all"; - -const mswMock = require("mswMock")().startServer(); -afterEach(() => expect(mswMock).not.toHaveBeenCalled()); - -const untouchable = require("untouchableMock"); - -describe("NativeThorchainWalletInfo", () => { - const info = native.info(); - - it("should return some static metadata", async () => { - await expect(untouchable.call(info, "thorchainSupportsNetwork")).resolves.toBe(true); - await expect(untouchable.call(info, "thorchainSupportsSecureTransfer")).resolves.toBe(false); - expect(untouchable.call(info, "thorchainSupportsNativeShapeShift")).toBe(false); - }); - - it("should return the correct account paths", async () => { - const paths = info.thorchainGetAccountPaths({ accountIdx: 0 }); - expect(paths).toMatchObject([{ addressNList: core.bip32ToAddressNList("m/44'/931'/0'/0/0") }]); - }); - - it("does not support getting the next account path", async () => { - expect(untouchable.call(info, "thorchainNextAccountPath", {})).toBe(undefined); - }); -}); - -describe("NativeThorchainWallet", () => { - let wallet: native.NativeHDWallet; - - beforeEach(async () => { - wallet = native.create({ deviceId: "native" }); - await wallet.loadDevice({ mnemonic: MNEMONIC }); - await expect(wallet.initialize()).resolves.toBe(true); - }); - - it("should generate a correct thorchain address", async () => { - await expect( - wallet.thorchainGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/931'/0'/0/0") }) - ).resolves.toBe("thor1ujumx36gj3jv33gcw49dfafdddza3kdcd38paq"); - }); - - it("should generate another correct thorchain address", async () => { - await expect( - wallet.thorchainGetAddress({ addressNList: core.bip32ToAddressNList("m/44'/931'/1337'/123/4") }) - ).resolves.toBe("thor14hqwsy4qpwzsdk2l3h3q82eghg4ctaa38rx63g"); - }); - - it("should sign a transaction correctly", async () => { - const signed = await wallet.thorchainSignTx({ - addressNList: core.bip32ToAddressNList("m/44'/931'/0'/0/0"), - tx: { - msg: [ - { - type: "thorchain/MsgSend", - value: { - from_address: "thor1ujumx36gj3jv33gcw49dfafdddza3kdcd38paq", - to_address: "thor14hqwsy4qpwzsdk2l3h3q82eghg4ctaa38rx63g", - amount: [ - { - denom: "rune", - amount: "123456", - }, - ], - }, - }, - ], - fee: { - amount: [], - gas: "1000000", - }, - memo: "hdwallet thorchain test", - signatures: [], - }, - chain_id: "thorchain-mainnet-v1", - account_number: "2722", - sequence: "11", - }); - - expect(signed?.signatures?.length).toBe(1); - expect(signed?.signatures?.[0]).toBe( - "hKgBg+lB6poFDTMIKPA/hBMkgrKb0BJ5aP1vy5KMze8/joV30TPZrayrLBK42/MDSCmVauNJbfwvRhrCQwRCmg==" - ); - }); -}); diff --git a/packages/hdwallet-native/src/thorchain.ts b/packages/hdwallet-native/src/thorchain.ts deleted file mode 100644 index 0c552ba5..00000000 --- a/packages/hdwallet-native/src/thorchain.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { StdTx } from "@cosmjs/amino"; -import type { SignerData } from "@cosmjs/stargate"; -import * as core from "@keepkey/hdwallet-core"; -import * as bech32 from "bech32"; -import CryptoJS from "crypto-js"; -import PLazy from "p-lazy"; - -import * as Isolation from "./crypto/isolation"; -import { NativeHDWalletBase } from "./native"; -import * as util from "./util"; - -const THOR_CHAIN = "thorchain-mainnet-v1"; - -const protoTxBuilder = PLazy.from(() => import("@keepkey/proto-tx-builder")); - -export function MixinNativeThorchainWalletInfo>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeThorchainWalletInfo extends Base implements core.ThorchainWalletInfo { - readonly _supportsThorchainInfo = true; - async thorchainSupportsNetwork(): Promise { - return true; - } - - async thorchainSupportsSecureTransfer(): Promise { - return false; - } - - thorchainSupportsNativeShapeShift(): boolean { - return false; - } - - thorchainGetAccountPaths(msg: core.ThorchainGetAccountPaths): Array { - const slip44 = core.slip44ByCoin("Thorchain"); - return [ - { - addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0], - }, - ]; - } - - // eslint-disable-next-line @typescript-eslint/no-unused-vars - thorchainNextAccountPath(msg: core.ThorchainAccountPath): core.ThorchainAccountPath | undefined { - // Only support one account for now. - return undefined; - } - }; -} - -export function MixinNativeThorchainWallet>(Base: TBase) { - // eslint-disable-next-line @typescript-eslint/no-shadow - return class MixinNativeThorchainWallet extends Base { - readonly _supportsThorchain = true; - - #masterKey: Isolation.Core.BIP32.Node | undefined; - - async thorchainInitializeWallet(masterKey: Isolation.Core.BIP32.Node): Promise { - this.#masterKey = masterKey; - } - - thorchainWipe(): void { - this.#masterKey = undefined; - } - - thorchainBech32ify(address: ArrayLike, prefix: string): string { - const words = bech32.toWords(address); - return bech32.encode(prefix, words); - } - - createThorchainAddress(publicKey: string) { - const message = CryptoJS.SHA256(CryptoJS.enc.Hex.parse(publicKey)); - const hash = CryptoJS.RIPEMD160(message as any).toString(); - const address = Buffer.from(hash, `hex`); - return this.thorchainBech32ify(address, `thor`); - } - - async thorchainGetAddress(msg: core.ThorchainGetAddress): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "thorchain"); - return this.createThorchainAddress(keyPair.publicKey.toString("hex")); - }); - } - - async thorchainSignTx(msg: core.ThorchainSignTx): Promise { - return this.needsMnemonic(!!this.#masterKey, async () => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const keyPair = await util.getKeyPair(this.#masterKey!, msg.addressNList, "thorchain"); - const adapter = await Isolation.Adapters.CosmosDirect.create(keyPair.node, "thor"); - - const signerData: SignerData = { - sequence: Number(msg.sequence), - accountNumber: Number(msg.account_number), - chainId: THOR_CHAIN, - }; - - return (await protoTxBuilder).sign(adapter.address, msg.tx as StdTx, adapter, signerData, "thor"); - }); - } - }; -} diff --git a/packages/hdwallet-native/src/util.test.ts b/packages/hdwallet-native/src/util.test.ts deleted file mode 100644 index ebc75b41..00000000 --- a/packages/hdwallet-native/src/util.test.ts +++ /dev/null @@ -1,21 +0,0 @@ -import * as Isolation from "./crypto/isolation"; -import * as util from "./util"; - -describe("getKeyPair", () => { - let masterKey: Isolation.Core.BIP32.Node; - - beforeAll(async () => { - const mnemonic = await Isolation.Engines.Default.BIP39.Mnemonic.create( - "all all all all all all all all all all all all" - ); - const seed = await mnemonic.toSeed(); - masterKey = await seed.toMasterKey(); - }); - - it("should produce the key pair at m/1337/0", async () => { - const keyPair = await util.getKeyPair(masterKey, [1337, 0], "bitcoin"); - expect(keyPair.publicKey.toString("hex")).toEqual( - "029bf8b52f7efe773323bf1746b8489c4e823adb73644476cc099df57b1be0cb94" - ); - }); -}); diff --git a/packages/hdwallet-native/src/util.ts b/packages/hdwallet-native/src/util.ts deleted file mode 100644 index 7e89d99e..00000000 --- a/packages/hdwallet-native/src/util.ts +++ /dev/null @@ -1,31 +0,0 @@ -import * as core from "@keepkey/hdwallet-core"; -import { ethers } from "ethers"; - -import { BTCScriptType } from "./bitcoin"; -import * as Isolation from "./crypto/isolation"; -import { getNetwork } from "./networks"; - -export async function getKeyPair( - node: Isolation.Core.BIP32.Node, - addressNList: number[], - coin: core.Coin, - scriptType?: BTCScriptType -): Promise { - const network = getNetwork(coin, scriptType); - const wallet = await Isolation.Adapters.BIP32.create(node, network); - const path = core.addressNListToBIP32(addressNList); - return await wallet.derivePath(path); -} - -export function buildMessage(message: ethers.utils.BytesLike): Uint8Array { - const messageBytes = - typeof message === "string" && !ethers.utils.isHexString(message) - ? ethers.utils.toUtf8Bytes(message) - : ethers.utils.arrayify(message); - - return ethers.utils.concat([ - ethers.utils.toUtf8Bytes("\x19Ethereum Signed Message:\n"), - ethers.utils.toUtf8Bytes(String(messageBytes.length)), - messageBytes, - ]); -} diff --git a/packages/hdwallet-native/tsconfig.json b/packages/hdwallet-native/tsconfig.json deleted file mode 100644 index 841f3956..00000000 --- a/packages/hdwallet-native/tsconfig.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "rootDir": "src", - "outDir": "dist" - }, - "include": ["src/**/*"], - "files": ["./src/modules.d.ts"], - "exclude": ["node_modules", "dist", "**/*.test.ts"], - "references": [{ "path": "../hdwallet-core" }] -} diff --git a/tsconfig.json b/tsconfig.json index acba7e93..03635b6b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -39,7 +39,6 @@ { "path": "./packages/hdwallet-keepkey-nodehid" }, { "path": "./packages/hdwallet-keepkey-nodewebusb" }, { "path": "./packages/hdwallet-keepkey-tcp" }, - { "path": "./packages/hdwallet-keepkey-webusb" }, - { "path": "./packages/hdwallet-native" }, + { "path": "./packages/hdwallet-keepkey-webusb" } ] } diff --git a/yarn.lock b/yarn.lock index b8a42578..9677ac4c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -221,7 +221,7 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/runtime@^7.19.0", "@babel/runtime@^7.25.0": +"@babel/runtime@^7.19.0": version "7.28.6" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.6.tgz#d267a43cb1836dc4d182cce93ae75ba954ef6d2b" integrity sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA== @@ -261,28 +261,6 @@ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== -"@bithighlander/bitcoin-cash-js-lib@^5.2.1": - version "5.2.1" - resolved "https://registry.yarnpkg.com/@bithighlander/bitcoin-cash-js-lib/-/bitcoin-cash-js-lib-5.2.1.tgz#3153dec5774b0574a2347f6ca75cf3d7399af1b2" - integrity sha512-FaqmntBmeiLxwwCuc6n7kZCUi3ZT1b75tWxpduV3Rdw3pOx17cuptsBuay30YX4v/gnXvPkjO8AF0XsO4kn6IQ== - dependencies: - bech32 "^1.1.2" - big-integer "^1.6.44" - 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" - "@cnakazawa/watch@^1.0.3": version "1.0.4" resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a" @@ -592,11 +570,6 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@eivifj/dot@^1.0.1": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@eivifj/dot/-/dot-1.0.3.tgz#b3a6d9662cd84ff4105e0f05620d1045e9d0d9fc" - integrity sha512-UE2x9N7XD/1qqtXA+4CZPD1RQAlM0lEdXdy09CJ/wNR+mgGKqwLRH4BGGfOAWwwz06pIT3c2tC4gvXbntGAeMA== - "@electron/get@^1.0.1": version "1.14.1" resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.14.1.tgz#16ba75f02dffb74c23965e72d617adc721d27f40" @@ -693,22 +666,7 @@ ethereum-cryptography "^2.0.0" micro-ftch "^0.3.1" -"@ethersproject/abi@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.7.0.tgz#b3f3e045bbbeed1af3947335c247ad625a44e449" - integrity sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/abi@^5.6.3", "@ethersproject/abi@^5.7.0": +"@ethersproject/abi@^5.6.3": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.8.0.tgz#e79bb51940ac35fe6f3262d7fe2cdb25ad5f07d9" integrity sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q== @@ -723,20 +681,7 @@ "@ethersproject/properties" "^5.8.0" "@ethersproject/strings" "^5.8.0" -"@ethersproject/abstract-provider@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz#b0a8550f88b6bf9d51f90e4795d48294630cb9ef" - integrity sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - -"@ethersproject/abstract-provider@^5.7.0", "@ethersproject/abstract-provider@^5.8.0": +"@ethersproject/abstract-provider@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz#7581f9be601afa1d02b95d26b9d9840926a35b0c" integrity sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg== @@ -749,18 +694,7 @@ "@ethersproject/transactions" "^5.8.0" "@ethersproject/web" "^5.8.0" -"@ethersproject/abstract-signer@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz#13f4f32117868452191a4649723cb086d2b596b2" - integrity sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/abstract-signer@^5.7.0", "@ethersproject/abstract-signer@^5.8.0": +"@ethersproject/abstract-signer@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz#8d7417e95e4094c1797a9762e6789c7356db0754" integrity sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA== @@ -771,18 +705,7 @@ "@ethersproject/logger" "^5.8.0" "@ethersproject/properties" "^5.8.0" -"@ethersproject/address@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.7.0.tgz#19b56c4d74a3b0a46bfdbb6cfcc0a153fc697f37" - integrity sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - -"@ethersproject/address@^5.7.0", "@ethersproject/address@^5.8.0": +"@ethersproject/address@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.8.0.tgz#3007a2c352eee566ad745dca1dbbebdb50a6a983" integrity sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA== @@ -793,46 +716,14 @@ "@ethersproject/logger" "^5.8.0" "@ethersproject/rlp" "^5.8.0" -"@ethersproject/base64@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.7.0.tgz#ac4ee92aa36c1628173e221d0d01f53692059e1c" - integrity sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - -"@ethersproject/base64@^5.7.0", "@ethersproject/base64@^5.8.0": +"@ethersproject/base64@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/base64/-/base64-5.8.0.tgz#61c669c648f6e6aad002c228465d52ac93ee83eb" integrity sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ== dependencies: "@ethersproject/bytes" "^5.8.0" -"@ethersproject/basex@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.7.0.tgz#97034dc7e8938a8ca943ab20f8a5e492ece4020b" - integrity sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - -"@ethersproject/basex@^5.7.0", "@ethersproject/basex@^5.8.0": - version "5.8.0" - resolved "https://registry.yarnpkg.com/@ethersproject/basex/-/basex-5.8.0.tgz#1d279a90c4be84d1c1139114a1f844869e57d03a" - integrity sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q== - dependencies: - "@ethersproject/bytes" "^5.8.0" - "@ethersproject/properties" "^5.8.0" - -"@ethersproject/bignumber@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.7.0.tgz#e2f03837f268ba655ffba03a57853e18a18dc9c2" - integrity sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - bn.js "^5.2.1" - -"@ethersproject/bignumber@^5.7.0", "@ethersproject/bignumber@^5.8.0": +"@ethersproject/bignumber@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.8.0.tgz#c381d178f9eeb370923d389284efa19f69efa5d7" integrity sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA== @@ -841,66 +732,21 @@ "@ethersproject/logger" "^5.8.0" bn.js "^5.2.1" -"@ethersproject/bytes@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.7.0.tgz#a00f6ea8d7e7534d6d87f47188af1148d71f155d" - integrity sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/bytes@^5.7.0", "@ethersproject/bytes@^5.8.0": +"@ethersproject/bytes@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.8.0.tgz#9074820e1cac7507a34372cadeb035461463be34" integrity sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A== dependencies: "@ethersproject/logger" "^5.8.0" -"@ethersproject/constants@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.7.0.tgz#df80a9705a7e08984161f09014ea012d1c75295e" - integrity sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - -"@ethersproject/constants@^5.7.0", "@ethersproject/constants@^5.8.0": +"@ethersproject/constants@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/constants/-/constants-5.8.0.tgz#12f31c2f4317b113a4c19de94e50933648c90704" integrity sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg== dependencies: "@ethersproject/bignumber" "^5.8.0" -"@ethersproject/contracts@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.7.0.tgz#c305e775abd07e48aa590e1a877ed5c316f8bd1e" - integrity sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg== - dependencies: - "@ethersproject/abi" "^5.7.0" - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - -"@ethersproject/hash@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.7.0.tgz#eb7aca84a588508369562e16e514b539ba5240a7" - integrity sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/hash@^5.7.0", "@ethersproject/hash@^5.8.0": +"@ethersproject/hash@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/hash/-/hash-5.8.0.tgz#b8893d4629b7f8462a90102572f8cd65a0192b4c" integrity sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA== @@ -915,89 +761,7 @@ "@ethersproject/properties" "^5.8.0" "@ethersproject/strings" "^5.8.0" -"@ethersproject/hdnode@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.7.0.tgz#e627ddc6b466bc77aebf1a6b9e47405ca5aef9cf" - integrity sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/hdnode@^5.7.0", "@ethersproject/hdnode@^5.8.0": - version "5.8.0" - resolved "https://registry.yarnpkg.com/@ethersproject/hdnode/-/hdnode-5.8.0.tgz#a51ae2a50bcd48ef6fd108c64cbae5e6ff34a761" - integrity sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA== - dependencies: - "@ethersproject/abstract-signer" "^5.8.0" - "@ethersproject/basex" "^5.8.0" - "@ethersproject/bignumber" "^5.8.0" - "@ethersproject/bytes" "^5.8.0" - "@ethersproject/logger" "^5.8.0" - "@ethersproject/pbkdf2" "^5.8.0" - "@ethersproject/properties" "^5.8.0" - "@ethersproject/sha2" "^5.8.0" - "@ethersproject/signing-key" "^5.8.0" - "@ethersproject/strings" "^5.8.0" - "@ethersproject/transactions" "^5.8.0" - "@ethersproject/wordlists" "^5.8.0" - -"@ethersproject/json-wallets@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz#5e3355287b548c32b368d91014919ebebddd5360" - integrity sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g== - dependencies: - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/pbkdf2" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/json-wallets@^5.7.0": - version "5.8.0" - resolved "https://registry.yarnpkg.com/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz#d18de0a4cf0f185f232eb3c17d5e0744d97eb8c9" - integrity sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w== - dependencies: - "@ethersproject/abstract-signer" "^5.8.0" - "@ethersproject/address" "^5.8.0" - "@ethersproject/bytes" "^5.8.0" - "@ethersproject/hdnode" "^5.8.0" - "@ethersproject/keccak256" "^5.8.0" - "@ethersproject/logger" "^5.8.0" - "@ethersproject/pbkdf2" "^5.8.0" - "@ethersproject/properties" "^5.8.0" - "@ethersproject/random" "^5.8.0" - "@ethersproject/strings" "^5.8.0" - "@ethersproject/transactions" "^5.8.0" - aes-js "3.0.0" - scrypt-js "3.0.1" - -"@ethersproject/keccak256@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.7.0.tgz#3186350c6e1cd6aba7940384ec7d6d9db01f335a" - integrity sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - js-sha3 "0.8.0" - -"@ethersproject/keccak256@^5.7.0", "@ethersproject/keccak256@^5.8.0": +"@ethersproject/keccak256@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/keccak256/-/keccak256-5.8.0.tgz#d2123a379567faf2d75d2aaea074ffd4df349e6a" integrity sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng== @@ -1005,111 +769,26 @@ "@ethersproject/bytes" "^5.8.0" js-sha3 "0.8.0" -"@ethersproject/logger@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.7.0.tgz#6ce9ae168e74fecf287be17062b590852c311892" - integrity sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig== - -"@ethersproject/logger@^5.7.0", "@ethersproject/logger@^5.8.0": +"@ethersproject/logger@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/logger/-/logger-5.8.0.tgz#f0232968a4f87d29623a0481690a2732662713d6" integrity sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA== -"@ethersproject/networks@5.7.1": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.7.1.tgz#118e1a981d757d45ccea6bb58d9fd3d9db14ead6" - integrity sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/networks@^5.7.0", "@ethersproject/networks@^5.8.0": +"@ethersproject/networks@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/networks/-/networks-5.8.0.tgz#8b4517a3139380cba9fb00b63ffad0a979671fde" integrity sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg== dependencies: "@ethersproject/logger" "^5.8.0" -"@ethersproject/pbkdf2@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz#d2267d0a1f6e123f3771007338c47cccd83d3102" - integrity sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - -"@ethersproject/pbkdf2@^5.7.0", "@ethersproject/pbkdf2@^5.8.0": - version "5.8.0" - resolved "https://registry.yarnpkg.com/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz#cd2621130e5dd51f6a0172e63a6e4a0c0a0ec37e" - integrity sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg== - dependencies: - "@ethersproject/bytes" "^5.8.0" - "@ethersproject/sha2" "^5.8.0" - -"@ethersproject/properties@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.7.0.tgz#a6e12cb0439b878aaf470f1902a176033067ed30" - integrity sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw== - dependencies: - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/properties@^5.7.0", "@ethersproject/properties@^5.8.0": +"@ethersproject/properties@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/properties/-/properties-5.8.0.tgz#405a8affb6311a49a91dabd96aeeae24f477020e" integrity sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw== dependencies: "@ethersproject/logger" "^5.8.0" -"@ethersproject/providers@5.7.2": - version "5.7.2" - resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.7.2.tgz#f8b1a4f275d7ce58cf0a2eec222269a08beb18cb" - integrity sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/base64" "^5.7.0" - "@ethersproject/basex" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/networks" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/web" "^5.7.0" - bech32 "1.1.4" - ws "7.4.6" - -"@ethersproject/random@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.7.0.tgz#af19dcbc2484aae078bb03656ec05df66253280c" - integrity sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/random@^5.7.0", "@ethersproject/random@^5.8.0": - version "5.8.0" - resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.8.0.tgz#1bced04d49449f37c6437c701735a1a022f0057a" - integrity sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A== - dependencies: - "@ethersproject/bytes" "^5.8.0" - "@ethersproject/logger" "^5.8.0" - -"@ethersproject/rlp@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.7.0.tgz#de39e4d5918b9d74d46de93af80b7685a9c21304" - integrity sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/rlp@^5.7.0", "@ethersproject/rlp@^5.8.0": +"@ethersproject/rlp@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/rlp/-/rlp-5.8.0.tgz#5a0d49f61bc53e051532a5179472779141451de5" integrity sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q== @@ -1117,37 +796,7 @@ "@ethersproject/bytes" "^5.8.0" "@ethersproject/logger" "^5.8.0" -"@ethersproject/sha2@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.7.0.tgz#9a5f7a7824ef784f7f7680984e593a800480c9fb" - integrity sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - hash.js "1.1.7" - -"@ethersproject/sha2@^5.7.0", "@ethersproject/sha2@^5.8.0": - version "5.8.0" - resolved "https://registry.yarnpkg.com/@ethersproject/sha2/-/sha2-5.8.0.tgz#8954a613bb78dac9b46829c0a95de561ef74e5e1" - integrity sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A== - dependencies: - "@ethersproject/bytes" "^5.8.0" - "@ethersproject/logger" "^5.8.0" - hash.js "1.1.7" - -"@ethersproject/signing-key@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.7.0.tgz#06b2df39411b00bc57c7c09b01d1e41cf1b16ab3" - integrity sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - bn.js "^5.2.1" - elliptic "6.5.4" - hash.js "1.1.7" - -"@ethersproject/signing-key@^5.7.0", "@ethersproject/signing-key@^5.8.0": +"@ethersproject/signing-key@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/signing-key/-/signing-key-5.8.0.tgz#9797e02c717b68239c6349394ea85febf8893119" integrity sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w== @@ -1159,28 +808,7 @@ elliptic "6.6.1" hash.js "1.1.7" -"@ethersproject/solidity@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.7.0.tgz#5e9c911d8a2acce2a5ebb48a5e2e0af20b631cb8" - integrity sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/sha2" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/strings@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.7.0.tgz#54c9d2a7c57ae8f1205c88a9d3a56471e14d5ed2" - integrity sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/strings@^5.7.0", "@ethersproject/strings@^5.8.0": +"@ethersproject/strings@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/strings/-/strings-5.8.0.tgz#ad79fafbf0bd272d9765603215ac74fd7953908f" integrity sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg== @@ -1189,22 +817,7 @@ "@ethersproject/constants" "^5.8.0" "@ethersproject/logger" "^5.8.0" -"@ethersproject/transactions@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.7.0.tgz#91318fc24063e057885a6af13fdb703e1f993d3b" - integrity sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ== - dependencies: - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/rlp" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - -"@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.7.0", "@ethersproject/transactions@^5.8.0": +"@ethersproject/transactions@^5.6.2", "@ethersproject/transactions@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.8.0.tgz#1e518822403abc99def5a043d1c6f6fe0007e46b" integrity sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg== @@ -1219,48 +832,7 @@ "@ethersproject/rlp" "^5.8.0" "@ethersproject/signing-key" "^5.8.0" -"@ethersproject/units@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.7.0.tgz#637b563d7e14f42deeee39245275d477aae1d8b1" - integrity sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg== - dependencies: - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/constants" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - -"@ethersproject/wallet@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.7.0.tgz#4e5d0790d96fe21d61d38fb40324e6c7ef350b2d" - integrity sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA== - dependencies: - "@ethersproject/abstract-provider" "^5.7.0" - "@ethersproject/abstract-signer" "^5.7.0" - "@ethersproject/address" "^5.7.0" - "@ethersproject/bignumber" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/hdnode" "^5.7.0" - "@ethersproject/json-wallets" "^5.7.0" - "@ethersproject/keccak256" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/random" "^5.7.0" - "@ethersproject/signing-key" "^5.7.0" - "@ethersproject/transactions" "^5.7.0" - "@ethersproject/wordlists" "^5.7.0" - -"@ethersproject/web@5.7.1": - version "5.7.1" - resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.7.1.tgz#de1f285b373149bee5928f4eb7bcb87ee5fbb4ae" - integrity sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w== - dependencies: - "@ethersproject/base64" "^5.7.0" - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/web@^5.7.0", "@ethersproject/web@^5.8.0": +"@ethersproject/web@^5.8.0": version "5.8.0" resolved "https://registry.yarnpkg.com/@ethersproject/web/-/web-5.8.0.tgz#3e54badc0013b7a801463a7008a87988efce8a37" integrity sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw== @@ -1271,28 +843,6 @@ "@ethersproject/properties" "^5.8.0" "@ethersproject/strings" "^5.8.0" -"@ethersproject/wordlists@5.7.0": - version "5.7.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.7.0.tgz#8fb2c07185d68c3e09eb3bfd6e779ba2774627f5" - integrity sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA== - dependencies: - "@ethersproject/bytes" "^5.7.0" - "@ethersproject/hash" "^5.7.0" - "@ethersproject/logger" "^5.7.0" - "@ethersproject/properties" "^5.7.0" - "@ethersproject/strings" "^5.7.0" - -"@ethersproject/wordlists@^5.7.0", "@ethersproject/wordlists@^5.8.0": - version "5.8.0" - resolved "https://registry.yarnpkg.com/@ethersproject/wordlists/-/wordlists-5.8.0.tgz#7a5654ee8d1bb1f4dbe43f91d217356d650ad821" - integrity sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg== - dependencies: - "@ethersproject/bytes" "^5.8.0" - "@ethersproject/hash" "^5.8.0" - "@ethersproject/logger" "^5.8.0" - "@ethersproject/properties" "^5.8.0" - "@ethersproject/strings" "^5.8.0" - "@findeth/abi@^0.3.0": version "0.3.1" resolved "https://registry.yarnpkg.com/@findeth/abi/-/abi-0.3.1.tgz#fe9a25211bc0c840c8bc53f937fd9af7278b9dab" @@ -1300,23 +850,6 @@ dependencies: keccak "^3.0.0" -"@fioprotocol/fiojs@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@fioprotocol/fiojs/-/fiojs-1.0.1.tgz#81779437603741bc4ca1c76d119b64c4157a3874" - integrity sha512-+rxJ/ynUkox/DO3ihHPpAc//DDI+DQvrphLqwRKufw0atC3GKluGR2qMTeO45O0UjorvOIw6esuuG7NpbVUm8Q== - dependencies: - ajv "^6.10.2" - babel-runtime "6.26.0" - bigi "^1.4.2" - browserify-aes "^1.2.0" - bs58 "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - ecurve "^1.0.6" - long "^4.0.0" - randombytes "^2.1.0" - text-encoding "0.7.0" - "@gar/promisify@^1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@gar/promisify/-/promisify-1.1.3.tgz#555193ab2e3bb3b6adc3d551c9c030d9e860daf6" @@ -2461,19 +1994,12 @@ dependencies: "@noble/hashes" "1.4.0" -"@noble/curves@^1.4.2": - version "1.9.7" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" - integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== - dependencies: - "@noble/hashes" "1.8.0" - "@noble/hashes@1.4.0", "@noble/hashes@~1.4.0": version "1.4.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.4.0.tgz#45814aa329f30e4fe0ba49426f49dfccdd066426" integrity sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg== -"@noble/hashes@1.8.0", "@noble/hashes@^1", "@noble/hashes@^1.0.0", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0": +"@noble/hashes@^1", "@noble/hashes@^1.0.0", "@noble/hashes@^1.2.0", "@noble/hashes@^1.3.1", "@noble/hashes@^1.4.0": version "1.8.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== @@ -3567,34 +3093,7 @@ "@parcel/utils" "2.16.4" nullthrows "^1.1.1" -"@peculiar/asn1-schema@^2.3.13", "@peculiar/asn1-schema@^2.3.8": - version "2.6.0" - resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz#0dca1601d5b0fed2a72fed7a5f1d0d7dbe3a6f82" - integrity sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg== - dependencies: - asn1js "^3.0.6" - pvtsutils "^1.3.6" - tslib "^2.8.1" - -"@peculiar/json-schema@^1.1.12": - version "1.1.12" - resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339" - integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w== - dependencies: - tslib "^2.0.0" - -"@peculiar/webcrypto@^1.4.3": - version "1.5.0" - resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz#9e57174c02c1291051c553600347e12b81469e10" - integrity sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg== - dependencies: - "@peculiar/asn1-schema" "^2.3.8" - "@peculiar/json-schema" "^1.1.12" - pvtsutils "^1.3.5" - tslib "^2.6.2" - webcrypto-core "^1.8.0" - -"@pioneer-platform/loggerdog@8.11.0", "@pioneer-platform/loggerdog@^8.0.1", "@pioneer-platform/loggerdog@^8.1.31": +"@pioneer-platform/loggerdog@8.11.0": version "8.11.0" resolved "https://registry.yarnpkg.com/@pioneer-platform/loggerdog/-/loggerdog-8.11.0.tgz#3fbec5aff4dde8ca81b45b668886758111a47c2e" integrity sha512-tX0g/Vmy5bbYqxz1vV1V+l6/jCR2xXWz3iA3JjxUdtErN7CwltJDssrPE4l7eDPEVnMWOPwjmic6jJZQ/7Xxtg== @@ -3603,27 +3102,6 @@ ts-node "^10.9.1" typescript "^5.0.4" -"@pioneer-platform/pioneer-coins@^8.1.19": - version "8.1.90" - resolved "https://registry.yarnpkg.com/@pioneer-platform/pioneer-coins/-/pioneer-coins-8.1.90.tgz#9ed9e93ce756d65a6428a23677420e088c83c46d" - integrity sha512-78FqMZTQ3irrjQw19weyUzG3ot+sDD0DFvYwMGR6Fk7BZlTBn3Y/ge3xPxElG5/YaXAhWOAzH7uM7YoY9w7Zyw== - dependencies: - "@pioneer-platform/loggerdog" "^8.1.31" - bech32 "^1.1.4" - bignumber.js "^9.0.1" - bitcoin-regex "^2.0.0" - bitcoincash-regex "^1.1.8" - bs58check "^3.0.1" - crypto-js "^4.0.0" - dash-regex "^1.0.10" - dogecoin-regex "^1.0.9" - ethereum-regex "^1.1.12" - ethereum-tx-decoder "^3.0.0" - litecoin-regex "^1.0.8" - monero-regex "^1.0.8" - neo-regex "^1.0.7" - ripple-regex "^1.1.8" - "@pioneer-platform/pioneer-coins@^9.11.11": version "9.20.8" resolved "https://registry.yarnpkg.com/@pioneer-platform/pioneer-coins/-/pioneer-coins-9.20.8.tgz#3f50770dfeba0c97bad8937f30408968a90a43c4" @@ -3735,79 +3213,6 @@ varuint-bitcoin "^1.0.4" wif "^2.0.1" -"@shapeshiftoss/bitcoinjs-lib@7.0.0-shapeshift.2": - version "7.0.0-shapeshift.2" - resolved "https://registry.yarnpkg.com/@shapeshiftoss/bitcoinjs-lib/-/bitcoinjs-lib-7.0.0-shapeshift.2.tgz#552a41907931708ae9f010cb2dbb2fe7c12bd1f7" - integrity sha512-cWlAQpb9InD1O0FnWyy1ancwkggCtfUFNQs01znoYNy8G0NzRCweGvdVNxRVTH1IAsxDB2AzRs9Zs9GT0tmsvQ== - dependencies: - "@noble/hashes" "^1.2.0" - bech32 "^2.0.0" - bip174 "^3.0.0" - bs58check "^4.0.0" - uint8array-tools "^0.0.9" - valibot "^0.38.0" - varuint-bitcoin "^2.0.0" - -"@shapeshiftoss/fiojs@1.0.1-shapeshift.2": - version "1.0.1-shapeshift.2" - resolved "https://registry.yarnpkg.com/@shapeshiftoss/fiojs/-/fiojs-1.0.1-shapeshift.2.tgz#d439c542b627f5a79ffa3a4ab0c5804c8d3a5452" - integrity sha512-1pu30rI6mI+47uv9CqnG3+ixLuXjWqbETxY9XK9AlEQuwnj6paFILyNwQqQu2Lfpv1zqqdDGbxISUbXOx2k6bA== - dependencies: - ajv "^6.10.2" - babel-runtime "6.26.0" - bigi "^1.4.2" - browserify-aes "^1.2.0" - bs58 "^4.0.1" - create-hash "^1.2.0" - create-hmac "^1.1.7" - ecurve "^1.0.6" - long "^4.0.0" - randombytes "^2.1.0" - web-encoding "^1.1.5" - -"@shapeshiftoss/fiosdk@1.2.1-shapeshift.6": - version "1.2.1-shapeshift.6" - resolved "https://registry.yarnpkg.com/@shapeshiftoss/fiosdk/-/fiosdk-1.2.1-shapeshift.6.tgz#f4b4bfd4dd32b304145b1396d17e08c9dc74d162" - integrity sha512-/99+WvaD6RapyKJBUqnBn7JdhxDUvxIcWVdsyzoQrHKTBnAk6V33r3b61DOqcj4ZDXiDxFl1MzfmGHuN64UB6g== - dependencies: - "@shapeshiftoss/fiojs" "1.0.1-shapeshift.2" - bip39 "^3.0.2" - hdkey "^1.1.1" - validate "^5.1.0" - web-encoding "^1.1.0" - wif "^2.0.6" - -"@shapeshiftoss/hdwallet-core@latest": - version "1.62.41" - resolved "https://registry.yarnpkg.com/@shapeshiftoss/hdwallet-core/-/hdwallet-core-1.62.41.tgz#1fcbed87500c8347cdbb572bbbefe99d3cda54a4" - integrity sha512-VWsQtUW6p26/jp3KPw9uVS8LAWEFp5tBcPsXnlVS1+YMrLIzAXGzqH5fsb6y2XRKn9vjX7ztI7zjtkFcc/TfWA== - dependencies: - "@shapeshiftoss/bitcoinjs-lib" "7.0.0-shapeshift.2" - "@shapeshiftoss/proto-tx-builder" "0.10.0" - "@solana/web3.js" "1.95.8" - bs58check "^4.0.0" - eip-712 "^1.0.0" - ethers "5.7.2" - eventemitter2 "^5.0.1" - lodash "^4.17.21" - rxjs "^6.4.0" - type-assertions "^1.1.0" - -"@shapeshiftoss/proto-tx-builder@0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@shapeshiftoss/proto-tx-builder/-/proto-tx-builder-0.10.0.tgz#ef5426db826458f52161c1cbda104ea1773ee2a3" - integrity sha512-qsRHgYrosKjQ/uG+/WsbSt1e46/CPDraCmm1BhMeRo24HNzei7BVHVMBT5/kKEW6Wz1vXtR9GknZVfZ8hbBj9w== - dependencies: - "@cosmjs/amino" "^0.29.4" - "@cosmjs/crypto" "0.29.4" - "@cosmjs/encoding" "^0.29.4" - "@cosmjs/proto-signing" "^0.29.4" - "@cosmjs/stargate" "^0.29.4" - bn.js "^5.2.1" - cosmjs-types "^0.5.1" - google-protobuf "^3.17.0" - osmojs "^0.37.0" - "@sindresorhus/is@^0.14.0": version "0.14.0" resolved "https://registry.yarnpkg.com/@sindresorhus/is/-/is-0.14.0.tgz#9fb3a3cf3132328151f353de4632e01e52102bea" @@ -3832,34 +3237,6 @@ dependencies: "@sinonjs/commons" "^1.7.0" -"@solana/buffer-layout@^4.0.1": - version "4.0.1" - resolved "https://registry.yarnpkg.com/@solana/buffer-layout/-/buffer-layout-4.0.1.tgz#b996235eaec15b1e0b5092a8ed6028df77fa6c15" - integrity sha512-E1ImOIAD1tBZFRdjeM4/pzTiTApC0AOBGwyAMS4fwIodCWArzJ3DWdoh8cKxeFM2fElkxBh2Aqts1BPC373rHA== - dependencies: - buffer "~6.0.3" - -"@solana/web3.js@1.95.8": - version "1.95.8" - resolved "https://registry.yarnpkg.com/@solana/web3.js/-/web3.js-1.95.8.tgz#2d49abda23f7a79a3cc499ab6680f7be11786ee1" - integrity sha512-sBHzNh7dHMrmNS5xPD1d0Xa2QffW/RXaxu/OysRXBfwTp+LYqGGmMtCYYwrHPrN5rjAmJCsQRNAwv4FM0t3B6g== - dependencies: - "@babel/runtime" "^7.25.0" - "@noble/curves" "^1.4.2" - "@noble/hashes" "^1.4.0" - "@solana/buffer-layout" "^4.0.1" - agentkeepalive "^4.5.0" - bigint-buffer "^1.1.5" - bn.js "^5.2.1" - borsh "^0.7.0" - bs58 "^4.0.1" - buffer "6.0.3" - fast-stable-stringify "^1.0.0" - jayson "^4.1.1" - node-fetch "^2.7.0" - rpc-websockets "^9.0.2" - superstruct "^2.0.2" - "@swc/core-darwin-arm64@1.15.18": version "1.15.18" resolved "https://registry.yarnpkg.com/@swc/core-darwin-arm64/-/core-darwin-arm64-1.15.18.tgz#fb487392f7bbe3179166b9b0d128916e39a627af" @@ -3934,7 +3311,7 @@ resolved "https://registry.yarnpkg.com/@swc/counter/-/counter-0.1.3.tgz#cc7463bd02949611c6329596fccd2b0ec782b0e9" integrity sha512-e2BR4lsJkkRlKZ/qCHPw9ZaSxc0MVUd7gtbtaB7aMvHeJVYe8sOB8DBZkP2DtISHGSku9sCK6T6cnY0CtXrOCQ== -"@swc/helpers@^0.5.0", "@swc/helpers@^0.5.11": +"@swc/helpers@^0.5.0": version "0.5.19" resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.19.tgz#9a8c8a0bdaecfdfb9b8ae5421c0c8e09246dfee9" integrity sha512-QamiFeIK3txNjgUTNppE6MiG3p7TdninpZu0E0PbqVh1a9FNLT2FRhisaa4NcaX52XVhA5l7Pk58Ft7Sqi/2sA== @@ -4032,38 +3409,13 @@ dependencies: "@babel/types" "^7.28.2" -"@types/bchaddrjs@^0.4.0": - version "0.4.3" - resolved "https://registry.yarnpkg.com/@types/bchaddrjs/-/bchaddrjs-0.4.3.tgz#f84ab159fbafe8f0b05e82bd86065feb6dabf912" - integrity sha512-KJT+Tz39T/Y8/WMijiL4DXhaaUODytoXxvLpwIvI+WwLzfKR4kLrnzLyuIId245GjsVSvK3T9qz/fbvK+//b5w== - -"@types/big.js@^6.0.2": - version "6.2.2" - resolved "https://registry.yarnpkg.com/@types/big.js/-/big.js-6.2.2.tgz#69422ec9ef59df1330ccfde2106d9e1159a083c3" - integrity sha512-e2cOW9YlVzFY2iScnGBBkplKsrn2CsObHQ2Hiw4V1sSyiGbgWL8IyqE3zFi1Pt5o1pdAtYkDAIsF3KKUPjdzaA== - -"@types/bn.js@*", "@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": +"@types/bn.js@^5.1.0", "@types/bn.js@^5.1.1": version "5.2.0" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-5.2.0.tgz#4349b9710e98f9ab3cdc50f1c5e4dcbd8ef29c80" integrity sha512-DLbJ1BPqxvQhIGbeu8VbUC1DiAiahHtAYvA0ZEAa4P31F7IaArc8z3C3BRQdWX4mtLQuABG4yzp76ZrS02Ui1Q== dependencies: "@types/node" "*" -"@types/bs58@^4.0.1": - version "4.0.4" - resolved "https://registry.yarnpkg.com/@types/bs58/-/bs58-4.0.4.tgz#49fbcb0c7db5f7cea26f0e0f61dc4a41a2445aab" - integrity sha512-0IEpMFXXQi2zXaXl9GJ3sRwQo0uEkD+yFOv+FnAU5lkPtcu6h61xb7jc2CFPEZ5BUOaiP13ThuGc9HD4R8lR5g== - dependencies: - "@types/node" "*" - base-x "^3.0.6" - -"@types/bs58check@^2.1.0": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@types/bs58check/-/bs58check-2.1.2.tgz#ca6264599cd9c0bdfeb839a0927f13a9cb77ba0f" - integrity sha512-xpXaQlOIY1KoXlA/ytHGHpEIU87PJt+g9SH7nC6HdCgaBwT2IEZIwBMHbjuX6BpnfbiUMlmwqurdLDwXpcdmSA== - dependencies: - "@types/node" "*" - "@types/cacheable-request@^6.0.1", "@types/cacheable-request@^6.0.2": version "6.0.3" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" @@ -4074,13 +3426,6 @@ "@types/node" "*" "@types/responselike" "^1.0.0" -"@types/connect@^3.4.33": - version "3.4.38" - resolved "https://registry.yarnpkg.com/@types/connect/-/connect-3.4.38.tgz#5ba7f3bc4fbbdeaff8dded952e5ff2cc53f8d858" - integrity sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug== - dependencies: - "@types/node" "*" - "@types/cookie@^0.4.0": version "0.4.1" resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" @@ -4105,23 +3450,11 @@ dependencies: "@types/ms" "*" -"@types/elliptic@^6.4.12": - version "6.4.18" - resolved "https://registry.yarnpkg.com/@types/elliptic/-/elliptic-6.4.18.tgz#bc96e26e1ccccbabe8b6f0e409c85898635482e1" - integrity sha512-UseG6H5vjRiNpQvrhy4VF/JXdA3V/Fp5amvveaL+fs28BZ6xIKJBPnUPRlEaZpysD9MbpfaLi8lbl7PGUAkpWw== - dependencies: - "@types/bn.js" "*" - "@types/eventsource@1.1.8": version "1.1.8" resolved "https://registry.yarnpkg.com/@types/eventsource/-/eventsource-1.1.8.tgz#48ae1f3aaf9bb84c713038f354112cc7ceaad519" integrity sha512-fJQNt9LijJCZwYvM6O30uLzdpAK9zs52Uc9iUW9M2Zsg0HQM6DLf6QysjC/wuFX+0798B8AppVMvgdO6IftPKQ== -"@types/fast-text-encoding@^1.0.1": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/fast-text-encoding/-/fast-text-encoding-1.0.3.tgz#53d76ebb5d897e261611cf8cec961b9c99108e20" - integrity sha512-bbGJt6IyiuyAhPOX7htQDDzv2bDGJdWyd6X+e1BcdPzU3e5jyjOdB86LoTSoE80faY9v8Wt7/ix3Sp+coRJ03Q== - "@types/google-protobuf@^3.15.1": version "3.15.12" resolved "https://registry.yarnpkg.com/@types/google-protobuf/-/google-protobuf-3.15.12.tgz#eb2ba0eddd65712211a2b455dc6071d665ccf49b" @@ -4195,12 +3528,10 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" -"@types/jquery@^3.5.22": - version "3.5.34" - resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.34.tgz#c1993eaac0db03cf9db974976dd8f07bbf7c5708" - integrity sha512-3m3939S3erqmTLJANS/uy0B6V7BorKx7RorcGZVjZ62dF5PAGbKEDZK1CuLtKombJkFA2T1jl8LAIIs7IV6gBQ== - dependencies: - "@types/sizzle" "*" +"@types/jquery@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-4.0.0.tgz#b7717b6e5103b50b115b707950357f302cc92fba" + integrity sha512-Z+to+A2VkaHq1DfI2oSwsoCdhCHMpTSgjWzNcbNlRGYzksDBpPUgEcAL+RQjOBJRaLoEAOHXxqDGBVP+BblBwg== "@types/js-levenshtein@^1.1.0": version "1.1.3" @@ -4219,11 +3550,6 @@ dependencies: "@types/node" "*" -"@types/lodash@^4.14.168": - version "4.17.24" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.24.tgz#4ae334fc62c0e915ca8ed8e35dcc6d4eeb29215f" - integrity sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ== - "@types/long@^4.0.1": version "4.0.2" resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a" @@ -4244,14 +3570,6 @@ resolved "https://registry.yarnpkg.com/@types/ms/-/ms-2.1.0.tgz#052aa67a48eccc4309d7f0191b7e41434b90bb78" integrity sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA== -"@types/node-fetch@^2.5.10": - version "2.6.13" - resolved "https://registry.yarnpkg.com/@types/node-fetch/-/node-fetch-2.6.13.tgz#e0c9b7b5edbdb1b50ce32c127e85e880872d56ee" - integrity sha512-QGpRVpzSaUs30JBSGPjOg4Uveu384erbHBoT1zeONvyCfwQxIkUshLAOqN/k9EjGviPRmWTTe6aH2qySWKTVSw== - dependencies: - "@types/node" "*" - form-data "^4.0.4" - "@types/node-hid@^1.3.1": version "1.3.4" resolved "https://registry.yarnpkg.com/@types/node-hid/-/node-hid-1.3.4.tgz#adad8841dc0e05f988da287a91c64c75c554cfe0" @@ -4271,7 +3589,7 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.18.tgz#1d3ca764718915584fcd9f6344621b7672665c67" integrity sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ== -"@types/node@^12.12.54", "@types/node@^12.12.6": +"@types/node@^12.12.6": version "12.20.55" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240" integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== @@ -4281,11 +3599,6 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.18.63.tgz#1788fa8da838dbb5f9ea994b834278205db6ca2b" integrity sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ== -"@types/node@^15.0.2": - version "15.14.9" - resolved "https://registry.yarnpkg.com/@types/node/-/node-15.14.9.tgz#bc43c990c3c9be7281868bbc7b8fdd6e2b57adfa" - integrity sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A== - "@types/node@^20.5.7": version "20.19.35" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.19.35.tgz#117b373fd1dff528b2f9f8c2d1a85de6af8101ca" @@ -4346,11 +3659,6 @@ dependencies: "@types/node" "*" -"@types/sizzle@*": - version "2.3.10" - resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.10.tgz#277a542aff6776d8a9b15f2ac682a663e3e94bbd" - integrity sha512-TC0dmN0K8YcWEAEfiPi5gJP14eJe30TTGjkvek3iM/1NdHHsdCA/Td6GvNndMOo/iSnIsZ4HuuhrYPDAmbxzww== - "@types/stack-utils@^1.0.1": version "1.0.1" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-1.0.1.tgz#0a851d3bd96498fa25c33ab7278ed3bd65f06c3e" @@ -4375,11 +3683,6 @@ dependencies: "@types/node" "*" -"@types/uuid@^10.0.0": - version "10.0.0" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d" - integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ== - "@types/uuid@^8.3.0": version "8.3.4" resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" @@ -4390,27 +3693,6 @@ resolved "https://registry.yarnpkg.com/@types/w3c-web-usb/-/w3c-web-usb-1.0.13.tgz#4792e2ef7f611d0ee260b7adbf4ed121326c04e1" integrity sha512-N2nSl3Xsx8mRHZBvMSdNGtzMyeleTvtlEw+ujujgXalPqOjIA6UtrqcB6OzyUjkTbDm3J7P1RNK1lgoO7jxtsw== -"@types/wif@^2.0.2": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@types/wif/-/wif-2.0.5.tgz#51a6999e692537bb58c028226457fb7b17b24d67" - integrity sha512-addYBlYjDxLfJxDUoyTzICnu0u4snCdGJpICIIFk65zGcdjah3twTJq1Fdy+OdeZSRiof2raFtMqSqF9KeqthQ== - dependencies: - "@types/node" "*" - -"@types/ws@^7.4.4": - version "7.4.7" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-7.4.7.tgz#f7c390a36f7a0679aa69de2d501319f4f8d9b702" - integrity sha512-JQbbmxZTZehdc2iszGKs5oC3NFnjeay7mtAWrdt7qNtAVK0g19muApzAy4bm9byz79xa2ZnO/BOBC2R8RC5Lww== - dependencies: - "@types/node" "*" - -"@types/ws@^8.2.2": - version "8.18.1" - resolved "https://registry.yarnpkg.com/@types/ws/-/ws-8.18.1.tgz#48464e4bf2ddfd17db13d845467f6070ffea4aa9" - integrity sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg== - dependencies: - "@types/node" "*" - "@types/yargs-parser@*": version "21.0.3" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.3.tgz#815e30b786d2e8f0dcd85fd5bcf5e1a04d008f15" @@ -4582,11 +3864,6 @@ dependencies: argparse "^2.0.1" -"@zxing/text-encoding@0.9.0", "@zxing/text-encoding@^0.9.0": - version "0.9.0" - resolved "https://registry.yarnpkg.com/@zxing/text-encoding/-/text-encoding-0.9.0.tgz#fb50ffabc6c7c66a0c96b4c03e3d9be74864b70b" - integrity sha512-U/4aVJ2mxI0aDNI8Uq0wEhMgY+u4CNtEb0om3+y3+niDAsoTCOB33UF0sxpzqzdqXLqmvc+vZyAt4O8pPdfkwA== - JSONStream@^1.0.4: version "1.3.5" resolved "https://registry.yarnpkg.com/JSONStream/-/JSONStream-1.3.5.tgz#3208c1f08d3a4d99261ab64f92302bc15e111ca0" @@ -4676,11 +3953,6 @@ add-stream@^1.0.0: resolved "https://registry.yarnpkg.com/add-stream/-/add-stream-1.0.0.tgz#6a7990437ca736d5e1288db92bd3266d5f5cb2aa" integrity sha512-qQLMr+8o0WC4FZGQTcJiKBVC59JylcPSrTtk6usvmIDFUOCKegapy1VHQwRbFMOFyb/inzUVqHs+eMYKDM1YeQ== -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - integrity sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw== - agent-base@6, agent-base@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77" @@ -4688,7 +3960,7 @@ agent-base@6, agent-base@^6.0.2: dependencies: debug "4" -agentkeepalive@^4.2.1, agentkeepalive@^4.5.0: +agentkeepalive@^4.2.1: version "4.6.0" resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-4.6.0.tgz#35f73e94b3f40bf65f105219c623ad19c136ea6a" integrity sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ== @@ -4703,7 +3975,7 @@ aggregate-error@^3.0.0: clean-stack "^2.0.0" indent-string "^4.0.0" -ajv@^6.10.2, ajv@^6.12.3, ajv@^6.12.4: +ajv@^6.12.3, ajv@^6.12.4: version "6.14.0" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.14.0.tgz#fd067713e228210636ebb08c60bd3765d6dbe73a" integrity sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw== @@ -4855,15 +4127,6 @@ asn1@~0.2.3: dependencies: safer-buffer "~2.1.0" -asn1js@^3.0.5, asn1js@^3.0.6: - version "3.0.7" - resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.7.tgz#15f1f2f59e60f80d5b43ef14047a294a969f824f" - integrity sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ== - dependencies: - pvtsutils "^1.3.6" - pvutils "^1.1.3" - tslib "^2.8.1" - assert-plus@1.0.0, assert-plus@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" @@ -4895,11 +4158,6 @@ async@^3.2.6: resolved "https://registry.yarnpkg.com/async/-/async-3.2.6.tgz#1b0728e14929d51b85b449b7f06e27c1145e38ce" integrity sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA== -async@~1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - integrity sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w== - asynckit@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" @@ -5020,20 +4278,12 @@ babel-preset-jest@^26.6.2: babel-plugin-jest-hoist "^26.6.2" babel-preset-current-node-syntax "^1.0.0" -babel-runtime@6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - integrity sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g== - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.11, base-x@^3.0.2, base-x@^3.0.6, base-x@^3.0.8: +base-x@^3.0.11, base-x@^3.0.2, base-x@^3.0.8: version "3.0.11" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.11.tgz#40d80e2a1aeacba29792ccc6c5354806421287ff" integrity sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA== @@ -5045,11 +4295,6 @@ base-x@^4.0.0: resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.1.tgz#817fb7b57143c501f649805cb247617ad016a885" integrity sha512-uAZ8x6r6S3aUM9rbHGVOIsR15U/ZSc82b3ymnCPsT45Gk1DDvhDPdIgB5MrhirZWt+5K0EEPQH985kNqZgNPFw== -base-x@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-5.0.1.tgz#16bf35254be1df8aca15e36b7c1dda74b2aa6b03" - integrity sha512-M7uio8Zt++eg3jPj+rHMfCC+IuygQHHCOU+IYsVtik6FWjuYpVt/+MRKcgsAMHh8mMFAwnB+Bs+mTrFiXjMzKg== - base64-arraybuffer-es6@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/base64-arraybuffer-es6/-/base64-arraybuffer-es6-0.7.0.tgz#dbe1e6c87b1bf1ca2875904461a7de40f21abc86" @@ -5078,14 +4323,6 @@ baseline-browser-mapping@^2.9.0: resolved "https://registry.yarnpkg.com/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz#5b09935025bf8a80e29130251e337c6a7fc8cbb9" integrity sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA== -bchaddrjs@^0.4.9: - version "0.4.9" - resolved "https://registry.yarnpkg.com/bchaddrjs/-/bchaddrjs-0.4.9.tgz#c17036bf5bab31bfbb9f3cec432c7c578f0faf46" - integrity sha512-Mf5Uf+P452ltYg1b/NncX/eAEKW+iAfUs8rO1mcgro8S+/WG6gRh8OqgBtyCK1jBHViajovWoAG+ZCkKbhZbNg== - dependencies: - bs58check "^2.1.2" - cashaddrjs "^0.3.12" - bcrypt-pbkdf@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" @@ -5093,43 +4330,21 @@ bcrypt-pbkdf@^1.0.0: dependencies: tweetnacl "^0.14.3" -bech32@1.1.4, bech32@^1.1.2, bech32@^1.1.4: +bech32@^1.1.2, bech32@^1.1.4: 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" - integrity sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg== - before-after-hook@^2.2.0: version "2.2.3" resolved "https://registry.yarnpkg.com/before-after-hook/-/before-after-hook-2.2.3.tgz#c51e809c81a4e354084422b9b26bad88249c517c" integrity sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ== -big-integer@1.6.36: - version "1.6.36" - resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.36.tgz#78631076265d4ae3555c04f85e7d9d2f3a071a36" - integrity sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg== - big-integer@^1.6.44: version "1.6.52" resolved "https://registry.yarnpkg.com/big-integer/-/big-integer-1.6.52.tgz#60a887f3047614a8e1bffe5d7173490a97dc8c85" integrity sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg== -bigi@^1.1.0, bigi@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/bigi/-/bigi-1.4.2.tgz#9c665a95f88b8b08fc05cfd731f561859d725825" - integrity sha512-ddkU+dFIuEIW8lE7ZwdIAf2UPoM90eaprg5m3YXAVVTmKlqV/9BX4A2M8BOK2yOq6/VgZFVhK6QAxJebhlbhzw== - -bigint-buffer@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/bigint-buffer/-/bigint-buffer-1.1.5.tgz#d038f31c8e4534c1f8d0015209bf34b4fa6dd442" - integrity sha512-trfYco6AoZ+rKhKnxA0hgX0HAbVP/s808/EuDSe2JDzUnCp/xAsli35Orvk67UrTEcwuxZqYZDmfA2RXJgxVvA== - dependencies: - bindings "^1.3.0" - bignumber.js@^9.0.0, bignumber.js@^9.0.1: version "9.3.1" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.1.tgz#759c5aaddf2ffdc4f154f7b493e1c8770f88c4d7" @@ -5152,19 +4367,19 @@ binary-extensions@^2.0.0: resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== -bindings@^1.3.0, bindings@^1.5.0: +bindings@^1.3.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== dependencies: file-uri-to-path "1.0.0" -bip174@2.1.0, bip174@^2.0.1, bip174@^3.0.0: +bip174@2.1.0, 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@^2.0.4, bip32@^2.0.5: +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== @@ -5177,14 +4392,7 @@ bip32@^2.0.4, bip32@^2.0.5: typeforce "^1.11.5" wif "^2.0.6" -bip39@^3.0.2, bip39@^3.0.4: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-3.1.0.tgz#c55a418deaf48826a6ceb34ac55b3ee1577e18a3" - integrity sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A== - dependencies: - "@noble/hashes" "^1.2.0" - -bip66@^1.1.0, bip66@^1.1.5: +bip66@^1.1.0: version "1.1.5" resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" integrity sha512-nemMHz95EmS38a26XbbdxIYj5csHd3RMP3H5bwQknX0WYHF01qhpufP42mLOwVICuH2JmhIhXiWs89MfUGL7Xw== @@ -5196,16 +4404,6 @@ bitcoin-ops@^1.3.0, bitcoin-ops@^1.4.0: resolved "https://registry.yarnpkg.com/bitcoin-ops/-/bitcoin-ops-1.4.1.tgz#e45de620398e22fd4ca6023de43974ff42240278" integrity sha512-pef6gxZFztEhaE9RY9HmWVmiIHqCb2OyS4HPKkpc6CIiiOa3Qmuoylxc5P2EkU3w+5eTSifI9SEZC88idAIGow== -bitcoin-regex@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/bitcoin-regex/-/bitcoin-regex-2.0.0.tgz#af4fcc0bf09b3efe8a9339c7bf21c2dcb1524c19" - integrity sha512-WQXyzd6hpVsbJwuzQXdhkjp1dVznTanbuFE4WinmwyOi6osmr75OD8U05a4xvOP24vzD+9ugNT7JJtTMEQe4hA== - -bitcoincash-regex@^1.1.8: - version "1.1.9" - resolved "https://registry.yarnpkg.com/bitcoincash-regex/-/bitcoincash-regex-1.1.9.tgz#09f1b0308aa81bc4971f79bb93c2300675d67da6" - integrity sha512-VthlTDYcqjUlnxLe0h3rK2X0umt314bSvDOFx/GJ+FJ64vbcCo58NZONpoO1MqYSRkSxroAYJN/qwq7oxZpt3A== - bl@^4.0.3, bl@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" @@ -5263,15 +4461,6 @@ boolean@^3.0.1: resolved "https://registry.yarnpkg.com/boolean/-/boolean-3.2.0.tgz#9e5294af4e98314494cbb17979fa54ca159f116b" integrity sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw== -borsh@^0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/borsh/-/borsh-0.7.0.tgz#6e9560d719d86d90dc589bca60ffc8a6c51fec2a" - integrity sha512-CLCsZGIBCFnPtkNnieW/a8wmreDmfUtjU2m9yHrzPXIlNbqVs0AQrSatSG6vdNYUqdc83tkQi2eHfF98ubzQLA== - dependencies: - bn.js "^5.2.0" - bs58 "^4.0.0" - text-encoding-utf-8 "^1.0.2" - brace-expansion@^1.1.7: version "1.1.12" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.12.tgz#ab9b454466e5a8cc3a187beaad580412a9c5b843" @@ -5320,7 +4509,7 @@ browser-process-hrtime@^1.0.0: resolved "https://registry.yarnpkg.com/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz#3c9b4b7d782c8121e56f10106d84c0d0ffc94626" integrity sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow== -browserify-aes@^1.0.6, browserify-aes@^1.2.0: +browserify-aes@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== @@ -5357,7 +4546,7 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "2.x" -bs58@^4.0.0, bs58@^4.0.1: +bs58@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/bs58/-/bs58-4.0.1.tgz#be161e76c354f6f788ae4071f63f34e8c4f0a42a" integrity sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw== @@ -5371,13 +4560,6 @@ bs58@^5.0.0: dependencies: base-x "^4.0.0" -bs58@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-6.0.0.tgz#a2cda0130558535dd281a2f8697df79caaf425d8" - integrity sha512-PD0wEnEYg6ijszw/u8s+iI3H17cTymlrwkKhDhPZq+Sokl3AU4htyBFTjAeNAlCCmg0f53g6ih3jATyCKftTfw== - dependencies: - base-x "^5.0.0" - 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" @@ -5395,14 +4577,6 @@ bs58check@^3.0.1: "@noble/hashes" "^1.2.0" bs58 "^5.0.0" -bs58check@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-4.0.0.tgz#46cda52a5713b7542dcb78ec2efdf78f5bf1d23c" - integrity sha512-FsGDOnFg9aVI9erdriULkd/JjEWONV/lQE5aYziB5PoBsXRind56lh8doIZIc9X4HoxT5x4bLjMWN1/NB8Zp5g== - dependencies: - "@noble/hashes" "^1.2.0" - bs58 "^6.0.0" - bser@2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/bser/-/bser-2.1.1.tgz#e6787da20ece9d07998533cfd9de6f5c38f4bc05" @@ -5430,14 +4604,6 @@ buffer-xor@^1.0.3: resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ== -buffer@6.0.3, buffer@^6.0.3, buffer@~6.0.3: - version "6.0.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6" - integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA== - dependencies: - base64-js "^1.3.1" - ieee754 "^1.2.1" - buffer@^5.0.5, buffer@^5.5.0, buffer@^5.6.0: version "5.7.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" @@ -5629,13 +4795,6 @@ caseless@~0.12.0: resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw== -cashaddrjs@^0.3.12: - version "0.3.12" - resolved "https://registry.yarnpkg.com/cashaddrjs/-/cashaddrjs-0.3.12.tgz#73089588113459741e854aa842db1f7816d8428d" - integrity sha512-GdjCYMVwd86HXcFcxyEZQLPLFv8a/u0ccYPsO0PpnUW26LhZzHX9l9QA+DjaeUah7tnebwPs33NWDbbUy8iVYQ== - dependencies: - big-integer "1.6.36" - chalk@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" @@ -5834,16 +4993,6 @@ co@^4.6.0: resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ== -codeclimate-test-reporter@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/codeclimate-test-reporter/-/codeclimate-test-reporter-0.5.1.tgz#2fd517e1a7932b00b0aafffc8d1dfbe91d0443cf" - integrity sha512-XCzmc8dH+R4orK11BCg5pBbXc35abxq9sept4YvUFRkFl9zb9MIVRrCKENe6U1TKAMTgvGJmrYyHn0y2lerpmg== - dependencies: - async "~1.5.2" - commander "2.9.0" - lcov-parse "0.0.10" - request "~2.88.0" - collect-v8-coverage@^1.0.0: version "1.0.3" resolved "https://registry.yarnpkg.com/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz#cc1f01eb8d02298cbc9a437c74c70ab4e5210b80" @@ -5906,11 +5055,6 @@ commander@^12.1.0: resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== -commander@^2.20.3: - version "2.20.3" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" - integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== - common-ancestor-path@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz#4f7d2d1394d91b7abdf51871c62f71eadb0182a7" @@ -5929,11 +5073,6 @@ component-emitter@^1.2.1: resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.1.tgz#ef1d5796f7d93f135ee6fb684340b26403c97d17" integrity sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ== -component-type@1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/component-type/-/component-type-1.2.1.tgz#8a47901700238e4fc32269771230226f24b415a9" - integrity sha512-Kgy+2+Uwr75vAi6ChWXgHuLvd+QLD7ssgpaRq2zCvt80ptvAfMc/hijcJxXkBa2wMlEZcJvC2H8Ubo+A9ATHIg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" @@ -6105,11 +5244,6 @@ copy-descriptor@^0.1.0: resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" integrity sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw== -core-js@^2.4.0: - version "2.6.12" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.12.tgz#d9333dfa7b065e347cc5682219d6f690859cc2ec" - integrity sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ== - core-js@^3.4: version "3.48.0" resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.48.0.tgz#1f813220a47bbf0e667e3885c36cd6f0593bf14d" @@ -6144,7 +5278,7 @@ cosmiconfig@^7.0.0: path-type "^4.0.0" yaml "^1.10.0" -cosmjs-types@^0.4.0, cosmjs-types@^0.4.1: +cosmjs-types@^0.4.0: version "0.4.1" resolved "https://registry.yarnpkg.com/cosmjs-types/-/cosmjs-types-0.4.1.tgz#3b2a53ba60d33159dd075596ce8267cfa7027063" integrity sha512-I7E/cHkIgoJzMNQdFF0YVqPlaTqrqKHrskuSTIqlEyxfB5Lf3WKCajSXVK2yHOfOFfSux/RxEdpMzw/eO4DIog== @@ -6176,7 +5310,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.3, create-hmac@^1.1.4, create-hmac@^1.1.7: +create-hmac@^1.1.3, 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== @@ -6255,11 +5389,6 @@ dargs@^7.0.0: resolved "https://registry.yarnpkg.com/dargs/-/dargs-7.0.0.tgz#04015c41de0bcb69ec84050f3d9be0caf8d6d5cc" integrity sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg== -dash-regex@^1.0.10: - version "1.0.11" - resolved "https://registry.yarnpkg.com/dash-regex/-/dash-regex-1.0.11.tgz#5596c8f09ec7b4a2e1f60fc09ac4c5ca76dbe4c7" - integrity sha512-sVf5KH7IzGZ47ykcukfPWNf2cvtEVWmOhWo/4W4uGOIKzZw7V2og3+FsiY1Gl4y59zITsUgYSzBf36kXMZaQXg== - dashdash@^1.12.0: version "1.14.1" resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" @@ -6423,11 +5552,6 @@ define-property@^2.0.2: is-descriptor "^1.0.2" isobject "^3.0.1" -delay@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/delay/-/delay-5.0.0.tgz#137045ef1b96e5071060dd5be60bf9334436bd1d" - integrity sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw== - delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -6515,11 +5639,6 @@ doctrine@^3.0.0: dependencies: esutils "^2.0.2" -dogecoin-regex@^1.0.9: - version "1.0.10" - resolved "https://registry.yarnpkg.com/dogecoin-regex/-/dogecoin-regex-1.0.10.tgz#0cb93bec25c4f2ff2166fb1bac839e089434a6c7" - integrity sha512-6+9OO9AZnBv88L+utqhHdqdkcI70bnPyBU4Q0Kbi0OgFU1QXrBd/EOJw4+uxfSNn8BOefqWgUKbIceYyrtoWkg== - dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" @@ -6570,15 +5689,6 @@ dotenv@~10.0.0: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-10.0.0.tgz#3d4227b8fb95f81096cdd2b66653fb2c7085ba81" integrity sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q== -drbg.js@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - integrity sha512-F4wZ06PvqxYLFEZKkFxTDcns9oFNk34hvmJSEwdzsxVQ8YI5YaxtACgQatkYgv2VI2CFkUd2Y+xosPQnHv809g== - dependencies: - browserify-aes "^1.0.6" - create-hash "^1.1.2" - create-hmac "^1.1.4" - dunder-proto@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" @@ -6606,14 +5716,6 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecurve@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/ecurve/-/ecurve-1.0.6.tgz#dfdabbb7149f8d8b78816be5a7d5b83fcf6de797" - integrity sha512-/BzEjNfiSuB7jIWKcS/z8FK9jNjmEWvUV2YZ4RLSmcDtP7Lq0m6FvDuSnJpBlDpGRpfRQeTLGLBI8H+kEv0r+w== - dependencies: - bigi "^1.1.0" - safe-buffer "^5.0.1" - ee-first@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" @@ -6656,19 +5758,6 @@ electron@^12.0.9: "@types/node" "^14.6.2" extract-zip "^1.0.3" -elliptic@6.5.4: - version "6.5.4" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.4.tgz#da37cebd31e79a1367e941b592ed1fbebd58abbb" - integrity sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ== - dependencies: - bn.js "^4.11.9" - brorand "^1.1.0" - hash.js "^1.0.0" - hmac-drbg "^1.0.1" - inherits "^2.0.4" - minimalistic-assert "^1.0.1" - minimalistic-crypto-utils "^1.0.1" - elliptic@6.6.1, elliptic@^6.4.0, elliptic@^6.5.3, elliptic@^6.5.4, elliptic@^6.5.7: version "6.6.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.6.1.tgz#3b8ffb02670bf69e382c7f65bf524c97c5405c06" @@ -6796,18 +5885,11 @@ es6-iterator@^2.0.3: es5-ext "^0.10.35" es6-symbol "^3.1.1" -es6-promise@^4.0.3, es6-promise@^4.2.8: +es6-promise@^4.2.8: version "4.2.8" resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== -es6-promisify@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/es6-promisify/-/es6-promisify-5.0.0.tgz#5109d62f3e56ea967c4b63505aef08291c8a5203" - integrity sha512-C+d6UdsYDk0lMebHNR4S2NybQMMngAOnOwYBQjTOiv0MkoJMP0Myw2mgpDLBcpfCmRLxyFqYhS/CfOENq4SJhQ== - dependencies: - es6-promise "^4.0.3" - es6-symbol@^3.1.1, es6-symbol@^3.1.3: version "3.1.4" resolved "https://registry.yarnpkg.com/es6-symbol/-/es6-symbol-3.1.4.tgz#f4e7d28013770b4208ecbf3e0bf14d3bcb557b8c" @@ -7078,18 +6160,6 @@ ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: "@scure/bip32" "1.4.0" "@scure/bip39" "1.3.0" -ethereum-regex@^1.1.12: - version "1.1.13" - resolved "https://registry.yarnpkg.com/ethereum-regex/-/ethereum-regex-1.1.13.tgz#d33fed7f153d5858adf84fdcf05e8d5c20aa675c" - integrity sha512-Ey1UmHGkC5zgm5Wcw9ZxkaCszKC93FYqAYHc18tvIT0pPxaUnBOc+MxJBZI+9pZ/1BKMCqNx6L5mvw4J15nYIA== - -ethereum-tx-decoder@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ethereum-tx-decoder/-/ethereum-tx-decoder-3.0.0.tgz#7ef704c1b7e228128cdb81d6a3d2ab57a378b90f" - integrity sha512-l+/K/CNAobJjfGs6lO4RrR17KQrwESrGH2GrkASn7MH2FAJRkItFP21Iy2fCOUjy1Y1nBVoTO6w1GPCgVQH2hg== - dependencies: - ethers "^4.0.37" - ethereumjs-util@^7.1.5: version "7.1.5" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" @@ -7101,57 +6171,6 @@ ethereumjs-util@^7.1.5: ethereum-cryptography "^0.1.3" rlp "^2.2.4" -ethers@5.7.2: - version "5.7.2" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.7.2.tgz#3a7deeabbb8c030d4126b24f84e525466145872e" - integrity sha512-wswUsmWo1aOK8rR7DIKiWSw9DbLWe6x98Jrn8wcTflTVvaXhAMaB5zGAXy0GYQEQp9iO1iSHWVyARQm11zUtyg== - dependencies: - "@ethersproject/abi" "5.7.0" - "@ethersproject/abstract-provider" "5.7.0" - "@ethersproject/abstract-signer" "5.7.0" - "@ethersproject/address" "5.7.0" - "@ethersproject/base64" "5.7.0" - "@ethersproject/basex" "5.7.0" - "@ethersproject/bignumber" "5.7.0" - "@ethersproject/bytes" "5.7.0" - "@ethersproject/constants" "5.7.0" - "@ethersproject/contracts" "5.7.0" - "@ethersproject/hash" "5.7.0" - "@ethersproject/hdnode" "5.7.0" - "@ethersproject/json-wallets" "5.7.0" - "@ethersproject/keccak256" "5.7.0" - "@ethersproject/logger" "5.7.0" - "@ethersproject/networks" "5.7.1" - "@ethersproject/pbkdf2" "5.7.0" - "@ethersproject/properties" "5.7.0" - "@ethersproject/providers" "5.7.2" - "@ethersproject/random" "5.7.0" - "@ethersproject/rlp" "5.7.0" - "@ethersproject/sha2" "5.7.0" - "@ethersproject/signing-key" "5.7.0" - "@ethersproject/solidity" "5.7.0" - "@ethersproject/strings" "5.7.0" - "@ethersproject/transactions" "5.7.0" - "@ethersproject/units" "5.7.0" - "@ethersproject/wallet" "5.7.0" - "@ethersproject/web" "5.7.1" - "@ethersproject/wordlists" "5.7.0" - -ethers@^4.0.37: - version "4.0.49" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.49.tgz#0eb0e9161a0c8b4761be547396bbe2fb121a8894" - integrity sha512-kPltTvWiyu+OktYy1IStSO16i2e7cS9D9OxZ81q2UUaiNPVrm/RTcbxamCXF9VUSKzJIdJV68EAIhTEVBalRWg== - dependencies: - aes-js "3.0.0" - bn.js "^4.11.9" - elliptic "6.5.4" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.4" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" - ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -7183,11 +6202,6 @@ eventemitter3@^4.0.4: resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== -eventemitter3@^5.0.1: - version "5.0.4" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.4.tgz#a86d66170433712dde814707ac52b5271ceb1feb" - integrity sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw== - evp_bytestokey@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" @@ -7386,11 +6400,6 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== -eyes@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/eyes/-/eyes-0.1.8.tgz#62cf120234c683785d902348a800ef3e0cc20bc0" - integrity sha512-GipyPsXO1anza0AOZdy69Im7hGFCNB7Y/NGjDlZGJ3GJJLtwNSb2vrzYrTYJRrRloVx7pl+bhUaTB8yiccPvFQ== - fake-indexeddb@^3.1.7: version "3.1.8" resolved "https://registry.yarnpkg.com/fake-indexeddb/-/fake-indexeddb-3.1.8.tgz#229e3cff6fa7355aebb3f147b908d2efa4605d70" @@ -7440,16 +6449,6 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== -fast-stable-stringify@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fast-stable-stringify/-/fast-stable-stringify-1.0.0.tgz#5c5543462b22aeeefd36d05b34e51c78cb86d313" - integrity sha512-wpYMUmFu5f00Sm0cj2pfivpmawLZ0NKdviQ4w9zJeR8JVtOpOxHmLaJuj0vxvGqMJQWyP/COUkF75/57OKyRag== - -fast-text-encoding@^1.0.3: - version "1.0.6" - resolved "https://registry.yarnpkg.com/fast-text-encoding/-/fast-text-encoding-1.0.6.tgz#0aa25f7f638222e3396d72bf936afcf1d42d6867" - integrity sha512-VhXlQgj9ioXCqGstD37E/HBeqEGV/qOD/kmbVG8h5xKBYvM1L3lR1Zn4555cQ8GkYbJa8aJSipLPndE1k6zK2w== - fastq@^1.6.0: version "1.20.1" resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.20.1.tgz#ca750a10dc925bc8b18839fd203e3ef4b3ced675" @@ -7557,19 +6556,6 @@ find-yarn-workspace-root@^2.0.0: dependencies: micromatch "^4.0.2" -fiosdk-offline@^1.2.21: - version "1.2.21" - resolved "https://registry.yarnpkg.com/fiosdk-offline/-/fiosdk-offline-1.2.21.tgz#59d2ebe850f8ac3ba6da134450ff57263865e3e7" - integrity sha512-tUCOHNhlwyg3WE9AbbaCnLZ+bhtI+4bdnBD5LmF7zmjbtfX60aiYBiJWAsIHyC+YLMhg9SHGgJnqF/1RvbDpQg== - dependencies: - "@fioprotocol/fiojs" "1.0.1" - "@types/fast-text-encoding" "^1.0.1" - bip39 "^3.0.2" - fast-text-encoding "^1.0.3" - hdkey "^1.1.1" - validate "^5.1.0" - wif "^2.0.6" - flat-cache@^3.0.4: version "3.2.0" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.2.0.tgz#2c0c2d5040c99b1632771a9d105725c0115363ee" @@ -7627,7 +6613,7 @@ form-data@^3.0.0: hasown "^2.0.2" mime-types "^2.1.35" -form-data@^4.0.0, form-data@^4.0.4, form-data@^4.0.5: +form-data@^4.0.0, form-data@^4.0.5: version "4.0.5" resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.5.tgz#b49e48858045ff4cbf6b03e1805cebcad3679053" integrity sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w== @@ -7735,11 +6721,6 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -funtypes@^3.0.1: - version "3.0.2" - resolved "https://registry.yarnpkg.com/funtypes/-/funtypes-3.0.2.tgz#c58b29c95395105fca7aad39a6fa3e295bd4092f" - integrity sha512-+OnS2Na79ixIf19lZKkqWyE7QXbaJUVIdpBAYNyjs7ZcSrQ/jQNZjuGjTqqqPGFLfnV/3DI/9kz96+gvpfCzVA== - gauge@^4.0.3: version "4.0.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-4.0.4.tgz#52ff0652f2bbf607a989793d53b751bef2328dce" @@ -8192,19 +7173,6 @@ hash-base@^3.0.0, hash-base@^3.1.2: safe-buffer "^5.2.1" to-buffer "^1.2.1" -hash-wasm@^4.9.0: - version "4.12.0" - resolved "https://registry.yarnpkg.com/hash-wasm/-/hash-wasm-4.12.0.tgz#f9f1a9f9121e027a9acbf6db5d59452ace1ef9bb" - integrity sha512-+/2B2rYLb48I/evdOIhP+K/DD2ca2fgBjp6O+GBEnCDk2e4rpeXIK8GvIyRPjTezgmWn9gmKwkQjjx6BtqDHVQ== - -hash.js@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - integrity sha512-/UETyP0W22QILqS+6HowevwhEFJ3MBJnwTf75Qob9Wz9t0DPuisL8kW8YZMK62dHAKE1c1p+gY1TtOLY+USEHA== - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" - hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7: version "1.1.7" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" @@ -8220,15 +7188,6 @@ hasown@^2.0.0, hasown@^2.0.2: dependencies: function-bind "^1.1.2" -hdkey@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.2.tgz#c60f9cf6f90fbf24a8a52ea06893f36a0108cd3e" - integrity sha512-PTQ4VKu0oRnCrYfLp04iQZ7T2Cxz0UsEXYauk2j8eh6PJXCpbXuCFhOmtIFtbET0i3PMWmHN9J11gU8LEgUljQ== - dependencies: - bs58check "^2.1.2" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - headers-utils@^1.2.0: version "1.2.5" resolved "https://registry.yarnpkg.com/headers-utils/-/headers-utils-1.2.5.tgz#899d6a76b21bcbe18d6108f56136fdbd4f30c404" @@ -8408,11 +7367,6 @@ iconv-lite@^0.7.0: dependencies: safer-buffer ">= 2.1.2 < 3.0.0" -idb-keyval@^6.0.3: - version "6.2.2" - resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-6.2.2.tgz#b0171b5f73944854a3291a5cdba8e12768c4854a" - integrity sha512-yjD9nARJ/jb1g+CvD0tlhUHOrJ9Sy0P8T9MF3YaLlHnSRpwPfpTX0XIvpmw3gAJUmEu3FiICLBDPXVwyEvrleg== - idna-uts46-hx@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" @@ -8420,7 +7374,7 @@ idna-uts46-hx@^2.3.1: dependencies: punycode "2.1.0" -ieee754@^1.1.13, ieee754@^1.2.1: +ieee754@^1.1.13: version "1.2.1" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== @@ -8921,24 +7875,6 @@ jake@^10.8.5: filelist "^1.0.4" picocolors "^1.1.1" -jayson@^4.1.1: - version "4.3.0" - resolved "https://registry.yarnpkg.com/jayson/-/jayson-4.3.0.tgz#22eb8f3dcf37a5e893830e5451f32bde6d1bde4d" - integrity sha512-AauzHcUcqs8OBnCHOkJY280VaTiCm57AbuO7lqzcw7JapGj50BisE3xhksye4zlTSR1+1tAz67wLTl8tEH1obQ== - dependencies: - "@types/connect" "^3.4.33" - "@types/node" "^12.12.54" - "@types/ws" "^7.4.4" - commander "^2.20.3" - delay "^5.0.0" - es6-promisify "^5.0.0" - eyes "^0.1.8" - isomorphic-ws "^4.0.1" - json-stringify-safe "^5.0.1" - stream-json "^1.9.1" - uuid "^8.3.2" - ws "^7.5.10" - jest-changed-files@^26.6.2: version "26.6.2" resolved "https://registry.yarnpkg.com/jest-changed-files/-/jest-changed-files-26.6.2.tgz#f6198479e1cc66f22f9ae1e22acaa0b429c042d0" @@ -9366,31 +8302,26 @@ jest@^26.6.3: import-local "^3.0.2" jest-cli "^26.6.3" -jose@^4.3.5: - version "4.15.9" - resolved "https://registry.yarnpkg.com/jose/-/jose-4.15.9.tgz#9b68eda29e9a0614c042fa29387196c7dd800100" - integrity sha512-1vUQX+IdDMVPj4k8kOxgUqlcK518yluMuGZwqlr44FS1ppZB/5GWh4rZG89erpOBOJjU/OBsnCVFfapsRz6nEA== - -jquery@^3.7.1: - version "3.7.1" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.7.1.tgz#083ef98927c9a6a74d05a6af02806566d16274de" - integrity sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg== +jquery@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jquery/-/jquery-4.0.0.tgz#95c33ac29005ff72ec444c5ba1cf457e61404fbb" + integrity sha512-TXCHVR3Lb6TZdtw1l3RTLf8RBWVGexdxL6AC8/e0xZKEpBflBsjh9/8LXw+dkNFuOyW9B7iB3O1sP7hS0Kiacg== js-levenshtein@^1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== -js-sha3@0.5.7, js-sha3@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== - js-sha3@0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.8.0.tgz#b9b7a5da73afad7dedd0f8c463954cbde6818840" integrity sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q== +js-sha3@^0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + integrity sha512-GII20kjaPX0zJ8wzkTbNDYMY7msuZcTWk8S5UOh6806Jq/wz1J8/bnr8uGU0DAUmYDjj2Mr4X1cW8v/GLYnR+g== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -9653,11 +8584,6 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -lcov-parse@0.0.10: - version "0.0.10" - resolved "https://registry.yarnpkg.com/lcov-parse/-/lcov-parse-0.0.10.tgz#1b0b8ff9ac9c7889250582b70b71315d9da6d9a3" - integrity sha512-YsL0D4QF/vNlNcHPXM832si9d2ROryFQ4r4JvcfMIiUYr1f6WULuO75YCtxNu4P+XMRHz0SfUc524+c+U3G5kg== - lerna@^5.2.0: version "5.6.2" resolved "https://registry.yarnpkg.com/lerna/-/lerna-5.6.2.tgz#cdcdfe4e8bf07eccb4ecff1c216def9c67e62af2" @@ -9825,11 +8751,6 @@ lines-and-columns@~2.0.3: resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-2.0.4.tgz#d00318855905d2660d8c0822e3f5a4715855fc42" integrity sha512-wM1+Z03eypVAVUCE7QdSqpVIvelbOakn1M0bPDoA4SGWPx3sNDVUiMo3L6To6WWGClB7VyXnhQ4Sn7gxiJbE6A== -litecoin-regex@^1.0.8: - version "1.0.9" - resolved "https://registry.yarnpkg.com/litecoin-regex/-/litecoin-regex-1.0.9.tgz#0e67b4f1aa50ab1fda2d2ecf32879bb24041cc7d" - integrity sha512-ytAS5XD0vMPUqTiifoueMCZhVLouyq/iOAG9hwfnQQwaRQy9xrgmvI//rsdIk+Qnfa02bJ0wLwDB4+yV1rNAjg== - lmdb@2.8.5: version "2.8.5" resolved "https://registry.yarnpkg.com/lmdb/-/lmdb-2.8.5.tgz#ce191110c755c0951caa062722e300c703973837" @@ -10391,11 +9312,6 @@ modify-values@^1.0.0: resolved "https://registry.yarnpkg.com/modify-values/-/modify-values-1.0.1.tgz#b3939fa605546474e3e3e3c63d64bd43b4ee6022" integrity sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw== -monero-regex@^1.0.8: - version "1.0.9" - resolved "https://registry.yarnpkg.com/monero-regex/-/monero-regex-1.0.9.tgz#4445e98a5d48d038b050fc25ff2e9155b989525c" - integrity sha512-4kUBp+a/DWmL/m/oVUQLJHe7BKvY4M3XoLtCnCBo/qbXH/FOD/umuttAMFoBTp/1imsYmvPtxxNYxdQY9T+DKg== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -10507,7 +9423,7 @@ mute-stream@0.0.8, mute-stream@~0.0.4: resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== -nan@^2.13.2, nan@^2.14.0: +nan@^2.13.2: version "2.25.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.25.0.tgz#937ed345e63d9481362a7942d49c4860d27eeabd" integrity sha512-0M90Ag7Xn5KMLLZ7zliPWP3rT90P6PN+IzVFS0VqmnPktBk3700xUVv8Ikm9EUaUE5SDWdp/BIxdENzVznpm1g== @@ -10554,11 +9470,6 @@ neo-async@^2.6.2: resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.2.tgz#b4aafb93e3aeb2d8174ca53cf163ab7d7308305f" integrity sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw== -neo-regex@^1.0.7: - version "1.0.8" - resolved "https://registry.yarnpkg.com/neo-regex/-/neo-regex-1.0.8.tgz#5ee1d77fcc41f7ac91ddf0215673230e840de27d" - integrity sha512-opwHKu5/HjHP2kGssiUKb108rGkamAaVGBf9aDhSvpiyPhSLHCd9ED9tzg2rtGDbOozQL8RvmwssYahjlIFyNw== - next-tick@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.1.0.tgz#1836ee30ad56d67ef281b22bd199f709449b35eb" @@ -11711,18 +10622,6 @@ pushdata-bitcoin@^1.0.1: dependencies: bitcoin-ops "^1.3.0" -pvtsutils@^1.3.5, pvtsutils@^1.3.6: - version "1.3.6" - resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.6.tgz#ec46e34db7422b9e4fdc5490578c1883657d6001" - integrity sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg== - dependencies: - tslib "^2.8.1" - -pvutils@^1.1.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.5.tgz#84b0dea4a5d670249aa9800511804ee0b7c2809c" - integrity sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA== - q@^1.5.1: version "1.5.1" resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" @@ -11941,11 +10840,6 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg== - regenerator-runtime@^0.14.1: version "0.14.1" resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" @@ -11990,7 +10884,7 @@ request-promise-native@^1.0.7: stealthy-require "^1.1.1" tough-cookie "^2.3.3" -request@^2.79.0, request@^2.88.0, request@~2.88.0: +request@^2.79.0, request@^2.88.0: version "2.88.2" resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== @@ -12126,11 +11020,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1, ripemd160@^2.0.3: hash-base "^3.1.2" inherits "^2.0.4" -ripple-regex@^1.1.8: - version "1.1.8" - resolved "https://registry.yarnpkg.com/ripple-regex/-/ripple-regex-1.1.8.tgz#7b9113e7c0be7470efea482a8f4b9ea25f8dec37" - integrity sha512-8KdXWuN8ofXP1dSzp89mkf/V465bPpO+jny1/Wp+hlvA05u+m7YX2mjBamefkRco8l5FdicX6+HhoP6yS9PXEw== - rlp@^2.2.4: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" @@ -12150,22 +11039,6 @@ roarr@^2.15.3: semver-compare "^1.0.0" sprintf-js "^1.1.2" -rpc-websockets@^9.0.2: - version "9.3.5" - resolved "https://registry.yarnpkg.com/rpc-websockets/-/rpc-websockets-9.3.5.tgz#9adb87514cb219434d67b7d3f455e5c132aff956" - integrity sha512-4mAmr+AEhPYJ9TmDtxF3r3ZcbWy7W8kvZ4PoZYw/Xgp2J7WixjwTgiQZsoTDvch5nimmg3Ay6/0Kuh9oIvVs9A== - dependencies: - "@swc/helpers" "^0.5.11" - "@types/uuid" "^10.0.0" - "@types/ws" "^8.2.2" - buffer "^6.0.3" - eventemitter3 "^5.0.1" - uuid "^11.0.0" - ws "^8.5.0" - optionalDependencies: - bufferutil "^4.0.1" - utf-8-validate "^6.0.0" - rsvp@^4.8.4: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" @@ -12257,30 +11130,11 @@ saxes@^5.0.1: dependencies: xmlchars "^2.2.0" -scrypt-js@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.4.tgz#32f8c5149f0797672e551c07e230f834b6af5f16" - integrity sha512-4KsaGcPnuhtCZQCxFxN3GVYIhKFPTdLd8PLC552XwbMndtD0cjRFAhDuuydXQ0h08ZfPgzqe6EKHozpuH74iDw== - -scrypt-js@3.0.1, scrypt-js@^3.0.0, scrypt-js@^3.0.1: +scrypt-js@^3.0.0, scrypt-js@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-3.0.1.tgz#d314a57c2aef69d1ad98a138a21fe9eafa9ee312" integrity sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA== -secp256k1@^3.0.1: - version "3.8.1" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.8.1.tgz#b62a62a882d6b16f9b51fe599c6b3a861e36c59f" - integrity sha512-tArjQw2P0RTdY7QmkNehgp6TVvQXq6ulIhxv8gaH6YubKG/wxxAoNKcbuXjDhybbc+b2Ihc7e0xxiGN744UIiQ== - dependencies: - bindings "^1.5.0" - bip66 "^1.1.5" - bn.js "^4.11.8" - create-hash "^1.2.0" - drbg.js "^1.0.1" - elliptic "^6.5.7" - nan "^2.14.0" - safe-buffer "^5.1.2" - secp256k1@^4.0.1: version "4.0.4" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-4.0.4.tgz#58f0bfe1830fe777d9ca1ffc7574962a8189f8ab" @@ -12396,11 +11250,6 @@ set-value@^2.0.0, set-value@^2.0.1: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - integrity sha512-/TjEmXQVEzdod/FFskf3o7oOAsGhHf2j1dZqRFbDzq4F3mvvxflIIi4Hd3bLQE9y/CpwqfSQam5JakI/mi3Pog== - setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -12779,11 +11628,6 @@ stream-browserify@^3.0.0: inherits "~2.0.4" readable-stream "^3.5.0" -stream-chain@^2.2.5: - version "2.2.5" - resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09" - integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA== - stream-http@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-3.2.0.tgz#1872dfcf24cb15752677e40e5c3f9cc1926028b5" @@ -12794,13 +11638,6 @@ stream-http@^3.2.0: readable-stream "^3.6.0" xtend "^4.0.2" -stream-json@^1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.9.1.tgz#e3fec03e984a503718946c170db7d74556c2a187" - integrity sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw== - dependencies: - stream-chain "^2.2.5" - strict-event-emitter@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.1.0.tgz#fd742c1fb7e3852f0b964ecdae2d7666a6fb7ef8" @@ -12916,11 +11753,6 @@ superstruct@^0.15.3: resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-0.15.5.tgz#0f0a8d3ce31313f0d84c6096cd4fa1bfdedc9dab" integrity sha512-4AOeU+P5UuE/4nOUkmcQdW5y7i9ndt1cQd/3iUe+LTz3RxESf/W/5lg4B74HbDMMv8PHnPnGCQFH45kBcrQYoQ== -superstruct@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/superstruct/-/superstruct-2.0.2.tgz#3f6d32fbdc11c357deff127d591a39b996300c54" - integrity sha512-uV+TFRZdXsqXTL2pRvujROjdZQ4RAlBUS5BTh9IGm+jTqQntYThciG/qu57Gs69yjnVUSqdxF9YLmSnpupBW9A== - supports-color@^7.0.0, supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -13009,21 +11841,6 @@ temp-dir@^1.0.0: resolved "https://registry.yarnpkg.com/temp-dir/-/temp-dir-1.0.0.tgz#0a7c0ea26d3a39afa7e0ebea9c1fc0bc4daa011d" integrity sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ== -tendermint-tx-builder@^1.0.9: - version "1.0.16" - resolved "https://registry.yarnpkg.com/tendermint-tx-builder/-/tendermint-tx-builder-1.0.16.tgz#85271682b655771c85e6148b5590226d9af946fd" - integrity sha512-QooHyd5BeyoqruneSzmDUUpyD1/U877mEDMLPRk/e2SvobZuALJWijQReny0hqTkukseQpIZNKMD4ypMa1pCaQ== - dependencies: - "@bithighlander/bitcoin-cash-js-lib" "^5.2.1" - "@pioneer-platform/loggerdog" "^8.0.1" - "@pioneer-platform/pioneer-coins" "^8.1.19" - "@shapeshiftoss/hdwallet-core" latest - "@types/node" "^15.0.2" - bip39 "^3.0.4" - codeclimate-test-reporter "^0.5.1" - fiosdk-offline "^1.2.21" - google-protobuf "^3.17.0" - term-size@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.1.tgz#2a6a54840432c2fb6320fea0f415531e90189f54" @@ -13046,16 +11863,6 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" -text-encoding-utf-8@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/text-encoding-utf-8/-/text-encoding-utf-8-1.0.2.tgz#585b62197b0ae437e3c7b5d0af27ac1021e10d13" - integrity sha512-8bw4MY9WjdsD2aMtO0OzOCY3pXGYNx2d2FfHRVUKkiCPDWjKuOlhLVASS+pD7VkLTVjW268LYJHwsnPFlBpbAg== - -text-encoding@0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/text-encoding/-/text-encoding-0.7.0.tgz#f895e836e45990624086601798ea98e8f36ee643" - integrity sha512-oJQ3f1hrOnbRLOcwKz0Liq2IcrvDeZRHXhd9RgLrsT+DjWY/nty1Hi7v3dtkaEYbPYe0mUoOfzRrMwfXXwgPUA== - text-extensions@^1.0.0: version "1.9.0" resolved "https://registry.yarnpkg.com/text-extensions/-/text-extensions-1.9.0.tgz#1853e45fee39c945ce6f6c36b2d659b5aabc2a26" @@ -13096,7 +11903,7 @@ timed-out@^4.0.1: resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" integrity sha512-G7r3AhovYtr5YKOWQkta8RKAPb+J9IsO4uVmzjl8AZwfhs8UcUwTiD6gcJYSgOtzyjvQKrKYn41syHbUWMkafA== -tiny-secp256k1@^1.1.1, tiny-secp256k1@^1.1.3, tiny-secp256k1@^1.1.6: +tiny-secp256k1@^1.1.3, tiny-secp256k1@^1.1.6: version "1.1.7" resolved "https://registry.yarnpkg.com/tiny-secp256k1/-/tiny-secp256k1-1.1.7.tgz#0c1b6b9d2d93404f9093dc7e287b0aa834480573" integrity sha512-eb+F6NabSnjbLwNoC+2o5ItbmP1kg7HliWue71JgLegQt6A5mTN8YbvTLCazdlg6e5SV6A+r8OGvZYskdlmhqQ== @@ -13285,7 +12092,7 @@ tslib@^1.8.1, tslib@^1.9.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2.0.0, tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.7.0, tslib@^2.8.0, tslib@^2.8.1: +tslib@^2.1.0, tslib@^2.3.0, tslib@^2.4.0, tslib@^2.8.0: version "2.8.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== @@ -13391,11 +12198,6 @@ type@^2.7.2: resolved "https://registry.yarnpkg.com/type/-/type-2.7.3.tgz#436981652129285cc3ba94f392886c2637ea0486" integrity sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ== -typecast@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/typecast/-/typecast-0.0.1.tgz#fffb75dcb6bdf1def8e293b6b6e893d6c1ed19de" - integrity sha512-L2f5OCLKsJdCjSyN0d5O6CkNxhiC8EQ2XlXnHpWZVNfF+mj2OTaXhAVnP0/7SY/sxO1DHZpOFMpIuGlFUZEGNA== - typed-array-buffer@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" @@ -13473,16 +12275,6 @@ uglify-js@^3.1.4: resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.19.3.tgz#82315e9bbc6f2b25888858acd1fff8441035b77f" integrity sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ== -uint8array-tools@^0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.8.tgz#712bab001f8347bd782f45bc47c76ffff32d1e0b" - integrity sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g== - -uint8array-tools@^0.0.9: - version "0.0.9" - resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.9.tgz#e29e6d05f3472273db1b0e370ac1d91e4a0a4e6f" - integrity sha512-9vqDWmoSXOoi+K14zNaf6LBV51Q8MayF0/IiQs3GlygIKUYtog603e6virExkjjFosfJUBI4LhbQK1iq8IG11A== - ultron@~1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" @@ -13621,13 +12413,6 @@ utf-8-validate@^5.0.2: dependencies: node-gyp-build "^4.3.0" -utf-8-validate@^6.0.0: - version "6.0.6" - resolved "https://registry.yarnpkg.com/utf-8-validate/-/utf-8-validate-6.0.6.tgz#8a842c9b15af3f6323a3d5ed5eb9e61d208d8c22" - integrity sha512-q3l3P9UtEEiAHcsgsqTgf9PPjctrDWoIXW3NpOHFdRDbLvu4DLIcxHangJ4RLrWkBcKjmcs/6NkerI8T/rE4LA== - dependencies: - node-gyp-build "^4.3.0" - utf8@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/utf8/-/utf8-3.0.0.tgz#f052eed1364d696e769ef058b183df88c87f69d1" @@ -13638,7 +12423,7 @@ util-deprecate@^1.0.1, util-deprecate@~1.0.1: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== -util@^0.12.3, util@^0.12.5: +util@^0.12.5: version "0.12.5" resolved "https://registry.yarnpkg.com/util/-/util-0.12.5.tgz#5f17a6059b73db61a875668781a1c2b136bd6fbc" integrity sha512-kZf/K6hEIrWHI6XqOFUiiMa+79wE/D8Q+NCNAWclkyg3b4d2k7s0QGepNjiABc+aR3N1PAyHL7p6UcLY6LmrnA== @@ -13659,16 +12444,6 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== -uuid@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - integrity sha512-nWg9+Oa3qD2CQzHIP4qKUqwNfzKn8P0LtFhotaCTFchsV7ZfDhAybeip/HZVeMIpZi9JgY1E3nUlwaCmZT1sEg== - -uuid@^11.0.0: - version "11.1.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.0.tgz#9549028be1753bb934fc96e2bca09bb4105ae912" - integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== - uuid@^3.3.2: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" @@ -13703,11 +12478,6 @@ v8-to-istanbul@^7.0.0: convert-source-map "^1.6.0" source-map "^0.7.3" -valibot@^0.38.0: - version "0.38.0" - resolved "https://registry.yarnpkg.com/valibot/-/valibot-0.38.0.tgz#2d035d2a5bd36e8ea8b48b56d44552ace1a7616f" - integrity sha512-RCJa0fetnzp+h+KN9BdgYOgtsMAG9bfoJ9JSjIhFHobKWVWyzM3jjaeNTdpFK9tQtf3q1sguXeERJ/LcmdFE7w== - validate-npm-package-license@^3.0.1, validate-npm-package-license@^3.0.4: version "3.0.4" resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" @@ -13730,15 +12500,6 @@ validate-npm-package-name@^4.0.0: dependencies: builtins "^5.0.0" -validate@^5.1.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/validate/-/validate-5.2.0.tgz#fe7355c1644092b67dd07731ad5716cb99f689a5" - integrity sha512-pVADd6GfDT7bALYvvzhfHnfmxCDem2bG7lGY3mwHzY7ktMH/SaczoF+eKkGokQEdGKozkJvyuOiSfQEHXp4zIA== - dependencies: - "@eivifj/dot" "^1.0.1" - component-type "1.2.1" - typecast "0.0.1" - varint@^5.0.0: version "5.0.2" resolved "https://registry.yarnpkg.com/varint/-/varint-5.0.2.tgz#5b47f8a947eb668b848e034dcfa87d0ff8a7f7a4" @@ -13751,13 +12512,6 @@ varuint-bitcoin@^1.0.4: dependencies: safe-buffer "^5.1.1" -varuint-bitcoin@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-2.0.0.tgz#59a53845a87ad18c42f184a3d325074465341523" - integrity sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog== - dependencies: - uint8array-tools "^0.0.8" - vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -13834,15 +12588,6 @@ weak-lru-cache@^1.2.2: resolved "https://registry.yarnpkg.com/weak-lru-cache/-/weak-lru-cache-1.2.2.tgz#fdbb6741f36bae9540d12f480ce8254060dccd19" integrity sha512-DEAoo25RfSYMuTGc9vPJzZcZullwIqRDSI9LOy+fkCJPi6hykCnfKaXTuPBDuXAUcqHXyOgFtHNp/kB2FjYHbw== -web-encoding@^1.1.0, web-encoding@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/web-encoding/-/web-encoding-1.1.5.tgz#fc810cf7667364a6335c939913f5051d3e0c4864" - integrity sha512-HYLeVCdJ0+lBYV2FvNZmv3HJ2Nt0QYXqZojk3d9FJOLkwnuhzM9tmamh8d7HPM8QqjKH8DeHkFTx+CFlWpZZDA== - dependencies: - util "^0.12.3" - optionalDependencies: - "@zxing/text-encoding" "0.9.0" - web3-bzz@1.10.4: version "1.10.4" resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.10.4.tgz#dcc787970767d9004c73d11d0eeef774ce16b880" @@ -14073,17 +12818,6 @@ web3@^1.5.1: web3-shh "1.10.4" web3-utils "1.10.4" -webcrypto-core@^1.8.0: - version "1.8.1" - resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.8.1.tgz#09d5bd8a9c48e9fbcaf412e06b1ff1a57514ce86" - integrity sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A== - dependencies: - "@peculiar/asn1-schema" "^2.3.13" - "@peculiar/json-schema" "^1.1.12" - asn1js "^3.0.5" - pvtsutils "^1.3.5" - tslib "^2.7.0" - webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -14298,11 +13032,6 @@ write-pkg@^4.0.0: type-fest "^0.4.1" write-json-file "^3.2.0" -ws@7.4.6: - version "7.4.6" - resolved "https://registry.yarnpkg.com/ws/-/ws-7.4.6.tgz#5654ca8ecdeee47c33a9a4bf6d28e2be2980377c" - integrity sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A== - ws@^3.0.0: version "3.3.3" resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" @@ -14312,16 +13041,11 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" -ws@^7, ws@^7.0.0, ws@^7.4.6, ws@^7.5.10: +ws@^7, ws@^7.0.0, ws@^7.4.6: version "7.5.10" resolved "https://registry.yarnpkg.com/ws/-/ws-7.5.10.tgz#58b5c20dc281633f6c19113f39b349bd8bd558d9" integrity sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ== -ws@^8.5.0: - version "8.19.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-8.19.0.tgz#ddc2bdfa5b9ad860204f5a72a4863a8895fd8c8b" - integrity sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg== - xhr-request-promise@^0.1.2: version "0.1.3" resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.3.tgz#2d5f4b16d8c6c893be97f1a62b0ed4cf3ca5f96c" @@ -14367,11 +13091,6 @@ xmlchars@^2.1.1, xmlchars@^2.2.0: resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb" integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw== -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - integrity sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA== - xstream@^11.14.0: version "11.14.0" resolved "https://registry.yarnpkg.com/xstream/-/xstream-11.14.0.tgz#2c071d26b18310523b6877e86b4e54df068a9ae5" From 8bc43a27d036aa4c762e9d1157d8e8f36ad2a850 Mon Sep 17 00:00:00 2001 From: highlander Date: Mon, 9 Mar 2026 16:48:25 -0600 Subject: [PATCH 2/3] fix: add missing bs58/bs58check deps, fix lint errors - Add bs58, bs58check as direct dependencies of hdwallet-keepkey (were phantom-hoisted from removed hdwallet-native) - Add @types/bs58, @types/bs58check as devDependencies - Fix prettier formatting in transport.ts (line too long from cast) - Apply eslint autofix (import sort, prettier, blank lines) - Suppress pre-existing namespace lint errors in solana.ts --- integration/src/bitcoin/bitcoin.ts | 3 --- packages/hdwallet-keepkey/package.json | 4 ++++ packages/hdwallet-keepkey/src/ethereum.ts | 1 + packages/hdwallet-keepkey/src/keepkey.ts | 6 +++++- packages/hdwallet-keepkey/src/ripple.ts | 1 + packages/hdwallet-keepkey/src/solana.ts | 3 ++- packages/hdwallet-keepkey/src/transport.ts | 3 ++- 7 files changed, 15 insertions(+), 6 deletions(-) diff --git a/integration/src/bitcoin/bitcoin.ts b/integration/src/bitcoin/bitcoin.ts index 8cc94c5d..eb43c023 100644 --- a/integration/src/bitcoin/bitcoin.ts +++ b/integration/src/bitcoin/bitcoin.ts @@ -359,7 +359,6 @@ export function bitcoinTests(get: () => { wallet: core.HDWallet; info: core.HDWa async () => { if (!wallet) return; - const res = wallet.btcSignMessage({ addressNList: core.bip32ToAddressNList("m/44'/0'/0'/0/0"), coin: "Bitcoin", @@ -381,7 +380,6 @@ export function bitcoinTests(get: () => { wallet: core.HDWallet; info: core.HDWa async () => { if (!wallet) return; - const res = await wallet.btcVerifyMessage({ address: "1FH6ehAd5ZFXCM1cLGzHxK1s4dGdq1JusM", coin: "Bitcoin", @@ -400,7 +398,6 @@ export function bitcoinTests(get: () => { wallet: core.HDWallet; info: core.HDWa async () => { if (!wallet) return; - const res = await wallet.btcVerifyMessage({ address: "1FH6ehAd5ZFXCM1cLGzHxK1s4dGdq1JusM", coin: "Bitcoin", diff --git a/packages/hdwallet-keepkey/package.json b/packages/hdwallet-keepkey/package.json index f8b6b2fa..a192d9d0 100644 --- a/packages/hdwallet-keepkey/package.json +++ b/packages/hdwallet-keepkey/package.json @@ -23,6 +23,8 @@ "@metamask/eth-sig-util": "^7.0.0", "@shapeshiftoss/bitcoinjs-lib": "5.2.0-shapeshift.2", "bignumber.js": "^9.0.1", + "bs58": "^4.0.0", + "bs58check": "^2.1.2", "crypto-js": "^4.0.0", "eip55": "^2.1.0", "google-protobuf": "^3.15.8", @@ -35,6 +37,8 @@ "@cosmjs/amino": "^0.28.13", "@cosmjs/proto-signing": "^0.28.13", "@cosmjs/stargate": "^0.28.13", + "@types/bs58": "^4.0.1", + "@types/bs58check": "^2.1.0", "@types/create-hash": "^1.2.2", "@types/crypto-js": "^4.0.0", "@types/google-protobuf": "^3.15.1", diff --git a/packages/hdwallet-keepkey/src/ethereum.ts b/packages/hdwallet-keepkey/src/ethereum.ts index 36d088c3..94ce8bca 100644 --- a/packages/hdwallet-keepkey/src/ethereum.ts +++ b/packages/hdwallet-keepkey/src/ethereum.ts @@ -6,6 +6,7 @@ import * as Types from "@keepkey/device-protocol/lib/types_pb"; import * as core from "@keepkey/hdwallet-core"; import { SignTypedDataVersion, TypedDataUtils } from "@metamask/eth-sig-util"; import * as eip55 from "eip55"; + import { Transport } from "./transport"; import { toUTF8Array } from "./utils"; diff --git a/packages/hdwallet-keepkey/src/keepkey.ts b/packages/hdwallet-keepkey/src/keepkey.ts index f470f31b..fa3551f8 100644 --- a/packages/hdwallet-keepkey/src/keepkey.ts +++ b/packages/hdwallet-keepkey/src/keepkey.ts @@ -1355,7 +1355,11 @@ export class KeepKeyHDWallet implements core.HDWallet, core.BTCWallet, core.ETHW return Solana.solanaSignTx(this.transport, msg); } - public solanaSignMessage(msg: { addressNList: number[]; message: Uint8Array | string; showDisplay?: boolean }): Promise<{ publicKey: Uint8Array; signature: Uint8Array }> { + public solanaSignMessage(msg: { + addressNList: number[]; + message: Uint8Array | string; + showDisplay?: boolean; + }): Promise<{ publicKey: Uint8Array; signature: Uint8Array }> { return Solana.solanaSignMessage(this.transport, msg); } diff --git a/packages/hdwallet-keepkey/src/ripple.ts b/packages/hdwallet-keepkey/src/ripple.ts index 3336beb7..a94efb57 100644 --- a/packages/hdwallet-keepkey/src/ripple.ts +++ b/packages/hdwallet-keepkey/src/ripple.ts @@ -1,6 +1,7 @@ import * as Messages from "@keepkey/device-protocol/lib/messages_pb"; import * as RippleMessages from "@keepkey/device-protocol/lib/messages-ripple_pb"; import * as core from "@keepkey/hdwallet-core"; + import { Transport } from "./transport"; export function rippleGetAccountPaths(msg: core.RippleGetAccountPaths): Array { diff --git a/packages/hdwallet-keepkey/src/solana.ts b/packages/hdwallet-keepkey/src/solana.ts index eebc4632..623f4321 100644 --- a/packages/hdwallet-keepkey/src/solana.ts +++ b/packages/hdwallet-keepkey/src/solana.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-namespace */ import * as Messages from "@keepkey/device-protocol/lib/messages_pb"; import * as core from "@keepkey/hdwallet-core"; import * as jspb from "google-protobuf"; @@ -723,7 +724,7 @@ export async function solanaSignTx(transport: Transport, msg: core.SolanaSignTx) */ export async function solanaSignMessage( transport: Transport, - msg: { addressNList: number[]; message: Uint8Array | string; showDisplay?: boolean }, + msg: { addressNList: number[]; message: Uint8Array | string; showDisplay?: boolean } ): Promise<{ publicKey: Uint8Array; signature: Uint8Array }> { return transport.lockDuring(async () => { const signMsg = new SolanaSignMessage(); diff --git a/packages/hdwallet-keepkey/src/transport.ts b/packages/hdwallet-keepkey/src/transport.ts index 49388997..2d01da3e 100644 --- a/packages/hdwallet-keepkey/src/transport.ts +++ b/packages/hdwallet-keepkey/src/transport.ts @@ -115,7 +115,8 @@ export class Transport extends core.Transport { public async getFirmwareHash(firmware: Uint8Array): Promise { if (typeof window !== "undefined" && window?.crypto) { - return new Uint8Array(await window.crypto.subtle.digest({ name: "SHA-256" }, firmware.buffer.slice(firmware.byteOffset, firmware.byteOffset + firmware.byteLength) as ArrayBuffer)); + const buf = firmware.buffer.slice(firmware.byteOffset, firmware.byteOffset + firmware.byteLength) as ArrayBuffer; + return new Uint8Array(await window.crypto.subtle.digest({ name: "SHA-256" }, buf)); } const hash = crypto.createHash("sha256"); hash.update(firmware); From 032349687fa14a8cc79f0e0605fe5637504ed3db Mon Sep 17 00:00:00 2001 From: highlander Date: Mon, 9 Mar 2026 16:50:50 -0600 Subject: [PATCH 3/3] ci: enable build + lint steps, fix sandbox lint Now that native packages are removed, the build passes cleanly. Add build and lint steps to GitHub Actions CI workflow. Fix import sort in sandbox (eslint autofix). --- .github/workflows/ci.yml | 6 ++++++ examples/sandbox/index.ts | 1 - yarn.lock | 17 ++++++++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3aa37d40..7fdb4ab7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,3 +25,9 @@ jobs: - name: Install dependencies run: yarn --frozen-lockfile + + - name: Build + run: yarn build + + - name: Lint + run: yarn lint diff --git a/examples/sandbox/index.ts b/examples/sandbox/index.ts index 027a7366..30cdbbf9 100644 --- a/examples/sandbox/index.ts +++ b/examples/sandbox/index.ts @@ -4,7 +4,6 @@ import * as core from "@keepkey/hdwallet-core"; import * as keepkey from "@keepkey/hdwallet-keepkey"; import * as keepkeyTcp from "@keepkey/hdwallet-keepkey-tcp"; import * as keepkeyWebUSB from "@keepkey/hdwallet-keepkey-webusb"; - import * as sigUtil from "@metamask/eth-sig-util"; import { TypedData } from "eip-712"; import $ from "jquery"; diff --git a/yarn.lock b/yarn.lock index 9677ac4c..6f024d7a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3416,6 +3416,21 @@ dependencies: "@types/node" "*" +"@types/bs58@^4.0.1": + version "4.0.4" + resolved "https://registry.yarnpkg.com/@types/bs58/-/bs58-4.0.4.tgz#49fbcb0c7db5f7cea26f0e0f61dc4a41a2445aab" + integrity sha512-0IEpMFXXQi2zXaXl9GJ3sRwQo0uEkD+yFOv+FnAU5lkPtcu6h61xb7jc2CFPEZ5BUOaiP13ThuGc9HD4R8lR5g== + dependencies: + "@types/node" "*" + base-x "^3.0.6" + +"@types/bs58check@^2.1.0": + version "2.1.2" + resolved "https://registry.yarnpkg.com/@types/bs58check/-/bs58check-2.1.2.tgz#ca6264599cd9c0bdfeb839a0927f13a9cb77ba0f" + integrity sha512-xpXaQlOIY1KoXlA/ytHGHpEIU87PJt+g9SH7nC6HdCgaBwT2IEZIwBMHbjuX6BpnfbiUMlmwqurdLDwXpcdmSA== + dependencies: + "@types/node" "*" + "@types/cacheable-request@^6.0.1", "@types/cacheable-request@^6.0.2": version "6.0.3" resolved "https://registry.yarnpkg.com/@types/cacheable-request/-/cacheable-request-6.0.3.tgz#a430b3260466ca7b5ca5bfd735693b36e7a9d183" @@ -4283,7 +4298,7 @@ balanced-match@^1.0.0: resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== -base-x@^3.0.11, base-x@^3.0.2, base-x@^3.0.8: +base-x@^3.0.11, base-x@^3.0.2, base-x@^3.0.6, base-x@^3.0.8: version "3.0.11" resolved "https://registry.yarnpkg.com/base-x/-/base-x-3.0.11.tgz#40d80e2a1aeacba29792ccc6c5354806421287ff" integrity sha512-xz7wQ8xDhdyP7tQxwdteLYeFfS68tSMNCZ/Y37WJ4bhGfKPpqEIlmIyueQHqOyoPhE6xNUqjzRr8ra0eF9VRvA==