diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index 8a6f2cf8..00000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,83 +0,0 @@ -version: 2.1 - -orbs: - hdwallet: - executors: - node: - docker: - - image: cimg/node:16.20.2 - kkemu: - docker: - - image: cimg/node:16.20.2 - - image: kktech/kkemu:latest - jobs: - build: - description: Get deps and persist to workspace - executor: kkemu - environment: - JEST_JUNIT_OUTPUT: "test-results/js-test-results.xml" - steps: - - run: sudo apt-get update && sudo apt-get install libudev-dev libusb-dev libusb-1.0 libtool - - checkout - - run: - name: Authenticate with registry - command: echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" > .npmrc - - restore_cache: - name: Restore Yarn Package Cache - keys: - - cache-v6-{{ checksum "yarn.lock" }} - - run: yarn --frozen-lockfile --cache-folder ./.yarn-cache - - run: - no_output_timeout: 30m - name: Build packages - command: yarn build - - run: - name: Lint - command: yarn lint - - run: - name: Run unit tests - command: yarn test --runInBand --coverage=false - - run: - name: Run integration tests - command: yarn test:integration --runInBand - - store_test_results: - path: test-results - - persist_to_workspace: - root: . - paths: - - node_modules - - .npmrc - - .yarn-cache - - save_cache: - name: Save Yarn Package Cache - key: cache-v6-{{ checksum "yarn.lock" }} - paths: - - .yarn-cache - - run: - name: Ensure repo is clean from uncommitted changes, likely yarn.lock is out of date - command: git diff --quiet || exit 1 - release-packages: - description: Build and release local dependency packages - executor: node - steps: - - checkout - - attach_workspace: - at: . - - run: yarn --cache-folder .yarn-cache - - run: git status - - run: ./node_modules/.bin/lerna publish from-package --yes --no-verify-access -workflows: - version: 2 - Build and Release: - jobs: - - hdwallet/build: - name: build - - hdwallet/release-packages: - name: release-packages - requires: - - build - filters: - branches: - only: - - master - - v1-legacy diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..e960fa2f --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,39 @@ +name: CI + +on: + push: + branches: [master] + pull_request: + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18] + steps: + - uses: actions/checkout@v4 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node-version }} + cache: yarn + + - name: Install system dependencies + run: sudo apt-get update && sudo apt-get install -y libudev-dev libusb-dev libusb-1.0-0-dev libtool + + - name: Install dependencies + run: yarn --frozen-lockfile + + - name: Build + run: yarn build + + - name: Lint + run: yarn lint + + - name: Unit tests + run: yarn test --runInBand --coverage=false + + - name: Ensure no uncommitted changes + run: git diff --quiet || exit 1 diff --git a/examples/sandbox/index.ts b/examples/sandbox/index.ts index 75bbaa65..27afc975 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 native from "@keepkey/hdwallet-native"; import * as sigUtil from "@metamask/eth-sig-util"; import { TypedData } from "eip-712"; import $ from "jquery"; @@ -217,25 +216,9 @@ class BIP39PathEditor { } } -const testPublicWalletXpubs = [ - "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(" "); - const keepkeyAdapter = keepkeyWebUSB.WebUSBKeepKeyAdapter.useKeyring(keyring); const kkbridgeAdapter = keepkeyTcp.TCPKeepKeyAdapter.useKeyring(keyring); const kkemuAdapter = keepkeyTcp.TCPKeepKeyAdapter.useKeyring(keyring); -const nativeAdapter = native.NativeAdapter.useKeyring(keyring); window["keyring"] = keyring; @@ -247,7 +230,6 @@ window["wallet"] = wallet; const $keepkey = $("#keepkey"); const $keepkeybridge = $("#keepkeybridge"); const $kkemu = $("#kkemu"); -const $native = $("#native"); const $keyring = $("#keyring"); $keepkey.on("click", async (e) => { @@ -271,13 +253,6 @@ $kkemu.on("click", async (e) => { $("#keyring select").val(await wallet.transport.getDeviceID()); }); -$native.on("click", async (e) => { - e.preventDefault(); - wallet = await nativeAdapter.pairDevice("testid"); - window["wallet"] = wallet; - $("#keyring select").val(await wallet.getDeviceID()); -}); - // Update settings button visibility based on wallet connection function updateSettingsButtonVisibility() { if (wallet && wallet.transport) { @@ -337,7 +312,6 @@ async function deviceConnected(deviceId) { keyring.on(["*", "*", core.Events.PIN_REQUEST], () => window["pinOpen"]()); keyring.on(["*", "*", core.Events.PASSPHRASE_REQUEST], () => window["passphraseOpen"]()); - keyring.on(["*", "*", native.NativeEvents.MNEMONIC_REQUIRED], () => window["mnemonicOpen"]()); try { await kkbridgeAdapter.pairDevice("http://localhost:1646"); @@ -345,12 +319,6 @@ async function deviceConnected(deviceId) { console.error("Could not initialize keepkey bridge", e); } - try { - await nativeAdapter.initialize(); - } catch (e) { - console.error("Could not initialize NativeAdapter", e); - } - for (const deviceID of Object.keys(keyring.wallets)) { await deviceConnected(deviceID); } @@ -423,9 +391,6 @@ window["mnemonicEntered"] = async function () { }; window["useTestWallet"] = async function () { - wallet.loadDevice({ - mnemonic: await native.crypto.Isolation.Engines.Dummy.BIP39.Mnemonic.create(testPublicWalletXpubs), - }); document.getElementById("#mnemonicModal").className = "modal"; }; @@ -480,16 +445,6 @@ $("#settings-kkemu").on("click", async (e) => { updateSettingsButtonVisibility(); }); -$("#settings-native").on("click", async (e) => { - e.preventDefault(); - wallet = await nativeAdapter.pairDevice("testid"); - window["wallet"] = wallet; - const deviceID = await wallet.getDeviceID(); - $("#keyring").val(deviceID); - $("#settings-keyring").val(deviceID); - updateSettingsButtonVisibility(); -}); - // Settings modal device management buttons $("#settings-getLabel").on("click", async () => { if (!wallet) { @@ -1082,22 +1037,6 @@ $("#kyc-pair-emulator").on("click", async function (e) { } }); -// KYC Pair Native -$("#kyc-pair-native").on("click", async function (e) { - e.preventDefault(); - try { - kycWallet = await nativeAdapter.pairDevice("kyc-testid"); - window["wallet"] = kycWallet; - wallet = kycWallet; - const deviceID = await kycWallet.getDeviceID(); - updateKycDeviceStatus(true, `Native Wallet ${deviceID.substring(0, 8)}...`); - await updateKycAddressPreview(); - } catch (error) { - console.error("Failed to pair native wallet:", error); - alert("Failed to pair native wallet."); - } -}); - // KYC Chain Selection $(".chain-option").on("click", async function () { $(".chain-option").removeClass("selected"); diff --git a/examples/sandbox/package.json b/examples/sandbox/package.json index 21751821..1cf456a7 100644 --- a/examples/sandbox/package.json +++ b/examples/sandbox/package.json @@ -4,7 +4,6 @@ "@keepkey/hdwallet-core": "1.53.16", "@keepkey/hdwallet-keepkey-tcp": "1.53.16", "@keepkey/hdwallet-keepkey-webusb": "1.53.16", - "@keepkey/hdwallet-native": "1.53.16", "@metamask/eth-sig-util": "^7.0.0", "@pioneer-platform/pioneer-coins": "^9.11.11", "bip32": "^2.0.4", 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..eb43c023 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,11 +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"), coin: "Bitcoin", @@ -386,11 +380,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", coin: "Bitcoin", @@ -409,11 +398,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", coin: "Bitcoin", 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-core/src/utils.ts b/packages/hdwallet-core/src/utils.ts index 1882ae4d..6c7d0aad 100644 --- a/packages/hdwallet-core/src/utils.ts +++ b/packages/hdwallet-core/src/utils.ts @@ -171,7 +171,7 @@ export function relativePath(path: BIP32Path): BIP32Path { export function toArrayBuffer(x: ArrayBuffer | ArrayBufferView): ArrayBuffer { if (x instanceof ArrayBuffer) return x; - return x.buffer.slice(x.byteOffset, x.byteOffset + x.byteLength); + return x.buffer.slice(x.byteOffset, x.byteOffset + x.byteLength) as ArrayBuffer; } export function mustBeDefined(x: T): NonNullable { 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/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 46a407b2..94ce8bca 100644 --- a/packages/hdwallet-keepkey/src/ethereum.ts +++ b/packages/hdwallet-keepkey/src/ethereum.ts @@ -6,11 +6,29 @@ 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 +259,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/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 16410a6d..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)); + 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); 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"