on master help sign in
ux: sign transactions with connected WC peer
04ba898tomholford
package-lock.json+95−32
@@ -2164,6 +2164,80 @@
2164 }
2164 }
2165 }
2165 }
2166 },
2166 },
2167+ "@ethereumjs/common": {
2168+ "version": "2.4.0",
2169+ "resolved": "https://registry.npmjs.org/@ethereumjs/common/-/common-2.4.0.tgz",
2170+ "integrity": "sha512-UdkhFWzWcJCZVsj1O/H8/oqj/0RVYjLc1OhPjBrQdALAkQHpCp8xXI4WLnuGTADqTdJZww0NtgwG+TRPkXt27w==",
2171+ "requires": {
2172+ "crc-32": "^1.2.0",
2173+ "ethereumjs-util": "^7.1.0"
2174+ },
2175+ "dependencies": {
2176+ "@types/bn.js": {
2177+ "version": "5.1.0",
2178+ "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz",
2179+ "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==",
2180+ "requires": {
2181+ "@types/node": "*"
2182+ }
2183+ },
2184+ "bn.js": {
2185+ "version": "5.2.0",
2186+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
2187+ "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
2188+ },
2189+ "ethereumjs-util": {
2190+ "version": "7.1.0",
2191+ "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz",
2192+ "integrity": "sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==",
2193+ "requires": {
2194+ "@types/bn.js": "^5.1.0",
2195+ "bn.js": "^5.1.2",
2196+ "create-hash": "^1.1.2",
2197+ "ethereum-cryptography": "^0.1.3",
2198+ "ethjs-util": "0.1.6",
2199+ "rlp": "^2.2.4"
2200+ }
2201+ }
2202+ }
2203+ },
2204+ "@ethereumjs/tx": {
2205+ "version": "3.3.0",
2206+ "resolved": "https://registry.npmjs.org/@ethereumjs/tx/-/tx-3.3.0.tgz",
2207+ "integrity": "sha512-yTwEj2lVzSMgE6Hjw9Oa1DZks/nKTWM8Wn4ykDNapBPua2f4nXO3qKnni86O6lgDj5fVNRqbDsD0yy7/XNGDEA==",
2208+ "requires": {
2209+ "@ethereumjs/common": "^2.4.0",
2210+ "ethereumjs-util": "^7.1.0"
2211+ },
2212+ "dependencies": {
2213+ "@types/bn.js": {
2214+ "version": "5.1.0",
2215+ "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.0.tgz",
2216+ "integrity": "sha512-QSSVYj7pYFN49kW77o2s9xTCwZ8F2xLbjLLSEVh8D2F4JUhZtPAGOFLTD+ffqksBx/u4cE/KImFjyhqCjn/LIA==",
2217+ "requires": {
2218+ "@types/node": "*"
2219+ }
2220+ },
2221+ "bn.js": {
2222+ "version": "5.2.0",
2223+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.0.tgz",
2224+ "integrity": "sha512-D7iWRBvnZE8ecXiLj/9wbxH7Tk79fAh8IHaTNq1RWRixsS02W+5qS+iE9yq6RYl0asXx5tw0bLhmT5pIfbSquw=="
2225+ },
2226+ "ethereumjs-util": {
2227+ "version": "7.1.0",
2228+ "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.1.0.tgz",
2229+ "integrity": "sha512-kR+vhu++mUDARrsMMhsjjzPduRVAeundLGXucGRHF3B4oEltOUspfgCVco4kckucj3FMlLaZHUl9n7/kdmr6Tw==",
2230+ "requires": {
2231+ "@types/bn.js": "^5.1.0",
2232+ "bn.js": "^5.1.2",
2233+ "create-hash": "^1.1.2",
2234+ "ethereum-cryptography": "^0.1.3",
2235+ "ethjs-util": "0.1.6",
2236+ "rlp": "^2.2.4"
2237+ }
2238+ }
2239+ }
2240+ },
2167 "@ethersproject/abi": {
2241 "@ethersproject/abi": {
2168 "version": "5.4.0",
2242 "version": "5.4.0",
2169 "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.4.0.tgz",
2243 "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.4.0.tgz",
@@ -10264,7 +10338,7 @@
10264 "dependencies": {
10338 "dependencies": {
10265 "openzeppelin-solidity": {
10339 "openzeppelin-solidity": {
10266 "version": "1.12.0",
10340 "version": "1.12.0",
10267− "resolved": false,
10341+ "resolved": "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-1.12.0.tgz",
10268 "integrity": "sha512-WlorzMXIIurugiSdw121RVD5qA3EfSI7GybTn+/Du0mPNgairjt29NpVTAaH8eLjAeAwlw46y7uQKy0NYem/gA=="
10342 "integrity": "sha512-WlorzMXIIurugiSdw121RVD5qA3EfSI7GybTn+/Du0mPNgairjt29NpVTAaH8eLjAeAwlw46y7uQKy0NYem/gA=="
10269 }
10343 }
10270 }
10344 }
@@ -10310,7 +10384,7 @@
10310 "dependencies": {
10384 "dependencies": {
10311 "openzeppelin-solidity": {
10385 "openzeppelin-solidity": {
10312 "version": "1.12.0",
10386 "version": "1.12.0",
10313− "resolved": false,
10387+ "resolved": "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-1.12.0.tgz",
10314 "integrity": "sha512-WlorzMXIIurugiSdw121RVD5qA3EfSI7GybTn+/Du0mPNgairjt29NpVTAaH8eLjAeAwlw46y7uQKy0NYem/gA=="
10388 "integrity": "sha512-WlorzMXIIurugiSdw121RVD5qA3EfSI7GybTn+/Du0mPNgairjt29NpVTAaH8eLjAeAwlw46y7uQKy0NYem/gA=="
10315 },
10389 },
10316 "truffle": {
10390 "truffle": {
@@ -12911,6 +12985,15 @@
12911 }
12985 }
12912 }
12986 }
12913 },
12987 },
12988+ "crc-32": {
12989+ "version": "1.2.0",
12990+ "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.0.tgz",
12991+ "integrity": "sha512-1uBwHxF+Y/4yF5G48fwnKq6QsIXheor3ZLPT80yGBV1oEUwpPojlEhQbWKVw1VwcTQyMGHK1/XMmTjmlsmTTGA==",
12992+ "requires": {
12993+ "exit-on-epipe": "~1.0.1",
12994+ "printj": "~1.1.0"
12995+ }
12996+ },
12914 "create-ecdh": {
12997 "create-ecdh": {
12915 "version": "4.0.4",
12998 "version": "4.0.4",
12916 "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
12999 "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
@@ -15183,11 +15266,6 @@
15183 }
15266 }
15184 }
15267 }
15185 },
15268 },
15186− "ethereum-common": {
15187− "version": "0.0.18",
15188− "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz",
15189− "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8="
15190− },
15191 "ethereum-cryptography": {
15269 "ethereum-cryptography": {
15192 "version": "0.1.3",
15270 "version": "0.1.3",
15193 "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
15271 "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
@@ -15241,31 +15319,6 @@
15241 "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz",
15319 "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz",
15242 "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA=="
15320 "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA=="
15243 },
15321 },
15244− "ethereumjs-tx": {
15245− "version": "1.3.7",
15246− "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz",
15247− "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==",
15248− "requires": {
15249− "ethereum-common": "^0.0.18",
15250− "ethereumjs-util": "^5.0.0"
15251− },
15252− "dependencies": {
15253− "ethereumjs-util": {
15254− "version": "5.2.1",
15255− "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz",
15256− "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==",
15257− "requires": {
15258− "bn.js": "^4.11.0",
15259− "create-hash": "^1.1.2",
15260− "elliptic": "^6.5.2",
15261− "ethereum-cryptography": "^0.1.3",
15262− "ethjs-util": "^0.1.3",
15263− "rlp": "^2.0.0",
15264− "safe-buffer": "^5.1.1"
15265− }
15266− }
15267− }
15268− },
15269 "ethereumjs-util": {
15322 "ethereumjs-util": {
15270 "version": "7.0.10",
15323 "version": "7.0.10",
15271 "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz",
15324 "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz",
@@ -15598,6 +15651,11 @@
15598 "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
15651 "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
15599 "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
15652 "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
15600 },
15653 },
15654+ "exit-on-epipe": {
15655+ "version": "1.0.1",
15656+ "resolved": "https://registry.npmjs.org/exit-on-epipe/-/exit-on-epipe-1.0.1.tgz",
15657+ "integrity": "sha512-h2z5mrROTxce56S+pnvAV890uu7ls7f1kEvVGJbw1OlFH3/mlJ5bkXu0KRyW94v37zzHPiUd55iLn3DA7TjWpw=="
15658+ },
15601 "expand-brackets": {
15659 "expand-brackets": {
15602 "version": "0.1.5",
15660 "version": "0.1.5",
15603 "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
15661 "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
@@ -28353,6 +28411,11 @@
28353 }
28411 }
28354 }
28412 }
28355 },
28413 },
28414+ "printj": {
28415+ "version": "1.1.2",
28416+ "resolved": "https://registry.npmjs.org/printj/-/printj-1.1.2.tgz",
28417+ "integrity": "sha512-zA2SmoLaxZyArQTOPj5LXecR+RagfPSU5Kw1qP+jkWeNlrq+eJZyY2oS68SU1Z/7/myXM4lo9716laOFAVStCQ=="
28418+ },
28356 "private": {
28419 "private": {
28357 "version": "0.1.8",
28420 "version": "0.1.8",
28358 "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
28421 "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
package.json+1−1
@@ -15,6 +15,7 @@
15 },
15 },
16 "proxy": "http://localhost:4000",
16 "proxy": "http://localhost:4000",
17 "dependencies": {
17 "dependencies": {
18+ "@ethereumjs/tx": "^3.3.0",
18 "@ledgerhq/hw-app-eth": "^6.0.2",
19 "@ledgerhq/hw-app-eth": "^6.0.2",
19 "@ledgerhq/hw-transport-u2f": "^5.36.0-deprecated",
20 "@ledgerhq/hw-transport-u2f": "^5.36.0-deprecated",
20 "@reach/disclosure": "^0.15.0",
21 "@reach/disclosure": "^0.15.0",
@@ -46,7 +47,6 @@
46 "classnames": "^2.2.6",
47 "classnames": "^2.2.6",
47 "copy-to-clipboard": "^3.2.0",
48 "copy-to-clipboard": "^3.2.0",
48 "ethereum-blockies-base64": "^1.0.2",
49 "ethereum-blockies-base64": "^1.0.2",
49− "ethereumjs-tx": "^1.3.7",
50 "ethereumjs-util": "^7.0.10",
50 "ethereumjs-util": "^7.0.10",
51 "file-saver": "^2.0.0",
51 "file-saver": "^2.0.0",
52 "final-form": "^4.18.4",
52 "final-form": "^4.18.4",
src/lib/WalletConnect.ts+11−43
@@ -1,59 +1,27 @@
1import { ITxData } from '@walletconnect/types';
1import { ITxData } from '@walletconnect/types';
2−import Tx from 'ethereumjs-tx';
2+import { Transaction } from '@ethereumjs/tx';
3−import { sanitizeHex } from './utils/address';
3+import { stripHexPrefix } from './utils/address';
4
4
5type SignWalletConnectTransactionArgs = {
5type SignWalletConnectTransactionArgs = {
6− txn: Tx;
7 from: string;
6 from: string;
7+ txn: Transaction;
8 txnSigner: (args: ITxData) => Promise<string>;
8 txnSigner: (args: ITxData) => Promise<string>;
9};
9};
10
10
11const walletConnectSignTransaction = async ({
11const walletConnectSignTransaction = async ({
12− txn,
13 from,
12 from,
13+ txn,
14 txnSigner,
14 txnSigner,
15}: SignWalletConnectTransactionArgs) => {
15}: SignWalletConnectTransactionArgs) => {
16− console.log(txn);
16+ let wcFormattedTx = txn.toJSON();
17−
17+ wcFormattedTx.from = from;
18− // example from:
18+ wcFormattedTx.gas = wcFormattedTx.gasLimit;
19− // https://docs.walletconnect.org/quick-start/dapps/client#sign-transaction-eth_signtransaction
20− // const formattedWCTx = {
21− // from: '0xbc28Ea04101F03aA7a94C1379bc3AB32E65e62d3', // Required
22− // to: '0x89D24A7b4cCB1b6fAA2625Fe562bDd9A23260359', // Required (for non contract deployments)
23− // data: '0x', // Required
24− // gasPrice: '0x02540be400', // Optional
25− // gas: '0x9c40', // Optional
26− // value: '0x00', // Optional
27− // nonce: '0x0114', // Optional
28− // };
29−
30− const txnValue =
31− txn.value.toString('hex') === '' ? '00' : txn.value.toString('hex');
32−
33− const formattedWCTx = {
34− from: from,
35− to: sanitizeHex(txn.to.toString('hex')),
36− data: sanitizeHex(txn.data.toString('hex')),
37− gasPrice: sanitizeHex(txn.gasPrice.toString('hex')),
38− gas: sanitizeHex(txn.gasLimit.toString('hex')),
39− value: sanitizeHex(txnValue),
40− nonce: sanitizeHex(
41− txn.nonce.length === 0 ? '00' : txn.nonce.toString('hex')
42− ),
43− };
44−
45− console.log(formattedWCTx);
46−
47− const sig = await txnSigner(formattedWCTx);
48−
49− console.log(sig);
50
19
51− // TODO: update passed in txn with signed data
20+ const signature = await txnSigner(wcFormattedTx);
52− // txn.v = Buffer.from(payload.v.slice(2), 'hex');
21+ const serializedTx = Buffer.from(stripHexPrefix(signature), 'hex');
53− // txn.r = Buffer.from(payload.r.slice(2), 'hex');
22+ const signedTx = Transaction.fromSerializedTx(serializedTx);
54− // txn.s = Buffer.from(payload.s.slice(2), 'hex');
55
23
56− return txn;
24+ return signedTx;
57};
25};
58
26
59export { walletConnectSignTransaction };
27export { walletConnectSignTransaction };
src/lib/txn.js → src/lib/txn.tsrenamed+13−5
@@ -1,4 +1,5 @@
1−import Tx from 'ethereumjs-tx';
1+import Common, { Chain, Hardfork } from '@ethereumjs/common';
2+import { Transaction } from '@ethereumjs/tx';
2import { toHex } from 'web3-utils';
3import { toHex } from 'web3-utils';
3import { safeFromWei, safeToWei } from './lib';
4import { safeFromWei, safeToWei } from './lib';
4import retry from 'async-retry';
5import retry from 'async-retry';
@@ -36,8 +37,9 @@ const signTransaction = async ({
36 chainId = toHex(chainId);
37 chainId = toHex(chainId);
37 gasPrice = toHex(safeToWei(gasPrice, 'gwei'));
38 gasPrice = toHex(safeToWei(gasPrice, 'gwei'));
38 gasLimit = toHex(gasLimit);
39 gasLimit = toHex(gasLimit);
40+ const from = wallet.address;
39
41
40− const txParams = { nonce, chainId, gasPrice, gasLimit };
42+ const txParams = { nonce, chainId, gasPrice, gasLimit, from };
41
43
42 // NB (jtobin)
44 // NB (jtobin)
43 //
45 //
@@ -84,7 +86,13 @@ const signTransaction = async ({
84
86
85 const utx = Object.assign(txn, signingParams);
87 const utx = Object.assign(txn, signingParams);
86
88
87− const stx = new Tx(utx);
89+ const chain =
90+ networkType === NETWORK_TYPES.ROPSTEN ? Chain.Ropsten : Chain.Mainnet;
91+ const common = new Common({
92+ chain: chain,
93+ hardfork: Hardfork.MuirGlacier,
94+ });
95+ let stx = Transaction.fromTxData(utx, { common, freeze: false });
88
96
89 //TODO should try-catch and display error message to user,
97 //TODO should try-catch and display error message to user,
90 // ie ledger's "pls enable contract data"
98 // ie ledger's "pls enable contract data"
@@ -96,9 +104,9 @@ const signTransaction = async ({
96 } else if (walletType === WALLET_TYPES.METAMASK) {
104 } else if (walletType === WALLET_TYPES.METAMASK) {
97 return metamaskSignTransaction(utx, wallet.address);
105 return metamaskSignTransaction(utx, wallet.address);
98 } else if (walletType === WALLET_TYPES.WALLET_CONNECT) {
106 } else if (walletType === WALLET_TYPES.WALLET_CONNECT) {
99− await walletConnectSignTransaction({
107+ stx = await walletConnectSignTransaction({
108+ from,
100 txn: stx,
109 txn: stx,
101− from: wallet.address,
102 txnSigner,
110 txnSigner,
103 });
111 });
104 } else {
112 } else {
src/lib/useWalletConnect.ts+1−7
@@ -76,13 +76,7 @@ export const useWalletConnect = () => {
76 await connector.killSession();
76 await connector.killSession();
77 };
77 };
78
78
79− type AuthenticateArgs = {
80− hdPath?: string;
81− };
82−
83− const authenticate = async ({
79+ const authenticate = async ({ hdPath = DEFAULT_HD_PATH }) => {
84− hdPath = DEFAULT_HD_PATH,
85− }: AuthenticateArgs) => {
86 if (!(address && connector)) {
80 if (!(address && connector)) {
87 return;
81 return;
88 }
82 }