Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: walletconnect #529

Closed
wants to merge 39 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b89366d
feat: init walletconnect
GMSteuart May 7, 2022
d15021b
perf: reduce wallet and adapter code
GMSteuart May 9, 2022
ddd992c
chore: cleanup
GMSteuart May 13, 2022
5d2243e
chore: remove accidentally added tsconfig
GMSteuart May 14, 2022
dc5c6ff
chore: remove unused methods
GMSteuart May 17, 2022
b5c6795
fix: disconnect alias
GMSteuart May 17, 2022
6e40a55
test: WalletConnectWalletInfo
GMSteuart May 18, 2022
1d12a32
test: init integration tests
GMSteuart May 18, 2022
4f8197f
Merge branch 'master' of https://github.com/shapeshift/hdwallet into …
GMSteuart May 18, 2022
32bbd4d
test: all pass
GMSteuart May 18, 2022
998f347
chore: remove added package
GMSteuart May 18, 2022
698781c
chore: cleanup
GMSteuart May 19, 2022
5a44577
docs: add readme
GMSteuart May 25, 2022
72b6038
fix: state syncing
GMSteuart May 25, 2022
dedb026
test: add sandbox
GMSteuart May 25, 2022
26bf49a
apply remaining changes requested in code review.
pastaghost May 26, 2022
dc58d91
Merge branch 'master' of https://github.com/shapeshift/hdwallet into …
pastaghost Jun 2, 2022
d3e6c72
remove incomplete unit test suite
pastaghost Jun 2, 2022
5824896
chore: run linter
pastaghost Jun 2, 2022
da47fd7
fix: add ignore warning directives
pastaghost Jun 2, 2022
d995692
chore(release): publish 1.23.1-alpha.0
pastaghost Jun 2, 2022
18cb5b8
Merge branch 'master' of https://github.com/shapeshift/hdwallet into …
GMSteuart Jun 8, 2022
509762c
chore: bump version and deps
GMSteuart Jun 9, 2022
fececa8
Merge branch 'feature-walletconnect' of github.com:GMSteuart/hdwallet…
GMSteuart Jun 9, 2022
0199553
chore: fix package versions
GMSteuart Jun 9, 2022
4386610
chore: revert package revert
GMSteuart Jun 9, 2022
1a5c742
build: add dev command
GMSteuart Jun 13, 2022
77b2e9a
refactor: config param to provider object
GMSteuart Jun 13, 2022
502290e
chore: run linter
pastaghost Jun 14, 2022
71c4c48
chore(release): publish 1.23.1-alpha.1
pastaghost Jun 14, 2022
6c13441
fix: move this.provider() call to end of initialize()
pastaghost Jun 16, 2022
4d3b5be
chore: run linter
pastaghost Jun 16, 2022
433dcc2
chore(release): publish 1.23.1-alpha.2
pastaghost Jun 16, 2022
c00e3ec
fix: return correct type from ethSendTx
pastaghost Jun 17, 2022
b04feec
chore(release): publish 1.23.1-alpha.3
pastaghost Jun 17, 2022
d3c190a
refactor: set walletconnect provider config in adapter constructor
pastaghost Jun 21, 2022
7a9e82d
fix: fetch ethereum address if previously unset
pastaghost Jun 21, 2022
6a37027
chore(release): publish 1.23.1-alpha.4
pastaghost Jun 21, 2022
4b80468
fix: bump dependency version in hdwallet-sandbox
pastaghost Jun 21, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/sandbox/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ <h4>Select</h4>
<button id="xdefi">Pair XDEFI</button>
<button id="keplr">Pair Keplr</button>
<button id="tallyHo">Pair Tally Ho</button>
<button id="walletConnect">Pair WalletConnect</button>

