diff --git a/examples/sandbox/index.html b/examples/sandbox/index.html index 89b88970d..f70b1a1b5 100644 --- a/examples/sandbox/index.html +++ b/examples/sandbox/index.html @@ -300,12 +300,13 @@
Arkeo

Ethereum

- + + - - - + + +
@@ -437,11 +438,6 @@

Mnemoic Required

- diff --git a/examples/sandbox/index.ts b/examples/sandbox/index.ts index e19c78df9..51a3d2875 100644 --- a/examples/sandbox/index.ts +++ b/examples/sandbox/index.ts @@ -1,5 +1,6 @@ import "regenerator-runtime/runtime"; +import * as sigUtil from "@metamask/eth-sig-util"; import * as coinbase from "@shapeshiftoss/hdwallet-coinbase"; import { CoinbaseProviderConfig } from "@shapeshiftoss/hdwallet-coinbase"; import * as core from "@shapeshiftoss/hdwallet-core"; @@ -19,7 +20,8 @@ import * as walletConnect from "@shapeshiftoss/hdwallet-walletconnect"; import * as walletConnectv2 from "@shapeshiftoss/hdwallet-walletconnectv2"; import * as xdefi from "@shapeshiftoss/hdwallet-xdefi"; import { EthereumProviderOptions } from "@walletconnect/ethereum-provider/dist/types/EthereumProvider"; -import $ from "jquery"; +import { TypedData } from "eip-712"; +import $, { noop } from "jquery"; import Web3 from "web3"; import { @@ -47,7 +49,8 @@ import { } from "./json/cosmos/cosmosAminoTx.json"; import * as dashTxJson from "./json/dashTx.json"; import * as dogeTxJson from "./json/dogeTx.json"; -import { eip712 } from "./json/ethTx.json"; +import { eip712, txs } from "./json/ethereum/ethTx.json"; +import { openSeaListNFTMessage } from "./json/ethereum/OpenSea-ethSignTypedDataV4.json"; import * as ltcTxJson from "./json/ltcTx.json"; import { osmosisDelegateTx, @@ -164,16 +167,6 @@ const $xdefi = $("#xdefi"); const $keplr = $("#keplr"); const $keyring = $("#keyring"); -const $ethAddr = $("#ethAddr"); -const $ethTx = $("#ethTx"); -const $ethSign = $("#ethSign"); -const $ethSend = $("#ethSend"); -const $ethVerify = $("#ethVerify"); -const $ethResults = $("#ethResults"); -const $ethEIP1559 = $("#ethEIP1559"); -const $ethSignTypedData = $("#ethSignTypedData"); -const $ethSignTypedDataPreCalculate = $("#ethSignTypedDataPreCalculate"); - $keepkey.on("click", async (e) => { e.preventDefault(); wallet = await keepkeyAdapter.pairDevice(undefined, /*tryDebugLink=*/ true); @@ -380,7 +373,10 @@ async function deviceConnected(deviceId) { } try { - await ledgerWebUSBAdapter.initialize(); + // skip initialize() on page load b/c: + // Error: WebUSBCouldNotInitialize.... + // "Must be handling a user gesture to show a permission request." + noop(); } catch (e) { console.error("Could not initialize LedgerWebUSBAdapter", e); } @@ -416,7 +412,7 @@ async function deviceConnected(deviceId) { } try { - await keplrAdapter.initialize([]); + await keplrAdapter.initialize(); } catch (e) { console.error("Could not initialize KeplrAdapter", e); } @@ -921,7 +917,7 @@ $rippleAddr.on("click", async (e) => { $rippleTx.on("click", async (e) => { e.preventDefault(); if (!wallet) { - $ethResults.val("No wallet?"); + $rippleResults.val("No wallet?"); return; } if (core.supportsRipple(wallet)) { @@ -954,7 +950,7 @@ const $eosResults = $("#eosResults"); $eosAddr.on("click", async (e) => { e.preventDefault(); if (!wallet) { - $ethResults.val("No wallet?"); + $eosResults.val("No wallet?"); return; } if (core.supportsEos(wallet)) { @@ -978,7 +974,7 @@ $eosAddr.on("click", async (e) => { $eosTx.on("click", async (e) => { e.preventDefault(); if (!wallet) { - $ethResults.val("No wallet?"); + $eosResults.val("No wallet?"); return; } if (core.supportsEos(wallet)) { @@ -1044,21 +1040,18 @@ const $fioResults = $("#fioResults"); $fioAddr.on("click", async (e) => { e.preventDefault(); if (!wallet) { - $ethResults.val("No wallet?"); + $fioResults.val("No wallet?"); return; } if (core.supportsFio(wallet)) { const { addressNList } = wallet.fioGetAccountPaths({ accountIdx: 0 })[0]; - let result = await wallet.fioGetPublicKey({ + let result = await wallet.fioGetAddress({ addressNList, showDisplay: false, - kind: 0, }); - result = await wallet.fioGetPublicKey({ + result = await wallet.fioGetAddress({ addressNList, showDisplay: true, - kind: 0, - address: result, }); $fioResults.val(result); } else { @@ -1070,7 +1063,7 @@ $fioAddr.on("click", async (e) => { $fioTx.on("click", async (e) => { e.preventDefault(); if (!wallet) { - $ethResults.val("No wallet?"); + $fioResults.val("No wallet?"); return; } if (core.supportsFio(wallet)) { @@ -1094,9 +1087,9 @@ $fioTx.on("click", async (e) => { console.info(res); console.info("signature = %d", res.signature); - console.info("serialized = %s", core.toHexString(res.serialized)); + console.info("serialized = %s", res.serialized); - $eosResults.val(res.fioFormSig); + $fioResults.val(JSON.stringify(res)); } else { const label = await wallet.getLabel(); $fioResults.val(label + " does not support Fio"); @@ -1496,7 +1489,7 @@ $thorchainSignSwap.on("click", async (e) => { $thorchainSwapResults.val(JSON.stringify(res)); } else { const label = await wallet.getLabel(); - $ethResults.val(label + " does not support ETH"); + $thorchainSwapResults.val(label + " does not support ETH"); } break; default: @@ -1666,7 +1659,7 @@ $thorchainSignAddLiquidity.on("click", async (e) => { $thorchainAddLiquidityResults.val(JSON.stringify(res)); } else { const label = await wallet.getLabel(); - $ethResults.val(label + " does not support ETH"); + $thorchainAddLiquidityResults.val(label + " does not support ETH"); } break; default: @@ -2480,36 +2473,34 @@ $osmosisSwap.on("click", async (e) => { * Bech32: false */ +interface EthOperationConfig { + handler: (params: any) => Promise; + useEIP1559?: boolean; + typedDataValue?: "OpenSea" | "EIP712DomainIsPrimaryType" | "longPrimaryTypeString"; +} let ethEIP1559Selected = false; -const ethTx = { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - nonce: "0x01", - gasPrice: "0x1dcd65000", - gasLimit: "0x5622", - value: "0x2c68af0bb14000", - to: "0x12eC06288EDD7Ae2CC41A843fE089237fC7354F0", - chainId: 1, - data: "", -}; - -const ethTx1559 = { - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - nonce: "0x0", - gasLimit: "0x5ac3", - maxFeePerGas: "0x16854be509", - maxPriorityFeePerGas: "0x540ae480", - value: "0x1550f7dca70000", // 0.006 eth - to: "0xfc0cc6e85dff3d75e3985e0cb83b090cfd498dd1", - chainId: 1, - data: "", -}; +const ethButtons = [ + "ethAddr", + "ethTx", + "ethSign", + "ethSend", + "ethVerify", + "ethResults", + "ethEIP1559", + "ethSignTypedData", + "ethSignTypedDataAlternate1", + "ethSignTypedDataAlternate2", +].reduce((acc, id) => { + acc[id] = $(`#${id}`); + return acc; +}, {} as Record>); -$ethAddr.on("click", async (e) => { +const performEthOperation = async (e: any, config: EthOperationConfig) => { e.preventDefault(); if (!wallet) { - $ethResults.val("No wallet?"); + ethButtons.ethResults.val("No wallet?"); return; } @@ -2518,139 +2509,145 @@ $ethAddr.on("click", async (e) => { coin: "Ethereum", accountIdx: 0, })[0]; - let result = await wallet.ethGetAddress({ - addressNList: hardenedPath.concat(relPath), - showDisplay: false, - }); - result = await wallet.ethGetAddress({ - addressNList: hardenedPath.concat(relPath), - showDisplay: true, - address: result, - }); - $ethResults.val(result); - } else { - const label = await wallet.getLabel(); - $ethResults.val(label + " does not support ETH"); - } -}); - -$ethTx.on("click", async (e) => { - e.preventDefault(); - if (!wallet) { - $ethResults.val("No wallet?"); - return; - } - if (core.supportsETH(wallet)) { - const res = ethEIP1559Selected ? await wallet.ethSignTx(ethTx1559) : await wallet.ethSignTx(ethTx); - $ethResults.val(JSON.stringify(res)); - } else { - const label = await wallet.getLabel(); - $ethResults.val(label + " does not support ETH"); - } -}); -$ethSign.on("click", async (e) => { - e.preventDefault(); - if (!wallet) { - $ethResults.val("No wallet?"); - return; - } - if (core.supportsETH(wallet)) { - const { hardenedPath: hard, relPath: rel } = wallet.ethGetAccountPaths({ - coin: "Ethereum", - accountIdx: 0, - })[0]; - const result = await wallet.ethSignMessage({ - addressNList: hard.concat(rel), - message: "Hello World", - }); - $ethResults.val(result.address + ", " + result.signature); - } else { - const label = await wallet.getLabel(); - $ethResults.val(label + " does not support ETH"); - } -}); + const tx = config.useEIP1559 && ethEIP1559Selected ? txs.ethTx1559 : txs.ethTxLegacy; + let typedData: TypedData | undefined; -$ethSend.on("click", async (e) => { - e.preventDefault(); - if (!wallet) { - $ethResults.val("No wallet?"); - return; - } - if (core.supportsETH(wallet)) { - const result = ethEIP1559Selected - ? await wallet.ethSendTx(ethTx1559 as core.ETHSignTx) - : await wallet.ethSendTx(ethTx as core.ETHSignTx); - console.info("Result: ", result); - $ethResults.val(result.hash); + switch (config.typedDataValue) { + case "OpenSea": + typedData = openSeaListNFTMessage; + break; + case "longPrimaryTypeString": + typedData = eip712["longPrimaryTypeString"]["typedData"]; + break; + case "EIP712DomainIsPrimaryType": + typedData = eip712["EIP712DomainIsPrimaryType"]["typedData"]; + break; + default: + typedData = undefined; + } + const result = await config.handler({ hardenedPath, relPath, tx, typedData }); + ethButtons.ethResults.val(result); } else { const label = await wallet.getLabel(); - $ethResults.val(label + " does not support ETH"); + ethButtons.ethResults.val(`${label} does not support ETH`); } -}); +}; -$ethVerify.on("click", async (e) => { - e.preventDefault(); - if (!wallet) { - $ethResults.val("No wallet?"); - return; - } - if (core.supportsETH(wallet)) { - const result = await wallet.ethVerifyMessage({ - address: "0x2068dD92B6690255553141Dfcf00dF308281f763", - message: "Hello World", - signature: - "61f1dda82e9c3800e960894396c9ce8164fd1526fccb136c71b88442405f7d09721725629915d10bc7cecfca2818fe76bc5816ed96a1b0cebee9b03b052980131b", - }); - $ethResults.val(result ? "✅" : "❌"); - } else { - const label = await wallet.getLabel(); - $ethResults.val(label + " does not support ETH"); - } -}); +ethButtons.ethAddr.on("click", (e) => + performEthOperation(e, { + handler: async ({ hardenedPath, relPath }) => { + let result = await wallet.ethGetAddress({ + addressNList: hardenedPath.concat(relPath), + showDisplay: false, + }); + result = await wallet.ethGetAddress({ + addressNList: hardenedPath.concat(relPath), + showDisplay: true, + address: result, + }); + return result; + }, + }) +); + +ethButtons.ethTx.on("click", (e) => + performEthOperation(e, { + handler: async ({ tx }) => { + const res = await wallet.ethSignTx(tx); + return JSON.stringify(res); + }, + useEIP1559: ethEIP1559Selected, + }) +); + +ethButtons.ethSign.on("click", (e) => + performEthOperation(e, { + handler: async ({ hardenedPath, relPath }) => { + const result = await wallet.ethSignMessage({ + addressNList: hardenedPath.concat(relPath), + message: "0x48656c6c6f20576f726c64", // "Hello World", + }); + return `Address: ${result.address} Signature: ${result.signature}`; + }, + }) +); + +ethButtons.ethSend.on("click", (e) => + performEthOperation(e, { + handler: async ({ tx }) => { + if (wallet?.ethSendTx) { + const result = await wallet.ethSendTx(tx as core.ETHSignTx); + return result.hash; + } else { + const label = await wallet.getVendor(); + return label + " does not support ethSendTx"; + } + }, + useEIP1559: ethEIP1559Selected, + }) +); + +ethButtons.ethVerify.on("click", (e) => + performEthOperation(e, { + handler: async () => { + const signerAddress = "0x2068dD92B6690255553141Dfcf00dF308281f763"; + const result = await wallet.ethVerifyMessage({ + address: signerAddress, + message: "Hello World", + signature: + "0x61f1dda82e9c3800e960894396c9ce8164fd1526fccb136c71b88442405f7d09721725629915d10bc7cecfca2818fe76bc5816ed96a1b0cebee9b03b052980131b", + }); + return result ? `✅ ${signerAddress} is the signer` : `❌ ${signerAddress} is NOT the signer`; + }, + }) +); -$ethEIP1559.on("click", async () => { - if (!ethEIP1559Selected) { - $ethEIP1559.attr("class", "button"); - } else { - $ethEIP1559.attr("class", "button-outline"); - } +ethButtons.ethEIP1559.on("click", () => { ethEIP1559Selected = !ethEIP1559Selected; + ethButtons.ethEIP1559.attr("class", ethEIP1559Selected ? "button" : "button-outline"); }); -$ethSignTypedData.on("click", async (e) => { - e.preventDefault(); - if (!wallet) { - $ethResults.val("No wallet?"); - return; - } - if (core.supportsETH(wallet)) { - const result = await wallet.ethSignTypedData({ - typedData: eip712["calculateHashesOnDevice"]["typedData"], - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - }); - $ethResults.val(JSON.stringify(result, null, 2)); - } -}); +const doesRecoveredMatchAddress = (typedData: TypedData, fromAddress: string, signature: string): boolean => { + const recoveredAddress = sigUtil.recoverTypedSignature({ + data: typedData, + signature: signature, + version: sigUtil.SignTypedDataVersion.V4, + }); + return Web3.utils.toChecksumAddress(recoveredAddress) === Web3.utils.toChecksumAddress(fromAddress); +}; -$ethSignTypedDataPreCalculate.on("click", async (e) => { - e.preventDefault(); - if (!wallet) { - $ethResults.val("No wallet?"); - return; - } - if (!keepkey.isKeepKey(wallet)) { - $ethResults.val("Action only supported for KeepKey"); - return; - } - if (core.supportsETH(wallet)) { - const result = await wallet.ethSignTypedData({ - typedData: eip712["precalculateHashes"]["typedData"], - addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"), - }); - $ethResults.val(JSON.stringify(result, null, 2)); - } -}); +const ethSignTypedDataHandler = async ({ hardenedPath, relPath, typedData }) => { + const { address, signature } = await wallet.ethSignTypedData({ + typedData, + addressNList: hardenedPath.concat(relPath), + }); + const success = doesRecoveredMatchAddress(typedData, address, signature); + return ( + (success ? `✅ "${address}" is the signer` : `❌ "${address}" is NOT the signer`) + `; Signature is: "${signature}"` + ); +}; + +ethButtons.ethSignTypedData.on("click", (e) => + performEthOperation(e, { + handler: ethSignTypedDataHandler, + typedDataValue: "OpenSea", + }) +); + +ethButtons.ethSignTypedDataAlternate1.on("click", (e) => + performEthOperation(e, { + handler: ethSignTypedDataHandler, + typedDataValue: "longPrimaryTypeString", + }) +); + +ethButtons.ethSignTypedDataAlternate2.on("click", (e) => + performEthOperation(e, { + handler: ethSignTypedDataHandler, + typedDataValue: "EIP712DomainIsPrimaryType", + }) +); /* ERC-20 diff --git a/examples/sandbox/json/ethTx.json b/examples/sandbox/json/ethTx.json deleted file mode 100644 index 77f3b5d2c..000000000 --- a/examples/sandbox/json/ethTx.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "eip712": { - "precalculateHashes": { - "typedData": { - "types": { - "EIP712Domain": [ - { - "name": "name", - "type": "string" - }, - { - "name": "version", - "type": "string" - }, - { - "name": "chainId", - "type": "uint256" - }, - { - "name": "verifyingContract", - "type": "address" - }, - { - "name": "salt", - "type": "bytes32" - } - ], - "Person": [ - { - "name": "name", - "type": "string" - }, - { - "name": "wallet", - "type": "address" - }, - { - "name": "married", - "type": "bool" - }, - { - "name": "kids", - "type": "uint8" - }, - { - "name": "karma", - "type": "int16" - }, - { - "name": "secret", - "type": "bytes" - }, - { - "name": "small_secret", - "type": "bytes16" - }, - { - "name": "pets", - "type": "string[]" - }, - { - "name": "two_best_friends", - "type": "string[2]" - } - ], - "ThisIsARidiculouslyLongPrimaryTypeToForceHashesToBePrecalculatedByHDWalletKeepKey": [ - { - "name": "from", - "type": "Person" - }, - { - "name": "to", - "type": "Person" - }, - { - "name": "messages", - "type": "string[]" - } - ] - }, - "primaryType": "ThisIsARidiculouslyLongPrimaryTypeToForceHashesToBePrecalculatedByHDWalletKeepKey", - "domain": { - "name": "Ether Mail", - "version": "1", - "chainId": 1, - "verifyingContract": "0x1e0Ae8205e9726E6F296ab8869160A6423E2337E", - "salt": "0xca92da1a6e91d9358328d2f2155af143a7cb74b81a3a4e3e57e2191823dbb56c" - }, - "message": { - "from": { - "name": "Amy", - "wallet": "0xc0004B62C5A39a728e4Af5bee0c6B4a4E54b15ad", - "married": true, - "kids": 2, - "karma": 4, - "secret": "0x62c5a39a728e4af5bee0c6b462c5a39a728e4af5bee0c6b462c5a39a728e4af5bee0c6b462c5a39a728e4af5bee0c6b4", - "small_secret": "0x5ccf0e54367104795a47bc0481645d9e", - "pets": ["parrot"], - "two_best_friends": ["Carl", "Denis"] - }, - "to": { - "name": "Bob", - "wallet": "0x54B0Fa66A065748C40dCA2C7Fe125A2028CF9982", - "married": false, - "kids": 0, - "karma": -4, - "secret": "0x7fe125a2028cf97fe125a2028cf97fe125a2028cf97fe125a2028cf97fe125a2028cf97fe125a2028cf97fe125a2028cf9", - "small_secret": "0xa5e5c47b64775abc476d2962403258de", - "pets": ["dog", "cat"], - "two_best_friends": ["Emil", "Franz"] - }, - "messages": ["Hello, Bob!", "How are you?", "Hope you're fine"] - } - } - }, - "calculateHashesOnDevice": { - "typedData": { - "types": { - "EIP712Domain": [ - { "name": "name", "type": "string" }, - { "name": "version", "type": "string" }, - { "name": "chainId", "type": "uint256" }, - { "name": "verifyingContract", "type": "address" } - ], - "Permit": [ - { "name": "owner", "type": "address" }, - { "name": "spender", "type": "address" }, - { "name": "value", "type": "uint256" }, - { "name": "nonce", "type": "uint256" }, - { "name": "deadline", "type": "uint256" } - ] - }, - "domain": { - "name": "USD Coin", - "version": "2", - "verifyingContract": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", - "chainId": 1 - }, - "primaryType": "Permit", - "message": { - "owner": "0x33b35c665496bA8E71B22373843376740401F106", - "spender": "0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45", - "value": "4023865", - "nonce": 0, - "deadline": 1655431026 - } - } - } - } - } \ No newline at end of file diff --git a/examples/sandbox/json/ethereum/OpenSea-ethSignTypedDataV4.json b/examples/sandbox/json/ethereum/OpenSea-ethSignTypedDataV4.json new file mode 100644 index 000000000..44b3a7400 --- /dev/null +++ b/examples/sandbox/json/ethereum/OpenSea-ethSignTypedDataV4.json @@ -0,0 +1,164 @@ +{ + "openSeaListNFTMessage": { + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ], + "OrderComponents": [ + { + "name": "offerer", + "type": "address" + }, + { + "name": "zone", + "type": "address" + }, + { + "name": "offer", + "type": "OfferItem[]" + }, + { + "name": "consideration", + "type": "ConsiderationItem[]" + }, + { + "name": "orderType", + "type": "uint8" + }, + { + "name": "startTime", + "type": "uint256" + }, + { + "name": "endTime", + "type": "uint256" + }, + { + "name": "zoneHash", + "type": "bytes32" + }, + { + "name": "salt", + "type": "uint256" + }, + { + "name": "conduitKey", + "type": "bytes32" + }, + { + "name": "counter", + "type": "uint256" + } + ], + "OfferItem": [ + { + "name": "itemType", + "type": "uint8" + }, + { + "name": "token", + "type": "address" + }, + { + "name": "identifierOrCriteria", + "type": "uint256" + }, + { + "name": "startAmount", + "type": "uint256" + }, + { + "name": "endAmount", + "type": "uint256" + } + ], + "ConsiderationItem": [ + { + "name": "itemType", + "type": "uint8" + }, + { + "name": "token", + "type": "address" + }, + { + "name": "identifierOrCriteria", + "type": "uint256" + }, + { + "name": "startAmount", + "type": "uint256" + }, + { + "name": "endAmount", + "type": "uint256" + }, + { + "name": "recipient", + "type": "address" + } + ] + }, + "primaryType": "OrderComponents", + "domain": { + "name": "Seaport", + "version": "1.5", + "chainId": 137, + "verifyingContract": "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC" + }, + "message": { + "offerer": "0x8c9Ed98b7C3961D22Cc871356C7b73d194608817", + "offer": [ + { + "itemType": "2", + "token": "0xa9a6A3626993D487d2Dbda3173cf58cA1a9D9e9f", + "identifierOrCriteria": "64560424590441301826453812164224751707642265079650986418901366599236941237984", + "startAmount": "1", + "endAmount": "1" + } + ], + "consideration": [ + { + "itemType": "1", + "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "identifierOrCriteria": "0", + "startAmount": "194707500000000000", + "endAmount": "194707500000000000", + "recipient": "0x8c9Ed98b7C3961D22Cc871356C7b73d194608817" + }, + { + "itemType": "1", + "token": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619", + "identifierOrCriteria": "0", + "startAmount": "4992500000000000", + "endAmount": "4992500000000000", + "recipient": "0x0000a26b00c1F0DF003000390027140000fAa719" + } + ], + "startTime": "1696393777", + "endTime": "1699072168", + "orderType": 0, + "zone": "0x0000000000000000000000000000000000000000", + "zoneHash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "salt": "24446860302761739304752683030156737591518664810215442929815805592127532436551", + "conduitKey": "0x0000007b02230091a7ed01230072f7006a004d60a8d4e71d599b8104250f0000", + "totalOriginalConsiderationItems": "2", + "counter": "0" + } + } +} diff --git a/examples/sandbox/json/ethereum/ethTx.json b/examples/sandbox/json/ethereum/ethTx.json new file mode 100644 index 000000000..c43243e07 --- /dev/null +++ b/examples/sandbox/json/ethereum/ethTx.json @@ -0,0 +1,198 @@ +{ + "eip712": { + "longPrimaryTypeString": { + "typedData": { + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + }, + { + "name": "salt", + "type": "bytes32" + } + ], + "Person": [ + { + "name": "name", + "type": "string" + }, + { + "name": "wallet", + "type": "address" + }, + { + "name": "married", + "type": "bool" + }, + { + "name": "kids", + "type": "uint8" + }, + { + "name": "karma", + "type": "int16" + }, + { + "name": "secret", + "type": "bytes" + }, + { + "name": "small_secret", + "type": "bytes16" + }, + { + "name": "pets", + "type": "string[]" + }, + { + "name": "two_best_friends", + "type": "string[2]" + } + ], + "ThisIsARidiculouslyLongPrimaryTypeToForceHashesToBePrecalculatedByHDWalletKeepKey": [ + { + "name": "from", + "type": "Person" + }, + { + "name": "to", + "type": "Person" + }, + { + "name": "messages", + "type": "string[]" + } + ] + }, + "primaryType": "ThisIsARidiculouslyLongPrimaryTypeToForceHashesToBePrecalculatedByHDWalletKeepKey", + "domain": { + "name": "Ether Mail", + "version": "1", + "chainId": 1, + "verifyingContract": "0x1e0Ae8205e9726E6F296ab8869160A6423E2337E", + "salt": "0xca92da1a6e91d9358328d2f2155af143a7cb74b81a3a4e3e57e2191823dbb56c" + }, + "message": { + "from": { + "name": "Amy", + "wallet": "0xc0004B62C5A39a728e4Af5bee0c6B4a4E54b15ad", + "married": true, + "kids": 2, + "karma": 4, + "secret": "0x62c5a39a728e4af5bee0c6b462c5a39a728e4af5bee0c6b462c5a39a728e4af5bee0c6b462c5a39a728e4af5bee0c6b4", + "small_secret": "0x5ccf0e54367104795a47bc0481645d9e", + "pets": [ + "parrot" + ], + "two_best_friends": [ + "Carl", + "Denis" + ] + }, + "to": { + "name": "Bob", + "wallet": "0x54B0Fa66A065748C40dCA2C7Fe125A2028CF9982", + "married": false, + "kids": 0, + "karma": -4, + "secret": "0x7fe125a2028cf97fe125a2028cf97fe125a2028cf97fe125a2028cf97fe125a2028cf97fe125a2028cf97fe125a2028cf9", + "small_secret": "0xa5e5c47b64775abc476d2962403258de", + "pets": [ + "dog", + "cat" + ], + "two_best_friends": [ + "Emil", + "Franz" + ] + }, + "messages": [ + "Hello, Bob!", + "How are you?", + "Hope you're fine" + ] + } + } + }, + "EIP712DomainIsPrimaryType": { + "typedData": { + "types": { + "EIP712Domain": [ + { + "name": "name", + "type": "string" + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + }, + { + "name": "verifyingContract", + "type": "address" + } + ] + }, + "domain": { + "name": "USD Coin", + "version": "2", + "verifyingContract": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", + "chainId": 1 + }, + "primaryType": "EIP712Domain" + } + } + }, + "txs": { + "ethTxLegacy": { + "addressNList": [ + 2147483692, + 2147483708, + 2147483648, + 0, + 0 + ], + "nonce": "0x01", + "gasPrice": "0x1dcd65000", + "gasLimit": "0x5622", + "value": "0x2c68af0bb14000", + "to": "0x12eC06288EDD7Ae2CC41A843fE089237fC7354F0", + "chainId": 1, + "data": "" + }, + "ethTx1559": { + "addressNList": [ + 2147483692, + 2147483708, + 2147483648, + 0, + 0 + ], + "nonce": "0x0", + "gasLimit": "0x5ac3", + "maxFeePerGas": "0x16854be509", + "maxPriorityFeePerGas": "0x540ae480", + "value": "0x1550f7dca70000", + "to": "0xfc0cc6e85dff3d75e3985e0cb83b090cfd498dd1", + "chainId": 1, + "data": "" + } + } +} diff --git a/examples/sandbox/package.json b/examples/sandbox/package.json index 8ebb73a06..a2d922812 100644 --- a/examples/sandbox/package.json +++ b/examples/sandbox/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-sandbox", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "private": true, "browserslist": "> 0.5%, last 2 versions, not dead", @@ -10,23 +10,25 @@ "clean": "rm -rf dist node_modules public .parcel-cache" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey-tcp": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey-webusb": "1.52.4", - "@shapeshiftoss/hdwallet-keplr": "1.52.4", - "@shapeshiftoss/hdwallet-ledger": "1.52.4", - "@shapeshiftoss/hdwallet-ledger-webhid": "1.52.4", - "@shapeshiftoss/hdwallet-ledger-webusb": "1.52.4", - "@shapeshiftoss/hdwallet-metamask": "1.52.4", - "@shapeshiftoss/hdwallet-native": "1.52.4", - "@shapeshiftoss/hdwallet-portis": "1.52.4", - "@shapeshiftoss/hdwallet-tallyho": "1.52.4", - "@shapeshiftoss/hdwallet-trezor": "1.52.4", - "@shapeshiftoss/hdwallet-trezor-connect": "1.52.4", - "@shapeshiftoss/hdwallet-walletconnect": "1.52.4", - "@shapeshiftoss/hdwallet-xdefi": "1.52.4", + "@metamask/eth-sig-util": "^7.0.0", + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey-tcp": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey-webusb": "1.52.11", + "@shapeshiftoss/hdwallet-keplr": "1.52.11", + "@shapeshiftoss/hdwallet-ledger": "1.52.11", + "@shapeshiftoss/hdwallet-ledger-webhid": "1.52.11", + "@shapeshiftoss/hdwallet-ledger-webusb": "1.52.11", + "@shapeshiftoss/hdwallet-metamask": "1.52.11", + "@shapeshiftoss/hdwallet-native": "1.52.11", + "@shapeshiftoss/hdwallet-portis": "1.52.11", + "@shapeshiftoss/hdwallet-tallyho": "1.52.11", + "@shapeshiftoss/hdwallet-trezor": "1.52.11", + "@shapeshiftoss/hdwallet-trezor-connect": "1.52.11", + "@shapeshiftoss/hdwallet-walletconnect": "1.52.11", + "@shapeshiftoss/hdwallet-xdefi": "1.52.11", "bip32": "^2.0.4", - "jquery": "^3.4.1", + "eip-712": "^1.0.0", + "jquery": "^3.7.1", "json": "^9.0.6", "p-queue": "^7.4.1", "parcel": "^2.3.2", @@ -34,6 +36,7 @@ "web3": "^1.5.1" }, "devDependencies": { + "@types/jquery": "^3.5.22", "https-browserify": "^1.0.0", "os-browserify": "^0.3.0", "path-browserify": "^1.0.1", diff --git a/examples/sandbox/tsconfig.json b/examples/sandbox/tsconfig.json index 1589f985f..07062f202 100644 --- a/examples/sandbox/tsconfig.json +++ b/examples/sandbox/tsconfig.json @@ -1,5 +1,6 @@ { "compilerOptions": { "resolveJsonModule": true, + "esModuleInterop": true } -} \ No newline at end of file +} diff --git a/integration/package.json b/integration/package.json index 18e780fa4..b87633a75 100644 --- a/integration/package.json +++ b/integration/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/integration", - "version": "1.52.4", + "version": "1.52.11", "main": "index.js", "license": "MIT", "private": true, @@ -10,15 +10,15 @@ "dev": "lerna run test --scope integration --parallel --include-filtered-dependencies" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey-nodewebusb": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey-tcp": "1.52.4", - "@shapeshiftoss/hdwallet-ledger": "1.52.4", - "@shapeshiftoss/hdwallet-native": "1.52.4", - "@shapeshiftoss/hdwallet-portis": "1.52.4", - "@shapeshiftoss/hdwallet-trezor": "1.52.4", - "@shapeshiftoss/hdwallet-xdefi": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey-nodewebusb": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey-tcp": "1.52.11", + "@shapeshiftoss/hdwallet-ledger": "1.52.11", + "@shapeshiftoss/hdwallet-native": "1.52.11", + "@shapeshiftoss/hdwallet-portis": "1.52.11", + "@shapeshiftoss/hdwallet-trezor": "1.52.11", + "@shapeshiftoss/hdwallet-xdefi": "1.52.11", "fast-json-stable-stringify": "^2.1.0", "msw": "^0.27.1", "whatwg-fetch": "^3.6.2" diff --git a/integration/src/thorchain/thorchain.ts b/integration/src/thorchain/thorchain.ts index cce066297..b95ec45a0 100644 --- a/integration/src/thorchain/thorchain.ts +++ b/integration/src/thorchain/thorchain.ts @@ -1,5 +1,6 @@ import * as core from "@shapeshiftoss/hdwallet-core"; import * as keepkey from "@shapeshiftoss/hdwallet-keepkey"; +import * as ledger from "@shapeshiftoss/hdwallet-ledger"; import tx_unsigned_swap_amino from "./tx01.mainnet.thorchain.swap.amino.json"; import tx_unsigned_swap from "./tx01.mainnet.thorchain.swap.json"; @@ -25,7 +26,7 @@ export function thorchainTests(get: () => { wallet: core.HDWallet; info: core.HD beforeAll(async () => { const { wallet: w } = get(); if (core.supportsThorchain(w)) wallet = w; - useAmino = w instanceof keepkey.KeepKeyHDWallet; + useAmino = w instanceof keepkey.KeepKeyHDWallet || w instanceof ledger.LedgerHDWallet; }); beforeEach(async () => { diff --git a/integration/src/wallets/ledger.ts b/integration/src/wallets/ledger.ts index 8e8a19db5..7a4543051 100644 --- a/integration/src/wallets/ledger.ts +++ b/integration/src/wallets/ledger.ts @@ -1,5 +1,6 @@ import * as core from "@shapeshiftoss/hdwallet-core"; import * as ledger from "@shapeshiftoss/hdwallet-ledger"; +import { toByteArray } from "base64-js"; export class MockTransport extends ledger.LedgerTransport { memoized = new Map(); @@ -96,7 +97,7 @@ export class MockTransport extends ledger.LedgerTransport { "Eth", "signTransaction", JSON.parse( - '["m/44\'/60\'/0\'/0/0","eb018501dcd650008256229412ec06288edd7ae2cc41a843fe089237fc7354f0872c68af0bb1400080018080"]' + '["m/44\'/60\'/0\'/0/0","eb018501dcd650008256229412ec06288edd7ae2cc41a843fe089237fc7354f0872c68af0bb1400080018080", null]' ), JSON.parse( '{"success":true,"payload":{"v":"26","r":"63db3dd3bf3e1fe7dde1969c0fc8850e34116d0b501c0483a0e08c0f77b8ce0a","s":"28297d012cccf389f6332415e96ee3fc0bbf8474d05f646e029cd281a031464b"},"coin":"Eth","method":"signTransaction"}' @@ -106,7 +107,7 @@ export class MockTransport extends ledger.LedgerTransport { "Eth", "signTransaction", JSON.parse( - '["m/44\'/60\'/0\'/0/0","f8620114149441e5560054824ea6b0732e656e3ad64e20e94e4580b844a9059cbb0000000000000000000000001d8ce9022f6284c3a5c317f8f34620107214e54500000000000000000000000000000000000000000000000000000002540be400018080"]' + '["m/44\'/60\'/0\'/0/0","f8620114149441e5560054824ea6b0732e656e3ad64e20e94e4580b844a9059cbb0000000000000000000000001d8ce9022f6284c3a5c317f8f34620107214e54500000000000000000000000000000000000000000000000000000002540be400018080", null]' ), JSON.parse( '{"success":true,"payload":{"v":"25","r":"1238fd332545415f09a01470350a5a20abc784dbf875cf58f7460560e66c597f","s":"10efa4dd6fdb381c317db8f815252c2ac0d2a883bd364901dee3dec5b7d3660a"},"coin":"Eth","method":"signTransaction"}' @@ -212,6 +213,61 @@ export class MockTransport extends ledger.LedgerTransport { '{"success":true,"coin":"Btc","method":"getWalletPublicKey","payload":{"bitcoinAddress":"1FH6ehAd5ZFXCM1cLGzHxK1s4dGdq1JusM","chainCode":"fixme","publicKey":"fixme"}}' ) ); + + // Thorchain + const compress_pk = toByteArray("AxUZcTuLQr3DZxEtMxMs8Uzt+SisV3HURLpFm5SXEXuj"); + this.memoize( + "Rune", + "getAddressAndPubKey", + JSON.parse(`[[${core.bip32ToAddressNList("m/44'/931'/0'/0/0")}], "thor"]`), + JSON.parse( + `{"success":true,"coin":"Rune","method":"getAddressAndPubkey","payload":{"bech32_address":"thor1ls33ayg26kmltw7jjy55p32ghjna09zp74t4az","compressed_pk":[${compress_pk}]}}` + ) + ); + + const sig1 = toByteArray( + "1s+0FVJ5R8O+ewGq5yNbTQuVG5MJZppFDqVJ4cd5D68ogOb2GMVHvYCH2dvQXo/uK/fT6Rk6dLGhK8tgW/HqtA==" + ); + const r1 = sig1.slice(0, 32); + const s1 = sig1.slice(32, 64); + const rawSig1 = Uint8Array.from([48, 68, 2, 32, ...r1, 2, 32, ...s1]); + this.memoize( + "Rune", + "sign", + JSON.parse( + '[{"tx":{"account_number":"17","chain_id":"thorchain-mainnet-v1","sequence":"2","fee":{"amount":[{"amount":"3000","denom":"rune"}],"gas":"200000"},"memo":"","msg":[{"type":"thorchain/MsgSend","value":{"amount":[{"amount":"100","denom":"rune"}],"from_address":"thor1ls33ayg26kmltw7jjy55p32ghjna09zp74t4az","to_address":"thor1wy58774wagy4hkljz9mchhqtgk949zdwwe80d5"}}],"signatures":[]},"addressNList":[2147483692,2147484579,2147483648,0,0],"chain_id":"thorchain-mainnet-v1","account_number":"17","sequence":"2"}]' + ), + { + success: true, + coin: "Rune", + method: "sign", + payload: { + signature: rawSig1, + }, + } + ); + + const sig2 = toByteArray( + "0Bjk7npdUw/Qa4MQTS4PH8sw8jM4JSzpd7G2DsF3DMVoYgdpO2fjHh/DUq6v30nghxUSJj0jNm0VIq9viPB+tQ==" + ); + const r2 = sig2.slice(0, 32); + const s2 = sig2.slice(32, 64); + const rawSig2 = Uint8Array.from([48, 68, 2, 32, ...r2, 2, 32, ...s2]); + this.memoize( + "Rune", + "sign", + JSON.parse( + '[{"tx":{"account_number":"2722","chain_id":"thorchain-mainnet-v1","sequence":"4","fee":{"amount":[{"amount":"0","denom":"rune"}],"gas":"350000"},"memo":"","msg":[{"type":"thorchain/MsgDeposit","value":{"coins":[{"asset":"THOR.RUNE","amount":"50994000"}],"memo":"SWAP:BNB.BNB:bnb12splwpg8jenr9pjw3dwc5rr35t8792y8pc4mtf:348953501","signer":"thor1ls33ayg26kmltw7jjy55p32ghjna09zp74t4az"}}],"signatures":[]},"addressNList":[2147483692,2147484579,2147483648,0,0],"chain_id":"thorchain-mainnet-v1","account_number":"2722","sequence":"4"}]' + ), + { + success: true, + coin: "Rune", + method: "sign", + payload: { + signature: rawSig2, + }, + } + ); } catch (e) { console.error(e); } diff --git a/lerna.json b/lerna.json index 775b6dc9a..945a5152d 100644 --- a/lerna.json +++ b/lerna.json @@ -1,6 +1,6 @@ { "lerna": "5.2.0", - "version": "1.52.4", + "version": "1.52.11", "npmClient": "yarn", "useWorkspaces": true, "command": { diff --git a/packages/hdwallet-coinbase/package.json b/packages/hdwallet-coinbase/package.json index 25c520c19..54460a217 100644 --- a/packages/hdwallet-coinbase/package.json +++ b/packages/hdwallet-coinbase/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-coinbase", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -15,7 +15,7 @@ }, "dependencies": { "@coinbase/wallet-sdk": "^3.6.6", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "eth-rpc-errors": "^4.0.3", "lodash": "^4.17.21" }, diff --git a/packages/hdwallet-core/package.json b/packages/hdwallet-core/package.json index e029713fd..ccfd84313 100644 --- a/packages/hdwallet-core/package.json +++ b/packages/hdwallet-core/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-core", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" diff --git a/packages/hdwallet-keepkey-chromeusb/package.json b/packages/hdwallet-keepkey-chromeusb/package.json index 054eac834..7e920ff54 100644 --- a/packages/hdwallet-keepkey-chromeusb/package.json +++ b/packages/hdwallet-keepkey-chromeusb/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-keepkey-chromeusb", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,7 +14,7 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey": "1.52.4" + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey": "1.52.11" } } diff --git a/packages/hdwallet-keepkey-electron/package.json b/packages/hdwallet-keepkey-electron/package.json index f262ba9f9..91ae2b017 100644 --- a/packages/hdwallet-keepkey-electron/package.json +++ b/packages/hdwallet-keepkey-electron/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-keepkey-electron", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,7 +14,7 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-keepkey": "1.52.4", + "@shapeshiftoss/hdwallet-keepkey": "1.52.11", "uuid": "^8.3.2" }, "peerDependencies": { diff --git a/packages/hdwallet-keepkey-nodehid/package.json b/packages/hdwallet-keepkey-nodehid/package.json index 591263715..c44c0dbe6 100644 --- a/packages/hdwallet-keepkey-nodehid/package.json +++ b/packages/hdwallet-keepkey-nodehid/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-keepkey-nodehid", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,7 +14,7 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-keepkey": "1.52.4" + "@shapeshiftoss/hdwallet-keepkey": "1.52.11" }, "peerDependencies": { "node-hid": "^2.1.1" diff --git a/packages/hdwallet-keepkey-nodewebusb/package.json b/packages/hdwallet-keepkey-nodewebusb/package.json index 80bf14329..df52fa24b 100644 --- a/packages/hdwallet-keepkey-nodewebusb/package.json +++ b/packages/hdwallet-keepkey-nodewebusb/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-keepkey-nodewebusb", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,8 +14,8 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey": "1.52.4" + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey": "1.52.11" }, "peerDependencies": { "usb": "^2.3.1" diff --git a/packages/hdwallet-keepkey-tcp/package.json b/packages/hdwallet-keepkey-tcp/package.json index 33d434735..511ffe376 100644 --- a/packages/hdwallet-keepkey-tcp/package.json +++ b/packages/hdwallet-keepkey-tcp/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-keepkey-tcp", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,8 +14,8 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey": "1.52.11", "axios": "^0.21.1" } } diff --git a/packages/hdwallet-keepkey-webusb/package.json b/packages/hdwallet-keepkey-webusb/package.json index 1925db865..62f99d397 100644 --- a/packages/hdwallet-keepkey-webusb/package.json +++ b/packages/hdwallet-keepkey-webusb/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-keepkey-webusb", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,8 +14,8 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-keepkey": "1.52.4" + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-keepkey": "1.52.11" }, "devDependencies": { "@types/w3c-web-usb": "^1.0.4" diff --git a/packages/hdwallet-keepkey/package.json b/packages/hdwallet-keepkey/package.json index c33d785cf..3afe17885 100644 --- a/packages/hdwallet-keepkey/package.json +++ b/packages/hdwallet-keepkey/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-keepkey", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -18,13 +18,13 @@ "@ethereumjs/common": "^2.4.0", "@ethereumjs/tx": "^3.3.0", "@keepkey/device-protocol": "^7.12.2", + "@metamask/eth-sig-util": "^7.0.0", "@shapeshiftoss/bitcoinjs-lib": "5.2.0-shapeshift.2", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "@shapeshiftoss/proto-tx-builder": "^0.8.0", "bignumber.js": "^9.0.1", "bnb-javascript-sdk-nobroadcast": "^2.16.14", "crypto-js": "^4.0.0", - "eip-712": "^1.0.0", "eip55": "^2.1.0", "google-protobuf": "^3.15.8", "icepick": "^2.4.0", diff --git a/packages/hdwallet-keepkey/src/ethereum.ts b/packages/hdwallet-keepkey/src/ethereum.ts index 4c2d0ddd4..4062cdfe1 100644 --- a/packages/hdwallet-keepkey/src/ethereum.ts +++ b/packages/hdwallet-keepkey/src/ethereum.ts @@ -3,10 +3,10 @@ import { FeeMarketEIP1559Transaction, Transaction } from "@ethereumjs/tx"; import * as Messages from "@keepkey/device-protocol/lib/messages_pb"; import * as Ethereum from "@keepkey/device-protocol/lib/messages-ethereum_pb"; import * as Types from "@keepkey/device-protocol/lib/types_pb"; +import { SignTypedDataVersion, TypedDataUtils } from "@metamask/eth-sig-util"; import * as core from "@shapeshiftoss/hdwallet-core"; -import { getMessage, getTypeHash } from "eip-712"; import * as eip55 from "eip55"; -import * as ethers from "ethers"; +import { arrayify, isBytes, isHexString } from "ethers/lib/utils.js"; import { Transport } from "./transport"; import { toUTF8Array } from "./utils"; @@ -173,10 +173,10 @@ export async function ethGetAddress(transport: Transport, msg: core.ETHGetAddres export async function ethSignMessage(transport: Transport, msg: core.ETHSignMessage): Promise { const { addressNList, message } = msg; - if (!ethers.utils.isHexString(message)) throw new Error("data is not an hex string"); + if (!isHexString(message)) throw new Error("data is not an hex string"); const m = new Ethereum.EthereumSignMessage(); m.setAddressNList(addressNList); - const messageBytes = ethers.utils.arrayify(message); + const messageBytes = arrayify(message); m.setMessage(messageBytes); const response = await transport.call(Messages.MessageType.MESSAGETYPE_ETHEREUMSIGNMESSAGE, m, { msgTimeout: core.LONG_TIMEOUT, @@ -188,80 +188,49 @@ export async function ethSignMessage(transport: Transport, msg: core.ETHSignMess }; } +/** + * Supports EIP-712 eth_signTypedData_v4 + * https://docs.metamask.io/wallet/how-to/sign-data/#use-eth_signtypeddata_v4 + * Due to lack of firmware support, a hashed version of the data is + * displayed to the user on the device when signing + */ export async function ethSignTypedData( transport: Transport, msg: core.ETHSignTypedData ): Promise { - /** - * If the message to be signed is sufficiently small, the KeepKey can calculate the - * domain separator and message hashes. Otherwise, we need to pre-calculate hashes - * here and verify on device. - */ - - const sTypes = JSON.stringify({ types: msg.typedData.types }); - const sPrimaryType = JSON.stringify({ primaryType: msg.typedData.primaryType }); - const sDomain = JSON.stringify({ domain: msg.typedData.domain }); - const sMessage = JSON.stringify({ message: msg.typedData.message }); - try { - if (sTypes.length > 2048 || sPrimaryType.length > 80 || sDomain.length > 2048 || sMessage.length > 2048) { - /* Pre-calculate domain separator and messages hashes and verify on KeepKey */ - - const domainSeparatorHash = getTypeHash(msg.typedData, "EIP712Domain"); - const domainSeparatorHash64 = Buffer.from(domainSeparatorHash).toString("base64"); - const messageHash = getMessage(msg.typedData, true); - const messageHash64 = Buffer.from(messageHash).toString("base64"); - - const t = new Ethereum.EthereumSignTypedHash(); - t.setAddressNList(msg.addressNList); - t.setDomainSeparatorHash(domainSeparatorHash64); - t.setMessageHash(messageHash64); - - const response = await transport.call(Messages.MessageType.MESSAGETYPE_ETHEREUMSIGNTYPEDHASH, t, { - msgTimeout: core.LONG_TIMEOUT, - }); - - const result = response.proto as Ethereum.EthereumTypedDataSignature; - const res: core.ETHSignedTypedData = { - address: result.getAddress() || "", - signature: "0x" + core.toHexString(result.getSignature_asU8()), - }; - - return res; - } else { - /* Let KeepKey calculate domain separator and message hashes */ - const dsh = new Ethereum.Ethereum712TypesValues(); - dsh.setAddressNList(msg.addressNList); - dsh.setEip712types(sTypes); - dsh.setEip712primetype(sPrimaryType); - dsh.setEip712data(sDomain); - dsh.setEip712typevals(1); - - let response = await transport.call(Messages.MessageType.MESSAGETYPE_ETHEREUM712TYPESVALUES, dsh, { - msgTimeout: core.LONG_TIMEOUT, - omitLock: true, - }); - - const mh = new Ethereum.Ethereum712TypesValues(); - mh.setAddressNList(msg.addressNList); - mh.setEip712types(sTypes); - mh.setEip712primetype(sPrimaryType); - mh.setEip712data(sMessage); - mh.setEip712typevals(2); + const version = SignTypedDataVersion.V4; + const EIP_712_DOMAIN = "EIP712Domain"; + const { types, primaryType, domain, message } = msg.typedData; + const domainSeparatorHash: Uint8Array = TypedDataUtils.hashStruct(EIP_712_DOMAIN, domain, types, version); + + const ethereumSignTypedHash = new Ethereum.EthereumSignTypedHash(); + ethereumSignTypedHash.setAddressNList(msg.addressNList); + ethereumSignTypedHash.setDomainSeparatorHash(domainSeparatorHash); + + let messageHash: Uint8Array | undefined = undefined; + // If "EIP712Domain" is the primaryType, messageHash is not required - look at T1 connect impl ;) + // todo: the firmware should define messageHash as an optional Uint8Array field for this case + if (primaryType !== EIP_712_DOMAIN) { + messageHash = TypedDataUtils.hashStruct(primaryType, message, types, version); + ethereumSignTypedHash.setMessageHash(messageHash); + } - response = await transport.call(Messages.MessageType.MESSAGETYPE_ETHEREUM712TYPESVALUES, mh, { + const response = await transport.call( + Messages.MessageType.MESSAGETYPE_ETHEREUMSIGNTYPEDHASH, + ethereumSignTypedHash, + { msgTimeout: core.LONG_TIMEOUT, - omitLock: true, - }); + } + ); - const result = response.proto as Ethereum.EthereumTypedDataSignature; - const res: core.ETHSignedTypedData = { - address: result.getAddress() || "", - signature: "0x" + core.toHexString(result.getSignature_asU8()), - }; + const result = response.proto as Ethereum.EthereumTypedDataSignature; + const res: core.ETHSignedTypedData = { + address: result.getAddress() || "", + signature: "0x" + core.toHexString(result.getSignature_asU8()), + }; - return res; - } + return res; } catch (error) { console.error({ error }); throw new Error("Failed to sign typed ETH message"); @@ -272,7 +241,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(ethers.utils.isBytes(msg.message) ? ethers.utils.arrayify(msg.message) : toUTF8Array(msg.message)); + m.setMessage(isBytes(msg.message) ? arrayify(msg.message) : toUTF8Array(msg.message)); let event: core.Event; try { event = await transport.call(Messages.MessageType.MESSAGETYPE_ETHEREUMVERIFYMESSAGE, m, { diff --git a/packages/hdwallet-keplr/package.json b/packages/hdwallet-keplr/package.json index 17e4cce06..4af4968c0 100644 --- a/packages/hdwallet-keplr/package.json +++ b/packages/hdwallet-keplr/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-keplr", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -15,7 +15,7 @@ }, "dependencies": { "@shapeshiftoss/caip": "8.15.0", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "@shapeshiftoss/proto-tx-builder": "^0.8.0", "@shapeshiftoss/types": "3.1.3", "base64-js": "^1.5.1", @@ -24,7 +24,7 @@ "devDependencies": { "@cosmjs/amino": "^0.28.13", "@cosmjs/stargate": "^0.28.13", - "@keplr-wallet/types": "^0.9.10", + "@keplr-wallet/types": "^0.12.35", "@types/lodash": "^4.14.168" } } diff --git a/packages/hdwallet-keplr/src/keplr.ts b/packages/hdwallet-keplr/src/keplr.ts index 42b73796e..f501c9c7e 100644 --- a/packages/hdwallet-keplr/src/keplr.ts +++ b/packages/hdwallet-keplr/src/keplr.ts @@ -134,7 +134,7 @@ export class KeplrHDWallet implements core.HDWallet, core.CosmosWallet, core.Osm initialized = false; provider: any = {}; - supportedNetworks: ChainReference[] = [CHAIN_REFERENCE.CosmosHubMainnet, CHAIN_REFERENCE.OsmosisMainnet]; + supportedNetworks: ChainReference[] = [CHAIN_REFERENCE.CosmosHubMainnet]; constructor() { this.info = new KeplrHDWalletInfo(); diff --git a/packages/hdwallet-ledger-webhid/package.json b/packages/hdwallet-ledger-webhid/package.json index 1c3dc736b..c9d3dc7d7 100644 --- a/packages/hdwallet-ledger-webhid/package.json +++ b/packages/hdwallet-ledger-webhid/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-ledger-webhid", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -19,8 +19,8 @@ "@ledgerhq/hw-transport": "^6.7.0", "@ledgerhq/hw-transport-webhid": "^6.7.0", "@ledgerhq/live-common": "^21.8.2", - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-ledger": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-ledger": "1.52.11", "@types/w3c-web-hid": "^1.0.2" }, "devDependencies": { diff --git a/packages/hdwallet-ledger-webusb/package.json b/packages/hdwallet-ledger-webusb/package.json index a7fc35562..5e4837880 100644 --- a/packages/hdwallet-ledger-webusb/package.json +++ b/packages/hdwallet-ledger-webusb/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-ledger-webusb", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -20,8 +20,8 @@ "@ledgerhq/hw-transport-webusb": "^6.7.0", "@ledgerhq/live-common": "^21.8.2", "@ledgerhq/logs": "^6.10.1", - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-ledger": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-ledger": "1.52.11", "@types/w3c-web-usb": "^1.0.4", "p-queue": "^7.4.1" }, diff --git a/packages/hdwallet-ledger-webusb/src/transport.ts b/packages/hdwallet-ledger-webusb/src/transport.ts index 52623993a..b0efc05af 100644 --- a/packages/hdwallet-ledger-webusb/src/transport.ts +++ b/packages/hdwallet-ledger-webusb/src/transport.ts @@ -79,6 +79,11 @@ export async function translateCoinAndMethod> { switch (coin) { + case "Rune": { + const thor = new ledger.THORChainApp(transport); + const methodInstance = thor[method as LedgerTransportMethodName<"Rune">].bind(thor); + return methodInstance as LedgerTransportMethod; + } case "Btc": { const btc = new Btc({ transport }); const methodInstance = btc[method as LedgerTransportMethodName<"Btc">].bind(btc); diff --git a/packages/hdwallet-ledger/package.json b/packages/hdwallet-ledger/package.json index 17804e258..17c662282 100644 --- a/packages/hdwallet-ledger/package.json +++ b/packages/hdwallet-ledger/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-ledger", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -18,7 +18,7 @@ "@ethereumjs/common": "^2.4.0", "@ethereumjs/tx": "^3.3.0", "@shapeshiftoss/bitcoinjs-lib": "5.2.0-shapeshift.2", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "base64-js": "^1.5.1", "bchaddrjs": "^0.4.4", "bitcoinjs-message": "^2.0.0", @@ -36,6 +36,7 @@ "@types/bs58check": "^2.1.0", "@types/ethereumjs-tx": "1.0.1", "@types/ethereumjs-util": "^6.1.0", + "@types/ripemd160": "^2.0.2", "typedoc": "^0.20.36" } } diff --git a/packages/hdwallet-ledger/src/bitcoin.ts b/packages/hdwallet-ledger/src/bitcoin.ts index a71841a1c..558cbd6fb 100644 --- a/packages/hdwallet-ledger/src/bitcoin.ts +++ b/packages/hdwallet-ledger/src/bitcoin.ts @@ -37,9 +37,16 @@ export async function btcSupportsScriptType(coin: core.Coin, scriptType?: core.B export async function btcGetAddress(transport: LedgerTransport, msg: core.BTCGetAddress): Promise { const bip32path = core.addressNListToBIP32(msg.addressNList); + + const scriptTypeish = (() => { + if (msg.coin === "BitcoinCash") return core.BTCInputScriptType.CashAddr; + if (msg.scriptType) return msg.scriptType; + return core.BTCInputScriptType.SpendAddress; + })(); + const opts = { verify: !!msg.showDisplay, - format: translateScriptType(msg.scriptType ?? core.BTCInputScriptType.SpendAddress), + format: translateScriptType(scriptTypeish), }; const res = await transport.call("Btc", "getWalletPublicKey", bip32path, opts); diff --git a/packages/hdwallet-ledger/src/ethereum.ts b/packages/hdwallet-ledger/src/ethereum.ts index 5d2dc0045..bb7ff5a2b 100644 --- a/packages/hdwallet-ledger/src/ethereum.ts +++ b/packages/hdwallet-ledger/src/ethereum.ts @@ -6,7 +6,7 @@ import EthereumTx from "ethereumjs-tx"; // @ts-ignore // TODO: fix ts-ignore import * as ethereumUtil from "ethereumjs-util"; -import * as ethers from "ethers"; +import { arrayify, isBytes } from "ethers/lib/utils.js"; import { isHexString } from "ethjs-util"; import { LedgerTransport } from "./transport"; @@ -96,7 +96,10 @@ export async function ethSignTx(transport: LedgerTransport, msg: core.ETHSignTx) const utx = new EthereumTx(txParams); - const res = await transport.call("Eth", "signTransaction", bip32path, utx.serialize().toString("hex")); + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore transport.call is drunk, there *is* a third argument to eth.signTransaction + // see https://github.com/LedgerHQ/ledgerjs/blob/master/packages/hw-app-eth/README.md#parameters-2 + const res = await transport.call("Eth", "signTransaction", bip32path, utx.serialize().toString("hex"), null); handleError(res, transport, "Could not sign ETH tx with Ledger"); const { v, r, s } = res.payload; @@ -157,7 +160,12 @@ export async function ethSignMessage( const bip32path = core.addressNListToBIP32(msg.addressNList); if (!isHexString(msg.message)) throw new Error("data is not an hex string"); - const res = await transport.call("Eth", "signPersonalMessage", bip32path, msg.message); + + // Ledger's inner implementation does a Buffer.from(messageHex, "hex").length on our message + // However, Buffer.from method with the "hex" encoding expects a valid hexadecimal string without the 0x prefix + // so we need to strip it in case it's present + const sanitizedMessageHex = msg.message.startsWith("0x") ? msg.message.slice(2) : msg.message; + const res = await transport.call("Eth", "signPersonalMessage", bip32path, sanitizedMessageHex); handleError(res, transport, "Could not sign ETH message with Ledger"); let { v } = res.payload; @@ -181,9 +189,7 @@ export async function ethVerifyMessage(msg: core.ETHVerifyMessage): Promise { + 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 + public thorchainNextAccountPath(msg: core.ThorchainAccountPath): core.ThorchainAccountPath | undefined { + return undefined; + } + // eslint-disable-next-line @typescript-eslint/no-unused-vars public hasNativeShapeShift(srcCoin: core.Coin, dstCoin: core.Coin): boolean { return false; @@ -223,6 +237,8 @@ export class LedgerHDWalletInfo implements core.HDWalletInfo, core.BTCWalletInfo switch (msg.coin) { case "Ethereum": return describeETHPath(msg.path); + case "Thorchain": + return core.thorchainDescribePath(msg.path); default: return describeUTXOPath(msg.path, msg.coin, msg.scriptType); } @@ -290,7 +306,10 @@ export class LedgerHDWalletInfo implements core.HDWalletInfo, core.BTCWalletInfo } } -export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWallet { +export class LedgerHDWallet + extends LedgerHDWalletInfo + implements core.HDWallet, core.BTCWallet, core.ETHWallet, core.ThorchainWallet +{ readonly _supportsETHInfo = true; readonly _supportsBTCInfo = true; readonly _supportsBTC = true; @@ -302,6 +321,8 @@ export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWa readonly _supportsPolygon = true; readonly _supportsGnosis = true; readonly _supportsArbitrum = true; + readonly _supportsThorchainInfo = true; + readonly _supportsThorchain = true; _isLedger = true; @@ -309,6 +330,7 @@ export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWa info: LedgerHDWalletInfo & core.HDWalletInfo; constructor(transport: LedgerTransport) { + super(); this.transport = transport; this.info = new LedgerHDWalletInfo(); } @@ -374,10 +396,6 @@ export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWa return version; } - public getVendor(): string { - return "Ledger"; - } - public async getModel(): Promise { const { device: { productName }, @@ -416,39 +434,6 @@ export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWa } } - // eslint-disable-next-line @typescript-eslint/no-unused-vars - public hasNativeShapeShift(srcCoin: core.Coin, dstCoin: core.Coin): boolean { - return false; - } - - public supportsBip44Accounts(): boolean { - return this.info.supportsBip44Accounts(); - } - - public supportsOfflineSigning(): boolean { - return true; - } - - public supportsBroadcast(): boolean { - return false; - } - - public hasOnDeviceDisplay(): boolean { - return true; - } - - public hasOnDevicePassphrase(): boolean { - return true; - } - - public hasOnDevicePinEntry(): boolean { - return true; - } - - public hasOnDeviceRecovery(): boolean { - return true; - } - // eslint-disable-next-line @typescript-eslint/no-unused-vars public async loadDevice(msg: core.LoadDevice): Promise { return; @@ -497,14 +482,6 @@ export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWa return; } - public async btcSupportsCoin(coin: core.Coin): Promise { - return this.info.btcSupportsCoin(coin); - } - - public async btcSupportsScriptType(coin: core.Coin, scriptType: core.BTCInputScriptType): Promise { - return this.info.btcSupportsScriptType(coin, scriptType); - } - public async btcGetAddress(msg: core.BTCGetAddress): Promise { await this.validateCurrentApp(msg.coin); return btc.btcGetAddress(this.transport, msg); @@ -515,14 +492,6 @@ export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWa return btc.btcSignTx(this, this.transport, msg); } - public async btcSupportsSecureTransfer(): Promise { - return this.info.btcSupportsSecureTransfer(); - } - - public btcSupportsNativeShapeShift(): boolean { - return this.info.btcSupportsNativeShapeShift(); - } - public async btcSignMessage(msg: core.BTCSignMessage): Promise { await this.validateCurrentApp(msg.coin); return btc.btcSignMessage(this, this.transport, msg); @@ -532,14 +501,6 @@ export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWa return btc.btcVerifyMessage(msg); } - public btcGetAccountPaths(msg: core.BTCGetAccountPaths): Array { - return this.info.btcGetAccountPaths(msg); - } - - public btcIsSameAccount(msg: Array): boolean { - return this.info.btcIsSameAccount(msg); - } - public async ethSignTx(msg: core.ETHSignTx): Promise { await this.validateCurrentApp("Ethereum"); return eth.ethSignTx(this.transport, msg); @@ -559,41 +520,17 @@ export class LedgerHDWallet implements core.HDWallet, core.BTCWallet, core.ETHWa return eth.ethVerifyMessage(msg); } - public async ethSupportsNetwork(chain_id: number): Promise { - return this.info.ethSupportsNetwork(chain_id); - } - - public async ethSupportsSecureTransfer(): Promise { - return this.info.ethSupportsSecureTransfer(); - } - - public ethSupportsNativeShapeShift(): boolean { - return this.info.ethSupportsNativeShapeShift(); - } - - public async ethSupportsEIP1559(): Promise { - return await this.info.ethSupportsEIP1559(); + public thorchainGetAddress(msg: core.ThorchainGetAddress): Promise { + return thorchain.thorchainGetAddress(this.transport, msg); } - public ethGetAccountPaths(msg: core.ETHGetAccountPath): Array { - return this.info.ethGetAccountPaths(msg); - } - - public describePath(msg: core.DescribePath): core.PathDescription { - return this.info.describePath(msg); + public thorchainSignTx(msg: core.ThorchainSignTx): Promise { + return thorchain.thorchainSignTx(this.transport, msg); } public disconnect(): Promise { return this.transport.disconnect(); } - - public btcNextAccountPath(msg: core.BTCAccountPath): core.BTCAccountPath | undefined { - return this.info.btcNextAccountPath(msg); - } - - public ethNextAccountPath(msg: core.ETHAccountPath): core.ETHAccountPath | undefined { - return this.info.ethNextAccountPath(msg); - } } export function info(): LedgerHDWalletInfo { diff --git a/packages/hdwallet-ledger/src/thorchain/common.ts b/packages/hdwallet-ledger/src/thorchain/common.ts new file mode 100644 index 000000000..0f6cb4f5a --- /dev/null +++ b/packages/hdwallet-ledger/src/thorchain/common.ts @@ -0,0 +1,113 @@ +export enum ErrorCode { + NoError = 0x9000, +} + +export const CLA = 0x55; +export const CHUNK_SIZE = 250; +export const APP_KEY = "CSM"; + +export const INS = { + GET_VERSION: 0x00, + INS_PUBLIC_KEY_SECP256K1: 0x01, // Obsolete + SIGN_SECP256K1: 0x02, + GET_ADDR_SECP256K1: 0x04, +}; + +export const PAYLOAD_TYPE = { + INIT: 0x00, + ADD: 0x01, + LAST: 0x02, +}; + +export const P1_VALUES = { + ONLY_RETRIEVE: 0x00, + SHOW_ADDRESS_IN_DEVICE: 0x01, +}; + +const ERROR_DESCRIPTION = { + 1: "U2F: Unknown", + 2: "U2F: Bad request", + 3: "U2F: Configuration unsupported", + 4: "U2F: Device Ineligible", + 5: "U2F: Timeout", + 14: "Timeout", + 0x9000: "No errors", + 0x9001: "Device is busy", + 0x6802: "Error deriving keys", + 0x6400: "Execution Error", + 0x6700: "Wrong Length", + 0x6982: "Empty Buffer", + 0x6983: "Output buffer too small", + 0x6984: "Data is invalid", + 0x6985: "Conditions not satisfied", + 0x6986: "Transaction rejected", + 0x6a80: "Bad key handle", + 0x6b00: "Invalid P1/P2", + 0x6d00: "Instruction not supported", + 0x6e00: "App does not seem to be open", + 0x6f00: "Unknown error", + 0x6f01: "Sign/verify error", +}; + +export function errorCodeToString(statusCode: any) { + if (statusCode in ERROR_DESCRIPTION) return ERROR_DESCRIPTION[statusCode as 1]; + return `Unknown Status Code: ${statusCode}`; +} + +export function processErrorResponse(response: any) { + if (response) { + if ( + typeof response === "object" && + response !== null && + !(response instanceof Array) && + !(response instanceof Date) + ) { + if (Object.prototype.hasOwnProperty.call(response, "statusCode")) { + return { + return_code: response.statusCode, + error_message: errorCodeToString(response.statusCode), + }; + } + + if ( + Object.prototype.hasOwnProperty.call(response, "return_code") && + Object.prototype.hasOwnProperty.call(response, "error_message") + ) { + return response; + } + } + return { + return_code: 0xffff, + error_message: response.toString(), + }; + } + + return { + return_code: 0xffff, + error_message: response.toString(), + }; +} + +export async function getVersion(transport: any) { + return transport.send(CLA, INS.GET_VERSION, 0, 0).then((response: any) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + + let targetId = 0; + if (response.length >= 9) { + targetId = (response[5] << 24) + (response[6] << 16) + (response[7] << 8) + (response[8] << 0); + } + + return { + return_code: returnCode, + error_message: errorCodeToString(returnCode), + // /// + test_mode: response[0] !== 0, + major: response[1], + minor: response[2], + patch: response[3], + device_locked: response[4] === 1, + target_id: targetId.toString(16), + }; + }, processErrorResponse); +} diff --git a/packages/hdwallet-ledger/src/thorchain/helpers.ts b/packages/hdwallet-ledger/src/thorchain/helpers.ts new file mode 100644 index 000000000..14a8893df --- /dev/null +++ b/packages/hdwallet-ledger/src/thorchain/helpers.ts @@ -0,0 +1,68 @@ +import { CLA, ErrorCode, errorCodeToString, INS, PAYLOAD_TYPE, processErrorResponse } from "./common"; + +const signSendChunkv1 = async (app: any, chunkIdx: any, chunkNum: any, chunk: any) => { + return app.transport + .send(CLA, INS.SIGN_SECP256K1, chunkIdx, chunkNum, chunk, [ErrorCode.NoError, 0x6984, 0x6a80]) + .then((response: any) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + let errorMessage = errorCodeToString(returnCode); + + if (returnCode === 0x6a80 || returnCode === 0x6984) { + errorMessage = `${errorMessage} : ${response.slice(0, response.length - 2).toString("ascii")}`; + } + + let signature = null; + if (response.length > 2) { + signature = response.slice(0, response.length - 2); + } + + return { + signature, + return_code: returnCode, + error_message: errorMessage, + }; + }, processErrorResponse); +}; + +export const serializePathv2 = (path: Array) => { + if (!path || path.length !== 5) { + throw new Error("Invalid path."); + } + + const buf = Buffer.alloc(20); + buf.writeUInt32LE(path[0], 0); + buf.writeUInt32LE(path[1], 4); + buf.writeUInt32LE(path[2], 8); + buf.writeUInt32LE(path[3], 12); + buf.writeUInt32LE(path[4], 16); + + return buf; +}; + +export const signSendChunkv2 = async (app: any, chunkIdx: any, chunkNum: any, chunk: any) => { + let payloadType = PAYLOAD_TYPE.ADD; + if (chunkIdx === 1) { + payloadType = PAYLOAD_TYPE.INIT; + } + if (chunkIdx === chunkNum) { + payloadType = PAYLOAD_TYPE.LAST; + } + + return signSendChunkv1(app, payloadType, 0, chunk); +}; + +export const publicKeyv2 = async (app: any, data: any) => { + return app.transport.send(CLA, INS.GET_ADDR_SECP256K1, 0, 0, data, [ErrorCode.NoError]).then((response: any) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + const compressedPk = Buffer.from(response.slice(0, 33)); + + return { + pk: "OBSOLETE PROPERTY", + compressed_pk: compressedPk, + return_code: returnCode, + error_message: errorCodeToString(returnCode), + }; + }, processErrorResponse); +}; diff --git a/packages/hdwallet-ledger/src/thorchain/hw-app-thor.ts b/packages/hdwallet-ledger/src/thorchain/hw-app-thor.ts new file mode 100644 index 000000000..1ff37717b --- /dev/null +++ b/packages/hdwallet-ledger/src/thorchain/hw-app-thor.ts @@ -0,0 +1,376 @@ +/** ****************************************************************************** + * (c) 2019 ZondaX GmbH + * (c) 2016-2017 Ledger + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + ******************************************************************************* */ +import { bech32 } from "@scure/base"; +import * as core from "@shapeshiftoss/hdwallet-core"; +import crypto from "crypto"; +import Ripemd160 from "ripemd160"; + +import { + APP_KEY, + CHUNK_SIZE, + CLA, + ErrorCode, + errorCodeToString, + getVersion, + INS, + P1_VALUES, + processErrorResponse, +} from "./common"; +import { publicKeyv2, serializePathv2, signSendChunkv2 } from "./helpers"; + +const THOR_CHAIN = "thorchain-mainnet-v1"; + +export type GetAddressAndPubKeyResponse = { + bech32_address: string; + compressed_pk: Uint8Array; + error_message: string; + return_code: number; +}; + +export type SignResponse = { + signature: Uint8Array; + error_message: string; + return_code: number; +}; + +const recursivelyOrderKeys = (unordered: any) => { + // If it's an array - recursively order any + // dictionary items within the array + if (Array.isArray(unordered)) { + unordered.forEach((item, index) => { + unordered[index] = recursivelyOrderKeys(item); + }); + return unordered; + } + + // If it's an object - let's order the keys + if (typeof unordered !== "object") return unordered; + const ordered: any = {}; + Object.keys(unordered) + .sort() + .forEach((key) => (ordered[key] = recursivelyOrderKeys(unordered[key]))); + return ordered; +}; + +const stringifyKeysInOrder = (data: any) => JSON.stringify(recursivelyOrderKeys(data)); + +class THORChainApp { + transport: any; + versionResponse: any; + + constructor(transport: any, scrambleKey = APP_KEY) { + if (!transport) { + throw new Error("Transport has not been defined"); + } + + this.transport = transport as any; + transport.decorateAppAPIMethods.bind(transport)( + this, + ["getVersion", "sign", "getAddressAndPubKey", "appInfo", "deviceInfo", "getBech32FromPK"], + scrambleKey + ); + } + + static serializeHRP(hrp: any) { + if (hrp == null || hrp.length < 3 || hrp.length > 83) { + throw new Error("Invalid HRP"); + } + const buf = Buffer.alloc(1 + hrp.length); + buf.writeUInt8(hrp.length, 0); + buf.write(hrp, 1); + return buf; + } + + static getBech32FromPK(hrp: any, pk: any) { + if (pk.length !== 33) { + throw new Error("expected compressed public key [31 bytes]"); + } + const hashSha256 = crypto.createHash("sha256").update(pk).digest(); + const hashRip = new Ripemd160().update(hashSha256).digest(); + // ts is drunk and doesn't like bech32.bech32 here + const encode = bech32.encode || (bech32 as any).bech32?.encode; + // ts is drunk and doesn't like bech32.bech32 here + const toWords = bech32.toWords || (bech32 as any).bech32?.toWords; + + return encode(hrp, toWords(hashRip)); + } + + async serializePath(path: Array) { + this.versionResponse = await getVersion(this.transport); + + if (this.versionResponse.return_code !== ErrorCode.NoError) { + throw this.versionResponse; + } + + switch (this.versionResponse.major) { + case 2: + return serializePathv2(path); + default: + return { + return_code: 0x6400, + error_message: "App Version is not supported", + }; + } + } + + async signGetChunks(path: Array, message: any) { + const serializedPath = await this.serializePath(path); + + const chunks = []; + chunks.push(serializedPath); + const buffer = Buffer.from(message); + + for (let i = 0; i < buffer.length; i += CHUNK_SIZE) { + let end = i + CHUNK_SIZE; + if (i > buffer.length) { + end = buffer.length; + } + chunks.push(buffer.slice(i, end)); + } + + return chunks; + } + + async getVersion() { + try { + this.versionResponse = await getVersion(this.transport); + return this.versionResponse; + } catch (e) { + return processErrorResponse(e); + } + } + + async appInfo() { + return this.transport.send(0xb0, 0x01, 0, 0).then((response: any) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + + const result = {} as any; + + let appName = "err"; + let appVersion = "err"; + let flagLen = 0; + let flagsValue = 0; + + if (response[0] !== 1) { + // Ledger responds with format ID 1. There is no spec for any format != 1 + result.error_message = "response format ID not recognized"; + result.return_code = 0x9001; + } else { + const appNameLen = response[1]; + appName = response.slice(2, 2 + appNameLen).toString("ascii"); + let idx = 2 + appNameLen; + const appVersionLen = response[idx]; + idx += 1; + appVersion = response.slice(idx, idx + appVersionLen).toString("ascii"); + idx += appVersionLen; + const appFlagsLen = response[idx]; + idx += 1; + flagLen = appFlagsLen; + flagsValue = response[idx]; + } + + return { + return_code: returnCode, + error_message: errorCodeToString(returnCode), + // // + appName, + appVersion, + flagLen, + flagsValue, + + flag_recovery: (flagsValue & 1) !== 0, + + flag_signed_mcu_code: (flagsValue & 2) !== 0, + + flag_onboarded: (flagsValue & 4) !== 0, + + flag_pin_validated: (flagsValue & 128) !== 0, + }; + }, processErrorResponse); + } + + async deviceInfo() { + return this.transport.send(0xe0, 0x01, 0, 0, Buffer.from([]), [ErrorCode.NoError, 0x6e00]).then((response: any) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + + if (returnCode === 0x6e00) { + return { + return_code: returnCode, + error_message: "This command is only available in the Dashboard", + }; + } + + const targetId = response.slice(0, 4).toString("hex"); + + let pos = 4; + const secureElementVersionLen = response[pos]; + pos += 1; + const seVersion = response.slice(pos, pos + secureElementVersionLen).toString(); + pos += secureElementVersionLen; + + const flagsLen = response[pos]; + pos += 1; + const flag = response.slice(pos, pos + flagsLen).toString("hex"); + pos += flagsLen; + + const mcuVersionLen = response[pos]; + pos += 1; + // Patch issue in mcu version + let tmp = response.slice(pos, pos + mcuVersionLen); + if (tmp[mcuVersionLen - 1] === 0) { + tmp = response.slice(pos, pos + mcuVersionLen - 1); + } + const mcuVersion = tmp.toString(); + + return { + return_code: returnCode, + error_message: errorCodeToString(returnCode), + // // + targetId, + seVersion, + flag, + mcuVersion, + }; + }, processErrorResponse); + } + + async publicKey(path: Array) { + try { + const serializedPath = await this.serializePath(path); + + switch (this.versionResponse.major) { + case 2: { + const data = Buffer.concat([THORChainApp.serializeHRP("thor"), serializedPath as any]); + return await publicKeyv2(this, data); + } + default: + return { + return_code: 0x6400, + error_message: "App Version is not supported", + }; + } + } catch (e) { + return processErrorResponse(e); + } + } + + async getAddressAndPubKey(path: Array, hrp: any): Promise { + try { + return await this.serializePath(path) + .then((serializedPath) => { + const data = Buffer.concat([THORChainApp.serializeHRP(hrp), serializedPath as any]); + return this.transport + .send(CLA, INS.GET_ADDR_SECP256K1, P1_VALUES.ONLY_RETRIEVE, 0, data, [ErrorCode.NoError]) + .then((response: any) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + + const compressedPk = Buffer.from(response.slice(0, 33)); + const bech32Address = Buffer.from(response.slice(33, -2)).toString(); + + return { + bech32_address: bech32Address, + compressed_pk: compressedPk, + return_code: returnCode, + error_message: errorCodeToString(returnCode), + }; + }, processErrorResponse); + }) + .catch((err) => processErrorResponse(err)); + } catch (e) { + return processErrorResponse(e); + } + } + + async showAddressAndPubKey(path: Array, hrp: any) { + try { + return await this.serializePath(path) + .then((serializedPath) => { + const data = Buffer.concat([THORChainApp.serializeHRP(hrp), serializedPath as any]); + return this.transport + .send(CLA, INS.GET_ADDR_SECP256K1, P1_VALUES.SHOW_ADDRESS_IN_DEVICE, 0, data, [ErrorCode.NoError]) + .then((response: any) => { + const errorCodeData = response.slice(-2); + const returnCode = errorCodeData[0] * 256 + errorCodeData[1]; + + const compressedPk = Buffer.from(response.slice(0, 33)); + const bech32Address = Buffer.from(response.slice(33, -2)).toString(); + + return { + bech32_address: bech32Address, + compressed_pk: compressedPk, + return_code: returnCode, + error_message: errorCodeToString(returnCode), + }; + }, processErrorResponse); + }) + .catch((err) => processErrorResponse(err)); + } catch (e) { + return processErrorResponse(e); + } + } + + async signSendChunk(chunkIdx: number, chunkNum: number, chunk: any) { + switch (this.versionResponse.major) { + case 2: + return signSendChunkv2(this, chunkIdx, chunkNum, chunk); + default: + return { + return_code: 0x6400, + error_message: "App Version is not supported", + }; + } + } + + async sign(msg: core.ThorchainSignTx): Promise { + const rawTx = stringifyKeysInOrder({ + account_number: msg.account_number, + chain_id: THOR_CHAIN, + fee: { amount: msg.tx.fee.amount, gas: msg.tx.fee.gas }, + memo: msg.tx.memo, + msgs: msg.tx.msg, + sequence: msg.sequence, + }); + + return this.signGetChunks(msg.addressNList, rawTx).then((chunks) => { + return this.signSendChunk(1, chunks.length, chunks[0]).then(async (response) => { + let result = { + return_code: response.return_code, + error_message: response.error_message, + signature: null, + }; + + for (let i = 1; i < chunks.length; i += 1) { + result = await this.signSendChunk(1 + i, chunks.length, chunks[i]); + if (result.return_code !== ErrorCode.NoError) { + break; + } + } + + return { + return_code: result.return_code, + error_message: result.error_message, + signature: result.signature, + }; + }, processErrorResponse); + }, processErrorResponse); + } +} + +export { THORChainApp }; diff --git a/packages/hdwallet-ledger/src/thorchain/index.ts b/packages/hdwallet-ledger/src/thorchain/index.ts new file mode 100644 index 000000000..e9e595cde --- /dev/null +++ b/packages/hdwallet-ledger/src/thorchain/index.ts @@ -0,0 +1,77 @@ +import type { AccountData, AminoSignResponse, OfflineAminoSigner, StdSignDoc, StdTx } from "@cosmjs/amino"; +import type { SignerData } from "@cosmjs/stargate"; +import * as core from "@shapeshiftoss/hdwallet-core"; +import { fromByteArray } from "base64-js"; +import PLazy from "p-lazy"; + +import { handleError, LedgerTransport } from ".."; +import { getSignature } from "./utils"; +export * from "./common"; +export * from "./helpers"; +export * from "./hw-app-thor"; + +const protoTxBuilder = PLazy.from(() => import("@shapeshiftoss/proto-tx-builder")); + +export const thorchainGetAddress = async ( + transport: LedgerTransport, + msg: core.ThorchainGetAddress +): Promise => { + const addressAndPubkey = await transport.call("Rune", "getAddressAndPubKey", msg.addressNList, "thor"); + + handleError(addressAndPubkey, transport, "Unable to obtain address and public key from device."); + + return addressAndPubkey.payload.bech32_address; +}; + +export const thorchainSignTx = async ( + transport: LedgerTransport, + msg: core.ThorchainSignTx +): Promise => { + const addressAndPubkey = await transport.call("Rune", "getAddressAndPubKey", msg.addressNList, "thor"); + + handleError(addressAndPubkey, transport, "Unable to obtain address and public key from device."); + + const { bech32_address: address, compressed_pk } = addressAndPubkey.payload; + const pubkey = fromByteArray(compressed_pk); + + const signResponse = await transport.call("Rune", "sign", msg); + + handleError(signResponse, transport, "Unable to obtain signature from device."); + + const signature = signResponse.payload.signature; + + const offlineSigner: OfflineAminoSigner = { + async getAccounts(): Promise { + return [ + { + address, + algo: "secp256k1", + pubkey: compressed_pk, + }, + ]; + }, + + async signAmino(signerAddress: string, signDoc: StdSignDoc): Promise { + if (signerAddress !== address) throw new Error("expected signerAddress to match address"); + + return { + signed: signDoc, + signature: { + pub_key: { + type: "tendermint/PubKeySecp256k1", + value: pubkey, + }, + signature: getSignature(signature), + }, + }; + }, + }; + + const signerData: SignerData = { + sequence: Number(msg.sequence), + accountNumber: Number(msg.account_number), + chainId: msg.chain_id, + }; + + return (await protoTxBuilder).sign(address, msg.tx as StdTx, offlineSigner, signerData, "thor"); +}; diff --git a/packages/hdwallet-ledger/src/thorchain/utils.ts b/packages/hdwallet-ledger/src/thorchain/utils.ts new file mode 100644 index 000000000..1c4b14b7c --- /dev/null +++ b/packages/hdwallet-ledger/src/thorchain/utils.ts @@ -0,0 +1,68 @@ +import { fromByteArray } from "base64-js"; + +export const getSignature = (signatureArray: Uint8Array) => { + // Check Type Length Value encoding + if (signatureArray.length < 64) { + throw new Error("Invalid Signature: Too short"); + } + if (signatureArray[0] !== 0x30) { + throw new Error("Invalid Ledger Signature TLV encoding: expected first byte 0x30"); + } + if (signatureArray[1] + 2 !== signatureArray.length) { + throw new Error("Invalid Signature: signature length does not match TLV"); + } + if (signatureArray[2] !== 0x02) { + throw new Error("Invalid Ledger Signature TLV encoding: expected length type 0x02"); + } + + // r signature + const rLength = signatureArray[3]; + let rSignature = signatureArray.slice(4, rLength + 4); + + // Drop leading zero on some 'r' signatures that are 33 bytes. + if (rSignature.length === 33 && rSignature[0] === 0) { + rSignature = rSignature.slice(1, 33); + } else if (rSignature.length === 33) { + throw new Error('Invalid signature: "r" too long'); + } + + // add leading zero's to pad to 32 bytes + while (rSignature.length < 32) { + const rSignaturePadded = new Uint8Array(32); + rSignaturePadded.set(rSignature, 32 - rSignature.length); + rSignature = rSignaturePadded; + } + + // s signature + if (signatureArray[rLength + 4] !== 0x02) { + throw new Error("Invalid Ledger Signature TLV encoding: expected length type 0x02"); + } + + const sLength = signatureArray[rLength + 5]; + + if (4 + rLength + 2 + sLength !== signatureArray.length) { + throw new Error("Invalid Ledger Signature: TLV byte lengths do not match message length"); + } + + let sSignature = signatureArray.slice(rLength + 6, signatureArray.length); + + // Drop leading zero on 's' signatures that are 33 bytes. This shouldn't occur since ledger signs using "Small s" math. But just to be sure... + if (sSignature.length === 33 && sSignature[0] === 0) { + sSignature = sSignature.slice(1, 33); + } else if (sSignature.length === 33) { + throw new Error('Invalid signature: "s" too long'); + } + + // add leading zero's to pad to 32 bytes + while (sSignature.length < 32) { + const sSignaturePadded = new Uint8Array(32); + sSignaturePadded.set(sSignature, 32 - sSignature.length); + sSignature = sSignaturePadded; + } + + if (rSignature.length !== 32 || sSignature.length !== 32) { + throw new Error("Invalid signatures: must be 32 bytes each"); + } + + return fromByteArray(Buffer.concat([rSignature, sSignature])); +}; diff --git a/packages/hdwallet-ledger/src/transport.ts b/packages/hdwallet-ledger/src/transport.ts index 70178159d..f45cc14f8 100644 --- a/packages/hdwallet-ledger/src/transport.ts +++ b/packages/hdwallet-ledger/src/transport.ts @@ -6,13 +6,15 @@ import type getDeviceInfo from "@ledgerhq/live-common/lib/hw/getDeviceInfo"; import type openApp from "@ledgerhq/live-common/lib/hw/openApp"; import * as core from "@shapeshiftoss/hdwallet-core"; +import { THORChainApp } from "./thorchain"; + type MethodsOnly = { [k in keyof T as T[k] extends (...args: any) => any ? k : never]: T[k]; }; type UnwrapPromise = T extends Promise ? R : T; type DefinitelyCallable = T extends (...args: any) => any ? T : never; -export type LedgerTransportCoinType = null | "Btc" | "Eth"; +export type LedgerTransportCoinType = null | "Btc" | "Eth" | "Rune"; type CurriedWithTransport any> = T extends ( transport: Transport, ...args: infer R @@ -33,6 +35,8 @@ type LedgerTransportMethodMap = T extends nul ? MethodsOnly : T extends "Eth" ? MethodsOnly + : T extends "Rune" + ? MethodsOnly : never; export type LedgerTransportMethodName = LedgerTransportMethodMap extends never ? never diff --git a/packages/hdwallet-metamask-shapeshift-multichain/package.json b/packages/hdwallet-metamask-shapeshift-multichain/package.json index 5382f6ba5..5ebdc6d04 100644 --- a/packages/hdwallet-metamask-shapeshift-multichain/package.json +++ b/packages/hdwallet-metamask-shapeshift-multichain/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-shapeshift-multichain", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -17,7 +17,7 @@ "@metamask/detect-provider": "^1.2.0", "@metamask/onboarding": "^1.0.1", "@shapeshiftoss/common-api": "^9.3.0", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "@shapeshiftoss/metamask-snaps-adapter": "^1.0.8", "@shapeshiftoss/metamask-snaps-types": "^1.0.8", "eth-rpc-errors": "^4.0.3", diff --git a/packages/hdwallet-metamask-shapeshift-multichain/src/adapter.ts b/packages/hdwallet-metamask-shapeshift-multichain/src/adapter.ts index e4bebef62..a5bf44cb8 100644 --- a/packages/hdwallet-metamask-shapeshift-multichain/src/adapter.ts +++ b/packages/hdwallet-metamask-shapeshift-multichain/src/adapter.ts @@ -2,7 +2,7 @@ import detectEthereumProvider from "@metamask/detect-provider"; import MetaMaskOnboarding from "@metamask/onboarding"; import * as core from "@shapeshiftoss/hdwallet-core"; import { enableShapeShiftSnap, shapeShiftSnapInstalled } from "@shapeshiftoss/metamask-snaps-adapter"; -import * as ethers from "ethers"; +import { providers } from "ethers"; import { SNAP_ID } from "./common"; import { MetaMaskShapeShiftMultiChainHDWallet } from "./shapeshift-multichain"; @@ -29,7 +29,7 @@ export class MetaMaskAdapter { mustBeMetaMask: true, silent: false, timeout: 3000, - })) as ethers.providers.ExternalProvider | null; + })) as providers.ExternalProvider | null; if (!provider) { const onboarding = new MetaMaskOnboarding(); onboarding.startOnboarding(); diff --git a/packages/hdwallet-metamask/package.json b/packages/hdwallet-metamask/package.json index 3f181baab..11c1b6211 100644 --- a/packages/hdwallet-metamask/package.json +++ b/packages/hdwallet-metamask/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-metamask", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -16,7 +16,7 @@ "dependencies": { "@metamask/detect-provider": "^1.2.0", "@metamask/onboarding": "^1.0.1", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "eth-rpc-errors": "^4.0.3", "lodash": "^4.17.21" }, diff --git a/packages/hdwallet-metamask/src/adapter.ts b/packages/hdwallet-metamask/src/adapter.ts index edc83e0c5..748f5ccaa 100644 --- a/packages/hdwallet-metamask/src/adapter.ts +++ b/packages/hdwallet-metamask/src/adapter.ts @@ -1,7 +1,7 @@ import detectEthereumProvider from "@metamask/detect-provider"; import MetaMaskOnboarding from "@metamask/onboarding"; import * as core from "@shapeshiftoss/hdwallet-core"; -import * as ethers from "ethers"; +import { providers } from "ethers"; import { MetaMaskHDWallet } from "./metamask"; @@ -27,7 +27,7 @@ export class MetaMaskAdapter { mustBeMetaMask: true, silent: false, timeout: 3000, - })) as ethers.providers.ExternalProvider | null; + })) as providers.ExternalProvider | null; if (!provider) { const onboarding = new MetaMaskOnboarding(); onboarding.startOnboarding(); diff --git a/packages/hdwallet-native-vault/package.json b/packages/hdwallet-native-vault/package.json index f0dc8af70..27af0b8ec 100644 --- a/packages/hdwallet-native-vault/package.json +++ b/packages/hdwallet-native-vault/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-native-vault", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,7 +14,7 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-native": "1.52.4", + "@shapeshiftoss/hdwallet-native": "1.52.11", "bip39": "^3.0.4", "hash-wasm": "^4.9.0", "idb-keyval": "^6.0.3", diff --git a/packages/hdwallet-native/package.json b/packages/hdwallet-native/package.json index 6a4973ca0..6dbdecf79 100644 --- a/packages/hdwallet-native/package.json +++ b/packages/hdwallet-native/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-native", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -16,7 +16,7 @@ "dependencies": { "@shapeshiftoss/bitcoinjs-lib": "5.2.0-shapeshift.2", "@shapeshiftoss/fiosdk": "1.2.1-shapeshift.6", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "@shapeshiftoss/proto-tx-builder": "^0.8.0", "@zxing/text-encoding": "^0.9.0", "bchaddrjs": "^0.4.9", diff --git a/packages/hdwallet-native/src/crypto/isolation/adapters/ethereum.ts b/packages/hdwallet-native/src/crypto/isolation/adapters/ethereum.ts index 3204630a2..f6e4c284a 100644 --- a/packages/hdwallet-native/src/crypto/isolation/adapters/ethereum.ts +++ b/packages/hdwallet-native/src/crypto/isolation/adapters/ethereum.ts @@ -1,22 +1,32 @@ import * as core from "@shapeshiftoss/hdwallet-core"; import { getMessage, TypedData } from "eip-712"; -import * as ethers from "ethers"; +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): ethers.Signature { +function ethSigFromRecoverableSig(x: SecP256K1.RecoverableSignature): Signature { const sig = SecP256K1.RecoverableSignature.sig(x); const recoveryParam = SecP256K1.RecoverableSignature.recoveryParam(x); - return ethers.utils.splitSignature(core.compatibleBufferConcat([sig, Buffer.from([recoveryParam])])); + return splitSignature(core.compatibleBufferConcat([sig, Buffer.from([recoveryParam])])); } export class SignerAdapter { protected readonly nodeAdapter: Isolation.Adapters.BIP32; - readonly provider?: ethers.providers.Provider; + readonly provider?: providers.Provider; - constructor(nodeAdapter: Isolation.Adapters.BIP32, provider?: ethers.providers.Provider) { + constructor(nodeAdapter: Isolation.Adapters.BIP32, provider?: providers.Provider) { this.nodeAdapter = nodeAdapter; this.provider = provider; } @@ -26,54 +36,54 @@ export class SignerAdapter { // 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: ethers.providers.Provider): never { + 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 ethers.utils.computeAddress(SecP256K1.UncompressedPoint.from(nodeAdapter.getPublicKey())); + return computeAddress(SecP256K1.UncompressedPoint.from(nodeAdapter.getPublicKey())); } - async signDigest(digest: ethers.BytesLike, addressNList: core.BIP32Path): Promise { + 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 : ethers.utils.arrayify(digest) + digest instanceof Uint8Array ? digest : arrayify(digest) ); const sig = SecP256K1.RecoverableSignature.sig(recoverableSig); const recoveryParam = SecP256K1.RecoverableSignature.recoveryParam(recoverableSig); - return ethers.utils.splitSignature(core.compatibleBufferConcat([sig, Buffer.from([recoveryParam])])); + return splitSignature(core.compatibleBufferConcat([sig, Buffer.from([recoveryParam])])); } async signTransaction( - transaction: ethers.utils.Deferrable, + transaction: Deferrable, addressNList: core.BIP32Path ): Promise { - const tx = await ethers.utils.resolveProperties(transaction); + const tx = await resolveProperties(transaction); if (tx.from != null) { - if (ethers.utils.getAddress(tx.from) !== (await this.getAddress(addressNList))) { + if (getAddress(tx.from) !== (await this.getAddress(addressNList))) { throw new Error("transaction from address mismatch"); } delete tx.from; } - const unsignedTx: ethers.UnsignedTransaction = { + const unsignedTx: UnsignedTransaction = { ...tx, - nonce: tx.nonce !== undefined ? ethers.BigNumber.from(tx.nonce).toNumber() : undefined, + nonce: tx.nonce !== undefined ? BigNumber.from(tx.nonce).toNumber() : undefined, }; const nodeAdapter = await this.nodeAdapter.derivePath(core.addressNListToBIP32(addressNList)); - const txBuf = ethers.utils.arrayify(ethers.utils.serializeTransaction(unsignedTx)); + const txBuf = arrayify(serializeTransaction(unsignedTx)); const rawSig = await SecP256K1.RecoverableSignature.signCanonically(nodeAdapter.node, "keccak256", txBuf); - return ethers.utils.serializeTransaction(unsignedTx, ethSigFromRecoverableSig(rawSig)); + return serializeTransaction(unsignedTx, ethSigFromRecoverableSig(rawSig)); } - async signMessage(messageData: ethers.BytesLike, addressNList: core.BIP32Path): Promise { + 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 ethers.utils.joinSignature(ethSigFromRecoverableSig(rawSig)); + return joinSignature(ethSigFromRecoverableSig(rawSig)); } async signTypedData(typedData: TypedData, addressNList: core.BIP32Path): Promise { @@ -81,7 +91,7 @@ export class SignerAdapter { 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 = ethers.utils.joinSignature(ethSigFromRecoverableSig(rawSig)); + const signature = joinSignature(ethSigFromRecoverableSig(rawSig)); return { address, signature }; } } diff --git a/packages/hdwallet-native/src/crypto/isolation/engines/default/bip39.ts b/packages/hdwallet-native/src/crypto/isolation/engines/default/bip39.ts index a7c1cafa0..f563e66a7 100644 --- a/packages/hdwallet-native/src/crypto/isolation/engines/default/bip39.ts +++ b/packages/hdwallet-native/src/crypto/isolation/engines/default/bip39.ts @@ -1,46 +1,16 @@ /// -import * as core from "@shapeshiftoss/hdwallet-core"; -import * as bip32crypto from "bip32/src/crypto"; +import { createSHA512, pbkdf2 } from "hash-wasm"; import { TextEncoder } from "web-encoding"; -import * as BIP32 from "../../core/bip32"; -import * as BIP39 from "../../core/bip39"; -import { safeBufferFrom } from "../../types"; -import * as BIP32Engine from "./bip32"; +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"; -// Poor man's single-block PBKDF2 implementation -//TODO: get something better -function pbkdf2_sha512_singleblock( - password: string, - salt: Uint8Array, - iterations: number -): Uint8Array & { length: 64 } { - function be32Buf(index: number): Buffer { - const indexBE = Buffer.alloc(4); - indexBE.writeUInt32BE(index); - return indexBE; - } - - const pwBuffer = safeBufferFrom(new TextEncoder().encode(password)); - - const out = bip32crypto.hmacSHA512(pwBuffer, core.compatibleBufferConcat([salt, be32Buf(1)])) as Buffer & { - length: 64; - }; - let lastU = out; - for (let i = 2; i <= iterations; i++) { - const newU = bip32crypto.hmacSHA512(pwBuffer, lastU) as Buffer & { length: 64 }; - for (let j = 0; j < out.length; j++) out[j] ^= newU[j]; - lastU = newU; - } - - return out; -} - -export class Mnemonic extends Revocable(class {}) implements BIP39.Mnemonic { +export class Mnemonic extends Revocable(class {}) implements Bip39Mnemonic { readonly #mnemonic: string; protected constructor(mnemonic: string) { @@ -48,18 +18,27 @@ export class Mnemonic extends Revocable(class {}) implements BIP39.Mnemonic { this.#mnemonic = mnemonic.normalize("NFKD"); } - static async create(mnemonic: string): Promise { + static async create(mnemonic: string): Promise { const obj = new Mnemonic(mnemonic); return revocable(obj, (x) => obj.addRevoker(x)); } - async toSeed(passphrase?: string): Promise { - if (passphrase !== undefined && typeof passphrase !== "string") throw new Error("bad passphrase type"); - + async toSeed(passphrase?: string): Promise { const mnemonic = this.#mnemonic; const salt = new TextEncoder().encode(`mnemonic${passphrase ?? ""}`.normalize("NFKD")); - const out = await BIP32Engine.Seed.create(pbkdf2_sha512_singleblock(mnemonic, salt, 2048)); + 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/ethereum.test.ts b/packages/hdwallet-native/src/ethereum.test.ts index 224278c6a..b3ce44d88 100644 --- a/packages/hdwallet-native/src/ethereum.test.ts +++ b/packages/hdwallet-native/src/ethereum.test.ts @@ -1,5 +1,5 @@ import * as core from "@shapeshiftoss/hdwallet-core"; -import * as ethers from "ethers"; +import { parseTransaction } from "ethers/lib/utils.js"; import * as native from "./native"; @@ -143,7 +143,7 @@ describe("NativeETHWallet", () => { "v": 38, } `);*/ - expect(ethers.utils.parseTransaction(sig!.serialized).from).toEqual("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"); + expect(parseTransaction(sig!.serialized).from).toEqual("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"); }); it("should sign a EIP-1559 transaction correctly", async () => { @@ -177,7 +177,7 @@ describe("NativeETHWallet", () => { "v": 38, } `);*/ - expect(ethers.utils.parseTransaction(sig!.serialized).from).toEqual("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"); + expect(parseTransaction(sig!.serialized).from).toEqual("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"); }); describe("sign and verify message", () => { diff --git a/packages/hdwallet-native/src/ethereum.ts b/packages/hdwallet-native/src/ethereum.ts index 3a7d8710e..ff35ea5ff 100644 --- a/packages/hdwallet-native/src/ethereum.ts +++ b/packages/hdwallet-native/src/ethereum.ts @@ -1,5 +1,5 @@ import * as core from "@shapeshiftoss/hdwallet-core"; -import * as ethers from "ethers"; +import { keccak256, parseTransaction, recoverAddress } from "ethers/lib/utils.js"; import * as Isolation from "./crypto/isolation"; import SignerAdapter from "./crypto/isolation/adapters/ethereum"; @@ -111,7 +111,7 @@ export function MixinNativeETHWallet { if (!signature.startsWith("0x")) signature = `0x${signature}`; - const digest = ethers.utils.keccak256(buildMessage(message)); - return ethers.utils.recoverAddress(digest, signature) === address; + const digest = keccak256(buildMessage(message)); + return recoverAddress(digest, signature) === address; } }; } diff --git a/packages/hdwallet-portis/package.json b/packages/hdwallet-portis/package.json index daf476efc..bc9f47bba 100644 --- a/packages/hdwallet-portis/package.json +++ b/packages/hdwallet-portis/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-portis", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -15,7 +15,7 @@ }, "dependencies": { "@portis/web3": "3.0.10", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "base64-js": "^1.5.1", "bip32": "^2.0.4", "bitcoinjs-lib": "^5.1.6", diff --git a/packages/hdwallet-tallyho/package.json b/packages/hdwallet-tallyho/package.json index 512ec2194..bce0e8ee4 100644 --- a/packages/hdwallet-tallyho/package.json +++ b/packages/hdwallet-tallyho/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-tallyho", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,7 +14,7 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "lodash": "^4.17.21", "tallyho-onboarding": "^1.0.2" }, diff --git a/packages/hdwallet-tallyho/src/adapter.ts b/packages/hdwallet-tallyho/src/adapter.ts index d04ba9369..06edd9b5e 100644 --- a/packages/hdwallet-tallyho/src/adapter.ts +++ b/packages/hdwallet-tallyho/src/adapter.ts @@ -1,10 +1,10 @@ import * as core from "@shapeshiftoss/hdwallet-core"; -import * as ethers from "ethers"; +import { providers } from "ethers"; import TallyHoOnboarding from "tallyho-onboarding"; import { TallyHoHDWallet } from "./tallyho"; -interface TallyHoEthereumProvider extends ethers.providers.ExternalProvider { +interface TallyHoEthereumProvider extends providers.ExternalProvider { isTally?: boolean; } @@ -23,6 +23,10 @@ export class TallyHoAdapter { return new TallyHoAdapter(keyring); } + public async initialize(): Promise { + return Object.keys(this.keyring.wallets).length; + } + public async pairDevice(): Promise { let provider: TallyHoEthereumProvider | null; // eslint-disable-next-line no-useless-catch diff --git a/packages/hdwallet-tallyho/src/ethereum.test.ts b/packages/hdwallet-tallyho/src/ethereum.test.ts index 99d465539..9ccaada1b 100644 --- a/packages/hdwallet-tallyho/src/ethereum.test.ts +++ b/packages/hdwallet-tallyho/src/ethereum.test.ts @@ -1,11 +1,11 @@ import * as core from "@shapeshiftoss/hdwallet-core"; -import * as ethers from "ethers"; +import { providers } from "ethers"; import * as ethereum from "./ethereum"; describe("Tally Ho - Ethereum Adapter", () => { it("ethVerifyMessage returns null as its not implemented", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue("0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8"), }; expect( @@ -36,7 +36,7 @@ describe("Tally Ho - Ethereum Adapter", () => { expect(paths).toMatchObject([]); }); it("ethSignTx returns null as its not implemented", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue({ r: "0x63db3dd3bf3e1fe7dde1969c0fc8850e34116d0b501c0483a0e08c0f77b8ce0a", s: "0x28297d012cccf389f6332415e96ee3fc0bbf8474d05f646e029cd281a031464b", @@ -63,7 +63,7 @@ describe("Tally Ho - Ethereum Adapter", () => { ).toEqual(null); }); it("ethSendTx returns a valid hash", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue("0x123"), }; @@ -85,7 +85,7 @@ describe("Tally Ho - Ethereum Adapter", () => { expect(hash).toMatchObject({ hash: "0x123" }); }); it("ethSendTx returns a valid hash if maxFeePerGas is present in msg", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue("0x123"), }; @@ -107,7 +107,7 @@ describe("Tally Ho - Ethereum Adapter", () => { expect(hash).toMatchObject({ hash: "0x123" }); }); it("ethSendTx returns null on error", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockRejectedValue(new Error("An Error has occurred")), }; @@ -130,7 +130,7 @@ describe("Tally Ho - Ethereum Adapter", () => { }); it("ethSignMessage returns a valid signature object", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue( `Object { "address": "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", @@ -201,7 +201,7 @@ describe("Tally Ho - Ethereum Adapter", () => { }); it("ethSignMessage returns null on error", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockRejectedValue(new Error("An Error has occurred")), }; @@ -219,7 +219,7 @@ describe("Tally Ho - Ethereum Adapter", () => { }); it("ethGetAddress returns a valid address", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue(["0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"]), }; @@ -228,7 +228,7 @@ describe("Tally Ho - Ethereum Adapter", () => { expect(address).toBe("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"); }); it("ethGetAddress returns null on error", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockRejectedValue(new Error("An error has occurred")), }; diff --git a/packages/hdwallet-trezor-connect/package.json b/packages/hdwallet-trezor-connect/package.json index 3437dbd4b..6643ae530 100644 --- a/packages/hdwallet-trezor-connect/package.json +++ b/packages/hdwallet-trezor-connect/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-trezor-connect", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,8 +14,8 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", - "@shapeshiftoss/hdwallet-trezor": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", + "@shapeshiftoss/hdwallet-trezor": "1.52.11", "@trezor/rollout": "^1.2.0", "trezor-connect": "^8.2.1" } diff --git a/packages/hdwallet-trezor/package.json b/packages/hdwallet-trezor/package.json index c09bacb6a..6cac7230c 100644 --- a/packages/hdwallet-trezor/package.json +++ b/packages/hdwallet-trezor/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-trezor", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -17,7 +17,7 @@ "dependencies": { "@ethereumjs/common": "^2.4.0", "@ethereumjs/tx": "^3.3.0", - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "base64-js": "^1.5.1", "lodash": "^4.17.21" }, diff --git a/packages/hdwallet-walletconnect/package.json b/packages/hdwallet-walletconnect/package.json index d53919558..d673e10d4 100644 --- a/packages/hdwallet-walletconnect/package.json +++ b/packages/hdwallet-walletconnect/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-walletconnect", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -15,7 +15,7 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "@walletconnect/qrcode-modal": "^1.7.8", "@walletconnect/web3-provider": "^1.7.8", "ethers": "^5.6.5" diff --git a/packages/hdwallet-walletconnectV2/package.json b/packages/hdwallet-walletconnectV2/package.json index 44d72ea45..22f0a598a 100644 --- a/packages/hdwallet-walletconnectV2/package.json +++ b/packages/hdwallet-walletconnectV2/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-walletconnectv2", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -15,7 +15,7 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "@walletconnect/ethereum-provider": "^2.10.1", "@walletconnect/modal": "^2.6.2", "ethers": "^5.6.5" diff --git a/packages/hdwallet-xdefi/package.json b/packages/hdwallet-xdefi/package.json index aaa1ca359..bef82b2bb 100644 --- a/packages/hdwallet-xdefi/package.json +++ b/packages/hdwallet-xdefi/package.json @@ -1,6 +1,6 @@ { "name": "@shapeshiftoss/hdwallet-xdefi", - "version": "1.52.4", + "version": "1.52.11", "license": "MIT", "publishConfig": { "access": "public" @@ -14,7 +14,7 @@ "prepublishOnly": "yarn clean && yarn build" }, "dependencies": { - "@shapeshiftoss/hdwallet-core": "1.52.4", + "@shapeshiftoss/hdwallet-core": "1.52.11", "lodash": "^4.17.21" }, "devDependencies": { diff --git a/packages/hdwallet-xdefi/src/adapter.ts b/packages/hdwallet-xdefi/src/adapter.ts index 61608bd7f..df3d710e4 100644 --- a/packages/hdwallet-xdefi/src/adapter.ts +++ b/packages/hdwallet-xdefi/src/adapter.ts @@ -1,5 +1,5 @@ import * as core from "@shapeshiftoss/hdwallet-core"; -import * as ethers from "ethers"; +import { providers } from "ethers"; import { XDEFIHDWallet } from "./xdefi"; @@ -7,7 +7,7 @@ declare global { // https://stackoverflow.com/questions/59459312/using-globalthis-in-typescript // Global declarations require the use of var // eslint-disable-next-line no-var - var xfi: { ethereum: ethers.providers.ExternalProvider } | null; + var xfi: { ethereum: providers.ExternalProvider } | null; } export class XDEFIAdapter { diff --git a/packages/hdwallet-xdefi/src/ethereum.test.ts b/packages/hdwallet-xdefi/src/ethereum.test.ts index 1643c591f..a615e6e4a 100644 --- a/packages/hdwallet-xdefi/src/ethereum.test.ts +++ b/packages/hdwallet-xdefi/src/ethereum.test.ts @@ -1,11 +1,11 @@ import * as core from "@shapeshiftoss/hdwallet-core"; -import * as ethers from "ethers"; +import { providers } from "ethers"; import * as ethereum from "./ethereum"; describe("XDEFI - Ethereum Adapter", () => { it("ethVerifyMessage returns null as its not implemented", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue("0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8"), }; expect( @@ -36,7 +36,7 @@ describe("XDEFI - Ethereum Adapter", () => { expect(paths).toMatchObject([]); }); it("ethSignTx returns null as its not implemented", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue({ r: "0x63db3dd3bf3e1fe7dde1969c0fc8850e34116d0b501c0483a0e08c0f77b8ce0a", s: "0x28297d012cccf389f6332415e96ee3fc0bbf8474d05f646e029cd281a031464b", @@ -69,7 +69,7 @@ describe("XDEFI - Ethereum Adapter", () => { }); }); it("ethSendTx returns a valid hash", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue("0x123"), }; @@ -91,7 +91,7 @@ describe("XDEFI - Ethereum Adapter", () => { expect(hash).toMatchObject({ hash: "0x123" }); }); it("ethSendTx returns a valid hash if maxFeePerGas is present in msg", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue("0x123"), }; @@ -114,7 +114,7 @@ describe("XDEFI - Ethereum Adapter", () => { expect(hash).toMatchObject({ hash: "0x123" }); }); it("ethSendTx returns null on error", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockRejectedValue(new Error("An Error has occurred")), }; @@ -179,7 +179,7 @@ describe("XDEFI - Ethereum Adapter", () => { }); it("ethSignMessage returns a valid signature object", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue( `Object { "address": "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8", @@ -210,7 +210,7 @@ describe("XDEFI - Ethereum Adapter", () => { }); it("ethSignMessage returns null on error", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockRejectedValue(new Error("An Error has occurred")), }; @@ -228,7 +228,7 @@ describe("XDEFI - Ethereum Adapter", () => { }); it("ethGetAddress returns a valid address", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockReturnValue(["0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"]), }; @@ -237,7 +237,7 @@ describe("XDEFI - Ethereum Adapter", () => { expect(address).toBe("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"); }); it("ethGetAddress returns null on error", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = { + const ethereumProvider: providers.ExternalProvider = { request: jest.fn().mockRejectedValue(new Error("An error has occurred")), }; @@ -246,7 +246,7 @@ describe("XDEFI - Ethereum Adapter", () => { expect(address).toBe(null); }); it("ethGetAddress returns null if no provider", async () => { - const ethereumProvider: ethers.providers.ExternalProvider = {}; + const ethereumProvider: providers.ExternalProvider = {}; const address = await ethereum.ethGetAddress(ethereumProvider); diff --git a/tsconfig.json b/tsconfig.json index 176257690..e92968f5c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -11,7 +11,6 @@ "sourceMap": true, "composite": true, "isolatedModules": true, - /* Strict Type-Checking Options */ "strict": true, diff --git a/yarn.lock b/yarn.lock index 2dcfd0cfa..62c3ddf77 100644 --- a/yarn.lock +++ b/yarn.lock @@ -755,15 +755,6 @@ bech32 "^1.1.4" readonly-date "^1.0.0" -"@cosmjs/encoding@^0.20.0": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.20.1.tgz#1d1162b3eca51b7244cd45102e313612cea77281" - integrity sha512-aBp153iq2LD4GwDGwodDWZk/eyAUZ8J8bbiqZ1uK8rrylzm9Rdw84aa6JxykezJe+uBPtoI4lx9eH7VQXCGDXw== - dependencies: - base64-js "^1.3.0" - bech32 "^1.1.4" - readonly-date "^1.0.0" - "@cosmjs/encoding@^0.24.1": version "0.24.1" resolved "https://registry.yarnpkg.com/@cosmjs/encoding/-/encoding-0.24.1.tgz#b30e92cdb70fc200a163b8c7aa5254606c8a09ab" @@ -815,7 +806,7 @@ "@cosmjs/stream" "^0.29.5" xstream "^11.14.0" -"@cosmjs/launchpad@^0.24.0-alpha.25", "@cosmjs/launchpad@^0.24.1": +"@cosmjs/launchpad@^0.24.1": version "0.24.1" resolved "https://registry.yarnpkg.com/@cosmjs/launchpad/-/launchpad-0.24.1.tgz#fe7e80734dfd60ea093429a646d7a38634c70134" integrity sha512-syqVGKRH6z1vw4DdAJOSu4OgUXJdkXQozqvDde0cXYwnvhb7EXGSg5CTtp+2GqTBJuNVfMZ2DSvrC2Ig8cWBQQ== @@ -841,13 +832,6 @@ dependencies: bn.js "^5.2.0" -"@cosmjs/math@^0.20.0": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.20.1.tgz#c3c2be821b8b5dbbb9b2c0401bd9f1472e821f2a" - integrity sha512-xt7BmpSw2OVGM2+JhlJvKv9OJs9+3DqgVL6+byUDC355CSISrZhFjJg9GFko1EFssDXz5YgvBZR5FkifC0xazw== - dependencies: - bn.js "^4.11.8" - "@cosmjs/math@^0.24.1": version "0.24.1" resolved "https://registry.yarnpkg.com/@cosmjs/math/-/math-0.24.1.tgz#9eed507885aacc9b269441fc9ecb00fb5876883a" @@ -869,7 +853,7 @@ dependencies: bn.js "^5.2.0" -"@cosmjs/proto-signing@0.24.1", "@cosmjs/proto-signing@^0.24.0-alpha.25": +"@cosmjs/proto-signing@0.24.1": version "0.24.1" resolved "https://registry.yarnpkg.com/@cosmjs/proto-signing/-/proto-signing-0.24.1.tgz#4ee38d4e0d29c626344fb832235fda8e8d645c28" integrity sha512-/rnyNx+FlG6b6O+igsb42eMN1/RXY+pTrNnAE8/YZaRloP9A6MXiTMO5JdYSTcjaD0mEVhejiy96bcyflKYXBg== @@ -1114,11 +1098,6 @@ resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.28.13.tgz#2fd2844ec832d7833811e2ae1691305d09791a08" integrity sha512-dVeMBiyg+46x7XBZEfJK8yTihphbCFpjVYmLJVqmTsHfJwymQ65cpyW/C+V/LgWARGK8hWQ/aX9HM5Ao8QmMSg== -"@cosmjs/utils@^0.20.0": - version "0.20.1" - resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.20.1.tgz#4d239b7d93c15523cdf109f225cbf61326fb69cd" - integrity sha512-xl9YnIrAAaBd6nFffwFbyrnKjqjD9zKGP8OBKxzyglxamHfqAS+PcJPEiaEpt+oUt7HAIOyhL3KK75Dh52hGvA== - "@cosmjs/utils@^0.24.1": version "0.24.1" resolved "https://registry.yarnpkg.com/@cosmjs/utils/-/utils-0.24.1.tgz#0adfefe63b7f17222bc2bc12f71296f35e7ad378" @@ -1246,7 +1225,7 @@ "@ethereumjs/common" "^2.4.0" ethereumjs-util "^7.1.0" -"@ethereumjs/tx@^4.1.2": +"@ethereumjs/tx@^4.1.2", "@ethereumjs/tx@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@ethereumjs/tx/-/tx-4.2.0.tgz#5988ae15daf5a3b3c815493bc6b495e76009e853" integrity sha512-1nc6VO4jtFd172BbSnTnDQVr9IYBFl1y4xPzZdtkrkKIncBCkdbgfdRV+MiTkJYAtTxvV12GRZLqBFT1PNK6Yw== @@ -2540,48 +2519,6 @@ resolved "https://registry.yarnpkg.com/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz#98c23c950a3d9b6c8f0daed06da6c3af06981340" integrity sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q== -"@iov/crypto@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@iov/crypto/-/crypto-2.1.0.tgz#10e91b6692e154958c11626dfd096a80e8a481a4" - integrity sha512-jnb4XuK50admolm7fBxOcxfAW2TO+wYrZlhDWiMETItY/Y5gNNa1zaDSO2wNIjjfGng+8nQ1yqnNhqy7busV2Q== - dependencies: - "@iov/encoding" "^2.1.0" - bip39 "^3.0.2" - bn.js "^4.11.8" - elliptic "^6.4.0" - js-sha3 "^0.8.0" - libsodium-wrappers "^0.7.6" - pbkdf2 "^3.0.16" - ripemd160 "^2.0.2" - sha.js "^2.4.11" - type-tagger "^1.0.0" - unorm "^1.5.0" - -"@iov/encoding@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@iov/encoding/-/encoding-2.1.0.tgz#434203c39874c68bc1d96e1278251f0feb23be07" - integrity sha512-5IOdLO7Xg/uRykuiCqeMYghQ3IjWDtGxv7NTWXkgpHuna0aewx43mRpT2NPCpOZd1tpuorDtQ7/zbDNRaIIF/w== - dependencies: - base64-js "^1.3.0" - bech32 "^1.1.3" - bn.js "^4.11.8" - readonly-date "^1.0.0" - -"@iov/encoding@^2.1.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@iov/encoding/-/encoding-2.5.0.tgz#9612e529f45e63633b2375c13db28b9330ce6293" - integrity sha512-HGHLlQEvD23rFjW5PQrxD2B/6LiBHVSxqX6gjOz9KfcmIMIftRA0qROrTITfjjjUr/yZZEeNk4qjuBls9TaYcA== - dependencies: - "@cosmjs/encoding" "^0.20.0" - "@cosmjs/math" "^0.20.0" - "@cosmjs/utils" "^0.20.0" - readonly-date "^1.0.0" - -"@iov/utils@2.0.2": - version "2.0.2" - resolved "https://registry.yarnpkg.com/@iov/utils/-/utils-2.0.2.tgz#3527f376d26100e07ac823bf87bebd0f24680d1c" - integrity sha512-4D8MEvTcFc/DVy5q25vHxRItmgJyeX85dixMH+MxdKr+yy71h3sYk+sVBEIn70uqGP7VqAJkGOPNFs08/XYELw== - "@isaacs/cliui@^8.0.2": version "8.0.2" resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" @@ -2867,16 +2804,12 @@ google-protobuf "^3.7.0-rc.2" pbjs "^0.0.5" -"@keplr-wallet/types@^0.9.10": - version "0.9.12" - resolved "https://registry.yarnpkg.com/@keplr-wallet/types/-/types-0.9.12.tgz#5771913343030a491c551a5a2eebb9cb0ad480f7" - integrity sha512-vtAczeD3+CgGExSZCnU9Wzs9Y8BpdbOii+UjIFHwCR57OXFQphbWHh2j15QFpV4CbebpDcBzIm+/4IAyLeI0Yw== +"@keplr-wallet/types@^0.12.35": + version "0.12.37" + resolved "https://registry.yarnpkg.com/@keplr-wallet/types/-/types-0.12.37.tgz#a136762547cf324355ed201f0146763e9a410dda" + integrity sha512-MhGnjIbG3JRo23+kF4fx0DMSkwJ2oqVdz9Xd2igb1Iwt6NDbLBD1vOrXTjByJwzawECbMsMIR1eEhw+myOwciw== dependencies: - "@cosmjs/launchpad" "^0.24.0-alpha.25" - "@cosmjs/proto-signing" "^0.24.0-alpha.25" - axios "^0.21.4" long "^4.0.0" - secretjs "^0.17.0" "@ledgerhq/compressjs@1.3.2": version "1.3.2" @@ -3909,6 +3842,14 @@ dependencies: "@lit-labs/ssr-dom-shim" "^1.0.0" +"@metamask/abi-utils@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@metamask/abi-utils/-/abi-utils-2.0.2.tgz#ad394e9cb8a95ac177cad942daadd88a246c0de8" + integrity sha512-B/A1dY/w4F/t6cDHUscklO6ovb/ztFsrsTXFd8QlqSByk/vyy+QbPE3VVpmmyI/7RX+PA1AJcvBdzCIz+r9dVQ== + dependencies: + "@metamask/utils" "^8.0.0" + superstruct "^1.0.3" + "@metamask/approval-controller@^3.5.1": version "3.5.1" resolved "https://registry.yarnpkg.com/@metamask/approval-controller/-/approval-controller-3.5.1.tgz#8d5099b7f0989d56b815a1423f395a15bf6bf056" @@ -3965,6 +3906,19 @@ json-rpc-random-id "^1.0.0" xtend "^4.0.1" +"@metamask/eth-sig-util@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-7.0.0.tgz#b035a2b826018578a5d463668bb64828271376d8" + integrity sha512-8KeXZB4SKx3EfNS5ahbjUMegyGvDQYk6Nk3hmM658sXpfAQR5ZlIXBgj+9RF+ZROqsU6EuNVgKt7Fr10re60PQ== + dependencies: + "@ethereumjs/util" "^8.1.0" + "@metamask/abi-utils" "^2.0.2" + "@metamask/utils" "^8.1.0" + ethereum-cryptography "^2.1.2" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + "@metamask/key-tree@^7.1.1": version "7.1.1" resolved "https://registry.yarnpkg.com/@metamask/key-tree/-/key-tree-7.1.1.tgz#559a76bf8fe0a3495c4a7aa41ed90f5475a7e2a2" @@ -4166,6 +4120,20 @@ semver "^7.5.4" superstruct "^1.0.3" +"@metamask/utils@^8.0.0", "@metamask/utils@^8.1.0": + version "8.2.0" + resolved "https://registry.yarnpkg.com/@metamask/utils/-/utils-8.2.0.tgz#51d608faf1ba7ba021084682160f275bb127d137" + integrity sha512-Zjx6y0PPrf9B4pdZ8JHl0grwJf/qNJ1dzYQh10/QSlj7Ct9Qy+r9PzdgGUHgA4oHohe1Phwy8MFnzB6TWZE11A== + dependencies: + "@ethereumjs/tx" "^4.2.0" + "@noble/hashes" "^1.3.1" + "@scure/base" "^1.1.3" + "@types/debug" "^4.1.7" + debug "^4.3.4" + pony-cause "^2.1.10" + semver "^7.5.4" + superstruct "^1.0.3" + "@motionone/animation@^10.15.1": version "10.15.1" resolved "https://registry.yarnpkg.com/@motionone/animation/-/animation-10.15.1.tgz#4a85596c31cbc5100ae8eb8b34c459fb0ccf6807" @@ -5461,7 +5429,7 @@ resolved "https://registry.yarnpkg.com/@protobufjs/utf8/-/utf8-1.1.0.tgz#a777360b5b39a1a2e5106f8e858f2fd2d060c570" integrity sha1-p3c2C1s5oaLlEG+OhY8v0tBgxXA= -"@scure/base@^1.0.0", "@scure/base@^1.1.1", "@scure/base@~1.1.0": +"@scure/base@^1.0.0", "@scure/base@^1.1.1", "@scure/base@^1.1.3", "@scure/base@~1.1.0": version "1.1.3" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.3.tgz#8584115565228290a6c6c4961973e0903bb3df2f" integrity sha512-/+SgoRjLq7Xlf0CWuLHq2LUZeL/w65kfzAPG5NH9pcmBhs+nunQTn4gvdwgMTIXnt9b2C/1SeL2XiysZEyIC9Q== @@ -6265,6 +6233,13 @@ jest-diff "^26.0.0" pretty-format "^26.0.0" +"@types/jquery@^3.5.22": + version "3.5.25" + resolved "https://registry.yarnpkg.com/@types/jquery/-/jquery-3.5.25.tgz#c817c71d414855f7d71f46da39f43e6b9579b0b9" + integrity sha512-gykx2c+OZf5nx2tv/5fDQqmvGgTiXshELy5jf9IgXPtVfSBl57IUYByN4osbwMXwJijWGOEYQABzGaFZE79A0Q== + dependencies: + "@types/sizzle" "*" + "@types/js-levenshtein@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@types/js-levenshtein/-/js-levenshtein-1.1.0.tgz#9541eec4ad6e3ec5633270a3a2b55d981edc44a9" @@ -6431,6 +6406,13 @@ resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.4.tgz#cd667bcfdd025213aafb7ca5915a932590acdcdc" integrity sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw== +"@types/ripemd160@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@types/ripemd160/-/ripemd160-2.0.2.tgz#e8ec7b1572e25fff9b3d0c4bc79022df4e037d12" + integrity sha512-hv3Oh/+ldCqp1xBRGi/1G6y2fxV6wUiiwjPt2Q7fe4UgmbD52ChdmxJyjDsGCRb9yuTBS9281UhH4D9gO85k7A== + dependencies: + "@types/node" "*" + "@types/secp256k1@^4.0.1": version "4.0.3" resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.3.tgz#1b8e55d8e00f08ee7220b4d59a6abe89c37a901c" @@ -6472,6 +6454,11 @@ dependencies: "@types/node" "*" +"@types/sizzle@*": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@types/sizzle/-/sizzle-2.3.5.tgz#d93dd29cdcd5801d90be968073b09a6b370780e4" + integrity sha512-tAe4Q+OLFOA/AMD+0lq8ovp8t3ysxAOeaScnfNdZpUxaGl51ZMDEITxkvFl1STudQ58mz6gzVGl9VhMKhwRnZQ== + "@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" @@ -8623,14 +8610,6 @@ buffer@^5.0.5, buffer@^5.1.0, buffer@^5.4.3, buffer@^5.5.0, buffer@^5.6.0: base64-js "^1.3.1" ieee754 "^1.1.13" -buffer@~5.4.3: - version "5.4.3" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.4.3.tgz#3fbc9c69eb713d323e3fc1a895eee0710c072115" - integrity sha512-zvj65TkFeIt3i6aj5bIvJDzjjQQGs4o/sNoezg1F1kYap9Nu2jcUdpwzRSJTHMMzG0H7bZkn4rNQpImhuxWX2A== - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - bufferutil@^4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/bufferutil/-/bufferutil-4.0.3.tgz#66724b756bed23cd7c28c4d306d7994f9943cc6b" @@ -8870,11 +8849,6 @@ chardet@^0.7.0: resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== -charenc@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667" - integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc= - checkpoint-store@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" @@ -9584,11 +9558,6 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" -crypt@~0.0.1: - version "0.0.2" - resolved "https://registry.yarnpkg.com/crypt/-/crypt-0.0.2.tgz#88d7ff7ec0dfb86f713dc87bbb42d044d3e6c41b" - integrity sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs= - crypto-browserify@3.12.0, crypto-browserify@^3.12.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" @@ -9735,11 +9704,6 @@ cuint@^0.2.2: resolved "https://registry.yarnpkg.com/cuint/-/cuint-0.2.2.tgz#408086d409550c2631155619e9fa7bcadc3b991b" integrity sha1-QICG1AlVDCYxFVYZ6fp7ytw7mRs= -curve25519-js@0.0.4: - version "0.0.4" - resolved "https://registry.yarnpkg.com/curve25519-js/-/curve25519-js-0.0.4.tgz#e6ad967e8cd284590d657bbfc90d8b50e49ba060" - integrity sha512-axn2UMEnkhyDUPWOwVKBMVIzSQy2ejH2xRGy1wq81dqRwApXfIzfbE3hIX0ZRFBIihf/KDqK158DLwESu4AK1w== - d@1, d@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/d/-/d-1.0.1.tgz#8698095372d58dbee346ffd0c7093f99f8f9eb5a" @@ -11013,7 +10977,7 @@ ethereum-cryptography@^0.1.3: secp256k1 "^4.0.1" setimmediate "^1.0.5" -ethereum-cryptography@^2.0.0: +ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== @@ -11293,7 +11257,7 @@ ethjs-unit@0.1.6, ethjs-unit@^0.1.6: bn.js "4.11.6" number-to-bn "1.7.0" -ethjs-util@0.1.6, ethjs-util@^0.1.3: +ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== @@ -11576,11 +11540,6 @@ fake-merkle-patricia-tree@^1.0.1: dependencies: checkpoint-store "^1.1.0" -fast-deep-equal@3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" - integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== - fast-deep-equal@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49" @@ -12559,7 +12518,7 @@ hash-wasm@^4.9.0: resolved "https://registry.yarnpkg.com/hash-wasm/-/hash-wasm-4.9.0.tgz#7e9dcc9f7d6bd0cc802f2a58f24edce999744206" integrity sha512-7SW7ejyfnRxuOc7ptQHSf4LDoZaWOivfzqw+5rpcQku0nHfmicPKE51ra9BiRLAmT8+gGLestr1XroUkqdjL6w== -hash.js@1.1.7, hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.7, hash.js@~1.1.7: +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" integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== @@ -13045,7 +13004,7 @@ is-boolean-object@^1.1.0: dependencies: call-bind "^1.0.2" -is-buffer@^1.1.5, is-buffer@~1.1.1: +is-buffer@^1.1.5: version "1.1.6" resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== @@ -14043,56 +14002,10 @@ jose@^4.3.5: resolved "https://registry.yarnpkg.com/jose/-/jose-4.3.5.tgz#890ec0b3bf26db0b36946ca54087335200deb6f7" integrity sha512-mdTu3En79OYMGBNHw4828hl6ZUOb+gQtNZVRgM+eVL3Rrs4ZYUv/yHPpfDh65GN2HhKBvJsvA0/6tKEcpkyzeg== -jquery@^3.4.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/jquery/-/jquery-3.6.0.tgz#c72a09f15c1bdce142f49dbf1170bdf8adac2470" - integrity sha512-JVzAR/AjBvVt2BmYhxRCSYysDsPcssdmTFnzyLEts9qNwmjmu4JTAMYubEfwVOSwpQ1I1sKKFcxhZCI2buerfw== - -js-crypto-env@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/js-crypto-env/-/js-crypto-env-0.3.2.tgz#02195723469da14449338ca2789fd7ff6784c533" - integrity sha512-F1uHiCkSOo36qBuuZABA4sBf+xeFBzhJZ0Sd7af8FAruszIhm1Xxv+Zr5Ne90Zlh7/fnxCsrdkj0N8f0a3lVlQ== - -js-crypto-hash@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/js-crypto-hash/-/js-crypto-hash-0.6.3.tgz#748e3e1853f69dad714636db3290736825506641" - integrity sha512-SG8c9tM8y3sUb4k7WvpVfu5vU7zfPvX+eaYR5578TvehkehdaQbqAc+y+1FwxnqQ3WZ0gsYoOKp/mW+mqtNoWA== - dependencies: - buffer "~5.4.3" - hash.js "~1.1.7" - js-crypto-env "^0.3.2" - md5 "~2.2.1" - sha3 "~2.1.0" - -js-crypto-hkdf@0.7.3: - version "0.7.3" - resolved "https://registry.yarnpkg.com/js-crypto-hkdf/-/js-crypto-hkdf-0.7.3.tgz#537c394a2e65bca80032daa07d2ffe7e4f78d32f" - integrity sha512-eAaVArAjS2GCacWGXY4hjBiexrLQYlI0PMOcbwtrSEj84XU3kUfMYZm9bpTyaTXgdHC/eQoXe/Of6biG+RSEaQ== - dependencies: - js-crypto-env "^0.3.2" - js-crypto-hmac "^0.6.3" - js-crypto-random "^0.4.3" - js-encoding-utils "0.5.6" - -js-crypto-hmac@^0.6.3: - version "0.6.3" - resolved "https://registry.yarnpkg.com/js-crypto-hmac/-/js-crypto-hmac-0.6.3.tgz#c33352c1ee6076b17b8f4cb0e2167814b2b77d6d" - integrity sha512-T0pKOaHACOSG6Xs6/06G8RDDeZouQwIQNBq9L/zoUGsd4F67gAjpT3q2lGigAGpUd1hiyy7vnhvLpz7VDt6DbA== - dependencies: - js-crypto-env "^0.3.2" - js-crypto-hash "^0.6.3" - -js-crypto-random@^0.4.3: - version "0.4.3" - resolved "https://registry.yarnpkg.com/js-crypto-random/-/js-crypto-random-0.4.3.tgz#898c2d91991eead02b4e461005e878fa9827fd74" - integrity sha512-C3gzphPPfw9jfQ9Q/LjhJMZxQNp3AaoVRDvyZkiB+zYltfs8tKQPsskWkXACpg1Nzh01PtSRUvVijjptd2qGHQ== - dependencies: - js-crypto-env "^0.3.2" - -js-encoding-utils@0.5.6: - version "0.5.6" - resolved "https://registry.yarnpkg.com/js-encoding-utils/-/js-encoding-utils-0.5.6.tgz#517351d8f4a85b2ad121183d41df8319981bee03" - integrity sha512-qnAGsUIWrmzh5n+3AXqbxX1KsB9hkQmJZf3aA9DLAS7GpL/NEHCBreFFbW+imramoU+Q0TDyvkwhRbBRH1TVkg== +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== js-levenshtein@^1.1.6: version "1.1.6" @@ -14985,15 +14898,6 @@ md5.js@^1.3.4: inherits "^2.0.1" safe-buffer "^5.1.2" -md5@~2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/md5/-/md5-2.2.1.tgz#53ab38d5fe3c8891ba465329ea23fac0540126f9" - integrity sha1-U6s41f48iJG6RlMp6iP6wFQBJvk= - dependencies: - charenc "~0.0.1" - crypt "~0.0.1" - is-buffer "~1.1.1" - mdn-data@2.0.14: version "2.0.14" resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.14.tgz#7113fc4281917d63ce29b43446f701e68c25ba50" @@ -15332,11 +15236,6 @@ minizlib@^2.1.1, minizlib@^2.1.2: minipass "^3.0.0" yallist "^4.0.0" -miscreant@0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/miscreant/-/miscreant-0.3.2.tgz#a91c046566cca70bd6b5e9fbdd3f67617fa85034" - integrity sha512-fL9KxsQz9BJB2KGPMHFrReioywkiomBiuaLk6EuChijK0BsJsIKJXdVomR+/bPj5mvbFD6wM0CM3bZio9g7OHA== - mixin-deep@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" @@ -16382,11 +16281,6 @@ pacote@^13.0.3, pacote@^13.6.1: ssri "^9.0.0" tar "^6.1.11" -pako@1.0.11: - version "1.0.11" - resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" - integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== - parcel@^2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/parcel/-/parcel-2.3.2.tgz#d1cb475f27edae981edea7a7104e04d3a35a87ca" @@ -16579,7 +16473,7 @@ pbjs@^0.0.5: commander "2.9.0" protocol-buffers-schema "3.1.0" -pbkdf2@^3.0.16, pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9, pbkdf2@^3.1.1: +pbkdf2@^3.0.17, pbkdf2@^3.0.3, pbkdf2@^3.0.9, pbkdf2@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.1.2.tgz#dd822aa0887580e52f1a039dc3eda108efae3075" integrity sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA== @@ -16701,6 +16595,11 @@ pocket-js-core@0.0.3: dependencies: axios "^0.18.0" +pony-cause@^2.1.10: + version "2.1.10" + resolved "https://registry.yarnpkg.com/pony-cause/-/pony-cause-2.1.10.tgz#828457ad6f13be401a075dbf14107a9057945174" + integrity sha512-3IKLNXclQgkU++2fSi93sQ6BznFuxSLB11HdvZQ6JW/spahf/P1pAHBQEahr20rs0htZW0UDkM1HmA+nZkXKsw== + posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" @@ -17143,10 +17042,10 @@ protobufjs@6.10.1: "@types/node" "^13.7.0" long "^4.0.0" -protobufjs@^6.11.2, protobufjs@^6.8.8, protobufjs@~6.11.2: - version "6.11.2" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b" - integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw== +protobufjs@^6.11.3, protobufjs@~6.11.3: + version "6.11.3" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" + integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -17162,10 +17061,10 @@ protobufjs@^6.11.2, protobufjs@^6.8.8, protobufjs@~6.11.2: "@types/node" ">=13.7.0" long "^4.0.0" -protobufjs@^6.11.3, protobufjs@~6.11.3: - version "6.11.3" - resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.3.tgz#637a527205a35caa4f3e2a9a4a13ddffe0e7af74" - integrity sha512-xL96WDdCZYdU7Slin569tFX712BxsxslWwAfAhCYjQKGTq7dAU91Lomy6nLLhh/dyGhk/YH4TwTSRxTzhuHyZg== +protobufjs@^6.8.8, protobufjs@~6.11.2: + version "6.11.2" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-6.11.2.tgz#de39fabd4ed32beaa08e9bb1e30d08544c1edf8b" + integrity sha512-4BQJoPooKJl2G9j3XftkIXjoC9C0Av2NOrWmbLWT1vH32GcSUHjM0Arra6UfTsVyfMAuFzaLucXn1sadxJydAw== dependencies: "@protobufjs/aspromise" "^1.1.2" "@protobufjs/base64" "^1.1.2" @@ -18139,24 +18038,7 @@ secp256k1@^3.0.1: nan "^2.14.0" safe-buffer "^5.1.2" -secretjs@^0.17.0: - version "0.17.5" - resolved "https://registry.yarnpkg.com/secretjs/-/secretjs-0.17.5.tgz#5b55e46cfa2719714831fc2019e21c21959fe587" - integrity sha512-sf0+Je9KIEMQr/wJOgeqyBOV0ruiMNHSwP4L2vXiJbtzJWQqyVHyPkpavAhruNZ+91XlSzAFP2X5MPxqPBC9fQ== - dependencies: - "@iov/crypto" "2.1.0" - "@iov/encoding" "2.1.0" - "@iov/utils" "2.0.2" - axios "0.21.1" - curve25519-js "0.0.4" - fast-deep-equal "3.1.1" - js-crypto-hkdf "0.7.3" - miscreant "0.3.2" - pako "1.0.11" - protobufjs "^6.11.2" - secure-random "1.1.2" - -secure-random@1.1.2, secure-random@^1.1.2: +secure-random@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/secure-random/-/secure-random-1.1.2.tgz#ed103b460a851632d420d46448b2a900a41e7f7c" integrity sha512-H2bdSKERKdBV1SwoqYm6C0y+9EA94v6SUBOWO8kDndc4NoUih7Dv6Tsgma7zO1lv27wIvjlD0ZpMQk7um5dheQ== @@ -18323,13 +18205,6 @@ sha.js@2, sha.js@^2.3.6, sha.js@^2.4.0, sha.js@^2.4.11, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -sha3@~2.1.0: - version "2.1.4" - resolved "https://registry.yarnpkg.com/sha3/-/sha3-2.1.4.tgz#000fac0fe7c2feac1f48a25e7a31b52a6492cc8f" - integrity sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg== - dependencies: - buffer "6.0.3" - shallow-clone@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-3.0.1.tgz#8f2981ad92531f55035b01fb230769a40e02efa3" @@ -19541,7 +19416,7 @@ tunnel@^0.0.6: resolved "https://registry.yarnpkg.com/tunnel/-/tunnel-0.0.6.tgz#72f1314b34a5b192db012324df2cc587ca47f92c" integrity sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg== -tweetnacl-util@^0.15.0: +tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== @@ -19633,11 +19508,6 @@ type-is@~1.6.17, type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -type-tagger@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/type-tagger/-/type-tagger-1.0.0.tgz#dc6297e52e17097c1b92b42c16816a18f631e7f4" - integrity sha512-FIPqqpmDgdaulCnRoKv1/d3U4xVBUrYn42QXWNP3XYmgfPUDuBUsgFOb9ntT0aIe0UsUP+lknpQ5d9Kn36RssA== - type@^1.0.1: version "1.2.0" resolved "https://registry.yarnpkg.com/type/-/type-1.2.0.tgz#848dd7698dafa3e54a6c479e759c4bc3f18847a0"