diff --git a/examples/sandbox/index.html b/examples/sandbox/index.html
index 0cdbe1c51..bf6675cf0 100644
--- a/examples/sandbox/index.html
+++ b/examples/sandbox/index.html
@@ -116,6 +116,7 @@
Select
+
diff --git a/examples/sandbox/index.ts b/examples/sandbox/index.ts
index 8c181b212..5920c8983 100644
--- a/examples/sandbox/index.ts
+++ b/examples/sandbox/index.ts
@@ -11,6 +11,7 @@ import * as ledgerWebHID from "@shapeshiftoss/hdwallet-ledger-webhid";
import * as ledgerWebUSB from "@shapeshiftoss/hdwallet-ledger-webusb";
import * as metaMask from "@shapeshiftoss/hdwallet-metamask";
import * as native from "@shapeshiftoss/hdwallet-native";
+import * as phantom from "@shapeshiftoss/hdwallet-phantom";
import * as portis from "@shapeshiftoss/hdwallet-portis";
import * as tallyHo from "@shapeshiftoss/hdwallet-tallyho";
import * as trezorConnect from "@shapeshiftoss/hdwallet-trezor-connect";
@@ -125,6 +126,7 @@ const kkbridgeAdapter = keepkeyTcp.TCPKeepKeyAdapter.useKeyring(keyring);
const kkemuAdapter = keepkeyTcp.TCPKeepKeyAdapter.useKeyring(keyring);
const portisAdapter = portis.PortisAdapter.useKeyring(keyring, { portisAppId });
const metaMaskAdapter = metaMask.MetaMaskAdapter.useKeyring(keyring);
+const phantomAdapter = phantom.PhantomAdapter.useKeyring(keyring);
const tallyHoAdapter = tallyHo.TallyHoAdapter.useKeyring(keyring);
const walletConnectAdapter = walletConnect.WalletConnectAdapter.useKeyring(keyring, walletConnectOptions);
const walletConnectV2Adapter = walletConnectv2.WalletConnectV2Adapter.useKeyring(keyring, walletConnectV2Options);
@@ -157,6 +159,7 @@ const $ledgerwebhid = $("#ledgerwebhid");
const $portis = $("#portis");
const $native = $("#native");
const $metaMask = $("#metaMask");
+const $phantom = $("#phantom");
const $coinbase = $("#coinbase");
const $tallyHo = $("#tallyHo");
const $walletConnect = $("#walletConnect");
@@ -241,6 +244,19 @@ $metaMask.on("click", async (e) => {
}
});
+$phantom.on("click", async (e) => {
+ e.preventDefault();
+ wallet = await phantomAdapter.pairDevice();
+ window["wallet"] = wallet;
+ let deviceID = "nothing";
+ try {
+ deviceID = await wallet.getDeviceID();
+ $("#keyring select").val(deviceID);
+ } catch (err) {
+ console.error(err);
+ }
+});
+
$coinbase.on("click", async (e) => {
e.preventDefault();
wallet = await coinbaseAdapter.pairDevice();
@@ -403,6 +419,12 @@ async function deviceConnected(deviceId) {
console.error("Could not initialize MetaMaskAdapter", e);
}
+ try {
+ await phantomAdapter.initialize();
+ } catch (e) {
+ console.error("Could not initialize PhantomAdapter", e);
+ }
+
try {
await tallyHoAdapter.initialize();
} catch (e) {
diff --git a/examples/sandbox/json/ethereum/OpenSea-ethSignTypedDataV4.json b/examples/sandbox/json/ethereum/OpenSea-ethSignTypedDataV4.json
index 44b3a7400..bd20f0def 100644
--- a/examples/sandbox/json/ethereum/OpenSea-ethSignTypedDataV4.json
+++ b/examples/sandbox/json/ethereum/OpenSea-ethSignTypedDataV4.json
@@ -118,7 +118,7 @@
"domain": {
"name": "Seaport",
"version": "1.5",
- "chainId": 137,
+ "chainId": 1,
"verifyingContract": "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC"
},
"message": {
diff --git a/examples/sandbox/json/ethereum/ethTx.json b/examples/sandbox/json/ethereum/ethTx.json
index c43243e07..7420ccdd6 100644
--- a/examples/sandbox/json/ethereum/ethTx.json
+++ b/examples/sandbox/json/ethereum/ethTx.json
@@ -156,7 +156,8 @@
"verifyingContract": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
"chainId": 1
},
- "primaryType": "EIP712Domain"
+ "primaryType": "EIP712Domain",
+ "message": {}
}
}
},
diff --git a/examples/sandbox/package.json b/examples/sandbox/package.json
index 70e96bf9d..ba5d2143e 100644
--- a/examples/sandbox/package.json
+++ b/examples/sandbox/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-sandbox",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"private": true,
"browserslist": "> 0.5%, last 2 versions, not dead",
@@ -12,24 +12,25 @@
"dependencies": {
"@esm2cjs/p-queue": "^7.3.0",
"@metamask/eth-sig-util": "^7.0.0",
- "@shapeshiftoss/hdwallet-coinbase": "1.55.5",
- "@shapeshiftoss/hdwallet-core": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey-tcp": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey-webusb": "1.55.5",
- "@shapeshiftoss/hdwallet-keplr": "1.55.5",
- "@shapeshiftoss/hdwallet-ledger": "1.55.5",
- "@shapeshiftoss/hdwallet-ledger-webhid": "1.55.5",
- "@shapeshiftoss/hdwallet-ledger-webusb": "1.55.5",
- "@shapeshiftoss/hdwallet-metamask": "1.55.5",
- "@shapeshiftoss/hdwallet-native": "1.55.5",
- "@shapeshiftoss/hdwallet-portis": "1.55.5",
- "@shapeshiftoss/hdwallet-tallyho": "1.55.5",
- "@shapeshiftoss/hdwallet-trezor": "1.55.5",
- "@shapeshiftoss/hdwallet-trezor-connect": "1.55.5",
- "@shapeshiftoss/hdwallet-walletconnect": "1.55.5",
- "@shapeshiftoss/hdwallet-walletconnectv2": "1.55.5",
- "@shapeshiftoss/hdwallet-xdefi": "1.55.5",
+ "@shapeshiftoss/hdwallet-coinbase": "1.55.6",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey-tcp": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey-webusb": "1.55.6",
+ "@shapeshiftoss/hdwallet-keplr": "1.55.6",
+ "@shapeshiftoss/hdwallet-ledger": "1.55.6",
+ "@shapeshiftoss/hdwallet-ledger-webhid": "1.55.6",
+ "@shapeshiftoss/hdwallet-ledger-webusb": "1.55.6",
+ "@shapeshiftoss/hdwallet-metamask": "1.55.6",
+ "@shapeshiftoss/hdwallet-native": "1.55.6",
+ "@shapeshiftoss/hdwallet-phantom": "1.55.6",
+ "@shapeshiftoss/hdwallet-portis": "1.55.6",
+ "@shapeshiftoss/hdwallet-tallyho": "1.55.6",
+ "@shapeshiftoss/hdwallet-trezor": "1.55.6",
+ "@shapeshiftoss/hdwallet-trezor-connect": "1.55.6",
+ "@shapeshiftoss/hdwallet-walletconnect": "1.55.6",
+ "@shapeshiftoss/hdwallet-walletconnectv2": "1.55.6",
+ "@shapeshiftoss/hdwallet-xdefi": "1.55.6",
"bip32": "^2.0.4",
"eip-712": "^1.0.0",
"jquery": "^3.7.1",
diff --git a/integration/package.json b/integration/package.json
index 8a964fe63..5e1b8b031 100644
--- a/integration/package.json
+++ b/integration/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/integration",
- "version": "1.55.5",
+ "version": "1.55.6",
"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.55.5",
- "@shapeshiftoss/hdwallet-keepkey": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey-nodewebusb": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey-tcp": "1.55.5",
- "@shapeshiftoss/hdwallet-ledger": "1.55.5",
- "@shapeshiftoss/hdwallet-native": "1.55.5",
- "@shapeshiftoss/hdwallet-portis": "1.55.5",
- "@shapeshiftoss/hdwallet-trezor": "1.55.5",
- "@shapeshiftoss/hdwallet-xdefi": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey-nodewebusb": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey-tcp": "1.55.6",
+ "@shapeshiftoss/hdwallet-ledger": "1.55.6",
+ "@shapeshiftoss/hdwallet-native": "1.55.6",
+ "@shapeshiftoss/hdwallet-portis": "1.55.6",
+ "@shapeshiftoss/hdwallet-trezor": "1.55.6",
+ "@shapeshiftoss/hdwallet-xdefi": "1.55.6",
"fast-json-stable-stringify": "^2.1.0",
"msw": "^0.27.1",
"whatwg-fetch": "^3.6.2"
diff --git a/lerna.json b/lerna.json
index d474d95b4..6b41bc3e9 100644
--- a/lerna.json
+++ b/lerna.json
@@ -1,6 +1,6 @@
{
"lerna": "5.2.0",
- "version": "1.55.5",
+ "version": "1.55.6",
"npmClient": "yarn",
"useWorkspaces": true,
"command": {
diff --git a/packages/hdwallet-coinbase/package.json b/packages/hdwallet-coinbase/package.json
index f93eab7bd..baa8a2acb 100644
--- a/packages/hdwallet-coinbase/package.json
+++ b/packages/hdwallet-coinbase/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-coinbase",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -15,7 +15,7 @@
},
"dependencies": {
"@coinbase/wallet-sdk": "^3.6.6",
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"eth-rpc-errors": "^4.0.3",
"lodash": "^4.17.21"
},
diff --git a/packages/hdwallet-coinbase/src/coinbase.ts b/packages/hdwallet-coinbase/src/coinbase.ts
index 2e148c75c..aca7b9431 100644
--- a/packages/hdwallet-coinbase/src/coinbase.ts
+++ b/packages/hdwallet-coinbase/src/coinbase.ts
@@ -344,7 +344,6 @@ export class CoinbaseHDWallet implements core.HDWallet, core.ETHWallet {
return this.info.ethNextAccountPath(msg);
}
- // TODO: Respect msg.addressNList!
// eslint-disable-next-line @typescript-eslint/no-unused-vars
public async ethGetAddress(msg: core.ETHGetAddress): Promise {
if (this.ethAddress) {
diff --git a/packages/hdwallet-core/package.json b/packages/hdwallet-core/package.json
index 0655e3ae6..53c5a67e5 100644
--- a/packages/hdwallet-core/package.json
+++ b/packages/hdwallet-core/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-core",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,8 +14,10 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
+ "@shapeshiftoss/bitcoinjs-lib": "5.2.0-shapeshift.2",
"@shapeshiftoss/proto-tx-builder": "^0.8.0",
"eip-712": "^1.0.0",
+ "ethers": "5.7.2",
"eventemitter2": "^5.0.1",
"lodash": "^4.17.21",
"rxjs": "^6.4.0",
diff --git a/packages/hdwallet-core/src/bitcoin.ts b/packages/hdwallet-core/src/bitcoin.ts
index 49c9971fb..5725d42a5 100644
--- a/packages/hdwallet-core/src/bitcoin.ts
+++ b/packages/hdwallet-core/src/bitcoin.ts
@@ -1,3 +1,4 @@
+import * as bitcoin from "@shapeshiftoss/bitcoinjs-lib";
import * as ta from "type-assertions";
import { addressNListToBIP32, slip44ByCoin } from "./utils";
@@ -488,3 +489,50 @@ export function segwitNativeAccount(coin: Coin, slip44: number, accountIdx: numb
addressNList: [0x80000000 + 84, 0x80000000 + slip44, 0x80000000 + accountIdx],
};
}
+
+export function validateVoutOrdering(msg: BTCSignTxNative, tx: bitcoin.Transaction): boolean {
+ // From THORChain specification:
+ /* ignoreTx checks if we can already ignore a tx according to preset rules
+
+ we expect array of "vout" for a BTC to have this format
+ OP_RETURN is mandatory only on inbound tx
+ vout:0 is our vault
+ vout:1 is any any change back to themselves
+ vout:2 is OP_RETURN (first 80 bytes)
+ vout:3 is OP_RETURN (next 80 bytes)
+
+ Rules to ignore a tx are:
+ - vout:0 doesn't have coins (value)
+ - vout:0 doesn't have address
+ - count vouts > 4
+ - count vouts with coins (value) > 2
+ */
+
+ // Check that vout:0 contains the vault address
+ if (bitcoin.address.fromOutputScript(tx.outs[0].script) != msg.vaultAddress) {
+ console.error("Vout:0 does not contain vault address.");
+ return false;
+ }
+
+ // TODO: Can we check and make sure vout:1 is our address?
+
+ // Check and make sure vout:2 exists
+ if (tx.outs.length < 3) {
+ console.error("Not enough outputs found in transaction.", msg);
+ return false;
+ }
+ // Check and make sure vout:2 has OP_RETURN data
+ const opcode = bitcoin.script.decompile(tx.outs[2].script)?.[0];
+ if (Object.keys(bitcoin.script.OPS).find((k) => bitcoin.script.OPS[k] === opcode) != "OP_RETURN") {
+ console.error("OP_RETURN output not found for transaction.");
+ return false;
+ }
+
+ // Make sure vout:3 does not exist
+ if (tx.outs[3]) {
+ console.error("Illegal second op_return output found.");
+ return false;
+ }
+
+ return true;
+}
diff --git a/packages/hdwallet-core/src/ethereum.ts b/packages/hdwallet-core/src/ethereum.ts
index 16d15a465..22bf307f2 100644
--- a/packages/hdwallet-core/src/ethereum.ts
+++ b/packages/hdwallet-core/src/ethereum.ts
@@ -1,5 +1,6 @@
import { Bytes } from "@ethersproject/bytes";
import { TypedData } from "eip-712";
+import { ethers } from "ethers";
import { addressNListToBIP32, slip44ByCoin } from "./utils";
import { BIP32Path, HDWallet, HDWalletInfo, PathDescription } from "./wallet";
@@ -240,3 +241,16 @@ export function describeETHPath(path: BIP32Path): PathDescription {
isPrefork: false,
};
}
+
+export function buildMessage(message: ethers.utils.BytesLike): Uint8Array {
+ const messageBytes =
+ typeof message === "string" && !ethers.utils.isHexString(message)
+ ? ethers.utils.toUtf8Bytes(message)
+ : ethers.utils.arrayify(message);
+
+ return ethers.utils.concat([
+ ethers.utils.toUtf8Bytes("\x19Ethereum Signed Message:\n"),
+ ethers.utils.toUtf8Bytes(String(messageBytes.length)),
+ messageBytes,
+ ]);
+}
diff --git a/packages/hdwallet-keepkey-chromeusb/package.json b/packages/hdwallet-keepkey-chromeusb/package.json
index d7391cf82..52e79af52 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,7 +14,7 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey": "1.55.5"
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey": "1.55.6"
}
}
diff --git a/packages/hdwallet-keepkey-electron/package.json b/packages/hdwallet-keepkey-electron/package.json
index ac024a86a..27849cefe 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,7 +14,7 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-keepkey": "1.55.5",
+ "@shapeshiftoss/hdwallet-keepkey": "1.55.6",
"uuid": "^8.3.2"
},
"peerDependencies": {
diff --git a/packages/hdwallet-keepkey-nodehid/package.json b/packages/hdwallet-keepkey-nodehid/package.json
index 3d3b638e4..9ed6ce3e4 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,7 +14,7 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-keepkey": "1.55.5"
+ "@shapeshiftoss/hdwallet-keepkey": "1.55.6"
},
"peerDependencies": {
"node-hid": "^2.1.1"
diff --git a/packages/hdwallet-keepkey-nodewebusb/package.json b/packages/hdwallet-keepkey-nodewebusb/package.json
index 5b662d7bd..25822cb38 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,8 +14,8 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey": "1.55.5"
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey": "1.55.6"
},
"peerDependencies": {
"usb": "^2.3.1"
diff --git a/packages/hdwallet-keepkey-tcp/package.json b/packages/hdwallet-keepkey-tcp/package.json
index af259f49a..6e4d800f5 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,8 +14,8 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey": "1.55.6",
"axios": "^0.21.1"
}
}
diff --git a/packages/hdwallet-keepkey-webusb/package.json b/packages/hdwallet-keepkey-webusb/package.json
index 3fc429e7d..7c08eccc4 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,8 +14,8 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
- "@shapeshiftoss/hdwallet-keepkey": "1.55.5"
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-keepkey": "1.55.6"
},
"devDependencies": {
"@types/w3c-web-usb": "^1.0.4"
diff --git a/packages/hdwallet-keepkey/package.json b/packages/hdwallet-keepkey/package.json
index f9fbb8722..ea0ca354f 100644
--- a/packages/hdwallet-keepkey/package.json
+++ b/packages/hdwallet-keepkey/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-keepkey",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -20,7 +20,7 @@
"@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.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"@shapeshiftoss/proto-tx-builder": "^0.8.0",
"bignumber.js": "^9.0.1",
"bnb-javascript-sdk-nobroadcast": "^2.16.14",
diff --git a/packages/hdwallet-keplr/package.json b/packages/hdwallet-keplr/package.json
index 5867ef595..88b4a7434 100644
--- a/packages/hdwallet-keplr/package.json
+++ b/packages/hdwallet-keplr/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-keplr",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -15,7 +15,7 @@
},
"dependencies": {
"@shapeshiftoss/caip": "8.15.0",
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"@shapeshiftoss/proto-tx-builder": "^0.8.0",
"@shapeshiftoss/types": "3.1.3",
"base64-js": "^1.5.1",
diff --git a/packages/hdwallet-ledger-webhid/package.json b/packages/hdwallet-ledger-webhid/package.json
index 9302ca9c3..b71ecd952 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -19,8 +19,8 @@
"@ledgerhq/hw-transport": "^6.31.2",
"@ledgerhq/hw-transport-webhid": "^6.29.2",
"@ledgerhq/live-common": "^21.8.2",
- "@shapeshiftoss/hdwallet-core": "1.55.5",
- "@shapeshiftoss/hdwallet-ledger": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-ledger": "1.55.6",
"@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 1bb60f3b0..cb39bdbba 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -20,8 +20,8 @@
"@ledgerhq/hw-transport-webusb": "^6.29.2",
"@ledgerhq/live-common": "^21.8.2",
"@ledgerhq/logs": "^6.10.1",
- "@shapeshiftoss/hdwallet-core": "1.55.5",
- "@shapeshiftoss/hdwallet-ledger": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-ledger": "1.55.6",
"@types/w3c-web-usb": "^1.0.4",
"p-queue": "^7.4.1"
},
diff --git a/packages/hdwallet-ledger/package.json b/packages/hdwallet-ledger/package.json
index bd838a6b7..fd547d79c 100644
--- a/packages/hdwallet-ledger/package.json
+++ b/packages/hdwallet-ledger/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-ledger",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -19,7 +19,7 @@
"@ethereumjs/tx": "^3.3.0",
"@ledgerhq/hw-app-cosmos": "^6.29.1",
"@shapeshiftoss/bitcoinjs-lib": "5.2.0-shapeshift.2",
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"base64-js": "^1.5.1",
"bchaddrjs": "^0.4.4",
"bitcoinjs-message": "^2.0.0",
diff --git a/packages/hdwallet-metamask-shapeshift-multichain/package.json b/packages/hdwallet-metamask-shapeshift-multichain/package.json
index f16c724c3..66734796b 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.55.5",
+ "version": "1.55.6",
"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.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"@shapeshiftoss/metamask-snaps-adapter": "^1.0.10",
"@shapeshiftoss/metamask-snaps-types": "^1.0.10",
"eth-rpc-errors": "^4.0.3",
diff --git a/packages/hdwallet-metamask/package.json b/packages/hdwallet-metamask/package.json
index 5927fc4e3..528a3d837 100644
--- a/packages/hdwallet-metamask/package.json
+++ b/packages/hdwallet-metamask/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-metamask",
- "version": "1.55.5",
+ "version": "1.55.6",
"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.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"eth-rpc-errors": "^4.0.3",
"lodash": "^4.17.21"
},
diff --git a/packages/hdwallet-metamask/src/metamask.ts b/packages/hdwallet-metamask/src/metamask.ts
index d305e7285..3592388e2 100644
--- a/packages/hdwallet-metamask/src/metamask.ts
+++ b/packages/hdwallet-metamask/src/metamask.ts
@@ -345,9 +345,8 @@ export class MetaMaskHDWallet implements core.HDWallet, core.ETHWallet {
return this.info.ethNextAccountPath(msg);
}
- // TODO: Respect msg.addressNList!
// eslint-disable-next-line @typescript-eslint/no-unused-vars
- public async ethGetAddress(msg: core.ETHGetAddress): Promise {
+ public async ethGetAddress(_msg: core.ETHGetAddress): Promise {
if (this.ethAddress) {
return this.ethAddress;
}
diff --git a/packages/hdwallet-native-vault/package.json b/packages/hdwallet-native-vault/package.json
index 1bec662a3..67fe8c531 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,7 +14,7 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-native": "1.55.5",
+ "@shapeshiftoss/hdwallet-native": "1.55.6",
"bip39": "^3.0.4",
"hash-wasm": "^4.11.0",
"idb-keyval": "^6.0.3",
diff --git a/packages/hdwallet-native/package.json b/packages/hdwallet-native/package.json
index 7043d1b29..72d8c5677 100644
--- a/packages/hdwallet-native/package.json
+++ b/packages/hdwallet-native/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-native",
- "version": "1.55.5",
+ "version": "1.55.6",
"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.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"@shapeshiftoss/proto-tx-builder": "^0.8.0",
"@zxing/text-encoding": "^0.9.0",
"bchaddrjs": "^0.4.9",
diff --git a/packages/hdwallet-native/src/bitcoin.ts b/packages/hdwallet-native/src/bitcoin.ts
index 182ea6bbd..7275d9af4 100644
--- a/packages/hdwallet-native/src/bitcoin.ts
+++ b/packages/hdwallet-native/src/bitcoin.ts
@@ -171,53 +171,6 @@ export function MixinNativeBTCWallet 4
- - count vouts with coins (value) > 2
- */
-
- // Check that vout:0 contains the vault address
- if (bitcoin.address.fromOutputScript(tx.outs[0].script) != msg.vaultAddress) {
- console.error("Vout:0 does not contain vault address.");
- return false;
- }
-
- // TODO: Can we check and make sure vout:1 is our address?
-
- // Check and make sure vout:2 exists
- if (tx.outs.length < 3) {
- console.error("Not enough outputs found in transaction.", msg);
- return false;
- }
- // Check and make sure vout:2 has OP_RETURN data
- const opcode = bitcoin.script.decompile(tx.outs[2].script)?.[0];
- if (Object.keys(bitcoin.script.OPS).find((k) => bitcoin.script.OPS[k] === opcode) != "OP_RETURN") {
- console.error("OP_RETURN output not found for transaction.");
- return false;
- }
-
- // Make sure vout:3 does not exist
- if (tx.outs[3]) {
- console.error("Illegal second op_return output found.");
- return false;
- }
-
- return true;
- }
-
async buildInput(coin: core.Coin, input: core.BTCSignTxInputNative): Promise {
return this.needsMnemonic(!!this.#masterKey, async () => {
const { addressNList, amount, hex, scriptType } = input;
@@ -355,7 +308,7 @@ export function MixinNativeBTCWallet {
- const messageBuf = buildMessage(messageData);
+ const messageBuf = core.buildMessage(messageData);
const nodeAdapter = await this.nodeAdapter.derivePath(core.addressNListToBIP32(addressNList));
const rawSig = await SecP256K1.RecoverableSignature.signCanonically(nodeAdapter.node, "keccak256", messageBuf);
return joinSignature(ethSigFromRecoverableSig(rawSig));
diff --git a/packages/hdwallet-native/src/ethereum.ts b/packages/hdwallet-native/src/ethereum.ts
index ff35ea5ff..f70a5b18b 100644
--- a/packages/hdwallet-native/src/ethereum.ts
+++ b/packages/hdwallet-native/src/ethereum.ts
@@ -4,7 +4,6 @@ import { keccak256, parseTransaction, recoverAddress } from "ethers/lib/utils.js
import * as Isolation from "./crypto/isolation";
import SignerAdapter from "./crypto/isolation/adapters/ethereum";
import { NativeHDWalletBase } from "./native";
-import { buildMessage } from "./util";
export function MixinNativeETHWalletInfo>(Base: TBase) {
// eslint-disable-next-line @typescript-eslint/no-shadow
@@ -142,7 +141,7 @@ export function MixinNativeETHWallet {
if (!signature.startsWith("0x")) signature = `0x${signature}`;
- const digest = keccak256(buildMessage(message));
+ const digest = keccak256(core.buildMessage(message));
return recoverAddress(digest, signature) === address;
}
};
diff --git a/packages/hdwallet-native/src/util.ts b/packages/hdwallet-native/src/util.ts
index 1a7c7862f..a6a0c4e46 100644
--- a/packages/hdwallet-native/src/util.ts
+++ b/packages/hdwallet-native/src/util.ts
@@ -1,5 +1,4 @@
import * as core from "@shapeshiftoss/hdwallet-core";
-import { ethers } from "ethers";
import { BTCScriptType } from "./bitcoin";
import * as Isolation from "./crypto/isolation";
@@ -16,16 +15,3 @@ export async function getKeyPair(
const path = core.addressNListToBIP32(addressNList);
return await wallet.derivePath(path);
}
-
-export function buildMessage(message: ethers.utils.BytesLike): Uint8Array {
- const messageBytes =
- typeof message === "string" && !ethers.utils.isHexString(message)
- ? ethers.utils.toUtf8Bytes(message)
- : ethers.utils.arrayify(message);
-
- return ethers.utils.concat([
- ethers.utils.toUtf8Bytes("\x19Ethereum Signed Message:\n"),
- ethers.utils.toUtf8Bytes(String(messageBytes.length)),
- messageBytes,
- ]);
-}
diff --git a/packages/hdwallet-phantom/package.json b/packages/hdwallet-phantom/package.json
new file mode 100644
index 000000000..238194a75
--- /dev/null
+++ b/packages/hdwallet-phantom/package.json
@@ -0,0 +1,26 @@
+{
+ "name": "@shapeshiftoss/hdwallet-phantom",
+ "version": "1.55.6",
+ "license": "MIT",
+ "publishConfig": {
+ "access": "public"
+ },
+ "main": "dist/index.js",
+ "source": "src/index.ts",
+ "types": "dist/index.d.ts",
+ "scripts": {
+ "build": "tsc --build",
+ "clean": "rm -rf dist node_modules tsconfig.tsbuildinfo",
+ "prepublishOnly": "yarn clean && yarn build"
+ },
+ "dependencies": {
+ "@shapeshiftoss/bitcoinjs-lib": "5.2.0-shapeshift.2",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "base64-js": "^1.5.1",
+ "bitcoinjs-message": "^2.0.0",
+ "lodash": "^4.17.21"
+ },
+ "devDependencies": {
+ "@types/lodash": "^4.14.168"
+ }
+}
diff --git a/packages/hdwallet-phantom/src/adapter.ts b/packages/hdwallet-phantom/src/adapter.ts
new file mode 100644
index 000000000..1a65a5480
--- /dev/null
+++ b/packages/hdwallet-phantom/src/adapter.ts
@@ -0,0 +1,62 @@
+import * as core from "@shapeshiftoss/hdwallet-core";
+
+import { PhantomHDWallet } from "./phantom";
+import { PhantomEvmProvider, PhantomUtxoProvider } from "./types";
+
+declare global {
+ interface Window {
+ phantom?: {
+ ethereum?: PhantomEvmProvider;
+ bitcoin?: PhantomUtxoProvider;
+ // TODO: update with proper types once implemented
+ // https://github.com/anza-xyz/wallet-adapter/blob/3761cd8cc867da39da7c0b070bbf8779402cff36/packages/wallets/phantom/src/adapter.ts#L36
+ solana?: any;
+ };
+ }
+}
+
+export class PhantomAdapter {
+ keyring: core.Keyring;
+
+ private constructor(keyring: core.Keyring) {
+ this.keyring = keyring;
+ }
+
+ public static useKeyring(keyring: core.Keyring) {
+ return new PhantomAdapter(keyring);
+ }
+
+ public async initialize(): Promise {
+ return Object.keys(this.keyring.wallets).length;
+ }
+
+ public async pairDevice(): Promise {
+ const evmProvider = window.phantom?.ethereum;
+ const bitcoinProvider = window.phantom?.bitcoin;
+
+ if (!evmProvider || !bitcoinProvider) {
+ window.open("https://phantom.app/", "_blank");
+ console.error("Please install Phantom!");
+ throw new Error("Phantom provider not found");
+ }
+
+ try {
+ await evmProvider.request?.({ method: "eth_requestAccounts" }).catch(() =>
+ evmProvider.request?.({
+ method: "wallet_requestPermissions",
+ params: [{ eth_accounts: {} }],
+ })
+ );
+ } catch (error) {
+ console.error("Could not get Phantom accounts. ");
+ throw error;
+ }
+ const wallet = new PhantomHDWallet(evmProvider, bitcoinProvider);
+ await wallet.initialize();
+ const deviceID = await wallet.getDeviceID();
+ this.keyring.add(wallet, deviceID);
+ this.keyring.emit(["Phantom", deviceID, core.Events.CONNECT], deviceID);
+
+ return wallet;
+ }
+}
diff --git a/packages/hdwallet-phantom/src/bitcoin.ts b/packages/hdwallet-phantom/src/bitcoin.ts
new file mode 100644
index 000000000..7dd00781e
--- /dev/null
+++ b/packages/hdwallet-phantom/src/bitcoin.ts
@@ -0,0 +1,169 @@
+import * as bitcoin from "@shapeshiftoss/bitcoinjs-lib";
+import * as core from "@shapeshiftoss/hdwallet-core";
+import { BTCInputScriptType } from "@shapeshiftoss/hdwallet-core";
+
+import { PhantomUtxoProvider } from "./types";
+
+export type BtcAccount = {
+ address: string;
+ // Phantom supposedly supports more scriptTypes but in effect, doesn't (currently)
+ // https://github.com/orgs/phantom/discussions/173
+ addressType: BTCInputScriptType.SpendWitness;
+ publicKey: string;
+ purpose: "payment" | "ordinals";
+};
+
+const fromHexString = (hexString: string) => {
+ const bytes = hexString.match(/.{1,2}/g);
+ if (!bytes) throw new Error("Invalid hex string");
+
+ return Uint8Array.from(bytes.map((byte) => parseInt(byte, 16)));
+};
+
+const getNetwork = (coin: string): bitcoin.networks.Network => {
+ switch (coin.toLowerCase()) {
+ case "bitcoin":
+ return bitcoin.networks.bitcoin;
+ default:
+ throw new Error(`Unsupported coin: ${coin}`);
+ }
+};
+
+export const btcGetAccountPaths = (msg: core.BTCGetAccountPaths): Array => {
+ const slip44 = core.slip44ByCoin(msg.coin);
+ if (slip44 === undefined) return [];
+
+ const bip84 = core.segwitNativeAccount(msg.coin, slip44, msg.accountIdx);
+
+ const coinPaths = {
+ bitcoin: [bip84],
+ } as Partial>>;
+
+ let paths: Array = coinPaths[msg.coin.toLowerCase()] || [];
+
+ if (msg.scriptType !== undefined) {
+ paths = paths.filter((path) => {
+ return path.scriptType === msg.scriptType;
+ });
+ }
+
+ return paths;
+};
+
+export async function bitcoinGetAddress(_msg: core.BTCGetAddress, provider: any): Promise {
+ const accounts = await provider.requestAccounts();
+ const paymentAddress = accounts.find((account: BtcAccount) => account.purpose === "payment")?.address;
+
+ return paymentAddress;
+}
+
+async function addInput(psbt: bitcoin.Psbt, input: core.BTCSignTxInput): Promise {
+ switch (input.scriptType) {
+ // Phantom supposedly supports more scriptTypes but in effect, doesn't (currently)
+ // https://github.com/orgs/phantom/discussions/173
+ case BTCInputScriptType.SpendWitness: {
+ psbt.addInput({
+ hash: input.txid,
+ index: input.vout,
+ nonWitnessUtxo: Buffer.from(input.hex, "hex"),
+ });
+
+ break;
+ }
+ default:
+ throw new Error(`Unsupported script type: ${input.scriptType}`);
+ }
+}
+
+async function addOutput(
+ wallet: core.BTCWallet,
+ psbt: bitcoin.Psbt,
+ output: core.BTCSignTxOutput,
+ coin: string
+): Promise {
+ if (!output.amount) throw new Error("Invalid output - missing amount.");
+
+ const address = await (async () => {
+ if (output.address) return output.address;
+
+ if (output.addressNList) {
+ const outputAddress = await wallet.btcGetAddress({ addressNList: output.addressNList, coin, showDisplay: false });
+ if (!outputAddress) throw new Error("Could not get address from wallet");
+ return outputAddress;
+ }
+ })();
+
+ if (!address) throw new Error("Invalid output - no address");
+
+ psbt.addOutput({ address, value: parseInt(output.amount) });
+}
+
+export async function bitcoinSignTx(
+ wallet: core.BTCWallet,
+ msg: core.BTCSignTx,
+ provider: PhantomUtxoProvider
+): Promise {
+ const network = getNetwork(msg.coin);
+
+ const psbt = new bitcoin.Psbt({ network });
+
+ psbt.setVersion(msg.version ?? 2);
+ if (msg.locktime) {
+ psbt.setLocktime(msg.locktime);
+ }
+
+ for (const input of msg.inputs) {
+ await addInput(psbt, input);
+ }
+
+ for (const output of msg.outputs) {
+ await addOutput(wallet, psbt, output, msg.coin);
+ }
+
+ if (msg.opReturnData) {
+ const data = Buffer.from(msg.opReturnData, "utf-8");
+ const embed = bitcoin.payments.embed({ data: [data] });
+ const script = embed.output;
+ if (!script) throw new Error("unable to build OP_RETURN script");
+ psbt.addOutput({ script, value: 0 });
+ }
+
+ const inputsToSign = await Promise.all(
+ msg.inputs.map(async (input, index) => {
+ const address = await wallet.btcGetAddress({
+ addressNList: input.addressNList,
+ coin: msg.coin,
+ showDisplay: false,
+ });
+
+ if (!address) throw new Error("Could not get address from wallet");
+
+ return {
+ address,
+ signingIndexes: [index],
+ sigHash: bitcoin.Transaction.SIGHASH_ALL,
+ };
+ })
+ );
+
+ const signedPsbtHex = await provider.signPSBT(fromHexString(psbt.toHex()), { inputsToSign });
+ const signedPsbt = bitcoin.Psbt.fromBuffer(Buffer.from(signedPsbtHex), { network });
+
+ signedPsbt.finalizeAllInputs();
+
+ const tx = signedPsbt.extractTransaction();
+
+ // If this is a THORChain transaction, validate the vout ordering
+ if (msg.vaultAddress && !core.validateVoutOrdering(msg, tx)) {
+ throw new Error("Improper vout ordering for BTC Thorchain transaction");
+ }
+
+ const signatures = signedPsbt.data.inputs.map((input) =>
+ input.partialSig ? input.partialSig[0].signature.toString("hex") : ""
+ );
+
+ return {
+ signatures,
+ serializedTx: tx.toHex(),
+ };
+}
diff --git a/packages/hdwallet-phantom/src/ethereum.ts b/packages/hdwallet-phantom/src/ethereum.ts
new file mode 100644
index 000000000..ee483f872
--- /dev/null
+++ b/packages/hdwallet-phantom/src/ethereum.ts
@@ -0,0 +1,111 @@
+import * as core from "@shapeshiftoss/hdwallet-core";
+import { ETHSignedMessage } from "@shapeshiftoss/hdwallet-core";
+import { isHexString } from "ethers/lib/utils";
+
+import { PhantomEvmProvider } from "./types";
+
+export function ethGetAccountPaths(msg: core.ETHGetAccountPath): Array {
+ const slip44 = core.slip44ByCoin(msg.coin);
+ if (slip44 === undefined) return [];
+ return [
+ {
+ addressNList: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx, 0, 0],
+ hardenedPath: [0x80000000 + 44, 0x80000000 + slip44, 0x80000000 + msg.accountIdx],
+ relPath: [0, 0],
+ description: "Phantom",
+ },
+ ];
+}
+
+export async function ethSendTx(
+ msg: core.ETHSignTx,
+ phantom: PhantomEvmProvider,
+ from: string
+): Promise {
+ try {
+ const utxBase = {
+ from: from,
+ to: msg.to,
+ value: msg.value,
+ chainId: msg.chainId,
+ data: msg.data,
+ gasLimit: msg.gasLimit,
+ };
+
+ const utx = msg.maxFeePerGas
+ ? {
+ ...utxBase,
+ maxFeePerGas: msg.maxFeePerGas,
+ maxPriorityFeePerGas: msg.maxPriorityFeePerGas,
+ }
+ : { ...utxBase, gasPrice: msg.gasPrice };
+
+ const signedTx = await phantom.request?.({
+ method: "eth_sendTransaction",
+ params: [utx],
+ });
+
+ return { hash: signedTx } as core.ETHTxHash;
+ } catch (error) {
+ console.error(error);
+ return null;
+ }
+}
+
+export async function ethSignMessage(
+ msg: core.ETHSignMessage,
+ phantom: PhantomEvmProvider,
+ address: string
+): Promise {
+ try {
+ if (!isHexString(msg.message)) throw new Error("data is not an hex string");
+ const signedMsg = await phantom.request?.({
+ method: "personal_sign",
+ params: [msg.message, address],
+ });
+
+ return {
+ address: address,
+ signature: signedMsg,
+ } as ETHSignedMessage;
+ } catch (error) {
+ console.error(error);
+ return null;
+ }
+}
+
+export async function ethSignTypedData(
+ msg: core.ETHSignTypedData,
+ phantom: PhantomEvmProvider,
+ address: string
+): Promise {
+ try {
+ const signedMsg = await phantom.request?.({
+ method: "eth_signTypedData_v4",
+ params: [address, JSON.stringify(msg.typedData)],
+ });
+
+ return {
+ address: address,
+ signature: signedMsg,
+ } as ETHSignedMessage;
+ } catch (error) {
+ console.error(error);
+ return null;
+ }
+}
+
+export async function ethGetAddress(phantom: PhantomEvmProvider): Promise {
+ if (!(phantom && phantom.request)) {
+ return null;
+ }
+ try {
+ const ethAccounts = await phantom.request({
+ method: "eth_accounts",
+ });
+ return ethAccounts[0];
+ } catch (error) {
+ console.error(error);
+ return null;
+ }
+}
diff --git a/packages/hdwallet-phantom/src/index.ts b/packages/hdwallet-phantom/src/index.ts
new file mode 100644
index 000000000..ee1fe48d8
--- /dev/null
+++ b/packages/hdwallet-phantom/src/index.ts
@@ -0,0 +1,2 @@
+export * from "./adapter";
+export * from "./phantom";
diff --git a/packages/hdwallet-phantom/src/phantom.test.ts b/packages/hdwallet-phantom/src/phantom.test.ts
new file mode 100644
index 000000000..202df1f20
--- /dev/null
+++ b/packages/hdwallet-phantom/src/phantom.test.ts
@@ -0,0 +1,179 @@
+import * as core from "@shapeshiftoss/hdwallet-core";
+
+import { PhantomHDWallet } from ".";
+import { PhantomUtxoProvider } from "./types";
+
+describe("PhantomHDWallet", () => {
+ let wallet: PhantomHDWallet;
+
+ beforeEach(() => {
+ wallet = new PhantomHDWallet(
+ core.untouchable("PhantomHDWallet:provider"),
+ core.untouchable("PhantomHDWallet:provider")
+ );
+ });
+
+ it("should match the metadata", async () => {
+ expect(wallet.getVendor()).toBe("Phantom");
+ expect(wallet.hasOnDevicePinEntry()).toBe(false);
+ expect(wallet.hasOnDevicePassphrase()).toBe(true);
+ expect(wallet.hasOnDeviceDisplay()).toBe(true);
+ expect(wallet.hasOnDeviceRecovery()).toBe(true);
+ expect(await wallet.ethSupportsNetwork(1)).toBe(true);
+ expect(await wallet.ethSupportsSecureTransfer()).toBe(false);
+ expect(wallet.ethSupportsNativeShapeShift()).toBe(false);
+ expect(await wallet.ethSupportsEIP1559()).toBe(true);
+ expect(wallet.supportsOfflineSigning()).toBe(false);
+ expect(wallet.supportsBip44Accounts()).toBe(false);
+ expect(wallet.supportsBroadcast()).toBe(true);
+ });
+
+ it("should test ethSignMessage", async () => {
+ wallet.evmProvider = {
+ _metamask: {
+ isUnlocked: () => true,
+ },
+ request: jest.fn().mockReturnValue(
+ `Object {
+ "address": "0x73d0385F4d8E00C5e6504C6030F47BF6212736A8",
+ "signature": "0x05f51140905ffa33ffdc57f46b0b8d8fbb1d2a99f8cd843ca27893c01c31351c08b76d83dce412731c846e3b50649724415deb522d00950fbf4f2c1459c2b70b1b",
+ }`
+ ),
+ };
+ const msg = "0x737570657220736563726574206d657373616765"; // super secret message
+ expect(
+ await wallet.ethSignMessage({
+ addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
+ message: msg,
+ })
+ ).toMatchInlineSnapshot(`
+ Object {
+ "address": "O",
+ "signature": "Object {
+ \\"address\\": \\"0x73d0385F4d8E00C5e6504C6030F47BF6212736A8\\",
+ \\"signature\\": \\"0x05f51140905ffa33ffdc57f46b0b8d8fbb1d2a99f8cd843ca27893c01c31351c08b76d83dce412731c846e3b50649724415deb522d00950fbf4f2c1459c2b70b1b\\",
+ }",
+ }
+ `);
+ });
+
+ it("ethSignMessage returns null on error", async () => {
+ wallet.evmProvider = {
+ _metamask: {
+ isUnlocked: () => true,
+ },
+ request: jest.fn().mockRejectedValue(new Error("An Error has occurred")),
+ };
+
+ const msg = "0x737570657220736563726574206d657373616765"; // super secret message
+ const sig = await wallet.ethSignMessage({
+ addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
+ message: msg,
+ });
+
+ expect(sig).toBe(null);
+ });
+
+ it("ethGetAddress returns a valid address", async () => {
+ wallet.evmProvider = {
+ _metamask: {
+ isUnlocked: () => true,
+ },
+ request: jest.fn().mockReturnValue(["0x73d0385F4d8E00C5e6504C6030F47BF6212736A8"]),
+ };
+
+ const address = await wallet.ethGetAddress();
+
+ expect(address).toEqual("0x73d0385F4d8E00C5e6504C6030F47BF6212736A8");
+ });
+ it("btcGetAddress returns a valid address", async () => {
+ wallet.bitcoinProvider = {
+ requestAccounts: jest.fn().mockReturnValue([
+ {
+ purpose: "payment",
+ address: "bc1q9sjm947kn2hz84syykmem7dshvevm8xm5dkrpg",
+ },
+ ]),
+ } as unknown as PhantomUtxoProvider;
+
+ const address = await wallet.btcGetAddress({
+ coin: "Bitcoin",
+ } as core.BTCGetAddress);
+
+ expect(address).toEqual("bc1q9sjm947kn2hz84syykmem7dshvevm8xm5dkrpg");
+ });
+
+ it("ethSendTx returns a valid hash", async () => {
+ wallet.evmProvider = {
+ _metamask: {
+ isUnlocked: () => true,
+ },
+ request: jest.fn().mockReturnValue("0x123"),
+ };
+
+ const hash = await wallet.ethSendTx({
+ addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
+ nonce: "0xDEADBEEF",
+ gasPrice: "0xDEADBEEF",
+ gasLimit: "0xDEADBEEF",
+ to: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ value: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ data: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ chainId: 1,
+ });
+ expect(wallet.evmProvider.request).toHaveBeenCalled();
+ expect(hash).toMatchObject({ hash: "0x123" });
+ });
+ it("ethSendTx returns a valid hash if maxFeePerGas is present in msg", async () => {
+ wallet.evmProvider = {
+ _metamask: {
+ isUnlocked: () => true,
+ },
+ request: jest.fn().mockReturnValue("0x123"),
+ };
+
+ const hash = await wallet.ethSendTx({
+ addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
+ nonce: "0xDEADBEEF",
+ gasLimit: "0xDEADBEEF",
+ maxFeePerGas: "0xDEADBEEF",
+ to: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ value: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ data: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ chainId: 1,
+ });
+ expect(wallet.evmProvider.request).toHaveBeenCalled();
+ expect(hash).toMatchObject({ hash: "0x123" });
+ });
+ it("ethSendTx returns null on error", async () => {
+ wallet.evmProvider = {
+ _metamask: {
+ isUnlocked: () => true,
+ },
+ request: jest.fn().mockRejectedValue(new Error("An Error has occurred")),
+ };
+
+ const hash = await wallet.ethSendTx({
+ addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
+ nonce: "0xDEADBEEF",
+ gasPrice: "0xDEADBEEF",
+ gasLimit: "0xDEADBEEF",
+ to: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ value: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ data: "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEF",
+ chainId: 1,
+ });
+ expect(wallet.evmProvider.request).toHaveBeenCalled();
+ expect(hash).toBe(null);
+ });
+ it("ethVerifyMessage returns true for a valid signature", async () => {
+ expect(
+ await wallet.ethVerifyMessage({
+ address: "0x2068dD92B6690255553141Dfcf00dF308281f763",
+ message: "Hello World",
+ signature:
+ "0x61f1dda82e9c3800e960894396c9ce8164fd1526fccb136c71b88442405f7d09721725629915d10bc7cecfca2818fe76bc5816ed96a1b0cebee9b03b052980131b",
+ })
+ ).toEqual(true);
+ });
+});
diff --git a/packages/hdwallet-phantom/src/phantom.ts b/packages/hdwallet-phantom/src/phantom.ts
new file mode 100644
index 000000000..30c001106
--- /dev/null
+++ b/packages/hdwallet-phantom/src/phantom.ts
@@ -0,0 +1,347 @@
+import * as core from "@shapeshiftoss/hdwallet-core";
+import { BTCInputScriptType } from "@shapeshiftoss/hdwallet-core";
+import Base64 from "base64-js";
+import * as bitcoinMsg from "bitcoinjs-message";
+import { keccak256, recoverAddress } from "ethers/lib/utils.js";
+import _ from "lodash";
+
+import * as btc from "./bitcoin";
+import * as eth from "./ethereum";
+import { PhantomEvmProvider, PhantomUtxoProvider } from "./types";
+
+export function isPhantom(wallet: core.HDWallet): wallet is PhantomHDWallet {
+ return _.isObject(wallet) && (wallet as any)._isPhantom;
+}
+
+export class PhantomHDWalletInfo implements core.HDWalletInfo, core.BTCWalletInfo, core.ETHWalletInfo {
+ readonly _supportsBTCInfo = true;
+ readonly _supportsETHInfo = true;
+
+ evmProvider: PhantomEvmProvider;
+
+ constructor(evmProvider: PhantomEvmProvider) {
+ this.evmProvider = evmProvider;
+ }
+
+ public getVendor(): string {
+ return "Phantom";
+ }
+
+ public hasOnDevicePinEntry(): boolean {
+ return false;
+ }
+
+ public hasOnDevicePassphrase(): boolean {
+ return true;
+ }
+
+ public hasOnDeviceDisplay(): boolean {
+ return true;
+ }
+
+ public hasOnDeviceRecovery(): boolean {
+ return true;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public hasNativeShapeShift(srcCoin: core.Coin, dstCoin: core.Coin): boolean {
+ return false;
+ }
+
+ public supportsBip44Accounts(): boolean {
+ return false;
+ }
+
+ public supportsOfflineSigning(): boolean {
+ return false;
+ }
+
+ public supportsBroadcast(): boolean {
+ return true;
+ }
+
+ public describePath(msg: core.DescribePath): core.PathDescription {
+ switch (msg.coin.toLowerCase()) {
+ case "bitcoin": {
+ const unknown = core.unknownUTXOPath(msg.path, msg.coin, msg.scriptType);
+
+ if (!msg.scriptType) return unknown;
+ if (!this.btcSupportsCoin(msg.coin)) return unknown;
+ if (!this.btcSupportsScriptType(msg.coin, msg.scriptType)) return unknown;
+
+ return core.describeUTXOPath(msg.path, msg.coin, msg.scriptType);
+ }
+ case "ethereum":
+ return core.describeETHPath(msg.path);
+ default:
+ throw new Error("Unsupported path");
+ }
+ }
+
+ /** Ethereum */
+
+ public async ethSupportsNetwork(chainId: number): Promise {
+ return chainId === 1;
+ }
+
+ public async ethGetChainId(): Promise {
+ try {
+ if (!this.evmProvider.request) throw new Error("Provider does not support ethereum.request");
+ // chainId as hex string
+ const chainId: string = await this.evmProvider.request({ method: "eth_chainId" });
+ return parseInt(chainId, 16);
+ } catch (e) {
+ console.error(e);
+ return null;
+ }
+ }
+
+ public async ethSupportsSecureTransfer(): Promise {
+ return false;
+ }
+
+ public ethSupportsNativeShapeShift(): boolean {
+ return false;
+ }
+
+ public async ethSupportsEIP1559(): Promise {
+ return true;
+ }
+
+ public ethGetAccountPaths(msg: core.ETHGetAccountPath): Array {
+ return eth.ethGetAccountPaths(msg);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public ethNextAccountPath(msg: core.ETHAccountPath): core.ETHAccountPath | undefined {
+ throw new Error("Method not implemented");
+ }
+
+ /** Bitcoin */
+
+ public async btcSupportsCoin(coin: core.Coin): Promise {
+ return coin === "bitcoin";
+ }
+
+ public async btcSupportsScriptType(coin: string, scriptType?: core.BTCInputScriptType | undefined): Promise {
+ if (!this.btcSupportsCoin(coin)) return false;
+
+ switch (scriptType) {
+ case core.BTCInputScriptType.SpendWitness:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ public async btcSupportsSecureTransfer(): Promise {
+ return false;
+ }
+
+ public btcSupportsNativeShapeShift(): boolean {
+ return false;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public btcGetAccountPaths(msg: core.BTCGetAccountPaths): Array {
+ return btc.btcGetAccountPaths(msg);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public btcIsSameAccount(msg: core.BTCAccountPath[]): boolean {
+ throw new Error("Method not implemented.");
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public btcNextAccountPath(msg: core.BTCAccountPath): core.BTCAccountPath | undefined {
+ throw new Error("Method not implemented");
+ }
+}
+
+export class PhantomHDWallet extends PhantomHDWalletInfo implements core.HDWallet, core.BTCWallet, core.ETHWallet {
+ readonly _supportsBTC = true;
+ readonly _supportsETH = true;
+ readonly _supportsEthSwitchChain = false;
+ readonly _supportsAvalanche = false;
+ readonly _supportsOptimism = false;
+ readonly _supportsPolygon = true;
+ readonly _supportsGnosis = false;
+ readonly _supportsArbitrum = false;
+ readonly _supportsArbitrumNova = false;
+ readonly _supportsBase = false;
+ readonly _supportsBSC = false;
+ readonly _isPhantom = true;
+
+ evmProvider: PhantomEvmProvider;
+ bitcoinProvider: PhantomUtxoProvider;
+
+ constructor(evmProvider: PhantomEvmProvider, bitcoinProvider: PhantomUtxoProvider) {
+ super(evmProvider);
+ this.evmProvider = evmProvider;
+ this.bitcoinProvider = bitcoinProvider;
+ }
+
+ public async getDeviceID(): Promise {
+ return "phantom:" + (await this.ethGetAddress());
+ }
+
+ async getFeatures(): Promise> {
+ return {};
+ }
+
+ public async getFirmwareVersion(): Promise {
+ return "phantom";
+ }
+
+ public async getModel(): Promise {
+ return "Phantom";
+ }
+
+ public async getLabel(): Promise {
+ return "Phantom";
+ }
+
+ public async isInitialized(): Promise {
+ return true;
+ }
+
+ public async isLocked(): Promise {
+ return !this.evmProvider._metamask.isUnlocked();
+ }
+
+ public async clearSession(): Promise {}
+
+ public async initialize(): Promise {}
+
+ public async ping(msg: core.Ping): Promise {
+ return { msg: msg.msg };
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async sendPin(pin: string): Promise {}
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async sendPassphrase(passphrase: string): Promise {}
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async sendCharacter(charater: string): Promise {}
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async sendWord(word: string): Promise {}
+
+ public async cancel(): Promise {}
+
+ public async wipe(): Promise {}
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async reset(msg: core.ResetDevice): Promise {}
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async recover(msg: core.RecoverDevice): Promise {}
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async loadDevice(msg: core.LoadDevice): Promise {}
+
+ public async disconnect(): Promise {}
+
+ public async getPublicKeys(msg: Array): Promise> {
+ return await Promise.all(
+ msg.map(async (getPublicKey) => {
+ const { coin, scriptType } = getPublicKey;
+
+ // Only p2wpkh effectively supported for now
+ if (coin === "Bitcoin" && scriptType === BTCInputScriptType.SpendWitness) {
+ // Note this is a pubKey, not an xpub, however phantom does not support utxo derivation,
+ // so this functions as an account (xpub) for all intents and purposes
+ const pubKey = await this.btcGetAddress({ coin: "Bitcoin" } as core.BTCGetAddress);
+ return { xpub: pubKey } as core.PublicKey;
+ }
+
+ return null;
+ })
+ );
+ }
+
+ /** Ethereum */
+
+ public async ethGetAddress(): Promise {
+ return eth.ethGetAddress(this.evmProvider);
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ public async ethSignTx(msg: core.ETHSignTx): Promise {
+ throw new Error("Method not implemented");
+ }
+
+ public async ethSendTx(msg: core.ETHSignTx): Promise {
+ const address = await this.ethGetAddress();
+ return address ? eth.ethSendTx(msg, this.evmProvider, address) : null;
+ }
+
+ public async ethSignMessage(msg: core.ETHSignMessage): Promise {
+ const address = await this.ethGetAddress();
+ return address ? eth.ethSignMessage(msg, this.evmProvider, address) : null;
+ }
+
+ async ethSignTypedData(msg: core.ETHSignTypedData): Promise {
+ const address = await this.ethGetAddress();
+ return address ? eth.ethSignTypedData(msg, this.evmProvider, address) : null;
+ }
+
+ public async ethVerifyMessage(msg: core.ETHVerifyMessage): Promise {
+ if (!msg.signature.startsWith("0x")) msg.signature = `0x${msg.signature}`;
+ const digest = keccak256(core.buildMessage(msg.message));
+ return recoverAddress(digest, msg.signature) === msg.address;
+ }
+
+ /** Bitcoin */
+
+ public async btcGetAddress(msg: core.BTCGetAddress): Promise {
+ const value = await (async () => {
+ switch (msg.coin) {
+ case "Bitcoin": {
+ const accounts = await this.bitcoinProvider.requestAccounts();
+ const paymentAddress = accounts.find((account) => account.purpose === "payment")?.address;
+
+ return paymentAddress;
+ }
+ default:
+ return null;
+ }
+ })();
+ if (!value || typeof value !== "string") return null;
+
+ return value;
+ }
+
+ public async btcSignTx(msg: core.BTCSignTx): Promise {
+ const { coin } = msg;
+ switch (coin) {
+ case "Bitcoin":
+ return btc.bitcoinSignTx(this, msg, this.bitcoinProvider);
+ default:
+ return null;
+ }
+ }
+
+ public async btcSignMessage(msg: core.BTCSignMessage): Promise {
+ const { coin } = msg;
+ switch (coin) {
+ case "Bitcoin": {
+ const address = await this.btcGetAddress({ coin } as core.BTCGetAddress);
+ if (!address) throw new Error(`Could not get ${coin} address`);
+ const message = new TextEncoder().encode(msg.message);
+
+ const { signature } = await this.bitcoinProvider.signMessage(address, message);
+ return { signature: core.toHexString(signature), address };
+ }
+ default:
+ return null;
+ }
+ }
+
+ public async btcVerifyMessage(msg: core.BTCVerifyMessage): Promise {
+ const signature = Base64.fromByteArray(core.fromHexString(msg.signature));
+ return bitcoinMsg.verify(msg.message, msg.address, signature);
+ }
+}
diff --git a/packages/hdwallet-phantom/src/types.ts b/packages/hdwallet-phantom/src/types.ts
new file mode 100644
index 000000000..ceaa936f9
--- /dev/null
+++ b/packages/hdwallet-phantom/src/types.ts
@@ -0,0 +1,23 @@
+import { providers } from "ethers";
+
+import { BtcAccount } from "./bitcoin";
+
+export type PhantomEvmProvider = providers.ExternalProvider & {
+ _metamask: {
+ isUnlocked: () => boolean;
+ };
+};
+
+export type PhantomUtxoProvider = providers.ExternalProvider & {
+ requestAccounts: () => Promise;
+ signMessage: (
+ address: string,
+ message: Uint8Array
+ ) => Promise<{
+ signature: Uint8Array;
+ }>;
+ signPSBT(
+ psbt: Uint8Array,
+ options: { inputsToSign: { sigHash?: number | undefined; address: string; signingIndexes: number[] }[] }
+ ): Promise;
+};
diff --git a/packages/hdwallet-phantom/tsconfig.json b/packages/hdwallet-phantom/tsconfig.json
new file mode 100644
index 000000000..0c82f8910
--- /dev/null
+++ b/packages/hdwallet-phantom/tsconfig.json
@@ -0,0 +1,10 @@
+{
+ "extends": "../../tsconfig.json",
+ "compilerOptions": {
+ "rootDir": "src",
+ "outDir": "dist"
+ },
+ "include": ["src/**/*"],
+ "exclude": ["node_modules", "dist", "**/*.test.ts"],
+ "references": [{ "path": "../hdwallet-core" }]
+}
\ No newline at end of file
diff --git a/packages/hdwallet-portis/package.json b/packages/hdwallet-portis/package.json
index 05429184e..08b422d30 100644
--- a/packages/hdwallet-portis/package.json
+++ b/packages/hdwallet-portis/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-portis",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -15,7 +15,7 @@
},
"dependencies": {
"@portis/web3": "3.0.10",
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"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 4218e5c5c..6f2383f1b 100644
--- a/packages/hdwallet-tallyho/package.json
+++ b/packages/hdwallet-tallyho/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-tallyho",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,7 +14,7 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"lodash": "^4.17.21",
"tallyho-onboarding": "^1.0.2"
},
diff --git a/packages/hdwallet-trezor-connect/package.json b/packages/hdwallet-trezor-connect/package.json
index 8ce6ca263..bc7d772a6 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.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,8 +14,8 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
- "@shapeshiftoss/hdwallet-trezor": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
+ "@shapeshiftoss/hdwallet-trezor": "1.55.6",
"@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 868635e0c..004e3575e 100644
--- a/packages/hdwallet-trezor/package.json
+++ b/packages/hdwallet-trezor/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-trezor",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -17,7 +17,7 @@
"dependencies": {
"@ethereumjs/common": "^2.4.0",
"@ethereumjs/tx": "^3.3.0",
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"base64-js": "^1.5.1",
"lodash": "^4.17.21"
},
diff --git a/packages/hdwallet-walletconnect/package.json b/packages/hdwallet-walletconnect/package.json
index b8ce276e2..7e62e6dcf 100644
--- a/packages/hdwallet-walletconnect/package.json
+++ b/packages/hdwallet-walletconnect/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-walletconnect",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -15,7 +15,7 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"@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 20622130f..ccc929665 100644
--- a/packages/hdwallet-walletconnectV2/package.json
+++ b/packages/hdwallet-walletconnectV2/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-walletconnectv2",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -15,7 +15,7 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"@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 57f24e1fe..c1e9b06d8 100644
--- a/packages/hdwallet-xdefi/package.json
+++ b/packages/hdwallet-xdefi/package.json
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-xdefi",
- "version": "1.55.5",
+ "version": "1.55.6",
"license": "MIT",
"publishConfig": {
"access": "public"
@@ -14,7 +14,7 @@
"prepublishOnly": "yarn clean && yarn build"
},
"dependencies": {
- "@shapeshiftoss/hdwallet-core": "1.55.5",
+ "@shapeshiftoss/hdwallet-core": "1.55.6",
"lodash": "^4.17.21"
},
"devDependencies": {