<select id="keyring" style="height: 100px" size="4"></select>
</div>
Expand Down
27 changes: 27 additions & 0 deletions examples/sandbox/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import * as native from "@shapeshiftoss/hdwallet-native";
import * as portis from "@shapeshiftoss/hdwallet-portis";
import * as tallyHo from "@shapeshiftoss/hdwallet-tallyho";
import * as trezorConnect from "@shapeshiftoss/hdwallet-trezor-connect";
import * as walletConnect from "@shapeshiftoss/hdwallet-walletconnect";
import * as xdefi from "@shapeshiftoss/hdwallet-xdefi";
import $ from "jquery";
import Web3 from "web3";
Expand Down Expand Up @@ -67,6 +68,7 @@ const kkemuAdapter = keepkeyTcp.TCPKeepKeyAdapter.useKeyring(keyring);
const portisAdapter = portis.PortisAdapter.useKeyring(keyring, { portisAppId });
const metaMaskAdapter = metaMask.MetaMaskAdapter.useKeyring(keyring);
const tallyHoAdapter = tallyHo.TallyHoAdapter.useKeyring(keyring);
const walletConnectAdapter = walletConnect.WalletConnectAdapter.useKeyring(keyring);
const xdefiAdapter = xdefi.XDEFIAdapter.useKeyring(keyring);
const keplrAdapter = keplr.KeplrAdapter.useKeyring(keyring);
const nativeAdapter = native.NativeAdapter.useKeyring(keyring, {
Expand Down Expand Up @@ -100,6 +102,7 @@ const $portis = $("#portis");
const $native = $("#native");
const $metaMask = $("#metaMask");
const $tallyHo = $("#tallyHo");
const $walletConnect = $("#walletConnect");
const $xdefi = $("#xdefi");
const $keplr = $("#keplr");
const $keyring = $("#keyring");
Expand Down Expand Up @@ -214,6 +217,24 @@ $tallyHo.on("click", async (e) => {
}
});

$walletConnect.on("click", async (e) => {
e.preventDefault();
try {
const config = {
rpc: {
1: "https://mainnet.infura.io/v3/d734c7eebcdf400185d7eb67322a7e57",
},
};
wallet = await walletConnectAdapter.pairDevice(config);
window["wallet"] = wallet;
let deviceID = "nothing";
deviceID = await wallet.getDeviceID();
$("#keyring select").val(deviceID);
} catch (error) {
console.error(error);
}
});

$xdefi.on("click", async (e) => {
e.preventDefault();
wallet = await xdefiAdapter.pairDevice("testid");
Expand Down Expand Up @@ -314,6 +335,12 @@ async function deviceConnected(deviceId) {
console.error("Could not initialize TallyHoAdapter", e);
}

try {
await walletConnectAdapter.initialize();
} catch (e) {
console.error("Could not initialize WalletConnectAdapter", e);
}

for (const deviceID of Object.keys(keyring.wallets)) {
await deviceConnected(deviceID);
}
Expand Down
3 changes: 2 additions & 1 deletion examples/sandbox/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hdwallet-sandbox",
"version": "1.23.0",
"version": "1.23.1-alpha.4",
"license": "MIT",
"private": true,
"browserslist": "> 0.5%, last 2 versions, not dead",
Expand All @@ -21,6 +21,7 @@
"@shapeshiftoss/hdwallet-portis": "1.23.0",
"@shapeshiftoss/hdwallet-trezor": "1.23.0",
"@shapeshiftoss/hdwallet-trezor-connect": "1.23.0",
"@shapeshiftoss/hdwallet-walletconnect": "^1.23.1-alpha.3",
"@shapeshiftoss/hdwallet-xdefi": "1.23.0",
"bip32": "^2.0.4",
"jquery": "^3.4.1",
Expand Down
20 changes: 10 additions & 10 deletions integration/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/integration",
"version": "1.23.0",
"version": "1.23.1-alpha.4",
"main": "index.js",
"license": "MIT",
"private": true,
Expand All @@ -10,15 +10,15 @@
"dev": "lerna run test --scope integration --parallel --include-filtered-dependencies"
},
"dependencies": {
"@shapeshiftoss/hdwallet-core": "1.23.0",
"@shapeshiftoss/hdwallet-keepkey": "1.23.0",
"@shapeshiftoss/hdwallet-keepkey-nodewebusb": "1.23.0",
"@shapeshiftoss/hdwallet-keepkey-tcp": "1.23.0",
"@shapeshiftoss/hdwallet-ledger": "1.23.0",
"@shapeshiftoss/hdwallet-native": "1.23.0",
"@shapeshiftoss/hdwallet-portis": "1.23.0",
"@shapeshiftoss/hdwallet-trezor": "1.23.0",
"@shapeshiftoss/hdwallet-xdefi": "1.23.0",
"@shapeshiftoss/hdwallet-core": "1.23.1-alpha.4",
"@shapeshiftoss/hdwallet-keepkey": "1.23.1-alpha.4",
"@shapeshiftoss/hdwallet-keepkey-nodewebusb": "1.23.1-alpha.4",
"@shapeshiftoss/hdwallet-keepkey-tcp": "1.23.1-alpha.4",
"@shapeshiftoss/hdwallet-ledger": "1.23.1-alpha.4",
"@shapeshiftoss/hdwallet-native": "1.23.1-alpha.4",
"@shapeshiftoss/hdwallet-portis": "1.23.1-alpha.4",
"@shapeshiftoss/hdwallet-trezor": "1.23.1-alpha.4",
"@shapeshiftoss/hdwallet-xdefi": "1.23.1-alpha.4",
"@types/jest": "^26.0.23",
"fast-json-stable-stringify": "^2.1.0",
"jest": "^26.6.3",
Expand Down
2 changes: 2 additions & 0 deletions integration/src/integration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import * as native from "@shapeshiftoss/hdwallet-native";
import * as portis from "@shapeshiftoss/hdwallet-portis";
import * as tallyHo from "@shapeshiftoss/hdwallet-tallyho";
import * as trezor from "@shapeshiftoss/hdwallet-trezor";
import * as walletconnect from "@shapeshiftoss/hdwallet-walletconnect";
import * as xdefi from "@shapeshiftoss/hdwallet-xdefi";

import { binanceTests } from "./binance";
Expand Down Expand Up @@ -56,6 +57,7 @@ export function integration(suite: WalletSuite): void {
(native.isNative(wallet) ? 1 : 0) +
(metamask.isMetaMask(wallet) ? 1 : 0) +
(tallyHo.isTallyHo(wallet) ? 1 : 0) +
(walletconnect.isWalletConnect(wallet) ? 1 : 0) +
(xdefi.isXDEFI(wallet) ? 1 : 0)
).toEqual(1);
});
Expand Down
3 changes: 3 additions & 0 deletions integration/src/walletconnect.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { integration } from "./integration";
import * as WalletConnect from "./wallets/walletconnect";
integration(WalletConnect);
216 changes: 216 additions & 0 deletions integration/src/wallets/walletconnect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,216 @@
import * as core from "@shapeshiftoss/hdwallet-core";
import * as walletconnect from "@shapeshiftoss/hdwallet-walletconnect";

export function name(): string {
return "WalletConnect";
}

export function createInfo(): core.HDWalletInfo {
return new walletconnect.WalletConnectWalletInfo();
}

export async function createWallet(): Promise<core.HDWallet> {
const accounts = [
"0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8",
"0x8CB8864f185f14e8d7da0000e4a55a09e4156ff6",
"0x4e8d2E3d5FDe8CB80A917e258548268734973f23",
];
const provider = {
request: jest.fn(({ method, params }: any) => {
switch (method) {
case "eth_accounts":
return accounts;
case "personal_sign": {
const [message] = params;

if (message === "48656c6c6f20576f726c64")
return "0x29f7212ecc1c76cea81174af267b67506f754ea8c73f144afa900a0d85b24b21319621aeb062903e856352f38305710190869c3ce5a1425d65ef4fa558d0fc251b";

throw new Error("unknown message");
}
case "eth_sendTransaction": {
const [{ to }] = params;

return `txHash-${to}`;
}
default:
throw new Error(`ethereum: Unkown method ${method}`);
}
}),
bridge: "https://bridge.walletconnect.org",
qrcode: true,
qrcodeModal: {},
qrcodeModalOptions: undefined,
rpc: null,
infuraId: "",
http: null,
wc: {
sendTransaction: jest.fn((msg) => {
const { to } = msg;
return { hash: `txHash-${to}` };
}),
signMessage: jest.fn().mockReturnValue({
address: "0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8",
signature:
"0x29f7212ecc1c76cea81174af267b67506f754ea8c73f144afa900a0d85b24b21319621aeb062903e856352f38305710190869c3ce5a1425d65ef4fa558d0fc251b",
}),
}, // connector
isConnecting: false,
connected: false,
connectCallbacks: [],
rpcUrl: "",
isWalletConnect: true,
connector: {
chainId: 1,
accounts,
connected: true,
},
walletMeta: {
// wc.peerMeta
},
enable: async () => Promise.resolve(accounts),
send: jest.fn(),
onConnect: jest.fn(),
triggerConnect: jest.fn(),
disconnect: jest.fn(), // alias for close
close: jest.fn(),
handleRequest: jest.fn(),
handleOtherRequests: jest.fn(),
handleReadRequests: jest.fn(),
formatResponse: jest.fn(),
getWalletConnector: jest.fn(),
subscribeWalletConnector: jest.fn(),
onDisconnect: jest.fn(),
updateState: jest.fn(),
updateRpcUrl: jest.fn(),
updateHttpConnection: jest.fn(),
sendAsyncPromise: jest.fn(),
};
const wallet = new walletconnect.WalletConnectHDWallet(provider as any);
await wallet.initialize();
return wallet;
}

export function selfTest(get: () => core.HDWallet): void {
let wallet: walletconnect.WalletConnectHDWallet;

beforeAll(async () => {
const w = get() as walletconnect.WalletConnectHDWallet;

if (walletconnect.isWalletConnect(w) && !core.supportsBTC(w) && core.supportsETH(w)) {
wallet = w;
} else {
throw new Error("Wallet is not a WalletConnect");
}
});

it("supports Ethereum mainnet", async () => {
if (!wallet) return;
expect(await wallet.ethSupportsNetwork()).toEqual(true);
});

it("does not support BTC", async () => {
if (!wallet) return;
expect(core.supportsBTC(wallet)).toBe(false);
});

it("does not support Native ShapeShift", async () => {
if (!wallet) return;
expect(wallet.ethSupportsNativeShapeShift()).toEqual(false);
});

it("does not support EIP1559", async () => {
if (!wallet) return;
expect(await wallet.ethSupportsEIP1559()).toEqual(false);
});

it("does not support Secure Transfer", async () => {
if (!wallet) return;
expect(await wallet.ethSupportsSecureTransfer()).toEqual(false);
});

it("uses correct eth bip44 paths", () => {
if (!wallet) return;
[0, 1, 3, 27].forEach((account) => {
const paths = wallet.ethGetAccountPaths({
coin: "Ethereum",
accountIdx: account,
});
expect(paths).toEqual([
{
addressNList: core.bip32ToAddressNList(`m/44'/60'/${account}'/0/0`),
hardenedPath: core.bip32ToAddressNList(`m/44'/60'/${account}'`),
relPath: [0, 0],
description: "WalletConnect",
},
]);
paths.forEach((path) => {
expect(
wallet.describePath({
coin: "Ethereum",
path: path.addressNList,
}).isKnown
).toBeTruthy();
});
});
});

it("can describe ETH paths", () => {
if (!wallet) return;
expect(
wallet.describePath({
path: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
coin: "Ethereum",
})
).toEqual({
verbose: "Ethereum Account #0",
coin: "Ethereum",
isKnown: true,
isPrefork: false,
accountIdx: 0,
wholeAccount: true,
});

expect(
wallet.describePath({
path: core.bip32ToAddressNList("m/44'/60'/3'/0/0"),
coin: "Ethereum",
})
).toEqual({
verbose: "Ethereum Account #3",
coin: "Ethereum",
isKnown: true,
isPrefork: false,
accountIdx: 3,
wholeAccount: true,
});

expect(
wallet.describePath({
path: core.bip32ToAddressNList("m/44'/60'/0'/0/3"),
coin: "Ethereum",
})
).toEqual({
verbose: "m/44'/60'/0'/0/3",
coin: "Ethereum",
isKnown: false,
});
});

it("should return a valid ETH address", async () => {
if (!wallet) return;
expect(await wallet.ethGetAddress()).toEqual("0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8");
});

it("should sign a message", async () => {
if (!wallet) return;
const res = await wallet.ethSignMessage({
addressNList: core.bip32ToAddressNList("m/44'/60'/0'/0/0"),
message: "Hello World",
});
expect(res?.address).toEqual("0x3f2329C9ADFbcCd9A84f52c906E936A42dA18CB8");
expect(res?.signature).toEqual(
"0x29f7212ecc1c76cea81174af267b67506f754ea8c73f144afa900a0d85b24b21319621aeb062903e856352f38305710190869c3ce5a1425d65ef4fa558d0fc251b"
);
});
}
3 changes: 2 additions & 1 deletion integration/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"compilerOptions": {
"rootDir": "src",
"outDir": "dist",
"resolveJsonModule": true
"resolveJsonModule": true,
"types": ["jest"]
},
"include": ["./src/**/*.[ts|json]"],
"exclude": ["node_modules", "dist"]
Expand Down
2 changes: 1 addition & 1 deletion lerna.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"lerna": "3.22.1",
"version": "1.23.0",
"version": "1.23.1-alpha.4",
"npmClient": "yarn",
"useWorkspaces": true,
"command": {
Expand Down
2 changes: 1 addition & 1 deletion packages/hdwallet-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@shapeshiftoss/hdwallet-core",
"version": "1.23.0",
"version": "1.23.1-alpha.4",
"license": "MIT",
"publishConfig": {
"access": "public"
Expand Down
Loading