From 6e9799bd17cc8e2283f2ca08d043836405f09180 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 8 Apr 2019 11:19:39 +0400 Subject: [PATCH 01/48] remove cookie store and session storage --- src/utils/storage/index.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/utils/storage/index.js b/src/utils/storage/index.js index e31f97e181..cb6b73ffba 100644 --- a/src/utils/storage/index.js +++ b/src/utils/storage/index.js @@ -1,9 +1,12 @@ // @flow import { - ImmortalStorage, CookieStore, IndexedDbStore, LocalStorageStore, SessionStorageStore, + ImmortalStorage, IndexedDbStore, LocalStorageStore, } from 'immortal-db' -const stores = [CookieStore, IndexedDbStore, LocalStorageStore, SessionStorageStore] +// Don't use sessionStorage and cookieStorage +// https://github.com/gruns/ImmortalDB/issues/22 +// https://github.com/gruns/ImmortalDB/issues/6 +const stores = [IndexedDbStore, LocalStorageStore] export const storage = new ImmortalStorage(stores) const PREFIX = 'v1' From 0f7d68b575207aff22e9222eb9762e06f5c7ba4e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 8 Apr 2019 11:46:05 +0400 Subject: [PATCH 02/48] eslint fix --- src/utils/storage/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/utils/storage/index.js b/src/utils/storage/index.js index cb6b73ffba..d1f3f1bff1 100644 --- a/src/utils/storage/index.js +++ b/src/utils/storage/index.js @@ -1,7 +1,5 @@ // @flow -import { - ImmortalStorage, IndexedDbStore, LocalStorageStore, -} from 'immortal-db' +import { ImmortalStorage, IndexedDbStore, LocalStorageStore } from 'immortal-db' // Don't use sessionStorage and cookieStorage // https://github.com/gruns/ImmortalDB/issues/22 From 6003d8db21fb9989b08925def86bf272973ddbd4 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 8 Apr 2019 13:29:19 +0400 Subject: [PATCH 03/48] display all safes and not owners only in safe list --- package.json | 12 +- src/routes/safeList/container/selector.js | 6 +- src/routes/safeList/store/selectors/index.js | 16 +- yarn.lock | 150 ++++++++++--------- 4 files changed, 98 insertions(+), 86 deletions(-) diff --git a/package.json b/package.json index 891e70deb6..8d920fb439 100644 --- a/package.json +++ b/package.json @@ -80,7 +80,7 @@ "react": "^16.8.6", "react-dom": "^16.8.6", "react-final-form": "^4.1.0", - "react-hot-loader": "^4.8.2", + "react-hot-loader": "4.8.3", "react-infinite-scroll-component": "^4.5.2", "react-redux": "^6.0.1", "react-router-dom": "^4.3.1", @@ -121,7 +121,7 @@ "@storybook/addon-knobs": "^5.0.6", "@storybook/addon-links": "^5.0.6", "@storybook/react": "^5.0.6", - "autoprefixer": "^9.4.10", + "autoprefixer": "9.5.1", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.0.1", "babel-jest": "^24.1.0", @@ -154,16 +154,16 @@ "postcss-simple-vars": "^5.0.2", "pre-commit": "^1.2.2", "prettier-eslint-cli": "^4.7.1", - "run-with-testrpc": "^0.3.0", + "run-with-testrpc": "0.3.1", "storybook-host": "^5.0.3", "storybook-router": "^0.3.3", "style-loader": "^0.23.1", - "truffle": "^5.0.10", + "truffle": "5.0.11", "truffle-contract": "^4.0.11", - "truffle-solidity-loader": "^0.1.10", + "truffle-solidity-loader": "0.1.11", "uglifyjs-webpack-plugin": "^2.1.2", "webpack": "^4.1.1", - "webpack-bundle-analyzer": "^3.1.0", + "webpack-bundle-analyzer": "3.2.0", "webpack-cli": "^3.2.3", "webpack-dev-server": "^3.1.0", "webpack-manifest-plugin": "^2.0.0-rc.2" diff --git a/src/routes/safeList/container/selector.js b/src/routes/safeList/container/selector.js index 101e6bfcda..9a301e0e5c 100644 --- a/src/routes/safeList/container/selector.js +++ b/src/routes/safeList/container/selector.js @@ -1,9 +1,9 @@ // @flow import { createStructuredSelector } from 'reselect' -import { safesByOwnerSelector } from '~/routes/safeList/store/selectors' +import { safesListSelector } from '~/routes/safeList/store/selectors' import { providerNameSelector } from '~/logic/wallets/store/selectors' -export default createStructuredSelector({ - safes: safesByOwnerSelector, +export default createStructuredSelector({ + safes: safesListSelector, provider: providerNameSelector, }) diff --git a/src/routes/safeList/store/selectors/index.js b/src/routes/safeList/store/selectors/index.js index 0d0dead139..dcea6bc6f1 100644 --- a/src/routes/safeList/store/selectors/index.js +++ b/src/routes/safeList/store/selectors/index.js @@ -10,15 +10,15 @@ import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' export const safesMapSelector = (state: GlobalState): Map => state[SAFE_REDUCER_ID] -const safesListSelector: Selector> = createSelector( +export const safesListSelector: Selector> = createSelector( safesMapSelector, (safes: Map): List => safes.toList(), ) -export const safesByOwnerSelector: Selector> = createSelector( - userAccountSelector, - safesListSelector, - (userAddress: string, safes: List): List => safes.filter( - (safe: Safe) => safe.owners.filter((owner: Owner) => sameAddress(owner.get('address'), userAddress)).count() > 0, - ), -) +// export const safesByOwnerSelector: Selector> = createSelector( +// userAccountSelector, +// safesListSelector, +// (userAddress: string, safes: List): List => safes.filter( +// (safe: Safe) => safe.owners.filter((owner: Owner) => sameAddress(owner.get('address'), userAddress)).count() > 0, +// ), +// ) diff --git a/yarn.lock b/yarn.lock index 2604025926..010c95d33a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2845,7 +2845,19 @@ atob@^2.1.1: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@^9.4.10, autoprefixer@^9.4.7: +autoprefixer@9.5.1: + version "9.5.1" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.5.1.tgz#243b1267b67e7e947f28919d786b50d3bb0fb357" + integrity sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ== + dependencies: + browserslist "^4.5.4" + caniuse-lite "^1.0.30000957" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.14" + postcss-value-parser "^3.3.1" + +autoprefixer@^9.4.7: version "9.5.0" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.5.0.tgz#7e51d0355c11596e6cf9a0afc9a44e86d1596c70" integrity sha512-hMKcyHsZn5+qL6AUeP3c8OyuteZ4VaUlg+fWbyl8z7PqsKHF/Bf8/px3K6AT8aMzDkBo8Bc11245MM+itDBOxQ== @@ -4226,7 +4238,7 @@ browserslist@^3.2.6: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" -browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.4.2, browserslist@^4.5.1, browserslist@^4.5.2: +browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.4.2, browserslist@^4.5.1, browserslist@^4.5.2, browserslist@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.4.tgz#166c4ecef3b51737a42436ea8002aeea466ea2c7" integrity sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag== @@ -4474,7 +4486,7 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000947, caniuse-lite@^1.0.30000955: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000947, caniuse-lite@^1.0.30000955, caniuse-lite@^1.0.30000957: version "1.0.30000957" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000957.tgz#fb1026bf184d7d62c685205358c3b24b9e29f7b3" integrity sha512-8wxNrjAzyiHcLXN/iunskqQnJquQQ6VX8JHfW5kLgAPRSiSuKZiNfmIkP5j7jgyXqAQBSoXyJxfnbCFS0ThSiQ== @@ -7775,10 +7787,10 @@ fuzzy-search@^3.0.1: resolved "https://registry.yarnpkg.com/fuzzy-search/-/fuzzy-search-3.0.1.tgz#14a4964508a9607d6e9a88818e7ff634108260b6" integrity sha512-rjUvzdsMlOyarm0oD5k6zVQwgvt4Tb5Xe3YdIGU+Vogw54+ueAGPUTMU2B9jfPQEie5cD11i/S9J9d+MNBSQ3Q== -ganache-cli@^6.0.3: - version "6.4.1" - resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.4.1.tgz#77c1682883a544dcad160b0e8155e282aefb4f1f" - integrity sha512-MUZ1DNnmlTrXnH6EuINuew75AI9d/wbIC0WpZCJo5Endsf6ZwEvfnfxGMpEnVizRri1mon2WWxLGAmALDxVcRQ== +ganache-cli@^6.4.2: + version "6.4.2" + resolved "https://registry.yarnpkg.com/ganache-cli/-/ganache-cli-6.4.2.tgz#4db8663b01c023b389dcafc447d6e7fcc0b52712" + integrity sha512-2hZY5xjvfVI2fvTtqQwzW5kgiqv6gtOONdqnNfBO38GGwQIZKdZCeQNwpFHZTUqPZ/hVwT4u5J5WUYyP3fG2YA== dependencies: bn.js "4.11.8" source-map-support "0.5.9" @@ -13075,10 +13087,10 @@ react-helmet-async@^0.2.0: react-fast-compare "^2.0.2" shallowequal "^1.0.2" -react-hot-loader@^4.8.2: - version "4.8.2" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.8.2.tgz#21a00cfca7fc848c53d78c34f6081f5ae3737dda" - integrity sha512-W5I8ps/32q5zL0mKfGGdPgsZfgljs/tdCTYxM6P1N8GV4+rUAu4g6ysy//5/jJpAFM0Bpgr6HrVLWK9h0jMdrA== +react-hot-loader@4.8.3: + version "4.8.3" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.8.3.tgz#14f018777a60ea9cfa60496c7341c2f967311253" + integrity sha512-Is8bKbSxuDLTqsWu1yjr+o1yA6yGDGjEQ2i1E8t/Nj1xJYC6QBRbyoofTn1xkMoKpcgXHuTJTqBhK0RY6moFJA== dependencies: fast-levenshtein "^2.0.6" global "^4.3.0" @@ -13991,13 +14003,13 @@ run-queue@^1.0.0, run-queue@^1.0.3: dependencies: aproba "^1.1.1" -run-with-testrpc@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/run-with-testrpc/-/run-with-testrpc-0.3.0.tgz#77205fc63e44e62202e0e5de51596038d82ba519" - integrity sha512-G4mvZz0O9AaYyESVEWzaYTagooKtWajd6t4zC7qxPs06pIyhYYzNytmxapCH/5tfWgsRSNfZ+XJhYPBvYpIlaQ== +run-with-testrpc@0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/run-with-testrpc/-/run-with-testrpc-0.3.1.tgz#93dcaab062ece14fb0c02d28def5f05e4bd8e136" + integrity sha512-+G9L7oMhLNXStmXGSjWtWxu7QVTJROJq3P1vruH01FaRtDiKIuvgqs9aZ3eJoTkfjg6UoOPxg/kwgYZlwKIvoQ== dependencies: colors "^1.1.2" - ganache-cli "^6.0.3" + ganache-cli "^6.4.2" rustbn.js@~0.2.0: version "0.2.0" @@ -15584,10 +15596,10 @@ truffle-box@^1.0.19: tmp "0.0.33" vcsurl "^0.1.1" -truffle-code-utils@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/truffle-code-utils/-/truffle-code-utils-1.1.4.tgz#7c8545d1d6d73b2ade8e6835d14ea8e1081116b1" - integrity sha512-tTMFU9NIQeHrppBZgWBTh1Xp28uTNxKDFIgrgOFDsKwHX/5z+7mLtSxXEErXqkBBK/MNVF5LhOT0mvT3eMPo2w== +truffle-code-utils@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/truffle-code-utils/-/truffle-code-utils-1.2.0.tgz#7e04e9b2fbfc5f44058acdc16c1e7d43dd83f585" + integrity sha512-VhpYJFpWcwcYLs3qQvB17OCeVDbUq1moDFf6CmrTeon6vgeF348wsjSuGdyJ12vHUWYu7Jdk+G+rXkl8DcRiFQ== truffle-compile-vyper@^1.0.10: version "1.0.10" @@ -15707,10 +15719,10 @@ truffle-contract@^4.0.11: web3-eth-abi "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -truffle-core@^5.0.10: - version "5.0.10" - resolved "https://registry.yarnpkg.com/truffle-core/-/truffle-core-5.0.10.tgz#1aa16c6d36ee44d4f1f520c270dd29d4f6e97bea" - integrity sha512-QOWKhoCKju9cnGzL1IuS0UixF1tTuaUa2s5D7OkVggdoyWncqjtGqaARWNoAoq+2RDuL95w8RadRY4A7/c7WqA== +truffle-core@^5.0.11: + version "5.0.11" + resolved "https://registry.yarnpkg.com/truffle-core/-/truffle-core-5.0.11.tgz#24298b6b55f859add7b15cbdf1209a0a2d7666d1" + integrity sha512-GPoLbD10CqnDPddFIFhsfTj8Y8F26Hk9GnB49tgHJN+Ezw4485+oZ+2YnlYHZjHVCD2Y832Y8Zx+ybdQXN4b8g== dependencies: app-module-path "^2.2.0" async "2.6.1" @@ -15747,14 +15759,14 @@ truffle-core@^5.0.10: truffle-config "^1.1.7" truffle-contract "^4.0.11" truffle-contract-sources "^0.1.3" - truffle-debug-utils "^1.0.13" - truffle-debugger "^5.0.4" - truffle-deployer "^3.0.10" + truffle-debug-utils "^1.0.14" + truffle-debugger "^5.0.5" + truffle-deployer "^3.0.11" truffle-error "^0.0.4" truffle-expect "^0.0.7" truffle-init "^1.0.7" truffle-interface-adapter "^0.1.2" - truffle-migrate "^3.0.10" + truffle-migrate "^3.0.11" truffle-provider "^0.1.6" truffle-provisioner "^0.1.4" truffle-require "^2.0.7" @@ -15766,19 +15778,19 @@ truffle-core@^5.0.10: xregexp "^4.2.4" yargs "^8.0.2" -truffle-debug-utils@^1.0.13: - version "1.0.13" - resolved "https://registry.yarnpkg.com/truffle-debug-utils/-/truffle-debug-utils-1.0.13.tgz#8f06d637d78e08af0c1b4744ea72629fa7f5198c" - integrity sha512-73We3ALSadkh2yoadrCtN/ueY4sRTNDGiqUVulA0RI7sPrf2UPOHji44ahE5WdjlCpuRISy4pktd3DeCln8vIw== +truffle-debug-utils@^1.0.14: + version "1.0.14" + resolved "https://registry.yarnpkg.com/truffle-debug-utils/-/truffle-debug-utils-1.0.14.tgz#a3c820bb41ed243c56c30ae607fd8776f5a7c6c6" + integrity sha512-hGpwNTMXXaJVi9RLhXhaOTtBdYYwYgFoENpd0bJEfXuB8obJTlS+3dFkZ7iPd5p3VuYRAJLhNy0rDb6pWwyTBA== dependencies: async "2.6.1" debug "^4.1.0" node-dir "0.1.17" -truffle-debugger@^5.0.4: - version "5.0.4" - resolved "https://registry.yarnpkg.com/truffle-debugger/-/truffle-debugger-5.0.4.tgz#dc5a598aa7a013bd5733fd71ecec1fd90e0fce40" - integrity sha512-RiR0qMe6X3sElzbQvXhZOsj9chHBxO8JABndj3anL4kf9YiWZ0hJ25AVxzyxA7sYSJfMwI7nrQyRNEQFRZwKXA== +truffle-debugger@^5.0.5: + version "5.0.5" + resolved "https://registry.yarnpkg.com/truffle-debugger/-/truffle-debugger-5.0.5.tgz#5695f1add0c25cd9131c004c9867aebb3e838a04" + integrity sha512-8ZrJCYoe4uyOcRQm91WkvsVo0GpC6BXw5AAPY+8nqB20jBz1oSk8DgY9MLdBtX9ASnZDgSta+hlX2ryIDQXnGg== dependencies: bn.js "^4.11.8" debug "^4.1.0" @@ -15790,9 +15802,9 @@ truffle-debugger@^5.0.4: redux-saga "1.0.0" remote-redux-devtools "^0.5.12" reselect-tree "^1.3.0" - truffle-code-utils "^1.1.4" + truffle-code-utils "^1.2.0" truffle-decode-utils "^1.0.7" - truffle-decoder "^2.0.3" + truffle-decoder "^2.0.4" truffle-expect "^0.0.7" truffle-solidity-utils "^1.2.2" web3 "1.0.0-beta.37" @@ -15807,10 +15819,10 @@ truffle-decode-utils@^1.0.7: lodash.clonedeep "^4.5.0" web3 "1.0.0-beta.37" -truffle-decoder@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/truffle-decoder/-/truffle-decoder-2.0.3.tgz#b5cc7d933160e6cd6aa52b8f085268ca5a551f16" - integrity sha512-0t5psJppiVOYVgVy1QNgb2J2Ixla+LeklDjrLfibaAT5IMdgujT7yJ8EuRciJxzXResVlaurNYHe7fnTfgQ8rQ== +truffle-decoder@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/truffle-decoder/-/truffle-decoder-2.0.4.tgz#eb5630c8ab6b7d889124efa621acee38dfc02e3b" + integrity sha512-nXI9Q+j3ZGN6Q3ObpwvtjXceyysozPzVea5v4k3KIz33AvpjadUt2uoqsabOQ31To90FgqD+vYgHu+BO8D4z4Q== dependencies: abi-decoder "^1.2.0" async-eventemitter "^0.2.4" @@ -15823,10 +15835,10 @@ truffle-decoder@^2.0.3: truffle-decode-utils "^1.0.7" web3 "1.0.0-beta.37" -truffle-deployer@^3.0.10: - version "3.0.10" - resolved "https://registry.yarnpkg.com/truffle-deployer/-/truffle-deployer-3.0.10.tgz#125247658ad0fb57e2159399503c3655a7c8f862" - integrity sha512-M+ITacJtdeBhROnmpWzKbC5h38gNvrP3NBUp6HAkK+Xd0PT/WpSkrQQnOmH0ijIfpgZsgW8riewDu1vH4T6wLQ== +truffle-deployer@^3.0.11: + version "3.0.11" + resolved "https://registry.yarnpkg.com/truffle-deployer/-/truffle-deployer-3.0.11.tgz#c61d35e2c7803cad0300f1262470cec84be52c27" + integrity sha512-iSHrvJ58VRuAPR0jWzADEqDMq7T7jKmspOcyQzKvy4MLjKXP1eDCklJUmWoUzbXRu5I9XZxcNUNxnLB+GyWQkA== dependencies: emittery "^0.4.0" truffle-contract "^4.0.11" @@ -15878,18 +15890,18 @@ truffle-interface-adapter@^0.1.2: bn.js "^4.11.8" web3 "1.0.0-beta.37" -truffle-migrate@^3.0.10: - version "3.0.10" - resolved "https://registry.yarnpkg.com/truffle-migrate/-/truffle-migrate-3.0.10.tgz#11037235b196e44804e15f28d8182926b0ff4c06" - integrity sha512-KXG7+IM2kS16NHAwQstgrFfVrTWaASiXu7fQyh/z4JkdsUmNaCatq99AJaSxftRlqYq7fQSSir3buyntmMelww== +truffle-migrate@^3.0.11: + version "3.0.11" + resolved "https://registry.yarnpkg.com/truffle-migrate/-/truffle-migrate-3.0.11.tgz#574c553aef2a561daae1937c51c126914af0f227" + integrity sha512-qLWWrDeHI4DJ+HEit03LdqPWoymk2MvDBm5z9ebovCMMXe3Rv6Gfu7QO48oLaWk5e8SEb95zprIZJfmXM7UAuw== dependencies: async "2.6.1" emittery "^0.4.0" node-dir "0.1.17" - truffle-deployer "^3.0.10" + truffle-deployer "^3.0.11" truffle-expect "^0.0.7" truffle-interface-adapter "^0.1.2" - truffle-reporters "^1.0.6" + truffle-reporters "^1.0.7" truffle-require "^2.0.7" web3 "1.0.0-beta.37" @@ -15907,10 +15919,10 @@ truffle-provisioner@^0.1.4: resolved "https://registry.yarnpkg.com/truffle-provisioner/-/truffle-provisioner-0.1.4.tgz#a470f7e603d069b481481dba92f5c9d2f1a8526a" integrity sha512-d4GhAsS4bEtYIfuedaFl9k22o7UJOsmgMZM8M3fQYI0uAGt9ApEGEL0Yvdy7/uWw/0T1796ZVe+EuzlbcjaiUQ== -truffle-reporters@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/truffle-reporters/-/truffle-reporters-1.0.6.tgz#d4ad66a71239e69f53886337d43c1d69c3a9be50" - integrity sha512-GrKUP9W7XATrXgKMudsIU2YscZOpyZzisKHVIJCAuTfzwsXgI1fKoN5luN0vvv6IlJdDLOxiRGE71/WVqGHm0g== +truffle-reporters@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/truffle-reporters/-/truffle-reporters-1.0.7.tgz#1e5ee60c37d81659b59639bed3bb8ccb0e129645" + integrity sha512-xS0HmKpq1pz63OspqQtfh0zCCS4T+pRyQh6fVp2FTzPbx31QzAQFen4P4Q1s1M05r2lTUIbCFjyRoX1HcwDEMw== dependencies: node-emoji "^1.8.1" ora "^3.0.0" @@ -15937,17 +15949,17 @@ truffle-resolver@^5.0.10: truffle-expect "^0.0.7" truffle-provisioner "^0.1.4" -truffle-solidity-loader@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/truffle-solidity-loader/-/truffle-solidity-loader-0.1.10.tgz#955848194e24e4584ddcd6e403830691ecc497e1" - integrity sha512-5/TSO3iCa/AhdPJWvYtT/G2IzLyELx0FytEoBUaQ0J/s4Y3+zGIzXeddDrdzzSKLvomq7xO/lFlltQ8j9DO6EA== +truffle-solidity-loader@0.1.11: + version "0.1.11" + resolved "https://registry.yarnpkg.com/truffle-solidity-loader/-/truffle-solidity-loader-0.1.11.tgz#3b6f4aa6ac6fd581fc30d01832316d7ca8e29240" + integrity sha512-vd4wvET1FCfTNq6NbyDyo3pasxYXL+uQ2Cf9bzyO0KmNwtDmiuBo5uSGTorqUKH52M0tzr2G0NSgZnobtOtjNA== dependencies: chalk "^1.1.3" find-up "^1.1.2" loader-utils "^1.1.0" schema-utils "^1.0.0" truffle-config "^1.1.7" - truffle-core "^5.0.10" + truffle-core "^5.0.11" truffle-solidity-utils@^1.2.2: version "1.2.2" @@ -15971,10 +15983,10 @@ truffle-workflow-compile@^2.0.10: truffle-external-compile "^1.0.7" truffle-resolver "^5.0.10" -truffle@^5.0.10: - version "5.0.10" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.10.tgz#f773522becbed0f66b372c6a9a1f36d233337e1e" - integrity sha512-wVp7ruznIm1iX7fTHZwjKZCaOkkQcTR1eWOCi2yTQ85wg1iQITpV7NLDpVandaNcz5Z0e8EdOrH9lFKLgxiAxQ== +truffle@5.0.11: + version "5.0.11" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.11.tgz#e593674415bf5e4a02eed5b940d736dece5ab447" + integrity sha512-LyXKxrvPuWuM31AF0U+d890e3ojYAjt4CeHO1zrjBG+/2ac/Fv31yqZS/cXN8xU09xCVC9uEcJ2Z23j9Q2KhRg== dependencies: app-module-path "^2.2.0" mocha "^4.1.0" @@ -17312,10 +17324,10 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-bundle-analyzer@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.1.0.tgz#2f19cbb87bb6d4f3cb4e59cb67c837bd9436e89d" - integrity sha512-nyDyWEs7C6DZlgvu1pR1zzJfIWSiGPbtaByZr8q+Fd2xp70FuM/8ngCJzj3Er1TYRLSFmp1F1OInbEm4DZH8NA== +webpack-bundle-analyzer@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.2.0.tgz#0630d298e88511d036d7c823705d7b852593d5c4" + integrity sha512-F6bwrg5TBb9HsHZCltH1L5F091ELQ+/i67MEH7jWkYRvVp53eONNneGaIXSdOQUiXUyd3RnkITWRfWvSVQGnZQ== dependencies: acorn "^6.0.7" acorn-walk "^6.1.1" From 3b27729d85b80ae1d22d2bab2b856be3f7163ea1 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 8 Apr 2019 16:53:45 +0400 Subject: [PATCH 04/48] load active tokens from localstorage when visiting safe view --- .../tokens/store/actions/loadActiveTokens.js | 26 ++++++++++++++++++ src/routes/safe/container/actions.js | 3 +++ src/routes/safe/container/index.jsx | 27 ++++++++++++------- src/routes/safe/container/selector.js | 2 +- .../store/actions/loadSafesFromStorage.js | 4 ++- 5 files changed, 51 insertions(+), 11 deletions(-) create mode 100644 src/logic/tokens/store/actions/loadActiveTokens.js diff --git a/src/logic/tokens/store/actions/loadActiveTokens.js b/src/logic/tokens/store/actions/loadActiveTokens.js new file mode 100644 index 0000000000..1e8abcbf55 --- /dev/null +++ b/src/logic/tokens/store/actions/loadActiveTokens.js @@ -0,0 +1,26 @@ +// @flow +import type { Dispatch as ReduxDispatch } from 'redux' +import { List, Map } from 'immutable' +import { type TokenProps, type Token, makeToken } from '~/logic/tokens/store/model/token' +import { type GlobalState } from '~/store/index' +import { getActiveTokens } from '~/logic/tokens/utils/tokensStorage' +import saveTokens from './saveTokens' + +const loadActiveTokens = (safeAddress: string) => async (dispatch: ReduxDispatch) => { + try { + const tokens: List = await getActiveTokens(safeAddress) + + if (tokens.size) { + const tokenRecords: Map = Map().withMutations((map) => { + tokens.forEach(token => map.set(token.address, makeToken(token))) + }) + + dispatch(saveTokens(safeAddress, tokenRecords)) + } + } catch (err) { + // eslint-disable-next-line + console.error('Error while getting safes from storage:', err) + } +} + +export default loadActiveTokens diff --git a/src/routes/safe/container/actions.js b/src/routes/safe/container/actions.js index 5799093e16..a1860317b4 100644 --- a/src/routes/safe/container/actions.js +++ b/src/routes/safe/container/actions.js @@ -1,13 +1,16 @@ // @flow import fetchSafe from '~/routes/safe/store/actions/fetchSafe' import { fetchTokens } from '~/logic/tokens/store/actions/fetchTokens' +import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens' export type Actions = { fetchSafe: typeof fetchSafe, fetchTokens: typeof fetchTokens, + loadActiveTokens: typeof loadActiveTokens, } export default { fetchSafe, fetchTokens, + loadActiveTokens, } diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index d32d0ec18e..dac25abcd4 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -6,26 +6,31 @@ import Layout from '~/routes/safe/component/Layout' import selector, { type SelectorProps } from './selector' import actions, { type Actions } from './actions' -type Props = Actions & SelectorProps & { - granted: boolean, -} +type Props = Actions & + SelectorProps & { + granted: boolean, + } const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 15000 class SafeView extends React.PureComponent { componentDidMount() { - const { safeUrl, fetchTokens, fetchSafe } = this.props + const { + safeUrl, fetchTokenBalances, fetchSafe, loadActiveTokens, + } = this.props + fetchSafe(safeUrl) - fetchTokens(safeUrl) + loadActiveTokens(safeUrl) + // fetchTokens(safeUrl) this.intervalId = setInterval(() => { - fetchTokens(safeUrl) + // fetchTokenBalances(safeUrl) fetchSafe(safeUrl) }, TIMEOUT) } componentDidUpdate(prevProps) { - const { safe, fetchTokens } = this.props + const { safe, fetchTokenBalances, loadActiveTokens } = this.props if (prevProps.safe) { return @@ -33,7 +38,8 @@ class SafeView extends React.PureComponent { if (safe) { const safeAddress = safe.get('address') - fetchTokens(safeAddress) + loadActiveTokens(safeAddress) + // fetchTokenBalances(safeAddress) } } @@ -64,4 +70,7 @@ class SafeView extends React.PureComponent { } } -export default connect(selector, actions)(SafeView) +export default connect<*, *, *, *>( + selector, + actions, +)(SafeView) diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index 5e1633669e..e9c5e433a6 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -42,7 +42,7 @@ export const grantedSelector: Selector = crea }, ) -export default createStructuredSelector({ +export default createStructuredSelector({ safe: safeSelector, provider: providerNameSelector, tokens: orderedTokenListSelector, diff --git a/src/routes/safe/store/actions/loadSafesFromStorage.js b/src/routes/safe/store/actions/loadSafesFromStorage.js index 4453624de3..1720b6b69b 100644 --- a/src/routes/safe/store/actions/loadSafesFromStorage.js +++ b/src/routes/safe/store/actions/loadSafesFromStorage.js @@ -7,7 +7,7 @@ import { loadFromStorage } from '~/utils/storage' import { addSafe } from './addSafe' import { buildSafe } from '~/routes/safe/store/reducer/safe' -export default () => async (dispatch: ReduxDispatch) => { +const loadSafesFromStorage = () => async (dispatch: ReduxDispatch) => { try { const safes: ?{ [string]: SafeProps } = await loadFromStorage(SAFES_KEY) @@ -23,3 +23,5 @@ export default () => async (dispatch: ReduxDispatch) => { return Promise.resolve() } + +export default loadSafesFromStorage From 8108b6bd0113eda7f95627160d2825323ff09505 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 8 Apr 2019 19:58:01 +0400 Subject: [PATCH 05/48] add an action to fetch token balances --- .../store/actions/fetchTokenBalances.js | 27 +++++++++++++++++++ src/logic/tokens/store/actions/fetchTokens.js | 2 +- .../tokens/store/actions/loadActiveTokens.js | 2 +- src/logic/tokens/store/selectors/index.js | 25 +++++++++++------ src/routes/safe/container/actions.js | 3 +++ src/routes/safe/container/index.jsx | 18 +++++++++---- 6 files changed, 62 insertions(+), 15 deletions(-) create mode 100644 src/logic/tokens/store/actions/fetchTokenBalances.js diff --git a/src/logic/tokens/store/actions/fetchTokenBalances.js b/src/logic/tokens/store/actions/fetchTokenBalances.js new file mode 100644 index 0000000000..90dd296eb0 --- /dev/null +++ b/src/logic/tokens/store/actions/fetchTokenBalances.js @@ -0,0 +1,27 @@ +// @flow +import type { Dispatch as ReduxDispatch } from 'redux' +import { Map, List } from 'immutable' +import { type Token } from '~/logic/tokens/store/model/token' +import { type GlobalState } from '~/store/index' +import { calculateBalanceOf } from './fetchTokens' +import { addTokens } from './saveTokens' + +const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( + dispatch: ReduxDispatch, +) => { + try { + const withBalances = await Promise.all( + tokens.map(async token => token.set('funds', await calculateBalanceOf(token.address, safeAddress))), + ) + const tokensMap = Map().withMutations((map) => { + withBalances.forEach(token => map.set(token.address, token)) + }) + + dispatch(addTokens(safeAddress, tokensMap)) + } catch (err) { + // eslint-disable-next-line + console.error('Error while loading active tokens from storage:', err) + } +} + +export default fetchTokenBalances diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index 4c68ce3362..10660fda32 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -34,7 +34,7 @@ export const getHumanFriendlyToken = ensureOnce(createHumanFriendlyTokenContract export const getStandardTokenContract = ensureOnce(createStandardTokenContract) -export const calculateBalanceOf = async (tokenAddress: string, address: string, decimals: number) => { +export const calculateBalanceOf = async (tokenAddress: string, address: string, decimals: number = 18) => { const erc20Token = await getStandardTokenContract() let balance = 0 diff --git a/src/logic/tokens/store/actions/loadActiveTokens.js b/src/logic/tokens/store/actions/loadActiveTokens.js index 1e8abcbf55..068531b5a2 100644 --- a/src/logic/tokens/store/actions/loadActiveTokens.js +++ b/src/logic/tokens/store/actions/loadActiveTokens.js @@ -19,7 +19,7 @@ const loadActiveTokens = (safeAddress: string) => async (dispatch: ReduxDispatch } } catch (err) { // eslint-disable-next-line - console.error('Error while getting safes from storage:', err) + console.error('Error while loading active tokens from storage:', err) } } diff --git a/src/logic/tokens/store/selectors/index.js b/src/logic/tokens/store/selectors/index.js index ad403dde12..fa0e1db65d 100644 --- a/src/logic/tokens/store/selectors/index.js +++ b/src/logic/tokens/store/selectors/index.js @@ -6,10 +6,10 @@ import { type GlobalState } from '~/store' import { TOKEN_REDUCER_ID } from '~/logic/tokens/store/reducer/tokens' import { type Token } from '~/logic/tokens/store/model/token' -const balancesSelector = (state: GlobalState) => state[TOKEN_REDUCER_ID] +const tokensStateSelector = (state: GlobalState) => state[TOKEN_REDUCER_ID] export const tokensSelector: Selector> = createSelector( - balancesSelector, + tokensStateSelector, safeParamAddressSelector, (tokens: Map>, address: string) => { if (!address) { @@ -20,25 +20,34 @@ export const tokensSelector: Selector> = createSelector( tokensSelector, (tokens: Map) => tokens.toList(), ) -export const activeTokensSelector = createSelector( +export const activeTokensSelector: Selector> = createSelector( tokenListSelector, (tokens: List) => tokens.filter((token: Token) => token.get('status')), ) -export const orderedTokenListSelector = createSelector( +export const orderedTokenListSelector: Selector> = createSelector( tokenListSelector, (tokens: List) => tokens.sortBy((token: Token) => token.get('symbol')), ) -export const tokenAddressesSelector = createSelector( +export const tokenAddressesSelector: Selector> = createSelector( tokenListSelector, - (balances: List) => { - const addresses = List().withMutations(list => balances.map(token => list.push(token.address))) + (tokens: List) => { + const addresses = List().withMutations(list => tokens.map(token => list.push(token.address))) + + return addresses + }, +) + +export const activeTokenAdressesSelector: Selector> = createSelector( + activeTokensSelector, + (tokens: List) => { + const addresses = List().withMutations(list => tokens.map(token => list.push(token.address))) return addresses }, diff --git a/src/routes/safe/container/actions.js b/src/routes/safe/container/actions.js index a1860317b4..21b11b96d1 100644 --- a/src/routes/safe/container/actions.js +++ b/src/routes/safe/container/actions.js @@ -2,15 +2,18 @@ import fetchSafe from '~/routes/safe/store/actions/fetchSafe' import { fetchTokens } from '~/logic/tokens/store/actions/fetchTokens' import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens' +import fetchTokenBalances from '~/logic/tokens/store/actions/fetchTokenBalances' export type Actions = { fetchSafe: typeof fetchSafe, fetchTokens: typeof fetchTokens, loadActiveTokens: typeof loadActiveTokens, + fetchTokenBalances: typeof fetchTokenBalances } export default { fetchSafe, fetchTokens, loadActiveTokens, + fetchTokenBalances, } diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index dac25abcd4..f026809bcb 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -16,21 +16,27 @@ const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 15000 class SafeView extends React.PureComponent { componentDidMount() { const { - safeUrl, fetchTokenBalances, fetchSafe, loadActiveTokens, + safeUrl, fetchTokenBalances, fetchSafe, loadActiveTokens, activeTokens, } = this.props fetchSafe(safeUrl) loadActiveTokens(safeUrl) - // fetchTokens(safeUrl) + + if (activeTokens.size) { + fetchTokenBalances(safeUrl, activeTokens) + } this.intervalId = setInterval(() => { - // fetchTokenBalances(safeUrl) + // eslint-disable-next-line + fetchTokenBalances(safeUrl, this.props.activeTokens) fetchSafe(safeUrl) }, TIMEOUT) } componentDidUpdate(prevProps) { - const { safe, fetchTokenBalances, loadActiveTokens } = this.props + const { + safe, fetchTokenBalances, loadActiveTokens, activeTokens, + } = this.props if (prevProps.safe) { return @@ -39,7 +45,9 @@ class SafeView extends React.PureComponent { if (safe) { const safeAddress = safe.get('address') loadActiveTokens(safeAddress) - // fetchTokenBalances(safeAddress) + if (activeTokens.size) { + fetchTokenBalances(safeAddress, activeTokens) + } } } From 8a8b29744a6287386b7011834c9e6b4bd9bde2c4 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 9 Apr 2019 12:48:17 +0400 Subject: [PATCH 06/48] action for fetching active token balances wip --- .../tokens/store/actions/fetchTokenBalances.js | 17 ++++++++++++++++- src/routes/safe/container/index.jsx | 9 ++++----- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/src/logic/tokens/store/actions/fetchTokenBalances.js b/src/logic/tokens/store/actions/fetchTokenBalances.js index 90dd296eb0..f57d7fc24e 100644 --- a/src/logic/tokens/store/actions/fetchTokenBalances.js +++ b/src/logic/tokens/store/actions/fetchTokenBalances.js @@ -1,10 +1,11 @@ // @flow -import type { Dispatch as ReduxDispatch } from 'redux' +import type { Dispatch as ReduxDispatch, GetState } from 'redux' import { Map, List } from 'immutable' import { type Token } from '~/logic/tokens/store/model/token' import { type GlobalState } from '~/store/index' import { calculateBalanceOf } from './fetchTokens' import { addTokens } from './saveTokens' +import { activeTokensSelector } from '~/logic/tokens/store/selectors' const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( dispatch: ReduxDispatch, @@ -24,4 +25,18 @@ const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( } } +export const fetchActiveTokenBalances = (safeAddress: string) => async ( + dispatch: ReduxDispatch, + getState: GetState, +) => { + try { + const state = getState() + const activeTokens = activeTokensSelector(state) + dispatch(fetchTokenBalances(safeAddress, activeTokens)) + } catch (err) { + // eslint-disable-next-line + console.error('Error while loading active tokens from storage:', err) + } +} + export default fetchTokenBalances diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index f026809bcb..19fc9bf584 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -35,18 +35,17 @@ class SafeView extends React.PureComponent { componentDidUpdate(prevProps) { const { - safe, fetchTokenBalances, loadActiveTokens, activeTokens, + fetchTokenBalances, loadActiveTokens, activeTokens, safeUrl, } = this.props if (prevProps.safe) { return } - if (safe) { - const safeAddress = safe.get('address') - loadActiveTokens(safeAddress) + if (safeUrl) { + loadActiveTokens(safeUrl) if (activeTokens.size) { - fetchTokenBalances(safeAddress, activeTokens) + fetchTokenBalances(safeUrl, activeTokens) } } } From 4f5986506b1893fa28ba869deae04a2237fbc062 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 9 Apr 2019 16:36:04 +0400 Subject: [PATCH 07/48] reducer fix, fetching balances and updating balances fixes --- .../store/actions/fetchTokenBalances.js | 21 +++------- .../tokens/store/actions/updateTokens.js | 31 +++++++++++++++ src/logic/tokens/store/reducer/tokens.js | 8 +--- src/routes/safe/container/index.jsx | 38 ++++++++----------- 4 files changed, 52 insertions(+), 46 deletions(-) create mode 100644 src/logic/tokens/store/actions/updateTokens.js diff --git a/src/logic/tokens/store/actions/fetchTokenBalances.js b/src/logic/tokens/store/actions/fetchTokenBalances.js index f57d7fc24e..9eefa654b2 100644 --- a/src/logic/tokens/store/actions/fetchTokenBalances.js +++ b/src/logic/tokens/store/actions/fetchTokenBalances.js @@ -1,15 +1,18 @@ // @flow -import type { Dispatch as ReduxDispatch, GetState } from 'redux' +import type { Dispatch as ReduxDispatch } from 'redux' import { Map, List } from 'immutable' import { type Token } from '~/logic/tokens/store/model/token' import { type GlobalState } from '~/store/index' import { calculateBalanceOf } from './fetchTokens' import { addTokens } from './saveTokens' -import { activeTokensSelector } from '~/logic/tokens/store/selectors' const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( dispatch: ReduxDispatch, ) => { + if (!safeAddress || !tokens || !tokens.size) { + return + } + try { const withBalances = await Promise.all( tokens.map(async token => token.set('funds', await calculateBalanceOf(token.address, safeAddress))), @@ -25,18 +28,4 @@ const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( } } -export const fetchActiveTokenBalances = (safeAddress: string) => async ( - dispatch: ReduxDispatch, - getState: GetState, -) => { - try { - const state = getState() - const activeTokens = activeTokensSelector(state) - dispatch(fetchTokenBalances(safeAddress, activeTokens)) - } catch (err) { - // eslint-disable-next-line - console.error('Error while loading active tokens from storage:', err) - } -} - export default fetchTokenBalances diff --git a/src/logic/tokens/store/actions/updateTokens.js b/src/logic/tokens/store/actions/updateTokens.js new file mode 100644 index 0000000000..601f241db4 --- /dev/null +++ b/src/logic/tokens/store/actions/updateTokens.js @@ -0,0 +1,31 @@ +// @flow +import { createAction } from 'redux-actions' +import { type Token } from '~/logic/tokens/store/model/token' +import { setActiveTokens, getActiveTokens, setToken } from '~/logic/tokens/utils/tokensStorage' +import type { Dispatch as ReduxDispatch } from 'redux' +import { type GlobalState } from '~/store/index' + +export const ADD_TOKEN = 'ADD_TOKEN' + +type AddTokenProps = { + safeAddress: string, + token: Token, +} + +export const addToken = createAction( + ADD_TOKEN, + (safeAddress: string, token: Token): AddTokenProps => ({ + safeAddress, + token, + }), +) + +const saveToken = (safeAddress: string, token: Token) => async (dispatch: ReduxDispatch) => { + dispatch(addToken(safeAddress, token)) + + const activeTokens = await getActiveTokens(safeAddress) + await setActiveTokens(safeAddress, activeTokens.push(token.toJS())) + setToken(safeAddress, token) +} + +export default saveToken diff --git a/src/logic/tokens/store/reducer/tokens.js b/src/logic/tokens/store/reducer/tokens.js index 70f87bcd69..3b8381e3eb 100644 --- a/src/logic/tokens/store/reducer/tokens.js +++ b/src/logic/tokens/store/reducer/tokens.js @@ -17,13 +17,7 @@ export default handleActions( [ADD_TOKENS]: (state: State, action: ActionType): State => { const { safeAddress, tokens } = action.payload - return state.update(safeAddress, (prevSafe: Map) => { - if (!prevSafe) { - return tokens - } - - return prevSafe.equals(tokens) ? prevSafe : tokens - }) + return state.update(safeAddress, (prevState: Map) => (prevState ? prevState.merge(tokens) : tokens)) }, [ADD_TOKEN]: (state: State, action: ActionType): State => { const { safeAddress, token } = action.payload diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index 19fc9bf584..20d989454b 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -6,52 +6,44 @@ import Layout from '~/routes/safe/component/Layout' import selector, { type SelectorProps } from './selector' import actions, { type Actions } from './actions' -type Props = Actions & +export type Props = Actions & SelectorProps & { granted: boolean, } const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 15000 -class SafeView extends React.PureComponent { +class SafeView extends React.Component { componentDidMount() { const { - safeUrl, fetchTokenBalances, fetchSafe, loadActiveTokens, activeTokens, + fetchSafe, loadActiveTokens, activeTokens, safeUrl, fetchTokenBalances, } = this.props fetchSafe(safeUrl) loadActiveTokens(safeUrl) if (activeTokens.size) { + // eslint-disable-next-line fetchTokenBalances(safeUrl, activeTokens) } this.intervalId = setInterval(() => { - // eslint-disable-next-line - fetchTokenBalances(safeUrl, this.props.activeTokens) - fetchSafe(safeUrl) + // update in another function so it uses up-to-date props values + this.checkForUpdates() }, TIMEOUT) } - componentDidUpdate(prevProps) { + componentWillUnmount() { + clearInterval(this.intervalId) + } + + checkForUpdates() { const { - fetchTokenBalances, loadActiveTokens, activeTokens, safeUrl, + safeUrl, activeTokens, fetchSafe, fetchTokenBalances, } = this.props - if (prevProps.safe) { - return - } - - if (safeUrl) { - loadActiveTokens(safeUrl) - if (activeTokens.size) { - fetchTokenBalances(safeUrl, activeTokens) - } - } - } - - componentWillUnmount() { - clearInterval(this.intervalId) + fetchSafe(safeUrl) + fetchTokenBalances(safeUrl, activeTokens) } intervalId: IntervalID @@ -77,7 +69,7 @@ class SafeView extends React.PureComponent { } } -export default connect<*, *, *, *>( +export default connect( selector, actions, )(SafeView) From 1125536412a0545a77c7f29ce6628cc7f8db81ad Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 9 Apr 2019 18:14:48 +0400 Subject: [PATCH 08/48] tokens fetch fixes, disable eth switch in tokens modal --- .../store/actions/fetchTokenBalances.js | 29 +++++++++++++++++-- src/logic/tokens/store/actions/fetchTokens.js | 19 ++---------- .../tokens/store/actions/loadActiveTokens.js | 15 ++++++---- src/logic/tokens/utils/tokenHelpers.js | 10 +++---- .../safe/component/Balances/Tokens/index.jsx | 9 ++++-- src/routes/safe/container/index.jsx | 6 +--- 6 files changed, 49 insertions(+), 39 deletions(-) diff --git a/src/logic/tokens/store/actions/fetchTokenBalances.js b/src/logic/tokens/store/actions/fetchTokenBalances.js index 9eefa654b2..0588ad58bf 100644 --- a/src/logic/tokens/store/actions/fetchTokenBalances.js +++ b/src/logic/tokens/store/actions/fetchTokenBalances.js @@ -1,11 +1,33 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' import { Map, List } from 'immutable' -import { type Token } from '~/logic/tokens/store/model/token' +import { BigNumber } from 'bignumber.js' import { type GlobalState } from '~/store/index' -import { calculateBalanceOf } from './fetchTokens' +import { type Token } from '~/logic/tokens/store/model/token' +import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' +import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3' +import { getStandardTokenContract } from './fetchTokens' import { addTokens } from './saveTokens' +export const calculateBalanceOf = async (tokenAddress: string, safeAddress: string, decimals: number = 18) => { + if (tokenAddress === ETH_ADDRESS) { + const ethBalance = await getBalanceInEtherOf(safeAddress) + return ethBalance + } + + const erc20Token = await getStandardTokenContract() + let balance = 0 + + try { + const token = await erc20Token.at(tokenAddress) + balance = await token.balanceOf(safeAddress) + } catch (err) { + console.error('Failed to fetch token balances: ', err) + } + + return new BigNumber(balance).div(10 ** decimals).toString() +} + const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( dispatch: ReduxDispatch, ) => { @@ -15,8 +37,9 @@ const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( try { const withBalances = await Promise.all( - tokens.map(async token => token.set('funds', await calculateBalanceOf(token.address, safeAddress))), + tokens.map(async token => token.set('funds', await calculateBalanceOf(token.address, safeAddress, token.decimals))), ) + const tokensMap = Map().withMutations((map) => { withBalances.forEach(token => map.set(token.address, token)) }) diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index 10660fda32..164f7b0660 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -2,7 +2,6 @@ import { List, Map } from 'immutable' import contract from 'truffle-contract' import axios from 'axios' -import { BigNumber } from 'bignumber.js' import type { Dispatch as ReduxDispatch } from 'redux' import StandardToken from '@gnosis.pm/util-contracts/build/contracts/GnosisStandardToken.json' import HumanFriendlyToken from '@gnosis.pm/util-contracts/build/contracts/HumanFriendlyToken.json' @@ -11,7 +10,7 @@ import { type GlobalState } from '~/store/index' import { makeToken, type Token, type TokenProps } from '~/logic/tokens/store/model/token' import { ensureOnce } from '~/utils/singleton' import { getActiveTokens, getTokens } from '~/logic/tokens/utils/tokensStorage' -import { getSafeEthToken } from '~/logic/tokens/utils/tokenHelpers' +import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' import saveTokens from './saveTokens' import { getRelayUrl } from '~/config/index' @@ -34,20 +33,6 @@ export const getHumanFriendlyToken = ensureOnce(createHumanFriendlyTokenContract export const getStandardTokenContract = ensureOnce(createStandardTokenContract) -export const calculateBalanceOf = async (tokenAddress: string, address: string, decimals: number = 18) => { - const erc20Token = await getStandardTokenContract() - let balance = 0 - - try { - const token = await erc20Token.at(tokenAddress) - balance = await token.balanceOf(address) - } catch (err) { - console.error('Failed to fetch token balances: ', err) - } - - return new BigNumber(balance).div(10 ** decimals).toString() -} - export const fetchTokensData = async () => { const apiUrl = getRelayUrl() const url = `${apiUrl}/tokens` @@ -57,7 +42,7 @@ export const fetchTokensData = async () => { export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispatch) => { const tokens: List = await getActiveTokens(safeAddress) - const ethBalance = await getSafeEthToken(safeAddress) + const ethBalance = await getEthAsToken(safeAddress) const customTokens = await getTokens(safeAddress) const { data: { results }, diff --git a/src/logic/tokens/store/actions/loadActiveTokens.js b/src/logic/tokens/store/actions/loadActiveTokens.js index 068531b5a2..7f6a4b55b2 100644 --- a/src/logic/tokens/store/actions/loadActiveTokens.js +++ b/src/logic/tokens/store/actions/loadActiveTokens.js @@ -4,19 +4,22 @@ import { List, Map } from 'immutable' import { type TokenProps, type Token, makeToken } from '~/logic/tokens/store/model/token' import { type GlobalState } from '~/store/index' import { getActiveTokens } from '~/logic/tokens/utils/tokensStorage' +import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' import saveTokens from './saveTokens' const loadActiveTokens = (safeAddress: string) => async (dispatch: ReduxDispatch) => { try { const tokens: List = await getActiveTokens(safeAddress) - if (tokens.size) { - const tokenRecords: Map = Map().withMutations((map) => { - tokens.forEach(token => map.set(token.address, makeToken(token))) - }) + // ETH is active by default and cannot be disabled + const eth = await getEthAsToken(safeAddress) - dispatch(saveTokens(safeAddress, tokenRecords)) - } + const tokenRecords: Map = Map().withMutations((map) => { + tokens.forEach(token => map.set(token.address, makeToken(token))) + map.set(eth.address, eth) + }) + + dispatch(saveTokens(safeAddress, tokenRecords)) } catch (err) { // eslint-disable-next-line console.error('Error while loading active tokens from storage:', err) diff --git a/src/logic/tokens/utils/tokenHelpers.js b/src/logic/tokens/utils/tokenHelpers.js index 3265af2b04..915ea3b106 100644 --- a/src/logic/tokens/utils/tokenHelpers.js +++ b/src/logic/tokens/utils/tokenHelpers.js @@ -4,14 +4,14 @@ import logo from '~/assets/icons/icon_etherTokens.svg' import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3' import { makeToken, type Token } from '~/logic/tokens/store/model/token' -export const ETH_ADDRESS = '0' +export const ETH_ADDRESS = '0x000' export const isEther = (symbol: string) => symbol === 'ETH' -export const getSafeEthToken = async (safeAddress: string) => { +export const getEthAsToken = async (safeAddress: string) => { const balance = await getBalanceInEtherOf(safeAddress) const ethBalance = makeToken({ - address: '0', + address: ETH_ADDRESS, name: 'Ether', symbol: 'ETH', decimals: 18, @@ -23,7 +23,7 @@ export const getSafeEthToken = async (safeAddress: string) => { } export const calculateActiveErc20TokensFrom = (tokens: List) => { - const addresses = List().withMutations(list => tokens.forEach((token: Token) => { + const activeTokens = List().withMutations(list => tokens.forEach((token: Token) => { const isDeactivated = isEther(token.symbol) || !token.status if (isDeactivated) { return @@ -32,5 +32,5 @@ export const calculateActiveErc20TokensFrom = (tokens: List) => { list.push(token) })) - return addresses + return activeTokens } diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index d8ddbca70e..f43251d98f 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -23,6 +23,7 @@ import Divider from '~/components/layout/Divider' import Hairline from '~/components/layout/Hairline' import Spacer from '~/components/Spacer' import Row from '~/components/layout/Row' +import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' import { type Token } from '~/logic/tokens/store/model/token' import actions, { type Actions } from './actions' import TokenPlaceholder from './assets/token_placeholder.png' @@ -123,9 +124,11 @@ class Tokens extends React.Component { {token.name} - - - + {token.address !== ETH_ADDRESS && ( + + + + )} ))} diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index 20d989454b..ac5b506f93 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -21,11 +21,7 @@ class SafeView extends React.Component { fetchSafe(safeUrl) loadActiveTokens(safeUrl) - - if (activeTokens.size) { - // eslint-disable-next-line - fetchTokenBalances(safeUrl, activeTokens) - } + fetchTokenBalances(safeUrl, activeTokens) this.intervalId = setInterval(() => { // update in another function so it uses up-to-date props values From 56c6892651f1e4bd967d399c091a1bcf37c4731f Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 9 Apr 2019 19:53:41 +0400 Subject: [PATCH 09/48] split fetching tokens function --- src/logic/tokens/store/actions/fetchTokens.js | 46 +++++-------------- src/logic/tokens/store/actions/saveTokens.js | 13 +----- .../safe/component/Balances/Tokens/actions.js | 7 ++- .../safe/component/Balances/Tokens/index.jsx | 6 +++ src/routes/safe/container/actions.js | 3 -- 5 files changed, 23 insertions(+), 52 deletions(-) diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index 164f7b0660..0c4a205ce5 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -1,5 +1,5 @@ // @flow -import { List, Map } from 'immutable' +import { Map } from 'immutable' import contract from 'truffle-contract' import axios from 'axios' import type { Dispatch as ReduxDispatch } from 'redux' @@ -9,8 +9,6 @@ import { getWeb3 } from '~/logic/wallets/getWeb3' import { type GlobalState } from '~/store/index' import { makeToken, type Token, type TokenProps } from '~/logic/tokens/store/model/token' import { ensureOnce } from '~/utils/singleton' -import { getActiveTokens, getTokens } from '~/logic/tokens/utils/tokensStorage' -import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' import saveTokens from './saveTokens' import { getRelayUrl } from '~/config/index' @@ -33,7 +31,7 @@ export const getHumanFriendlyToken = ensureOnce(createHumanFriendlyTokenContract export const getStandardTokenContract = ensureOnce(createStandardTokenContract) -export const fetchTokensData = async () => { +const fetchTokenList = async () => { const apiUrl = getRelayUrl() const url = `${apiUrl}/tokens` const errMsg = 'Error querying safe balances' @@ -41,44 +39,22 @@ export const fetchTokensData = async () => { } export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispatch) => { - const tokens: List = await getActiveTokens(safeAddress) - const ethBalance = await getEthAsToken(safeAddress) - const customTokens = await getTokens(safeAddress) - const { - data: { results }, - } = await fetchTokensData() - try { - const balancesRecords = await Promise.all( - results.map(async (item: TokenProps) => { - const status = tokens.findIndex(activeToken => activeToken.name === item.name) !== -1 - const funds = status ? await calculateBalanceOf(item.address, safeAddress, item.decimals) : '0' - - return makeToken({ ...item, status, funds }) - }), - ) - - const customTokenRecords = await Promise.all( - customTokens.map(async (item: TokenProps) => { - const status = tokens.findIndex(activeToken => activeToken.name === item.name) !== -1 - const funds = status ? await calculateBalanceOf(item.address, safeAddress, item.decimals) : '0' + const { + data: { results: tokenList }, + } = await fetchTokenList() - return makeToken({ ...item, status, funds }) - }), - ) - - const balances: Map = Map().withMutations((map) => { - balancesRecords.forEach(record => map.set(record.address, record)) - customTokenRecords.forEach(record => map.set(record.address, record)) - - map.set(ethBalance.address, ethBalance) + const tokensMap: Map = Map().withMutations((map) => { + tokenList.forEach((token: TokenProps) => map.set(token.address, makeToken(token))) }) - return dispatch(saveTokens(safeAddress, balances)) + dispatch(saveTokens(safeAddress, tokensMap)) } catch (err) { // eslint-disable-next-line - console.log('Error fetching tokens... ' + err) + console.log('Error fetching token list ' + err) return Promise.resolve() } } + +export default fetchTokens diff --git a/src/logic/tokens/store/actions/saveTokens.js b/src/logic/tokens/store/actions/saveTokens.js index f2399b8570..0fca88b899 100644 --- a/src/logic/tokens/store/actions/saveTokens.js +++ b/src/logic/tokens/store/actions/saveTokens.js @@ -10,8 +10,6 @@ import { calculateActiveErc20TokensFrom } from '~/logic/tokens/utils/tokenHelper export const ADD_TOKENS = 'ADD_TOKENS' -const setTokensOnce = ensureOnceAsync(setActiveTokens) - type TokenProps = { safeAddress: string, tokens: Map, @@ -25,13 +23,4 @@ export const addTokens = createAction( }), ) -const saveTokens = (safeAddress: string, tokens: Map) => async ( - dispatch: ReduxDispatch, -) => { - dispatch(addTokens(safeAddress, tokens)) - - const activeAddresses: List = calculateActiveErc20TokensFrom(tokens.toList()) - await setTokensOnce(safeAddress, activeAddresses) -} - -export default saveTokens +export default addTokens diff --git a/src/routes/safe/component/Balances/Tokens/actions.js b/src/routes/safe/component/Balances/Tokens/actions.js index 971349a5b5..dfede04416 100644 --- a/src/routes/safe/component/Balances/Tokens/actions.js +++ b/src/routes/safe/component/Balances/Tokens/actions.js @@ -1,13 +1,16 @@ // @flow import enableToken from '~/logic/tokens/store/actions/enableToken' import disableToken from '~/logic/tokens/store/actions/disableToken' +import fetchTokens from '~/logic/tokens/store/actions/fetchTokens' export type Actions = { - enableToken: typeof enableToken, - disableToken: typeof disableToken, + enableToken: Function, + disableToken: Function, + fetchTokens: Function } export default { enableToken, disableToken, + fetchTokens, } diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index f43251d98f..8504902b18 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -51,6 +51,12 @@ class Tokens extends React.Component { filter: '', } + componentDidMount() { + const { fetchTokens } = this.props + + fetchTokens() + } + onCancelSearch = () => { this.setState(() => ({ filter: '' })) } diff --git a/src/routes/safe/container/actions.js b/src/routes/safe/container/actions.js index 21b11b96d1..3fb578b641 100644 --- a/src/routes/safe/container/actions.js +++ b/src/routes/safe/container/actions.js @@ -1,19 +1,16 @@ // @flow import fetchSafe from '~/routes/safe/store/actions/fetchSafe' -import { fetchTokens } from '~/logic/tokens/store/actions/fetchTokens' import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens' import fetchTokenBalances from '~/logic/tokens/store/actions/fetchTokenBalances' export type Actions = { fetchSafe: typeof fetchSafe, - fetchTokens: typeof fetchTokens, loadActiveTokens: typeof loadActiveTokens, fetchTokenBalances: typeof fetchTokenBalances } export default { fetchSafe, - fetchTokens, loadActiveTokens, fetchTokenBalances, } From f5983447eee5849abc53266cf6e0b209d8075d93 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 10 Apr 2019 12:56:08 +0400 Subject: [PATCH 10/48] fix token fetch --- src/routes/safe/component/Balances/Tokens/index.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index 8504902b18..175e037db8 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -52,9 +52,9 @@ class Tokens extends React.Component { } componentDidMount() { - const { fetchTokens } = this.props + const { fetchTokens, safeAddress } = this.props - fetchTokens() + fetchTokens(safeAddress) } onCancelSearch = () => { From 93cf045c00a60437c4ec3a48cfbe9ba084ac034d Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 10 Apr 2019 17:24:32 +0400 Subject: [PATCH 11/48] update safe and token models --- src/logic/tokens/store/model/token.js | 6 ------ src/routes/safe/store/actions/addSafe.js | 4 ++-- src/routes/safe/store/actions/fetchSafe.js | 4 ++-- src/routes/safe/store/model/safe.js | 8 +++++--- src/routes/safe/store/reducer/safe.js | 6 ++++-- src/routes/safe/store/test/builder/safe.builder.js | 4 ++-- src/test/builder/safe.redux.builder.js | 4 ++-- 7 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/logic/tokens/store/model/token.js b/src/logic/tokens/store/model/token.js index 7705ce8ad6..ba439eeae1 100644 --- a/src/logic/tokens/store/model/token.js +++ b/src/logic/tokens/store/model/token.js @@ -8,9 +8,6 @@ export type TokenProps = { symbol: string, decimals: number, logoUri: string, - funds: string, - status: boolean, - removable: boolean, } export const makeToken: RecordFactory = Record({ @@ -19,9 +16,6 @@ export const makeToken: RecordFactory = Record({ symbol: '', decimals: 0, logoUri: '', - funds: '0', - status: true, - removable: false, }) export type Token = RecordOf diff --git a/src/routes/safe/store/actions/addSafe.js b/src/routes/safe/store/actions/addSafe.js index 858b9137aa..7ad8857528 100644 --- a/src/routes/safe/store/actions/addSafe.js +++ b/src/routes/safe/store/actions/addSafe.js @@ -1,7 +1,7 @@ // @flow import { List } from 'immutable' import { createAction } from 'redux-actions' -import { type Safe, makeSafe } from '~/routes/safe/store/model/safe' +import SafeRecord, { type Safe } from '~/routes/safe/store/model/safe' import { saveSafes, setOwners } from '~/logic/safe/utils' import { makeOwner, type Owner } from '~/routes/safe/store/model/owner' import type { Dispatch as ReduxDispatch, GetState } from 'redux' @@ -37,7 +37,7 @@ const saveSafe = ( const owners: List = buildOwnersFrom(ownersName, ownersAddress) const state: GlobalState = getState() - const safe: Safe = makeSafe({ + const safe: Safe = SafeRecord({ name, address, threshold, diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index bf2db97f09..e285afb279 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -3,7 +3,7 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { List, Map } from 'immutable' import { type GlobalState } from '~/store/index' import { makeOwner } from '~/routes/safe/store/model/owner' -import { type SafeProps, makeSafe } from '~/routes/safe/store/model/safe' +import SafeRecord, { type SafeProps } from '~/routes/safe/store/model/safe' import updateSafe from '~/routes/safe/store/actions/updateSafe' import { getOwners, getSafeName } from '~/logic/safe/utils' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' @@ -29,7 +29,7 @@ export const buildSafe = async (safeAddress: string, safeName: string) => { owners, } - return makeSafe(safe) + return SafeRecord(safe) } export default (safeAddress: string) => async (dispatch: ReduxDispatch) => { diff --git a/src/routes/safe/store/model/safe.js b/src/routes/safe/store/model/safe.js index 093673dd6c..acbdfcfe3c 100644 --- a/src/routes/safe/store/model/safe.js +++ b/src/routes/safe/store/model/safe.js @@ -1,5 +1,5 @@ // @flow -import { List, Record } from 'immutable' +import { List, Record, Map } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' import type { Owner } from '~/routes/safe/store/model/owner' @@ -8,15 +8,17 @@ export type SafeProps = { address: string, threshold: number, owners: List, + activeTokensBalances: Map, } -export const makeSafe: RecordFactory = Record({ +const SafeRecord: RecordFactory = Record({ name: '', address: '', threshold: 0, owners: List([]), + activeTokensBalances: Map([]), }) export type Safe = RecordOf -// Useage const someRecord: Safe = makeSafe({ name: ... }) +export default SafeRecord diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 203aa46642..878c501452 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -2,7 +2,7 @@ import { Map } from 'immutable' import { handleActions, type ActionType } from 'redux-actions' import { ADD_SAFE, buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' -import { type Safe, type SafeProps, makeSafe } from '~/routes/safe/store/model/safe' +import SafeRecord, { type Safe, type SafeProps } from '~/routes/safe/store/model/safe' import { type OwnerProps } from '~/routes/safe/store/model/owner' import { loadFromStorage } from '~/utils/storage' import { SAFES_KEY } from '~/logic/safe/utils' @@ -21,10 +21,12 @@ export const buildSafe = (storedSafe: SafeProps) => { address: storedSafe.address, name: storedSafe.name, threshold: storedSafe.threshold, + activeTokens: storedSafe.activeTokens, + balances: storedSafe.balances, owners, } - return makeSafe(safe) + return SafeRecord(safe) } const buildSafesFrom = (loadedSafes: Object): Map => { diff --git a/src/routes/safe/store/test/builder/safe.builder.js b/src/routes/safe/store/test/builder/safe.builder.js index 15a772ada5..1a551ba4ec 100644 --- a/src/routes/safe/store/test/builder/safe.builder.js +++ b/src/routes/safe/store/test/builder/safe.builder.js @@ -1,12 +1,12 @@ // @flow -import { makeSafe, type Safe } from '~/routes/safe/store/model/safe' +import SafeRecord, { type Safe } from '~/routes/safe/store/model/safe' import { buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' class SafeBuilder { safe: Safe constructor() { - this.safe = makeSafe() + this.safe = SafeRecord() } withAddress(address: string) { diff --git a/src/test/builder/safe.redux.builder.js b/src/test/builder/safe.redux.builder.js index 8b36c05e70..35b45ccf63 100644 --- a/src/test/builder/safe.redux.builder.js +++ b/src/test/builder/safe.redux.builder.js @@ -1,5 +1,5 @@ // @flow -import { makeSafe, type Safe } from '~/routes/safe/store/model/safe' +import SafeRecord, { type Safe } from '~/routes/safe/store/model/safe' import addSafe, { buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' import { FIELD_NAME, @@ -18,7 +18,7 @@ class SafeBuilder { safe: Safe constructor() { - this.safe = makeSafe() + this.safe = SafeRecord() } withAddress(address: string) { From a158fe4a1599d15121b990d24e058c4fbbaff6bd Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Wed, 10 Apr 2019 20:04:29 +0400 Subject: [PATCH 12/48] add extended token selector --- src/logic/tokens/store/model/token.js | 4 ++++ src/routes/safe/container/selector.js | 28 ++++++++++++++++++++---- src/routes/safe/store/model/safe.js | 12 ++++++++-- src/routes/safe/store/selectors/index.js | 16 +++++++++++++- 4 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/logic/tokens/store/model/token.js b/src/logic/tokens/store/model/token.js index ba439eeae1..ab1c9a9bfe 100644 --- a/src/logic/tokens/store/model/token.js +++ b/src/logic/tokens/store/model/token.js @@ -8,6 +8,7 @@ export type TokenProps = { symbol: string, decimals: number, logoUri: string, + balance: string } export const makeToken: RecordFactory = Record({ @@ -16,6 +17,9 @@ export const makeToken: RecordFactory = Record({ symbol: '', decimals: 0, logoUri: '', + balance: undefined, }) +// balance is only set in extendedSafeTokensSelector when we display user's token balances + export type Token = RecordOf diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index e9c5e433a6..850a63624e 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -1,13 +1,18 @@ // @flow -import { List } from 'immutable' +import { List, Map } from 'immutable' import { createSelector, createStructuredSelector, type Selector } from 'reselect' -import { safeSelector, type RouterProps, type SafeSelectorProps } from '~/routes/safe/store/selectors' +import { + safeSelector, + safeTokensSelector, + type RouterProps, + type SafeSelectorProps, +} from '~/routes/safe/store/selectors' import { providerNameSelector, userAccountSelector, networkSelector } from '~/logic/wallets/store/selectors' import { type Safe } from '~/routes/safe/store/model/safe' import { type Owner } from '~/routes/safe/store/model/owner' import { type GlobalState } from '~/store' import { sameAddress } from '~/logic/wallets/ethAddresses' -import { activeTokensSelector, orderedTokenListSelector } from '~/logic/tokens/store/selectors' +import { activeTokensSelector, orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors' import { type Token } from '~/logic/tokens/store/model/token' import { safeParamAddressSelector } from '../store/selectors' @@ -42,10 +47,25 @@ export const grantedSelector: Selector = crea }, ) +const extendedSafeTokensSelector: Selector> = createSelector( + safeTokensSelector, + tokensSelector, + (safeTokens: Map, tokensList: Map) => { + // const extendedTokens = safeTokens.map(token => tokensList.get(token.address).set('balance', token.balance)) + const extendedTokens = Map().withMutations((map) => { + safeTokens.forEach(({ address, balance }: { address: string, balance: string }) => { + map.set(address, tokensList.get(address).set(balance)) + }) + }) + + return extendedTokens + }, +) + export default createStructuredSelector({ safe: safeSelector, provider: providerNameSelector, - tokens: orderedTokenListSelector, + tokens: extendedSafeTokensSelector, activeTokens: activeTokensSelector, granted: grantedSelector, userAddress: userAccountSelector, diff --git a/src/routes/safe/store/model/safe.js b/src/routes/safe/store/model/safe.js index acbdfcfe3c..06ed3b72ed 100644 --- a/src/routes/safe/store/model/safe.js +++ b/src/routes/safe/store/model/safe.js @@ -2,13 +2,14 @@ import { List, Record, Map } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' import type { Owner } from '~/routes/safe/store/model/owner' +import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' export type SafeProps = { name: string, address: string, threshold: number, owners: List, - activeTokensBalances: Map, + tokens: List>, } const SafeRecord: RecordFactory = Record({ @@ -16,9 +17,16 @@ const SafeRecord: RecordFactory = Record({ address: '', threshold: 0, owners: List([]), - activeTokensBalances: Map([]), + tokens: List([ + { + address: ETH_ADDRESS, + balance: '0', + }, + ]), }) +// Tokens is a list of currently enabled tokens for the safe with balances + export type Safe = RecordOf export default SafeRecord diff --git a/src/routes/safe/store/selectors/index.js b/src/routes/safe/store/selectors/index.js index 4f2d557f3b..6191bb8d84 100644 --- a/src/routes/safe/store/selectors/index.js +++ b/src/routes/safe/store/selectors/index.js @@ -78,6 +78,20 @@ export const safeSelector: Selector }, ) -export default createStructuredSelector({ +export const safeTokensSelector: Selector> = createSelector( + safeSelector, + (safe: Safe) => { + if (!safe) { + return Map() + } + + const tokens = safe.get('tokens') + + return tokens + }, +) + +export default createStructuredSelector({ safe: safeSelector, + tokens: safeTokensSelector, }) From 78883eacb1ecbfac6ce675535dcd1795ae9622d9 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 11 Apr 2019 12:05:59 +0400 Subject: [PATCH 13/48] extended token selector fix, dep bump --- package.json | 14 +- src/routes/load/container/Load.jsx | 12 +- src/routes/safe/container/selector.js | 6 +- yarn.lock | 340 ++++++++++++++------------ 4 files changed, 197 insertions(+), 175 deletions(-) diff --git a/package.json b/package.json index 8d920fb439..a82d0e4c75 100644 --- a/package.json +++ b/package.json @@ -82,7 +82,7 @@ "react-final-form": "^4.1.0", "react-hot-loader": "4.8.3", "react-infinite-scroll-component": "^4.5.2", - "react-redux": "^6.0.1", + "react-redux": "7.0.1", "react-router-dom": "^4.3.1", "recompose": "^0.30.0", "redux": "^4.0.1", @@ -134,7 +134,7 @@ "detect-port": "^1.2.2", "eslint": "^5.16.0", "eslint-config-airbnb": "^17.1.0", - "eslint-plugin-flowtype": "^3.4.2", + "eslint-plugin-flowtype": "3.6.1", "eslint-plugin-import": "^2.9.0", "eslint-plugin-jest": "^22.3.0", "eslint-plugin-jsx-a11y": "^6.0.3", @@ -148,7 +148,7 @@ "html-webpack-plugin": "^3.0.4", "jest": "^24.1.0", "json-loader": "^0.5.7", - "mini-css-extract-plugin": "^0.5.0", + "mini-css-extract-plugin": "0.6.0", "postcss-loader": "^3.0.0", "postcss-mixins": "^6.2.0", "postcss-simple-vars": "^5.0.2", @@ -158,14 +158,14 @@ "storybook-host": "^5.0.3", "storybook-router": "^0.3.3", "style-loader": "^0.23.1", - "truffle": "5.0.11", + "truffle": "5.0.12", "truffle-contract": "^4.0.11", - "truffle-solidity-loader": "0.1.11", + "truffle-solidity-loader": "0.1.12", "uglifyjs-webpack-plugin": "^2.1.2", "webpack": "^4.1.1", - "webpack-bundle-analyzer": "3.2.0", + "webpack-bundle-analyzer": "3.3.0", "webpack-cli": "^3.2.3", - "webpack-dev-server": "^3.1.0", + "webpack-dev-server": "3.3.1", "webpack-manifest-plugin": "^2.0.0-rc.2" } } diff --git a/src/routes/load/container/Load.jsx b/src/routes/load/container/Load.jsx index 4dc1cd7bea..3e5967e9e0 100644 --- a/src/routes/load/container/Load.jsx +++ b/src/routes/load/container/Load.jsx @@ -19,7 +19,7 @@ export const loadSafe = async (safeName: string, safeAddress: string, updateSafe await updateSafe(safeRecord) - const storedSafes = await loadFromStorage(SAFES_KEY) || {} + const storedSafes = (await loadFromStorage(SAFES_KEY)) || {} storedSafes[safeAddress] = safeRecord.toJSON() saveSafes(storedSafes) @@ -33,6 +33,7 @@ class Load extends React.Component { const safeAddress = values[FIELD_LOAD_ADDRESS] await loadSafe(safeName, safeAddress, updateSafe) + const url = `${SAFELIST_ADDRESS}/${safeAddress}` history.push(url) } catch (error) { @@ -42,9 +43,7 @@ class Load extends React.Component { } render() { - const { - provider, network, userAddress, - } = this.props + const { provider, network, userAddress } = this.props return ( @@ -59,4 +58,7 @@ class Load extends React.Component { } } -export default connect(selector, actions)(Load) +export default connect( + selector, + actions, +)(Load) diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index 850a63624e..f9fb55c67a 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -54,7 +54,11 @@ const extendedSafeTokensSelector: Selector // const extendedTokens = safeTokens.map(token => tokensList.get(token.address).set('balance', token.balance)) const extendedTokens = Map().withMutations((map) => { safeTokens.forEach(({ address, balance }: { address: string, balance: string }) => { - map.set(address, tokensList.get(address).set(balance)) + const baseToken = tokensList.get(address) + + if (baseToken) { + map.set(address, baseToken.set(balance)) + } }) }) diff --git a/yarn.lock b/yarn.lock index 010c95d33a..93ad203477 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1086,7 +1086,7 @@ dependencies: regenerator-runtime "^0.12.0" -"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2": +"@babel/runtime@^7.0.0", "@babel/runtime@^7.1.2", "@babel/runtime@^7.2.0", "@babel/runtime@^7.3.1", "@babel/runtime@^7.3.4", "@babel/runtime@^7.4.2", "@babel/runtime@^7.4.3": version "7.4.3" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.4.3.tgz#79888e452034223ad9609187a0ad1fe0d2ad4bdc" integrity sha512-9lsJwJLxDh/T3Q3SZszfWOTkk3pHbkmH+3KY+zwIDmsNlxsumuhS2TH3NIpktU4kNvfzy+k3eLT7aTJSPTo0OA== @@ -4651,7 +4651,7 @@ chokidar@^1.6.1: optionalDependencies: fsevents "^1.0.0" -chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.4: +chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.5.tgz#0ae8434d962281a5f56c72869e79cb6d9d86ad4d" integrity sha512-i0TprVWp+Kj4WRPtInjexJ8Q+BqTE909VpH8xVhXrJkoc5QC8VO9TryGOqTr+2hljzc1sC62t22h5tZePodM/A== @@ -4973,7 +4973,7 @@ compressible@~2.0.16: dependencies: mime-db ">= 1.38.0 < 2" -compression@^1.5.2: +compression@^1.7.4: version "1.7.4" resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== @@ -5021,7 +5021,7 @@ configstore@^4.0.0: write-file-atomic "^2.0.0" xdg-basedir "^3.0.0" -connect-history-api-fallback@^1.3.0: +connect-history-api-fallback@^1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== @@ -5600,13 +5600,6 @@ decamelize@^1.1.1, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= -decamelize@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-2.0.0.tgz#656d7bbc8094c4c788ea53c5840908c9c7d063c7" - integrity sha512-Ikpp5scV3MSYxY39ymh45ZLEecsTdv/Xj2CaQfI8RLMuwi7XvjX9H/fhraiSuU+C5w5NTDu4ZU72xNiZnurBPg== - dependencies: - xregexp "4.0.0" - decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -5788,17 +5781,17 @@ del@^2.2.0: pinkie-promise "^2.0.0" rimraf "^2.2.8" -del@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/del/-/del-3.0.0.tgz#53ecf699ffcbcb39637691ab13baf160819766e5" - integrity sha1-U+z2mf/LyzljdpGrE7rxYIGXZuU= +del@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.0.tgz#049543b8290e1a9293e2bd150ab3a06f637322b8" + integrity sha512-C4kvKNlYrwXhKxz97BuohF8YoGgQ23Xm9lvoHmgT7JaPGprSEjk3+XFled74Yt/x0ZABUHg2D67covzAPUKx5Q== dependencies: globby "^6.1.0" - is-path-cwd "^1.0.0" - is-path-in-cwd "^1.0.0" - p-map "^1.1.1" - pify "^3.0.0" - rimraf "^2.2.8" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" delayed-stream@~1.0.0: version "1.0.0" @@ -6362,10 +6355,10 @@ eslint-module-utils@^2.3.0: debug "^2.6.8" pkg-dir "^2.0.0" -eslint-plugin-flowtype@^3.4.2: - version "3.5.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-3.5.1.tgz#903c542c33039bc1db16355fff2d26733903bb0b" - integrity sha512-mIhq7jhBSWNMp3ECmlWK+b9EFmLE+3Jd9axk05LB+snbRPkc3/lYTgb4Bu9lgt1QLmrxFDWsASdKj9CAIehckg== +eslint-plugin-flowtype@3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-3.6.1.tgz#99cfa3a30e8a2c9ea40c507b25ea9a320af4ceae" + integrity sha512-VVuPKb5kgWFhxCkAMpL5wi44AK+4nkxa3XXZVa2PKf00n4INNbdKmZC0tT8qeNTHoDPYMXbqak4tGC9YtIOqGw== dependencies: lodash "^4.17.11" @@ -7111,7 +7104,7 @@ expect@^24.7.1: jest-message-util "^24.7.1" jest-regex-util "^24.3.0" -express@^4.14.0, express@^4.16.2, express@^4.16.3: +express@^4.14.0, express@^4.16.3, express@^4.16.4: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" integrity sha512-j12Uuyb4FMrd/qQAm6uCHAkPtO8FDTRJZBDd5D2KOL2eLaz1yUNdUB/NOIyq0iU4q4cFarsUCrnFDPBcnksuOg== @@ -8447,7 +8440,7 @@ html-encoding-sniffer@^1.0.2: dependencies: whatwg-encoding "^1.0.1" -html-entities@^1.2.0: +html-entities@^1.2.0, html-entities@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= @@ -9187,6 +9180,11 @@ is-path-cwd@^1.0.0: resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-1.0.0.tgz#d225ec23132e89edd38fda767472e62e65f1106d" integrity sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0= +is-path-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.0.0.tgz#d4777a8e227a00096a31f030db3770f84b116c02" + integrity sha512-m5dHHzpOXEiv18JEORttBO64UgTEypx99vCxQLjbBvGhOJxnTNglYoFXxwo6AbsQb79sqqycQEHv2hWkHZAijA== + is-path-in-cwd@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz#5ac48b345ef675339bd6c7a48a912110b241cf52" @@ -9194,6 +9192,13 @@ is-path-in-cwd@^1.0.0: dependencies: is-path-inside "^1.0.0" +is-path-in-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.0.0.tgz#68e452a6eec260500cec21e029c0a44cc0dcd2ea" + integrity sha512-6Vz5Gc9s/sDA3JBVu0FzWufm8xaBsqy1zn8Q6gmvGP6nSDMw78aS4poBNeatWjaRpTpxxLn1WOndAiOlk+qY8A== + dependencies: + is-path-inside "^1.0.0" + is-path-inside@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-1.0.1.tgz#8ef5b7de50437a3fdca6b4e865ef7aa55cb48036" @@ -9201,7 +9206,7 @@ is-path-inside@^1.0.0: dependencies: path-is-inside "^1.0.1" -is-plain-obj@^1.1.0: +is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= @@ -10115,7 +10120,7 @@ keycode@^2.2.0: resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.2.0.tgz#3d0af56dc7b8b8e5cba8d0a97f107204eec22b04" integrity sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ= -killable@^1.0.0: +killable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== @@ -10426,6 +10431,11 @@ lodash.debounce@^4.0.8: resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= +lodash.escaperegexp@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz#64762c48618082518ac3df4ccf5d5886dae20347" + integrity sha1-ZHYsSGGAglGKw99Mz11YhtriA0c= + lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" @@ -10521,7 +10531,7 @@ loglevel-colored-level-prefix@^1.0.0: chalk "^1.1.3" loglevel "^1.4.1" -loglevel@^1.4.1: +loglevel@^1.4.1, loglevel@^1.6.1: version "1.6.1" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.1.tgz#e0fc95133b6ef276cdc8887cdaf24aa6f156f8fa" integrity sha1-4PyVEztu8nbNyIh82vJKpvFW+Po= @@ -10929,6 +10939,16 @@ min-document@^2.19.0: dependencies: dom-walk "^0.1.0" +mini-css-extract-plugin@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.6.0.tgz#a3f13372d6fcde912f3ee4cd039665704801e3b9" + integrity sha512-79q5P7YGI6rdnVyIAV4NXpBQJFWdkzJxCim3Kog4078fM0piAaFlwocqbejdWtLW1cEzCexPrh6EdyFsPgVdAw== + dependencies: + loader-utils "^1.1.0" + normalize-url "^2.0.1" + schema-utils "^1.0.0" + webpack-sources "^1.1.0" + mini-css-extract-plugin@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.5.0.tgz#ac0059b02b9692515a637115b0cc9fed3a35c7b0" @@ -11374,6 +11394,15 @@ normalize-scroll-left@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-scroll-left/-/normalize-scroll-left-0.1.2.tgz#6b79691ba79eb5fb107fa5edfbdc06b55caee2aa" integrity sha512-F9YMRls0zCF6BFIE2YnXDRpHPpfd91nOIaNdDgrx5YMoPLo8Wqj+6jNXHQsYBavJeXP4ww8HCt0xQAKc5qk2Fg== +normalize-url@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-2.0.1.tgz#835a9da1551fa26f70e92329069a23aa6574d7e6" + integrity sha512-D6MUW4K/VzoJ4rJ01JFKxDrtY1v9wrgzCX5f2qj/lzH1m/lW6MhUZFKerVsnyjOhOsYzI9Kqqak+10l4LvLpMw== + dependencies: + prepend-http "^2.0.0" + query-string "^5.0.1" + sort-keys "^2.0.0" + normalize-url@^3.0.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" @@ -11622,7 +11651,7 @@ opn@5.4.0: dependencies: is-wsl "^1.1.0" -opn@^5.1.0, opn@^5.4.0: +opn@^5.4.0, opn@^5.5.0: version "5.5.0" resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== @@ -11800,10 +11829,10 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" -p-map@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/p-map/-/p-map-1.2.0.tgz#e4e94f311eabbc8633a1e79908165fca26241b6b" - integrity sha512-r6zKACMNhjPJMTl8KcFH4li//gkrXWfbD6feV8l6doRHlzljFWGJ2AP6iKaCJXyZmAUMOPtvbW7EXkbWO/pLEA== +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== p-reduce@^1.0.0: version "1.0.0" @@ -12120,7 +12149,7 @@ popper.js@^1.14.1, popper.js@^1.14.4: resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.7.tgz#e31ec06cfac6a97a53280c3e55e4e0c860e7738e" integrity sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ== -portfinder@^1.0.9: +portfinder@^1.0.20: version "1.0.20" resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.20.tgz#bea68632e54b2e13ab7b0c4775e9b41bf270e44a" integrity sha512-Yxe4mTyDzTd59PZJY4ojZR8F+E5e97iq2ZOHPz3HDgSvYC5siNad2tLooQ5y5QHyQhc3xVqvyk/eNA3wuoa7Sw== @@ -12530,6 +12559,11 @@ prepend-http@^1.0.1: resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= +prepend-http@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-2.0.0.tgz#e92434bfa5ea8c19f41cdfd401d741a3c819d897" + integrity sha1-6SQ0v6XqjBn0HN/UAddBo8gZ2Jc= + preserve@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/preserve/-/preserve-0.2.0.tgz#815ed1f6ebc65926f865b310c0713bcb3315ce4b" @@ -13137,7 +13171,7 @@ react-inspector@^2.2.2, react-inspector@^2.3.0, react-inspector@^2.3.1: is-dom "^1.0.9" prop-types "^15.6.1" -react-is@^16.6.3, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.2, react-is@^16.8.4: +react-is@^16.6.3, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6: version "16.8.6" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.8.6.tgz#5bbc1e2d29141c9fbdfed456343fe2bc430a6a16" integrity sha512-aUk3bHfZ2bRSVFFbbeVS4i+lNPZr3/WM5jT2J5omUVV1zzcs1nAaf3l51ctA5FFvCRbhrH0bdAsRRQddFJZPtA== @@ -13177,17 +13211,17 @@ react-popper@^1.3.3: typed-styles "^0.0.7" warning "^4.0.2" -react-redux@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-6.0.1.tgz#0d423e2c1cb10ada87293d47e7de7c329623ba4d" - integrity sha512-T52I52Kxhbqy/6TEfBv85rQSDz6+Y28V/pf52vDWs1YRXG19mcFOGfHnY2HsNFHyhP+ST34Aih98fvt6tqwVcQ== +react-redux@7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.0.1.tgz#321285e6c85c3586d11cc066ab33dc580da599fb" + integrity sha512-orSiI/QXtGiiJmf8lN/zVTx4hysFo/kGOsce28IUu/mu98AGemBwPTDzf64P4Vf/miRmevO8/w2RSw2awDd21w== dependencies: - "@babel/runtime" "^7.3.1" + "@babel/runtime" "^7.4.3" hoist-non-react-statics "^3.3.0" invariant "^2.2.4" loose-envify "^1.4.0" prop-types "^15.7.2" - react-is "^16.8.2" + react-is "^16.8.6" react-resize-detector@^3.2.1: version "3.4.0" @@ -13937,7 +13971,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@~2.6.2: +rimraf@2, rimraf@2.6.3, rimraf@^2.2.8, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2, rimraf@^2.6.3, rimraf@~2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -14228,7 +14262,7 @@ select@^1.1.2: resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= -selfsigned@^1.9.1: +selfsigned@^1.10.4: version "1.10.4" resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.4.tgz#cdd7eccfca4ed7635d47a08bf2d5d3074092e2cd" integrity sha512-9AukTiDmHXGXWtWjembZ5NDmVvP2695EtpgbCsxCa68w3c88B+alqbmZ4O3hZ4VWGXeGWzEVdvqgAJD8DQPCDw== @@ -14250,6 +14284,11 @@ semver@5.5.0: resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" integrity sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA== +semver@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.0.0.tgz#05e359ee571e5ad7ed641a6eec1e547ba52dea65" + integrity sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ== + semver@~5.4.1: version "5.4.1" resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" @@ -14290,7 +14329,7 @@ serve-favicon@^2.5.0: parseurl "~1.3.2" safe-buffer "5.1.1" -serve-index@^1.7.2: +serve-index@^1.9.1: version "1.9.1" resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= @@ -14586,6 +14625,13 @@ solidity-sha3@^0.4.1: left-pad "^1.1.1" web3 "^0.16.0" +sort-keys@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-2.0.0.tgz#658535584861ec97d730d6cf41822e1f56684128" + integrity sha1-ZYU1WEhh7JfXMNbPQYIuH1ZoQSg= + dependencies: + is-plain-obj "^1.0.0" + source-list-map@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" @@ -15584,10 +15630,10 @@ truffle-blockchain-utils@^0.0.8: resolved "https://registry.yarnpkg.com/truffle-blockchain-utils/-/truffle-blockchain-utils-0.0.8.tgz#09995c36016a54092b337f237c3dc1a3dca12341" integrity sha512-4dbgqd4GrloKNLiaXACiymE3R2PsNFOlbgOh/CGkQVLArtcbgBAl7Fg2l5yVfDV8dtOFWHddj/2UkY25KY1+Dw== -truffle-box@^1.0.19: - version "1.0.19" - resolved "https://registry.yarnpkg.com/truffle-box/-/truffle-box-1.0.19.tgz#a22d60b0983796b3323e9f664c11e6354ddc3927" - integrity sha512-rjepxnDMzyKRqLb9FDMkvOuRca3DYWpidUhbvUuc9paK+8mADj0Yh/w8zBGUaOIG3HcphO81vfWnfsgA5wVQjQ== +truffle-box@^1.0.20: + version "1.0.20" + resolved "https://registry.yarnpkg.com/truffle-box/-/truffle-box-1.0.20.tgz#2069ebca20026b5ce783c42fde5f7e72d57d67d1" + integrity sha512-pfTJbvi9eQG6B2cIw0BibOOCvnEsHpadVTsmXECJhxcf34QH6fYCwPdExe8fgu2p5r6g4+77RJ/21n2h7IMvUw== dependencies: fs-extra "6.0.1" github-download "^0.5.0" @@ -15596,10 +15642,10 @@ truffle-box@^1.0.19: tmp "0.0.33" vcsurl "^0.1.1" -truffle-code-utils@^1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/truffle-code-utils/-/truffle-code-utils-1.2.0.tgz#7e04e9b2fbfc5f44058acdc16c1e7d43dd83f585" - integrity sha512-VhpYJFpWcwcYLs3qQvB17OCeVDbUq1moDFf6CmrTeon6vgeF348wsjSuGdyJ12vHUWYu7Jdk+G+rXkl8DcRiFQ== +truffle-code-utils@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/truffle-code-utils/-/truffle-code-utils-1.2.1.tgz#5abe1ce8237ee90ca511c7a612b98d545030a47f" + integrity sha512-baCmNq6dcRnRkoGdSS4e0/yNtsmCyWApCxjjB18fNaavs6QGNQVguFJ3n4Dd7dglQxc4dqwjcngt2I+GFIAt5w== truffle-compile-vyper@^1.0.10: version "1.0.10" @@ -15719,10 +15765,10 @@ truffle-contract@^4.0.11: web3-eth-abi "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -truffle-core@^5.0.11: - version "5.0.11" - resolved "https://registry.yarnpkg.com/truffle-core/-/truffle-core-5.0.11.tgz#24298b6b55f859add7b15cbdf1209a0a2d7666d1" - integrity sha512-GPoLbD10CqnDPddFIFhsfTj8Y8F26Hk9GnB49tgHJN+Ezw4485+oZ+2YnlYHZjHVCD2Y832Y8Zx+ybdQXN4b8g== +truffle-core@^5.0.12: + version "5.0.12" + resolved "https://registry.yarnpkg.com/truffle-core/-/truffle-core-5.0.12.tgz#bc89b6429fd3de21e3ed816438840945f71673e5" + integrity sha512-G6JVqOK7vr2MSbDD59yEYHGhn7nFgMm35YbyahsxI5QyphfTFTntTmI/L+RAX37dZhfuR4OuAlYWjivA6kzXuQ== dependencies: app-module-path "^2.2.0" async "2.6.1" @@ -15754,19 +15800,19 @@ truffle-core@^5.0.11: spawn-args "^0.1.0" temp "^0.8.3" truffle-artifactor "^4.0.10" - truffle-box "^1.0.19" + truffle-box "^1.0.20" truffle-compile "^4.0.10" truffle-config "^1.1.7" truffle-contract "^4.0.11" truffle-contract-sources "^0.1.3" - truffle-debug-utils "^1.0.14" - truffle-debugger "^5.0.5" - truffle-deployer "^3.0.11" + truffle-debug-utils "^1.0.15" + truffle-debugger "^5.0.6" + truffle-deployer "^3.0.12" truffle-error "^0.0.4" truffle-expect "^0.0.7" truffle-init "^1.0.7" truffle-interface-adapter "^0.1.2" - truffle-migrate "^3.0.11" + truffle-migrate "^3.0.12" truffle-provider "^0.1.6" truffle-provisioner "^0.1.4" truffle-require "^2.0.7" @@ -15778,51 +15824,51 @@ truffle-core@^5.0.11: xregexp "^4.2.4" yargs "^8.0.2" -truffle-debug-utils@^1.0.14: - version "1.0.14" - resolved "https://registry.yarnpkg.com/truffle-debug-utils/-/truffle-debug-utils-1.0.14.tgz#a3c820bb41ed243c56c30ae607fd8776f5a7c6c6" - integrity sha512-hGpwNTMXXaJVi9RLhXhaOTtBdYYwYgFoENpd0bJEfXuB8obJTlS+3dFkZ7iPd5p3VuYRAJLhNy0rDb6pWwyTBA== +truffle-debug-utils@^1.0.15: + version "1.0.15" + resolved "https://registry.yarnpkg.com/truffle-debug-utils/-/truffle-debug-utils-1.0.15.tgz#7ec407601d182b2564488806fa2c5e1ad466a3c5" + integrity sha512-IKNCgN1d+bHNB022yetSrJtNjeDuCs5IHiNmugycHu6uoMTRTGICvJ3MlGWoNjKeR6OKzIgG5YTRLXHitv+ejg== dependencies: async "2.6.1" debug "^4.1.0" node-dir "0.1.17" -truffle-debugger@^5.0.5: - version "5.0.5" - resolved "https://registry.yarnpkg.com/truffle-debugger/-/truffle-debugger-5.0.5.tgz#5695f1add0c25cd9131c004c9867aebb3e838a04" - integrity sha512-8ZrJCYoe4uyOcRQm91WkvsVo0GpC6BXw5AAPY+8nqB20jBz1oSk8DgY9MLdBtX9ASnZDgSta+hlX2ryIDQXnGg== +truffle-debugger@^5.0.6: + version "5.0.6" + resolved "https://registry.yarnpkg.com/truffle-debugger/-/truffle-debugger-5.0.6.tgz#dfc61e61f97d6c2b52e3b273d269a332388aaeb0" + integrity sha512-0qRIHcZmLymj23aTl3pk6z05MsTdOj3gn2qV4AfEOEoCpJaLAc0PH3iE/vBYxLBZ2LbBf+Zlvz/wvBUcJkwKTA== dependencies: bn.js "^4.11.8" debug "^4.1.0" - fast-levenshtein "^2.0.6" json-pointer "^0.6.0" + lodash.escaperegexp "^4.1.2" lodash.sum "^4.0.2" redux "^3.7.2" redux-cli-logger "^2.0.1" redux-saga "1.0.0" remote-redux-devtools "^0.5.12" reselect-tree "^1.3.0" - truffle-code-utils "^1.2.0" - truffle-decode-utils "^1.0.7" - truffle-decoder "^2.0.4" + truffle-code-utils "^1.2.1" + truffle-decode-utils "^1.0.8" + truffle-decoder "^2.0.5" truffle-expect "^0.0.7" truffle-solidity-utils "^1.2.2" web3 "1.0.0-beta.37" web3-eth-abi "1.0.0-beta.37" -truffle-decode-utils@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/truffle-decode-utils/-/truffle-decode-utils-1.0.7.tgz#c26e88ef8fff48d878b7515166bcfc47ec75f2c3" - integrity sha512-b3zU6v8ZYteyJ98ujupOsWwprcHYGsqn9AR1QfLopKtSLCVB6L8bWewI0m+rIgBsDV8SI3rNL5/YA69wCrmvHw== +truffle-decode-utils@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/truffle-decode-utils/-/truffle-decode-utils-1.0.8.tgz#2cefc99a9671463cb46f8a3ded7782ec56dc9a5f" + integrity sha512-qMz0S0eFPoAnfh3mrYGsGm6a2jKPEtUHYhHIBV92tketSE2uA83HTYZ87mQa0W3/9SmwTRAdQnR8tFLQ2RlHBA== dependencies: bn.js "^4.11.8" lodash.clonedeep "^4.5.0" web3 "1.0.0-beta.37" -truffle-decoder@^2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/truffle-decoder/-/truffle-decoder-2.0.4.tgz#eb5630c8ab6b7d889124efa621acee38dfc02e3b" - integrity sha512-nXI9Q+j3ZGN6Q3ObpwvtjXceyysozPzVea5v4k3KIz33AvpjadUt2uoqsabOQ31To90FgqD+vYgHu+BO8D4z4Q== +truffle-decoder@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/truffle-decoder/-/truffle-decoder-2.0.5.tgz#096b9b371343a3a2dda37d1585e70c1a2beddf72" + integrity sha512-WUr1Mkb895IUpG+Z5wLKLCnt+5/pKQWEsC7dIvFcVepxGExP+5wjPOD4fKOwSb8V01whIJfkcGU3MRJuEUxSIw== dependencies: abi-decoder "^1.2.0" async-eventemitter "^0.2.4" @@ -15832,13 +15878,13 @@ truffle-decoder@^2.0.4: lodash.isequal "^4.5.0" lodash.merge "^4.6.1" lodash.range "^3.2.0" - truffle-decode-utils "^1.0.7" + truffle-decode-utils "^1.0.8" web3 "1.0.0-beta.37" -truffle-deployer@^3.0.11: - version "3.0.11" - resolved "https://registry.yarnpkg.com/truffle-deployer/-/truffle-deployer-3.0.11.tgz#c61d35e2c7803cad0300f1262470cec84be52c27" - integrity sha512-iSHrvJ58VRuAPR0jWzADEqDMq7T7jKmspOcyQzKvy4MLjKXP1eDCklJUmWoUzbXRu5I9XZxcNUNxnLB+GyWQkA== +truffle-deployer@^3.0.12: + version "3.0.12" + resolved "https://registry.yarnpkg.com/truffle-deployer/-/truffle-deployer-3.0.12.tgz#fb0342d4ef5a706e30012f8763f62de95b29330f" + integrity sha512-bttgzZ0oQvBAZ9Y9SsE9r89nbWPBo3Co7jDTbGxjkAkNwKZcs/dImTBBFAhIbhg2mORkz06tuVN76Kfw4598Ng== dependencies: emittery "^0.4.0" truffle-contract "^4.0.11" @@ -15890,18 +15936,18 @@ truffle-interface-adapter@^0.1.2: bn.js "^4.11.8" web3 "1.0.0-beta.37" -truffle-migrate@^3.0.11: - version "3.0.11" - resolved "https://registry.yarnpkg.com/truffle-migrate/-/truffle-migrate-3.0.11.tgz#574c553aef2a561daae1937c51c126914af0f227" - integrity sha512-qLWWrDeHI4DJ+HEit03LdqPWoymk2MvDBm5z9ebovCMMXe3Rv6Gfu7QO48oLaWk5e8SEb95zprIZJfmXM7UAuw== +truffle-migrate@^3.0.12: + version "3.0.12" + resolved "https://registry.yarnpkg.com/truffle-migrate/-/truffle-migrate-3.0.12.tgz#8eadcdcab1e428422ed39028f2471b1efe1f44c6" + integrity sha512-ylC5A7xiA/EFWp+bbAjPPw5pi7qN24sBiy4Yd6qOzXRtP0ZgdBAtNRKrrm2c1YZhyuLU693hMS+h8jP3aij5mQ== dependencies: async "2.6.1" emittery "^0.4.0" node-dir "0.1.17" - truffle-deployer "^3.0.11" + truffle-deployer "^3.0.12" truffle-expect "^0.0.7" truffle-interface-adapter "^0.1.2" - truffle-reporters "^1.0.7" + truffle-reporters "^1.0.8" truffle-require "^2.0.7" web3 "1.0.0-beta.37" @@ -15919,10 +15965,10 @@ truffle-provisioner@^0.1.4: resolved "https://registry.yarnpkg.com/truffle-provisioner/-/truffle-provisioner-0.1.4.tgz#a470f7e603d069b481481dba92f5c9d2f1a8526a" integrity sha512-d4GhAsS4bEtYIfuedaFl9k22o7UJOsmgMZM8M3fQYI0uAGt9ApEGEL0Yvdy7/uWw/0T1796ZVe+EuzlbcjaiUQ== -truffle-reporters@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/truffle-reporters/-/truffle-reporters-1.0.7.tgz#1e5ee60c37d81659b59639bed3bb8ccb0e129645" - integrity sha512-xS0HmKpq1pz63OspqQtfh0zCCS4T+pRyQh6fVp2FTzPbx31QzAQFen4P4Q1s1M05r2lTUIbCFjyRoX1HcwDEMw== +truffle-reporters@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/truffle-reporters/-/truffle-reporters-1.0.8.tgz#60ae1c14df8c6143f5b80e8e7d770dad24f2a140" + integrity sha512-NhHjUhSKRctZKFsS4ndrAhY3CKWa7oGCvqXr5P/bu4WKT3jbayTIv9SmfS2vwVwZ6OlczmWwgoYGQuw9LX7Zfw== dependencies: node-emoji "^1.8.1" ora "^3.0.0" @@ -15949,17 +15995,17 @@ truffle-resolver@^5.0.10: truffle-expect "^0.0.7" truffle-provisioner "^0.1.4" -truffle-solidity-loader@0.1.11: - version "0.1.11" - resolved "https://registry.yarnpkg.com/truffle-solidity-loader/-/truffle-solidity-loader-0.1.11.tgz#3b6f4aa6ac6fd581fc30d01832316d7ca8e29240" - integrity sha512-vd4wvET1FCfTNq6NbyDyo3pasxYXL+uQ2Cf9bzyO0KmNwtDmiuBo5uSGTorqUKH52M0tzr2G0NSgZnobtOtjNA== +truffle-solidity-loader@0.1.12: + version "0.1.12" + resolved "https://registry.yarnpkg.com/truffle-solidity-loader/-/truffle-solidity-loader-0.1.12.tgz#50aee0f20eaca18788a5de69207a523b1cba372d" + integrity sha512-NQhyVOS5xfHUrsITECTcgmGBquqAsX6TxuHk+oePtVK5eTcS4v9j+f6pd5Hno4Hd9RmdWr/NbvE8X6rxwhKo1w== dependencies: chalk "^1.1.3" find-up "^1.1.2" loader-utils "^1.1.0" schema-utils "^1.0.0" truffle-config "^1.1.7" - truffle-core "^5.0.11" + truffle-core "^5.0.12" truffle-solidity-utils@^1.2.2: version "1.2.2" @@ -15983,10 +16029,10 @@ truffle-workflow-compile@^2.0.10: truffle-external-compile "^1.0.7" truffle-resolver "^5.0.10" -truffle@5.0.11: - version "5.0.11" - resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.11.tgz#e593674415bf5e4a02eed5b940d736dece5ab447" - integrity sha512-LyXKxrvPuWuM31AF0U+d890e3ojYAjt4CeHO1zrjBG+/2ac/Fv31yqZS/cXN8xU09xCVC9uEcJ2Z23j9Q2KhRg== +truffle@5.0.12: + version "5.0.12" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.0.12.tgz#05ab7d2561a3ee4fd5e026dcc4b91b8f3c6e3795" + integrity sha512-dqnDmtTGNcnL29PHQwPE/CVmFFeGLuTFeb4TS3VY/vbASefu118IKXcadOWzkCPPwktv/njwylHSPhwoS00F2A== dependencies: app-module-path "^2.2.0" mocha "^4.1.0" @@ -17324,10 +17370,10 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-bundle-analyzer@3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.2.0.tgz#0630d298e88511d036d7c823705d7b852593d5c4" - integrity sha512-F6bwrg5TBb9HsHZCltH1L5F091ELQ+/i67MEH7jWkYRvVp53eONNneGaIXSdOQUiXUyd3RnkITWRfWvSVQGnZQ== +webpack-bundle-analyzer@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.0.tgz#2c18aca01fa03f11dccb3f627fb40b9f38bd7225" + integrity sha512-xNz1oC5pFiVLyDHDz2qZs3ydAuIWv96zokdBZAz+xdhD8BX3mytCmbWkzLzNRDjuWEovhQtycuvpfd368XvLBA== dependencies: acorn "^6.0.7" acorn-walk "^6.1.1" @@ -17360,7 +17406,7 @@ webpack-cli@^3.2.3: v8-compile-cache "^2.0.2" yargs "^12.0.5" -webpack-dev-middleware@^3.5.1: +webpack-dev-middleware@^3.5.1, webpack-dev-middleware@^3.6.2: version "3.6.2" resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.6.2.tgz#f37a27ad7c09cd7dc67cd97655413abaa1f55942" integrity sha512-A47I5SX60IkHrMmZUlB0ZKSWi29TZTcPz7cha1Z75yYOsgWh/1AcPmQEbC8ZIbU3A1ytSv1PMU0PyPz2Lmz2jg== @@ -17370,41 +17416,41 @@ webpack-dev-middleware@^3.5.1: range-parser "^1.0.3" webpack-log "^2.0.0" -webpack-dev-server@^3.1.0: - version "3.2.1" - resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.2.1.tgz#1b45ce3ecfc55b6ebe5e36dab2777c02bc508c4e" - integrity sha512-sjuE4mnmx6JOh9kvSbPYw3u/6uxCLHNWfhWaIPwcXWsvWOPN+nc5baq4i9jui3oOBRXGonK9+OI0jVkaz6/rCw== +webpack-dev-server@3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.3.1.tgz#7046e49ded5c1255a82c5d942bcdda552b72a62d" + integrity sha512-jY09LikOyGZrxVTXK0mgIq9y2IhCoJ05848dKZqX1gAGLU1YDqgpOT71+W53JH/wI4v6ky4hm+KvSyW14JEs5A== dependencies: ansi-html "0.0.7" bonjour "^3.5.0" - chokidar "^2.0.0" - compression "^1.5.2" - connect-history-api-fallback "^1.3.0" + chokidar "^2.1.5" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" debug "^4.1.1" - del "^3.0.0" - express "^4.16.2" - html-entities "^1.2.0" + del "^4.1.0" + express "^4.16.4" + html-entities "^1.2.1" http-proxy-middleware "^0.19.1" import-local "^2.0.0" internal-ip "^4.2.0" ip "^1.1.5" - killable "^1.0.0" - loglevel "^1.4.1" - opn "^5.1.0" - portfinder "^1.0.9" + killable "^1.0.1" + loglevel "^1.6.1" + opn "^5.5.0" + portfinder "^1.0.20" schema-utils "^1.0.0" - selfsigned "^1.9.1" - semver "^5.6.0" - serve-index "^1.7.2" + selfsigned "^1.10.4" + semver "^6.0.0" + serve-index "^1.9.1" sockjs "0.3.19" sockjs-client "1.3.0" spdy "^4.0.0" - strip-ansi "^3.0.0" + strip-ansi "^3.0.1" supports-color "^6.1.0" url "^0.11.0" - webpack-dev-middleware "^3.5.1" + webpack-dev-middleware "^3.6.2" webpack-log "^2.0.0" - yargs "12.0.2" + yargs "12.0.5" webpack-hot-middleware@^2.24.3: version "2.24.3" @@ -17740,11 +17786,6 @@ xmlhttprequest@*, xmlhttprequest@1.8.0, xmlhttprequest@^1.8.0: resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" integrity sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw= -xregexp@4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.0.0.tgz#e698189de49dd2a18cc5687b05e17c8e43943020" - integrity sha512-PHyM+sQouu7xspQQwELlGwwd05mXUFqwFYfqPO0cC7x4fxyHnnuetmQr6CjJiafIDoH4MogHb9dOoJzR/Y4rFg== - xregexp@^4.2.4: version "4.2.4" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-4.2.4.tgz#02a4aea056d65a42632c02f0233eab8e4d7e57ed" @@ -17789,13 +17830,6 @@ yallist@^3.0.0, yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== -yargs-parser@^10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-10.1.0.tgz#7202265b89f7e9e9f2e5765e0fe735a905edbaa8" - integrity sha512-VCIyR1wJoEBZUqk5PA+oOBF6ypbwh5aNB3I50guxAL/quggdfs4TtNHQrSazFA3fYZ+tEqfs0zIGlv0c/rgjbQ== - dependencies: - camelcase "^4.1.0" - yargs-parser@^11.1.1: version "11.1.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" @@ -17861,25 +17895,7 @@ yargs@11.1.0, yargs@^11.0.0: y18n "^3.2.1" yargs-parser "^9.0.2" -yargs@12.0.2: - version "12.0.2" - resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.2.tgz#fe58234369392af33ecbef53819171eff0f5aadc" - integrity sha512-e7SkEx6N6SIZ5c5H22RTZae61qtn3PYUE8JYbBFlK9sYmh3DMQ6E5ygtaG/2BW0JZi4WGgTR2IV5ChqlqrDGVQ== - dependencies: - cliui "^4.0.0" - decamelize "^2.0.0" - find-up "^3.0.0" - get-caller-file "^1.0.1" - os-locale "^3.0.0" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^2.0.0" - which-module "^2.0.0" - y18n "^3.2.1 || ^4.0.0" - yargs-parser "^10.1.0" - -yargs@^12.0.2, yargs@^12.0.5: +yargs@12.0.5, yargs@^12.0.2, yargs@^12.0.5: version "12.0.5" resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== From fe35b811c4957dadd06cfb46b221d3fb2c6971fc Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 11 Apr 2019 15:19:22 +0400 Subject: [PATCH 14/48] refactor tokens reducer --- src/logic/tokens/store/actions/addToken.js | 5 ++-- src/logic/tokens/store/reducer/tokens.js | 32 ++++++++-------------- src/logic/tokens/store/selectors/index.js | 18 ++---------- src/routes/safe/container/selector.js | 12 ++++---- src/routes/safe/store/actions/fetchSafe.js | 7 +++-- src/routes/safe/store/model/safe.js | 2 +- src/test/tokens.dom.enabling.test.js | 2 +- src/test/tokens.redux.adding.test.js | 1 - src/test/tokens.redux.remove.test.js | 1 - 9 files changed, 29 insertions(+), 51 deletions(-) diff --git a/src/logic/tokens/store/actions/addToken.js b/src/logic/tokens/store/actions/addToken.js index 601f241db4..725324b5f0 100644 --- a/src/logic/tokens/store/actions/addToken.js +++ b/src/logic/tokens/store/actions/addToken.js @@ -14,14 +14,13 @@ type AddTokenProps = { export const addToken = createAction( ADD_TOKEN, - (safeAddress: string, token: Token): AddTokenProps => ({ - safeAddress, + (token: Token): AddTokenProps => ({ token, }), ) const saveToken = (safeAddress: string, token: Token) => async (dispatch: ReduxDispatch) => { - dispatch(addToken(safeAddress, token)) + dispatch(addToken(token)) const activeTokens = await getActiveTokens(safeAddress) await setActiveTokens(safeAddress, activeTokens.push(token.toJS())) diff --git a/src/logic/tokens/store/reducer/tokens.js b/src/logic/tokens/store/reducer/tokens.js index 3b8381e3eb..1bec30e977 100644 --- a/src/logic/tokens/store/reducer/tokens.js +++ b/src/logic/tokens/store/reducer/tokens.js @@ -5,8 +5,6 @@ import { type Token } from '~/logic/tokens/store/model/token' import { ADD_TOKEN } from '~/logic/tokens/store/actions/addToken' import { REMOVE_TOKEN } from '~/logic/tokens/store/actions/removeToken' import { ADD_TOKENS } from '~/logic/tokens/store/actions/saveTokens' -import { DISABLE_TOKEN } from '~/logic/tokens/store/actions/disableToken' -import { ENABLE_TOKEN } from '~/logic/tokens/store/actions/enableToken' export const TOKEN_REDUCER_ID = 'tokens' @@ -15,33 +13,27 @@ export type State = Map> export default handleActions( { [ADD_TOKENS]: (state: State, action: ActionType): State => { - const { safeAddress, tokens } = action.payload + const { tokens } = action.payload - return state.update(safeAddress, (prevState: Map) => (prevState ? prevState.merge(tokens) : tokens)) + const newState = state.withMutations((map) => { + tokens.forEach((token) => { + map.set(token.address, token) + }) + }) + + return newState }, [ADD_TOKEN]: (state: State, action: ActionType): State => { - const { safeAddress, token } = action.payload + const { token } = action.payload const { address: tokenAddress } = token - return state.setIn([safeAddress, tokenAddress], token) + return state.set(tokenAddress, token) }, [REMOVE_TOKEN]: (state: State, action: ActionType): State => { - const { safeAddress, token } = action.payload - const { address: tokenAddress } = token - - return state.removeIn([safeAddress, tokenAddress]) - }, - [DISABLE_TOKEN]: (state: State, action: ActionType): State => { - const { safeAddress, token } = action.payload - const { address: tokenAddress } = token - - return state.setIn([safeAddress, tokenAddress, 'status'], false) - }, - [ENABLE_TOKEN]: (state: State, action: ActionType): State => { - const { safeAddress, token } = action.payload + const { token } = action.payload const { address: tokenAddress } = token - return state.setIn([safeAddress, tokenAddress, 'status'], true) + return state.remove(tokenAddress) }, }, Map(), diff --git a/src/logic/tokens/store/selectors/index.js b/src/logic/tokens/store/selectors/index.js index fa0e1db65d..4798469ae8 100644 --- a/src/logic/tokens/store/selectors/index.js +++ b/src/logic/tokens/store/selectors/index.js @@ -20,16 +20,11 @@ export const tokensSelector: Selector> = createSelector( - tokensSelector, +export const tokenListSelector: Selector, List> = createSelector( + tokensStateSelector, (tokens: Map) => tokens.toList(), ) -export const activeTokensSelector: Selector> = createSelector( - tokenListSelector, - (tokens: List) => tokens.filter((token: Token) => token.get('status')), -) - export const orderedTokenListSelector: Selector> = createSelector( tokenListSelector, (tokens: List) => tokens.sortBy((token: Token) => token.get('symbol')), @@ -43,12 +38,3 @@ export const tokenAddressesSelector: Selector> = createSelector( - activeTokensSelector, - (tokens: List) => { - const addresses = List().withMutations(list => tokens.map(token => list.push(token.address))) - - return addresses - }, -) diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index f9fb55c67a..8bfa9dbbf4 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -12,7 +12,7 @@ import { type Safe } from '~/routes/safe/store/model/safe' import { type Owner } from '~/routes/safe/store/model/owner' import { type GlobalState } from '~/store' import { sameAddress } from '~/logic/wallets/ethAddresses' -import { activeTokensSelector, orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors' +import { orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors' import { type Token } from '~/logic/tokens/store/model/token' import { safeParamAddressSelector } from '../store/selectors' @@ -53,11 +53,11 @@ const extendedSafeTokensSelector: Selector (safeTokens: Map, tokensList: Map) => { // const extendedTokens = safeTokens.map(token => tokensList.get(token.address).set('balance', token.balance)) const extendedTokens = Map().withMutations((map) => { - safeTokens.forEach(({ address, balance }: { address: string, balance: string }) => { - const baseToken = tokensList.get(address) + safeTokens.forEach((token: { address: string, balance: string }) => { + const baseToken = tokensList.get(token.address) if (baseToken) { - map.set(address, baseToken.set(balance)) + map.set(token.address, baseToken.set(token.balance)) } }) }) @@ -69,8 +69,8 @@ const extendedSafeTokensSelector: Selector export default createStructuredSelector({ safe: safeSelector, provider: providerNameSelector, - tokens: extendedSafeTokensSelector, - activeTokens: activeTokensSelector, + tokens: orderedTokenListSelector, + activeTokens: extendedSafeTokensSelector, granted: grantedSelector, userAddress: userAccountSelector, network: networkSelector, diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index e285afb279..696a684dc5 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -9,7 +9,10 @@ import { getOwners, getSafeName } from '~/logic/safe/utils' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' import { getWeb3 } from '~/logic/wallets/getWeb3' -const buildOwnersFrom = (safeOwners: string[], storedOwners: Map) => safeOwners.map((ownerAddress: string) => { +const buildOwnersFrom = ( + safeOwners: string[], + storedOwners: Map, // eslint-disable-next-line +) => safeOwners.map((ownerAddress: string) => { const ownerName = storedOwners.get(ownerAddress.toLowerCase()) || 'UNKNOWN' return makeOwner({ name: ownerName, address: ownerAddress }) }) @@ -34,7 +37,7 @@ export const buildSafe = async (safeAddress: string, safeName: string) => { export default (safeAddress: string) => async (dispatch: ReduxDispatch) => { try { - const safeName = await getSafeName(safeAddress) || 'LOADED SAFE' + const safeName = (await getSafeName(safeAddress)) || 'LOADED SAFE' const safeRecord = await buildSafe(safeAddress, safeName) return dispatch(updateSafe(safeRecord)) diff --git a/src/routes/safe/store/model/safe.js b/src/routes/safe/store/model/safe.js index 06ed3b72ed..4054767313 100644 --- a/src/routes/safe/store/model/safe.js +++ b/src/routes/safe/store/model/safe.js @@ -9,7 +9,7 @@ export type SafeProps = { address: string, threshold: number, owners: List, - tokens: List>, + tokens?: List>, } const SafeRecord: RecordFactory = Record({ diff --git a/src/test/tokens.dom.enabling.test.js b/src/test/tokens.dom.enabling.test.js index e1b1a75b99..fec8fca8b2 100644 --- a/src/test/tokens.dom.enabling.test.js +++ b/src/test/tokens.dom.enabling.test.js @@ -10,7 +10,7 @@ import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { travelToTokens } from '~/test/builder/safe.dom.utils' import { sleep } from '~/utils/timer' import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps' -import { tokenListSelector, activeTokensSelector } from '~/logic/tokens/store/selectors' +import { tokenListSelector } from '~/logic/tokens/store/selectors' import { getActiveTokenAddresses } from '~/logic/tokens/utils/tokensStorage' import { enableFirstToken, testToken } from '~/test/builder/tokens.dom.utils' import * as fetchTokensModule from '~/logic/tokens/store/actions/fetchTokens' diff --git a/src/test/tokens.redux.adding.test.js b/src/test/tokens.redux.adding.test.js index 8a8e1fea6e..c675834d37 100644 --- a/src/test/tokens.redux.adding.test.js +++ b/src/test/tokens.redux.adding.test.js @@ -10,7 +10,6 @@ import { testToken } from '~/test/builder/tokens.dom.utils' import * as fetchTokensModule from '~/logic/tokens/store/actions/fetchTokens' import * as enhancedFetchModule from '~/utils/fetch' import addToken from '~/logic/tokens/store/actions/addToken' -import { activeTokensSelector } from '~/logic/tokens/store/selectors' describe('DOM > Feature > Add new ERC 20 Tokens', () => { // let web3 diff --git a/src/test/tokens.redux.remove.test.js b/src/test/tokens.redux.remove.test.js index 30ebf7563b..4f718a5646 100644 --- a/src/test/tokens.redux.remove.test.js +++ b/src/test/tokens.redux.remove.test.js @@ -10,7 +10,6 @@ import { testToken } from '~/test/builder/tokens.dom.utils' import * as fetchTokensModule from '~/logic/tokens/store/actions/fetchTokens' import * as enhancedFetchModule from '~/utils/fetch' import addToken from '~/logic/tokens/store/actions/addToken' -import { activeTokensSelector, tokenListSelector } from '~/logic/tokens/store/selectors' import removeTokenAction from '~/logic/tokens/store/actions/removeToken' import { makeToken } from '~/logic/tokens/store/model/token' From f94e598609e4e24e1142daf3eab5cf32db175c5a Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 11 Apr 2019 18:12:27 +0400 Subject: [PATCH 15/48] balance fetch fixes --- .../store/actions/fetchTokenBalances.js | 6 ++--- src/logic/tokens/store/actions/saveTokens.js | 2 +- src/logic/tokens/store/selectors/index.js | 27 +++---------------- .../safe/component/Balances/dataFetcher.js | 6 ++--- src/routes/safe/container/selector.js | 10 ++++--- 5 files changed, 17 insertions(+), 34 deletions(-) diff --git a/src/logic/tokens/store/actions/fetchTokenBalances.js b/src/logic/tokens/store/actions/fetchTokenBalances.js index 0588ad58bf..d8a6ec1e62 100644 --- a/src/logic/tokens/store/actions/fetchTokenBalances.js +++ b/src/logic/tokens/store/actions/fetchTokenBalances.js @@ -7,7 +7,7 @@ import { type Token } from '~/logic/tokens/store/model/token' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3' import { getStandardTokenContract } from './fetchTokens' -import { addTokens } from './saveTokens' +import saveTokens from './saveTokens' export const calculateBalanceOf = async (tokenAddress: string, safeAddress: string, decimals: number = 18) => { if (tokenAddress === ETH_ADDRESS) { @@ -37,14 +37,14 @@ const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( try { const withBalances = await Promise.all( - tokens.map(async token => token.set('funds', await calculateBalanceOf(token.address, safeAddress, token.decimals))), + tokens.map(async token => token.set('balance', await calculateBalanceOf(token.address, safeAddress, token.decimals))), ) const tokensMap = Map().withMutations((map) => { withBalances.forEach(token => map.set(token.address, token)) }) - dispatch(addTokens(safeAddress, tokensMap)) + dispatch(saveTokens(safeAddress, tokensMap)) } catch (err) { // eslint-disable-next-line console.error('Error while loading active tokens from storage:', err) diff --git a/src/logic/tokens/store/actions/saveTokens.js b/src/logic/tokens/store/actions/saveTokens.js index 0fca88b899..36a3ed3b28 100644 --- a/src/logic/tokens/store/actions/saveTokens.js +++ b/src/logic/tokens/store/actions/saveTokens.js @@ -15,7 +15,7 @@ type TokenProps = { tokens: Map, } -export const addTokens = createAction( +const addTokens = createAction( ADD_TOKENS, (safeAddress: string, tokens: Map): TokenProps => ({ safeAddress, diff --git a/src/logic/tokens/store/selectors/index.js b/src/logic/tokens/store/selectors/index.js index 4798469ae8..30ab6b484a 100644 --- a/src/logic/tokens/store/selectors/index.js +++ b/src/logic/tokens/store/selectors/index.js @@ -1,27 +1,15 @@ // @flow import { List, Map } from 'immutable' import { createSelector, type Selector } from 'reselect' -import { safeParamAddressSelector, type RouterProps } from '~/routes/safe/store/selectors' +import { type RouterProps } from '~/routes/safe/store/selectors' import { type GlobalState } from '~/store' import { TOKEN_REDUCER_ID } from '~/logic/tokens/store/reducer/tokens' import { type Token } from '~/logic/tokens/store/model/token' -const tokensStateSelector = (state: GlobalState) => state[TOKEN_REDUCER_ID] - -export const tokensSelector: Selector> = createSelector( - tokensStateSelector, - safeParamAddressSelector, - (tokens: Map>, address: string) => { - if (!address) { - return Map() - } - - return tokens.get(address) || Map() - }, -) +export const tokensSelector = (state: GlobalState) => state[TOKEN_REDUCER_ID] export const tokenListSelector: Selector, List> = createSelector( - tokensStateSelector, + tokensSelector, (tokens: Map) => tokens.toList(), ) @@ -29,12 +17,3 @@ export const orderedTokenListSelector: Selector) => tokens.sortBy((token: Token) => token.get('symbol')), ) - -export const tokenAddressesSelector: Selector> = createSelector( - tokenListSelector, - (tokens: List) => { - const addresses = List().withMutations(list => tokens.map(token => list.push(token.address))) - - return addresses - }, -) diff --git a/src/routes/safe/component/Balances/dataFetcher.js b/src/routes/safe/component/Balances/dataFetcher.js index ecb60fe265..f54ffd8354 100644 --- a/src/routes/safe/component/Balances/dataFetcher.js +++ b/src/routes/safe/component/Balances/dataFetcher.js @@ -17,9 +17,9 @@ export type BalanceRow = SortRow export const getBalanceData = (activeTokens: List): Array => { const rows = activeTokens.map((token: Token) => ({ - [BALANCE_TABLE_ASSET_ID]: token.get('name'), - [BALANCE_TABLE_BALANCE_ID]: `${token.get('funds')} ${token.get('symbol')}`, - [buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)]: Number(token.get('funds')), + [BALANCE_TABLE_ASSET_ID]: token.name, + [BALANCE_TABLE_BALANCE_ID]: `${token.balance} ${token.symbol}`, + [buildOrderFieldFrom(BALANCE_TABLE_BALANCE_ID)]: Number(token.balance), [FIXED]: token.get('symbol') === 'ETH', })) diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index 8bfa9dbbf4..c62d905b48 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -47,11 +47,15 @@ export const grantedSelector: Selector = crea }, ) +type UserToken = { + address: string, + balance: string, +} + const extendedSafeTokensSelector: Selector> = createSelector( safeTokensSelector, tokensSelector, - (safeTokens: Map, tokensList: Map) => { - // const extendedTokens = safeTokens.map(token => tokensList.get(token.address).set('balance', token.balance)) + (safeTokens: List, tokensList: Map) => { const extendedTokens = Map().withMutations((map) => { safeTokens.forEach((token: { address: string, balance: string }) => { const baseToken = tokensList.get(token.address) @@ -62,7 +66,7 @@ const extendedSafeTokensSelector: Selector }) }) - return extendedTokens + return extendedTokens.toList() }, ) From be295d1ef5a841c67f51e2ae2764e8d0fa709353 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 11 Apr 2019 19:44:48 +0400 Subject: [PATCH 16/48] tokens balance refactor wip --- src/routes/safe/container/actions.js | 2 +- src/routes/safe/container/index.jsx | 8 ++++---- .../safe}/store/actions/fetchTokenBalances.js | 20 ++++++++++--------- src/routes/safe/store/model/safe.js | 2 +- src/routes/safe/store/reducer/safe.js | 5 ++--- 5 files changed, 19 insertions(+), 18 deletions(-) rename src/{logic/tokens => routes/safe}/store/actions/fetchTokenBalances.js (68%) diff --git a/src/routes/safe/container/actions.js b/src/routes/safe/container/actions.js index 3fb578b641..5450856a0d 100644 --- a/src/routes/safe/container/actions.js +++ b/src/routes/safe/container/actions.js @@ -1,7 +1,7 @@ // @flow import fetchSafe from '~/routes/safe/store/actions/fetchSafe' import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens' -import fetchTokenBalances from '~/logic/tokens/store/actions/fetchTokenBalances' +import fetchTokenBalances from '~/routes/safe/store/actions/fetchTokenBalances' export type Actions = { fetchSafe: typeof fetchSafe, diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index ac5b506f93..618f39ee7a 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -16,12 +16,12 @@ const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 15000 class SafeView extends React.Component { componentDidMount() { const { - fetchSafe, loadActiveTokens, activeTokens, safeUrl, fetchTokenBalances, + fetchSafe, loadActiveTokens, activeTokens, safeUrl, fetchTokenBalances, safe, } = this.props fetchSafe(safeUrl) loadActiveTokens(safeUrl) - fetchTokenBalances(safeUrl, activeTokens) + fetchTokenBalances(safe, activeTokens) this.intervalId = setInterval(() => { // update in another function so it uses up-to-date props values @@ -35,11 +35,11 @@ class SafeView extends React.Component { checkForUpdates() { const { - safeUrl, activeTokens, fetchSafe, fetchTokenBalances, + safeUrl, activeTokens, fetchSafe, fetchTokenBalances, safe, } = this.props fetchSafe(safeUrl) - fetchTokenBalances(safeUrl, activeTokens) + fetchTokenBalances(safe, activeTokens) } intervalId: IntervalID diff --git a/src/logic/tokens/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js similarity index 68% rename from src/logic/tokens/store/actions/fetchTokenBalances.js rename to src/routes/safe/store/actions/fetchTokenBalances.js index d8a6ec1e62..33236adf76 100644 --- a/src/logic/tokens/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -6,8 +6,9 @@ import { type GlobalState } from '~/store/index' import { type Token } from '~/logic/tokens/store/model/token' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3' -import { getStandardTokenContract } from './fetchTokens' -import saveTokens from './saveTokens' +import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' +import type { Safe } from '~/routes/safe/store/model/safe' +import updateSafe from './updateSafe' export const calculateBalanceOf = async (tokenAddress: string, safeAddress: string, decimals: number = 18) => { if (tokenAddress === ETH_ADDRESS) { @@ -28,23 +29,24 @@ export const calculateBalanceOf = async (tokenAddress: string, safeAddress: stri return new BigNumber(balance).div(10 ** decimals).toString() } -const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( +const fetchTokenBalances = (safe: Safe, tokens: List) => async ( dispatch: ReduxDispatch, ) => { - if (!safeAddress || !tokens || !tokens.size) { + if (!safe || !tokens || !tokens.size) { return } try { const withBalances = await Promise.all( - tokens.map(async token => token.set('balance', await calculateBalanceOf(token.address, safeAddress, token.decimals))), + tokens.map(async token => ({ + address: token.address, + balance: await calculateBalanceOf(token.address, safe.address, token.decimals), + })), ) - const tokensMap = Map().withMutations((map) => { - withBalances.forEach(token => map.set(token.address, token)) - }) + const safeWithBalances = safe.set('tokens', List(withBalances)) - dispatch(saveTokens(safeAddress, tokensMap)) + dispatch(updateSafe(safeWithBalances)) } catch (err) { // eslint-disable-next-line console.error('Error while loading active tokens from storage:', err) diff --git a/src/routes/safe/store/model/safe.js b/src/routes/safe/store/model/safe.js index 4054767313..05ac10f50f 100644 --- a/src/routes/safe/store/model/safe.js +++ b/src/routes/safe/store/model/safe.js @@ -9,7 +9,7 @@ export type SafeProps = { address: string, threshold: number, owners: List, - tokens?: List>, + tokens?: List, } const SafeRecord: RecordFactory = Record({ diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 878c501452..8043b3f8b8 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -21,8 +21,7 @@ export const buildSafe = (storedSafe: SafeProps) => { address: storedSafe.address, name: storedSafe.name, threshold: storedSafe.threshold, - activeTokens: storedSafe.activeTokens, - balances: storedSafe.balances, + tokens: storedSafe.tokens, owners, } @@ -58,7 +57,7 @@ export default handleActions( { [UPDATE_SAFE]: (state: State, action: ActionType): State => { const safe = action.payload - const safeAddress = safe.get('address') + const safeAddress = safe.address const hasSafe = !!state.get(safeAddress) if (hasSafe) { From 5f142bcc756cee970e81545fb01ba5c04dca753c Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 11 Apr 2019 20:10:52 +0400 Subject: [PATCH 17/48] add eth balance to safe model --- src/routes/safe/store/actions/fetchSafe.js | 4 +++- src/routes/safe/store/model/safe.js | 10 +++------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 696a684dc5..159933c507 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -7,7 +7,7 @@ import SafeRecord, { type SafeProps } from '~/routes/safe/store/model/safe' import updateSafe from '~/routes/safe/store/actions/updateSafe' import { getOwners, getSafeName } from '~/logic/safe/utils' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' -import { getWeb3 } from '~/logic/wallets/getWeb3' +import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3' const buildOwnersFrom = ( safeOwners: string[], @@ -21,6 +21,7 @@ export const buildSafe = async (safeAddress: string, safeName: string) => { const web3 = getWeb3() const SafeContract = await getGnosisSafeContract(web3) const gnosisSafe = await SafeContract.at(safeAddress) + const ethBalance = await getBalanceInEtherOf(safeAddress) const threshold = Number(await gnosisSafe.getThreshold()) const owners = List(buildOwnersFrom(await gnosisSafe.getOwners(), await getOwners(safeAddress))) @@ -30,6 +31,7 @@ export const buildSafe = async (safeAddress: string, safeName: string) => { name: safeName, threshold, owners, + ethBalance, } return SafeRecord(safe) diff --git a/src/routes/safe/store/model/safe.js b/src/routes/safe/store/model/safe.js index 05ac10f50f..032cdd0850 100644 --- a/src/routes/safe/store/model/safe.js +++ b/src/routes/safe/store/model/safe.js @@ -2,12 +2,12 @@ import { List, Record, Map } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' import type { Owner } from '~/routes/safe/store/model/owner' -import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' export type SafeProps = { name: string, address: string, threshold: number, + ethBalance: string, owners: List, tokens?: List, } @@ -16,13 +16,9 @@ const SafeRecord: RecordFactory = Record({ name: '', address: '', threshold: 0, + ethBalance: 0, owners: List([]), - tokens: List([ - { - address: ETH_ADDRESS, - balance: '0', - }, - ]), + tokens: List([]), }) // Tokens is a list of currently enabled tokens for the safe with balances From 3530d2f3056a2d5a1ddcf63a437177ad5f7c2d96 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Thu, 11 Apr 2019 20:24:14 +0400 Subject: [PATCH 18/48] remove eth from list of active tokens --- .../tokens/store/actions/loadActiveTokens.js | 5 ---- src/logic/tokens/utils/tokenHelpers.js | 24 +++++++++---------- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/logic/tokens/store/actions/loadActiveTokens.js b/src/logic/tokens/store/actions/loadActiveTokens.js index 7f6a4b55b2..3dc4c59f8a 100644 --- a/src/logic/tokens/store/actions/loadActiveTokens.js +++ b/src/logic/tokens/store/actions/loadActiveTokens.js @@ -4,19 +4,14 @@ import { List, Map } from 'immutable' import { type TokenProps, type Token, makeToken } from '~/logic/tokens/store/model/token' import { type GlobalState } from '~/store/index' import { getActiveTokens } from '~/logic/tokens/utils/tokensStorage' -import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' import saveTokens from './saveTokens' const loadActiveTokens = (safeAddress: string) => async (dispatch: ReduxDispatch) => { try { const tokens: List = await getActiveTokens(safeAddress) - // ETH is active by default and cannot be disabled - const eth = await getEthAsToken(safeAddress) - const tokenRecords: Map = Map().withMutations((map) => { tokens.forEach(token => map.set(token.address, makeToken(token))) - map.set(eth.address, eth) }) dispatch(saveTokens(safeAddress, tokenRecords)) diff --git a/src/logic/tokens/utils/tokenHelpers.js b/src/logic/tokens/utils/tokenHelpers.js index 915ea3b106..cfb740d9b0 100644 --- a/src/logic/tokens/utils/tokenHelpers.js +++ b/src/logic/tokens/utils/tokenHelpers.js @@ -7,20 +7,20 @@ import { makeToken, type Token } from '~/logic/tokens/store/model/token' export const ETH_ADDRESS = '0x000' export const isEther = (symbol: string) => symbol === 'ETH' -export const getEthAsToken = async (safeAddress: string) => { - const balance = await getBalanceInEtherOf(safeAddress) +// export const getEthAsToken = async (safeAddress: string) => { +// const balance = await getBalanceInEtherOf(safeAddress) - const ethBalance = makeToken({ - address: ETH_ADDRESS, - name: 'Ether', - symbol: 'ETH', - decimals: 18, - logoUri: logo, - funds: balance, - }) +// const ethBalance = makeToken({ +// address: ETH_ADDRESS, +// name: 'Ether', +// symbol: 'ETH', +// decimals: 18, +// logoUri: logo, +// funds: balance, +// }) - return ethBalance -} +// return ethBalance +// } export const calculateActiveErc20TokensFrom = (tokens: List) => { const activeTokens = List().withMutations(list => tokens.forEach((token: Token) => { From 50a315b839743814cb4a9feb12fa63b1cd3bbb45 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 12 Apr 2019 13:57:03 +0400 Subject: [PATCH 19/48] show eth balance in balance tab --- package.json | 2 +- src/logic/tokens/utils/tokenHelpers.js | 25 +++++++++++-------------- src/routes/safe/component/Layout.jsx | 12 +++++++++--- src/routes/safe/container/selector.js | 19 ++++++++++++++++++- yarn.lock | 8 ++++---- 5 files changed, 43 insertions(+), 23 deletions(-) diff --git a/package.json b/package.json index a82d0e4c75..52f5e2e28b 100644 --- a/package.json +++ b/package.json @@ -163,7 +163,7 @@ "truffle-solidity-loader": "0.1.12", "uglifyjs-webpack-plugin": "^2.1.2", "webpack": "^4.1.1", - "webpack-bundle-analyzer": "3.3.0", + "webpack-bundle-analyzer": "3.3.2", "webpack-cli": "^3.2.3", "webpack-dev-server": "3.3.1", "webpack-manifest-plugin": "^2.0.0-rc.2" diff --git a/src/logic/tokens/utils/tokenHelpers.js b/src/logic/tokens/utils/tokenHelpers.js index cfb740d9b0..a7aecd2f8c 100644 --- a/src/logic/tokens/utils/tokenHelpers.js +++ b/src/logic/tokens/utils/tokenHelpers.js @@ -1,26 +1,23 @@ // @flow import { List } from 'immutable' import logo from '~/assets/icons/icon_etherTokens.svg' -import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3' import { makeToken, type Token } from '~/logic/tokens/store/model/token' export const ETH_ADDRESS = '0x000' export const isEther = (symbol: string) => symbol === 'ETH' -// export const getEthAsToken = async (safeAddress: string) => { -// const balance = await getBalanceInEtherOf(safeAddress) +export const getEthAsToken = (balance: string) => { + const eth = makeToken({ + address: ETH_ADDRESS, + name: 'Ether', + symbol: 'ETH', + decimals: 18, + logoUri: logo, + balance, + }) -// const ethBalance = makeToken({ -// address: ETH_ADDRESS, -// name: 'Ether', -// symbol: 'ETH', -// decimals: 18, -// logoUri: logo, -// funds: balance, -// }) - -// return ethBalance -// } + return eth +} export const calculateActiveErc20TokensFrom = (tokens: List) => { const activeTokens = List().withMutations(list => tokens.forEach((token: Token) => { diff --git a/src/routes/safe/component/Layout.jsx b/src/routes/safe/component/Layout.jsx index 68a5d6a2b1..c8acb4f480 100644 --- a/src/routes/safe/component/Layout.jsx +++ b/src/routes/safe/component/Layout.jsx @@ -94,8 +94,8 @@ class Layout extends React.Component { if (!safe) { return } - // - const address = safe.get('address') + + const { address, ethBalance } = safe return ( @@ -129,7 +129,13 @@ class Layout extends React.Component { {tabIndex === 0 && ( - + )} ) diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index c62d905b48..cf522759cb 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -15,6 +15,7 @@ import { sameAddress } from '~/logic/wallets/ethAddresses' import { orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors' import { type Token } from '~/logic/tokens/store/model/token' import { safeParamAddressSelector } from '../store/selectors' +import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' export type SelectorProps = { safe: SafeSelectorProps, @@ -52,10 +53,22 @@ type UserToken = { balance: string, } +const safeEthAsTokenSelector: Selector = createSelector( + safeSelector, + (safe: Safe) => { + if (!safe) { + return undefined + } + + return getEthAsToken(safe.ethBalance) + }, +) + const extendedSafeTokensSelector: Selector> = createSelector( safeTokensSelector, tokensSelector, - (safeTokens: List, tokensList: Map) => { + safeEthAsTokenSelector, + (safeTokens: List, tokensList: Map, ethAsToken: Token) => { const extendedTokens = Map().withMutations((map) => { safeTokens.forEach((token: { address: string, balance: string }) => { const baseToken = tokensList.get(token.address) @@ -64,6 +77,10 @@ const extendedSafeTokensSelector: Selector map.set(token.address, baseToken.set(token.balance)) } }) + + if (ethAsToken) { + map.set(ethAsToken.address, ethAsToken) + } }) return extendedTokens.toList() diff --git a/yarn.lock b/yarn.lock index 93ad203477..0dc4a1809a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17370,10 +17370,10 @@ webidl-conversions@^4.0.2: resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== -webpack-bundle-analyzer@3.3.0: - version "3.3.0" - resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.0.tgz#2c18aca01fa03f11dccb3f627fb40b9f38bd7225" - integrity sha512-xNz1oC5pFiVLyDHDz2qZs3ydAuIWv96zokdBZAz+xdhD8BX3mytCmbWkzLzNRDjuWEovhQtycuvpfd368XvLBA== +webpack-bundle-analyzer@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.3.2.tgz#3da733a900f515914e729fcebcd4c40dde71fc6f" + integrity sha512-7qvJLPKB4rRWZGjVp5U1KEjwutbDHSKboAl0IfafnrdXMrgC0tOtZbQD6Rw0u4cmpgRN4O02Fc0t8eAT+FgGzA== dependencies: acorn "^6.0.7" acorn-walk "^6.1.1" From f797e2db772ec554114749025a75e301e7fc0989 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 12 Apr 2019 15:46:56 +0400 Subject: [PATCH 20/48] use addSafe instead updateSafe while adding a new safe --- src/routes/load/container/Load.jsx | 10 +++++----- src/routes/load/container/actions.js | 8 +++----- src/routes/safe/store/actions/fetchSafe.js | 4 ++-- src/routes/safe/store/actions/setTokenActive.js | 0 src/routes/safe/store/reducer/safe.js | 7 +------ 5 files changed, 11 insertions(+), 18 deletions(-) create mode 100644 src/routes/safe/store/actions/setTokenActive.js diff --git a/src/routes/load/container/Load.jsx b/src/routes/load/container/Load.jsx index 3e5967e9e0..13ba0012ca 100644 --- a/src/routes/load/container/Load.jsx +++ b/src/routes/load/container/Load.jsx @@ -8,16 +8,16 @@ import { loadFromStorage } from '~/utils/storage' import { SAFELIST_ADDRESS } from '~/routes/routes' import { history } from '~/store' import selector, { type SelectorProps } from './selector' -import actions, { type Actions, type UpdateSafe } from './actions' +import actions, { type Actions } from './actions' import Layout from '../components/Layout' import { FIELD_LOAD_NAME, FIELD_LOAD_ADDRESS } from '../components/fields' type Props = SelectorProps & Actions -export const loadSafe = async (safeName: string, safeAddress: string, updateSafe: UpdateSafe) => { +export const loadSafe = async (safeName: string, safeAddress: string, addSafe: Function) => { const safeRecord = await buildSafe(safeAddress, safeName) - await updateSafe(safeRecord) + await addSafe(safeRecord) const storedSafes = (await loadFromStorage(SAFES_KEY)) || {} storedSafes[safeAddress] = safeRecord.toJSON() @@ -28,11 +28,11 @@ export const loadSafe = async (safeName: string, safeAddress: string, updateSafe class Load extends React.Component { onLoadSafeSubmit = async (values: Object) => { try { - const { updateSafe } = this.props + const { addSafe } = this.props const safeName = values[FIELD_LOAD_NAME] const safeAddress = values[FIELD_LOAD_ADDRESS] - await loadSafe(safeName, safeAddress, updateSafe) + await loadSafe(safeName, safeAddress, addSafe) const url = `${SAFELIST_ADDRESS}/${safeAddress}` history.push(url) diff --git a/src/routes/load/container/actions.js b/src/routes/load/container/actions.js index 08a56d7eea..ef7f691456 100644 --- a/src/routes/load/container/actions.js +++ b/src/routes/load/container/actions.js @@ -1,12 +1,10 @@ // @flow -import updateSafe from '~/routes/safe/store/actions/updateSafe' - -export type UpdateSafe = typeof updateSafe +import { addSafe } from '~/routes/safe/store/actions/addSafe' export type Actions = { - updateSafe: typeof updateSafe, + addSafe: Function, } export default { - updateSafe, + addSafe, } diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 159933c507..d0ee469809 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -4,7 +4,7 @@ import { List, Map } from 'immutable' import { type GlobalState } from '~/store/index' import { makeOwner } from '~/routes/safe/store/model/owner' import SafeRecord, { type SafeProps } from '~/routes/safe/store/model/safe' -import updateSafe from '~/routes/safe/store/actions/updateSafe' +import { addSafe } from '~/routes/safe/store/actions/addSafe' import { getOwners, getSafeName } from '~/logic/safe/utils' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3' @@ -42,7 +42,7 @@ export default (safeAddress: string) => async (dispatch: ReduxDispatch( const safe = action.payload const safeAddress = safe.address - const hasSafe = !!state.get(safeAddress) - if (hasSafe) { - return state.update(safeAddress, prevSafe => (prevSafe.equals(safe) ? prevSafe : safe)) - } - - return state.set(safeAddress, safe) + return state.mergeIn(safeAddress, safe) }, [ADD_SAFE]: (state: State, action: ActionType): State => { const { safe }: { safe: Safe } = action.payload From a6249de48d3db752ac0bbfaf69b439e3fa416b22 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 12 Apr 2019 17:26:24 +0400 Subject: [PATCH 21/48] add SafeToken record --- src/logic/safe/safeFrontendOperations.js | 4 +-- src/logic/safe/utils/safeStorage.js | 2 +- .../tokens/store/actions/loadActiveTokens.js | 6 ++-- src/logic/tokens/utils/tokensStorage.js | 34 ++++++++----------- src/routes/safe/component/AddOwner/index.jsx | 4 +-- .../safe/component/RemoveOwner/index.jsx | 2 +- .../safe/component/RemoveOwner/selector.js | 2 +- src/routes/safe/component/Safe/Owners.jsx | 2 +- src/routes/safe/component/Safe/index.jsx | 2 +- src/routes/safe/component/SendToken/index.jsx | 2 +- .../Threshold/ThresholdForm/index.jsx | 2 +- src/routes/safe/component/Threshold/index.jsx | 2 +- .../Transactions/Collapsed/Confirmations.jsx | 2 +- .../Transactions/Collapsed/index.jsx | 2 +- .../Transactions/Transaction/index.jsx | 4 +-- .../Transactions/Transaction/selector.js | 4 +-- .../safe/component/Transactions/index.jsx | 4 +-- .../safe/component/Transactions/selector.js | 2 +- src/routes/safe/container/selector.js | 4 +-- src/routes/safe/store/actions/addSafe.js | 4 +-- src/routes/safe/store/actions/fetchSafe.js | 4 +-- .../safe/store/actions/fetchTransactions.js | 6 ++-- .../store/actions/loadSafesFromStorage.js | 2 +- .../safe/store/actions/setTokenActive.js | 0 .../safe/store/actions/updateActiveTokens.js | 7 ++++ .../store/{model => models}/confirmation.js | 2 +- .../safe/store/{model => models}/owner.js | 0 .../safe/store/{model => models}/safe.js | 7 ++-- src/routes/safe/store/models/safeToken.js | 17 ++++++++++ .../store/{model => models}/transaction.js | 2 +- src/routes/safe/store/reducer/safe.js | 4 +-- src/routes/safe/store/reducer/transactions.js | 2 +- src/routes/safe/store/selectors/index.js | 6 ++-- .../safe/store/test/builder/safe.builder.js | 2 +- .../safe/store/test/granted.selector.js | 2 +- src/routes/safe/store/test/safe.selector.js | 2 +- src/routes/safeList/components/Layout.jsx | 2 +- src/routes/safeList/components/SafeTable.jsx | 2 +- src/routes/safeList/container/index.jsx | 2 +- src/routes/safeList/store/selectors/index.js | 4 +-- .../safeList/store/test/safes.selector.js | 2 +- src/test/builder/safe.redux.builder.js | 2 +- src/test/safe.redux.load.test.js | 4 +-- src/test/safe.redux.owners.test.js | 2 +- src/test/safe.redux.transactions.test.js | 6 ++-- src/test/utils/historyServiceHelper.js | 4 +-- src/test/utils/safeHelper.js | 2 +- 47 files changed, 104 insertions(+), 83 deletions(-) delete mode 100644 src/routes/safe/store/actions/setTokenActive.js create mode 100644 src/routes/safe/store/actions/updateActiveTokens.js rename src/routes/safe/store/{model => models}/confirmation.js (98%) rename src/routes/safe/store/{model => models}/owner.js (100%) rename src/routes/safe/store/{model => models}/safe.js (71%) create mode 100644 src/routes/safe/store/models/safeToken.js rename src/routes/safe/store/{model => models}/transaction.js (87%) diff --git a/src/logic/safe/safeFrontendOperations.js b/src/logic/safe/safeFrontendOperations.js index 6e30b687bd..8a3cfc579c 100644 --- a/src/logic/safe/safeFrontendOperations.js +++ b/src/logic/safe/safeFrontendOperations.js @@ -1,10 +1,10 @@ // @flow import { List } from 'immutable' -import { type Transaction } from '~/routes/safe/store/model/transaction' +import { type Transaction } from '~/routes/safe/store/models/transaction' import { executeTransaction, approveTransaction } from '~/logic/safe/safeBlockchainOperations' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { getWeb3 } from '~/logic/wallets/getWeb3' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' import { storeSubject } from '~/utils/storage/transactions' diff --git a/src/logic/safe/utils/safeStorage.js b/src/logic/safe/utils/safeStorage.js index b8fac592d2..2301a5e136 100644 --- a/src/logic/safe/utils/safeStorage.js +++ b/src/logic/safe/utils/safeStorage.js @@ -1,5 +1,5 @@ // @flow -import { type Owner } from '~/routes/safe/store/model/owner' +import { type Owner } from '~/routes/safe/store/models/owner' import { List, Map } from 'immutable' import { loadFromStorage, saveToStorage } from '~/utils/storage' diff --git a/src/logic/tokens/store/actions/loadActiveTokens.js b/src/logic/tokens/store/actions/loadActiveTokens.js index 3dc4c59f8a..0d1270a11b 100644 --- a/src/logic/tokens/store/actions/loadActiveTokens.js +++ b/src/logic/tokens/store/actions/loadActiveTokens.js @@ -6,15 +6,15 @@ import { type GlobalState } from '~/store/index' import { getActiveTokens } from '~/logic/tokens/utils/tokensStorage' import saveTokens from './saveTokens' -const loadActiveTokens = (safeAddress: string) => async (dispatch: ReduxDispatch) => { +const loadActiveTokens = () => async (dispatch: ReduxDispatch) => { try { - const tokens: List = await getActiveTokens(safeAddress) + const tokens: List = await getActiveTokens() const tokenRecords: Map = Map().withMutations((map) => { tokens.forEach(token => map.set(token.address, makeToken(token))) }) - dispatch(saveTokens(safeAddress, tokenRecords)) + dispatch(saveTokens(tokenRecords)) } catch (err) { // eslint-disable-next-line console.error('Error while loading active tokens from storage:', err) diff --git a/src/logic/tokens/utils/tokensStorage.js b/src/logic/tokens/utils/tokensStorage.js index 028056498b..bb21540313 100644 --- a/src/logic/tokens/utils/tokensStorage.js +++ b/src/logic/tokens/utils/tokensStorage.js @@ -4,41 +4,38 @@ import { type Token, type TokenProps } from '~/logic/tokens/store/model/token' import { loadFromStorage, saveToStorage } from '~/utils/storage' export const ACTIVE_TOKENS_KEY = 'ACTIVE_TOKENS' -export const TOKENS_KEY = 'TOKENS' +export const CUSTOM_TOKENS_KEY = 'CUSTOM_TOKENS' -const getActiveTokensKey = (safeAddress: string) => `${ACTIVE_TOKENS_KEY}-${safeAddress}` -const getTokensKey = (safeAddress: string) => `${TOKENS_KEY}-${safeAddress}` +// Tokens which are active at least in one of used safes in the app should be saved to localstorage +// to avoid iterating a large amount of data of tokens from the backend +// Custom tokens should be saved too unless they're deleted (marking them as inactive doesn't count) -export const setActiveTokens = async (safeAddress: string, tokens: List) => { +export const setActiveTokens = async (tokens: List) => { try { - const key = getActiveTokensKey(safeAddress) - await saveToStorage(key, tokens.toJS()) + await saveToStorage(ACTIVE_TOKENS_KEY, tokens.toJS()) } catch (err) { // eslint-disable-next-line console.log('Error storing tokens in localstorage') } } -export const getActiveTokens = async (safeAddress: string): Promise> => { - const key = getActiveTokensKey(safeAddress) - const data = await loadFromStorage(key) +export const getActiveTokens = async (): Promise> => { + const data = await loadFromStorage(ACTIVE_TOKENS_KEY) return data ? List(data) : List() } -export const getTokens = async (safeAddress: string): Promise> => { - const key = getTokensKey(safeAddress) - const data = await loadFromStorage(key) +export const getCustomTokens = async (): Promise> => { + const data = await loadFromStorage(CUSTOM_TOKENS_KEY) return data ? List(data) : List() } export const setToken = async (safeAddress: string, token: Token) => { - const data: List = await getTokens(safeAddress) + const data: List = await getCustomTokens() try { - const key = getTokensKey(safeAddress) - await saveToStorage(key, data.push(token)) + await saveToStorage(CUSTOM_TOKENS_KEY, data.push(token)) } catch (err) { // eslint-disable-next-line console.log('Error adding token in localstorage') @@ -46,12 +43,11 @@ export const setToken = async (safeAddress: string, token: Token) => { } export const removeTokenFromStorage = async (safeAddress: string, token: Token) => { - const data: List = await getTokens(safeAddress) + const data: List = await getCustomTokens() try { const index = data.indexOf(token) - const key = getTokensKey(safeAddress) - await saveToStorage(key, data.remove(index)) + await saveToStorage(CUSTOM_TOKENS_KEY, data.remove(index)) } catch (err) { // eslint-disable-next-line console.log('Error removing token in localstorage') @@ -59,7 +55,7 @@ export const removeTokenFromStorage = async (safeAddress: string, token: Token) } export const removeFromActiveTokens = async (safeAddress: string, token: Token) => { - const activeTokens = await getActiveTokens(safeAddress) + const activeTokens = await getActiveTokens() const index = activeTokens.findIndex(activeToken => activeToken.name === token.name) if (index !== -1) { diff --git a/src/routes/safe/component/AddOwner/index.jsx b/src/routes/safe/component/AddOwner/index.jsx index e41692828c..4e1b61c0cf 100644 --- a/src/routes/safe/component/AddOwner/index.jsx +++ b/src/routes/safe/component/AddOwner/index.jsx @@ -3,8 +3,8 @@ import * as React from 'react' import { List } from 'immutable' import Stepper from '~/components/Stepper' import { connect } from 'react-redux' -import { type Safe } from '~/routes/safe/store/model/safe' -import { type Owner, makeOwner } from '~/routes/safe/store/model/owner' +import { type Safe } from '~/routes/safe/store/models/safe' +import { type Owner, makeOwner } from '~/routes/safe/store/models/owner' import { setOwners } from '~/utils/storage' import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations' import AddOwnerForm, { NAME_PARAM, OWNER_ADDRESS_PARAM, INCREASE_PARAM } from './AddOwnerForm' diff --git a/src/routes/safe/component/RemoveOwner/index.jsx b/src/routes/safe/component/RemoveOwner/index.jsx index a8b5510736..001860ecb6 100644 --- a/src/routes/safe/component/RemoveOwner/index.jsx +++ b/src/routes/safe/component/RemoveOwner/index.jsx @@ -2,7 +2,7 @@ import * as React from 'react' import Stepper from '~/components/Stepper' import { connect } from 'react-redux' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations' import RemoveOwnerForm, { DECREASE_PARAM } from './RemoveOwnerForm' import Review from './Review' diff --git a/src/routes/safe/component/RemoveOwner/selector.js b/src/routes/safe/component/RemoveOwner/selector.js index 3f8e9247e7..6a99db3604 100644 --- a/src/routes/safe/component/RemoveOwner/selector.js +++ b/src/routes/safe/component/RemoveOwner/selector.js @@ -2,7 +2,7 @@ import { List } from 'immutable' import { createStructuredSelector, createSelector } from 'reselect' import { userAccountSelector } from '~/logic/wallets/store/selectors' -import { type Transaction } from '~/routes/safe/store/model/transaction' +import { type Transaction } from '~/routes/safe/store/models/transaction' import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index' const pendingTransactionsSelector = createSelector( diff --git a/src/routes/safe/component/Safe/Owners.jsx b/src/routes/safe/component/Safe/Owners.jsx index ff433fe9bd..acc106c364 100644 --- a/src/routes/safe/component/Safe/Owners.jsx +++ b/src/routes/safe/component/Safe/Owners.jsx @@ -15,7 +15,7 @@ import Delete from '@material-ui/icons/Delete' import Person from '@material-ui/icons/Person' import ExpandLess from '@material-ui/icons/ExpandLess' import ExpandMore from '@material-ui/icons/ExpandMore' -import { type OwnerProps } from '~/routes/safe/store/model/owner' +import { type OwnerProps } from '~/routes/safe/store/models/owner' import { type WithStyles } from '~/theme/mui' import { sameAddress } from '~/logic/wallets/ethAddresses' diff --git a/src/routes/safe/component/Safe/index.jsx b/src/routes/safe/component/Safe/index.jsx index 2ce549cbd3..290a491e6b 100644 --- a/src/routes/safe/component/Safe/index.jsx +++ b/src/routes/safe/component/Safe/index.jsx @@ -8,7 +8,7 @@ import Bold from '~/components/layout/Bold' import Img from '~/components/layout/Img' import Paragraph from '~/components/layout/Paragraph' import Row from '~/components/layout/Row' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { type Token } from '~/logic/tokens/store/model/token' import Transactions from '~/routes/safe/component/Transactions' diff --git a/src/routes/safe/component/SendToken/index.jsx b/src/routes/safe/component/SendToken/index.jsx index 92f8c1a0fa..905c638aae 100644 --- a/src/routes/safe/component/SendToken/index.jsx +++ b/src/routes/safe/component/SendToken/index.jsx @@ -4,7 +4,7 @@ import { BigNumber } from 'bignumber.js' import { connect } from 'react-redux' import Stepper from '~/components/Stepper' import { sleep } from '~/utils/timer' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import { type Token } from '~/logic/tokens/store/model/token' import { isEther } from '~/logic/tokens/utils/tokens' diff --git a/src/routes/safe/component/Threshold/ThresholdForm/index.jsx b/src/routes/safe/component/Threshold/ThresholdForm/index.jsx index 6b757725af..c1d4b9fddc 100644 --- a/src/routes/safe/component/Threshold/ThresholdForm/index.jsx +++ b/src/routes/safe/component/Threshold/ThresholdForm/index.jsx @@ -6,7 +6,7 @@ import OpenPaper from '~/components/Stepper/OpenPaper' import Field from '~/components/forms/Field' import TextField from '~/components/forms/TextField' import { composeValidators, minValue, maxValue, mustBeInteger, required } from '~/components/forms/validator' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' export const THRESHOLD_PARAM = 'threshold' diff --git a/src/routes/safe/component/Threshold/index.jsx b/src/routes/safe/component/Threshold/index.jsx index 64dc7b7e1a..3b5a18e26f 100644 --- a/src/routes/safe/component/Threshold/index.jsx +++ b/src/routes/safe/component/Threshold/index.jsx @@ -3,7 +3,7 @@ import * as React from 'react' import Stepper from '~/components/Stepper' import { connect } from 'react-redux' import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import ThresholdForm, { THRESHOLD_PARAM } from './ThresholdForm' import selector, { type SelectorProps } from './selector' import actions, { type Actions } from './actions' diff --git a/src/routes/safe/component/Transactions/Collapsed/Confirmations.jsx b/src/routes/safe/component/Transactions/Collapsed/Confirmations.jsx index b4e49d7e1f..04a02ab11c 100644 --- a/src/routes/safe/component/Transactions/Collapsed/Confirmations.jsx +++ b/src/routes/safe/component/Transactions/Collapsed/Confirmations.jsx @@ -14,7 +14,7 @@ import Person from '@material-ui/icons/Person' import ExpandLess from '@material-ui/icons/ExpandLess' import ExpandMore from '@material-ui/icons/ExpandMore' import { type WithStyles } from '~/theme/mui' -import { type Confirmation, type ConfirmationProps } from '~/routes/safe/store/model/confirmation' +import { type Confirmation, type ConfirmationProps } from '~/routes/safe/store/models/confirmation' const styles = { nested: { diff --git a/src/routes/safe/component/Transactions/Collapsed/index.jsx b/src/routes/safe/component/Transactions/Collapsed/index.jsx index d57b0b0aaa..1a94be9c5f 100644 --- a/src/routes/safe/component/Transactions/Collapsed/index.jsx +++ b/src/routes/safe/component/Transactions/Collapsed/index.jsx @@ -9,7 +9,7 @@ import ListItemText from '~/components/List/ListItemText' import Avatar from '@material-ui/core/Avatar' import Group from '@material-ui/icons/Group' import MailOutline from '@material-ui/icons/MailOutline' -import { type Confirmation } from '~/routes/safe/store/model/confirmation' +import { type Confirmation } from '~/routes/safe/store/models/confirmation' import Confirmations from './Confirmations' type Props = { diff --git a/src/routes/safe/component/Transactions/Transaction/index.jsx b/src/routes/safe/component/Transactions/Transaction/index.jsx index 69b885ec25..389ebb06eb 100644 --- a/src/routes/safe/component/Transactions/Transaction/index.jsx +++ b/src/routes/safe/component/Transactions/Transaction/index.jsx @@ -16,11 +16,11 @@ import Atm from '@material-ui/icons/LocalAtm' import DoneAll from '@material-ui/icons/DoneAll' import CompareArrows from '@material-ui/icons/CompareArrows' import Collapsed from '~/routes/safe/component/Transactions/Collapsed' -import { type Transaction } from '~/routes/safe/store/model/transaction' +import { type Transaction } from '~/routes/safe/store/models/transaction' import Hairline from '~/components/layout/Hairline/index' import Button from '~/components/layout/Button' import { sameAddress } from '~/logic/wallets/ethAddresses' -import { type Confirmation } from '~/routes/safe/store/model/confirmation' +import { type Confirmation } from '~/routes/safe/store/models/confirmation' import selector, { type SelectorProps } from './selector' type Props = Open & diff --git a/src/routes/safe/component/Transactions/Transaction/selector.js b/src/routes/safe/component/Transactions/Transaction/selector.js index ba81065f7a..13e75084b5 100644 --- a/src/routes/safe/component/Transactions/Transaction/selector.js +++ b/src/routes/safe/component/Transactions/Transaction/selector.js @@ -2,9 +2,9 @@ import { createStructuredSelector } from 'reselect' import { confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors' -import { type Transaction } from '~/routes/safe/store/model/transaction' +import { type Transaction } from '~/routes/safe/store/models/transaction' import { type GlobalState } from '~/store' -import { type Confirmation } from '~/routes/safe/store/model/confirmation' +import { type Confirmation } from '~/routes/safe/store/models/confirmation' export type SelectorProps = { confirmed: confirmationsTransactionSelector, diff --git a/src/routes/safe/component/Transactions/index.jsx b/src/routes/safe/component/Transactions/index.jsx index 77cb22cfb7..32676d6473 100644 --- a/src/routes/safe/component/Transactions/index.jsx +++ b/src/routes/safe/component/Transactions/index.jsx @@ -2,11 +2,11 @@ import * as React from 'react' import { List } from 'immutable' import { connect } from 'react-redux' -import { type Transaction } from '~/routes/safe/store/model/transaction' +import { type Transaction } from '~/routes/safe/store/models/transaction' import NoTransactions from '~/routes/safe/component/Transactions/NoTransactions' import GnoTransaction from '~/routes/safe/component/Transactions/Transaction' import { sameAddress } from '~/logic/wallets/ethAddresses' -import { type Confirmation } from '~/routes/safe/store/model/confirmation' +import { type Confirmation } from '~/routes/safe/store/models/confirmation' import { processTransaction } from '~/logic/safe/safeFrontendOperations' import selector, { type SelectorProps } from './selector' import actions, { type Actions } from './actions' diff --git a/src/routes/safe/component/Transactions/selector.js b/src/routes/safe/component/Transactions/selector.js index 4097dc64bf..bb199222e6 100644 --- a/src/routes/safe/component/Transactions/selector.js +++ b/src/routes/safe/component/Transactions/selector.js @@ -1,7 +1,7 @@ // @flow import { List } from 'immutable' import { createStructuredSelector } from 'reselect' -import { type Transaction } from '~/routes/safe/store/model/transaction' +import { type Transaction } from '~/routes/safe/store/models/transaction' import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors' diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index cf522759cb..9ddf24b091 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -8,8 +8,8 @@ import { type SafeSelectorProps, } from '~/routes/safe/store/selectors' import { providerNameSelector, userAccountSelector, networkSelector } from '~/logic/wallets/store/selectors' -import { type Safe } from '~/routes/safe/store/model/safe' -import { type Owner } from '~/routes/safe/store/model/owner' +import { type Safe } from '~/routes/safe/store/models/safe' +import { type Owner } from '~/routes/safe/store/models/owner' import { type GlobalState } from '~/store' import { sameAddress } from '~/logic/wallets/ethAddresses' import { orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors' diff --git a/src/routes/safe/store/actions/addSafe.js b/src/routes/safe/store/actions/addSafe.js index 7ad8857528..23f0d04f41 100644 --- a/src/routes/safe/store/actions/addSafe.js +++ b/src/routes/safe/store/actions/addSafe.js @@ -1,9 +1,9 @@ // @flow import { List } from 'immutable' import { createAction } from 'redux-actions' -import SafeRecord, { type Safe } from '~/routes/safe/store/model/safe' +import SafeRecord, { type Safe } from '~/routes/safe/store/models/safe' import { saveSafes, setOwners } from '~/logic/safe/utils' -import { makeOwner, type Owner } from '~/routes/safe/store/model/owner' +import { makeOwner, type Owner } from '~/routes/safe/store/models/owner' import type { Dispatch as ReduxDispatch, GetState } from 'redux' import { type GlobalState } from '~/store/index' import { safesMapSelector } from '~/routes/safeList/store/selectors/index' diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index d0ee469809..a90670b270 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -2,8 +2,8 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { List, Map } from 'immutable' import { type GlobalState } from '~/store/index' -import { makeOwner } from '~/routes/safe/store/model/owner' -import SafeRecord, { type SafeProps } from '~/routes/safe/store/model/safe' +import { makeOwner } from '~/routes/safe/store/models/owner' +import SafeRecord, { type SafeProps } from '~/routes/safe/store/models/safe' import { addSafe } from '~/routes/safe/store/actions/addSafe' import { getOwners, getSafeName } from '~/logic/safe/utils' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' diff --git a/src/routes/safe/store/actions/fetchTransactions.js b/src/routes/safe/store/actions/fetchTransactions.js index 60daf2ffc0..b1aebb3dc2 100644 --- a/src/routes/safe/store/actions/fetchTransactions.js +++ b/src/routes/safe/store/actions/fetchTransactions.js @@ -3,9 +3,9 @@ import { List, Map } from 'immutable' import axios from 'axios' import type { Dispatch as ReduxDispatch } from 'redux' import { type GlobalState } from '~/store/index' -import { makeOwner } from '~/routes/safe/store/model/owner' -import { makeTransaction, type Transaction } from '~/routes/safe/store/model/transaction' -import { makeConfirmation } from '~/routes/safe/store/model/confirmation' +import { makeOwner } from '~/routes/safe/store/models/owner' +import { makeTransaction, type Transaction } from '~/routes/safe/store/models/transaction' +import { makeConfirmation } from '~/routes/safe/store/models/confirmation' import { loadSafeSubjects } from '~/utils/storage/transactions' import { buildTxServiceUrlFrom, type TxServiceType } from '~/logic/safe/safeTxHistory' import { getOwners } from '~/logic/safe/utils' diff --git a/src/routes/safe/store/actions/loadSafesFromStorage.js b/src/routes/safe/store/actions/loadSafesFromStorage.js index 1720b6b69b..1923e12b69 100644 --- a/src/routes/safe/store/actions/loadSafesFromStorage.js +++ b/src/routes/safe/store/actions/loadSafesFromStorage.js @@ -2,7 +2,7 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { type GlobalState } from '~/store/index' import { SAFES_KEY } from '~/logic/safe/utils' -import { type SafeProps } from '~/routes/safe/store/model/safe' +import { type SafeProps } from '~/routes/safe/store/models/safe' import { loadFromStorage } from '~/utils/storage' import { addSafe } from './addSafe' import { buildSafe } from '~/routes/safe/store/reducer/safe' diff --git a/src/routes/safe/store/actions/setTokenActive.js b/src/routes/safe/store/actions/setTokenActive.js deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js new file mode 100644 index 0000000000..d8a57afcf9 --- /dev/null +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -0,0 +1,7 @@ +// @flow +import updateSafe from './updateSafe' +import type { SafeToken, Token } from '~/logic/tokens/store/model' + +const updateActiveTokens = (tokenAddress: string) => { + +} \ No newline at end of file diff --git a/src/routes/safe/store/model/confirmation.js b/src/routes/safe/store/models/confirmation.js similarity index 98% rename from src/routes/safe/store/model/confirmation.js rename to src/routes/safe/store/models/confirmation.js index 46227df440..01786fe520 100644 --- a/src/routes/safe/store/model/confirmation.js +++ b/src/routes/safe/store/models/confirmation.js @@ -1,7 +1,7 @@ // @flow import { Record } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' -import { makeOwner, type Owner } from '~/routes/safe/store/model/owner' +import { makeOwner, type Owner } from '~/routes/safe/store/models/owner' import { type TxServiceType } from '~/logic/safe/safeTxHistory' export type ConfirmationProps = { diff --git a/src/routes/safe/store/model/owner.js b/src/routes/safe/store/models/owner.js similarity index 100% rename from src/routes/safe/store/model/owner.js rename to src/routes/safe/store/models/owner.js diff --git a/src/routes/safe/store/model/safe.js b/src/routes/safe/store/models/safe.js similarity index 71% rename from src/routes/safe/store/model/safe.js rename to src/routes/safe/store/models/safe.js index 032cdd0850..f8b523ca5b 100644 --- a/src/routes/safe/store/model/safe.js +++ b/src/routes/safe/store/models/safe.js @@ -1,7 +1,8 @@ // @flow -import { List, Record, Map } from 'immutable' +import { List, Record } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' -import type { Owner } from '~/routes/safe/store/model/owner' +import type { Owner } from '~/routes/safe/store/models/owner' +import type { SafeToken } from '~/routes/safe/store/models/safeToken' export type SafeProps = { name: string, @@ -9,7 +10,7 @@ export type SafeProps = { threshold: number, ethBalance: string, owners: List, - tokens?: List, + tokens?: List, } const SafeRecord: RecordFactory = Record({ diff --git a/src/routes/safe/store/models/safeToken.js b/src/routes/safe/store/models/safeToken.js new file mode 100644 index 0000000000..8d4b3e05b8 --- /dev/null +++ b/src/routes/safe/store/models/safeToken.js @@ -0,0 +1,17 @@ +// @flow +import { Record } from 'immutable' +import type { RecordFactory, RecordOf } from 'immutable' + +export type SafeTokenProps = { + address: string, + balance: string, +} + +const SafeTokenRecord: RecordFactory = Record({ + address: '', + balance: '0', +}) + +export type SafeToken = RecordOf + +export default SafeTokenRecord diff --git a/src/routes/safe/store/model/transaction.js b/src/routes/safe/store/models/transaction.js similarity index 87% rename from src/routes/safe/store/model/transaction.js rename to src/routes/safe/store/models/transaction.js index 174acd07ef..e2e4e096c9 100644 --- a/src/routes/safe/store/model/transaction.js +++ b/src/routes/safe/store/models/transaction.js @@ -1,7 +1,7 @@ // @flow import { List, Record } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' -import { type Confirmation } from '~/routes/safe/store/model/confirmation' +import { type Confirmation } from '~/routes/safe/store/models/confirmation' export type TransactionProps = { name: string, diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index f5a5a1f81c..4111596121 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -2,8 +2,8 @@ import { Map } from 'immutable' import { handleActions, type ActionType } from 'redux-actions' import { ADD_SAFE, buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' -import SafeRecord, { type Safe, type SafeProps } from '~/routes/safe/store/model/safe' -import { type OwnerProps } from '~/routes/safe/store/model/owner' +import SafeRecord, { type Safe, type SafeProps } from '~/routes/safe/store/models/safe' +import { type OwnerProps } from '~/routes/safe/store/models/owner' import { loadFromStorage } from '~/utils/storage' import { SAFES_KEY } from '~/logic/safe/utils' import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' diff --git a/src/routes/safe/store/reducer/transactions.js b/src/routes/safe/store/reducer/transactions.js index d5aa8a4d99..01dbc6bf3d 100644 --- a/src/routes/safe/store/reducer/transactions.js +++ b/src/routes/safe/store/reducer/transactions.js @@ -2,7 +2,7 @@ import { List, Map } from 'immutable' import { handleActions, type ActionType } from 'redux-actions' import addTransactions, { ADD_TRANSACTIONS } from '~/routes/safe/store/actions/addTransactions' -import { type Transaction } from '~/routes/safe/store/model/transaction' +import { type Transaction } from '~/routes/safe/store/models/transaction' export const TRANSACTIONS_REDUCER_ID = 'transactions' diff --git a/src/routes/safe/store/selectors/index.js b/src/routes/safe/store/selectors/index.js index 6191bb8d84..470915b6fa 100644 --- a/src/routes/safe/store/selectors/index.js +++ b/src/routes/safe/store/selectors/index.js @@ -4,11 +4,11 @@ import { type Match } from 'react-router-dom' import { createSelector, createStructuredSelector, type Selector } from 'reselect' import { type GlobalState } from '~/store/index' import { SAFE_PARAM_ADDRESS } from '~/routes/routes' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { safesMapSelector } from '~/routes/safeList/store/selectors' import { type State as TransactionsState, TRANSACTIONS_REDUCER_ID } from '~/routes/safe/store/reducer/transactions' -import { type Transaction } from '~/routes/safe/store/model/transaction' -import { type Confirmation } from '~/routes/safe/store/model/confirmation' +import { type Transaction } from '~/routes/safe/store/models/transaction' +import { type Confirmation } from '~/routes/safe/store/models/confirmation' export type RouterProps = { match: Match, diff --git a/src/routes/safe/store/test/builder/safe.builder.js b/src/routes/safe/store/test/builder/safe.builder.js index 1a551ba4ec..4e7932bee7 100644 --- a/src/routes/safe/store/test/builder/safe.builder.js +++ b/src/routes/safe/store/test/builder/safe.builder.js @@ -1,5 +1,5 @@ // @flow -import SafeRecord, { type Safe } from '~/routes/safe/store/model/safe' +import SafeRecord, { type Safe } from '~/routes/safe/store/models/safe' import { buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' class SafeBuilder { diff --git a/src/routes/safe/store/test/granted.selector.js b/src/routes/safe/store/test/granted.selector.js index 9db2e965de..e0151d6625 100644 --- a/src/routes/safe/store/test/granted.selector.js +++ b/src/routes/safe/store/test/granted.selector.js @@ -2,7 +2,7 @@ import { Map } from 'immutable' import { type Match } from 'react-router-dom' import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder' import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps' import { getProviderInfo } from '~/logic/wallets/getWeb3' diff --git a/src/routes/safe/store/test/safe.selector.js b/src/routes/safe/store/test/safe.selector.js index f8f8b9313a..ed60e4618d 100644 --- a/src/routes/safe/store/test/safe.selector.js +++ b/src/routes/safe/store/test/safe.selector.js @@ -2,7 +2,7 @@ import { Map } from 'immutable' import { type Match } from 'react-router-dom' import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder' import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps' import { safeSelector } from '../selectors' diff --git a/src/routes/safeList/components/Layout.jsx b/src/routes/safeList/components/Layout.jsx index fda002a0cd..e684accf54 100644 --- a/src/routes/safeList/components/Layout.jsx +++ b/src/routes/safeList/components/Layout.jsx @@ -2,7 +2,7 @@ import { List } from 'immutable' import * as React from 'react' import NoSafe from '~/components/NoSafe' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import SafeTable from '~/routes/safeList/components/SafeTable' type Props = { diff --git a/src/routes/safeList/components/SafeTable.jsx b/src/routes/safeList/components/SafeTable.jsx index 96a9eff7c4..78dc14d216 100644 --- a/src/routes/safeList/components/SafeTable.jsx +++ b/src/routes/safeList/components/SafeTable.jsx @@ -6,7 +6,7 @@ import Link from '~/components/layout/Link' import Table, { TableBody, TableCell, TableHead, TableRow, } from '~/components/layout/Table' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { SAFELIST_ADDRESS } from '~/routes/routes' type Props = { diff --git a/src/routes/safeList/container/index.jsx b/src/routes/safeList/container/index.jsx index 8604c6bdad..6eaf1bb749 100644 --- a/src/routes/safeList/container/index.jsx +++ b/src/routes/safeList/container/index.jsx @@ -3,7 +3,7 @@ import { List } from 'immutable' import * as React from 'react' import { connect } from 'react-redux' import Page from '~/components/layout/Page' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import Layout from '../components/Layout' import selector from './selector' diff --git a/src/routes/safeList/store/selectors/index.js b/src/routes/safeList/store/selectors/index.js index dcea6bc6f1..2a02a79612 100644 --- a/src/routes/safeList/store/selectors/index.js +++ b/src/routes/safeList/store/selectors/index.js @@ -2,9 +2,9 @@ import { List, Map } from 'immutable' import { createSelector, type Selector } from 'reselect' import { type GlobalState } from '~/store/index' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { userAccountSelector } from '~/logic/wallets/store/selectors' -import { type Owner } from '~/routes/safe/store/model/owner' +import { type Owner } from '~/routes/safe/store/models/owner' import { sameAddress } from '~/logic/wallets/ethAddresses' import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' diff --git a/src/routes/safeList/store/test/safes.selector.js b/src/routes/safeList/store/test/safes.selector.js index 2ce17dc839..3a128f71ca 100644 --- a/src/routes/safeList/store/test/safes.selector.js +++ b/src/routes/safeList/store/test/safes.selector.js @@ -1,7 +1,7 @@ // @flow import { List, Map } from 'immutable' import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { getProviderInfo } from '~/logic/wallets/getWeb3' import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder' import { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider' diff --git a/src/test/builder/safe.redux.builder.js b/src/test/builder/safe.redux.builder.js index 35b45ccf63..9839c6b22b 100644 --- a/src/test/builder/safe.redux.builder.js +++ b/src/test/builder/safe.redux.builder.js @@ -1,5 +1,5 @@ // @flow -import SafeRecord, { type Safe } from '~/routes/safe/store/model/safe' +import SafeRecord, { type Safe } from '~/routes/safe/store/models/safe' import addSafe, { buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' import { FIELD_NAME, diff --git a/src/test/safe.redux.load.test.js b/src/test/safe.redux.load.test.js index 7a9dbf8fab..06afb7bb34 100644 --- a/src/test/safe.redux.load.test.js +++ b/src/test/safe.redux.load.test.js @@ -1,12 +1,12 @@ // @flow import { Map, List } from 'immutable' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { aNewStore } from '~/store' import { aMinedSafe } from '~/test/builder/safe.redux.builder' import updateSafe from '~/routes/safe/store/actions/updateSafe' import { loadSafe } from '~/routes/load/container/Load' import { safesMapSelector } from '~/routes/safeList/store/selectors' -import { makeOwner, type Owner } from '~/routes/safe/store/model/owner' +import { makeOwner, type Owner } from '~/routes/safe/store/models/owner' import { getWeb3 } from '~/logic/wallets/getWeb3' import { safesInitialState } from '~/routes/safe/store/reducer/safe' import { setOwners, OWNERS_KEY } from '~/utils/storage' diff --git a/src/test/safe.redux.owners.test.js b/src/test/safe.redux.owners.test.js index 16d1963f1e..73ef32aafd 100644 --- a/src/test/safe.redux.owners.test.js +++ b/src/test/safe.redux.owners.test.js @@ -4,7 +4,7 @@ import { aNewStore } from '~/store' import { getWeb3 } from '~/logic/wallets/getWeb3' import { confirmationsTransactionSelector, safeTransactionsSelector } from '~/routes/safe/store/selectors' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { NAME_PARAM, OWNER_ADDRESS_PARAM, INCREASE_PARAM } from '~/routes/safe/component/AddOwner/AddOwnerForm' diff --git a/src/test/safe.redux.transactions.test.js b/src/test/safe.redux.transactions.test.js index d37b352ffe..1809e816c0 100644 --- a/src/test/safe.redux.transactions.test.js +++ b/src/test/safe.redux.transactions.test.js @@ -1,10 +1,10 @@ // @flow import { List } from 'immutable' import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations' -import { type Safe } from '~/routes/safe/store/model/safe' -import { makeOwner } from '~/routes/safe/store/model/owner' +import { type Safe } from '~/routes/safe/store/models/safe' +import { makeOwner } from '~/routes/safe/store/models/owner' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' -import { makeConfirmation } from '~/routes/safe/store/model/confirmation' +import { makeConfirmation } from '~/routes/safe/store/models/confirmation' import { aNewStore } from '~/store' import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { getSafeFrom } from '~/test/utils/safeHelper' diff --git a/src/test/utils/historyServiceHelper.js b/src/test/utils/historyServiceHelper.js index fb6192dd84..9e47926b09 100644 --- a/src/test/utils/historyServiceHelper.js +++ b/src/test/utils/historyServiceHelper.js @@ -1,7 +1,7 @@ // @flow import { List, Map } from 'immutable' -import { type Confirmation } from '~/routes/safe/store/model/confirmation' -import { type Transaction } from '~/routes/safe/store/model/transaction' +import { type Confirmation } from '~/routes/safe/store/models/confirmation' +import { type Transaction } from '~/routes/safe/store/models/transaction' import { sameAddress } from '~/logic/wallets/ethAddresses' export const testSizeOfSafesWith = (transactions: Map>, size: number) => { diff --git a/src/test/utils/safeHelper.js b/src/test/utils/safeHelper.js index fb094bbc86..077e8a7d1c 100644 --- a/src/test/utils/safeHelper.js +++ b/src/test/utils/safeHelper.js @@ -3,7 +3,7 @@ import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps' import { safeSelector } from '~/routes/safe/store/selectors/index' import { type Match } from 'react-router-dom' import { type GlobalState } from '~/store' -import { type Safe } from '~/routes/safe/store/model/safe' +import { type Safe } from '~/routes/safe/store/models/safe' export const getSafeFrom = (state: GlobalState, safeAddress: string): Safe => { const match: Match = buildMathPropsFrom(safeAddress) From 49f000447c389ca813a57c588e96122d6d927ae7 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 12 Apr 2019 18:41:47 +0400 Subject: [PATCH 22/48] update readme --- readme.md | 14 ++++---- .../safe/component/Balances/Tokens/actions.js | 11 +++---- src/routes/safe/container/actions.js | 2 +- src/routes/safe/store/actions/addSafe.js | 8 ++--- .../safe/store/actions/updateActiveTokens.js | 32 ++++++++++++++++--- src/routes/safe/store/models/safe.js | 2 +- 6 files changed, 45 insertions(+), 24 deletions(-) diff --git a/readme.md b/readme.md index 2101aecc40..3cc96031e1 100644 --- a/readme.md +++ b/readme.md @@ -11,12 +11,14 @@ These instructions will get you a copy of the project up and running on your loc What things you need to install the software and how to install them ``` -npm install truffle // recommended usage of -g flag -npm install ganache-cli // recommended usage of -g flag -npm install flow-type // recommended usage of -g flag +yarn add truffle // recommended usage of -g flag +yarn add ganache-cli // recommended usage of -g flag +yarn add flow-type // recommended usage of -g flag git clone https://github.com/gnosis/safe-contracts.git ``` +We use [yarn](https://yarnpkg.com) in our infrastacture, so we decided to go with yarn in the README + ### Installing A step by step series of examples that tell you have to get a development env running @@ -29,14 +31,14 @@ ganache-cli -b 3 Start the project in the other one ``` cd safe-contracts && truffle compile && truffle migrate && cd .. -npm install -npm start +yarn install +yarn start ``` ## Running the tests ``` -npm test +yarn test ``` diff --git a/src/routes/safe/component/Balances/Tokens/actions.js b/src/routes/safe/component/Balances/Tokens/actions.js index dfede04416..8ed94ed601 100644 --- a/src/routes/safe/component/Balances/Tokens/actions.js +++ b/src/routes/safe/component/Balances/Tokens/actions.js @@ -1,16 +1,13 @@ // @flow -import enableToken from '~/logic/tokens/store/actions/enableToken' -import disableToken from '~/logic/tokens/store/actions/disableToken' import fetchTokens from '~/logic/tokens/store/actions/fetchTokens' +import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens' export type Actions = { - enableToken: Function, - disableToken: Function, - fetchTokens: Function + fetchTokens: Function, + updateActiveTokens: Function } export default { - enableToken, - disableToken, fetchTokens, + updateActiveTokens, } diff --git a/src/routes/safe/container/actions.js b/src/routes/safe/container/actions.js index 5450856a0d..f9808dede6 100644 --- a/src/routes/safe/container/actions.js +++ b/src/routes/safe/container/actions.js @@ -6,7 +6,7 @@ import fetchTokenBalances from '~/routes/safe/store/actions/fetchTokenBalances' export type Actions = { fetchSafe: typeof fetchSafe, loadActiveTokens: typeof loadActiveTokens, - fetchTokenBalances: typeof fetchTokenBalances + fetchTokenBalances: typeof fetchTokenBalances, } export default { diff --git a/src/routes/safe/store/actions/addSafe.js b/src/routes/safe/store/actions/addSafe.js index 23f0d04f41..c6d237eaf9 100644 --- a/src/routes/safe/store/actions/addSafe.js +++ b/src/routes/safe/store/actions/addSafe.js @@ -1,11 +1,11 @@ // @flow import { List } from 'immutable' import { createAction } from 'redux-actions' -import SafeRecord, { type Safe } from '~/routes/safe/store/models/safe' +import type { Dispatch as ReduxDispatch, GetState } from 'redux' +import { type GlobalState } from '~/store' import { saveSafes, setOwners } from '~/logic/safe/utils' +import SafeRecord, { type Safe } from '~/routes/safe/store/models/safe' import { makeOwner, type Owner } from '~/routes/safe/store/models/owner' -import type { Dispatch as ReduxDispatch, GetState } from 'redux' -import { type GlobalState } from '~/store/index' import { safesMapSelector } from '~/routes/safeList/store/selectors/index' export const ADD_SAFE = 'ADD_SAFE' @@ -20,7 +20,7 @@ type ActionReturn = { safe: Safe, } -export const addSafe = createAction( +export const addSafe = createAction( ADD_SAFE, (safe: Safe): ActionReturn => ({ safe, diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index d8a57afcf9..d9d19fad96 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -1,7 +1,29 @@ // @flow -import updateSafe from './updateSafe' -import type { SafeToken, Token } from '~/logic/tokens/store/model' +import { createAction } from 'redux-actions' +import type { Dispatch as ReduxDispatch } from 'redux' +import { type GlobalState } from '~/store' +import type { SafeToken } from '~/routes/safe/store/models/safeToken' +import SafeTokenRecord from '~/routes/safe/store/models/safeToken' -const updateActiveTokens = (tokenAddress: string) => { - -} \ No newline at end of file +export const UPDATE_SAFE_TOKENS = 'UPDATE_SAFE_TOKENS' + +type ActionReturn = { + token: SafeToken, +} + +export const updateTokenAction = createAction( + UPDATE_SAFE_TOKENS, + (token: SafeToken): ActionReturn => ({ + token, + }), +) + +const updateActiveTokens = (safeAddress: string, tokenAddress: string) => async ( + dispatch: ReduxDispatch, +) => { + const token: SafeToken = SafeTokenRecord({ address: tokenAddress }) + + dispatch(updateTokenAction(token)) +} + +export default updateActiveTokens diff --git a/src/routes/safe/store/models/safe.js b/src/routes/safe/store/models/safe.js index f8b523ca5b..32bfdcd6e0 100644 --- a/src/routes/safe/store/models/safe.js +++ b/src/routes/safe/store/models/safe.js @@ -8,9 +8,9 @@ export type SafeProps = { name: string, address: string, threshold: number, - ethBalance: string, owners: List, tokens?: List, + ethBalance?: string, } const SafeRecord: RecordFactory = Record({ From f8d1e6801e78e9ddf22fe48aeded3a261b20176b Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 12 Apr 2019 18:56:09 +0400 Subject: [PATCH 23/48] Update safe tokens wip --- src/routes/safe/store/actions/updateActiveTokens.js | 3 ++- src/routes/safe/store/reducer/safe.js | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index d9d19fad96..e573c489f5 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -14,6 +14,7 @@ type ActionReturn = { export const updateTokenAction = createAction( UPDATE_SAFE_TOKENS, (token: SafeToken): ActionReturn => ({ + safeAddress, token, }), ) @@ -23,7 +24,7 @@ const updateActiveTokens = (safeAddress: string, tokenAddress: string) => async ) => { const token: SafeToken = SafeTokenRecord({ address: tokenAddress }) - dispatch(updateTokenAction(token)) + dispatch(updateTokenAction(safeAddress, token)) } export default updateActiveTokens diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 4111596121..352fad201a 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -7,6 +7,7 @@ import { type OwnerProps } from '~/routes/safe/store/models/owner' import { loadFromStorage } from '~/utils/storage' import { SAFES_KEY } from '~/logic/safe/utils' import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' +import { UPDATE_SAFE_TOKENS } from '~/routes/safe/store/actions/updateActiveTokens' export const SAFE_REDUCER_ID = 'safes' @@ -66,6 +67,7 @@ export default handleActions( return state.set(safe.address, safe) }, + [UPDATE_SAFE_TOKENS]: (state: State, action: ActionType): }, Map(), ) From 413cfa39d4084a684060ed7fd7ab6419919a7bb7 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 12 Apr 2019 18:57:37 +0400 Subject: [PATCH 24/48] reducer fix --- src/logic/tokens/store/model/token.js | 2 +- src/routes/safe/component/Balances/Tokens/actions.js | 2 +- src/routes/safe/store/actions/fetchTokenBalances.js | 4 +--- src/routes/safe/store/reducer/safe.js | 5 ++++- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/logic/tokens/store/model/token.js b/src/logic/tokens/store/model/token.js index ab1c9a9bfe..bbe9ce3f6d 100644 --- a/src/logic/tokens/store/model/token.js +++ b/src/logic/tokens/store/model/token.js @@ -8,7 +8,7 @@ export type TokenProps = { symbol: string, decimals: number, logoUri: string, - balance: string + balance: string, } export const makeToken: RecordFactory = Record({ diff --git a/src/routes/safe/component/Balances/Tokens/actions.js b/src/routes/safe/component/Balances/Tokens/actions.js index 8ed94ed601..cf7ed1937c 100644 --- a/src/routes/safe/component/Balances/Tokens/actions.js +++ b/src/routes/safe/component/Balances/Tokens/actions.js @@ -4,7 +4,7 @@ import updateActiveTokens from '~/routes/safe/store/actions/updateActiveTokens' export type Actions = { fetchTokens: Function, - updateActiveTokens: Function + updateActiveTokens: Function, } export default { diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index 33236adf76..6b41950a70 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -29,9 +29,7 @@ export const calculateBalanceOf = async (tokenAddress: string, safeAddress: stri return new BigNumber(balance).div(10 ** decimals).toString() } -const fetchTokenBalances = (safe: Safe, tokens: List) => async ( - dispatch: ReduxDispatch, -) => { +const fetchTokenBalances = (safe: Safe, tokens: List) => async (dispatch: ReduxDispatch) => { if (!safe || !tokens || !tokens.size) { return } diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 352fad201a..941eb6e343 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -67,7 +67,10 @@ export default handleActions( return state.set(safe.address, safe) }, - [UPDATE_SAFE_TOKENS]: (state: State, action: ActionType): + [UPDATE_SAFE_TOKENS]: (state: State, action: ActionType): State => { + const { safeAddress, token } = action.payload + const tokens = state.getIn([safeAddress, 'tokens']) + } }, Map(), ) From 595731d192f29e8fc491b70c7bc7f359e1d7138b Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 12 Apr 2019 19:15:01 +0400 Subject: [PATCH 25/48] fix displaying active tokens --- .../safe/component/Balances/Tokens/index.jsx | 8 ++----- .../safe/store/actions/updateActiveTokens.js | 2 +- src/routes/safe/store/reducer/safe.js | 22 +++++++++++++++---- 3 files changed, 21 insertions(+), 11 deletions(-) diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index 175e037db8..150721994e 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -67,13 +67,9 @@ class Tokens extends React.Component { onSwitch = (token: Token) => (e: SyntheticInputEvent) => { const { checked } = e.target - const { safeAddress, enableToken, disableToken } = this.props + const { safeAddress, updateActiveTokens } = this.props - if (checked) { - enableToken(safeAddress, token) - } else { - disableToken(safeAddress, token) - } + updateActiveTokens(safeAddress, token.address) } setImageToPlaceholder = (e) => { diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index e573c489f5..83b71dcf37 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -13,7 +13,7 @@ type ActionReturn = { export const updateTokenAction = createAction( UPDATE_SAFE_TOKENS, - (token: SafeToken): ActionReturn => ({ + (safeAddress: string, token: SafeToken): ActionReturn => ({ safeAddress, token, }), diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 941eb6e343..557a16401f 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -1,9 +1,10 @@ // @flow -import { Map } from 'immutable' +import { Map, List } from 'immutable' import { handleActions, type ActionType } from 'redux-actions' import { ADD_SAFE, buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' import SafeRecord, { type Safe, type SafeProps } from '~/routes/safe/store/models/safe' import { type OwnerProps } from '~/routes/safe/store/models/owner' +import type { SafeToken } from '~/routes/safe/store/models/safeToken' import { loadFromStorage } from '~/utils/storage' import { SAFES_KEY } from '~/logic/safe/utils' import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' @@ -68,9 +69,22 @@ export default handleActions( return state.set(safe.address, safe) }, [UPDATE_SAFE_TOKENS]: (state: State, action: ActionType): State => { - const { safeAddress, token } = action.payload - const tokens = state.getIn([safeAddress, 'tokens']) - } + const { safeAddress, token: updatedToken } = action.payload + + const tokens: List = state.getIn([safeAddress, 'tokens']) + console.log(tokens) + const index = tokens.findIndex(token => token.address === updatedToken.address) + console.log('called') + let newState + if (index !== -1) { + newState = state.setIn([safeAddress, 'tokens'], tokens.delete(index)) + } else { + newState = state.setIn([safeAddress, 'tokens'], tokens.push(updatedToken)) + } + console.log(newState.toJS()) + + return newState + }, }, Map(), ) From 910382c5f2e48da88c706e12bf0e6ca9a6b43879 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Fri, 12 Apr 2019 20:06:34 +0400 Subject: [PATCH 26/48] Active tokens WIP, needs debugging: tokens get washed after safe update --- src/routes/safe/container/index.jsx | 4 ++-- src/routes/safe/store/actions/fetchSafe.js | 13 +++++++++---- .../safe/store/actions/fetchTokenBalances.js | 14 ++++---------- src/routes/safe/store/reducer/safe.js | 2 +- 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index 618f39ee7a..895fa530ff 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -20,7 +20,7 @@ class SafeView extends React.Component { } = this.props fetchSafe(safeUrl) - loadActiveTokens(safeUrl) + // loadActiveTokens(safeUrl) fetchTokenBalances(safe, activeTokens) this.intervalId = setInterval(() => { @@ -38,7 +38,7 @@ class SafeView extends React.Component { safeUrl, activeTokens, fetchSafe, fetchTokenBalances, safe, } = this.props - fetchSafe(safeUrl) + fetchSafe(safeUrl, true) fetchTokenBalances(safe, activeTokens) } diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index a90670b270..29aca03bbb 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -8,6 +8,7 @@ import { addSafe } from '~/routes/safe/store/actions/addSafe' import { getOwners, getSafeName } from '~/logic/safe/utils' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3' +import updateSafe from '~/routes/safe/store/actions/updateSafe' const buildOwnersFrom = ( safeOwners: string[], @@ -37,12 +38,16 @@ export const buildSafe = async (safeAddress: string, safeName: string) => { return SafeRecord(safe) } -export default (safeAddress: string) => async (dispatch: ReduxDispatch) => { +export default (safeAddress: string, update: boolean = false) => async (dispatch: ReduxDispatch) => { try { const safeName = (await getSafeName(safeAddress)) || 'LOADED SAFE' - const safeRecord = await buildSafe(safeAddress, safeName) - - return dispatch(addSafe(safeRecord)) + const safe = await buildSafe(safeAddress, safeName) + console.log(safe.toJS()) + if (update) { + dispatch(updateSafe(safe)) + } else { + dispatch(addSafe(safe)) + } } catch (err) { // eslint-disable-next-line console.error('Error while updating safe information: ', err) diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index 6b41950a70..5c56f64359 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -1,21 +1,15 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' -import { Map, List } from 'immutable' +import { List } from 'immutable' import { BigNumber } from 'bignumber.js' import { type GlobalState } from '~/store/index' import { type Token } from '~/logic/tokens/store/model/token' -import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' -import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3' +import SafeTokenRecord from '~/routes/safe/store/models/safeToken' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' -import type { Safe } from '~/routes/safe/store/model/safe' +import type { Safe } from '~/routes/safe/store/models/safe' import updateSafe from './updateSafe' export const calculateBalanceOf = async (tokenAddress: string, safeAddress: string, decimals: number = 18) => { - if (tokenAddress === ETH_ADDRESS) { - const ethBalance = await getBalanceInEtherOf(safeAddress) - return ethBalance - } - const erc20Token = await getStandardTokenContract() let balance = 0 @@ -36,7 +30,7 @@ const fetchTokenBalances = (safe: Safe, tokens: List) => async (dispatch: try { const withBalances = await Promise.all( - tokens.map(async token => ({ + tokens.map(async token => SafeTokenRecord({ address: token.address, balance: await calculateBalanceOf(token.address, safe.address, token.decimals), })), diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 557a16401f..d24b76ca81 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -61,7 +61,7 @@ export default handleActions( const safe = action.payload const safeAddress = safe.address - return state.mergeIn(safeAddress, safe) + return state.mergeIn([safeAddress], safe) }, [ADD_SAFE]: (state: State, action: ActionType): State => { const { safe }: { safe: Safe } = action.payload From f4860687788b6e385e4f1d9c334df9f8782cf564 Mon Sep 17 00:00:00 2001 From: mmv Date: Mon, 15 Apr 2019 13:14:18 +0400 Subject: [PATCH 27/48] rewrite fetchSafe function to support updates --- package.json | 6 +- src/routes/load/container/Load.jsx | 6 +- src/routes/safe/store/actions/fetchSafe.js | 14 +- src/routes/safe/store/reducer/safe.js | 6 +- yarn.lock | 1085 ++++++++++---------- 5 files changed, 585 insertions(+), 532 deletions(-) diff --git a/package.json b/package.json index 52f5e2e28b..b8eb17d42e 100644 --- a/package.json +++ b/package.json @@ -80,9 +80,9 @@ "react": "^16.8.6", "react-dom": "^16.8.6", "react-final-form": "^4.1.0", - "react-hot-loader": "4.8.3", + "react-hot-loader": "4.8.4", "react-infinite-scroll-component": "^4.5.2", - "react-redux": "7.0.1", + "react-redux": "7.0.2", "react-router-dom": "^4.3.1", "recompose": "^0.30.0", "redux": "^4.0.1", @@ -142,7 +142,7 @@ "ethereumjs-abi": "^0.6.7", "extract-text-webpack-plugin": "^4.0.0-beta.0", "file-loader": "^3.0.1", - "flow-bin": "0.96.0", + "flow-bin": "0.97.0", "fs-extra": "^7.0.1", "html-loader": "^0.5.5", "html-webpack-plugin": "^3.0.4", diff --git a/src/routes/load/container/Load.jsx b/src/routes/load/container/Load.jsx index 13ba0012ca..a33e536f8b 100644 --- a/src/routes/load/container/Load.jsx +++ b/src/routes/load/container/Load.jsx @@ -15,12 +15,12 @@ import { FIELD_LOAD_NAME, FIELD_LOAD_ADDRESS } from '../components/fields' type Props = SelectorProps & Actions export const loadSafe = async (safeName: string, safeAddress: string, addSafe: Function) => { - const safeRecord = await buildSafe(safeAddress, safeName) + const safeProps = await buildSafe(safeAddress, safeName) - await addSafe(safeRecord) + await addSafe(safeProps) const storedSafes = (await loadFromStorage(SAFES_KEY)) || {} - storedSafes[safeAddress] = safeRecord.toJSON() + storedSafes[safeAddress] = safeProps saveSafes(storedSafes) } diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 29aca03bbb..3fbfe6ebe6 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -3,13 +3,15 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { List, Map } from 'immutable' import { type GlobalState } from '~/store/index' import { makeOwner } from '~/routes/safe/store/models/owner' -import SafeRecord, { type SafeProps } from '~/routes/safe/store/models/safe' +import { type SafeProps } from '~/routes/safe/store/models/safe' import { addSafe } from '~/routes/safe/store/actions/addSafe' import { getOwners, getSafeName } from '~/logic/safe/utils' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' import { getWeb3, getBalanceInEtherOf } from '~/logic/wallets/getWeb3' import updateSafe from '~/routes/safe/store/actions/updateSafe' +// eslint-disable-next-line +// eslint-disable-next-line const buildOwnersFrom = ( safeOwners: string[], storedOwners: Map, // eslint-disable-next-line @@ -35,18 +37,18 @@ export const buildSafe = async (safeAddress: string, safeName: string) => { ethBalance, } - return SafeRecord(safe) + return safe } export default (safeAddress: string, update: boolean = false) => async (dispatch: ReduxDispatch) => { try { const safeName = (await getSafeName(safeAddress)) || 'LOADED SAFE' - const safe = await buildSafe(safeAddress, safeName) - console.log(safe.toJS()) + const safeProps: SafeProps = await buildSafe(safeAddress, safeName) + if (update) { - dispatch(updateSafe(safe)) + dispatch(updateSafe(safeProps)) } else { - dispatch(addSafe(safe)) + dispatch(addSafe(safeProps)) } } catch (err) { // eslint-disable-next-line diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index d24b76ca81..125c8d1124 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -66,7 +66,11 @@ export default handleActions( [ADD_SAFE]: (state: State, action: ActionType): State => { const { safe }: { safe: Safe } = action.payload - return state.set(safe.address, safe) + // if you add a new safe it needs to be set as a record + // in case of update it shouldn't, because a record would be initialized + // with initial props and it would overwrite existing ones + + return state.set(safe.address, SafeRecord(safe)) }, [UPDATE_SAFE_TOKENS]: (state: State, action: ActionType): State => { const { safeAddress, token: updatedToken } = action.payload diff --git a/yarn.lock b/yarn.lock index 0dc4a1809a..e80baea973 100644 --- a/yarn.lock +++ b/yarn.lock @@ -46,7 +46,7 @@ semver "^5.4.1" source-map "^0.5.0" -"@babel/core@^7.1.0", "@babel/core@^7.1.6", "@babel/core@^7.4.0": +"@babel/core@^7.1.0", "@babel/core@^7.4.0", "@babel/core@^7.4.3": version "7.4.3" resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.4.3.tgz#198d6d3af4567be3989550d97e068de94503074f" integrity sha512-oDpASqKFlbspQfzAE7yaeTmdljSH2ADIvBlb0RwbStltTuWa0+7CCI1fYVINNv9saHPa1W7oaKeuNuKj+RQCvA== @@ -990,7 +990,7 @@ js-levenshtein "^1.1.3" semver "^5.3.0" -"@babel/preset-env@^7.1.6", "@babel/preset-env@^7.4.1", "@babel/preset-env@^7.4.2": +"@babel/preset-env@^7.4.1", "@babel/preset-env@^7.4.2", "@babel/preset-env@^7.4.3": version "7.4.3" resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.4.3.tgz#e71e16e123dc0fbf65a52cbcbcefd072fbd02880" integrity sha512-FYbZdV12yHdJU5Z70cEg0f6lvtpZ8jFSDakTm7WXeJbLXh4R0ztGEu/SW7G1nJ2ZvKwDhz8YrbA84eYyprmGqw== @@ -1117,7 +1117,7 @@ globals "^11.1.0" lodash "^4.17.11" -"@babel/types@^7.0.0", "@babel/types@^7.1.6", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.4.0": +"@babel/types@^7.0.0", "@babel/types@^7.2.0", "@babel/types@^7.2.2", "@babel/types@^7.3.0", "@babel/types@^7.4.0": version "7.4.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.4.0.tgz#670724f77d24cce6cc7d8cf64599d511d164894c" integrity sha512-aPvkXyU2SPOnztlgo8n9cEiXW755mgyvueUPcpStqdzoSPm0fjO0vQBjLkt3JKJW7ufikfcnMTTPsN1xaTsBPA== @@ -1588,14 +1588,14 @@ uuid "^3.2.1" "@storybook/addon-actions@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.0.6.tgz#78cf9c05b8b6cde1d5d46961ffb95d92be16bf46" - integrity sha512-Qbenp6Dv8uphDKsIemtW8bSu3PNYIDSB5av7bW9GieYex8QL6ntv7dja0DaD6NmIfjOZdO0Q0U3Nc9CAgHGOBQ== - dependencies: - "@storybook/addons" "5.0.6" - "@storybook/components" "5.0.6" - "@storybook/core-events" "5.0.6" - "@storybook/theming" "5.0.6" + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.0.8.tgz#85b74bd7c672d4e668830c7e7bc820f7c35daf2c" + integrity sha512-MwIYzJGi1Pok9CkTznqABT+rGLBDURixKgkzGEphMLDWXQSOIg8AdLvlr8EC1U+pDyFqgG9fGeDgOa8W5bVdHQ== + dependencies: + "@storybook/addons" "5.0.8" + "@storybook/components" "5.0.8" + "@storybook/core-events" "5.0.8" + "@storybook/theming" "5.0.8" core-js "^2.6.5" fast-deep-equal "^2.0.1" global "^4.3.2" @@ -1608,14 +1608,14 @@ uuid "^3.3.2" "@storybook/addon-knobs@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.0.6.tgz#f291d7e18d30ef65284dc424d1b7527f114183b6" - integrity sha512-Qgj84wGuBSxY0As127OVmd6bz6JLWsYteqjhlSu9vRfQrSszbQSEJb9ikOhE0I7g+hS0u3zWU+HDb9EgN/87SA== - dependencies: - "@storybook/addons" "5.0.6" - "@storybook/components" "5.0.6" - "@storybook/core-events" "5.0.6" - "@storybook/theming" "5.0.6" + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.0.8.tgz#6d20e29e409839b6bbfcb7a6063dae683f88b619" + integrity sha512-fW6Zwb3rwfOvXXuEwrgAEUpISRINMmTRzkwI6cMclvwoG3S9T+VdU1/WFttwAVmrJRbjb3cNOyFldXNDTWenlA== + dependencies: + "@storybook/addons" "5.0.8" + "@storybook/components" "5.0.8" + "@storybook/core-events" "5.0.8" + "@storybook/theming" "5.0.8" copy-to-clipboard "^3.0.8" core-js "^2.6.5" escape-html "^1.0.3" @@ -1630,56 +1630,56 @@ util-deprecate "^1.0.2" "@storybook/addon-links@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-5.0.6.tgz#8c6dae2d31df8dc0f1988b6f3fd0ffaf7ad0e482" - integrity sha512-cOlW+T10u+KBWRD3i+vJBgta2P/0V69vdAbGqK56j5Okr3kqS3ZJsM5avNhjmysvuQIlw0mAMC2Q9SK3Kn1P2Q== + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-5.0.8.tgz#2ab42a45641180677561ff8cb069c4bd0877b16a" + integrity sha512-KwEIfFgBNcxpTAu+o0L8DV4vg7HP740Fm5RSFH3APGCE8MrmRL+hVcMEcp9KmFf6FMD/V7y5nku4jhlbGjAi1w== dependencies: - "@storybook/addons" "5.0.6" - "@storybook/core-events" "5.0.6" + "@storybook/addons" "5.0.8" + "@storybook/core-events" "5.0.8" common-tags "^1.8.0" core-js "^2.6.5" global "^4.3.2" prop-types "^15.6.2" qs "^6.5.2" -"@storybook/addons@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.0.6.tgz#3ecb7fd8421e6557b1abc71ebede905e8decfebc" - integrity sha512-VZFYnckWRErkOTZG3a3y7jvnPUjOsTCbWSxvJVMM5SfPzlZbcUz16wJDCJ/pQWI0VzhHFEAVfae9DcuiF031Ow== +"@storybook/addons@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.0.8.tgz#9bca24ab8e95a36dc91e4e2855449e751702cdfb" + integrity sha512-Tl/ntlBt+KfAEaLyzfFTJsqmawtmKvrJDy8kqNM1oIfsOxig25T9eqU8RfWgK99bMdsbhA99P+cplk6LuVY1Ww== dependencies: - "@storybook/channels" "5.0.6" - "@storybook/client-logger" "5.0.6" + "@storybook/channels" "5.0.8" + "@storybook/client-logger" "5.0.8" core-js "^2.6.5" global "^4.3.2" util-deprecate "^1.0.2" -"@storybook/channel-postmessage@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.0.6.tgz#a774cd548d9f229456a56915754db7fd9da7429a" - integrity sha512-62gAChPQSnmmdcsCgeU+g/tSqOHLX/nNzmKEsP20v57NqhFwTNfKLMTbQxrl8ttigTafxQZZjQA4EecN0eu16g== +"@storybook/channel-postmessage@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.0.8.tgz#b68ea103d4401abdef540bb21b20f54b4665bba7" + integrity sha512-Gl7+bshczSTHpQa4FzL19+xyzOK9vTUh2pGQwBEp2zZXVGD46vLyUKsnYCqm+/vrWg/1mx/I1GzqAmqkhH2CuA== dependencies: - "@storybook/channels" "5.0.6" - "@storybook/client-logger" "5.0.6" + "@storybook/channels" "5.0.8" + "@storybook/client-logger" "5.0.8" core-js "^2.6.5" global "^4.3.2" telejson "^2.1.0" -"@storybook/channels@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.0.6.tgz#bf056194d633cae873875d6e238c1abadb301dbe" - integrity sha512-3Q3uKP5R8q8Q0w6us0f/rlS864ySwl/dN1MZsRg1EaFU+YCy09Mx+3IQDF3FlxseXaQ6UtHcBnMcST4j6FO0ew== +"@storybook/channels@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.0.8.tgz#d44517cd6f19f87ccab5e899bd9b515a4395c97c" + integrity sha512-t0PVow9xxQMK04ltp1LtrACG5f63vUM/THtdtoucxepirpfTGr+9B2SP791ZDtpARp5sFqAB7CGN8zDGfZF7lQ== dependencies: core-js "^2.6.5" -"@storybook/client-api@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.0.6.tgz#a1622c46abaf1417fcfbbfab4fa8f032b564cd00" - integrity sha512-GtqHP5JrWmPOs9VcUdcLi40WLFKw8PdOnM+zMajm+vucyAr/wkc81VtnPjRAOVlZ4TdzGmsSWgFUOewniXlw6g== +"@storybook/client-api@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.0.8.tgz#42d058007835b6fc941b133542bcd232fd816d4d" + integrity sha512-djBVje/ZMkwdIzrZGtkDHrMy6HHDOrQSL0ppk2YgYaB40IF5KPhjnoPH09sOFHy9uW9d3chWQlkAESIjPQwpCA== dependencies: - "@storybook/addons" "5.0.6" - "@storybook/client-logger" "5.0.6" - "@storybook/core-events" "5.0.6" - "@storybook/router" "5.0.6" + "@storybook/addons" "5.0.8" + "@storybook/client-logger" "5.0.8" + "@storybook/core-events" "5.0.8" + "@storybook/router" "5.0.8" common-tags "^1.8.0" core-js "^2.6.5" eventemitter3 "^3.1.0" @@ -1691,10 +1691,10 @@ memoizerific "^1.11.3" qs "^6.5.2" -"@storybook/client-logger@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.0.6.tgz#d183534ccc8c864039113dcc33407e7f1f5d7594" - integrity sha512-WYF3E2A5UzAPcCVs3A2xqbdrDfGi/g6zByDZYnmgW46U7NkvmGRPLGMt/lTXBQNwB3LVNlg7SRQO/AJwgqIJ0Q== +"@storybook/client-logger@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.0.8.tgz#d37ee57f7d6ec207f60c3f87163d564427f5b82c" + integrity sha512-PKmSx6M7WNHwUUh4R9OluKWZfkHN7PztaRWrp9dvNy9rOd/c7vVWK1ekGRaMR06MHkszZ5boPerV8c9xEydEfg== dependencies: core-js "^2.6.5" @@ -1707,16 +1707,16 @@ glamorous "^4.12.1" prop-types "^15.6.1" -"@storybook/components@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.0.6.tgz#de77af3443f771d94a692edb719bc0d8c0149daf" - integrity sha512-C++A39n9O09PU2e4Y8x/zbZ+Tf0t/mfPw83Mkh8d8OHS4rHdVKEhq6QC8oDuqT9YBNhJOohtg5d9n+7s8sqZyQ== - dependencies: - "@storybook/addons" "5.0.6" - "@storybook/client-logger" "5.0.6" - "@storybook/core-events" "5.0.6" - "@storybook/router" "5.0.6" - "@storybook/theming" "5.0.6" +"@storybook/components@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.0.8.tgz#9dc83b2cd13bd37ab17ebf804ec13c922018195e" + integrity sha512-aIU/lySNIei4YljCd6uYcMgg1pRuQ08hPzk3aJ8OHODAOXUxWCN8STyPwB6h2q01HFZ0rhlEDeoybszFr7bORQ== + dependencies: + "@storybook/addons" "5.0.8" + "@storybook/client-logger" "5.0.8" + "@storybook/core-events" "5.0.8" + "@storybook/router" "5.0.8" + "@storybook/theming" "5.0.8" core-js "^2.6.5" global "^4.3.2" immer "^1.12.0" @@ -1738,32 +1738,32 @@ recompose "^0.30.0" render-fragment "^0.1.1" -"@storybook/core-events@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.0.6.tgz#ead92a1e463d53fa57151b62192e74f8e3f45b3b" - integrity sha512-OpNHSAxgaok1JYbF5AOML23rIyIyTxir7Ou/s4McN2k0Z2huLaIBA3aeu7vSMygOvN+q6VGMc4uC7f6WQ6kwUg== +"@storybook/core-events@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.0.8.tgz#9d941dd748590185d3a2e0a4aeb1365be1778c62" + integrity sha512-3sTAtkebvQOuu5OxHHPK3xGP1RBp65Nls3t3l3KAZEqQ5vQ0w30lbe0gEWMqLz4MMCy84E+Xz297G3a74eQ/xA== dependencies: core-js "^2.6.5" -"@storybook/core@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.0.6.tgz#142b4d98888dce6e4e6d1b235d09777954cee2de" - integrity sha512-Uzl0CzM2Th24T47TLImis0sFiCzDy2tExDt24p/ojMy2HYA/aT+kTGUN5OMXBZTKDbRFQgv0P2vzHCWyS//Zmw== +"@storybook/core@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.0.8.tgz#59de7c0ffdad4eb79054ddf9c5da3108a35f993d" + integrity sha512-tUdRnsdvcuoNF2lAB4e0mztcX4iunHFD+30QcAiTY9ShNBKvL73wLxVhzP+gfY0XqA9XnUb4t1XM/8t7VzOpCQ== dependencies: "@babel/plugin-proposal-class-properties" "^7.3.0" "@babel/plugin-proposal-object-rest-spread" "^7.3.2" "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-transform-react-constant-elements" "^7.2.0" "@babel/preset-env" "^7.4.1" - "@storybook/addons" "5.0.6" - "@storybook/channel-postmessage" "5.0.6" - "@storybook/client-api" "5.0.6" - "@storybook/client-logger" "5.0.6" - "@storybook/core-events" "5.0.6" - "@storybook/node-logger" "5.0.6" - "@storybook/router" "5.0.6" - "@storybook/theming" "5.0.6" - "@storybook/ui" "5.0.6" + "@storybook/addons" "5.0.8" + "@storybook/channel-postmessage" "5.0.8" + "@storybook/client-api" "5.0.8" + "@storybook/client-logger" "5.0.8" + "@storybook/core-events" "5.0.8" + "@storybook/node-logger" "5.0.8" + "@storybook/router" "5.0.8" + "@storybook/theming" "5.0.8" + "@storybook/ui" "5.0.8" airbnb-js-shims "^1 || ^2" autoprefixer "^9.4.7" babel-plugin-add-react-displayname "^0.0.5" @@ -1819,10 +1819,10 @@ webpack-dev-middleware "^3.5.1" webpack-hot-middleware "^2.24.3" -"@storybook/node-logger@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.0.6.tgz#80044c2b9d278c9c191ee5bc9e15e93247146b3a" - integrity sha512-8KKhhsftxjpew1VOXHZDudylzF7y3SUHxvChykK3V4yjZlbtR5a5U8EGE5Bx5HW0aoInFk08uYTMqsHDRvccfw== +"@storybook/node-logger@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.0.8.tgz#712239bc3eb5b9f2940232a3c75577db596c01be" + integrity sha512-10CNULeWdQzAY69S3hV3Wc/A7QnYcMnxB5ISP1TEr83reFWFGQuDM1EJ3/Qe9RtdgAHndH2uz2fN37kX1M3ZAw== dependencies: chalk "^2.4.2" core-js "^2.6.5" @@ -1831,16 +1831,16 @@ regenerator-runtime "^0.12.1" "@storybook/react@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.0.6.tgz#b51c62f82b20536b0550a96e1c61cd9ec1457182" - integrity sha512-ldjlFeedgCFLduN4s96GZ8S97Y4us/a5JGlUS3isluzbw7iChnmghi3jd9XaG7QzMe8jXpbIErXZ4HtF8nAEaw== + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.0.8.tgz#9b73010e3f84c40dd3fcc91a30c32604a31051d3" + integrity sha512-4rVfLDoCvg/1F2Wfv9PktVStng3v4IbELwkQ0lH9qwOQJBy66UcXoGzbXfvn+sLOnbNHftT4SdPkdmL8HuoUnQ== dependencies: "@babel/plugin-transform-react-constant-elements" "^7.2.0" "@babel/preset-flow" "^7.0.0" "@babel/preset-react" "^7.0.0" - "@storybook/core" "5.0.6" - "@storybook/node-logger" "5.0.6" - "@storybook/theming" "5.0.6" + "@storybook/core" "5.0.8" + "@storybook/node-logger" "5.0.8" + "@storybook/theming" "5.0.8" "@svgr/webpack" "^4.0.3" babel-plugin-named-asset-import "^0.3.0" babel-plugin-react-docgen "^2.0.2" @@ -1856,26 +1856,26 @@ semver "^5.6.0" webpack "^4.29.0" -"@storybook/router@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.0.6.tgz#1856aaa2771145a7ace804d893fa92bc73418039" - integrity sha512-mK+chRfpoINrDEWXQ7P2Gff179hl3q0bPfDo4DwbGO0wf0yOKDGXf+S/vlIF29+5weyhrMe4Si9PALq4ibsl6Q== +"@storybook/router@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.0.8.tgz#fcbbe29a65c7c65aebe25bc79eeb9f573cc7f3a8" + integrity sha512-6A9OGFkmrSQr7ZvemiibbVj4eULtkT6prEkbOi6aPMZmDq+gTT17jR1B6ekfciQmQoOPfmlpZsZkqlxejXxqoA== dependencies: "@reach/router" "^1.2.1" - "@storybook/theming" "5.0.6" + "@storybook/theming" "5.0.8" core-js "^2.6.5" global "^4.3.2" memoizerific "^1.11.3" qs "^6.5.2" -"@storybook/theming@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.0.6.tgz#5827d780eb45a031ad27cd19bd87cd70a818546f" - integrity sha512-Kz0/ujHknhan7DHApLIdSzfLAMbpo7AEKmi+R060ZV0ImGmAP9O7Ytqws7u1O25fgA4AgCDyeDpT4N9i83la+w== +"@storybook/theming@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.0.8.tgz#b91c45599155f636fd5e24b04cb0c8fa2acf5187" + integrity sha512-0GLGynbP2VSUMQomF+VZD165zQNCrDdy0VXcndWfS+FrTFwaUeCl0oRS6resJGehCVO5KqTviEx7uBVURW3nlA== dependencies: "@emotion/core" "^10.0.7" "@emotion/styled" "^10.0.7" - "@storybook/client-logger" "5.0.6" + "@storybook/client-logger" "5.0.8" common-tags "^1.8.0" core-js "^2.6.5" deep-object-diff "^1.1.0" @@ -1888,17 +1888,17 @@ prop-types "^15.6.2" react-inspector "^2.3.1" -"@storybook/ui@5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.0.6.tgz#954b1284d0a21e8c0154e56c2f76e58e66fe09fe" - integrity sha512-XmyJokPE7gWKmZXAVXnlRZgU3vQKyUMt6KJrg8Q6GqbvyaPN6p5OlLVDZMgPA/5DpCGfMUEp3BMbJpl9SI97tA== - dependencies: - "@storybook/addons" "5.0.6" - "@storybook/client-logger" "5.0.6" - "@storybook/components" "5.0.6" - "@storybook/core-events" "5.0.6" - "@storybook/router" "5.0.6" - "@storybook/theming" "5.0.6" +"@storybook/ui@5.0.8": + version "5.0.8" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.0.8.tgz#2c3dd151a22c9eb4e78d28af3910b7533b624742" + integrity sha512-Q9bY9zbxn4oDQ2eT8AxUj0O6eDVWHOZYEuTuijFSgJ/5bUXZmhB6aMU67QvdYJlAn07k7zcR5k09Q4a4kqaKXw== + dependencies: + "@storybook/addons" "5.0.8" + "@storybook/client-logger" "5.0.8" + "@storybook/components" "5.0.8" + "@storybook/core-events" "5.0.8" + "@storybook/router" "5.0.8" + "@storybook/theming" "5.0.8" core-js "^2.6.5" fast-deep-equal "^2.0.1" fuzzy-search "^3.0.1" @@ -1929,115 +1929,115 @@ telejson "^2.1.1" util-deprecate "^1.0.2" -"@svgr/babel-plugin-add-jsx-attribute@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.0.0.tgz#5acf239cd2747b1a36ec7e708de05d914cb9b948" - integrity sha512-PDvHV2WhSGCSExp+eIMEKxYd1Q0SBvXLb4gAOXbdh0dswHFFgXWzxGjCmx5aln4qGrhkuN81khzYzR/44DYaMA== +"@svgr/babel-plugin-add-jsx-attribute@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-4.2.0.tgz#dadcb6218503532d6884b210e7f3c502caaa44b1" + integrity sha512-j7KnilGyZzYr/jhcrSYS3FGWMZVaqyCG0vzMCwzvei0coIkczuYMcniK07nI0aHJINciujjH11T72ICW5eL5Ig== -"@svgr/babel-plugin-remove-jsx-attribute@^4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-4.0.3.tgz#32564b5c4d761b51e34492b6a4894196c0f75803" - integrity sha512-fpG7AzzJxz1tc8ITYS1jCAt1cq4ydK2R+sx//BMTJgvOjfk91M5GiqFolP8aYTzLcum92IGNAVFS3zEcucOQEA== +"@svgr/babel-plugin-remove-jsx-attribute@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-4.2.0.tgz#297550b9a8c0c7337bea12bdfc8a80bb66f85abc" + integrity sha512-3XHLtJ+HbRCH4n28S7y/yZoEQnRpl0tvTZQsHqvaeNXPra+6vE5tbRliH3ox1yZYPCxrlqaJT/Mg+75GpDKlvQ== -"@svgr/babel-plugin-remove-jsx-empty-expression@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-4.0.0.tgz#0b59338c00671cf8137eb823bd84a3efac686502" - integrity sha512-nBGVl6LzXTdk1c6w3rMWcjq3mYGz+syWc5b3CdqAiEeY/nswYDoW/cnGUKKC8ofD6/LaG+G/IUnfv3jKoHz43A== +"@svgr/babel-plugin-remove-jsx-empty-expression@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-4.2.0.tgz#c196302f3e68eab6a05e98af9ca8570bc13131c7" + integrity sha512-yTr2iLdf6oEuUE9MsRdvt0NmdpMBAkgK8Bjhl6epb+eQWk6abBaX3d65UZ3E3FWaOwePyUgNyNCMVG61gGCQ7w== -"@svgr/babel-plugin-replace-jsx-attribute-value@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.0.0.tgz#91785643540c2300f3d89e515b37af9b5ce4e695" - integrity sha512-ejQqpTfORy6TT5w1x/2IQkscgfbtNFjitcFDu63GRz7qfhVTYhMdiJvJ1+Aw9hmv9bO4tXThGQDr1IF5lIvgew== +"@svgr/babel-plugin-replace-jsx-attribute-value@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-4.2.0.tgz#310ec0775de808a6a2e4fd4268c245fd734c1165" + integrity sha512-U9m870Kqm0ko8beHawRXLGLvSi/ZMrl89gJ5BNcT452fAjtF2p4uRzXkdzvGJJJYBgx7BmqlDjBN/eCp5AAX2w== -"@svgr/babel-plugin-svg-dynamic-title@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.0.0.tgz#eb8d50b80ba0a26f9b27c7268e2a803d90f1bc9e" - integrity sha512-OE6GT9WRKWqd0Dk6NJ5TYXTF5OxAyn74+c/D+gTLbCXnK2A0luEXuwMbe5zR5Px4A/jow2OeEBboTENl4vtuQg== +"@svgr/babel-plugin-svg-dynamic-title@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-4.2.0.tgz#43f0f689a5347a894160eb51b39a109889a4df20" + integrity sha512-gH2qItapwCUp6CCqbxvzBbc4dh4OyxdYKsW3EOkYexr0XUmQL0ScbdNh6DexkZ01T+sdClniIbnCObsXcnx3sQ== -"@svgr/babel-plugin-svg-em-dimensions@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-4.0.0.tgz#0de3972c46ff1960bed765646037a3a7f9e1da3d" - integrity sha512-QeDRGHXfjYEBTXxV0TsjWmepsL9Up5BOOlMFD557x2JrSiVGUn2myNxHIrHiVW0+nnWnaDcrkjg/jUvbJ5nKCg== +"@svgr/babel-plugin-svg-em-dimensions@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-4.2.0.tgz#9a94791c9a288108d20a9d2cc64cac820f141391" + integrity sha512-C0Uy+BHolCHGOZ8Dnr1zXy/KgpBOkEUYY9kI/HseHVPeMbluaX3CijJr7D4C5uR8zrc1T64nnq/k63ydQuGt4w== -"@svgr/babel-plugin-transform-react-native-svg@^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-4.0.0.tgz#5e8ecc2a9870ae05fb1e553b1fe9c6b5853a1c66" - integrity sha512-c6eE6ovs14k6dmHKoy26h7iRFhjWNnwYVrDWIPfouVm/gcLIeMw/ME4i91O5LEfaDHs6kTRCcVpbAVbNULZOtw== +"@svgr/babel-plugin-transform-react-native-svg@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-4.2.0.tgz#151487322843359a1ca86b21a3815fd21a88b717" + integrity sha512-7YvynOpZDpCOUoIVlaaOUU87J4Z6RdD6spYN4eUb5tfPoKGSF9OG2NuhgYnq4jSkAxcpMaXWPf1cePkzmqTPNw== -"@svgr/babel-plugin-transform-svg-component@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.1.0.tgz#257159e28a21ac20988b1eaa5f59d4724f37fdaa" - integrity sha512-uulxdx2p3nrM2BkrtADQHK8IhEzCxdUILfC/ddvFC8tlFWuKiA3ych8C6q0ulyQHq34/3hzz+3rmUbhWF9redg== +"@svgr/babel-plugin-transform-svg-component@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-4.2.0.tgz#5f1e2f886b2c85c67e76da42f0f6be1b1767b697" + integrity sha512-hYfYuZhQPCBVotABsXKSCfel2slf/yvJY8heTVX1PCTaq/IgASq1IyxPPKJ0chWREEKewIU/JMSsIGBtK1KKxw== -"@svgr/babel-preset@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-4.1.0.tgz#f6fa8ad90064b85dd7a3566a70b7006e789e8385" - integrity sha512-Nat5aJ3VO3LE8KfMyIbd3sGWnaWPiFCeWIdEV+lalga0To/tpmzsnPDdnrR9fNYhvSSLJbwhU/lrLYt9wXY0ZQ== - dependencies: - "@svgr/babel-plugin-add-jsx-attribute" "^4.0.0" - "@svgr/babel-plugin-remove-jsx-attribute" "^4.0.3" - "@svgr/babel-plugin-remove-jsx-empty-expression" "^4.0.0" - "@svgr/babel-plugin-replace-jsx-attribute-value" "^4.0.0" - "@svgr/babel-plugin-svg-dynamic-title" "^4.0.0" - "@svgr/babel-plugin-svg-em-dimensions" "^4.0.0" - "@svgr/babel-plugin-transform-react-native-svg" "^4.0.0" - "@svgr/babel-plugin-transform-svg-component" "^4.1.0" - -"@svgr/core@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@svgr/core/-/core-4.1.0.tgz#4f8ad24fb4ab25c787c12a6bbb511c6430558f83" - integrity sha512-ahv3lvOKuUAcs0KbQ4Jr5fT5pGHhye4ew8jZVS4lw8IQdWrbG/o3rkpgxCPREBk7PShmEoGQpteeXVwp2yExuQ== +"@svgr/babel-preset@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/babel-preset/-/babel-preset-4.2.0.tgz#c9fc236445a02a8cd4e750085e51c181de00d6c5" + integrity sha512-iLetHpRCQXfK47voAs5/uxd736cCyocEdorisjAveZo8ShxJ/ivSZgstBmucI1c8HyMF5tOrilJLoFbhpkPiKw== + dependencies: + "@svgr/babel-plugin-add-jsx-attribute" "^4.2.0" + "@svgr/babel-plugin-remove-jsx-attribute" "^4.2.0" + "@svgr/babel-plugin-remove-jsx-empty-expression" "^4.2.0" + "@svgr/babel-plugin-replace-jsx-attribute-value" "^4.2.0" + "@svgr/babel-plugin-svg-dynamic-title" "^4.2.0" + "@svgr/babel-plugin-svg-em-dimensions" "^4.2.0" + "@svgr/babel-plugin-transform-react-native-svg" "^4.2.0" + "@svgr/babel-plugin-transform-svg-component" "^4.2.0" + +"@svgr/core@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/core/-/core-4.2.0.tgz#f32ef8b9d05312aaa775896ec30ae46a6521e248" + integrity sha512-nvzXaf2VavqjMCTTfsZfjL4o9035KedALkMzk82qOlHOwBb8JT+9+zYDgBl0oOunbVF94WTLnvGunEg0csNP3Q== dependencies: - "@svgr/plugin-jsx" "^4.1.0" - camelcase "^5.0.0" - cosmiconfig "^5.0.7" + "@svgr/plugin-jsx" "^4.2.0" + camelcase "^5.3.1" + cosmiconfig "^5.2.0" -"@svgr/hast-util-to-babel-ast@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.1.0.tgz#a1eb0f47059769896f759f47995b636fce5d9fa4" - integrity sha512-tdkEZHmigYYiVhIEzycAMKN5aUSpddUnjr6v7bPwaNTFuSyqGUrpCg1JlIGi7PUaaJVHbn6whGQMGUpKOwT5nw== +"@svgr/hast-util-to-babel-ast@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-4.2.0.tgz#dd743435a5f3a8e84a1da067f27b5fae3d7b6b63" + integrity sha512-IvAeb7gqrGB5TH9EGyBsPrMRH/QCzIuAkLySKvH2TLfLb2uqk98qtJamordRQTpHH3e6TORfBXoTo7L7Opo/Ow== dependencies: - "@babel/types" "^7.1.6" + "@babel/types" "^7.4.0" -"@svgr/plugin-jsx@^4.1.0": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-4.1.0.tgz#4045e9cc0589374a6c182a1217c80e6734b5cbec" - integrity sha512-xwu+9TGziuN7cu7p+vhCw2EJIfv8iDNMzn2dR0C7fBYc8q+SRtYTcg4Uyn8ZWh6DM+IZOlVrS02VEMT0FQzXSA== +"@svgr/plugin-jsx@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-jsx/-/plugin-jsx-4.2.0.tgz#15a91562c9b5f90640ea0bdcb2ad59d692ee7ae9" + integrity sha512-AM1YokmZITgveY9bulLVquqNmwiFo2Px2HL+IlnTCR01YvWDfRL5QKdnF7VjRaS5MNP938mmqvL0/8oz3zQMkg== dependencies: - "@babel/core" "^7.1.6" - "@svgr/babel-preset" "^4.1.0" - "@svgr/hast-util-to-babel-ast" "^4.1.0" + "@babel/core" "^7.4.3" + "@svgr/babel-preset" "^4.2.0" + "@svgr/hast-util-to-babel-ast" "^4.2.0" rehype-parse "^6.0.0" - unified "^7.0.2" - vfile "^3.0.1" + unified "^7.1.0" + vfile "^4.0.0" -"@svgr/plugin-svgo@^4.0.3": - version "4.0.3" - resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-4.0.3.tgz#a07ea0a736c26fa3a5440fe8e222e2e887764cab" - integrity sha512-MgL1CrlxvNe+1tQjPUc2bIJtsdJOIE5arbHlPgW+XVWGjMZTUcyNNP8R7/IjM2Iyrc98UJY+WYiiWHrinnY9ZQ== +"@svgr/plugin-svgo@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/plugin-svgo/-/plugin-svgo-4.2.0.tgz#2a594a2d3312955e75fd87dc77ae51f377c809f3" + integrity sha512-zUEKgkT172YzHh3mb2B2q92xCnOAMVjRx+o0waZ1U50XqKLrVQ/8dDqTAtnmapdLsGurv8PSwenjLCUpj6hcvw== dependencies: - cosmiconfig "^5.0.7" + cosmiconfig "^5.2.0" merge-deep "^3.0.2" - svgo "^1.1.1" + svgo "^1.2.1" "@svgr/webpack@^4.0.3": - version "4.1.0" - resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-4.1.0.tgz#20c88f32f731c7b1d4711045b2b993887d731c28" - integrity sha512-d09ehQWqLMywP/PT/5JvXwPskPK9QCXUjiSkAHehreB381qExXf5JFCBWhfEyNonRbkIneCeYM99w+Ud48YIQQ== + version "4.2.0" + resolved "https://registry.yarnpkg.com/@svgr/webpack/-/webpack-4.2.0.tgz#b7cdef42ae671a27ed4cfe118a0f2da7f4e9ebed" + integrity sha512-sm3UUJHmRlqEg8w8bjUT+FAMf5lkgCydxotEapinpd10kzrpQP++Qd+bmuepE3hsIUU68BO24vgQALQ92qBZEw== dependencies: - "@babel/core" "^7.1.6" + "@babel/core" "^7.4.3" "@babel/plugin-transform-react-constant-elements" "^7.0.0" - "@babel/preset-env" "^7.1.6" + "@babel/preset-env" "^7.4.3" "@babel/preset-react" "^7.0.0" - "@svgr/core" "^4.1.0" - "@svgr/plugin-jsx" "^4.1.0" - "@svgr/plugin-svgo" "^4.0.3" - loader-utils "^1.1.0" + "@svgr/core" "^4.2.0" + "@svgr/plugin-jsx" "^4.2.0" + "@svgr/plugin-svgo" "^4.2.0" + loader-utils "^1.2.3" "@types/babel__core@^7.1.0": - version "7.1.0" - resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.0.tgz#710f2487dda4dcfd010ca6abb2b4dc7394365c51" - integrity sha512-wJTeJRt7BToFx3USrCDs2BhEi4ijBInTQjOIukj6a/5tEkwpFMVZ+1ppgmE+Q/FQyc5P/VWUbx7I9NELrKruHA== + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.1.1.tgz#ce9a9e5d92b7031421e1d0d74ae59f572ba48be6" + integrity sha512-+hjBtgcFPYyCTo0A15+nxrCVJL7aC6Acg87TXd5OW3QhHswdrOLoles+ldL2Uk8q++7yIfl4tURtztccdeeyOw== dependencies: "@babel/parser" "^7.1.0" "@babel/types" "^7.0.0" @@ -2088,9 +2088,9 @@ indefinite-observable "^1.0.1" "@types/node@*": - version "11.13.0" - resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.0.tgz#b0df8d6ef9b5001b2be3a94d909ce3c29a80f9e1" - integrity sha512-rx29MMkRdVmzunmiA4lzBYJNnXsW/PhG4kMBy2ATsYaDjGGR75dCFEVVROKpNwlVdcUX3xxlghKQOeDPBJobng== + version "11.13.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-11.13.4.tgz#f83ec3c3e05b174b7241fadeb6688267fe5b22ca" + integrity sha512-+rabAZZ3Yn7tF/XPGHupKIL5EcAbrLxnTr/hgQICxbeuAfWtT0UZSfULE+ndusckBItcv4o6ZeOJplQikVcLvQ== "@types/node@^10.12.18", "@types/node@^10.3.2": version "10.14.4" @@ -2108,16 +2108,16 @@ integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== "@types/react-transition-group@^2.0.8": - version "2.0.16" - resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.0.16.tgz#2dcb9e396ab385ee19c4af1c9caa469a14cd042f" - integrity sha512-FUJEx2BGJPU1qVQoWd9v7wpOwnCPTWhcE4iTaU5prry9SvwiI11lCXOci8Nz9cM/Fuf650l7Skg6nlVeCYjPFA== + version "2.9.0" + resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-2.9.0.tgz#2a74a885432d673a93a2c93c34ce5dbf9f1426f8" + integrity sha512-hP7vUaZMVSWKxo133P8U51U6UZ7+pbY+eAQb8+p6SZ2rB1rj3mOTDgTzhhi+R2SCB4S+sWekAAGoxdiZPG0ReQ== dependencies: "@types/react" "*" "@types/react@*": - version "16.8.12" - resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.12.tgz#ffbdd7bcd2b7037c3f78e26c708922a2befbb71f" - integrity sha512-MZZiv11BQhsxFp5DHDmRKBi6Nv3jwOhRiFFDE7ZJ1+rb52gdOd9y/qY0+5wyV/PQVK9926wFMjpQj3BJ18pb4Q== + version "16.8.13" + resolved "https://registry.yarnpkg.com/@types/react/-/react-16.8.13.tgz#a82b15aad9ab91c40edca0d6889b7745ae24f053" + integrity sha512-otJ4ntMuHGrvm67CdDJMAls4WqotmAmW0g3HmWi9LCjSWXrxoXY/nHXrtmMfvPEEmGFNm6NdgMsJmnfH820Qaw== dependencies: "@types/prop-types" "*" csstype "^2.2.0" @@ -2132,7 +2132,7 @@ resolved "https://registry.yarnpkg.com/@types/tinycolor2/-/tinycolor2-1.4.1.tgz#2f5670c9d1d6e558897a810ed284b44918fc1253" integrity sha512-25L/RL5tqZkquKXVHM1fM2bd23qjfbcPpAZ2N/H05Y45g3UEi+Hw8CbDV28shKY8gH1SHiLpZSxPI1lacqdpGg== -"@types/unist@*", "@types/unist@^2.0.0": +"@types/unist@*", "@types/unist@^2.0.0", "@types/unist@^2.0.2": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== @@ -2155,9 +2155,9 @@ "@types/vfile-message" "*" "@types/yargs@^12.0.2", "@types/yargs@^12.0.9": - version "12.0.11" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.11.tgz#a090d88e1f40a910e6443c95493c1c035c76ebdc" - integrity sha512-IsU1TD+8cQCyG76ZqxP0cVFnofvfzT8p/wO8ENT4jbN/KKN3grsHFgHNl/U+08s33ayX4LwI85cEhYXCOlOkMw== + version "12.0.12" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-12.0.12.tgz#45dd1d0638e8c8f153e87d296907659296873916" + integrity sha512-SOhuU4wNBxhhTHxYaiG5NY4HBhDIDnJF60GU+2LqHAdKKer86//e4yg69aENCtQ04n0ovz+tq2YPME5t5yp4pw== "@webassemblyjs/ast@1.8.5": version "1.8.5" @@ -2386,9 +2386,9 @@ acorn-globals@^1.0.4: acorn "^2.1.0" acorn-globals@^4.1.0: - version "4.3.0" - resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.0.tgz#e3b6f8da3c1552a95ae627571f7dd6923bb54103" - integrity sha512-hMtHj3s5RnuhvHPowpBYvJVj3rAar82JiDQHvGs1zO0l10ocX/xEdBShNHTJaboucJUsScghp74pH3s7EnHHQw== + version "4.3.1" + resolved "https://registry.yarnpkg.com/acorn-globals/-/acorn-globals-4.3.1.tgz#deb149c59276657ebd40ba2ba849ddd529763ccf" + integrity sha512-gJSiKY8dBIjV/0jagZIFBdVMtfQyA5QHCvAT48H2q8REQoW8Fs5AOjqBql1LgSXgrMWdevcE+8cdZ33NtVbIBA== dependencies: acorn "^6.0.1" acorn-walk "^6.0.1" @@ -2845,7 +2845,7 @@ atob@^2.1.1: resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== -autoprefixer@9.5.1: +autoprefixer@9.5.1, autoprefixer@^9.4.7: version "9.5.1" resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.5.1.tgz#243b1267b67e7e947f28919d786b50d3bb0fb357" integrity sha512-KJSzkStUl3wP0D5sdMlP82Q52JLy5+atf2MHAre48+ckWkXgixmfHyWmA77wFDy6jTHU6mIgXv6hAQ2mf1PjJQ== @@ -2857,18 +2857,6 @@ autoprefixer@9.5.1: postcss "^7.0.14" postcss-value-parser "^3.3.1" -autoprefixer@^9.4.7: - version "9.5.0" - resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.5.0.tgz#7e51d0355c11596e6cf9a0afc9a44e86d1596c70" - integrity sha512-hMKcyHsZn5+qL6AUeP3c8OyuteZ4VaUlg+fWbyl8z7PqsKHF/Bf8/px3K6AT8aMzDkBo8Bc11245MM+itDBOxQ== - dependencies: - browserslist "^4.4.2" - caniuse-lite "^1.0.30000947" - normalize-range "^0.1.2" - num2fraction "^1.2.2" - postcss "^7.0.14" - postcss-value-parser "^3.3.1" - aws-sign2@~0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" @@ -4238,7 +4226,7 @@ browserslist@^3.2.6: caniuse-lite "^1.0.30000844" electron-to-chromium "^1.3.47" -browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.4.2, browserslist@^4.5.1, browserslist@^4.5.2, browserslist@^4.5.4: +browserslist@^4.0.0, browserslist@^4.3.4, browserslist@^4.5.2, browserslist@^4.5.4: version "4.5.4" resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.5.4.tgz#166c4ecef3b51737a42436ea8002aeea466ea2c7" integrity sha512-rAjx494LMjqKnMPhFkuLmLp8JWEX0o8ADTGeAbOqaF+XCvYLreZrG5uVjnPBlAQ8REZK4pzXGvp0bWgrFtKaag== @@ -4440,9 +4428,9 @@ callsites@^2.0.0: integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= callsites@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.0.0.tgz#fb7eb569b72ad7a45812f93fd9430a3e410b3dd3" - integrity sha512-tWnkwu9YEq2uzlBDI4RcLn8jrFvF9AOi8PxDNU3hZZjJcjkcRAq3vCI+vZcg1SuxISDYe86k9VZFwAxDiJGoAw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== camel-case@3.0.x: version "3.0.0" @@ -4452,7 +4440,7 @@ camel-case@3.0.x: no-case "^2.2.0" upper-case "^1.1.1" -camelcase-css@^2.0.0: +camelcase-css@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== @@ -4471,7 +4459,7 @@ camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0= -camelcase@^5.0.0, camelcase@^5.2.0: +camelcase@^5.0.0, camelcase@^5.2.0, camelcase@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== @@ -4486,10 +4474,10 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000947, caniuse-lite@^1.0.30000955, caniuse-lite@^1.0.30000957: - version "1.0.30000957" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000957.tgz#fb1026bf184d7d62c685205358c3b24b9e29f7b3" - integrity sha512-8wxNrjAzyiHcLXN/iunskqQnJquQQ6VX8JHfW5kLgAPRSiSuKZiNfmIkP5j7jgyXqAQBSoXyJxfnbCFS0ThSiQ== +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000929, caniuse-lite@^1.0.30000955, caniuse-lite@^1.0.30000957: + version "1.0.30000959" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000959.tgz#215d3455866da874179c6170202f0cc64f961cfd" + integrity sha512-6BvqmS0VLmY4sJCz6AbIJRQfcns8McDxi424y+3kmtisJeA9/5qslP+K8sqremDau7UU4WSsqdRP032JrqZY8Q== capture-exit@^2.0.0: version "2.0.0" @@ -4735,9 +4723,9 @@ cli-cursor@^2.1.0: restore-cursor "^2.0.0" cli-spinners@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.0.0.tgz#4b078756fc17a8f72043fdc9f1f14bf4fa87e2df" - integrity sha512-yiEBmhaKPPeBj7wWm4GEdtPZK940p9pl3EANIrnJ3JnvWyrPjcFcsEq6qRUuQ7fzB0+Y82ld3p6B34xo95foWw== + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.1.0.tgz#22c34b4d51f573240885b201efda4e4ec9fff3c7" + integrity sha512-8B00fJOEh1HPrx4fo5eW16XmE1PcL1tGpGrxy63CXGP9nHdPBN63X75hA1zhvQuhVztJWLqV58Roj2qlNM7cAA== cli-table3@0.5.1: version "0.5.1" @@ -4924,7 +4912,7 @@ commander@2.17.x: resolved "https://registry.yarnpkg.com/commander/-/commander-2.17.1.tgz#bd77ab7de6de94205ceacc72f1716d29f20a77bf" integrity sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg== -commander@^2.11.0, commander@^2.18.0, commander@^2.19.0, commander@^2.8.1: +commander@^2.11.0, commander@^2.18.0, commander@^2.19.0, commander@^2.8.1, commander@~2.20.0: version "2.20.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.0.tgz#d58bb2b5c1ee8f87b0d340027e9e94e222c5a422" integrity sha512-7j2y+40w61zy6YC2iRNpUe/NwhNyoXrYpHMrSunaMG64nRnaf96zO/KMQR4OyN/UnE5KLyEBnKHd4aG3rskjpQ== @@ -5027,11 +5015,12 @@ connect-history-api-fallback@^1.6.0: integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== connected-react-router@^6.3.1: - version "6.3.2" - resolved "https://registry.yarnpkg.com/connected-react-router/-/connected-react-router-6.3.2.tgz#8c90b77f1d7b783608cd50e4f69bf60e47265425" - integrity sha512-YxrAfMExl/OBsi+ojA4ywZeC7cmQ52MnZ4bhzqLhhjuOiXcQogC4kW0kodouXAXrXDovb2l3yEhDfpH99/wYcw== + version "6.4.0" + resolved "https://registry.yarnpkg.com/connected-react-router/-/connected-react-router-6.4.0.tgz#c382a9e70fdd1247c09c7ece7854622db4d46234" + integrity sha512-RZRLD7qUz9OdmCn0JkW7pOiUsR7v9NtqnYKfqrxXsfO2ozMLR2/MjHaSPpdbMr4VE5TY6MwzAXUSkheN2ldqug== dependencies: immutable "^3.8.1" + prop-types "^15.7.2" seamless-immutable "^7.1.3" console-browserify@^1.1.0: @@ -5106,31 +5095,31 @@ copy-descriptor@^0.1.0: integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= copy-to-clipboard@^3.0.8: - version "3.0.8" - resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.0.8.tgz#f4e82f4a8830dce4666b7eb8ded0c9bcc313aba9" - integrity sha512-c3GdeY8qxCHGezVb1EFQfHYK/8NZRemgcTIzPq7PuxjHAf/raKibn2QdhHPb/y6q74PMgH6yizaDZlRmw6QyKw== + version "3.1.0" + resolved "https://registry.yarnpkg.com/copy-to-clipboard/-/copy-to-clipboard-3.1.0.tgz#0a28141899e6bd217b9dc13fd1689b3b38820b44" + integrity sha512-+RNyDq266tv5aGhfRsL6lxgj8Y6sCvTrVJnFUVvuxuqkcSMaLISt1wd4JkdQSphbcLTIQ9kEpTULNnoCXAFdng== dependencies: - toggle-selection "^1.0.3" + toggle-selection "^1.0.6" core-js-compat@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.0.0.tgz#cd9810b8000742535a4a43773866185e310bd4f7" - integrity sha512-W/Ppz34uUme3LmXWjMgFlYyGnbo1hd9JvA0LNQ4EmieqVjg2GPYbj3H6tcdP2QGPGWdRKUqZVbVKLNIFVs/HiA== + version "3.0.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.0.1.tgz#bff73ba31ca8687431b9c88f78d3362646fb76f0" + integrity sha512-2pC3e+Ht/1/gD7Sim/sqzvRplMiRnFQVlPpDVaHtY9l7zZP7knamr3VRD6NyGfHd84MrDC0tAM9ulNxYMW0T3g== dependencies: - browserslist "^4.5.1" - core-js "3.0.0" - core-js-pure "3.0.0" - semver "^5.6.0" + browserslist "^4.5.4" + core-js "3.0.1" + core-js-pure "3.0.1" + semver "^6.0.0" -core-js-pure@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.0.0.tgz#a5679adb4875427c8c0488afc93e6f5b7125859b" - integrity sha512-yPiS3fQd842RZDgo/TAKGgS0f3p2nxssF1H65DIZvZv0Od5CygP8puHXn3IQiM/39VAvgCbdaMQpresrbGgt9g== +core-js-pure@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/core-js-pure/-/core-js-pure-3.0.1.tgz#37358fb0d024e6b86d443d794f4e37e949098cbe" + integrity sha512-mSxeQ6IghKW3MoyF4cz19GJ1cMm7761ON+WObSyLfTu/Jn3x7w4NwNFnrZxgl4MTSvYYepVLNuRtlB4loMwJ5g== -core-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.0.tgz#a8dbfa978d29bfc263bfb66c556d0ca924c28957" - integrity sha512-WBmxlgH2122EzEJ6GH8o9L/FeoUKxxxZ6q6VUxoTlsE4EvbTWKJb447eyVxTEuq0LpXjlq/kCB2qgBvsYRkLvQ== +core-js@3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-3.0.1.tgz#1343182634298f7f38622f95e73f54e48ddf4738" + integrity sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew== core-js@^1.0.0: version "1.2.7" @@ -5165,7 +5154,7 @@ cosmiconfig@^4.0.0: parse-json "^4.0.0" require-from-string "^2.0.1" -cosmiconfig@^5.0.0, cosmiconfig@^5.0.5, cosmiconfig@^5.0.7, cosmiconfig@^5.2.0: +cosmiconfig@^5.0.0, cosmiconfig@^5.0.5, cosmiconfig@^5.2.0: version "5.2.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.0.tgz#45038e4d28a7fe787203aede9c25bca4a08b12c8" integrity sha512-nxt+Nfc3JAqf4WIWd0jXLjTJZmsPLrA9DDc4nRw2KFJQJK7DNooqSXrNI7tzLG50CF8axczly5UV929tBmh/7g== @@ -5567,7 +5556,7 @@ debounce@^1.1.0: resolved "https://registry.yarnpkg.com/debounce/-/debounce-1.2.0.tgz#44a540abc0ea9943018dc0eaa95cce87f65cd131" integrity sha512-mYtLl1xfZLi1m4RtQYlZgJUNQjl4ZxVnHzIR8nLLgi4q1YT8o/WM+MK/f8yfcc9s5Ir5zRaPZyZU6xs1Syoocg== -debug@2.6.9, debug@^2.1.2, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.8, debug@^2.6.9: version "2.6.9" resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== @@ -5697,7 +5686,7 @@ deepmerge@^3.0.0: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-3.2.0.tgz#58ef463a57c08d376547f8869fdc5bcee957f44e" integrity sha512-6+LuZGU7QCNUnAJyX8cIrlzoEgggTM6B7mm+znKOX4t5ltluT9KLjN6g61ECMS0LTsLW7yDpNoxhix5FZcrIow== -default-gateway@^4.0.1: +default-gateway@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== @@ -5960,7 +5949,7 @@ dom-converter@^0.2: dependencies: utila "~0.4" -dom-helpers@^3.2.1, dom-helpers@^3.3.1: +dom-helpers@^3.2.1, dom-helpers@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8" integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA== @@ -6121,9 +6110,9 @@ ejs@^2.6.1: integrity sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ== electron-to-chromium@^1.3.103, electron-to-chromium@^1.3.122, electron-to-chromium@^1.3.47: - version "1.3.122" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.122.tgz#b32a0805f48557bd3c3b8104eadc7fa511b14a9a" - integrity sha512-3RKoIyCN4DhP2dsmleuFvpJAIDOseWH88wFYBzb22CSwoFDSWRc4UAMfrtc9h8nBdJjTNIN3rogChgOy6eFInw== + version "1.3.124" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.124.tgz#861fc0148748a11b3e5ccebdf8b795ff513fa11f" + integrity sha512-glecGr/kFdfeXUHOHAWvGcXrxNU+1wSO/t5B23tT1dtlvYB26GY8aHzZSWD7HqhqC800Lr+w/hQul6C5AF542w== elliptic@6.3.3: version "6.3.3" @@ -6265,9 +6254,9 @@ es-to-primitive@^1.2.0: is-symbol "^1.0.2" es5-shim@^4.5.10: - version "4.5.12" - resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.12.tgz#508c13dda1c87dd3df1b50e69e7b96b82149b649" - integrity sha512-MjoCAHE6P2Dirme70Cxd9i2Ng8rhXiaVSsxDWdSwimfLERJL/ypR2ed2rTYkeeYrMk8gq281dzKLiGcdrmc8qg== + version "4.5.13" + resolved "https://registry.yarnpkg.com/es5-shim/-/es5-shim-4.5.13.tgz#5d88062de049f8969f83783f4a4884395f21d28b" + integrity sha512-xi6hh6gsvDE0MaW4Vp1lgNEBpVcCXRWfPXj5egDvtgLz4L9MEvNwYEMdJH+JJinWkwa8c3c3o5HduV7dB/e1Hw== es6-shim@^0.35.3: version "0.35.5" @@ -6347,10 +6336,10 @@ eslint-import-resolver-node@^0.3.2: debug "^2.6.9" resolve "^1.5.0" -eslint-module-utils@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.3.0.tgz#546178dab5e046c8b562bbb50705e2456d7bda49" - integrity sha512-lmDJgeOOjk8hObTysjqH7wyMi+nsHwwvfBykwfhjR1LNdd7C2uFJBvx4OpWYpXOw4df1yE1cDEVd1yLHitk34w== +eslint-module-utils@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.4.0.tgz#8b93499e9b00eab80ccb6614e69f03678e84e09a" + integrity sha512-14tltLm38Eu3zS+mt0KvILC3q8jyIAH518MlG+HO0p+yK885Lb1UHTY/UgR91eOyGdmxAPb+OLoW4znqIT6Ndw== dependencies: debug "^2.6.8" pkg-dir "^2.0.0" @@ -6363,20 +6352,21 @@ eslint-plugin-flowtype@3.6.1: lodash "^4.17.11" eslint-plugin-import@^2.9.0: - version "2.16.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.16.0.tgz#97ac3e75d0791c4fac0e15ef388510217be7f66f" - integrity sha512-z6oqWlf1x5GkHIFgrSvtmudnqM6Q60KM4KvpWi5ubonMjycLjndvd5+8VAZIsTlHC03djdgJuyKG6XO577px6A== + version "2.17.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.1.tgz#b888feb4d9b3ee155113c8dccdd4bec5db33bdf4" + integrity sha512-lzD9uvRvW4MsHzIOMJEDSb5MOV9LzgxRPBaovvOhJqzgxRHYfGy9QOrMuwHIh5ehKFJ7Z3DcrcGKDQ0IbP0EdQ== dependencies: + array-includes "^3.0.3" contains-path "^0.1.0" debug "^2.6.9" doctrine "1.5.0" eslint-import-resolver-node "^0.3.2" - eslint-module-utils "^2.3.0" + eslint-module-utils "^2.4.0" has "^1.0.3" lodash "^4.17.11" minimatch "^3.0.4" read-pkg-up "^2.0.0" - resolve "^1.9.0" + resolve "^1.10.0" eslint-plugin-jest@^22.3.0: version "22.4.1" @@ -7524,10 +7514,10 @@ flatted@^2.0.0: resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.0.tgz#55122b6536ea496b4b44893ee2608141d10d9916" integrity sha512-R+H8IZclI8AAkSBRQJLVOsxwAoHd6WC40b4QTNWIjzAa6BXOBfQcM587MXDTVPeYaopFNWHUFLx7eNmHDSxMWg== -flow-bin@0.96.0: - version "0.96.0" - resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.96.0.tgz#3b0379d97304dc1879ae6db627cd2d6819998661" - integrity sha512-OSxERs0EdhVxEVCst/HmlT/RcnXsQQIRqcfK9J9wC8/93JQj+xQz4RtlsmYe1PSRYaozuDLyPS5pIA81Zwzaww== +flow-bin@0.97.0: + version "0.97.0" + resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.97.0.tgz#036ffcfc27503367a9d906ec9d843a0aa6f6bb83" + integrity sha512-jXjD05gkatLuC4+e28frH1hZoRwr1iASP6oJr61Q64+kR4kmzaS+AdFBhYgoYS5kpoe4UzwDebWK8ETQFNh00w== flush-write-stream@^1.0.0: version "1.1.1" @@ -8147,7 +8137,7 @@ gud@^1.0.0: resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== -gzip-size@5.0.0, gzip-size@^5.0.0: +gzip-size@5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.0.0.tgz#a55ecd99222f4c48fd8c01c625ce3b349d0a0e80" integrity sha512-5iI7omclyqrnWw4XbXAmGhPsABkSIDQonv2K0h61lybgofWa6iZyvrI3r2zsJH4P8Nb64fFVzlvfhs0g7BBxAA== @@ -8155,15 +8145,23 @@ gzip-size@5.0.0, gzip-size@^5.0.0: duplexer "^0.1.1" pify "^3.0.0" +gzip-size@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.0.tgz#2db0396c71f5c902d5cf6b52add5030b93c99bd2" + integrity sha512-wfSnvypBDRW94v5W3ckvvz/zFUNdJ81VgOP6tE4bPpRUcc0wGqU+y0eZjJEvKxwubJFix6P84sE8M51YWLT7rQ== + dependencies: + duplexer "^0.1.1" + pify "^4.0.1" + handle-thing@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== handlebars@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.1.tgz#6e4e41c18ebe7719ae4d38e5aca3d32fa3dd23d3" - integrity sha512-3Zhi6C0euYZL5sM0Zcy7lInLXKQ+YLcF/olbN010mzGQ4XVm50JeyBnMqofHh696GrciGruC7kCcApPDJvVgwA== + version "4.1.2" + resolved "https://registry.yarnpkg.com/handlebars/-/handlebars-4.1.2.tgz#b6b37c1ced0306b221e094fc7aca3ec23b131b67" + integrity sha512-nvfrjqvt9xQ8Z/w0ijewdD/vvWDTOweBUm96NTr66Wfvo1mJenBLwcYmPs3TIBP5ruzYGD7Hx/DaM9RmhroGPw== dependencies: neo-async "^2.6.0" optimist "^0.6.1" @@ -8827,9 +8825,9 @@ inquirer@^3.0.6: through "^2.3.6" inquirer@^6.2.0, inquirer@^6.2.2: - version "6.2.2" - resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.2.2.tgz#46941176f65c9eb20804627149b743a218f25406" - integrity sha512-Z2rREiXA6cHRR9KBOarR3WuLlFzlIfAEIiB45ll5SSadMg7WqOh1MKEjjndfuH5ewXdixWCxqnVfGOQzPeiztA== + version "6.3.1" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.3.1.tgz#7a413b5e7950811013a3db491c61d1f3b776e8e7" + integrity sha512-MmL624rfkFt4TG9y/Jvmt8vdmOo836U7Y0Hxr2aFk3RelZEGX4Igk0KabWrcaaZaTv9uzglOqWh1Vly+FAWAXA== dependencies: ansi-escapes "^3.2.0" chalk "^2.4.2" @@ -8842,15 +8840,15 @@ inquirer@^6.2.0, inquirer@^6.2.2: run-async "^2.2.0" rxjs "^6.4.0" string-width "^2.1.0" - strip-ansi "^5.0.0" + strip-ansi "^5.1.0" through "^2.3.6" internal-ip@^4.2.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.2.0.tgz#46e81b638d84c338e5c67e42b1a17db67d0814fa" - integrity sha512-ZY8Rk+hlvFeuMmG5uH1MXhhdeMntmIaxaInvAmzMq/SHV8rv4Kh+6GiQNNDQd0wZFrcO+FiTBo8lui/osKOyJw== + version "4.3.0" + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" + integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== dependencies: - default-gateway "^4.0.1" + default-gateway "^4.2.0" ipaddr.js "^1.9.0" interpret@^1.0.0, interpret@^1.1.0, interpret@^1.2.0: @@ -9101,9 +9099,9 @@ is-function@^1.0.1: integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU= is-generator-fn@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.0.0.tgz#038c31b774709641bda678b1f06a4e3227c10b3e" - integrity sha512-elzyIdM7iKoFHzcrndIqjYomImhxrFRnGP3galODoII4TB9gI7mZ+FnlLQmmjf27SxHS2gKEeyhX5/+YRS6H9g== + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-2.1.0.tgz#7d140adc389aaf3011a8f2a2a4cfa6faadffb118" + integrity sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ== is-glob@^2.0.0, is-glob@^2.0.1: version "2.0.1" @@ -9819,9 +9817,9 @@ js-tokens@^3.0.2: integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.9.0, js-yaml@^3.9.1: - version "3.13.0" - resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.0.tgz#38ee7178ac0eea2c97ff6d96fff4b18c7d8cf98e" - integrity sha512-pZZoSxcCYco+DIKBTimr67J6Hy+EYGZDY/HCWC+iAEA9h1ByhMXAIVUXMcMFpOCxQ/xjXmPI2MkDL5HRm5eFrQ== + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== dependencies: argparse "^1.0.7" esprima "^4.0.0" @@ -10164,9 +10162,9 @@ klaw@^1.0.0: graceful-fs "^4.1.9" kleur@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.2.tgz#83c7ec858a41098b613d5998a7b653962b504f68" - integrity sha512-3h7B2WRT5LNXOtQiAaWonilegHcPSf9nLVXlSTci8lu1dZUuui61+EsPEZqSVxY7rXYmB2DVKMQILxaO5WL61Q== + version "3.0.3" + resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" + integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== last-call-webpack-plugin@^3.0.0: version "3.0.0" @@ -10234,9 +10232,9 @@ level-errors@^1.0.3: errno "~0.1.1" level-errors@^2.0.0, level-errors@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.0.tgz#2de5b566b62eef92f99e19be74397fbc512563fa" - integrity sha512-AmY4HCp9h3OiU19uG+3YWkdELgy05OTP/r23aNHaQKWv8DO787yZgsEuGVkoph40uwN+YdUKnANlrxSsoOaaxg== + version "2.0.1" + resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-2.0.1.tgz#2132a677bf4e679ce029f517c2f17432800c05c8" + integrity sha512-UVprBJXite4gPS+3VznfgDSU8PTRuVX0NXwoWW50KLxd2yw4Y1t2JUR5In1itQnudZqRMT9DlAM3Q//9NCjCFw== dependencies: errno "~0.1.1" @@ -10750,9 +10748,9 @@ memdown@^1.0.0: safe-buffer "~5.1.1" memoize-one@^5.0.0: - version "5.0.2" - resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.2.tgz#6aba5276856d72fb44ead3efab86432f94ba203d" - integrity sha512-o7lldN4fs/axqctc03NF+PMhd2veRrWeJ2n2GjEzUPBD4F9rmNg4A+bQCACIzwjHJEXuYv4aFFMaH35KZfHUrw== + version "5.0.4" + resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.4.tgz#005928aced5c43d890a4dfab18ca908b0ec92cbc" + integrity sha512-P0z5IeAH6qHHGkJIXWw0xC2HNEgkx/9uWWBQw64FJj3/ol14VYdfVGWWr0fXfjhhv3TKVIqUq65os6O4GUNksA== memoizerific@^1.11.3: version "1.11.3" @@ -10895,7 +10893,12 @@ miller-rabin@^4.0.0: bn.js "^4.0.0" brorand "^1.0.1" -"mime-db@>= 1.38.0 < 2", mime-db@~1.38.0: +"mime-db@>= 1.38.0 < 2": + version "1.39.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.39.0.tgz#f95a20275742f7d2ad0429acfe40f4233543780e" + integrity sha512-DTsrw/iWVvwHH+9Otxccdyy0Tgiil6TWK/xhfARJZF/QFhwOgZgOIvA2/VIGpM8U7Q8z5nDmdDWC6tuVMJNibw== + +mime-db@~1.38.0: version "1.38.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad" integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg== @@ -10913,9 +10916,9 @@ mime@1.4.1: integrity sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ== mime@^2.0.3, mime@^2.3.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.1.tgz#19eb7357bebbda37df585b14038347721558c715" - integrity sha512-VRUfmQO0rCd3hKwBymAn3kxYzBHr3I/wdVMywgG3HhXOwrCQgN84ZagpdTm2tZ4TNtwsSmyJWYO88mb5XvzGqQ== + version "2.4.2" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.2.tgz#ce5229a5e99ffc313abac806b482c10e7ba6ac78" + integrity sha512-zJBfZDkwRu+j3Pdd2aHsR5GfH2jIWhmL1ZzBoc+X+3JEti2hbArWcyJ+1laC1D2/U/W1a/+Cegj0/OnEU2ybjg== mimic-fn@^1.0.0: version "1.2.0" @@ -11148,7 +11151,7 @@ nan@2.10.0: resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" integrity sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA== -nan@^2.0.8, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: +nan@^2.0.8, nan@^2.11.0, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: version "2.13.2" resolved "https://registry.yarnpkg.com/nan/-/nan-2.13.2.tgz#f51dc7ae66ba7d5d55e1e6d4d8092e802c9aefe7" integrity sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw== @@ -11186,11 +11189,11 @@ natural-compare@^1.4.0: integrity sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= needle@^2.2.1: - version "2.2.4" - resolved "https://registry.yarnpkg.com/needle/-/needle-2.2.4.tgz#51931bff82533b1928b7d1d69e01f1b00ffd2a4e" - integrity sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.0.tgz#ce3fea21197267bacb310705a7bbe24f2a3a3492" + integrity sha512-QBZu7aAFR0522EyaXZM0FZ9GLpq6lvQ3uq8gteiDUp7wKdy0lSd2hPlgFwVuW1CBkfEs9PfDQsQzZghLs/psdg== dependencies: - debug "^2.1.2" + debug "^4.1.0" iconv-lite "^0.4.4" sax "^1.2.4" @@ -11329,9 +11332,9 @@ node-pre-gyp@^0.10.0: tar "^4" node-releases@^1.1.13, node-releases@^1.1.3: - version "1.1.13" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.13.tgz#8c03296b5ae60c08e2ff4f8f22ae45bd2f210083" - integrity sha512-fKZGviSXR6YvVPyc011NHuJDSD8gFQvLPmc2d2V3BS4gr52ycyQ1Xzs7a8B+Ax3Ni/W+5h1h4SqmzeoA8WZRmA== + version "1.1.14" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.14.tgz#f1f41c83cac82caebd6739e6313d56b3b09c9189" + integrity sha512-d58EpVZRhQE60kWiWUaaPlK9dyC4zg3ZoMcHcky2d4hDksyQj0rUozwInOl0C66mBsqo01Tuns8AvxnL5S7PKg== dependencies: semver "^5.3.0" @@ -11505,9 +11508,9 @@ object-inspect@~1.6.0: integrity sha512-GJzfBZ6DgDAmnuaM3104jR4s1Myxr3Y3zfIyN4z3UdqN69oSRacNK8UhnobDdC+7J2AHCjGwxQubNJfE70SXXQ== object-keys@^1.0.11, object-keys@^1.0.12: - version "1.1.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032" - integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== object-keys@~0.4.0: version "0.4.0" @@ -11797,9 +11800,9 @@ p-finally@^1.0.0: integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-is-promise@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.0.0.tgz#7554e3d572109a87e1f3f53f6a7d85d1b194f4c5" - integrity sha512-pzQPhYMCAgLAKPWD2jC3Se9fEfrD9npNos0y150EeqZll7akhEgGhTW/slB6lHku8AvYGiJ+YJ5hfHKePPgFWg== + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== p-limit@^1.1.0: version "1.3.0" @@ -12145,9 +12148,9 @@ polished@^2.3.3: "@babel/runtime" "^7.2.0" popper.js@^1.14.1, popper.js@^1.14.4: - version "1.14.7" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.7.tgz#e31ec06cfac6a97a53280c3e55e4e0c860e7738e" - integrity sha512-4q1hNvoUre/8srWsH7hnoSJ5xVmIL4qgz+s4qf2TnJIMyZFUFMGH+9vE7mXynAlHSZ/NdTmmow86muD0myUkVQ== + version "1.15.0" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.15.0.tgz#5560b99bbad7647e9faa475c6b8056621f5a4ff2" + integrity sha512-w010cY1oCUmI+9KwwlWki+r5jxKfTFDVoadl7MSrIujHU5MJ5OR6HTDj6Xo8aoR/QsA56x8jKjA59qGH4ELtrA== portfinder@^1.0.20: version "1.0.20" @@ -12228,12 +12231,12 @@ postcss-flexbugs-fixes@^4.1.0: postcss "^7.0.0" postcss-js@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-2.0.0.tgz#f75b70470009eb37f998ee9bb516a2899c19ef8d" - integrity sha512-9kAApW9G5kN8FkQ0ZdvSmbgbHIRrKmXtde2ZWYbwrW51gfEWfGsLlUu57mTpioPrmQlQFOgEvaeGYp+poqlX0A== + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-js/-/postcss-js-2.0.1.tgz#4154e906ff410930afab63a24210be1b831e89a9" + integrity sha512-8XQGohCbj6+kq8e3w6WlexkGaSjb5S8zoXnH49eB8JC6+qN2kQW+ib6fTjRgCpRRN9eeFOhMlD0NDjThW1DCBg== dependencies: - camelcase-css "^2.0.0" - postcss "^7.0.0" + camelcase-css "^2.0.1" + postcss "^7.0.14" postcss-load-config@^2.0.0: version "2.0.0" @@ -12613,9 +12616,9 @@ prettier-eslint@^8.5.0: vue-eslint-parser "^2.0.2" prettier@^1.7.0: - version "1.16.4" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.16.4.tgz#73e37e73e018ad2db9c76742e2647e21790c9717" - integrity sha512-ZzWuos7TI5CKUeQAtFd6Zhm2s6EpAD/ZLApIhsF9pRvRtM1RFo61dM/4MSRUA0SuLugA/zgrZD8m0BaY46Og7g== + version "1.17.0" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.17.0.tgz#53b303676eed22cc14a9f0cec09b477b3026c008" + integrity sha512-sXe5lSt2WQlCbydGETgfm1YBShgOX4HxQkFPvbxkcwgDvGDeqVau8h+12+lmSVlP3rHPz0oavfddSZg/q+Szjw== pretty-error@^2.0.2, pretty-error@^2.1.1: version "2.1.1" @@ -13121,10 +13124,10 @@ react-helmet-async@^0.2.0: react-fast-compare "^2.0.2" shallowequal "^1.0.2" -react-hot-loader@4.8.3: - version "4.8.3" - resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.8.3.tgz#14f018777a60ea9cfa60496c7341c2f967311253" - integrity sha512-Is8bKbSxuDLTqsWu1yjr+o1yA6yGDGjEQ2i1E8t/Nj1xJYC6QBRbyoofTn1xkMoKpcgXHuTJTqBhK0RY6moFJA== +react-hot-loader@4.8.4: + version "4.8.4" + resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.8.4.tgz#357ba342e367fd42d6a870a9c0601c23fa0730c6" + integrity sha512-O98btZXcm24ZgP+aPBD0W9N+GEnkOg6vlLEy/IMZ53u3K/dGqO0I/RU4qrmQzE+wMDLpwNo5TwxaAjVw9Y+IBA== dependencies: fast-levenshtein "^2.0.6" global "^4.3.0" @@ -13144,9 +13147,9 @@ react-hotkeys@2.0.0-pre4: prop-types "^15.6.1" react-html-attributes@^1.4.2: - version "1.4.3" - resolved "https://registry.yarnpkg.com/react-html-attributes/-/react-html-attributes-1.4.3.tgz#8c36c35fce6b750938d286af428ed1da7625186e" - integrity sha1-jDbDX85rdQk40oavQo7R2nYlGG4= + version "1.4.6" + resolved "https://registry.yarnpkg.com/react-html-attributes/-/react-html-attributes-1.4.6.tgz#9558b56bb81c60f6cee9ae7d5e97434a59c086ff" + integrity sha512-uS3MmThNKFH2EZUQQw4k5pIcU7XIr208UE5dktrj/GOH1CMagqxDl4DCLpt3o2l9x+IB5nVYBeN3Cr4IutBXAg== dependencies: html-element-attributes "^1.0.0" @@ -13192,11 +13195,11 @@ react-modal@^3.8.1: warning "^3.0.0" react-popper-tooltip@^2.8.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.8.1.tgz#bbaec88b729e3b7e9f26521857e7f908bccdecf3" - integrity sha512-eL0PT5yz9H9lkG934TMh7czZWwDlqFady7CcJKMP5RcmBxTFBY4U7k71FEyxNaHd07nhMhUwbk0/Fgf2yw3LEg== + version "2.8.2" + resolved "https://registry.yarnpkg.com/react-popper-tooltip/-/react-popper-tooltip-2.8.2.tgz#4803446362a815b1406e39526ddeb299ed2fb414" + integrity sha512-k0T5y42Lhru4+7/YqB20YoHtlemlKE/6hT8nWtQzvoyBw/eKCahK6+udW4iZ6KwRYM/vocih14d0OPkMccqhWA== dependencies: - "@babel/runtime" "^7.3.4" + "@babel/runtime" "^7.4.3" react-popper "^1.3.3" react-popper@^1.3.3: @@ -13211,10 +13214,10 @@ react-popper@^1.3.3: typed-styles "^0.0.7" warning "^4.0.2" -react-redux@7.0.1: - version "7.0.1" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.0.1.tgz#321285e6c85c3586d11cc066ab33dc580da599fb" - integrity sha512-orSiI/QXtGiiJmf8lN/zVTx4hysFo/kGOsce28IUu/mu98AGemBwPTDzf64P4Vf/miRmevO8/w2RSw2awDd21w== +react-redux@7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.0.2.tgz#34b280a3482aaf60e7d4a504b1295165cbe6b86a" + integrity sha512-uKRuMgQt8dWbcz0U75oFK5tDo3boyAKrqvf/j94vpqRFFZfyDDy4kofUgloFIGyuKTq2Zz51zgK9RzOTFXk5ew== dependencies: "@babel/runtime" "^7.4.3" hoist-non-react-statics "^3.3.0" @@ -13291,11 +13294,11 @@ react-textarea-autosize@^7.0.4: prop-types "^15.6.0" react-transition-group@^2.2.1: - version "2.8.0" - resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.8.0.tgz#d6d8f635d81a0955b67348be5d017cff77d6c75f" - integrity sha512-So23a1MPn8CGoW5WNU4l0tLiVkOFmeXSS1K4Roe+dxxqqHvI/2XBmj76jx+u96LHnQddWG7LX8QovPAainSmWQ== + version "2.9.0" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-2.9.0.tgz#df9cdb025796211151a436c69a8f3b97b5b07c8d" + integrity sha512-+HzNTCHpeQyl4MJ/bdE0u6XRMe9+XG/+aL4mCxVN4DnPBQ0/5bfHWPDuOZUzYdMj94daZaZdCCc1Dzt9R/xSSg== dependencies: - dom-helpers "^3.3.1" + dom-helpers "^3.4.0" loose-envify "^1.4.0" prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" @@ -14664,9 +14667,9 @@ source-map-support@^0.4.15: source-map "^0.5.6" source-map-support@^0.5.3, source-map-support@^0.5.6, source-map-support@~0.5.10: - version "0.5.11" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.11.tgz#efac2ce0800355d026326a0ca23e162aeac9a4e2" - integrity sha512-//sajEx/fGL3iw6fltKMdPvy8kL3kJ2O3iuYlRoT3k9Kb4BjOoZ+BZzaNHeuaruSt+Kf3Zk9tnfAQg9/AJqUVQ== + version "0.5.12" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.12.tgz#b4f3b10d51857a5af0138d3ce8003b201613d599" + integrity sha512-4h2Pbvyy15EE02G+JOZpUCmqWJuqrs+sEkzewTm++BPi7Hvn/HwcqLAcNxYAyI0x13CpPPn+kMjl+hplXMHITQ== dependencies: buffer-from "^1.0.0" source-map "^0.6.0" @@ -14740,9 +14743,9 @@ spdx-expression-parse@^3.0.0: spdx-license-ids "^3.0.0" spdx-license-ids@^3.0.0: - version "3.0.3" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.3.tgz#81c0ce8f21474756148bbb5f3bfc0f36bf15d76e" - integrity sha512-uBIcIl3Ih6Phe3XHK1NqboJLdGfwr1UN3k6wSD1dZpmPsIkb8AGNbZYJ1fOBk834+Gxy8rpfDxrS6XLEMZMY2g== + version "3.0.4" + resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.4.tgz#75ecd1a88de8c184ef015eafb51b5b48bfd11bb1" + integrity sha512-7j8LYJLeY/Yb6ACbQ7F76qy5jHkp0U6jgBfJsk97bwWlVUnUWsAgpyaCvo17h0/RQGnQ036tVDomiwoI4pDkQA== spdy-transport@^3.0.0: version "3.0.0" @@ -15136,10 +15139,10 @@ svg-url-loader@^2.3.2: file-loader "1.1.11" loader-utils "1.1.0" -svgo@^1.0.0, svgo@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.0.tgz#305a8fc0f4f9710828c65039bb93d5793225ffc3" - integrity sha512-xBfxJxfk4UeVN8asec9jNxHiv3UAMv/ujwBWGYvQhhMb2u3YTGKkiybPcLFDLq7GLLWE9wa73e0/m8L5nTzQbw== +svgo@^1.0.0, svgo@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.2.1.tgz#3fedde75a4016193e1c2608b5fdef6f3e4a9fd99" + integrity sha512-Y1+LyT4/y1ms4/0yxPMSlvx6dIbgklE9w8CIOnfeoFGB74MEkq8inSfEr6NhocTaFbyYp0a1dvNgRKGRmEBlzA== dependencies: chalk "^2.4.1" coa "^2.0.2" @@ -15148,7 +15151,7 @@ svgo@^1.0.0, svgo@^1.1.1: css-tree "1.0.0-alpha.28" css-url-regex "^1.1.0" csso "^3.5.1" - js-yaml "^3.12.0" + js-yaml "^3.13.0" mkdirp "~0.5.1" object.values "^1.1.0" sax "~1.2.4" @@ -15243,9 +15246,9 @@ taffydb@2.7.3: integrity sha1-KtNxaWKUmPylvIQkMJbTzeDsOjQ= tapable@^1.0.0, tapable@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.1.tgz#4d297923c5a72a42360de2ab52dadfaaec00018e" - integrity sha512-9I2ydhj8Z9veORCw5PRm4u9uebCn0mcCa6scWoNcbZ6dAtoo2618u9UUzxgmsCOreJpqDDuv61LvwofW7hLcBA== + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== tape@^4.6.3, tape@^4.8.0: version "4.10.1" @@ -15529,7 +15532,7 @@ to-space-case@^1.0.0: dependencies: to-no-case "^1.0.0" -toggle-selection@^1.0.3: +toggle-selection@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/toggle-selection/-/toggle-selection-1.0.6.tgz#6e45b1263f2017fa0acc7d89d78b15b8bf77da32" integrity sha1-bkWxJj8gF/oKzH2J14sVuL932jI= @@ -16096,7 +16099,7 @@ typed-styles@^0.0.7: resolved "https://registry.yarnpkg.com/typed-styles/-/typed-styles-0.0.7.tgz#93392a008794c4595119ff62dde6809dbc40a3d9" integrity sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q== -typedarray-to-buffer@^3.1.2: +typedarray-to-buffer@^3.1.2, typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== @@ -16179,11 +16182,11 @@ uglify-js@3.4.x: source-map "~0.6.1" uglify-js@^3.0.0, uglify-js@^3.1.4: - version "3.5.3" - resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.5.3.tgz#d490bb5347f23025f0c1bc0dee901d98e4d6b063" - integrity sha512-rIQPT2UMDnk4jRX+w4WO84/pebU2jiLsjgIyrCktYgSvx28enOE3iYQMr+BD1rHiitWnDmpu0cY/LfIEpKcjcw== + version "3.5.4" + resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.5.4.tgz#4a64d57f590e20a898ba057f838dcdfb67a939b9" + integrity sha512-GpKo28q/7Bm5BcX9vOu4S46FwisbPbAmkkqPnGIpKvKTM96I85N6XHQV+k4I6FA2wxgLhcsSyHoNhzucwCflvA== dependencies: - commander "~2.19.0" + commander "~2.20.0" source-map "~0.6.1" uglifyjs-webpack-plugin@^2.1.2: @@ -16241,7 +16244,7 @@ unicode-property-aliases-ecmascript@^1.0.4: resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== -unified@^7.0.2: +unified@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/unified/-/unified-7.1.0.tgz#5032f1c1ee3364bd09da12e27fdd4a7553c7be13" integrity sha512-lbk82UOIGuCEsZhPj8rNAkXSDXd6p0QLzIuSsCdxrqnqU56St4eyOB+AlXsVgVeRmetPTYydIuvFfpDIed8mqw== @@ -16301,6 +16304,13 @@ unist-util-stringify-position@^1.0.0, unist-util-stringify-position@^1.1.1: resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-1.1.2.tgz#3f37fcf351279dcbca7480ab5889bb8a832ee1c6" integrity sha512-pNCVrk64LZv1kElr0N1wPiHEUoXNVFERp+mlTg/s9R5Lwg87f9bM/3sQB99w+N9D/qnM9ar3+AKDBwo/gm/iQQ== +unist-util-stringify-position@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.0.tgz#4c452c0dbcbc509f7bcd366e9a8afd646f9d51ae" + integrity sha512-Uz5negUTrf9zm2ZT2Z9kdOL7Mr7FJLyq3ByqagUi7QZRVK1HnspVazvSqwHt73jj7APHtpuJ4K110Jm8O6/elw== + dependencies: + "@types/unist" "^2.0.2" + universal-analytics@^0.4.17: version "0.4.20" resolved "https://registry.yarnpkg.com/universal-analytics/-/universal-analytics-0.4.20.tgz#d6b64e5312bf74f7c368e3024a922135dbf24b03" @@ -16376,7 +16386,7 @@ url-parse-lax@^1.0.0: dependencies: prepend-http "^1.0.1" -url-parse@1.4.4, url-parse@^1.4.3: +url-parse@1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.4.tgz#cac1556e95faa0303691fec5cf9d5a1bc34648f8" integrity sha512-/92DTTorg4JjktLNLe6GPS2/RvAd/RGr6LuktmWSMLEOa6rjnlrFXNgSbSmkNvCoL2T028A0a1JaJLzRMlFoHg== @@ -16384,6 +16394,14 @@ url-parse@1.4.4, url-parse@^1.4.3: querystringify "^2.0.0" requires-port "^1.0.0" +url-parse@^1.4.3: + version "1.4.6" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.6.tgz#baf91d6e6783c8a795eb476892ffef2737fc0456" + integrity sha512-/B8AD9iQ01seoXmXf9z/MjLZQIdOoYl/+gvsQF6+mpnxaTfG9P7srYaiqaDMyKkR36XMXfhqSHss5MyFAO8lew== + dependencies: + 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" @@ -16535,7 +16553,15 @@ vfile-message@^1.0.0: dependencies: unist-util-stringify-position "^1.1.1" -vfile@^3.0.0, vfile@^3.0.1: +vfile-message@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.0.tgz#750bbb86fe545988a67e899b329bbcabb73edef6" + integrity sha512-YS6qg6UpBfIeiO+6XlhPOuJaoLvt1Y9g2cmlwqhBOOU0XRV8j5RLeoz72t6PWLvNXq3EBG1fQ05wNPrUoz0deQ== + dependencies: + "@types/unist" "^2.0.2" + unist-util-stringify-position "^1.1.1" + +vfile@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/vfile/-/vfile-3.0.1.tgz#47331d2abe3282424f4a4bb6acd20a44c4121803" integrity sha512-y7Y3gH9BsUSdD4KzHsuMaCzRjglXN0W2EcMf0gpvu6+SbsGhMje7xDc8AEoeXy6mIwCKMI6BkjMsRjzQbhMEjQ== @@ -16545,6 +16571,17 @@ vfile@^3.0.0, vfile@^3.0.1: unist-util-stringify-position "^1.0.0" vfile-message "^1.0.0" +vfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.0.0.tgz#ebf3b48af9fcde524d5e08d5f75812058a5f78ad" + integrity sha512-WMNeHy5djSl895BqE86D7WqA0Ie5fAIeGCa7V1EqiXyJg5LaGch2SUaZueok5abYQGH6mXEAsZ45jkoILIOlyA== + dependencies: + "@types/unist" "^2.0.2" + is-buffer "^2.0.0" + replace-ext "1.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + vm-browserify@0.0.4: version "0.0.4" resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-0.0.4.tgz#5d7ea45bbef9e4a6ff65f95438e0a87c357d5a73" @@ -16648,10 +16685,10 @@ web3-bzz@1.0.0-beta.37: swarm-js "0.1.37" underscore "1.8.3" -web3-bzz@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.51.tgz#6956da6d0e3d6a8d602ffec5f03db0da468c6ba5" - integrity sha512-9zDifUc3qPOF2WJ2H/81Ki4rTLa4elB0OG8h3IEYHjXOLDHKzswBQC3favhvm/ZQ2WmnkGd04vsU2iQzBmr1OQ== +web3-bzz@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.52.tgz#36e79ba3b6310485c41528be635fa2b18518903e" + integrity sha512-yva0KW0cIEdFyHaGMHuMGjl4jea/esNBVwfFsejNRJy2W2jSMjnji+AFXnkcq8MhOAyNtQD4WzNdad9F51PaZg== dependencies: "@babel/runtime" "^7.3.1" "@types/node" "^10.12.18" @@ -16676,15 +16713,15 @@ web3-core-helpers@1.0.0-beta.37: web3-eth-iban "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-core-helpers@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.51.tgz#c18dc8634c8db60ab29ffd039819930b520e97ca" - integrity sha512-kA5JMJyrB5yxX3dQuziBP0Yo9i+MKwtYfA2E7DTbEoUueqjPcEwXMUxmpGROYmufCcfoe/B/FqpC8CzkqmHokw== +web3-core-helpers@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.52.tgz#9ba41078f7e144cc2c9887a2a0039cc8d44c485f" + integrity sha512-VJCJMEplvrU7jCgn0MCuLLa+XWkQVttQpShM5i0XkcKs2gmisMtoLO3lATx2b32ruu29EriBYkkAVzc0/nxppg== dependencies: "@babel/runtime" "^7.3.1" lodash "^4.17.11" - web3-eth-iban "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-eth-iban "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" web3-core-method@1.0.0-beta.35: version "1.0.0-beta.35" @@ -16708,10 +16745,10 @@ web3-core-method@1.0.0-beta.37: web3-core-subscriptions "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-core-method@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.51.tgz#1113e6de5b185a80c35a9671fe5c76dc0ad31b29" - integrity sha512-Tl5jGWqx01W6OFPNZI1c4wtCt+HPKWldWrLORKfW0zHyXrYDH6V2BuitA7R7j+54+c/61W3C2E6a+g7sQ8+mWA== +web3-core-method@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.52.tgz#0f80551047e097dde5c60ab82f42b16e1686c421" + integrity sha512-lLbDsV2pxxrUDIWvRI/u6MsvG8mKGfCYOifXqb+yqAruhoNs/Gahoa/1UTjsn0qhVQafsffFRXaEhi6BQDQOYA== dependencies: "@babel/runtime" "^7.3.1" eventemitter3 "3.1.0" @@ -16773,10 +16810,10 @@ web3-core-subscriptions@1.0.0-beta.37: underscore "1.8.3" web3-core-helpers "1.0.0-beta.37" -web3-core-subscriptions@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.51.tgz#64e150d1699543e4ab7bad7a9ce2bb5715a5b2d8" - integrity sha512-bM4KlA37Or/XfrZKLtXlvUSISKWUkXOH/32s0DBnxRkKuey8QKK460H5KF9/HS8LfY7cO11NAepnFe4Tk1rSaQ== +web3-core-subscriptions@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.52.tgz#50a10dd1ee80095cc1d117a7bb35da76b3af174e" + integrity sha512-ZE6VsTVZ9PHV3FOJHnXOxUr4RuwXUpqC+RxCESb/UXvwHNnPbKNPpQjcoc5shaFrtOVtY14bIl35qTxVHSeGWg== dependencies: "@babel/runtime" "^7.3.1" eventemitter3 "^3.1.0" @@ -16802,16 +16839,16 @@ web3-core@1.0.0-beta.37: web3-core-requestmanager "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-core@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.51.tgz#0f6d979186f3624b232bd8b6fe497e70153836ea" - integrity sha512-RZRAt0O+LsU1jV6BtuZBQYjE+YcNa9Bu6FzEAMZ92EdgiAkUB2kbTeipVGCMxOST26kWXUtwCwxkkx4g6iy41A== +web3-core@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.52.tgz#11c949c109871fa1c19b26c70e0e5a3b03f700d2" + integrity sha512-UKHNBIj5b4M40DrGJRQKgWTtbqZCCZck38oQgBbtLAUUQmvlZybLf8jGWUfMamyhJg/eBqT/t1l7OcAn5i9zrA== dependencies: "@babel/runtime" "^7.3.1" "@types/bn.js" "^4.11.4" "@types/node" "^10.12.18" lodash "^4.17.11" - web3-utils "1.0.0-beta.51" + web3-utils "1.0.0-beta.52" web3-eth-abi@1.0.0-beta.35: version "1.0.0-beta.35" @@ -16832,15 +16869,15 @@ web3-eth-abi@1.0.0-beta.37: underscore "1.8.3" web3-utils "1.0.0-beta.37" -web3-eth-abi@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.51.tgz#1ca1415529869b5a6598f6246aff409c3891ae05" - integrity sha512-mTcMpIihZECzZ5oWUh9Jg7x5pVhPv6xPTPWxY9007QKbbBH01GwPogoxBz1X7RfWOwGqZABfxFgXow5NkL0T3A== +web3-eth-abi@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.52.tgz#88dc2d36e2f99dfe255f8f64b6f613bad82779d8" + integrity sha512-c03sH6y7ncp9tBPt0EZEcyFyou4kyYdr72VJMY8ip0JAfZgl4WI9XcGpD207z0lR4Ki1PSCfkh+ZigoXxggouw== dependencies: "@babel/runtime" "^7.3.1" ethers "^4.0.27" lodash "^4.17.11" - web3-utils "1.0.0-beta.51" + web3-utils "1.0.0-beta.52" web3-eth-accounts@1.0.0-beta.35: version "1.0.0-beta.35" @@ -16874,10 +16911,10 @@ web3-eth-accounts@1.0.0-beta.37: web3-core-method "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-eth-accounts@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.51.tgz#5bd3f3d0e63f2cac329d41947d878533afcca9ea" - integrity sha512-6HJu4Vrli7p1S52mV83juFjWn0w7rUE4q9cZdYwsGmqHGrOmV7E3zuBEyuA+kelPLpSmcJDOnEowvORmRdpAyw== +web3-eth-accounts@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.52.tgz#06be3e1dd3a50fc4457c1cea77fc9a51a7baf0b1" + integrity sha512-B52yDVK2/3NKce1CESTZ/sD+6lU9pdNk4tPAtTkWTTPlejAbNlI04SdCX+hn2XJpDjsvU2HRSY3uNugVTrRQ6w== dependencies: "@babel/runtime" "^7.3.1" crypto-browserify "3.12.0" @@ -16885,11 +16922,11 @@ web3-eth-accounts@1.0.0-beta.51: lodash "^4.17.11" scrypt.js "0.2.0" uuid "3.3.2" - web3-core "1.0.0-beta.51" - web3-core-helpers "1.0.0-beta.51" - web3-core-method "1.0.0-beta.51" - web3-providers "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-core "1.0.0-beta.52" + web3-core-helpers "1.0.0-beta.52" + web3-core-method "1.0.0-beta.52" + web3-providers "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" web3-eth-contract@1.0.0-beta.35: version "1.0.0-beta.35" @@ -16919,22 +16956,22 @@ web3-eth-contract@1.0.0-beta.37: web3-eth-abi "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-eth-contract@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.51.tgz#5ec464d007195e6f02118c3a8bb3ece3b67dcd34" - integrity sha512-iVMay6OXDjDPeiPoeGpa6PQGuwIPxL/8UAVIlWVB1CYG9+FY6kcOUO7vI7dnDVwN1zneAslf9h86px6hgR92OQ== +web3-eth-contract@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.52.tgz#9db66edd01433b3edb2bde9bde1314b64890dd04" + integrity sha512-X5Eqi/onxaBw04urowcYXl4L7eS3NuAFdBxSYP14rdTtP03TbgZEJ1GZDftF3cgMorvfGKcTyxyK0VYj/l+lfg== dependencies: "@babel/runtime" "^7.3.1" "@types/bn.js" "^4.11.4" lodash "^4.17.11" - web3-core "1.0.0-beta.51" - web3-core-helpers "1.0.0-beta.51" - web3-core-method "1.0.0-beta.51" - web3-core-subscriptions "1.0.0-beta.51" - web3-eth-abi "1.0.0-beta.51" - web3-eth-accounts "1.0.0-beta.51" - web3-providers "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-core "1.0.0-beta.52" + web3-core-helpers "1.0.0-beta.52" + web3-core-method "1.0.0-beta.52" + web3-core-subscriptions "1.0.0-beta.52" + web3-eth-abi "1.0.0-beta.52" + web3-eth-accounts "1.0.0-beta.52" + web3-providers "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" web3-eth-ens@1.0.0-beta.37: version "1.0.0-beta.37" @@ -16950,22 +16987,22 @@ web3-eth-ens@1.0.0-beta.37: web3-eth-contract "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-eth-ens@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.51.tgz#277222936f1ac9421c1c5f7e14cc4efba82644a2" - integrity sha512-JpHlAIUZGLGTTHWKBFciv5KGBi/+n0uqaO/dXoIfB/jI0Gcm5GYEwUt8TU/Y0/WVHvw/ttU1e0laJYPzTTEB8w== +web3-eth-ens@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.52.tgz#430ad56c70076a2cc868cfe999f4958f7f992b9d" + integrity sha512-8VTOF+v5pAjq1FmakXRceY6VrIoPB7DqfSc+K4aAOJ/tuIMIpe6pt0Bl9IYAbpgFrFqL7ow22d9xcd77ULIwiQ== dependencies: "@babel/runtime" "^7.3.1" eth-ens-namehash "2.0.8" lodash "^4.17.11" - web3-core "1.0.0-beta.51" - web3-core-helpers "1.0.0-beta.51" - web3-core-method "1.0.0-beta.51" - web3-eth-abi "1.0.0-beta.51" - web3-eth-contract "1.0.0-beta.51" - web3-net "1.0.0-beta.51" - web3-providers "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-core "1.0.0-beta.52" + web3-core-helpers "1.0.0-beta.52" + web3-core-method "1.0.0-beta.52" + web3-eth-abi "1.0.0-beta.52" + web3-eth-contract "1.0.0-beta.52" + web3-net "1.0.0-beta.52" + web3-providers "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" web3-eth-iban@1.0.0-beta.35: version "1.0.0-beta.35" @@ -16983,14 +17020,14 @@ web3-eth-iban@1.0.0-beta.37: bn.js "4.11.6" web3-utils "1.0.0-beta.37" -web3-eth-iban@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.51.tgz#40e24e6f1691f28dca18641bffe33aa1557eaecd" - integrity sha512-GNLsEWpEkyJqmogsF+mQLlO06tPOudfhVBCPC68SIOw6wQTqAtoqzOot3EJdrEIDGet9eujOoBs6VWAjNbMGRA== +web3-eth-iban@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.52.tgz#4b953ef78b073701458858872f494edfca4adeab" + integrity sha512-LJZRZ+hZZPU9Fb7xR54mX1li5aKMp9xj9wgZZa4ikdL7iWi0rg1tOacEhbxWGQsjEYhGZYcvxhW9RIdHOwAySg== dependencies: "@babel/runtime" "^7.3.1" bn.js "4.11.8" - web3-utils "1.0.0-beta.51" + web3-utils "1.0.0-beta.52" web3-eth-personal@1.0.0-beta.35: version "1.0.0-beta.35" @@ -17014,18 +17051,18 @@ web3-eth-personal@1.0.0-beta.37: web3-net "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-eth-personal@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.51.tgz#c1839bf4bfd516921133bf74d321840f3fed21a7" - integrity sha512-Mq6uAvhfsKf7FSZVqJOfmb7i5zxQ6HkbTRcAyOOOfSmGnTvxSIjtKZCTAVv3UeBh3pxIXn5FSDlKngaj1MbYXg== +web3-eth-personal@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.52.tgz#5a032d1ea938207be0c077da07ea410dbf7c4c82" + integrity sha512-tNjoB9KztpZL2ayjWYxaInwMrEGxBV7rGMt3hkhk9y4UxlK+8rZtrboz5hggzcgzHaVGnG73rdynhbuPU/cSAQ== dependencies: "@babel/runtime" "^7.3.1" - web3-core "1.0.0-beta.51" - web3-core-helpers "1.0.0-beta.51" - web3-core-method "1.0.0-beta.51" - web3-net "1.0.0-beta.51" - web3-providers "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-core "1.0.0-beta.52" + web3-core-helpers "1.0.0-beta.52" + web3-core-method "1.0.0-beta.52" + web3-net "1.0.0-beta.52" + web3-providers "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" web3-eth@1.0.0-beta.35: version "1.0.0-beta.35" @@ -17064,27 +17101,27 @@ web3-eth@1.0.0-beta.37: web3-net "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-eth@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.51.tgz#43bda606c0e865c448697a9fa409936f37a7b68a" - integrity sha512-w+8YtfKAcEPmOtYf47cjQw3t6dm5YcGvkl4jVZF00WHuvkPMFsXBTbZdH4aVgjPhubl53rdLrJwAP2b7X83+kQ== +web3-eth@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.52.tgz#16b03293f648b3f80bf8d19703dfbe467029d06d" + integrity sha512-mpuIFSIke/ZVdWfEzq0QRJAxcDh50BJflsdUMbNaxf5prP7Sz8FZJz/fHiu4H4cEM6aW8Bi0Hsoqad4+caX6Uw== dependencies: "@babel/runtime" "^7.3.1" ethereumjs-tx "^1.3.7" rxjs "^6.4.0" - web3-core "1.0.0-beta.51" - web3-core-helpers "1.0.0-beta.51" - web3-core-method "1.0.0-beta.51" - web3-core-subscriptions "1.0.0-beta.51" - web3-eth-abi "1.0.0-beta.51" - web3-eth-accounts "1.0.0-beta.51" - web3-eth-contract "1.0.0-beta.51" - web3-eth-ens "1.0.0-beta.51" - web3-eth-iban "1.0.0-beta.51" - web3-eth-personal "1.0.0-beta.51" - web3-net "1.0.0-beta.51" - web3-providers "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-core "1.0.0-beta.52" + web3-core-helpers "1.0.0-beta.52" + web3-core-method "1.0.0-beta.52" + web3-core-subscriptions "1.0.0-beta.52" + web3-eth-abi "1.0.0-beta.52" + web3-eth-accounts "1.0.0-beta.52" + web3-eth-contract "1.0.0-beta.52" + web3-eth-ens "1.0.0-beta.52" + web3-eth-iban "1.0.0-beta.52" + web3-eth-personal "1.0.0-beta.52" + web3-net "1.0.0-beta.52" + web3-providers "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" web3-net@1.0.0-beta.35: version "1.0.0-beta.35" @@ -17104,18 +17141,18 @@ web3-net@1.0.0-beta.37: web3-core-method "1.0.0-beta.37" web3-utils "1.0.0-beta.37" -web3-net@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.51.tgz#a818909f65e8dba1c923abd53b1ab1e99fb9481a" - integrity sha512-1xeBIb/Tvf6PVNZ0u+pPrULNkLefTf0uuo8Hyx82EfY+mvMz6jvNDyFsD8spDGJUuxlDabFnoZdiaEv7LNwwSg== +web3-net@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.52.tgz#2c6c04639bd24e44ef3b220845669926c323aff7" + integrity sha512-rw66c5A5VTF/m3Acnr9ebIAgbr28q5jhXs8A8/F4VjbsDmUhQuQr3deyTPfyOEyupcnn6QRLoQ1EFVzeaUP7Ng== dependencies: "@babel/runtime" "^7.3.1" lodash "^4.17.11" - web3-core "1.0.0-beta.51" - web3-core-helpers "1.0.0-beta.51" - web3-core-method "1.0.0-beta.51" - web3-providers "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-core "1.0.0-beta.52" + web3-core-helpers "1.0.0-beta.52" + web3-core-method "1.0.0-beta.52" + web3-providers "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" web3-provider-engine@14.1.0: version "14.1.0" @@ -17195,17 +17232,17 @@ web3-providers-ws@1.0.0-beta.37: web3-core-helpers "1.0.0-beta.37" websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" -web3-providers@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-providers/-/web3-providers-1.0.0-beta.51.tgz#b2ee544bd75db7ddec400dc0330a277f6d667a0a" - integrity sha512-aWUEZIou4+zEZbLaBf1GQwbNoERq66mLEB6ubcPz1WEq1T5jfUPfwO4b4W2bEbEZVsoxS1ZJvSFkj1yAtD0X+g== +web3-providers@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-providers/-/web3-providers-1.0.0-beta.52.tgz#04a514430dc9740ff6da35334590886a9df4f71c" + integrity sha512-eRmWOn6BeYfAt8UQmCRnqXo1++IjSiIz7+EY9WJ+m7J5ncq/gQN3idWQxT3QZzGRiAvZlO8ZUuF7ff0vuufakg== dependencies: "@babel/runtime" "^7.3.1" "@types/node" "^10.12.18" eventemitter3 "3.1.0" lodash "^4.17.11" url-parse "1.4.4" - websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" + websocket "^1.0.28" xhr2-cookies "1.1.0" web3-shh@1.0.0-beta.35: @@ -17228,19 +17265,19 @@ web3-shh@1.0.0-beta.37: web3-core-subscriptions "1.0.0-beta.37" web3-net "1.0.0-beta.37" -web3-shh@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.51.tgz#69127b33da1ca615aaba6441d42cc88c53ce2827" - integrity sha512-IA4oaNH+PaGWQtTe7BmENszNTeSTsZ15hBNnOrMIyeF0PeghPj7sCenTtU/q8Ie6jR0oXfTXJOQCS/Q/QC3Ksg== +web3-shh@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.52.tgz#02ce376cb7a20276e49701684b5a9eda4e49c6ab" + integrity sha512-Qu9cb9fifUFIDTGujnBnInO3D2OCXDAmCowqMWebEazoZxk9P4oYWmumym1ZErixqEWREb4lkoayyEDSpARzSg== dependencies: "@babel/runtime" "^7.3.1" - web3-core "1.0.0-beta.51" - web3-core-helpers "1.0.0-beta.51" - web3-core-method "1.0.0-beta.51" - web3-core-subscriptions "1.0.0-beta.51" - web3-net "1.0.0-beta.51" - web3-providers "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-core "1.0.0-beta.52" + web3-core-helpers "1.0.0-beta.52" + web3-core-method "1.0.0-beta.52" + web3-core-subscriptions "1.0.0-beta.52" + web3-net "1.0.0-beta.52" + web3-providers "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" web3-utils@1.0.0-beta.35: version "1.0.0-beta.35" @@ -17268,10 +17305,10 @@ web3-utils@1.0.0-beta.37: underscore "1.8.3" utf8 "2.1.1" -web3-utils@1.0.0-beta.51: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.51.tgz#6b0767289be4f27b14895b011bcb5fa6c707fca5" - integrity sha512-c9sRSscu0NIjD96X4ToDOgTxGyJevppuB+uHOgWkziaLGqlw/Li1l24nGkvr0Zqpt9SufvfPcWf8EEC92pnwKg== +web3-utils@1.0.0-beta.52: + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.52.tgz#27f9beeac3e1ea981eba9824d79e2971f156eebc" + integrity sha512-WdHyzPcZu/sOnNrkcOZT20QEX9FhwD9OJJXENojQNvMK2a1xo3n8JWBcC2gzAGwsa0Aah6z2B3Xwa1P//8FaoA== dependencies: "@babel/runtime" "^7.3.1" "@types/bn.js" "^4.11.4" @@ -17343,22 +17380,22 @@ web3@^0.20.1: xmlhttprequest "*" web3@^1.0.0-beta.36: - version "1.0.0-beta.51" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.51.tgz#1099df908ef3421704e0aa0c3ec680d3bd2cf01b" - integrity sha512-cSjJe8AwR9TKELLkGwk2HNL+37e+Y3x0nKkdBNpBZQNZR0SeoT3Jckkd7pBgrJKcyupItN+tKF48x5yNRvHzrQ== + version "1.0.0-beta.52" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.52.tgz#a524888b84206d1ceea8abe1d6056bd7a0a8e33f" + integrity sha512-IWBV1gS7sElHqD2mkwjdyeEmY4YhWn7C+b+pdOWgDJ6j70ux2bqVMfsP0saZ9nWeF1TWMvUnrFsyZ7C4/VnhTA== dependencies: "@babel/runtime" "^7.3.1" "@types/node" "^10.12.18" - web3-bzz "1.0.0-beta.51" - web3-core "1.0.0-beta.51" - web3-core-helpers "1.0.0-beta.51" - web3-core-method "1.0.0-beta.51" - web3-eth "1.0.0-beta.51" - web3-eth-personal "1.0.0-beta.51" - web3-net "1.0.0-beta.51" - web3-providers "1.0.0-beta.51" - web3-shh "1.0.0-beta.51" - web3-utils "1.0.0-beta.51" + web3-bzz "1.0.0-beta.52" + web3-core "1.0.0-beta.52" + web3-core-helpers "1.0.0-beta.52" + web3-core-method "1.0.0-beta.52" + web3-eth "1.0.0-beta.52" + web3-eth-personal "1.0.0-beta.52" + web3-net "1.0.0-beta.52" + web3-providers "1.0.0-beta.52" + web3-shh "1.0.0-beta.52" + web3-utils "1.0.0-beta.52" webidl-conversions@^2.0.0: version "2.0.1" @@ -17488,9 +17525,9 @@ webpack-sources@^1.1.0, webpack-sources@^1.3.0: source-map "~0.6.1" webpack@^4.1.1, webpack@^4.29.0: - version "4.29.6" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.29.6.tgz#66bf0ec8beee4d469f8b598d3988ff9d8d90e955" - integrity sha512-MwBwpiE1BQpMDkbnUUaW6K8RFZjljJHArC6tWQJoFm0oQtfoSebtg4Y7/QHnJ/SddtjYLHaKGX64CFjG5rehJw== + version "4.30.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.30.0.tgz#aca76ef75630a22c49fcc235b39b4c57591d33a9" + integrity sha512-4hgvO2YbAFUhyTdlR4FNyt2+YaYBYHavyzjCMbZzgglo02rlKi/pcsEzwCuCpsn1ryzIl1cq/u8ArIKu8JBYMg== dependencies: "@webassemblyjs/ast" "1.8.5" "@webassemblyjs/helper-module-context" "1.8.5" @@ -17539,6 +17576,16 @@ websocket@1.0.26, "websocket@git://github.com/frozeman/WebSocket-Node.git#browse typedarray-to-buffer "^3.1.2" yaeti "^0.0.6" +websocket@^1.0.28: + version "1.0.28" + resolved "https://registry.yarnpkg.com/websocket/-/websocket-1.0.28.tgz#9e5f6fdc8a3fe01d4422647ef93abdd8d45a78d3" + integrity sha512-00y/20/80P7H4bCYkzuuvvfDvh+dgtXi5kzDf3UcZwN6boTYaKvsrtZ5lIYm1Gsg48siMErd9M4zjSYfYFHTrA== + dependencies: + debug "^2.2.0" + nan "^2.11.0" + typedarray-to-buffer "^3.1.5" + yaeti "^0.0.6" + wget-improved@^1.4.0: version "1.5.0" resolved "https://registry.yarnpkg.com/wget-improved/-/wget-improved-1.5.0.tgz#fc9e89379f6eba72a5586ccc9d52f5580616f20f" From 3c5d7fc7f1205257fa882ac4c0d90ac61aa42f9e Mon Sep 17 00:00:00 2001 From: mmv Date: Mon, 15 Apr 2019 13:50:56 +0400 Subject: [PATCH 28/48] fix token balance updating --- src/routes/safe/container/selector.js | 2 +- src/routes/safe/store/actions/fetchSafe.js | 2 +- src/routes/safe/store/actions/fetchTokenBalances.js | 5 +++++ src/routes/safe/store/reducer/safe.js | 4 +--- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index 9ddf24b091..54aa8b1ac6 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -74,7 +74,7 @@ const extendedSafeTokensSelector: Selector const baseToken = tokensList.get(token.address) if (baseToken) { - map.set(token.address, baseToken.set(token.balance)) + map.set(token.address, baseToken.set('balance', token.balance)) } }) diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 3fbfe6ebe6..17ef2f3a25 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -3,7 +3,7 @@ import type { Dispatch as ReduxDispatch } from 'redux' import { List, Map } from 'immutable' import { type GlobalState } from '~/store/index' import { makeOwner } from '~/routes/safe/store/models/owner' -import { type SafeProps } from '~/routes/safe/store/models/safe' +import type { SafeProps } from '~/routes/safe/store/models/safe' import { addSafe } from '~/routes/safe/store/actions/addSafe' import { getOwners, getSafeName } from '~/logic/safe/utils' import { getGnosisSafeContract } from '~/logic/contracts/safeContracts' diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index 5c56f64359..efb304bae1 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -8,8 +8,13 @@ import SafeTokenRecord from '~/routes/safe/store/models/safeToken' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import type { Safe } from '~/routes/safe/store/models/safe' import updateSafe from './updateSafe' +import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'; export const calculateBalanceOf = async (tokenAddress: string, safeAddress: string, decimals: number = 18) => { + if (tokenAddress === ETH_ADDRESS) { + return '0' + } + const erc20Token = await getStandardTokenContract() let balance = 0 diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index 125c8d1124..df46d1746a 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -76,16 +76,14 @@ export default handleActions( const { safeAddress, token: updatedToken } = action.payload const tokens: List = state.getIn([safeAddress, 'tokens']) - console.log(tokens) const index = tokens.findIndex(token => token.address === updatedToken.address) - console.log('called') + let newState if (index !== -1) { newState = state.setIn([safeAddress, 'tokens'], tokens.delete(index)) } else { newState = state.setIn([safeAddress, 'tokens'], tokens.push(updatedToken)) } - console.log(newState.toJS()) return newState }, From fc3e1e48df74f2c145ee144997dbeb0bc8b42b31 Mon Sep 17 00:00:00 2001 From: mmv Date: Mon, 15 Apr 2019 14:13:47 +0400 Subject: [PATCH 29/48] eslint fix --- src/routes/safe/store/actions/fetchTokenBalances.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index efb304bae1..d821a6fe01 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -8,7 +8,7 @@ import SafeTokenRecord from '~/routes/safe/store/models/safeToken' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import type { Safe } from '~/routes/safe/store/models/safe' import updateSafe from './updateSafe' -import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers'; +import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' export const calculateBalanceOf = async (tokenAddress: string, safeAddress: string, decimals: number = 18) => { if (tokenAddress === ETH_ADDRESS) { From 400a19f901078403273fd31d704c428444c9af30 Mon Sep 17 00:00:00 2001 From: mmv Date: Mon, 15 Apr 2019 15:40:02 +0400 Subject: [PATCH 30/48] fix token balance updating --- src/routes/safe/container/index.jsx | 16 ++++++++++---- src/routes/safe/store/actions/fetchSafe.js | 1 + .../safe/store/actions/fetchTokenBalances.js | 21 ++++++++++--------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index 895fa530ff..135034bcd5 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -16,12 +16,12 @@ const TIMEOUT = process.env.NODE_ENV === 'test' ? 1500 : 15000 class SafeView extends React.Component { componentDidMount() { const { - fetchSafe, loadActiveTokens, activeTokens, safeUrl, fetchTokenBalances, safe, + fetchSafe, loadActiveTokens, activeTokens, safeUrl, fetchTokenBalances, } = this.props fetchSafe(safeUrl) // loadActiveTokens(safeUrl) - fetchTokenBalances(safe, activeTokens) + fetchTokenBalances(safeUrl, activeTokens) this.intervalId = setInterval(() => { // update in another function so it uses up-to-date props values @@ -29,17 +29,25 @@ class SafeView extends React.Component { }, TIMEOUT) } + componentDidUpdate(prevProps) { + const { activeTokens } = this.props + + if (!activeTokens.equals(prevProps.activeTokens)) { + this.checkForUpdates() + } + } + componentWillUnmount() { clearInterval(this.intervalId) } checkForUpdates() { const { - safeUrl, activeTokens, fetchSafe, fetchTokenBalances, safe, + safeUrl, activeTokens, fetchSafe, fetchTokenBalances, } = this.props fetchSafe(safeUrl, true) - fetchTokenBalances(safe, activeTokens) + fetchTokenBalances(safeUrl, activeTokens) } intervalId: IntervalID diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 17ef2f3a25..3f4a1ce629 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -46,6 +46,7 @@ export default (safeAddress: string, update: boolean = false) => async (dispatch const safeProps: SafeProps = await buildSafe(safeAddress, safeName) if (update) { + console.log(safeProps) dispatch(updateSafe(safeProps)) } else { dispatch(addSafe(safeProps)) diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index d821a6fe01..6f6badcca7 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -6,7 +6,6 @@ import { type GlobalState } from '~/store/index' import { type Token } from '~/logic/tokens/store/model/token' import SafeTokenRecord from '~/routes/safe/store/models/safeToken' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' -import type { Safe } from '~/routes/safe/store/models/safe' import updateSafe from './updateSafe' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' @@ -28,22 +27,24 @@ export const calculateBalanceOf = async (tokenAddress: string, safeAddress: stri return new BigNumber(balance).div(10 ** decimals).toString() } -const fetchTokenBalances = (safe: Safe, tokens: List) => async (dispatch: ReduxDispatch) => { - if (!safe || !tokens || !tokens.size) { +const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( + dispatch: ReduxDispatch, +) => { + if (!safeAddress || !tokens || !tokens.size) { return } try { const withBalances = await Promise.all( - tokens.map(async token => SafeTokenRecord({ - address: token.address, - balance: await calculateBalanceOf(token.address, safe.address, token.decimals), - })), + tokens + .filter(token => token.address !== ETH_ADDRESS) + .map(async token => SafeTokenRecord({ + address: token.address, + balance: await calculateBalanceOf(token.address, safeAddress, token.decimals), + })), ) - const safeWithBalances = safe.set('tokens', List(withBalances)) - - dispatch(updateSafe(safeWithBalances)) + dispatch(updateSafe({ address: safeAddress, tokens: List(withBalances) })) } catch (err) { // eslint-disable-next-line console.error('Error while loading active tokens from storage:', err) From d7127fb968bd37afb18355aa9f3ea0ee9e6b8f28 Mon Sep 17 00:00:00 2001 From: mmv Date: Mon, 15 Apr 2019 16:31:30 +0400 Subject: [PATCH 31/48] rewrite active tokens logic to use updateSafe action --- src/routes/safe/store/actions/fetchSafe.js | 1 - .../safe/store/actions/updateActiveTokens.js | 40 +++++++++++-------- src/routes/safe/store/reducer/safe.js | 16 -------- src/routes/safeList/store/selectors/index.js | 11 ----- 4 files changed, 24 insertions(+), 44 deletions(-) diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 3f4a1ce629..17ef2f3a25 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -46,7 +46,6 @@ export default (safeAddress: string, update: boolean = false) => async (dispatch const safeProps: SafeProps = await buildSafe(safeAddress, safeName) if (update) { - console.log(safeProps) dispatch(updateSafe(safeProps)) } else { dispatch(addSafe(safeProps)) diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index 83b71dcf37..96a3b9665b 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -1,30 +1,38 @@ // @flow -import { createAction } from 'redux-actions' -import type { Dispatch as ReduxDispatch } from 'redux' +import { List } from 'immutable' +import type { Dispatch as ReduxDispatch, GetState } from 'redux' import { type GlobalState } from '~/store' import type { SafeToken } from '~/routes/safe/store/models/safeToken' import SafeTokenRecord from '~/routes/safe/store/models/safeToken' +import { safeTokensSelector } from '~/routes/safe/store/selectors/index' +import { SAFE_PARAM_ADDRESS } from '~/routes/routes' +import updateSafe from './updateSafe' -export const UPDATE_SAFE_TOKENS = 'UPDATE_SAFE_TOKENS' - -type ActionReturn = { - token: SafeToken, -} - -export const updateTokenAction = createAction( - UPDATE_SAFE_TOKENS, - (safeAddress: string, token: SafeToken): ActionReturn => ({ - safeAddress, - token, - }), -) +const generateMatchProps = (safeAddress: string) => ({ + match: { + params: { + [SAFE_PARAM_ADDRESS]: safeAddress, + }, + }, +}) const updateActiveTokens = (safeAddress: string, tokenAddress: string) => async ( dispatch: ReduxDispatch, + getState: GetState, ) => { const token: SafeToken = SafeTokenRecord({ address: tokenAddress }) + const state = getState() + const safeTokens: List = safeTokensSelector(state, generateMatchProps(safeAddress)) + const index = safeTokens.findIndex(safeToken => safeToken.address === token.address) + + let updatedTokens + if (index !== -1) { + updatedTokens = safeTokens.delete(index) + } else { + updatedTokens = safeTokens.push(token) + } - dispatch(updateTokenAction(safeAddress, token)) + dispatch(updateSafe({ address: safeAddress, tokens: updatedTokens })) } export default updateActiveTokens diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index df46d1746a..ae4fa407c5 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -8,7 +8,6 @@ import type { SafeToken } from '~/routes/safe/store/models/safeToken' import { loadFromStorage } from '~/utils/storage' import { SAFES_KEY } from '~/logic/safe/utils' import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' -import { UPDATE_SAFE_TOKENS } from '~/routes/safe/store/actions/updateActiveTokens' export const SAFE_REDUCER_ID = 'safes' @@ -72,21 +71,6 @@ export default handleActions( return state.set(safe.address, SafeRecord(safe)) }, - [UPDATE_SAFE_TOKENS]: (state: State, action: ActionType): State => { - const { safeAddress, token: updatedToken } = action.payload - - const tokens: List = state.getIn([safeAddress, 'tokens']) - const index = tokens.findIndex(token => token.address === updatedToken.address) - - let newState - if (index !== -1) { - newState = state.setIn([safeAddress, 'tokens'], tokens.delete(index)) - } else { - newState = state.setIn([safeAddress, 'tokens'], tokens.push(updatedToken)) - } - - return newState - }, }, Map(), ) diff --git a/src/routes/safeList/store/selectors/index.js b/src/routes/safeList/store/selectors/index.js index 2a02a79612..b9247ec0bc 100644 --- a/src/routes/safeList/store/selectors/index.js +++ b/src/routes/safeList/store/selectors/index.js @@ -3,9 +3,6 @@ import { List, Map } from 'immutable' import { createSelector, type Selector } from 'reselect' import { type GlobalState } from '~/store/index' import { type Safe } from '~/routes/safe/store/models/safe' -import { userAccountSelector } from '~/logic/wallets/store/selectors' -import { type Owner } from '~/routes/safe/store/models/owner' -import { sameAddress } from '~/logic/wallets/ethAddresses' import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' export const safesMapSelector = (state: GlobalState): Map => state[SAFE_REDUCER_ID] @@ -14,11 +11,3 @@ export const safesListSelector: Selector> = createSe safesMapSelector, (safes: Map): List => safes.toList(), ) - -// export const safesByOwnerSelector: Selector> = createSelector( -// userAccountSelector, -// safesListSelector, -// (userAddress: string, safes: List): List => safes.filter( -// (safe: Safe) => safe.owners.filter((owner: Owner) => sameAddress(owner.get('address'), userAddress)).count() > 0, -// ), -// ) From 81e05c132dbca4ddfbfbec496675f77955f7ebfd Mon Sep 17 00:00:00 2001 From: mmv Date: Mon, 15 Apr 2019 16:44:17 +0400 Subject: [PATCH 32/48] remove unused vars, add comment for generateProps func --- src/routes/safe/store/actions/updateActiveTokens.js | 2 ++ src/routes/safe/store/reducer/safe.js | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index 96a3b9665b..6acc7a0950 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -8,6 +8,8 @@ import { safeTokensSelector } from '~/routes/safe/store/selectors/index' import { SAFE_PARAM_ADDRESS } from '~/routes/routes' import updateSafe from './updateSafe' +// the selector uses ownProps argument/router props to get the address of the safe +// so in order to use it I had to recreate the same structure const generateMatchProps = (safeAddress: string) => ({ match: { params: { diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index ae4fa407c5..ca0443fe8c 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -1,10 +1,9 @@ // @flow -import { Map, List } from 'immutable' +import { Map } from 'immutable' import { handleActions, type ActionType } from 'redux-actions' import { ADD_SAFE, buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' import SafeRecord, { type Safe, type SafeProps } from '~/routes/safe/store/models/safe' import { type OwnerProps } from '~/routes/safe/store/models/owner' -import type { SafeToken } from '~/routes/safe/store/models/safeToken' import { loadFromStorage } from '~/utils/storage' import { SAFES_KEY } from '~/logic/safe/utils' import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' From 0b6be00632eb630e5274ca3a0743569aeaef28da Mon Sep 17 00:00:00 2001 From: mmv Date: Mon, 15 Apr 2019 17:59:31 +0400 Subject: [PATCH 33/48] fix checkbox displaying in manage tokens modal --- .../safe/component/Balances/Tokens/index.jsx | 37 +++++++++++-------- src/routes/safe/component/Balances/index.jsx | 7 +++- src/routes/safe/store/reducer/safe.js | 4 +- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index 150721994e..1f46fbebdc 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -65,8 +65,7 @@ class Tokens extends React.Component { this.setState(() => ({ filter: value })) } - onSwitch = (token: Token) => (e: SyntheticInputEvent) => { - const { checked } = e.target + onSwitch = (token: Token) => () => { const { safeAddress, updateActiveTokens } = this.props updateActiveTokens(safeAddress, token.address) @@ -78,7 +77,9 @@ class Tokens extends React.Component { } render() { - const { onClose, classes, tokens } = this.props + const { + onClose, classes, tokens, activeTokens, + } = this.props const { filter } = this.state const searchClasses = { input: classes.searchInput, @@ -120,19 +121,23 @@ class Tokens extends React.Component { - {filteredTokens.map((token: Token) => ( - - - {token.name} - - - {token.address !== ETH_ADDRESS && ( - - - - )} - - ))} + {filteredTokens.map((token: Token) => { + const isActive = activeTokens.findIndex(({ address }) => address === token.address) !== -1 + + return ( + + + {token.name} + + + {token.address !== ETH_ADDRESS && ( + + + + )} + + ) + })} ) diff --git a/src/routes/safe/component/Balances/index.jsx b/src/routes/safe/component/Balances/index.jsx index 9b1c66e7db..f1c61517ec 100644 --- a/src/routes/safe/component/Balances/index.jsx +++ b/src/routes/safe/component/Balances/index.jsx @@ -102,7 +102,12 @@ class Balances extends React.Component { handleClose={this.onHide('Token')} open={showToken} > - + diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index ca0443fe8c..cdff553c47 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -25,7 +25,7 @@ export const buildSafe = (storedSafe: SafeProps) => { owners, } - return SafeRecord(safe) + return safe } const buildSafesFrom = (loadedSafes: Object): Map => { @@ -36,7 +36,7 @@ const buildSafesFrom = (loadedSafes: Object): Map => { const safeRecords = keys.map((address: string) => buildSafe(loadedSafes[address])) return safes.withMutations(async (map) => { - safeRecords.forEach((safe: Safe) => map.set(safe.get('address'), safe)) + safeRecords.forEach((safe: SafeProps) => map.set(safe.address, safe)) }) } catch (err) { // eslint-disable-next-line From 2c8a79e58289f17c9888e682bab86292bf3a0f52 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 15 Apr 2019 22:21:39 +0400 Subject: [PATCH 34/48] remove cdu, otherwise it will fail on many token updates because of inconsistent request finishes, debouncing tbd --- src/routes/safe/component/Balances/Tokens/index.jsx | 4 +++- src/routes/safe/container/index.jsx | 12 ++++++------ src/routes/safe/store/actions/updateActiveTokens.js | 9 +++++---- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index 1f46fbebdc..e384e11319 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -25,6 +25,7 @@ import Spacer from '~/components/Spacer' import Row from '~/components/layout/Row' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' import { type Token } from '~/logic/tokens/store/model/token' +import { type SafeToken } from '~/routes/safe/store/models/safeToken' import actions, { type Actions } from './actions' import TokenPlaceholder from './assets/token_placeholder.png' import { styles } from './style' @@ -34,6 +35,7 @@ type Props = Actions & { classes: Object, tokens: List, safeAddress: string, + activeTokens: List } type State = { @@ -68,7 +70,7 @@ class Tokens extends React.Component { onSwitch = (token: Token) => () => { const { safeAddress, updateActiveTokens } = this.props - updateActiveTokens(safeAddress, token.address) + updateActiveTokens(safeAddress, token) } setImageToPlaceholder = (e) => { diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index 135034bcd5..ea6233e60b 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -29,13 +29,13 @@ class SafeView extends React.Component { }, TIMEOUT) } - componentDidUpdate(prevProps) { - const { activeTokens } = this.props + // componentDidUpdate(prevProps) { + // const { activeTokens } = this.props - if (!activeTokens.equals(prevProps.activeTokens)) { - this.checkForUpdates() - } - } + // if (!activeTokens.equals(prevProps.activeTokens)) { + // this.checkForUpdates() + // } + // } componentWillUnmount() { clearInterval(this.intervalId) diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index 6acc7a0950..fd03360ccb 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -6,7 +6,8 @@ import type { SafeToken } from '~/routes/safe/store/models/safeToken' import SafeTokenRecord from '~/routes/safe/store/models/safeToken' import { safeTokensSelector } from '~/routes/safe/store/selectors/index' import { SAFE_PARAM_ADDRESS } from '~/routes/routes' -import updateSafe from './updateSafe' +import type { Token } from '~/logic/tokens/store/model/token' +import updateSafe from '~/routes/safe/store/actions/updateSafe' // the selector uses ownProps argument/router props to get the address of the safe // so in order to use it I had to recreate the same structure @@ -18,11 +19,11 @@ const generateMatchProps = (safeAddress: string) => ({ }, }) -const updateActiveTokens = (safeAddress: string, tokenAddress: string) => async ( +const updateActiveTokens = (safeAddress: string, token: Token) => async ( dispatch: ReduxDispatch, getState: GetState, ) => { - const token: SafeToken = SafeTokenRecord({ address: tokenAddress }) + const safeTokenInstance: SafeToken = SafeTokenRecord({ address: token.address }) const state = getState() const safeTokens: List = safeTokensSelector(state, generateMatchProps(safeAddress)) const index = safeTokens.findIndex(safeToken => safeToken.address === token.address) @@ -31,7 +32,7 @@ const updateActiveTokens = (safeAddress: string, tokenAddress: string) => async if (index !== -1) { updatedTokens = safeTokens.delete(index) } else { - updatedTokens = safeTokens.push(token) + updatedTokens = safeTokens.push(safeTokenInstance) } dispatch(updateSafe({ address: safeAddress, tokens: updatedTokens })) From 7df11f3bcfc26db3315f4ff5f136e2423512b1e6 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Mon, 15 Apr 2019 22:24:43 +0400 Subject: [PATCH 35/48] update fix --- src/routes/safe/container/index.jsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/routes/safe/container/index.jsx b/src/routes/safe/container/index.jsx index ea6233e60b..374089fe89 100644 --- a/src/routes/safe/container/index.jsx +++ b/src/routes/safe/container/index.jsx @@ -29,13 +29,13 @@ class SafeView extends React.Component { }, TIMEOUT) } - // componentDidUpdate(prevProps) { - // const { activeTokens } = this.props + componentDidUpdate(prevProps) { + const { activeTokens } = this.props - // if (!activeTokens.equals(prevProps.activeTokens)) { - // this.checkForUpdates() - // } - // } + if (activeTokens.size > prevProps.activeTokens.size) { + this.checkForUpdates() + } + } componentWillUnmount() { clearInterval(this.intervalId) From b9b936dd51c3f69656c059a6f22fc2748037db89 Mon Sep 17 00:00:00 2001 From: mmv Date: Tue, 16 Apr 2019 14:28:16 +0400 Subject: [PATCH 36/48] activeTokens refactor (again) --- src/routes/safe/container/selector.js | 16 ++++++++++------ .../safe/store/actions/fetchTokenBalances.js | 4 ++-- .../safe/store/actions/updateActiveTokens.js | 13 +++++-------- src/routes/safe/store/models/safe.js | 10 +++++----- src/routes/safe/store/models/safeToken.js | 17 ----------------- src/routes/safe/store/models/tokenBalance.js | 17 +++++++++++++++++ src/routes/safe/store/selectors/index.js | 19 ++++++++++++++----- 7 files changed, 53 insertions(+), 43 deletions(-) delete mode 100644 src/routes/safe/store/models/safeToken.js create mode 100644 src/routes/safe/store/models/tokenBalance.js diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index 54aa8b1ac6..2317fd7afb 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -3,7 +3,8 @@ import { List, Map } from 'immutable' import { createSelector, createStructuredSelector, type Selector } from 'reselect' import { safeSelector, - safeTokensSelector, + safeActiveTokensSelector, + safeBalancesSelector, type RouterProps, type SafeSelectorProps, } from '~/routes/safe/store/selectors' @@ -14,6 +15,7 @@ import { type GlobalState } from '~/store' import { sameAddress } from '~/logic/wallets/ethAddresses' import { orderedTokenListSelector, tokensSelector } from '~/logic/tokens/store/selectors' import { type Token } from '~/logic/tokens/store/model/token' +import { type TokenBalance } from '~/routes/safe/store/models/tokenBalance' import { safeParamAddressSelector } from '../store/selectors' import { getEthAsToken } from '~/logic/tokens/utils/tokenHelpers' @@ -65,16 +67,18 @@ const safeEthAsTokenSelector: Selector = creat ) const extendedSafeTokensSelector: Selector> = createSelector( - safeTokensSelector, + safeActiveTokensSelector, + safeBalancesSelector, tokensSelector, safeEthAsTokenSelector, - (safeTokens: List, tokensList: Map, ethAsToken: Token) => { + (safeTokens: List, balances: List, tokensList: Map, ethAsToken: Token) => { const extendedTokens = Map().withMutations((map) => { - safeTokens.forEach((token: { address: string, balance: string }) => { - const baseToken = tokensList.get(token.address) + safeTokens.forEach((tokenAddress: string) => { + const baseToken = tokensList.get(tokenAddress) + const tokenBalance = balances.find(tknBalance => tknBalance.address === tokenAddress) || '0' if (baseToken) { - map.set(token.address, baseToken.set('balance', token.balance)) + map.set(tokenAddress, baseToken.set('balance', tokenBalance)) } }) diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index 6f6badcca7..93b301a2cb 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -4,7 +4,7 @@ import { List } from 'immutable' import { BigNumber } from 'bignumber.js' import { type GlobalState } from '~/store/index' import { type Token } from '~/logic/tokens/store/model/token' -import SafeTokenRecord from '~/routes/safe/store/models/safeToken' +import TokenBalanceRecord from '~/routes/safe/store/models/tokenBalance' import { getStandardTokenContract } from '~/logic/tokens/store/actions/fetchTokens' import updateSafe from './updateSafe' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' @@ -38,7 +38,7 @@ const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( const withBalances = await Promise.all( tokens .filter(token => token.address !== ETH_ADDRESS) - .map(async token => SafeTokenRecord({ + .map(async token => TokenBalanceRecord({ address: token.address, balance: await calculateBalanceOf(token.address, safeAddress, token.decimals), })), diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index 6acc7a0950..08ddf94c44 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -2,9 +2,7 @@ import { List } from 'immutable' import type { Dispatch as ReduxDispatch, GetState } from 'redux' import { type GlobalState } from '~/store' -import type { SafeToken } from '~/routes/safe/store/models/safeToken' -import SafeTokenRecord from '~/routes/safe/store/models/safeToken' -import { safeTokensSelector } from '~/routes/safe/store/selectors/index' +import { safeActiveTokensSelector } from '~/routes/safe/store/selectors' import { SAFE_PARAM_ADDRESS } from '~/routes/routes' import updateSafe from './updateSafe' @@ -22,19 +20,18 @@ const updateActiveTokens = (safeAddress: string, tokenAddress: string) => async dispatch: ReduxDispatch, getState: GetState, ) => { - const token: SafeToken = SafeTokenRecord({ address: tokenAddress }) const state = getState() - const safeTokens: List = safeTokensSelector(state, generateMatchProps(safeAddress)) - const index = safeTokens.findIndex(safeToken => safeToken.address === token.address) + const safeTokens: List = safeActiveTokensSelector(state, generateMatchProps(safeAddress)) + const index = safeTokens.findIndex(safeToken => safeToken === tokenAddress) let updatedTokens if (index !== -1) { updatedTokens = safeTokens.delete(index) } else { - updatedTokens = safeTokens.push(token) + updatedTokens = safeTokens.push(tokenAddress) } - dispatch(updateSafe({ address: safeAddress, tokens: updatedTokens })) + dispatch(updateSafe({ address: safeAddress, activeTokens: updatedTokens })) } export default updateActiveTokens diff --git a/src/routes/safe/store/models/safe.js b/src/routes/safe/store/models/safe.js index 32bfdcd6e0..480f95dfcf 100644 --- a/src/routes/safe/store/models/safe.js +++ b/src/routes/safe/store/models/safe.js @@ -2,14 +2,15 @@ import { List, Record } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' import type { Owner } from '~/routes/safe/store/models/owner' -import type { SafeToken } from '~/routes/safe/store/models/safeToken' +import TokenBalance from '~/routes/safe/store/models/tokenBalance' export type SafeProps = { name: string, address: string, threshold: number, owners: List, - tokens?: List, + balances?: List, + activeTokens?: List, ethBalance?: string, } @@ -19,11 +20,10 @@ const SafeRecord: RecordFactory = Record({ threshold: 0, ethBalance: 0, owners: List([]), - tokens: List([]), + activeTokens: List([]), + balances: List([]), }) -// Tokens is a list of currently enabled tokens for the safe with balances - export type Safe = RecordOf export default SafeRecord diff --git a/src/routes/safe/store/models/safeToken.js b/src/routes/safe/store/models/safeToken.js deleted file mode 100644 index 8d4b3e05b8..0000000000 --- a/src/routes/safe/store/models/safeToken.js +++ /dev/null @@ -1,17 +0,0 @@ -// @flow -import { Record } from 'immutable' -import type { RecordFactory, RecordOf } from 'immutable' - -export type SafeTokenProps = { - address: string, - balance: string, -} - -const SafeTokenRecord: RecordFactory = Record({ - address: '', - balance: '0', -}) - -export type SafeToken = RecordOf - -export default SafeTokenRecord diff --git a/src/routes/safe/store/models/tokenBalance.js b/src/routes/safe/store/models/tokenBalance.js new file mode 100644 index 0000000000..b8f1ed80eb --- /dev/null +++ b/src/routes/safe/store/models/tokenBalance.js @@ -0,0 +1,17 @@ +// @flow +import { Record } from 'immutable' +import type { RecordFactory, RecordOf } from 'immutable' + +export type TokenBalanceProps = { + address: string, + balance: string, +} + +const TokenBalanceRecord: RecordFactory = Record({ + address: '', + balance: '0', +}) + +export type TokenBalance = RecordOf + +export default TokenBalanceRecord diff --git a/src/routes/safe/store/selectors/index.js b/src/routes/safe/store/selectors/index.js index 470915b6fa..100e3cbd47 100644 --- a/src/routes/safe/store/selectors/index.js +++ b/src/routes/safe/store/selectors/index.js @@ -78,20 +78,29 @@ export const safeSelector: Selector }, ) -export const safeTokensSelector: Selector> = createSelector( +export const safeActiveTokensSelector: Selector> = createSelector( safeSelector, (safe: Safe) => { if (!safe) { - return Map() + return List() } - const tokens = safe.get('tokens') + return safe.activeTokens + }, +) + +export const safeBalancesSelector: Selector> = createSelector( + safeSelector, + (safe: Safe) => { + if (!safe) { + return List() + } - return tokens + return safe.balances }, ) export default createStructuredSelector({ safe: safeSelector, - tokens: safeTokensSelector, + tokens: safeActiveTokensSelector, }) From 76b41a4cbb4be334e306c8fd05992b27e1643b40 Mon Sep 17 00:00:00 2001 From: mmv Date: Tue, 16 Apr 2019 15:13:08 +0400 Subject: [PATCH 37/48] merge fixes --- src/routes/safe/component/Balances/Tokens/index.jsx | 2 +- src/routes/safe/store/actions/fetchTokenBalances.js | 2 +- src/routes/safe/store/actions/updateActiveTokens.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index e384e11319..870c5042e7 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -70,7 +70,7 @@ class Tokens extends React.Component { onSwitch = (token: Token) => () => { const { safeAddress, updateActiveTokens } = this.props - updateActiveTokens(safeAddress, token) + updateActiveTokens(safeAddress, token.address) } setImageToPlaceholder = (e) => { diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index 93b301a2cb..2c602fde3c 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -44,7 +44,7 @@ const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( })), ) - dispatch(updateSafe({ address: safeAddress, tokens: List(withBalances) })) + dispatch(updateSafe({ address: safeAddress, balances: List(withBalances) })) } catch (err) { // eslint-disable-next-line console.error('Error while loading active tokens from storage:', err) diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index a63d2f5db3..affddef190 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -23,7 +23,7 @@ const updateActiveTokens = (safeAddress: string, tokenAddress: string) => async ) => { const state = getState() const safeTokens: List = safeActiveTokensSelector(state, generateMatchProps(safeAddress)) - const index = safeTokens.findIndex(safeToken => safeToken === tokenAddress) + const index = safeTokens.findIndex(address => address === tokenAddress) let updatedTokens if (index !== -1) { From 4c1197a3b53e5afa3a82370031efc8e022ebfad2 Mon Sep 17 00:00:00 2001 From: mmv Date: Tue, 16 Apr 2019 15:15:56 +0400 Subject: [PATCH 38/48] fix token balance selector --- src/routes/safe/container/selector.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index 2317fd7afb..c9eddd0249 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -75,10 +75,10 @@ const extendedSafeTokensSelector: Selector const extendedTokens = Map().withMutations((map) => { safeTokens.forEach((tokenAddress: string) => { const baseToken = tokensList.get(tokenAddress) - const tokenBalance = balances.find(tknBalance => tknBalance.address === tokenAddress) || '0' + const tokenBalance = balances.find(tknBalance => tknBalance.address === tokenAddress) if (baseToken) { - map.set(tokenAddress, baseToken.set('balance', tokenBalance)) + map.set(tokenAddress, baseToken.set('balance', tokenBalance ? tokenBalance.balance : '0')) } }) From 3373b83a2775fcf769149e4b35f698548418853b Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 16 Apr 2019 16:13:28 +0400 Subject: [PATCH 39/48] storage middleware wip, add optimization comment --- src/logic/tokens/store/actions/addToken.js | 2 +- .../safe/component/Balances/Tokens/index.jsx | 7 ++++++- .../safe/store/middleware/safeStorage.js | 21 +++++++++++++++++++ src/store/index.js | 3 ++- 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 src/routes/safe/store/middleware/safeStorage.js diff --git a/src/logic/tokens/store/actions/addToken.js b/src/logic/tokens/store/actions/addToken.js index 725324b5f0..71c927c900 100644 --- a/src/logic/tokens/store/actions/addToken.js +++ b/src/logic/tokens/store/actions/addToken.js @@ -3,7 +3,7 @@ import { createAction } from 'redux-actions' import { type Token } from '~/logic/tokens/store/model/token' import { setActiveTokens, getActiveTokens, setToken } from '~/logic/tokens/utils/tokensStorage' import type { Dispatch as ReduxDispatch } from 'redux' -import { type GlobalState } from '~/store/index' +import { type GlobalState } from '~/store/' export const ADD_TOKEN = 'ADD_TOKEN' diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index 870c5042e7..a074be015c 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -25,7 +25,7 @@ import Spacer from '~/components/Spacer' import Row from '~/components/layout/Row' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' import { type Token } from '~/logic/tokens/store/model/token' -import { type SafeToken } from '~/routes/safe/store/models/safeToken' +import { type TokenBalance } from '~/routes/safe/store/models/tokenBalance' import actions, { type Actions } from './actions' import TokenPlaceholder from './assets/token_placeholder.png' import { styles } from './style' @@ -48,6 +48,11 @@ const filterBy = (filter: string, tokens: List): List => tokens.fi || token.name.toLowerCase().includes(filter.toLowerCase()), ) +// OPTIMIZATION IDEA (Thanks Andre) +// Calculate active tokens on component mount, store it in component state +// After user closes modal, dispatch an action so we dont have 100500 actions +// And selectors dont recalculate + class Tokens extends React.Component { state = { filter: '', diff --git a/src/routes/safe/store/middleware/safeStorage.js b/src/routes/safe/store/middleware/safeStorage.js new file mode 100644 index 0000000000..78c55a95d9 --- /dev/null +++ b/src/routes/safe/store/middleware/safeStorage.js @@ -0,0 +1,21 @@ +// @flow +import { ADD_SAFE } from '~/routes/safe/store/actions/addSafe' +import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' +import { saveToStorage } from '~/utils/storage' +import { SAFES_KEY } from '~/logic/safe/utils' +import type { GetState } from 'redux' +import { type GlobalState } from '~/store/' + +const watchedActions = [ADD_SAFE, UPDATE_SAFE] + +const safeStorageMware = store => next => async (action) => { + const handledAction = next(action) + if (watchedActions.includes(action.type)) { + const { getState }: { getState: GetState } = store + const state: GlobalState = store.getState() + console.log(state) + } + return handledAction +} + +export default safeStorageMware diff --git a/src/store/index.js b/src/store/index.js index 084d7f850c..9542511c57 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -7,6 +7,7 @@ import { import thunk from 'redux-thunk' import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/logic/wallets/store/reducer/provider' import safe, { SAFE_REDUCER_ID, type State as SafeState } from '~/routes/safe/store/reducer/safe' +import safeStorage from '~/routes/safe/store/middleware/safeStorage' import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/logic/tokens/store/reducer/tokens' import transactions, { type State as TransactionsState, @@ -17,7 +18,7 @@ export const history = createBrowserHistory() // eslint-disable-next-line const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose -const finalCreateStore = composeEnhancers(applyMiddleware(thunk, routerMiddleware(history))) +const finalCreateStore = composeEnhancers(applyMiddleware(thunk, routerMiddleware(history), safeStorage)) export type GlobalState = { providers: ProviderState, From 7e49f8dd16fff8df6d0f75e0d51231d4b7a8e47e Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Tue, 16 Apr 2019 16:41:36 +0400 Subject: [PATCH 40/48] fix storing safe in localstorage --- src/routes/safe/store/actions/addSafe.js | 12 ++---------- .../safe/store/middleware/safeStorage.js | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/src/routes/safe/store/actions/addSafe.js b/src/routes/safe/store/actions/addSafe.js index c6d237eaf9..af89c35c27 100644 --- a/src/routes/safe/store/actions/addSafe.js +++ b/src/routes/safe/store/actions/addSafe.js @@ -1,12 +1,10 @@ // @flow import { List } from 'immutable' import { createAction } from 'redux-actions' -import type { Dispatch as ReduxDispatch, GetState } from 'redux' +import type { Dispatch as ReduxDispatch } from 'redux' import { type GlobalState } from '~/store' -import { saveSafes, setOwners } from '~/logic/safe/utils' import SafeRecord, { type Safe } from '~/routes/safe/store/models/safe' import { makeOwner, type Owner } from '~/routes/safe/store/models/owner' -import { safesMapSelector } from '~/routes/safeList/store/selectors/index' export const ADD_SAFE = 'ADD_SAFE' @@ -33,9 +31,8 @@ const saveSafe = ( threshold: number, ownersName: string[], ownersAddress: string[], -) => async (dispatch: ReduxDispatch, getState: GetState) => { +) => async (dispatch: ReduxDispatch) => { const owners: List = buildOwnersFrom(ownersName, ownersAddress) - const state: GlobalState = getState() const safe: Safe = SafeRecord({ name, @@ -43,11 +40,6 @@ const saveSafe = ( threshold, owners, }) - const safes = safesMapSelector(state) - const newSafes = safes.set(address, safe) - - setOwners(address, owners) - saveSafes(newSafes.toJSON()) dispatch(addSafe(safe)) } diff --git a/src/routes/safe/store/middleware/safeStorage.js b/src/routes/safe/store/middleware/safeStorage.js index 78c55a95d9..90d0d6a625 100644 --- a/src/routes/safe/store/middleware/safeStorage.js +++ b/src/routes/safe/store/middleware/safeStorage.js @@ -1,20 +1,27 @@ // @flow import { ADD_SAFE } from '~/routes/safe/store/actions/addSafe' import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' -import { saveToStorage } from '~/utils/storage' -import { SAFES_KEY } from '~/logic/safe/utils' -import type { GetState } from 'redux' +import type { Store, AnyAction } from 'redux' import { type GlobalState } from '~/store/' +import { saveSafes, setOwners } from '~/logic/safe/utils' +import { safesMapSelector } from '~/routes/safeList/store/selectors/index' const watchedActions = [ADD_SAFE, UPDATE_SAFE] -const safeStorageMware = store => next => async (action) => { +const safeStorageMware = (store: Store) => (next: Function) => async (action: AnyAction) => { const handledAction = next(action) + if (watchedActions.includes(action.type)) { - const { getState }: { getState: GetState } = store const state: GlobalState = store.getState() - console.log(state) + const safes = safesMapSelector(state) + saveSafes(safes.toJSON()) + + if (action.type === ADD_SAFE) { + const { safe } = action.payload + setOwners(safe.address, safe.owners) + } } + return handledAction } From dc185e893cd1102be5ace941dfe26bc268cdb35b Mon Sep 17 00:00:00 2001 From: mmv Date: Wed, 17 Apr 2019 12:28:28 +0400 Subject: [PATCH 41/48] fix safe loading from storage wip --- package.json | 10 +- src/routes/safe/store/reducer/safe.js | 11 +- yarn.lock | 248 +++++++++++++------------- 3 files changed, 135 insertions(+), 134 deletions(-) diff --git a/package.json b/package.json index b8eb17d42e..16ecabd9e2 100644 --- a/package.json +++ b/package.json @@ -117,10 +117,10 @@ "@babel/preset-flow": "^7.0.0-beta.40", "@babel/preset-react": "^7.0.0-beta.40", "@sambego/storybook-state": "^1.0.7", - "@storybook/addon-actions": "^5.0.6", - "@storybook/addon-knobs": "^5.0.6", - "@storybook/addon-links": "^5.0.6", - "@storybook/react": "^5.0.6", + "@storybook/addon-actions": "5.0.9", + "@storybook/addon-knobs": "5.0.9", + "@storybook/addon-links": "5.0.9", + "@storybook/react": "5.0.9", "autoprefixer": "9.5.1", "babel-core": "^7.0.0-bridge.0", "babel-eslint": "^10.0.1", @@ -135,7 +135,7 @@ "eslint": "^5.16.0", "eslint-config-airbnb": "^17.1.0", "eslint-plugin-flowtype": "3.6.1", - "eslint-plugin-import": "^2.9.0", + "eslint-plugin-import": "2.17.2", "eslint-plugin-jest": "^22.3.0", "eslint-plugin-jsx-a11y": "^6.0.3", "eslint-plugin-react": "^7.7.0", diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index cdff553c47..fd89d13682 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -18,10 +18,7 @@ export const buildSafe = (storedSafe: SafeProps) => { const owners = buildOwnersFrom(Array.from(names), Array.from(addresses)) const safe: SafeProps = { - address: storedSafe.address, - name: storedSafe.name, - threshold: storedSafe.threshold, - tokens: storedSafe.tokens, + ...storedSafe, owners, } @@ -62,12 +59,16 @@ export default handleActions( return state.mergeIn([safeAddress], safe) }, [ADD_SAFE]: (state: State, action: ActionType): State => { - const { safe }: { safe: Safe } = action.payload + const { safe }: { safe: SafeProps } = action.payload // if you add a new safe it needs to be set as a record // in case of update it shouldn't, because a record would be initialized // with initial props and it would overwrite existing ones + if (state.has(safe.address)) { + return state.mergeIn([safe.address], safe) + } + return state.set(safe.address, SafeRecord(safe)) }, }, diff --git a/yarn.lock b/yarn.lock index e80baea973..73f8460b16 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1571,6 +1571,26 @@ dependencies: uuid "^3.1.0" +"@storybook/addon-actions@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.0.9.tgz#c604ea9086ff517a488a2605ff040539ae68b103" + integrity sha512-npkesPnVB8Vi18pM0wT3fn67DqZ3lZmxqahdHn+SI7ROR+Jm6mcOAOCPqKZtpWIyvLBqgK8BuodXNL04cNhIeg== + dependencies: + "@storybook/addons" "5.0.9" + "@storybook/components" "5.0.9" + "@storybook/core-events" "5.0.9" + "@storybook/theming" "5.0.9" + core-js "^2.6.5" + fast-deep-equal "^2.0.1" + global "^4.3.2" + lodash "^4.17.11" + make-error "^1.3.5" + polished "^2.3.3" + prop-types "^15.6.2" + react "^16.8.1" + react-inspector "^2.3.0" + uuid "^3.3.2" + "@storybook/addon-actions@^3.2.10": version "3.4.12" resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-3.4.12.tgz#ff6cbaf563c3cb5d648d6a35f66cfa50ced49bf4" @@ -1587,35 +1607,15 @@ react-inspector "^2.2.2" uuid "^3.2.1" -"@storybook/addon-actions@^5.0.6": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/addon-actions/-/addon-actions-5.0.8.tgz#85b74bd7c672d4e668830c7e7bc820f7c35daf2c" - integrity sha512-MwIYzJGi1Pok9CkTznqABT+rGLBDURixKgkzGEphMLDWXQSOIg8AdLvlr8EC1U+pDyFqgG9fGeDgOa8W5bVdHQ== - dependencies: - "@storybook/addons" "5.0.8" - "@storybook/components" "5.0.8" - "@storybook/core-events" "5.0.8" - "@storybook/theming" "5.0.8" - core-js "^2.6.5" - fast-deep-equal "^2.0.1" - global "^4.3.2" - lodash "^4.17.11" - make-error "^1.3.5" - polished "^2.3.3" - prop-types "^15.6.2" - react "^16.8.1" - react-inspector "^2.3.0" - uuid "^3.3.2" - -"@storybook/addon-knobs@^5.0.6": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.0.8.tgz#6d20e29e409839b6bbfcb7a6063dae683f88b619" - integrity sha512-fW6Zwb3rwfOvXXuEwrgAEUpISRINMmTRzkwI6cMclvwoG3S9T+VdU1/WFttwAVmrJRbjb3cNOyFldXNDTWenlA== +"@storybook/addon-knobs@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-knobs/-/addon-knobs-5.0.9.tgz#1310822a0cccc3606fe28e9c42e30982f28cf90a" + integrity sha512-ZMSbd507Brvsn6Flm1V0DQVM50ZtbBlu5+wZRXCMwBA7D2pYVJbjwYVdRl7Ms4RA4g6u3GzRfzCPIXefs91qbQ== dependencies: - "@storybook/addons" "5.0.8" - "@storybook/components" "5.0.8" - "@storybook/core-events" "5.0.8" - "@storybook/theming" "5.0.8" + "@storybook/addons" "5.0.9" + "@storybook/components" "5.0.9" + "@storybook/core-events" "5.0.9" + "@storybook/theming" "5.0.9" copy-to-clipboard "^3.0.8" core-js "^2.6.5" escape-html "^1.0.3" @@ -1629,57 +1629,57 @@ react-select "^2.3.0" util-deprecate "^1.0.2" -"@storybook/addon-links@^5.0.6": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-5.0.8.tgz#2ab42a45641180677561ff8cb069c4bd0877b16a" - integrity sha512-KwEIfFgBNcxpTAu+o0L8DV4vg7HP740Fm5RSFH3APGCE8MrmRL+hVcMEcp9KmFf6FMD/V7y5nku4jhlbGjAi1w== +"@storybook/addon-links@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/addon-links/-/addon-links-5.0.9.tgz#e450b5038a31cc6e83167c7fa497500c2c5388f8" + integrity sha512-EmK5MnjmELg3XIlEVboOfNlJPLm/flqgtPuRCqZZFQQTN3I+dP7vcdel2y2Q6QlRP4cuODHTuYL+2sXauWtDDQ== dependencies: - "@storybook/addons" "5.0.8" - "@storybook/core-events" "5.0.8" + "@storybook/addons" "5.0.9" + "@storybook/core-events" "5.0.9" common-tags "^1.8.0" core-js "^2.6.5" global "^4.3.2" prop-types "^15.6.2" qs "^6.5.2" -"@storybook/addons@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.0.8.tgz#9bca24ab8e95a36dc91e4e2855449e751702cdfb" - integrity sha512-Tl/ntlBt+KfAEaLyzfFTJsqmawtmKvrJDy8kqNM1oIfsOxig25T9eqU8RfWgK99bMdsbhA99P+cplk6LuVY1Ww== +"@storybook/addons@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/addons/-/addons-5.0.9.tgz#27791868c84acf36e16ec7b0c61c878b82dbae32" + integrity sha512-PzAiLWziVpLlyZ6yzu8f86J9HIbUiSbbRe4t9nMrR9W54rbIqciM9DFq0HdX2KkuTFhQWnAdzD/WhpLcZpB5PA== dependencies: - "@storybook/channels" "5.0.8" - "@storybook/client-logger" "5.0.8" + "@storybook/channels" "5.0.9" + "@storybook/client-logger" "5.0.9" core-js "^2.6.5" global "^4.3.2" util-deprecate "^1.0.2" -"@storybook/channel-postmessage@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.0.8.tgz#b68ea103d4401abdef540bb21b20f54b4665bba7" - integrity sha512-Gl7+bshczSTHpQa4FzL19+xyzOK9vTUh2pGQwBEp2zZXVGD46vLyUKsnYCqm+/vrWg/1mx/I1GzqAmqkhH2CuA== +"@storybook/channel-postmessage@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/channel-postmessage/-/channel-postmessage-5.0.9.tgz#e357f3645cf1ac708a00e345841ce94cf9ab7e81" + integrity sha512-GEmYXOFZf1M3CqvB71F5e5MZmEHsOjwdggyxXymzpnjbe9NtUyUKkvU7NCE5/Xmv6SA6Am9lyyrAjQ8EnQBdeA== dependencies: - "@storybook/channels" "5.0.8" - "@storybook/client-logger" "5.0.8" + "@storybook/channels" "5.0.9" + "@storybook/client-logger" "5.0.9" core-js "^2.6.5" global "^4.3.2" telejson "^2.1.0" -"@storybook/channels@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.0.8.tgz#d44517cd6f19f87ccab5e899bd9b515a4395c97c" - integrity sha512-t0PVow9xxQMK04ltp1LtrACG5f63vUM/THtdtoucxepirpfTGr+9B2SP791ZDtpARp5sFqAB7CGN8zDGfZF7lQ== +"@storybook/channels@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/channels/-/channels-5.0.9.tgz#a750b349a8278ab58bdcc41ae00f5cb60644ad83" + integrity sha512-JX9repbRH6WVRT1A6KQA7mDkowFhWHJbMG8WtZ1hCXgwFBKmN01IKspZrZj9vokyVIngWGxt52BnOJ6NdaF5SA== dependencies: core-js "^2.6.5" -"@storybook/client-api@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.0.8.tgz#42d058007835b6fc941b133542bcd232fd816d4d" - integrity sha512-djBVje/ZMkwdIzrZGtkDHrMy6HHDOrQSL0ppk2YgYaB40IF5KPhjnoPH09sOFHy9uW9d3chWQlkAESIjPQwpCA== +"@storybook/client-api@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/client-api/-/client-api-5.0.9.tgz#d0942a17aa114129a2bcb7eae32eeccb0b54e126" + integrity sha512-HkquVtwfX0lX0J2t+sQJ54FKOiVwg3QbpWyi9Ujf8QPS3xDR1BpJqZ+P7DjLZDYFcPmeb5QWokA59fEANwutNw== dependencies: - "@storybook/addons" "5.0.8" - "@storybook/client-logger" "5.0.8" - "@storybook/core-events" "5.0.8" - "@storybook/router" "5.0.8" + "@storybook/addons" "5.0.9" + "@storybook/client-logger" "5.0.9" + "@storybook/core-events" "5.0.9" + "@storybook/router" "5.0.9" common-tags "^1.8.0" core-js "^2.6.5" eventemitter3 "^3.1.0" @@ -1691,10 +1691,10 @@ memoizerific "^1.11.3" qs "^6.5.2" -"@storybook/client-logger@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.0.8.tgz#d37ee57f7d6ec207f60c3f87163d564427f5b82c" - integrity sha512-PKmSx6M7WNHwUUh4R9OluKWZfkHN7PztaRWrp9dvNy9rOd/c7vVWK1ekGRaMR06MHkszZ5boPerV8c9xEydEfg== +"@storybook/client-logger@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/client-logger/-/client-logger-5.0.9.tgz#39dcabcfaee3ea04cab5a95ac9027459581d1731" + integrity sha512-EIWrXzScR5Ex1rdPgngECFrY8c/ngR4V6lgMdEJypW2GUbcRDRZPdJ13KSaDvkbSwkfHKZmKsjYLlOM2Ss0oOg== dependencies: core-js "^2.6.5" @@ -1707,16 +1707,16 @@ glamorous "^4.12.1" prop-types "^15.6.1" -"@storybook/components@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.0.8.tgz#9dc83b2cd13bd37ab17ebf804ec13c922018195e" - integrity sha512-aIU/lySNIei4YljCd6uYcMgg1pRuQ08hPzk3aJ8OHODAOXUxWCN8STyPwB6h2q01HFZ0rhlEDeoybszFr7bORQ== +"@storybook/components@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/components/-/components-5.0.9.tgz#981610abea5fba57f7399e62728cac9fd9339db9" + integrity sha512-4CCfVva0S4HkeotyvBSSjatAiPeUFZUpMm7YB586vsAGKmobZnLUZ2jKoYKZTJS/Z7WVOnHHLLv+wQ/PvYZpew== dependencies: - "@storybook/addons" "5.0.8" - "@storybook/client-logger" "5.0.8" - "@storybook/core-events" "5.0.8" - "@storybook/router" "5.0.8" - "@storybook/theming" "5.0.8" + "@storybook/addons" "5.0.9" + "@storybook/client-logger" "5.0.9" + "@storybook/core-events" "5.0.9" + "@storybook/router" "5.0.9" + "@storybook/theming" "5.0.9" core-js "^2.6.5" global "^4.3.2" immer "^1.12.0" @@ -1738,32 +1738,32 @@ recompose "^0.30.0" render-fragment "^0.1.1" -"@storybook/core-events@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.0.8.tgz#9d941dd748590185d3a2e0a4aeb1365be1778c62" - integrity sha512-3sTAtkebvQOuu5OxHHPK3xGP1RBp65Nls3t3l3KAZEqQ5vQ0w30lbe0gEWMqLz4MMCy84E+Xz297G3a74eQ/xA== +"@storybook/core-events@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/core-events/-/core-events-5.0.9.tgz#4b7a33f271a5ed7994a702c74d6a3ad117ba168f" + integrity sha512-gZtqZRflqhtH7uJMkdTWn4bRlfQU0PrAb/VeSCv20N/3HGCyKOwKhzCeV74u8A0FyVMVJfM0vWrjKMBC9LNyUQ== dependencies: core-js "^2.6.5" -"@storybook/core@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.0.8.tgz#59de7c0ffdad4eb79054ddf9c5da3108a35f993d" - integrity sha512-tUdRnsdvcuoNF2lAB4e0mztcX4iunHFD+30QcAiTY9ShNBKvL73wLxVhzP+gfY0XqA9XnUb4t1XM/8t7VzOpCQ== +"@storybook/core@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/core/-/core-5.0.9.tgz#2bad4eebc4cdc5aaf12635a53f3cd7612ee77278" + integrity sha512-OT7TFzCUOhmYiWhj1txbWFBW9HeyAYePcJyp6UARWK20TPR45OS5DZSJq2LF/DaIUrtVGJmwxMWNp08mkazhQA== dependencies: "@babel/plugin-proposal-class-properties" "^7.3.0" "@babel/plugin-proposal-object-rest-spread" "^7.3.2" "@babel/plugin-syntax-dynamic-import" "^7.2.0" "@babel/plugin-transform-react-constant-elements" "^7.2.0" "@babel/preset-env" "^7.4.1" - "@storybook/addons" "5.0.8" - "@storybook/channel-postmessage" "5.0.8" - "@storybook/client-api" "5.0.8" - "@storybook/client-logger" "5.0.8" - "@storybook/core-events" "5.0.8" - "@storybook/node-logger" "5.0.8" - "@storybook/router" "5.0.8" - "@storybook/theming" "5.0.8" - "@storybook/ui" "5.0.8" + "@storybook/addons" "5.0.9" + "@storybook/channel-postmessage" "5.0.9" + "@storybook/client-api" "5.0.9" + "@storybook/client-logger" "5.0.9" + "@storybook/core-events" "5.0.9" + "@storybook/node-logger" "5.0.9" + "@storybook/router" "5.0.9" + "@storybook/theming" "5.0.9" + "@storybook/ui" "5.0.9" airbnb-js-shims "^1 || ^2" autoprefixer "^9.4.7" babel-plugin-add-react-displayname "^0.0.5" @@ -1819,10 +1819,10 @@ webpack-dev-middleware "^3.5.1" webpack-hot-middleware "^2.24.3" -"@storybook/node-logger@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.0.8.tgz#712239bc3eb5b9f2940232a3c75577db596c01be" - integrity sha512-10CNULeWdQzAY69S3hV3Wc/A7QnYcMnxB5ISP1TEr83reFWFGQuDM1EJ3/Qe9RtdgAHndH2uz2fN37kX1M3ZAw== +"@storybook/node-logger@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/node-logger/-/node-logger-5.0.9.tgz#d971301c27c9c8e957649cf868456052f0846f15" + integrity sha512-QJPUAoFEBtZiHZOohO0+/fbS+sNm36aEOy2H6+QP5fRjnHVNoayurFYro2AlBU+ONvQ31cG0Ou9X+2UAzusDEg== dependencies: chalk "^2.4.2" core-js "^2.6.5" @@ -1830,17 +1830,17 @@ pretty-hrtime "^1.0.3" regenerator-runtime "^0.12.1" -"@storybook/react@^5.0.6": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.0.8.tgz#9b73010e3f84c40dd3fcc91a30c32604a31051d3" - integrity sha512-4rVfLDoCvg/1F2Wfv9PktVStng3v4IbELwkQ0lH9qwOQJBy66UcXoGzbXfvn+sLOnbNHftT4SdPkdmL8HuoUnQ== +"@storybook/react@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/react/-/react-5.0.9.tgz#a4da49f9fd922ea017acd4da242c66816192a358" + integrity sha512-V8TMnAAPLdKewdorLQrUKmUZKzugCdd4/LAGPhVhAYnMTs2PPykU1rYng7+Lgq4aTpoDUOUn+59O8h8V2+uiYQ== dependencies: "@babel/plugin-transform-react-constant-elements" "^7.2.0" "@babel/preset-flow" "^7.0.0" "@babel/preset-react" "^7.0.0" - "@storybook/core" "5.0.8" - "@storybook/node-logger" "5.0.8" - "@storybook/theming" "5.0.8" + "@storybook/core" "5.0.9" + "@storybook/node-logger" "5.0.9" + "@storybook/theming" "5.0.9" "@svgr/webpack" "^4.0.3" babel-plugin-named-asset-import "^0.3.0" babel-plugin-react-docgen "^2.0.2" @@ -1856,26 +1856,26 @@ semver "^5.6.0" webpack "^4.29.0" -"@storybook/router@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.0.8.tgz#fcbbe29a65c7c65aebe25bc79eeb9f573cc7f3a8" - integrity sha512-6A9OGFkmrSQr7ZvemiibbVj4eULtkT6prEkbOi6aPMZmDq+gTT17jR1B6ekfciQmQoOPfmlpZsZkqlxejXxqoA== +"@storybook/router@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/router/-/router-5.0.9.tgz#89e5ef2600d9c9015435b909b9929edad7af3cd1" + integrity sha512-ruHXh4crwfkE9Z4KNwcQdGJi1yK4RKaYP1NDW8M/rLdw0m5ybGZcrLzvnJPCT5R5JEmV5DzAjVzXp6IA5fk7yg== dependencies: "@reach/router" "^1.2.1" - "@storybook/theming" "5.0.8" + "@storybook/theming" "5.0.9" core-js "^2.6.5" global "^4.3.2" memoizerific "^1.11.3" qs "^6.5.2" -"@storybook/theming@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.0.8.tgz#b91c45599155f636fd5e24b04cb0c8fa2acf5187" - integrity sha512-0GLGynbP2VSUMQomF+VZD165zQNCrDdy0VXcndWfS+FrTFwaUeCl0oRS6resJGehCVO5KqTviEx7uBVURW3nlA== +"@storybook/theming@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/theming/-/theming-5.0.9.tgz#3daef3d2eb5d9e4f68399f44920df3d6e62fd623" + integrity sha512-KuzRKaQIyYwFPc6MSWdpMCy4lQlvcmCNDMTRzH73+qNewka+c+gdOBzgQt3dn3uG0e8hBbsa1gx/URTZAgf7Pg== dependencies: "@emotion/core" "^10.0.7" "@emotion/styled" "^10.0.7" - "@storybook/client-logger" "5.0.8" + "@storybook/client-logger" "5.0.9" common-tags "^1.8.0" core-js "^2.6.5" deep-object-diff "^1.1.0" @@ -1888,17 +1888,17 @@ prop-types "^15.6.2" react-inspector "^2.3.1" -"@storybook/ui@5.0.8": - version "5.0.8" - resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.0.8.tgz#2c3dd151a22c9eb4e78d28af3910b7533b624742" - integrity sha512-Q9bY9zbxn4oDQ2eT8AxUj0O6eDVWHOZYEuTuijFSgJ/5bUXZmhB6aMU67QvdYJlAn07k7zcR5k09Q4a4kqaKXw== - dependencies: - "@storybook/addons" "5.0.8" - "@storybook/client-logger" "5.0.8" - "@storybook/components" "5.0.8" - "@storybook/core-events" "5.0.8" - "@storybook/router" "5.0.8" - "@storybook/theming" "5.0.8" +"@storybook/ui@5.0.9": + version "5.0.9" + resolved "https://registry.yarnpkg.com/@storybook/ui/-/ui-5.0.9.tgz#87f317703690cbb9ef7084933e60a8bbe1c1a701" + integrity sha512-4GEtSDT3TL5NICgPeXnm16MDu9e0Yt/7Ummx8jaUdA9okOLDklqTshfHX1LZpkk8NvEoX0l8R56yVGAMgc0GIg== + dependencies: + "@storybook/addons" "5.0.9" + "@storybook/client-logger" "5.0.9" + "@storybook/components" "5.0.9" + "@storybook/core-events" "5.0.9" + "@storybook/router" "5.0.9" + "@storybook/theming" "5.0.9" core-js "^2.6.5" fast-deep-equal "^2.0.1" fuzzy-search "^3.0.1" @@ -6351,10 +6351,10 @@ eslint-plugin-flowtype@3.6.1: dependencies: lodash "^4.17.11" -eslint-plugin-import@^2.9.0: - version "2.17.1" - resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.1.tgz#b888feb4d9b3ee155113c8dccdd4bec5db33bdf4" - integrity sha512-lzD9uvRvW4MsHzIOMJEDSb5MOV9LzgxRPBaovvOhJqzgxRHYfGy9QOrMuwHIh5ehKFJ7Z3DcrcGKDQ0IbP0EdQ== +eslint-plugin-import@2.17.2: + version "2.17.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.17.2.tgz#d227d5c6dc67eca71eb590d2bb62fb38d86e9fcb" + integrity sha512-m+cSVxM7oLsIpmwNn2WXTJoReOF9f/CtLMo7qOVmKd1KntBy0hEcuNZ3erTmWjx+DxRO0Zcrm5KwAvI9wHcV5g== dependencies: array-includes "^3.0.3" contains-path "^0.1.0" From e3d798448677d2d083f7c044aec3e3e705d0cc43 Mon Sep 17 00:00:00 2001 From: mmv Date: Wed, 17 Apr 2019 13:13:38 +0400 Subject: [PATCH 42/48] fix safe loading from storage --- src/routes/safe/store/reducer/safe.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/routes/safe/store/reducer/safe.js b/src/routes/safe/store/reducer/safe.js index fd89d13682..28d6ec09df 100644 --- a/src/routes/safe/store/reducer/safe.js +++ b/src/routes/safe/store/reducer/safe.js @@ -1,8 +1,9 @@ // @flow -import { Map } from 'immutable' +import { Map, List } from 'immutable' import { handleActions, type ActionType } from 'redux-actions' import { ADD_SAFE, buildOwnersFrom } from '~/routes/safe/store/actions/addSafe' import SafeRecord, { type Safe, type SafeProps } from '~/routes/safe/store/models/safe' +import TokenBalance from '~/routes/safe/store/models/tokenBalance' import { type OwnerProps } from '~/routes/safe/store/models/owner' import { loadFromStorage } from '~/utils/storage' import { SAFES_KEY } from '~/logic/safe/utils' @@ -16,10 +17,14 @@ export const buildSafe = (storedSafe: SafeProps) => { const names = storedSafe.owners.map((owner: OwnerProps) => owner.name) const addresses = storedSafe.owners.map((owner: OwnerProps) => owner.address) const owners = buildOwnersFrom(Array.from(names), Array.from(addresses)) + const activeTokens = List(storedSafe.activeTokens) + const balances = storedSafe.balances.map(balance => TokenBalance(balance)) const safe: SafeProps = { ...storedSafe, owners, + balances, + activeTokens, } return safe @@ -56,7 +61,7 @@ export default handleActions( const safe = action.payload const safeAddress = safe.address - return state.mergeIn([safeAddress], safe) + return state.update(safeAddress, prevSafe => prevSafe.merge(safe)) }, [ADD_SAFE]: (state: State, action: ActionType): State => { const { safe }: { safe: SafeProps } = action.payload @@ -66,7 +71,7 @@ export default handleActions( // with initial props and it would overwrite existing ones if (state.has(safe.address)) { - return state.mergeIn([safe.address], safe) + return state.update(safe.address, prevSafe => prevSafe.merge(safe)) } return state.set(safe.address, SafeRecord(safe)) From 81fbb3b662ed4a545bffef52dd0977145d45927e Mon Sep 17 00:00:00 2001 From: mmv Date: Wed, 17 Apr 2019 15:35:35 +0400 Subject: [PATCH 43/48] add selector for all active tokens --- src/routes/safe/store/selectors/index.js | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/routes/safe/store/selectors/index.js b/src/routes/safe/store/selectors/index.js index 100e3cbd47..948a0d0631 100644 --- a/src/routes/safe/store/selectors/index.js +++ b/src/routes/safe/store/selectors/index.js @@ -1,5 +1,5 @@ // @flow -import { Map, List } from 'immutable' +import { Map, List, Set } from 'immutable' import { type Match } from 'react-router-dom' import { createSelector, createStructuredSelector, type Selector } from 'reselect' import { type GlobalState } from '~/store/index' @@ -9,6 +9,7 @@ import { safesMapSelector } from '~/routes/safeList/store/selectors' import { type State as TransactionsState, TRANSACTIONS_REDUCER_ID } from '~/routes/safe/store/reducer/transactions' import { type Transaction } from '~/routes/safe/store/models/transaction' import { type Confirmation } from '~/routes/safe/store/models/confirmation' +import { safesListSelector } from '~/routes/safeList/store/selectors/' export type RouterProps = { match: Match, @@ -100,6 +101,21 @@ export const safeBalancesSelector: Selector> = createSelector( + safesListSelector, + (safes: List) => { + const addresses = Set().withMutations((set) => { + safes.forEach((safe: Safe) => { + safe.activeTokens.forEach((tokenAddress) => { + set.add(tokenAddress) + }) + }) + }) + + return addresses + }, +) + export default createStructuredSelector({ safe: safeSelector, tokens: safeActiveTokensSelector, From cdaa6c8223af8837cd094c166da4438aff4a3d56 Mon Sep 17 00:00:00 2001 From: mmv Date: Wed, 17 Apr 2019 16:47:21 +0400 Subject: [PATCH 44/48] fix loading tokens from storage --- src/index.js | 2 ++ src/logic/tokens/store/actions/fetchTokens.js | 4 ++-- .../tokens/store/actions/loadActiveTokens.js | 12 +++++----- src/logic/tokens/store/actions/saveTokens.js | 11 ++-------- src/logic/tokens/utils/tokensStorage.js | 8 +++---- .../safe/store/middleware/safeStorage.js | 22 ++++++++++++++++++- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/src/index.js b/src/index.js index 4b31cb2e78..9b33ff72c9 100644 --- a/src/index.js +++ b/src/index.js @@ -6,7 +6,9 @@ import ReactDOM from 'react-dom' import Root from '~/components/Root' import { store } from '~/store' import loadSafesFromStorage from '~/routes/safe/store/actions/loadSafesFromStorage' +import loadActiveTokens from '~/logic/tokens/store/actions/loadActiveTokens' +store.dispatch(loadActiveTokens()) store.dispatch(loadSafesFromStorage()) ReactDOM.render(, document.getElementById('root')) diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index 0c4a205ce5..a1a3ab21eb 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -38,7 +38,7 @@ const fetchTokenList = async () => { return axios.get(url, errMsg) } -export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispatch) => { +export const fetchTokens = () => async (dispatch: ReduxDispatch) => { try { const { data: { results: tokenList }, @@ -48,7 +48,7 @@ export const fetchTokens = (safeAddress: string) => async (dispatch: ReduxDispat tokenList.forEach((token: TokenProps) => map.set(token.address, makeToken(token))) }) - dispatch(saveTokens(safeAddress, tokensMap)) + dispatch(saveTokens(tokensMap)) } catch (err) { // eslint-disable-next-line console.log('Error fetching token list ' + err) diff --git a/src/logic/tokens/store/actions/loadActiveTokens.js b/src/logic/tokens/store/actions/loadActiveTokens.js index 0d1270a11b..2037c7e6bc 100644 --- a/src/logic/tokens/store/actions/loadActiveTokens.js +++ b/src/logic/tokens/store/actions/loadActiveTokens.js @@ -1,6 +1,6 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' -import { List, Map } from 'immutable' +import { Map, List } from 'immutable' import { type TokenProps, type Token, makeToken } from '~/logic/tokens/store/model/token' import { type GlobalState } from '~/store/index' import { getActiveTokens } from '~/logic/tokens/utils/tokensStorage' @@ -8,13 +8,13 @@ import saveTokens from './saveTokens' const loadActiveTokens = () => async (dispatch: ReduxDispatch) => { try { - const tokens: List = await getActiveTokens() + const tokens: Map = await getActiveTokens() - const tokenRecords: Map = Map().withMutations((map) => { - tokens.forEach(token => map.set(token.address, makeToken(token))) - }) + const tokenRecordsList: List = List( + Object.values(tokens).map(token => makeToken(token)), + ) - dispatch(saveTokens(tokenRecords)) + dispatch(saveTokens(tokenRecordsList)) } catch (err) { // eslint-disable-next-line console.error('Error while loading active tokens from storage:', err) diff --git a/src/logic/tokens/store/actions/saveTokens.js b/src/logic/tokens/store/actions/saveTokens.js index 36a3ed3b28..bc2a380037 100644 --- a/src/logic/tokens/store/actions/saveTokens.js +++ b/src/logic/tokens/store/actions/saveTokens.js @@ -1,24 +1,17 @@ // @flow -import { Map, List } from 'immutable' +import { Map } from 'immutable' import { createAction } from 'redux-actions' -import type { Dispatch as ReduxDispatch } from 'redux' import { type Token } from '~/logic/tokens/store/model/token' -import { ensureOnceAsync } from '~/utils/singleton' -import { type GlobalState } from '~/store/index' -import { setActiveTokens } from '~/logic/tokens/utils/tokensStorage' -import { calculateActiveErc20TokensFrom } from '~/logic/tokens/utils/tokenHelpers' export const ADD_TOKENS = 'ADD_TOKENS' type TokenProps = { - safeAddress: string, tokens: Map, } const addTokens = createAction( ADD_TOKENS, - (safeAddress: string, tokens: Map): TokenProps => ({ - safeAddress, + (tokens: Map): TokenProps => ({ tokens, }), ) diff --git a/src/logic/tokens/utils/tokensStorage.js b/src/logic/tokens/utils/tokensStorage.js index bb21540313..692db811ae 100644 --- a/src/logic/tokens/utils/tokensStorage.js +++ b/src/logic/tokens/utils/tokensStorage.js @@ -1,5 +1,5 @@ // @flow -import { List } from 'immutable' +import { List, Map } from 'immutable' import { type Token, type TokenProps } from '~/logic/tokens/store/model/token' import { loadFromStorage, saveToStorage } from '~/utils/storage' @@ -10,7 +10,7 @@ export const CUSTOM_TOKENS_KEY = 'CUSTOM_TOKENS' // to avoid iterating a large amount of data of tokens from the backend // Custom tokens should be saved too unless they're deleted (marking them as inactive doesn't count) -export const setActiveTokens = async (tokens: List) => { +export const setActiveTokens = async (tokens: Map) => { try { await saveToStorage(ACTIVE_TOKENS_KEY, tokens.toJS()) } catch (err) { @@ -19,10 +19,10 @@ export const setActiveTokens = async (tokens: List) => { } } -export const getActiveTokens = async (): Promise> => { +export const getActiveTokens = async (): Promise> => { const data = await loadFromStorage(ACTIVE_TOKENS_KEY) - return data ? List(data) : List() + return data || Map({}) } export const getCustomTokens = async (): Promise> => { diff --git a/src/routes/safe/store/middleware/safeStorage.js b/src/routes/safe/store/middleware/safeStorage.js index 90d0d6a625..ab765e1827 100644 --- a/src/routes/safe/store/middleware/safeStorage.js +++ b/src/routes/safe/store/middleware/safeStorage.js @@ -4,7 +4,11 @@ import { UPDATE_SAFE } from '~/routes/safe/store/actions/updateSafe' import type { Store, AnyAction } from 'redux' import { type GlobalState } from '~/store/' import { saveSafes, setOwners } from '~/logic/safe/utils' -import { safesMapSelector } from '~/routes/safeList/store/selectors/index' +import { safesMapSelector } from '~/routes/safeList/store/selectors' +import { getActiveTokensAddressesForAllSafes } from '~/routes/safe/store/selectors' +import { tokensSelector } from '~/logic/tokens/store/selectors' +import type { Token } from '~/logic/tokens/store/model/token' +import { setActiveTokens } from '~/logic/tokens/utils/tokensStorage' const watchedActions = [ADD_SAFE, UPDATE_SAFE] @@ -16,6 +20,22 @@ const safeStorageMware = (store: Store) => (next: Function) => asyn const safes = safesMapSelector(state) saveSafes(safes.toJSON()) + // recalculate active tokens + if (action.payload.activeTokens) { + const tokens = tokensSelector(state) + const activeTokenAddresses = getActiveTokensAddressesForAllSafes(state) + + const activeTokens = tokens.withMutations((map) => { + map.forEach((token: Token) => { + if (!activeTokenAddresses.has(token.address)) { + map.remove(token.address) + } + }) + }) + + setActiveTokens(activeTokens) + } + if (action.type === ADD_SAFE) { const { safe } = action.payload setOwners(safe.address, safe.owners) From 289f5f6febe9b5695173abe39b5d807f60802222 Mon Sep 17 00:00:00 2001 From: mmv Date: Wed, 17 Apr 2019 18:37:15 +0400 Subject: [PATCH 45/48] token redux-related stuff cleanup after refactor --- .../tokens/store/actions/disableToken.js | 21 ------------- src/logic/tokens/store/actions/enableToken.js | 22 ------------- src/logic/tokens/store/actions/fetchTokens.js | 8 ++--- .../tokens/store/actions/updateTokens.js | 31 ------------------- .../safe/store/actions/fetchTokenBalances.js | 1 - 5 files changed, 3 insertions(+), 80 deletions(-) delete mode 100644 src/logic/tokens/store/actions/disableToken.js delete mode 100644 src/logic/tokens/store/actions/enableToken.js delete mode 100644 src/logic/tokens/store/actions/updateTokens.js diff --git a/src/logic/tokens/store/actions/disableToken.js b/src/logic/tokens/store/actions/disableToken.js deleted file mode 100644 index ceafec7caf..0000000000 --- a/src/logic/tokens/store/actions/disableToken.js +++ /dev/null @@ -1,21 +0,0 @@ -// @flow -import { createAction } from 'redux-actions' -import { type Token } from '~/logic/tokens/store/model/token' -import type { Dispatch as ReduxDispatch } from 'redux' -import { type GlobalState } from '~/store/index' -import { removeFromActiveTokens } from '~/logic/tokens/utils/tokensStorage' - -export const DISABLE_TOKEN = 'DISABLE_TOKEN' - -export const disableToken = createAction(DISABLE_TOKEN, (safeAddress: string, token: Token) => ({ - safeAddress, - token, -})) - -const hideToken = (safeAddress: string, token: Token) => async (dispatch: ReduxDispatch) => { - dispatch(disableToken(safeAddress, token)) - - await removeFromActiveTokens(safeAddress, token) -} - -export default hideToken diff --git a/src/logic/tokens/store/actions/enableToken.js b/src/logic/tokens/store/actions/enableToken.js deleted file mode 100644 index 055433db62..0000000000 --- a/src/logic/tokens/store/actions/enableToken.js +++ /dev/null @@ -1,22 +0,0 @@ -// @flow -import { createAction } from 'redux-actions' -import type { Dispatch as ReduxDispatch } from 'redux' -import { type GlobalState } from '~/store/index' -import { type Token } from '~/logic/tokens/store/model/token' -import { setActiveTokens, getActiveTokens } from '~/logic/tokens/utils/tokensStorage' - -export const ENABLE_TOKEN = 'ENABLE_TOKEN' - -export const enableToken = createAction(ENABLE_TOKEN, (safeAddress: string, token: Token) => ({ - safeAddress, - token, -})) - -const setTokenEnabled = (safeAddress: string, token: Token) => async (dispatch: ReduxDispatch) => { - dispatch(enableToken(safeAddress, token)) - - const activeTokens = await getActiveTokens(safeAddress) - await setActiveTokens(safeAddress, activeTokens.push(token)) -} - -export default setTokenEnabled diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index a1a3ab21eb..82ae59f75f 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -1,5 +1,5 @@ // @flow -import { Map } from 'immutable' +import { List } from 'immutable' import contract from 'truffle-contract' import axios from 'axios' import type { Dispatch as ReduxDispatch } from 'redux' @@ -44,11 +44,9 @@ export const fetchTokens = () => async (dispatch: ReduxDispatch) => data: { results: tokenList }, } = await fetchTokenList() - const tokensMap: Map = Map().withMutations((map) => { - tokenList.forEach((token: TokenProps) => map.set(token.address, makeToken(token))) - }) + const tokens = List(tokenList.map((token: TokenProps) => makeToken(token))) - dispatch(saveTokens(tokensMap)) + dispatch(saveTokens(tokens)) } catch (err) { // eslint-disable-next-line console.log('Error fetching token list ' + err) diff --git a/src/logic/tokens/store/actions/updateTokens.js b/src/logic/tokens/store/actions/updateTokens.js deleted file mode 100644 index 601f241db4..0000000000 --- a/src/logic/tokens/store/actions/updateTokens.js +++ /dev/null @@ -1,31 +0,0 @@ -// @flow -import { createAction } from 'redux-actions' -import { type Token } from '~/logic/tokens/store/model/token' -import { setActiveTokens, getActiveTokens, setToken } from '~/logic/tokens/utils/tokensStorage' -import type { Dispatch as ReduxDispatch } from 'redux' -import { type GlobalState } from '~/store/index' - -export const ADD_TOKEN = 'ADD_TOKEN' - -type AddTokenProps = { - safeAddress: string, - token: Token, -} - -export const addToken = createAction( - ADD_TOKEN, - (safeAddress: string, token: Token): AddTokenProps => ({ - safeAddress, - token, - }), -) - -const saveToken = (safeAddress: string, token: Token) => async (dispatch: ReduxDispatch) => { - dispatch(addToken(safeAddress, token)) - - const activeTokens = await getActiveTokens(safeAddress) - await setActiveTokens(safeAddress, activeTokens.push(token.toJS())) - setToken(safeAddress, token) -} - -export default saveToken diff --git a/src/routes/safe/store/actions/fetchTokenBalances.js b/src/routes/safe/store/actions/fetchTokenBalances.js index 2c602fde3c..96437d7c81 100644 --- a/src/routes/safe/store/actions/fetchTokenBalances.js +++ b/src/routes/safe/store/actions/fetchTokenBalances.js @@ -37,7 +37,6 @@ const fetchTokenBalances = (safeAddress: string, tokens: List) => async ( try { const withBalances = await Promise.all( tokens - .filter(token => token.address !== ETH_ADDRESS) .map(async token => TokenBalanceRecord({ address: token.address, balance: await calculateBalanceOf(token.address, safeAddress, token.decimals), From 43e8521aba56067c5cd6b4b2e36be0d4b44bf2fc Mon Sep 17 00:00:00 2001 From: mmv Date: Wed, 17 Apr 2019 18:37:41 +0400 Subject: [PATCH 46/48] eslint fix --- src/logic/tokens/store/actions/fetchTokens.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/logic/tokens/store/actions/fetchTokens.js b/src/logic/tokens/store/actions/fetchTokens.js index 82ae59f75f..82385118a2 100644 --- a/src/logic/tokens/store/actions/fetchTokens.js +++ b/src/logic/tokens/store/actions/fetchTokens.js @@ -7,7 +7,7 @@ import StandardToken from '@gnosis.pm/util-contracts/build/contracts/GnosisStand import HumanFriendlyToken from '@gnosis.pm/util-contracts/build/contracts/HumanFriendlyToken.json' import { getWeb3 } from '~/logic/wallets/getWeb3' import { type GlobalState } from '~/store/index' -import { makeToken, type Token, type TokenProps } from '~/logic/tokens/store/model/token' +import { makeToken, type TokenProps } from '~/logic/tokens/store/model/token' import { ensureOnce } from '~/utils/singleton' import saveTokens from './saveTokens' import { getRelayUrl } from '~/config/index' From c633165dd2e5d77ba8c10edf94e36dd215b0ae99 Mon Sep 17 00:00:00 2001 From: mmv Date: Wed, 17 Apr 2019 18:40:30 +0400 Subject: [PATCH 47/48] rename setActiveTokens to saveActiveTokens --- src/logic/tokens/store/actions/addToken.js | 4 ++-- src/logic/tokens/utils/tokensStorage.js | 4 ++-- src/routes/safe/store/actions/updateSafes.js | 8 -------- src/routes/safe/store/middleware/safeStorage.js | 4 ++-- 4 files changed, 6 insertions(+), 14 deletions(-) delete mode 100644 src/routes/safe/store/actions/updateSafes.js diff --git a/src/logic/tokens/store/actions/addToken.js b/src/logic/tokens/store/actions/addToken.js index 71c927c900..6d3fe9e49a 100644 --- a/src/logic/tokens/store/actions/addToken.js +++ b/src/logic/tokens/store/actions/addToken.js @@ -1,7 +1,7 @@ // @flow import { createAction } from 'redux-actions' import { type Token } from '~/logic/tokens/store/model/token' -import { setActiveTokens, getActiveTokens, setToken } from '~/logic/tokens/utils/tokensStorage' +import { saveActiveTokens, getActiveTokens, setToken } from '~/logic/tokens/utils/tokensStorage' import type { Dispatch as ReduxDispatch } from 'redux' import { type GlobalState } from '~/store/' @@ -23,7 +23,7 @@ const saveToken = (safeAddress: string, token: Token) => async (dispatch: ReduxD dispatch(addToken(token)) const activeTokens = await getActiveTokens(safeAddress) - await setActiveTokens(safeAddress, activeTokens.push(token.toJS())) + await saveActiveTokens(safeAddress, activeTokens.push(token.toJS())) setToken(safeAddress, token) } diff --git a/src/logic/tokens/utils/tokensStorage.js b/src/logic/tokens/utils/tokensStorage.js index 692db811ae..0af8417ab2 100644 --- a/src/logic/tokens/utils/tokensStorage.js +++ b/src/logic/tokens/utils/tokensStorage.js @@ -10,7 +10,7 @@ export const CUSTOM_TOKENS_KEY = 'CUSTOM_TOKENS' // to avoid iterating a large amount of data of tokens from the backend // Custom tokens should be saved too unless they're deleted (marking them as inactive doesn't count) -export const setActiveTokens = async (tokens: Map) => { +export const saveActiveTokens = async (tokens: Map) => { try { await saveToStorage(ACTIVE_TOKENS_KEY, tokens.toJS()) } catch (err) { @@ -59,6 +59,6 @@ export const removeFromActiveTokens = async (safeAddress: string, token: Token) const index = activeTokens.findIndex(activeToken => activeToken.name === token.name) if (index !== -1) { - await setActiveTokens(safeAddress, activeTokens.delete(index)) + await saveActiveTokens(safeAddress, activeTokens.delete(index)) } } diff --git a/src/routes/safe/store/actions/updateSafes.js b/src/routes/safe/store/actions/updateSafes.js deleted file mode 100644 index bdcfad6511..0000000000 --- a/src/routes/safe/store/actions/updateSafes.js +++ /dev/null @@ -1,8 +0,0 @@ -// @flow -import { createAction } from 'redux-actions' - -export const UPDATE_SAFES = 'UPDATE_SAFES' - -const updateSafesInBatch = createAction(UPDATE_SAFES) - -export default updateSafesInBatch diff --git a/src/routes/safe/store/middleware/safeStorage.js b/src/routes/safe/store/middleware/safeStorage.js index ab765e1827..3104687b3a 100644 --- a/src/routes/safe/store/middleware/safeStorage.js +++ b/src/routes/safe/store/middleware/safeStorage.js @@ -8,7 +8,7 @@ import { safesMapSelector } from '~/routes/safeList/store/selectors' import { getActiveTokensAddressesForAllSafes } from '~/routes/safe/store/selectors' import { tokensSelector } from '~/logic/tokens/store/selectors' import type { Token } from '~/logic/tokens/store/model/token' -import { setActiveTokens } from '~/logic/tokens/utils/tokensStorage' +import { saveActiveTokens } from '~/logic/tokens/utils/tokensStorage' const watchedActions = [ADD_SAFE, UPDATE_SAFE] @@ -33,7 +33,7 @@ const safeStorageMware = (store: Store) => (next: Function) => asyn }) }) - setActiveTokens(activeTokens) + saveActiveTokens(activeTokens) } if (action.type === ADD_SAFE) { From 84af7ae182010c9b15b04ccdf1d62385b698208f Mon Sep 17 00:00:00 2001 From: mmv Date: Wed, 17 Apr 2019 19:41:43 +0400 Subject: [PATCH 48/48] eslint fixes --- .../safe/component/Balances/Tokens/index.jsx | 58 ++++++++++++++----- .../safe/store/actions/updateActiveTokens.js | 35 ++++------- 2 files changed, 55 insertions(+), 38 deletions(-) diff --git a/src/routes/safe/component/Balances/Tokens/index.jsx b/src/routes/safe/component/Balances/Tokens/index.jsx index a074be015c..099049e714 100644 --- a/src/routes/safe/component/Balances/Tokens/index.jsx +++ b/src/routes/safe/component/Balances/Tokens/index.jsx @@ -1,10 +1,9 @@ // @flow import * as React from 'react' import { connect } from 'react-redux' -import { List } from 'immutable' +import { List, Set } from 'immutable' import classNames from 'classnames/bind' import SearchBar from 'material-ui-search-bar' -import InfiniteScroll from 'react-infinite-scroll-component' import { withStyles } from '@material-ui/core/styles' import MuiList from '@material-ui/core/List' import Img from '~/components/layout/Img' @@ -25,7 +24,6 @@ import Spacer from '~/components/Spacer' import Row from '~/components/layout/Row' import { ETH_ADDRESS } from '~/logic/tokens/utils/tokenHelpers' import { type Token } from '~/logic/tokens/store/model/token' -import { type TokenBalance } from '~/routes/safe/store/models/tokenBalance' import actions, { type Actions } from './actions' import TokenPlaceholder from './assets/token_placeholder.png' import { styles } from './style' @@ -35,11 +33,12 @@ type Props = Actions & { classes: Object, tokens: List, safeAddress: string, - activeTokens: List + activeTokens: List, } type State = { filter: string, + activeTokensAddresses: Set, } const filterBy = (filter: string, tokens: List): List => tokens.filter( @@ -56,12 +55,39 @@ const filterBy = (filter: string, tokens: List): List => tokens.fi class Tokens extends React.Component { state = { filter: '', + activeTokensAddresses: Set([]), + activeTokensCalculated: false, } componentDidMount() { - const { fetchTokens, safeAddress } = this.props + const { fetchTokens, safeAddress, activeTokens } = this.props fetchTokens(safeAddress) + + // this.setState({ + // activeTokensAddresses: Set(activeTokens.map(({ address }) => address)), + // }) + } + + static getDerivedStateFromProps(nextProps, prevState) { + if (!prevState.activeTokensCalculated) { + const { activeTokens } = nextProps + + return { + activeTokensAddresses: Set(activeTokens.map(({ address }) => address)), + activeTokensCalculated: true, + } + } + return null + } + + componentWillUnmount() { + const { activeTokensAddresses } = this.state + const { updateActiveTokens, safeAddress } = this.props + + activeTokensAddresses.forEach((tokenAddress: string) => { + updateActiveTokens(safeAddress, activeTokensAddresses.toList()) + }) } onCancelSearch = () => { @@ -73,9 +99,17 @@ class Tokens extends React.Component { } onSwitch = (token: Token) => () => { - const { safeAddress, updateActiveTokens } = this.props - - updateActiveTokens(safeAddress, token.address) + const { activeTokensAddresses } = this.state + + if (activeTokensAddresses.has(token.address)) { + this.setState({ + activeTokensAddresses: activeTokensAddresses.remove(token.address), + }) + } else { + this.setState({ + activeTokensAddresses: activeTokensAddresses.add(token.address), + }) + } } setImageToPlaceholder = (e) => { @@ -84,10 +118,8 @@ class Tokens extends React.Component { } render() { - const { - onClose, classes, tokens, activeTokens, - } = this.props - const { filter } = this.state + const { onClose, classes, tokens } = this.props + const { filter, activeTokensAddresses } = this.state const searchClasses = { input: classes.searchInput, root: classes.searchRoot, @@ -129,7 +161,7 @@ class Tokens extends React.Component { {filteredTokens.map((token: Token) => { - const isActive = activeTokens.findIndex(({ address }) => address === token.address) !== -1 + const isActive = activeTokensAddresses.has(token.address) return ( diff --git a/src/routes/safe/store/actions/updateActiveTokens.js b/src/routes/safe/store/actions/updateActiveTokens.js index affddef190..630e353d8c 100644 --- a/src/routes/safe/store/actions/updateActiveTokens.js +++ b/src/routes/safe/store/actions/updateActiveTokens.js @@ -1,38 +1,23 @@ // @flow import { List } from 'immutable' -import type { Dispatch as ReduxDispatch, GetState } from 'redux' +import type { Dispatch as ReduxDispatch } from 'redux' import { type GlobalState } from '~/store' -import { type TokenBalance } from '/routes/safe/store/models/tokenBalance' -import { safeActiveTokensSelector } from '~/routes/safe/store/selectors' -import { SAFE_PARAM_ADDRESS } from '~/routes/routes' import updateSafe from './updateSafe' // the selector uses ownProps argument/router props to get the address of the safe // so in order to use it I had to recreate the same structure -const generateMatchProps = (safeAddress: string) => ({ - match: { - params: { - [SAFE_PARAM_ADDRESS]: safeAddress, - }, - }, -}) +// const generateMatchProps = (safeAddress: string) => ({ +// match: { +// params: { +// [SAFE_PARAM_ADDRESS]: safeAddress, +// }, +// }, +// }) -const updateActiveTokens = (safeAddress: string, tokenAddress: string) => async ( +const updateActiveTokens = (safeAddress: string, activeTokens: List) => async ( dispatch: ReduxDispatch, - getState: GetState, ) => { - const state = getState() - const safeTokens: List = safeActiveTokensSelector(state, generateMatchProps(safeAddress)) - const index = safeTokens.findIndex(address => address === tokenAddress) - - let updatedTokens - if (index !== -1) { - updatedTokens = safeTokens.delete(index) - } else { - updatedTokens = safeTokens.push(tokenAddress) - } - - dispatch(updateSafe({ address: safeAddress, activeTokens: updatedTokens })) + dispatch(updateSafe({ address: safeAddress, activeTokens })) } export default updateActiveTokens