on master help sign in
ux: [WIP] Sign txns with connected wallet
a7d0e3atomholford
package-lock.json+53−53
@@ -8783,46 +8783,46 @@
8783 }
8783 }
8784 },
8784 },
8785 "@walletconnect/browser-utils": {
8785 "@walletconnect/browser-utils": {
8786− "version": "1.5.1",
8786+ "version": "1.5.2",
8787− "resolved": "https://registry.npmjs.org/@walletconnect/browser-utils/-/browser-utils-1.5.1.tgz",
8787+ "resolved": "https://registry.npmjs.org/@walletconnect/browser-utils/-/browser-utils-1.5.2.tgz",
8788− "integrity": "sha512-pH5xnTaFvOsrxgLlazKqFhfiUE0zxmErgcrwV2B4vFKHLf3/j1MPxZmOpnqC/VsMAUNcJr2/xrrHu4O1Jy7rPg==",
8788+ "integrity": "sha512-nP7ktHwYmvHfXIbq7lGPoig8nO7HYi2dWE8UDxBlgNMs4mvzm2jyN6cm0JZ4xh5gO90/gQwbyuU33zLcZGUPhw==",
8789 "requires": {
8789 "requires": {
8790 "@walletconnect/safe-json": "1.0.0",
8790 "@walletconnect/safe-json": "1.0.0",
8791− "@walletconnect/types": "^1.5.1",
8791+ "@walletconnect/types": "^1.5.2",
8792 "@walletconnect/window-getters": "1.0.0",
8792 "@walletconnect/window-getters": "1.0.0",
8793 "@walletconnect/window-metadata": "1.0.0",
8793 "@walletconnect/window-metadata": "1.0.0",
8794 "detect-browser": "5.2.0"
8794 "detect-browser": "5.2.0"
8795 }
8795 }
8796 },
8796 },
8797 "@walletconnect/client": {
8797 "@walletconnect/client": {
8798− "version": "1.5.1",
8798+ "version": "1.5.2",
8799− "resolved": "https://registry.npmjs.org/@walletconnect/client/-/client-1.5.1.tgz",
8799+ "resolved": "https://registry.npmjs.org/@walletconnect/client/-/client-1.5.2.tgz",
8800− "integrity": "sha512-/NODRyToXmtNYfPZF3aPc9VGF1B8C6J+EmKtf4cKhAifir8S2XIWk7zLTHRm9DmSFuDF8hWQhTip14Bovp9WZw==",
8800+ "integrity": "sha512-dAMK4zqNBZ88YpUQxTMt3RCS2ThTwecPmlq3MK76liLwrsGYRfnQ104GHZGI93rZEdcDWX04p5e3NsCXWMXcNw==",
8801 "requires": {
8801 "requires": {
8802− "@walletconnect/core": "^1.5.1",
8802+ "@walletconnect/core": "^1.5.2",
8803− "@walletconnect/iso-crypto": "^1.5.1",
8803+ "@walletconnect/iso-crypto": "^1.5.2",
8804− "@walletconnect/types": "^1.5.1",
8804+ "@walletconnect/types": "^1.5.2",
8805− "@walletconnect/utils": "^1.5.1"
8805+ "@walletconnect/utils": "^1.5.2"
8806 }
8806 }
8807 },
8807 },
8808 "@walletconnect/core": {
8808 "@walletconnect/core": {
8809− "version": "1.5.1",
8809+ "version": "1.5.2",
8810− "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-1.5.1.tgz",
8810+ "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-1.5.2.tgz",
8811− "integrity": "sha512-WGcZS+22395s70C0lAJyc6FnE3F362AZ4S85mGD8JRlRTDiVxZ+nbyaU+6GRLq3MJK2W65Ffw6gMmwniUdVrEw==",
8811+ "integrity": "sha512-uzrIbjzSHdPPeFSqwPYhp/VhyJKUODDc0STt+5R1A2orE1nh9Rb6XqSkBfLkOlf8pdKUObI95Lr0LH9TbSzF/A==",
8812 "requires": {
8812 "requires": {
8813− "@walletconnect/socket-transport": "^1.5.1",
8813+ "@walletconnect/socket-transport": "^1.5.2",
8814− "@walletconnect/types": "^1.5.1",
8814+ "@walletconnect/types": "^1.5.2",
8815− "@walletconnect/utils": "^1.5.1"
8815+ "@walletconnect/utils": "^1.5.2"
8816 }
8816 }
8817 },
8817 },
8818 "@walletconnect/crypto": {
8818 "@walletconnect/crypto": {
8819− "version": "1.0.0",
8819+ "version": "1.0.1",
8820− "resolved": "https://registry.npmjs.org/@walletconnect/crypto/-/crypto-1.0.0.tgz",
8820+ "resolved": "https://registry.npmjs.org/@walletconnect/crypto/-/crypto-1.0.1.tgz",
8821− "integrity": "sha512-G2eQ7xD8q+8fDEtdULlLtGinmuqDTcG5oZ5xGaKkEqDEaHA56B1UV99GvISXbSHGCkFhPFWAokBK05AGQgzZeg==",
8821+ "integrity": "sha512-IgUReNrycIFxkGgq8YT9HsosCkhutakWD9Q411PR0aJfxpEa/VKJeaLRtoz6DvJpztWStwhIHnAbBoOVR72a6g==",
8822 "requires": {
8822 "requires": {
8823 "@walletconnect/encoding": "^1.0.0",
8823 "@walletconnect/encoding": "^1.0.0",
8824 "@walletconnect/environment": "^1.0.0",
8824 "@walletconnect/environment": "^1.0.0",
8825− "@walletconnect/randombytes": "^1.0.0",
8825+ "@walletconnect/randombytes": "^1.0.1",
8826 "aes-js": "^3.1.2",
8826 "aes-js": "^3.1.2",
8827 "hash.js": "^1.1.7"
8827 "hash.js": "^1.1.7"
8828 },
8828 },
@@ -8849,13 +8849,13 @@
8849 "integrity": "sha512-4BwqyWy6KpSvkocSaV7WR3BlZfrxLbJSLkg+j7Gl6pTDE+U55lLhJvQaMuDVazXYxcjBsG09k7UlH7cGiUI5vQ=="
8849 "integrity": "sha512-4BwqyWy6KpSvkocSaV7WR3BlZfrxLbJSLkg+j7Gl6pTDE+U55lLhJvQaMuDVazXYxcjBsG09k7UlH7cGiUI5vQ=="
8850 },
8850 },
8851 "@walletconnect/iso-crypto": {
8851 "@walletconnect/iso-crypto": {
8852− "version": "1.5.1",
8852+ "version": "1.5.2",
8853− "resolved": "https://registry.npmjs.org/@walletconnect/iso-crypto/-/iso-crypto-1.5.1.tgz",
8853+ "resolved": "https://registry.npmjs.org/@walletconnect/iso-crypto/-/iso-crypto-1.5.2.tgz",
8854− "integrity": "sha512-OAak844/EBynQyg/TnoPCajkYw2rsVZOASAh+Bb7U7NMuyJ+xQ37RBLuL/a3BaGXS3t/mpJJ5RuHGzoU8USB+A==",
8854+ "integrity": "sha512-tRd0+AfmOy0nwCqLx7oR3DyrsahgoyOAm/KqKzKu2eawnfG4dSaluUa/PxMjoC5r93K+ka7qmCq4k4m53qYiog==",
8855 "requires": {
8855 "requires": {
8856− "@walletconnect/crypto": "^1.0.0",
8856+ "@walletconnect/crypto": "^1.0.1",
8857− "@walletconnect/types": "^1.5.1",
8857+ "@walletconnect/types": "^1.5.2",
8858− "@walletconnect/utils": "^1.5.1"
8858+ "@walletconnect/utils": "^1.5.2"
8859 }
8859 }
8860 },
8860 },
8861 "@walletconnect/jsonrpc-types": {
8861 "@walletconnect/jsonrpc-types": {
@@ -8881,22 +8881,22 @@
8881 "integrity": "sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw=="
8881 "integrity": "sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw=="
8882 },
8882 },
8883 "@walletconnect/qrcode-modal": {
8883 "@walletconnect/qrcode-modal": {
8884− "version": "1.5.1",
8884+ "version": "1.5.2",
8885− "resolved": "https://registry.npmjs.org/@walletconnect/qrcode-modal/-/qrcode-modal-1.5.1.tgz",
8885+ "resolved": "https://registry.npmjs.org/@walletconnect/qrcode-modal/-/qrcode-modal-1.5.2.tgz",
8886− "integrity": "sha512-eu+CudCdfSRI8nCPGmzTQAFEF/BsqGf9wcE7fL9H8mv5Zpl86gbXKcBHekqr7fgnZ6wmkeDdRK7wLhHL3L6fpw==",
8886+ "integrity": "sha512-ciWh7kfZQ4qX+YYfF6+qVqw1Z0kyITGnzH7K2jEIxgCI5jsKeKoMcIfucSGIODGrM7OWshB/oA19UFTRdj4GFg==",
8887 "requires": {
8887 "requires": {
8888− "@walletconnect/browser-utils": "^1.5.1",
8888+ "@walletconnect/browser-utils": "^1.5.2",
8889 "@walletconnect/mobile-registry": "^1.4.0",
8889 "@walletconnect/mobile-registry": "^1.4.0",
8890− "@walletconnect/types": "^1.5.1",
8890+ "@walletconnect/types": "^1.5.2",
8891 "copy-to-clipboard": "^3.3.1",
8891 "copy-to-clipboard": "^3.3.1",
8892 "preact": "10.4.1",
8892 "preact": "10.4.1",
8893 "qrcode": "1.4.4"
8893 "qrcode": "1.4.4"
8894 }
8894 }
8895 },
8895 },
8896 "@walletconnect/randombytes": {
8896 "@walletconnect/randombytes": {
8897− "version": "1.0.0",
8897+ "version": "1.0.1",
8898− "resolved": "https://registry.npmjs.org/@walletconnect/randombytes/-/randombytes-1.0.0.tgz",
8898+ "resolved": "https://registry.npmjs.org/@walletconnect/randombytes/-/randombytes-1.0.1.tgz",
8899− "integrity": "sha512-vP9HQIzz9PWH+ohQHqXeKZUbSivyTe3Le4c6oQPCExtw2P0ps4jKOyk4UGTxgcN2Rllj8ftPjiYQlQHKHXZuTA==",
8899+ "integrity": "sha512-YJTyq69i0PtxVg7osEpKfvjTaWuAsR49QEcqGKZRKVQWMbGXBZ65fovemK/SRgtiFRv0V8PwsrlKSheqzfPNcg==",
8900 "requires": {
8900 "requires": {
8901 "@walletconnect/encoding": "^1.0.0",
8901 "@walletconnect/encoding": "^1.0.0",
8902 "@walletconnect/environment": "^1.0.0",
8902 "@walletconnect/environment": "^1.0.0",
@@ -8909,12 +8909,12 @@
8909 "integrity": "sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg=="
8909 "integrity": "sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg=="
8910 },
8910 },
8911 "@walletconnect/socket-transport": {
8911 "@walletconnect/socket-transport": {
8912− "version": "1.5.1",
8912+ "version": "1.5.2",
8913− "resolved": "https://registry.npmjs.org/@walletconnect/socket-transport/-/socket-transport-1.5.1.tgz",
8913+ "resolved": "https://registry.npmjs.org/@walletconnect/socket-transport/-/socket-transport-1.5.2.tgz",
8914− "integrity": "sha512-DSjXH539IvCdE2SRB94Jn270x9nJbNZmRRVwuY7KbGXaiU93qVD4QFl/O1+QLmrpdL/zA9L0mH8TWIP6PTGrHA==",
8914+ "integrity": "sha512-eXafL2STkPocpYo0lDTpsQFIQ5ggCw78dXri9kqNhiSwRdLpjswGxt745V37enOXuFumz18MRXp3Og8yc+HIFQ==",
8915 "requires": {
8915 "requires": {
8916− "@walletconnect/types": "^1.5.1",
8916+ "@walletconnect/types": "^1.5.2",
8917− "@walletconnect/utils": "^1.5.1",
8917+ "@walletconnect/utils": "^1.5.2",
8918 "ws": "7.3.0"
8918 "ws": "7.3.0"
8919 },
8919 },
8920 "dependencies": {
8920 "dependencies": {
@@ -8926,19 +8926,19 @@
8926 }
8926 }
8927 },
8927 },
8928 "@walletconnect/types": {
8928 "@walletconnect/types": {
8929− "version": "1.5.1",
8929+ "version": "1.5.2",
8930− "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-1.5.1.tgz",
8930+ "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-1.5.2.tgz",
8931− "integrity": "sha512-e3Tzy4NbNyM5yyLzKLNKRnMq4IZWjH0GsWQRNMl2WCSdssHPgSC4LQlxVtmMZt9NwceeGjmCZb4G25eD6hcbLA=="
8931+ "integrity": "sha512-ygUIqrn+IyANuA3OKLX2GzVB18zUvoRTWX0llKeM0unSlrF7oEs8m5+H5NHLB9sDs00Jae7Eb+JvUaGa/VKIPw=="
8932 },
8932 },
8933 "@walletconnect/utils": {
8933 "@walletconnect/utils": {
8934− "version": "1.5.1",
8934+ "version": "1.5.2",
8935− "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-1.5.1.tgz",
8935+ "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-1.5.2.tgz",
8936− "integrity": "sha512-ME6LvPCH2jB4sCCvtTJc+ztZY7mBCUT+FijDNH/RIU4KM7+E+fhEzRsNcJM3FPREVEJepaZJkjWPmEVnXp2mkA==",
8936+ "integrity": "sha512-3m7Ty7oe/jb2NbYj7IAli+cyqlpg4XZG1xGrzCcQEEG6bkijCyc4qd51amimyh38wPsXp+kq7C4I+WAPBd9TkA==",
8937 "requires": {
8937 "requires": {
8938− "@walletconnect/browser-utils": "^1.5.1",
8938+ "@walletconnect/browser-utils": "^1.5.2",
8939 "@walletconnect/encoding": "^1.0.0",
8939 "@walletconnect/encoding": "^1.0.0",
8940 "@walletconnect/jsonrpc-utils": "^1.0.0",
8940 "@walletconnect/jsonrpc-utils": "^1.0.0",
8941− "@walletconnect/types": "^1.5.1",
8941+ "@walletconnect/types": "^1.5.2",
8942 "bn.js": "4.11.8",
8942 "bn.js": "4.11.8",
8943 "js-sha3": "0.8.0",
8943 "js-sha3": "0.8.0",
8944 "query-string": "6.13.5"
8944 "query-string": "6.13.5"
@@ -10264,7 +10264,7 @@
10264 "dependencies": {
10264 "dependencies": {
10265 "openzeppelin-solidity": {
10265 "openzeppelin-solidity": {
10266 "version": "1.12.0",
10266 "version": "1.12.0",
10267− "resolved": "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-1.12.0.tgz",
10267+ "resolved": false,
10268 "integrity": "sha512-WlorzMXIIurugiSdw121RVD5qA3EfSI7GybTn+/Du0mPNgairjt29NpVTAaH8eLjAeAwlw46y7uQKy0NYem/gA=="
10268 "integrity": "sha512-WlorzMXIIurugiSdw121RVD5qA3EfSI7GybTn+/Du0mPNgairjt29NpVTAaH8eLjAeAwlw46y7uQKy0NYem/gA=="
10269 }
10269 }
10270 }
10270 }
@@ -10310,7 +10310,7 @@
10310 "dependencies": {
10310 "dependencies": {
10311 "openzeppelin-solidity": {
10311 "openzeppelin-solidity": {
10312 "version": "1.12.0",
10312 "version": "1.12.0",
10313− "resolved": "https://registry.npmjs.org/openzeppelin-solidity/-/openzeppelin-solidity-1.12.0.tgz",
10313+ "resolved": false,
10314 "integrity": "sha512-WlorzMXIIurugiSdw121RVD5qA3EfSI7GybTn+/Du0mPNgairjt29NpVTAaH8eLjAeAwlw46y7uQKy0NYem/gA=="
10314 "integrity": "sha512-WlorzMXIIurugiSdw121RVD5qA3EfSI7GybTn+/Du0mPNgairjt29NpVTAaH8eLjAeAwlw46y7uQKy0NYem/gA=="
10315 },
10315 },
10316 "truffle": {
10316 "truffle": {
@@ -28596,9 +28596,9 @@
28596 }
28596 }
28597 },
28597 },
28598 "buffer-from": {
28598 "buffer-from": {
28599− "version": "1.1.1",
28599+ "version": "1.1.2",
28600− "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
28600+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
28601− "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
28601+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
28602 },
28602 },
28603 "camelcase": {
28603 "camelcase": {
28604 "version": "5.3.1",
28604 "version": "5.3.1",
package.json+3−3
@@ -31,8 +31,8 @@
31 "@types/styled-components": "^5.1.10",
31 "@types/styled-components": "^5.1.10",
32 "@types/styled-system": "^5.1.11",
32 "@types/styled-system": "^5.1.11",
33 "@types/styled-system__css": "^5.0.15",
33 "@types/styled-system__css": "^5.0.15",
34− "@walletconnect/client": "^1.5.1",
34+ "@walletconnect/client": "^1.5.2",
35− "@walletconnect/qrcode-modal": "^1.5.1",
35+ "@walletconnect/qrcode-modal": "^1.5.2",
36 "@welldone-software/why-did-you-render": "^3.2.3",
36 "@welldone-software/why-did-you-render": "^3.2.3",
37 "async-retry": "^1.2.3",
37 "async-retry": "^1.2.3",
38 "azimuth-js": "^0.22.1",
38 "azimuth-js": "^0.22.1",
@@ -101,7 +101,7 @@
101 "start": "react-scripts start",
101 "start": "react-scripts start",
102 "build": "react-scripts build",
102 "build": "react-scripts build",
103 "build:ropsten": "REACT_APP_ROPSTEN=true react-scripts build",
103 "build:ropsten": "REACT_APP_ROPSTEN=true react-scripts build",
104− "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!@tlon\/indigo-react)/\" --env=jsdom",
104+ "test": "react-scripts test --transformIgnorePatterns \"node_modules/(?!@tlon/indigo-react)/\" --env=jsdom",
105 "eject": "react-scripts eject",
105 "eject": "react-scripts eject",
106 "checksum": "cd build && find . -exec shasum -a256 {} ';' > ../checksums.txt && cd ..",
106 "checksum": "cd build && find . -exec shasum -a256 {} ';' > ../checksums.txt && cd ..",
107 "zip": "BRIDGE_VERSION=${REACT_APP_BRIDGE_VERSION:-$npm_package_version}; zip -ur bridge-$BRIDGE_VERSION.zip README.md bridge-https.py checksums.txt && cd build && zip -ur ../bridge-$BRIDGE_VERSION.zip ./* && cd ..",
107 "zip": "BRIDGE_VERSION=${REACT_APP_BRIDGE_VERSION:-$npm_package_version}; zip -ur bridge-$BRIDGE_VERSION.zip README.md bridge-https.py checksums.txt && cd build && zip -ur ../bridge-$BRIDGE_VERSION.zip ./* && cd ..",
src/lib/WalletConnect.tsnew file+59
@@ -0,0 +1,59 @@
1+import { ITxData } from '@walletconnect/types';
2+import Tx from 'ethereumjs-tx';
3+import { sanitizeHex } from './utils/address';
4+
5+type SignWalletConnectTransactionArgs = {
6+ txn: Tx;
7+ from: string;
8+ txnSigner: (args: ITxData) => Promise<string>;
9+};
10+
11+const walletConnectSignTransaction = async ({
12+ txn,
13+ from,
14+ txnSigner,
15+}: SignWalletConnectTransactionArgs) => {
16+ console.log(txn);
17+
18+ // example from:
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+
51+ // TODO: update passed in txn with signed data
52+ // txn.v = Buffer.from(payload.v.slice(2), 'hex');
53+ // txn.r = Buffer.from(payload.r.slice(2), 'hex');
54+ // txn.s = Buffer.from(payload.s.slice(2), 'hex');
55+
56+ return txn;
57+};
58+
59+export { walletConnectSignTransaction };
src/lib/txn.js+8
@@ -6,6 +6,7 @@ import retry from 'async-retry';
6import { NETWORK_TYPES } from './network';
6import { NETWORK_TYPES } from './network';
7import { ledgerSignTransaction } from './ledger';
7import { ledgerSignTransaction } from './ledger';
8import { trezorSignTransaction } from './trezor';
8import { trezorSignTransaction } from './trezor';
9+import { walletConnectSignTransaction } from './WalletConnect';
9import { metamaskSignTransaction, FakeMetamaskTransaction } from './metamask';
10import { metamaskSignTransaction, FakeMetamaskTransaction } from './metamask';
10import { addHexPrefix } from './utils/address';
11import { addHexPrefix } from './utils/address';
11import { CHECK_BLOCK_EVERY_MS, WALLET_TYPES } from './constants';
12import { CHECK_BLOCK_EVERY_MS, WALLET_TYPES } from './constants';
@@ -28,6 +29,7 @@ const signTransaction = async ({
28 chainId, // number
29 chainId, // number
29 gasPrice, // string, in gwei
30 gasPrice, // string, in gwei
30 gasLimit, // string | number
31 gasLimit, // string | number
32+ txnSigner, // optionally inject a transaction signing function
31}) => {
33}) => {
32 // TODO: require these in txn object
34 // TODO: require these in txn object
33 nonce = toHex(nonce);
35 nonce = toHex(nonce);
@@ -93,6 +95,12 @@ const signTransaction = async ({
93 await trezorSignTransaction(stx, walletHdPath);
95 await trezorSignTransaction(stx, walletHdPath);
94 } else if (walletType === WALLET_TYPES.METAMASK) {
96 } else if (walletType === WALLET_TYPES.METAMASK) {
95 return metamaskSignTransaction(utx, wallet.address);
97 return metamaskSignTransaction(utx, wallet.address);
98+ } else if (walletType === WALLET_TYPES.WALLET_CONNECT) {
99+ await walletConnectSignTransaction({
100+ txn: stx,
101+ from: wallet.address,
102+ txnSigner,
103+ });
96 } else {
104 } else {
97 stx.sign(wallet.privateKey);
105 stx.sign(wallet.privateKey);
98 }
106 }
src/lib/useEthereumTransaction.js+12
@@ -10,6 +10,7 @@ import {
10 GAS_LIMITS,
10 GAS_LIMITS,
11 DEFAULT_GAS_PRICE_GWEI,
11 DEFAULT_GAS_PRICE_GWEI,
12 PROGRESS_ANIMATION_DELAY_MS,
12 PROGRESS_ANIMATION_DELAY_MS,
13+ WALLET_TYPES,
13} from './constants';
14} from './constants';
14import {
15import {
15 signTransaction,
16 signTransaction,
@@ -23,6 +24,7 @@ import useDeepEqualReference from 'lib/useDeepEqualReference';
23import useGasPrice from 'lib/useGasPrice';
24import useGasPrice from 'lib/useGasPrice';
24import { timeout } from 'lib/timeout';
25import { timeout } from 'lib/timeout';
25import { safeToWei, safeFromWei } from 'lib/lib';
26import { safeToWei, safeFromWei } from 'lib/lib';
27+import { useWalletConnect } from './useWalletConnect';
26
28
27const STATE = {
29const STATE = {
28 NONE: 'NONE',
30 NONE: 'NONE',
@@ -48,6 +50,7 @@ export default function useEthereumTransaction(
48 const { wallet, walletType, walletHdPath } = useWallet();
50 const { wallet, walletType, walletHdPath } = useWallet();
49 const { web3, networkType } = useNetwork();
51 const { web3, networkType } = useNetwork();
50 const { pointCursor } = usePointCursor();
52 const { pointCursor } = usePointCursor();
53+ const { signTransaction: wcSign } = useWalletConnect();
51
54
52 const _web3 = need.web3(web3);
55 const _web3 = need.web3(web3);
53 const _wallet = need.wallet(wallet);
56 const _wallet = need.wallet(wallet);
@@ -107,6 +110,12 @@ export default function useEthereumTransaction(
107 ? unsignedTransactions
110 ? unsignedTransactions
108 : [unsignedTransactions];
111 : [unsignedTransactions];
109
112
113+ // Due to React's Rules of Hooks, optionally inject the
114+ // WC transaction signing function
115+ // https://reactjs.org/docs/hooks-rules.html
116+ const txnSigner =
117+ walletType === WALLET_TYPES.WALLET_CONNECT ? wcSign : undefined;
118+
110 const txns = await Promise.all(
119 const txns = await Promise.all(
111 utxs.map((utx, i) =>
120 utxs.map((utx, i) =>
112 signTransaction({
121 signTransaction({
@@ -119,6 +128,7 @@ export default function useEthereumTransaction(
119 chainId,
128 chainId,
120 gasPrice: gasPrice.toFixed(0),
129 gasPrice: gasPrice.toFixed(0),
121 gasLimit,
130 gasLimit,
131+ txnSigner,
122 })
132 })
123 )
133 )
124 );
134 );
@@ -126,6 +136,7 @@ export default function useEthereumTransaction(
126 setSignedTransactions(txns);
136 setSignedTransactions(txns);
127 setState(STATE.SIGNED);
137 setState(STATE.SIGNED);
128 } catch (error) {
138 } catch (error) {
139+ console.error(error);
129 setError(error);
140 setError(error);
130 }
141 }
131 }, [
142 }, [
@@ -139,6 +150,7 @@ export default function useEthereumTransaction(
139 unsignedTransactions,
150 unsignedTransactions,
140 walletHdPath,
151 walletHdPath,
141 walletType,
152 walletType,
153+ wcSign,
142 ]);
154 ]);
143
155
144 const broadcast = useCallback(async () => {
156 const broadcast = useCallback(async () => {
src/lib/useWalletConnect.ts+37−6
@@ -1,5 +1,7 @@
1import WalletConnect from '@walletconnect/client';
1import WalletConnect from '@walletconnect/client';
2import QRCodeModal from '@walletconnect/qrcode-modal';
2import QRCodeModal from '@walletconnect/qrcode-modal';
3+import { ITxData } from '@walletconnect/types';
4+
3import { useEffect, useState } from 'react';
5import { useEffect, useState } from 'react';
4import { Just } from 'folktale/maybe';
6import { Just } from 'folktale/maybe';
5
7
@@ -58,12 +60,12 @@ export const useWalletConnect = () => {
58 }, []);
60 }, []);
59
61
60 // Behavior
62 // Behavior
61− const connect = () => {
63+ const connect = async () => {
62 if (!connector || connector.connected) {
64 if (!connector || connector.connected) {
63 return;
65 return;
64 }
66 }
65
67
66− connector.createSession();
68+ await connector.createSession();
67 };
69 };
68
70
69 const disconnect = async () => {
71 const disconnect = async () => {
@@ -91,8 +93,6 @@ export const useWalletConnect = () => {
91 walletType: WALLET_TYPES.WALLET_CONNECT,
93 walletType: WALLET_TYPES.WALLET_CONNECT,
92 });
94 });
93
95
94− // Inspired by the MetamaskWallet implementation :)
95− // TODO: We should refactor / unify how we handle wallets
96 const wallet: WalletConnectWallet = {
96 const wallet: WalletConnectWallet = {
97 address,
97 address,
98 };
98 };
@@ -110,6 +110,37 @@ export const useWalletConnect = () => {
110 return connector.connected;
110 return connector.connected;
111 };
111 };
112
112
113+ const signTransaction = async ({
114+ from,
115+ to,
116+ gas,
117+ gasPrice,
118+ value,
119+ data,
120+ nonce,
121+ }: ITxData): Promise<string> => {
122+ return new Promise((resolve, reject) => {
123+ if (!connector || !isConnected()) {
124+ reject(new Error('No connected wallet available for signing'));
125+ return;
126+ }
127+
128+ return connector
129+ .signTransaction({
130+ from,
131+ to,
132+ gas,
133+ gasPrice,
134+ value,
135+ data,
136+ nonce,
137+ })
138+ .then((txHash: string) => resolve(txHash))
139+ .catch((error: Error) => reject(error));
140+ });
141+ };
142+
143+ // Event Handlers
113 const initConnectHandler = () => {
144 const initConnectHandler = () => {
114 if (!connector) {
145 if (!connector) {
115 return;
146 return;
@@ -152,8 +183,6 @@ export const useWalletConnect = () => {
152 throw error;
183 throw error;
153 }
184 }
154
185
155− // TODO: Confirm what should happen on update?
156− // For now, disconnect and logout
157 disconnect();
186 disconnect();
158 });
187 });
159 };
188 };
@@ -185,6 +214,7 @@ export const useWalletConnect = () => {
185 connector.off('connect');
214 connector.off('connect');
186 connector.off('disconnect');
215 connector.off('disconnect');
187 connector.off('session_update');
216 connector.off('session_update');
217+ connector.off('modal_closed');
188 };
218 };
189 // eslint-disable-next-line react-hooks/exhaustive-deps
219 // eslint-disable-next-line react-hooks/exhaustive-deps
190 }, [connector]);
220 }, [connector]);
@@ -198,5 +228,6 @@ export const useWalletConnect = () => {
198 isConnected,
228 isConnected,
199 peerMeta,
229 peerMeta,
200 resetConnector,
230 resetConnector,
231+ signTransaction,
201 };
232 };
202};
233};
src/lib/utils/address.ts+9
@@ -37,3 +37,12 @@ export const eqAddr = (addr0, addr1) =>
37export const publicToAddress = (publicKey: Buffer): string => {
37export const publicToAddress = (publicKey: Buffer): string => {
38 return toHex(pubToAddress(publicKey, true).toString('hex'));
38 return toHex(pubToAddress(publicKey, true).toString('hex'));
39};
39};
40+
41+export function sanitizeHex(hex: string): string {
42+ hex = hex.substring(0, 2) === '0x' ? hex.substring(2) : hex;
43+ if (hex === '') {
44+ return '';
45+ }
46+ hex = hex.length % 2 !== 0 ? '0' + hex : hex;
47+ return '0x' + hex;
48+}