From c23d91c7bf823ff4fdefd139d6163124e3ebea06 Mon Sep 17 00:00:00 2001 From: Vladimir Volek Date: Mon, 10 Sep 2018 13:07:51 +0200 Subject: [PATCH 01/51] #14 Fixed menu hover effect --- src/views/Wallet/components/TopNavigationAccount/index.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/views/Wallet/components/TopNavigationAccount/index.js b/src/views/Wallet/components/TopNavigationAccount/index.js index 25034591..53929d80 100644 --- a/src/views/Wallet/components/TopNavigationAccount/index.js +++ b/src/views/Wallet/components/TopNavigationAccount/index.js @@ -36,13 +36,12 @@ const StyledNavLink = styled(NavLink)` } `; - const TopNavigationAccount = (props: any) => { const urlParams = props.match.params; const basePath = `/device/${urlParams.device}/network/${urlParams.network}/account/${urlParams.account}`; return ( - + Summary Send Receive From 69a5b0b9124879cacd13d8c445720059975e5767 Mon Sep 17 00:00:00 2001 From: Vladimir Volek Date: Mon, 10 Sep 2018 13:23:31 +0200 Subject: [PATCH 02/51] Removed unused less deps --- package.json | 2 -- yarn.lock | 39 --------------------------------------- 2 files changed, 41 deletions(-) diff --git a/package.json b/package.json index 4001c4d8..3c57abf3 100644 --- a/package.json +++ b/package.json @@ -89,8 +89,6 @@ "file-loader": "1.1.11", "flow-bin": "0.72.0", "jest": "^23.4.2", - "less": "^3.0.1", - "less-loader": "4.1.0", "stylelint": "^8.0.0", "stylelint-config-standard": "^18.2.0", "stylelint-config-styled-components": "^0.1.1", diff --git a/yarn.lock b/yarn.lock index 6862c6ee..b45b201c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3335,12 +3335,6 @@ envinfo@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/envinfo/-/envinfo-4.4.2.tgz#472c49f3a8b9bca73962641ce7cb692bf623cd1c" -errno@^0.1.1: - version "0.1.4" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.4.tgz#b896e23a9e5e8ba33871fc996abd3635fc9a1c7d" - dependencies: - prr "~0.0.0" - errno@^0.1.3, errno@~0.1.7: version "0.1.7" resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" @@ -4855,10 +4849,6 @@ ignore@^3.3.5: version "3.3.7" resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.7.tgz#612289bfb3c220e186a58118618d5be8c1bab021" -image-size@~0.5.0: - version "0.5.5" - resolved "https://registry.yarnpkg.com/image-size/-/image-size-0.5.5.tgz#09dfd4ab9d20e29eb1c3e80b8990378df9e3cb9c" - import-local@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/import-local/-/import-local-1.0.0.tgz#5e4ffdc03f4fe6c009c6729beb29631c2f8227bc" @@ -5935,27 +5925,6 @@ left-pad@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/left-pad/-/left-pad-1.3.0.tgz#5b8a3a7765dfe001261dde915589e782f8c94d1e" -less-loader@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/less-loader/-/less-loader-4.1.0.tgz#2c1352c5b09a4f84101490274fd51674de41363e" - dependencies: - clone "^2.1.1" - loader-utils "^1.1.0" - pify "^3.0.0" - -less@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/less/-/less-3.0.1.tgz#ba2fea24a5632ccb8c84230d6043c0bf91855e37" - optionalDependencies: - errno "^0.1.1" - graceful-fs "^4.1.2" - image-size "~0.5.0" - mime "^1.4.1" - mkdirp "^0.5.0" - promise "^7.1.1" - request "2.81.0" - source-map "^0.5.3" - leven@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/leven/-/leven-2.1.0.tgz#c2e7a9f772094dee9d34202ae8acce4687875580" @@ -6453,10 +6422,6 @@ mime@1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/mime/-/mime-1.4.1.tgz#121f9ebc49e3766f311a76e1fa1c8003c4b03aa6" -mime@^1.4.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - mime@^2.1.0: version "2.3.1" resolved "https://registry.yarnpkg.com/mime/-/mime-2.3.1.tgz#b1621c54d63b97c47d3cfe7f7215f7d64517c369" @@ -7750,10 +7715,6 @@ proxy-addr@~2.0.3: forwarded "~0.1.2" ipaddr.js "1.6.0" -prr@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/prr/-/prr-0.0.0.tgz#1a84b85908325501411853d0081ee3fa86e2926a" - prr@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" From b2bbd99a059ed65728aaf60dfb1213fcafc7f5c6 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Mon, 10 Sep 2018 18:17:26 +0200 Subject: [PATCH 03/51] add LICENSE file --- LICENSE | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..3f77f61c --- /dev/null +++ b/LICENSE @@ -0,0 +1,54 @@ +TREZOR REFERENCE SOURCE LICENSE (T-RSL) +======================================= + +This license governs use of the accompanying software. If you use the software, +you accept this license. If you do not accept the license, do not use the +software. + +1. Definitions +-------------- + +The terms "reproduce," "reproduction" and "distribution" have the same meaning +here as under U.S. copyright law. + +"You" means the licensee of the software. + +"Your company" means the company you worked for when you downloaded the +software. + +"Reference use" means use of the software within your company as a reference, +in read only form, for the sole purposes of debugging your products, +maintaining your products, or enhancing the interoperability of your products +with the software, and specifically excludes the right to distribute the +software outside of your company. + +"Licensed patents" means any Licensor patent claims which read directly on the +software as distributed by the Licensor under this license. + +2. Grant of Rights +------------------ + +(A) Copyright Grant - Subject to the terms of this license, the Licensor grants +you a non-transferable, non-exclusive, worldwide, royalty-free copyright +license to reproduce the software for reference use. + +(B) Patent Grant - Subject to the terms of this license, the Licensor grants +you a non-transferable, non-exclusive, worldwide, royalty-free patent license +under licensed patents for reference use. + +3. Limitations +-------------- + +(A) No Trademark License - This license does not grant you any rights to use +the Licensor's name, logo, or trademarks. + +(B) If you begin patent litigation against the Licensor over patents that you +think may apply to the software (including a cross-claim or counterclaim in +a lawsuit), your license to the software ends automatically. + +(C) The software is licensed "as-is." You bear the risk of using it. The +Licensor gives no express warranties, guarantees or conditions. You may have +additional consumer rights under your local laws which this license cannot +change. To the extent permitted under your local laws, the Licensor excludes +the implied warranties of merchantability, fitness for a particular purpose and +non-infringement. From 99da86761756b63e908616783506bffed8a4095c Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 16:27:45 +0200 Subject: [PATCH 04/51] fixed flow issues --- .flowconfig | 4 +++- src/actions/ModalActions.js | 16 ++++++++-------- src/components/modals/device/Duplicate/index.js | 2 +- src/index.js | 2 +- src/utils/promiseUtils.js | 2 +- .../components/AccountMenu/index.js | 3 +++ src/views/Wallet/index.js | 2 +- src/views/Wallet/views/AccountSend/index.js | 2 +- .../components/AccountBalance/index.js | 4 ++-- 9 files changed, 21 insertions(+), 16 deletions(-) diff --git a/.flowconfig b/.flowconfig index b28be239..9a632b96 100644 --- a/.flowconfig +++ b/.flowconfig @@ -7,8 +7,9 @@ .*/node_modules/redux/.* .*/node_modules/react-router/.* .*/node_modules/react-router-redux/.* +.*/node_modules/oboe/test/.* .*/_old/.* -.*/src/solidity/.* +.*/public/solidity/.* [libs] ./src/flowtype/npm/redux_v3.x.x.js @@ -41,4 +42,5 @@ module.name_mapper='^views' -> '/src/views' module.name_mapper='^data' -> '/src/data' module.name_mapper='^services' -> '/src/services' module.name_mapper='^support' -> '/src/support' +module.name_mapper='^public' -> '/public' module.system=haste diff --git a/src/actions/ModalActions.js b/src/actions/ModalActions.js index 1c0675af..cc55e4af 100644 --- a/src/actions/ModalActions.js +++ b/src/actions/ModalActions.js @@ -24,14 +24,14 @@ export const onPinSubmit = (value: string): Action => { }; }; -export const onPassphraseSubmit = (/* passphrase: string */): AsyncAction => async (dispatch: Dispatch): Promise => { - // const resp = await TrezorConnect.uiResponse({ - // type: UI.RECEIVE_PASSPHRASE, - // payload: { - // value: passphrase, - // save: true, - // }, - // }); +export const onPassphraseSubmit = (passphrase: string): AsyncAction => async (dispatch: Dispatch): Promise => { + const resp = await TrezorConnect.uiResponse({ + type: UI.RECEIVE_PASSPHRASE, + payload: { + value: passphrase, + save: true, + }, + }); dispatch({ type: MODAL.CLOSE, diff --git a/src/components/modals/device/Duplicate/index.js b/src/components/modals/device/Duplicate/index.js index 772867ce..9aeea355 100644 --- a/src/components/modals/device/Duplicate/index.js +++ b/src/components/modals/device/Duplicate/index.js @@ -12,7 +12,7 @@ import icons from 'config/icons'; import colors from 'config/colors'; import Link from 'components/Link'; -import { Props } from './index'; +import type { Props } from 'components/modals/index'; type State = { defaultName: string; diff --git a/src/index.js b/src/index.js index c6c4cbd6..dc1da114 100644 --- a/src/index.js +++ b/src/index.js @@ -4,7 +4,7 @@ import { render } from 'react-dom'; import baseStyles from 'support/BaseStyles'; import { onBeforeUnload } from 'actions/WalletActions'; import App from 'views/index'; -import store from 'store'; +import store from './store'; const root: ?HTMLElement = document.getElementById('root'); if (root) { diff --git a/src/utils/promiseUtils.js b/src/utils/promiseUtils.js index e1e992f1..48be95a1 100644 --- a/src/utils/promiseUtils.js +++ b/src/utils/promiseUtils.js @@ -4,7 +4,7 @@ // import root from 'window-or-global'; // import Promise from 'es6-promise'; -export async function resolveAfter(msec: number, value: any = null): Promise { +export async function resolveAfter(msec: number, value?: any): Promise { await new Promise((resolve) => { //root.setTimeout(resolve, msec, value); window.setTimeout(resolve, msec, value); diff --git a/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js b/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js index 879ea222..3b597266 100644 --- a/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js +++ b/src/views/Wallet/components/LeftNavigation/components/AccountMenu/index.js @@ -113,6 +113,9 @@ const AccountMenu = (props: Props): ?React$Element => { const { config } = props.localStorage; const selectedCoin = config.coins.find(c => c.network === location.state.network); + + if (!selected || !selectedCoin) return; + const fiatRate = props.fiat.find(f => f.network === selectedCoin.network); const deviceAccounts: Accounts = findDeviceAccounts(accounts, selected, location.state.network); diff --git a/src/views/Wallet/index.js b/src/views/Wallet/index.js index e84feef3..07024a52 100644 --- a/src/views/Wallet/index.js +++ b/src/views/Wallet/index.js @@ -20,7 +20,7 @@ import TopNavigationAccount from './components/TopNavigationAccount'; import TopNavigationDeviceSettings from './components/TopNavigationDeviceSettings'; type WalletContainerProps = { - // wallet: $ElementType, + wallet: $ElementType, children?: React.Node } diff --git a/src/views/Wallet/views/AccountSend/index.js b/src/views/Wallet/views/AccountSend/index.js index 03a37abb..6e213606 100644 --- a/src/views/Wallet/views/AccountSend/index.js +++ b/src/views/Wallet/views/AccountSend/index.js @@ -237,7 +237,7 @@ class AccountSend extends Component { } getTokensSelectData(tokens: Array, accountNetwork: any) { - const tokensSelectData = tokens.map(t => ({ value: t.symbol, label: t.symbol })); + const tokensSelectData: Array<{ value: string, label: string }> = tokens.map(t => ({ value: t.symbol, label: t.symbol })); tokensSelectData.unshift({ value: accountNetwork.symbol, label: accountNetwork.symbol }); return tokensSelectData; diff --git a/src/views/Wallet/views/AccountSummary/components/AccountBalance/index.js b/src/views/Wallet/views/AccountSummary/components/AccountBalance/index.js index b90e8fec..17384817 100644 --- a/src/views/Wallet/views/AccountSummary/components/AccountBalance/index.js +++ b/src/views/Wallet/views/AccountSummary/components/AccountBalance/index.js @@ -97,7 +97,7 @@ class AccountBalance extends Component { let fiat = ''; if (fiatRate) { accountBalance = new BigNumber(this.props.balance); - fiatRateValue = new BigNumber(fiatRate.value); + fiatRateValue = new BigNumber(fiatRate.value).toFixed(2); fiat = accountBalance.times(fiatRateValue).toFixed(2); } @@ -127,7 +127,7 @@ class AccountBalance extends Component { {fiatRate && ( - ${fiatRateValue.toFixed(2)} + ${fiatRateValue} 1.00 {selectedCoin.symbol} )} From 021f932ded68672de7ab01699fd7b30f5b9992d9 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 3 Sep 2018 17:30:31 +0200 Subject: [PATCH 05/51] bump web3 version to 1.0.0-beta.35 (websocket support) --- package.json | 2 +- yarn.lock | 896 +++++++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 832 insertions(+), 66 deletions(-) diff --git a/package.json b/package.json index 3c57abf3..9c82e146 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "styled-media-query": "^2.0.2", "styled-normalize": "^8.0.0", "trezor-connect": "5.0.30", - "web3": "^0.19.0", + "web3": "1.0.0-beta.35", "webpack": "^4.16.3", "webpack-bundle-analyzer": "^2.13.1", "whatwg-fetch": "^2.0.4", diff --git a/yarn.lock b/yarn.lock index b45b201c..85cb2b8a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -558,6 +558,10 @@ any-observable@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.2.0.tgz#c67870058003579009083f54ac0abafb5c33d242" +any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" + anymatch@^1.3.0: version "1.3.2" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-1.3.2.tgz#553dcb8f91e3c889845dfdba34c77721b90b9d7a" @@ -805,6 +809,10 @@ aws4@^1.6.0: version "1.7.0" resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.7.0.tgz#d4d0e9b9dbfca77bf08eeb0a8a471550fe39e289" +aws4@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" + axobject-query@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-2.0.1.tgz#05dfa705ada8ad9db993fa6896f22d395b0b0a07" @@ -1678,6 +1686,10 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" +base64-js@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" @@ -1720,10 +1732,6 @@ bignumber.js@2.4.0, bignumber.js@^2.3.0: version "2.4.0" resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8" -bignumber.js@^4.0.2: - version "4.1.0" - resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-4.1.0.tgz#db6f14067c140bd46624815a7916c92d9b6c24b1" - binary-extensions@^1.0.0: version "1.11.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205" @@ -1742,17 +1750,32 @@ bip66@^1.1.3: dependencies: safe-buffer "^5.0.1" +bl@^1.0.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" + dependencies: + readable-stream "^2.3.5" + safe-buffer "^5.1.1" + block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" dependencies: inherits "~2.0.0" -bluebird@^3.5.1: +bluebird@^2.9.34: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" + +bluebird@^3.5.0, bluebird@^3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.4.0, bn.js@^4.8.0: +bn.js@4.11.6: + version "4.11.6" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -1771,6 +1794,21 @@ body-parser@1.18.2: raw-body "2.3.2" type-is "~1.6.15" +body-parser@^1.16.0: + version "1.18.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" + dependencies: + bytes "3.0.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "~1.6.3" + iconv-lite "0.4.23" + on-finished "~2.3.0" + qs "6.5.2" + raw-body "2.3.3" + type-is "~1.6.16" + bonjour@^3.5.0: version "3.5.0" resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" @@ -1882,6 +1920,12 @@ browserify-rsa@^4.0.0: bn.js "^4.1.0" randombytes "^2.0.1" +browserify-sha3@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" + dependencies: + js-sha3 "^0.3.1" + browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" @@ -1931,6 +1975,25 @@ bser@^2.0.0: dependencies: node-int64 "^0.4.0" +buffer-alloc-unsafe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" + +buffer-alloc@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" + dependencies: + buffer-alloc-unsafe "^1.1.0" + buffer-fill "^1.0.0" + +buffer-crc32@~0.2.3: + version "0.2.13" + resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" + +buffer-fill@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" + buffer-from@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.0.tgz#87fcaa3a298358e0ade6e442cfce840740d1ad04" @@ -1939,10 +2002,22 @@ buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" +buffer-to-arraybuffer@^0.0.5: + version "0.0.5" + resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" + buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" +buffer@^3.0.1: + version "3.6.0" + resolved "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" + dependencies: + base64-js "0.0.8" + ieee754 "^1.1.4" + isarray "^1.0.0" + buffer@^4.3.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" @@ -1958,6 +2033,13 @@ buffer@^5.0.3: base64-js "^1.0.2" ieee754 "^1.1.4" +buffer@^5.0.5: + version "5.2.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + builtin-modules@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -2454,7 +2536,7 @@ colors@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/colors/-/colors-1.1.2.tgz#168a4701756b6a7f51a12ce0c97bfa28c084ed63" -combined-stream@1.0.6: +combined-stream@1.0.6, combined-stream@~1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" dependencies: @@ -2474,7 +2556,7 @@ commander@^2.11.0: version "2.12.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.1.tgz#468635c4168d06145b9323356d1da84d14ac4a7a" -commander@^2.13.0: +commander@^2.8.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -2482,6 +2564,12 @@ commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" +commander@~2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" + dependencies: + graceful-readlink ">= 1.0.0" + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -2585,6 +2673,10 @@ cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" +cookiejar@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" + copy-concurrently@^1.0.0: version "1.0.5" resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" @@ -2629,16 +2721,14 @@ core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -cosmiconfig@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-3.1.0.tgz#640a94bf9847f321800403cd273af60665c73397" +cors@^2.8.1: + version "2.8.4" + resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" dependencies: - is-directory "^0.3.1" - js-yaml "^3.9.0" - parse-json "^3.0.0" - require-from-string "^2.0.1" + object-assign "^4" + vary "^1" -cosmiconfig@^5.0.5: +cosmiconfig@^5.0.0, cosmiconfig@^5.0.5: version "5.0.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" dependencies: @@ -2727,7 +2817,7 @@ cryptiles@2.x.x: dependencies: boom "2.x.x" -crypto-browserify@^3.11.0: +crypto-browserify@3.12.0, crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" dependencies: @@ -2743,10 +2833,6 @@ crypto-browserify@^3.11.0: randombytes "^2.0.0" randomfill "^1.0.3" -crypto-js@^3.1.4: - version "3.1.8" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" - css-animation@^1.3.2: version "1.4.1" resolved "https://registry.yarnpkg.com/css-animation/-/css-animation-1.4.1.tgz#5b8813125de0fbbbb0bbe1b472ae84221469b7a8" @@ -2955,6 +3041,54 @@ decompress-response@^3.2.0, decompress-response@^3.3.0: dependencies: mimic-response "^1.0.0" +decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" + dependencies: + file-type "^5.2.0" + is-stream "^1.1.0" + tar-stream "^1.5.2" + +decompress-tarbz2@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" + dependencies: + decompress-tar "^4.1.0" + file-type "^6.1.0" + is-stream "^1.1.0" + seek-bzip "^1.0.5" + unbzip2-stream "^1.0.9" + +decompress-targz@^4.0.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" + dependencies: + decompress-tar "^4.1.1" + file-type "^5.2.0" + is-stream "^1.1.0" + +decompress-unzip@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" + dependencies: + file-type "^3.8.0" + get-stream "^2.2.0" + pify "^2.3.0" + yauzl "^2.4.2" + +decompress@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" + dependencies: + decompress-tar "^4.0.0" + decompress-tarbz2 "^4.0.0" + decompress-targz "^4.0.0" + decompress-unzip "^4.0.1" + graceful-fs "^4.1.10" + make-dir "^1.0.0" + pify "^2.3.0" + strip-dirs "^2.0.0" + deep-diff@^0.3.5: version "0.3.8" resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84" @@ -3280,6 +3414,18 @@ elliptic@^6.0.0, elliptic@^6.2.3: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" +elliptic@^6.4.0: + version "6.4.1" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + emoji-regex@^6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.5.1.tgz#9baea929b155565c11ea41c6626eaa65cef992c2" @@ -3643,6 +3789,26 @@ etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" +eth-lib@0.1.27, eth-lib@^0.1.26: + version "0.1.27" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + keccakjs "^0.2.1" + nano-json-stream-parser "^0.1.2" + servify "^0.1.12" + ws "^3.0.0" + xhr-request-promise "^0.1.2" + +eth-lib@0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" + dependencies: + bn.js "^4.11.6" + elliptic "^6.4.0" + xhr-request-promise "^0.1.2" + ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" @@ -3685,6 +3851,13 @@ ethereumjs-util@^5.1.4: safe-buffer "^5.1.1" secp256k1 "^3.0.1" +ethjs-unit@0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" + dependencies: + bn.js "4.11.6" + number-to-bn "1.7.0" + ethjs-util@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.4.tgz#1c8b6879257444ef4d3f3fbbac2ded12cd997d93" @@ -3704,6 +3877,10 @@ event-stream@~3.3.0: stream-combiner "~0.0.4" through "~2.3.1" +eventemitter3@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" + eventemitter3@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" @@ -3798,7 +3975,7 @@ expect@^23.4.0: jest-message-util "^23.4.0" jest-regex-util "^23.3.0" -express@^4.16.2: +express@^4.14.0, express@^4.16.2: version "4.16.3" resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" dependencies: @@ -3846,7 +4023,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@^3.0.0, extend@~3.0.1: +extend@^3.0.0, extend@~3.0.1, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" @@ -3958,6 +4135,12 @@ fbjs@^0.8.5: setimmediate "^1.0.5" ua-parser-js "^0.7.18" +fd-slicer@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" + dependencies: + pend "~1.2.0" + figures@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/figures/-/figures-1.7.0.tgz#cbe1e3affcf1cd44b80cadfed28dc793a9701d2e" @@ -3985,6 +4168,18 @@ file-loader@1.1.11: loader-utils "^1.0.2" schema-utils "^0.4.5" +file-type@^3.8.0: + version "3.9.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" + +file-type@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" + +file-type@^6.1.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" + filename-regex@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/filename-regex/-/filename-regex-2.0.1.tgz#c1c4b9bee3e09725ddb106b75c1e301fe2f18b26" @@ -4111,6 +4306,12 @@ follow-redirects@^1.0.0: dependencies: debug "^3.1.0" +for-each@^0.3.2: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + dependencies: + is-callable "^1.1.3" + for-in@^1.0.1, for-in@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" @@ -4137,7 +4338,7 @@ form-data@~2.1.1: combined-stream "^1.0.5" mime-types "^2.1.12" -form-data@~2.3.1: +form-data@~2.3.1, form-data@~2.3.2: version "2.3.2" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" dependencies: @@ -4170,12 +4371,32 @@ from@~0: version "0.1.7" resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe" +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + +fs-extra@^2.0.0, fs-extra@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" + dependencies: + graceful-fs "^4.1.2" + jsonfile "^2.1.0" + fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" dependencies: minipass "^2.2.1" +fs-promise@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" + dependencies: + any-promise "^1.3.0" + fs-extra "^2.0.0" + mz "^2.6.0" + thenify-all "^1.6.0" + fs-readdir-recursive@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz#e32fc030a2ccee44a6b5371308da54be0b397d27" @@ -4215,7 +4436,7 @@ fstream-ignore@^1.0.5: inherits "2" minimatch "^3.0.0" -fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2: +fstream@^1.0.0, fstream@^1.0.10, fstream@^1.0.2, fstream@^1.0.8: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" dependencies: @@ -4261,6 +4482,13 @@ get-stream@3.0.0, get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" +get-stream@^2.2.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" + dependencies: + object-assign "^4.0.1" + pinkie-promise "^2.0.0" + get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" @@ -4344,7 +4572,7 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" -global@^4.3.0: +global@^4.3.0, global@~4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" dependencies: @@ -4413,7 +4641,7 @@ gonzales-pe@^4.0.3: dependencies: minimist "1.1.x" -got@^7.0.0: +got@7.1.0, got@^7.0.0, got@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" dependencies: @@ -4454,10 +4682,14 @@ got@^8.2.0: url-parse-lax "^3.0.0" url-to-options "^1.0.1" -graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4: +graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.4, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" +"graceful-readlink@>= 1.0.0": + version "1.0.1" + resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" + grouped-queue@^0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/grouped-queue/-/grouped-queue-0.3.3.tgz#c167d2a5319c5a0e0964ef6a25b7c2df8996c85c" @@ -4511,6 +4743,13 @@ har-validator@~5.0.3: ajv "^5.1.0" har-schema "^2.0.0" +har-validator@~5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" + dependencies: + ajv "^5.3.0" + har-schema "^2.0.0" + has-ansi@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" @@ -4766,6 +5005,19 @@ http-errors@1.6.2, http-errors@~1.6.2: setprototypeof "1.0.3" statuses ">= 1.3.1 < 2" +http-errors@1.6.3, http-errors@~1.6.3: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-https@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" + http-parser-js@>=0.4.0: version "0.4.12" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.12.tgz#b9cfbf4a2cf26f0fc34b10ca1489a27771e3474f" @@ -4811,7 +5063,7 @@ iconv-lite@0.4.19, iconv-lite@~0.4.13: version "0.4.19" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.19.tgz#f7468f60135f5e5dad3399c0a81be9a1603a082b" -iconv-lite@^0.4.17, iconv-lite@^0.4.4: +iconv-lite@0.4.23, iconv-lite@^0.4.17, iconv-lite@^0.4.4: version "0.4.23" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.23.tgz#297871f63be507adcfbfca715d0cd0eed84e9a63" dependencies: @@ -5120,6 +5372,10 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" +is-function@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" + is-generator-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" @@ -5150,6 +5406,10 @@ is-hexadecimal@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.2.tgz#b6e710d7d07bb66b98cb8cece5c9b4921deeb835" +is-natural-number@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" + is-number@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-2.1.0.tgz#01fcbbb393463a548f2f466cce16dece49db908f" @@ -5266,7 +5526,7 @@ is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" -is-typedarray@~1.0.0: +is-typedarray@^1.0.0, is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -5698,6 +5958,10 @@ js-base64@^2.1.9: version "2.3.2" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.2.tgz#a79a923666372b580f8e27f51845c6f7e8fbfbaf" +js-sha3@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" + js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -5845,6 +6109,12 @@ json5@^0.5.0, json5@^0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" +jsonfile@^2.1.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" + optionalDependencies: + graceful-fs "^4.1.6" + jsonify@~0.0.0: version "0.0.0" resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" @@ -5873,6 +6143,13 @@ keccak@^1.0.2: nan "^2.2.1" safe-buffer "^5.1.0" +keccakjs@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" + dependencies: + browserify-sha3 "^0.0.1" + sha3 "^1.1.0" + keyv@3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/keyv/-/keyv-3.0.0.tgz#44923ba39e68b12a7cec7df6c3268c031f2ef373" @@ -6406,12 +6683,22 @@ mime-db@~1.30.0: version "1.30.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.30.0.tgz#74c643da2dd9d6a45399963465b26d5ca7d71f01" +mime-db@~1.36.0: + version "1.36.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" + mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.7: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: mime-db "~1.30.0" +mime-types@^2.1.16, mime-types@~2.1.19: + version "2.1.20" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" + dependencies: + mime-db "~1.36.0" + mime-types@~2.1.17, mime-types@~2.1.18: version "2.1.18" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" @@ -6516,12 +6803,26 @@ mixin-deep@^1.2.0: for-in "^1.0.2" is-extendable "^1.0.1" -mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp-promise@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" + dependencies: + mkdirp "*" + +mkdirp@*, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" +mock-fs@^4.1.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.6.0.tgz#d944ef4c3e03ceb4e8332b4b31b8ac254051c8ae" + +mout@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" + move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -6561,13 +6862,29 @@ mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" +mz@^2.6.0: + version "2.7.0" + resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" + dependencies: + any-promise "^1.0.0" + object-assign "^4.0.1" + thenify-all "^1.0.0" + +nan@2.10.0, nan@^2.9.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" + +nan@^2.0.8, nan@^2.3.3: + version "2.11.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" + nan@^2.2.1, nan@^2.3.0: version "2.8.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" -nan@^2.9.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" +nano-json-stream-parser@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" nanomatch@^1.2.9: version "1.2.9" @@ -6821,6 +7138,13 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" +number-to-bn@1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" + dependencies: + bn.js "4.11.6" + strip-hex-prefix "1.0.0" + nwsapi@^2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.0.7.tgz#6fc54c254621f10cac5225b76e81c74120139b78" @@ -6829,7 +7153,11 @@ oauth-sign@~0.8.1, oauth-sign@~0.8.2: version "0.8.2" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.8.2.tgz#46a6ab7f0aead8deae9ec0565780b7d4efeb9d43" -object-assign@4.x, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + +object-assign@4.x, object-assign@^4, object-assign@^4.0.0, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -6893,6 +7221,12 @@ object.pick@^1.3.0: dependencies: isobject "^3.0.1" +oboe@2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" + dependencies: + http-https "^1.0.0" + obuf@^1.0.0, obuf@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -7115,6 +7449,13 @@ parse-glob@^3.0.4: is-extglob "^1.0.0" is-glob "^2.0.0" +parse-headers@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" + dependencies: + for-each "^0.3.2" + trim "0.0.1" + parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -7230,6 +7571,10 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" +pend@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" + performance-now@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" @@ -7782,14 +8127,14 @@ qs@6.5.1: version "6.5.1" resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.1.tgz#349cdf6eef89ec45c12d7d5eb3fc0c870343a6d8" +qs@6.5.2, qs@~6.5.1, qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + qs@~6.4.0: version "6.4.0" resolved "https://registry.yarnpkg.com/qs/-/qs-6.4.0.tgz#13e26d28ad6b0ffaa91312cd3bf708ed351e7233" -qs@~6.5.1: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -7851,6 +8196,10 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" +randomhex@0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" + range-parser@^1.0.3, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -7868,6 +8217,15 @@ raw-body@2.3.2: iconv-lite "0.4.19" unpipe "1.0.0" +raw-body@2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.3.3.tgz#1b324ece6b5706e153855bc1148c65bb7f6ea0c3" + dependencies: + bytes "3.0.0" + http-errors "1.6.3" + iconv-lite "0.4.23" + unpipe "1.0.0" + rc-align@2.x: version "2.3.5" resolved "https://registry.yarnpkg.com/rc-align/-/rc-align-2.3.5.tgz#5085cfa4d685ee9d030b9afd2971eb370c5e80a1" @@ -8129,7 +8487,7 @@ readable-stream@1.0: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.1, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: +readable-stream@^2.0.1, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -8444,6 +8802,31 @@ request@2.81.0: tunnel-agent "^0.6.0" uuid "^3.0.0" +request@^2.79.0: + version "2.88.0" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.0" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.4.3" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + request@^2.87.0: version "2.87.0" resolved "https://registry.yarnpkg.com/request/-/request-2.87.0.tgz#32f00235cd08d482b4d0d68db93a829c0ed5756e" @@ -8683,6 +9066,25 @@ scoped-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" +scrypt.js@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" + dependencies: + scrypt "^6.0.2" + scryptsy "^1.2.1" + +scrypt@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" + dependencies: + nan "^2.0.8" + +scryptsy@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" + dependencies: + pbkdf2 "^3.0.3" + secp256k1@^3.0.1: version "3.4.0" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.4.0.tgz#1c905b256fa4ae5b9cc170e672dd59b4c5de46a4" @@ -8696,6 +9098,12 @@ secp256k1@^3.0.1: nan "^2.2.1" safe-buffer "^5.1.0" +seek-bzip@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" + dependencies: + commander "~2.8.1" + select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -8757,6 +9165,16 @@ serve-static@1.13.2: parseurl "~1.3.2" send "0.16.2" +servify@^0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" + dependencies: + body-parser "^1.16.0" + cors "^2.8.1" + express "^4.14.0" + request "^2.79.0" + xhr "^2.3.3" + set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -8802,6 +9220,12 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" +sha3@^1.1.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" + dependencies: + nan "2.10.0" + shallowequal@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/shallowequal/-/shallowequal-0.2.2.tgz#1e32fd5bcab6ad688a4812cb0cc04efc75c7014e" @@ -8851,6 +9275,18 @@ signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" +simple-concat@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" + +simple-get@^2.7.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" + dependencies: + decompress-response "^3.3.0" + once "^1.3.1" + simple-concat "^1.0.0" + sisteransi@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-0.1.1.tgz#5431447d5f7d1675aac667ccd0b865a4994cb3ce" @@ -9095,6 +9531,10 @@ static-extend@^0.1.1: version "1.4.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.4.0.tgz#bb73d446da2796106efcc1b601a253d6c46bd087" +"statuses@>= 1.4.0 < 2": + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + stealthy-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" @@ -9239,6 +9679,12 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" +strip-dirs@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" + dependencies: + is-natural-number "^4.0.1" + strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -9429,6 +9875,24 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" +swarm-js@0.1.37: + version "0.1.37" + resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" + dependencies: + bluebird "^3.5.0" + buffer "^5.0.5" + decompress "^4.0.0" + eth-lib "^0.1.26" + fs-extra "^2.1.2" + fs-promise "^2.0.0" + got "^7.1.0" + mime-types "^2.1.16" + mkdirp-promise "^5.0.1" + mock-fs "^4.1.0" + setimmediate "^1.0.5" + tar.gz "^1.0.5" + xhr-request-promise "^0.1.2" + symbol-observable@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" @@ -9484,7 +9948,29 @@ tar-pack@^3.4.0: tar "^2.2.1" uid-number "^0.0.6" -tar@^2.2.1: +tar-stream@^1.5.2: + version "1.6.1" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.1.tgz#f84ef1696269d6223ca48f6e1eeede3f7e81f395" + dependencies: + bl "^1.0.0" + buffer-alloc "^1.1.0" + end-of-stream "^1.0.0" + fs-constants "^1.0.0" + readable-stream "^2.3.0" + to-buffer "^1.1.0" + xtend "^4.0.0" + +tar.gz@^1.0.5: + version "1.0.7" + resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" + dependencies: + bluebird "^2.9.34" + commander "^2.8.1" + fstream "^1.0.8" + mout "^0.11.0" + tar "^2.1.1" + +tar@^2.1.1, tar@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -9529,6 +10015,18 @@ textextensions@2: version "2.2.0" resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286" +thenify-all@^1.0.0, thenify-all@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" + dependencies: + thenify ">= 3.1.0 < 4" + +"thenify@>= 3.1.0 < 4": + version "3.3.0" + resolved "https://registry.yarnpkg.com/thenify/-/thenify-3.3.0.tgz#e69e38a1babe969b0108207978b9f62b88604839" + dependencies: + any-promise "^1.0.0" + throat@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/throat/-/throat-4.1.0.tgz#89037cbc92c56ab18926e6ba4cbb200e15672a6a" @@ -9572,6 +10070,10 @@ to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" +to-buffer@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" + to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -9612,7 +10114,7 @@ touch@^1.0.0: dependencies: nopt "~1.0.10" -tough-cookie@>=2.3.3, tough-cookie@^2.3.4: +tough-cookie@>=2.3.3, tough-cookie@^2.3.4, tough-cookie@~2.4.3: version "2.4.3" resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" dependencies: @@ -9711,6 +10213,12 @@ type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" +typedarray-to-buffer@^3.1.2: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + dependencies: + is-typedarray "^1.0.0" + typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -9767,6 +10275,21 @@ uid-number@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" +ultron@~1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" + +unbzip2-stream@^1.0.9: + version "1.2.5" + resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz#73a033a567bbbde59654b193c44d48a7e4f43c47" + dependencies: + buffer "^3.0.1" + through "^2.3.6" + +underscore@1.8.3: + version "1.8.3" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" + underscore@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.6.0.tgz#8b38b10cacdef63337b8b24e4ff86d45aea529a8" @@ -9918,6 +10441,10 @@ url-parse@^1.1.8, url-parse@~1.4.0: querystringify "^2.0.0" requires-port "^1.0.0" +url-set-query@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" + url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" @@ -9939,9 +10466,9 @@ user-home@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/user-home/-/user-home-1.1.1.tgz#2b5be23a32b63a7c9deb8d0f28d485724a3df190" -utf8@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" +utf8@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" util-deprecate@~1.0.1: version "1.0.2" @@ -9978,6 +10505,10 @@ utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" +uuid@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" + uuid@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.1.0.tgz#3dd3d3e790abc24d7b0d3a034ffababe28ebbc04" @@ -9986,6 +10517,10 @@ uuid@^3.0.1, uuid@^3.1.0: version "3.2.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.2.1.tgz#12c528bb9d58d0b9265d9a2f6f0fe8be17ff1f14" +uuid@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" + v8-compile-cache@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-1.1.2.tgz#8d32e4f16974654657e676e0e467a348e89b0dc4" @@ -10007,7 +10542,7 @@ value-equal@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7" -vary@~1.1.2: +vary@^1, vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -10117,15 +10652,200 @@ wbuf@^1.1.0, wbuf@^1.7.2: dependencies: minimalistic-assert "^1.0.0" -web3@^0.19.0: - version "0.19.1" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.19.1.tgz#e763d5b1107c4bc24abd4f8cbee1ba3659e6eb31" - dependencies: - bignumber.js "^4.0.2" - crypto-js "^3.1.4" - utf8 "^2.1.1" - xhr2 "*" - xmlhttprequest "*" +web3-bzz@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.35.tgz#9d5e1362b3db2afd77d65619b7cd46dd5845c192" + dependencies: + got "7.1.0" + swarm-js "0.1.37" + underscore "1.8.3" + +web3-core-helpers@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.35.tgz#d681d218a0c6e3283ee1f99a078ab9d3eef037f1" + dependencies: + underscore "1.8.3" + web3-eth-iban "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-core-method@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.35.tgz#fc10e2d546cf4886038e6130bd5726b0952a4e5f" + dependencies: + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.35" + web3-core-promievent "1.0.0-beta.35" + web3-core-subscriptions "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-core-promievent@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.35.tgz#4f1b24737520fa423fee3afee110fbe82bcb8691" + dependencies: + any-promise "1.3.0" + eventemitter3 "1.1.1" + +web3-core-requestmanager@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.35.tgz#2b77cbf6303720ad68899b39fa7f584dc03dbc8f" + dependencies: + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.35" + web3-providers-http "1.0.0-beta.35" + web3-providers-ipc "1.0.0-beta.35" + web3-providers-ws "1.0.0-beta.35" + +web3-core-subscriptions@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.35.tgz#c1b76a2ad3c6e80f5d40b8ba560f01e0f4628758" + dependencies: + eventemitter3 "1.1.1" + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.35" + +web3-core@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.35.tgz#0c44d3c50d23219b0b1531d145607a9bc7cd4b4f" + dependencies: + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-core-requestmanager "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-eth-abi@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.35.tgz#2eb9c1c7c7233db04010defcb192293e0db250e6" + dependencies: + bn.js "4.11.6" + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-eth-accounts@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz#7d0e5a69f510dc93874471599eb7abfa9ddf3e63" + dependencies: + any-promise "1.3.0" + crypto-browserify "3.12.0" + eth-lib "0.2.7" + scrypt.js "0.2.0" + underscore "1.8.3" + uuid "2.0.1" + web3-core "1.0.0-beta.35" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-eth-contract@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.35.tgz#5276242d8a3358d9f1ce92b71575c74f9015935c" + dependencies: + underscore "1.8.3" + web3-core "1.0.0-beta.35" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-core-promievent "1.0.0-beta.35" + web3-core-subscriptions "1.0.0-beta.35" + web3-eth-abi "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-eth-iban@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.35.tgz#5aa10327a9abb26bcfc4ba79d7bad18a002b332c" + dependencies: + bn.js "4.11.6" + web3-utils "1.0.0-beta.35" + +web3-eth-personal@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.35.tgz#ecac95b7a53d04a567447062d5cae5f49879e89f" + dependencies: + web3-core "1.0.0-beta.35" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-net "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-eth@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.35.tgz#c52c804afb95e6624b6f5e72a9af90fbf5005b68" + dependencies: + underscore "1.8.3" + web3-core "1.0.0-beta.35" + web3-core-helpers "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-core-subscriptions "1.0.0-beta.35" + web3-eth-abi "1.0.0-beta.35" + web3-eth-accounts "1.0.0-beta.35" + web3-eth-contract "1.0.0-beta.35" + web3-eth-iban "1.0.0-beta.35" + web3-eth-personal "1.0.0-beta.35" + web3-net "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-net@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.35.tgz#5c6688e0dea71fcd910ee9dc5437b94b7f6b3354" + dependencies: + web3-core "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" + +web3-providers-http@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.35.tgz#92059d9d6de6e9f82f4fae30b743efd841afc1e1" + dependencies: + web3-core-helpers "1.0.0-beta.35" + xhr2-cookies "1.1.0" + +web3-providers-ipc@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.35.tgz#031afeb10fade2ebb0ef2fb82f5e58c04be842d9" + dependencies: + oboe "2.1.3" + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.35" + +web3-providers-ws@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.35.tgz#5d38603fd450243a26aae0ff7f680644e77fa240" + dependencies: + underscore "1.8.3" + web3-core-helpers "1.0.0-beta.35" + websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" + +web3-shh@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.35.tgz#7e4a585f8beee0c1927390937c6537748a5d1a58" + dependencies: + web3-core "1.0.0-beta.35" + web3-core-method "1.0.0-beta.35" + web3-core-subscriptions "1.0.0-beta.35" + web3-net "1.0.0-beta.35" + +web3-utils@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.35.tgz#ced9e1df47c65581c441c5f2af76b05a37a273d7" + dependencies: + bn.js "4.11.6" + eth-lib "0.1.27" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randomhex "0.1.5" + underscore "1.8.3" + utf8 "2.1.1" + +web3@1.0.0-beta.35: + version "1.0.0-beta.35" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.35.tgz#6475095bd451a96e50a32b997ddee82279292f11" + dependencies: + web3-bzz "1.0.0-beta.35" + web3-core "1.0.0-beta.35" + web3-eth "1.0.0-beta.35" + web3-eth-personal "1.0.0-beta.35" + web3-net "1.0.0-beta.35" + web3-shh "1.0.0-beta.35" + web3-utils "1.0.0-beta.35" webidl-conversions@^4.0.2: version "4.0.2" @@ -10287,6 +11007,15 @@ websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" +"websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": + version "1.0.26" + resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" + dependencies: + debug "^2.2.0" + nan "^2.3.3" + typedarray-to-buffer "^3.1.2" + yaeti "^0.0.6" + whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.3.tgz#57c235bc8657e914d24e1a397d3c82daee0a6ba3" @@ -10394,12 +11123,13 @@ write@^0.2.1: dependencies: mkdirp "^0.5.1" -ws@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" +ws@^3.0.0: + version "3.3.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" dependencies: async-limiter "~1.0.0" safe-buffer "~5.1.0" + ultron "~1.1.0" ws@^5.2.0: version "5.2.2" @@ -10411,18 +11141,43 @@ x-is-string@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/x-is-string/-/x-is-string-0.1.0.tgz#474b50865af3a49a9c4657f05acd145458f77d82" -xhr2@*: - version "0.1.4" - resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" +xhr-request-promise@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" + dependencies: + xhr-request "^1.0.1" + +xhr-request@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" + dependencies: + buffer-to-arraybuffer "^0.0.5" + object-assign "^4.1.1" + query-string "^5.0.1" + simple-get "^2.7.0" + timed-out "^4.0.1" + url-set-query "^1.0.0" + xhr "^2.0.4" + +xhr2-cookies@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" + dependencies: + cookiejar "^2.1.1" + +xhr@^2.0.4, xhr@^2.3.3: + version "2.5.0" + resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" + dependencies: + global "~4.3.0" + is-function "^1.0.1" + parse-headers "^2.0.0" + xtend "^4.0.0" xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" -xmlhttprequest@*: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" @@ -10435,6 +11190,10 @@ y18n@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" +yaeti@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" + yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" @@ -10513,6 +11272,13 @@ yarn-run-all@^3.1.1: shell-quote "^1.6.1" string.prototype.padend "^3.0.0" +yauzl@^2.4.2: + version "2.10.0" + resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" + dependencies: + buffer-crc32 "~0.2.3" + fd-slicer "~1.1.0" + yeoman-environment@^2.0.0, yeoman-environment@^2.0.5: version "2.1.1" resolved "https://registry.yarnpkg.com/yeoman-environment/-/yeoman-environment-2.1.1.tgz#10a045f7fc4397873764882eae055a33e56ee1c5" From 414d0b0d01b0b0037290ecc9af5b69fab39c3c42 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 3 Sep 2018 17:43:17 +0200 Subject: [PATCH 06/51] removed web3 references --- src/actions/SelectedAccountActions.js | 5 +---- src/actions/WalletActions.js | 7 +++++-- src/reducers/SelectedAccountReducer.js | 3 --- src/services/RouterService.js | 5 ++--- src/services/TrezorConnectService.js | 7 ++----- src/views/Landing/Container.js | 2 -- 6 files changed, 10 insertions(+), 19 deletions(-) diff --git a/src/actions/SelectedAccountActions.js b/src/actions/SelectedAccountActions.js index cb426256..0bacf1b3 100644 --- a/src/actions/SelectedAccountActions.js +++ b/src/actions/SelectedAccountActions.js @@ -47,8 +47,7 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct || prevState.accounts !== state.accounts || prevState.discovery !== state.discovery || prevState.tokens !== state.tokens - || prevState.pending !== state.pending - || prevState.web3 !== state.web3) { + || prevState.pending !== state.pending) { if (locationChange) { // dispose current account view dispatch(dispose()); @@ -59,7 +58,6 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct const discovery = stateUtils.getDiscoveryProcess(state); const tokens = stateUtils.getAccountTokens(state, account); const pending = stateUtils.getAccountPendingTx(state.pending, account); - const web3 = stateUtils.getWeb3(state); const payload: $ElementType = { location: location.pathname, @@ -68,7 +66,6 @@ export const updateSelectedValues = (prevState: State, action: Action): AsyncAct discovery, tokens, pending, - web3, }; let needUpdate: boolean = false; diff --git a/src/actions/WalletActions.js b/src/actions/WalletActions.js index a4bb0040..32830e26 100644 --- a/src/actions/WalletActions.js +++ b/src/actions/WalletActions.js @@ -5,8 +5,11 @@ import { LOCATION_CHANGE } from 'react-router-redux'; import * as WALLET from 'actions/constants/wallet'; import * as stateUtils from 'reducers/utils'; -import type -{ +import type { + Account, + Coin, + Discovery, + Token, Device, TrezorDevice, RouterLocationState, diff --git a/src/reducers/SelectedAccountReducer.js b/src/reducers/SelectedAccountReducer.js index a83b2dca..0500fb13 100644 --- a/src/reducers/SelectedAccountReducer.js +++ b/src/reducers/SelectedAccountReducer.js @@ -10,7 +10,6 @@ import type { Token, PendingTx, Discovery, - Web3Instance, } from 'flowtype'; export type State = { @@ -20,7 +19,6 @@ export type State = { network: ?Coin; tokens: Array, pending: Array, - web3: ?Web3Instance, discovery: ?Discovery }; @@ -30,7 +28,6 @@ export const initialState: State = { network: null, tokens: [], pending: [], - web3: null, discovery: null, }; diff --git a/src/services/RouterService.js b/src/services/RouterService.js index db3157cd..92ba3b4d 100644 --- a/src/services/RouterService.js +++ b/src/services/RouterService.js @@ -72,7 +72,6 @@ const RouterService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa __unloading = true; } else if (action.type === LOCATION_CHANGE && !__unloading) { const { location } = api.getState().router; - const { web3 } = api.getState(); const { devices } = api.getState(); const { error } = api.getState().connect; @@ -92,8 +91,8 @@ const RouterService: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispa redirectPath = '/'; } else { const isModalOpened: boolean = api.getState().modal.opened; - // if web3 wasn't initialized yet or there are no devices attached or initialization error occurs - const landingPage: boolean = web3.length < 1 || devices.length < 1 || error !== null; + // there are no devices attached or initialization error occurs + const landingPage: boolean = devices.length < 1 || error !== null; // modal is still opened and currentPath is still valid // example 1 (valid blocking): url changes while passphrase modal opened but device is still connected (we want user to finish this action) diff --git a/src/services/TrezorConnectService.js b/src/services/TrezorConnectService.js index f69f5b13..f32a17a5 100644 --- a/src/services/TrezorConnectService.js +++ b/src/services/TrezorConnectService.js @@ -7,8 +7,6 @@ import { import * as TrezorConnectActions from 'actions/TrezorConnectActions'; import * as DiscoveryActions from 'actions/DiscoveryActions'; import * as ModalActions from 'actions/ModalActions'; -import { init as initWeb3 } from 'actions/Web3Actions'; -import * as WEB3 from 'actions/constants/web3'; import * as STORAGE from 'actions/constants/localStorage'; import * as CONNECT from 'actions/constants/TrezorConnect'; @@ -32,9 +30,8 @@ const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: Middlewa } else if (action.type === TRANSPORT.ERROR) { // TODO: check if modal is open // api.dispatch( push('/') ); - } else if (action.type === TRANSPORT.START && api.getState().web3.length < 1) { - api.dispatch(initWeb3()); - } else if (action.type === WEB3.READY) { + } else if (action.type === TRANSPORT.START) { + // api.dispatch({ type: WEB3.READY }); api.dispatch(TrezorConnectActions.postInit()); } else if (action.type === DEVICE.DISCONNECT) { api.dispatch(TrezorConnectActions.deviceDisconnect(action.device)); diff --git a/src/views/Landing/Container.js b/src/views/Landing/Container.js index da89a4b0..6c891761 100644 --- a/src/views/Landing/Container.js +++ b/src/views/Landing/Container.js @@ -8,7 +8,6 @@ import LandingPage from './index'; export type StateProps = { localStorage: $ElementType, modal: $ElementType, - web3: $ElementType, wallet: $ElementType, connect: $ElementType, router: $ElementType, @@ -29,7 +28,6 @@ export type Props = StateProps & DispatchProps; const mapStateToProps: MapStateToProps = (state: State): StateProps => ({ localStorage: state.localStorage, modal: state.modal, - web3: state.web3, wallet: state.wallet, connect: state.connect, router: state.router, From b5a885907bbef9af0680940f7ac8e2f1d1857404 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 3 Sep 2018 17:43:34 +0200 Subject: [PATCH 07/51] add Web3Service --- src/actions/Web3Actions.js | 2 ++ src/services/Web3Service.js | 28 ++++++++++++++++++++++++++++ src/services/index.js | 1 + 3 files changed, 31 insertions(+) create mode 100644 src/services/Web3Service.js diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index e1c1b73e..e72ecabb 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -39,6 +39,8 @@ export type Web3UpdateGasPriceAction = { export type Web3Action = { type: typeof WEB3.READY, +} | { + type: typeof WEB3.START, } | { type: typeof WEB3.CREATE, instance: Web3Instance diff --git a/src/services/Web3Service.js b/src/services/Web3Service.js new file mode 100644 index 00000000..996e9984 --- /dev/null +++ b/src/services/Web3Service.js @@ -0,0 +1,28 @@ +/* @flow */ + + +import TrezorConnect, { TRANSPORT } from 'trezor-connect'; +import * as WEB3 from 'actions/constants/web3'; + +import type { + Middleware, + MiddlewareAPI, + MiddlewareDispatch, + Action, +} from 'flowtype'; + +/** + * Middleware + */ +const Web3Service: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => { + // pass action + next(action); + + if (action.type === WEB3.START) { + api.dispatch(WalletActions.clearUnavailableDevicesData(prevState, action.device)); + } + + return action; +}; + +export default Web3Service; \ No newline at end of file diff --git a/src/services/index.js b/src/services/index.js index b2ed5a5b..d8aef7c9 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -4,6 +4,7 @@ import RouterService from './RouterService'; import LocalStorageService from './LocalStorageService'; import CoinmarketcapService from './CoinmarketcapService'; import TrezorConnectService from './TrezorConnectService'; +import Web3Service from './Web3Service'; export default [ WalletService, From 2280633b5d114780b88c9f59a38fa10675c1aa70 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 3 Sep 2018 17:45:50 +0200 Subject: [PATCH 08/51] removed WEB3.READY --- src/reducers/WalletReducer.js | 4 ++-- src/services/TrezorConnectService.js | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/reducers/WalletReducer.js b/src/reducers/WalletReducer.js index aa4f6d26..3676bdfc 100644 --- a/src/reducers/WalletReducer.js +++ b/src/reducers/WalletReducer.js @@ -2,7 +2,7 @@ import { LOCATION_CHANGE } from 'react-router-redux'; -import { DEVICE } from 'trezor-connect'; +import { DEVICE, TRANSPORT } from 'trezor-connect'; import * as MODAL from 'actions/constants/modal'; import * as WEB3 from 'actions/constants/web3'; import * as WALLET from 'actions/constants/wallet'; @@ -41,7 +41,7 @@ export default function wallet(state: State = initialState, action: Action): Sta initialPathname: action.pathname, }; - case WEB3.READY: + case TRANSPORT.START: return { ...state, ready: true, diff --git a/src/services/TrezorConnectService.js b/src/services/TrezorConnectService.js index f32a17a5..38c9e733 100644 --- a/src/services/TrezorConnectService.js +++ b/src/services/TrezorConnectService.js @@ -31,7 +31,6 @@ const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: Middlewa // TODO: check if modal is open // api.dispatch( push('/') ); } else if (action.type === TRANSPORT.START) { - // api.dispatch({ type: WEB3.READY }); api.dispatch(TrezorConnectActions.postInit()); } else if (action.type === DEVICE.DISCONNECT) { api.dispatch(TrezorConnectActions.deviceDisconnect(action.device)); From 408d85f19af34fc3aa448f3396d79fbb6899d3ab Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Mon, 3 Sep 2018 17:47:15 +0200 Subject: [PATCH 09/51] logger is back --- src/store.js | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/store.js b/src/store.js index b69d1243..bae277fb 100644 --- a/src/store.js +++ b/src/store.js @@ -37,10 +37,22 @@ if (process.env.NODE_ENV === 'development') { // return pass.length === 0; // }; + const logger = createLogger({ + level: 'info', + predicate: excludeLogger, + collapsed: true, + }); + + const devToolsExtension: ?Function = window.devToolsExtension; + if (typeof devToolsExtension === 'function') { + enhancers.push(devToolsExtension()); + } + composedEnhancers = compose( - applyMiddleware(...middleware, ...services), + applyMiddleware(logger, ...middleware, ...services), ...enhancers, ); + } else { composedEnhancers = compose( applyMiddleware(...middleware, ...services), From 7bb5e7f6e1ed9ed7160c1e89b3eedbc729fa590c Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 5 Sep 2018 15:43:26 +0200 Subject: [PATCH 10/51] trezor-connect@5.0.31 --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9c82e146..8bdac135 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "styled-components": "^3.3.3", "styled-media-query": "^2.0.2", "styled-normalize": "^8.0.0", - "trezor-connect": "5.0.30", + "trezor-connect": "5.0.31", "web3": "1.0.0-beta.35", "webpack": "^4.16.3", "webpack-bundle-analyzer": "^2.13.1", diff --git a/yarn.lock b/yarn.lock index 85cb2b8a..8f23b158 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10139,9 +10139,9 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" -trezor-connect@5.0.30: - version "5.0.30" - resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-5.0.30.tgz#3a71613a6d6e63532c7880c1dc25abca18f0b0e7" +trezor-connect@5.0.31: + version "5.0.31" + resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-5.0.31.tgz#7ecf5e26e154962b638ddc35e68a52d57f4cc107" dependencies: babel-runtime "^6.26.0" events "^1.1.1" From 0b3d6ef3120cd2568b14e370f3a2be3c8c69c443 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 5 Sep 2018 15:44:47 +0200 Subject: [PATCH 11/51] removed Web3Service (unused) --- src/services/Web3Service.js | 28 ---------------------------- src/services/index.js | 1 - 2 files changed, 29 deletions(-) delete mode 100644 src/services/Web3Service.js diff --git a/src/services/Web3Service.js b/src/services/Web3Service.js deleted file mode 100644 index 996e9984..00000000 --- a/src/services/Web3Service.js +++ /dev/null @@ -1,28 +0,0 @@ -/* @flow */ - - -import TrezorConnect, { TRANSPORT } from 'trezor-connect'; -import * as WEB3 from 'actions/constants/web3'; - -import type { - Middleware, - MiddlewareAPI, - MiddlewareDispatch, - Action, -} from 'flowtype'; - -/** - * Middleware - */ -const Web3Service: Middleware = (api: MiddlewareAPI) => (next: MiddlewareDispatch) => (action: Action): Action => { - // pass action - next(action); - - if (action.type === WEB3.START) { - api.dispatch(WalletActions.clearUnavailableDevicesData(prevState, action.device)); - } - - return action; -}; - -export default Web3Service; \ No newline at end of file diff --git a/src/services/index.js b/src/services/index.js index d8aef7c9..b2ed5a5b 100644 --- a/src/services/index.js +++ b/src/services/index.js @@ -4,7 +4,6 @@ import RouterService from './RouterService'; import LocalStorageService from './LocalStorageService'; import CoinmarketcapService from './CoinmarketcapService'; import TrezorConnectService from './TrezorConnectService'; -import Web3Service from './Web3Service'; export default [ WalletService, From a2c7189d3d518355e2f559f781f61753055e542b Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 11:43:52 +0200 Subject: [PATCH 12/51] new lib "ethereum-input-data-decoder" --- package.json | 1 + yarn.lock | 100 +++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 8bdac135..27cbad89 100644 --- a/package.json +++ b/package.json @@ -28,6 +28,7 @@ "color-hash": "^1.0.3", "copy-webpack-plugin": "^4.5.2", "date-fns": "^1.29.0", + "ethereum-input-data-decoder": "^0.0.12", "ethereumjs-tx": "^1.3.3", "ethereumjs-units": "^0.2.0", "ethereumjs-util": "^5.1.4", diff --git a/yarn.lock b/yarn.lock index 8f23b158..3073d0ad 100644 --- a/yarn.lock +++ b/yarn.lock @@ -453,6 +453,10 @@ add-dom-event-listener@1.x: dependencies: object-assign "4.x" +aes-js@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" + ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" @@ -1775,7 +1779,7 @@ bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -3402,6 +3406,15 @@ elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" +elliptic@6.3.3: + version "6.3.3" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + inherits "^2.0.1" + elliptic@^6.0.0, elliptic@^6.2.3: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -3813,6 +3826,20 @@ ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" +ethereum-input-data-decoder@^0.0.12: + version "0.0.12" + resolved "https://registry.yarnpkg.com/ethereum-input-data-decoder/-/ethereum-input-data-decoder-0.0.12.tgz#e7abd764e76ba6942028051717759234cf64ba6d" + dependencies: + ethereumjs-abi "^0.6.4" + ethers "^2.1.3" + +ethereumjs-abi@^0.6.4: + version "0.6.5" + resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" + dependencies: + bn.js "^4.10.0" + ethereumjs-util "^4.3.0" + ethereumjs-tx@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.3.tgz#ece051d3efdbe771ad2a518d61632ca2ab75ecbb" @@ -3826,6 +3853,16 @@ ethereumjs-units@^0.2.0: dependencies: bignumber.js "^2.3.0" +ethereumjs-util@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" + dependencies: + bn.js "^4.8.0" + create-hash "^1.1.2" + keccakjs "^0.2.0" + rlp "^2.0.0" + secp256k1 "^3.0.1" + ethereumjs-util@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.2.tgz#25ba0215cbb4c2f0b108a6f96af2a2e62e45921f" @@ -3851,6 +3888,49 @@ ethereumjs-util@^5.1.4: safe-buffer "^5.1.1" secp256k1 "^3.0.1" +ethers-contracts@2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ethers-contracts/-/ethers-contracts-2.2.1.tgz#e2bf5dd5e157313ba454b50c646c8472fcd0a8b3" + dependencies: + ethers-utils "^2.1.0" + +ethers-providers@2.1.19: + version "2.1.19" + resolved "https://registry.yarnpkg.com/ethers-providers/-/ethers-providers-2.1.19.tgz#d597e298f70cfbf8da207c303af0a5cbed5b4cd2" + dependencies: + ethers-utils "^2.1.0" + inherits "2.0.1" + xmlhttprequest "1.8.0" + +ethers-utils@2.1.11, ethers-utils@^2.1.0: + version "2.1.11" + resolved "https://registry.yarnpkg.com/ethers-utils/-/ethers-utils-2.1.11.tgz#b27535ca3226118be300211c39c896b1e5e21641" + dependencies: + bn.js "^4.4.0" + hash.js "^1.0.0" + js-sha3 "0.5.7" + xmlhttprequest "1.8.0" + +ethers-wallet@2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/ethers-wallet/-/ethers-wallet-2.1.8.tgz#2819a51d439525ddedeec84992b0b83f59da3cef" + dependencies: + aes-js "3.0.0" + elliptic "6.3.3" + ethers-utils "^2.1.0" + scrypt-js "2.0.3" + setimmediate "1.0.4" + uuid "2.0.1" + +ethers@^2.1.3: + version "2.2.6" + resolved "http://registry.npmjs.org/ethers/-/ethers-2.2.6.tgz#d1081c3e132930686fa7a3b508ae4d0ef8bd986a" + dependencies: + ethers-contracts "2.2.1" + ethers-providers "2.1.19" + ethers-utils "2.1.11" + ethers-wallet "2.1.8" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -5958,6 +6038,10 @@ js-base64@^2.1.9: version "2.3.2" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.2.tgz#a79a923666372b580f8e27f51845c6f7e8fbfbaf" +js-sha3@0.5.7: + version "0.5.7" + resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" + js-sha3@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" @@ -6143,7 +6227,7 @@ keccak@^1.0.2: nan "^2.2.1" safe-buffer "^5.1.0" -keccakjs@^0.2.1: +keccakjs@^0.2.0, keccakjs@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" dependencies: @@ -9066,6 +9150,10 @@ scoped-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" +scrypt-js@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" + scrypt.js@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" @@ -9201,6 +9289,10 @@ set-value@^2.0.0: is-plain-object "^2.0.3" split-string "^3.0.1" +setimmediate@1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" + setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -11178,6 +11270,10 @@ xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" +xmlhttprequest@1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" + xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From cd48bd2cc02e9cf54f767b799d19dc457ca220b0 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 11:49:49 +0200 Subject: [PATCH 13/51] blockchain actions and reducer --- src/actions/BlockchainActions.js | 181 ++++++++++++++++++++++++++++ src/actions/constants/blockchain.js | 7 ++ src/reducers/BlockchainReducer.js | 62 ++++++++++ src/reducers/index.js | 2 + 4 files changed, 252 insertions(+) create mode 100644 src/actions/BlockchainActions.js create mode 100644 src/actions/constants/blockchain.js create mode 100644 src/reducers/BlockchainReducer.js diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js new file mode 100644 index 00000000..72f9c111 --- /dev/null +++ b/src/actions/BlockchainActions.js @@ -0,0 +1,181 @@ +/* @flow */ + +import Web3 from 'web3'; +import HDKey from 'hdkey'; + +import EthereumjsUtil from 'ethereumjs-util'; +import EthereumjsUnits from 'ethereumjs-units'; +import EthereumjsTx from 'ethereumjs-tx'; +import TrezorConnect from 'trezor-connect'; +import BigNumber from 'bignumber.js'; + +import type { EstimateGasOptions } from 'web3'; +import type { TransactionStatus, TransactionReceipt } from 'web3'; +import { strip } from 'utils/ethUtils'; +import * as BLOCKCHAIN from 'actions/constants/blockchain'; +import * as WEB3 from 'actions/constants/web3'; +import * as PENDING from 'actions/constants/pendingTx'; + +import * as Web3Actions from './Web3Actions'; + +import type { + TrezorDevice, + Dispatch, + GetState, + Action, + AsyncAction, + PromiseAction, + ThunkAction, + AccountDiscovery, + EthereumTxRequest +} from 'flowtype'; + +import type { Token } from 'reducers/TokensReducer'; +import type { NetworkToken } from 'reducers/LocalStorageReducer'; + +export type BlockchainAction = { + type: typeof BLOCKCHAIN.START | typeof BLOCKCHAIN.CONNECTING, + network: string, +} | { + type: typeof BLOCKCHAIN.STOP, + network: string, +}; + +export const discoverAccount = (device: TrezorDevice, xpub: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + // get data from connect + // Temporary disabled, enable after trezor-connect@5.0.32 release + const txs = await TrezorConnect.ethereumGetAccountInfo({ + account: { + address: xpub, + // block: 3984156, + block: 0, + transactions: 0 + }, + coin: network, + }); + + if (!txs.success) { + throw new Error(txs.payload.error); + } + + // blockbook web3 fallback + const web3account = await dispatch( Web3Actions.discoverAccount(xpub, network) ); + // return { transactions: txs.payload, ...web3account }; + return { + transactions: txs.payload.transactions, + block: txs.payload.block, + balance: web3account.balance, + nonce: web3account.nonce, + }; +}; + +export const getTokenInfo = (input: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + return await dispatch( Web3Actions.getTokenInfo(input, network) ); +} + +export const getTokenBalance = (token: Token): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + return await dispatch( Web3Actions.getTokenBalance(token) ); +} + +export const getGasPrice = (network: string, defaultGasPrice: number): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + try { + const gasPrice = await dispatch( Web3Actions.getCurrentGasPrice(network) ); + return new BigNumber(gasPrice); + } catch (error) { + return new BigNumber(defaultGasPrice); + } +} + +export const estimateGasLimit = (network: string, data: string, value: string, gasPrice: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + return await dispatch( Web3Actions.estimateGasLimit(network, { to: '', data, value, gasPrice }) ); +} + +export const onBlockMined = (network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + + // try to resolve pending transactions + // await dispatch( Web3Actions.resolvePendingTransactions(network) ); + + // get network accounts + // const accounts: Array = getState().accounts.filter(a => a.network === network).map(a => { + // return { + // address: a.address, + // block: a.block, + // transactions: a.transactions + // } + // }); + const accounts: Array = getState().accounts.filter(a => a.network === network); + + // find out which account changed + const response = await TrezorConnect.ethereumGetAccountInfo({ + accounts, + coin: network, + }); + + if (!response.success) { + + } else { + response.payload.forEach((a, i) => { + if (a.transactions > 0) { + dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) + } + }); + } + + //return await dispatch( Web3Actions.estimateGasLimit(network, { to: '', data, value, gasPrice }) ); + console.warn("onBlockMined", response) +} + +export const onNotification = (payload: any): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + + // this event can be triggered multiple times + // 1. check if pair [txid + address] is already in reducer + const address: string = EthereumjsUtil.toChecksumAddress(payload.tx.address); + const txInfo = await dispatch( Web3Actions.getPendingInfo(payload.coin, payload.tx.txid) ); + + // const exists = getState().pending.filter(p => p.id === payload.tx.txid && p.address === address); + const exists = getState().pending.filter(p => { + console.warn("CHECK", p.address === address, p.id === payload.tx.txid, p) + return p.address === address; + }); + if (exists.length < 1) { + + console.warn("TXINFO!", txInfo); + if (txInfo) { + dispatch({ + type: PENDING.ADD, + payload: { + id: payload.tx.txid, + network: payload.coin, + currency: "tETH", + amount: txInfo.value, + total: "0", + tx: {}, + nonce: txInfo.nonce, + address, + } + }); + } else { + // tx info not found (yet?) + // dispatch({ + // type: PENDING.ADD_UNKNOWN, + // payload: { + // network: payload.coin, + // ...payload.tx, + // } + // }); + } + } + + console.warn("WEB3", payload, exists, getState().pending, address) +} + + +export const subscribe = (network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const addresses: Array = getState().accounts.filter(a => a.network === network).map(a => a.address); + // $FlowIssue: trezor-connect@5.0.32 + return await TrezorConnect.blockchainSubscribe({ + // accounts: addresses, + accounts: [], + coin: network + }); +} \ No newline at end of file diff --git a/src/actions/constants/blockchain.js b/src/actions/constants/blockchain.js new file mode 100644 index 00000000..f0addc68 --- /dev/null +++ b/src/actions/constants/blockchain.js @@ -0,0 +1,7 @@ +/* @flow */ + +export const START: 'backend__start' = 'backend__start'; +export const STOP: 'backend__stop' = 'backend__stop'; +export const CONNECTING: 'backend__connecting' = 'backend__connecting'; +export const CONNECTED: 'backend__connected' = 'backend__connected'; +export const DISCONNECTED: 'backend__disconnected' = 'backend__disconnected'; \ No newline at end of file diff --git a/src/reducers/BlockchainReducer.js b/src/reducers/BlockchainReducer.js new file mode 100644 index 00000000..92de9c27 --- /dev/null +++ b/src/reducers/BlockchainReducer.js @@ -0,0 +1,62 @@ +/* @flow */ + +import { BLOCKCHAIN } from 'trezor-connect'; + +import type { Action } from 'flowtype'; + +export type BlockchainNetwork = { + +name: string; + connected: boolean; +} + +export type State = Array; + +export const initialState: State = []; + +const find = (state: State, name: string): number => { + return state.findIndex(b => b.name === name); +} + +const connect = (state: State, action: any): State => { + const network: BlockchainNetwork = { + name: action.payload.coin, + connected: true, + } + const newState: State = [...state]; + const index: number = find(newState, action.payload.coin); + if (index >= 0) { + newState[index] = network; + } else { + newState.push(network); + } + return newState; +}; + +const disconnect = (state: State, action: any): State => { + const network: BlockchainNetwork = { + name: action.payload.coin, + connected: false, + } + const newState: State = [...state]; + const index: number = find(newState, action.payload.coin); + if (index >= 0) { + newState[index] = network; + } else { + newState.push(network); + } + return newState; +}; + + +export default (state: State = initialState, action: Action): State => { + switch (action.type) { + + case BLOCKCHAIN.CONNECT: + return connect(state, action); + case BLOCKCHAIN.ERROR: + return disconnect(state, action); + + default: + return state; + } +}; \ No newline at end of file diff --git a/src/reducers/index.js b/src/reducers/index.js index 1d0be6a7..ed6f1aa6 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -19,6 +19,7 @@ import pending from 'reducers/PendingTxReducer'; import fiat from 'reducers/FiatRateReducer'; import wallet from 'reducers/WalletReducer'; import devices from 'reducers/DevicesReducer'; +import blockchain from 'reducers/BlockchainReducer'; const reducers = { router: routerReducer, @@ -39,6 +40,7 @@ const reducers = { fiat, wallet, devices, + blockchain }; export type Reducers = typeof reducers; From 84999a90610887297672f2b6666f17a2e5ea825f Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 13:05:27 +0200 Subject: [PATCH 14/51] ropsten tokens (trezor) --- public/data/ropstenTokens.json | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/public/data/ropstenTokens.json b/public/data/ropstenTokens.json index 082693ce..f4d716ae 100644 --- a/public/data/ropstenTokens.json +++ b/public/data/ropstenTokens.json @@ -4,5 +4,17 @@ "name": "PLASMA", "symbol" :"PLASMA", "decimals": 6 + }, + { + "address": "0x58cda554935e4a1f2acbe15f8757400af275e084", + "name": "Trezor01", + "symbol": "T01", + "decimals": 0 + }, + { + "address": "0xa04761a776af2bed654a041430a063fd9d20fad4", + "name": "Trezor13", + "symbol": "T013", + "decimals": 13 } ] \ No newline at end of file From 5babe75cda4544e34f6621a4e2ae3bec5462f56a Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 13:05:48 +0200 Subject: [PATCH 15/51] update flowtype --- src/flowtype/index.js | 50 ++++++++ src/flowtype/npm/bignumber.js | 4 +- src/flowtype/npm/redux_v3.x.x.js | 8 +- src/flowtype/npm/web3.js | 190 ++++++++++++------------------- 4 files changed, 133 insertions(+), 119 deletions(-) diff --git a/src/flowtype/index.js b/src/flowtype/index.js index 025df015..3fd602a0 100644 --- a/src/flowtype/index.js +++ b/src/flowtype/index.js @@ -7,6 +7,8 @@ import type { Middleware as ReduxMiddleware, ThunkAction as ReduxThunkAction, AsyncAction as ReduxAsyncAction, + PromiseAction as ReduxPromiseAction, + ThunkDispatch as ReduxThunkDispatch, PlainDispatch as ReduxPlainDispatch, } from 'redux'; @@ -15,6 +17,7 @@ import type { ReducersState } from 'reducers'; // Actions import type { SelectedAccountAction } from 'actions/SelectedAccountActions'; import type { AccountAction } from 'actions/AccountsActions'; +import type { BlockchainAction } from 'actions/BlockchainActions'; import type { DiscoveryAction } from 'actions/DiscoveryActions'; import type { StorageAction } from 'actions/LocalStorageActions'; import type { LogAction } from 'actions/LogActions'; @@ -37,6 +40,7 @@ import type { DeviceFirmwareStatus, DeviceMessageType, TransportMessageType, + BlockchainMessageType, UiMessageType, } from 'trezor-connect'; @@ -102,6 +106,11 @@ type UiEventAction = { // }, } +type BlockchainEventAction = { + type: BlockchainMessageType, + payload: any, +} + // TODO: join this message with uiMessage type IFrameHandshake = { type: 'iframe_handshake', @@ -114,9 +123,11 @@ export type Action = | TransportEventAction | DeviceEventAction | UiEventAction + | BlockchainEventAction | SelectedAccountAction | AccountAction + | BlockchainAction | DiscoveryAction | StorageAction | LogAction @@ -154,6 +165,45 @@ export type Middleware = ReduxMiddleware; export type ThunkAction = ReduxThunkAction; export type AsyncAction = ReduxAsyncAction; +export type PromiseAction = ReduxPromiseAction; export type Store = ReduxStore; export type GetState = () => State; + + +// temporary types +export type AccountDiscovery = { + transactions: number; + block: number; + balance: string; + nonce: number; +} + +import type { Token } from 'reducers/TokensReducer'; + +export type EthereumTxRequest = { + network: string; + token: ?Token; + from: string; + to: string; + amount: string; + data: string; + gasLimit: string; + gasPrice: string; + nonce: number; +} +// copypaste from trezor-connect +export type EthereumPreparedTx = { + to: string, + value: string, + gasPrice: string, + gasLimit: string, + nonce: string, + data?: string, + chainId?: number, + txType?: number, + v: string, + r: string, + s: string, +} + diff --git a/src/flowtype/npm/bignumber.js b/src/flowtype/npm/bignumber.js index 5fa3a6fe..9f34ac28 100644 --- a/src/flowtype/npm/bignumber.js +++ b/src/flowtype/npm/bignumber.js @@ -1,3 +1,5 @@ +/* @flow */ + declare module 'bignumber.js' { declare type $npm$big$number$object = number | string | T_BigNumber declare type $npm$cmp$result = -1 | 0 | 1 @@ -24,7 +26,7 @@ declare module 'bignumber.js' { constructor(value: $npm$big$number$object): T_BigNumber; // Methods - abs(): BigNumber; + abs(): T_BigNumber; cmp(n: $npm$big$number$object): $npm$cmp$result; div(n: $npm$big$number$object): T_BigNumber; dividedBy(n: $npm$big$number$object): T_BigNumber; diff --git a/src/flowtype/npm/redux_v3.x.x.js b/src/flowtype/npm/redux_v3.x.x.js index d0717bdf..cdd88212 100644 --- a/src/flowtype/npm/redux_v3.x.x.js +++ b/src/flowtype/npm/redux_v3.x.x.js @@ -1,10 +1,12 @@ +/* @flow */ + declare module 'redux' { /* S = State A = Action D = Dispatch - + R = Promise response */ declare export type DispatchAPI = (action: A) => A; @@ -13,12 +15,14 @@ declare module 'redux' { declare export type ThunkAction = (dispatch: ReduxDispatch, getState: () => S) => void; declare export type AsyncAction = (dispatch: ReduxDispatch, getState: () => S) => Promise; + declare export type PromiseAction = (dispatch: ReduxDispatch, getState: () => S) => Promise; declare export type ThunkDispatch = (action: ThunkAction) => void; declare export type AsyncDispatch = (action: AsyncAction) => Promise; + declare export type PromiseDispatch = (action: PromiseAction) => Promise; declare export type PlainDispatch}> = DispatchAPI; /* NEW: Dispatch is now a combination of these different dispatch types */ - declare export type ReduxDispatch = PlainDispatch & ThunkDispatch & AsyncDispatch; + declare export type ReduxDispatch = PlainDispatch & ThunkDispatch & AsyncDispatch & PromiseDispatch; declare export type MiddlewareAPI = { // dispatch: Dispatch; diff --git a/src/flowtype/npm/web3.js b/src/flowtype/npm/web3.js index 81e27543..eff45ab0 100644 --- a/src/flowtype/npm/web3.js +++ b/src/flowtype/npm/web3.js @@ -1,8 +1,10 @@ +/* @flow */ + import type BigNumber from 'bignumber.js'; import type { EthereumUnitT, EthereumAddressT } from 'ethereum-types'; declare module 'web3' { - declare type ProviderT = { + declare type HttpProviderT = { host: string; timeout: number; isConnected: () => boolean; @@ -10,14 +12,25 @@ declare module 'web3' { sendAsync: (payload: any, callback: (error: Error, result: any) => void) => any; }; + declare type WebsocketProviderT = { + on: (type: string, callback: () => any) => void; + removeAllListeners: (type: string) => void; + reset: () => void; + connected: boolean; + } + declare class Web3T { static providers: { - HttpProvider: (host: string, timeout?: number) => ProviderT; + HttpProvider: (host: string, timeout?: number) => HttpProviderT; + WebsocketProvider: (host: string, options?: any) => WebsocketProviderT; }; - constructor(ProviderT): Web3T; - currentProvider: ProviderT; + // constructor(HttpProviderT): Web3T; + constructor(WebsocketProviderT): Web3T; + // currentProvider: HttpProviderT; + currentProvider: WebsocketProviderT; eth: Eth; + utils: Utils; toHex: (str: string | number) => string; isAddress: (address: string) => boolean; @@ -78,20 +91,33 @@ declare module 'web3' { transactionIndex: number } + //declare function F_CardanoGetAddress(params: (P.$Common & CARDANO.$CardanoGetAddress)): Promise; + //declare function F_CardanoGetAddress(params: (P.$Common & { bundle: Array })): Promise; + + declare type PromiseEvent = { + once: typeof F_PromiseEventOn; + on: typeof F_PromiseEventOn; + off: (type: string, callback: Function) => PromiseEvent; + then: () => (result: T) => PromiseEvent; + catch: () => (error: Error) => PromiseEvent; + } + + declare function F_PromiseEventOn(type: 'transactionHash', callback: (hash: string) => void): PromiseEvent; + declare function F_PromiseEventOn(type: 'receipt', callback: (receipt: TransactionReceipt) => void): PromiseEvent; + declare function F_PromiseEventOn(type: 'confirmation', callback: (confirmations: number, receipt: TransactionReceipt) => void): PromiseEvent; + declare function F_PromiseEventOn(type: 'error', callback: (error: Error) => void): PromiseEvent; + declare class Eth { - getGasPrice: (callback: (error: Error, gasPrice: string) => void) => void, - getBalance: (address: string, callback: (error: Error, balance: BigNumber) => void) => void, - getTransactionCount: (address: string, callback: (error: Error, result: number) => void) => void, - getTransaction: (txid: string, callback: (error: Error, result: TransactionStatus) => void) => void, - getTransactionReceipt: (txid: string, callback: (error: Error, result: TransactionReceipt) => void) => void, - getBlockNumber: (callback: (error: Error, blockNumber: number) => void) => void, - getBlock: (hash: string, callback: (error: Error, result: any) => void) => void, - // getAccounts: (callback: (error: Error, accounts: Array) => void) => void, - // sign: (payload: string, signer: EthereumAddressT) => Promise, - contract: (abi: Array) => ContractFactory, - estimateGas: (options: EstimateGasOptions, callback: (error: ?Error, gas: ?number) => void) => void, - sendRawTransaction: (tx: any, callback: (error: Error, result: string) => void) => void, - filter: (type: string) => Filter; // return intance with "watch" + getBalance: (address: string) => Promise; + getTransactionCount: (address: string) => Promise; + estimateGas: (options: EstimateGasOptions) => Promise; + getGasPrice: () => Promise; + getBlockNumber: () => Promise; + Contract: (abi: Array, options?: any) => Contract; + sendSignedTransaction: (tx: string) => PromiseEvent; + getTransaction: (txid: string) => Promise; + getTransactionReceipt: (txid: string) => Promise; + subscribe: (type: string, callback: Function) => any; } declare export class Filter { @@ -99,108 +125,40 @@ declare module 'web3' { stopWatching: (callback: any) => void, } - declare export class ContractFactory { - // constructor(abi: Array); - eth: Eth; - abi: Array; - at: (address: string, callback: ?(error: Error, contract: Contract) => void) => Contract; // TODO + declare type ContractMethod = { + call: () => Promise; } declare export class Contract { - name: { - call: (callback: (error: Error, name: string) => void) => void; - }, - symbol: { - call: (callback: (error: Error, symbol: string) => void) => void; - }, - decimals: { - call: (callback: (error: Error, decimals: BigNumber) => void) => void; - }, - balanceOf: (address: string, callback: (error: Error, balance: BigNumber) => void) => void, - transfer: any, + clone: () => Contract; + + options: { + address: string; + jsonInterface: JSON; + }; + + methods: { + name: () => ContractMethod; + symbol: () => ContractMethod; + decimals: () => ContractMethod; + balanceOf: (address: string) => ContractMethod; + transfer: (to: string, amount: any) => { + encodeABI: () => string; + } + }; } - declare export default typeof Web3T; -} - - -// -// - - -/*declare module 'web3' { - - module.exports = { - eth: { - _requestManager: any; - iban: { - (iban: string): void; - fromAddress: (address: string) => any; - fromBban: (bban: string) => any; - createIndirect: (options: any) => any; - isValid: (iban: string) => boolean; - }; - sendIBANTransaction: any; - contract: (abi: any) => { - eth: any; - abi: any[]; - new: (...args: any[]) => { - _eth: any; - transactionHash: any; - address: any; - abi: any[]; - }; - at: (address: any, callback: Function) => any; - getData: (...args: any[]) => any; - }; - filter: (fil: any, callback: any, filterCreationErrorCallback: any) => { - requestManager: any; - options: any; - implementation: { - [x: string]: any; - }; - filterId: any; - callbacks: any[]; - getLogsCallbacks: any[]; - pollFilters: any[]; - formatter: any; - watch: (callback: any) => any; - stopWatching: (callback: any) => any; - get: (callback: any) => any; - }; - namereg: () => { - eth: any; - abi: any[]; - new: (...args: any[]) => { - _eth: any; - transactionHash: any; - address: any; - abi: any[]; - }; - at: (address: any, callback: Function) => any; - getData: (...args: any[]) => any; - }; - icapNamereg: () => { - eth: any; - abi: any[]; - new: (...args: any[]) => { - _eth: any; - transactionHash: any; - address: any; - abi: any[]; - }; - at: (address: any, callback: Function) => any; - getData: (...args: any[]) => any; - }; - isSyncing: (callback: any) => { - requestManager: any; - pollId: string; - callbacks: any[]; - lastSyncState: boolean; - addCallback: (callback: any) => any; - stopWatching: () => void; - }; - } + declare class Utils { + toHex: (str: string | number) => string; + hexToNumberString: (str: string) => string; + + isAddress: (address: string) => boolean; + toWei: (number: BigNumber, unit?: EthereumUnitT) => BigNumber; + toWei: (number: string, unit?: EthereumUnitT) => string; + toDecimal: (number: BigNumber) => number; + toDecimal: (number: string) => number; + soliditySha3: (payload: string | number | BigNumber | Object) => String; } -} -*/ \ No newline at end of file + + declare export default typeof Web3T; +} \ No newline at end of file From afc6135f09b0c7d4a851fb4a72161fd2fb164605 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 13:06:26 +0200 Subject: [PATCH 16/51] fix: account summary default view --- src/views/Wallet/views/AccountSummary/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/views/Wallet/views/AccountSummary/index.js b/src/views/Wallet/views/AccountSummary/index.js index 1996fc99..67d976db 100644 --- a/src/views/Wallet/views/AccountSummary/index.js +++ b/src/views/Wallet/views/AccountSummary/index.js @@ -69,7 +69,7 @@ const AccountSummary = (props: Props) => { } = props.selectedAccount; // flow - if (!device || !account || !network) return null; + if (!device || !account || !network) return ; const explorerLink: string = `${network.explorer.address}${account.address}`; const pendingAmount: BigNumber = stateUtils.getPendingAmount(pending, network.symbol); From 6c387967f9db728394142fb41e4890d3c51dd8df Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 13:23:43 +0200 Subject: [PATCH 17/51] added web3 to config --- public/data/appConfig.json | 33 ++++++++++----------------------- 1 file changed, 10 insertions(+), 23 deletions(-) diff --git a/public/data/appConfig.json b/public/data/appConfig.json index bf0d4277..8aa1cee6 100644 --- a/public/data/appConfig.json +++ b/public/data/appConfig.json @@ -19,6 +19,9 @@ ] } ], + "web3": [ + "wss://eth2.trezor.io/geth" + ], "explorer": { "tx": "https://etherscan.io/tx/", "address": "https://etherscan.io/address/" @@ -43,6 +46,9 @@ ] } ], + "web3": [ + "wss://etc2.trezor.io/geth" + ], "explorer": { "tx": "https://gastracker.io/tx/", "address": "https://gastracker.io/addr/" @@ -67,33 +73,14 @@ ] } ], + "web3": [ + "wss://ropsten3.trezor.io", + "wss://ropsten1.trezor.io/geth" + ], "explorer": { "tx": "https://ropsten.etherscan.io/tx/", "address": "https://ropsten.etherscan.io/address/" } - }, - { - "name": "Ethereum Rinkeby", - "symbol": "tETH", - "network": "rinkeby", - "chainId": 4, - "bip44": "m/44'/61'/0'/0", - "defaultGasPrice": 64, - "defaultGasLimit": 21000, - "defaultGasLimitTokens": 200000, - "tokens": "./data/rinkebyTokens.json", - "backends": [ - { - "name": "TREZOR Wallet - Ethereum", - "urls": [ - "https://rinkeby.infura.io/QGyVKozSUEh2YhL4s2G4" - ] - } - ], - "explorer": { - "tx": "https://rinkeby.etherscan.io/tx/", - "address": "https://rinkeby.etherscan.io/address/" - } } ], From a913759ef402a2fbe4db6713ca2a5d571f6267d7 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 13:24:07 +0200 Subject: [PATCH 18/51] web3 reducer (new types) --- src/reducers/Web3Reducer.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/reducers/Web3Reducer.js b/src/reducers/Web3Reducer.js index 40903eec..d0d45d23 100644 --- a/src/reducers/Web3Reducer.js +++ b/src/reducers/Web3Reducer.js @@ -3,7 +3,8 @@ import Web3 from 'web3'; -import type { ContractFactory } from 'web3'; +import type { Contract } from 'web3'; +import * as STORAGE from 'actions/constants/localStorage'; import * as WEB3 from 'actions/constants/web3'; import type { Action } from 'flowtype'; @@ -18,7 +19,7 @@ export type Web3Instance = { chainId: number; latestBlock: any; gasPrice: string; - erc20: ContractFactory; + erc20: Contract; } export type State = Array; @@ -26,8 +27,13 @@ export type State = Array; const initialState: State = []; const createWeb3 = (state: State, instance: Web3Instance): State => { + const index: number = state.findIndex(w3 => w3.network === instance.network); const newState: Array = [...state]; - newState.push(instance); + if (index >= 0) { + newState[index] = instance; + } else { + newState.push(instance); + } return newState; }; From 26978fe9840704071e5c9dbd53fbb902b2f83d7c Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 13:25:21 +0200 Subject: [PATCH 19/51] web3 actions splitted to blockchain actions --- src/actions/AccountsActions.js | 28 +- src/actions/BlockchainActions.js | 7 +- src/actions/DiscoveryActions.js | 272 +++++++----- src/actions/PendingTxActions.js | 3 + src/actions/SendFormActions.js | 138 +++--- src/actions/TokenActions.js | 13 +- src/actions/TrezorConnectActions.js | 17 +- src/actions/Web3Actions.js | 608 +++++++++++++-------------- src/actions/constants/account.js | 1 + src/actions/constants/pendingTx.js | 1 + src/services/TrezorConnectService.js | 12 +- 11 files changed, 590 insertions(+), 510 deletions(-) diff --git a/src/actions/AccountsActions.js b/src/actions/AccountsActions.js index 2bc3a8f1..65ab5d50 100644 --- a/src/actions/AccountsActions.js +++ b/src/actions/AccountsActions.js @@ -2,7 +2,7 @@ import * as ACCOUNT from 'actions/constants/account'; import type { Action, TrezorDevice } from 'flowtype'; -import type { State } from 'reducers/AccountsReducer'; +import type { Account, State } from 'reducers/AccountsReducer'; export type AccountFromStorageAction = { type: typeof ACCOUNT.FROM_STORAGE, @@ -11,11 +11,12 @@ export type AccountFromStorageAction = { export type AccountCreateAction = { type: typeof ACCOUNT.CREATE, - device: TrezorDevice, - network: string, - index: number, - path: Array, - address: string + payload: Account, +} + +export type AccountUpdateAction = { + type: typeof ACCOUNT.UPDATE, + payload: Account, } export type AccountSetBalanceAction = { @@ -36,9 +37,10 @@ export type AccountSetNonceAction = { export type AccountAction = AccountFromStorageAction - | AccountCreateAction - | AccountSetBalanceAction - | AccountSetNonceAction; + | AccountCreateAction + | AccountUpdateAction + | AccountSetBalanceAction + | AccountSetNonceAction; export const setBalance = (address: string, network: string, deviceState: string, balance: string): Action => ({ type: ACCOUNT.SET_BALANCE, @@ -55,3 +57,11 @@ export const setNonce = (address: string, network: string, deviceState: string, deviceState, nonce, }); +<<<<<<< HEAD +======= + +export const update = (account: Account): Action => ({ + type: ACCOUNT.UPDATE, + payload: account +}); +>>>>>>> web3 actions splitted to blockchain actions diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 72f9c111..3e63144f 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -116,7 +116,7 @@ export const onBlockMined = (network: string): PromiseAction => async (dis } else { response.payload.forEach((a, i) => { if (a.transactions > 0) { - dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) + // dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) } }); } @@ -134,16 +134,14 @@ export const onNotification = (payload: any): PromiseAction => async (disp // const exists = getState().pending.filter(p => p.id === payload.tx.txid && p.address === address); const exists = getState().pending.filter(p => { - console.warn("CHECK", p.address === address, p.id === payload.tx.txid, p) return p.address === address; }); if (exists.length < 1) { - - console.warn("TXINFO!", txInfo); if (txInfo) { dispatch({ type: PENDING.ADD, payload: { + type: 'send', id: payload.tx.txid, network: payload.coin, currency: "tETH", @@ -152,6 +150,7 @@ export const onNotification = (payload: any): PromiseAction => async (disp tx: {}, nonce: txInfo.nonce, address, + rejected: false } }); } else { diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index b31534a0..2f04b96d 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -10,8 +10,10 @@ import type { } from 'flowtype'; import type { Discovery, State } from 'reducers/DiscoveryReducer'; import * as AccountsActions from './AccountsActions'; +import * as Web3Actions from './Web3Actions'; -import { getNonceAsync, getBalanceAsync } from './Web3Actions'; +import * as BlockchainActions from './BlockchainActions'; +import { setBalance as setTokenBalance } from './TokenActions'; export type DiscoveryStartAction = { @@ -44,15 +46,123 @@ export type DiscoveryAction = { type: typeof DISCOVERY.FROM_STORAGE, payload: State } | DiscoveryStartAction - | DiscoveryWaitingAction - | DiscoveryStopAction - | DiscoveryCompleteAction; + | DiscoveryWaitingAction + | DiscoveryStopAction + | DiscoveryCompleteAction; +export const start = (device: TrezorDevice, network: string, ignoreCompleted?: boolean): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { + const selected = getState().wallet.selectedDevice; + if (!selected) { + // TODO: throw error + console.error('Start discovery: no selected device', device); + return; + } if (selected.path !== device.path) { + console.error('Start discovery: requested device is not selected', device, selected); + return; + } if (!selected.state) { + console.warn("Start discovery: Selected device wasn't authenticated yet..."); + return; + } if (selected.connected && !selected.available) { + console.warn('Start discovery: Selected device is unavailable...'); + return; + } + + const discovery: State = getState().discovery; + const discoveryProcess: ?Discovery = discovery.find(d => d.deviceState === device.state && d.network === network); + + if (!selected.connected && (!discoveryProcess || !discoveryProcess.completed)) { + dispatch({ + type: DISCOVERY.WAITING_FOR_DEVICE, + device, + network, + }); + return; + } + + const blockchain = getState().blockchain.find(b => b.name === network); + if (blockchain && !blockchain.connected) { + console.error("NO BACKEND!") // TODO + return; + } + + if (!discoveryProcess) { + dispatch(begin(device, network)) + } else if (discoveryProcess.completed && !ignoreCompleted) { + dispatch({ + type: DISCOVERY.COMPLETE, + device, + network, + }); + } else if (discoveryProcess.interrupted || discoveryProcess.waitingForDevice) { + // discovery cycle was interrupted + // start from beginning + dispatch(begin(device, network)); + } else { + dispatch(discoverAccount(device, discoveryProcess)); + } +}; -// Because start() is calling begin() and begin() is calling start() one of them must be declared first -// otherwise eslint will start complaining -let begin; +// first iteration +// generate public key for this account +// start discovery process +const begin = (device: TrezorDevice, network: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const { config } = getState().localStorage; + const coinToDiscover = config.coins.find(c => c.network === network); + if (!coinToDiscover) return; + dispatch({ + type: DISCOVERY.WAITING_FOR_DEVICE, + device, + network, + }); + + // get xpub from TREZOR + const response = await TrezorConnect.getPublicKey({ + device: { + path: device.path, + instance: device.instance, + state: device.state, + }, + path: coinToDiscover.bip44, + keepSession: true, // acquire and hold session + useEmptyPassphrase: !device.instance, + }); + + // handle TREZOR response error + if (!response.success) { + dispatch({ + type: NOTIFICATION.ADD, + payload: { + type: 'error', + title: 'Discovery error', + message: response.payload.error, + cancelable: true, + actions: [ + { + label: 'Try again', + callback: () => { + dispatch(start(device, network)); + }, + }, + ], + }, + }); + return; + } + + // send data to reducer + dispatch({ + type: DISCOVERY.START, + network: coinToDiscover.network, + device, + publicKey: response.payload.publicKey, + chainCode: response.payload.chainCode, + basePath, + }); + + // next iteration + dispatch(start(device, network)); +}; const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { const { completed } = discoveryProcess; @@ -66,64 +176,53 @@ const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): Asy // TODO: check if address was created before - // verify address with TREZOR - const verifyAddress = await TrezorConnect.ethereumGetAddress({ - device: { - path: device.path, - instance: device.instance, - state: device.state, - }, - path, - showOnTrezor: false, - keepSession: true, - useEmptyPassphrase: !device.instance, - }); - if (discoveryProcess.interrupted) return; + try { + const account = await dispatch( BlockchainActions.discoverAccount(device, ethAddress, network) ); + if (discoveryProcess.interrupted) return; - // TODO: with block-book (Martin) - // const discoveryA = await TrezorConnect.accountDiscovery({ - // device: { - // path: device.path, - // instance: device.instance, - // state: device.state - // }, - // }); - // if (discoveryProcess.interrupted) return; - - if (verifyAddress && verifyAddress.success) { - //const trezorAddress: string = '0x' + verifyAddress.payload.address; - const trezorAddress: string = EthereumjsUtil.toChecksumAddress(verifyAddress.payload.address); - if (trezorAddress !== ethAddress) { - // throw inconsistent state error - console.warn('Inconsistent state', trezorAddress, ethAddress); + // const accountIsEmpty = account.transactions <= 0 && account.nonce <= 0 && account.balance === '0'; + const accountIsEmpty = account.nonce <= 0 && account.balance === '0'; + if (!accountIsEmpty || (accountIsEmpty && completed) || (accountIsEmpty && discoveryProcess.accountIndex === 0)) { dispatch({ - type: NOTIFICATION.ADD, + type: ACCOUNT.CREATE, payload: { - type: 'error', - title: 'Address validation error', - message: `Addresses are different. TREZOR: ${trezorAddress} HDKey: ${ethAddress}`, - cancelable: true, - actions: [ - { - label: 'Try again', - callback: () => { - dispatch(start(device, discoveryProcess.network)); - }, - }, - ], - }, + index: discoveryProcess.accountIndex, + loaded: true, + network, + deviceID: device.features ? device.features.device_id : '0', + deviceState: device.state || '0', + addressPath: path, + address: ethAddress, + balance: account.balance, + nonce: account.nonce, + block: account.block, + transactions: account.transactions + } }); - return; + + dispatch( Web3Actions.getTxInput() ); } - } else { - // handle TREZOR communication error + + if (accountIsEmpty) { + dispatch( finish(device, discoveryProcess) ); + } else { + if (!completed) { dispatch( discoverAccount(device, discoveryProcess) ); } + } + + } catch (error) { + + dispatch({ + type: DISCOVERY.STOP, + device + }); + dispatch({ type: NOTIFICATION.ADD, payload: { type: 'error', - title: 'Address validation error', - message: verifyAddress.payload.error, + title: 'Account discovery error', + message: error.message, cancelable: true, actions: [ { @@ -135,56 +234,33 @@ const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): Asy ], }, }); - return; } +}; - const web3instance = getState().web3.find(w3 => w3.network === network); - if (!web3instance) return; +const finish = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - const balance = await getBalanceAsync(web3instance.web3, ethAddress); - if (discoveryProcess.interrupted) return; - const nonce: number = await getNonceAsync(web3instance.web3, ethAddress); - if (discoveryProcess.interrupted) return; + console.warn("FINISH!"); + await TrezorConnect.getFeatures({ + device: { + path: device.path, + instance: device.instance, + state: device.state, + }, + keepSession: false, + useEmptyPassphrase: !device.instance, + }); - const addressIsEmpty = nonce < 1 && !balance.greaterThan(0); + await dispatch( BlockchainActions.subscribe(discoveryProcess.network) ); - if (!addressIsEmpty || (addressIsEmpty && completed) || (addressIsEmpty && discoveryProcess.accountIndex === 0)) { - dispatch({ - type: ACCOUNT.CREATE, - device, - network, - index: discoveryProcess.accountIndex, - path, - address: ethAddress, - }); - dispatch( - AccountsActions.setBalance(ethAddress, network, device.state || 'undefined', web3instance.web3.fromWei(balance.toString(), 'ether')), - ); - dispatch(AccountsActions.setNonce(ethAddress, network, device.state || 'undefined', nonce)); - - if (!completed) { dispatch(discoverAccount(device, discoveryProcess)); } - } + if (discoveryProcess.interrupted) return; - if (addressIsEmpty) { - // release acquired sesssion - await TrezorConnect.getFeatures({ - device: { - path: device.path, - instance: device.instance, - state: device.state, - }, - keepSession: false, - useEmptyPassphrase: !device.instance, - }); - if (discoveryProcess.interrupted) return; + dispatch({ + type: DISCOVERY.COMPLETE, + device, + network: discoveryProcess.network, + }); - dispatch({ - type: DISCOVERY.COMPLETE, - device, - network, - }); - } -}; +} export const start = (device: TrezorDevice, network: string, ignoreCompleted?: boolean): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { const selected = getState().wallet.selectedDevice; diff --git a/src/actions/PendingTxActions.js b/src/actions/PendingTxActions.js index f9ebb839..b4f398d3 100644 --- a/src/actions/PendingTxActions.js +++ b/src/actions/PendingTxActions.js @@ -7,6 +7,9 @@ import type { State, PendingTx } from 'reducers/PendingTxReducer'; export type PendingTxAction = { type: typeof PENDING.FROM_STORAGE, payload: State +} | { + type: typeof PENDING.ADD, + payload: PendingTx } | { type: typeof PENDING.TX_RESOLVED, tx: PendingTx, diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index ae2189bd..ae5165d1 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -27,7 +27,8 @@ import type { State, FeeLevel } from 'reducers/SendFormReducer'; import type { Account } from 'reducers/AccountsReducer'; import type { Props } from 'views/Wallet/views/AccountSend/Container'; import * as SessionStorageActions from './SessionStorageActions'; -import { estimateGas, pushTx } from './Web3Actions'; +import { prepareEthereumTx, serializeEthereumTx } from './TxActions'; +import * as BlockchainActions from './BlockchainActions'; export type SendTxAction = { type: typeof SEND.TX_COMPLETE, @@ -223,14 +224,13 @@ export const getFeeLevels = (symbol: string, gasPrice: BigNumber | string, gasLi // initialize component -export const init = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { +export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { const { account, network, - web3, } = getState().selectedAccount; - if (!account || !network || !web3) return; + if (!account || !network) return; const stateFromStorage = SessionStorageActions.load(getState().router.location.pathname); if (stateFromStorage) { @@ -243,7 +243,10 @@ export const init = (): ThunkAction => (dispatch: Dispatch, getState: GetState): // TODO: check if there are some unfinished tx in localStorage - const gasPrice: BigNumber = new BigNumber(EthereumjsUnits.convert(web3.gasPrice, 'wei', 'gwei')) || new BigNumber(network.defaultGasPrice); + + // const gasPrice: BigNumber = new BigNumber(EthereumjsUnits.convert(web3.gasPrice, 'wei', 'gwei')) || new BigNumber(network.defaultGasPrice); + const gasPrice: BigNumber = await dispatch( BlockchainActions.getGasPrice(network.network, network.defaultGasPrice) ); + // const gasPrice: BigNumber = new BigNumber(network.defaultGasPrice); const gasLimit: string = network.defaultGasLimit.toString(); const feeLevels: Array = getFeeLevels(network.symbol, gasPrice, gasLimit); @@ -709,12 +712,9 @@ export const onNonceChange = (nonce: string): AsyncAction => async (dispatch: Di const estimateGasPrice = (): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { const { - web3, network, } = getState().selectedAccount; - if (!web3 || !network) return; - - const w3 = web3.web3; + if (!network) return; const state: State = getState().sendForm; const requestedData = state.data; @@ -732,14 +732,7 @@ const estimateGasPrice = (): AsyncAction => async (dispatch: Dispatch, getState: return; } - // TODO: allow data starting with 0x ... - const data: string = `0x${state.data.length % 2 === 0 ? state.data : `0${state.data}`}`; - const gasLimit = await estimateGas(w3, { - to: '0x0000000000000000000000000000000000000000', - data, - value: w3.toHex(w3.toWei(state.amount, 'ether')), - gasPrice: w3.toHex(EthereumjsUnits.convert(state.gasPrice, 'gwei', 'wei')), - }); + const gasLimit: number = await dispatch( BlockchainActions.estimateGasLimit(network.network, state.data, state.amount, state.gasPrice) ); if (getState().sendForm.data === requestedData) { dispatch(onGasLimitChange(gasLimit.toString())); @@ -777,56 +770,69 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge const { account, network, - web3, pending, } = getState().selectedAccount; - if (!account || !web3 || !network) return; + + if (!account || !network) return; const currentState: State = getState().sendForm; const isToken: boolean = currentState.currency !== currentState.networkSymbol; - const w3 = web3.web3; - const address_n = account.addressPath; - - let data: string = `0x${currentState.data}`; - let txAmount: string = w3.toHex(w3.toWei(currentState.amount, 'ether')); - let txAddress: string = currentState.address; - if (isToken) { - const token: ?Token = findToken(getState().tokens, account.address, currentState.currency, account.deviceState); - if (!token) return; - - const contract = web3.erc20.at(token.address); - const amountValue: string = new BigNumber(currentState.amount).times(Math.pow(10, token.decimals)).toString(10); - - data = contract.transfer.getData(currentState.address, amountValue, { - from: account.address, - gasLimit: currentState.gasLimit, - gasPrice: currentState.gasPrice, - }); - txAmount = '0x00'; - txAddress = token.address; - } - - const pendingNonce: number = getPendingNonce(pending); + const pendingNonce: number = stateUtils.getPendingNonce(pending); const nonce = pendingNonce > 0 && pendingNonce >= account.nonce ? pendingNonce : account.nonce; - console.warn('NONCE', nonce, account.nonce, pendingNonce); - - const txData = { - address_n, - // from: currentAddress.address - to: txAddress, - value: txAmount, - data, - chainId: web3.chainId, - nonce: w3.toHex(nonce), - gasLimit: w3.toHex(currentState.gasLimit), - gasPrice: w3.toHex(EthereumjsUnits.convert(currentState.gasPrice, 'gwei', 'wei')), - r: '', - s: '', - v: '', - }; + console.warn("NONCE", nonce); + + const txData = await dispatch( prepareEthereumTx({ + network: network.network, + token: isToken ? findToken(getState().tokens, account.address, currentState.currency, account.deviceState) : null, + from: account.address, + to: currentState.address, + amount: currentState.amount, + data: currentState.data, + gasLimit: currentState.gasLimit, + gasPrice: currentState.gasPrice, + nonce + }) ); + + // let data: string = `0x${currentState.data}`; + // let txAmount: string = w3.toHex(w3.toWei(currentState.amount, 'ether')); + // let txAddress: string = currentState.address; + // if (isToken) { + // const token: ?Token = findToken(getState().tokens, account.address, currentState.currency, account.deviceState); + // if (!token) return; + + // const contract = web3.erc20.at(token.address); + // const amountValue: string = new BigNumber(currentState.amount).times(Math.pow(10, token.decimals)).toString(10); + + // data = contract.transfer.getData(currentState.address, amountValue, { + // from: account.address, + // gasLimit: currentState.gasLimit, + // gasPrice: currentState.gasPrice, + // }); + // txAmount = '0x00'; + // txAddress = token.address; + // } + + + + // console.warn('NONCE', nonce, account.nonce, pendingNonce); + + // const txData = { + // address_n, + // // from: currentAddress.address + // to: txAddress, + // value: txAmount, + // data, + // chainId: web3.chainId, + // nonce: w3.toHex(nonce), + // gasLimit: w3.toHex(currentState.gasLimit), + // gasPrice: w3.toHex(EthereumjsUnits.convert(currentState.gasPrice, 'gwei', 'wei')), + // r: '', + // s: '', + // v: '', + // }; const selected: ?TrezorDevice = getState().wallet.selectedDevice; if (!selected) return; @@ -861,9 +867,17 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge txData.v = signedTransaction.payload.v; try { - const tx = new EthereumjsTx(txData); - const serializedTx = `0x${tx.serialize().toString('hex')}`; - const txid: string = await pushTx(w3, serializedTx); + const serializedTx: string = await dispatch( serializeEthereumTx(txData) ); + const push = await TrezorConnect.pushTransaction({ + tx: serializedTx, + coin: network.network + }); + + if (!push.success) { + throw new Error( push.payload.error ); + } + + const txid = push.payload.txid; dispatch({ type: SEND.TX_COMPLETE, @@ -871,7 +885,7 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge selectedCurrency: currentState.currency, amount: currentState.amount, total: currentState.total, - tx, + tx: txData, nonce, txid, txData, diff --git a/src/actions/TokenActions.js b/src/actions/TokenActions.js index bac9ce9d..68860968 100644 --- a/src/actions/TokenActions.js +++ b/src/actions/TokenActions.js @@ -9,7 +9,7 @@ import type { import type { State, Token } from 'reducers/TokensReducer'; import type { Account } from 'reducers/AccountsReducer'; import type { NetworkToken } from 'reducers/LocalStorageReducer'; -import { getTokenInfoAsync, getTokenBalanceAsync } from './Web3Actions'; +import * as BlockchainActions from './BlockchainActions'; export type TokenAction = { type: typeof TOKEN.FROM_STORAGE, @@ -42,15 +42,11 @@ export const load = (input: string, network: string): AsyncAction => async (disp // when options is a large list (>200 items) return result.slice(0, 100); } - const web3instance = getState().web3.find(w3 => w3.network === network); - if (!web3instance) return; - const info = await getTokenInfoAsync(web3instance.erc20, input); + const info = await dispatch( BlockchainActions.getTokenInfo(input, network) ); if (info) { return [info]; } - //await resolveAfter(300000); - //await resolveAfter(3000); }; export const setBalance = (tokenAddress: string, ethAddress: string, balance: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { @@ -68,9 +64,6 @@ export const setBalance = (tokenAddress: string, ethAddress: string, balance: st }; export const add = (token: NetworkToken, account: Account): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - const web3instance = getState().web3.find(w3 => w3.network === account.network); - if (!web3instance) return; - const tkn: Token = { loaded: false, deviceState: account.deviceState, @@ -88,7 +81,7 @@ export const add = (token: NetworkToken, account: Account): AsyncAction => async payload: tkn, }); - const tokenBalance = await getTokenBalanceAsync(web3instance.erc20, tkn); + const tokenBalance = await dispatch( BlockchainActions.getTokenBalance(tkn) ); dispatch(setBalance(token.address, account.address, tokenBalance)); }; diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index f4b9925e..e110eda8 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -1,6 +1,6 @@ /* @flow */ import TrezorConnect, { - DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT, + UI, DEVICE, DEVICE_EVENT, UI_EVENT, TRANSPORT_EVENT, BLOCKCHAIN_EVENT } from 'trezor-connect'; import * as CONNECT from 'actions/constants/TrezorConnect'; import * as NOTIFICATION from 'actions/constants/notification'; @@ -12,11 +12,13 @@ import { push } from 'react-router-redux'; import type { DeviceMessage, + DeviceMessageType, UiMessage, + UiMessageType, TransportMessage, - DeviceMessageType, TransportMessageType, - UiMessageType, + BlockchainMessage, + BlockchainMessageType, } from 'trezor-connect'; import type { @@ -115,6 +117,15 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS }); }); + TrezorConnect.on(BLOCKCHAIN_EVENT, (event: BlockchainMessage): void => { + // post event to reducers + const type: BlockchainMessageType = event.type; // assert flow type + dispatch({ + type, + payload: event.payload, + }); + }); + // $FlowIssue LOCAL not declared // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://sisyfos.trezor.io/connect/'; // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://connect.trezor.io/5/'; diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index e72ecabb..73623539 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -1,13 +1,15 @@ /* @flow */ import Web3 from 'web3'; - -import type { - ContractFactory, - EstimateGasOptions, - TransactionStatus, - TransactionReceipt, -} from 'web3'; -import type BigNumber from 'bignumber.js'; +import HDKey from 'hdkey'; +import BigNumber from 'bignumber.js'; + +import EthereumjsUtil from 'ethereumjs-util'; +import EthereumjsUnits from 'ethereumjs-units'; +import EthereumjsTx from 'ethereumjs-tx'; +import InputDataDecoder from 'ethereum-input-data-decoder'; +import TrezorConnect from 'trezor-connect'; +import type { EstimateGasOptions, TransactionStatus, TransactionReceipt } from 'web3'; +import { strip } from 'utils/ethUtils'; import * as WEB3 from 'actions/constants/web3'; import * as PENDING from 'actions/constants/pendingTx'; @@ -15,6 +17,10 @@ import type { Dispatch, GetState, AsyncAction, + PromiseAction, + AccountDiscovery, + EthereumTxRequest, + EthereumPreparedTx } from 'flowtype'; import type { Account } from 'reducers/AccountsReducer'; @@ -44,377 +50,335 @@ export type Web3Action = { } | { type: typeof WEB3.CREATE, instance: Web3Instance -} - | Web3UpdateBlockAction - | Web3UpdateGasPriceAction; +} | Web3UpdateBlockAction + | Web3UpdateGasPriceAction; + +export const initWeb3 = (network: string, urlIndex: number = 0): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + return new Promise(async (resolve, reject) => { + // check if requested web was initialized before + const instance = getState().web3.find(w3 => w3.network === network); + if (instance && instance.web3.currentProvider.connected) { + resolve(instance); + return; + } -export function init(instance: ?Web3, coinIndex: number = 0): AsyncAction { - return async (dispatch: Dispatch, getState: GetState): Promise => { + // requested web3 wasn't initialized or is disconnected + // initialize again const { config, ERC20Abi } = getState().localStorage; - - const coin = config.coins[coinIndex]; + const coin = config.coins.find(c => c.network === network); if (!coin) { - // all instances done - dispatch({ - type: WEB3.READY, - }); + // coin not found + reject(new Error(`Network ${ network} not found in application config.`)); return; } - const { network } = coin; - const urls = coin.backends[0].urls; - - let web3host: string = urls[0]; - - if (instance) { - const currentHost = instance.currentProvider.host; - const currentHostIndex: number = urls.indexOf(currentHost); - - if (currentHostIndex + 1 < urls.length) { - web3host = urls[currentHostIndex + 1]; - } else { - console.error(`TODO: Backend ${network} not working`, instance.currentProvider); - - dispatch({ - type: WEB3.CREATE, - instance: { - network, - web3: instance, - chainId: coin.chainId, - erc20: instance.eth.contract(ERC20Abi), - latestBlock: '0', - gasPrice: '0', - }, - }); - - // try next coin - dispatch(init(null, coinIndex + 1)); - return; - } + // get first url + const url = coin.web3[ urlIndex ]; + if (!url) { + reject(new Error('Web3 backend is not responding')); + return; } - //const instance = new Web3(window.web3.currentProvider); - const web3 = new Web3(new Web3.providers.HttpProvider(web3host)); - - // instance = new Web3( new Web3.providers.HttpProvider('https://pyrus2.ubiqscan.io') ); // UBQ - //instance = new Web3( new Web3.providers.HttpProvider('https://node.expanse.tech/') ); // EXP - //instance = new Web3( new Web3.providers.HttpProvider('http://10.34.0.91:8545/') ); - - //web3 = new Web3(new Web3.providers.HttpProvider("https://api.myetherapi.com/rop")); - //instance = new Web3(new Web3.providers.HttpProvider("https://ropsten.infura.io2/QGyVKozSUEh2YhL4s2G4")); - //web3 = new Web3( new Web3.providers.HttpProvider("ws://34.230.234.51:30303") ); - + const web3 = new Web3( new Web3.providers.WebsocketProvider(url) ); - // initial check if backend is running - if (!web3.currentProvider.isConnected()) { - // try different url - dispatch(init(web3, coinIndex)); - return; - } + const onConnect = async () => { - const erc20 = web3.eth.contract(ERC20Abi); + const latestBlock = await web3.eth.getBlockNumber(); + const gasPrice = await web3.eth.getGasPrice(); - dispatch({ - type: WEB3.CREATE, - instance: { + const instance = { network, web3, chainId: coin.chainId, - erc20, - latestBlock: '0', - gasPrice: '0', - }, - }); - - // dispatch({ - // type: WEB3.GAS_PRICE_UPDATED, - // network, - // gasPrice - // }); - - - // console.log("GET CHAIN", instance.version.network) - - // instance.version.getWhisper((err, shh) => { - // console.log("-----whisperrr", error, shh) - // }) - + erc20: new web3.eth.Contract(ERC20Abi), + latestBlock, + gasPrice, + } - // const sshFilter = instance.ssh.filter('latest'); - // sshFilter.watch((error, blockHash) => { - // console.warn("SSH", error, blockHash); - // }); + console.warn("CONNECT", web3) - //const shh = instance.shh.newIdentity(); + dispatch({ + type: WEB3.CREATE, + instance, + }); - // const latestBlockFilter = web3.eth.filter('latest'); + // await dispatch( _onNewBlock(instance) ); - const onBlockMined = async (error: ?Error, blockHash: ?string) => { - if (error) { - window.setTimeout(() => { - // try again - onBlockMined(new Error('manually_triggered_error'), undefined); - }, 30000); - } - - if (blockHash) { - dispatch({ - type: WEB3.BLOCK_UPDATED, - network, - blockHash, - }); - } + resolve(instance); + } - // TODO: filter only current device - const accounts = getState().accounts.filter(a => a.network === network); - for (const account of accounts) { - const nonce = await getNonceAsync(web3, account.address); - if (nonce !== account.nonce) { - dispatch(AccountsActions.setNonce(account.address, account.network, account.deviceState, nonce)); - - // dispatch( getBalance(account) ); - // TODO: check if nonce was updated, - // update tokens balance, - // update account balance, - // update pending transactions + const onEnd = async () => { + web3.currentProvider.removeAllListeners('connect'); + web3.currentProvider.removeAllListeners('end'); + web3.currentProvider.removeAllListeners('error'); + web3.currentProvider.reset(); + // if (web3.eth) + // web3.eth.clearSubscriptions(); + + const instance = getState().web3.find(w3 => w3.network === network); + + if (instance && instance.web3.currentProvider.connected) { + // backend disconnects + // dispatch({ + // type: 'WEB3.DISCONNECT', + // network + // }); + } else { + // backend initialization error for given url, try next one + try { + const web3 = await dispatch( initWeb3(network, urlIndex + 1) ); + resolve(web3); + } catch (error) { + reject(error); } - dispatch(getBalance(account)); - // dispatch( getNonce(account) ); } + } - const tokens = getState().tokens.filter(t => t.network === network); - tokens.forEach(token => dispatch(getTokenBalance(token))); - - dispatch(getGasPrice(network)); - - const pending = getState().pending.filter(p => p.network === network); - pending.forEach(pendingTx => dispatch(getTransactionReceipt(pendingTx))); - }; - - // latestBlockFilter.watch(onBlockMined); - onBlockMined(new Error('manually_triggered_error'), undefined); - + web3.currentProvider.on('connect', onConnect); + web3.currentProvider.on('end', onEnd); + web3.currentProvider.on('error', onEnd); + }); +} - // init next coin - dispatch(init(web3, coinIndex + 1)); +const _onNewBlock = (instance: Web3Instance): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + // const latestBlock = await instance.web3.eth.getBlockNumber(); - // let instance2 = new Web3( new Web3.providers.HttpProvider('https://pyrus2.ubiqscan.io') ); - // console.log("INIT WEB3", instance, instance2); - // instance2.eth.getGasPrice((error, gasPrice) => { - // console.log("---gasss price from UBQ", gasPrice) - // }); - }; -} + // dispatch({ + // type: WEB3.BLOCK_UPDATED, + // network: instance.network, + // blockHash: latestBlock, + // }); + -export function getGasPrice(network: string): AsyncAction { - return async (dispatch: Dispatch, getState: GetState): Promise => { - const index: number = getState().web3.findIndex(w3 => w3.network === network); + // TODO: filter only current device + const accounts = getState().accounts.filter(a => a.network === instance.network); + for (const account of accounts) { + const nonce = await instance.web3.eth.getTransactionCount(account.address); + if (nonce !== account.nonce) { + dispatch(AccountsActions.setNonce(account.address, account.network, account.deviceState, nonce)); + } - const web3instance = getState().web3[index]; - const { web3 } = web3instance; - web3.eth.getGasPrice((error, gasPrice) => { - if (!error) { - if (web3instance.gasPrice && web3instance.gasPrice.toString() !== gasPrice.toString()) { - dispatch({ - type: WEB3.GAS_PRICE_UPDATED, - network, - gasPrice, - }); - } - } - }); - }; -} + const balance = await instance.web3.eth.getBalance(account.address); + const newBalance = EthereumjsUnits.convert(balance, 'wei', 'ether'); + if (newBalance !== account.balance) { + dispatch(AccountsActions.setBalance( + account.address, + account.network, + account.deviceState, + newBalance + )); + } + } + + const tokens = getState().tokens.filter(t => t.network === instance.network); + for (const token of tokens) { + const balance = await dispatch( getTokenBalance(token) ); + console.warn("TOK BALAC", balance) + // const newBalance: string = balance.dividedBy(Math.pow(10, token.decimals)).toString(10); + if (balance !== token.balance) { + dispatch(TokenActions.setBalance( + token.address, + token.ethAddress, + balance, + )); + } + } -export function getBalance(account: Account): AsyncAction { - return async (dispatch: Dispatch, getState: GetState): Promise => { - const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0]; - const { web3 } = web3instance; - - web3.eth.getBalance(account.address, (error: Error, balance: BigNumber) => { - if (!error) { - const newBalance: string = web3.fromWei(balance.toString(), 'ether'); - if (account.balance !== newBalance) { - dispatch(AccountsActions.setBalance( - account.address, - account.network, - account.deviceState, - newBalance, - )); - - // dispatch( loadHistory(addr) ); - } - } - }); - }; -} + // dispatch(getGasPrice(network)); -export function getTokenBalance(token: Token): AsyncAction { - return async (dispatch: Dispatch, getState: GetState): Promise => { - const web3instance = getState().web3.filter(w3 => w3.network === token.network)[0]; - const contract = web3instance.erc20.at(token.address); - - contract.balanceOf(token.ethAddress, (error: Error, balance: BigNumber) => { - if (balance) { - const newBalance: string = balance.dividedBy(Math.pow(10, token.decimals)).toString(10); - if (newBalance !== token.balance) { - dispatch(TokenActions.setBalance( - token.address, - token.ethAddress, - newBalance, - )); - } - } - }); - }; + } -export function getNonce(account: Account): AsyncAction { - return async (dispatch: Dispatch, getState: GetState): Promise => { - const web3instance = getState().web3.filter(w3 => w3.network === account.network)[0]; - const { web3 } = web3instance; - - web3.eth.getTransactionCount(account.address, (error: Error, result: number) => { - if (!error) { - if (account.nonce !== result) { - dispatch(AccountsActions.setNonce(account.address, account.network, account.deviceState, result)); - } - } - }); +export const discoverAccount = (address: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance: Web3Instance = await dispatch( initWeb3(network) ); + const balance = await instance.web3.eth.getBalance(address); + const nonce = await instance.web3.eth.getTransactionCount(address); + return { + transactions: 0, + block: 0, + balance: EthereumjsUnits.convert(balance, 'wei', 'ether'), + nonce }; } -export const getTransactionReceipt = (tx: PendingTx): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - const web3instance = getState().web3.filter(w3 => w3.network === tx.network)[0]; - const { web3 } = web3instance; - - web3.eth.getTransaction(tx.id, (error: Error, status: TransactionStatus) => { - if (!error && !status) { +export const resolvePendingTransactions = (network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance: Web3Instance = await dispatch( initWeb3(network) ); + const pending = getState().pending.filter(p => p.network === network); + for (const tx of pending) { + const status = await instance.web3.eth.getTransaction(tx.id); + if (!status) { dispatch({ type: PENDING.TX_NOT_FOUND, tx, }); - } else if (status && status.blockNumber) { - web3.eth.getTransactionReceipt(tx.id, (error: Error, receipt: TransactionReceipt) => { - if (receipt) { - if (status.gas !== receipt.gasUsed) { - dispatch({ - type: PENDING.TX_TOKEN_ERROR, - tx, - }); - } + } else { + const receipt = await instance.web3.eth.getTransactionReceipt(tx.id); + if (receipt) { + if (status.gas !== receipt.gasUsed) { dispatch({ - type: PENDING.TX_RESOLVED, + type: PENDING.TX_TOKEN_ERROR, tx, - receipt, }); } - }); + dispatch({ + type: PENDING.TX_RESOLVED, + tx, + receipt, + }); + } } - }); -}; + } +} -export const getTransaction = (web3: Web3, txid: string): Promise => new Promise((resolve, reject) => { - web3.eth.getTransaction(txid, (error, result) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); -}); +export const getPendingInfo = (network: string, txid: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance: Web3Instance = await dispatch( initWeb3(network) ); + const tx = await instance.web3.eth.getTransaction(txid); -export const getBalanceAsync = (web3: Web3, address: string): Promise => new Promise((resolve, reject) => { - web3.eth.getBalance(address, (error: Error, result: BigNumber) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); -}); + /* + if (tx.input !== "0x") { + // find token: + // tx.to <= smart contract address -export const getTokenBalanceAsync = (erc20: ContractFactory, token: Token): Promise => new Promise((resolve, reject) => { - const contract = erc20.at(token.address); - contract.balanceOf(token.ethAddress, (error: Error, balance: BigNumber) => { - if (error) { - reject(error); - } else { - const newBalance: string = balance.dividedBy(Math.pow(10, token.decimals)).toString(10); - resolve(newBalance); + // smart contract data + const decoder = new InputDataDecoder(instance.erc20.options.jsonInterface); + const data = decoder.decodeData(tx.input); + if (data.name === 'transfer') { + console.warn("DATA!", data.inputs[0], data.inputs[1].toString(10)); } - }); -}); + -export const getNonceAsync = (web3: Web3, address: string): Promise => new Promise((resolve, reject) => { - web3.eth.getTransactionCount(address, (error: Error, result: number) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); -}); + } + */ + // return tx; +} +export const getTxInput = (): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + + const instance: Web3Instance = await dispatch( initWeb3("ropsten") ); + console.warn("GETTX", instance.erc20.options.jsonInterface) + // const inputData = instance.web3.utils.hexToAscii("0xa9059cbb00000000000000000000000073d0385f4d8e00c5e6504c6030f47bf6212736a80000000000000000000000000000000000000000000000000000000000000001"); + // console.warn("input data!", inputData); +} -export const getTokenInfoAsync = (erc20: ContractFactory, address: string): Promise => new Promise((resolve) => { - const contract = erc20.at(address, (error/* , res */) => { - // console.warn("callback", error, res) - }); - const info: NetworkToken = { +export const updateAccount = (account: Account, newAccount: AccountDiscovery, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance: Web3Instance = await dispatch( initWeb3(network) ); + const balance = await instance.web3.eth.getBalance(account.address); + const nonce = await instance.web3.eth.getTransactionCount(account.address); + + dispatch( AccountsActions.update( { ...account, ...newAccount, balance: EthereumjsUnits.convert(balance, 'wei', 'ether'), nonce }) ); + // TODO update tokens for this account + +} + +export const getTokenInfo = (address: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance: Web3Instance = await dispatch( initWeb3(network) ); + const contract = instance.erc20.clone(); + contract.options.address = address; + + const name = await contract.methods.name().call(); + const symbol = await contract.methods.symbol().call(); + const decimals = await contract.methods.decimals().call(); + + return { address, - name: '', - symbol: '', - decimals: 0, + name, + symbol, + decimals, }; +}; - contract.name.call((error: Error, name: string) => { - if (error) { - resolve(null); - return; - } - info.name = name; +export const getTokenBalance = (token: Token): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance = await dispatch( initWeb3(token.network) ); + const contract = instance.erc20.clone(); + contract.options.address = token.address; + const balance = await contract.methods.balanceOf(token.ethAddress).call(); + return new BigNumber(balance).dividedBy(Math.pow(10, token.decimals)).toString(10); +}; - contract.symbol.call((error: Error, symbol: string) => { - if (error) { - resolve(null); - return; - } - info.symbol = symbol; +export const getCurrentGasPrice = (network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance = getState().web3.find(w3 => w3.network === network); + if (instance) { + return EthereumjsUnits.convert(instance.gasPrice, 'wei', 'gwei'); + } else { + return "0"; + } + + // const index: number = getState().web3.findIndex(w3 => w3.network === network); + + // const web3instance = getState().web3[index]; + // const web3 = web3instance.web3; + // web3.eth.getGasPrice((error, gasPrice) => { + // if (!error) { + // if (web3instance.gasPrice && web3instance.gasPrice.toString() !== gasPrice.toString()) { + // dispatch({ + // type: WEB3.GAS_PRICE_UPDATED, + // network, + // gasPrice, + // }); + // } + // } + // }); +} - contract.decimals.call((error: Error, decimals: BigNumber) => { - if (decimals) { - info.decimals = decimals.toNumber(); - resolve(info); - } else { - resolve(null); - } - }); - }); - }); -}); - -export const estimateGas = (web3: Web3, options: EstimateGasOptions): Promise => new Promise((resolve, reject) => { - web3.eth.estimateGas(options, (error: ?Error, gas: ?number) => { - if (error) { - reject(error); - } else if (typeof gas === 'number') { - resolve(gas); - } - }); -}); +export const estimateGasLimit = (network: string, options: EstimateGasOptions): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance = await dispatch( initWeb3(network) ); + // TODO: allow data starting with 0x ... + options.to = '0x0000000000000000000000000000000000000000'; + options.data = `0x${options.data.length % 2 === 0 ? options.data : `0${options.data}`}`; + options.value = instance.web3.utils.toHex( EthereumjsUnits.convert(options.value || '0', 'ether', 'wei') ); + options.gasPrice = instance.web3.utils.toHex( EthereumjsUnits.convert(options.gasPrice, 'gwei', 'wei') ); -export const pushTx = (web3: Web3, tx: any): Promise => new Promise((resolve, reject) => { - web3.eth.sendRawTransaction(tx, (error: Error, result: string) => { - if (error) { - reject(error); - } else { - resolve(result); - } - }); -}); \ No newline at end of file + const limit = await instance.web3.eth.estimateGas(options); + return limit; +}; + +// export const prepareTx = (tx: EthereumTxRequest): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + +// const instance = await dispatch( initWeb3(tx.network) ); +// const token = tx.token; +// let data: string = `0x${tx.data}`; // TODO: check if already prefixed +// let value: string = instance.web3.utils.toHex( EthereumjsUnits.convert(tx.amount, 'ether', 'wei') ); +// let to: string = tx.to; + +// if (token) { +// // smart contract transaction +// const contract = instance.erc20.clone(); +// contract.options.address = token.address; +// const tokenAmount: string = new BigNumber(tx.amount).times(Math.pow(10, token.decimals)).toString(10); +// data = instance.erc20.methods.transfer(to, tokenAmount).encodeABI(); +// value = '0x00'; +// to = token.address; +// } + +// return { +// to, +// value, +// data, +// chainId: instance.chainId, +// nonce: instance.web3.utils.toHex(tx.nonce), +// gasLimit: instance.web3.utils.toHex(tx.gasLimit), +// gasPrice: instance.web3.utils.toHex( EthereumjsUnits.convert(tx.gasPrice, 'gwei', 'wei') ), +// r: '', +// s: '', +// v: '', +// } +// }; + +// export const pushTx = (network: string, tx: EthereumPreparedTx): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +// const instance = await dispatch( initWeb3(network) ); +// const ethTx = new EthereumjsTx(tx); +// const serializedTx = `0x${ethTx.serialize().toString('hex')}`; + +// return new Promise((resolve, reject) => { +// instance.web3.eth.sendSignedTransaction(serializedTx) +// .on('error', error => reject(error)) +// .once('transactionHash', (hash: string) => { +// resolve(hash); +// }); +// }); +// }; diff --git a/src/actions/constants/account.js b/src/actions/constants/account.js index 18075a00..d1baa199 100644 --- a/src/actions/constants/account.js +++ b/src/actions/constants/account.js @@ -6,6 +6,7 @@ export const DISPOSE: 'account__dispose' = 'account__dispose'; export const CREATE: 'account__create' = 'account__create'; export const REMOVE: 'account__remove' = 'account__remove'; +export const UPDATE: 'account__update' = 'account__update'; export const SET_BALANCE: 'account__set_balance' = 'account__set_balance'; export const SET_NONCE: 'account__set_nonce' = 'account__set_nonce'; export const FROM_STORAGE: 'account__from_storage' = 'account__from_storage'; diff --git a/src/actions/constants/pendingTx.js b/src/actions/constants/pendingTx.js index c2cfc0c2..04f8ef91 100644 --- a/src/actions/constants/pendingTx.js +++ b/src/actions/constants/pendingTx.js @@ -2,6 +2,7 @@ export const FROM_STORAGE: 'pending__from_storage' = 'pending__from_storage'; +export const ADD: 'pending__add' = 'pending__add'; export const TX_RESOLVED: 'pending__tx_resolved' = 'pending__tx_resolved'; export const TX_NOT_FOUND: 'pending__tx_not_found' = 'pending__tx_not_found'; export const TX_TOKEN_ERROR: 'pending__tx_token_error' = 'pending__tx_token_error'; \ No newline at end of file diff --git a/src/services/TrezorConnectService.js b/src/services/TrezorConnectService.js index 38c9e733..a320cfd8 100644 --- a/src/services/TrezorConnectService.js +++ b/src/services/TrezorConnectService.js @@ -1,11 +1,12 @@ /* @flow */ import { push } from 'react-router-redux'; -import { - TRANSPORT, DEVICE, +import TrezorConnect, { + TRANSPORT, DEVICE_EVENT, UI_EVENT, UI, DEVICE, BLOCKCHAIN } from 'trezor-connect'; import * as TrezorConnectActions from 'actions/TrezorConnectActions'; import * as DiscoveryActions from 'actions/DiscoveryActions'; +import * as BlockchainActions from 'actions/BlockchainActions'; import * as ModalActions from 'actions/ModalActions'; import * as STORAGE from 'actions/constants/localStorage'; import * as CONNECT from 'actions/constants/TrezorConnect'; @@ -32,6 +33,9 @@ const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: Middlewa // api.dispatch( push('/') ); } else if (action.type === TRANSPORT.START) { api.dispatch(TrezorConnectActions.postInit()); + + api.dispatch( BlockchainActions.subscribe('ropsten') ); + } else if (action.type === DEVICE.DISCONNECT) { api.dispatch(TrezorConnectActions.deviceDisconnect(action.device)); } else if (action.type === CONNECT.REMEMBER_REQUEST) { @@ -59,6 +63,10 @@ const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: Middlewa api.dispatch(TrezorConnectActions.onSelectDevice(action.device)); } else if (action.type === CONNECT.COIN_CHANGED) { api.dispatch(TrezorConnectActions.coinChanged(action.payload.network)); + } else if (action.type === BLOCKCHAIN.BLOCK) { + // api.dispatch(BlockchainActions.onBlockMined(action.payload.coin)); + } else if (action.type === BLOCKCHAIN.NOTIFICATION) { + // api.dispatch(BlockchainActions.onNotification(action.payload)); } return action; From a6ac8239f0ee27986859b5f49cd68c0734cfab43 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 13:25:32 +0200 Subject: [PATCH 20/51] before merge --- src/actions/TxActions.js | 55 +++++++++++++++++++++++++++++ src/reducers/AccountsReducer.js | 38 ++++++++++---------- src/reducers/DiscoveryReducer.js | 10 +++--- src/reducers/LocalStorageReducer.js | 3 +- src/reducers/PendingTxReducer.js | 37 +++++++++++-------- src/reducers/WalletReducer.js | 1 - 6 files changed, 102 insertions(+), 42 deletions(-) create mode 100644 src/actions/TxActions.js diff --git a/src/actions/TxActions.js b/src/actions/TxActions.js new file mode 100644 index 00000000..ac8535a8 --- /dev/null +++ b/src/actions/TxActions.js @@ -0,0 +1,55 @@ +/* @flow */ + +import EthereumjsTx from 'ethereumjs-tx'; +import EthereumjsUnits from 'ethereumjs-units'; +import BigNumber from 'bignumber.js'; +import { toHex } from 'web3-utils'; +import { initWeb3 } from './Web3Actions'; + +import type { + Dispatch, + GetState, + PromiseAction, + EthereumTxRequest, + EthereumPreparedTx +} from 'flowtype'; + + +export const prepareEthereumTx = (tx: EthereumTxRequest): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const instance = await dispatch( initWeb3(tx.network) ); + const token = tx.token; + let data: string = `0x${tx.data}`; // TODO: check if already prefixed + let value: string = toHex( EthereumjsUnits.convert(tx.amount, 'ether', 'wei') ); + let to: string = tx.to; + + if (token) { + // smart contract transaction + const contract = instance.erc20.clone(); + contract.options.address = token.address; + const tokenAmount: string = new BigNumber(tx.amount).times(Math.pow(10, token.decimals)).toString(10); + data = instance.erc20.methods.transfer(to, tokenAmount).encodeABI(); + value = '0x00'; + to = token.address; + } + + return { + to, + value, + data, + chainId: instance.chainId, + nonce: toHex(tx.nonce), + gasLimit: toHex(tx.gasLimit), + gasPrice: toHex( EthereumjsUnits.convert(tx.gasPrice, 'gwei', 'wei') ), + r: '', + s: '', + v: '', + } +}; + +export const serializeEthereumTx = (tx: EthereumPreparedTx): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + const ethTx = new EthereumjsTx(tx); + console.warn("SERIALIZE 1", `0x${ ethTx.serialize().toString('hex') }`) + console.warn("SERIALIZE 2", toHex( ethTx.serialize() )) + return `0x${ ethTx.serialize().toString('hex') }`; + // return toHex( ethTx.serialize() ); +} \ No newline at end of file diff --git a/src/reducers/AccountsReducer.js b/src/reducers/AccountsReducer.js index c601424f..df05ff00 100644 --- a/src/reducers/AccountsReducer.js +++ b/src/reducers/AccountsReducer.js @@ -7,7 +7,6 @@ import * as ACCOUNT from 'actions/constants/account'; import type { Action, TrezorDevice } from 'flowtype'; import type { - AccountCreateAction, AccountSetBalanceAction, AccountSetNonceAction, } from 'actions/AccountsActions'; @@ -22,6 +21,8 @@ export type Account = { +address: string; balance: string; nonce: number; + block: number; + transactions: number; } export type State = Array; @@ -37,28 +38,14 @@ export const findDeviceAccounts = (state: State, device: TrezorDevice, network: return state.filter(addr => addr.deviceState === device.state); }; -const createAccount = (state: State, action: AccountCreateAction): State => { +const createAccount = (state: State, account: Account): State => { // TODO check with device_id // check if account was created before - // const exist: ?Account = state.find(account => account.address === action.address && account.network === action.network && action.device.features && account.deviceID === action.device.features.device_id); - const exist: ?Account = state.find(account => account.address === action.address && account.network === action.network && account.deviceState === action.device.state); + const exist: ?Account = state.find(a => a.address === account.address && a.network === account.network && a.deviceState === account.deviceState); if (exist) { return state; } - - const account: Account = { - loaded: false, - network: action.network, - deviceID: action.device.features ? action.device.features.device_id : '0', - deviceState: action.device.state || 'undefined', - index: action.index, - addressPath: action.path, - address: action.address, - balance: '0', - nonce: 0, - }; - - const newState: State = [...state]; + const newState: State = [ ...state ]; newState.push(account); return newState; }; @@ -74,8 +61,16 @@ const clear = (state: State, devices: Array): State => { return newState; }; +const updateAccount = (state: State, account: Account): State => { + const index: number = state.findIndex(a => a.address === account.address && a.network === account.network && a.deviceState === account.deviceState); + const newState: State = [...state]; + newState[index] = account; + return newState; +} + const setBalance = (state: State, action: AccountSetBalanceAction): State => { - const index: number = state.findIndex(account => account.address === action.address && account.network === action.network && account.deviceState === action.deviceState); + // const index: number = state.findIndex(account => account.address === action.address && account.network === action.network && account.deviceState === action.deviceState); + const index: number = state.findIndex(account => account.address === action.address && account.network === action.network); const newState: State = [...state]; newState[index].loaded = true; newState[index].balance = action.balance; @@ -93,7 +88,7 @@ const setNonce = (state: State, action: AccountSetNonceAction): State => { export default (state: State = initialState, action: Action): State => { switch (action.type) { case ACCOUNT.CREATE: - return createAccount(state, action); + return createAccount(state, action.payload); case CONNECT.FORGET: case CONNECT.FORGET_SINGLE: @@ -105,6 +100,9 @@ export default (state: State = initialState, action: Action): State => { //case CONNECT.FORGET_SINGLE : // return forgetAccounts(state, action); + case ACCOUNT.UPDATE : + return updateAccount(state, action.payload); + case ACCOUNT.SET_BALANCE: return setBalance(state, action); case ACCOUNT.SET_NONCE: diff --git a/src/reducers/DiscoveryReducer.js b/src/reducers/DiscoveryReducer.js index 81e8ffb7..244df89c 100644 --- a/src/reducers/DiscoveryReducer.js +++ b/src/reducers/DiscoveryReducer.js @@ -16,9 +16,7 @@ import type { DiscoveryCompleteAction, } from 'actions/DiscoveryActions'; -import type { - AccountCreateAction, -} from 'actions/AccountsActions'; +import type { Account } from './AccountsReducer'; export type Discovery = { network: string; @@ -75,8 +73,8 @@ const complete = (state: State, action: DiscoveryCompleteAction): State => { return newState; }; -const accountCreate = (state: State, action: AccountCreateAction): State => { - const index: number = findIndex(state, action.network, action.device.state || '0'); +const accountCreate = (state: State, account: Account): State => { + const index: number = findIndex(state, account.network, account.deviceState); const newState: State = [...state]; newState[index].accountIndex++; return newState; @@ -162,7 +160,7 @@ export default function discovery(state: State = initialState, action: Action): case DISCOVERY.START: return start(state, action); case ACCOUNT.CREATE: - return accountCreate(state, action); + return accountCreate(state, action.payload); case DISCOVERY.STOP: return stop(state, action); case DISCOVERY.COMPLETE: diff --git a/src/reducers/LocalStorageReducer.js b/src/reducers/LocalStorageReducer.js index bfbc3491..47e1c9d4 100644 --- a/src/reducers/LocalStorageReducer.js +++ b/src/reducers/LocalStorageReducer.js @@ -22,7 +22,8 @@ export type Coin = { backends: Array<{ name: string; urls: Array; - }> + }>; + web3: Array; } export type NetworkToken = { diff --git a/src/reducers/PendingTxReducer.js b/src/reducers/PendingTxReducer.js index c6108d74..5cccf9e8 100644 --- a/src/reducers/PendingTxReducer.js +++ b/src/reducers/PendingTxReducer.js @@ -6,6 +6,7 @@ import type { Action } from 'flowtype'; import type { SendTxAction } from 'actions/SendFormActions'; export type PendingTx = { + +type: 'send' | 'recv'; +id: string; +network: string; +currency: string; @@ -21,19 +22,25 @@ export type State = Array; const initialState: State = []; -const add = (state: State, action: SendTxAction): State => { +// const add01 = (state: State, action: SendTxAction): State => { +// const newState = [...state]; +// newState.push({ +// id: action.txid, +// network: action.account.network, +// currency: action.selectedCurrency, +// amount: action.amount, +// total: action.total, +// tx: action.tx, +// nonce: action.nonce, +// address: action.account.address, +// rejected: false, +// }); +// return newState; +// }; + +const add = (state: State, payload: any): State => { const newState = [...state]; - newState.push({ - id: action.txid, - network: action.account.network, - currency: action.selectedCurrency, - amount: action.amount, - total: action.total, - tx: action.tx, - nonce: action.nonce, - address: action.account.address, - rejected: false, - }); + newState.push(payload); return newState; }; @@ -48,9 +55,11 @@ const reject = (state: State, id: string): State => state.map((tx) => { export default function pending(state: State = initialState, action: Action): State { switch (action.type) { - case SEND.TX_COMPLETE: - return add(state, action); + // case SEND.TX_COMPLETE: + // return add(state, action); + case PENDING.ADD: + return add(state, action.payload); case PENDING.TX_RESOLVED: return remove(state, action.tx.id); case PENDING.TX_NOT_FOUND: diff --git a/src/reducers/WalletReducer.js b/src/reducers/WalletReducer.js index 3676bdfc..5eb5698c 100644 --- a/src/reducers/WalletReducer.js +++ b/src/reducers/WalletReducer.js @@ -4,7 +4,6 @@ import { LOCATION_CHANGE } from 'react-router-redux'; import { DEVICE, TRANSPORT } from 'trezor-connect'; import * as MODAL from 'actions/constants/modal'; -import * as WEB3 from 'actions/constants/web3'; import * as WALLET from 'actions/constants/wallet'; import * as CONNECT from 'actions/constants/TrezorConnect'; From 6354332e4007d811bdb13f89e59ebac5b81ee72c Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 12 Sep 2018 16:59:31 +0200 Subject: [PATCH 21/51] fixed conflicts after merge --- src/actions/AccountsActions.js | 3 - src/actions/DiscoveryActions.js | 135 ++------------------------------ src/actions/SendFormActions.js | 1 + src/store.js | 15 ++-- yarn.lock | 24 +++++- 5 files changed, 37 insertions(+), 141 deletions(-) diff --git a/src/actions/AccountsActions.js b/src/actions/AccountsActions.js index 65ab5d50..8c14e594 100644 --- a/src/actions/AccountsActions.js +++ b/src/actions/AccountsActions.js @@ -57,11 +57,8 @@ export const setNonce = (address: string, network: string, deviceState: string, deviceState, nonce, }); -<<<<<<< HEAD -======= export const update = (account: Account): Action => ({ type: ACCOUNT.UPDATE, payload: account }); ->>>>>>> web3 actions splitted to blockchain actions diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index 2f04b96d..58be9d91 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -150,6 +150,12 @@ const begin = (device: TrezorDevice, network: string): AsyncAction => async (dis return; } + // check for interruption + const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === device.state && d.network === network); + if (discoveryProcess && discoveryProcess.interrupted) return; + + const basePath: Array = response.payload.path; + // send data to reducer dispatch({ type: DISCOVERY.START, @@ -262,135 +268,6 @@ const finish = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction } -export const start = (device: TrezorDevice, network: string, ignoreCompleted?: boolean): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { - const selected = getState().wallet.selectedDevice; - if (!selected) { - // TODO: throw error - console.error('Start discovery: no selected device', device); - return; - } if (selected.path !== device.path) { - console.error('Start discovery: requested device is not selected', device, selected); - return; - } if (!selected.state) { - console.warn("Start discovery: Selected device wasn't authenticated yet..."); - return; - } if (selected.connected && !selected.available) { - console.warn('Start discovery: Selected device is unavailable...'); - return; - } - - const web3 = getState().web3.find(w3 => w3.network === network); - if (!web3) { - console.error('Start discovery: Web3 does not exist', network); - return; - } - - if (!web3.web3.currentProvider.isConnected()) { - console.error('Start discovery: Web3 is not connected', network); - dispatch({ - type: DISCOVERY.WAITING_FOR_BACKEND, - device, - network, - }); - return; - } - - const { discovery }: { discovery: State } = getState(); - const discoveryProcess: ?Discovery = discovery.find(d => d.deviceState === device.state && d.network === network); - - - if (!selected.connected && (!discoveryProcess || !discoveryProcess.completed)) { - dispatch({ - type: DISCOVERY.WAITING_FOR_DEVICE, - device, - network, - }); - return; - } - - if (!discoveryProcess) { - dispatch(begin(device, network)); - } else if (discoveryProcess.completed && !ignoreCompleted) { - dispatch({ - type: DISCOVERY.COMPLETE, - device, - network, - }); - } else if (discoveryProcess.interrupted || discoveryProcess.waitingForDevice) { - // discovery cycle was interrupted - // start from beginning - dispatch(begin(device, network)); - } else { - dispatch(discoverAccount(device, discoveryProcess)); - } -}; - -begin = (device: TrezorDevice, network: string): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - const { config } = getState().localStorage; - const coinToDiscover = config.coins.find(c => c.network === network); - if (!coinToDiscover) return; - - dispatch({ - type: DISCOVERY.WAITING_FOR_DEVICE, - device, - network, - }); - - // get xpub from TREZOR - const response = await TrezorConnect.getPublicKey({ - device: { - path: device.path, - instance: device.instance, - state: device.state, - }, - path: coinToDiscover.bip44, - keepSession: true, // acquire and hold session - useEmptyPassphrase: !device.instance, - }); - - // handle TREZOR response error - if (!response.success) { - // TODO: check message - console.warn('DISCOVERY ERROR', response); - dispatch({ - type: NOTIFICATION.ADD, - payload: { - type: 'error', - title: 'Discovery error', - message: response.payload.error, - cancelable: true, - actions: [ - { - label: 'Try again', - callback: () => { - dispatch(start(device, network)); - }, - }, - ], - }, - }); - return; - } - - // check for interruption - const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === device.state && d.network === network); - if (discoveryProcess && discoveryProcess.interrupted) return; - - const basePath: Array = response.payload.path; - - // send data to reducer - dispatch({ - type: DISCOVERY.START, - network: coinToDiscover.network, - device, - publicKey: response.payload.publicKey, - chainCode: response.payload.chainCode, - basePath, - }); - - dispatch(start(device, network)); -}; - export const restore = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { const selected = getState().wallet.selectedDevice; diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index ae5165d1..0bd0e8d8 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -12,6 +12,7 @@ import * as SEND from 'actions/constants/send'; import { initialState } from 'reducers/SendFormReducer'; import { findToken } from 'reducers/TokensReducer'; import { findDevice, getPendingAmount, getPendingNonce } from 'reducers/utils'; +import * as stateUtils from 'reducers/utils'; import type { Dispatch, diff --git a/src/store.js b/src/store.js index bae277fb..25a8d65d 100644 --- a/src/store.js +++ b/src/store.js @@ -6,13 +6,14 @@ import thunk from 'redux-thunk'; // import createHistory from 'history/createBrowserHistory'; // import { useRouterHistory } from 'react-router'; import createHistory from 'history/createHashHistory'; +import { createLogger } from 'redux-logger'; import reducers from 'reducers'; import services from 'services'; import Raven from 'raven-js'; import RavenMiddleware from 'redux-raven-middleware'; -// import type { Action, GetState, Store } from 'flowtype'; +import type { Action, GetState, Store } from 'flowtype'; export const history: History = createHistory({ queryKey: false }); @@ -30,12 +31,12 @@ const middleware = [ let composedEnhancers: any; if (process.env.NODE_ENV === 'development') { - // const excludeLogger = (getState: GetState, action: Action): boolean => { - // //'@@router/LOCATION_CHANGE' - // const excluded: Array = ['LOG_TO_EXCLUDE', 'log__add']; - // const pass: Array = excluded.filter(act => action.type === act); - // return pass.length === 0; - // }; + const excludeLogger = (getState: GetState, action: Action): boolean => { + //'@@router/LOCATION_CHANGE' + const excluded: Array = ['LOG_TO_EXCLUDE', 'log__add']; + const pass: Array = excluded.filter(act => action.type === act); + return pass.length === 0; + }; const logger = createLogger({ level: 'info', diff --git a/yarn.lock b/yarn.lock index 3073d0ad..d9e807b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2560,6 +2560,10 @@ commander@^2.11.0: version "2.12.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.12.1.tgz#468635c4168d06145b9323356d1da84d14ac4a7a" +commander@^2.13.0: + version "2.18.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" + commander@^2.8.1: version "2.17.1" resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" @@ -2732,7 +2736,16 @@ cors@^2.8.1: object-assign "^4" vary "^1" -cosmiconfig@^5.0.0, cosmiconfig@^5.0.5: +cosmiconfig@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-3.1.0.tgz#640a94bf9847f321800403cd273af60665c73397" + dependencies: + is-directory "^0.3.1" + js-yaml "^3.9.0" + parse-json "^3.0.0" + require-from-string "^2.0.1" + +cosmiconfig@^5.0.5: version "5.0.6" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.0.6.tgz#dca6cf680a0bd03589aff684700858c81abeeb39" dependencies: @@ -6893,7 +6906,7 @@ mkdirp-promise@^5.0.1: dependencies: mkdirp "*" -mkdirp@*, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: @@ -11223,6 +11236,13 @@ ws@^3.0.0: safe-buffer "~5.1.0" ultron "~1.1.0" +ws@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" + dependencies: + async-limiter "~1.0.0" + safe-buffer "~5.1.0" + ws@^5.2.0: version "5.2.2" resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" From 9c651669c8ff40e0388703c35fac1643341151d0 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 09:26:49 +0200 Subject: [PATCH 22/51] added missing package "react-sticky-el" --- package.json | 1 + yarn.lock | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/package.json b/package.json index 27cbad89..fadd8458 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "react-router-redux": "next", "react-scale-text": "^1.2.2", "react-select": "2.0.0", + "react-sticky-el": "^1.0.20", "react-transition-group": "^2.2.1", "redbox-react": "^1.6.0", "redux": "4.0.0", diff --git a/yarn.lock b/yarn.lock index d9e807b2..2b50bd16 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8135,18 +8135,18 @@ prop-types@15.x, prop-types@^15.5.10, prop-types@^15.5.4, prop-types@^15.5.8, pr loose-envify "^1.3.1" object-assign "^4.1.1" -prop-types@^15.6.1: - version "15.6.1" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" +prop-types@>=15.5.10, prop-types@^15.6.2: + version "15.6.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" dependencies: - fbjs "^0.8.16" loose-envify "^1.3.1" object-assign "^4.1.1" -prop-types@^15.6.2: - version "15.6.2" - resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.2.tgz#05d5ca77b4453e985d60fc7ff8c859094a497102" +prop-types@^15.6.1: + version "15.6.1" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.6.1.tgz#36644453564255ddda391191fb3a125cbdf654ca" dependencies: + fbjs "^0.8.16" loose-envify "^1.3.1" object-assign "^4.1.1" @@ -8482,6 +8482,12 @@ react-select@2.0.0: react-input-autosize "^2.2.1" react-transition-group "^2.2.1" +react-sticky-el@^1.0.20: + version "1.0.20" + resolved "https://registry.yarnpkg.com/react-sticky-el/-/react-sticky-el-1.0.20.tgz#b3c5e7128218633f440dc67aec239d1cd078342d" + dependencies: + prop-types ">=15.5.10" + react-transition-group@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.2.1.tgz#e9fb677b79e6455fd391b03823afe84849df4a10" From c7cd4c9525764c00ebfb0ed6aa26f9d2a463bbb1 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 09:27:09 +0200 Subject: [PATCH 23/51] fixed webpack config for local build --- webpack/local.babel.js | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/webpack/local.babel.js b/webpack/local.babel.js index c62b2e08..92930de8 100644 --- a/webpack/local.babel.js +++ b/webpack/local.babel.js @@ -2,6 +2,7 @@ import webpack from 'webpack'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import CopyWebpackPlugin from 'copy-webpack-plugin'; +import MiniCssExtractPlugin from '../../trezor-connect/node_modules/mini-css-extract-plugin'; import { TREZOR_CONNECT_ROOT, @@ -47,20 +48,17 @@ module.exports = { { test: /\.js?$/, exclude: /node_modules/, + use: ['babel-loader'], + }, + { + test: /\.less$/, use: [ - 'babel-loader', { - loader: 'eslint-loader', - options: { - emitWarning: true, - }, - }, - { - loader: 'stylelint-custom-processor-loader', - options: { - configPath: '.stylelintrc', - }, + loader: MiniCssExtractPlugin.loader, + options: { publicPath: '../' }, }, + `${TREZOR_CONNECT_ROOT}/node_modules/css-loader`, + `${TREZOR_CONNECT_ROOT}/node_modules/less-loader`, ], }, { @@ -113,6 +111,11 @@ module.exports = { hints: false, }, plugins: [ + new MiniCssExtractPlugin({ + filename: '[name].css', + chunkFilename: '[id].css', + }), + new HtmlWebpackPlugin({ chunks: ['index'], template: `${SRC}index.html`, From e2f397d2410900a0fbac6f3634fb4ead6f4d794a Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 09:32:41 +0200 Subject: [PATCH 24/51] local build TrezorConnect endpoint --- src/actions/TrezorConnectActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index e110eda8..064b04d8 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -127,8 +127,8 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS }); // $FlowIssue LOCAL not declared + window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://connect.trezor.io/5/'; // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://sisyfos.trezor.io/connect/'; - // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://connect.trezor.io/5/'; //window.__TREZOR_CONNECT_SRC = 'https://sisyfos.trezor.io/connect/'; // window.__TREZOR_CONNECT_SRC = 'https://localhost:8088/'; From 9293a33b57fbede3fb917e3d22da6a97e74833d2 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 14:38:52 +0200 Subject: [PATCH 25/51] update constants --- src/actions/constants/blockchain.js | 3 +-- src/actions/constants/discovery.js | 2 +- src/actions/constants/web3.js | 3 ++- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/actions/constants/blockchain.js b/src/actions/constants/blockchain.js index f0addc68..d494f215 100644 --- a/src/actions/constants/blockchain.js +++ b/src/actions/constants/blockchain.js @@ -1,7 +1,6 @@ /* @flow */ -export const START: 'backend__start' = 'backend__start'; -export const STOP: 'backend__stop' = 'backend__stop'; +export const READY: 'backend__ready' = 'backend__ready'; export const CONNECTING: 'backend__connecting' = 'backend__connecting'; export const CONNECTED: 'backend__connected' = 'backend__connected'; export const DISCONNECTED: 'backend__disconnected' = 'backend__disconnected'; \ No newline at end of file diff --git a/src/actions/constants/discovery.js b/src/actions/constants/discovery.js index 1fca3045..e7287b1e 100644 --- a/src/actions/constants/discovery.js +++ b/src/actions/constants/discovery.js @@ -5,5 +5,5 @@ export const START: 'discovery__start' = 'discovery__start'; export const STOP: 'discovery__stop' = 'discovery__stop'; export const COMPLETE: 'discovery__complete' = 'discovery__complete'; export const WAITING_FOR_DEVICE: 'discovery__waiting_for_device' = 'discovery__waiting_for_device'; -export const WAITING_FOR_BACKEND: 'discovery__waiting_for_backend' = 'discovery__waiting_for_backend'; +export const WAITING_FOR_BLOCKCHAIN: 'discovery__waiting_for_blockchain' = 'discovery__waiting_for_blockchain'; export const FROM_STORAGE: 'discovery__from_storage' = 'discovery__from_storage'; \ No newline at end of file diff --git a/src/actions/constants/web3.js b/src/actions/constants/web3.js index 232db739..54b8836f 100644 --- a/src/actions/constants/web3.js +++ b/src/actions/constants/web3.js @@ -7,4 +7,5 @@ export const CREATE: 'web3__create' = 'web3__create'; export const READY: 'web3__ready' = 'web3__ready'; export const BLOCK_UPDATED: 'web3__block_updated' = 'web3__block_updated'; export const GAS_PRICE_UPDATED: 'web3__gas_price_updated' = 'web3__gas_price_updated'; -export const PENDING_TX_RESOLVED: 'web3__pending_tx_resolved' = 'web3__pending_tx_resolved'; \ No newline at end of file +export const PENDING_TX_RESOLVED: 'web3__pending_tx_resolved' = 'web3__pending_tx_resolved'; +export const DISCONNECT: 'web3__disconnect' = 'web3__disconnect'; \ No newline at end of file From e4552b09985ce05681bba42b9724d2e251468253 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 14:39:08 +0200 Subject: [PATCH 26/51] update web3 flowtype --- src/flowtype/npm/web3.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/flowtype/npm/web3.js b/src/flowtype/npm/web3.js index eff45ab0..1b04d7d4 100644 --- a/src/flowtype/npm/web3.js +++ b/src/flowtype/npm/web3.js @@ -13,6 +13,9 @@ declare module 'web3' { }; declare type WebsocketProviderT = { + connection: { + close: () => void; + }; // WebSocket type on: (type: string, callback: () => any) => void; removeAllListeners: (type: string) => void; reset: () => void; From 1379a2e7450d25f5b029c448dc340b8bdafd0dec Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 14:40:41 +0200 Subject: [PATCH 27/51] update actions and reducers --- src/actions/BlockchainActions.js | 64 ++++++++++++-------- src/actions/DiscoveryActions.js | 23 +++++-- src/actions/TrezorConnectActions.js | 3 - src/actions/Web3Actions.js | 90 +++++++++++----------------- src/reducers/DiscoveryReducer.js | 17 +++--- src/reducers/PendingTxReducer.js | 41 ++++++------- src/reducers/Web3Reducer.js | 9 +++ src/services/TrezorConnectService.js | 10 ++-- 8 files changed, 136 insertions(+), 121 deletions(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 3e63144f..9e4a79a3 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -34,12 +34,8 @@ import type { Token } from 'reducers/TokensReducer'; import type { NetworkToken } from 'reducers/LocalStorageReducer'; export type BlockchainAction = { - type: typeof BLOCKCHAIN.START | typeof BLOCKCHAIN.CONNECTING, - network: string, -} | { - type: typeof BLOCKCHAIN.STOP, - network: string, -}; + type: typeof BLOCKCHAIN.READY, +} export const discoverAccount = (device: TrezorDevice, xpub: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { // get data from connect @@ -93,36 +89,22 @@ export const estimateGasLimit = (network: string, data: string, value: string, g export const onBlockMined = (network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { // try to resolve pending transactions - // await dispatch( Web3Actions.resolvePendingTransactions(network) ); - - // get network accounts - // const accounts: Array = getState().accounts.filter(a => a.network === network).map(a => { - // return { - // address: a.address, - // block: a.block, - // transactions: a.transactions - // } - // }); + await dispatch( Web3Actions.resolvePendingTransactions(network) ); + const accounts: Array = getState().accounts.filter(a => a.network === network); - // find out which account changed const response = await TrezorConnect.ethereumGetAccountInfo({ accounts, coin: network, }); - if (!response.success) { - - } else { + if (response.success) { response.payload.forEach((a, i) => { if (a.transactions > 0) { - // dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) + dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) } }); } - - //return await dispatch( Web3Actions.estimateGasLimit(network, { to: '', data, value, gasPrice }) ); - console.warn("onBlockMined", response) } export const onNotification = (payload: any): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { @@ -177,4 +159,38 @@ export const subscribe = (network: string): PromiseAction => async (dispat accounts: [], coin: network }); +} + +// Conditionally subscribe to blockchain backend +// called after TrezorConnect.init successfully emits TRANSPORT.START event +// checks if there are discovery processes loaded from LocalStorage +// if so starts subscription to proper networks +export const init = (): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + if (getState().discovery.length > 0) { + // get unique networks + const networks: Array = []; + getState().discovery.forEach(discovery => { + if (networks.indexOf(discovery.network) < 0) { + networks.push(discovery.network); + } + }); + + // subscribe + for (let i = 0; i < networks.length; i++) { + await dispatch( subscribe(networks[i]) ); + } + } else { + await dispatch( subscribe('ropsten') ); + } + + // continue wallet initialization + dispatch({ + type: BLOCKCHAIN.READY + }); +} + +// Handle BLOCKCHAIN.ERROR event from TrezorConnect +// disconnect and remove Web3 webscocket instance if exists +export const error = (payload: any): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + dispatch( Web3Actions.disconnect(payload.coin) ); } \ No newline at end of file diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index 58be9d91..107a061c 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -6,7 +6,7 @@ import * as DISCOVERY from 'actions/constants/discovery'; import * as ACCOUNT from 'actions/constants/account'; import * as NOTIFICATION from 'actions/constants/notification'; import type { - ThunkAction, AsyncAction, Action, GetState, Dispatch, TrezorDevice, + ThunkAction, AsyncAction, PromiseAction, Action, GetState, Dispatch, TrezorDevice, } from 'flowtype'; import type { Discovery, State } from 'reducers/DiscoveryReducer'; import * as AccountsActions from './AccountsActions'; @@ -26,7 +26,7 @@ export type DiscoveryStartAction = { } export type DiscoveryWaitingAction = { - type: typeof DISCOVERY.WAITING_FOR_DEVICE | typeof DISCOVERY.WAITING_FOR_BACKEND, + type: typeof DISCOVERY.WAITING_FOR_DEVICE | typeof DISCOVERY.WAITING_FOR_BLOCKCHAIN, device: TrezorDevice, network: string } @@ -80,8 +80,12 @@ export const start = (device: TrezorDevice, network: string, ignoreCompleted?: b } const blockchain = getState().blockchain.find(b => b.name === network); - if (blockchain && !blockchain.connected) { - console.error("NO BACKEND!") // TODO + if (blockchain && !blockchain.connected && (!discoveryProcess || !discoveryProcess.completed)) { + dispatch({ + type: DISCOVERY.WAITING_FOR_BLOCKCHAIN, + device, + network, + }); return; } @@ -93,7 +97,7 @@ export const start = (device: TrezorDevice, network: string, ignoreCompleted?: b device, network, }); - } else if (discoveryProcess.interrupted || discoveryProcess.waitingForDevice) { + } else if (discoveryProcess.interrupted || discoveryProcess.waitingForDevice || discoveryProcess.waitingForBlockchain) { // discovery cycle was interrupted // start from beginning dispatch(begin(device, network)); @@ -268,12 +272,19 @@ const finish = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction } +export const reconnect = (network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + await dispatch(BlockchainActions.subscribe(network)); + dispatch(restore()); +} + export const restore = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { const selected = getState().wallet.selectedDevice; if (selected && selected.connected && selected.features) { - const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === selected.state && d.waitingForDevice); + const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === selected.state && (d.interrupted || d.waitingForDevice || d.waitingForBlockchain)); + console.warn("AAAA2") if (discoveryProcess) { + console.warn("AAAA3", discoveryProcess) dispatch(start(selected, discoveryProcess.network)); } } diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index 064b04d8..eeef3218 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -9,7 +9,6 @@ import { getDuplicateInstanceNumber } from 'reducers/utils'; import { push } from 'react-router-redux'; - import type { DeviceMessage, DeviceMessageType, @@ -129,8 +128,6 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS // $FlowIssue LOCAL not declared window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://connect.trezor.io/5/'; // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://sisyfos.trezor.io/connect/'; - //window.__TREZOR_CONNECT_SRC = 'https://sisyfos.trezor.io/connect/'; - // window.__TREZOR_CONNECT_SRC = 'https://localhost:8088/'; try { await TrezorConnect.init({ diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index 73623539..9050cd85 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -16,6 +16,7 @@ import * as PENDING from 'actions/constants/pendingTx'; import type { Dispatch, GetState, + ThunkAction, AsyncAction, PromiseAction, AccountDiscovery, @@ -23,6 +24,7 @@ import type { EthereumPreparedTx } from 'flowtype'; +import type { EthereumAccount } from 'trezor-connect'; import type { Account } from 'reducers/AccountsReducer'; import type { PendingTx } from 'reducers/PendingTxReducer'; import type { Web3Instance } from 'reducers/Web3Reducer'; @@ -48,7 +50,7 @@ export type Web3Action = { } | { type: typeof WEB3.START, } | { - type: typeof WEB3.CREATE, + type: typeof WEB3.CREATE | typeof WEB3.DISCONNECT, instance: Web3Instance } | Web3UpdateBlockAction | Web3UpdateGasPriceAction; @@ -108,13 +110,8 @@ export const initWeb3 = (network: string, urlIndex: number = 0): PromiseAction { - web3.currentProvider.removeAllListeners('connect'); - web3.currentProvider.removeAllListeners('end'); - web3.currentProvider.removeAllListeners('error'); - web3.currentProvider.reset(); - // if (web3.eth) - // web3.eth.clearSubscriptions(); + web3.currentProvider.reset(); const instance = getState().web3.find(w3 => w3.network === network); if (instance && instance.web3.currentProvider.connected) { @@ -263,14 +260,25 @@ export const getTxInput = (): PromiseAction => async (dispatch: Dispatch, } -export const updateAccount = (account: Account, newAccount: AccountDiscovery, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const updateAccount = (account: Account, newAccount: EthereumAccount, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const instance: Web3Instance = await dispatch( initWeb3(network) ); const balance = await instance.web3.eth.getBalance(account.address); const nonce = await instance.web3.eth.getTransactionCount(account.address); - dispatch( AccountsActions.update( { ...account, ...newAccount, balance: EthereumjsUnits.convert(balance, 'wei', 'ether'), nonce }) ); - // TODO update tokens for this account - + + // update tokens for this account + const tokens = getState().tokens.filter(t => t.network === account.network && t.ethAddress === account.address); + for (const token of tokens) { + const balance = await dispatch( getTokenBalance(token) ); + // const newBalance: string = balance.dividedBy(Math.pow(10, token.decimals)).toString(10); + if (balance !== token.balance) { + dispatch(TokenActions.setBalance( + token.address, + token.ethAddress, + balance, + )); + } + } } export const getTokenInfo = (address: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { @@ -337,48 +345,18 @@ export const estimateGasLimit = (network: string, options: EstimateGasOptions): return limit; }; -// export const prepareTx = (tx: EthereumTxRequest): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { - -// const instance = await dispatch( initWeb3(tx.network) ); -// const token = tx.token; -// let data: string = `0x${tx.data}`; // TODO: check if already prefixed -// let value: string = instance.web3.utils.toHex( EthereumjsUnits.convert(tx.amount, 'ether', 'wei') ); -// let to: string = tx.to; - -// if (token) { -// // smart contract transaction -// const contract = instance.erc20.clone(); -// contract.options.address = token.address; -// const tokenAmount: string = new BigNumber(tx.amount).times(Math.pow(10, token.decimals)).toString(10); -// data = instance.erc20.methods.transfer(to, tokenAmount).encodeABI(); -// value = '0x00'; -// to = token.address; -// } - -// return { -// to, -// value, -// data, -// chainId: instance.chainId, -// nonce: instance.web3.utils.toHex(tx.nonce), -// gasLimit: instance.web3.utils.toHex(tx.gasLimit), -// gasPrice: instance.web3.utils.toHex( EthereumjsUnits.convert(tx.gasPrice, 'gwei', 'wei') ), -// r: '', -// s: '', -// v: '', -// } -// }; - -// export const pushTx = (network: string, tx: EthereumPreparedTx): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { -// const instance = await dispatch( initWeb3(network) ); -// const ethTx = new EthereumjsTx(tx); -// const serializedTx = `0x${ethTx.serialize().toString('hex')}`; - -// return new Promise((resolve, reject) => { -// instance.web3.eth.sendSignedTransaction(serializedTx) -// .on('error', error => reject(error)) -// .once('transactionHash', (hash: string) => { -// resolve(hash); -// }); -// }); -// }; +export const disconnect = (network: string): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { + // check if Web3 was already initialized + const instance = getState().web3.find(w3 => w3.network === network); + if (instance) { + // reset current connection + instance.web3.currentProvider.reset(); + instance.web3.currentProvider.connection.close(); + + // remove instance from reducer + dispatch({ + type: WEB3.DISCONNECT, + instance + }); + } +}; diff --git a/src/reducers/DiscoveryReducer.js b/src/reducers/DiscoveryReducer.js index 244df89c..aebb392e 100644 --- a/src/reducers/DiscoveryReducer.js +++ b/src/reducers/DiscoveryReducer.js @@ -29,7 +29,7 @@ export type Discovery = { interrupted: boolean; completed: boolean; waitingForDevice: boolean; - waitingForBackend: boolean; + waitingForBlockchain: boolean; } export type State = Array; @@ -53,7 +53,7 @@ const start = (state: State, action: DiscoveryStartAction): State => { interrupted: false, completed: false, waitingForDevice: false, - waitingForBackend: false, + waitingForBlockchain: false, }; const newState: State = [...state]; @@ -96,6 +96,7 @@ const stop = (state: State, action: DiscoveryStopAction): State => { if (d.deviceState === action.device.state && !d.completed) { d.interrupted = true; d.waitingForDevice = false; + d.waitingForBlockchain = false; } return d; }); @@ -114,7 +115,7 @@ const waitingForDevice = (state: State, action: DiscoveryWaitingAction): State = interrupted: false, completed: false, waitingForDevice: true, - waitingForBackend: false, + waitingForBlockchain: false, }; const index: number = findIndex(state, action.network, deviceState); @@ -128,7 +129,7 @@ const waitingForDevice = (state: State, action: DiscoveryWaitingAction): State = return newState; }; -const waitingForBackend = (state: State, action: DiscoveryWaitingAction): State => { +const waitingForBlockchain = (state: State, action: DiscoveryWaitingAction): State => { const deviceState: string = action.device.state || '0'; const instance: Discovery = { network: action.network, @@ -141,7 +142,7 @@ const waitingForBackend = (state: State, action: DiscoveryWaitingAction): State interrupted: false, completed: false, waitingForDevice: false, - waitingForBackend: true, + waitingForBlockchain: true, }; const index: number = findIndex(state, action.network, deviceState); @@ -167,8 +168,8 @@ export default function discovery(state: State = initialState, action: Action): return complete(state, action); case DISCOVERY.WAITING_FOR_DEVICE: return waitingForDevice(state, action); - case DISCOVERY.WAITING_FOR_BACKEND: - return waitingForBackend(state, action); + case DISCOVERY.WAITING_FOR_BLOCKCHAIN: + return waitingForBlockchain(state, action); case DISCOVERY.FROM_STORAGE: return action.payload.map((d) => { const hdKey: HDKey = new HDKey(); @@ -179,7 +180,7 @@ export default function discovery(state: State = initialState, action: Action): hdKey, interrupted: false, waitingForDevice: false, - waitingForBackend: false, + waitingForBlockchain: false, }; }); case CONNECT.FORGET: diff --git a/src/reducers/PendingTxReducer.js b/src/reducers/PendingTxReducer.js index 5cccf9e8..b8c80f57 100644 --- a/src/reducers/PendingTxReducer.js +++ b/src/reducers/PendingTxReducer.js @@ -22,23 +22,24 @@ export type State = Array; const initialState: State = []; -// const add01 = (state: State, action: SendTxAction): State => { -// const newState = [...state]; -// newState.push({ -// id: action.txid, -// network: action.account.network, -// currency: action.selectedCurrency, -// amount: action.amount, -// total: action.total, -// tx: action.tx, -// nonce: action.nonce, -// address: action.account.address, -// rejected: false, -// }); -// return newState; -// }; +const add = (state: State, action: SendTxAction): State => { + const newState = [...state]; + newState.push({ + type: 'send', + id: action.txid, + network: action.account.network, + currency: action.selectedCurrency, + amount: action.amount, + total: action.total, + tx: action.tx, + nonce: action.nonce, + address: action.account.address, + rejected: false, + }); + return newState; +}; -const add = (state: State, payload: any): State => { +const add_NEW = (state: State, payload: any): State => { const newState = [...state]; newState.push(payload); return newState; @@ -55,11 +56,11 @@ const reject = (state: State, id: string): State => state.map((tx) => { export default function pending(state: State = initialState, action: Action): State { switch (action.type) { - // case SEND.TX_COMPLETE: - // return add(state, action); + case SEND.TX_COMPLETE: + return add(state, action); - case PENDING.ADD: - return add(state, action.payload); + // case PENDING.ADD: + // return add(state, action.payload); case PENDING.TX_RESOLVED: return remove(state, action.tx.id); case PENDING.TX_NOT_FOUND: diff --git a/src/reducers/Web3Reducer.js b/src/reducers/Web3Reducer.js index d0d45d23..9c25d9c8 100644 --- a/src/reducers/Web3Reducer.js +++ b/src/reducers/Web3Reducer.js @@ -51,6 +51,13 @@ const updateGasPrice = (state: State, action: Web3UpdateGasPriceAction): State = return newState; }; +const disconnect = (state: State, instance: Web3Instance): State => { + const index: number = state.indexOf(instance); + const newState: Array = [...state]; + newState.splice(index, 1); + return newState; +}; + export default function web3(state: State = initialState, action: Action): State { switch (action.type) { case WEB3.CREATE: @@ -59,6 +66,8 @@ export default function web3(state: State = initialState, action: Action): State return updateLatestBlock(state, action); case WEB3.GAS_PRICE_UPDATED: return updateGasPrice(state, action); + case WEB3.DISCONNECT: + return disconnect(state, action.instance); default: return state; } diff --git a/src/services/TrezorConnectService.js b/src/services/TrezorConnectService.js index a320cfd8..5a4255c2 100644 --- a/src/services/TrezorConnectService.js +++ b/src/services/TrezorConnectService.js @@ -10,6 +10,7 @@ import * as BlockchainActions from 'actions/BlockchainActions'; import * as ModalActions from 'actions/ModalActions'; import * as STORAGE from 'actions/constants/localStorage'; import * as CONNECT from 'actions/constants/TrezorConnect'; +import { READY as BLOCKCHAIN_READY } from 'actions/constants/blockchain'; import type { Middleware, @@ -32,10 +33,9 @@ const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: Middlewa // TODO: check if modal is open // api.dispatch( push('/') ); } else if (action.type === TRANSPORT.START) { + api.dispatch(BlockchainActions.init()); + } else if (action.type === BLOCKCHAIN_READY) { api.dispatch(TrezorConnectActions.postInit()); - - api.dispatch( BlockchainActions.subscribe('ropsten') ); - } else if (action.type === DEVICE.DISCONNECT) { api.dispatch(TrezorConnectActions.deviceDisconnect(action.device)); } else if (action.type === CONNECT.REMEMBER_REQUEST) { @@ -64,9 +64,11 @@ const TrezorConnectService: Middleware = (api: MiddlewareAPI) => (next: Middlewa } else if (action.type === CONNECT.COIN_CHANGED) { api.dispatch(TrezorConnectActions.coinChanged(action.payload.network)); } else if (action.type === BLOCKCHAIN.BLOCK) { - // api.dispatch(BlockchainActions.onBlockMined(action.payload.coin)); + api.dispatch(BlockchainActions.onBlockMined(action.payload.coin)); } else if (action.type === BLOCKCHAIN.NOTIFICATION) { // api.dispatch(BlockchainActions.onNotification(action.payload)); + } else if (action.type === BLOCKCHAIN.ERROR) { + api.dispatch( BlockchainActions.error(action.payload) ); } return action; From 67eadc332d13516027756e7615d52ddfca7a4091 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 14:41:06 +0200 Subject: [PATCH 28/51] added blockchain connect Notification --- .../components/SelectedAccount/index.js | 36 +++++++++++++++++-- .../Wallet/views/AccountReceive/Container.js | 3 ++ .../Wallet/views/AccountSend/Container.js | 4 ++- .../Wallet/views/AccountSummary/Container.js | 3 ++ 4 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/views/Wallet/components/SelectedAccount/index.js b/src/views/Wallet/components/SelectedAccount/index.js index 98f5c092..259a9773 100644 --- a/src/views/Wallet/components/SelectedAccount/index.js +++ b/src/views/Wallet/components/SelectedAccount/index.js @@ -1,6 +1,7 @@ /* @flow */ import * as React from 'react'; import { Notification } from 'components/Notification'; +import { reconnect } from 'actions/DiscoveryActions'; import type { State } from 'flowtype'; @@ -8,11 +9,12 @@ export type StateProps = { className: string; selectedAccount: $ElementType, wallet: $ElementType, + blockchain: $ElementType, children?: React.Node } export type DispatchProps = { - + blockchainReconnect: typeof reconnect; } export type Props = StateProps & DispatchProps; @@ -28,8 +30,26 @@ const SelectedAccount = (props: Props) => { const { account, discovery, + network } = accountState; + const blockchain = props.blockchain.find(b => b.name === network.network); + if (blockchain && !blockchain.connected) { + return ( + { + await props.blockchainReconnect(network.network); + } + }] + } /> + ); + } + // account not found (yet). checking why... if (!account) { if (!discovery || discovery.waitingForDevice) { @@ -57,10 +77,20 @@ const SelectedAccount = (props: Props) => { message="Connect device to load accounts" /> ); - } if (discovery.waitingForBackend) { + } if (discovery.waitingForBlockchain) { // case 4: backend is not working return ( - + { + await props.blockchainReconnect(discovery.network); + } + }] + } /> ); } if (discovery.completed) { // case 5: account not found and discovery is completed diff --git a/src/views/Wallet/views/AccountReceive/Container.js b/src/views/Wallet/views/AccountReceive/Container.js index 5695877b..22f5eda6 100644 --- a/src/views/Wallet/views/AccountReceive/Container.js +++ b/src/views/Wallet/views/AccountReceive/Container.js @@ -2,6 +2,7 @@ import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; +import { reconnect } from 'actions/DiscoveryActions'; import { showAddress } from 'actions/ReceiveActions'; import type { MapStateToProps, MapDispatchToProps } from 'react-redux'; import type { State, Dispatch } from 'flowtype'; @@ -28,12 +29,14 @@ const mapStateToProps: MapStateToProps = (state: St className: 'receive', selectedAccount: state.selectedAccount, wallet: state.wallet, + blockchain: state.blockchain, receive: state.receive, modal: state.modal, }); const mapDispatchToProps: MapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({ + blockchainReconnect: bindActionCreators(reconnect, dispatch), showAddress: bindActionCreators(showAddress, dispatch), }); diff --git a/src/views/Wallet/views/AccountSend/Container.js b/src/views/Wallet/views/AccountSend/Container.js index 847bac63..0dee8fbc 100644 --- a/src/views/Wallet/views/AccountSend/Container.js +++ b/src/views/Wallet/views/AccountSend/Container.js @@ -5,6 +5,7 @@ import * as React from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; +import { reconnect } from 'actions/DiscoveryActions'; import SendFormActions from 'actions/SendFormActions'; import * as SessionStorageActions from 'actions/SessionStorageActions'; import type { MapStateToProps, MapDispatchToProps } from 'react-redux'; @@ -12,7 +13,6 @@ import type { State, Dispatch } from 'flowtype'; import type { StateProps as BaseStateProps, DispatchProps as BaseDispatchProps } from 'views/Wallet/components/SelectedAccount'; import AccountSend from './index'; - type OwnProps = { } export type StateProps = BaseStateProps & { @@ -33,6 +33,7 @@ const mapStateToProps: MapStateToProps = (state: St className: 'send-from', selectedAccount: state.selectedAccount, wallet: state.wallet, + blockchain: state.blockchain, sendForm: state.sendForm, fiat: state.fiat, @@ -40,6 +41,7 @@ const mapStateToProps: MapStateToProps = (state: St }); const mapDispatchToProps: MapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({ + blockchainReconnect: bindActionCreators(reconnect, dispatch), sendFormActions: bindActionCreators(SendFormActions, dispatch), saveSessionStorage: bindActionCreators(SessionStorageActions.save, dispatch), }); diff --git a/src/views/Wallet/views/AccountSummary/Container.js b/src/views/Wallet/views/AccountSummary/Container.js index e7239ebb..5163b737 100644 --- a/src/views/Wallet/views/AccountSummary/Container.js +++ b/src/views/Wallet/views/AccountSummary/Container.js @@ -3,6 +3,7 @@ import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; import type { MapStateToProps, MapDispatchToProps } from 'react-redux'; +import { reconnect } from 'actions/DiscoveryActions'; import * as TokenActions from 'actions/TokenActions'; import type { State, Dispatch } from 'flowtype'; @@ -30,6 +31,7 @@ const mapStateToProps: MapStateToProps = (state: St className: 'summary', selectedAccount: state.selectedAccount, wallet: state.wallet, + blockchain: state.blockchain, tokens: state.tokens, summary: state.summary, @@ -38,6 +40,7 @@ const mapStateToProps: MapStateToProps = (state: St }); const mapDispatchToProps: MapDispatchToProps = (dispatch: Dispatch): DispatchProps => ({ + blockchainReconnect: bindActionCreators(reconnect, dispatch), addToken: bindActionCreators(TokenActions.add, dispatch), loadTokens: bindActionCreators(TokenActions.load, dispatch), removeToken: bindActionCreators(TokenActions.remove, dispatch), From 8884d65c8fa4c87cd5f7860b7cbe84604cfbea28 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 14:43:02 +0200 Subject: [PATCH 29/51] removed unused action --- src/actions/DiscoveryActions.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index 107a061c..202bc8fa 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -210,8 +210,6 @@ const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): Asy transactions: account.transactions } }); - - dispatch( Web3Actions.getTxInput() ); } if (accountIsEmpty) { From f0d7de8aa1a458fb4c0c0205748c7966da2aa49b Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 14:51:45 +0200 Subject: [PATCH 30/51] ethereumGetAccountInfo only if there are some accounts --- src/actions/BlockchainActions.js | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 9e4a79a3..de319eb5 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -92,18 +92,20 @@ export const onBlockMined = (network: string): PromiseAction => async (dis await dispatch( Web3Actions.resolvePendingTransactions(network) ); const accounts: Array = getState().accounts.filter(a => a.network === network); - // find out which account changed - const response = await TrezorConnect.ethereumGetAccountInfo({ - accounts, - coin: network, - }); - - if (response.success) { - response.payload.forEach((a, i) => { - if (a.transactions > 0) { - dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) - } + if (accounts.length > 0) { + // find out which account changed + const response = await TrezorConnect.ethereumGetAccountInfo({ + accounts, + coin: network, }); + + if (response.success) { + response.payload.forEach((a, i) => { + if (a.transactions > 0) { + dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) + } + }); + } } } @@ -179,8 +181,6 @@ export const init = (): PromiseAction => async (dispatch: Dispatch, getSta for (let i = 0; i < networks.length; i++) { await dispatch( subscribe(networks[i]) ); } - } else { - await dispatch( subscribe('ropsten') ); } // continue wallet initialization From 44709ddd10ef32b18ec1f1360e401c02bb6dd1e5 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Thu, 13 Sep 2018 16:37:02 +0200 Subject: [PATCH 31/51] rename LICENSE to LICENSE.md --- LICENSE => LICENSE.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename LICENSE => LICENSE.md (100%) diff --git a/LICENSE b/LICENSE.md similarity index 100% rename from LICENSE rename to LICENSE.md From 17ba68f19bb3e5a070b541830cc42ddb8b225f54 Mon Sep 17 00:00:00 2001 From: Pavol Rusnak Date: Thu, 13 Sep 2018 16:40:16 +0200 Subject: [PATCH 32/51] fix format in license --- LICENSE.md | 104 ++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 54 deletions(-) diff --git a/LICENSE.md b/LICENSE.md index 3f77f61c..1bebd9dc 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,54 +1,50 @@ -TREZOR REFERENCE SOURCE LICENSE (T-RSL) -======================================= - -This license governs use of the accompanying software. If you use the software, -you accept this license. If you do not accept the license, do not use the -software. - -1. Definitions --------------- - -The terms "reproduce," "reproduction" and "distribution" have the same meaning -here as under U.S. copyright law. - -"You" means the licensee of the software. - -"Your company" means the company you worked for when you downloaded the -software. - -"Reference use" means use of the software within your company as a reference, -in read only form, for the sole purposes of debugging your products, -maintaining your products, or enhancing the interoperability of your products -with the software, and specifically excludes the right to distribute the -software outside of your company. - -"Licensed patents" means any Licensor patent claims which read directly on the -software as distributed by the Licensor under this license. - -2. Grant of Rights ------------------- - -(A) Copyright Grant - Subject to the terms of this license, the Licensor grants -you a non-transferable, non-exclusive, worldwide, royalty-free copyright -license to reproduce the software for reference use. - -(B) Patent Grant - Subject to the terms of this license, the Licensor grants -you a non-transferable, non-exclusive, worldwide, royalty-free patent license -under licensed patents for reference use. - -3. Limitations --------------- - -(A) No Trademark License - This license does not grant you any rights to use -the Licensor's name, logo, or trademarks. - -(B) If you begin patent litigation against the Licensor over patents that you -think may apply to the software (including a cross-claim or counterclaim in -a lawsuit), your license to the software ends automatically. - -(C) The software is licensed "as-is." You bear the risk of using it. The -Licensor gives no express warranties, guarantees or conditions. You may have -additional consumer rights under your local laws which this license cannot -change. To the extent permitted under your local laws, the Licensor excludes -the implied warranties of merchantability, fitness for a particular purpose and -non-infringement. +# TREZOR REFERENCE SOURCE LICENSE (T-RSL) + +This license governs use of the accompanying software. If you use the software, +you accept this license. If you do not accept the license, do not use the +software. + +## 1. Definitions + +The terms "reproduce," "reproduction" and "distribution" have the same meaning +here as under U.S. copyright law. + +"You" means the licensee of the software. + +"Your company" means the company you worked for when you downloaded the +software. + +"Reference use" means use of the software within your company as a reference, +in read only form, for the sole purposes of debugging your products, +maintaining your products, or enhancing the interoperability of your products +with the software, and specifically excludes the right to distribute the +software outside of your company. + +"Licensed patents" means any Licensor patent claims which read directly on the +software as distributed by the Licensor under this license. + +## 2. Grant of Rights + +(A) Copyright Grant - Subject to the terms of this license, the Licensor grants +you a non-transferable, non-exclusive, worldwide, royalty-free copyright +license to reproduce the software for reference use. + +(B) Patent Grant - Subject to the terms of this license, the Licensor grants +you a non-transferable, non-exclusive, worldwide, royalty-free patent license +under licensed patents for reference use. + +## 3. Limitations + +(A) No Trademark License - This license does not grant you any rights to use +the Licensor's name, logo, or trademarks. + +(B) If you begin patent litigation against the Licensor over patents that you +think may apply to the software (including a cross-claim or counterclaim in +a lawsuit), your license to the software ends automatically. + +(C) The software is licensed "as-is." You bear the risk of using it. The +Licensor gives no express warranties, guarantees or conditions. You may have +additional consumer rights under your local laws which this license cannot +change. To the extent permitted under your local laws, the Licensor excludes +the implied warranties of merchantability, fitness for a particular purpose and +non-infringement. From 8c579a158066ac09f2a6d3449d43232404b315ef Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 19:20:44 +0200 Subject: [PATCH 33/51] fix flow error --- .../Wallet/components/SelectedAccount/index.js | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/src/views/Wallet/components/SelectedAccount/index.js b/src/views/Wallet/components/SelectedAccount/index.js index 259a9773..9067b6b1 100644 --- a/src/views/Wallet/components/SelectedAccount/index.js +++ b/src/views/Wallet/components/SelectedAccount/index.js @@ -33,6 +33,8 @@ const SelectedAccount = (props: Props) => { network } = accountState; + if (!network) return; // TODO: this shouldn't happen. change accountState reducer? + const blockchain = props.blockchain.find(b => b.name === network.network); if (blockchain && !blockchain.connected) { return ( @@ -77,21 +79,6 @@ const SelectedAccount = (props: Props) => { message="Connect device to load accounts" /> ); - } if (discovery.waitingForBlockchain) { - // case 4: backend is not working - return ( - { - await props.blockchainReconnect(discovery.network); - } - }] - } /> - ); } if (discovery.completed) { // case 5: account not found and discovery is completed return ( From b8fff2a30806ffc97df1dae21f7a34ccfc1fb9ea Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 19:20:52 +0200 Subject: [PATCH 34/51] change web3 url --- public/data/appConfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/public/data/appConfig.json b/public/data/appConfig.json index 8aa1cee6..0f93f264 100644 --- a/public/data/appConfig.json +++ b/public/data/appConfig.json @@ -74,7 +74,6 @@ } ], "web3": [ - "wss://ropsten3.trezor.io", "wss://ropsten1.trezor.io/geth" ], "explorer": { From d4c9db093c9e7d6611c2209ba20afe22d06c3dcc Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 19:21:40 +0200 Subject: [PATCH 35/51] updateGasPrice on block mined --- src/actions/BlockchainActions.js | 4 +- src/actions/Web3Actions.js | 84 +++++++------------------------- 2 files changed, 20 insertions(+), 68 deletions(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index de319eb5..6dc45c39 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -91,6 +91,8 @@ export const onBlockMined = (network: string): PromiseAction => async (dis // try to resolve pending transactions await dispatch( Web3Actions.resolvePendingTransactions(network) ); + await dispatch( Web3Actions.updateGasPrice(network) ); + const accounts: Array = getState().accounts.filter(a => a.network === network); if (accounts.length > 0) { // find out which account changed @@ -98,7 +100,7 @@ export const onBlockMined = (network: string): PromiseAction => async (dis accounts, coin: network, }); - + if (response.success) { response.payload.forEach((a, i) => { if (a.transactions > 0) { diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index 9050cd85..60b132bb 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -137,57 +137,6 @@ export const initWeb3 = (network: string, urlIndex: number = 0): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { - - // const latestBlock = await instance.web3.eth.getBlockNumber(); - - // dispatch({ - // type: WEB3.BLOCK_UPDATED, - // network: instance.network, - // blockHash: latestBlock, - // }); - - - - // TODO: filter only current device - const accounts = getState().accounts.filter(a => a.network === instance.network); - for (const account of accounts) { - const nonce = await instance.web3.eth.getTransactionCount(account.address); - if (nonce !== account.nonce) { - dispatch(AccountsActions.setNonce(account.address, account.network, account.deviceState, nonce)); - } - - const balance = await instance.web3.eth.getBalance(account.address); - const newBalance = EthereumjsUnits.convert(balance, 'wei', 'ether'); - if (newBalance !== account.balance) { - dispatch(AccountsActions.setBalance( - account.address, - account.network, - account.deviceState, - newBalance - )); - } - } - - const tokens = getState().tokens.filter(t => t.network === instance.network); - for (const token of tokens) { - const balance = await dispatch( getTokenBalance(token) ); - console.warn("TOK BALAC", balance) - // const newBalance: string = balance.dividedBy(Math.pow(10, token.decimals)).toString(10); - if (balance !== token.balance) { - dispatch(TokenActions.setBalance( - token.address, - token.ethAddress, - balance, - )); - } - } - - // dispatch(getGasPrice(network)); - - -} - export const discoverAccount = (address: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const instance: Web3Instance = await dispatch( initWeb3(network) ); const balance = await instance.web3.eth.getBalance(address); @@ -312,24 +261,25 @@ export const getCurrentGasPrice = (network: string): PromiseAction => as if (instance) { return EthereumjsUnits.convert(instance.gasPrice, 'wei', 'gwei'); } else { - return "0"; + throw "0"; } +} - // const index: number = getState().web3.findIndex(w3 => w3.network === network); - - // const web3instance = getState().web3[index]; - // const web3 = web3instance.web3; - // web3.eth.getGasPrice((error, gasPrice) => { - // if (!error) { - // if (web3instance.gasPrice && web3instance.gasPrice.toString() !== gasPrice.toString()) { - // dispatch({ - // type: WEB3.GAS_PRICE_UPDATED, - // network, - // gasPrice, - // }); - // } - // } - // }); +export const updateGasPrice = (network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + try { + const instance = await dispatch( initWeb3(network) ); + const gasPrice = await instance.web3.eth.getGasPrice(); + if (instance.gasPrice !== gasPrice) { + dispatch({ + type: WEB3.GAS_PRICE_UPDATED, + network, + gasPrice + }); + } + } catch (e) { + // silent action + // nothing happens if this fails + } } From 7f11e7207be801d79dd2beddc08280a513c78b08 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Thu, 13 Sep 2018 19:31:32 +0200 Subject: [PATCH 36/51] remove comments --- src/actions/SendFormActions.js | 40 ---------------------------------- 1 file changed, 40 deletions(-) diff --git a/src/actions/SendFormActions.js b/src/actions/SendFormActions.js index 0bd0e8d8..6288c9d6 100644 --- a/src/actions/SendFormActions.js +++ b/src/actions/SendFormActions.js @@ -783,8 +783,6 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge const pendingNonce: number = stateUtils.getPendingNonce(pending); const nonce = pendingNonce > 0 && pendingNonce >= account.nonce ? pendingNonce : account.nonce; - console.warn("NONCE", nonce); - const txData = await dispatch( prepareEthereumTx({ network: network.network, token: isToken ? findToken(getState().tokens, account.address, currentState.currency, account.deviceState) : null, @@ -797,44 +795,6 @@ export const onSend = (): AsyncAction => async (dispatch: Dispatch, getState: Ge nonce }) ); - // let data: string = `0x${currentState.data}`; - // let txAmount: string = w3.toHex(w3.toWei(currentState.amount, 'ether')); - // let txAddress: string = currentState.address; - // if (isToken) { - // const token: ?Token = findToken(getState().tokens, account.address, currentState.currency, account.deviceState); - // if (!token) return; - - // const contract = web3.erc20.at(token.address); - // const amountValue: string = new BigNumber(currentState.amount).times(Math.pow(10, token.decimals)).toString(10); - - // data = contract.transfer.getData(currentState.address, amountValue, { - // from: account.address, - // gasLimit: currentState.gasLimit, - // gasPrice: currentState.gasPrice, - // }); - // txAmount = '0x00'; - // txAddress = token.address; - // } - - - - // console.warn('NONCE', nonce, account.nonce, pendingNonce); - - // const txData = { - // address_n, - // // from: currentAddress.address - // to: txAddress, - // value: txAmount, - // data, - // chainId: web3.chainId, - // nonce: w3.toHex(nonce), - // gasLimit: w3.toHex(currentState.gasLimit), - // gasPrice: w3.toHex(EthereumjsUnits.convert(currentState.gasPrice, 'gwei', 'wei')), - // r: '', - // s: '', - // v: '', - // }; - const selected: ?TrezorDevice = getState().wallet.selectedDevice; if (!selected) return; From 815fba5e6b5cf36cae286c55162f83e91a88959e Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 14 Sep 2018 12:20:39 +0200 Subject: [PATCH 37/51] disable PromiseActions from logger --- src/store.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/store.js b/src/store.js index 25a8d65d..30e78995 100644 --- a/src/store.js +++ b/src/store.js @@ -33,8 +33,8 @@ let composedEnhancers: any; if (process.env.NODE_ENV === 'development') { const excludeLogger = (getState: GetState, action: Action): boolean => { //'@@router/LOCATION_CHANGE' - const excluded: Array = ['LOG_TO_EXCLUDE', 'log__add']; - const pass: Array = excluded.filter(act => action.type === act); + const excluded: Array = ['LOG_TO_EXCLUDE', 'log__add', undefined]; + const pass: Array = excluded.filter(act => action.type === act); return pass.length === 0; }; From 6740b7198d972bfbaba58ef3c598e20800aacf33 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 14 Sep 2018 12:20:59 +0200 Subject: [PATCH 38/51] update account tokens on each block --- src/actions/BlockchainActions.js | 10 +++++++++- src/actions/Web3Actions.js | 4 ++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 6dc45c39..5d2a4781 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -16,6 +16,7 @@ import * as BLOCKCHAIN from 'actions/constants/blockchain'; import * as WEB3 from 'actions/constants/web3'; import * as PENDING from 'actions/constants/pendingTx'; +import * as AccountsActions from './AccountsActions'; import * as Web3Actions from './Web3Actions'; import type { @@ -43,7 +44,6 @@ export const discoverAccount = (device: TrezorDevice, xpub: string, network: str const txs = await TrezorConnect.ethereumGetAccountInfo({ account: { address: xpub, - // block: 3984156, block: 0, transactions: 0 }, @@ -104,7 +104,15 @@ export const onBlockMined = (network: string): PromiseAction => async (dis if (response.success) { response.payload.forEach((a, i) => { if (a.transactions > 0) { + // load additional data from Web3 (balance, nonce, tokens) dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) + } else { + // there are no new txs, just update block + dispatch( AccountsActions.update( { ...accounts[i], ...a }) ); + + // HACK: since blockbook can't work with smart contracts for now + // try to update tokens balances added to this account using Web3 + dispatch( Web3Actions.updateAccountTokens(accounts[i]) ); } }); } diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index 60b132bb..cae70fe1 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -216,6 +216,10 @@ export const updateAccount = (account: Account, newAccount: EthereumAccount, net dispatch( AccountsActions.update( { ...account, ...newAccount, balance: EthereumjsUnits.convert(balance, 'wei', 'ether'), nonce }) ); // update tokens for this account + dispatch( updateAccountTokens(account) ); +} + +export const updateAccountTokens = (account: Account): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const tokens = getState().tokens.filter(t => t.network === account.network && t.ethAddress === account.address); for (const token of tokens) { const balance = await dispatch( getTokenBalance(token) ); From ab2dddbf446ce3b821641477f8f5fc56db6d0fc2 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 14 Sep 2018 16:44:24 +0200 Subject: [PATCH 39/51] renamed blockchain constants --- src/actions/constants/blockchain.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/actions/constants/blockchain.js b/src/actions/constants/blockchain.js index d494f215..ff0d9b36 100644 --- a/src/actions/constants/blockchain.js +++ b/src/actions/constants/blockchain.js @@ -1,6 +1,6 @@ /* @flow */ -export const READY: 'backend__ready' = 'backend__ready'; -export const CONNECTING: 'backend__connecting' = 'backend__connecting'; -export const CONNECTED: 'backend__connected' = 'backend__connected'; -export const DISCONNECTED: 'backend__disconnected' = 'backend__disconnected'; \ No newline at end of file +export const READY: 'blockchain__ready' = 'blockchain__ready'; +export const CONNECTING: 'blockchain__connecting' = 'blockchain__connecting'; +export const CONNECTED: 'blockchain__connected' = 'blockchain__connected'; +export const DISCONNECTED: 'blockchain__disconnected' = 'blockchain__disconnected'; \ No newline at end of file From 7790babb3ad39d4cf961ac290d961c50579c1653 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 14 Sep 2018 16:45:40 +0200 Subject: [PATCH 40/51] changed coin network field, removed "backend" field in config --- public/data/appConfig.json | 35 ++---------------- .../{ropsten-logo.png => trop-logo.png} | Bin 2 files changed, 4 insertions(+), 31 deletions(-) rename src/images/{ropsten-logo.png => trop-logo.png} (100%) diff --git a/public/data/appConfig.json b/public/data/appConfig.json index 0f93f264..c9c3ca0c 100644 --- a/public/data/appConfig.json +++ b/public/data/appConfig.json @@ -3,22 +3,13 @@ { "name": "Ethereum", "symbol": "ETH", - "network": "ethereum", + "network": "eth", "bip44": "m/44'/60'/0'/0", "chainId": 1, "defaultGasPrice": 64, "defaultGasLimit": 21000, "defaultGasLimitTokens": 200000, "tokens": "./data/ethereumTokens.json", - "backends": [ - { - "name": "TREZOR Wallet - Ethereum", - "urls": [ - "https://mainnet.infura.io/QGyVKozSUEh2YhL4s2G4", - "http://88.208.115.69" - ] - } - ], "web3": [ "wss://eth2.trezor.io/geth" ], @@ -30,22 +21,13 @@ { "name": "Ethereum Classic", "symbol": "ETC", - "network": "ethereum-classic", + "network": "etc", "chainId": 61, "bip44": "m/44'/61'/0'/0", "defaultGasPrice": 64, "defaultGasLimit": 21000, "defaultGasLimitTokens": 200000, "tokens": "./data/ethereumClassicTokens.json", - "backends": [ - { - "name": "TREZOR Wallet - Ethereum", - "urls": [ - "https://etc-geth.0xinfra.com/", - "https://mew.epool.io/" - ] - } - ], "web3": [ "wss://etc2.trezor.io/geth" ], @@ -56,23 +38,14 @@ }, { "name": "Ethereum Ropsten", - "symbol": "tETH", - "network": "ropsten", + "symbol": "tROP", + "network": "trop", "chainId": 3, "bip44": "m/44'/60'/0'/0", "defaultGasPrice": 64, "defaultGasLimit": 21000, "defaultGasLimitTokens": 200000, "tokens": "./data/ropstenTokens.json", - "backends": [ - { - "name": "TREZOR Wallet - Ethereum", - "urls": [ - "https://ropsten.infura.io/QGyVKozSUEh2YhL4s2G4", - "http://10.34.2.5:8545" - ] - } - ], "web3": [ "wss://ropsten1.trezor.io/geth" ], diff --git a/src/images/ropsten-logo.png b/src/images/trop-logo.png similarity index 100% rename from src/images/ropsten-logo.png rename to src/images/trop-logo.png From 892f4fe7c0c4d9829642497b9711c24f32fda05f Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Fri, 14 Sep 2018 16:46:17 +0200 Subject: [PATCH 41/51] TrezorConnect BLOCKCHAIN events returns CoinInfo object --- src/actions/BlockchainActions.js | 13 +++++++++---- src/actions/Web3Actions.js | 4 +++- src/reducers/BlockchainReducer.js | 10 ++++++---- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 5d2a4781..9f68065c 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -86,7 +86,9 @@ export const estimateGasLimit = (network: string, data: string, value: string, g return await dispatch( Web3Actions.estimateGasLimit(network, { to: '', data, value, gasPrice }) ); } -export const onBlockMined = (network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const onBlockMined = (coinInfo: any): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { + // incoming "coinInfo" from TrezorConnect is CoinInfo | EthereumNetwork type + const network: string = coinInfo.shortcut.toLowerCase(); // try to resolve pending transactions await dispatch( Web3Actions.resolvePendingTransactions(network) ); @@ -119,12 +121,15 @@ export const onBlockMined = (network: string): PromiseAction => async (dis } } + +// not used for now, waiting for fix in blockbook export const onNotification = (payload: any): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { // this event can be triggered multiple times // 1. check if pair [txid + address] is already in reducer + const network: string = payload.coin.shortcut.toLowerCase(); const address: string = EthereumjsUtil.toChecksumAddress(payload.tx.address); - const txInfo = await dispatch( Web3Actions.getPendingInfo(payload.coin, payload.tx.txid) ); + const txInfo = await dispatch( Web3Actions.getPendingInfo(network, payload.tx.txid) ); // const exists = getState().pending.filter(p => p.id === payload.tx.txid && p.address === address); const exists = getState().pending.filter(p => { @@ -137,7 +142,7 @@ export const onNotification = (payload: any): PromiseAction => async (disp payload: { type: 'send', id: payload.tx.txid, - network: payload.coin, + network, currency: "tETH", amount: txInfo.value, total: "0", @@ -152,7 +157,7 @@ export const onNotification = (payload: any): PromiseAction => async (disp // dispatch({ // type: PENDING.ADD_UNKNOWN, // payload: { - // network: payload.coin, + // network, // ...payload.tx, // } // }); diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index cae70fe1..a6821ef8 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -299,7 +299,9 @@ export const estimateGasLimit = (network: string, options: EstimateGasOptions): return limit; }; -export const disconnect = (network: string): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { +export const disconnect = (coinInfo: any): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { + // incoming "coinInfo" from TrezorConnect is CoinInfo | EthereumNetwork type + const network: string = coinInfo.shortcut.toLowerCase(); // check if Web3 was already initialized const instance = getState().web3.find(w3 => w3.network === network); if (instance) { diff --git a/src/reducers/BlockchainReducer.js b/src/reducers/BlockchainReducer.js index 92de9c27..b4d4a12b 100644 --- a/src/reducers/BlockchainReducer.js +++ b/src/reducers/BlockchainReducer.js @@ -18,12 +18,13 @@ const find = (state: State, name: string): number => { } const connect = (state: State, action: any): State => { + const name = action.payload.coin.shortcut.toLowerCase(); const network: BlockchainNetwork = { - name: action.payload.coin, + name, connected: true, } const newState: State = [...state]; - const index: number = find(newState, action.payload.coin); + const index: number = find(newState, name); if (index >= 0) { newState[index] = network; } else { @@ -33,12 +34,13 @@ const connect = (state: State, action: any): State => { }; const disconnect = (state: State, action: any): State => { + const name = action.payload.coin.shortcut.toLowerCase(); const network: BlockchainNetwork = { - name: action.payload.coin, + name, connected: false, } const newState: State = [...state]; - const index: number = find(newState, action.payload.coin); + const index: number = find(newState, name); if (index >= 0) { newState[index] = network; } else { From 91f20e0dd2058cd3f0f0646c72aeb180b86bf6cc Mon Sep 17 00:00:00 2001 From: Vladimir Volek Date: Mon, 17 Sep 2018 10:18:41 +0200 Subject: [PATCH 42/51] Fixed dependency --- src/views/Wallet/components/LeftNavigation/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/views/Wallet/components/LeftNavigation/index.js b/src/views/Wallet/components/LeftNavigation/index.js index dc57e112..15d2821f 100644 --- a/src/views/Wallet/components/LeftNavigation/index.js +++ b/src/views/Wallet/components/LeftNavigation/index.js @@ -2,7 +2,6 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import colors from 'config/colors'; import Icon from 'components/Icon'; -import Sticky from 'react-sticky-el'; import icons from 'config/icons'; import { TransitionGroup, CSSTransition } from 'react-transition-group'; import styled from 'styled-components'; @@ -178,7 +177,6 @@ class LeftNavigation extends Component { - ); } From 4c9f5468b3f6c42c0f9dfdf169a938970e1008b7 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 18 Sep 2018 11:01:16 +0200 Subject: [PATCH 43/51] cleaning up flowtype (DiscoveryResult + EthTxRequest) --- src/actions/BlockchainActions.js | 11 ++++++--- src/actions/TxActions.js | 26 +++++++++++++++++----- src/actions/Web3Actions.js | 6 ++--- src/flowtype/index.js | 38 -------------------------------- 4 files changed, 30 insertions(+), 51 deletions(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 9f68065c..5221c96e 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -27,8 +27,6 @@ import type { AsyncAction, PromiseAction, ThunkAction, - AccountDiscovery, - EthereumTxRequest } from 'flowtype'; import type { Token } from 'reducers/TokensReducer'; @@ -38,7 +36,14 @@ export type BlockchainAction = { type: typeof BLOCKCHAIN.READY, } -export const discoverAccount = (device: TrezorDevice, xpub: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export type DiscoveryResult = { + transactions: number; + block: number; + balance: string; + nonce: number; +} + +export const discoverAccount = (device: TrezorDevice, xpub: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { // get data from connect // Temporary disabled, enable after trezor-connect@5.0.32 release const txs = await TrezorConnect.ethereumGetAccountInfo({ diff --git a/src/actions/TxActions.js b/src/actions/TxActions.js index ac8535a8..8bdaed0e 100644 --- a/src/actions/TxActions.js +++ b/src/actions/TxActions.js @@ -10,12 +10,28 @@ import type { Dispatch, GetState, PromiseAction, - EthereumTxRequest, - EthereumPreparedTx } from 'flowtype'; +import type { + EthereumTransaction +} from 'trezor-connect'; + +import type { Token } from 'reducers/TokensReducer'; + +type EthereumTxRequest = { + network: string; + token: ?Token; + from: string; + to: string; + amount: string; + data: string; + gasLimit: string; + gasPrice: string; + nonce: number; +} + -export const prepareEthereumTx = (tx: EthereumTxRequest): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const prepareEthereumTx = (tx: EthereumTxRequest): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const instance = await dispatch( initWeb3(tx.network) ); const token = tx.token; let data: string = `0x${tx.data}`; // TODO: check if already prefixed @@ -46,10 +62,8 @@ export const prepareEthereumTx = (tx: EthereumTxRequest): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const serializeEthereumTx = (tx: EthereumTransaction): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const ethTx = new EthereumjsTx(tx); - console.warn("SERIALIZE 1", `0x${ ethTx.serialize().toString('hex') }`) - console.warn("SERIALIZE 2", toHex( ethTx.serialize() )) return `0x${ ethTx.serialize().toString('hex') }`; // return toHex( ethTx.serialize() ); } \ No newline at end of file diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index a6821ef8..6738953d 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -19,9 +19,6 @@ import type { ThunkAction, AsyncAction, PromiseAction, - AccountDiscovery, - EthereumTxRequest, - EthereumPreparedTx } from 'flowtype'; import type { EthereumAccount } from 'trezor-connect'; @@ -30,6 +27,7 @@ import type { PendingTx } from 'reducers/PendingTxReducer'; import type { Web3Instance } from 'reducers/Web3Reducer'; import type { Token } from 'reducers/TokensReducer'; import type { NetworkToken } from 'reducers/LocalStorageReducer'; +import type { DiscoveryResult } from './BlockchainActions'; import * as TokenActions from './TokenActions'; import * as AccountsActions from './AccountsActions'; @@ -137,7 +135,7 @@ export const initWeb3 = (network: string, urlIndex: number = 0): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const discoverAccount = (address: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const instance: Web3Instance = await dispatch( initWeb3(network) ); const balance = await instance.web3.eth.getBalance(address); const nonce = await instance.web3.eth.getTransactionCount(address); diff --git a/src/flowtype/index.js b/src/flowtype/index.js index 3fd602a0..ece6a996 100644 --- a/src/flowtype/index.js +++ b/src/flowtype/index.js @@ -169,41 +169,3 @@ export type PromiseAction = ReduxPromiseAction; export type Store = ReduxStore; export type GetState = () => State; - - -// temporary types -export type AccountDiscovery = { - transactions: number; - block: number; - balance: string; - nonce: number; -} - -import type { Token } from 'reducers/TokensReducer'; - -export type EthereumTxRequest = { - network: string; - token: ?Token; - from: string; - to: string; - amount: string; - data: string; - gasLimit: string; - gasPrice: string; - nonce: number; -} -// copypaste from trezor-connect -export type EthereumPreparedTx = { - to: string, - value: string, - gasPrice: string, - gasLimit: string, - nonce: string, - data?: string, - chainId?: number, - txType?: number, - v: string, - r: string, - s: string, -} - From d4bcf160d273f0868b84a52721f16de89ed08e26 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 18 Sep 2018 11:12:00 +0200 Subject: [PATCH 44/51] remove console.log --- src/actions/BlockchainActions.js | 2 -- src/actions/DiscoveryActions.js | 5 ----- src/actions/Web3Actions.js | 6 ------ src/views/Landing/components/InstallBridge/index.js | 1 - 4 files changed, 14 deletions(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 5221c96e..3c13a0cf 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -168,8 +168,6 @@ export const onNotification = (payload: any): PromiseAction => async (disp // }); } } - - console.warn("WEB3", payload, exists, getState().pending, address) } diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index 202bc8fa..14799a46 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -246,8 +246,6 @@ const discoverAccount = (device: TrezorDevice, discoveryProcess: Discovery): Asy }; const finish = (device: TrezorDevice, discoveryProcess: Discovery): AsyncAction => async (dispatch: Dispatch, getState: GetState): Promise => { - - console.warn("FINISH!"); await TrezorConnect.getFeatures({ device: { path: device.path, @@ -277,12 +275,9 @@ export const reconnect = (network: string): PromiseAction => async (dispat export const restore = (): ThunkAction => (dispatch: Dispatch, getState: GetState): void => { const selected = getState().wallet.selectedDevice; - if (selected && selected.connected && selected.features) { const discoveryProcess: ?Discovery = getState().discovery.find(d => d.deviceState === selected.state && (d.interrupted || d.waitingForDevice || d.waitingForBlockchain)); - console.warn("AAAA2") if (discoveryProcess) { - console.warn("AAAA3", discoveryProcess) dispatch(start(selected, discoveryProcess.network)); } } diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index 6738953d..a7a8c1d1 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -95,15 +95,11 @@ export const initWeb3 = (network: string, urlIndex: number = 0): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { - const instance: Web3Instance = await dispatch( initWeb3("ropsten") ); - console.warn("GETTX", instance.erc20.options.jsonInterface) // const inputData = instance.web3.utils.hexToAscii("0xa9059cbb00000000000000000000000073d0385f4d8e00c5e6504c6030f47bf6212736a80000000000000000000000000000000000000000000000000000000000000001"); // console.warn("input data!", inputData); } diff --git a/src/views/Landing/components/InstallBridge/index.js b/src/views/Landing/components/InstallBridge/index.js index ecf72ebf..67177f79 100644 --- a/src/views/Landing/components/InstallBridge/index.js +++ b/src/views/Landing/components/InstallBridge/index.js @@ -103,7 +103,6 @@ export default class InstallBridge extends Component { } onChange(value: InstallTarget) { - console.warn(value); this.setState({ target: value, }); From 38669a5dfba1d6cc4e4eab0b3cdd52b020af6e1f Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 18 Sep 2018 11:17:07 +0200 Subject: [PATCH 45/51] remove ethereum-input-data-decoder package (not used for now) --- package.json | 1 - src/actions/Web3Actions.js | 2 +- yarn.lock | 100 +------------------------------------ 3 files changed, 3 insertions(+), 100 deletions(-) diff --git a/package.json b/package.json index fadd8458..14e4102a 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "color-hash": "^1.0.3", "copy-webpack-plugin": "^4.5.2", "date-fns": "^1.29.0", - "ethereum-input-data-decoder": "^0.0.12", "ethereumjs-tx": "^1.3.3", "ethereumjs-units": "^0.2.0", "ethereumjs-util": "^5.1.4", diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index a7a8c1d1..ce894771 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -6,7 +6,7 @@ import BigNumber from 'bignumber.js'; import EthereumjsUtil from 'ethereumjs-util'; import EthereumjsUnits from 'ethereumjs-units'; import EthereumjsTx from 'ethereumjs-tx'; -import InputDataDecoder from 'ethereum-input-data-decoder'; +// import InputDataDecoder from 'ethereum-input-data-decoder'; import TrezorConnect from 'trezor-connect'; import type { EstimateGasOptions, TransactionStatus, TransactionReceipt } from 'web3'; import { strip } from 'utils/ethUtils'; diff --git a/yarn.lock b/yarn.lock index 2b50bd16..6f485cac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -453,10 +453,6 @@ add-dom-event-listener@1.x: dependencies: object-assign "4.x" -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - ajv-keywords@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-2.1.1.tgz#617997fc5f60576894c435f940d819e135b80762" @@ -1779,7 +1775,7 @@ bn.js@4.11.6: version "4.11.6" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" -bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0, bn.js@^4.8.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" @@ -3419,15 +3415,6 @@ elegant-spinner@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/elegant-spinner/-/elegant-spinner-1.0.1.tgz#db043521c95d7e303fd8f345bedc3349cfb0729e" -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.0.1" - elliptic@^6.0.0, elliptic@^6.2.3: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" @@ -3839,20 +3826,6 @@ ethereum-common@^0.0.18: version "0.0.18" resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" -ethereum-input-data-decoder@^0.0.12: - version "0.0.12" - resolved "https://registry.yarnpkg.com/ethereum-input-data-decoder/-/ethereum-input-data-decoder-0.0.12.tgz#e7abd764e76ba6942028051717759234cf64ba6d" - dependencies: - ethereumjs-abi "^0.6.4" - ethers "^2.1.3" - -ethereumjs-abi@^0.6.4: - version "0.6.5" - resolved "https://registry.yarnpkg.com/ethereumjs-abi/-/ethereumjs-abi-0.6.5.tgz#5a637ef16ab43473fa72a29ad90871405b3f5241" - dependencies: - bn.js "^4.10.0" - ethereumjs-util "^4.3.0" - ethereumjs-tx@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.3.tgz#ece051d3efdbe771ad2a518d61632ca2ab75ecbb" @@ -3866,16 +3839,6 @@ ethereumjs-units@^0.2.0: dependencies: bignumber.js "^2.3.0" -ethereumjs-util@^4.3.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - keccakjs "^0.2.0" - rlp "^2.0.0" - secp256k1 "^3.0.1" - ethereumjs-util@^5.0.0: version "5.1.2" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.1.2.tgz#25ba0215cbb4c2f0b108a6f96af2a2e62e45921f" @@ -3901,49 +3864,6 @@ ethereumjs-util@^5.1.4: safe-buffer "^5.1.1" secp256k1 "^3.0.1" -ethers-contracts@2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ethers-contracts/-/ethers-contracts-2.2.1.tgz#e2bf5dd5e157313ba454b50c646c8472fcd0a8b3" - dependencies: - ethers-utils "^2.1.0" - -ethers-providers@2.1.19: - version "2.1.19" - resolved "https://registry.yarnpkg.com/ethers-providers/-/ethers-providers-2.1.19.tgz#d597e298f70cfbf8da207c303af0a5cbed5b4cd2" - dependencies: - ethers-utils "^2.1.0" - inherits "2.0.1" - xmlhttprequest "1.8.0" - -ethers-utils@2.1.11, ethers-utils@^2.1.0: - version "2.1.11" - resolved "https://registry.yarnpkg.com/ethers-utils/-/ethers-utils-2.1.11.tgz#b27535ca3226118be300211c39c896b1e5e21641" - dependencies: - bn.js "^4.4.0" - hash.js "^1.0.0" - js-sha3 "0.5.7" - xmlhttprequest "1.8.0" - -ethers-wallet@2.1.8: - version "2.1.8" - resolved "https://registry.yarnpkg.com/ethers-wallet/-/ethers-wallet-2.1.8.tgz#2819a51d439525ddedeec84992b0b83f59da3cef" - dependencies: - aes-js "3.0.0" - elliptic "6.3.3" - ethers-utils "^2.1.0" - scrypt-js "2.0.3" - setimmediate "1.0.4" - uuid "2.0.1" - -ethers@^2.1.3: - version "2.2.6" - resolved "http://registry.npmjs.org/ethers/-/ethers-2.2.6.tgz#d1081c3e132930686fa7a3b508ae4d0ef8bd986a" - dependencies: - ethers-contracts "2.2.1" - ethers-providers "2.1.19" - ethers-utils "2.1.11" - ethers-wallet "2.1.8" - ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -6051,10 +5971,6 @@ js-base64@^2.1.9: version "2.3.2" resolved "https://registry.yarnpkg.com/js-base64/-/js-base64-2.3.2.tgz#a79a923666372b580f8e27f51845c6f7e8fbfbaf" -js-sha3@0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - js-sha3@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" @@ -6240,7 +6156,7 @@ keccak@^1.0.2: nan "^2.2.1" safe-buffer "^5.1.0" -keccakjs@^0.2.0, keccakjs@^0.2.1: +keccakjs@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" dependencies: @@ -9169,10 +9085,6 @@ scoped-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" -scrypt-js@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - scrypt.js@0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" @@ -9308,10 +9220,6 @@ set-value@^2.0.0: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -11296,10 +11204,6 @@ xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" From e512812eb407fb475815eae40e35d4a495e74e29 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 18 Sep 2018 11:27:41 +0200 Subject: [PATCH 46/51] unifying DiscoveryResult type with EthereumAccount from 'trezor-connect' --- src/actions/BlockchainActions.js | 20 ++++++++------------ src/actions/Web3Actions.js | 4 ++-- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 3c13a0cf..353cd345 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -28,7 +28,7 @@ import type { PromiseAction, ThunkAction, } from 'flowtype'; - +import type { EthereumAccount } from 'trezor-connect'; import type { Token } from 'reducers/TokensReducer'; import type { NetworkToken } from 'reducers/LocalStorageReducer'; @@ -36,21 +36,16 @@ export type BlockchainAction = { type: typeof BLOCKCHAIN.READY, } -export type DiscoveryResult = { - transactions: number; - block: number; - balance: string; - nonce: number; -} - -export const discoverAccount = (device: TrezorDevice, xpub: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const discoverAccount = (device: TrezorDevice, address: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { // get data from connect // Temporary disabled, enable after trezor-connect@5.0.32 release const txs = await TrezorConnect.ethereumGetAccountInfo({ account: { - address: xpub, + address, block: 0, - transactions: 0 + transactions: 0, + balance: "0", + nonce: 0 }, coin: network, }); @@ -60,9 +55,10 @@ export const discoverAccount = (device: TrezorDevice, xpub: string, network: str } // blockbook web3 fallback - const web3account = await dispatch( Web3Actions.discoverAccount(xpub, network) ); + const web3account = await dispatch( Web3Actions.discoverAccount(address, network) ); // return { transactions: txs.payload, ...web3account }; return { + address, transactions: txs.payload.transactions, block: txs.payload.block, balance: web3account.balance, diff --git a/src/actions/Web3Actions.js b/src/actions/Web3Actions.js index ce894771..b4611bd3 100644 --- a/src/actions/Web3Actions.js +++ b/src/actions/Web3Actions.js @@ -27,7 +27,6 @@ import type { PendingTx } from 'reducers/PendingTxReducer'; import type { Web3Instance } from 'reducers/Web3Reducer'; import type { Token } from 'reducers/TokensReducer'; import type { NetworkToken } from 'reducers/LocalStorageReducer'; -import type { DiscoveryResult } from './BlockchainActions'; import * as TokenActions from './TokenActions'; import * as AccountsActions from './AccountsActions'; @@ -131,11 +130,12 @@ export const initWeb3 = (network: string, urlIndex: number = 0): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { +export const discoverAccount = (address: string, network: string): PromiseAction => async (dispatch: Dispatch, getState: GetState): Promise => { const instance: Web3Instance = await dispatch( initWeb3(network) ); const balance = await instance.web3.eth.getBalance(address); const nonce = await instance.web3.eth.getTransactionCount(address); return { + address, transactions: 0, block: 0, balance: EthereumjsUnits.convert(balance, 'wei', 'ether'), From 0029a4c819a8c6abded9ce700bee9a69dfa1d527 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 18 Sep 2018 15:58:15 +0200 Subject: [PATCH 47/51] remove unused import --- src/actions/DiscoveryActions.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/actions/DiscoveryActions.js b/src/actions/DiscoveryActions.js index 14799a46..0daea108 100644 --- a/src/actions/DiscoveryActions.js +++ b/src/actions/DiscoveryActions.js @@ -10,8 +10,6 @@ import type { } from 'flowtype'; import type { Discovery, State } from 'reducers/DiscoveryReducer'; import * as AccountsActions from './AccountsActions'; -import * as Web3Actions from './Web3Actions'; - import * as BlockchainActions from './BlockchainActions'; import { setBalance as setTokenBalance } from './TokenActions'; From 271792664e54fe41590f716ae9a257eda1551f44 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 18 Sep 2018 16:42:26 +0200 Subject: [PATCH 48/51] bump trezor-connect --- package.json | 2 +- yarn.lock | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 14e4102a..d920fb90 100644 --- a/package.json +++ b/package.json @@ -57,7 +57,7 @@ "styled-components": "^3.3.3", "styled-media-query": "^2.0.2", "styled-normalize": "^8.0.0", - "trezor-connect": "5.0.31", + "trezor-connect": "^5.0.32", "web3": "1.0.0-beta.35", "webpack": "^4.16.3", "webpack-bundle-analyzer": "^2.13.1", diff --git a/yarn.lock b/yarn.lock index 6f485cac..0aeaea58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10158,9 +10158,9 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" -trezor-connect@5.0.31: - version "5.0.31" - resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-5.0.31.tgz#7ecf5e26e154962b638ddc35e68a52d57f4cc107" +trezor-connect@^5.0.32: + version "5.0.32" + resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-5.0.32.tgz#a8077f46653fec16d8dc25358e157ed1048a4def" dependencies: babel-runtime "^6.26.0" events "^1.1.1" From 4ea7f682501fa8dcfc25a2f9159cb739442e0448 Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Tue, 18 Sep 2018 16:43:00 +0200 Subject: [PATCH 49/51] using connect test version from sisyfos.trezor.io --- src/actions/TrezorConnectActions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/actions/TrezorConnectActions.js b/src/actions/TrezorConnectActions.js index eeef3218..94f99347 100644 --- a/src/actions/TrezorConnectActions.js +++ b/src/actions/TrezorConnectActions.js @@ -126,8 +126,8 @@ export const init = (): AsyncAction => async (dispatch: Dispatch, getState: GetS }); // $FlowIssue LOCAL not declared - window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://connect.trezor.io/5/'; - // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://sisyfos.trezor.io/connect/'; + window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://sisyfos.trezor.io/connect/'; + // window.__TREZOR_CONNECT_SRC = typeof LOCAL === 'string' ? LOCAL : 'https://connect.trezor.io/5/'; try { await TrezorConnect.init({ From 34e00d392e10230615d12b75bd1083b4d3220c10 Mon Sep 17 00:00:00 2001 From: Vladimir Volek Date: Wed, 19 Sep 2018 14:50:43 +0200 Subject: [PATCH 50/51] Fixed fiat ticker network --- public/data/appConfig.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/data/appConfig.json b/public/data/appConfig.json index c9c3ca0c..93b1520b 100644 --- a/public/data/appConfig.json +++ b/public/data/appConfig.json @@ -58,11 +58,11 @@ "fiatValueTickers": [ { - "network": "ethereum", + "network": "eth", "url": "https://api.coinmarketcap.com/v1/ticker/ethereum/" }, { - "network": "ethereum-classic", + "network": "etc", "url": "https://api.coinmarketcap.com/v1/ticker/ethereum-classic/" } ], From c9b9359e70b462f3610d896c9b583d704014df3a Mon Sep 17 00:00:00 2001 From: Szymon Lesisz Date: Wed, 19 Sep 2018 18:46:50 +0200 Subject: [PATCH 51/51] fix for disappearing accounts balance after block is mined --- src/actions/BlockchainActions.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/BlockchainActions.js b/src/actions/BlockchainActions.js index 353cd345..5414df9d 100644 --- a/src/actions/BlockchainActions.js +++ b/src/actions/BlockchainActions.js @@ -111,7 +111,7 @@ export const onBlockMined = (coinInfo: any): PromiseAction => async (dispa dispatch( Web3Actions.updateAccount(accounts[i], a, network) ) } else { // there are no new txs, just update block - dispatch( AccountsActions.update( { ...accounts[i], ...a }) ); + dispatch( AccountsActions.update( { ...accounts[i], block: a.block }) ); // HACK: since blockbook can't work with smart contracts for now // try to update tokens balances added to this account using Web3