on master help sign in
Merge pull request #600 from urbit/t/walletconnect

ux: WalletConnect login

commit3dc583fbe7faac53fa09a0445121d407b9523a5d authorfang <github@fang.io> dateMon 16 Aug 2021, 22:59 (5 years ago) parentd68c64632a9379
12 files changed+1013−51
package-lock.json+523−30 package.json+4−2 src/lib/WalletConnect.ts+27 src/lib/authToken.ts+71−15 src/lib/constants.ts+2 src/lib/txn.js → src/lib/txn.ts+20−4 src/lib/types/BridgeWallet.ts+5 src/lib/types/WalletConnectWallet.ts+5 src/lib/useEthereumTransaction.js+12 src/lib/useWalletConnect.ts+238 src/views/Login/Other.js+4 src/views/Login/WalletConnect.tsx+102
package-lock.json+523−30
@@ -2164,6 +2164,80 @@
21642164 }
21652165 }
21662166 },
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+ },
21672241 "@ethersproject/abi": {
21682242 "version": "5.4.0",
21692243 "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.4.0.tgz",
@@ -8782,6 +8856,208 @@
87828856 "eslint-visitor-keys": "^2.0.0"
87838857 }
87848858 },
8859+ "@walletconnect/browser-utils": {
8860+ "version": "1.6.1",
8861+ "resolved": "https://registry.npmjs.org/@walletconnect/browser-utils/-/browser-utils-1.6.1.tgz",
8862+ "integrity": "sha512-73RoyCuOqqK6hrRspkLRPFAsp5/ir9omyBbQygaFmFaCyxFKDKNMmrq/9UZvicqlhNCSutuuOrZizbzZsEVhtA==",
8863+ "requires": {
8864+ "@walletconnect/safe-json": "1.0.0",
8865+ "@walletconnect/types": "^1.6.1",
8866+ "@walletconnect/window-getters": "1.0.0",
8867+ "@walletconnect/window-metadata": "1.0.0",
8868+ "detect-browser": "5.2.0"
8869+ }
8870+ },
8871+ "@walletconnect/client": {
8872+ "version": "1.6.1",
8873+ "resolved": "https://registry.npmjs.org/@walletconnect/client/-/client-1.6.1.tgz",
8874+ "integrity": "sha512-W80gELPzPD2x07OjBGK6LApCCi0uI3YSWAf2c/el5LA3OGLGXG29zVC5TEsK4y1uJwbwoifl1hn6rMhXocrA4Q==",
8875+ "requires": {
8876+ "@walletconnect/core": "^1.6.1",
8877+ "@walletconnect/iso-crypto": "^1.6.1",
8878+ "@walletconnect/types": "^1.6.1",
8879+ "@walletconnect/utils": "^1.6.1"
8880+ }
8881+ },
8882+ "@walletconnect/core": {
8883+ "version": "1.6.1",
8884+ "resolved": "https://registry.npmjs.org/@walletconnect/core/-/core-1.6.1.tgz",
8885+ "integrity": "sha512-rYYsBywbJsULk40szBlh2Xh9z01D/FmkJlfkUeqq6zRLr7HaUm9zSoI9+WaA2yxfVGzw+HMnuukT4UINKZGgPg==",
8886+ "requires": {
8887+ "@walletconnect/socket-transport": "^1.6.1",
8888+ "@walletconnect/types": "^1.6.1",
8889+ "@walletconnect/utils": "^1.6.1"
8890+ }
8891+ },
8892+ "@walletconnect/crypto": {
8893+ "version": "1.0.1",
8894+ "resolved": "https://registry.npmjs.org/@walletconnect/crypto/-/crypto-1.0.1.tgz",
8895+ "integrity": "sha512-IgUReNrycIFxkGgq8YT9HsosCkhutakWD9Q411PR0aJfxpEa/VKJeaLRtoz6DvJpztWStwhIHnAbBoOVR72a6g==",
8896+ "requires": {
8897+ "@walletconnect/encoding": "^1.0.0",
8898+ "@walletconnect/environment": "^1.0.0",
8899+ "@walletconnect/randombytes": "^1.0.1",
8900+ "aes-js": "^3.1.2",
8901+ "hash.js": "^1.1.7"
8902+ },
8903+ "dependencies": {
8904+ "aes-js": {
8905+ "version": "3.1.2",
8906+ "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.1.2.tgz",
8907+ "integrity": "sha512-e5pEa2kBnBOgR4Y/p20pskXI74UEz7de8ZGVo58asOtvSVG5YAbJeELPZxOmt+Bnz3rX753YKhfIn4X4l1PPRQ=="
8908+ }
8909+ }
8910+ },
8911+ "@walletconnect/encoding": {
8912+ "version": "1.0.0",
8913+ "resolved": "https://registry.npmjs.org/@walletconnect/encoding/-/encoding-1.0.0.tgz",
8914+ "integrity": "sha512-4nkJFnS0QF5JdieG/3VPD1/iEWkLSZ14EBInLZ00RWxmC6EMZrzAeHNAWIgm+xP3NK0lqz+7lEsmWGtcl5gYnQ==",
8915+ "requires": {
8916+ "is-typedarray": "1.0.0",
8917+ "typedarray-to-buffer": "3.1.5"
8918+ }
8919+ },
8920+ "@walletconnect/environment": {
8921+ "version": "1.0.0",
8922+ "resolved": "https://registry.npmjs.org/@walletconnect/environment/-/environment-1.0.0.tgz",
8923+ "integrity": "sha512-4BwqyWy6KpSvkocSaV7WR3BlZfrxLbJSLkg+j7Gl6pTDE+U55lLhJvQaMuDVazXYxcjBsG09k7UlH7cGiUI5vQ=="
8924+ },
8925+ "@walletconnect/iso-crypto": {
8926+ "version": "1.6.1",
8927+ "resolved": "https://registry.npmjs.org/@walletconnect/iso-crypto/-/iso-crypto-1.6.1.tgz",
8928+ "integrity": "sha512-BM+5R7HYB4r0xojw+FeSg7DPdxY3/i6Z1tLCD83wRaK+Vs2QUvI+SdmU0OLm9AJmodos/Qrhw3IgZSEtExT9yw==",
8929+ "requires": {
8930+ "@walletconnect/crypto": "^1.0.1",
8931+ "@walletconnect/types": "^1.6.1",
8932+ "@walletconnect/utils": "^1.6.1"
8933+ }
8934+ },
8935+ "@walletconnect/jsonrpc-types": {
8936+ "version": "1.0.0",
8937+ "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-types/-/jsonrpc-types-1.0.0.tgz",
8938+ "integrity": "sha512-11QXNq5H1PKZk7bP8SxgmCw3HRaDuPOVE+wObqEvmhc7OWYUZqfuaaMb+OXGRSOHL3sbC+XHfdeCxFTMXSFyng==",
8939+ "requires": {
8940+ "keyvaluestorage-interface": "^1.0.0"
8941+ }
8942+ },
8943+ "@walletconnect/jsonrpc-utils": {
8944+ "version": "1.0.0",
8945+ "resolved": "https://registry.npmjs.org/@walletconnect/jsonrpc-utils/-/jsonrpc-utils-1.0.0.tgz",
8946+ "integrity": "sha512-qUHbKUK6sHeHn67qtHZoLoYk5hS6x1arTPjKDRkY93/6Fx+ZmNIpdm1owX3l6aYueyegJ7mz43FpvYHUqJ8xcw==",
8947+ "requires": {
8948+ "@walletconnect/environment": "^1.0.0",
8949+ "@walletconnect/jsonrpc-types": "^1.0.0"
8950+ }
8951+ },
8952+ "@walletconnect/mobile-registry": {
8953+ "version": "1.4.0",
8954+ "resolved": "https://registry.npmjs.org/@walletconnect/mobile-registry/-/mobile-registry-1.4.0.tgz",
8955+ "integrity": "sha512-ZtKRio4uCZ1JUF7LIdecmZt7FOLnX72RPSY7aUVu7mj7CSfxDwUn6gBuK6WGtH+NZCldBqDl5DenI5fFSvkKYw=="
8956+ },
8957+ "@walletconnect/qrcode-modal": {
8958+ "version": "1.6.1",
8959+ "resolved": "https://registry.npmjs.org/@walletconnect/qrcode-modal/-/qrcode-modal-1.6.1.tgz",
8960+ "integrity": "sha512-CCw7fdnkqMK/NX1J2ji+PS8z0VNKC9xFCvG4rp+rZENyA+LHBgeviteD60dZW9nl/kEKvSwMQLSI82L8To8ZGg==",
8961+ "requires": {
8962+ "@walletconnect/browser-utils": "^1.6.1",
8963+ "@walletconnect/mobile-registry": "^1.4.0",
8964+ "@walletconnect/types": "^1.6.1",
8965+ "copy-to-clipboard": "^3.3.1",
8966+ "preact": "10.4.1",
8967+ "qrcode": "1.4.4"
8968+ }
8969+ },
8970+ "@walletconnect/randombytes": {
8971+ "version": "1.0.1",
8972+ "resolved": "https://registry.npmjs.org/@walletconnect/randombytes/-/randombytes-1.0.1.tgz",
8973+ "integrity": "sha512-YJTyq69i0PtxVg7osEpKfvjTaWuAsR49QEcqGKZRKVQWMbGXBZ65fovemK/SRgtiFRv0V8PwsrlKSheqzfPNcg==",
8974+ "requires": {
8975+ "@walletconnect/encoding": "^1.0.0",
8976+ "@walletconnect/environment": "^1.0.0",
8977+ "randombytes": "^2.1.0"
8978+ }
8979+ },
8980+ "@walletconnect/safe-json": {
8981+ "version": "1.0.0",
8982+ "resolved": "https://registry.npmjs.org/@walletconnect/safe-json/-/safe-json-1.0.0.tgz",
8983+ "integrity": "sha512-QJzp/S/86sUAgWY6eh5MKYmSfZaRpIlmCJdi5uG4DJlKkZrHEF7ye7gA+VtbVzvTtpM/gRwO2plQuiooIeXjfg=="
8984+ },
8985+ "@walletconnect/socket-transport": {
8986+ "version": "1.6.1",
8987+ "resolved": "https://registry.npmjs.org/@walletconnect/socket-transport/-/socket-transport-1.6.1.tgz",
8988+ "integrity": "sha512-dn1eBO3SrgIUpBo8geKCvAUe7pPg/3qO6KRibj7cF+kY+u2hNId0W79UaZmHFbX9TUVZHg+oYBKonydv8ozUAw==",
8989+ "requires": {
8990+ "@walletconnect/types": "^1.6.1",
8991+ "@walletconnect/utils": "^1.6.1",
8992+ "ws": "7.5.3"
8993+ },
8994+ "dependencies": {
8995+ "ws": {
8996+ "version": "7.5.3",
8997+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
8998+ "integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg=="
8999+ }
9000+ }
9001+ },
9002+ "@walletconnect/types": {
9003+ "version": "1.6.1",
9004+ "resolved": "https://registry.npmjs.org/@walletconnect/types/-/types-1.6.1.tgz",
9005+ "integrity": "sha512-seqL/ONP0iRNVEPbbl0NVCSWTPym4NiU2R/MPx9zK63dTH6lgR5Kp7QRfz+EWCoP6SCPr9vtyhQ0CMl3/qdCmw=="
9006+ },
9007+ "@walletconnect/utils": {
9008+ "version": "1.6.1",
9009+ "resolved": "https://registry.npmjs.org/@walletconnect/utils/-/utils-1.6.1.tgz",
9010+ "integrity": "sha512-gi/7YKOEmA2hbirzj5MVVkgpIq2TI8iI4qqGUMtSZYHKoU170UzmML3IYPRL6mEBz6Jv77mDOp60JsRMzWdsxA==",
9011+ "requires": {
9012+ "@walletconnect/browser-utils": "^1.6.1",
9013+ "@walletconnect/encoding": "^1.0.0",
9014+ "@walletconnect/jsonrpc-utils": "^1.0.0",
9015+ "@walletconnect/types": "^1.6.1",
9016+ "bn.js": "4.11.8",
9017+ "js-sha3": "0.8.0",
9018+ "query-string": "6.13.5"
9019+ },
9020+ "dependencies": {
9021+ "bn.js": {
9022+ "version": "4.11.8",
9023+ "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.11.8.tgz",
9024+ "integrity": "sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA=="
9025+ },
9026+ "js-sha3": {
9027+ "version": "0.8.0",
9028+ "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz",
9029+ "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q=="
9030+ },
9031+ "query-string": {
9032+ "version": "6.13.5",
9033+ "resolved": "https://registry.npmjs.org/query-string/-/query-string-6.13.5.tgz",
9034+ "integrity": "sha512-svk3xg9qHR39P3JlHuD7g3nRnyay5mHbrPctEBDUxUkHRifPHXJDhBUycdCC0NBjXoDf44Gb+IsOZL1Uwn8M/Q==",
9035+ "requires": {
9036+ "decode-uri-component": "^0.2.0",
9037+ "split-on-first": "^1.0.0",
9038+ "strict-uri-encode": "^2.0.0"
9039+ }
9040+ },
9041+ "strict-uri-encode": {
9042+ "version": "2.0.0",
9043+ "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
9044+ "integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
9045+ }
9046+ }
9047+ },
9048+ "@walletconnect/window-getters": {
9049+ "version": "1.0.0",
9050+ "resolved": "https://registry.npmjs.org/@walletconnect/window-getters/-/window-getters-1.0.0.tgz",
9051+ "integrity": "sha512-xB0SQsLaleIYIkSsl43vm8EwETpBzJ2gnzk7e0wMF3ktqiTGS6TFHxcprMl5R44KKh4tCcHCJwolMCaDSwtAaA=="
9052+ },
9053+ "@walletconnect/window-metadata": {
9054+ "version": "1.0.0",
9055+ "resolved": "https://registry.npmjs.org/@walletconnect/window-metadata/-/window-metadata-1.0.0.tgz",
9056+ "integrity": "sha512-9eFvmJxIKCC3YWOL97SgRkKhlyGXkrHwamfechmqszbypFspaSk+t2jQXAEU7YClHF6Qjw5eYOmy1//zFi9/GA==",
9057+ "requires": {
9058+ "@walletconnect/window-getters": "^1.0.0"
9059+ }
9060+ },
87859061 "@webassemblyjs/ast": {
87869062 "version": "1.9.0",
87879063 "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
@@ -11508,12 +11784,31 @@
1150811784 "ieee754": "^1.1.13"
1150911785 }
1151011786 },
11787+ "buffer-alloc": {
11788+ "version": "1.2.0",
11789+ "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
11790+ "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
11791+ "requires": {
11792+ "buffer-alloc-unsafe": "^1.1.0",
11793+ "buffer-fill": "^1.0.0"
11794+ }
11795+ },
11796+ "buffer-alloc-unsafe": {
11797+ "version": "1.1.0",
11798+ "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
11799+ "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
11800+ },
1151111801 "buffer-compare": {
1151211802 "version": "1.1.1",
1151311803 "resolved": "https://registry.npmjs.org/buffer-compare/-/buffer-compare-1.1.1.tgz",
1151411804 "integrity": "sha1-W+e+hTr4kZjR9N3AkNHWakiu9ZY=",
1151511805 "optional": true
1151611806 },
11807+ "buffer-fill": {
11808+ "version": "1.0.0",
11809+ "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
11810+ "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw="
11811+ },
1151711812 "buffer-from": {
1151811813 "version": "1.1.0",
1151911814 "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.0.tgz",
@@ -12690,6 +12985,15 @@
1269012985 }
1269112986 }
1269212987 },
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+ },
1269312997 "create-ecdh": {
1269412998 "version": "4.0.4",
1269512999 "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
@@ -13508,6 +13812,11 @@
1350813812 "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
1350913813 "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
1351013814 },
13815+ "detect-browser": {
13816+ "version": "5.2.0",
13817+ "resolved": "https://registry.npmjs.org/detect-browser/-/detect-browser-5.2.0.tgz",
13818+ "integrity": "sha512-tr7XntDAu50BVENgQfajMLzacmSe34D+qZc4zjnniz0ZVuw/TZcLcyxHQjYpJTM36sGEkZZlYLnIM1hH7alTMA=="
13819+ },
1351113820 "detect-indent": {
1351213821 "version": "4.0.0",
1351313822 "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-4.0.0.tgz",
@@ -13571,6 +13880,11 @@
1357113880 "randombytes": "^2.0.0"
1357213881 }
1357313882 },
13883+ "dijkstrajs": {
13884+ "version": "1.0.2",
13885+ "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.2.tgz",
13886+ "integrity": "sha512-QV6PMaHTCNmKSeP6QoXhVTw9snc9VD8MulTT0Bd99Pacp4SS1cjcrYPgBPmibqKVtMJJfqC6XvOXgPMEEPH/fg=="
13887+ },
1357413888 "dir-glob": {
1357513889 "version": "3.0.1",
1357613890 "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
@@ -14952,11 +15266,6 @@
1495215266 }
1495315267 }
1495415268 },
14955− "ethereum-common": {
14956− "version": "0.0.18",
14957− "resolved": "https://registry.npmjs.org/ethereum-common/-/ethereum-common-0.0.18.tgz",
14958− "integrity": "sha1-L9w1dvIykDNYl26znaeDIT/5Uj8="
14959− },
1496015269 "ethereum-cryptography": {
1496115270 "version": "0.1.3",
1496215271 "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz",
@@ -15010,31 +15319,6 @@
1501015319 "resolved": "https://registry.npmjs.org/ethereumjs-common/-/ethereumjs-common-1.5.2.tgz",
1501115320 "integrity": "sha512-hTfZjwGX52GS2jcVO6E2sx4YuFnf0Fhp5ylo4pEPhEffNln7vS59Hr5sLnp3/QCazFLluuBZ+FZ6J5HTp0EqCA=="
1501215321 },
15013− "ethereumjs-tx": {
15014− "version": "1.3.7",
15015− "resolved": "https://registry.npmjs.org/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz",
15016− "integrity": "sha512-wvLMxzt1RPhAQ9Yi3/HKZTn0FZYpnsmQdbKYfUUpi4j1SEIcbkd9tndVjcPrufY3V7j2IebOpC00Zp2P/Ay2kA==",
15017− "requires": {
15018− "ethereum-common": "^0.0.18",
15019− "ethereumjs-util": "^5.0.0"
15020− },
15021− "dependencies": {
15022− "ethereumjs-util": {
15023− "version": "5.2.1",
15024− "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-5.2.1.tgz",
15025− "integrity": "sha512-v3kT+7zdyCm1HIqWlLNrHGqHGLpGYIhjeHxQjnDXjLT2FyGJDsd3LWMYUo7pAFRrk86CR3nUJfhC81CCoJNNGQ==",
15026− "requires": {
15027− "bn.js": "^4.11.0",
15028− "create-hash": "^1.1.2",
15029− "elliptic": "^6.5.2",
15030− "ethereum-cryptography": "^0.1.3",
15031− "ethjs-util": "^0.1.3",
15032− "rlp": "^2.0.0",
15033− "safe-buffer": "^5.1.1"
15034− }
15035− }
15036− }
15037− },
1503815322 "ethereumjs-util": {
1503915323 "version": "7.0.10",
1504015324 "resolved": "https://registry.npmjs.org/ethereumjs-util/-/ethereumjs-util-7.0.10.tgz",
@@ -15367,6 +15651,11 @@
1536715651 "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
1536815652 "integrity": "sha1-BjJjj42HfMghB9MKD/8aF8uhzQw="
1536915653 },
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+ },
1537015659 "expand-brackets": {
1537115660 "version": "0.1.5",
1537215661 "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
@@ -22707,6 +22996,11 @@
2270722996 "json-buffer": "3.0.0"
2270822997 }
2270922998 },
22999+ "keyvaluestorage-interface": {
23000+ "version": "1.0.0",
23001+ "resolved": "https://registry.npmjs.org/keyvaluestorage-interface/-/keyvaluestorage-interface-1.0.0.tgz",
23002+ "integrity": "sha512-8t6Q3TclQ4uZynJY9IGr2+SsIGwK9JHcO6ootkHCGA0CrQCRy+VkouYNO2xicET6b9al7QKzpebNow+gkpCL8g=="
23003+ },
2271023004 "killable": {
2271123005 "version": "1.0.1",
2271223006 "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
@@ -26371,6 +26665,11 @@
2637126665 "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
2637226666 "optional": true
2637326667 },
26668+ "pngjs": {
26669+ "version": "3.4.0",
26670+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-3.4.0.tgz",
26671+ "integrity": "sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w=="
26672+ },
2637426673 "pnglib": {
2637526674 "version": "0.0.1",
2637626675 "resolved": "https://registry.npmjs.org/pnglib/-/pnglib-0.0.1.tgz",
@@ -28044,6 +28343,11 @@
2804428343 }
2804528344 }
2804628345 },
28346+ "preact": {
28347+ "version": "10.4.1",
28348+ "resolved": "https://registry.npmjs.org/preact/-/preact-10.4.1.tgz",
28349+ "integrity": "sha512-WKrRpCSwL2t3tpOOGhf2WfTpcmbpxaWtDbdJdKdjd0aEiTkvOmS4NBkG6kzlaAHI9AkQ3iVqbFWM3Ei7mZ4o1Q=="
28350+ },
2804728351 "prelude-ls": {
2804828352 "version": "1.1.2",
2804928353 "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
@@ -28107,6 +28411,11 @@
2810728411 }
2810828412 }
2810928413 },
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+ },
2811028419 "private": {
2811128420 "version": "0.1.8",
2811228421 "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@@ -28322,6 +28631,185 @@
2832228631 "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
2832328632 "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
2832428633 },
28634+ "qrcode": {
28635+ "version": "1.4.4",
28636+ "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.4.4.tgz",
28637+ "integrity": "sha512-oLzEC5+NKFou9P0bMj5+v6Z40evexeE29Z9cummZXZ9QXyMr3lphkURzxjXgPJC5azpxcshoDWV1xE46z+/c3Q==",
28638+ "requires": {
28639+ "buffer": "^5.4.3",
28640+ "buffer-alloc": "^1.2.0",
28641+ "buffer-from": "^1.1.1",
28642+ "dijkstrajs": "^1.0.1",
28643+ "isarray": "^2.0.1",
28644+ "pngjs": "^3.3.0",
28645+ "yargs": "^13.2.4"
28646+ },
28647+ "dependencies": {
28648+ "ansi-regex": {
28649+ "version": "4.1.0",
28650+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
28651+ "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg=="
28652+ },
28653+ "ansi-styles": {
28654+ "version": "3.2.1",
28655+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
28656+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
28657+ "requires": {
28658+ "color-convert": "^1.9.0"
28659+ }
28660+ },
28661+ "buffer-from": {
28662+ "version": "1.1.2",
28663+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
28664+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
28665+ },
28666+ "camelcase": {
28667+ "version": "5.3.1",
28668+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
28669+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
28670+ },
28671+ "cliui": {
28672+ "version": "5.0.0",
28673+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
28674+ "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
28675+ "requires": {
28676+ "string-width": "^3.1.0",
28677+ "strip-ansi": "^5.2.0",
28678+ "wrap-ansi": "^5.1.0"
28679+ }
28680+ },
28681+ "color-convert": {
28682+ "version": "1.9.3",
28683+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
28684+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
28685+ "requires": {
28686+ "color-name": "1.1.3"
28687+ }
28688+ },
28689+ "color-name": {
28690+ "version": "1.1.3",
28691+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
28692+ "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
28693+ },
28694+ "emoji-regex": {
28695+ "version": "7.0.3",
28696+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
28697+ "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA=="
28698+ },
28699+ "find-up": {
28700+ "version": "3.0.0",
28701+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
28702+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
28703+ "requires": {
28704+ "locate-path": "^3.0.0"
28705+ }
28706+ },
28707+ "is-fullwidth-code-point": {
28708+ "version": "2.0.0",
28709+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
28710+ "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
28711+ },
28712+ "isarray": {
28713+ "version": "2.0.5",
28714+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
28715+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
28716+ },
28717+ "locate-path": {
28718+ "version": "3.0.0",
28719+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
28720+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
28721+ "requires": {
28722+ "p-locate": "^3.0.0",
28723+ "path-exists": "^3.0.0"
28724+ }
28725+ },
28726+ "p-limit": {
28727+ "version": "2.3.0",
28728+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
28729+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
28730+ "requires": {
28731+ "p-try": "^2.0.0"
28732+ }
28733+ },
28734+ "p-locate": {
28735+ "version": "3.0.0",
28736+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
28737+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
28738+ "requires": {
28739+ "p-limit": "^2.0.0"
28740+ }
28741+ },
28742+ "p-try": {
28743+ "version": "2.2.0",
28744+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
28745+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
28746+ },
28747+ "require-main-filename": {
28748+ "version": "2.0.0",
28749+ "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
28750+ "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
28751+ },
28752+ "string-width": {
28753+ "version": "3.1.0",
28754+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
28755+ "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
28756+ "requires": {
28757+ "emoji-regex": "^7.0.1",
28758+ "is-fullwidth-code-point": "^2.0.0",
28759+ "strip-ansi": "^5.1.0"
28760+ }
28761+ },
28762+ "strip-ansi": {
28763+ "version": "5.2.0",
28764+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
28765+ "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
28766+ "requires": {
28767+ "ansi-regex": "^4.1.0"
28768+ }
28769+ },
28770+ "wrap-ansi": {
28771+ "version": "5.1.0",
28772+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
28773+ "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
28774+ "requires": {
28775+ "ansi-styles": "^3.2.0",
28776+ "string-width": "^3.0.0",
28777+ "strip-ansi": "^5.0.0"
28778+ }
28779+ },
28780+ "y18n": {
28781+ "version": "4.0.3",
28782+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
28783+ "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ=="
28784+ },
28785+ "yargs": {
28786+ "version": "13.3.2",
28787+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
28788+ "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
28789+ "requires": {
28790+ "cliui": "^5.0.0",
28791+ "find-up": "^3.0.0",
28792+ "get-caller-file": "^2.0.1",
28793+ "require-directory": "^2.1.1",
28794+ "require-main-filename": "^2.0.0",
28795+ "set-blocking": "^2.0.0",
28796+ "string-width": "^3.0.0",
28797+ "which-module": "^2.0.0",
28798+ "y18n": "^4.0.0",
28799+ "yargs-parser": "^13.1.2"
28800+ }
28801+ },
28802+ "yargs-parser": {
28803+ "version": "13.1.2",
28804+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
28805+ "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
28806+ "requires": {
28807+ "camelcase": "^5.0.0",
28808+ "decamelize": "^1.2.0"
28809+ }
28810+ }
28811+ }
28812+ },
2832528813 "qs": {
2832628814 "version": "6.7.0",
2832728815 "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
@@ -31790,6 +32278,11 @@
3179032278 }
3179132279 }
3179232280 },
32281+ "split-on-first": {
32282+ "version": "1.1.0",
32283+ "resolved": "https://registry.npmjs.org/split-on-first/-/split-on-first-1.1.0.tgz",
32284+ "integrity": "sha512-43ZssAJaMusuKWL8sKUBQXHWOpq8d6CfN/u1p4gUzfJkM05C8rxTmYrkIPTXapZpORA6LkkzcUulJ8FqA7Uudw=="
32285+ },
3179332286 "split-string": {
3179432287 "version": "3.1.0",
3179532288 "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
package.json+4−2
@@ -15,6 +15,7 @@
1515 },
1616 "proxy": "http://localhost:4000",
1717 "dependencies": {
18+ "@ethereumjs/tx": "^3.3.0",
1819 "@ledgerhq/hw-app-eth": "^6.0.2",
1920 "@ledgerhq/hw-transport-u2f": "^5.36.0-deprecated",
2021 "@reach/disclosure": "^0.15.0",
@@ -31,6 +32,8 @@
3132 "@types/styled-components": "^5.1.10",
3233 "@types/styled-system": "^5.1.11",
3334 "@types/styled-system__css": "^5.0.15",
35+ "@walletconnect/client": "^1.6.1",
36+ "@walletconnect/qrcode-modal": "^1.6.1",
3437 "@welldone-software/why-did-you-render": "^3.2.3",
3538 "async-retry": "^1.2.3",
3639 "azimuth-js": "^0.22.1",
@@ -44,7 +47,6 @@
4447 "classnames": "^2.2.6",
4548 "copy-to-clipboard": "^3.2.0",
4649 "ethereum-blockies-base64": "^1.0.2",
47− "ethereumjs-tx": "^1.3.7",
4850 "ethereumjs-util": "^7.0.10",
4951 "file-saver": "^2.0.0",
5052 "final-form": "^4.18.4",
@@ -99,7 +101,7 @@
99101 "start": "react-scripts start",
100102 "build": "react-scripts build",
101103 "build:ropsten": "REACT_APP_ROPSTEN=true react-scripts build",
102− "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",
103105 "eject": "react-scripts eject",
104106 "checksum": "cd build && find . -exec shasum -a256 {} ';' > ../checksums.txt && cd ..",
105107 "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+27
@@ -0,0 +1,27 @@
1+import { ITxData } from '@walletconnect/types';
2+import { Transaction } from '@ethereumjs/tx';
3+import { stripHexPrefix } from './utils/address';
4+
5+type SignWalletConnectTransactionArgs = {
6+ from: string;
7+ txn: Transaction;
8+ txnSigner: (args: ITxData) => Promise<string>;
9+};
10+
11+const walletConnectSignTransaction = async ({
12+ from,
13+ txn,
14+ txnSigner,
15+}: SignWalletConnectTransactionArgs) => {
16+ let wcFormattedTx = txn.toJSON();
17+ wcFormattedTx.from = from;
18+ wcFormattedTx.gas = wcFormattedTx.gasLimit;
19+
20+ const signature = await txnSigner(wcFormattedTx);
21+ const serializedTx = Buffer.from(stripHexPrefix(signature), 'hex');
22+ const signedTx = Transaction.fromSerializedTx(serializedTx);
23+
24+ return signedTx;
25+};
26+
27+export { walletConnectSignTransaction };
src/lib/authToken.ts+71−15
@@ -1,9 +1,12 @@
11import { crypto } from 'bitcoinjs-lib';
22import { ecdsaSign } from 'secp256k1';
3+import Web3 from 'web3';
4+import WalletConnect from '@walletconnect/client';
35
46import { WALLET_TYPES } from './constants';
57import { ledgerSignMessage } from './ledger';
68import { trezorSignMessage } from './trezor';
9+import BridgeWallet from './types/BridgeWallet';
710
811const MESSAGE = 'Bridge Authentication Token';
912
@@ -22,25 +25,78 @@ function signMessage(privateKey: Buffer) {
2225 return ethSignature;
2326}
2427
25−export const getAuthToken = async ({
26− wallet,
27− walletType,
28− walletHdPath,
29− web3,
30−}) => {
31− if (walletType === WALLET_TYPES.METAMASK) {
32− return web3.eth.personal.sign(MESSAGE, wallet.address, '');
33− }
34− if (walletType === WALLET_TYPES.LEDGER) {
35− return ledgerSignMessage(MESSAGE, walletHdPath);
36− }
37− if (walletType === WALLET_TYPES.TREZOR) {
38− return trezorSignMessage(MESSAGE, walletHdPath);
39− }
28+type MetamaskAuthTokenArgs = {
29+ address: string;
30+ web3: Web3;
31+ walletType: symbol;
32+};
33+
34+type LedgerAuthTokenArgs = {
35+ walletHdPath: string;
36+ walletType: symbol;
37+};
38+
39+type TrezorAuthTokenArgs = LedgerAuthTokenArgs;
40+
41+type WalletConnectAuthTokenArgs = {
42+ address: string;
43+ connector: WalletConnect;
44+ walletType: symbol;
45+};
46+
47+type DefaultAuthTokenArgs = {
48+ wallet: BridgeWallet;
49+ walletType?: symbol;
50+};
51+
52+type GetAuthTokenArgs =
53+ | MetamaskAuthTokenArgs
54+ | LedgerAuthTokenArgs
55+ | TrezorAuthTokenArgs
56+ | WalletConnectAuthTokenArgs
57+ | DefaultAuthTokenArgs;
4058
59+const getMetamaskAuthToken = ({ address, web3 }: MetamaskAuthTokenArgs) => {
60+ return web3.eth.personal.sign(MESSAGE, address, '');
61+};
62+
63+const getLedgerAuthToken = ({ walletHdPath }: LedgerAuthTokenArgs) => {
64+ return ledgerSignMessage(MESSAGE, walletHdPath);
65+};
66+
67+const getTrezorAuthToken = ({ walletHdPath }: TrezorAuthTokenArgs) => {
68+ return trezorSignMessage(MESSAGE, walletHdPath);
69+};
70+
71+const getWalletConnectAuthToken = ({
72+ address,
73+ connector,
74+}: WalletConnectAuthTokenArgs) => {
75+ return connector.signPersonalMessage([MESSAGE, address]);
76+};
77+
78+const getDefaultAuthToken = ({ wallet }: DefaultAuthTokenArgs) => {
4179 const signature = signMessage(wallet.privateKey);
4280
4381 const token = `0x${Buffer.from(signature).toString('hex')}`;
4482
4583 return token;
4684};
85+
86+export const getAuthToken = async ({
87+ walletType,
88+ ...args
89+}: GetAuthTokenArgs) => {
90+ switch (walletType) {
91+ case WALLET_TYPES.METAMASK:
92+ return getMetamaskAuthToken(args);
93+ case WALLET_TYPES.LEDGER:
94+ return getLedgerAuthToken(args);
95+ case WALLET_TYPES.TREZOR:
96+ return getTrezorAuthToken(args);
97+ case WALLET_TYPES.WALLET_CONNECT:
98+ return getWalletConnectAuthToken(args);
99+ default:
100+ return getDefaultAuthToken(args);
101+ }
102+};
src/lib/constants.ts+2
@@ -87,12 +87,14 @@ const WALLET_TYPES = {
8787 PRIVATE_KEY: Symbol('PRIVATE_KEY'),
8888 KEYSTORE: Symbol('KEYSTORE'),
8989 METAMASK: Symbol('METAMASK'),
90+ WALLET_CONNECT: Symbol('WALLET_CONNECT'),
9091};
9192
9293const NONCUSTODIAL_WALLETS = new Set([
9394 WALLET_TYPES.METAMASK,
9495 WALLET_TYPES.TREZOR,
9596 WALLET_TYPES.LEDGER,
97+ WALLET_TYPES.WALLET_CONNECT,
9698]);
9799
98100export {
src/lib/txn.js → src/lib/txn.tsrenamed+20−4
@@ -1,4 +1,5 @@
1−import Tx from 'ethereumjs-tx';
1+import Common, { Chain, Hardfork } from '@ethereumjs/common';
2+import { Transaction } from '@ethereumjs/tx';
23import { toHex } from 'web3-utils';
34import { safeFromWei, safeToWei } from './lib';
45import retry from 'async-retry';
@@ -6,6 +7,7 @@ import retry from 'async-retry';
67import { NETWORK_TYPES } from './network';
78import { ledgerSignTransaction } from './ledger';
89import { trezorSignTransaction } from './trezor';
10+import { walletConnectSignTransaction } from './WalletConnect';
911import { metamaskSignTransaction, FakeMetamaskTransaction } from './metamask';
1012import { addHexPrefix } from './utils/address';
1113import { CHECK_BLOCK_EVERY_MS, WALLET_TYPES } from './constants';
@@ -28,14 +30,16 @@ const signTransaction = async ({
2830 chainId, // number
2931 gasPrice, // string, in gwei
3032 gasLimit, // string | number
33+ txnSigner, // optionally inject a transaction signing function
3134}) => {
3235 // TODO: require these in txn object
3336 nonce = toHex(nonce);
3437 chainId = toHex(chainId);
3538 gasPrice = toHex(safeToWei(gasPrice, 'gwei'));
3639 gasLimit = toHex(gasLimit);
40+ const from = wallet.address;
3741
38− const txParams = { nonce, chainId, gasPrice, gasLimit };
42+ const txParams = { nonce, chainId, gasPrice, gasLimit, from };
3943
4044 // NB (jtobin)
4145 //
@@ -82,7 +86,13 @@ const signTransaction = async ({
8286
8387 const utx = Object.assign(txn, signingParams);
8488
85− 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 });
8696
8797 //TODO should try-catch and display error message to user,
8898 // ie ledger's "pls enable contract data"
@@ -93,8 +103,14 @@ const signTransaction = async ({
93103 await trezorSignTransaction(stx, walletHdPath);
94104 } else if (walletType === WALLET_TYPES.METAMASK) {
95105 return metamaskSignTransaction(utx, wallet.address);
106+ } else if (walletType === WALLET_TYPES.WALLET_CONNECT) {
107+ stx = await walletConnectSignTransaction({
108+ from,
109+ txn: stx,
110+ txnSigner,
111+ });
96112 } else {
97− stx.sign(wallet.privateKey);
113+ stx = stx.sign(wallet.privateKey);
98114 }
99115
100116 return stx;
src/lib/types/BridgeWallet.tsnew file+5
@@ -0,0 +1,5 @@
1+import { BIP32Interface } from 'bitcoinjs-lib';
2+
3+export default interface BridgeWallet extends BIP32Interface {
4+ address: string;
5+}
src/lib/types/WalletConnectWallet.tsnew file+5
@@ -0,0 +1,5 @@
1+type WalletConnectWallet = {
2+ address: string;
3+};
4+
5+export default WalletConnectWallet;
src/lib/useEthereumTransaction.js+12
@@ -10,6 +10,7 @@ import {
1010 GAS_LIMITS,
1111 DEFAULT_GAS_PRICE_GWEI,
1212 PROGRESS_ANIMATION_DELAY_MS,
13+ WALLET_TYPES,
1314} from './constants';
1415import {
1516 signTransaction,
@@ -23,6 +24,7 @@ import useDeepEqualReference from 'lib/useDeepEqualReference';
2324import useGasPrice from 'lib/useGasPrice';
2425import { timeout } from 'lib/timeout';
2526import { safeToWei, safeFromWei } from 'lib/lib';
27+import { useWalletConnect } from './useWalletConnect';
2628
2729const STATE = {
2830 NONE: 'NONE',
@@ -48,6 +50,7 @@ export default function useEthereumTransaction(
4850 const { wallet, walletType, walletHdPath } = useWallet();
4951 const { web3, networkType } = useNetwork();
5052 const { pointCursor } = usePointCursor();
53+ const { signTransaction: wcSign } = useWalletConnect();
5154
5255 const _web3 = need.web3(web3);
5356 const _wallet = need.wallet(wallet);
@@ -107,6 +110,12 @@ export default function useEthereumTransaction(
107110 ? unsignedTransactions
108111 : [unsignedTransactions];
109112
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+
110119 const txns = await Promise.all(
111120 utxs.map((utx, i) =>
112121 signTransaction({
@@ -119,6 +128,7 @@ export default function useEthereumTransaction(
119128 chainId,
120129 gasPrice: gasPrice.toFixed(0),
121130 gasLimit,
131+ txnSigner,
122132 })
123133 )
124134 );
@@ -126,6 +136,7 @@ export default function useEthereumTransaction(
126136 setSignedTransactions(txns);
127137 setState(STATE.SIGNED);
128138 } catch (error) {
139+ console.error('error signing txs', error);
129140 setError(error);
130141 }
131142 }, [
@@ -139,6 +150,7 @@ export default function useEthereumTransaction(
139150 unsignedTransactions,
140151 walletHdPath,
141152 walletType,
153+ wcSign,
142154 ]);
143155
144156 const broadcast = useCallback(async () => {
src/lib/useWalletConnect.tsnew file+238
@@ -0,0 +1,238 @@
1+import WalletConnect from '@walletconnect/client';
2+import QRCodeModal from '@walletconnect/qrcode-modal';
3+import { ITxData } from '@walletconnect/types';
4+
5+import { useEffect, useMemo, useState } from 'react';
6+import { Just } from 'folktale/maybe';
7+
8+import { useWallet } from 'store/wallet';
9+import { getAuthToken } from './authToken';
10+import { WALLET_TYPES } from './constants';
11+import WalletConnectWallet from './types/WalletConnectWallet';
12+
13+type PeerMeta = {
14+ description: string;
15+ icons?: string[];
16+ name: string;
17+ url: string;
18+};
19+
20+type ConnectEvent = {
21+ event: 'connect';
22+ params: [
23+ {
24+ accounts: string[];
25+ chainId: number;
26+ peerId: string;
27+ peerMeta: PeerMeta;
28+ }
29+ ];
30+};
31+
32+export const useWalletConnect = () => {
33+ const { setWallet, setAuthToken, resetWallet } = useWallet();
34+ const [connector, setConnector] = useState<WalletConnect | null>(null);
35+ const [address, setAddress] = useState<string | null>(null);
36+ const [peerMeta, setPeerMeta] = useState<PeerMeta | null>(null);
37+
38+ const resetConnector = () => {
39+ const newConnector = new WalletConnect({
40+ bridge: 'https://bridge.walletconnect.org',
41+ qrcodeModal: QRCodeModal,
42+ });
43+
44+ setConnector(newConnector);
45+
46+ // restore state from cached connection
47+ if (newConnector.accounts.length > 0) {
48+ setAddress(newConnector.accounts[0]);
49+ }
50+
51+ if (newConnector.peerMeta) {
52+ setPeerMeta(newConnector.peerMeta);
53+ }
54+ };
55+
56+ // Init connector
57+ useEffect(() => {
58+ resetConnector();
59+ // eslint-disable-next-line react-hooks/exhaustive-deps
60+ }, []);
61+
62+ // Behavior
63+ const connect = async () => {
64+ if (!connector || connector.connected) {
65+ return;
66+ }
67+
68+ await connector.createSession();
69+ };
70+
71+ const disconnect = async () => {
72+ if (!connector) {
73+ return;
74+ }
75+
76+ await connector.killSession();
77+ };
78+
79+ const authenticate = async () => {
80+ if (!(address && connector)) {
81+ return;
82+ }
83+
84+ const authToken = await getAuthToken({
85+ address,
86+ connector,
87+ walletType: WALLET_TYPES.WALLET_CONNECT,
88+ });
89+
90+ const wallet: WalletConnectWallet = {
91+ address,
92+ };
93+
94+ setAuthToken(Just(authToken));
95+ setWallet(Just(wallet));
96+ };
97+
98+ const isConnected = () => {
99+ if (!connector) {
100+ return false;
101+ }
102+
103+ return connector.connected;
104+ };
105+
106+ const peerIcon = useMemo(() => {
107+ if (!peerMeta?.icons) {
108+ return null;
109+ }
110+
111+ // Some peers return a list of empty string(s) :)
112+ const iconCandidates = peerMeta.icons.filter(pm => pm !== '');
113+
114+ return iconCandidates.length > 0 ? iconCandidates[0] : null;
115+ }, [peerMeta]);
116+
117+ const signTransaction = async ({
118+ from,
119+ to,
120+ gas,
121+ gasPrice,
122+ value,
123+ data,
124+ nonce,
125+ }: ITxData): Promise<string> => {
126+ return new Promise((resolve, reject) => {
127+ if (!connector || !isConnected()) {
128+ reject(new Error('No connected wallet available for signing'));
129+ return;
130+ }
131+
132+ return connector
133+ .signTransaction({
134+ from,
135+ to,
136+ gas,
137+ gasPrice,
138+ value,
139+ data,
140+ nonce,
141+ })
142+ .then((txHash: string) => resolve(txHash))
143+ .catch((error: Error) => reject(error));
144+ });
145+ };
146+
147+ // Event Handlers
148+ const initConnectHandler = () => {
149+ if (!connector) {
150+ return;
151+ }
152+
153+ connector.on('connect', async (error, payload: ConnectEvent) => {
154+ if (error) {
155+ throw error;
156+ }
157+
158+ const address = payload.params[0].accounts[0];
159+ setAddress(address);
160+ setPeerMeta(payload.params[0].peerMeta);
161+ });
162+ };
163+
164+ const initDisconnectHandler = () => {
165+ if (!connector) {
166+ return;
167+ }
168+
169+ connector.on('disconnect', (error, _payload) => {
170+ if (error) {
171+ throw error;
172+ }
173+
174+ setAddress(null);
175+ setPeerMeta(null);
176+ resetWallet();
177+ });
178+ };
179+
180+ const initSessionUpdateHandler = () => {
181+ if (!connector) {
182+ return;
183+ }
184+
185+ connector.on('session_update', (error, payload) => {
186+ if (error) {
187+ throw error;
188+ }
189+
190+ disconnect();
191+ });
192+ };
193+
194+ const initModalClosedHandler = () => {
195+ if (!connector) {
196+ return;
197+ }
198+
199+ connector.on('modal_closed', () => {
200+ resetWallet();
201+ resetConnector();
202+ });
203+ };
204+
205+ // Init and clean up
206+ useEffect(() => {
207+ if (!connector) {
208+ return;
209+ }
210+
211+ initConnectHandler();
212+ initDisconnectHandler();
213+ initSessionUpdateHandler();
214+ initModalClosedHandler();
215+
216+ return () => {
217+ // Clean up listeners
218+ connector.off('connect');
219+ connector.off('disconnect');
220+ connector.off('session_update');
221+ connector.off('modal_closed');
222+ };
223+ // eslint-disable-next-line react-hooks/exhaustive-deps
224+ }, [connector]);
225+
226+ return {
227+ address,
228+ authenticate,
229+ connect,
230+ connector,
231+ disconnect,
232+ isConnected,
233+ peerIcon,
234+ peerMeta,
235+ resetConnector,
236+ signTransaction,
237+ };
238+};
src/views/Login/Other.js+4
@@ -11,6 +11,7 @@ import Ledger from './Ledger';
1111import Metamask from './Metamask';
1212import Trezor from './Trezor';
1313import Mnemonic from './Mnemonic';
14+import WalletConnect from './WalletConnect';
1415
1516const NAMES = {
1617 PRIVATE_KEY: 'PRIVATE_KEY',
@@ -19,6 +20,7 @@ const NAMES = {
1920 TREZOR: 'TREZOR',
2021 METAMASK: 'METAMASK',
2122 MNEMONIC: 'MNEMONIC',
23+ WALLET_CONNECT: 'WALLET_CONNECT',
2224};
2325
2426const VIEWS = {
@@ -28,6 +30,7 @@ const VIEWS = {
2830 [NAMES.TREZOR]: Trezor,
2931 [NAMES.METAMASK]: Metamask,
3032 [NAMES.MNEMONIC]: Mnemonic,
33+ [NAMES.WALLET_CONNECT]: WalletConnect,
3134};
3235
3336const OPTIONS = [
@@ -37,6 +40,7 @@ const OPTIONS = [
3740 { text: 'Trezor', value: NAMES.TREZOR },
3841 { text: 'Ethereum Private Key', value: NAMES.PRIVATE_KEY },
3942 { text: 'Ethereum Keystore', value: NAMES.KEYSTORE },
43+ { text: 'WalletConnect', value: NAMES.WALLET_CONNECT },
4044];
4145
4246const isHardware = name => !![NAMES.TREZOR, NAMES.LEDGER].find(n => n === name);
src/views/Login/WalletConnect.tsxnew file+102
@@ -0,0 +1,102 @@
1+import { Image } from '@tlon/indigo-react';
2+import BridgeForm from 'form/BridgeForm';
3+import FormError from 'form/FormError';
4+import SubmitButton from 'form/SubmitButton';
5+import { Grid, Text as LegacyText } from 'indigo-react';
6+import { WALLET_TYPES } from 'lib/constants';
7+import useLoginView from 'lib/useLoginView';
8+import { useWalletConnect } from 'lib/useWalletConnect';
9+import { abbreviateAddress } from 'lib/utils/address';
10+import { ForwardButton, RestartButton } from 'components/Buttons';
11+
12+const WalletConnectLogin = ({ className, goHome }) => {
13+ useLoginView(WALLET_TYPES.WALLET_CONNECT);
14+
15+ const {
16+ address,
17+ authenticate,
18+ connect,
19+ connector,
20+ disconnect,
21+ isConnected,
22+ peerIcon,
23+ peerMeta,
24+ } = useWalletConnect();
25+
26+ const onSubmit = async () => {
27+ await authenticate();
28+ return;
29+ };
30+
31+ return (
32+ connector && (
33+ <>
34+ <Grid className={className}>
35+ {!isConnected() && (
36+ <Grid.Item full as={LegacyText} className="f6 gray4 mb3">
37+ Note that WalletConnect is a young protocol, not all wallets may
38+ work fully
39+ </Grid.Item>
40+ )}
41+
42+ {isConnected() && peerMeta && (
43+ <Grid.Item full className="f6 gray5 mt3 mb3">
44+ <Grid>
45+ <Grid.Item style={{ gridArea: 'auto / 3 / auto / 5' }}>
46+ {peerIcon ? (
47+ <Image src={peerIcon} />
48+ ) : (
49+ <LegacyText>Icon Unavailable</LegacyText>
50+ )}
51+ </Grid.Item>
52+ <Grid.Item
53+ className={'flex-col align-center justify-center'}
54+ style={{ gridArea: 'auto / 6 / auto / 11' }}>
55+ <LegacyText as="div">{peerMeta.name}</LegacyText>
56+ <LegacyText as="div">
57+ {address ? abbreviateAddress(address) : null}
58+ </LegacyText>
59+ <RestartButton
60+ as="a"
61+ className={'gray3'}
62+ onClick={disconnect}>
63+ disconnect
64+ </RestartButton>
65+ </Grid.Item>
66+ </Grid>
67+ </Grid.Item>
68+ )}
69+
70+ <BridgeForm onSubmit={onSubmit} afterSubmit={goHome}>
71+ {({ handleSubmit, submitting }) => (
72+ <>
73+ {isConnected() ? (
74+ <>
75+ <Grid.Item full as={FormError} />
76+
77+ <Grid.Item
78+ full
79+ as={SubmitButton}
80+ handleSubmit={handleSubmit}>
81+ {submitting
82+ ? 'Please check your WalletConnect wallet'
83+ : 'Authenticate'}
84+ </Grid.Item>
85+ </>
86+ ) : (
87+ <>
88+ <Grid.Item full as={ForwardButton} solid onClick={connect}>
89+ {'Connect'}
90+ </Grid.Item>
91+ </>
92+ )}
93+ </>
94+ )}
95+ </BridgeForm>
96+ </Grid>
97+ </>
98+ )
99+ );
100+};
101+
102+export default WalletConnectLogin;