From 50cc377b48568fa495cbcbd3aa5d11ef05394069 Mon Sep 17 00:00:00 2001 From: AMStrix Date: Fri, 14 Dec 2018 13:36:22 -0600 Subject: [PATCH] User Auth Conversion (#19) --- .gitignore | 3 +- .travis.yml | 16 - README.md | 23 +- admin/README.md | 2 - admin/package.json | 4 +- admin/src/components/Home/index.tsx | 13 +- admin/src/components/Proposals/index.less | 88 - admin/src/components/Proposals/index.tsx | 219 +- admin/src/store.ts | 37 +- admin/src/types.ts | 87 - admin/src/web3helper.ts | 227 -- admin/tsconfig.json | 1 - admin/webpack.config.js | 1 - admin/yarn.lock | 867 +---- backend/.env.example | 14 +- backend/README.md | 62 +- backend/grant/app.py | 14 +- backend/grant/commands.py | 14 +- backend/grant/email/send.py | 3 + backend/grant/extensions.py | 4 +- backend/grant/proposal/models.py | 1 - backend/grant/proposal/views.py | 63 +- backend/grant/settings.py | 16 +- .../grant/templates/emails/team_invite.html | 33 +- backend/grant/user/commands.py | 7 +- backend/grant/user/models.py | 108 +- backend/grant/user/views.py | 160 +- backend/grant/utils/auth.py | 97 +- backend/grant/utils/upload.py | 79 +- backend/grant/web3/__init__.py | 1 - backend/grant/web3/dev_contracts.py | 19 - backend/grant/web3/proposal.py | 178 - backend/grant/web3/util.py | 86 - backend/migrations/versions/13d788130b39_.py | 49 + backend/migrations/versions/a6087d62cb4b_.py | 38 + backend/requirements/prod.txt | 11 +- backend/tests/config.py | 21 +- backend/tests/proposal/test_invite_api.py | 21 +- backend/tests/settings.py | 7 +- backend/tests/test_data.py | 47 +- backend/tests/user/test_invite_api.py | 42 +- .../tests/user/test_required_sm_decorator.py | 71 - backend/tests/user/test_user_api.py | 101 +- backend/tests/web3/__init__.py | 0 backend/tests/web3/test_proposal_read.py | 127 - contract/.envexample | 2 - contract/.gitignore | 5 - contract/.nvmrc | 1 - contract/README.md | 42 - contract/bin/build-abi.js | 31 - contract/bin/build-types.js | 10 - contract/contracts/CrowdFund.sol | 301 -- contract/contracts/CrowdFundFactory.sol | 31 - contract/contracts/Forward.sol | 15 - contract/contracts/Migrations.sol | 23 - contract/contracts/PrivateFund.sol | 202 -- contract/contracts/PrivateFundFactory.sol | 33 - contract/main.js | 13 - contract/migrations/1_initial_migration.js | 5 - contract/migrations/2_deploy_contracts.js | 5 - contract/package.json | 24 - contract/test/CrowdFundDeadlineTest.js | 118 - contract/test/CrowdFundTest.js | 457 --- contract/test/ForwardTest.js | 26 - contract/test/PrivateFundTest.js | 235 -- contract/test/utils.js | 65 - contract/truffle-config.js | 108 - contract/yarn.lock | 2888 ----------------- frontend/.envexample | 9 - frontend/.gitignore | 1 - frontend/README.md | 43 +- frontend/bin/dev.js | 3 - frontend/bin/init-truffle.js | 53 - frontend/bin/truffle-util.js | 166 - frontend/client/Routes.tsx | 10 +- frontend/client/api/api.ts | 35 +- frontend/client/api/axios.ts | 2 + frontend/client/components/AddressInput.tsx | 4 +- .../components/AuthFlow/ProvideIdentity.less | 14 - .../components/AuthFlow/ProvideIdentity.tsx | 34 - .../components/AuthFlow/SelectProvider.less | 23 - .../components/AuthFlow/SelectProvider.tsx | 25 - .../client/components/AuthFlow/SignIn.less | 34 +- .../client/components/AuthFlow/SignIn.tsx | 104 +- .../client/components/AuthFlow/SignUp.less | 42 +- .../client/components/AuthFlow/SignUp.tsx | 137 +- .../client/components/AuthFlow/index.less | 10 +- frontend/client/components/AuthFlow/index.tsx | 152 +- .../AuthFlow/providers/Address.less | 9 - .../components/AuthFlow/providers/Address.tsx | 52 - .../AuthFlow/providers/ChooseAddress.less | 110 - .../AuthFlow/providers/ChooseAddress.tsx | 162 - .../components/AuthFlow/providers/Ledger.less | 25 - .../components/AuthFlow/providers/Ledger.tsx | 117 - .../components/AuthFlow/providers/Trezor.tsx | 66 - .../components/AuthFlow/providers/Web3.less | 16 - .../components/AuthFlow/providers/Web3.tsx | 90 - frontend/client/components/AuthRoute.tsx | 10 +- frontend/client/components/Comment/index.tsx | 2 +- .../client/components/CreateFlow/Final.tsx | 35 +- .../client/components/CreateFlow/Team.tsx | 4 +- .../client/components/CreateFlow/index.tsx | 26 +- frontend/client/components/Header/Auth.tsx | 11 +- frontend/client/components/Header/Drawer.tsx | 13 +- frontend/client/components/Identicon.tsx | 5 +- .../MetaMaskRequiredButton/index.tsx | 27 +- .../client/components/PasswordFormItems.less | 10 + .../client/components/PasswordFormItems.tsx | 92 + .../client/components/Profile/AvatarEdit.tsx | 14 +- .../client/components/Profile/ProfileEdit.tsx | 25 +- .../components/Profile/ProfileProposal.tsx | 2 +- .../client/components/Profile/ProfileUser.tsx | 9 +- frontend/client/components/Profile/index.tsx | 14 +- .../Proposal/CampaignBlock/index.tsx | 21 +- .../components/Proposal/CancelModal.tsx | 29 +- .../Proposal/Governance/Refunds.tsx | 42 +- .../Proposal/Milestones/MilestoneAction.tsx | 44 +- .../components/Proposal/Milestones/index.tsx | 11 +- frontend/client/components/Proposal/index.tsx | 6 +- .../components/Settings/ChangePassword.less | 18 + .../components/Settings/ChangePassword.tsx | 112 + .../client/components/Settings/index.less | 9 + frontend/client/components/Settings/index.tsx | 38 + .../client/components/Template/Web3Error.less | 47 - .../client/components/Template/Web3Error.tsx | 32 - frontend/client/components/Template/index.tsx | 85 +- frontend/client/components/UserAvatar.tsx | 3 - frontend/client/components/UserRow/index.tsx | 2 +- frontend/client/lib/Web3Container.tsx | 38 - frontend/client/lib/crowdFundContracts.ts | 33 - .../client/lib/crowdFundFactoryContract.ts | 24 - frontend/client/lib/getContract.ts | 32 - frontend/client/lib/getWeb3.ts | 48 - frontend/client/modules/auth/actions.ts | 151 +- frontend/client/modules/auth/reducers.ts | 74 +- frontend/client/modules/auth/sagas.ts | 25 +- frontend/client/modules/auth/types.ts | 3 + frontend/client/modules/create/actions.ts | 10 +- frontend/client/modules/create/utils.ts | 13 +- frontend/client/modules/proposals/actions.ts | 22 +- frontend/client/modules/users/actions.ts | 4 +- frontend/client/modules/users/reducers.ts | 11 +- frontend/client/modules/web3/actions.ts | 477 --- frontend/client/modules/web3/index.ts | 8 - frontend/client/modules/web3/reducers.ts | 216 -- frontend/client/modules/web3/sagas.ts | 45 - frontend/client/modules/web3/selectors.ts | 5 - frontend/client/modules/web3/types.ts | 73 - frontend/client/pages/settings.tsx | 18 +- frontend/client/pages/sign-out.tsx | 2 +- frontend/client/store/configure.tsx | 21 +- frontend/client/store/reducers.tsx | 4 - frontend/client/store/sagas.ts | 2 - frontend/client/styles/antd-overrides.less | 10 +- frontend/client/utils/auth.ts | 56 - frontend/client/utils/s3.ts | 25 + frontend/client/utils/units.ts | 5 - frontend/client/utils/validators.ts | 22 +- frontend/client/utils/wallet.ts | 79 - frontend/client/utils/web3.ts | 43 - frontend/client/web3interact/crowdFund.ts | 149 - frontend/config/env.js | 10 - frontend/config/paths.js | 3 - .../config/webpack.config.js/resolvers.js | 2 - frontend/package.json | 15 +- frontend/stories/UserRow.story.tsx | 3 - frontend/stories/props.tsx | 15 - frontend/tsconfig.json | 4 +- frontend/types/user.ts | 3 +- frontend/yarn.lock | 1238 ++----- 170 files changed, 1657 insertions(+), 11452 deletions(-) delete mode 100644 admin/src/web3helper.ts delete mode 100644 backend/grant/web3/__init__.py delete mode 100644 backend/grant/web3/dev_contracts.py delete mode 100644 backend/grant/web3/proposal.py delete mode 100644 backend/grant/web3/util.py create mode 100644 backend/migrations/versions/13d788130b39_.py create mode 100644 backend/migrations/versions/a6087d62cb4b_.py delete mode 100644 backend/tests/user/test_required_sm_decorator.py delete mode 100644 backend/tests/web3/__init__.py delete mode 100644 backend/tests/web3/test_proposal_read.py delete mode 100644 contract/.envexample delete mode 100644 contract/.gitignore delete mode 100644 contract/.nvmrc delete mode 100644 contract/README.md delete mode 100644 contract/bin/build-abi.js delete mode 100644 contract/bin/build-types.js delete mode 100644 contract/contracts/CrowdFund.sol delete mode 100644 contract/contracts/CrowdFundFactory.sol delete mode 100644 contract/contracts/Forward.sol delete mode 100644 contract/contracts/Migrations.sol delete mode 100644 contract/contracts/PrivateFund.sol delete mode 100644 contract/contracts/PrivateFundFactory.sol delete mode 100644 contract/main.js delete mode 100644 contract/migrations/1_initial_migration.js delete mode 100644 contract/migrations/2_deploy_contracts.js delete mode 100644 contract/package.json delete mode 100644 contract/test/CrowdFundDeadlineTest.js delete mode 100644 contract/test/CrowdFundTest.js delete mode 100644 contract/test/ForwardTest.js delete mode 100644 contract/test/PrivateFundTest.js delete mode 100644 contract/test/utils.js delete mode 100644 contract/truffle-config.js delete mode 100644 contract/yarn.lock delete mode 100644 frontend/bin/init-truffle.js delete mode 100644 frontend/bin/truffle-util.js delete mode 100644 frontend/client/components/AuthFlow/ProvideIdentity.less delete mode 100644 frontend/client/components/AuthFlow/ProvideIdentity.tsx delete mode 100644 frontend/client/components/AuthFlow/SelectProvider.less delete mode 100644 frontend/client/components/AuthFlow/SelectProvider.tsx delete mode 100644 frontend/client/components/AuthFlow/providers/Address.less delete mode 100644 frontend/client/components/AuthFlow/providers/Address.tsx delete mode 100644 frontend/client/components/AuthFlow/providers/ChooseAddress.less delete mode 100644 frontend/client/components/AuthFlow/providers/ChooseAddress.tsx delete mode 100644 frontend/client/components/AuthFlow/providers/Ledger.less delete mode 100644 frontend/client/components/AuthFlow/providers/Ledger.tsx delete mode 100644 frontend/client/components/AuthFlow/providers/Trezor.tsx delete mode 100644 frontend/client/components/AuthFlow/providers/Web3.less delete mode 100644 frontend/client/components/AuthFlow/providers/Web3.tsx create mode 100644 frontend/client/components/PasswordFormItems.less create mode 100644 frontend/client/components/PasswordFormItems.tsx create mode 100644 frontend/client/components/Settings/ChangePassword.less create mode 100644 frontend/client/components/Settings/ChangePassword.tsx create mode 100644 frontend/client/components/Settings/index.less create mode 100644 frontend/client/components/Settings/index.tsx delete mode 100644 frontend/client/components/Template/Web3Error.less delete mode 100644 frontend/client/components/Template/Web3Error.tsx delete mode 100644 frontend/client/lib/Web3Container.tsx delete mode 100644 frontend/client/lib/crowdFundContracts.ts delete mode 100644 frontend/client/lib/crowdFundFactoryContract.ts delete mode 100644 frontend/client/lib/getContract.ts delete mode 100644 frontend/client/lib/getWeb3.ts delete mode 100644 frontend/client/modules/web3/actions.ts delete mode 100644 frontend/client/modules/web3/index.ts delete mode 100644 frontend/client/modules/web3/reducers.ts delete mode 100644 frontend/client/modules/web3/sagas.ts delete mode 100644 frontend/client/modules/web3/selectors.ts delete mode 100644 frontend/client/modules/web3/types.ts delete mode 100644 frontend/client/utils/auth.ts create mode 100644 frontend/client/utils/s3.ts delete mode 100644 frontend/client/utils/wallet.ts delete mode 100644 frontend/client/utils/web3.ts delete mode 100644 frontend/client/web3interact/crowdFund.ts diff --git a/.gitignore b/.gitignore index 721ac915..204755af 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ .idea -contract/build \ No newline at end of file +.DS_Store +.vscode \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 4ac831d7..cab3be3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,22 +15,6 @@ matrix: before_install: - cd backend/ - cp .env.example .env - env: - - CROWD_FUND_URL=https://eip-712.herokuapp.com/contract/crowd-fund CROWD_FUND_FACTORY_URL=https://eip-712.herokuapp.com/contract/factory install: pip install -r requirements/dev.txt script: - flask test - # Contracts - - language: node_js - node_js: 8.13.0 - before_install: - - cd contract/ - install: yarn && yarn add global truffle ganache-cli@6.1.8 - before_script: - - ganache-cli > /dev/null & - - sleep 10 - script: - - yarn run test - env: - - CROWD_FUND_URL=https://eip-712.herokuapp.com/contract/crowd-fund - CROWD_FUND_FACTORY_URL=https://eip-712.herokuapp.com/contract/factory diff --git a/README.md b/README.md index fc57f56e..6844801a 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,12 @@ -# (ALPHA) Grant.io Mono Repo +# ZCash Grant System -This is a collection of the various services and components that make up [Grant.io](http://grant.io). - -[Grant.io](http://grant.io) is under heavy development, and is not considered stable. Use at your own risk! +This is a collection of the various services and components that make up the ZCash Grant System. ### Setup -__________________ - -##### Docker -To get setup quickly, simply use docker-compose to spin up the necessary services - - TBD +--- ##### Locally -Alternatively, run the backend and front-end services locally. Instructions for each respective component can be found in: @@ -24,17 +16,12 @@ Instructions for each respective component can be found in: We currently only offer instructions for unix based systems. Windows may or may not be compatible. - ### Testing + To run tests across all components simultaneously, use the following command TBD - ### Deployment + TBD - - - - - diff --git a/admin/README.md b/admin/README.md index f8f04ad2..38440f85 100644 --- a/admin/README.md +++ b/admin/README.md @@ -11,8 +11,6 @@ This is the admin component of [Grant.io](http://grant.io). yarn ``` -1. Make sure ganache is running and contracts have been built for the dev network (if frontend dev is running this should be the case). - 1. Run the webpack build for the admin ui: ```bash diff --git a/admin/package.json b/admin/package.json index 0b3ccf7d..1b7ad97e 100644 --- a/admin/package.json +++ b/admin/package.json @@ -97,7 +97,6 @@ "tslint-react": "^3.6.0", "typescript": "3.0.3", "url-loader": "^1.1.1", - "web3": "^1.0.0-beta.34", "webpack": "^4.19.0", "webpack-cli": "^3.1.0", "webpack-dev-server": "^3.1.8", @@ -107,7 +106,6 @@ "devDependencies": { "@types/bn.js": "4.11.1", "@types/ethereumjs-util": "5.2.0", - "@types/query-string": "6.1.0", - "@types/web3": "1.0.3" + "@types/query-string": "6.1.0" } } diff --git a/admin/src/components/Home/index.tsx b/admin/src/components/Home/index.tsx index 50cd068e..c9d75b1b 100644 --- a/admin/src/components/Home/index.tsx +++ b/admin/src/components/Home/index.tsx @@ -14,17 +14,8 @@ class Home extends React.Component {

Home

isLoggedIn: {JSON.stringify(store.isLoggedIn)}
-
web3 enabled: {JSON.stringify(store.web3Enabled)}
-
web3 type: {store.web3Type}
-
ethereum network: {store.ethNetId}
-
ethereum account: {store.ethAccount}
-
CrowdFundFactory: {store.crowdFundFactoryDefinitionStatus}
- {userCount > -1 && ( - <> -
user count: {userCount}
-
proposal count: {proposalCount}
- - )} +
user count: {userCount}
+
proposal count: {proposalCount}
); } diff --git a/admin/src/components/Proposals/index.less b/admin/src/components/Proposals/index.less index e00cc4aa..041a517f 100644 --- a/admin/src/components/Proposals/index.less +++ b/admin/src/components/Proposals/index.less @@ -18,16 +18,6 @@ left: 216px; z-index: 5; background: white; - - &-status { - position: fixed; - top: 0.2rem; - right: 0.2rem; - color: white; - padding: 0 0.4rem; - border-radius: 0.5rem; - background: rgba(0, 0, 0, 0.25); - } } &-proposal { @@ -114,83 +104,5 @@ margin: 0.2rem 0 0.2rem 0.4rem; } } - - &-contract { - &-method { - opacity: 0.7; - } - - &-array { - margin-left: 0.7rem; - margin-bottom: 0.2rem; - - &-milestones, - &-contributors { - display: flex; - - & span { - opacity: 0.7; - } - - & > div { - margin-right: 0.5rem; - padding: 0.2rem; - border: 1px solid rgba(0, 0, 0, 0.1); - } - } - } - - &-status { - display: inline-block; - width: 0.6rem; - height: 0.6rem; - border-radius: 0.3rem; - margin-right: 0.2rem; - - &.is-unloaded { - background-color: rgb(197, 197, 197); - } - &.is-loading { - background-color: rgb(241, 177, 0); - } - &.is-waiting { - background-color: rgb(0, 226, 230); - } - &.is-loaded { - background-color: rgb(0, 165, 25); - } - &.is-error { - background-color: rgb(194, 0, 0); - } - } - - &-method { - margin-top: 0.5rem; - } - - &-inputs { - display: inline-block; - min-width: 300px; - background: rgba(0, 0, 0, 0.1); - padding: 0.23rem; - border-radius: 0.2rem; - margin-right: 0.5rem; - } - - &-input { - margin-right: 0.5rem; - - &.is-wei, - &.is-string, - &.is-integer { - width: 13rem; - } - } - - & .ant-alert { - max-width: 600px; - margin: 0.5rem 0 0.5rem 0.8rem; - } - } } } diff --git a/admin/src/components/Proposals/index.tsx b/admin/src/components/Proposals/index.tsx index d8fae60e..c70ca59c 100644 --- a/admin/src/components/Proposals/index.tsx +++ b/admin/src/components/Proposals/index.tsx @@ -1,17 +1,11 @@ import React from 'react'; import { view } from 'react-easy-state'; -import { Icon, Button, Popover, InputNumber, Checkbox, Alert, Input } from 'antd'; +import { Icon, Button, Popover } from 'antd'; import { RouteComponentProps, withRouter } from 'react-router'; import Showdown from 'showdown'; import moment from 'moment'; import store from 'src/store'; -import { - Proposal, - Contract, - ContractMethod as TContractMethod, - ContractMilestone, - ContractContributor, -} from 'src/types'; +import { Proposal } from 'src/types'; import './index.less'; import Field from 'components/Field'; import { Link } from 'react-router-dom'; @@ -52,9 +46,6 @@ class ProposalsNaked extends React.Component { icon="reload" onClick={() => store.fetchProposals()} /> -
- {store.crowdFundGeneralStatus} -
@@ -68,7 +59,6 @@ class ProposalsNaked extends React.Component {
{proposals.length === 0 &&
no proposals
} {proposals.length > 0 && @@ -191,34 +181,6 @@ class ProposalItemNaked extends React.Component {
} /> - {!store.web3Enabled && } - {store.web3Enabled && ( - - - {Object.keys(p.contract) - .map(k => k as keyof Contract) - .map(k => ( - - ))} - - } - /> - )} ); @@ -229,182 +191,5 @@ class ProposalItemNaked extends React.Component { } const ProposalItem = view(ProposalItemNaked); -// tslint:disable-next-line:max-classes-per-file -class ContractMethodNaked extends React.Component< - TContractMethod & { proposalId: number; name: string } -> { - state = {}; - render() { - const { name, value, status, type, format } = this.props; - const isObj = typeof value === 'object' && value !== null; - const isArray = Array.isArray(value); - const fmt = (val: any) => { - if (val && format === 'time') { - const asNumber = Number(val) * 1000; - return `${moment(asNumber).format()} (${moment(asNumber).fromNow()})`; - } else if (val && format === 'duration') { - const asNumber = Number(val) * 1000; - return `${asNumber} (${moment.duration(asNumber).humanize()})`; - } - return value; - }; - if (type === 'send') { - return ; - } - return ( -
-
- {name}: - {(!isObj && {fmt(value)}) || ( -
- {isArray && - name !== 'milestones' && - name !== 'contributors' && - (value as string[]).map((x, i) => ( -
- {i}: {x} -
- ))} - {isArray && - name === 'milestones' && ( -
- {(value as ContractMilestone[]).map((cm, idx) => ( -
-
- paid: {JSON.stringify(cm.paid)} -
-
- amount: {cm.amount} -
-
- payoutRequestVoteDeadline:{' '} - {Number(cm.payoutRequestVoteDeadline) < 2 - ? cm.payoutRequestVoteDeadline - : moment(Number(cm.payoutRequestVoteDeadline) * 1000).fromNow()} -
-
- amountVotingAgainstPayout:{' '} - {cm.amountVotingAgainstPayout} -
-
- ))} -
- )} - {isArray && - name === 'contributors' && ( -
- {(value as ContractContributor[]).map(c => ( -
-
- address: {c.address} -
-
- milestoneNoVotes:{' '} - {JSON.stringify(c.milestoneNoVotes)} -
-
- contributionAmount: {c.contributionAmount} -
-
- refundVote: {JSON.stringify(c.refundVote)} -
-
- refunded: {JSON.stringify(c.refunded)} -
-
- ))} -
- )} -
- )} -
- ); - } -} -const ContractMethod = view(ContractMethodNaked); - -// tslint:disable-next-line:max-classes-per-file -class ContractMethodSendNaked extends React.Component< - TContractMethod & { proposalId: number; name: string } -> { - state = { - args: this.props.input.map(i => (i.type === 'boolean' ? false : '')) as any[], - }; - render() { - const { name, status, input, proposalId, error } = this.props; - return ( -
-
-
- {input.length === 0 && 'no input'} - {input.map( - (x, idx) => - ((x.type === 'wei' || x.type === 'integer') && ( - { - const args = [...this.state.args]; - args[idx] = val; - this.setState({ args }); - }} - value={this.state.args[idx]} - className={`Proposals-proposal-contract-input is-${x.type || ''}`} - /> - )) || - (x.type === 'string' && ( - { - const args = [...this.state.args]; - args[idx] = evt.currentTarget.value; - this.setState({ args }); - }} - value={this.state.args[idx]} - className={`Proposals-proposal-contract-input is-${x.type || ''}`} - /> - )) || ( - { - const args = [...this.state.args]; - args[idx] = evt.target.checked; - this.setState({ args }); - }} - value={this.state.args[idx]} - className={`Proposals-proposal-contract-input is-${x.type || ''}`} - > - {x.name} - - ), - )} -
- - {error && } -
- ); - } -} -const ContractMethodSend = view(ContractMethodSendNaked); - const Proposals = withRouter(view(ProposalsNaked)); export default Proposals; diff --git a/admin/src/store.ts b/admin/src/store.ts index b20dd94b..65f08654 100644 --- a/admin/src/store.ts +++ b/admin/src/store.ts @@ -1,13 +1,6 @@ -import { cloneDeep } from 'lodash'; -import Web3 from 'web3'; import { store } from 'react-easy-state'; import axios, { AxiosError } from 'axios'; -import { User, Proposal, INITIAL_CONTRACT, Contract, ContractMethodInput } from './types'; -import { - initializeWeb3, - populateProposalContract, - proposalContractSend, -} from './web3helper'; +import { User, Proposal } from './types'; // API const api = axios.create({ @@ -50,7 +43,6 @@ async function deleteUser(id: string) { async function fetchProposals() { const { data } = await api.get('/admin/proposals'); - data.forEach((p: Proposal) => (p.contract = cloneDeep(INITIAL_CONTRACT))); return data; } @@ -73,12 +65,6 @@ const app = store({ users: [] as User[], proposalsFetched: false, proposals: [] as Proposal[], - web3Type: '', - web3Enabled: false, - ethNetId: -1, - ethAccount: '', - crowdFundFactoryDefinitionStatus: '', - crowdFundGeneralStatus: 'idle', removeGeneralError(i: number) { app.generalError.splice(i, 1); @@ -144,24 +130,6 @@ const app = store({ } }, - async populateProposalContract(proposalId: number) { - console.log(proposalId); - if (web3) { - await populateProposalContract(app, web3, proposalId); - } - }, - - async proposalContractSend( - proposalId: number, - methodName: keyof Contract, - inputs: ContractMethodInput[], - args: any[], - ) { - if (web3) { - await proposalContractSend(app, web3, proposalId, methodName, inputs, args); - } - }, - async deleteProposal(id: number) { try { await deleteProposal(id); @@ -188,8 +156,5 @@ function handleApiError(e: AxiosError) { app.checkLogin(); window.setInterval(app.checkLogin, 10000); -let web3: null | Web3 = null; -initializeWeb3(app).then(x => (web3 = x)); - export type TApp = typeof app; export default app; diff --git a/admin/src/types.ts b/admin/src/types.ts index 0f14ebcf..608c9209 100644 --- a/admin/src/types.ts +++ b/admin/src/types.ts @@ -23,7 +23,6 @@ export interface Proposal { team: User[]; comments: Comment[]; contractStatus: string; - contract: Contract; } export interface Comment { commentId: string; @@ -41,89 +40,3 @@ export interface User { proposals: Proposal[]; comments: Comment[]; } - -// web3 contract -export const INITIAL_CONTRACT_CONTRIBUTOR = { - address: '', - milestoneNoVotes: [] as string[], - contributionAmount: '', - refundVote: false, - refunded: false, -}; -export type ContractContributor = typeof INITIAL_CONTRACT_CONTRIBUTOR; -export const INITIAL_CONTRACT_MILESTONE = { - amount: '', - payoutRequestVoteDeadline: '', - amountVotingAgainstPayout: '', - paid: '', -}; -export type ContractMilestone = typeof INITIAL_CONTRACT_MILESTONE; -export interface ContractMethodInput { - type: string; - name: string; -} -export const INITIAL_CONTRACT_METHOD = { - updated: '', - status: 'unloaded', - value: '' as string | string[] | ContractMilestone[] | ContractContributor[], - type: '', - input: [] as ContractMethodInput[], - error: '', - format: '', -}; -export type ContractMethod = typeof INITIAL_CONTRACT_METHOD; -export const INITIAL_CONTRACT = { - isCallerTrustee: { ...INITIAL_CONTRACT_METHOD }, - immediateFirstMilestonePayout: { ...INITIAL_CONTRACT_METHOD }, - beneficiary: { ...INITIAL_CONTRACT_METHOD }, - amountRaised: { ...INITIAL_CONTRACT_METHOD }, - raiseGoal: { ...INITIAL_CONTRACT_METHOD }, - isRaiseGoalReached: { ...INITIAL_CONTRACT_METHOD }, - amountVotingForRefund: { ...INITIAL_CONTRACT_METHOD }, - milestoneVotingPeriod: { ...INITIAL_CONTRACT_METHOD, format: 'duration' }, - deadline: { ...INITIAL_CONTRACT_METHOD, format: 'time' }, - isFailed: { ...INITIAL_CONTRACT_METHOD }, - getBalance: { ...INITIAL_CONTRACT_METHOD, type: 'eth' }, - frozen: { ...INITIAL_CONTRACT_METHOD }, - getFreezeReason: { ...INITIAL_CONTRACT_METHOD }, - trustees: { ...INITIAL_CONTRACT_METHOD, type: 'array' }, - contributorList: { ...INITIAL_CONTRACT_METHOD, type: 'array' }, - contributors: { ...INITIAL_CONTRACT_METHOD, type: 'deep' }, - milestones: { ...INITIAL_CONTRACT_METHOD, type: 'array' }, - contribute: { - ...INITIAL_CONTRACT_METHOD, - type: 'send', - input: [{ name: 'value', type: 'wei' }], - }, - refund: { - ...INITIAL_CONTRACT_METHOD, - type: 'send', - input: [], - }, - withdraw: { - ...INITIAL_CONTRACT_METHOD, - type: 'send', - input: [{ name: 'address', type: 'string' }], - }, - requestMilestonePayout: { - ...INITIAL_CONTRACT_METHOD, - type: 'send', - input: [{ name: 'index', type: 'integer' }], - }, - voteMilestonePayout: { - ...INITIAL_CONTRACT_METHOD, - type: 'send', - input: [{ name: 'index', type: 'integer' }, { name: 'vote', type: 'boolean' }], - }, - payMilestonePayout: { - ...INITIAL_CONTRACT_METHOD, - type: 'send', - input: [{ name: 'index', type: 'integer' }], - }, - voteRefund: { - ...INITIAL_CONTRACT_METHOD, - type: 'send', - input: [{ name: 'vote', type: 'boolean' }], - }, -}; -export type Contract = typeof INITIAL_CONTRACT; diff --git a/admin/src/web3helper.ts b/admin/src/web3helper.ts deleted file mode 100644 index 1eeee75e..00000000 --- a/admin/src/web3helper.ts +++ /dev/null @@ -1,227 +0,0 @@ -import { pick } from 'lodash'; -import Web3 from 'web3'; -import { TransactionObject } from 'web3/eth/types'; -import EthContract from 'web3/eth/contract'; -import { TApp } from './store'; -import CrowdFundFactory from 'contracts/contracts/CrowdFundFactory.json'; -import CrowdFund from 'contracts/contracts/CrowdFund.json'; -import { - Proposal, - Contract, - INITIAL_CONTRACT, - ContractMilestone, - ContractContributor, - ContractMethodInput, - INITIAL_CONTRACT_CONTRIBUTOR, - INITIAL_CONTRACT_MILESTONE, -} from './types'; - -type Web3Method = (index: number) => TransactionObject; - -export async function initializeWeb3(app: TApp): Promise { - let web3 = (window as any).web3; - if (web3) { - app.web3Type = 'injected'; - web3 = new Web3(web3.currentProvider); - } else if (process.env.NODE_ENV !== 'production') { - const localProviderString = 'http://localhost:8545'; - const provider = new Web3.providers.HttpProvider(localProviderString); - web3 = new Web3(provider); - app.web3Type = 'local - ' + localProviderString; - } else { - console.error('No web3 detected!'); - app.web3Enabled = false; - return null; - } - try { - app.ethNetId = await web3.eth.net.getId(); - getAccount(app, web3); - window.setInterval(() => getAccount(app, web3), 10000); - checkCrowdFundFactory(app, web3); - app.web3Enabled = true; - return web3; - } catch (e) { - if (e.message && e.message.startsWith('Invalid JSON RPC response:')) { - console.warn('Unable to interact with web3. Web3 will be disabled.'); - } else { - console.error('There was a problem interacting with web3.', e); - } - app.web3Enabled = false; - return null; - } -} - -async function getAccount(app: TApp, web3: Web3) { - await web3.eth.getAccounts((_, accounts) => { - app.ethAccount = (accounts.length && accounts[0]) || ''; - }); -} - -function checkCrowdFundFactory(app: TApp, web3: Web3) { - web3.eth.net.getId((_, netId) => { - const networks = Object.keys((CrowdFundFactory as any).networks).join(', '); - if (!(CrowdFundFactory as any).networks[netId]) { - app.crowdFundFactoryDefinitionStatus = `network mismatch (has ${networks})`; - } else { - app.crowdFundFactoryDefinitionStatus = `loaded, has correct network (${networks})`; - } - }); -} - -export async function proposalContractSend( - app: TApp, - web3: Web3, - proposalId: number, - methodName: keyof Contract, - inputs: ContractMethodInput[], - args: any[], -) { - const storeProposal = app.proposals.find(p => p.proposalId === proposalId); - if (storeProposal) { - const { proposalAddress } = storeProposal; - await getAccount(app, web3); - const storeMethod = storeProposal.contract[methodName]; - const contract = new web3.eth.Contract(CrowdFund.abi, proposalAddress); - app.crowdFundGeneralStatus = `calling (${storeProposal.title}).${methodName}...`; - try { - console.log(args); - storeMethod.status = 'loading'; - storeMethod.error = ''; - if (inputs.length === 1 && inputs[0].name === 'value') { - await contract.methods[methodName]() - .send({ - from: app.ethAccount, - value: args[0], - }) - .once('transactionHash', () => { - storeMethod.status = 'waiting'; - }) - .once('confirmation', () => { - storeMethod.status = 'loaded'; - }); - } else { - await contract.methods[methodName](...args) - .send({ from: app.ethAccount }) - .once('transactionHash', () => { - storeMethod.status = 'waiting'; - }) - .once('confirmation', () => { - storeMethod.status = 'loaded'; - }); - } - } catch (e) { - console.error(e); - storeMethod.error = e.message || e.toString(); - storeMethod.status = 'error'; - } - app.crowdFundGeneralStatus = `idle`; - } -} - -export async function populateProposalContract( - app: TApp, - web3: Web3, - proposalId: number, -) { - const storeProposal = app.proposals.find(p => p.proposalId === proposalId); - - if (storeProposal) { - const { proposalAddress } = storeProposal; - const contract = new web3.eth.Contract(CrowdFund.abi, proposalAddress); - storeProposal.contractStatus = 'loading...'; - const methods = Object.keys(INITIAL_CONTRACT).map(k => k as keyof Contract); - for (const method of methods) { - const methodType = INITIAL_CONTRACT[method].type; - if (methodType !== 'deep' && methodType !== 'send') { - app.crowdFundGeneralStatus = `calling (${storeProposal.title}).${method}...`; - const storeMethod = storeProposal.contract[method]; - const contractMethod = contract.methods[method]; - try { - storeMethod.status = 'loading'; - if (methodType === 'eth' && method === 'getBalance') { - storeMethod.value = (await web3.eth.getBalance(proposalAddress)) + ''; - } else if (methodType === 'array') { - const result = await collectArrayElements(contractMethod, app.ethAccount); - if (method === 'milestones') { - storeMethod.value = result.map(r => - // clean-up incoming object before attaching to store - cleanClone(INITIAL_CONTRACT_MILESTONE, r), - ); - } else { - storeMethod.value = result.map(r => r + ''); - } - } else { - storeMethod.value = - (await contractMethod().call({ from: app.ethAccount })) + ''; - } - storeMethod.status = 'loaded'; - } catch (e) { - console.error(proposalId, method, e); - storeMethod.status = 'error'; - } - } - } - await populateProposalContractDeep(storeProposal.contract, contract, app.ethAccount); - storeProposal.contractStatus = 'updated @ ' + new Date().toISOString(); - app.crowdFundGeneralStatus = `idle`; - } -} - -async function populateProposalContractDeep( - storeContract: Proposal['contract'], - contract: EthContract, - fromAcct: string, -) { - storeContract.contributors.status = 'loading'; - const milestones = storeContract.milestones.value as ContractMilestone[]; - const contributorList = storeContract.contributorList.value as string[]; - const contributors = await Promise.all( - contributorList.map(async addr => { - const contributor = await contract.methods - .contributors(addr) - .call({ from: fromAcct }); - contributor.address = addr; - contributor.milestoneNoVotes = await Promise.all( - milestones.map( - async (_, idx) => - await contract.methods - .getContributorMilestoneVote(addr, idx) - .call({ from: fromAcct }), - ), - ); - contributor.contributionAmount = await contract.methods - .getContributorContributionAmount(addr) - .call({ from: fromAcct }); - // clean-up incoming object before attaching to store - return cleanClone(INITIAL_CONTRACT_CONTRIBUTOR, contributor); - }), - ); - storeContract.contributors.value = contributors as ContractContributor[]; - storeContract.contributors.status = 'loaded'; -} - -// clone and filter keys by keySource object's keys -export function cleanClone(keySource: T, target: Partial) { - const sourceKeys = Object.keys(keySource); - const fullClone = { ...(target as object) }; - const clone = pick(fullClone, sourceKeys); - return clone as T; -} - -export async function collectArrayElements( - method: Web3Method, - account: string, -): Promise { - const arrayElements = []; - let noError = true; - let index = 0; - while (noError) { - try { - arrayElements.push(await method(index).call({ from: account })); - index += 1; - } catch (e) { - noError = false; - } - } - return arrayElements; -} diff --git a/admin/tsconfig.json b/admin/tsconfig.json index 97ac59e8..af600ca1 100644 --- a/admin/tsconfig.json +++ b/admin/tsconfig.json @@ -20,7 +20,6 @@ "lib": ["dom", "es2017"], "paths": { "src/*": ["./*"], - "contracts/*": ["../../contract/build/*"], "components/*": ["./components/*"], "styles/*": ["./styles/*"] } diff --git a/admin/webpack.config.js b/admin/webpack.config.js index 79659a64..df9876b7 100644 --- a/admin/webpack.config.js +++ b/admin/webpack.config.js @@ -113,7 +113,6 @@ module.exports = { // tsconfig.compilerOptions.paths should sync with these alias: { src: path.resolve(__dirname, 'src'), - contracts: path.resolve(__dirname, '../contract/build'), components: path.resolve(__dirname, 'src/components'), styles: path.resolve(__dirname, 'src/styles'), }, diff --git a/admin/yarn.lock b/admin/yarn.lock index f30f87a4..6dc9c256 100644 --- a/admin/yarn.lock +++ b/admin/yarn.lock @@ -1048,7 +1048,7 @@ version "4.14.117" resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.117.tgz#695a7f514182771a1e0f4345d189052ee33c8778" -"@types/node@*", "@types/node@^10.3.2": +"@types/node@*": version "10.12.0" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.12.0.tgz#ea6dcbddbc5b584c83f06c60e82736d8fbb0c235" @@ -1120,17 +1120,6 @@ dependencies: source-map "^0.6.1" -"@types/underscore@*": - version "1.8.9" - resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.8.9.tgz#fef41f800cd23db1b4f262ddefe49cd952d82323" - -"@types/web3@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.3.tgz#2c5f6905d46eb6e40da8eb7c1e553463862fa599" - dependencies: - "@types/bn.js" "*" - "@types/underscore" "*" - "@types/webpack-env@^1.13.6": version "1.13.6" resolved "http://registry.npmjs.org/@types/webpack-env/-/webpack-env-1.13.6.tgz#128d1685a7c34d31ed17010fc87d6a12c1de6976" @@ -1464,10 +1453,6 @@ address@1.0.3, address@>=0.0.1, address@^1.0.1, address@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/address/-/address-1.0.3.tgz#b5f50631f8d6cec8bd20c963963afb55e06cbce9" -aes-js@3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-3.0.0.tgz#e21df10ad6c2053295bcbb8dab40b09dbea87e4d" - af-webpack@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/af-webpack/-/af-webpack-1.1.1.tgz#f557385c7de9a7b2715d0d042aac513d22970116" @@ -1715,7 +1700,7 @@ any-observable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" -any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: +any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" @@ -2212,10 +2197,6 @@ balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" -base64-js@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" - base64-js@^1.0.2: version "1.3.0" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.0.tgz#cab1e6118f051095e58b5281aea8c1cd22bfc0e3" @@ -2291,36 +2272,15 @@ bizcharts@^3.1.10: prop-types "^15.6.0" warning "^3.0.0" -bl@^1.0.0: - version "1.2.2" - resolved "http://registry.npmjs.org/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" - dependencies: - readable-stream "^2.3.5" - safe-buffer "^5.1.1" - -block-stream@*: - version "0.0.9" - resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" - dependencies: - inherits "~2.0.0" - -bluebird@^2.9.34: - version "2.11.0" - resolved "http://registry.npmjs.org/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - -bluebird@^3.5.0, bluebird@^3.5.1: +bluebird@^3.5.1: version "3.5.2" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.2.tgz#1be0908e054a751754549c270489c1505d4ab15a" -bn.js@4.11.6: - version "4.11.6" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - -bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0: +bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" -body-parser@1.18.3, body-parser@^1.16.0, body-parser@^1.18.2: +body-parser@1.18.3, body-parser@^1.18.2: version "1.18.3" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.3.tgz#5b292198ffdd553b3a0f20ded0592b956955c8b4" dependencies: @@ -2441,12 +2401,6 @@ browserify-rsa@^4.0.0: bn.js "^4.1.0" randombytes "^2.0.1" -browserify-sha3@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" - dependencies: - js-sha3 "^0.3.1" - browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" @@ -2496,10 +2450,6 @@ buffer-alloc@^1.2.0: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - buffer-fill@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" @@ -2512,22 +2462,10 @@ buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" -buffer-to-arraybuffer@^0.0.5: - version "0.0.5" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.5.tgz#6064a40fa76eb43c723aba9ef8f6e1216d10511a" - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" -buffer@^3.0.1: - version "3.6.0" - resolved "http://registry.npmjs.org/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" - dependencies: - base64-js "0.0.8" - ieee754 "^1.1.4" - isarray "^1.0.0" - buffer@^4.3.0: version "4.9.1" resolved "http://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" @@ -2536,13 +2474,6 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.5: - version "5.2.1" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - builtin-modules@^1.0.0, builtin-modules@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" @@ -2963,7 +2894,7 @@ combined-stream@^1.0.6, combined-stream@~1.0.6: dependencies: delayed-stream "~1.0.0" -commander@2, commander@^2.12.1, commander@^2.13.0, commander@^2.14.1, commander@^2.8.1, commander@^2.9.0: +commander@2, commander@^2.12.1, commander@^2.13.0, commander@^2.14.1, commander@^2.9.0: version "2.19.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a" @@ -2975,12 +2906,6 @@ commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" -commander@~2.8.1: - version "2.8.1" - resolved "http://registry.npmjs.org/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - dependencies: - graceful-readlink ">= 1.0.0" - commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -3098,7 +3023,7 @@ cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" -cookiejar@^2.1.0, cookiejar@^2.1.1: +cookiejar@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" @@ -3152,13 +3077,6 @@ core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -cors@^2.8.1: - version "2.8.4" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" - dependencies: - object-assign "^4" - vary "^1" - cosmiconfig@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-4.0.0.tgz#760391549580bbd2df1e562bc177b13c290972dc" @@ -3250,7 +3168,7 @@ cross-spawn@^6.0.0, cross-spawn@^6.0.5: shebang-command "^1.2.0" which "^1.2.9" -crypto-browserify@3.12.0, crypto-browserify@^3.11.0: +crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" dependencies: @@ -3676,60 +3594,12 @@ 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" -decompress-response@^3.2.0, decompress-response@^3.3.0: +decompress-response@^3.2.0: version "3.3.0" resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-3.3.0.tgz#80a4dd323748384bfa248083622aedec982adff3" dependencies: mimic-response "^1.0.0" -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -4121,16 +3991,7 @@ element-resize-detector@1.1.13: dependencies: batch-processor "^1.0.0" -elliptic@6.3.3: - version "6.3.3" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.3.3.tgz#5482d9646d54bcb89fd7d994fc9e2e9568876e3f" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - inherits "^2.0.1" - -elliptic@^6.0.0, elliptic@^6.2.3, elliptic@^6.4.0: +elliptic@^6.0.0, elliptic@^6.2.3: version "6.4.1" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" dependencies: @@ -4381,33 +4242,6 @@ etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" -eth-ens-namehash@2.0.8: - version "2.0.8" - resolved "https://registry.yarnpkg.com/eth-ens-namehash/-/eth-ens-namehash-2.0.8.tgz#229ac46eca86d52e0c991e7cb2aef83ff0f68bcf" - dependencies: - idna-uts46-hx "^2.3.1" - js-sha3 "^0.5.7" - -eth-lib@0.1.27, eth-lib@^0.1.26: - version "0.1.27" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - keccakjs "^0.2.1" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" - xhr-request-promise "^0.1.2" - -eth-lib@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - ethereum-blockies-base64@1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/ethereum-blockies-base64/-/ethereum-blockies-base64-1.0.2.tgz#4aebca52142bf4d16a3144e6e2b59303e39ed2b3" @@ -4426,28 +4260,6 @@ ethereumjs-util@5.2.0: safe-buffer "^5.1.1" secp256k1 "^3.0.1" -ethers@4.0.0-beta.1: - version "4.0.0-beta.1" - resolved "https://registry.yarnpkg.com/ethers/-/ethers-4.0.0-beta.1.tgz#0648268b83e0e91a961b1af971c662cdf8cbab6d" - dependencies: - "@types/node" "^10.3.2" - aes-js "3.0.0" - bn.js "^4.4.0" - elliptic "6.3.3" - hash.js "1.1.3" - js-sha3 "0.5.7" - scrypt-js "2.0.3" - setimmediate "1.0.4" - uuid "2.0.1" - xmlhttprequest "1.8.0" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - ethjs-util@^0.1.3: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" @@ -4455,10 +4267,6 @@ ethjs-util@^0.1.3: is-hex-prefixed "1.0.0" strip-hex-prefix "1.0.0" -eventemitter3@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" - eventemitter3@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" @@ -4609,7 +4417,7 @@ expect@^23.6.0: jest-message-util "^23.4.0" jest-regex-util "^23.3.0" -express@^4.14.0, express@^4.16.2: +express@^4.16.2: version "4.16.4" resolved "https://registry.yarnpkg.com/express/-/express-4.16.4.tgz#fddef61926109e24c515ea97fd2f1bdbf62df12e" dependencies: @@ -4769,12 +4577,6 @@ fbjs@^0.8.0, fbjs@^0.8.15, fbjs@^0.8.16, fbjs@^0.8.9: setimmediate "^1.0.5" ua-parser-js "^0.7.18" -fd-slicer@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.1.0.tgz#25c7c89cb1f9077f8891bbe61d8f390eae256f1e" - dependencies: - pend "~1.2.0" - fecha@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fecha/-/fecha-2.3.3.tgz#948e74157df1a32fd1b12c3a3c3cdcb6ec9d96cd" @@ -4806,18 +4608,6 @@ file-loader@^2.0.0: loader-utils "^1.0.2" schema-utils "^1.0.0" -file-type@^3.8.0: - version "3.9.0" - resolved "http://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" - -file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - file-uri-to-path@1: version "1.0.0" resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" @@ -4955,7 +4745,7 @@ font-awesome@^4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/font-awesome/-/font-awesome-4.7.0.tgz#8fa8cf0411a1a31afd07b06d2902bb9fc815a133" -for-each@^0.3.2, for-each@~0.3.3: +for-each@~0.3.3: version "0.3.3" resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" dependencies: @@ -5035,17 +4825,6 @@ from2@^2.1.0: inherits "^2.0.1" readable-stream "^2.0.0" -fs-constants@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" - -fs-extra@^2.0.0, fs-extra@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - fs-extra@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" @@ -5068,15 +4847,6 @@ fs-minipass@^1.2.5: dependencies: minipass "^2.2.1" -fs-promise@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" - dependencies: - any-promise "^1.3.0" - fs-extra "^2.0.0" - mz "^2.6.0" - thenify-all "^1.6.0" - fs-write-stream-atomic@^1.0.8: version "1.0.10" resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" @@ -5097,15 +4867,6 @@ fsevents@^1.2.2, fsevents@^1.2.3: nan "^2.9.2" node-pre-gyp "^0.10.0" -fstream@^1.0.2, fstream@^1.0.8: - version "1.0.11" - resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" - dependencies: - graceful-fs "^4.1.2" - inherits "~2.0.0" - mkdirp ">=0.5 0" - rimraf "2" - ftp@~0.3.10: version "0.3.10" resolved "https://registry.yarnpkg.com/ftp/-/ftp-0.3.10.tgz#9197d861ad8142f3e63d5a83bfe4c59f7330885d" @@ -5158,13 +4919,6 @@ get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" -get-stream@^2.2.0: - version "2.3.1" - resolved "http://registry.npmjs.org/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" - dependencies: - object-assign "^4.0.1" - pinkie-promise "^2.0.0" - get-stream@^3.0.0: version "3.0.0" resolved "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" @@ -5266,7 +5020,7 @@ global-prefix@^1.0.1: is-windows "^1.0.1" which "^1.2.14" -global@4.3.2, global@^4.3.0, global@~4.3.0: +global@4.3.2, global@^4.3.0: version "4.3.2" resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" dependencies: @@ -5314,7 +5068,23 @@ globby@^8.0.1: pify "^3.0.0" slash "^1.0.0" -got@7.1.0, got@^7.0.0, got@^7.1.0: +got@^6.7.1: + version "6.7.1" + resolved "http://registry.npmjs.org/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +got@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" dependencies: @@ -5333,30 +5103,10 @@ got@7.1.0, got@^7.0.0, got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -got@^6.7.1: - version "6.7.1" - resolved "http://registry.npmjs.org/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - dependencies: - create-error-class "^3.0.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" - -graceful-fs@^4.1.10, graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: +graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.6: version "4.1.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" - graphlib@^2.1.5: version "2.1.5" resolved "https://registry.yarnpkg.com/graphlib/-/graphlib-2.1.5.tgz#6afe1afcc5148555ec799e499056795bd6938c87" @@ -5552,13 +5302,6 @@ hash-base@^3.0.0: inherits "^2.0.1" safe-buffer "^5.0.1" -hash.js@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.3.tgz#340dedbe6290187151c1ea1d777a3448935df846" - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.0" - hash.js@^1.0.0, hash.js@^1.0.3, hash.js@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" @@ -5705,10 +5448,6 @@ http-errors@1.6.3, http-errors@~1.6.2, http-errors@~1.6.3: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - http-parser-js@>=0.4.0: version "0.5.0" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.0.tgz#d65edbede84349d0dc30320815a15d39cc3cbbd8" @@ -5805,12 +5544,6 @@ identity-obj-proxy@^3.0.0: dependencies: harmony-reflect "^1.4.6" -idna-uts46-hx@^2.3.1: - version "2.3.1" - resolved "https://registry.yarnpkg.com/idna-uts46-hx/-/idna-uts46-hx-2.3.1.tgz#a1dc5c4df37eee522bf66d969cc980e00e8711f9" - dependencies: - punycode "2.1.0" - ieee754@^1.1.4: version "1.1.12" resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.12.tgz#50bf24e5b9c8bb98af4964c941cdb0918da7b60b" @@ -5900,7 +5633,7 @@ inflight@^1.0.4: once "^1.3.0" wrappy "1" -inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: +inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" @@ -6155,10 +5888,6 @@ is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" -is-function@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - is-generator-fn@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-generator-fn/-/is-generator-fn-1.0.0.tgz#969d49e1bb3329f6bb7f09089be26578b2ddd46a" @@ -6199,10 +5928,6 @@ is-installed-globally@^0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - is-negative-zero@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" @@ -6343,7 +6068,7 @@ is-symbol@^1.0.2: dependencies: has-symbols "^1.0.0" -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -6774,14 +6499,6 @@ js-levenshtein@^1.1.3: version "1.1.4" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.4.tgz#3a56e3cbf589ca0081eb22cd9ba0b1290a16d26e" -js-sha3@0.5.7, js-sha3@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.5.7.tgz#0d4ffd8002d5333aabaf4a23eed2f6374c9f28e7" - -js-sha3@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" - js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -6924,12 +6641,6 @@ jsonfile-updater@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/jsonfile-updater/-/jsonfile-updater-3.1.0.tgz#fd29c28d85bb2a96200b53832643a17865db1e85" -jsonfile@^2.1.0: - version "2.4.0" - resolved "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - optionalDependencies: - graceful-fs "^4.1.6" - jsonfile@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-3.0.1.tgz#a5ecc6f65f53f662c4415c7675a0331d0992ec66" @@ -6971,13 +6682,6 @@ keccak@^1.0.2: nan "^2.2.1" safe-buffer "^5.1.0" -keccakjs@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" - dependencies: - browserify-sha3 "^0.0.1" - sha3 "^1.1.0" - killable@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" @@ -7562,7 +7266,7 @@ miller-rabin@^4.0.0: version "1.37.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.37.0.tgz#0b6a0ce6fdbe9576e25f1f2d2fde8830dc0ad0d8" -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.18, mime-types@~2.1.19: version "2.1.21" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.21.tgz#28995aa1ecb770742fe6ae7e58f9181c744b3f96" dependencies: @@ -7685,22 +7389,12 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - dependencies: - mkdirp "*" - -mkdirp@*, mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.x, mkdirp@0.x, mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" dependencies: minimist "0.0.8" -mock-fs@^4.1.0: - version "4.7.0" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.7.0.tgz#9f17e219cacb8094f4010e0a8c38589e2b33c299" - moment@2.x, moment@^2.19.3, moment@^2.22.2: version "2.22.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" @@ -7709,10 +7403,6 @@ moo@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e" -mout@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" - move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -7764,7 +7454,7 @@ mute-stream@0.0.7: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -mz@^2.6.0, mz@^2.7.0: +mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" dependencies: @@ -7772,18 +7462,10 @@ mz@^2.6.0, mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@2.10.0: - version "2.10.0" - resolved "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - -nan@^2.0.8, nan@^2.2.1, nan@^2.3.3, nan@^2.9.2: +nan@^2.2.1, nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" -nano-json-stream-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" - nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -8036,13 +7718,6 @@ number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" -number-to-bn@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - dependencies: - bn.js "4.11.6" - strip-hex-prefix "1.0.0" - numeral@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/numeral/-/numeral-2.0.6.tgz#4ad080936d443c2561aed9f2197efffe25f4e506" @@ -8055,7 +7730,7 @@ oauth-sign@~0.9.0: version "0.9.0" resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" -object-assign@4.x, object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: +object-assign@4.x, object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" @@ -8132,12 +7807,6 @@ object.values@^1.0.4: function-bind "^1.1.0" has "^1.0.1" -oboe@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" - dependencies: - http-https "^1.0.0" - obuf@^1.0.0, obuf@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -8395,13 +8064,6 @@ parse-glob@^3.0.4: is-extglob "^1.0.0" is-glob "^2.0.0" -parse-headers@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" - dependencies: - for-each "^0.3.2" - trim "0.0.1" - parse-json@^2.2.0: version "2.2.0" resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" @@ -8521,10 +8183,6 @@ pbkdf2@^3.0.3: safe-buffer "^5.0.1" sha.js "^2.4.8" -pend@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -9082,10 +8740,6 @@ punycode@1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" -punycode@2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.0.tgz#5f863edc89b96db09074bad7947bf09056ca4e7d" - punycode@^1.2.4, punycode@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" @@ -9180,10 +8834,6 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -randomhex@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" - range-parser@^1.0.3, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -9800,7 +9450,7 @@ read-pkg@^4.0.1: parse-json "^4.0.0" pify "^3.0.0" -"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.0, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: +"readable-stream@1 || 2", readable-stream@2, readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.4, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6: version "2.3.6" resolved "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" dependencies: @@ -10029,7 +9679,7 @@ request-promise-native@^1.0.5: stealthy-require "^1.1.0" tough-cookie ">=2.3.3" -request@^2.79.0, request@^2.83.0, request@^2.87.0, request@^2.88.0: +request@^2.83.0, request@^2.87.0, request@^2.88.0: version "2.88.0" resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" dependencies: @@ -10167,7 +9817,7 @@ right-align@^0.1.1: dependencies: align-text "^0.1.1" -rimraf@2, rimraf@^2.2.8, rimraf@^2.4.4, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: +rimraf@^2.2.8, rimraf@^2.4.4, rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.2: version "2.6.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" dependencies: @@ -10319,29 +9969,6 @@ scoped-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" -scrypt-js@2.0.3: - version "2.0.3" - resolved "http://registry.npmjs.org/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" - -scrypt.js@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" - dependencies: - scrypt "^6.0.2" - scryptsy "^1.2.1" - -scrypt@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - dependencies: - nan "^2.0.8" - -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - dependencies: - pbkdf2 "^3.0.3" - secp256k1@^3.0.1: version "3.5.2" resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.2.tgz#f95f952057310722184fe9c914e6b71281f2f2ae" @@ -10355,12 +9982,6 @@ secp256k1@^3.0.1: nan "^2.2.1" safe-buffer "^5.1.0" -seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - dependencies: - commander "~2.8.1" - select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -10428,16 +10049,6 @@ serve-static@1.13.2: parseurl "~1.3.2" send "0.16.2" -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -10460,10 +10071,6 @@ set-value@^2.0.0: is-plain-object "^2.0.3" split-string "^3.0.1" -setimmediate@1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.4.tgz#20e81de622d4a02588ce0c8da8973cbcf1d3138f" - setimmediate@^1.0.4, setimmediate@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" @@ -10479,12 +10086,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -sha3@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" - dependencies: - nan "2.10.0" - shallow-clone@^0.1.2: version "0.1.2" resolved "https://registry.yarnpkg.com/shallow-clone/-/shallow-clone-0.1.2.tgz#5909e874ba77106d73ac414cfec1ffca87d97060" @@ -10557,18 +10158,6 @@ signale@^1.3.0: figures "^2.0.0" pkg-conf "^2.1.0" -simple-concat@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.0.tgz#7344cbb8b6e26fb27d66b2fc86f9f6d5997521c6" - -simple-get@^2.7.0: - version "2.8.1" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-2.8.1.tgz#0e22e91d4575d87620620bc91308d57a77f44b5d" - dependencies: - decompress-response "^3.3.0" - once "^1.3.1" - simple-concat "^1.0.0" - simple-statistics@~6.1.0: version "6.1.1" resolved "https://registry.yarnpkg.com/simple-statistics/-/simple-statistics-6.1.1.tgz#e3a0799ffc49914d6f421c5a4ac585f6a13e2bad" @@ -11003,12 +10592,6 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - dependencies: - is-natural-number "^4.0.1" - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" @@ -11101,24 +10684,6 @@ svgo@^1.0.0, svgo@^1.0.5: unquote "~1.1.1" util.promisify "~1.0.0" -swarm-js@0.1.37: - version "0.1.37" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - decompress "^4.0.0" - eth-lib "^0.1.26" - fs-extra "^2.1.2" - fs-promise "^2.0.0" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar.gz "^1.0.5" - xhr-request-promise "^0.1.2" - symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -11160,36 +10725,6 @@ tape@^4.5.1: string.prototype.trim "~1.1.2" through "~2.3.8" -tar-stream@^1.5.2: - version "1.6.2" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" - dependencies: - bl "^1.0.0" - buffer-alloc "^1.2.0" - end-of-stream "^1.0.0" - fs-constants "^1.0.0" - readable-stream "^2.3.0" - to-buffer "^1.1.1" - xtend "^4.0.0" - -tar.gz@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" - dependencies: - bluebird "^2.9.34" - commander "^2.8.1" - fstream "^1.0.8" - mout "^0.11.0" - tar "^2.1.1" - -tar@^2.1.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" - dependencies: - block-stream "*" - fstream "^1.0.2" - inherits "2" - tar@^4: version "4.4.6" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.6.tgz#63110f09c00b4e60ac8bcfe1bf3c8660235fbc9b" @@ -11226,7 +10761,7 @@ textextensions@2: version "2.2.0" resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286" -thenify-all@^1.0.0, thenify-all@^1.6.0: +thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" dependencies: @@ -11261,7 +10796,7 @@ thunky@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.3.tgz#f5df732453407b09191dae73e2a8cc73f381a826" -timed-out@^4.0.0, timed-out@^4.0.1: +timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" @@ -11293,10 +10828,6 @@ to-arraybuffer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" -to-buffer@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" - to-fast-properties@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" @@ -11362,10 +10893,6 @@ trim-right@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - tryer@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" @@ -11527,12 +11054,6 @@ type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" -typedarray-to-buffer@^3.1.2: - version "3.1.5" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" - dependencies: - is-typedarray "^1.0.0" - typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -11589,10 +11110,6 @@ uglifyjs-webpack-plugin@^1.2.4: webpack-sources "^1.1.0" worker-farm "^1.5.2" -ultron@~1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.1.tgz#9fe1536a10a664a65266a1e3ccf85fd36302bc9c" - umi-build-dev@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/umi-build-dev/-/umi-build-dev-1.1.2.tgz#1daa5744a78a1a2cd4ba9390ad383fb5bf05ca58" @@ -11712,17 +11229,6 @@ umi@^2.0.0-beta.10: url "^0.11.0" yargs-parser "^10.1.0" -unbzip2-stream@^1.0.9: - version "1.3.1" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.3.1.tgz#7854da51622a7e63624221196357803b552966a1" - dependencies: - buffer "^3.0.1" - through "^2.3.6" - -underscore@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" - underscore@~1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.4.4.tgz#61a6a32010622afa07963bf325203cf12239d604" @@ -11886,10 +11392,6 @@ url-polyfill@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/url-polyfill/-/url-polyfill-1.1.0.tgz#d34e1a596d954b864bc8608f84c592820df422db" -url-set-query@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" @@ -11924,10 +11426,6 @@ use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" -utf8@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" - util-deprecate@^1.0.1, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" @@ -11975,10 +11473,6 @@ utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" -uuid@2.0.1: - version "2.0.1" - resolved "http://registry.npmjs.org/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - uuid@^3.0.1, uuid@^3.1.0, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" @@ -11998,7 +11492,7 @@ value-equal@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-0.4.0.tgz#c5bdd2f54ee093c04839d71ce2e4758a6890abc7" -vary@^1, vary@~1.1.2: +vary@~1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" @@ -12109,214 +11603,6 @@ wbuf@^1.1.0, wbuf@^1.7.2: dependencies: minimalistic-assert "^1.0.0" -web3-bzz@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.36.tgz#adb3fe7a70053eb7843e32b106792b01b482ef41" - dependencies: - got "7.1.0" - swarm-js "0.1.37" - underscore "1.8.3" - -web3-core-helpers@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.36.tgz#6f618e80f1a6588d846efbfdc28f92ae0477f8d2" - dependencies: - underscore "1.8.3" - web3-eth-iban "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-core-method@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.36.tgz#855c0365ae7d0ead394d973ea9e28828602900e0" - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-core-promievent@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.36.tgz#3a5127787fff751be6de272722cbc77dc9523fd5" - dependencies: - any-promise "1.3.0" - eventemitter3 "1.1.1" - -web3-core-requestmanager@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.36.tgz#70c8eead84da9ed1cf258e6dde3f137116d0691b" - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - web3-providers-http "1.0.0-beta.36" - web3-providers-ipc "1.0.0-beta.36" - web3-providers-ws "1.0.0-beta.36" - -web3-core-subscriptions@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.36.tgz#20f1f20c85d5b40f1e5a49b070ba977a142621f3" - dependencies: - eventemitter3 "1.1.1" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - -web3-core@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.36.tgz#86182f2456c2cf1cd6e7654d314e195eac211917" - dependencies: - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-requestmanager "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-abi@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.36.tgz#21c0f222701db827a8a269accb9cd18bbd8f70f9" - dependencies: - ethers "4.0.0-beta.1" - underscore "1.8.3" - web3-utils "1.0.0-beta.36" - -web3-eth-accounts@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.36.tgz#8aea37df9b038ef2c6cda608856ffd861b39eeef" - dependencies: - any-promise "1.3.0" - crypto-browserify "3.12.0" - eth-lib "0.2.7" - scrypt.js "0.2.0" - underscore "1.8.3" - uuid "2.0.1" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-contract@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.36.tgz#c0c366c4e4016896142208cee758a2ff2a31be2a" - dependencies: - underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-ens@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.0.0-beta.36.tgz#c7440b42b597fd74f64bc402f03ad2e832f423d8" - dependencies: - eth-ens-namehash "2.0.8" - underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-promievent "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-eth-contract "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth-iban@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.36.tgz#00cb3aba7a5aeb15d02b07421042e263d7b2e01b" - dependencies: - bn.js "4.11.6" - web3-utils "1.0.0-beta.36" - -web3-eth-personal@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.36.tgz#95545998a8ee377e3bb71e27c8d1a5dc1d7d5a21" - dependencies: - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-eth@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.36.tgz#04a8c748d344c1accaa26d7d5d0eac0da7127f14" - dependencies: - underscore "1.8.3" - web3-core "1.0.0-beta.36" - web3-core-helpers "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-eth-abi "1.0.0-beta.36" - web3-eth-accounts "1.0.0-beta.36" - web3-eth-contract "1.0.0-beta.36" - web3-eth-ens "1.0.0-beta.36" - web3-eth-iban "1.0.0-beta.36" - web3-eth-personal "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-net@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.36.tgz#396cd35cb40934ed022a1f44a8a642d3908c41eb" - dependencies: - web3-core "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - -web3-providers-http@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.36.tgz#c1937a2e64f8db7cd30f166794e37cf0fcca1131" - dependencies: - web3-core-helpers "1.0.0-beta.36" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.36.tgz#0c78efb4ed6b0305ec830e1e0b785e61217ee605" - dependencies: - oboe "2.1.3" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - -web3-providers-ws@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.36.tgz#27b74082c7adfa0cb5a65535eb312e49008c97c3" - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.36" - websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" - -web3-shh@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.36.tgz#6ff297594480edefc710d9d287765a0c4a5d5af1" - dependencies: - web3-core "1.0.0-beta.36" - web3-core-method "1.0.0-beta.36" - web3-core-subscriptions "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - -web3-utils@1.0.0-beta.36: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.36.tgz#dc19c9aeec009b1816cc91ef64d7fe9f8ee344c9" - dependencies: - bn.js "4.11.6" - eth-lib "0.1.27" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randomhex "0.1.5" - underscore "1.8.3" - utf8 "2.1.1" - -web3@^1.0.0-beta.34: - version "1.0.0-beta.36" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.36.tgz#2954da9e431124c88396025510d840ba731c8373" - dependencies: - web3-bzz "1.0.0-beta.36" - web3-core "1.0.0-beta.36" - web3-eth "1.0.0-beta.36" - web3-eth-personal "1.0.0-beta.36" - web3-net "1.0.0-beta.36" - web3-shh "1.0.0-beta.36" - web3-utils "1.0.0-beta.36" - webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -12577,15 +11863,6 @@ websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" -"websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": - version "1.0.26" - resolved "git://github.com/frozeman/WebSocket-Node.git#6c72925e3f8aaaea8dc8450f97627e85263999f2" - dependencies: - debug "^2.2.0" - nan "^2.3.3" - typedarray-to-buffer "^3.1.2" - yaeti "^0.0.6" - whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz#5abacf777c32166a51d085d6b4f3e7d27113ddb0" @@ -12711,14 +11988,6 @@ write-json-file@^2.3.0: sort-keys "^2.0.0" write-file-atomic "^2.0.0" -ws@^3.0.0: - version "3.3.3" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.3.tgz#f1cf84fe2d5e901ebce94efaece785f187a228f2" - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - ws@^4.0.0: version "4.1.0" resolved "http://registry.npmjs.org/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" @@ -12742,39 +12011,6 @@ xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" -xhr-request-promise@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" - dependencies: - xhr-request "^1.0.1" - -xhr-request@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.1.0.tgz#f4a7c1868b9f198723444d82dcae317643f2e2ed" - dependencies: - buffer-to-arraybuffer "^0.0.5" - object-assign "^4.1.1" - query-string "^5.0.1" - simple-get "^2.7.0" - timed-out "^4.0.1" - url-set-query "^1.0.0" - xhr "^2.0.4" - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - dependencies: - cookiejar "^2.1.1" - -xhr@^2.0.4, xhr@^2.3.3: - version "2.5.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" - dependencies: - global "~4.3.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" @@ -12783,10 +12019,6 @@ xmlchars@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/xmlchars/-/xmlchars-1.3.1.tgz#1dda035f833dbb4f86a0c28eaa6ca769214793cf" -xmlhttprequest@1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - xregexp@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/xregexp/-/xregexp-2.0.0.tgz#52a63e56ca0b84a7f3a5f3d61872f126ad7a5943" @@ -12814,10 +12046,6 @@ y18n@^3.2.1: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" @@ -12921,13 +12149,6 @@ yargs@~3.10.0: decamelize "^1.0.0" window-size "0.1.0" -yauzl@^2.4.2: - version "2.10.0" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.1.0" - yeoman-environment@^2.0.5: version "2.3.3" resolved "https://registry.yarnpkg.com/yeoman-environment/-/yeoman-environment-2.3.3.tgz#1bd9720714cc49036e901503a789d809df8f51bf" diff --git a/backend/.env.example b/backend/.env.example index bbeced82..253953c3 100644 --- a/backend/.env.example +++ b/backend/.env.example @@ -7,17 +7,11 @@ REDISTOGO_URL="redis://localhost:6379" SECRET_KEY="not-so-secret" SENDGRID_API_KEY="optional, but emails won't send without it" -# for ropsten use the following -# ETHEREUM_ENDPOINT_URI = "https://ropsten.infura.io/API_KEY" -ETHEREUM_ENDPOINT_URI = "http://localhost:8545" - -# CROWD_FUND_URL = "https://eip-712.herokuapp.com/contract/crowd-fund" -# CROWD_FUND_FACTORY_URL = "https://eip-712.herokuapp.com/contract/factory" -CROWD_FUND_URL = "http://localhost:5000/dev-contracts/CrowdFund.json" -CROWD_FUND_FACTORY_URL = "http://localhost:5000/dev-contracts/CrowdFundFactory.json" # SENTRY_DSN="https://PUBLICKEY@sentry.io/PROJECTID" # SENTRY_RELEASE="optional, overrides git hash" -UPLOAD_DIRECTORY = "/tmp" -UPLOAD_URL = "http://localhost:5000" # for constructing download url +AWS_ACCESS_KEY_ID=your-user-access-key +AWS_SECRET_ACCESS_KEY=your-user-secret-access-key +AWS_DEFAULT_REGION=us-west-2 +S3_BUCKET=your-bucket-name diff --git a/backend/README.md b/backend/README.md index 21ba7b86..a5f46d57 100644 --- a/backend/README.md +++ b/backend/README.md @@ -29,8 +29,8 @@ database tables and perform the initial migration flask db migrate flask db upgrade - ## Running the App + Depending on what you need to run, there are several services that need to be started If you just need the API, you can run @@ -46,9 +46,8 @@ To deploy export DATABASE_URL="" flask run # start the flask server -In your production environment, make sure the ``FLASK_DEBUG`` environment -variable is unset or is set to ``0``. - +In your production environment, make sure the `FLASK_DEBUG` environment +variable is unset or is set to `0`. ## Shell @@ -56,8 +55,7 @@ To open the interactive shell, run flask shell -By default, you will have access to the flask ``app``. - +By default, you will have access to the flask `app`. ## Running Tests @@ -65,7 +63,6 @@ To run all tests, run flask test - ## Migrations Whenever a database migration needs to be made. Run the following commands @@ -78,18 +75,65 @@ This will generate a new migration script. Then run To apply the migration. -For a full migration command reference, run ``flask db --help``. +For a full migration command reference, run `flask db --help`. ## Commands + To create a proposal, run flask create_proposal "FUNDING_REQUIRED" 1 123 "My Awesome Proposal" "### Hi! I have a great proposal" ## External Services + To decode EIP-712 signed messages, a Grant.io deployed service was created `https://eip-712.herokuapp.com`. To adjust this endpoint, simply export `AUTH_URL` with a new endpoint value: export AUTH_URL=http://new-endpoint.com -To learn more about this auth service, you can visit the repo [here](https://github.com/grant-project/eip-712-server). \ No newline at end of file +To learn more about this auth service, you can visit the repo [here](https://github.com/grant-project/eip-712-server). + +## S3 Storage Setup + +1. create bucket, keep the `bucket name` and `region` handy +1. unblock public access `Amazon S3 > BUCKET_NAME > Permissions > Public access settings` +1. set the CORS configuration, replace HOST_NAME with desired domain, or `*` to allow all + Amazon S3 > BUCKET_NAME > Permissions > CORS configuration + + ``` + + + + HOST_NAME + GET + POST + PUT + * + + + ``` + +1. create IAM Policy, replace `BUCKET_NAME` with correct name. + + ``` + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "s3:PutObject", + "s3:PutObjectAcl", + "s3:GetObject", + "s3:DeleteObject" + ], + "Resource": [ + "arn:aws:s3:::BUCKET_NAME/*" + ] + } + ] + } + ``` + +1. create IAM user with programatic access (Access key) and assign that user the policy created above +1. copy the user's `Access key ID`, `Secret access key`, `bucket name` & `bucket region` to private `.env`, see `.env.example` diff --git a/backend/grant/app.py b/backend/grant/app.py index 104b09e7..59ff9d28 100644 --- a/backend/grant/app.py +++ b/backend/grant/app.py @@ -3,11 +3,12 @@ from flask import Flask from flask_cors import CORS from flask_sslify import SSLify +from flask_security import SQLAlchemyUserDatastore from sentry_sdk.integrations.flask import FlaskIntegration import sentry_sdk -from grant import commands, proposal, user, comment, milestone, admin, email, web3 as web3module -from grant.extensions import bcrypt, migrate, db, ma, mail, web3 +from grant import commands, proposal, user, comment, milestone, admin, email +from grant.extensions import bcrypt, migrate, db, ma, mail, security from grant.settings import SENTRY_RELEASE, ENV @@ -36,9 +37,11 @@ def register_extensions(app): migrate.init_app(app, db) ma.init_app(app) mail.init_app(app) - web3.init_app(app) + user_datastore = SQLAlchemyUserDatastore(db, user.models.User, user.models.Role) + security.init_app(app, user_datastore) - CORS(app) + # supports_credentials for session cookies + CORS(app, supports_credentials=True) SSLify(app) return None @@ -51,9 +54,6 @@ def register_blueprints(app): app.register_blueprint(milestone.views.blueprint) app.register_blueprint(admin.views.blueprint) app.register_blueprint(email.views.blueprint) - # Only add these routes locally - if ENV == 'development': - app.register_blueprint(web3module.dev_contracts.blueprint) def register_shellcontext(app): diff --git a/backend/grant/commands.py b/backend/grant/commands.py index 62dd4d9c..b652e099 100644 --- a/backend/grant/commands.py +++ b/backend/grant/commands.py @@ -15,11 +15,19 @@ TEST_PATH = os.path.join(PROJECT_ROOT, "tests") @click.command() -def test(): +@click.option( + "-t", + "--test", + default=None, + help="Specify a specific test string to match (ex: test_api_user)" +) +def test(test): """Run the tests.""" import pytest - - rv = pytest.main([TEST_PATH, "--verbose"]) + if test: + rv = pytest.main([TEST_PATH, "--verbose", "-k", test]) + else: + rv = pytest.main([TEST_PATH, "--verbose"]) exit(rv) diff --git a/backend/grant/email/send.py b/backend/grant/email/send.py index c2928dd2..3efca35b 100644 --- a/backend/grant/email/send.py +++ b/backend/grant/email/send.py @@ -9,6 +9,7 @@ default_template_args = { 'unsubscribe_url': 'https://grant.io/unsubscribe', } + def signup_info(email_args): return { 'subject': 'Confirm your email on Grant.io', @@ -16,6 +17,7 @@ def signup_info(email_args): 'preview': 'Welcome to Grant.io, we just need to confirm your email address.', } + def team_invite_info(email_args): return { 'subject': '{} has invited you to a project'.format(email_args['inviter'].display_name), @@ -23,6 +25,7 @@ def team_invite_info(email_args): 'preview': 'You’ve been invited to the "{}" project team'.format(email_args['proposal'].title) } + get_info_lookup = { 'signup': signup_info, 'team_invite': team_invite_info diff --git a/backend/grant/extensions.py b/backend/grant/extensions.py index 2dc1f7e9..afbfe70a 100644 --- a/backend/grant/extensions.py +++ b/backend/grant/extensions.py @@ -5,11 +5,11 @@ from flask_marshmallow import Marshmallow from flask_migrate import Migrate from flask_sqlalchemy import SQLAlchemy from flask_sendgrid import SendGrid -from flask_web3 import FlaskWeb3 +from flask_security import Security bcrypt = Bcrypt() db = SQLAlchemy() migrate = Migrate() ma = Marshmallow() mail = SendGrid() -web3 = FlaskWeb3() +security = Security() diff --git a/backend/grant/proposal/models.py b/backend/grant/proposal/models.py index 33c74173..4e7e1761 100644 --- a/backend/grant/proposal/models.py +++ b/backend/grant/proposal/models.py @@ -53,7 +53,6 @@ class ProposalTeamInvite(db.Model): def get_pending_for_user(user): return ProposalTeamInvite.query.filter( ProposalTeamInvite.accepted == None, - (func.lower(user.account_address) == func.lower(ProposalTeamInvite.address)) | (func.lower(user.email_address) == func.lower(ProposalTeamInvite.address)) ).all() diff --git a/backend/grant/proposal/views.py b/backend/grant/proposal/views.py index 185f7994..04fc8c9a 100644 --- a/backend/grant/proposal/views.py +++ b/backend/grant/proposal/views.py @@ -10,10 +10,9 @@ from grant.comment.models import Comment, comment_schema, comments_schema from grant.milestone.models import Milestone from grant.user.models import User, SocialMedia, Avatar from grant.email.send import send_email -from grant.utils.auth import requires_sm, requires_team_member_auth, verify_signed_auth, BadSignatureException +from grant.utils.auth import requires_auth, requires_team_member_auth from grant.utils.exceptions import ValidationException -from grant.utils.misc import is_email, make_url -from grant.web3.proposal import read_proposal +from grant.utils.misc import is_email from .models import( Proposal, proposals_schema, @@ -53,7 +52,7 @@ def get_proposal_comments(proposal_id): proposal = Proposal.query.filter_by(id=proposal_id).first() if not proposal: return {"message": "No proposal matching id"}, 404 - + # Only pull top comments, replies will be attached to them comments = Comment.query.filter_by(proposal_id=proposal_id, parent_comment_id=None) num_comments = Comment.query.filter_by(proposal_id=proposal_id).count() @@ -65,12 +64,10 @@ def get_proposal_comments(proposal_id): @blueprint.route("//comments", methods=["POST"]) -@requires_sm +@requires_auth @endpoint.api( parameter('comment', type=str, required=True), - parameter('parentCommentId', type=int, required=False), - parameter('signedMessage', type=str, required=True), - parameter('rawTypedData', type=str, required=True) + parameter('parentCommentId', type=int, required=False) ) def post_proposal_comments(proposal_id, comment, parent_comment_id, signed_message, raw_typed_data): # Make sure proposal exists @@ -84,24 +81,6 @@ def post_proposal_comments(proposal_id, comment, parent_comment_id, signed_messa if not parent: return {"message": "Parent comment doesn’t exist"}, 400 - # Make sure comment content matches - typed_data = ast.literal_eval(raw_typed_data) - if comment != typed_data['message']['comment']: - return {"message": "Comment doesn’t match signature data"}, 400 - - # Verify the signature - try: - sig_address = verify_signed_auth(signed_message, raw_typed_data) - if sig_address.lower() != g.current_user.account_address.lower(): - return { - "message": "Message signature address ({sig_address}) doesn't match current account address ({account_address})".format( - sig_address=sig_address, - account_address=g.current_user.account_address - ) - }, 400 - except BadSignatureException: - return {"message": "Invalid message signature"}, 400 - # Make the comment comment = Comment( proposal_id=proposal_id, @@ -123,27 +102,21 @@ def get_proposals(stage): if stage: proposals = ( Proposal.query.filter_by(status="LIVE", stage=stage) - .order_by(Proposal.date_created.desc()) - .all() + .order_by(Proposal.date_created.desc()) + .all() ) else: proposals = Proposal.query.order_by(Proposal.date_created.desc()).all() dumped_proposals = proposals_schema.dump(proposals) - - try: - for p in dumped_proposals: - proposal_contract = read_proposal(p['proposal_address']) - p['crowd_fund'] = proposal_contract - filtered_proposals = list(filter(lambda p: p['crowd_fund'] is not None, dumped_proposals)) - return filtered_proposals - except Exception as e: - print(e) - print(traceback.format_exc()) - return {"message": "Oops! Something went wrong."}, 500 + return dumped_proposals + # except Exception as e: + # print(e) + # print(traceback.format_exc()) + # return {"message": "Oops! Something went wrong."}, 500 @blueprint.route("/drafts", methods=["POST"]) -@requires_sm +@requires_auth @endpoint.api() def make_proposal_draft(): proposal = Proposal.create(status="DRAFT") @@ -154,7 +127,7 @@ def make_proposal_draft(): @blueprint.route("/drafts", methods=["GET"]) -@requires_sm +@requires_auth @endpoint.api() def get_proposal_drafts(): proposals = ( @@ -167,6 +140,7 @@ def get_proposal_drafts(): ) return proposals_schema.dump(proposals), 200 + @blueprint.route("/", methods=["PUT"]) @requires_team_member_auth @endpoint.api( @@ -202,7 +176,7 @@ def update_proposal(milestones, proposal_id, **kwargs): proposal_id=g.current_proposal.id ) db.session.add(m) - + # Commit db.session.commit() return proposal_schema.dump(g.current_proposal), 200 @@ -278,6 +252,7 @@ def post_proposal_update(proposal_id, title, content): dumped_update = proposal_update_schema.dump(update) return dumped_update, 201 + @blueprint.route("//invite", methods=["POST"]) @requires_team_member_auth @endpoint.api( @@ -294,7 +269,7 @@ def post_proposal_team_invite(proposal_id, address): # Send email # TODO: Move this to some background task / after request action email = address - user = User.get_by_identifier(email_address=address, account_address=address) + user = User.get_by_email(email_address=address) if user: email = user.email_address if is_email(email): @@ -352,7 +327,7 @@ def get_proposal_contribution(proposal_id, contribution_id): @blueprint.route("//contributions", methods=["POST"]) -@requires_sm +@requires_auth @endpoint.api( parameter('txId', type=str, required=True), parameter('fromAddress', type=str, required=True), diff --git a/backend/grant/settings.py b/backend/grant/settings.py index 11b14a5e..e42b0eab 100644 --- a/backend/grant/settings.py +++ b/backend/grant/settings.py @@ -9,21 +9,20 @@ environment variables. import subprocess from environs import Env + def git_revision_short_hash(): try: return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD']) except subprocess.CalledProcessError: return 0 + env = Env() env.read_env() ENV = env.str("FLASK_ENV", default="production") DEBUG = ENV == "development" SITE_URL = env.str('SITE_URL', default='https://grant.io') -AUTH_URL = env.str('AUTH_URL', default='https://eip-712.herokuapp.com') -CROWD_FUND_FACTORY_URL = env.str('CROWD_FUND_FACTORY_URL', default=None) -CROWD_FUND_URL = env.str('CROWD_FUND_URL', default=None) SQLALCHEMY_DATABASE_URI = env.str("DATABASE_URL") QUEUES = ["default"] SECRET_KEY = env.str("SECRET_KEY") @@ -34,10 +33,13 @@ CACHE_TYPE = "simple" # Can be "memcached", "redis", etc. SQLALCHEMY_TRACK_MODIFICATIONS = False SENDGRID_API_KEY = env.str("SENDGRID_API_KEY", default="") SENDGRID_DEFAULT_FROM = "noreply@grant.io" -ETHEREUM_PROVIDER = "http" -ETHEREUM_ENDPOINT_URI = env.str("ETHEREUM_ENDPOINT_URI") SENTRY_DSN = env.str("SENTRY_DSN", default=None) SENTRY_RELEASE = env.str("SENTRY_RELEASE", default=git_revision_short_hash()) -UPLOAD_DIRECTORY = env.str("UPLOAD_DIRECTORY") -UPLOAD_URL = env.str("UPLOAD_URL") MAX_CONTENT_LENGTH = 5 * 1024 * 1024 # 5MB (limits file uploads, raises RequestEntityTooLarge) +AWS_ACCESS_KEY_ID = env.str("AWS_ACCESS_KEY_ID") +AWS_SECRET_ACCESS_KEY = env.str("AWS_SECRET_ACCESS_KEY") +AWS_DEFAULT_REGION = env.str("AWS_DEFAULT_REGION") +S3_BUCKET = env.str("S3_BUCKET") +SECURITY_USER_IDENTITY_ATTRIBUTES = ['email_address'] # default is 'email' +SECURITY_PASSWORD_HASH = 'bcrypt' +SECURITY_PASSWORD_SALT = SECRET_KEY diff --git a/backend/grant/templates/emails/team_invite.html b/backend/grant/templates/emails/team_invite.html index 33cdb8c8..cdd1abde 100644 --- a/backend/grant/templates/emails/team_invite.html +++ b/backend/grant/templates/emails/team_invite.html @@ -1,16 +1,16 @@

- You’ve been invited by {{ args.inviter.display_name }} - to join the team for - {{ args.proposal.title or 'Untitled Project'|safe }}, - a project on Grant.io! If you want to accept the invitation, continue to the - site below. + You’ve been invited by {{ args.inviter.display_name }} to + join the team for + {{ args.proposal.title or 'Untitled Project'|safe }}, a project on Grant.io! If you want to accept the invitation, continue to + the site below.

{% if not args.user %} -

- It looks like you don't yet have a Grant.io account, so you'll need to - sign up first before you can join the team. -

+

+ It looks like you don't yet have a Grant.io account, so you'll need to sign up + first before you can join the team. +

{% endif %} @@ -19,16 +19,17 @@
- - {% if args.user %} - See invitation - {% else %} - Get started - {% endif %} + + {% if args.user %} See invitation {% else %} Get started {% endif + %}
- \ No newline at end of file + diff --git a/backend/grant/user/commands.py b/backend/grant/user/commands.py index 1e8e2dca..db8b44ee 100644 --- a/backend/grant/user/commands.py +++ b/backend/grant/user/commands.py @@ -11,12 +11,9 @@ def delete_user(identity): print(identity) user = None if str.isdigit(identity): - user = User.query.filter(id=identity).first() + user = User.get_by_id(identity) else: - user = User.query.filter( - (User.account_address == identity) | - (User.email_address == identity) - ).first() + user = User.get_by_email(identity) if user: db.session.delete(user) diff --git a/backend/grant/user/models.py b/backend/grant/user/models.py index 8131be4c..50556a74 100644 --- a/backend/grant/user/models.py +++ b/backend/grant/user/models.py @@ -1,10 +1,34 @@ -from sqlalchemy import func +from flask_security import UserMixin, RoleMixin +from flask_security.core import current_user +from flask_security.utils import hash_password, verify_and_update_password, login_user, logout_user +from sqlalchemy.ext.hybrid import hybrid_property + from grant.comment.models import Comment from grant.email.models import EmailVerification -from grant.extensions import ma, db +from grant.email.send import send_email +from grant.extensions import ma, db, security from grant.utils.misc import make_url from grant.utils.social import get_social_info_from_url -from grant.email.send import send_email +from grant.utils.upload import extract_avatar_filename, construct_avatar_url + + +def is_current_authed_user_id(user_id): + return current_user.is_authenticated and \ + current_user.id == user_id + + +class RolesUsers(db.Model): + __tablename__ = 'roles_users' + id = db.Column(db.Integer(), primary_key=True) + user_id = db.Column('user_id', db.Integer(), db.ForeignKey('user.id')) + role_id = db.Column('role_id', db.Integer(), db.ForeignKey('role.id')) + + +class Role(db.Model, RoleMixin): + __tablename__ = 'role' + id = db.Column(db.Integer(), primary_key=True) + name = db.Column(db.String(80), unique=True) + description = db.Column(db.String(255)) class SocialMedia(db.Model): @@ -24,50 +48,66 @@ class Avatar(db.Model): __tablename__ = "avatar" id = db.Column(db.Integer(), primary_key=True) - image_url = db.Column(db.String(255), unique=False, nullable=True) + _image_url = db.Column("image_url", db.String(255), unique=False, nullable=True) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) user = db.relationship("User", back_populates="avatar") + @hybrid_property + def image_url(self): + return construct_avatar_url(self._image_url) + + @image_url.setter + def image_url(self, image_url): + self._image_url = extract_avatar_filename(image_url) + def __init__(self, image_url, user_id): self.image_url = image_url self.user_id = user_id -class User(db.Model): +class User(db.Model, UserMixin): __tablename__ = "user" id = db.Column(db.Integer(), primary_key=True) - email_address = db.Column(db.String(255), unique=True, nullable=True) - account_address = db.Column(db.String(255), unique=True, nullable=True) + email_address = db.Column(db.String(255), unique=True, nullable=False) + password = db.Column(db.String(255), unique=False, nullable=False) display_name = db.Column(db.String(255), unique=False, nullable=True) title = db.Column(db.String(255), unique=False, nullable=True) + active = db.Column(db.Boolean, default=True) social_medias = db.relationship(SocialMedia, backref="user", lazy=True, cascade="all, delete-orphan") comments = db.relationship(Comment, backref="user", lazy=True) avatar = db.relationship(Avatar, uselist=False, back_populates="user", cascade="all, delete-orphan") - email_verification = db.relationship(EmailVerification, uselist=False, back_populates="user", lazy=True, cascade="all, delete-orphan") + email_verification = db.relationship(EmailVerification, uselist=False, + back_populates="user", lazy=True, cascade="all, delete-orphan") + roles = db.relationship('Role', secondary='roles_users', + backref=db.backref('users', lazy='dynamic')) # TODO - add create and validate methods - def __init__(self, email_address=None, account_address=None, display_name=None, title=None): - if not email_address and not account_address: - raise ValueError("Either email_address or account_address is required to create a user") - + def __init__( + self, + email_address, + password, + active, + roles, + display_name=None, + title=None, + ): self.email_address = email_address - self.account_address = account_address self.display_name = display_name self.title = title + self.password = password @staticmethod - def create(email_address=None, account_address=None, display_name=None, title=None, _send_email=True): - user = User( - account_address=account_address, + def create(email_address=None, password=None, display_name=None, title=None, _send_email=True): + user = security.datastore.create_user( email_address=email_address, + password=hash_password(password), display_name=display_name, title=title ) - db.session.add(user) - db.session.flush() + security.datastore.commit() # Setup & send email verification ev = EmailVerification(user_id=user.id) @@ -83,21 +123,33 @@ class User(db.Model): return user @staticmethod - def get_by_identifier(email_address: str = None, account_address: str = None): - if not email_address and not account_address: - raise ValueError("Either email_address or account_address is required to get a user") + def get_by_id(user_id: int): + return security.datastore.get_user(user_id) + + @staticmethod + def get_by_email(email_address: str): + return security.datastore.get_user(email_address) + + @staticmethod + def logout_current_user(): + logout_user() # logs current user out + + def check_password(self, password: str): + return verify_and_update_password(password, self) + + def set_password(self, password: str): + self.password = hash_password(password) + db.session.commit() + + def login(self): + login_user(self) - return User.query.filter( - (func.lower(User.account_address) == func.lower(account_address)) | - (func.lower(User.email_address) == func.lower(email_address)) - ).first() class UserSchema(ma.Schema): class Meta: model = User # Fields to expose fields = ( - "account_address", "title", "email_address", "social_medias", @@ -113,9 +165,11 @@ class UserSchema(ma.Schema): def get_userid(self, obj): return obj.id + user_schema = UserSchema() users_schema = UserSchema(many=True) + class SocialMediaSchema(ma.Schema): class Meta: model = SocialMedia @@ -125,7 +179,7 @@ class SocialMediaSchema(ma.Schema): "service", "username", ) - + url = ma.Method("get_url") service = ma.Method("get_service") username = ma.Method("get_username") diff --git a/backend/grant/user/views.py b/backend/grant/user/views.py index 59c61db0..603ddf4c 100644 --- a/backend/grant/user/views.py +++ b/backend/grant/user/views.py @@ -10,27 +10,14 @@ from grant.proposal.models import ( invites_with_proposal_schema, user_proposals_schema ) -from grant.utils.auth import requires_sm, requires_same_user_auth, verify_signed_auth, BadSignatureException -from grant.utils.upload import save_avatar, send_upload, remove_avatar -from grant.web3.proposal import read_user_proposal -from grant.settings import UPLOAD_URL +from grant.utils.auth import requires_auth, requires_same_user_auth +from grant.utils.upload import remove_avatar, sign_avatar_upload, AvatarException + from .models import User, SocialMedia, Avatar, users_schema, user_schema, db blueprint = Blueprint('user', __name__, url_prefix='/api/v1/users') -def populate_user_proposals_cfs(proposals): - for p in proposals: - proposal_contract = read_user_proposal(p['proposal_address']) - if proposal_contract: - p['target'] = proposal_contract['target'] - p['funded'] = proposal_contract['funded'] - else: - p['target'] = None - filtered_proposals = list(filter(lambda p: p['target'] is not None, proposals)) - return filtered_proposals - - @blueprint.route("/", methods=["GET"]) @endpoint.api( parameter('proposalId', type=str, required=False) @@ -52,136 +39,121 @@ def get_users(proposal_id): @blueprint.route("/me", methods=["GET"]) -@requires_sm +@requires_auth @endpoint.api() def get_me(): dumped_user = user_schema.dump(g.current_user) return dumped_user -@blueprint.route("/", methods=["GET"]) +@blueprint.route("/", methods=["GET"]) @endpoint.api( parameter("withProposals", type=bool, required=False), parameter("withComments", type=bool, required=False), parameter("withFunded", type=bool, required=False) ) -def get_user(user_identity, with_proposals, with_comments, with_funded): - user = User.get_by_identifier(email_address=user_identity, account_address=user_identity) +def get_user(user_id, with_proposals, with_comments, with_funded): + user = User.get_by_id(user_id) if user: result = user_schema.dump(user) if with_proposals: proposals = Proposal.get_by_user(user) proposals_dump = user_proposals_schema.dump(proposals) - result["createdProposals"] = populate_user_proposals_cfs(proposals_dump) + result["createdProposals"] = proposals_dump if with_funded: contributions = Proposal.get_by_user_contribution(user) contributions_dump = user_proposals_schema.dump(contributions) - result["fundedProposals"] = populate_user_proposals_cfs(contributions_dump) + result["fundedProposals"] = contributions_dump if with_comments: comments = Comment.get_by_user(user) comments_dump = user_comments_schema.dump(comments) result["comments"] = comments_dump return result else: - message = "User with account_address or user_identity matching {} not found".format(user_identity) + message = "User with id matching {} not found".format(user_id) return {"message": message}, 404 @blueprint.route("/", methods=["POST"]) @endpoint.api( - parameter('accountAddress', type=str, required=True), parameter('emailAddress', type=str, required=True), + parameter('password', type=str, required=True), parameter('displayName', type=str, required=True), - parameter('title', type=str, required=True), - parameter('signedMessage', type=str, required=True), - parameter('rawTypedData', type=str, required=True) + parameter('title', type=str, required=True) ) def create_user( - account_address, email_address, + password, display_name, - title, - signed_message, - raw_typed_data + title ): - existing_user = User.get_by_identifier(email_address=email_address, account_address=account_address) + existing_user = User.get_by_email(email_address) if existing_user: - return {"message": "User with that address or email already exists"}, 409 + return {"message": "User with that email already exists"}, 409 - # Handle signature - try: - sig_address = verify_signed_auth(signed_message, raw_typed_data) - if sig_address.lower() != account_address.lower(): - return { - "message": "Message signature address ({sig_address}) doesn't match account_address ({account_address})".format( - sig_address=sig_address, - account_address=account_address - ) - }, 400 - except BadSignatureException: - return {"message": "Invalid message signature"}, 400 - - # TODO: Handle avatar & social stuff too user = User.create( - account_address=account_address, email_address=email_address, + password=password, display_name=display_name, title=title ) + user.login() result = user_schema.dump(user) return result, 201 @blueprint.route("/auth", methods=["POST"]) @endpoint.api( - parameter('accountAddress', type=str, required=True), - parameter('signedMessage', type=str, required=True), - parameter('rawTypedData', type=str, required=True) + parameter('email', type=str, required=True), + parameter('password', type=str, required=True) ) -def auth_user(account_address, signed_message, raw_typed_data): - existing_user = User.get_by_identifier(account_address=account_address) +def auth_user(email, password): + existing_user = User.get_by_email(email) if not existing_user: - return {"message": "No user exists with that address"}, 400 - - try: - sig_address = verify_signed_auth(signed_message, raw_typed_data) - if sig_address.lower() != account_address.lower(): - return { - "message": "Message signature address ({sig_address}) doesn't match account_address ({account_address})".format( - sig_address=sig_address, - account_address=account_address - ) - }, 400 - except BadSignatureException: - return {"message": "Invalid message signature"}, 400 - + return {"message": "No user exists with that email"}, 400 + if not existing_user.check_password(password): + return {"message": "Invalid password"}, 403 + existing_user.login() return user_schema.dump(existing_user) -@blueprint.route("/avatar", methods=["POST"]) -@requires_sm +@blueprint.route("/password", methods=["PUT"]) +@requires_auth +@endpoint.api( + parameter('currentPassword', type=str, required=True), + parameter('password', type=str, required=True), +) +def update_user_password(current_password, password): + if not g.current_user.check_password(current_password): + return {"message": "Current password incorrect"}, 403 + g.current_user.set_password(password) + return None, 200 + + +@blueprint.route("/logout", methods=["POST"]) +@requires_auth @endpoint.api() -def upload_avatar(): +def logout_user(): + User.logout_current_user() + return None, 200 + + +@blueprint.route("/avatar", methods=["POST"]) +@requires_auth +@endpoint.api( + parameter('mimetype', type=str, required=True) +) +def upload_avatar(mimetype): user = g.current_user - if 'file' not in request.files: - return {"message": "No file in post"}, 400 - file = request.files['file'] - if file.filename == '': - return {"message": "No selected file"}, 400 try: - filename = save_avatar(file, user.id) - return {"url": "{0}/api/v1/users/avatar/{1}".format(UPLOAD_URL, filename)} - except Exception as e: + signed_post = sign_avatar_upload(mimetype, user.id) + return signed_post + except AvatarException as e: return {"message": str(e)}, 400 -@blueprint.route("/avatar/", methods=["GET"]) -def get_avatar(filename): - return send_upload(filename) - - @blueprint.route("/avatar", methods=["DELETE"]) -@requires_sm +@requires_auth @endpoint.api( parameter('url', type=str, required=True) ) @@ -190,8 +162,8 @@ def delete_avatar(url): remove_avatar(url, user.id) -@blueprint.route("/", methods=["PUT"]) -@requires_sm +@blueprint.route("/", methods=["PUT"]) +@requires_auth @requires_same_user_auth @endpoint.api( parameter('displayName', type=str, required=True), @@ -199,7 +171,7 @@ def delete_avatar(url): parameter('socialMedias', type=list, required=True), parameter('avatar', type=str, required=True) ) -def update_user(user_identity, display_name, title, social_medias, avatar): +def update_user(user_id, display_name, title, social_medias, avatar): user = g.current_user if display_name is not None: @@ -223,29 +195,29 @@ def update_user(user_identity, display_name, title, social_medias, avatar): new_avatar = Avatar(image_url=avatar, user_id=user.id) db.session.add(new_avatar) - old_avatar_url = db_avatar and db_avatar.image_url - if old_avatar_url and old_avatar_url != new_avatar.image_url: - remove_avatar(old_avatar_url, user.id) + old_avatar_url = db_avatar and db_avatar.image_url + if old_avatar_url and old_avatar_url != avatar: + remove_avatar(old_avatar_url, user.id) db.session.commit() result = user_schema.dump(user) return result -@blueprint.route("//invites", methods=["GET"]) +@blueprint.route("//invites", methods=["GET"]) @requires_same_user_auth @endpoint.api() -def get_user_invites(user_identity): +def get_user_invites(user_id): invites = ProposalTeamInvite.get_pending_for_user(g.current_user) return invites_with_proposal_schema.dump(invites) -@blueprint.route("//invites//respond", methods=["PUT"]) +@blueprint.route("//invites//respond", methods=["PUT"]) @requires_same_user_auth @endpoint.api( parameter('response', type=bool, required=True) ) -def respond_to_invite(user_identity, invite_id, response): +def respond_to_invite(user_id, invite_id, response): invite = ProposalTeamInvite.query.filter_by(id=invite_id).first() if not invite: return {"message": "No invite found with id {}".format(invite_id)}, 404 diff --git a/backend/grant/utils/auth.py b/backend/grant/utils/auth.py index 2cf8c53c..bd823f5d 100644 --- a/backend/grant/utils/auth.py +++ b/backend/grant/utils/auth.py @@ -3,107 +3,48 @@ import json from functools import wraps import requests +from flask_security.core import current_user from flask import request, g, jsonify -from itsdangerous import SignatureExpired, BadSignature -from itsdangerous import TimedJSONWebSignatureSerializer as Serializer import sentry_sdk -from grant.settings import SECRET_KEY, AUTH_URL +from grant.settings import SECRET_KEY from ..proposal.models import Proposal from ..user.models import User -TWO_WEEKS = 1209600 - -def generate_token(user, expiration=TWO_WEEKS): - s = Serializer(SECRET_KEY, expires_in=expiration) - token = s.dumps({ - 'id': user.id, - 'email': user.email, - }).decode('utf-8') - return token - - -def verify_token(token): - s = Serializer(SECRET_KEY) - try: - data = s.loads(token) - except (BadSignature, SignatureExpired): - return None - return data - - -# Custom exception for bad auth -class BadSignatureException(Exception): - pass - - -def verify_signed_auth(signature, typed_data): - loaded_typed_data = ast.literal_eval(typed_data) - if loaded_typed_data['domain']['name'] != 'Grant.io': - raise BadSignatureException("Signature is not for Grant.io") - - url = AUTH_URL + "/message/recover" - payload = json.dumps({"sig": signature, "data": loaded_typed_data}) - headers = {'content-type': 'application/json'} - response = requests.request("POST", url, data=payload, headers=headers) - json_response = response.json() - recovered_address = json_response.get('recoveredAddress') - if not recovered_address: - raise BadSignatureException("Authorization signature is invalid") - - return recovered_address - - -# Decorator that requires you to have EIP-712 message signature headers for auth -def requires_sm(f): +def requires_auth(f): @wraps(f) def decorated(*args, **kwargs): - signature = request.headers.get('MsgSignature', None) - typed_data = request.headers.get('RawTypedData', None) - - if typed_data and signature: - try: - auth_address = verify_signed_auth(signature, typed_data) - except BadSignatureException: - return jsonify(message="Invalid auth message signature"), 401 - - user = User.get_by_identifier(account_address=auth_address) - if not user: - return jsonify(message="No user exists with address: {}".format(auth_address)), 401 - - g.current_user = user - with sentry_sdk.configure_scope() as scope: - scope.user = { - "id": user.id, - } - return f(*args, **kwargs) - - return jsonify(message="Authentication is required to access this resource"), 401 - + if not current_user.is_authenticated: + return jsonify(message="Authentication is required to access this resource"), 401 + g.current_user = current_user + with sentry_sdk.configure_scope() as scope: + scope.user = { + "id": current_user.id, + } + return f(*args, **kwargs) return decorated -# Decorator that requires you to be the user you're interacting with + def requires_same_user_auth(f): @wraps(f) def decorated(*args, **kwargs): - user_identity = kwargs["user_identity"] - if not user_identity: - return jsonify(message="Decorator requires_same_user_auth requires path variable "), 500 + user_id = kwargs["user_id"] + if not user_id: + return jsonify(message="Decorator requires_same_user_auth requires path variable "), 500 - user = User.get_by_identifier(account_address=user_identity, email_address=user_identity) + user = User.get_by_id(user_id=user_id) if not user: - return jsonify(message="Could not find user with identity {}".format(user_identity)), 403 + return jsonify(message="Could not find user with id {}".format(user_id)), 403 if user.id != g.current_user.id: return jsonify(message="You are not authorized to modify this user"), 403 return f(*args, **kwargs) - return requires_sm(decorated) + return requires_auth(decorated) -# Decorator that requires you to be a team member of a proposal to access def requires_team_member_auth(f): @wraps(f) def decorated(*args, **kwargs): @@ -121,4 +62,4 @@ def requires_team_member_auth(f): g.current_proposal = proposal return f(*args, **kwargs) - return requires_sm(decorated) + return requires_auth(decorated) diff --git a/backend/grant/utils/upload.py b/backend/grant/utils/upload.py index 24cb368c..3614be44 100644 --- a/backend/grant/utils/upload.py +++ b/backend/grant/utils/upload.py @@ -1,54 +1,63 @@ -import os import re -from hashlib import md5 -from werkzeug.utils import secure_filename -from flask import send_from_directory -from grant.settings import UPLOAD_DIRECTORY +import uuid +import boto3 +from flask import current_app IMAGE_MIME_TYPES = set(['image/png', 'image/jpg', 'image/gif']) AVATAR_MAX_SIZE = 2 * 1024 * 1024 # 2MB -class FileValidationException(Exception): +class AvatarException(Exception): pass -def allowed_avatar_file(file): - if file.mimetype not in IMAGE_MIME_TYPES: - raise FileValidationException("Unacceptable file type: {0}".format(file.mimetype)) - file.seek(0, os.SEEK_END) - size = file.tell() - file.seek(0) - if size > AVATAR_MAX_SIZE: - raise FileValidationException( - "File size is too large ({0}KB), max size is {1}KB".format(size / 1024, AVATAR_MAX_SIZE / 1024) - ) +def allowed_avatar_type(mimetype): + if mimetype not in IMAGE_MIME_TYPES: + raise AvatarException("Unacceptable file type: {0}".format(mimetype)) return True -def hash_file(file): - hasher = md5() - buf = file.read() - hasher.update(buf) - file.seek(0) - return hasher.hexdigest() +def extract_avatar_filename(url): + match = re.search(r'avatars/(\d+\.\w+\.\w+)$', url) + if match: + return match.group(1) + else: + raise AvatarException("Unable to extract avatar filename from %s" % url) -def save_avatar(file, user_id): - if file and allowed_avatar_file(file): - ext = file.mimetype.replace('image/', '') - filename = "{0}.{1}.{2}".format(user_id, hash_file(file), ext) - file.save(os.path.join(UPLOAD_DIRECTORY, filename)) - return filename +def construct_avatar_url(filename): + S3_BUCKET = current_app.config['S3_BUCKET'] + return "https://%s.s3.amazonaws.com/avatars/%s" % (S3_BUCKET, filename) def remove_avatar(url, user_id): - match = re.search(r'/api/v1/users/avatar/(\d+.\w+.\w+)', url) - if match: - filename = match.group(1) - if filename.startswith(str(user_id) + '.'): - os.remove(os.path.join(UPLOAD_DIRECTORY, filename)) + S3_BUCKET = current_app.config['S3_BUCKET'] + filename = extract_avatar_filename(url) + user_match = re.search(r'^(\d+)\.\w+\.\w+$', filename) + if user_match and user_match.group(1) == str(user_id): + s3 = boto3.resource('s3') + s3.Object(S3_BUCKET, 'avatars/' + filename).delete() -def send_upload(filename): - return send_from_directory(UPLOAD_DIRECTORY, secure_filename(filename)) +def sign_avatar_upload(mimetype, user_id): + S3_BUCKET = current_app.config['S3_BUCKET'] + if mimetype and allowed_avatar_type(mimetype): + ext = mimetype.replace('image/', '') + filename = "{0}.{1}.{2}".format(user_id, uuid.uuid4().hex, ext) + key = "avatars/" + filename + s3 = boto3.client('s3') + presigned_post = s3.generate_presigned_post( + Bucket=S3_BUCKET, + Key=key, + Fields={"acl": "public-read", "Content-Type": mimetype}, + Conditions=[ + {"acl": "public-read"}, + {"Content-Type": mimetype}, + ["content-length-range", 0, AVATAR_MAX_SIZE] + ], + ExpiresIn=3600 + ) + return { + "data": presigned_post, + "url": construct_avatar_url(filename) + } diff --git a/backend/grant/web3/__init__.py b/backend/grant/web3/__init__.py deleted file mode 100644 index dc348e3a..00000000 --- a/backend/grant/web3/__init__.py +++ /dev/null @@ -1 +0,0 @@ -from . import dev_contracts \ No newline at end of file diff --git a/backend/grant/web3/dev_contracts.py b/backend/grant/web3/dev_contracts.py deleted file mode 100644 index 465930bf..00000000 --- a/backend/grant/web3/dev_contracts.py +++ /dev/null @@ -1,19 +0,0 @@ -import json - -from flask import Blueprint, jsonify - -blueprint = Blueprint('dev-contracts', __name__, url_prefix='/dev-contracts') - - -@blueprint.route("/CrowdFundFactory.json", methods=["GET"]) -def factory(): - with open("../contract/build/contracts/CrowdFundFactory.json", "r") as read_file: - crowd_fund_factory_json = json.load(read_file) - return jsonify(crowd_fund_factory_json) - - -@blueprint.route("/CrowdFund.json", methods=["GET"]) -def crowd_find(): - with open("../contract/build/contracts/CrowdFund.json", "r") as read_file: - crowd_fund_json = json.load(read_file) - return jsonify(crowd_fund_json) diff --git a/backend/grant/web3/proposal.py b/backend/grant/web3/proposal.py deleted file mode 100644 index 6e6e78b4..00000000 --- a/backend/grant/web3/proposal.py +++ /dev/null @@ -1,178 +0,0 @@ -import time - -import requests -from flask_web3 import current_web3 - -from grant.settings import CROWD_FUND_URL -from .util import batch_call, call_array, RpcError - -crowd_fund_abi = None - - -def get_crowd_fund_abi(): - global crowd_fund_abi - if crowd_fund_abi: - return crowd_fund_abi - - crowd_fund_json = requests.get(CROWD_FUND_URL).json() - crowd_fund_abi = crowd_fund_json['abi'] - return crowd_fund_abi - - -def read_proposal(address): - if not address: - return None - - current_web3.eth.defaultAccount = '0x537680D921C000fC52Af9962ceEb4e359C50F424' if not current_web3.eth.accounts else \ - current_web3.eth.accounts[0] - crowd_fund_abi = get_crowd_fund_abi() - contract = current_web3.eth.contract(address=address, abi=crowd_fund_abi) - - crowd_fund = {} - methods = [ - "immediateFirstMilestonePayout", - "raiseGoal", - "amountVotingForRefund", - "beneficiary", - "deadline", - "milestoneVotingPeriod", - "frozen", - "isRaiseGoalReached", - ] - - # batched - calls = list(map(lambda x: [x, None], methods)) - try: - crowd_fund = batch_call(current_web3, address, crowd_fund_abi, calls, contract) - # catch dead contracts here - except RpcError: - return None - - # balance (sync) - crowd_fund['balance'] = current_web3.eth.getBalance(address) - - # arrays (sync) - crowd_fund['milestones'] = call_array(contract.functions.milestones) - crowd_fund['trustees'] = call_array(contract.functions.trustees) - contributor_list = call_array(contract.functions.contributorList) - - # make milestones - def make_ms(enum_ms): - index = enum_ms[0] - ms = enum_ms[1] - is_immediate = index == 0 and crowd_fund['immediateFirstMilestonePayout'] - deadline = ms[2] * 1000 - amount_against = ms[1] - pct_against = round(amount_against * 100 / crowd_fund['raiseGoal']) - paid = ms[3] - state = 'WAITING' - if crowd_fund["isRaiseGoalReached"] and deadline > 0: - if paid: - state = 'PAID' - elif deadline > time.time() * 1000: - state = 'ACTIVE' - elif pct_against >= 50: - state = 'REJECTED' - else: - state = 'PAID' - return { - "index": index, - "state": state, - "amount": str(ms[0]), - "amountAgainstPayout": str(amount_against), - "percentAgainstPayout": pct_against, - "payoutRequestVoteDeadline": deadline, - "isPaid": paid, - "isImmediatePayout": is_immediate - } - - crowd_fund['milestones'] = list(map(make_ms, enumerate(crowd_fund['milestones']))) - - # contributor calls (batched) - contributors_calls = list(map(lambda c_addr: ['contributors', (c_addr,)], contributor_list)) - contrib_votes_calls = [] - for c_addr in contributor_list: - for msi in range(len(crowd_fund['milestones'])): - contrib_votes_calls.append(['getContributorMilestoneVote', (c_addr, msi)]) - derived_calls = contributors_calls + contrib_votes_calls - derived_results = batch_call(current_web3, address, crowd_fund_abi, derived_calls, contract) - - # make contributors - contributors = [] - for contrib_address in contributor_list: - contrib_raw = derived_results['contributors' + contrib_address] - - def get_no_vote(i): - return derived_results['getContributorMilestoneVote' + contrib_address + str(i)] - - no_votes = list(map(get_no_vote, range(len(crowd_fund['milestones'])))) - - contrib = { - "address": contrib_address, - "contributionAmount": str(contrib_raw[0]), - "refundVote": contrib_raw[1], - "refunded": contrib_raw[2], - "milestoneNoVotes": no_votes, - } - contributors.append(contrib) - crowd_fund['contributors'] = contributors - - # massage names and numbers - crowd_fund['target'] = crowd_fund.pop('raiseGoal') - crowd_fund['isFrozen'] = crowd_fund.pop('frozen') - crowd_fund['deadline'] = crowd_fund['deadline'] * 1000 - crowd_fund['milestoneVotingPeriod'] = crowd_fund['milestoneVotingPeriod'] * 60 * 1000 - if crowd_fund['isRaiseGoalReached']: - crowd_fund['funded'] = crowd_fund['target'] - crowd_fund['percentFunded'] = 100 - else: - crowd_fund['funded'] = crowd_fund['balance'] - crowd_fund['percentFunded'] = round(crowd_fund['balance'] * 100 / crowd_fund['target']) - crowd_fund['percentVotingForRefund'] = round(crowd_fund['amountVotingForRefund'] * 100 / crowd_fund['target']) - - bn_keys = ['amountVotingForRefund', 'balance', 'funded', 'target'] - for k in bn_keys: - crowd_fund[k] = str(crowd_fund[k]) - - return crowd_fund - - -def read_user_proposal(address): - if not address: - return None - - current_web3.eth.defaultAccount = '0x537680D921C000fC52Af9962ceEb4e359C50F424' if not current_web3.eth.accounts else \ - current_web3.eth.accounts[0] - crowd_fund_abi = get_crowd_fund_abi() - contract = current_web3.eth.contract(address=address, abi=crowd_fund_abi) - - crowd_fund = {} - methods = [ - "raiseGoal", - ] - - # batched - calls = list(map(lambda x: [x, None], methods)) - try: - crowd_fund = batch_call(current_web3, address, crowd_fund_abi, calls, contract) - # catch dead contracts here - except RpcError: - return None - - # balance (sync) - crowd_fund['balance'] = current_web3.eth.getBalance(address) - crowd_fund['target'] = str(crowd_fund.pop('raiseGoal')) - crowd_fund['funded'] = str(crowd_fund.pop('balance')) - - return crowd_fund - - -def validate_contribution_tx(tx_id, from_address, to_address, amount): - amount_wei = current_web3.toWei(amount, 'ether') - tx = current_web3.eth.getTransaction(tx_id) - if tx: - if from_address.lower() == tx.get("from").lower() and \ - to_address == tx.get("to") and \ - amount_wei == tx.get("value"): - return True - return False diff --git a/backend/grant/web3/util.py b/backend/grant/web3/util.py deleted file mode 100644 index b7674972..00000000 --- a/backend/grant/web3/util.py +++ /dev/null @@ -1,86 +0,0 @@ -import requests -from web3.providers.base import JSONBaseProvider -from web3.utils.contracts import prepare_transaction, find_matching_fn_abi -from web3 import EthereumTesterProvider -from grant.settings import ETHEREUM_ENDPOINT_URI -from hexbytes import HexBytes -from eth_abi import decode_abi -from web3.utils.abi import get_abi_output_types, map_abi_data -from web3.utils.normalizers import BASE_RETURN_NORMALIZERS - - -class RpcError(Exception): - pass - - -def call_array(fn): - results = [] - no_error = True - index = 0 - while no_error: - try: - results.append(fn(index).call()) - index += 1 - except Exception: - no_error = False - return results - - -def make_key(method, args): - return method + "".join(list(map(lambda z: str(z), args))) if args else method - - -def tester_batch(calls, contract): - # fallback to sync calls for eth-tester instead of implementing batching - results = {} - for call in calls: - method, args = call - args = args if args else () - results[make_key(method, args)] = contract.functions[method](*args).call() - return results - - -def batch(node_address, params): - base_provider = JSONBaseProvider() - request_data = b'[' + b','.join( - [base_provider.encode_rpc_request('eth_call', p) for p in params] - ) + b']' - r = requests.post(node_address, data=request_data, headers={'Content-Type': 'application/json'}) - responses = base_provider.decode_rpc_response(r.content) - return responses - - -def batch_call(w3, address, abi, calls, contract): - # TODO: use web3py batching once its added - # this implements batched rpc calls using web3py helper methods - # web3py doesn't support this out-of-box yet - # issue: https://github.com/ethereum/web3.py/issues/832 - if not calls: - return [] - if type(w3.providers[0]) is EthereumTesterProvider: - return tester_batch(calls, contract) - inputs = [] - for c in calls: - name, args = c - tx = {"from": w3.eth.defaultAccount, "to": address} - prepared = prepare_transaction(address, w3, name, abi, None, tx, args) - inputs.append([prepared, 'latest']) - responses = batch(ETHEREUM_ENDPOINT_URI, inputs) - if 'error' in responses[0]: - message = responses[0]['error']['message'] if 'message' in responses[0]['error'] else 'No error message found.' - raise RpcError("rpc error: {0}".format(message)) - results = {} - for r in zip(calls, responses): - result = HexBytes(r[1]['result']) - fn_id, args = r[0] - fn_abi = find_matching_fn_abi(abi, fn_id, args) - output_types = get_abi_output_types(fn_abi) - output_data = decode_abi(output_types, result) - normalized_data = map_abi_data(BASE_RETURN_NORMALIZERS, output_types, output_data) - key = make_key(fn_id, args) - if len(normalized_data) == 1: - results[key] = normalized_data[0] - else: - results[key] = normalized_data - - return results diff --git a/backend/migrations/versions/13d788130b39_.py b/backend/migrations/versions/13d788130b39_.py new file mode 100644 index 00000000..f5972171 --- /dev/null +++ b/backend/migrations/versions/13d788130b39_.py @@ -0,0 +1,49 @@ +"""empty message + +Revision ID: 13d788130b39 +Revises: a6087d62cb4b +Create Date: 2018-12-11 14:42:18.681421 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '13d788130b39' +down_revision = 'a6087d62cb4b' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('role', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('name', sa.String(length=80), nullable=True), + sa.Column('description', sa.String(length=255), nullable=True), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('name') + ) + op.create_table('roles_users', + sa.Column('id', sa.Integer(), nullable=False), + sa.Column('user_id', sa.Integer(), nullable=True), + sa.Column('role_id', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['role_id'], ['role.id'], ), + sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), + sa.PrimaryKeyConstraint('id') + ) + op.add_column('user', sa.Column('active', sa.Boolean(), nullable=True)) + op.add_column('user', sa.Column('password', sa.String(length=255), nullable=False)) + op.drop_column('user', 'password_hash') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('user', sa.Column('password_hash', sa.VARCHAR(length=255), autoincrement=False, nullable=False)) + op.drop_column('user', 'password') + op.drop_column('user', 'active') + op.drop_table('roles_users') + op.drop_table('role') + # ### end Alembic commands ### diff --git a/backend/migrations/versions/a6087d62cb4b_.py b/backend/migrations/versions/a6087d62cb4b_.py new file mode 100644 index 00000000..4812d336 --- /dev/null +++ b/backend/migrations/versions/a6087d62cb4b_.py @@ -0,0 +1,38 @@ +"""empty message + +Revision ID: a6087d62cb4b +Revises: 3699cb98fc2a +Create Date: 2018-12-10 11:38:36.875419 + +""" +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'a6087d62cb4b' +down_revision = '3699cb98fc2a' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('user', sa.Column('password_hash', sa.String(length=255), nullable=False)) + op.alter_column('user', 'email_address', + existing_type=sa.VARCHAR(length=255), + nullable=False) + op.drop_constraint('user_account_address_key', 'user', type_='unique') + op.drop_column('user', 'account_address') + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('user', sa.Column('account_address', sa.VARCHAR(length=255), autoincrement=False, nullable=True)) + op.create_unique_constraint('user_account_address_key', 'user', ['account_address']) + op.alter_column('user', 'email_address', + existing_type=sa.VARCHAR(length=255), + nullable=True) + op.drop_column('user', 'password_hash') + # ### end Alembic commands ### diff --git a/backend/requirements/prod.txt b/backend/requirements/prod.txt index 90845545..92716eca 100644 --- a/backend/requirements/prod.txt +++ b/backend/requirements/prod.txt @@ -57,11 +57,14 @@ sendgrid==5.3.0 # input validation flask-yolo2API==0.2.6 -#web3 -flask-web3==0.1.1 -web3==4.8.1 - #sentry sentry-sdk[flask]==0.5.5 +#boto3 (AWS sdk) +boto3==1.9.52 + +# force SSL Flask-SSLify==0.1.5 + +# sessions +Flask-Security==3.0.0 diff --git a/backend/tests/config.py b/backend/tests/config.py index f80be828..26179745 100644 --- a/backend/tests/config.py +++ b/backend/tests/config.py @@ -1,3 +1,4 @@ +import json from flask_testing import TestCase from grant.app import create_app @@ -21,7 +22,7 @@ class BaseTestConfig(TestCase): def tearDown(self): db.session.remove() db.drop_all() - + def assertStatus(self, response, status_code, message=None): """ Overrides TestCase's default to print out response JSON. @@ -33,6 +34,7 @@ class BaseTestConfig(TestCase): assert_status = assertStatus + class BaseUserConfig(BaseTestConfig): headers = { "MsgSignature": message["sig"], @@ -42,8 +44,8 @@ class BaseUserConfig(BaseTestConfig): def setUp(self): super(BaseUserConfig, self).setUp() self.user = User.create( - account_address=test_user["accountAddress"], email_address=test_user["emailAddress"], + password=test_user["password"], display_name=test_user["displayName"], title=test_user["title"], ) @@ -52,19 +54,32 @@ class BaseUserConfig(BaseTestConfig): avatar = Avatar(image_url=test_user["avatar"]["link"], user_id=self.user.id) db.session.add(avatar) + self.user_password = test_user["password"] + self.other_user = User.create( - account_address=test_other_user["accountAddress"], email_address=test_other_user["emailAddress"], + password=test_other_user["password"], display_name=test_other_user["displayName"], title=test_other_user["title"] ) db.session.commit() + def login_default_user(self): + self.app.post( + "/api/v1/users/auth", + data=json.dumps({ + "email": self.user.email_address, + "password": self.user_password + }), + content_type="application/json" + ) + def remove_default_user(self): User.query.filter_by(id=self.user.id).delete() db.session.commit() + class BaseProposalCreatorConfig(BaseUserConfig): def setUp(self): super().setUp() diff --git a/backend/tests/proposal/test_invite_api.py b/backend/tests/proposal/test_invite_api.py index f18c5fc3..b8e79d7d 100644 --- a/backend/tests/proposal/test_invite_api.py +++ b/backend/tests/proposal/test_invite_api.py @@ -7,19 +7,10 @@ from ..test_data import test_proposal, test_user class TestAPI(BaseProposalCreatorConfig): - def test_create_invite_by_account_address(self): - invite_res = self.app.post( - "/api/v1/proposals/{}/invite".format(self.proposal.id), - data=json.dumps({ "address": "0x8B0B72F8bDE212991135668922fD5acE557DE6aB" }), - headers=self.headers, - content_type='application/json' - ) - self.assertStatus(invite_res, 201) - def test_create_invite_by_email_address(self): invite_res = self.app.post( "/api/v1/proposals/{}/invite".format(self.proposal.id), - data=json.dumps({ "address": "test@test.test" }), + data=json.dumps({"address": "test@test.test"}), headers=self.headers, content_type='application/json' ) @@ -29,7 +20,7 @@ class TestAPI(BaseProposalCreatorConfig): def test_no_auth_create_invite_fails(self): invite_res = self.app.post( "/api/v1/proposals/{}/invite".format(self.proposal.id), - data=json.dumps({ "address": "0x8B0B72F8bDE212991135668922fD5acE557DE6aB" }), + data=json.dumps({"address": "0x8B0B72F8bDE212991135668922fD5acE557DE6aB"}), content_type='application/json' ) self.assertStatus(invite_res, 401) @@ -38,7 +29,7 @@ class TestAPI(BaseProposalCreatorConfig): def test_invalid_proposal_create_invite_fails(self): invite_res = self.app.post( "/api/v1/proposals/12345/invite", - data=json.dumps({ "address": "0x8B0B72F8bDE212991135668922fD5acE557DE6aB" }), + data=json.dumps({"address": "0x8B0B72F8bDE212991135668922fD5acE557DE6aB"}), headers=self.headers, content_type='application/json' ) @@ -58,7 +49,7 @@ class TestAPI(BaseProposalCreatorConfig): headers=self.headers ) self.assertStatus(delete_res, 202) - + # Rejects if unknown proposal def test_invalid_invite_delete_invite(self): delete_res = self.app.delete( @@ -66,14 +57,14 @@ class TestAPI(BaseProposalCreatorConfig): headers=self.headers ) self.assertStatus(delete_res, 404) - + # Rejects if not authorized def test_no_auth_delete_invite_fails(self): delete_res = self.app.delete( "/api/v1/proposals/{}/invite/12345".format(self.proposal) ) self.assertStatus(delete_res, 401) - + # Rejects if the invite was already accepted def test_accepted_invite_delete_invite(self): address = "0x8B0B72F8bDE212991135668922fD5acE557DE6aB" diff --git a/backend/tests/settings.py b/backend/tests/settings.py index 0e2ee7e3..fdbe1b89 100644 --- a/backend/tests/settings.py +++ b/backend/tests/settings.py @@ -8,5 +8,8 @@ DEBUG_TB_ENABLED = False CACHE_TYPE = 'simple' # Can be "memcached", "redis", etc. SQLALCHEMY_TRACK_MODIFICATIONS = False WTF_CSRF_ENABLED = False # Allows form testing -ETHEREUM_PROVIDER = "test" -ETHEREUM_ENDPOINT_URI = "" + +AWS_ACCESS_KEY_ID = "your-user-access-key" +AWS_SECRET_ACCESS_KEY = "your-user-secret-access-key" +AWS_DEFAULT_REGION = "us-west-2" +S3_BUCKET = "your-bucket-name" diff --git a/backend/tests/test_data.py b/backend/tests/test_data.py index d1e89fce..0cea842d 100644 --- a/backend/tests/test_data.py +++ b/backend/tests/test_data.py @@ -26,32 +26,32 @@ message = { { "name": "name", "type": "string" - }, - { - "name": "version", - "type": "string" - }, - { - "name": "chainId", - "type": "uint256" - } - ] - }, - "message": { - "message": "I am proving the identity of 0x6bEeA1Cef016c23e292381b6FcaeC092960e41aa on Grant.io", - "time": "Tue, 27 Nov 2018 19:02:04 GMT" - }, - "primaryType": "authorization" -} + }, + { + "name": "version", + "type": "string" + }, + { + "name": "chainId", + "type": "uint256" + } + ] + }, + "message": { + "message": "I am proving the identity of 0x6bEeA1Cef016c23e292381b6FcaeC092960e41aa on Grant.io", + "time": "Tue, 27 Nov 2018 19:02:04 GMT" + }, + "primaryType": "authorization" + } } test_user = { - "accountAddress": '0x6bEeA1Cef016c23e292381b6FcaeC092960e41aa', "displayName": 'Groot', "emailAddress": 'iam@groot.com', + "password": "p4ssw0rd", "title": 'I am Groot!', "avatar": { - "link": 'https://avatars2.githubusercontent.com/u/1393943?s=400&v=4' + "link": 'https://your-bucket-name.s3.amazonaws.com/avatars/1.b0be8bf740ce419a80ea9e1f55974ce1.png' }, "socialMedias": [ { @@ -65,11 +65,10 @@ test_user = { test_team = [test_user] test_other_user = { - "accountAddress": "0xA65AD9c6006fe8948E75EC0861A1BAbaD8168DE0", "displayName": 'Faketoshi', "emailAddress": 'fake@toshi.com', - "title": 'The Real Fake Satoshi' - # TODO make signed messages for this for more tests + "title": 'The Real Fake Satoshi', + "password": 'n4k0m0t0' } milestones = [ @@ -91,8 +90,8 @@ test_proposal = { "milestones": milestones, "category": random.choice(CATEGORIES), "target": "123.456", - "payoutAddress": test_team[0]["accountAddress"], - "trustees": [test_team[0]["accountAddress"]], + "payoutAddress": "123", + "trustees": ["123"], "deadlineDuration": 100, "voteDuration": 100 } diff --git a/backend/tests/user/test_invite_api.py b/backend/tests/user/test_invite_api.py index 32548364..7cddbdd9 100644 --- a/backend/tests/user/test_invite_api.py +++ b/backend/tests/user/test_invite_api.py @@ -8,22 +8,6 @@ from ..test_data import test_proposal, test_user class TestAPI(BaseProposalCreatorConfig): - def test_get_user_invites_by_address(self): - invite = ProposalTeamInvite( - proposal_id=self.proposal.id, - address=self.user.account_address - ) - db.session.add(invite) - db.session.commit() - - invites_res = self.app.get( - "/api/v1/users/{}/invites".format(self.user.account_address), - headers=self.headers - ) - self.assertStatus(invites_res, 200) - self.assertEqual(invites_res.json[0]['address'], self.user.account_address) - self.assertEqual(invites_res.json[0]['proposal']['proposalId'], self.proposal.id) - def test_get_user_invites_by_email(self): invite = ProposalTeamInvite( proposal_id=self.proposal.id, @@ -51,65 +35,65 @@ class TestAPI(BaseProposalCreatorConfig): proposal_id = self.other_proposal.id invite = ProposalTeamInvite( proposal_id=proposal_id, - address=self.user.account_address + address=self.user.email_address ) db.session.add(invite) db.session.commit() invites_res = self.app.put( - "/api/v1/users/{}/invites/{}/respond".format(self.user.account_address, invite.id), + "/api/v1/users/{}/invites/{}/respond".format(self.user.id, invite.id), headers=self.headers, - data=json.dumps({ "response": True }), + data=json.dumps({"response": True}), content_type='application/json' ) self.assertStatus(invites_res, 200) # Make sure we made the team, coach proposal = Proposal.query.filter_by(id=proposal_id).first() - self.assertTrue(len(proposal.team) == 2) #TODO: More thorough check than length + self.assertTrue(len(proposal.team) == 2) # TODO: More thorough check than length def test_put_user_invite_response_reject(self): proposal_id = self.other_proposal.id invite = ProposalTeamInvite( proposal_id=proposal_id, - address=self.user.account_address + address=self.user.email_address ) db.session.add(invite) db.session.commit() invites_res = self.app.put( - "/api/v1/users/{}/invites/{}/respond".format(self.user.account_address, invite.id), + "/api/v1/users/{}/invites/{}/respond".format(self.user.id, invite.id), headers=self.headers, - data=json.dumps({ "response": False }), + data=json.dumps({"response": False}), content_type='application/json' ) self.assertStatus(invites_res, 200) # Make sure we made the team, coach proposal = Proposal.query.filter_by(id=proposal_id).first() - self.assertTrue(len(proposal.team) == 1) #TODO: More thorough check than length + self.assertTrue(len(proposal.team) == 1) # TODO: More thorough check than length def test_no_auth_put_user_invite_response(self): proposal_id = self.other_proposal.id invite = ProposalTeamInvite( proposal_id=proposal_id, - address=self.user.account_address + address=self.user.email_address ) db.session.add(invite) db.session.commit() invites_res = self.app.put( - "/api/v1/users/{}/invites/{}/respond".format(self.user.account_address, invite.id), - data=json.dumps({ "response": True }), + "/api/v1/users/{}/invites/{}/respond".format(self.user.id, invite.id), + data=json.dumps({"response": True}), content_type='application/json' ) self.assertStatus(invites_res, 401) def test_invalid_invite_put_user_invite_response(self): invites_res = self.app.put( - "/api/v1/users/{}/invites/1234567890/respond".format(self.user.account_address), + "/api/v1/users/{}/invites/1234567890/respond".format(self.user.id), headers=self.headers, - data=json.dumps({ "response": True }), + data=json.dumps({"response": True}), content_type='application/json' ) self.assertStatus(invites_res, 404) diff --git a/backend/tests/user/test_required_sm_decorator.py b/backend/tests/user/test_required_sm_decorator.py deleted file mode 100644 index 9d3f2d21..00000000 --- a/backend/tests/user/test_required_sm_decorator.py +++ /dev/null @@ -1,71 +0,0 @@ -import json - -from ..config import BaseTestConfig -from ..test_data import test_user, message - - -class TestRequiredSignedMessageDecorator(BaseTestConfig): - def test_required_sm_aborts_without_data_and_sig_headers(self): - self.app.post( - "/api/v1/users/", - data=json.dumps(test_user), - content_type='application/json' - ) - - response = self.app.get( - "/api/v1/users/me", - headers={ - "MsgSignature": message["sig"], - # "RawTypedData: message["data"] - } - ) - - self.assert401(response) - - response = self.app.get( - "/api/v1/users/me", - headers={ - # "MsgSignature": message["sig"], - "RawTypedData": message["data"] - } - ) - - self.assert401(response) - - def test_required_sm_aborts_without_existing_user(self): - # We don't create the user here to test a failure case - # self.app.post( - # "/api/v1/users/", - # data=json.dumps(user), - # content_type='application/json' - # ) - - response = self.app.get( - "/api/v1/users/me", - headers={ - "MsgSignature": message["sig"], - "RawTypedData": message["data"] - } - ) - - self.assert401(response) - - def test_required_sm_decorator_authorizes_when_recovered_address_matches_existing_user(self): - self.app.post( - "/api/v1/users/", - data=json.dumps(test_user), - content_type='application/json' - ) - - response = self.app.get( - "/api/v1/users/me", - headers={ - "MsgSignature": message["sig"], - "RawTypedData": message["data"] - } - ) - - response_json = response.json - - self.assert200(response) - self.assertEqual(response_json["displayName"], test_user["displayName"]) diff --git a/backend/tests/user/test_user_api.py b/backend/tests/user/test_user_api.py index 86ed9056..d563d746 100644 --- a/backend/tests/user/test_user_api.py +++ b/backend/tests/user/test_user_api.py @@ -26,10 +26,10 @@ class TestAPI(BaseUserConfig): self.assertStatus(response, 201) # User - user_db = User.get_by_identifier(account_address=test_user["accountAddress"]) + user_db = User.get_by_email(test_user["emailAddress"]) self.assertEqual(user_db.display_name, test_user["displayName"]) self.assertEqual(user_db.title, test_user["title"]) - self.assertEqual(user_db.account_address, test_user["accountAddress"]) + self.assertEqual(user_db.email_address, test_user["emailAddress"]) def test_get_all_users(self): users_get_resp = self.app.get( @@ -39,9 +39,9 @@ class TestAPI(BaseUserConfig): users_json = users_get_resp.json self.assertEqual(users_json[0]["displayName"], self.user.display_name) - def test_get_single_user_by_email(self): + def test_get_single_user_by_id(self): users_get_resp = self.app.get( - "/api/v1/users/{}".format(self.user.email_address) + "/api/v1/users/{}".format(self.user.id) ) users_json = users_get_resp.json @@ -50,18 +50,79 @@ class TestAPI(BaseUserConfig): self.assertEqual(users_json["socialMedias"][0]["username"], 'groot') self.assertEqual(users_json["socialMedias"][0]["url"], self.user.social_medias[0].social_media_link) self.assertEqual(users_json["displayName"], self.user.display_name) - - def test_get_single_user_by_account_address(self): - users_get_resp = self.app.get( - "/api/v1/users/{}".format(self.user.account_address) - ) - users_json = users_get_resp.json - self.assertEqual(users_json["avatar"]["imageUrl"], self.user.avatar.image_url) - self.assertEqual(users_json["socialMedias"][0]["service"], 'GITHUB') - self.assertEqual(users_json["socialMedias"][0]["username"], 'groot') - self.assertEqual(users_json["socialMedias"][0]["url"], self.user.social_medias[0].social_media_link) - self.assertEqual(users_json["displayName"], self.user.display_name) + def test_user_auth_success(self): + user_auth_resp = self.app.post( + "/api/v1/users/auth", + data=json.dumps({ + "email": self.user.email_address, + "password": self.user_password + }), + content_type="application/json" + ) + print(user_auth_resp.headers) + self.assertEqual(user_auth_resp.json['emailAddress'], self.user.email_address) + self.assertEqual(user_auth_resp.json['displayName'], self.user.display_name) + + def test_user_auth_required(self): + login_resp = self.app.post( + "/api/v1/users/auth", + data=json.dumps({ + "email": self.user.email_address, + "password": self.user_password + }), + content_type="application/json" + ) + print(login_resp.headers) + # should have session cookie now + me_resp = self.app.get( + "/api/v1/users/me", + data=json.dumps({ + "email": self.user.email_address, + "password": self.user_password + }), + content_type="application/json" + ) + print(me_resp.headers) + self.assert200(me_resp) + + def test_user_auth_required_fail(self): + me_resp = self.app.get( + "/api/v1/users/me", + data=json.dumps({ + "email": self.user.email_address, + "password": self.user_password + }), + + content_type="application/json" + ) + print(me_resp.json) + print(me_resp.headers) + self.assert401(me_resp) + + def test_user_auth_bad_password(self): + user_auth_resp = self.app.post( + "/api/v1/users/auth", + data=json.dumps({ + "email": self.user.email_address, + "password": "badpassword" + }), + content_type="application/json" + ) + self.assert403(user_auth_resp) + self.assertTrue(user_auth_resp.json['message'] is not None) + + def test_user_auth_bad_email(self): + user_auth_resp = self.app.post( + "/api/v1/users/auth", + data=json.dumps({ + "email": "bademail@bad.com", + "password": "somepassword" + }), + content_type="application/json" + ) + self.assert400(user_auth_resp) + self.assertTrue(user_auth_resp.json['message'] is not None) def test_create_user_duplicate_400(self): # self.user is identical to test_user, should throw @@ -73,14 +134,16 @@ class TestAPI(BaseUserConfig): self.assertEqual(response.status_code, 409) - def test_update_user_remove_social_and_avatar(self): + @patch('grant.user.views.remove_avatar') + def test_update_user_remove_social_and_avatar(self, mock_remove_avatar): + self.login_default_user() updated_user = animalify(copy.deepcopy(user_schema.dump(self.user))) updated_user["displayName"] = 'new display name' updated_user["avatar"] = {} updated_user["socialMedias"] = [] user_update_resp = self.app.put( - "/api/v1/users/{}".format(self.user.account_address), + "/api/v1/users/{}".format(self.user.id), data=json.dumps(updated_user), headers=self.headers, content_type='application/json' @@ -92,13 +155,15 @@ class TestAPI(BaseUserConfig): self.assertFalse(len(user_json["socialMedias"])) self.assertEqual(user_json["displayName"], updated_user["displayName"]) self.assertEqual(user_json["title"], updated_user["title"]) + mock_remove_avatar.assert_called_with(test_user["avatar"]["link"], 1) def test_update_user_400_when_required_param_not_passed(self): + self.login_default_user() updated_user = animalify(copy.deepcopy(user_schema.dump(self.user))) updated_user["displayName"] = 'new display name' del updated_user["avatar"] user_update_resp = self.app.put( - "/api/v1/users/{}".format(self.user.account_address), + "/api/v1/users/{}".format(self.user.id), data=json.dumps(updated_user), headers=self.headers, content_type='application/json' diff --git a/backend/tests/web3/__init__.py b/backend/tests/web3/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/backend/tests/web3/test_proposal_read.py b/backend/tests/web3/test_proposal_read.py deleted file mode 100644 index 634da15f..00000000 --- a/backend/tests/web3/test_proposal_read.py +++ /dev/null @@ -1,127 +0,0 @@ -import time - -import eth_tester.backends.pyevm.main as py_evm_main -import requests -from flask_web3 import current_web3 - -from grant.extensions import web3 -from grant.settings import CROWD_FUND_URL, CROWD_FUND_FACTORY_URL -from grant.web3.proposal import read_proposal -from ..config import BaseTestConfig - -# increase gas limit on eth-tester -# https://github.com/ethereum/web3.py/issues/1013 -# https://gitter.im/ethereum/py-evm?at=5b7eb68c4be56c5918854337 -py_evm_main.GENESIS_GAS_LIMIT = 10000000 - - -class TestWeb3ProposalRead(BaseTestConfig): - def create_app(self): - self.real_app = BaseTestConfig.create_app(self) - return self.real_app - - def setUp(self): - BaseTestConfig.setUp(self) - # the following will properly configure web3 with test config - web3.init_app(self.real_app) - crowd_fund_factory_json = requests.get(CROWD_FUND_FACTORY_URL).json() - self.crowd_fund_json = requests.get(CROWD_FUND_URL).json() - current_web3.eth.defaultAccount = current_web3.eth.accounts[0] - CrowdFundFactory = current_web3.eth.contract( - abi=crowd_fund_factory_json['abi'], bytecode=crowd_fund_factory_json['bytecode']) - tx_hash = CrowdFundFactory.constructor().transact() - tx_receipt = current_web3.eth.waitForTransactionReceipt(tx_hash) - self.crowd_fund_factory = current_web3.eth.contract( - address=tx_receipt.contractAddress, - abi=crowd_fund_factory_json['abi'] - ) - - def get_mock_proposal_read(self, contributors=[]): - mock_proposal_read = { - "immediateFirstMilestonePayout": True, - "amountVotingForRefund": "0", - "beneficiary": current_web3.eth.accounts[0], - # "deadline": 1541706179000, - "milestoneVotingPeriod": 3600000, - "isRaiseGoalReached": False, - "balance": "0", - "milestones": [ - { - "index": 0, - "state": "WAITING", - "amount": "5000000000000000000", - "amountAgainstPayout": "0", - "percentAgainstPayout": 0, - "payoutRequestVoteDeadline": 0, - "isPaid": False, - "isImmediatePayout": True - } - ], - "trustees": [current_web3.eth.accounts[0]], - "contributors": [], - "target": "5000000000000000000", - "isFrozen": False, - "funded": "0", - "percentFunded": 0, - "percentVotingForRefund": 0 - } - for c in contributors: - mock_proposal_read['contributors'].append({ - "address": current_web3.eth.accounts[c[0]], - "contributionAmount": str(c[1] * 1000000000000000000), - "refundVote": False, - "refunded": False, - "milestoneNoVotes": [False] - }) - return mock_proposal_read - - def create_crowd_fund(self): - tx_hash = self.crowd_fund_factory.functions.createCrowdFund( - 5000000000000000000, # ethAmount - current_web3.eth.accounts[0], # payout - [current_web3.eth.accounts[0]], # trustees - [5000000000000000000], # milestone amounts - 60, # duration (minutes) - 60, # voting period (minutes) - True # immediate first milestone payout - ).transact() - tx_receipt = current_web3.eth.waitForTransactionReceipt(tx_hash) - tx_events = self.crowd_fund_factory.events.ContractCreated().processReceipt(tx_receipt) - contract_address = tx_events[0]['args']['newAddress'] - return contract_address - - def fund_crowd_fund(self, address): - contract = current_web3.eth.contract(address=address, abi=self.crowd_fund_json['abi']) - accts = current_web3.eth.accounts - for c in [[5, 1], [6, 1], [7, 3]]: - tx_hash = contract.functions.contribute().transact({ - "from": accts[c[0]], - "value": c[1] * 1000000000000000000 - }) - current_web3.eth.waitForTransactionReceipt(tx_hash) - - def test_proposal_read_new(self): - contract_address = self.create_crowd_fund() - proposal_read = read_proposal(contract_address) - deadline = proposal_read.pop('deadline') - deadline_diff = deadline - time.time() * 1000 - self.assertGreater(60000, deadline_diff) - self.assertGreater(deadline_diff, 50000) - self.maxDiff = None - self.assertEqual(proposal_read, self.get_mock_proposal_read()) - - def test_proposal_funded(self): - contract_address = self.create_crowd_fund() - self.fund_crowd_fund(contract_address) - proposal_read = read_proposal(contract_address) - expected = self.get_mock_proposal_read([[5, 1], [6, 1], [7, 3]]) - expected['funded'] = expected['target'] - expected['balance'] = expected['target'] - expected['isRaiseGoalReached'] = True - expected['percentFunded'] = 100 - deadline = proposal_read.pop('deadline') - deadline_diff = deadline - time.time() * 1000 - self.assertGreater(60000, deadline_diff) - self.assertGreater(deadline_diff, 50000) - self.maxDiff = None - self.assertEqual(proposal_read, expected) diff --git a/contract/.envexample b/contract/.envexample deleted file mode 100644 index c8fa77c7..00000000 --- a/contract/.envexample +++ /dev/null @@ -1,2 +0,0 @@ -INFURA_KEY=key -MNEMONIC=mnemonic \ No newline at end of file diff --git a/contract/.gitignore b/contract/.gitignore deleted file mode 100644 index 16c4f657..00000000 --- a/contract/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -.idea/ -yarn-error.log -.env -build diff --git a/contract/.nvmrc b/contract/.nvmrc deleted file mode 100644 index 85943544..00000000 --- a/contract/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -8.13.0 \ No newline at end of file diff --git a/contract/README.md b/contract/README.md deleted file mode 100644 index 9892f751..00000000 --- a/contract/README.md +++ /dev/null @@ -1,42 +0,0 @@ -# Grant.io Smart Contracts - -This is a collection of the smart contracts and associated testing and build -process used for the [Grant.io](http://grant.io) dApp. - -## API - -This repo provides Truffle build artifacts, ABI json, and type definitions -for all contracts. You can import them like so: - -```ts -import { - EscrowContract, // Truffle build artifacts - EscrowABI, // Contract ABI - Escrow, // Contract type defintion -} from 'grant-contracts'; -``` - -## Commands - -To run any commands, you must install node dependencies, and have `truffle` -installed globally. - -### Testing - -```bash -yarn run test -``` - -Runs the truffle test suite - -### Building - -```bash -yarn run build -``` - -Builds the contract artifact JSON files, ABI JSON files, and type definitions - -### Publishing - -TBD \ No newline at end of file diff --git a/contract/bin/build-abi.js b/contract/bin/build-abi.js deleted file mode 100644 index f3787f11..00000000 --- a/contract/bin/build-abi.js +++ /dev/null @@ -1,31 +0,0 @@ -const fs = require('fs'); -const path = require('path'); - -const contractsPath = path.resolve(__dirname, '../build/contracts'); -const abiPath = path.resolve(__dirname, '../build/abi'); - -fs.readdir(contractsPath, (err, files) => { - if (err) { - console.error(err); - process.exit(1); - } - - if (!fs.existsSync(abiPath)) { - fs.mkdirSync(abiPath); - } - - files.forEach(file => { - fs.readFile( - path.join(contractsPath, file), - { encoding: 'utf8'}, - (err, data) => { - if (err) { - console.error(err); - process.exit(1); - } - const json = JSON.parse(data); - fs.writeFileSync(path.join(abiPath, file), JSON.stringify(json.abi, null, 2)); - } - ); - }); -}); \ No newline at end of file diff --git a/contract/bin/build-types.js b/contract/bin/build-types.js deleted file mode 100644 index 1ee4ae19..00000000 --- a/contract/bin/build-types.js +++ /dev/null @@ -1,10 +0,0 @@ -const path = require('path'); -const { generateTypeChainWrappers } = require('typechain'); - -process.env.DEBUG = 'typechain'; -generateTypeChainWrappers({ - cwd: path.resolve(__dirname, '..'), - glob: path.resolve(__dirname, '../build/abi/*.json'), - outDir: path.resolve(__dirname, '../build/typedefs'), - force: true, -}); diff --git a/contract/contracts/CrowdFund.sol b/contract/contracts/CrowdFund.sol deleted file mode 100644 index 0d2a8548..00000000 --- a/contract/contracts/CrowdFund.sol +++ /dev/null @@ -1,301 +0,0 @@ -pragma solidity ^0.4.24; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - - -contract CrowdFund { - using SafeMath for uint256; - - enum FreezeReason { - CALLER_IS_TRUSTEE, - CROWD_FUND_FAILED, - MAJORITY_VOTING_TO_REFUND - } - - FreezeReason freezeReason; - - struct Milestone { - uint amount; - uint amountVotingAgainstPayout; - uint payoutRequestVoteDeadline; - bool paid; - } - - struct Contributor { - uint contributionAmount; - // array index bool reflect milestone index vote - bool[] milestoneNoVotes; - bool refundVote; - bool refunded; - } - - event Deposited(address indexed payee, uint256 weiAmount); - event Withdrawn(address indexed payee, uint256 weiAmount); - - bool public frozen; - bool public isRaiseGoalReached; - bool public immediateFirstMilestonePayout; - uint public milestoneVotingPeriod; - uint public deadline; - uint public raiseGoal; - uint public amountRaised; - uint public frozenBalance; - uint public minimumContributionAmount; - uint public amountVotingForRefund; - address public beneficiary; - mapping(address => Contributor) public contributors; - address[] public contributorList; - // authorized addresses to ask for milestone payouts - address[] public trustees; - // constructor ensures that all values combined equal raiseGoal - Milestone[] public milestones; - - constructor( - uint _raiseGoal, - address _beneficiary, - address[] _trustees, - uint[] _milestones, - uint _deadline, - uint _milestoneVotingPeriod, - bool _immediateFirstMilestonePayout) - public { - require(_raiseGoal >= 1 ether, "Raise goal is smaller than 1 ether"); - require(_trustees.length >= 1 && _trustees.length <= 10, "Trustee addresses must be at least 1 and not more than 10"); - require(_milestones.length >= 1 && _milestones.length <= 10, "Milestones must be at least 1 and not more than 10"); - // TODO - require minimum duration - // TODO - require minimum milestone voting period - - // ensure that cumalative milestone payouts equal raiseGoalAmount - uint milestoneTotal = 0; - for (uint i = 0; i < _milestones.length; i++) { - uint milestoneAmount = _milestones[i]; - require(milestoneAmount > 0, "Milestone amount must be greater than 0"); - milestoneTotal = milestoneTotal.add(milestoneAmount); - milestones.push(Milestone({ - amount: milestoneAmount, - payoutRequestVoteDeadline: 0, - amountVotingAgainstPayout: 0, - paid: false - })); - } - require(milestoneTotal == _raiseGoal, "Milestone total must equal raise goal"); - // TODO - increase minimum contribution amount is 0.1% of raise goal - minimumContributionAmount = 1; - raiseGoal = _raiseGoal; - beneficiary = _beneficiary; - trustees = _trustees; - deadline = now + _deadline; - milestoneVotingPeriod = _milestoneVotingPeriod; - immediateFirstMilestonePayout = _immediateFirstMilestonePayout; - isRaiseGoalReached = false; - amountVotingForRefund = 0; - frozen = false; - // assumes no ether contributed as part of contract deployment - amountRaised = 0; - } - - function contribute() public payable onlyOnGoing onlyUnfrozen { - // don't allow overfunding - uint newAmountRaised = amountRaised.add(msg.value); - require(newAmountRaised <= raiseGoal, "Contribution exceeds the raise goal."); - // require minimumContributionAmount (set during construction) - // there may be a special case where just enough has been raised so that the remaining raise amount is just smaller than the minimumContributionAmount - // in this case, allow that the msg.value + amountRaised will equal the raiseGoal. - // This makes sure that we don't enter a scenario where a proposal can never be fully funded - bool greaterThanMinimum = msg.value >= minimumContributionAmount; - bool exactlyRaiseGoal = newAmountRaised == raiseGoal; - require(greaterThanMinimum || exactlyRaiseGoal, "msg.value greater than minimum, or msg.value == remaining amount to be raised"); - // in cases where an address pays > 1 times - if (contributors[msg.sender].contributionAmount == 0) { - contributors[msg.sender] = Contributor({ - contributionAmount: msg.value, - milestoneNoVotes: new bool[](milestones.length), - refundVote: false, - refunded: false - }); - contributorList.push(msg.sender); - } - else { - contributors[msg.sender].contributionAmount = contributors[msg.sender].contributionAmount.add(msg.value); - } - - amountRaised = newAmountRaised; - if (amountRaised == raiseGoal) { - isRaiseGoalReached = true; - } - emit Deposited(msg.sender, msg.value); - } - - function requestMilestonePayout (uint index) public onlyTrustee onlyRaised onlyUnfrozen { - bool milestoneAlreadyPaid = milestones[index].paid; - bool voteDeadlineHasPassed = milestones[index].payoutRequestVoteDeadline > now; - bool majorityAgainstPayout = isMajorityVoting(milestones[index].amountVotingAgainstPayout); - // prevent requesting paid milestones - require(!milestoneAlreadyPaid, "Milestone already paid"); - - int lowestIndexPaid = -1; - for (uint i = 0; i < milestones.length; i++) { - if (milestones[i].paid) { - lowestIndexPaid = int(i); - } - } - - require(index == uint(lowestIndexPaid + 1), "Milestone request must be for first unpaid milestone"); - // begin grace period for contributors to vote no on milestone payout - if (milestones[index].payoutRequestVoteDeadline == 0) { - if (index == 0 && immediateFirstMilestonePayout) { - // make milestone payouts immediately avtheailable for the first milestone if immediateFirstMilestonePayout is set during consutrction - milestones[index].payoutRequestVoteDeadline = 1; - } else { - milestones[index].payoutRequestVoteDeadline = now.add(milestoneVotingPeriod); - } - } - // if the payoutRequestVoteDealine has passed and majority voted against it previously, begin the grace period with 2 times the deadline - else if (voteDeadlineHasPassed && majorityAgainstPayout) { - milestones[index].payoutRequestVoteDeadline = now.add(milestoneVotingPeriod.mul(2)); - } - } - - function voteMilestonePayout(uint index, bool vote) public onlyContributor onlyRaised onlyUnfrozen { - bool existingMilestoneNoVote = contributors[msg.sender].milestoneNoVotes[index]; - require(existingMilestoneNoVote != vote, "Vote value must be different than existing vote state"); - bool milestoneVotingStarted = milestones[index].payoutRequestVoteDeadline > 0; - bool votePeriodHasEnded = milestones[index].payoutRequestVoteDeadline <= now; - bool onGoingVote = milestoneVotingStarted && !votePeriodHasEnded; - require(onGoingVote, "Milestone voting must be open"); - contributors[msg.sender].milestoneNoVotes[index] = vote; - if (!vote) { - milestones[index].amountVotingAgainstPayout = milestones[index].amountVotingAgainstPayout.sub(contributors[msg.sender].contributionAmount); - } else { - milestones[index].amountVotingAgainstPayout = milestones[index].amountVotingAgainstPayout.add(contributors[msg.sender].contributionAmount); - } - } - - function payMilestonePayout(uint index) public onlyRaised onlyUnfrozen { - bool voteDeadlineHasPassed = milestones[index].payoutRequestVoteDeadline < now; - bool majorityVotedNo = isMajorityVoting(milestones[index].amountVotingAgainstPayout); - bool milestoneAlreadyPaid = milestones[index].paid; - if (voteDeadlineHasPassed && !majorityVotedNo && !milestoneAlreadyPaid) { - milestones[index].paid = true; - uint amount = milestones[index].amount; - beneficiary.transfer(amount); - emit Withdrawn(beneficiary, amount); - // if the final milestone just got paid - if (milestones.length.sub(index) == 1) { - // useful to selfdestruct in case funds were forcefully deposited into contract. otherwise they are lost. - selfdestruct(beneficiary); - } - } else { - revert("required conditions were not satisfied"); - } - } - - function voteRefund(bool vote) public onlyContributor onlyRaised onlyUnfrozen { - bool refundVote = contributors[msg.sender].refundVote; - require(vote != refundVote, "Existing vote state is identical to vote value"); - contributors[msg.sender].refundVote = vote; - if (!vote) { - amountVotingForRefund = amountVotingForRefund.sub(contributors[msg.sender].contributionAmount); - } else { - amountVotingForRefund = amountVotingForRefund.add(contributors[msg.sender].contributionAmount); - } - } - - function refund() public onlyUnfrozen { - bool callerIsTrustee = isCallerTrustee(); - bool crowdFundFailed = isFailed(); - bool majorityVotingToRefund = isMajorityVoting(amountVotingForRefund); - require(callerIsTrustee || crowdFundFailed || majorityVotingToRefund, "Required conditions for refund are not met"); - if (callerIsTrustee) { - freezeReason = FreezeReason.CALLER_IS_TRUSTEE; - } else if (crowdFundFailed) { - freezeReason = FreezeReason.CROWD_FUND_FAILED; - } else { - freezeReason = FreezeReason.MAJORITY_VOTING_TO_REFUND; - } - frozen = true; - frozenBalance = address(this).balance; - } - - // anyone can refund a contributor if a crowdfund has been frozen - function withdraw(address refundAddress) public onlyFrozen { - require(frozen, "CrowdFund is not frozen"); - bool isRefunded = contributors[refundAddress].refunded; - require(!isRefunded, "Specified address is already refunded"); - contributors[refundAddress].refunded = true; - uint contributionAmount = contributors[refundAddress].contributionAmount; - uint amountToRefund = contributionAmount.mul(address(this).balance).div(frozenBalance); - refundAddress.transfer(amountToRefund); - emit Withdrawn(refundAddress, amountToRefund); - } - - // it may be useful to selfdestruct in case funds were force deposited to the contract - function destroy() public onlyTrustee onlyFrozen { - for (uint i = 0; i < contributorList.length; i++) { - address contributorAddress = contributorList[i]; - if (!contributors[contributorAddress].refunded) { - revert("At least one contributor has not yet refunded"); - } - } - selfdestruct(beneficiary); - } - - function isMajorityVoting(uint valueVoting) public view returns (bool) { - return valueVoting.mul(2) > amountRaised; - } - - function isCallerTrustee() public view returns (bool) { - for (uint i = 0; i < trustees.length; i++) { - if (msg.sender == trustees[i]) { - return true; - } - } - return false; - } - - function isFailed() public view returns (bool) { - return now >= deadline && !isRaiseGoalReached; - } - - function getContributorMilestoneVote(address contributorAddress, uint milestoneIndex) public view returns (bool) { - return contributors[contributorAddress].milestoneNoVotes[milestoneIndex]; - } - - function getContributorContributionAmount(address contributorAddress) public view returns (uint) { - return contributors[contributorAddress].contributionAmount; - } - - function getFreezeReason() public view returns (uint) { - return uint(freezeReason); - } - - modifier onlyFrozen() { - require(frozen, "CrowdFund is not frozen"); - _; - } - - modifier onlyUnfrozen() { - require(!frozen, "CrowdFund is frozen"); - _; - } - - modifier onlyRaised() { - require(isRaiseGoalReached, "Raise goal is not reached"); - _; - } - - modifier onlyOnGoing() { - require(now <= deadline && !isRaiseGoalReached, "CrowdFund is not ongoing"); - _; - } - - modifier onlyContributor() { - require(contributors[msg.sender].contributionAmount != 0, "Caller is not a contributor"); - _; - } - - modifier onlyTrustee() { - require(isCallerTrustee(), "Caller is not a trustee"); - _; - } - -} diff --git a/contract/contracts/CrowdFundFactory.sol b/contract/contracts/CrowdFundFactory.sol deleted file mode 100644 index a77455ed..00000000 --- a/contract/contracts/CrowdFundFactory.sol +++ /dev/null @@ -1,31 +0,0 @@ -pragma solidity ^0.4.24; -import "./CrowdFund.sol"; - -contract CrowdFundFactory { - address[] crowdfunds; - - event ContractCreated(address newAddress); - - function createCrowdFund ( - uint raiseGoalAmount, - address payOutAddress, - address[] trusteesAddresses, - uint[] allMilestones, - uint durationInSeconds, - uint milestoneVotingPeriodInSeconds, - bool immediateFirstMilestonePayout - ) public returns(address) { - address newCrowdFundContract = new CrowdFund( - raiseGoalAmount, - payOutAddress, - trusteesAddresses, - allMilestones, - durationInSeconds, - milestoneVotingPeriodInSeconds, - immediateFirstMilestonePayout - ); - emit ContractCreated(newCrowdFundContract); - crowdfunds.push(newCrowdFundContract); - return newCrowdFundContract; - } -} \ No newline at end of file diff --git a/contract/contracts/Forward.sol b/contract/contracts/Forward.sol deleted file mode 100644 index 257d9b1e..00000000 --- a/contract/contracts/Forward.sol +++ /dev/null @@ -1,15 +0,0 @@ -pragma solidity ^0.4.24; - -contract Forward { - address public destinationAddress; - - constructor(address _destinationAddress) public { - destinationAddress = _destinationAddress; - } - - function() public payable { } - - function payOut() public { - destinationAddress.transfer(address(this).balance); - } -} \ No newline at end of file diff --git a/contract/contracts/Migrations.sol b/contract/contracts/Migrations.sol deleted file mode 100644 index c4efb65e..00000000 --- a/contract/contracts/Migrations.sol +++ /dev/null @@ -1,23 +0,0 @@ -pragma solidity ^0.4.23; - -contract Migrations { - address public owner; - uint public last_completed_migration; - - constructor() public { - owner = msg.sender; - } - - modifier restricted() { - if (msg.sender == owner) _; - } - - function setCompleted(uint completed) public restricted { - last_completed_migration = completed; - } - - function upgrade(address new_address) public restricted { - Migrations upgraded = Migrations(new_address); - upgraded.setCompleted(last_completed_migration); - } -} diff --git a/contract/contracts/PrivateFund.sol b/contract/contracts/PrivateFund.sol deleted file mode 100644 index b8bdb2a6..00000000 --- a/contract/contracts/PrivateFund.sol +++ /dev/null @@ -1,202 +0,0 @@ -pragma solidity ^0.4.24; -import "openzeppelin-solidity/contracts/math/SafeMath.sol"; - -contract PrivateFund { - - using SafeMath for uint256; - - struct Milestone { - uint amount; - bool openRequest; - bool paid; - } - - struct BoardMember { - bool[] milestoneApprovals; - address refundAddress; - // TODO - refactor not to waste space like this; - bool exists; - } - - event Transfered(address payee, uint weiAmount); - event Deposited(address indexed payee, uint256 weiAmount); - event Withdrawn(address indexed payee, uint256 weiAmount); - - uint public amountRaised; - uint public raiseGoal; - uint public quorum; - address public beneficiary; - address public funder; - address[] public trustees; - bool unanimityForRefunds; - - mapping(address => BoardMember) public boardMembers; - address[] public boardMembersList; - // constructor ensures that all values combined equal raiseGoal - Milestone[] public milestones; - - constructor( - uint _raiseGoal, - address _beneficiary, - address[] _trustees, - uint _quorum, - address[] _boardMembers, - uint[] _milestones, - address _funder, - bool _unanimityForRefunds) - public { - require(_raiseGoal >= 1 ether, "Raise goal is smaller than 1 ether"); - require(_milestones.length >= 1, "Milestones must be at least 1"); - require(_quorum <= _boardMembers.length, "quorum is larger than total number of boardMembers"); - require(_quorum >= 1, "quorum must be at least 1"); - // TODO - require minimum milestone voting period - - // ensure that cumalative milestone payouts equal raiseGoalAmount - uint milestoneTotal = 0; - for (uint i = 0; i < _milestones.length; i++) { - uint milestoneAmount = _milestones[i]; - require(milestoneAmount > 0, "Milestone amount must be greater than 0"); - milestoneTotal = milestoneTotal.add(milestoneAmount); - milestones.push(Milestone({ - amount: milestoneAmount, - openRequest: false, - paid: false - })); - } - require(milestoneTotal == _raiseGoal, "Milestone total must equal raise goal"); - - boardMembersList = _boardMembers; - for (uint e = 0; e < boardMembersList.length; e++) { - address boardMemberAddress = boardMembersList[e]; - boardMembers[boardMemberAddress] = BoardMember({ - milestoneApprovals: new bool[](milestones.length), - refundAddress: 0, - exists: true - }); - } - - quorum = _quorum; - raiseGoal = _raiseGoal; - beneficiary = _beneficiary; - trustees = _trustees; - funder = _funder; - unanimityForRefunds = _unanimityForRefunds; - amountRaised = 0; - } - - function contribute() public payable { - require(msg.sender == funder, "Sender must be funder"); - require(amountRaised.add(msg.value) == raiseGoal, "Contribution must be exactly raise goal"); - amountRaised = msg.value; - emit Deposited(msg.sender, msg.value); - } - - function requestMilestonePayout (uint index) public onlyTrustee onlyRaised { - bool milestoneAlreadyPaid = milestones[index].paid; - // prevent requesting paid milestones - require(!milestoneAlreadyPaid, "Milestone already paid"); - - int lowestIndexPaid = -1; - for (uint i = 0; i < milestones.length; i++) { - if (milestones[i].paid) { - lowestIndexPaid = int(i); - } - } - - require(index == uint(lowestIndexPaid + 1), "Milestone request must be for first unpaid milestone"); - // begin grace period for contributors to vote no on milestone payout - require(!milestones[index].openRequest, "Milestone must not have already been requested"); - milestones[index].openRequest = true; - } - - function voteMilestonePayout(uint index, bool vote) public onlyBoardMember onlyRaised { - bool existingMilestoneVote = boardMembers[msg.sender].milestoneApprovals[index]; - require(existingMilestoneVote != vote, "Vote value must be different than existing vote state"); - require(milestones[index].openRequest, "Milestone voting must be open"); - boardMembers[msg.sender].milestoneApprovals[index] = vote; - } - - function payMilestonePayout(uint index) public onlyRaised { - bool quorumReached = isQuorumReachedForMilestonePayout(index); - bool milestoneAlreadyPaid = milestones[index].paid; - if (quorumReached && !milestoneAlreadyPaid) { - milestones[index].paid = true; - milestones[index].openRequest = false; - fundTransfer(beneficiary, milestones[index].amount); - // TODO trigger self-destruct with any un-spent funds (since funds could have been force sent at any point) - } else { - revert("required conditions were not satisfied"); - } - } - - function voteRefundAddress(address refundAddress) public onlyBoardMember onlyRaised { - boardMembers[msg.sender].refundAddress = refundAddress; - } - - function refund(address refundAddress) public onlyBoardMember onlyRaised { - require(isConsensusReachedForRefund(refundAddress), "Unanimity is not reached to refund to given address"); - selfdestruct(refundAddress); - } - - function fundTransfer(address etherReceiver, uint256 amount) private { - etherReceiver.transfer(amount); - emit Transfered(etherReceiver, amount); - } - - function isConsensusReachedForRefund(address refundAddress) public view onlyRaised returns (bool) { - uint yesVotes = 0; - for (uint i = 0; i < boardMembersList.length; i++) { - address boardMemberAddress = boardMembersList[i]; - address boardMemberRefundAddressSelection = boardMembers[boardMemberAddress].refundAddress; - if (boardMemberRefundAddressSelection == refundAddress) { - yesVotes += 1; - } - } - if (unanimityForRefunds) { - return yesVotes == boardMembersList.length; - } else { - return yesVotes >= quorum; - } - } - - function isQuorumReachedForMilestonePayout(uint milestoneIndex) public view onlyRaised returns (bool) { - uint yesVotes = 0; - for (uint i = 0; i < boardMembersList.length; i++) { - address boardMemberAddress = boardMembersList[i]; - bool boardMemberVote = boardMembers[boardMemberAddress].milestoneApprovals[milestoneIndex]; - if (boardMemberVote) { - yesVotes += 1; - } - } - return yesVotes >= quorum; - } - - function isCallerTrustee() public view returns (bool) { - for (uint i = 0; i < trustees.length; i++) { - if (msg.sender == trustees[i]) { - return true; - } - } - return false; - } - - function getBoardMemberMilestoneVote(address boardMemberAddress, uint milestoneIndex) public view returns (bool) { - return boardMembers[boardMemberAddress].milestoneApprovals[milestoneIndex]; - } - - modifier onlyRaised() { - require(raiseGoal == amountRaised, "Proposal is not funded"); - _; - } - - modifier onlyBoardMember() { - require(boardMembers[msg.sender].exists, "Caller is not a board member"); - _; - } - - modifier onlyTrustee() { - require(isCallerTrustee(), "Caller is not a trustee"); - _; - } - -} \ No newline at end of file diff --git a/contract/contracts/PrivateFundFactory.sol b/contract/contracts/PrivateFundFactory.sol deleted file mode 100644 index 18b6cf5d..00000000 --- a/contract/contracts/PrivateFundFactory.sol +++ /dev/null @@ -1,33 +0,0 @@ -pragma solidity ^0.4.24; -import "./PrivateFund.sol"; - -contract PrivateFundFactory { - address[] privateFunds; - - event ContractCreated(address newAddress); - - function createPrivateFund ( - uint _raiseGoal, - address _beneficiary, - address[] _trustees, - uint _quorum, - address[] _boardMembers, - uint[] _milestones, - address _funder, - bool _unanimityForRefunds - ) public returns(address) { - address newPrivateFundContract = new PrivateFund( - _raiseGoal, - _beneficiary, - _trustees, - _quorum, - _boardMembers, - _milestones, - _funder, - _unanimityForRefunds - ); - emit ContractCreated(newPrivateFundContract); - privateFunds.push(newPrivateFundContract); - return newPrivateFundContract; - } -} \ No newline at end of file diff --git a/contract/main.js b/contract/main.js deleted file mode 100644 index 3d36aec0..00000000 --- a/contract/main.js +++ /dev/null @@ -1,13 +0,0 @@ -export { default as CrowdFundContract } from './build/contracts/CrowdFund.json'; -export { default as CrowdFundFactoryContract } from './build/contracts/CrowdFundFactory.json'; -export { default as MigrationsContract } from './build/contracts/Migrations.json'; -export { default as SafeMathContract } from './build/contracts/SafeMath.json'; - -export { default as CrowdFundABI } from './build/abi/CrowdFund.json'; -export { default as CrowdFundFactoryABI } from './build/abi/CrowdFundFactory.json'; -export { default as MigrationsABI } from './build/abi/Migrations.json'; -export { default as SafeMathABI } from './build/abi/SafeMath.json'; - -export { CrowdFund } from './build/typedefs/CrowdFund.ts'; -export { CrowdFundFactory } from './build/typedefs/CrowdFundFactory.ts'; -export { Migrations } from './build/typedefs/Migrations.ts'; diff --git a/contract/migrations/1_initial_migration.js b/contract/migrations/1_initial_migration.js deleted file mode 100644 index 4d5f3f9b..00000000 --- a/contract/migrations/1_initial_migration.js +++ /dev/null @@ -1,5 +0,0 @@ -var Migrations = artifacts.require("./Migrations.sol"); - -module.exports = function(deployer) { - deployer.deploy(Migrations); -}; diff --git a/contract/migrations/2_deploy_contracts.js b/contract/migrations/2_deploy_contracts.js deleted file mode 100644 index c68edc08..00000000 --- a/contract/migrations/2_deploy_contracts.js +++ /dev/null @@ -1,5 +0,0 @@ -const CrowdFundFactory = artifacts.require("./CrowdFundFactory.sol"); - -module.exports = function(deployer) { - deployer.deploy(CrowdFundFactory); -}; diff --git a/contract/package.json b/contract/package.json deleted file mode 100644 index 031efaa2..00000000 --- a/contract/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "grant-contract", - "version": "1.0.0", - "description": "", - "main": "main.js", - "directories": { - "test": "test" - }, - "scripts": { - "test": "truffle test", - "build": "truffle compile && node ./bin/build-abi && node ./bin/build-types" - }, - "author": "", - "license": "ISC", - "dependencies": { - "openzeppelin-solidity": "^1.12.0", - "truffle-hdwallet-provider": "^0.0.6" - }, - "devDependencies": { - "chai": "^4.1.2", - "eth-gas-reporter": "^0.1.10", - "typechain": "0.2.7" - } -} diff --git a/contract/test/CrowdFundDeadlineTest.js b/contract/test/CrowdFundDeadlineTest.js deleted file mode 100644 index b8c08f72..00000000 --- a/contract/test/CrowdFundDeadlineTest.js +++ /dev/null @@ -1,118 +0,0 @@ -const CrowdFund = artifacts.require("CrowdFund"); -const { increaseTime } = require("./utils"); - -const HOUR = 3600; -const DAY = HOUR * 24; -const ETHER = 10 ** 18; -const DEADLINE = DAY * 100; -const AFTER_DEADLINE_EXPIRES = DEADLINE + DAY; - -contract("CrowdFund Deadline", accounts => { - const [ - firstAccount, - firstTrusteeAccount, - thirdAccount, - fourthAccount - ] = accounts; - const raiseGoal = ETHER; - const beneficiary = firstTrusteeAccount; - // TODO - set multiple trustees and add tests - const trustees = [firstTrusteeAccount]; - // TODO - set multiple milestones and add tests - const milestones = [raiseGoal]; - const deadline = DEADLINE; - const milestoneVotingPeriod = HOUR; - const immediateFirstMilestonePayout = false; - - let crowdFund; - - beforeEach(async () => { - crowdFund = await CrowdFund.new( - raiseGoal, - beneficiary, - trustees, - milestones, - deadline, - milestoneVotingPeriod, - immediateFirstMilestonePayout, - { from: firstAccount } - ); - }); - - it("returns true when isFailed is called after deadline has passed", async () => { - assert.equal(await crowdFund.isFailed.call(), false); - await increaseTime(AFTER_DEADLINE_EXPIRES); - assert.equal(await crowdFund.isFailed.call(), true); - }); - - it("allows anyone to refund after time is up and goal is not reached and sets refund reason to 1", async () => { - const fundAmount = raiseGoal / 10; - await crowdFund.contribute({ - from: fourthAccount, - value: fundAmount, - gasPrice: 0, - }); - assert.equal( - (await crowdFund.contributors(fourthAccount))[0].toNumber(), - fundAmount - ); - assert.equal(await crowdFund.contributorList(0), fourthAccount); - const initBalance = await web3.eth.getBalance(fourthAccount); - await increaseTime(AFTER_DEADLINE_EXPIRES); - await crowdFund.refund(); - assert.equal((await crowdFund.getFreezeReason()), 1) - await crowdFund.withdraw(fourthAccount); - const finalBalance = await web3.eth.getBalance(fourthAccount); - assert.ok(finalBalance.equals(initBalance.plus(fundAmount))); - }); - - it("refunds remaining proportionally when fundraiser has failed", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ - from: fourthAccount, - value: tenthOfRaiseGoal - }); - const initBalanceFourthAccount = await web3.eth.getBalance(fourthAccount); - await increaseTime(AFTER_DEADLINE_EXPIRES); - assert.ok(await crowdFund.isFailed()); - await crowdFund.refund(); - await crowdFund.withdraw(fourthAccount); - const finalBalanceFourthAccount = await web3.eth.getBalance(fourthAccount); - assert.ok(finalBalanceFourthAccount.gt(initBalanceFourthAccount)); - }); - - it("refund remaining proportionally when fundraiser has failed (more complex)", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ - from: fourthAccount, - value: tenthOfRaiseGoal - }); - await crowdFund.contribute({ - from: thirdAccount, - value: tenthOfRaiseGoal * 4 - }); - const initBalanceFourthAccount = await web3.eth.getBalance(fourthAccount); - const initBalanceThirdAccount = await web3.eth.getBalance(thirdAccount); - await increaseTime(AFTER_DEADLINE_EXPIRES); - assert.ok(await crowdFund.isFailed()); - const afterContributionBalanceFourthAccount = await web3.eth.getBalance( - fourthAccount - ); - const afterContributionBalanceThirdAccount = await web3.eth.getBalance( - thirdAccount - ); - // fourthAccount contributed a tenth of the raise goal, compared to third account with a fourth - assert.ok( - afterContributionBalanceFourthAccount.gt( - afterContributionBalanceThirdAccount - ) - ); - await crowdFund.refund(); - await crowdFund.withdraw(fourthAccount); - await crowdFund.withdraw(thirdAccount); - const finalBalanceFourthAccount = await web3.eth.getBalance(fourthAccount); - const finalBalanceThirdAccount = await web3.eth.getBalance(thirdAccount); - assert.ok(finalBalanceFourthAccount.gt(initBalanceFourthAccount)); - assert.ok(finalBalanceThirdAccount.gt(initBalanceThirdAccount)); - }); -}); diff --git a/contract/test/CrowdFundTest.js b/contract/test/CrowdFundTest.js deleted file mode 100644 index 0da9a3d5..00000000 --- a/contract/test/CrowdFundTest.js +++ /dev/null @@ -1,457 +0,0 @@ -// References https://michalzalecki.com/ethereum-test-driven-introduction-to-solidity/ -const CrowdFund = artifacts.require("CrowdFund"); -const { increaseTime, assertRevert, assertVMException } = require("./utils"); - -const HOUR = 3600; -const DAY = HOUR * 24; -const ETHER = 10 ** 18; -const NOW = Math.round(new Date().getTime() / 1000); -const AFTER_VOTING_EXPIRES = HOUR * 2; - -contract("CrowdFund", accounts => { - const [ - firstAccount, - firstTrusteeAccount, - thirdAccount, - fourthAccount, - fifthAccount - ] = accounts; - const raiseGoal = 1 * ETHER; - const beneficiary = firstTrusteeAccount; - // TODO - set multiple trustees and add tests - const trustees = [firstTrusteeAccount]; - // TODO - set multiple milestones and add tests - const milestones = [raiseGoal]; - const deadline = NOW + DAY * 100; - const milestoneVotingPeriod = HOUR; - const immediateFirstMilestonePayout = false; - - let crowdFund; - - beforeEach(async () => { - crowdFund = await CrowdFund.new( - raiseGoal, - beneficiary, - trustees, - milestones, - deadline, - milestoneVotingPeriod, - immediateFirstMilestonePayout, - { from: fifthAccount } - ); - }); - - // [BEGIN] constructor - // TODO - test all initial variables have expected values - it("initializes", async () => { - assert.equal(await crowdFund.raiseGoal.call(), raiseGoal); - assert.equal(await crowdFund.beneficiary.call(), beneficiary); - - trustees.forEach(async (address, i) => { - assert.equal(await crowdFund.trustees.call(i), trustees[i]); - }); - - milestones.forEach(async (milestoneAmount, i) => { - assert.equal(await crowdFund.milestones.call(i)[0], milestoneAmount); - }); - }); - - // [END] constructor - // [BEGIN] contribute - - it("reverts on next contribution once raise goal is reached", async () => { - await crowdFund.contribute({ - from: firstAccount, - value: raiseGoal - }); - assert.ok(await crowdFund.isRaiseGoalReached()); - assertRevert( - crowdFund.contribute({ - from: firstAccount, - value: raiseGoal - }) - ); - }); - - it("keeps track of contributions", async () => { - await crowdFund.contribute({ - from: firstAccount, - value: raiseGoal / 10 - }); - await crowdFund.contribute({ - from: firstTrusteeAccount, - value: raiseGoal / 10 - }); - await crowdFund.contribute({ - from: firstTrusteeAccount, - value: raiseGoal / 10 - }); - assert.equal( - (await crowdFund.contributors(firstAccount))[0].toNumber(), - raiseGoal / 10 - ); - assert.equal( - (await crowdFund.contributors(firstTrusteeAccount))[0].toNumber(), - raiseGoal / 5 - ); - }); - - // TODO BLOCKED - it reverts when contribution is under 1 wei. Blocked by switching contract to use minimum percentage contribution - - it("revertd on contribution that exceeds raise goal", async () => { - assertRevert( - crowdFund.contribute({ - from: firstAccount, - value: raiseGoal + raiseGoal / 10 - }) - ); - }); - - // [BEGIN] requestMilestonePayout - - it("does not allow milestone requests when caller is not a trustee", async () => { - assertRevert(crowdFund.requestMilestonePayout(0, { from: firstAccount })); - }); - - it("does not allow milestone requests when milestone has already been paid", async () => { - await crowdFund.contribute({ from: thirdAccount, value: raiseGoal }); - const initBalance = await web3.eth.getBalance(firstTrusteeAccount); - await crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - await increaseTime(AFTER_VOTING_EXPIRES); - await crowdFund.payMilestonePayout(0); - const finalBalance = await web3.eth.getBalance(firstTrusteeAccount); - assert.ok(finalBalance.greaterThan(initBalance)); - // TODO - enable - // assertRevert( - // crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }) - // ); - }); - - // [END] requestMilestonePayout - // [BEGIN] voteMilestonePayout - - it("only counts milestone vote once", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ from: thirdAccount, value: tenthOfRaiseGoal }); - await crowdFund.contribute({ - from: firstAccount, - value: tenthOfRaiseGoal * 9 - }); - assert.ok(await crowdFund.isRaiseGoalReached()); - await crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - // first vote - await crowdFund.voteMilestonePayout(0, true, { from: firstAccount }); - assert.equal( - (await crowdFund.milestones(0))[1].toNumber(), - tenthOfRaiseGoal * 9 - ); - // second vote - assertRevert( - crowdFund.voteMilestonePayout(0, true, { from: firstAccount }) - ); - assert.equal( - (await crowdFund.milestones(0))[1].toNumber(), - tenthOfRaiseGoal * 9 - ); - }); - - it("does not allow milestone voting before vote period has started", async () => { - await crowdFund.contribute({ - from: thirdAccount, - value: raiseGoal / 10 - }); - await crowdFund.contribute({ - from: firstAccount, - value: (raiseGoal / 10) * 9 - }); - assertRevert( - crowdFund.voteMilestonePayout(0, true, { from: thirdAccount }) - ); - }); - - it("does not allow milestone voting after vote period has ended", async () => { - await crowdFund.contribute({ - from: thirdAccount, - value: raiseGoal / 10 - }); - await crowdFund.contribute({ - from: firstAccount, - value: (raiseGoal / 10) * 9 - }); - await crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - await crowdFund.voteMilestonePayout(0, true, { from: thirdAccount }); - await increaseTime(AFTER_VOTING_EXPIRES); - assertRevert( - crowdFund.voteMilestonePayout(0, true, { from: firstAccount }) - ); - }); - - // [END] voteMilestonePayout - // [BEGIN] payMilestonePayout - - it("pays milestone when milestone is unpaid, caller is trustee, and no earlier milestone is unpaid", async () => { - await crowdFund.contribute({ from: thirdAccount, value: raiseGoal }); - const initBalance = await web3.eth.getBalance(firstTrusteeAccount); - await crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - await increaseTime(AFTER_VOTING_EXPIRES); - await crowdFund.payMilestonePayout(0); - const finalBalance = await web3.eth.getBalance(firstTrusteeAccount); - assert.ok(finalBalance.greaterThan(initBalance)); - }); - - it("does not pay milestone when vote deadline has not passed", async () => { - await crowdFund.contribute({ from: thirdAccount, value: raiseGoal }); - await crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - assertRevert( - crowdFund.payMilestonePayout(0, { from: firstTrusteeAccount }) - ); - }); - - it("does not pay milestone when raise goal is not met", async () => { - await crowdFund.contribute({ - from: thirdAccount, - value: raiseGoal / 10 - }); - assert.ok((await crowdFund.raiseGoal()).gt(await crowdFund.amountRaised())); - assertRevert( - crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }) - ); - }); - - it("does not pay milestone when majority is voting no on a milestone", async () => { - await crowdFund.contribute({ from: thirdAccount, value: raiseGoal }); - await crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - await crowdFund.voteMilestonePayout(0, true, { from: thirdAccount }); - await increaseTime(AFTER_VOTING_EXPIRES); - assertRevert(crowdFund.payMilestonePayout(0)); - }); - - // [END] payMilestonePayout - // [BEGIN] voteRefund - - it("keeps track of refund vote amount", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ from: thirdAccount, value: tenthOfRaiseGoal }); - await crowdFund.contribute({ - from: firstAccount, - value: tenthOfRaiseGoal * 9 - }); - assert.ok(await crowdFund.isRaiseGoalReached()); - await crowdFund.voteRefund(true, { from: thirdAccount }); - await crowdFund.voteRefund(true, { from: firstAccount }); - assert.equal( - (await crowdFund.amountVotingForRefund()).toNumber(), - tenthOfRaiseGoal * 9 + tenthOfRaiseGoal - ); - await crowdFund.voteRefund(false, { from: firstAccount }); - assert.equal( - (await crowdFund.amountVotingForRefund()).toNumber(), - tenthOfRaiseGoal - ); - }); - - it("does not allow non-contributors to vote", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ from: thirdAccount, value: tenthOfRaiseGoal }); - await crowdFund.contribute({ - from: firstAccount, - value: tenthOfRaiseGoal * 9 - }); - assert.ok(await crowdFund.isRaiseGoalReached()); - assertRevert(crowdFund.voteRefund(true, { from: firstTrusteeAccount })); - }); - - it("only allows contributors to vote after raise goal has been reached", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ - from: fourthAccount, - value: tenthOfRaiseGoal - }); - assert.ok(!(await crowdFund.isRaiseGoalReached())); - assertRevert(crowdFund.voteRefund(true, { from: fourthAccount })); - await crowdFund.contribute({ - from: firstAccount, - value: tenthOfRaiseGoal * 9 - }); - assert.ok(await crowdFund.isRaiseGoalReached()); - assert.ok(await crowdFund.voteRefund(true, { from: fourthAccount })); - }); - - it("only adds refund voter amount once", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ from: thirdAccount, value: tenthOfRaiseGoal }); - await crowdFund.contribute({ - from: firstAccount, - value: tenthOfRaiseGoal * 9 - }); - assert.ok(await crowdFund.isRaiseGoalReached()); - await crowdFund.voteRefund(true, { from: thirdAccount }); - assert.equal( - (await crowdFund.amountVotingForRefund()).toNumber(), - tenthOfRaiseGoal - ); - await crowdFund.voteRefund(false, { from: thirdAccount }); - assert.equal((await crowdFund.amountVotingForRefund()).toNumber(), 0); - await crowdFund.voteRefund(true, { from: thirdAccount }); - assert.equal( - (await crowdFund.amountVotingForRefund()).toNumber(), - tenthOfRaiseGoal - ); - assertVMException(crowdFund.voteRefund(true, { from: thirdAccount })); - }); - - // [END] voteRefund - // [BEGIN] refund - - it("does not allow non-trustees to refund", async () => { - await crowdFund.contribute({ - from: fourthAccount, - value: raiseGoal / 5 - }); - - assert.ok(!(await crowdFund.isRaiseGoalReached())); - assertRevert(crowdFund.refund()); - }); - - it("allows trustee to refund while the CrowdFund is on-going and sets reason to 0", async () => { - await crowdFund.contribute({ - from: fourthAccount, - value: raiseGoal / 5 - }); - assert.ok(!(await crowdFund.isRaiseGoalReached())); - const balanceAfterFundingFourthAccount = await web3.eth.getBalance( - fourthAccount - ); - await crowdFund.refund({ from: firstTrusteeAccount }); - assert.equal((await crowdFund.getFreezeReason()), 0); - await crowdFund.withdraw(fourthAccount); - const balanceAfterRefundFourthAccount = await web3.eth.getBalance( - fourthAccount - ); - assert.ok( - balanceAfterRefundFourthAccount.gt(balanceAfterFundingFourthAccount) - ); - }); - - it("allows trustee to refund after the CrowdFund has finished", async () => { - await crowdFund.contribute({ - from: fourthAccount, - value: raiseGoal - }); - - assert.ok(await crowdFund.isRaiseGoalReached()); - const balanceAfterFundingFourthAccount = await web3.eth.getBalance( - fourthAccount - ); - await crowdFund.refund({ from: firstTrusteeAccount }); - await crowdFund.withdraw(fourthAccount); - const balanceAfterRefundFourthAccount = await web3.eth.getBalance( - fourthAccount - ); - assert.ok( - balanceAfterRefundFourthAccount.gt(balanceAfterFundingFourthAccount) - ); - }); - - it("reverts if non-trustee attempts to refund on active CrowdFund", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ - from: fourthAccount, - value: tenthOfRaiseGoal - }); - assertRevert(crowdFund.refund()); - }); - - it("reverts if non-trustee attempts to refund a successful CrowdFund without a majority voting to refund", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ - from: fourthAccount, - value: tenthOfRaiseGoal * 2 - }); - await crowdFund.contribute({ - from: thirdAccount, - value: tenthOfRaiseGoal * 8 - }); - assert.ok(await crowdFund.isRaiseGoalReached()); - assertRevert(crowdFund.refund()); - }); - - it("refunds proportionally if majority is voting for refund after raise goal has been reached and sets reason to 2", async () => { - const tenthOfRaiseGoal = raiseGoal / 10; - await crowdFund.contribute({ - from: fourthAccount, - value: tenthOfRaiseGoal * 2 - }); - await crowdFund.contribute({ - from: thirdAccount, - value: tenthOfRaiseGoal * 8 - }); - const initBalanceFourthAccount = await web3.eth.getBalance(fourthAccount); - const initBalanceThirdAccount = await web3.eth.getBalance(thirdAccount); - assert.ok(await crowdFund.isRaiseGoalReached()); - const afterContributionBalanceFourthAccount = await web3.eth.getBalance( - fourthAccount - ); - const afterContributionBalanceThirdAccount = await web3.eth.getBalance( - thirdAccount - ); - // fourthAccount contributed a tenth of the raise goal, compared to third account with a fourth - assert.ok( - afterContributionBalanceFourthAccount.gt( - afterContributionBalanceThirdAccount - ) - ); - await crowdFund.voteRefund(true, { from: thirdAccount }); - await crowdFund.refund(); - assert.equal((await crowdFund.getFreezeReason()), 2) - await crowdFund.withdraw(fourthAccount); - await crowdFund.withdraw(thirdAccount); - const finalBalanceFourthAccount = await web3.eth.getBalance(fourthAccount); - const finalBalanceThirdAccount = await web3.eth.getBalance(thirdAccount); - assert.ok(finalBalanceFourthAccount.gt(initBalanceFourthAccount)); - assert.ok(finalBalanceThirdAccount.gt(initBalanceThirdAccount)); - }); - - it("refunds full amounts even if raise goal isn't reached", async () => { - const initialBalance = await web3.eth.getBalance(fourthAccount); - const contribution = raiseGoal / 2; - const receipt = await crowdFund.contribute({ - from: fourthAccount, - value: contribution, - gasPrice: 0, - }); - await crowdFund.refund({ from: firstTrusteeAccount }); - await crowdFund.withdraw(fourthAccount); - const balance = await web3.eth.getBalance(fourthAccount); - const diff = initialBalance.minus(balance); - assert( - balance.equals(initialBalance), - `Expected full refund, but refund was short ${diff.toString()} wei` - ); - }); - - // [END] refund - // [BEGIN] getContributorMilestoneVote - - it("returns milestone vote for a contributor", async () => { - await crowdFund.contribute({ from: thirdAccount, value: raiseGoal }); - await crowdFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - await crowdFund.voteMilestonePayout(0, true, { from: thirdAccount }); - await increaseTime(AFTER_VOTING_EXPIRES); - const milestoneVote = await crowdFund.getContributorMilestoneVote.call(thirdAccount, 0); - assert.equal(true, milestoneVote) - }); - - - // [END] getContributorMilestoneVote - - // [BEGIN] getContributorContributionAmount - - it("returns amount a contributor has contributed", async () => { - const constributionAmount = raiseGoal / 5 - await crowdFund.contribute({ from: thirdAccount, value: constributionAmount }); - const contractContributionAmount = await crowdFund.getContributorContributionAmount(thirdAccount) - assert.equal(contractContributionAmount.toNumber(), constributionAmount) - }); - -}); diff --git a/contract/test/ForwardTest.js b/contract/test/ForwardTest.js deleted file mode 100644 index a1d6bfef..00000000 --- a/contract/test/ForwardTest.js +++ /dev/null @@ -1,26 +0,0 @@ -const Forward = artifacts.require("Forward"); - -contract("Forward", accounts => { - const [creatorAccount, destinationAddress] = accounts; - const amount = 1; - - let forward; - - beforeEach(async () => { - forward = await Forward.new(destinationAddress, { from: creatorAccount }); - }); - - it("deposits", async () => { - await forward.sendTransaction({ from: creatorAccount, value: amount }); - const forwardBalance = await web3.eth.getBalance(forward.address); - assert.equal(forwardBalance.toNumber(), amount); - }); - - it("forwards", async () => { - const initBalance = await web3.eth.getBalance(destinationAddress); - await forward.sendTransaction({ from: creatorAccount, value: amount }); - await forward.payOut({ from: creatorAccount }); - const finalBalance = await web3.eth.getBalance(destinationAddress); - assert.ok(finalBalance.gt(initBalance)); - }); -}); diff --git a/contract/test/PrivateFundTest.js b/contract/test/PrivateFundTest.js deleted file mode 100644 index 10bda6a4..00000000 --- a/contract/test/PrivateFundTest.js +++ /dev/null @@ -1,235 +0,0 @@ -// test/CrowdFundTest.js -// References https://michalzalecki.com/ethereum-test-driven-introduction-to-solidity/ -const PrivateFund = artifacts.require("PrivateFund"); -const { assertRevert } = require("./utils"); - -const ETHER = 10 ** 18; - -contract("PrivateFund", accounts => { - const [ - funderAccount, - firstTrusteeAccount, - refundAccount, - boardOne, - boardTwo, - boardThree - ] = accounts; - const raiseGoal = 1 * ETHER; - const halfRaiseGoal = raiseGoal / 2; - const beneficiary = firstTrusteeAccount; - // TODO - set multiple trustees and add tests - const trustees = [beneficiary]; - const quorum = 2; - const boardMembers = [boardOne, boardTwo, boardThree]; - const milestones = [halfRaiseGoal, halfRaiseGoal]; - const funder = funderAccount; - const useQuroumForRefund = false; - - let privateFund; - - beforeEach(async () => { - privateFund = await PrivateFund.new( - raiseGoal, - beneficiary, - trustees, - quorum, - boardMembers, - milestones, - funder, - useQuroumForRefund, - { from: funderAccount } - ); - }); - - // [BEGIN] constructor - // TODO - test all initial variables have expected values - it("initializes", async () => { - assert.equal(await privateFund.raiseGoal.call(), raiseGoal); - assert.equal(await privateFund.beneficiary.call(), beneficiary); - - trustees.forEach(async (address, i) => { - assert.equal(await privateFund.trustees.call(i), trustees[i]); - }); - - // TODO - get working - // milestones.forEach(async (milestoneAmount, i) => { - // console.log(i) - // assert.equal(await privateFund.milestones(i)[0], milestoneAmount); - // }); - }); - - // [END] constructor - // [BEGIN] contribute - - it("revert on next contribution once raise goal is reached", async () => { - await privateFund.contribute({ - from: funderAccount, - value: raiseGoal - }); - assertRevert( - privateFund.contribute({ - from: funderAccount, - value: raiseGoal - }) - ); - }); - - it("revert when raiseGoal isn't paid in full", async () => { - assertRevert( - privateFund.contribute({ - from: funderAccount, - value: raiseGoal / 5 - }) - ); - }); - - it("amountRaised is set after contribution", async () => { - await privateFund.contribute({ - from: funderAccount, - value: raiseGoal - }); - assert.equal( - (await privateFund.amountRaised()).toNumber(), - (await privateFund.raiseGoal()).toNumber() - ); - }); - - // [BEGIN] requestMilestonePayout - - it("does not request milestone when earlier milestone is unpaid", async () => { - await privateFund.contribute({ from: funderAccount, value: raiseGoal }); - assertRevert( - privateFund.requestMilestonePayout(1, { from: firstTrusteeAccount }) - ); - }); - - it("does not allow milestone request when caller is not trustee", async () => { - assertRevert( - privateFund.requestMilestonePayout(0, { from: funderAccount }) - ); - }); - - it("does not allow milestone request when milestone has already been paid", async () => { - await privateFund.contribute({ from: funderAccount, value: raiseGoal }); - const initBalance = await web3.eth.getBalance(beneficiary); - await privateFund.requestMilestonePayout(0, { from: beneficiary }); - await privateFund.voteMilestonePayout(0, true, { from: boardOne }); - await privateFund.voteMilestonePayout(0, true, { from: boardTwo }); - await privateFund.payMilestonePayout(0); - const finalBalance = await web3.eth.getBalance(beneficiary); - assert.ok(finalBalance.greaterThan(initBalance)); - assertRevert(privateFund.requestMilestonePayout(0, { from: beneficiary })); - }); - - // [END] requestMilestonePayout - // [BEGIN] voteMilestonePayout - - it("persists board member votes", async () => { - await privateFund.contribute({ - from: funderAccount, - value: raiseGoal - }); - - await privateFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - - await privateFund.voteMilestonePayout(0, true, { from: boardOne }); - await privateFund.voteMilestonePayout(0, true, { from: boardTwo }); - assert.equal((await privateFund.getBoardMemberMilestoneVote(boardOne, 0)), true ) - }); - - it("only allows board members to vote", async () => { - await privateFund.contribute({ - from: funderAccount, - value: raiseGoal - }); - - await privateFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - - assertRevert( - privateFund.voteMilestonePayout(0, true, { from: funderAccount }) // even funders can't vote unless they are also part of the board - ); - }); - - it("does not allow milestone voting before vote period has started", async () => { - await privateFund.contribute({ - from: funderAccount, - value: raiseGoal - }); - - assertRevert( - privateFund.voteMilestonePayout(0, true, { from: boardThree }) - ); - }); - - // [END] voteMilestonePayout - // [BEGIN] payMilestonePayout - - it("pays milestone when milestone is unpaid, quorum is reached, caller is trustee, and no earlier milestone is unpaid", async () => { - await privateFund.contribute({ from: funderAccount, value: raiseGoal }); - const initBalance = await web3.eth.getBalance(beneficiary); - - await privateFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - // quorum of two needed - await privateFund.voteMilestonePayout(0, true, { from: boardOne }); - await privateFund.voteMilestonePayout(0, true, { from: boardTwo }); - - await privateFund.payMilestonePayout(0); - const finalBalance = await web3.eth.getBalance(firstTrusteeAccount); - assert.ok(finalBalance.greaterThan(initBalance)); - }); - - it("does not pay milestone when raise goal is not met", async () => { - assert.ok( - (await privateFund.raiseGoal()).gt(await privateFund.amountRaised()) - ); - assertRevert( - privateFund.requestMilestonePayout(0, { from: firstTrusteeAccount }) - ); - }); - - it("does not pay milestone when quorum is not reached", async () => { - await privateFund.contribute({ from: funderAccount, value: raiseGoal }); - await privateFund.requestMilestonePayout(0, { from: firstTrusteeAccount }); - // only one vote in favor - await privateFund.voteMilestonePayout(0, true, { from: boardOne }); - assertRevert(privateFund.payMilestonePayout(0)); - }); - - // [END] payMilestonePayout - // [BEGIN] voteRefundAddress - - it("keeps track of refund vote address choices", async () => { - await privateFund.contribute({ from: funderAccount, value: raiseGoal }); - await privateFund.voteRefundAddress(refundAccount, { from: boardOne }); - await privateFund.voteRefundAddress(refundAccount, { from: boardTwo }); - assert.equal((await privateFund.boardMembers(boardOne))[0], refundAccount); - assert.equal((await privateFund.boardMembers(boardTwo))[0], refundAccount); - }); - - it("does not allow non-contributors to vote", async () => { - await privateFund.contribute({ - from: funderAccount, - value: raiseGoal - }); - assertRevert(privateFund.voteRefundAddress(true, { from: funderAccount })); - }); - - // [BEGIN] refund - - // TODO - fix up - // it("refunds to voted refund address", async () => { - // const refundBalanceInit = await web3.eth.getBalance(refundAccount); - // - // await privateFund.contribute({ from: funderAccount, value: raiseGoal }); - // await privateFund.voteRefundAddress(refundAccount, { from: boardOne }); - // await privateFund.voteRefundAddress(refundAccount, { from: boardTwo }); - // await privateFund.voteRefundAddress(refundAccount, { from: boardThree }); - // await privateFund.refund(refundAccount, { from: boardTwo }); - // - // const refundBalancePostRefund = await web3.eth.getBalance(refundAccount); - // - // assert.ok(refundBalancePostRefund.gt(refundBalanceInit)); - // }); - // - // [END] refund -}); diff --git a/contract/test/utils.js b/contract/test/utils.js deleted file mode 100644 index 2b20fbd6..00000000 --- a/contract/test/utils.js +++ /dev/null @@ -1,65 +0,0 @@ -// source: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/test/helpers/increaseTime.js - -const should = require("chai").should(); - -async function assertRevert(promise) { - try { - await promise; - } catch (error) { - error.message.should.include( - "revert", - `Expected "revert", got ${error} instead` - ); - return; - } - should.fail("Expected revert not received"); -} - - -async function assertVMException(promise) { - try { - await promise; - } catch (error) { - error.message.should.include( - "VM Exception", - `Expected "VM Exception", got ${error} instead` - ); - return; - } - should.fail("Expected VM Exception not received"); -} - -async function increaseTime(duration) { - const id = Date.now(); - - return new Promise((resolve, reject) => { - web3.currentProvider.sendAsync( - { - jsonrpc: "2.0", - method: "evm_increaseTime", - params: [duration], - id: id - }, - err1 => { - if (err1) return reject(err1); - - web3.currentProvider.sendAsync( - { - jsonrpc: "2.0", - method: "evm_mine", - id: id + 1 - }, - (err2, res) => { - return err2 ? reject(err2) : resolve(res); - } - ); - } - ); - }); -} - -module.exports = { - assertRevert, - increaseTime, - assertVMException -}; \ No newline at end of file diff --git a/contract/truffle-config.js b/contract/truffle-config.js deleted file mode 100644 index 8497add2..00000000 --- a/contract/truffle-config.js +++ /dev/null @@ -1,108 +0,0 @@ -/** - * Use this file to configure your truffle project. It's seeded with some - * common settings for different networks and features like migrations, - * compilation and testing. Uncomment the ones you need or modify - * them to suit your project as necessary. - * - * More information about configuration can be found at: - * - * truffleframework.com/docs/advanced/configuration - * - * To deploy via Infura you'll need a wallet provider (like truffle-hdwallet-provider) - * to sign your transactions before they're sent to a remote public node. Infura API - * keys are available for free at: infura.io/register - * - * > > Using Truffle V5 or later? Make sure you install the `web3-one` version. - * - * > > $ npm install truffle-hdwallet-provider@web3-one - * - * You'll also need a mnemonic - the twelve word phrase the wallet uses to generate - * public/private key pairs. If you're publishing your code to GitHub make sure you load this - * phrase from a file you've .gitignored so it doesn't accidentally become public. - * - */ - -const HDWallet = require('truffle-hdwallet-provider'); -const infuraKey = process.env.INFURA_KEY; -// -// const fs = require('fs'); -const mnemonic = process.env.MNEMONIC; - -module.exports = { - /** - * Networks define how you connect to your ethereum client and let you set the - * defaults web3 uses to send transactions. If you don't specify one truffle - * will spin up a development blockchain for you on port 9545 when you - * run `develop` or `test`. You can ask a truffle command to use a specific - * network from the command line, e.g - * - * $ truffle test --network - */ - - networks: { - // Useful for testing. The `development` name is special - truffle uses it by default - // if it's defined here and no other network is specified at the command line. - // You should run a client (like ganache-cli, geth or parity) in a separate terminal - // tab if you use this network and you must also set the `host`, `port` and `network_id` - // options below to some value. - // - development: { - host: "127.0.0.1", // Localhost (default: none) - port: 8545, // Standard Ethereum port (default: none) - network_id: "*" // Any network (default: none) - }, - - // Another network with more advanced options... - advanced: { - // port: 8777, // Custom port - // network_id: 1342, // Custom network - // gas: 8500000, // Gas sent with each transaction (default: ~6700000) - // gasPrice: 20000000000, // 20 gwei (in wei) (default: 100 gwei) - // from:
, // Account to send txs from (default: accounts[0]) - // websockets: true // Enable EventEmitter interface for web3 (default: false) - }, - - // Useful for deploying to a public network. - // NB: It's important to wrap the provider as a function. - ropsten: { - provider: function () { return new HDWallet(mnemonic, 'https://ropsten.infura.io/' + infuraKey) }, - network_id: 3, // Ropsten's id - gas: 5500000, // Ropsten has a lower block limit than mainnet - gasPrice: 20, - confirmations: 2, // # of confs to wait between deployments. (default: 0) - timeoutBlocks: 200, // # of blocks before a deployment times out (minimum/default: 50) - skipDryRun: true // Skip dry run before migrations? (default: false for public nets ) - }, - - // Useful for private networks - private: { - // provider: () => new HDWalletProvider(mnemonic, `https://network.io`), - // network_id: 2111, // This network is yours, in the cloud. - // production: true // Treats this network as if it was a public net. (default: false) - } - }, - - // Set default mocha options here, use special reporters etc. - mocha: { - reporter: "eth-gas-reporter", - reporterOptions: { - currency: "USD", - gasPrice: 21 - } - }, - - // Configure your compilers - compilers: { - solc: { - // version: "0.5.1", // Fetch exact version from solc-bin (default: truffle's version) - // docker: true, // Use "0.5.1" you've installed locally with docker (default: false) - // settings: { // See the solidity docs for advice about optimization and evmVersion - // optimizer: { - // enabled: false, - // runs: 200 - // }, - // evmVersion: "byzantium" - // } - } - } -}; diff --git a/contract/yarn.lock b/contract/yarn.lock deleted file mode 100644 index 43f48aa1..00000000 --- a/contract/yarn.lock +++ /dev/null @@ -1,2888 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@types/concat-stream@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@types/concat-stream/-/concat-stream-1.6.0.tgz#394dbe0bb5fee46b38d896735e8b68ef2390d00d" - dependencies: - "@types/node" "*" - -"@types/form-data@0.0.33": - version "0.0.33" - resolved "https://registry.yarnpkg.com/@types/form-data/-/form-data-0.0.33.tgz#c9ac85b2a5fd18435b8c85d9ecb50e6d6c893ff8" - dependencies: - "@types/node" "*" - -"@types/node@*": - version "10.9.4" - resolved "https://registry.yarnpkg.com/@types/node/-/node-10.9.4.tgz#0f4cb2dc7c1de6096055357f70179043c33e9897" - -"@types/node@^8.0.0": - version "8.10.29" - resolved "https://registry.yarnpkg.com/@types/node/-/node-8.10.29.tgz#b3a13b58dd7b0682bf1b42022bef4a5a9718f687" - -"@types/node@^9.3.0", "@types/node@^9.4.1": - version "9.6.31" - resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.31.tgz#4d1722987f8d808b4c194dceb8c213bd92f028e5" - -"@types/qs@^6.2.31": - version "6.5.1" - resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.5.1.tgz#a38f69c62528d56ba7bd1f91335a8004988d72f7" - -abi-decoder@^1.0.8: - version "1.2.0" - resolved "https://registry.yarnpkg.com/abi-decoder/-/abi-decoder-1.2.0.tgz#c42882dbb91b444805f0cd203a87a5cc3c22f4a8" - dependencies: - web3 "^0.18.4" - -abstract-leveldown@~2.6.0: - version "2.6.3" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.6.3.tgz#1c5e8c6a5ef965ae8c35dfb3a8770c476b82c4b8" - dependencies: - xtend "~4.0.0" - -abstract-leveldown@~2.7.1: - version "2.7.2" - resolved "https://registry.yarnpkg.com/abstract-leveldown/-/abstract-leveldown-2.7.2.tgz#87a44d7ebebc341d59665204834c8b7e0932cc93" - dependencies: - xtend "~4.0.0" - -aes-js@^0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/aes-js/-/aes-js-0.2.4.tgz#94b881ab717286d015fa219e08fb66709dda5a3d" - -ajv@^5.3.0: - version "5.5.2" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-5.5.2.tgz#73b5eeca3fab653e3d3f9422b341ad42205dc965" - dependencies: - co "^4.6.0" - fast-deep-equal "^1.0.0" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.3.0" - -ansi-regex@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" - -ansi-regex@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" - -ansi-styles@^2.2.1: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" - -ansi-styles@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" - dependencies: - color-convert "^1.9.0" - -array-back@^1.0.3, array-back@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-1.0.4.tgz#644ba7f095f7ffcf7c43b5f0dc39d3c1f03c063b" - dependencies: - typical "^2.6.0" - -array-back@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/array-back/-/array-back-2.0.0.tgz#6877471d51ecc9c9bfa6136fb6c7d5fe69748022" - dependencies: - typical "^2.6.1" - -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - dependencies: - safer-buffer "~2.1.0" - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - -assertion-error@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" - -async-eventemitter@^0.2.2: - version "0.2.4" - resolved "https://registry.yarnpkg.com/async-eventemitter/-/async-eventemitter-0.2.4.tgz#f5e7c8ca7d3e46aab9ec40a292baf686a0bafaca" - dependencies: - async "^2.4.0" - -async-eventemitter@ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c: - version "0.2.3" - resolved "https://codeload.github.com/ahultgren/async-eventemitter/tar.gz/fa06e39e56786ba541c180061dbf2c0a5bbf951c" - dependencies: - async "^2.4.0" - -async-limiter@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.0.tgz#78faed8c3d074ab81f22b4e985d79e8738f720f8" - -async@^1.4.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/async/-/async-1.5.2.tgz#ec6a61ae56480c0c3cb241c95618e20892f9672a" - -async@^2.0.1, async@^2.1.2, async@^2.4.0, async@^2.5.0: - version "2.6.1" - resolved "https://registry.yarnpkg.com/async/-/async-2.6.1.tgz#b245a23ca71930044ec53fa46aa00a3e87c6a610" - dependencies: - lodash "^4.17.10" - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - -aws4@^1.8.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f" - -babel-code-frame@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" - dependencies: - chalk "^1.1.3" - esutils "^2.0.2" - js-tokens "^3.0.2" - -babel-core@^6.0.14, babel-core@^6.26.0: - version "6.26.3" - resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-6.26.3.tgz#b2e2f09e342d0f0c88e2f02e067794125e75c207" - dependencies: - babel-code-frame "^6.26.0" - babel-generator "^6.26.0" - babel-helpers "^6.24.1" - babel-messages "^6.23.0" - babel-register "^6.26.0" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - convert-source-map "^1.5.1" - debug "^2.6.9" - json5 "^0.5.1" - lodash "^4.17.4" - minimatch "^3.0.4" - path-is-absolute "^1.0.1" - private "^0.1.8" - slash "^1.0.0" - source-map "^0.5.7" - -babel-generator@^6.26.0: - version "6.26.1" - resolved "https://registry.yarnpkg.com/babel-generator/-/babel-generator-6.26.1.tgz#1844408d3b8f0d35a404ea7ac180f087a601bd90" - dependencies: - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - detect-indent "^4.0.0" - jsesc "^1.3.0" - lodash "^4.17.4" - source-map "^0.5.7" - trim-right "^1.0.1" - -babel-helper-builder-binary-assignment-operator-visitor@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-builder-binary-assignment-operator-visitor/-/babel-helper-builder-binary-assignment-operator-visitor-6.24.1.tgz#cce4517ada356f4220bcae8a02c2b346f9a56664" - dependencies: - babel-helper-explode-assignable-expression "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-call-delegate@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-call-delegate/-/babel-helper-call-delegate-6.24.1.tgz#ece6aacddc76e41c3461f88bfc575bd0daa2df8d" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-define-map@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-define-map/-/babel-helper-define-map-6.26.0.tgz#a5f56dab41a25f97ecb498c7ebaca9819f95be5f" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-explode-assignable-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-explode-assignable-expression/-/babel-helper-explode-assignable-expression-6.24.1.tgz#f25b82cf7dc10433c55f70592d5746400ac22caa" - dependencies: - babel-runtime "^6.22.0" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-function-name@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz#d3475b8c03ed98242a25b48351ab18399d3580a9" - dependencies: - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-get-function-arity@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz#8f7782aa93407c41d3aa50908f89b031b1b6853d" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-hoist-variables@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-hoist-variables/-/babel-helper-hoist-variables-6.24.1.tgz#1ecb27689c9d25513eadbc9914a73f5408be7a76" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-optimise-call-expression@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-optimise-call-expression/-/babel-helper-optimise-call-expression-6.24.1.tgz#f7a13427ba9f73f8f4fa993c54a97882d1244257" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-helper-regex@^6.24.1: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-helper-regex/-/babel-helper-regex-6.26.0.tgz#325c59f902f82f24b74faceed0363954f6495e72" - dependencies: - babel-runtime "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-helper-remap-async-to-generator@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-remap-async-to-generator/-/babel-helper-remap-async-to-generator-6.24.1.tgz#5ec581827ad723fecdd381f1c928390676e4551b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helper-replace-supers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helper-replace-supers/-/babel-helper-replace-supers-6.24.1.tgz#bf6dbfe43938d17369a213ca8a8bf74b6a90ab1a" - dependencies: - babel-helper-optimise-call-expression "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-helpers@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-helpers/-/babel-helpers-6.24.1.tgz#3471de9caec388e5c850e597e58a26ddf37602b2" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-messages@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-messages/-/babel-messages-6.23.0.tgz#f3cdf4703858035b2a2951c6ec5edf6c62f2630e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-check-es2015-constants@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-check-es2015-constants/-/babel-plugin-check-es2015-constants-6.22.0.tgz#35157b101426fd2ffd3da3f75c7d1e91835bbf8a" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-syntax-async-functions@^6.8.0: - version "6.13.0" - resolved "http://registry.npmjs.org/babel-plugin-syntax-async-functions/-/babel-plugin-syntax-async-functions-6.13.0.tgz#cad9cad1191b5ad634bf30ae0872391e0647be95" - -babel-plugin-syntax-exponentiation-operator@^6.8.0: - version "6.13.0" - resolved "http://registry.npmjs.org/babel-plugin-syntax-exponentiation-operator/-/babel-plugin-syntax-exponentiation-operator-6.13.0.tgz#9ee7e8337290da95288201a6a57f4170317830de" - -babel-plugin-syntax-trailing-function-commas@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-6.22.0.tgz#ba0360937f8d06e40180a43fe0d5616fff532cf3" - -babel-plugin-transform-async-to-generator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-async-to-generator/-/babel-plugin-transform-async-to-generator-6.24.1.tgz#6536e378aff6cb1d5517ac0e40eb3e9fc8d08761" - dependencies: - babel-helper-remap-async-to-generator "^6.24.1" - babel-plugin-syntax-async-functions "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-arrow-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-arrow-functions/-/babel-plugin-transform-es2015-arrow-functions-6.22.0.tgz#452692cb711d5f79dc7f85e440ce41b9f244d221" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoped-functions@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoped-functions/-/babel-plugin-transform-es2015-block-scoped-functions-6.22.0.tgz#bbc51b49f964d70cb8d8e0b94e820246ce3a6141" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-block-scoping@^6.23.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-block-scoping/-/babel-plugin-transform-es2015-block-scoping-6.26.0.tgz#d70f5299c1308d05c12f463813b0a09e73b1895f" - dependencies: - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - lodash "^4.17.4" - -babel-plugin-transform-es2015-classes@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-classes/-/babel-plugin-transform-es2015-classes-6.24.1.tgz#5a4c58a50c9c9461e564b4b2a3bfabc97a2584db" - dependencies: - babel-helper-define-map "^6.24.1" - babel-helper-function-name "^6.24.1" - babel-helper-optimise-call-expression "^6.24.1" - babel-helper-replace-supers "^6.24.1" - babel-messages "^6.23.0" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-computed-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-computed-properties/-/babel-plugin-transform-es2015-computed-properties-6.24.1.tgz#6fe2a8d16895d5634f4cd999b6d3480a308159b3" - dependencies: - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-destructuring@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-destructuring/-/babel-plugin-transform-es2015-destructuring-6.23.0.tgz#997bb1f1ab967f682d2b0876fe358d60e765c56d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-duplicate-keys@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-duplicate-keys/-/babel-plugin-transform-es2015-duplicate-keys-6.24.1.tgz#73eb3d310ca969e3ef9ec91c53741a6f1576423e" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-for-of@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-for-of/-/babel-plugin-transform-es2015-for-of-6.23.0.tgz#f47c95b2b613df1d3ecc2fdb7573623c75248691" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-function-name@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-function-name/-/babel-plugin-transform-es2015-function-name-6.24.1.tgz#834c89853bc36b1af0f3a4c5dbaa94fd8eacaa8b" - dependencies: - babel-helper-function-name "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-literals/-/babel-plugin-transform-es2015-literals-6.22.0.tgz#4f54a02d6cd66cf915280019a31d31925377ca2e" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-modules-amd@^6.22.0, babel-plugin-transform-es2015-modules-amd@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-amd/-/babel-plugin-transform-es2015-modules-amd-6.24.1.tgz#3b3e54017239842d6d19c3011c4bd2f00a00d154" - dependencies: - babel-plugin-transform-es2015-modules-commonjs "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-commonjs@^6.23.0, babel-plugin-transform-es2015-modules-commonjs@^6.24.1: - version "6.26.2" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-commonjs/-/babel-plugin-transform-es2015-modules-commonjs-6.26.2.tgz#58a793863a9e7ca870bdc5a881117ffac27db6f3" - dependencies: - babel-plugin-transform-strict-mode "^6.24.1" - babel-runtime "^6.26.0" - babel-template "^6.26.0" - babel-types "^6.26.0" - -babel-plugin-transform-es2015-modules-systemjs@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-systemjs/-/babel-plugin-transform-es2015-modules-systemjs-6.24.1.tgz#ff89a142b9119a906195f5f106ecf305d9407d23" - dependencies: - babel-helper-hoist-variables "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-modules-umd@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-modules-umd/-/babel-plugin-transform-es2015-modules-umd-6.24.1.tgz#ac997e6285cd18ed6176adb607d602344ad38468" - dependencies: - babel-plugin-transform-es2015-modules-amd "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - -babel-plugin-transform-es2015-object-super@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-object-super/-/babel-plugin-transform-es2015-object-super-6.24.1.tgz#24cef69ae21cb83a7f8603dad021f572eb278f8d" - dependencies: - babel-helper-replace-supers "^6.24.1" - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-parameters@^6.23.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-parameters/-/babel-plugin-transform-es2015-parameters-6.24.1.tgz#57ac351ab49caf14a97cd13b09f66fdf0a625f2b" - dependencies: - babel-helper-call-delegate "^6.24.1" - babel-helper-get-function-arity "^6.24.1" - babel-runtime "^6.22.0" - babel-template "^6.24.1" - babel-traverse "^6.24.1" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-shorthand-properties@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-shorthand-properties/-/babel-plugin-transform-es2015-shorthand-properties-6.24.1.tgz#24f875d6721c87661bbd99a4622e51f14de38aa0" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-spread@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-spread/-/babel-plugin-transform-es2015-spread-6.22.0.tgz#d6d68a99f89aedc4536c81a542e8dd9f1746f8d1" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-sticky-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-sticky-regex/-/babel-plugin-transform-es2015-sticky-regex-6.24.1.tgz#00c1cdb1aca71112cdf0cf6126c2ed6b457ccdbc" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-plugin-transform-es2015-template-literals@^6.22.0: - version "6.22.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-template-literals/-/babel-plugin-transform-es2015-template-literals-6.22.0.tgz#a84b3450f7e9f8f1f6839d6d687da84bb1236d8d" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-typeof-symbol@^6.23.0: - version "6.23.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-typeof-symbol/-/babel-plugin-transform-es2015-typeof-symbol-6.23.0.tgz#dec09f1cddff94b52ac73d505c84df59dcceb372" - dependencies: - babel-runtime "^6.22.0" - -babel-plugin-transform-es2015-unicode-regex@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-es2015-unicode-regex/-/babel-plugin-transform-es2015-unicode-regex-6.24.1.tgz#d38b12f42ea7323f729387f18a7c5ae1faeb35e9" - dependencies: - babel-helper-regex "^6.24.1" - babel-runtime "^6.22.0" - regexpu-core "^2.0.0" - -babel-plugin-transform-exponentiation-operator@^6.22.0: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-exponentiation-operator/-/babel-plugin-transform-exponentiation-operator-6.24.1.tgz#2ab0c9c7f3098fa48907772bb813fe41e8de3a0e" - dependencies: - babel-helper-builder-binary-assignment-operator-visitor "^6.24.1" - babel-plugin-syntax-exponentiation-operator "^6.8.0" - babel-runtime "^6.22.0" - -babel-plugin-transform-regenerator@^6.22.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-regenerator/-/babel-plugin-transform-regenerator-6.26.0.tgz#e0703696fbde27f0a3efcacf8b4dca2f7b3a8f2f" - dependencies: - regenerator-transform "^0.10.0" - -babel-plugin-transform-strict-mode@^6.24.1: - version "6.24.1" - resolved "https://registry.yarnpkg.com/babel-plugin-transform-strict-mode/-/babel-plugin-transform-strict-mode-6.24.1.tgz#d5faf7aa578a65bbe591cf5edae04a0c67020758" - dependencies: - babel-runtime "^6.22.0" - babel-types "^6.24.1" - -babel-preset-env@^1.3.2: - version "1.7.0" - resolved "https://registry.yarnpkg.com/babel-preset-env/-/babel-preset-env-1.7.0.tgz#dea79fa4ebeb883cd35dab07e260c1c9c04df77a" - dependencies: - babel-plugin-check-es2015-constants "^6.22.0" - babel-plugin-syntax-trailing-function-commas "^6.22.0" - babel-plugin-transform-async-to-generator "^6.22.0" - babel-plugin-transform-es2015-arrow-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoped-functions "^6.22.0" - babel-plugin-transform-es2015-block-scoping "^6.23.0" - babel-plugin-transform-es2015-classes "^6.23.0" - babel-plugin-transform-es2015-computed-properties "^6.22.0" - babel-plugin-transform-es2015-destructuring "^6.23.0" - babel-plugin-transform-es2015-duplicate-keys "^6.22.0" - babel-plugin-transform-es2015-for-of "^6.23.0" - babel-plugin-transform-es2015-function-name "^6.22.0" - babel-plugin-transform-es2015-literals "^6.22.0" - babel-plugin-transform-es2015-modules-amd "^6.22.0" - babel-plugin-transform-es2015-modules-commonjs "^6.23.0" - babel-plugin-transform-es2015-modules-systemjs "^6.23.0" - babel-plugin-transform-es2015-modules-umd "^6.23.0" - babel-plugin-transform-es2015-object-super "^6.22.0" - babel-plugin-transform-es2015-parameters "^6.23.0" - babel-plugin-transform-es2015-shorthand-properties "^6.22.0" - babel-plugin-transform-es2015-spread "^6.22.0" - babel-plugin-transform-es2015-sticky-regex "^6.22.0" - babel-plugin-transform-es2015-template-literals "^6.22.0" - babel-plugin-transform-es2015-typeof-symbol "^6.23.0" - babel-plugin-transform-es2015-unicode-regex "^6.22.0" - babel-plugin-transform-exponentiation-operator "^6.22.0" - babel-plugin-transform-regenerator "^6.22.0" - browserslist "^3.2.6" - invariant "^2.2.2" - semver "^5.3.0" - -babel-register@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-register/-/babel-register-6.26.0.tgz#6ed021173e2fcb486d7acb45c6009a856f647071" - dependencies: - babel-core "^6.26.0" - babel-runtime "^6.26.0" - core-js "^2.5.0" - home-or-tmp "^2.0.0" - lodash "^4.17.4" - mkdirp "^0.5.1" - source-map-support "^0.4.15" - -babel-runtime@^6.18.0, babel-runtime@^6.22.0, babel-runtime@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" - dependencies: - core-js "^2.4.0" - regenerator-runtime "^0.11.0" - -babel-template@^6.24.1, babel-template@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-template/-/babel-template-6.26.0.tgz#de03e2d16396b069f46dd9fff8521fb1a0e35e02" - dependencies: - babel-runtime "^6.26.0" - babel-traverse "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - lodash "^4.17.4" - -babel-traverse@^6.24.1, babel-traverse@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.26.0.tgz#46a9cbd7edcc62c8e5c064e2d2d8d0f4035766ee" - dependencies: - babel-code-frame "^6.26.0" - babel-messages "^6.23.0" - babel-runtime "^6.26.0" - babel-types "^6.26.0" - babylon "^6.18.0" - debug "^2.6.8" - globals "^9.18.0" - invariant "^2.2.2" - lodash "^4.17.4" - -babel-types@^6.19.0, babel-types@^6.24.1, babel-types@^6.26.0: - version "6.26.0" - resolved "https://registry.yarnpkg.com/babel-types/-/babel-types-6.26.0.tgz#a3b073f94ab49eb6fa55cd65227a334380632497" - dependencies: - babel-runtime "^6.26.0" - esutils "^2.0.2" - lodash "^4.17.4" - to-fast-properties "^1.0.3" - -babelify@^7.3.0: - version "7.3.0" - resolved "http://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz#aa56aede7067fd7bd549666ee16dc285087e88e5" - dependencies: - babel-core "^6.0.14" - object-assign "^4.0.0" - -babylon@^6.18.0: - version "6.18.0" - resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.18.0.tgz#af2f3b88fa6f5c1e4c634d1a0f8eac4f55b395e3" - -backoff@^2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f" - dependencies: - precond "0.2" - -balanced-match@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base-x@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-1.1.0.tgz#42d3d717474f9ea02207f6d1aa1f426913eeb7ac" - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - dependencies: - tweetnacl "^0.14.3" - -"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2": - version "2.0.7" - resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" - -bindings@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" - -bip39@^2.2.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/bip39/-/bip39-2.5.0.tgz#51cbd5179460504a63ea3c000db3f787ca051235" - dependencies: - create-hash "^1.1.0" - pbkdf2 "^3.0.9" - randombytes "^2.0.1" - safe-buffer "^5.0.1" - unorm "^1.3.3" - -bip66@^1.1.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - dependencies: - safe-buffer "^5.0.1" - -bn.js@^4.10.0, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.8, bn.js@^4.4.0, bn.js@^4.8.0: - version "4.11.8" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" - -brace-expansion@^1.1.7: - version "1.1.11" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" - dependencies: - balanced-match "^1.0.0" - concat-map "0.0.1" - -brorand@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" - -browser-stdout@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.0.tgz#f351d32969d32fa5d7a5567154263d928ae3bd1f" - -browserify-aes@^1.0.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - -browserify-sha3@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" - dependencies: - js-sha3 "^0.3.1" - -browserslist@^3.2.6: - version "3.2.8" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-3.2.8.tgz#b0005361d6471f0f5952797a76fc985f1f978fc6" - dependencies: - caniuse-lite "^1.0.30000844" - electron-to-chromium "^1.3.47" - -bs58@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - -bs58@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-3.1.0.tgz#d4c26388bf4804cac714141b1945aa47e5eb248e" - dependencies: - base-x "^1.1.0" - -bs58check@^1.0.8: - version "1.3.4" - resolved "https://registry.yarnpkg.com/bs58check/-/bs58check-1.3.4.tgz#c52540073749117714fa042c3047eb8f9151cbf8" - dependencies: - bs58 "^3.1.0" - create-hash "^1.1.0" - -buffer-from@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" - -buffer-xor@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" - -builtin-modules@^1.0.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" - -camelcase@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-3.0.0.tgz#32fc4b9fcdaf845fcdf7e73bb97cac2261f0ab0a" - -caniuse-lite@^1.0.30000844: - version "1.0.30000885" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30000885.tgz#e889e9f8e7e50e769f2a49634c932b8aee622984" - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - -chai@^4.1.2: - version "4.1.2" - resolved "https://registry.yarnpkg.com/chai/-/chai-4.1.2.tgz#0f64584ba642f0f2ace2806279f4f06ca23ad73c" - dependencies: - assertion-error "^1.0.1" - check-error "^1.0.1" - deep-eql "^3.0.0" - get-func-name "^2.0.0" - pathval "^1.0.0" - type-detect "^4.0.0" - -chalk@^1.1.3: - version "1.1.3" - resolved "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" - dependencies: - ansi-styles "^2.2.1" - escape-string-regexp "^1.0.2" - has-ansi "^2.0.0" - strip-ansi "^3.0.0" - supports-color "^2.0.0" - -chalk@^2.3.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.1.tgz#18c49ab16a037b6eb0152cc83e3471338215b66e" - dependencies: - ansi-styles "^3.2.1" - escape-string-regexp "^1.0.5" - supports-color "^5.3.0" - -check-error@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" - -checkpoint-store@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/checkpoint-store/-/checkpoint-store-1.1.0.tgz#04e4cb516b91433893581e6d4601a78e9552ea06" - dependencies: - functional-red-black-tree "^1.0.1" - -cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -cli-table3@^0.5.0: - version "0.5.1" - resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" - dependencies: - object-assign "^4.1.0" - string-width "^2.1.1" - optionalDependencies: - colors "^1.1.2" - -cliui@^3.2.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - wrap-ansi "^2.0.0" - -clone@^2.0.0, clone@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" - -co@^4.6.0: - version "4.6.0" - resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" - -code-point-at@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -coinstring@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - dependencies: - bs58 "^2.0.1" - create-hash "^1.1.1" - -color-convert@^1.9.0: - version "1.9.3" - resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" - dependencies: - color-name "1.1.3" - -color-name@1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" - -colors@^1.1.2: - version "1.3.2" - resolved "https://registry.yarnpkg.com/colors/-/colors-1.3.2.tgz#2df8ff573dfbf255af562f8ce7181d6b971a359b" - -combined-stream@1.0.6, combined-stream@~1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.6.tgz#723e7df6e801ac5613113a7e445a9b69cb632818" - dependencies: - delayed-stream "~1.0.0" - -command-line-args@^4.0.7: - version "4.0.7" - resolved "https://registry.yarnpkg.com/command-line-args/-/command-line-args-4.0.7.tgz#f8d1916ecb90e9e121eda6428e41300bfb64cc46" - dependencies: - array-back "^2.0.0" - find-replace "^1.0.3" - typical "^2.6.1" - -commander@2.11.0: - version "2.11.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" - -concat-map@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" - -concat-stream@^1.4.6, concat-stream@^1.5.1, concat-stream@^1.6.0: - version "1.6.2" - resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" - dependencies: - buffer-from "^1.0.0" - inherits "^2.0.3" - readable-stream "^2.2.2" - typedarray "^0.0.6" - -convert-source-map@^1.5.1: - version "1.6.0" - resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.6.0.tgz#51b537a8c43e0f04dec1993bffcdd504e758ac20" - dependencies: - safe-buffer "~5.1.1" - -core-js@^2.4.0, core-js@^2.5.0: - version "2.5.7" - resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.5.7.tgz#f972608ff0cead68b841a16a932d0b183791814e" - -core-util-is@1.0.2, core-util-is@~1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - -create-hash@^1.1.0, create-hash@^1.1.1, create-hash@^1.1.2: - version "1.2.0" - resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - -create-hmac@^1.1.4: - version "1.1.7" - resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" - dependencies: - cipher-base "^1.0.3" - create-hash "^1.1.0" - inherits "^2.0.1" - ripemd160 "^2.0.0" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -cross-fetch@^2.1.0, cross-fetch@^2.1.1: - version "2.2.2" - resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.2.2.tgz#a47ff4f7fc712daba8f6a695a11c948440d45723" - dependencies: - node-fetch "2.1.2" - whatwg-fetch "2.0.4" - -crypto-js@^3.1.4: - version "3.1.8" - resolved "https://registry.yarnpkg.com/crypto-js/-/crypto-js-3.1.8.tgz#715f070bf6014f2ae992a98b3929258b713f08d5" - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - dependencies: - assert-plus "^1.0.0" - -debug@3.1.0, debug@^3.0.1: - version "3.1.0" - resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261" - dependencies: - ms "2.0.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" - dependencies: - ms "2.0.0" - -decamelize@^1.1.1: - version "1.2.0" - resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" - -deep-eql@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-3.0.1.tgz#dfc9404400ad1c8fe023e7da1df1c147c4b444df" - dependencies: - type-detect "^4.0.0" - -deep-equal@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" - -deferred-leveldown@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/deferred-leveldown/-/deferred-leveldown-1.2.2.tgz#3acd2e0b75d1669924bc0a4b642851131173e1eb" - dependencies: - abstract-leveldown "~2.6.0" - -define-properties@^1.1.2: - version "1.1.3" - resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" - dependencies: - object-keys "^1.0.12" - -defined@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - -detect-indent@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/detect-indent/-/detect-indent-4.0.0.tgz#f76d064352cdf43a1cb6ce619c4ee3a9475de208" - dependencies: - repeating "^2.0.0" - -diff@3.3.1: - version "3.3.1" - resolved "https://registry.yarnpkg.com/diff/-/diff-3.3.1.tgz#aa8567a6eed03c531fc89d3f711cd0e5259dec75" - -dom-walk@^0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" - -drbg.js@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - dependencies: - browserify-aes "^1.0.6" - create-hash "^1.1.2" - create-hmac "^1.1.4" - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -electron-to-chromium@^1.3.47: - version "1.3.64" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.64.tgz#39f5a93bf84ab7e10cfbb7522ccfc3f1feb756cf" - -elliptic@^6.2.3: - version "6.4.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - -encoding@^0.1.11: - version "0.1.12" - resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb" - dependencies: - iconv-lite "~0.4.13" - -end-of-stream@^1.1.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.1.tgz#ed29634d19baba463b6ce6b80a37213eab71ec43" - dependencies: - once "^1.4.0" - -errno@~0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" - dependencies: - prr "~1.0.1" - -error-ex@^1.2.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" - dependencies: - is-arrayish "^0.2.1" - -es-abstract@^1.5.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.12.0.tgz#9dbbdd27c6856f0001421ca18782d786bf8a6165" - dependencies: - es-to-primitive "^1.1.1" - function-bind "^1.1.1" - has "^1.0.1" - is-callable "^1.1.3" - is-regex "^1.0.4" - -es-to-primitive@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.1.1.tgz#45355248a88979034b6792e19bb81f2b7975dd0d" - dependencies: - is-callable "^1.1.1" - is-date-object "^1.0.1" - is-symbol "^1.0.1" - -escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" - -esutils@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" - -eth-block-tracker@^2.2.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-2.3.1.tgz#ab6d177e5b50128fa06d7ae9e0489c7484bac95e" - dependencies: - async-eventemitter ahultgren/async-eventemitter#fa06e39e56786ba541c180061dbf2c0a5bbf951c - eth-query "^2.1.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.3" - ethjs-util "^0.1.3" - json-rpc-engine "^3.6.0" - pify "^2.3.0" - tape "^4.6.3" - -eth-block-tracker@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/eth-block-tracker/-/eth-block-tracker-3.0.1.tgz#95cd5e763c7293e0b1b2790a2a39ac2ac188a5e1" - dependencies: - eth-query "^2.1.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.3" - ethjs-util "^0.1.3" - json-rpc-engine "^3.6.0" - pify "^2.3.0" - tape "^4.6.3" - -eth-gas-reporter@^0.1.10: - version "0.1.10" - resolved "https://registry.yarnpkg.com/eth-gas-reporter/-/eth-gas-reporter-0.1.10.tgz#6ac24958f0e018d4729902e802dc8449e8a5ff72" - dependencies: - abi-decoder "^1.0.8" - cli-table3 "^0.5.0" - colors "^1.1.2" - lodash "^4.17.4" - mocha "^4.1.0" - req-cwd "^2.0.0" - request "^2.83.0" - request-promise-native "^1.0.5" - shelljs "^0.7.8" - solidity-parser-antlr "^0.2.10" - sync-request "^6.0.0" - -eth-json-rpc-infura@^3.1.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/eth-json-rpc-infura/-/eth-json-rpc-infura-3.1.2.tgz#04c5d0cee98619e93ba8a9842492b771b316e83a" - dependencies: - cross-fetch "^2.1.1" - eth-json-rpc-middleware "^1.5.0" - json-rpc-engine "^3.4.0" - json-rpc-error "^2.0.0" - tape "^4.8.0" - -eth-json-rpc-middleware@^1.5.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/eth-json-rpc-middleware/-/eth-json-rpc-middleware-1.6.0.tgz#5c9d4c28f745ccb01630f0300ba945f4bef9593f" - dependencies: - async "^2.5.0" - eth-query "^2.1.2" - eth-tx-summary "^3.1.2" - ethereumjs-block "^1.6.0" - ethereumjs-tx "^1.3.3" - ethereumjs-util "^5.1.2" - ethereumjs-vm "^2.1.0" - fetch-ponyfill "^4.0.0" - json-rpc-engine "^3.6.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - tape "^4.6.3" - -eth-query@^2.0.2, eth-query@^2.1.0, eth-query@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/eth-query/-/eth-query-2.1.2.tgz#d6741d9000106b51510c72db92d6365456a6da5e" - dependencies: - json-rpc-random-id "^1.0.0" - xtend "^4.0.1" - -eth-sig-util@^1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-1.4.2.tgz#8d958202c7edbaae839707fba6f09ff327606210" - dependencies: - ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" - ethereumjs-util "^5.1.1" - -eth-tx-summary@^3.1.2: - version "3.2.3" - resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.3.tgz#a52d7215616888e012fbc083b3eacd28f3e64764" - dependencies: - async "^2.1.2" - bn.js "^4.11.8" - clone "^2.0.0" - concat-stream "^1.5.1" - end-of-stream "^1.1.0" - eth-query "^2.0.2" - ethereumjs-block "^1.4.1" - ethereumjs-tx "^1.1.1" - ethereumjs-util "^5.0.1" - ethereumjs-vm "2.3.4" - through2 "^2.0.3" - treeify "^1.0.1" - web3-provider-engine "^13.3.2" - -ethereum-common@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.2.0.tgz#13bf966131cce1eeade62a1b434249bb4cb120ca" - -ethereum-common@^0.0.18: - version "0.0.18" - resolved "https://registry.yarnpkg.com/ethereum-common/-/ethereum-common-0.0.18.tgz#2fdc3576f232903358976eb39da783213ff9523f" - -"ethereumjs-abi@git+https://github.com/ethereumjs/ethereumjs-abi.git": - version "0.6.5" - resolved "git+https://github.com/ethereumjs/ethereumjs-abi.git#00ba8463a7f7a67fcad737ff9c2ebd95643427f7" - dependencies: - bn.js "^4.10.0" - ethereumjs-util "^5.0.0" - -ethereumjs-account@^2.0.3: - version "2.0.5" - resolved "https://registry.yarnpkg.com/ethereumjs-account/-/ethereumjs-account-2.0.5.tgz#eeafc62de544cb07b0ee44b10f572c9c49e00a84" - dependencies: - ethereumjs-util "^5.0.0" - rlp "^2.0.0" - safe-buffer "^5.1.1" - -ethereumjs-block@^1.2.2, ethereumjs-block@^1.4.1, ethereumjs-block@^1.6.0, ethereumjs-block@~1.7.0: - version "1.7.1" - resolved "https://registry.yarnpkg.com/ethereumjs-block/-/ethereumjs-block-1.7.1.tgz#78b88e6cc56de29a6b4884ee75379b6860333c3f" - dependencies: - async "^2.0.1" - ethereum-common "0.2.0" - ethereumjs-tx "^1.2.2" - ethereumjs-util "^5.0.0" - merkle-patricia-tree "^2.1.2" - -ethereumjs-common@~0.4.0: - version "0.4.1" - resolved "https://registry.yarnpkg.com/ethereumjs-common/-/ethereumjs-common-0.4.1.tgz#27690a24a817b058cc3a2aedef9392e8d7d63984" - -ethereumjs-tx@^1.1.1, ethereumjs-tx@^1.2.0, ethereumjs-tx@^1.2.2, ethereumjs-tx@^1.3.3: - version "1.3.7" - resolved "https://registry.yarnpkg.com/ethereumjs-tx/-/ethereumjs-tx-1.3.7.tgz#88323a2d875b10549b8347e09f4862b546f3d89a" - dependencies: - ethereum-common "^0.0.18" - ethereumjs-util "^5.0.0" - -ethereumjs-util@^4.4.0: - version "4.5.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-4.5.0.tgz#3e9428b317eebda3d7260d854fddda954b1f1bc6" - dependencies: - bn.js "^4.8.0" - create-hash "^1.1.2" - keccakjs "^0.2.0" - rlp "^2.0.0" - secp256k1 "^3.0.1" - -ethereumjs-util@^5.0.0, ethereumjs-util@^5.0.1, ethereumjs-util@^5.1.1, ethereumjs-util@^5.1.2, ethereumjs-util@^5.1.3, ethereumjs-util@^5.1.5, ethereumjs-util@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - ethjs-util "^0.1.3" - keccak "^1.0.2" - rlp "^2.0.0" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - -ethereumjs-vm@2.3.4: - version "2.3.4" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.3.4.tgz#f635d7cb047571a1840a6e9a74d29de4488f8ad6" - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereum-common "0.2.0" - ethereumjs-account "^2.0.3" - ethereumjs-block "~1.7.0" - ethereumjs-util "^5.1.3" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.1.2" - rustbn.js "~0.1.1" - safe-buffer "^5.1.1" - -ethereumjs-vm@^2.0.2, ethereumjs-vm@^2.1.0, ethereumjs-vm@^2.3.4: - version "2.4.0" - resolved "https://registry.yarnpkg.com/ethereumjs-vm/-/ethereumjs-vm-2.4.0.tgz#244f1e35f2755e537a13546111d1a4c159d34b13" - dependencies: - async "^2.1.2" - async-eventemitter "^0.2.2" - ethereumjs-account "^2.0.3" - ethereumjs-block "~1.7.0" - ethereumjs-common "~0.4.0" - ethereumjs-util "^5.2.0" - fake-merkle-patricia-tree "^1.0.1" - functional-red-black-tree "^1.0.1" - merkle-patricia-tree "^2.1.2" - rustbn.js "~0.2.0" - safe-buffer "^5.1.1" - -ethereumjs-wallet@0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/ethereumjs-wallet/-/ethereumjs-wallet-0.6.0.tgz#82763b1697ee7a796be7155da9dfb49b2f98cfdb" - dependencies: - aes-js "^0.2.3" - bs58check "^1.0.8" - ethereumjs-util "^4.4.0" - hdkey "^0.7.0" - scrypt.js "^0.2.0" - utf8 "^2.1.1" - uuid "^2.0.1" - -ethjs-util@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - -evp_bytestokey@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" - dependencies: - md5.js "^1.3.4" - safe-buffer "^5.1.1" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - -fake-merkle-patricia-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/fake-merkle-patricia-tree/-/fake-merkle-patricia-tree-1.0.1.tgz#4b8c3acfb520afadf9860b1f14cd8ce3402cddd3" - dependencies: - checkpoint-store "^1.1.0" - -fast-deep-equal@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz#c053477817c86b51daa853c81e059b733d023614" - -fast-json-stable-stringify@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2" - -fetch-ponyfill@^4.0.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/fetch-ponyfill/-/fetch-ponyfill-4.1.0.tgz#ae3ce5f732c645eab87e4ae8793414709b239893" - dependencies: - node-fetch "~1.7.1" - -find-replace@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" - dependencies: - array-back "^1.0.4" - test-value "^2.1.0" - -find-up@^1.0.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" - dependencies: - path-exists "^2.0.0" - pinkie-promise "^2.0.0" - -for-each@^0.3.2, for-each@~0.3.3: - version "0.3.3" - resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" - dependencies: - is-callable "^1.1.3" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - -form-data@^2.2.0, form-data@~2.3.2: - version "2.3.2" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.2.tgz#4970498be604c20c005d4f5c23aecd21d6b49099" - dependencies: - asynckit "^0.4.0" - combined-stream "1.0.6" - mime-types "^2.1.12" - -fs-extra@^0.30.0: - version "0.30.0" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-0.30.0.tgz#f233ffcc08d4da7d432daa449776989db1df93f0" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - klaw "^1.0.0" - path-is-absolute "^1.0.0" - rimraf "^2.2.8" - -fs-extra@^4.0.2: - version "4.0.3" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-4.0.3.tgz#0d852122e5bc5beb453fb028e9c0c9bf36340c94" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^4.0.0" - universalify "^0.1.0" - -fs.realpath@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" - -function-bind@^1.0.2, function-bind@^1.1.1, function-bind@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - -functional-red-black-tree@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" - -get-caller-file@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" - -get-func-name@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" - -get-port@^3.1.0: - version "3.2.0" - resolved "https://registry.yarnpkg.com/get-port/-/get-port-3.2.0.tgz#dd7ce7de187c06c8bf353796ac71e099f0980ebc" - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - dependencies: - assert-plus "^1.0.0" - -glob@7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -glob@^7.0.0, glob@^7.0.5, glob@^7.1.2, glob@~7.1.2: - version "7.1.3" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" - dependencies: - fs.realpath "^1.0.0" - inflight "^1.0.4" - inherits "2" - minimatch "^3.0.4" - once "^1.3.0" - path-is-absolute "^1.0.0" - -global@~4.3.0: - version "4.3.2" - resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f" - dependencies: - min-document "^2.19.0" - process "~0.5.1" - -globals@^9.18.0: - version "9.18.0" - resolved "https://registry.yarnpkg.com/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" - -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - -growl@1.10.3: - version "1.10.3" - resolved "https://registry.yarnpkg.com/growl/-/growl-1.10.3.tgz#1926ba90cf3edfe2adb4927f5880bc22c66c790f" - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - -har-validator@~5.1.0: - version "5.1.0" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.0.tgz#44657f5688a22cfd4b72486e81b3a3fb11742c29" - dependencies: - ajv "^5.3.0" - har-schema "^2.0.0" - -has-ansi@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" - dependencies: - ansi-regex "^2.0.0" - -has-flag@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" - -has-flag@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" - -has@^1.0.1, has@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - dependencies: - function-bind "^1.1.1" - -hash-base@^3.0.0: - version "3.0.4" - resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -hash.js@^1.0.0, hash.js@^1.0.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.5.tgz#e38ab4b85dfb1e0c40fe9265c0e9b54854c23812" - dependencies: - inherits "^2.0.3" - minimalistic-assert "^1.0.1" - -hdkey@^0.7.0: - version "0.7.1" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-0.7.1.tgz#caee4be81aa77921e909b8d228dd0f29acaee632" - dependencies: - coinstring "^2.0.0" - secp256k1 "^3.0.1" - -he@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" - -hmac-drbg@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" - dependencies: - hash.js "^1.0.3" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.1" - -home-or-tmp@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" - dependencies: - os-homedir "^1.0.0" - os-tmpdir "^1.0.1" - -hosted-git-info@^2.1.4: - version "2.7.1" - resolved "https://registry.yarnpkg.com/hosted-git-info/-/hosted-git-info-2.7.1.tgz#97f236977bd6e125408930ff6de3eec6281ec047" - -http-basic@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/http-basic/-/http-basic-7.0.0.tgz#82f0a506be942732ec8deebee80e746ef5736dba" - dependencies: - "@types/concat-stream" "^1.6.0" - "@types/node" "^9.4.1" - caseless "~0.12.0" - concat-stream "^1.4.6" - http-response-object "^3.0.1" - parse-cache-control "^1.0.1" - -http-response-object@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/http-response-object/-/http-response-object-3.0.1.tgz#90174d44c27b5e797cf6efe51a043bc889ae64bf" - dependencies: - "@types/node" "^9.3.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -iconv-lite@~0.4.13: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - dependencies: - safer-buffer ">= 2.1.2 < 3" - -immediate@^3.2.3: - version "3.2.3" - resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" - -inflight@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" - dependencies: - once "^1.3.0" - wrappy "1" - -inherits@2, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - -interpret@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.1.0.tgz#7ed1b1410c6a0e0f78cf95d3b8440c63f78b8614" - -invariant@^2.2.2: - version "2.2.4" - resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" - dependencies: - loose-envify "^1.0.0" - -invert-kv@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-1.0.0.tgz#104a8e4aaca6d3d8cd157a8ef8bfab2d7a3ffdb6" - -is-arrayish@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" - -is-builtin-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-builtin-module/-/is-builtin-module-1.0.0.tgz#540572d34f7ac3119f8f76c30cbc1b1e037affbe" - dependencies: - builtin-modules "^1.0.0" - -is-callable@^1.1.1, is-callable@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75" - -is-date-object@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16" - -is-finite@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finite/-/is-finite-1.0.2.tgz#cc6677695602be550ef11e8b4aa6305342b6d0aa" - dependencies: - number-is-nan "^1.0.0" - -is-fn@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fn/-/is-fn-1.0.0.tgz#9543d5de7bcf5b08a22ec8a20bae6e286d510d8c" - -is-fullwidth-code-point@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" - dependencies: - number-is-nan "^1.0.0" - -is-fullwidth-code-point@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" - -is-function@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5" - -is-hex-prefixed@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - -is-regex@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491" - dependencies: - has "^1.0.1" - -is-stream@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" - -is-symbol@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - -is-utf8@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/is-utf8/-/is-utf8-0.2.1.tgz#4b0da1442104d1b336340e80797e865cf39f7d72" - -isarray@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - -isarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - -js-sha3@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" - -"js-tokens@^3.0.0 || ^4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" - -js-tokens@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - -jsesc@^1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-1.3.0.tgz#46c3fec8c1892b12b0833db9bc7622176dbab34b" - -jsesc@~0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" - -json-rpc-engine@^3.4.0, json-rpc-engine@^3.6.0: - version "3.7.3" - resolved "https://registry.yarnpkg.com/json-rpc-engine/-/json-rpc-engine-3.7.3.tgz#81dcabdb4f1ba5f79f99f04f560d20817908e4b5" - dependencies: - async "^2.0.1" - babel-preset-env "^1.3.2" - babelify "^7.3.0" - clone "^2.1.1" - json-rpc-error "^2.0.0" - promise-to-callback "^1.0.0" - -json-rpc-error@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/json-rpc-error/-/json-rpc-error-2.0.0.tgz#a7af9c202838b5e905c7250e547f1aff77258a02" - dependencies: - inherits "^2.0.1" - -json-rpc-random-id@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-rpc-random-id/-/json-rpc-random-id-1.0.1.tgz#ba49d96aded1444dbb8da3d203748acbbcdec8c8" - -json-schema-traverse@^0.3.0: - version "0.3.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz#349a6d44c53a51de89b40805c5d5e59b417d3340" - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - -json-stable-stringify@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/json-stable-stringify/-/json-stable-stringify-1.0.1.tgz#9a759d39c5f2ff503fd5300646ed445f88c4f9af" - dependencies: - jsonify "~0.0.0" - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - -json5@^0.5.1: - version "0.5.1" - resolved "https://registry.yarnpkg.com/json5/-/json5-0.5.1.tgz#1eade7acc012034ad84e2396767ead9fa5495821" - -jsonfile@^2.1.0: - version "2.4.0" - resolved "http://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonfile@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" - optionalDependencies: - graceful-fs "^4.1.6" - -jsonify@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/jsonify/-/jsonify-0.0.0.tgz#2c74b6ee41d93ca51b7b5aaee8f503631d252a73" - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -keccak@^1.0.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" - dependencies: - bindings "^1.2.1" - inherits "^2.0.3" - nan "^2.2.1" - safe-buffer "^5.1.0" - -keccakjs@^0.2.0: - version "0.2.1" - resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" - dependencies: - browserify-sha3 "^0.0.1" - sha3 "^1.1.0" - -klaw@^1.0.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/klaw/-/klaw-1.3.1.tgz#4088433b46b3b1ba259d78785d8e96f73ba02439" - optionalDependencies: - graceful-fs "^4.1.9" - -lcid@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/lcid/-/lcid-1.0.0.tgz#308accafa0bc483a3867b4b6f2b9506251d1b835" - dependencies: - invert-kv "^1.0.0" - -level-codec@~7.0.0: - version "7.0.1" - resolved "https://registry.yarnpkg.com/level-codec/-/level-codec-7.0.1.tgz#341f22f907ce0f16763f24bddd681e395a0fb8a7" - -level-errors@^1.0.3: - version "1.1.2" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.1.2.tgz#4399c2f3d3ab87d0625f7e3676e2d807deff404d" - dependencies: - errno "~0.1.1" - -level-errors@~1.0.3: - version "1.0.5" - resolved "https://registry.yarnpkg.com/level-errors/-/level-errors-1.0.5.tgz#83dbfb12f0b8a2516bdc9a31c4876038e227b859" - dependencies: - errno "~0.1.1" - -level-iterator-stream@~1.3.0: - version "1.3.1" - resolved "https://registry.yarnpkg.com/level-iterator-stream/-/level-iterator-stream-1.3.1.tgz#e43b78b1a8143e6fa97a4f485eb8ea530352f2ed" - dependencies: - inherits "^2.0.1" - level-errors "^1.0.3" - readable-stream "^1.0.33" - xtend "^4.0.0" - -level-ws@0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/level-ws/-/level-ws-0.0.0.tgz#372e512177924a00424b0b43aef2bb42496d228b" - dependencies: - readable-stream "~1.0.15" - xtend "~2.1.1" - -levelup@^1.2.1: - version "1.3.9" - resolved "https://registry.yarnpkg.com/levelup/-/levelup-1.3.9.tgz#2dbcae845b2bb2b6bea84df334c475533bbd82ab" - dependencies: - deferred-leveldown "~1.2.1" - level-codec "~7.0.0" - level-errors "~1.0.3" - level-iterator-stream "~1.3.0" - prr "~1.0.1" - semver "~5.4.1" - xtend "~4.0.0" - -load-json-file@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/load-json-file/-/load-json-file-1.1.0.tgz#956905708d58b4bab4c2261b04f59f31c99374c0" - dependencies: - graceful-fs "^4.1.2" - parse-json "^2.2.0" - pify "^2.0.0" - pinkie-promise "^2.0.0" - strip-bom "^2.0.0" - -lodash.assign@^4.0.3, lodash.assign@^4.0.6: - version "4.2.0" - resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" - -lodash@^4.13.1, lodash@^4.17.10, lodash@^4.17.4: - version "4.17.10" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.10.tgz#1b7793cf7259ea38fb3661d4d38b3260af8ae4e7" - -loose-envify@^1.0.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" - dependencies: - js-tokens "^3.0.0 || ^4.0.0" - -ltgt@~2.2.0: - version "2.2.1" - resolved "https://registry.yarnpkg.com/ltgt/-/ltgt-2.2.1.tgz#f35ca91c493f7b73da0e07495304f17b31f87ee5" - -md5.js@^1.3.4: - version "1.3.4" - resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.4.tgz#e9bdbde94a20a5ac18b04340fc5764d5b09d901d" - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -memdown@^1.0.0: - version "1.4.1" - resolved "https://registry.yarnpkg.com/memdown/-/memdown-1.4.1.tgz#b4e4e192174664ffbae41361aa500f3119efe215" - dependencies: - abstract-leveldown "~2.7.1" - functional-red-black-tree "^1.0.1" - immediate "^3.2.3" - inherits "~2.0.1" - ltgt "~2.2.0" - safe-buffer "~5.1.1" - -memorystream@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/memorystream/-/memorystream-0.3.1.tgz#86d7090b30ce455d63fbae12dda51a47ddcaf9b2" - -merkle-patricia-tree@^2.1.2: - version "2.3.1" - resolved "https://registry.yarnpkg.com/merkle-patricia-tree/-/merkle-patricia-tree-2.3.1.tgz#7d4e7263a9c85c1679187cad4a6d71f48d524c71" - dependencies: - async "^1.4.2" - ethereumjs-util "^5.0.0" - level-ws "0.0.0" - levelup "^1.2.1" - memdown "^1.0.0" - readable-stream "^2.0.0" - rlp "^2.0.0" - semaphore ">=1.0.1" - -mime-db@~1.36.0: - version "1.36.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.36.0.tgz#5020478db3c7fe93aad7bbcc4dcf869c43363397" - -mime-types@^2.1.12, mime-types@~2.1.19: - version "2.1.20" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.20.tgz#930cb719d571e903738520f8470911548ca2cc19" - dependencies: - mime-db "~1.36.0" - -min-document@^2.19.0: - version "2.19.0" - resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" - dependencies: - dom-walk "^0.1.0" - -minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" - -minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" - -minimatch@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" - dependencies: - brace-expansion "^1.1.7" - -minimist@0.0.8: - version "0.0.8" - resolved "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" - -minimist@~1.2.0: - version "1.2.0" - resolved "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" - -mkdirp@0.5.1, mkdirp@^0.5.1: - version "0.5.1" - resolved "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" - dependencies: - minimist "0.0.8" - -mocha@^4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/mocha/-/mocha-4.1.0.tgz#7d86cfbcf35cb829e2754c32e17355ec05338794" - dependencies: - browser-stdout "1.3.0" - commander "2.11.0" - debug "3.1.0" - diff "3.3.1" - escape-string-regexp "1.0.5" - glob "7.1.2" - growl "1.10.3" - he "1.1.1" - mkdirp "0.5.1" - supports-color "4.4.0" - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - -nan@2.10.0: - version "2.10.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" - -nan@^2.0.8, nan@^2.2.1: - version "2.11.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.0.tgz#574e360e4d954ab16966ec102c0c049fd961a099" - -node-fetch@2.1.2: - version "2.1.2" - resolved "http://registry.npmjs.org/node-fetch/-/node-fetch-2.1.2.tgz#ab884e8e7e57e38a944753cec706f788d1768bb5" - -node-fetch@~1.7.1: - version "1.7.3" - resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.7.3.tgz#980f6f72d85211a5347c6b2bc18c5b84c3eb47ef" - dependencies: - encoding "^0.1.11" - is-stream "^1.0.1" - -normalize-package-data@^2.3.2: - version "2.4.0" - resolved "https://registry.yarnpkg.com/normalize-package-data/-/normalize-package-data-2.4.0.tgz#12f95a307d58352075a04907b84ac8be98ac012f" - dependencies: - hosted-git-info "^2.1.4" - is-builtin-module "^1.0.0" - semver "2 || 3 || 4 || 5" - validate-npm-package-license "^3.0.1" - -number-is-nan@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - -object-assign@^4.0.0, object-assign@^4.1.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - -object-inspect@~1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" - -object-keys@^1.0.12: - version "1.0.12" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.0.12.tgz#09c53855377575310cca62f55bb334abff7b3ed2" - -object-keys@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-0.4.0.tgz#28a6aae7428dd2c3a92f3d95f21335dd204e0336" - -once@^1.3.0, once@^1.4.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" - dependencies: - wrappy "1" - -openzeppelin-solidity@^1.12.0: - version "1.12.0" - resolved "https://registry.yarnpkg.com/openzeppelin-solidity/-/openzeppelin-solidity-1.12.0.tgz#7b9c55975e73370d4541e3442b30cb3d91ac973a" - -os-homedir@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" - -os-locale@^1.4.0: - version "1.4.0" - resolved "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz#20f9f17ae29ed345e8bde583b13d2009803c14d9" - dependencies: - lcid "^1.0.0" - -os-tmpdir@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" - -parse-cache-control@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/parse-cache-control/-/parse-cache-control-1.0.1.tgz#8eeab3e54fa56920fe16ba38f77fa21aacc2d74e" - -parse-headers@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.1.tgz#6ae83a7aa25a9d9b700acc28698cd1f1ed7e9536" - dependencies: - for-each "^0.3.2" - trim "0.0.1" - -parse-json@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-2.2.0.tgz#f480f40434ef80741f8469099f8dea18f55a4dc9" - dependencies: - error-ex "^1.2.0" - -path-exists@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-2.1.0.tgz#0feb6c64f0fc518d9a754dd5efb62c7022761f4b" - dependencies: - pinkie-promise "^2.0.0" - -path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" - -path-parse@^1.0.5: - version "1.0.6" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" - -path-type@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/path-type/-/path-type-1.1.0.tgz#59c44f7ee491da704da415da5a4070ba4f8fe441" - dependencies: - graceful-fs "^4.1.2" - pify "^2.0.0" - pinkie-promise "^2.0.0" - -pathval@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.0.tgz#b942e6d4bde653005ef6b71361def8727d0645e0" - -pbkdf2@^3.0.3, pbkdf2@^3.0.9: - version "3.0.16" - resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.16.tgz#7404208ec6b01b62d85bf83853a8064f8d9c2a5c" - dependencies: - create-hash "^1.1.2" - create-hmac "^1.1.4" - ripemd160 "^2.0.1" - safe-buffer "^5.0.1" - sha.js "^2.4.8" - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - -pify@^2.0.0, pify@^2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" - -pinkie-promise@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" - dependencies: - pinkie "^2.0.0" - -pinkie@^2.0.0: - version "2.0.4" - resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" - -precond@0.2: - version "0.2.3" - resolved "https://registry.yarnpkg.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac" - -prettier@^1.9.1: - version "1.14.2" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.14.2.tgz#0ac1c6e1a90baa22a62925f41963c841983282f9" - -private@^0.1.6, private@^0.1.8: - version "0.1.8" - resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" - -process-nextick-args@~2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.0.tgz#a37d732f4271b4ab1ad070d35508e8290788ffaa" - -process@~0.5.1: - version "0.5.2" - resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf" - -promise-to-callback@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/promise-to-callback/-/promise-to-callback-1.0.0.tgz#5d2a749010bfb67d963598fcd3960746a68feef7" - dependencies: - is-fn "^1.0.0" - set-immediate-shim "^1.0.1" - -promise@^8.0.0: - version "8.0.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-8.0.1.tgz#e45d68b00a17647b6da711bf85ed6ed47208f450" - dependencies: - asap "~2.0.3" - -prr@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" - -psl@^1.1.24: - version "1.1.29" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.29.tgz#60f580d360170bb722a797cc704411e6da850c67" - -punycode@^1.4.1: - version "1.4.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" - -qs@^6.4.0, qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - -randombytes@^2.0.1: - version "2.0.6" - resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.0.6.tgz#d302c522948588848a8d300c932b44c24231da80" - dependencies: - safe-buffer "^5.1.0" - -read-pkg-up@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/read-pkg-up/-/read-pkg-up-1.0.1.tgz#9d63c13276c065918d57f002a57f40a1b643fb02" - dependencies: - find-up "^1.0.0" - read-pkg "^1.0.0" - -read-pkg@^1.0.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-1.1.0.tgz#f5ffaa5ecd29cb31c0474bca7d756b6bb29e3f28" - dependencies: - load-json-file "^1.0.0" - normalize-package-data "^2.3.2" - path-type "^1.0.0" - -readable-stream@^1.0.33: - version "1.1.14" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.1.14.tgz#7cf4c54ef648e3813084c636dd2079e166c081d9" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -readable-stream@^2.0.0, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.9: - version "2.3.6" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.3" - isarray "~1.0.0" - process-nextick-args "~2.0.0" - safe-buffer "~5.1.1" - string_decoder "~1.1.1" - util-deprecate "~1.0.1" - -readable-stream@~1.0.15: - version "1.0.34" - resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-1.0.34.tgz#125820e34bc842d2f2aaafafe4c2916ee32c157c" - dependencies: - core-util-is "~1.0.0" - inherits "~2.0.1" - isarray "0.0.1" - string_decoder "~0.10.x" - -rechoir@^0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" - dependencies: - resolve "^1.1.6" - -regenerate@^1.2.1: - version "1.4.0" - resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" - -regenerator-runtime@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9" - -regenerator-transform@^0.10.0: - version "0.10.1" - resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd" - dependencies: - babel-runtime "^6.18.0" - babel-types "^6.19.0" - private "^0.1.6" - -regexpu-core@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-2.0.0.tgz#49d038837b8dcf8bfa5b9a42139938e6ea2ae240" - dependencies: - regenerate "^1.2.1" - regjsgen "^0.2.0" - regjsparser "^0.1.4" - -regjsgen@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.2.0.tgz#6c016adeac554f75823fe37ac05b92d5a4edb1f7" - -regjsparser@^0.1.4: - version "0.1.5" - resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.1.5.tgz#7ee8f84dc6fa792d3fd0ae228d24bd949ead205c" - dependencies: - jsesc "~0.5.0" - -repeating@^2.0.0: - version "2.0.1" - resolved "https://registry.yarnpkg.com/repeating/-/repeating-2.0.1.tgz#5214c53a926d3552707527fbab415dbc08d06dda" - dependencies: - is-finite "^1.0.0" - -req-cwd@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/req-cwd/-/req-cwd-2.0.0.tgz#d4082b4d44598036640fb73ddea01ed53db49ebc" - dependencies: - req-from "^2.0.0" - -req-from@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/req-from/-/req-from-2.0.0.tgz#d74188e47f93796f4aa71df6ee35ae689f3e0e70" - dependencies: - resolve-from "^3.0.0" - -request-promise-core@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/request-promise-core/-/request-promise-core-1.1.1.tgz#3eee00b2c5aa83239cfb04c5700da36f81cd08b6" - dependencies: - lodash "^4.13.1" - -request-promise-native@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/request-promise-native/-/request-promise-native-1.0.5.tgz#5281770f68e0c9719e5163fd3fab482215f4fda5" - dependencies: - request-promise-core "1.1.1" - stealthy-require "^1.1.0" - tough-cookie ">=2.3.3" - -request@^2.67.0, request@^2.83.0: - version "2.88.0" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef" - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.0" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.4.3" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -require-directory@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" - -require-from-string@^1.1.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-1.2.1.tgz#529c9ccef27380adfec9a2f965b649bbee636418" - -require-main-filename@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" - -resolve-from@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" - -resolve@^1.1.6: - version "1.8.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.8.1.tgz#82f1ec19a423ac1fbd080b0bab06ba36e84a7a26" - dependencies: - path-parse "^1.0.5" - -resolve@~1.7.1: - version "1.7.1" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.7.1.tgz#aadd656374fd298aee895bc026b8297418677fd3" - dependencies: - path-parse "^1.0.5" - -resumer@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/resumer/-/resumer-0.0.0.tgz#f1e8f461e4064ba39e82af3cdc2a8c893d076759" - dependencies: - through "~2.3.4" - -rimraf@^2.2.8: - version "2.6.2" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.2.tgz#2ed8150d24a16ea8651e6d6ef0f47c4158ce7a36" - dependencies: - glob "^7.0.5" - -ripemd160@^2.0.0, ripemd160@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" - dependencies: - hash-base "^3.0.0" - inherits "^2.0.1" - -rlp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9" - dependencies: - safe-buffer "^5.1.1" - -rustbn.js@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.1.2.tgz#979fa0f9562216dd667c9d2cd179ae5d13830eff" - -rustbn.js@~0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/rustbn.js/-/rustbn.js-0.2.0.tgz#8082cb886e707155fd1cb6f23bd591ab8d55d0ca" - -safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - -scrypt.js@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" - dependencies: - scrypt "^6.0.2" - scryptsy "^1.2.1" - -scrypt@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - dependencies: - nan "^2.0.8" - -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - dependencies: - pbkdf2 "^3.0.3" - -secp256k1@^3.0.1: - version "3.5.2" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.2.tgz#f95f952057310722184fe9c914e6b71281f2f2ae" - dependencies: - bindings "^1.2.1" - bip66 "^1.1.3" - bn.js "^4.11.3" - create-hash "^1.1.2" - drbg.js "^1.0.1" - elliptic "^6.2.3" - nan "^2.2.1" - safe-buffer "^5.1.0" - -semaphore@>=1.0.1, semaphore@^1.0.3: - version "1.1.0" - resolved "https://registry.yarnpkg.com/semaphore/-/semaphore-1.1.0.tgz#aaad8b86b20fe8e9b32b16dc2ee682a8cd26a8aa" - -"semver@2 || 3 || 4 || 5", semver@^5.3.0: - version "5.5.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.5.1.tgz#7dfdd8814bdb7cabc7be0fb1d734cfb66c940477" - -semver@~5.4.1: - version "5.4.1" - resolved "https://registry.yarnpkg.com/semver/-/semver-5.4.1.tgz#e059c09d8571f0540823733433505d3a2f00b18e" - -set-blocking@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" - -set-immediate-shim@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" - -sha.js@^2.4.0, sha.js@^2.4.8: - version "2.4.11" - resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" - dependencies: - inherits "^2.0.1" - safe-buffer "^5.0.1" - -sha3@^1.1.0: - version "1.2.2" - resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.2.tgz#a66c5098de4c25bc88336ec8b4817d005bca7ba9" - dependencies: - nan "2.10.0" - -shelljs@^0.7.8: - version "0.7.8" - resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.7.8.tgz#decbcf874b0d1e5fb72e14b164a9683048e9acb3" - dependencies: - glob "^7.0.0" - interpret "^1.0.0" - rechoir "^0.6.2" - -slash@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" - -solc@^0.4.2: - version "0.4.24" - resolved "https://registry.yarnpkg.com/solc/-/solc-0.4.24.tgz#354f14b269b38cbaa82a47d1ff151723502b954e" - dependencies: - fs-extra "^0.30.0" - memorystream "^0.3.1" - require-from-string "^1.1.0" - semver "^5.3.0" - yargs "^4.7.1" - -solidity-parser-antlr@^0.2.10: - version "0.2.15" - resolved "https://registry.yarnpkg.com/solidity-parser-antlr/-/solidity-parser-antlr-0.2.15.tgz#4be687a0a53da268c6a07398e0cfb3168896d610" - -source-map-support@^0.4.15: - version "0.4.18" - resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.4.18.tgz#0286a6de8be42641338594e97ccea75f0a2c585f" - dependencies: - source-map "^0.5.6" - -source-map@^0.5.6, source-map@^0.5.7: - version "0.5.7" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" - -spdx-correct@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.0.0.tgz#05a5b4d7153a195bc92c3c425b69f3b2a9524c82" - dependencies: - spdx-expression-parse "^3.0.0" - spdx-license-ids "^3.0.0" - -spdx-exceptions@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz#2c7ae61056c714a5b9b9b2b2af7d311ef5c78fe9" - -spdx-expression-parse@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz#99e119b7a5da00e05491c9fa338b7904823b41d0" - dependencies: - spdx-exceptions "^2.1.0" - spdx-license-ids "^3.0.0" - -spdx-license-ids@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz#e2a303236cac54b04031fa7a5a79c7e701df852f" - -sshpk@^1.7.0: - version "1.14.2" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.14.2.tgz#c6fc61648a3d9c4e764fd3fcdf4ea105e492ba98" - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - dashdash "^1.12.0" - getpass "^0.1.1" - safer-buffer "^2.0.2" - optionalDependencies: - bcrypt-pbkdf "^1.0.0" - ecc-jsbn "~0.1.1" - jsbn "~0.1.0" - tweetnacl "~0.14.0" - -stealthy-require@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/stealthy-require/-/stealthy-require-1.1.1.tgz#35b09875b4ff49f26a777e509b3090a3226bf24b" - -string-width@^1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" - dependencies: - code-point-at "^1.0.0" - is-fullwidth-code-point "^1.0.0" - strip-ansi "^3.0.0" - -string-width@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" - dependencies: - is-fullwidth-code-point "^2.0.0" - strip-ansi "^4.0.0" - -string.prototype.trim@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea" - dependencies: - define-properties "^1.1.2" - es-abstract "^1.5.0" - function-bind "^1.0.2" - -string_decoder@~0.10.x: - version "0.10.31" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-0.10.31.tgz#62e203bc41766c6c28c9fc84301dab1c5310fa94" - -string_decoder@~1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" - dependencies: - safe-buffer "~5.1.0" - -strip-ansi@^3.0.0, strip-ansi@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" - dependencies: - ansi-regex "^2.0.0" - -strip-ansi@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" - dependencies: - ansi-regex "^3.0.0" - -strip-bom@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-2.0.0.tgz#6219a85616520491f35788bdbf1447a99c7e6b0e" - dependencies: - is-utf8 "^0.2.0" - -strip-hex-prefix@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - dependencies: - is-hex-prefixed "1.0.0" - -supports-color@4.4.0: - version "4.4.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-4.4.0.tgz#883f7ddabc165142b2a61427f3352ded195d1a3e" - dependencies: - has-flag "^2.0.0" - -supports-color@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" - -supports-color@^5.3.0: - version "5.5.0" - resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" - dependencies: - has-flag "^3.0.0" - -sync-request@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/sync-request/-/sync-request-6.0.0.tgz#db867eccc4ed31bbcb9fa3732393a3413da582ed" - dependencies: - http-response-object "^3.0.1" - sync-rpc "^1.2.1" - then-request "^6.0.0" - -sync-rpc@^1.2.1: - version "1.3.4" - resolved "https://registry.yarnpkg.com/sync-rpc/-/sync-rpc-1.3.4.tgz#24bcbdb2ffcb98f23690c15b304660085cdd206c" - dependencies: - get-port "^3.1.0" - -tape@^4.4.0, tape@^4.6.3, tape@^4.8.0: - version "4.9.1" - resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" - dependencies: - deep-equal "~1.0.1" - defined "~1.0.0" - for-each "~0.3.3" - function-bind "~1.1.1" - glob "~7.1.2" - has "~1.0.3" - inherits "~2.0.3" - minimist "~1.2.0" - object-inspect "~1.6.0" - resolve "~1.7.1" - resumer "~0.0.0" - string.prototype.trim "~1.1.2" - through "~2.3.8" - -test-value@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" - dependencies: - array-back "^1.0.3" - typical "^2.6.0" - -then-request@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/then-request/-/then-request-6.0.0.tgz#2cab198e48f2d8e79c8c1ed260198368a4a0bcba" - dependencies: - "@types/concat-stream" "^1.6.0" - "@types/form-data" "0.0.33" - "@types/node" "^8.0.0" - "@types/qs" "^6.2.31" - caseless "~0.12.0" - concat-stream "^1.6.0" - form-data "^2.2.0" - http-basic "^7.0.0" - http-response-object "^3.0.1" - promise "^8.0.0" - qs "^6.4.0" - -through2@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.3.tgz#0004569b37c7c74ba39c43f3ced78d1ad94140be" - dependencies: - readable-stream "^2.1.5" - xtend "~4.0.1" - -through@~2.3.4, through@~2.3.8: - version "2.3.8" - resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" - -to-fast-properties@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-1.0.3.tgz#b83571fa4d8c25b82e231b06e3a3055de4ca1a47" - -tough-cookie@>=2.3.3, tough-cookie@~2.4.3: - version "2.4.3" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781" - dependencies: - psl "^1.1.24" - punycode "^1.4.1" - -treeify@^1.0.1: - version "1.1.0" - resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" - -trim-right@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/trim-right/-/trim-right-1.0.1.tgz#cb2e1203067e0c8de1f614094b9fe45704ea6003" - -trim@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" - -truffle-hdwallet-provider@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/truffle-hdwallet-provider/-/truffle-hdwallet-provider-0.0.6.tgz#775c677693a94d83a515815d7fd7f0a73f00c3e9" - dependencies: - bip39 "^2.2.0" - ethereumjs-wallet "0.6.0" - web3 "^0.18.2" - web3-provider-engine "^14.0.5" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - -type-detect@^4.0.0: - version "4.0.8" - resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" - -typechain@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/typechain/-/typechain-0.2.7.tgz#46a52f25176d8cecf08cd509a768aacf92d3f4a3" - dependencies: - chalk "^2.3.0" - command-line-args "^4.0.7" - debug "^3.0.1" - fs-extra "^4.0.2" - glob "^7.1.2" - prettier "^1.9.1" - -typedarray@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" - -typical@^2.6.0, typical@^2.6.1: - version "2.6.1" - resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" - -universalify@^0.1.0: - version "0.1.2" - resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" - -unorm@^1.3.3: - version "1.4.1" - resolved "https://registry.yarnpkg.com/unorm/-/unorm-1.4.1.tgz#364200d5f13646ca8bcd44490271335614792300" - -utf8@^2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.2.tgz#1fa0d9270e9be850d9b05027f63519bf46457d96" - -util-deprecate@~1.0.1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" - -uuid@^2.0.1: - version "2.0.3" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.3.tgz#67e2e863797215530dff318e5bf9dcebfd47b21a" - -uuid@^3.3.2: - version "3.3.2" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" - -validate-npm-package-license@^3.0.1: - version "3.0.4" - resolved "https://registry.yarnpkg.com/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz#fc91f6b9c7ba15c857f4cb2c5defeec39d4f410a" - dependencies: - spdx-correct "^3.0.0" - spdx-expression-parse "^3.0.0" - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -web3-provider-engine@^13.3.2: - version "13.8.0" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-13.8.0.tgz#4c7c1ad2af5f1fe10343b8a65495879a2f9c00df" - dependencies: - async "^2.5.0" - clone "^2.0.0" - eth-block-tracker "^2.2.2" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.1" - ethereumjs-vm "^2.0.2" - fetch-ponyfill "^4.0.0" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.67.0" - semaphore "^1.0.3" - solc "^0.4.2" - tape "^4.4.0" - xhr "^2.2.0" - xtend "^4.0.1" - -web3-provider-engine@^14.0.5: - version "14.0.6" - resolved "https://registry.yarnpkg.com/web3-provider-engine/-/web3-provider-engine-14.0.6.tgz#cbdd66fe20c0136a3a495cbe40d18b6c4160d5f0" - dependencies: - async "^2.5.0" - backoff "^2.5.0" - clone "^2.0.0" - cross-fetch "^2.1.0" - eth-block-tracker "^3.0.0" - eth-json-rpc-infura "^3.1.0" - eth-sig-util "^1.4.2" - ethereumjs-block "^1.2.2" - ethereumjs-tx "^1.2.0" - ethereumjs-util "^5.1.5" - ethereumjs-vm "^2.3.4" - json-rpc-error "^2.0.0" - json-stable-stringify "^1.0.1" - promise-to-callback "^1.0.0" - readable-stream "^2.2.9" - request "^2.67.0" - semaphore "^1.0.3" - tape "^4.4.0" - ws "^5.1.1" - xhr "^2.2.0" - xtend "^4.0.1" - -web3@^0.18.2, web3@^0.18.4: - version "0.18.4" - resolved "https://registry.yarnpkg.com/web3/-/web3-0.18.4.tgz#81ec1784145491f2eaa8955b31c06049e07c5e7d" - dependencies: - bignumber.js "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2" - crypto-js "^3.1.4" - utf8 "^2.1.1" - xhr2 "*" - xmlhttprequest "*" - -whatwg-fetch@2.0.4: - version "2.0.4" - resolved "http://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.4.tgz#dde6a5df315f9d39991aa17621853d720b85566f" - -which-module@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/which-module/-/which-module-1.0.0.tgz#bba63ca861948994ff307736089e3b96026c2a4f" - -window-size@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075" - -wrap-ansi@^2.0.0: - version "2.1.0" - resolved "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" - dependencies: - string-width "^1.0.1" - strip-ansi "^3.0.1" - -wrappy@1: - version "1.0.2" - resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" - -ws@^5.1.1: - version "5.2.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-5.2.2.tgz#dffef14866b8e8dc9133582514d1befaf96e980f" - dependencies: - async-limiter "~1.0.0" - -xhr2@*: - version "0.1.4" - resolved "https://registry.yarnpkg.com/xhr2/-/xhr2-0.1.4.tgz#7f87658847716db5026323812f818cadab387a5f" - -xhr@^2.2.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd" - dependencies: - global "~4.3.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - -xmlhttprequest@*: - version "1.8.0" - resolved "https://registry.yarnpkg.com/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz#67fe075c5c24fef39f9d65f5f7b7fe75171968fc" - -xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.0, xtend@~4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af" - -xtend@~2.1.1: - version "2.1.2" - resolved "https://registry.yarnpkg.com/xtend/-/xtend-2.1.2.tgz#6efecc2a4dad8e6962c4901b337ce7ba87b5d28b" - dependencies: - object-keys "~0.4.0" - -y18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/y18n/-/y18n-3.2.1.tgz#6d15fba884c08679c0d77e88e7759e811e07fa41" - -yargs-parser@^2.4.1: - version "2.4.1" - resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" - dependencies: - camelcase "^3.0.0" - lodash.assign "^4.0.6" - -yargs@^4.7.1: - version "4.8.1" - resolved "http://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz#c0c42924ca4aaa6b0e6da1739dfb216439f9ddc0" - dependencies: - cliui "^3.2.0" - decamelize "^1.1.1" - get-caller-file "^1.0.1" - lodash.assign "^4.0.3" - os-locale "^1.4.0" - read-pkg-up "^1.0.1" - require-directory "^2.1.1" - require-main-filename "^1.0.1" - set-blocking "^2.0.0" - string-width "^1.0.1" - which-module "^1.0.0" - window-size "^0.2.0" - y18n "^3.2.1" - yargs-parser "^2.4.1" diff --git a/frontend/.envexample b/frontend/.envexample index 6c76bffc..2b4218c0 100644 --- a/frontend/.envexample +++ b/frontend/.envexample @@ -1,6 +1,3 @@ -# Funds these addresses when `npm run truffle` runs. Comma separated. -FUND_ETH_ADDRESSES=0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520,0xDECAF9CD2367cdbb726E904cD6397eDFcAe6068DEe0460DFa261520,0xDECAF9CD2367cdbb726E904cD6397eDFcAe6068D - # Disable typescript checking for dev building (reduce build time & resource usage) NO_DEV_TS_CHECK=true @@ -14,9 +11,3 @@ BACKEND_URL=http://localhost:5000 # sentry SENTRY_DSN=https://PUBLICKEY@sentry.io/PROJECTID SENTRY_RELEASE="optional, overrides git hash" - -# CROWD_FUND_URL=https://eip-712.herokuapp.com/contract/crowd-fund -# CROWD_FUND_FACTORY_URL=https://eip-712.herokuapp.com/contract/factory - -CROWD_FUND_URL=http://localhost:5000/dev-contracts/CrowdFund.json -CROWD_FUND_FACTORY_URL=http://localhost:5000/dev-contracts/CrowdFundFactory.json \ No newline at end of file diff --git a/frontend/.gitignore b/frontend/.gitignore index bdecb5ec..e04aab36 100644 --- a/frontend/.gitignore +++ b/frontend/.gitignore @@ -8,5 +8,4 @@ dist *.log .env *.pid -client/lib/contracts .vscode diff --git a/frontend/README.md b/frontend/README.md index 1baa6f7b..aeab6168 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -1,37 +1,23 @@ # Grant.io Front-End -This is the front-end component of [Grant.io](http://grant.io). +This is the front-end component of ZCash Grant System. +## Setup + +1. Install (Nodejs 8.13)[https://nodejs.org/en/blog/release/v0.8.13/] and (yarn)[https://yarnpkg.com/en/]. + +1. Run `yarn` to install dependencies. ## Development -1. Install local project dependencies, and also install Truffle & Ganache globally: - ```bash - # Local dependencies - yarn - # Global dependencies - yarn global add truffle ganache-cli - ``` +1. Make sure the `backend` component is running. -2. (In a separate terminal) Run the ganache development blockchain: - ```bash - yarn run ganache - ``` - -3. Ensure you have grant-contract cloned locally and setup. - - -4. (In a separate terminal) Initialize truffle, open up the repl (Changes to smart contracts will require you to re-run this): - ```bash - yarn run truffle - ``` - -5. Run the next.js server / webpack build for the front-end: +1. Run the webpack dev-server: ```bash yarn run dev ``` -5. Go to the dapp on localhost:3000. You'll need to setup metamask to connect to the ganache network. You'll want to add a custom "RPC" network, and point it towards localhost:8545. +1. Go to the app on localhost:3000. ## Testing @@ -40,14 +26,3 @@ This is the front-end component of [Grant.io](http://grant.io). TBD -### Smart Contract - -Truffle can run tests written in Solidity or JavaScript against your smart contracts. Note the command varies slightly if you're in or outside of the development console. - -```bash -# If inside the truffle console -test - -# If outside the truffle console -truffle test -``` diff --git a/frontend/bin/dev.js b/frontend/bin/dev.js index b57ba00b..67909488 100644 --- a/frontend/bin/dev.js +++ b/frontend/bin/dev.js @@ -9,7 +9,6 @@ const webpackDevMiddleware = require('webpack-dev-middleware'); const webpackHotMiddleware = require('webpack-hot-middleware'); const express = require('express'); const paths = require('../config/paths'); -const truffleUtil = require('./truffle-util'); const { logMessage } = require('./utils'); const app = express(); @@ -22,8 +21,6 @@ const start = async () => { rimraf.sync(paths.clientBuild); rimraf.sync(paths.serverBuild); - await truffleUtil.ethereumCheck(); - const [clientConfig, serverConfig] = webpackConfig; clientConfig.entry.bundle = [ `webpack-hot-middleware/client?path=http://localhost:${WEBPACK_PORT}/__webpack_hmr`, diff --git a/frontend/bin/init-truffle.js b/frontend/bin/init-truffle.js deleted file mode 100644 index b8bb982d..00000000 --- a/frontend/bin/init-truffle.js +++ /dev/null @@ -1,53 +0,0 @@ -// Initialize the truffle environment however we want, web3 is available -const rimraf = require('rimraf'); -const path = require('path'); -const fs = require('fs'); -const childProcess = require('child_process'); - -require('dotenv').config({path: path.resolve(__dirname, '../.env')}); - -const contractsDir = path.resolve(__dirname, '../client/lib/contracts'); - -const CONTRACTS_REPO_BASE_PATH = path.resolve( - __dirname, - '../../contract', -); - -const externalBuildContractsDir = path.join( - CONTRACTS_REPO_BASE_PATH, - '/build/contracts', -); - -module.exports = function (done) { - // Remove the old contracts - rimraf.sync(contractsDir); - - // Fund ETH accounts - const ethAccounts = process.env.FUND_ETH_ADDRESSES - ? process.env.FUND_ETH_ADDRESSES.split(',').map(a => a.trim()) - : []; - - if (ethAccounts.length) { - console.info('Sending 50 ETH to the following addresses...'); - ethAccounts.forEach((addr, i) => { - web3.eth.sendTransaction({ - to: addr, - from: web3.eth.accounts[i], - value: web3.toWei('50', 'ether'), - }); - console.info(` ${addr} <- from ${web3.eth.accounts[i]}`); - }); - } else { - console.info('No accounts specified for funding in .env file...'); - } - - console.info('Changing working directory to: ' + process.cwd()); - console.info('Compiling smart contracts...'); - childProcess.execSync('yarn build', {cwd: CONTRACTS_REPO_BASE_PATH}); - console.info('Running migrations...'); - childProcess.execSync('truffle migrate', {cwd: CONTRACTS_REPO_BASE_PATH}); - console.info('Linking contracts to client/lib/contracts...'); - fs.symlinkSync(externalBuildContractsDir, contractsDir); - console.info('Truffle initialized, starting repl console!'); - done(); -}; diff --git a/frontend/bin/truffle-util.js b/frontend/bin/truffle-util.js deleted file mode 100644 index 37699e5b..00000000 --- a/frontend/bin/truffle-util.js +++ /dev/null @@ -1,166 +0,0 @@ -const rimraf = require('rimraf'); -const path = require('path'); -const fs = require('fs'); -const childProcess = require('child_process'); -const Web3 = require('web3'); - -const paths = require('../config/paths'); -const truffleConfig = require('../truffle'); -const { logMessage } = require('./utils'); - -require('../config/env'); - -module.exports = {}; - -const CHECK_CONTRACT_IDS = ['CrowdFundFactory.json'] - -const clean = (module.exports.clean = () => { - rimraf.sync(paths.contractsBuild); -}); - -const compile = (module.exports.compile = () => { - logMessage('truffle compile, please wait...', 'info'); - try { - childProcess.execSync('yarn build', { cwd: paths.contractsBase }); - } catch (e) { - logMessage(e.stdout.toString('utf8'), 'error'); - process.exit(1); - } -}); - -const migrate = (module.exports.migrate = () => { - logMessage('truffle migrate, please wait...', 'info'); - try { - childProcess.execSync('truffle migrate', { cwd: paths.contractsBase }); - } catch (e) { - logMessage(e.stdout.toString('utf8'), 'error'); - process.exit(1); - } -}); - -const makeWeb3Conn = () => { - const { host, port } = truffleConfig.networks.development; - return `ws://${host}:${port}`; -}; - -const createWeb3 = () => { - return new Web3(makeWeb3Conn()); -}; - -const isGanacheUp = (module.exports.isGanacheUp = verbose => - new Promise((res, rej) => { - verbose && logMessage(`Testing ganache @ ${makeWeb3Conn()}...`, 'info'); - // console.log('curProv', web3.eth.currentProvider); - const web3 = createWeb3(); - web3.eth.net - .isListening() - .then(() => { - verbose && logMessage('Ganache is UP!', 'info'); - res(true); - web3.currentProvider.connection.close(); - }) - .catch(e => { - logMessage('Ganache appears to be down, unable to connect.', 'error'); - res(false); - }); - })); - -const getGanacheNetworkId = (module.exports.getGanacheNetworkId = () => { - const web3 = createWeb3(); - return web3.eth.net - .getId() - .then(id => { - web3.currentProvider.connection.close(); - return id; - }) - .catch(() => -1); -}); - -const checkContractsNetworkIds = (id) => - new Promise((res, rej) => { - const buildDir = paths.contractsBuild; - fs.readdir(buildDir, (err) => { - if (err) { - logMessage(`No contracts build directory @ ${buildDir}`, 'error'); - res(false); - } else { - const allHaveId = CHECK_CONTRACT_IDS.reduce((ok, name) => { - const contractPath = path.join(buildDir, name); - if (!fs.existsSync(contractPath)) { - return false; - } - const contract = require(contractPath); - const contractHasKeys = Object.keys(contract.networks).length > 0; - if (!contractHasKeys) { - logMessage('Contract does not contain network keys.', 'error'); - return false; - } else { - if (contractHasKeys && !contract.networks[id]) { - const actual = Object.keys(contract.networks).join(', '); - logMessage( - `${name} should have networks[${id}], it has ${actual}`, - 'error', - ); - return false; - } - } - return true && ok; - }, true); - res(allHaveId); - } - }); - }); -module.exports.checkContractsNetworkIds = checkContractsNetworkIds; - -const fundWeb3v1 = (module.exports.fundWeb3v1 = () => { - // Fund ETH accounts - const ethAccounts = process.env.FUND_ETH_ADDRESSES - ? process.env.FUND_ETH_ADDRESSES.split(',').map(a => a.trim()) - : []; - const web3 = createWeb3(); - return web3.eth.getAccounts().then(accts => { - if (ethAccounts.length) { - logMessage('Sending 50% of ETH balance from accounts...', 'info'); - const txs = ethAccounts.map((addr, i) => { - return web3.eth - .getBalance(accts[i]) - .then(parseInt) - .then(bal => { - const amount = '' + Math.round(bal / 2); - const amountEth = web3.utils.fromWei(amount); - return web3.eth - .sendTransaction({ - to: addr, - from: accts[i], - value: amount, - }) - .then(() => logMessage(` ${addr} <- ${amountEth} from ${accts[i]}`)) - .catch(e => - logMessage(` Error sending funds to ${addr} : ${e}`, 'error'), - ); - }); - }); - return Promise.all(txs).then(() => web3.currentProvider.connection.close()); - } else { - logMessage('No accounts specified for funding in .env file...', 'warning'); - } - }); -}); - -module.exports.ethereumCheck = () => - isGanacheUp(true) - .then(isUp => !isUp && Promise.reject('network down')) - .then(getGanacheNetworkId) - .then(checkContractsNetworkIds) - .then(allHaveId => { - if (!allHaveId) { - logMessage('Contract problems, will compile & migrate.', 'warning'); - clean(); - compile(); - migrate(); - fundWeb3v1(); - } else { - logMessage('OK, Contracts have correct network id.', 'info'); - } - }) - .catch(e => logMessage('WARNING: ethereum setup has a problem: ' + e, 'error')); diff --git a/frontend/client/Routes.tsx b/frontend/client/Routes.tsx index 38a8aaec..ce5661ba 100644 --- a/frontend/client/Routes.tsx +++ b/frontend/client/Routes.tsx @@ -34,7 +34,7 @@ import 'styles/style.less'; interface RouteConfig extends RouteProps { route: RouteProps; template: TemplateProps; - requiresWeb3?: boolean; + requiresAuth?: boolean; onlyLoggedIn?: boolean; onlyLoggedOut?: boolean; } @@ -61,7 +61,7 @@ const routeConfigs: RouteConfig[] = [ }, template: { title: 'Create a Proposal', - requiresWeb3: true, + requiresAuth: true, }, onlyLoggedIn: true, }, @@ -74,7 +74,7 @@ const routeConfigs: RouteConfig[] = [ }, template: { title: 'Browse proposals', - requiresWeb3: false, + requiresAuth: false, }, }, { @@ -87,7 +87,7 @@ const routeConfigs: RouteConfig[] = [ title: 'Edit proposal', isFullScreen: true, hideFooter: true, - requiresWeb3: true, + requiresAuth: true, }, onlyLoggedIn: true, }, @@ -99,7 +99,7 @@ const routeConfigs: RouteConfig[] = [ }, template: { title: 'Proposal', - requiresWeb3: false, + requiresAuth: false, }, }, { diff --git a/frontend/client/api/api.ts b/frontend/client/api/api.ts index 8249c7e3..a404d6a4 100644 --- a/frontend/client/api/api.ts +++ b/frontend/client/api/api.ts @@ -55,27 +55,42 @@ export function getUser(address: string): Promise<{ data: User }> { }); } -export function createUser(payload: { - accountAddress: string; - emailAddress: string; - displayName: string; +export function createUser(user: { + email: string; + password: string; + name: string; title: string; - signedMessage: string; - rawTypedData: string; }): Promise<{ data: User }> { + const payload = { + emailAddress: user.email, + password: user.password, + displayName: user.name, + title: user.title, + }; return axios.post('/api/v1/users', payload); } export function authUser(payload: { - accountAddress: string; - signedMessage: string; - rawTypedData: string; + email: string; + password: string; }): Promise<{ data: User }> { return axios.post('/api/v1/users/auth', payload); } +export function logoutUser() { + return axios.post('/api/v1/users/logout'); +} + +export function checkUserAuth(): Promise<{ data: User }> { + return axios.get(`/api/v1/users/me`); +} + +export function updateUserPassword(currentPassword: string, password: string) { + return axios.put(`/api/v1/users/password`, { currentPassword, password }); +} + export function updateUser(user: User): Promise<{ data: User }> { - return axios.put(`/api/v1/users/${user.accountAddress}`, formatUserForPost(user)); + return axios.put(`/api/v1/users/${user.userid}`, formatUserForPost(user)); } export function verifyEmail(code: string): Promise { diff --git a/frontend/client/api/axios.ts b/frontend/client/api/axios.ts index 14322f2d..b9bd2939 100644 --- a/frontend/client/api/axios.ts +++ b/frontend/client/api/axios.ts @@ -3,6 +3,8 @@ import axios from 'axios'; const instance = axios.create({ baseURL: process.env.BACKEND_URL, headers: {}, + // for session cookies + withCredentials: true, }); instance.interceptors.response.use( diff --git a/frontend/client/components/AddressInput.tsx b/frontend/client/components/AddressInput.tsx index 4377f519..b8cd6152 100644 --- a/frontend/client/components/AddressInput.tsx +++ b/frontend/client/components/AddressInput.tsx @@ -3,7 +3,7 @@ import classnames from 'classnames'; import { Form, Input } from 'antd'; import { InputProps } from 'antd/lib/input'; import { FormItemProps } from 'antd/lib/form'; -import { isValidEthAddress } from 'utils/validators'; +import { isValidAddress } from 'utils/validators'; import Identicon from 'components/Identicon'; import { DONATION } from 'utils/constants'; import './AddressInput.less'; @@ -22,7 +22,7 @@ export default class AddressInput extends React.Component { const { value, onChange, className, showIdenticon } = this.props; const passedFormItemProps = this.props.formItemProps || {}; const passedInputProps = this.props.inputProps || {}; - const isInvalid = value && !isValidEthAddress(value); + const isInvalid = value && !isValidAddress(value); const formItemProps = { validateStatus: (isInvalid diff --git a/frontend/client/components/AuthFlow/ProvideIdentity.less b/frontend/client/components/AuthFlow/ProvideIdentity.less deleted file mode 100644 index 3d6dccf7..00000000 --- a/frontend/client/components/AuthFlow/ProvideIdentity.less +++ /dev/null @@ -1,14 +0,0 @@ -.ProvideIdentity { - display: flex; - flex-direction: column; - align-items: center; - width: 100%; - margin: 0 auto; - - &-back { - margin-top: 2rem; - opacity: 0.7; - font-size: 0.8rem; - text-align: center; - } -} \ No newline at end of file diff --git a/frontend/client/components/AuthFlow/ProvideIdentity.tsx b/frontend/client/components/AuthFlow/ProvideIdentity.tsx deleted file mode 100644 index 6aca95c7..00000000 --- a/frontend/client/components/AuthFlow/ProvideIdentity.tsx +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import loadable from 'loadable-components'; -import { AUTH_PROVIDER } from 'utils/auth'; -import './ProvideIdentity.less'; - -const AddressProvider = loadable(() => import('./providers/Address')); -const LedgerProvider = loadable(() => import('./providers/Ledger')); -const TrezorProvider = loadable(() => import('./providers/Trezor')); -const Web3Provider = loadable(() => import('./providers/Web3')); - -const PROVIDER_COMPONENTS = { - [AUTH_PROVIDER.ADDRESS]: AddressProvider, - [AUTH_PROVIDER.LEDGER]: LedgerProvider, - [AUTH_PROVIDER.TREZOR]: TrezorProvider, - [AUTH_PROVIDER.WEB3]: Web3Provider, -}; - -interface Props { - provider: AUTH_PROVIDER; - onSelectAddress(addr: string): void; - reset(): void; -} - -export default (props: Props) => { - const ProviderComponent = PROVIDER_COMPONENTS[props.provider]; - return ( -
- -

- Want to use a different method? Click here. -

-
- ); -}; diff --git a/frontend/client/components/AuthFlow/SelectProvider.less b/frontend/client/components/AuthFlow/SelectProvider.less deleted file mode 100644 index c2311295..00000000 --- a/frontend/client/components/AuthFlow/SelectProvider.less +++ /dev/null @@ -1,23 +0,0 @@ -.SelectProvider { - display: flex; - flex-direction: column; - align-items: center; - - &-provider { - display: flex; - max-width: 360px; - width: 100%; - height: 4rem; - justify-content: center; - align-items: center; - margin-bottom: 0.75rem; - border: 1px solid rgba(#000, 0.15); - border-radius: 2px; - cursor: pointer; - font-size: 1.2rem; - - &:hover { - border: 1px solid rgba(#000, 0.3); - } - } -} \ No newline at end of file diff --git a/frontend/client/components/AuthFlow/SelectProvider.tsx b/frontend/client/components/AuthFlow/SelectProvider.tsx deleted file mode 100644 index 3e233f9b..00000000 --- a/frontend/client/components/AuthFlow/SelectProvider.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import React from 'react'; -import { AUTH_PROVIDER, AUTH_PROVIDERS } from 'utils/auth'; -import './SelectProvider.less'; - -interface Props { - onSelect(provider: AUTH_PROVIDER): void; -} - -export default class SelectProvider extends React.PureComponent { - render() { - return ( -
- {Object.values(AUTH_PROVIDERS).map(provider => ( - - ))} -
- ); - } -} diff --git a/frontend/client/components/AuthFlow/SignIn.less b/frontend/client/components/AuthFlow/SignIn.less index 55c48dca..c8f897de 100644 --- a/frontend/client/components/AuthFlow/SignIn.less +++ b/frontend/client/components/AuthFlow/SignIn.less @@ -7,36 +7,10 @@ margin: 0 auto; padding: 1rem; box-shadow: 0 1px 2px rgba(#000, 0.2); - } - &-identity { - display: flex; - align-items: center; - margin-bottom: 1.25rem; - - &-identicon { - border-radius: 100%; - width: 3.6rem; - height: 3.6rem; - margin-right: 0.75rem; - box-shadow: 0 1px 2px rgba(#000, 0.3); - } - - &-info { - width: 0; - flex: 1 1 auto; - - &-name { - font-size: 1.4rem; - } - - &-address { - font-size: 0.8rem; - // Bug: doesn't seem to like opacity, so apply to children - > * { - opacity: 0.7; - } - } + & button, + & input { + margin-bottom: 0.5rem; } } @@ -51,4 +25,4 @@ max-width: @max-width; margin: 1rem auto 0; } -} \ No newline at end of file +} diff --git a/frontend/client/components/AuthFlow/SignIn.tsx b/frontend/client/components/AuthFlow/SignIn.tsx index e9848eba..71fc1d0c 100644 --- a/frontend/client/components/AuthFlow/SignIn.tsx +++ b/frontend/client/components/AuthFlow/SignIn.tsx @@ -1,12 +1,8 @@ import React from 'react'; import { connect } from 'react-redux'; -import { Button, Alert } from 'antd'; +import { Button, Alert, Input } from 'antd'; import { authActions } from 'modules/auth'; -import { User } from 'types'; import { AppState } from 'store/reducers'; -import { AUTH_PROVIDER } from 'utils/auth'; -import Identicon from 'components/Identicon'; -import ShortAddress from 'components/ShortAddress'; import './SignIn.less'; interface StateProps { @@ -18,65 +14,77 @@ interface DispatchProps { authUser: typeof authActions['authUser']; } -interface OwnProps { - // TODO: Use common use User type instead - user: User; - provider: AUTH_PROVIDER; - reset(): void; -} +type Props = StateProps & DispatchProps; -type Props = StateProps & DispatchProps & OwnProps; +const STATE = { + password: '', + email: '', + isAttemptedAuth: false, +}; -class SignIn extends React.Component { +type State = typeof STATE; + +class SignIn extends React.Component { + state: State = { ...STATE }; render() { - const { user, authUserError } = this.props; + const { authUserError, isAuthingUser } = this.props; + const { email, password, isAttemptedAuth } = this.state; return (
-
- + this.setState({ email: e.currentTarget.value })} + size="large" + autoComplete="email" + required={true} /> -
-
{user.displayName}
- - - -
-
- - + this.setState({ password: e.currentTarget.value })} + size="large" + autoComplete="current-password" + required={true} + /> + +
- {authUserError && ( - - )} - - {/* - Temporarily only supporting web3, so there are no other identites -

- Want to use a different identity? Click here. -

- */} + {isAttemptedAuth && + authUserError && ( + + )}
); } - private authUser = () => { - this.props.authUser(this.props.user.accountAddress); + private handleLogin = (ev: React.FormEvent) => { + ev.preventDefault(); + const { email, password } = this.state; + this.setState({ isAttemptedAuth: true }); + this.props.authUser(email, password); }; } -export default connect( +export default connect( state => ({ isAuthingUser: state.auth.isAuthingUser, authUserError: state.auth.authUserError, diff --git a/frontend/client/components/AuthFlow/SignUp.less b/frontend/client/components/AuthFlow/SignUp.less index 7a278a34..dc214406 100644 --- a/frontend/client/components/AuthFlow/SignUp.less +++ b/frontend/client/components/AuthFlow/SignUp.less @@ -7,41 +7,17 @@ box-shadow: 0 1px 2px rgba(#000, 0.2); } - &-identity { - display: flex; - align-items: center; - margin-bottom: 1rem; - - &-identicon { - border-radius: 100%; - width: 3.6rem; - height: 3.6rem; - margin-right: 0.75rem; - box-shadow: 0 1px 2px rgba(#000, 0.3); - } - - &-address { - width: 0; - flex: 1 1 auto; - font-size: 1rem; - opacity: 0.8; - } - } - &-form { &-item { - margin-bottom: 0.4rem; + margin-bottom: 0.5rem; + } - .ant-form-item-label { - padding-bottom: 0.2rem; - } + &-controls { + margin-top: 0.5rem; + } + + &-alert { + margin-top: 1rem; } } - - &-back { - margin-top: 2rem; - opacity: 0.7; - font-size: 0.8rem; - text-align: center; - } -} \ No newline at end of file +} diff --git a/frontend/client/components/AuthFlow/SignUp.tsx b/frontend/client/components/AuthFlow/SignUp.tsx index 09dba976..eaa91e27 100644 --- a/frontend/client/components/AuthFlow/SignUp.tsx +++ b/frontend/client/components/AuthFlow/SignUp.tsx @@ -1,11 +1,10 @@ import React from 'react'; import { connect } from 'react-redux'; import { Form, Input, Button, Alert } from 'antd'; -import Identicon from 'components/Identicon'; -import ShortAddress from 'components/ShortAddress'; -import { AUTH_PROVIDER } from 'utils/auth'; +import { FormComponentProps } from 'antd/lib/form'; import { authActions } from 'modules/auth'; import { AppState } from 'store/reducers'; +import PasswordFormItems from 'components/PasswordFormItems'; import './SignUp.less'; interface StateProps { @@ -17,114 +16,98 @@ interface DispatchProps { createUser: typeof authActions['createUser']; } -interface OwnProps { - address: string; - provider: AUTH_PROVIDER; - reset(): void; -} - -type Props = StateProps & DispatchProps & OwnProps; - -interface State { - name: string; - title: string; - email: string; -} - -class SignUp extends React.Component { - state: State = { - name: '', - title: '', - email: '', - }; +type Props = StateProps & DispatchProps & FormComponentProps; +class SignUp extends React.Component { render() { - const { address, isCreatingUser, createUserError } = this.props; - const { name, title, email } = this.state; + const { isCreatingUser, createUserError } = this.props; + const { getFieldDecorator } = this.props.form; return (
-
- - -
- -
+ - + {getFieldDecorator('name', { + rules: [{ required: true, message: 'Please add a display name' }], + })( + , + )} - + {getFieldDecorator('title', { + rules: [{ required: true, message: 'Please add your title' }], + })( + , + )} - + {getFieldDecorator('email', { + rules: [ + { type: 'email', message: 'Invalid email' }, + { required: true, message: 'Please enter your email' }, + ], + })( + , + )} - + +
+ +
{createUserError && ( )}
- - {/* - Temporarily only supporting web3, so there are no other identites -

- Want to use a different identity? Click here. -

- */}
); } - private handleChange = (ev: React.ChangeEvent) => { - const { name, value } = ev.currentTarget; - this.setState({ [name]: value } as any); - }; - private handleSubmit = (ev: React.FormEvent) => { ev.preventDefault(); - const { address, createUser } = this.props; - const { name, title, email } = this.state; - createUser({ address, name, title, email }); + const { createUser } = this.props; + this.props.form.validateFieldsAndScroll((err: any, values: any) => { + if (!err) { + delete values.passwordConfirm; + createUser(values); + } + }); }; } -export default connect( +const FormWrappedSignUp = Form.create()(SignUp); + +export default connect( state => ({ isCreatingUser: state.auth.isCreatingUser, createUserError: state.auth.createUserError, @@ -132,4 +115,4 @@ export default connect( { createUser: authActions.createUser, }, -)(SignUp); +)(FormWrappedSignUp); diff --git a/frontend/client/components/AuthFlow/index.less b/frontend/client/components/AuthFlow/index.less index eb7f615b..8f087084 100644 --- a/frontend/client/components/AuthFlow/index.less +++ b/frontend/client/components/AuthFlow/index.less @@ -4,11 +4,17 @@ margin: 0 auto 0.25rem; text-align: center; } - + &-subtitle { font-size: 1.2rem; margin-bottom: 2rem; opacity: 0.7; text-align: center; } -} \ No newline at end of file + + &-switch { + font-size: 1.2rem; + margin-top: 2rem; + text-align: center; + } +} diff --git a/frontend/client/components/AuthFlow/index.tsx b/frontend/client/components/AuthFlow/index.tsx index 1bee853d..a6f126e3 100644 --- a/frontend/client/components/AuthFlow/index.tsx +++ b/frontend/client/components/AuthFlow/index.tsx @@ -2,163 +2,71 @@ import React from 'react'; import { connect } from 'react-redux'; import { Spin } from 'antd'; import { AppState } from 'store/reducers'; -import { AUTH_PROVIDER } from 'utils/auth'; import { authActions } from 'modules/auth'; import SignIn from './SignIn'; import SignUp from './SignUp'; -import SelectProvider from './SelectProvider'; -import ProvideIdentity from './ProvideIdentity'; import './index.less'; interface StateProps { - web3Accounts: AppState['web3']['accounts']; - checkedUsers: AppState['auth']['checkedUsers']; + authUser: AppState['auth']['user']; isCheckingUser: AppState['auth']['isCheckingUser']; } -interface DispatchProps { - checkUser: typeof authActions['checkUser']; -} - -type Props = StateProps & DispatchProps; - -interface State { - provider: AUTH_PROVIDER | null; - address: string | null; -} - -const DEFAULT_STATE: State = { - // Temporarily hardcode to web3, change to null when others are supported - provider: AUTH_PROVIDER.WEB3, - address: null, -}; +type Props = StateProps; class AuthFlow extends React.Component { - state: State = { ...DEFAULT_STATE }; - + state: { page: 'SIGN_IN' | 'SIGN_UP' } = { page: 'SIGN_IN' }; private pages = { SIGN_IN: { - title: () => 'Prove your Identity', - subtitle: () => 'Log into your Grant.io account by proving your identity', + title: 'Sign in', + subtitle: '', render: () => { - const { address, provider } = this.state; - const user = address && this.props.checkedUsers[address]; - return ( - user && - provider && - ); + return ; }, + renderSwitch: () => ( + <> + No account?{' '} + this.setState({ page: 'SIGN_UP' })}>Create a new account. + + ), }, SIGN_UP: { - title: () => 'Claim your Identity', - subtitle: () => 'Create a Grant.io account by claiming your identity', + title: 'Create your Account', + subtitle: 'Please enter your details below', render: () => { - const { address, provider } = this.state; - return ( - address && - provider && ( - - ) - ); - }, - }, - SELECT_PROVIDER: { - title: () => 'Provide an Identity', - subtitle: () => - 'Sign in or create a new account by selecting your identity provider', - render: () => , - }, - PROVIDE_IDENTITY: { - title: () => 'Provide an Identity', - subtitle: () => { - switch (this.state.provider) { - case AUTH_PROVIDER.ADDRESS: - return 'Enter your Ethereum Address'; - case AUTH_PROVIDER.LEDGER: - return 'Connect with your Ledger'; - case AUTH_PROVIDER.TREZOR: - return 'Connect with your TREZOR'; - case AUTH_PROVIDER.WEB3: - // TODO: Dynamically use web3 name - return 'Connect with MetaMask'; - } - }, - render: () => { - return ( - this.state.provider && ( - - ) - ); + return ; }, + renderSwitch: () => ( + <> + Already have an account?{' '} + this.setState({ page: 'SIGN_IN' })}>Sign in. + + ), }, }; - componentDidMount() { - // If web3 is available, default to it - const { web3Accounts } = this.props; - if (web3Accounts && web3Accounts[0]) { - this.setState({ - provider: AUTH_PROVIDER.WEB3, - address: web3Accounts[0], - }); - this.props.checkUser(web3Accounts[0]); - } - } - render() { - const { checkedUsers, isCheckingUser } = this.props; - const { provider, address } = this.state; - const checkedUser = address && checkedUsers[address]; - let page; + const { isCheckingUser } = this.props; + const page = this.pages[this.state.page]; - if (provider) { - if (address) { - // TODO: If address results in user, show SIGN_IN. - if (isCheckingUser) { - return ; - } else if (checkedUser) { - page = this.pages.SIGN_IN; - } else { - page = this.pages.SIGN_UP; - } - } else { - page = this.pages.PROVIDE_IDENTITY; - } - } else { - page = this.pages.SELECT_PROVIDER; + if (isCheckingUser) { + return ; } return (
-

{page.title()}

-

{page.subtitle()}

+ {page.title &&

{page.title}

} + {page.subtitle &&

{page.subtitle}

}
{page.render()}
+
{page.renderSwitch()}
); } - - private setProvider = (provider: AUTH_PROVIDER) => { - this.setState({ provider }); - }; - - private setAddress = (address: string) => { - this.setState({ address }); - this.props.checkUser(address); - }; - - private resetState = () => { - this.setState({ ...DEFAULT_STATE }); - }; } -export default connect( +export default connect( state => ({ - web3Accounts: state.web3.accounts, - checkedUsers: state.auth.checkedUsers, + authUser: state.auth.user, isCheckingUser: state.auth.isCheckingUser, }), { diff --git a/frontend/client/components/AuthFlow/providers/Address.less b/frontend/client/components/AuthFlow/providers/Address.less deleted file mode 100644 index ab2c9b9b..00000000 --- a/frontend/client/components/AuthFlow/providers/Address.less +++ /dev/null @@ -1,9 +0,0 @@ -.AddressProvider { - width: 100%; - max-width: 360px; - margin: -0.5rem auto 0; - - &-address { - margin-bottom: 0.5rem; - } -} \ No newline at end of file diff --git a/frontend/client/components/AuthFlow/providers/Address.tsx b/frontend/client/components/AuthFlow/providers/Address.tsx deleted file mode 100644 index d19a3672..00000000 --- a/frontend/client/components/AuthFlow/providers/Address.tsx +++ /dev/null @@ -1,52 +0,0 @@ -import React from 'react'; -import { Form, Button } from 'antd'; -import { isValidEthAddress } from 'utils/validators'; -import AddressInput from 'components/AddressInput'; -import './Address.less'; - -interface Props { - onSelectAddress(addr: string): void; -} - -interface State { - address: string; -} - -export default class AddressProvider extends React.Component { - state: State = { - address: '', - }; - - render() { - const { address } = this.state; - return ( -
- - - - - ); - } - - private handleChange = (ev: React.ChangeEvent) => { - this.setState({ address: ev.currentTarget.value }); - }; - - private handleSubmit = (ev: React.FormEvent) => { - ev.preventDefault(); - this.props.onSelectAddress(this.state.address); - }; -} diff --git a/frontend/client/components/AuthFlow/providers/ChooseAddress.less b/frontend/client/components/AuthFlow/providers/ChooseAddress.less deleted file mode 100644 index 934462b6..00000000 --- a/frontend/client/components/AuthFlow/providers/ChooseAddress.less +++ /dev/null @@ -1,110 +0,0 @@ -@addresses-max-width: 36rem; -@addresses-width: 10rem; -@addresses-padding: 1rem; - - -.ChooseAddress { - display: flex; - flex-direction: column; - justify-content: center; - - // Shared styles between addresses and loader - &-addresses, - &-loading { - display: flex; - flex-wrap: wrap; - justify-content: center; - align-items: center; - max-width: 36rem; - margin-bottom: 1rem; - } - - &-buttons { - display: flex; - justify-content: center; - - &-button { - margin: 0 0.25rem; - } - } - - &-error { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - max-width: 30rem; - margin: 0 auto 2rem; - - .ant-alert { - margin-bottom: 1rem; - } - } -} - -.AddressChoice { - width: 10rem; - padding: 1rem; - margin: 0 0.75rem 1rem; - background: #FFF; - border: 1px solid rgba(#000, 0.12); - border-radius: 4px; - cursor: pointer; - transition: transform 100ms ease, border-color 100ms ease; - outline: none; - - &:hover, - &:focus { - transform: translateY(-2px); - border-color: rgba(#000, 0.2); - } - - &:active { - transform: translateY(0); - border-color: rgba(#000, 0.28); - } - - &-avatar { - display: block; - width: 6rem; - height: 6rem; - margin: 0 auto 1rem; - border-radius: 100%; - - .is-fake & { - background: #000; - color: #000; - opacity: 0.2; - } - } - - &-name, - &-address { - margin: 0 auto; - - .is-fake & { - background: #000; - color: #000; - transform: scaleY(0.8); - } - } - - &-name { - font-size: 1rem; - - .is-fake & { - opacity: 0.2; - width: 60%; - } - } - - &-address { - opacity: 0.6; - font-size: 0.8rem; - - .is-fake & { - opacity: 0.1; - width: 80%; - } - } -} \ No newline at end of file diff --git a/frontend/client/components/AuthFlow/providers/ChooseAddress.tsx b/frontend/client/components/AuthFlow/providers/ChooseAddress.tsx deleted file mode 100644 index 31532e51..00000000 --- a/frontend/client/components/AuthFlow/providers/ChooseAddress.tsx +++ /dev/null @@ -1,162 +0,0 @@ -import React from 'react'; -import { Button, Spin, Icon, Alert } from 'antd'; -import classnames from 'classnames'; -import Identicon from 'components/Identicon'; -import ShortAddress from 'components/ShortAddress'; -import './ChooseAddress.less'; - -interface Props { - addresses: string[]; - loadingMessage: string; - handleDeriveAddresses(index: number, numNeeded: number): Promise; - onSelectAddress(address: string): void; -} - -interface State { - index: number; - isLoading: boolean; - error: null | string; -} - -const ADDRESSES_PER_PAGE = 6; - -export default class ChooseAddress extends React.PureComponent { - state: State = { - index: 0, - isLoading: false, - error: null, - }; - - componentDidMount() { - this.deriveAddresses(); - } - - componentDidUpdate(prevProps: Props) { - // Detect resets of the array, kick off derive - if (prevProps.addresses !== this.props.addresses && !this.props.addresses.length) { - this.setState({ index: 0 }, () => { - this.deriveAddresses(); - }); - } - } - - render() { - const { addresses } = this.props; - const { index, isLoading, error } = this.state; - - let content; - if (error) { - content = ( -
- - -
- ); - } else { - if (isLoading) { - content = ( - -
- {new Array(ADDRESSES_PER_PAGE).fill(null).map((_, idx) => ( - - ))} -
-
- ); - } else { - const pageAddresses = addresses.slice(index, index + ADDRESSES_PER_PAGE); - content = ( -
- {pageAddresses.map(address => ( - - ))} -
- ); - } - - content = ( - <> - {content} -
- - -
- - ); - } - - return
{content}
; - } - - private deriveAddresses = () => { - this.setState( - { - isLoading: true, - error: null, - }, - () => { - this.props - .handleDeriveAddresses(this.state.index, ADDRESSES_PER_PAGE) - .then(() => this.setState({ isLoading: false })) - .catch(err => this.setState({ isLoading: false, error: err.message })); - }, - ); - }; - - private next = () => { - this.setState({ index: this.state.index + ADDRESSES_PER_PAGE }, () => { - if (!this.props.addresses[this.state.index + ADDRESSES_PER_PAGE]) { - this.deriveAddresses(); - } - }); - }; - - private prev = () => { - this.setState({ index: Math.max(0, this.state.index - ADDRESSES_PER_PAGE) }); - }; -} - -interface AddressChoiceProps { - address: string; - name: string; - isFake?: boolean; - onClick?(address: string): void; -} - -const AddressChoice: React.SFC = props => ( - -); diff --git a/frontend/client/components/AuthFlow/providers/Ledger.less b/frontend/client/components/AuthFlow/providers/Ledger.less deleted file mode 100644 index 2e233421..00000000 --- a/frontend/client/components/AuthFlow/providers/Ledger.less +++ /dev/null @@ -1,25 +0,0 @@ -.LedgerProvider { - display: flex; - flex-direction: column; - justify-content: center; - - &-type { - display: flex; - justify-content: center; - margin-top: -0.5rem; - margin-bottom: 1.25rem; - - .ant-radio-button-wrapper { - min-width: 5rem; - text-align: center; - } - } - - &-hint { - opacity: 0.7; - font-size: 0.8rem; - text-align: center; - margin-top: 1.5rem; - margin-bottom: -1rem; - } -} \ No newline at end of file diff --git a/frontend/client/components/AuthFlow/providers/Ledger.tsx b/frontend/client/components/AuthFlow/providers/Ledger.tsx deleted file mode 100644 index e2e518be..00000000 --- a/frontend/client/components/AuthFlow/providers/Ledger.tsx +++ /dev/null @@ -1,117 +0,0 @@ -import React from 'react'; -import TransportU2F from '@ledgerhq/hw-transport-u2f'; -import LedgerEth from '@ledgerhq/hw-app-eth'; -import { Radio } from 'antd'; -import { RadioChangeEvent } from 'antd/lib/radio'; -import ChooseAddress from './ChooseAddress'; -import { deriveAddressesFromPubKey, parseLedgerError } from 'utils/wallet'; -import './Ledger.less'; - -enum ADDRESS_TYPE { - LEGACY = 'LEGACY', - LIVE = 'LIVE', -} - -interface Props { - onSelectAddress(addr: string): void; -} - -interface State { - publicKey: null | string; - chainCode: null | string; - addresses: string[]; - addressType: ADDRESS_TYPE; -} - -const DPATHS = { - LEGACY: `m/44'/60'/0'/0`, - LIVE: `m/44'/60'/$index'/0/0`, -}; - -export default class LedgerProvider extends React.Component { - state: State = { - publicKey: null, - chainCode: null, - addresses: [], - addressType: ADDRESS_TYPE.LIVE, - }; - - render() { - const { addresses, addressType } = this.state; - return ( -
-
- - Live - Legacy - -
- - - -
- Don't see your address? Try changing between Live and Legacy addresses. -
-
- ); - } - - private deriveAddresses = async (index: number, numAddresses: number) => { - const { addressType } = this.state; - let addresses = [...this.state.addresses]; - - try { - if (addressType === ADDRESS_TYPE.LIVE) { - const app = await this.getEthApp(); - for (let i = index; i < index + numAddresses; i++) { - const res = await app.getAddress(DPATHS.LIVE.replace('$index', i.toString())); - addresses.push(res.address); - } - } else { - let { chainCode, publicKey } = this.state; - if (!chainCode || !publicKey) { - const app = await this.getEthApp(); - const res = await app.getAddress(DPATHS.LEGACY, false, true); - chainCode = res.chainCode; - publicKey = res.publicKey; - this.setState({ chainCode, publicKey }); - } - - addresses = addresses.concat( - deriveAddressesFromPubKey({ - chainCode, - publicKey, - index, - numAddresses, - }), - ); - } - } catch (err) { - const msg = parseLedgerError(err); - throw new Error(msg); - } - - this.setState({ addresses }); - }; - - private getEthApp = async () => { - const transport = await TransportU2F.create(); - return new LedgerEth(transport); - }; - - private changeAddressType = (ev: RadioChangeEvent) => { - const addressType = ev.target.value as ADDRESS_TYPE; - if (addressType === this.state.addressType) { - return; - } - this.setState({ - addresses: [], - addressType, - }); - }; -} diff --git a/frontend/client/components/AuthFlow/providers/Trezor.tsx b/frontend/client/components/AuthFlow/providers/Trezor.tsx deleted file mode 100644 index 7f27c541..00000000 --- a/frontend/client/components/AuthFlow/providers/Trezor.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import React from 'react'; -import TrezorConnect from 'trezor-connect'; -import ChooseAddress from './ChooseAddress'; -import { deriveAddressesFromPubKey } from 'utils/wallet'; - -interface Props { - onSelectAddress(addr: string): void; -} - -interface State { - publicKey: null | string; - chainCode: null | string; - addresses: string[]; -} - -const DPATHS = { - MAINNET: `m/44'/60'/0'/0`, - TESTNET: `m/44'/1'/0'/0`, -}; - -export default class TrezorProvider extends React.Component { - state: State = { - publicKey: null, - chainCode: null, - addresses: [], - }; - - render() { - return ( - - ); - } - - private deriveAddresses = async (index: number, numAddresses: number) => { - let { chainCode, publicKey } = this.state; - if (!chainCode || !publicKey) { - const res = await this.getPublicKey(); - chainCode = res.chainCode; - publicKey = res.publicKey; - this.setState({ chainCode, publicKey }); - } - - const addresses = this.state.addresses.concat( - deriveAddressesFromPubKey({ - chainCode, - publicKey, - index, - numAddresses, - }), - ); - this.setState({ addresses }); - }; - - private getPublicKey = async () => { - const res = await TrezorConnect.getPublicKey({ path: DPATHS.TESTNET }); - if (res.success === false) { - throw new Error(res.payload.error); - } - return res.payload; - }; -} diff --git a/frontend/client/components/AuthFlow/providers/Web3.less b/frontend/client/components/AuthFlow/providers/Web3.less deleted file mode 100644 index 248ff8c1..00000000 --- a/frontend/client/components/AuthFlow/providers/Web3.less +++ /dev/null @@ -1,16 +0,0 @@ -.Web3Provider { - max-width: 360px; - margin: 0 auto; - text-align: center; - - &-logo { - display: block; - max-width: 120px; - margin: 0 auto 1.5rem; - } - - &-description { - font-size: 0.9rem; - margin-bottom: 1rem; - } -} \ No newline at end of file diff --git a/frontend/client/components/AuthFlow/providers/Web3.tsx b/frontend/client/components/AuthFlow/providers/Web3.tsx deleted file mode 100644 index f491854e..00000000 --- a/frontend/client/components/AuthFlow/providers/Web3.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { Button, Alert, Spin } from 'antd'; -import { enableWeb3 } from 'modules/web3/actions'; -import { AppState } from 'store/reducers'; -import MetamaskIcon from 'static/images/metamask.png'; -import './Web3.less'; - -interface StateProps { - accounts: AppState['web3']['accounts']; - isEnablingWeb3: AppState['web3']['isEnablingWeb3']; - accountsLoading: AppState['web3']['accountsLoading']; - web3EnableError: AppState['web3']['web3EnableError']; - accountsError: AppState['web3']['accountsError']; -} - -interface DispatchProps { - enableWeb3: typeof enableWeb3; -} - -interface OwnProps { - onSelectAddress(addr: string): void; -} - -type Props = StateProps & DispatchProps & OwnProps; - -class Web3Provider extends React.Component { - componentWillMount() { - if (!this.props.accounts || !this.props.accounts[0]) { - this.props.enableWeb3(); - } - } - - componentDidUpdate() { - const { accounts } = this.props; - if (accounts && accounts[0]) { - this.props.onSelectAddress(accounts[0]); - } - } - - render() { - const { - isEnablingWeb3, - accountsLoading, - web3EnableError, - accountsError, - } = this.props; - const isLoading = isEnablingWeb3 || accountsLoading; - const error = web3EnableError || accountsError; - return ( -
- {isLoading ? ( - - ) : ( - <> - -

- Make sure you have MetaMask or another web3 provider installed and unlocked, - then click below. -

- {error && ( - - )} - - - )} -
- ); - } -} - -export default connect( - state => ({ - accounts: state.web3.accounts, - isEnablingWeb3: state.web3.isEnablingWeb3, - accountsLoading: state.web3.accountsLoading, - web3EnableError: state.web3.web3EnableError, - accountsError: state.web3.accountsError, - }), - { - enableWeb3, - }, -)(Web3Provider); diff --git a/frontend/client/components/AuthRoute.tsx b/frontend/client/components/AuthRoute.tsx index f51cb641..422145e6 100644 --- a/frontend/client/components/AuthRoute.tsx +++ b/frontend/client/components/AuthRoute.tsx @@ -1,12 +1,10 @@ import React from 'react'; import { connect } from 'react-redux'; -import { Spin } from 'antd'; import { Route, Redirect, RouteProps } from 'react-router-dom'; import { AppState } from 'store/reducers'; interface StateProps { user: AppState['auth']['user']; - isAuthingUser: AppState['auth']['isAuthingUser']; } interface OwnProps { @@ -17,11 +15,8 @@ type Props = RouteProps & StateProps & OwnProps; class AuthRoute extends React.Component { public render() { - const { user, isAuthingUser, onlyLoggedOut, ...routeProps } = this.props; - - if (isAuthingUser) { - return ; - } else if ((user && !onlyLoggedOut) || (!user && onlyLoggedOut)) { + const { user, onlyLoggedOut, ...routeProps } = this.props; + if ((user && !onlyLoggedOut) || (!user && onlyLoggedOut)) { return ; } else { // TODO: redirect to desired destination after auth @@ -33,5 +28,4 @@ class AuthRoute extends React.Component { export default connect((state: AppState) => ({ user: state.auth.user, - isAuthingUser: state.auth.isAuthingUser, }))(AuthRoute); diff --git a/frontend/client/components/Comment/index.tsx b/frontend/client/components/Comment/index.tsx index 35e5adf7..f22eb213 100644 --- a/frontend/client/components/Comment/index.tsx +++ b/frontend/client/components/Comment/index.tsx @@ -50,7 +50,7 @@ class Comment extends React.Component { public render(): React.ReactNode { const { comment, isSignedIn, isPostCommentPending } = this.props; const { isReplying, reply } = this.state; - const authorPath = `/profile/${comment.author.accountAddress}`; + const authorPath = `/profile/${comment.author.userid}`; return (
diff --git a/frontend/client/components/CreateFlow/Final.tsx b/frontend/client/components/CreateFlow/Final.tsx index bc72a5f8..7dc4114e 100644 --- a/frontend/client/components/CreateFlow/Final.tsx +++ b/frontend/client/components/CreateFlow/Final.tsx @@ -10,8 +10,6 @@ import './Final.less'; interface StateProps { form: AppState['create']['form']; - crowdFundError: AppState['web3']['crowdFundError']; - crowdFundCreatedAddress: AppState['web3']['crowdFundCreatedAddress']; createdProposal: ProposalWithCrowdFund | null; } @@ -27,19 +25,21 @@ class CreateFinal extends React.Component { } render() { - const { crowdFundError, crowdFundCreatedAddress, createdProposal } = this.props; + const { createdProposal } = this.props; let content; - if (crowdFundError) { - content = ( -
- -
- Something went wrong during creation: "{crowdFundError}"{' '} - Click here to try again. -
-
- ); - } else if (crowdFundCreatedAddress && createdProposal) { + // TODO - handle errors? + // if (crowdFundError) { + // content = ( + //
+ // + //
+ // Something went wrong during creation: "{crowdFundError}"{' '} + // Click here to try again. + //
+ //
+ // ); + // } else + if (createdProposal) { content = (
@@ -72,12 +72,7 @@ class CreateFinal extends React.Component { export default connect( (state: AppState) => ({ form: state.create.form, - crowdFundError: state.web3.crowdFundError, - crowdFundCreatedAddress: state.web3.crowdFundCreatedAddress, - createdProposal: getProposalByAddress( - state, - state.web3.crowdFundCreatedAddress || '', - ), + createdProposal: getProposalByAddress(state, 'notanaddress'), }), { createProposal: createActions.createProposal, diff --git a/frontend/client/components/CreateFlow/Team.tsx b/frontend/client/components/CreateFlow/Team.tsx index 330a4f59..c940ba1f 100644 --- a/frontend/client/components/CreateFlow/Team.tsx +++ b/frontend/client/components/CreateFlow/Team.tsx @@ -4,7 +4,7 @@ import { Icon, Form, Input, Button, Popconfirm, message } from 'antd'; import { User, TeamInvite, ProposalDraft } from 'types'; import TeamMemberComponent from './TeamMember'; import { postProposalInvite, deleteProposalInvite } from 'api/api'; -import { isValidEthAddress, isValidEmail } from 'utils/validators'; +import { isValidAddress, isValidEmail } from 'utils/validators'; import { AppState } from 'store/reducers'; import './Team.less'; @@ -52,7 +52,7 @@ class CreateFlowTeam extends React.Component { render() { const { team, invites, address } = this.state; const inviteError = - address && !isValidEmail(address) && !isValidEthAddress(address) + address && !isValidEmail(address) && !isValidAddress(address) ? 'That doesn’t look like an email address or ETH address' : undefined; const inviteDisabled = !!inviteError || !address; diff --git a/frontend/client/components/CreateFlow/index.tsx b/frontend/client/components/CreateFlow/index.tsx index 2c601c63..a0c36f97 100644 --- a/frontend/client/components/CreateFlow/index.tsx +++ b/frontend/client/components/CreateFlow/index.tsx @@ -19,7 +19,7 @@ import createExampleProposal from './example'; import { createActions } from 'modules/create'; import { ProposalDraft } from 'types'; import { getCreateErrors } from 'modules/create/utils'; -import { web3Actions } from 'modules/web3'; + import { AppState } from 'store/reducers'; import './index.less'; @@ -104,12 +104,11 @@ interface StateProps { form: AppState['create']['form']; isSavingDraft: AppState['create']['isSavingDraft']; hasSavedDraft: AppState['create']['hasSavedDraft']; - accounts: AppState['web3']['accounts']; + accounts: string[]; } interface DispatchProps { updateForm: typeof createActions['updateForm']; - resetCreateCrowdFund: typeof web3Actions['resetCreateCrowdFund']; } type Props = StateProps & DispatchProps & RouteComponentProps; @@ -145,7 +144,7 @@ class CreateFlow extends React.Component { } componentDidMount() { - this.props.resetCreateCrowdFund(); + console.warn('TODO - implement RESET_CROWDFUND if necessary'); } componentWillUnmount() { @@ -326,18 +325,17 @@ class CreateFlow extends React.Component { } const withConnect = connect( - (state: AppState) => ({ - form: state.create.form, - isSavingDraft: state.create.isSavingDraft, - hasSavedDraft: state.create.hasSavedDraft, - crowdFundLoading: state.web3.crowdFundLoading, - crowdFundError: state.web3.crowdFundError, - crowdFundCreatedAddress: state.web3.crowdFundCreatedAddress, - accounts: state.web3.accounts, - }), + (state: AppState) => { + console.warn('TODO - remove/refactor accounts'); + return { + form: state.create.form, + isSavingDraft: state.create.isSavingDraft, + hasSavedDraft: state.create.hasSavedDraft, + accounts: ['notanaccount'], + }; + }, { updateForm: createActions.updateForm, - resetCreateCrowdFund: web3Actions.resetCreateCrowdFund, }, ); diff --git a/frontend/client/components/Header/Auth.tsx b/frontend/client/components/Header/Auth.tsx index e3c5cc08..d944b19c 100644 --- a/frontend/client/components/Header/Auth.tsx +++ b/frontend/client/components/Header/Auth.tsx @@ -4,15 +4,12 @@ import { connect } from 'react-redux'; import { Link } from 'react-router-dom'; import classnames from 'classnames'; import UserAvatar from 'components/UserAvatar'; -import Identicon from 'components/Identicon'; import { AppState } from 'store/reducers'; import './Auth.less'; interface StateProps { user: AppState['auth']['user']; isAuthingUser: AppState['auth']['isAuthingUser']; - accounts: AppState['web3']['accounts']; - accountsLoading: AppState['web3']['accountsLoading']; } type Props = StateProps; @@ -27,7 +24,7 @@ class HeaderAuth extends React.Component { }; render() { - const { accounts, accountsLoading, user, isAuthingUser } = this.props; + const { user, isAuthingUser } = this.props; const { isMenuOpen } = this.state; const isAuthed = !!user; @@ -35,9 +32,7 @@ class HeaderAuth extends React.Component { let isLoading; if (user) { avatar = ; - } else if (accounts && accounts[0]) { - avatar = ; - } else if (accountsLoading || isAuthingUser) { + } else if (isAuthingUser) { avatar = ''; isLoading = true; } @@ -118,6 +113,4 @@ class HeaderAuth extends React.Component { export default connect(state => ({ user: state.auth.user, isAuthingUser: state.auth.isAuthingUser, - accounts: state.web3.accounts, - accountsLoading: state.web3.accountsLoading, }))(HeaderAuth); diff --git a/frontend/client/components/Header/Drawer.tsx b/frontend/client/components/Header/Drawer.tsx index bdc37312..32d41cdc 100644 --- a/frontend/client/components/Header/Drawer.tsx +++ b/frontend/client/components/Header/Drawer.tsx @@ -3,13 +3,11 @@ import { connect } from 'react-redux'; import { Drawer, Menu } from 'antd'; import { Link } from 'react-router-dom'; import UserAvatar from 'components/UserAvatar'; -import Identicon from 'components/Identicon'; import { AppState } from 'store/reducers'; import './Drawer.less'; interface StateProps { user: AppState['auth']['user']; - accounts: AppState['web3']['accounts']; } interface OwnProps { @@ -29,7 +27,7 @@ class HeaderDrawer extends React.Component { } render() { - const { isOpen, onClose, user, accounts } = this.props; + const { isOpen, onClose, user } = this.props; let userTitle: React.ReactNode = 'Account'; if (user) { @@ -39,15 +37,7 @@ class HeaderDrawer extends React.Component { My account ); - } else if (accounts && accounts[0]) { - userTitle = ( - <> - - Account - - ); } - return ( { export default connect(state => ({ user: state.auth.user, - accounts: state.web3.accounts, }))(HeaderDrawer); diff --git a/frontend/client/components/Identicon.tsx b/frontend/client/components/Identicon.tsx index fbf3ce3e..8d3ffa1e 100644 --- a/frontend/client/components/Identicon.tsx +++ b/frontend/client/components/Identicon.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import makeBlockie from 'ethereum-blockies-base64'; import defaultUserImg from 'static/images/default-user.jpg'; interface Props { @@ -10,8 +9,8 @@ interface Props { export default class Identicon extends React.PureComponent { render() { - const { address, className } = this.props; - const blockie = address ? makeBlockie(address) : defaultUserImg; + const { className } = this.props; + const blockie = defaultUserImg; const style = { display: 'block', ...(this.props.style || {}), diff --git a/frontend/client/components/MetaMaskRequiredButton/index.tsx b/frontend/client/components/MetaMaskRequiredButton/index.tsx index 253433f9..7f22b67c 100644 --- a/frontend/client/components/MetaMaskRequiredButton/index.tsx +++ b/frontend/client/components/MetaMaskRequiredButton/index.tsx @@ -1,7 +1,6 @@ import React from 'react'; import { connect } from 'react-redux'; import { AppState } from 'store/reducers'; -import { web3Actions } from 'modules/web3'; import { Alert } from 'antd'; import metaMaskImgSrc from 'static/images/metamask.png'; import './index.less'; @@ -16,11 +15,7 @@ interface StateProps { isWrongNetwork: boolean; } -interface DispatchProps { - setAccounts: typeof web3Actions['setAccounts']; -} - -type Props = OwnProps & StateProps & DispatchProps; +type Props = OwnProps & StateProps; class MetaMaskRequiredButton extends React.PureComponent { render() { @@ -48,7 +43,7 @@ class MetaMaskRequiredButton extends React.PureComponent { message={ <> It looks like your MetaMask account is locked. Please unlock it and{' '} - click here to continue. + null}>click here to continue. } /> @@ -70,13 +65,11 @@ class MetaMaskRequiredButton extends React.PureComponent { } } -export default connect( - state => ({ - isMissingWeb3: state.web3.isMissingWeb3, - isWeb3Locked: state.web3.isWeb3Locked, - isWrongNetwork: state.web3.isWrongNetwork, - }), - { - setAccounts: web3Actions.setAccounts, - }, -)(MetaMaskRequiredButton); +export default connect(state => { + console.warn('TODO - convert to LoginRequiredButton?', state); + return { + isMissingWeb3: false, + isWeb3Locked: false, + isWrongNetwork: false, + }; +})(MetaMaskRequiredButton); diff --git a/frontend/client/components/PasswordFormItems.less b/frontend/client/components/PasswordFormItems.less new file mode 100644 index 00000000..25cf3ce1 --- /dev/null +++ b/frontend/client/components/PasswordFormItems.less @@ -0,0 +1,10 @@ +.PasswordFormItems { + &-confirm { + .ant-form-item-label label { + display: none; // hide label, keep geometry + } + } + .ant-form-item { + margin-bottom: 0.5rem; + } +} diff --git a/frontend/client/components/PasswordFormItems.tsx b/frontend/client/components/PasswordFormItems.tsx new file mode 100644 index 00000000..4f569c4c --- /dev/null +++ b/frontend/client/components/PasswordFormItems.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import classnames from 'classnames'; +import { Form, Input, Row, Col } from 'antd'; +import { FormItemProps } from 'antd/lib/form'; +import { WrappedFormUtils } from 'antd/lib/form/Form'; +import './PasswordFormItems.less'; + +export interface Props { + form: WrappedFormUtils; + className?: string; + formItemProps?: FormItemProps; +} + +const STATE = { + passwordConfirmDirty: true, +}; + +type State = typeof STATE; + +export default class AddressInput extends React.Component { + state: State = { ...STATE }; + render() { + const { passwordConfirmDirty } = this.state; + const { className } = this.props; + const { getFieldDecorator, validateFields, getFieldValue } = this.props.form; + const passedFormItemProps = this.props.formItemProps || {}; + + const formItemProps = { + className: classnames(className, passedFormItemProps.className), + }; + + return ( + + + + {getFieldDecorator('password', { + rules: [ + { required: true, message: 'Please enter a password' }, + { min: 8, message: 'Please use at least 8 characters' }, + { + validator: (_, val, cb) => { + if (val && passwordConfirmDirty) { + validateFields(['passwordConfirm'], { force: true }); + } + cb(); + }, + }, + ], + })( + , + )} + + + + + {getFieldDecorator('passwordConfirm', { + rules: [ + { required: true, message: 'Please confirm password' }, + { + validator: (_, val, cb) => { + if (val && val !== getFieldValue('password')) { + cb('Passwords do not match'); + } else { + cb(); + } + }, + }, + ], + })( + + this.setState({ + passwordConfirmDirty: passwordConfirmDirty || !!e.target.value, + }) + } + placeholder="confirm password" + autoComplete="off" + />, + )} + + + + ); + } +} diff --git a/frontend/client/components/Profile/AvatarEdit.tsx b/frontend/client/components/Profile/AvatarEdit.tsx index 91630843..465bf6e9 100644 --- a/frontend/client/components/Profile/AvatarEdit.tsx +++ b/frontend/client/components/Profile/AvatarEdit.tsx @@ -4,6 +4,7 @@ import { Upload, Icon, Modal, Button, Alert } from 'antd'; import Cropper from 'react-cropper'; import 'cropperjs/dist/cropper.css'; import { UploadFile } from 'antd/lib/upload/interface'; +import { uploadSignedPost } from 'utils/s3'; import { User } from 'types'; import { getBase64 } from 'utils/blob'; import UserAvatar from 'components/UserAvatar'; @@ -155,17 +156,12 @@ export default class AvatarEdit extends React.PureComponent { this.cropperRef.current .getCroppedCanvas({ width: 400, height: 400 }) .toBlob((blob: Blob) => { - const formData = new FormData(); - formData.append('file', blob); this.setState({ isUploading: true }); axios - .post('/api/v1/users/avatar', formData, { - headers: { - 'Content-Type': 'multipart/form-data', - }, - }) - .then(res => { - this.props.onDone(res.data.url); + .post('/api/v1/users/avatar', { mimetype: blob.type }) + .then(res => uploadSignedPost(blob, res.data.data).then(() => res.data.url)) + .then(url => { + this.props.onDone(url); this.handleClose(); }) .catch(err => { diff --git a/frontend/client/components/Profile/ProfileEdit.tsx b/frontend/client/components/Profile/ProfileEdit.tsx index 6af8b3c4..768cc9fa 100644 --- a/frontend/client/components/Profile/ProfileEdit.tsx +++ b/frontend/client/components/Profile/ProfileEdit.tsx @@ -48,11 +48,7 @@ export default class ProfileEdit extends React.PureComponent { render() { const { fields } = this.state; const error = getCreateTeamMemberError(fields); - const isMissingField = - !fields.displayName || - !fields.title || - !fields.emailAddress || - !fields.accountAddress; + const isMissingField = !fields.displayName || !fields.title || !fields.emailAddress; const isDisabled = !!error || isMissingField || !this.state.isChanged; return ( @@ -72,7 +68,7 @@ export default class ProfileEdit extends React.PureComponent { > { /> - - - - {Object.values(SOCIAL_INFO).map(s => { const field = fields.socialMedias.find(sm => sm.service === s.service); @@ -182,7 +167,11 @@ export default class ProfileEdit extends React.PureComponent { const propsAvatar = this.props.user.avatar; const stateAvatar = this.state.fields.avatar; // cleanup uploaded file if we cancel - if (propsAvatar && stateAvatar && propsAvatar.imageUrl !== stateAvatar.imageUrl) { + if ( + stateAvatar && + stateAvatar.imageUrl && + (!propsAvatar || propsAvatar.imageUrl !== stateAvatar.imageUrl) + ) { axios.delete('/api/v1/users/avatar', { params: { url: stateAvatar.imageUrl }, }); diff --git a/frontend/client/components/Profile/ProfileProposal.tsx b/frontend/client/components/Profile/ProfileProposal.tsx index bdfd8e5f..546fe027 100644 --- a/frontend/client/components/Profile/ProfileProposal.tsx +++ b/frontend/client/components/Profile/ProfileProposal.tsx @@ -30,7 +30,7 @@ export default class Profile extends React.Component {

Team

{team.map(user => ( - + ))}
diff --git a/frontend/client/components/Profile/ProfileUser.tsx b/frontend/client/components/Profile/ProfileUser.tsx index cf775af6..63d4f2a4 100644 --- a/frontend/client/components/Profile/ProfileUser.tsx +++ b/frontend/client/components/Profile/ProfileUser.tsx @@ -7,7 +7,6 @@ import { UserState } from 'modules/users/reducers'; import ProfileEdit from './ProfileEdit'; import UserAvatar from 'components/UserAvatar'; import { SOCIAL_INFO } from 'utils/social'; -import ShortAddress from 'components/ShortAddress'; import './ProfileUser.less'; import { AppState } from 'store/reducers'; @@ -41,7 +40,7 @@ class ProfileUser extends React.Component { user: { socialMedias }, } = this.props; - const isSelf = !!authUser && authUser.accountAddress === user.accountAddress; + const isSelf = !!authUser && authUser.userid === user.userid; if (this.state.isEditing) { return ( @@ -68,12 +67,6 @@ class ProfileUser extends React.Component { {user.emailAddress}
)} - {user.accountAddress && ( -
- ethereum address - -
- )}
{socialMedias.length > 0 && (
diff --git a/frontend/client/components/Profile/index.tsx b/frontend/client/components/Profile/index.tsx index 3ffc7d26..4e4f9ac3 100644 --- a/frontend/client/components/Profile/index.tsx +++ b/frontend/client/components/Profile/index.tsx @@ -43,8 +43,8 @@ class Profile extends React.Component { const userLookupParam = this.props.match.params.id; const { authUser } = this.props; if (!userLookupParam) { - if (authUser && authUser.accountAddress) { - return ; + if (authUser && authUser.userid) { + return ; } else { return ; } @@ -52,9 +52,7 @@ class Profile extends React.Component { const user = this.props.usersMap[userLookupParam]; const waiting = !user || !user.hasFetched; - // TODO: Replace with userid checks - const isAuthedUser = - user && authUser && user.accountAddress === authUser.accountAddress; + const isAuthedUser = user && authUser && user.userid === authUser.userid; if (waiting) { return ; @@ -120,11 +118,7 @@ class Profile extends React.Component { /> )} {invites.map(invite => ( - + ))}
diff --git a/frontend/client/components/Proposal/CampaignBlock/index.tsx b/frontend/client/components/Proposal/CampaignBlock/index.tsx index 7fd07f9c..67194976 100644 --- a/frontend/client/components/Proposal/CampaignBlock/index.tsx +++ b/frontend/client/components/Proposal/CampaignBlock/index.tsx @@ -8,7 +8,6 @@ import { fromWei } from 'utils/units'; import { connect } from 'react-redux'; import { compose } from 'recompose'; import { AppState } from 'store/reducers'; -import { web3Actions } from 'modules/web3'; import { withRouter } from 'react-router'; import ShortAddress from 'components/ShortAddress'; import UnitDisplay from 'components/UnitDisplay'; @@ -22,14 +21,10 @@ interface OwnProps { } interface StateProps { - sendLoading: AppState['web3']['sendLoading']; + sendLoading: boolean; } -interface ActionProps { - fundCrowdFund: typeof web3Actions['fundCrowdFund']; -} - -type Props = OwnProps & StateProps & ActionProps; +type Props = OwnProps & StateProps; interface State { amountToRaise: string; @@ -71,8 +66,8 @@ export class ProposalCampaignBlock extends React.Component { }; sendTransaction = () => { - const { proposal, fundCrowdFund } = this.props; - fundCrowdFund(proposal, this.state.amountToRaise); + const { proposal } = this.props; + console.warn('TODO - remove, implement or refactor sendTransaction', proposal); this.setState({ amountToRaise: '' }); }; @@ -226,15 +221,13 @@ export class ProposalCampaignBlock extends React.Component { } function mapStateToProps(state: AppState) { + console.warn('TODO - new redux flag for sendLoading?', state); return { - sendLoading: state.web3.sendLoading, + sendLoading: false, }; } -const withConnect = connect( - mapStateToProps, - { fundCrowdFund: web3Actions.fundCrowdFund }, -); +const withConnect = connect(mapStateToProps); const ConnectedProposalCampaignBlock = compose( withRouter, diff --git a/frontend/client/components/Proposal/CancelModal.tsx b/frontend/client/components/Proposal/CancelModal.tsx index 303be079..6da2b945 100644 --- a/frontend/client/components/Proposal/CancelModal.tsx +++ b/frontend/client/components/Proposal/CancelModal.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { connect } from 'react-redux'; import { Modal, Alert } from 'antd'; import { ProposalWithCrowdFund } from 'types'; -import { web3Actions } from 'modules/web3'; import { AppState } from 'store/reducers'; interface OwnProps { @@ -12,15 +11,11 @@ interface OwnProps { } interface StateProps { - isRefundActionPending: AppState['web3']['isRefundActionPending']; - refundActionError: AppState['web3']['refundActionError']; + isRefundActionPending: boolean; + refundActionError: string; } -interface DispatchProps { - triggerRefund: typeof web3Actions['triggerRefund']; -} - -type Props = StateProps & DispatchProps & OwnProps; +type Props = StateProps & OwnProps; class CancelModal extends React.Component { componentDidUpdate() { @@ -90,16 +85,14 @@ class CancelModal extends React.Component { }; private cancelProposal = () => { - this.props.triggerRefund(this.props.proposal); + console.warn('TODO - implement cancelProposal'); }; } -export default connect( - state => ({ - isRefundActionPending: state.web3.isRefundActionPending, - refundActionError: state.web3.refundActionError, - }), - { - triggerRefund: web3Actions.triggerRefund, - }, -)(CancelModal); +export default connect(state => { + console.warn('TODO - redux isRefundActionPending/refundActionError?', state); + return { + isRefundActionPending: false, + refundActionError: '', + }; +})(CancelModal); diff --git a/frontend/client/components/Proposal/Governance/Refunds.tsx b/frontend/client/components/Proposal/Governance/Refunds.tsx index 5c5bd701..48942d36 100644 --- a/frontend/client/components/Proposal/Governance/Refunds.tsx +++ b/frontend/client/components/Proposal/Governance/Refunds.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { connect } from 'react-redux'; import { Progress, Button, Alert } from 'antd'; import { ProposalWithCrowdFund } from 'types'; -import { web3Actions } from 'modules/web3'; import { AppState } from 'store/reducers'; import classnames from 'classnames'; import Placeholder from 'components/Placeholder'; @@ -12,26 +11,21 @@ interface OwnProps { } interface StateProps { - isRefundActionPending: AppState['web3']['isRefundActionPending']; - refundActionError: AppState['web3']['refundActionError']; - accounts: AppState['web3']['accounts']; + isRefundActionPending: boolean; + refundActionError: string; } -interface ActionProps { - voteRefund: typeof web3Actions['voteRefund']; - withdrawRefund: typeof web3Actions['withdrawRefund']; -} - -type Props = OwnProps & StateProps & ActionProps; +type Props = OwnProps & StateProps; class GovernanceRefunds extends React.Component { render() { - const { proposal, accounts, isRefundActionPending, refundActionError } = this.props; - const account = accounts[0]; + const { proposal, isRefundActionPending, refundActionError } = this.props; const { crowdFund } = proposal; const isStillFunding = !crowdFund.isRaiseGoalReached && crowdFund.deadline > Date.now(); + const account = 'sorrynotanaccount'; + if (isStillFunding && !crowdFund.isFrozen) { return ( { } voteRefund = (vote: boolean) => { - this.props.voteRefund(this.props.proposal, vote); + console.warn('TODO - implement or remove voteRefund', vote); }; withdrawRefund = () => { - const { proposal, accounts } = this.props; - this.props.withdrawRefund(proposal, accounts[0]); + const { proposal } = this.props; + console.warn('TODO - implement or remove withdrawRefund', proposal); }; } -const ConnectedGovernanceRefunds = connect( - state => ({ - isRefundActionPending: state.web3.isRefundActionPending, - refundActionError: state.web3.refundActionError, - accounts: state.web3.accounts, - }), - { - voteRefund: web3Actions.voteRefund, - withdrawRefund: web3Actions.withdrawRefund, - }, -)(GovernanceRefunds); +const ConnectedGovernanceRefunds = connect(state => { + console.warn('TODO - new redux isRefundActionPending/refundActionError?', state); + return { + isRefundActionPending: false, + refundActionError: '', + }; +})(GovernanceRefunds); export default ConnectedGovernanceRefunds; diff --git a/frontend/client/components/Proposal/Milestones/MilestoneAction.tsx b/frontend/client/components/Proposal/Milestones/MilestoneAction.tsx index a8d25ee9..a7ee2523 100644 --- a/frontend/client/components/Proposal/Milestones/MilestoneAction.tsx +++ b/frontend/client/components/Proposal/Milestones/MilestoneAction.tsx @@ -3,7 +3,6 @@ import moment from 'moment'; import { connect } from 'react-redux'; import { Button, Progress, Alert } from 'antd'; import { ProposalWithCrowdFund, MILESTONE_STATE } from 'types'; -import { web3Actions } from 'modules/web3'; import { AppState } from 'store/reducers'; import UnitDisplay from 'components/UnitDisplay'; import Placeholder from 'components/Placeholder'; @@ -15,18 +14,12 @@ interface OwnProps { } interface StateProps { - isMilestoneActionPending: AppState['web3']['isMilestoneActionPending']; - milestoneActionError: AppState['web3']['milestoneActionError']; - accounts: AppState['web3']['accounts']; + isMilestoneActionPending: boolean; + milestoneActionError: string; + accounts: string[]; } -interface ActionProps { - requestMilestonePayout: typeof web3Actions['requestMilestonePayout']; - payMilestonePayout: typeof web3Actions['payMilestonePayout']; - voteMilestonePayout: typeof web3Actions['voteMilestonePayout']; -} - -type Props = OwnProps & StateProps & ActionProps; +type Props = OwnProps & StateProps; export class Milestones extends React.Component { render() { @@ -234,29 +227,28 @@ export class Milestones extends React.Component { } private requestPayout = (milestoneIndex: number) => { - this.props.requestMilestonePayout(this.props.proposal, milestoneIndex); + console.warn('TODO - implement/refactor requestPayout', milestoneIndex); }; private payPayout = (milestoneIndex: number) => { - this.props.payMilestonePayout(this.props.proposal, milestoneIndex); + console.warn('TODO - implement/refactor payPayout', milestoneIndex); }; private votePayout = (milestoneIndex: number, vote: boolean) => { - this.props.voteMilestonePayout(this.props.proposal, milestoneIndex, vote); + console.warn('TODO - implement/refactor votePayout', milestoneIndex, vote); }; } -const ConnectedMilestones = connect( - (state: AppState) => ({ - accounts: state.web3.accounts, - isMilestoneActionPending: state.web3.isMilestoneActionPending, - milestoneActionError: state.web3.milestoneActionError, - }), - { - requestMilestonePayout: web3Actions.requestMilestonePayout, - payMilestonePayout: web3Actions.payMilestonePayout, - voteMilestonePayout: web3Actions.voteMilestonePayout, - }, -)(Milestones); +const ConnectedMilestones = connect((state: AppState) => { + console.warn( + 'TODO - new redux user-role-for-proposal/accounts + isMilestoneActionPending + milestoneActionError', + state, + ); + return { + accounts: [], + isMilestoneActionPending: false, + milestoneActionError: '', + }; +})(Milestones); export default (props: OwnProps) => ; diff --git a/frontend/client/components/Proposal/Milestones/index.tsx b/frontend/client/components/Proposal/Milestones/index.tsx index 17914ef6..9b19482a 100644 --- a/frontend/client/components/Proposal/Milestones/index.tsx +++ b/frontend/client/components/Proposal/Milestones/index.tsx @@ -31,7 +31,7 @@ interface OwnProps { } interface StateProps { - accounts: AppState['web3']['accounts']; + accounts: string[]; } type Props = OwnProps & StateProps; @@ -294,8 +294,11 @@ class ProposalMilestones extends React.Component { }; } -const ConnectedProposalMilestones = connect((state: AppState) => ({ - accounts: state.web3.accounts, -}))(ProposalMilestones); +const ConnectedProposalMilestones = connect((state: AppState) => { + console.warn('TODO - new redux accounts/user-role-for-proposal', state); + return { + accounts: [], + }; +})(ProposalMilestones); export default ConnectedProposalMilestones; diff --git a/frontend/client/components/Proposal/index.tsx b/frontend/client/components/Proposal/index.tsx index ce5dfc7e..985f8da3 100644 --- a/frontend/client/components/Proposal/index.tsx +++ b/frontend/client/components/Proposal/index.tsx @@ -20,7 +20,6 @@ import UpdateModal from './UpdateModal'; import CancelModal from './CancelModal'; import classnames from 'classnames'; import { withRouter } from 'react-router'; -import { web3Actions } from 'modules/web3'; import SocialShare from 'components/SocialShare'; import './style.less'; @@ -253,14 +252,15 @@ export class ProposalDetail extends React.Component { } function mapStateToProps(state: AppState, ownProps: OwnProps) { + console.warn('TODO - new redux user-proposal-role/account'); return { proposal: getProposal(state, ownProps.proposalId), - account: (state.web3.accounts.length && state.web3.accounts[0]) || null, + account: 'notarealaccount' || null, }; } function mapDispatchToProps(dispatch: Dispatch) { - return bindActionCreators({ ...proposalActions, ...web3Actions }, dispatch); + return bindActionCreators({ ...proposalActions }, dispatch); } const withConnect = connect( diff --git a/frontend/client/components/Settings/ChangePassword.less b/frontend/client/components/Settings/ChangePassword.less new file mode 100644 index 00000000..17becf09 --- /dev/null +++ b/frontend/client/components/Settings/ChangePassword.less @@ -0,0 +1,18 @@ +.ChangePassword { + max-width: 400px; + margin: 0 auto; + + &-form { + & > .ant-form-item { + margin-bottom: 0.5rem; + } + + & button { + margin: 0.6rem auto 0; + } + } + + &-alert { + margin-top: 1rem; + } +} diff --git a/frontend/client/components/Settings/ChangePassword.tsx b/frontend/client/components/Settings/ChangePassword.tsx new file mode 100644 index 00000000..e9d11bf1 --- /dev/null +++ b/frontend/client/components/Settings/ChangePassword.tsx @@ -0,0 +1,112 @@ +import React from 'react'; +import { Form, Input, Button, Alert } from 'antd'; +import { FormComponentProps } from 'antd/lib/form'; +import { updateUserPassword } from 'api/api'; +import PasswordFormItems from 'components/PasswordFormItems'; +import './ChangePassword.less'; + +type Props = FormComponentProps; + +const STATE = { + passwordConfirmDirty: false, + passwordChangePending: false, + passwordChangeSuccess: false, + passwordChangeError: '', +}; + +type State = typeof STATE; + +class ChangePassword extends React.Component { + state: State = { ...STATE }; + + render() { + const { + passwordChangeError, + passwordChangePending, + passwordChangeSuccess, + } = this.state; + const { getFieldDecorator } = this.props.form; + + return ( +
+
+ + {getFieldDecorator('currentPassword', { + rules: [{ required: true, message: 'Please enter your current password' }], + })( + , + )} + + + + +
+ +
+ + {passwordChangeError && ( + + )} + + {passwordChangeSuccess && ( + this.setState({ passwordChangeSuccess: false })} + className="ChangePassword-alert" + /> + )} + +
+ ); + } + + private handleSubmit = (ev: React.FormEvent) => { + ev.preventDefault(); + this.props.form.validateFieldsAndScroll((err: any, values: any) => { + if (!err) { + this.setState({ + passwordChangePending: true, + passwordChangeError: '', + passwordChangeSuccess: false, + }); + updateUserPassword(values.currentPassword, values.password) + .then(() => { + this.setState({ passwordChangePending: false, passwordChangeSuccess: true }); + this.props.form.resetFields(); + }) + .catch(e => { + this.setState({ + passwordChangePending: false, + passwordChangeError: e.message || e.toSring(), + }); + }); + } + }); + }; +} + +const FormWrappedChangePassword = Form.create()(ChangePassword); + +export default FormWrappedChangePassword; diff --git a/frontend/client/components/Settings/index.less b/frontend/client/components/Settings/index.less new file mode 100644 index 00000000..b09bb582 --- /dev/null +++ b/frontend/client/components/Settings/index.less @@ -0,0 +1,9 @@ +.Settings { + max-width: 800px; + margin: 0 auto; + + & > h1 { + text-align: center; + font-size: 1.4rem; + } +} diff --git a/frontend/client/components/Settings/index.tsx b/frontend/client/components/Settings/index.tsx new file mode 100644 index 00000000..4612b8a0 --- /dev/null +++ b/frontend/client/components/Settings/index.tsx @@ -0,0 +1,38 @@ +import React from 'react'; +import { AppState } from 'store/reducers'; +import { connect } from 'react-redux'; +import './index.less'; +import { Tabs } from 'antd'; +import ChangePassword from './ChangePassword'; + +const { TabPane } = Tabs; + +interface StateProps { + authUser: AppState['auth']['user']; +} + +type Props = StateProps; + +class Settings extends React.Component { + render() { + const { authUser } = this.props; + if (!authUser) return null; + + return ( +
+

Settings

+ + + + + +
+ ); + } +} + +const withConnect = connect(state => ({ + authUser: state.auth.user, +})); + +export default withConnect(Settings); diff --git a/frontend/client/components/Template/Web3Error.less b/frontend/client/components/Template/Web3Error.less deleted file mode 100644 index 0737a907..00000000 --- a/frontend/client/components/Template/Web3Error.less +++ /dev/null @@ -1,47 +0,0 @@ -@keyframes fade-in { - from { - transform: translateY(1rem); - opacity: 0; - } - to { - transform: translateY(0rem); - opacity: 1; - } -} - -.Web3Error { - text-align: center; - width: 100%; - max-width: 360px; - margin: 0 auto; - animation: fade-in 500ms ease; - - &-icon { - display: block; - height: 120px; - margin: 0 auto 2rem; - } - - &-message { - font-size: 1.1rem; - margin-bottom: 2rem; - } - - &-button { - display: block; - margin: 0 auto 2rem; - padding: 0; - height: 3rem; - line-height: 3rem; - max-width: 220px; - font-size: 1.2rem; - color: #fff; - background: #f88500; - border-radius: 4px; - - &:hover { - color: #fff; - opacity: 0.8; - } - } -} \ No newline at end of file diff --git a/frontend/client/components/Template/Web3Error.tsx b/frontend/client/components/Template/Web3Error.tsx deleted file mode 100644 index 9c8f7f58..00000000 --- a/frontend/client/components/Template/Web3Error.tsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import './Web3Error.less'; - -interface Props { - icon?: string; - message: React.ReactNode; - button?: { - text: React.ReactNode; - href?: string; - onClick?: (ev: React.MouseEvent) => void; - }; -} - -const Web3Error: React.SFC = ({ icon, message, button }) => ( -
- {icon && } -

{message}

- {button && ( - - {button.text} - - )} -
-); - -export default Web3Error; diff --git a/frontend/client/components/Template/index.tsx b/frontend/client/components/Template/index.tsx index 641ddda9..034f74fe 100644 --- a/frontend/client/components/Template/index.tsx +++ b/frontend/client/components/Template/index.tsx @@ -5,21 +5,11 @@ import classnames from 'classnames'; import BasicHead from 'components/BasicHead'; import Header from 'components/Header'; import Footer from 'components/Footer'; -import Web3Error from './Web3Error'; -import { web3Actions } from 'modules/web3'; import { AppState } from 'store/reducers'; -import MetamaskIcon from 'static/images/metamask.png'; -import WrongNetworkIcon from 'static/images/wrong-network.png'; import './index.less'; interface StateProps { - isMissingWeb3: boolean; - isWeb3Locked: boolean; - isWrongNetwork: boolean; -} - -interface DispatchProps { - setAccounts: typeof web3Actions['setAccounts']; + authUser: AppState['auth']['user']; } export interface TemplateProps { @@ -27,10 +17,10 @@ export interface TemplateProps { isHeaderTransparent?: boolean; isFullScreen?: boolean; hideFooter?: boolean; - requiresWeb3?: boolean; + requiresAuth?: boolean; } -type Props = StateProps & DispatchProps & TemplateProps; +type Props = StateProps & TemplateProps; class Template extends React.PureComponent { render() { @@ -40,60 +30,20 @@ class Template extends React.PureComponent { isHeaderTransparent, isFullScreen, hideFooter, - requiresWeb3, - isMissingWeb3, - isWeb3Locked, - isWrongNetwork, + requiresAuth, + authUser, } = this.props; let content = children; let isCentered = false; - if (requiresWeb3) { - if (isMissingWeb3) { + if (requiresAuth) { + if (!authUser) { isCentered = true; content = ( - +
+ Login required.
TODO: links or redirect +
); - } else if (isWeb3Locked) { - isCentered = true; - content = ( - - ); - } else if (isWrongNetwork) { - isCentered = true; - content = ( - - The Grant.io smart contract is currently only supported on the{' '} - Ropsten network. Please change your network to continue. - - } - /> - ); - } else { - content = children; } } @@ -116,13 +66,8 @@ class Template extends React.PureComponent { } } -export default connect( - state => ({ - isMissingWeb3: state.web3.isMissingWeb3, - isWeb3Locked: state.web3.isWeb3Locked, - isWrongNetwork: state.web3.isWrongNetwork, - }), - { - setAccounts: web3Actions.setAccounts, - }, -)(Template); +export default connect(state => { + return { + authUser: state.auth.user, + }; +})(Template); diff --git a/frontend/client/components/UserAvatar.tsx b/frontend/client/components/UserAvatar.tsx index a3e41f45..28b8317c 100644 --- a/frontend/client/components/UserAvatar.tsx +++ b/frontend/client/components/UserAvatar.tsx @@ -1,5 +1,4 @@ import React from 'react'; -import Identicon from 'components/Identicon'; import { User } from 'types'; import defaultUserImg from 'static/images/default-user.jpg'; @@ -11,8 +10,6 @@ interface Props { const UserAvatar: React.SFC = ({ user, className }) => { if (user.avatar && user.avatar.imageUrl) { return ; - } else if (user.accountAddress) { - return ; } else { return ; } diff --git a/frontend/client/components/UserRow/index.tsx b/frontend/client/components/UserRow/index.tsx index fff76bc9..06fe384b 100644 --- a/frontend/client/components/UserRow/index.tsx +++ b/frontend/client/components/UserRow/index.tsx @@ -9,7 +9,7 @@ interface Props { } const UserRow = ({ user }: Props) => ( - +
diff --git a/frontend/client/lib/Web3Container.tsx b/frontend/client/lib/Web3Container.tsx deleted file mode 100644 index e9bf2de0..00000000 --- a/frontend/client/lib/Web3Container.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { AppState } from 'store/reducers'; - -export interface Web3RenderProps { - accounts: any[]; -} - -interface OwnProps { - render(props: Web3RenderProps & { props: any }): React.ReactNode; - renderLoading(): React.ReactNode; -} - -interface StateProps { - isMissingWeb3: boolean; - accounts: any[]; -} - -type Props = OwnProps & StateProps; - -class Web3Container extends React.Component { - render() { - const { isMissingWeb3, accounts } = this.props; - - return !isMissingWeb3 && accounts.length - ? this.props.render({ accounts, props: { ...this.props } }) - : this.props.renderLoading(); - } -} - -function mapStateToProps(state: AppState): StateProps { - return { - isMissingWeb3: state.web3.isMissingWeb3, - accounts: state.web3.accounts, - }; -} - -export default connect(mapStateToProps)(Web3Container); diff --git a/frontend/client/lib/crowdFundContracts.ts b/frontend/client/lib/crowdFundContracts.ts deleted file mode 100644 index 2fcf8a11..00000000 --- a/frontend/client/lib/crowdFundContracts.ts +++ /dev/null @@ -1,33 +0,0 @@ -import Web3 from 'web3'; -import getContractInstance from './getContract'; -import { fetchCrowdFundJSON } from 'api/api'; - -const contractCache = {} as { [key: string]: any }; -let CrowdFund: any = null; - -export async function getCrowdFundContract(web3: Web3 | null, deployedAddress: string) { - if (!web3) { - throw new Error('getCrowdFundAddress: web3 was null but is required.'); - } - if (!contractCache[deployedAddress]) { - if (!CrowdFund) { - try { - CrowdFund = await fetchCrowdFundJSON(); - } catch (err) { - console.error(err); - throw new Error('getCrowdFundContract: could not fetch definition JSON.'); - } - } - try { - contractCache[deployedAddress] = await getContractInstance( - web3, - CrowdFund, - deployedAddress, - ); - } catch (e) { - console.error(`Could not lookup crowdFund contract @ ${deployedAddress}: `, e); - return null; - } - } - return contractCache[deployedAddress]; -} diff --git a/frontend/client/lib/crowdFundFactoryContract.ts b/frontend/client/lib/crowdFundFactoryContract.ts deleted file mode 100644 index f0f4d570..00000000 --- a/frontend/client/lib/crowdFundFactoryContract.ts +++ /dev/null @@ -1,24 +0,0 @@ -import Web3 from 'web3'; -import getContractInstance from './getContract'; -import { fetchCrowdFundFactoryJSON } from 'api/api'; - -let crowdFundFactory: any = null; -let CrowdFundFactory: any = null; - -export async function getCrowdFundFactoryContract(web3: Web3 | null) { - if (!web3) { - throw new Error('getCrowdFundFactoryContract: web3 was null but is required.'); - } - if (!crowdFundFactory) { - if (!CrowdFundFactory) { - try { - CrowdFundFactory = await fetchCrowdFundFactoryJSON(); - } catch (err) { - console.error(err); - throw new Error('getCrowdFundFactoryContract: could not fetch definition JSON.'); - } - } - crowdFundFactory = await getContractInstance(web3, CrowdFundFactory); - } - return crowdFundFactory; -} diff --git a/frontend/client/lib/getContract.ts b/frontend/client/lib/getContract.ts deleted file mode 100644 index 58cccd80..00000000 --- a/frontend/client/lib/getContract.ts +++ /dev/null @@ -1,32 +0,0 @@ -import Web3 from 'web3'; - -export class WrongNetworkError extends Error {} - -const getContractInstance = async ( - web3: Web3, - contractDefinition: any, - deployedAddress?: string, -) => { - // get network ID and the deployed address - const networkId = await web3.eth.net.getId(); - if (!deployedAddress && !contractDefinition.networks[networkId]) { - throw new WrongNetworkError( - `Wrong web3 network configured. Deployed address: ${deployedAddress}; networkId: ${networkId}, contractDefinitionNetworks: ${JSON.stringify( - contractDefinition.networks, - )}`, - ); - } - - deployedAddress = deployedAddress || contractDefinition.networks[networkId].address; - - // create the instance - const contract = new web3.eth.Contract(contractDefinition.abi, deployedAddress); - - // use gas from e2e injected window.web3.provider - if ((web3.currentProvider as any)._e2eContractGas) { - contract.options.gas = (web3.currentProvider as any)._e2eContractGas; - } - return contract; -}; - -export default getContractInstance; diff --git a/frontend/client/lib/getWeb3.ts b/frontend/client/lib/getWeb3.ts deleted file mode 100644 index e0144099..00000000 --- a/frontend/client/lib/getWeb3.ts +++ /dev/null @@ -1,48 +0,0 @@ -import Web3 from 'web3'; - -interface Web3Window extends Window { - web3?: Web3; -} - -let clientWeb3: null | Web3 = null; - -const resolveWeb3 = (resolve: (web3: Web3) => void, reject: (err: Error) => void) => { - if (clientWeb3) { - return resolve(clientWeb3); - } - if (typeof window === 'undefined') { - return reject(new Error('No global window variable')); - } - let { web3 } = window as Web3Window; - if (typeof web3 !== 'undefined') { - console.info(`Injected web3 detected.`); - web3 = new Web3(web3.currentProvider); - } else { - return reject(new Error('No web3 instance available')); - } - clientWeb3 = web3; - resolve(web3); -}; - -export const initializeWeb3 = () => - new Promise((resolve, reject) => { - // Wait for loading completion to avoid race conditions with web3 injection timing. - window.addEventListener(`load`, () => { - resolveWeb3(resolve, reject); - }); - // If document has loaded already, try to get Web3 immediately. - if (document.readyState !== `loading`) { - resolveWeb3(resolve, reject); - } - }); - -export default () => { - if (clientWeb3) { - return clientWeb3; - } else { - throw new Error( - 'getWeb3 - web3 does not exist or is not yet initialized.' + - ' Use store.web3.isMissingWeb3 to guard this behavior.', - ); - } -}; diff --git a/frontend/client/modules/auth/actions.ts b/frontend/client/modules/auth/actions.ts index 5bb03e2e..5f4bb944 100644 --- a/frontend/client/modules/auth/actions.ts +++ b/frontend/client/modules/auth/actions.ts @@ -1,55 +1,55 @@ import types from './types'; import { Dispatch } from 'redux'; import * as Sentry from '@sentry/browser'; -import { sleep } from 'utils/helpers'; -import { generateAuthSignatureData } from 'utils/auth'; -import { AppState } from 'store/reducers'; import { createUser as apiCreateUser, - getUser as apiGetUser, + checkUserAuth, authUser as apiAuthUser, + logoutUser, } from 'api/api'; -import { signData } from 'modules/web3/actions'; -import { AuthSignatureData } from 'types'; +import { User } from 'types'; -type GetState = () => AppState; +function setSentryScope(user: User) { + Sentry.configureScope(scope => { + scope.setUser({ + id: user.userid.toString(), + }); + }); +} -const getAuthSignature = ( - address: string, - dispatch: Dispatch, -): Promise => { - const sigData = generateAuthSignatureData(address); - return (dispatch( - signData(sigData.data, sigData.types, sigData.primaryType), - ) as any) as Promise; -}; +// check if user has authenticated session +export function checkUser() { + return async (dispatch: Dispatch) => { + dispatch({ type: types.CHECK_USER_PENDING }); + try { + const res = await checkUserAuth(); + setSentryScope(res.data); + dispatch({ + type: types.CHECK_USER_FULFILLED, + payload: { + user: res.data, + }, + }); + } catch (err) { + dispatch({ + type: types.CHECK_USER_REJECTED, + payload: err.message || err.toString(), + error: true, + }); + } + }; +} -// Auth from previous state, or request signature with new auth -export function authUser(address: string, authSignature?: Falsy | AuthSignatureData) { +export function authUser(email: string, password: string) { return async (dispatch: Dispatch) => { dispatch({ type: types.AUTH_USER_PENDING }); - try { - if (!authSignature) { - authSignature = await getAuthSignature(address, dispatch); - } - const res = await apiAuthUser({ - accountAddress: address, - signedMessage: authSignature.signedMessage, - rawTypedData: JSON.stringify(authSignature.rawTypedData), - }); - // sentry user scope - Sentry.configureScope(scope => { - scope.setUser({ - email: res.data.emailAddress, - accountAddress: res.data.accountAddress, - }); - }); + const res = await apiAuthUser({ email, password }); + setSentryScope(res.data); dispatch({ type: types.AUTH_USER_FULFILLED, payload: { user: res.data, - authSignature, }, }); } catch (err) { @@ -63,29 +63,19 @@ export function authUser(address: string, authSignature?: Falsy | AuthSignatureD } export function createUser(user: { - address: string; email: string; + password: string; name: string; title: string; }) { return async (dispatch: Dispatch) => { dispatch({ type: types.CREATE_USER_PENDING }); - try { - const authSignature = await getAuthSignature(user.address, dispatch); - const res = await apiCreateUser({ - accountAddress: user.address, - emailAddress: user.email, - displayName: user.name, - title: user.title, - signedMessage: authSignature.signedMessage, - rawTypedData: JSON.stringify(authSignature.rawTypedData), - }); + const res = await apiCreateUser(user); dispatch({ type: types.CREATE_USER_FULFILLED, payload: { user: res.data, - authSignature, }, }); } catch (err) { @@ -98,70 +88,11 @@ export function createUser(user: { }; } -export function checkUser(address: string) { - return async (dispatch: Dispatch, getState: GetState) => { - const checkedUsers = getState().auth.checkedUsers; - if (checkedUsers[address] !== undefined) { - return; - } - - dispatch({ type: types.CHECK_USER_PENDING }); - - try { - const res = await apiGetUser(address); - dispatch({ - type: types.CHECK_USER_FULFILLED, - payload: { - address, - user: res.data, - }, - }); - } catch (err) { - if (err.response && err.response.status === 404) { - dispatch({ - type: types.CHECK_USER_FULFILLED, - payload: { - address, - user: false, - }, - }); - } else { - dispatch({ - type: types.CHECK_USER_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } - } - }; -} - -export function signToken(address: string) { +export function logout() { return async (dispatch: Dispatch) => { - // TODO: Implement signing - dispatch({ type: types.SIGN_TOKEN_PENDING }); - await sleep(500); - dispatch({ - type: types.SIGN_TOKEN_FULFILLED, - payload: { - token: Math.random(), - address, - }, + await dispatch({ + type: types.LOGOUT, + payload: logoutUser(), }); }; } - -export function setToken(address: string, signedMessage: string) { - // TODO: Check token for errors - return { - type: types.SIGN_TOKEN_FULFILLED, - payload: { - token: signedMessage, - address, - }, - }; -} - -export function logout() { - return { type: types.LOGOUT }; -} diff --git a/frontend/client/modules/auth/reducers.ts b/frontend/client/modules/auth/reducers.ts index a9b86592..53f936e0 100644 --- a/frontend/client/modules/auth/reducers.ts +++ b/frontend/client/modules/auth/reducers.ts @@ -8,7 +8,6 @@ export interface AuthState { isAuthingUser: boolean; authUserError: string | null; - checkedUsers: { [address: string]: User | false }; isCheckingUser: boolean; isCreatingUser: boolean; @@ -28,7 +27,6 @@ export const INITIAL_STATE: AuthState = { isCreatingUser: false, createUserError: null, - checkedUsers: {}, isCheckingUser: false, authSignature: null, @@ -53,18 +51,8 @@ export default function createReducer( return { ...state, user: action.payload.user, - authSignature: action.payload.authSignature, // TODO: Make this the real token - authSignatureAddress: action.payload.user.accountAddress, isAuthingUser: false, }; - case usersTypes.UPDATE_USER_FULFILLED: - return { - ...state, - user: - state.user && state.user.accountAddress === action.payload.user.accountAddress - ? action.payload.user - : state.user, - }; case types.AUTH_USER_REJECTED: return { ...state, @@ -72,6 +60,33 @@ export default function createReducer( authUserError: action.payload, }; + case types.CHECK_USER_PENDING: + return { + ...state, + isCheckingUser: true, + }; + case types.CHECK_USER_FULFILLED: + return { + ...state, + user: action.payload.user, + isCheckingUser: false, + }; + case types.CHECK_USER_REJECTED: + return { + ...state, + isCheckingUser: false, + }; + + // update authenticated user when general user updated + case usersTypes.UPDATE_USER_FULFILLED: + return { + ...state, + user: + state.user && state.user.userid === action.payload.user.userid + ? action.payload.user + : state.user, + }; + case types.CREATE_USER_PENDING: return { ...state, @@ -82,13 +97,7 @@ export default function createReducer( return { ...state, user: action.payload.user, - authSignature: action.payload.authSignature, - authSignatureAddress: action.payload.user.accountAddress, isCreatingUser: false, - checkedUsers: { - ...state.checkedUsers, - [action.payload.user.address]: action.payload.user, - }, }; case types.CREATE_USER_REJECTED: return { @@ -97,31 +106,6 @@ export default function createReducer( createUserError: action.payload, }; - case types.CHECK_USER_PENDING: - return { - ...state, - isCheckingUser: true, - }; - case types.CHECK_USER_FULFILLED: - return { - ...state, - isCheckingUser: false, - checkedUsers: action.payload.user - ? { - ...state.checkedUsers, - [action.payload.address]: action.payload.user, - } - : { - ...state.checkedUsers, - [action.payload.address]: false, - }, - }; - case types.CHECK_USER_REJECTED: - return { - ...state, - isCheckingUser: false, - }; - case types.SIGN_TOKEN_PENDING: return { ...state, @@ -143,12 +127,10 @@ export default function createReducer( signAuthError: action.payload, }; - case types.LOGOUT: + case types.LOGOUT_FULFILLED: return { ...state, user: null, - authSignature: null, - authSignatureAddress: null, }; } return state; diff --git a/frontend/client/modules/auth/sagas.ts b/frontend/client/modules/auth/sagas.ts index 1322d535..e190bbf5 100644 --- a/frontend/client/modules/auth/sagas.ts +++ b/frontend/client/modules/auth/sagas.ts @@ -1,26 +1,9 @@ import { SagaIterator } from 'redux-saga'; -import { select, put, all, takeEvery } from 'redux-saga/effects'; -import { REHYDRATE } from 'redux-persist'; -import { getAuthSignature, getAuthSignatureAddress } from './selectors'; -import { authUser } from './actions'; +import { put } from 'redux-saga/effects'; +import { checkUser } from './actions'; -export function* authFromToken(): SagaIterator { - const address: ReturnType = yield select( - getAuthSignatureAddress, - ); - if (!address) { - return; - } - const signature: ReturnType = yield select(getAuthSignature); - - // TODO: Figure out how to type redux-saga with thunks - yield put(authUser(address, signature)); -} +// TODO: poll checkUser? export default function* authSaga(): SagaIterator { - yield all([ - // Run authFromToken as soon as persisted state is hydrated - // TODO: Do this server-side at some point - takeEvery(REHYDRATE, authFromToken), - ]); + yield put(checkUser()); } diff --git a/frontend/client/modules/auth/types.ts b/frontend/client/modules/auth/types.ts index 90b2631e..f68f1043 100644 --- a/frontend/client/modules/auth/types.ts +++ b/frontend/client/modules/auth/types.ts @@ -20,6 +20,9 @@ enum AuthTypes { SIGN_TOKEN_REJECTED = 'SIGN_TOKEN_REJECTED', LOGOUT = 'LOGOUT', + LOGOUT_PENDING = 'LOGOUT_PENDING', + LOGOUT_FULFILLED = 'LOGOUT_FULFILLED', + LOGOUT_REJECTED = 'LOGOUT_REJECTED', } export default AuthTypes; diff --git a/frontend/client/modules/create/actions.ts b/frontend/client/modules/create/actions.ts index 0cf62cd0..1fc15140 100644 --- a/frontend/client/modules/create/actions.ts +++ b/frontend/client/modules/create/actions.ts @@ -1,8 +1,10 @@ import { Dispatch } from 'redux'; import { ProposalDraft } from 'types'; -import { createCrowdFund } from 'modules/web3/actions'; +// import { AppState } from 'store/reducers'; import types, { CreateDraftOptions } from './types'; +// type GetState = () => AppState; + export function initializeForm(proposalId: number) { return { type: types.INITIALIZE_FORM_PENDING, @@ -43,9 +45,5 @@ export function deleteDraft(proposalId: number) { } export function createProposal(form: ProposalDraft) { - return async (dispatch: Dispatch) => { - // TODO: Move more of the backend handling into this action. - dispatch(createCrowdFund(form)); - // TODO: dispatch reset conditionally, if crowd fund is success - }; + console.log('TODO - implement createProposal', form); } diff --git a/frontend/client/modules/create/utils.ts b/frontend/client/modules/create/utils.ts index 8a1116a1..08997f3e 100644 --- a/frontend/client/modules/create/utils.ts +++ b/frontend/client/modules/create/utils.ts @@ -1,8 +1,7 @@ import { ProposalDraft, CreateMilestone } from 'types'; import { User } from 'types'; -import { isValidEthAddress, getAmountError } from 'utils/validators'; +import { getAmountError } from 'utils/validators'; import { MILESTONE_STATE, ProposalWithCrowdFund } from 'types'; -import { ProposalContractData } from 'modules/web3/actions'; import { Wei, toWei } from 'utils/units'; import { ONE_DAY } from 'utils/time'; import { PROPOSAL_CATEGORY } from 'api/constants'; @@ -89,7 +88,7 @@ export function getCreateErrors( } // Payout address - if (payoutAddress && !isValidEthAddress(payoutAddress)) { + if (!payoutAddress) { errors.payoutAddress = 'That doesn’t look like a valid address'; } @@ -102,7 +101,7 @@ export function getCreateErrors( } let err = ''; - if (!isValidEthAddress(address)) { + if (!address) { err = 'That doesn’t look like a valid address'; } else if (trustees.indexOf(address) !== idx) { err = 'That address is already a trustee'; @@ -156,10 +155,8 @@ export function getCreateTeamMemberError(user: User) { return 'Display name can only be 30 characters maximum'; } else if (user.title.length > 30) { return 'Title can only be 30 characters maximum'; - } else if (!/.+\@.+\..+/.test(user.emailAddress)) { + } else if (!user.emailAddress || !/.+\@.+\..+/.test(user.emailAddress)) { return 'That doesn’t look like a valid email address'; - } else if (!isValidEthAddress(user.accountAddress)) { - return 'That doesn’t look like a valid ETH address'; } return ''; @@ -186,7 +183,7 @@ function milestoneToMilestoneAmount(milestone: CreateMilestone, raiseGoal: Wei) return raiseGoal.divn(100).mul(Wei(milestone.payoutPercent)); } -export function proposalToContractData(form: ProposalDraft): ProposalContractData { +export function proposalToContractData(form: ProposalDraft): any { const targetInWei = toWei(form.target, 'ether'); const milestoneAmounts = form.milestones.map(m => milestoneToMilestoneAmount(m, targetInWei), diff --git a/frontend/client/modules/proposals/actions.ts b/frontend/client/modules/proposals/actions.ts index 99df774f..f3ee11b0 100644 --- a/frontend/client/modules/proposals/actions.ts +++ b/frontend/client/modules/proposals/actions.ts @@ -8,8 +8,7 @@ import { postProposalComment as apiPostProposalComment, } from 'api/api'; import { Dispatch } from 'redux'; -import { ProposalWithCrowdFund, Comment, AuthSignatureData } from 'types'; -import { signData } from 'modules/web3/actions'; +import { ProposalWithCrowdFund, Comment } from 'types'; export type TFetchProposals = typeof fetchProposals; export function fetchProposals() { @@ -65,27 +64,12 @@ export function postProposalComment( dispatch({ type: types.POST_PROPOSAL_COMMENT_PENDING }); try { - const sigData: AuthSignatureData = (await dispatch( - signData( - { comment }, - { - comment: [ - { - name: 'Comment', - type: 'string', - }, - ], - }, - 'comment', - ), - )) as any; - const res = await apiPostProposalComment({ proposalId, parentCommentId, comment, - signedMessage: sigData.signedMessage, - rawTypedData: JSON.stringify(sigData.rawTypedData), + signedMessage: '', + rawTypedData: '', }); dispatch({ diff --git a/frontend/client/modules/users/actions.ts b/frontend/client/modules/users/actions.ts index 64997154..4bf2e2ae 100644 --- a/frontend/client/modules/users/actions.ts +++ b/frontend/client/modules/users/actions.ts @@ -8,7 +8,7 @@ import { } from 'api/api'; import { Dispatch } from 'redux'; import { cleanClone } from 'utils/helpers'; -import { INITIAL_TEAM_MEMBER_STATE } from 'modules/users/reducers'; +import { INITIAL_USER } from 'modules/users/reducers'; export function fetchUser(userFetchId: string) { return async (dispatch: Dispatch) => { @@ -26,7 +26,7 @@ export function fetchUser(userFetchId: string) { } export function updateUser(user: User) { - const userClone = cleanClone(INITIAL_TEAM_MEMBER_STATE, user); + const userClone = cleanClone(INITIAL_USER, user); return async (dispatch: Dispatch) => { dispatch({ type: types.UPDATE_USER_PENDING, payload: { user } }); try { diff --git a/frontend/client/modules/users/reducers.ts b/frontend/client/modules/users/reducers.ts index bd98e207..50614cb9 100644 --- a/frontend/client/modules/users/reducers.ts +++ b/frontend/client/modules/users/reducers.ts @@ -27,9 +27,8 @@ export interface UsersState { map: { [index: string]: UserState }; } -export const INITIAL_TEAM_MEMBER_STATE: User = { +export const INITIAL_USER: User = { userid: 0, - accountAddress: '', avatar: null, displayName: '', emailAddress: '', @@ -38,7 +37,7 @@ export const INITIAL_TEAM_MEMBER_STATE: User = { }; export const INITIAL_USER_STATE: UserState = { - ...INITIAL_TEAM_MEMBER_STATE, + ...INITIAL_USER, isFetching: false, hasFetched: false, fetchError: null, @@ -86,19 +85,19 @@ export default (state = INITIAL_STATE, action: any) => { }); // update case types.UPDATE_USER_PENDING: - return updateUserState(state, payload.user.accountAddress, { + return updateUserState(state, payload.user.userid, { isUpdating: true, updateError: null, }); case types.UPDATE_USER_FULFILLED: return updateUserState( state, - payload.user.accountAddress, + payload.user.userid, { isUpdating: false }, payload.user, ); case types.UPDATE_USER_REJECTED: - return updateUserState(state, payload.user.accountAddress, { + return updateUserState(state, payload.user.userid, { isUpdating: false, updateError: errorStatus, }); diff --git a/frontend/client/modules/web3/actions.ts b/frontend/client/modules/web3/actions.ts deleted file mode 100644 index 45a22dba..00000000 --- a/frontend/client/modules/web3/actions.ts +++ /dev/null @@ -1,477 +0,0 @@ -import types from './types'; -import { Dispatch } from 'redux'; -import getWeb3, { initializeWeb3 } from 'lib/getWeb3'; -import { WrongNetworkError } from 'lib/getContract'; -import { sleep } from 'utils/helpers'; -import { web3ErrorToString } from 'utils/web3'; -import { putProposalPublish } from 'api/api'; -import { proposalToContractData } from 'modules/create/utils'; -import { AppState } from 'store/reducers'; -import { Wei } from 'utils/units'; -import { AuthSignatureData, ProposalDraft, ProposalWithCrowdFund } from 'types'; -import { - fetchProposal, - fetchProposals, - postProposalContribution, -} from 'modules/proposals/actions'; -import { getCrowdFundContract } from 'lib/crowdFundContracts'; -import { getCrowdFundFactoryContract } from 'lib/crowdFundFactoryContract'; - -type GetState = () => AppState; - -function handleWrongNetworkError(dispatch: (action: any) => void) { - return (err: Error) => { - if (err.constructor === WrongNetworkError) { - dispatch({ type: types.SET_WRONG_NETWORK }); - } else { - throw err; - } - }; -} - -export type TSetWeb3 = typeof setWeb3; -export function setWeb3() { - return (dispatch: Dispatch) => { - return dispatch({ - type: types.WEB3, - payload: initializeWeb3(), - }); - }; -} - -export function checkNetwork() { - return async (dispatch: Dispatch) => { - try { - await getCrowdFundFactoryContract(getWeb3()); - } catch (err) { - handleWrongNetworkError(dispatch)(err); - } - }; -} - -export function enableWeb3() { - return { type: types.ENABLE_WEB3_PENDING }; -} - -export type TSetAccounts = typeof setAccounts; -export function setAccounts() { - return (dispatch: Dispatch) => { - const web3 = getWeb3(); - if (web3) { - dispatch({ type: types.ACCOUNTS_PENDING }); - - web3.eth - .getAccounts() - .then((accounts: any[]) => { - if (accounts && accounts.length) { - dispatch({ - type: types.ACCOUNTS_FULFILLED, - payload: accounts, - }); - } else { - dispatch({ type: types.SET_WEB3_LOCKED }); - throw new Error('No accounts found. Make sure metamask is unlocked.'); - } - }) - .catch((err: Error) => { - dispatch({ - type: types.ACCOUNTS_REJECTED, - payload: err.message || err.toString(), - }); - }); - } else { - dispatch({ - type: types.ACCOUNTS_REJECTED, - payload: 'No web3 object available', - error: true, - }); - } - }; -} - -// TODO: Move these to a better place? -export interface ProposalContractData { - ethAmount: Wei; - payoutAddress: string; - trusteesAddresses: string[]; - milestoneAmounts: Wei[]; - durationInMinutes: number; - milestoneVotingPeriodInMinutes: number; - immediateFirstMilestonePayout: boolean; -} - -export type TCreateCrowdFund = typeof createCrowdFund; -export function createCrowdFund(proposal: ProposalDraft) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ - type: types.CROWD_FUND_PENDING, - }); - - const { - ethAmount, - payoutAddress, - trusteesAddresses, - milestoneAmounts, - durationInMinutes, - milestoneVotingPeriodInMinutes, - immediateFirstMilestonePayout, - } = proposalToContractData(proposal); - - const state = getState(); - const accounts = state.web3.accounts; - - try { - const CrowdFundFactoryContract = await getCrowdFundFactoryContract(getWeb3()); - await CrowdFundFactoryContract.methods - .createCrowdFund( - ethAmount, - payoutAddress, - [payoutAddress, ...trusteesAddresses], - milestoneAmounts, - durationInMinutes, - milestoneVotingPeriodInMinutes, - immediateFirstMilestonePayout, - ) - .send({ from: accounts[0] }) - .once('confirmation', async (_: any, receipt: any) => { - const crowdFundContractAddress = - receipt.events.ContractCreated.returnValues.newAddress; - await putProposalPublish(proposal, crowdFundContractAddress); - dispatch({ - type: types.CROWD_FUND_CREATED, - payload: crowdFundContractAddress, - }); - // TODO: Type me as promise dispatch - (dispatch as any)(fetchProposals()).catch(handleWrongNetworkError(dispatch)); - }); - } catch (err) { - dispatch({ - type: types.CROWD_FUND_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } - }; -} - -export function resetCreateCrowdFund() { - return { type: types.RESET_CROWD_FUND }; -} - -export type TRequestMilestonePayout = typeof requestMilestonePayout; -export function requestMilestonePayout(proposal: ProposalWithCrowdFund, index: number) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ - type: types.REQUEST_MILESTONE_PAYOUT_PENDING, - }); - const state = getState(); - const account = state.web3.accounts[0]; - const { proposalAddress, proposalId } = proposal; - const crowdFundContract = await getCrowdFundContract(getWeb3(), proposalAddress); - - try { - await crowdFundContract.methods - .requestMilestonePayout(index) - .send({ from: account }) - .once('confirmation', async () => { - await sleep(5000); - await dispatch(fetchProposal(proposalId)); - dispatch({ - type: types.REQUEST_MILESTONE_PAYOUT_FULFILLED, - }); - }); - } catch (err) { - dispatch({ - type: types.REQUEST_MILESTONE_PAYOUT_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } - }; -} - -export type TPayMilestonePayout = typeof payMilestonePayout; -export function payMilestonePayout(proposal: ProposalWithCrowdFund, index: number) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ - type: types.PAY_MILESTONE_PAYOUT_PENDING, - }); - const state = getState(); - const account = state.web3.accounts[0]; - const { proposalAddress, proposalId } = proposal; - const crowdFundContract = await getCrowdFundContract(getWeb3(), proposalAddress); - - try { - await crowdFundContract.methods - .payMilestonePayout(index) - .send({ from: account }) - .once('confirmation', async () => { - await sleep(5000); - await dispatch(fetchProposal(proposalId)); - dispatch({ - type: types.PAY_MILESTONE_PAYOUT_FULFILLED, - }); - }); - } catch (err) { - console.error('Pay milestone payout failed:', err); - dispatch({ - type: types.PAY_MILESTONE_PAYOUT_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } - }; -} - -// TODO: BigNumber me -export type TSendTransaction = typeof fundCrowdFund; -export function fundCrowdFund(proposal: ProposalWithCrowdFund, value: number | string) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ - type: types.SEND_PENDING, - }); - const state = getState(); - const web3 = getWeb3(); - const account = state.web3.accounts[0]; - const { proposalAddress, proposalId } = proposal; - const crowdFundContract = await getCrowdFundContract(web3, proposalAddress); - - const handleErr = (err: Error) => { - dispatch({ - type: types.SEND_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - }; - - try { - if (!web3) { - throw new Error('No web3 instance available'); - } - await crowdFundContract.methods - .contribute() - .send({ from: account, value: web3.utils.toWei(String(value), 'ether') }) - .once('confirmation', async (_: number, receipt: any) => { - try { - await sleep(5000); - await dispatch( - postProposalContribution( - proposalId, - receipt.transactionHash, - account, - String(value), - ), - ); - await dispatch(fetchProposal(proposalId)); - dispatch({ - type: types.SEND_FULFILLED, - }); - } catch (err) { - handleErr(err); - } - }); - } catch (err) { - handleErr(err); - } - }; -} - -export function voteMilestonePayout( - proposal: ProposalWithCrowdFund, - index: number, - vote: boolean, -) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: types.VOTE_AGAINST_MILESTONE_PAYOUT_PENDING }); - const state = getState(); - const account = state.web3.accounts[0]; - const { proposalAddress, proposalId } = proposal; - const crowdFundContract = await getCrowdFundContract(getWeb3(), proposalAddress); - - try { - await crowdFundContract.methods - .voteMilestonePayout(index, vote) - .send({ from: account }) - .once('confirmation', async () => { - await sleep(5000); - await dispatch(fetchProposal(proposalId)); - dispatch({ type: types.VOTE_AGAINST_MILESTONE_PAYOUT_FULFILLED }); - }); - } catch (err) { - console.error('Vote against payout failed:', err); - dispatch({ - type: types.VOTE_AGAINST_MILESTONE_PAYOUT_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } - }; -} - -export function voteRefund(proposal: ProposalWithCrowdFund, vote: boolean) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: types.VOTE_REFUND_PENDING }); - const state = getState(); - const account = state.web3.accounts[0]; - const { proposalAddress, proposalId } = proposal; - const crowdFundContract = await getCrowdFundContract(getWeb3(), proposalAddress); - - try { - await crowdFundContract.methods - .voteRefund(vote) - .send({ from: account }) - .once('confirmation', async () => { - await sleep(5000); - await dispatch(fetchProposal(proposalId)); - dispatch({ type: types.VOTE_REFUND_FULFILLED }); - }); - } catch (err) { - dispatch({ - type: types.VOTE_REFUND_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } - }; -} - -async function freezeContract(crowdFundContract: any, account: string) { - let isFrozen = await crowdFundContract.methods.frozen().call({ from: account }); - // Already frozen, all good here - if (isFrozen) { - return; - } - - await new Promise((resolve, reject) => { - crowdFundContract.methods - .refund() - .send({ from: account }) - .once('confirmation', async () => { - await sleep(5000); - isFrozen = await crowdFundContract.methods.frozen().call({ from: account }); - resolve(); - }) - .catch((err: Error) => reject(err)); - }); - if (!isFrozen) { - throw new Error('Proposal isn’t in a refundable state yet.'); - } -} - -export function triggerRefund(proposal: ProposalWithCrowdFund) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: types.WITHDRAW_REFUND_PENDING }); - const state = getState(); - const account = state.web3.accounts[0]; - const { proposalAddress, proposalId } = proposal; - const crowdFundContract = await getCrowdFundContract(getWeb3(), proposalAddress); - - try { - await freezeContract(crowdFundContract, account); - await dispatch(fetchProposal(proposalId)); - dispatch({ type: types.TRIGGER_REFUND_FULFILLED }); - } catch (err) { - dispatch({ - type: types.TRIGGER_REFUND_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } - }; -} - -export function withdrawRefund(proposal: ProposalWithCrowdFund, address: string) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: types.WITHDRAW_REFUND_PENDING }); - const state = getState(); - const account = state.web3.accounts[0]; - const { proposalAddress, proposalId } = proposal; - const crowdFundContract = await getCrowdFundContract(getWeb3(), proposalAddress); - - try { - await freezeContract(crowdFundContract, account); - await crowdFundContract.methods - .withdraw(address) - .send({ from: account }) - .once('confirmation', async () => { - await sleep(5000); - await dispatch(fetchProposal(proposalId)); - dispatch({ type: types.WITHDRAW_REFUND_FULFILLED }); - }); - } catch (err) { - dispatch({ - type: types.WITHDRAW_REFUND_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } - }; -} - -// TODO: Fill out params with typed data -export function signData(data: object, dataTypes: object, primaryType: string) { - return async (dispatch: Dispatch, getState: GetState) => { - dispatch({ type: types.SIGN_DATA_PENDING }); - const state = getState(); - const { accounts } = state.web3; - const web3 = getWeb3(); - - return new Promise(async (resolve, reject) => { - const handleErr = (err: any) => { - console.error(err); - dispatch({ - type: types.SIGN_DATA_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - reject(err); - }; - - try { - const chainId = await web3.eth.net.getId(); - const rawTypedData = { - domain: { - name: 'Grant.io', - version: 1, - chainId, - }, - types: { - ...dataTypes, - EIP712Domain: [ - { name: 'name', type: 'string' }, - { name: 'version', type: 'string' }, - { name: 'chainId', type: 'uint256' }, - ], - }, - message: data, - primaryType, - }; - - (web3.currentProvider as any).send( - { - method: 'eth_signTypedData_v3', - params: [accounts[0], JSON.stringify(rawTypedData)], - from: accounts[0], - }, - (err: Error | undefined, res: any) => { - if (err) { - return handleErr(err); - } - if (res.error) { - const msg = web3ErrorToString(res.error); - return handleErr(new Error(msg)); - } - const payload: AuthSignatureData = { - signedMessage: res.result, - rawTypedData, - }; - dispatch({ type: types.SIGN_DATA_FULFILLED, payload }); - resolve(payload); - }, - ); - } catch (err) { - handleErr(err); - } - }); - }; -} diff --git a/frontend/client/modules/web3/index.ts b/frontend/client/modules/web3/index.ts deleted file mode 100644 index ee55c51a..00000000 --- a/frontend/client/modules/web3/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -import reducers, { Web3State, INITIAL_STATE } from './reducers'; -import * as web3Actions from './actions'; -import * as web3Types from './types'; -import web3Sagas from './sagas'; - -export { web3Actions, web3Types, web3Sagas, Web3State, INITIAL_STATE }; - -export default reducers; diff --git a/frontend/client/modules/web3/reducers.ts b/frontend/client/modules/web3/reducers.ts deleted file mode 100644 index 7aa6415c..00000000 --- a/frontend/client/modules/web3/reducers.ts +++ /dev/null @@ -1,216 +0,0 @@ -import types from './types'; - -export interface Web3State { - isMissingWeb3: boolean; - isWrongNetwork: boolean; - isWeb3Locked: boolean; - - isEnablingWeb3: boolean; - web3EnableError: null | string; - - accounts: any[]; - accountsLoading: boolean; - accountsError: null | string; - - sendLoading: boolean; - sendError: null | string; - - crowdFundLoading: boolean; - crowdFundError: string | null; - crowdFundCreatedAddress: string | null; - - isMilestoneActionPending: boolean; - milestoneActionError: null | string; - - isRefundActionPending: boolean; - refundActionError: null | string; -} - -export const INITIAL_STATE: Web3State = { - isMissingWeb3: false, - isWrongNetwork: false, - isWeb3Locked: false, - - isEnablingWeb3: false, - web3EnableError: null, - - accounts: [], - accountsLoading: false, - accountsError: null, - - sendLoading: false, - sendError: null, - - crowdFundLoading: false, - crowdFundError: null, - crowdFundCreatedAddress: null, - - isMilestoneActionPending: false, - milestoneActionError: null, - - isRefundActionPending: false, - refundActionError: null, -}; - -export default (state = INITIAL_STATE, action: any): Web3State => { - const { payload } = action; - - switch (action.type) { - case types.WEB3_FULFILLED: - return { - ...state, - isMissingWeb3: false, - }; - case types.WEB3_REJECTED: - return { - ...state, - isMissingWeb3: true, - }; - - case types.ENABLE_WEB3_PENDING: - return { - ...state, - isEnablingWeb3: true, - }; - case types.ENABLE_WEB3_FULFILLED: - return { - ...state, - isEnablingWeb3: false, - }; - case types.ENABLE_WEB3_REJECTED: - return { - ...state, - isEnablingWeb3: false, - web3EnableError: action.payload, - }; - - case types.CROWD_FUND_PENDING: - return { - ...state, - crowdFundLoading: true, - crowdFundError: null, - }; - case types.CROWD_FUND_CREATED: - return { - ...state, - crowdFundLoading: false, - crowdFundCreatedAddress: payload, - }; - case types.CROWD_FUND_REJECTED: - return { - ...state, - crowdFundLoading: false, - crowdFundError: payload, - }; - case types.RESET_CROWD_FUND: - return { - ...state, - crowdFundLoading: false, - crowdFundError: null, - crowdFundCreatedAddress: null, - }; - - case types.ACCOUNTS_PENDING: - return { - ...state, - accounts: [], - accountsLoading: true, - accountsError: null, - }; - case types.ACCOUNTS_FULFILLED: - return { - ...state, - accounts: payload, - accountsLoading: false, - isWeb3Locked: false, - }; - case types.ACCOUNTS_REJECTED: - return { - ...state, - accountsLoading: false, - accountsError: payload, - }; - - case types.SEND_PENDING: - return { - ...state, - sendError: null, - sendLoading: true, - }; - case types.SEND_FULFILLED: - return { - ...state, - sendLoading: false, - }; - case types.SEND_REJECTED: - return { - ...state, - sendLoading: false, - sendError: action.payload, - }; - - case types.SET_WRONG_NETWORK: - return { - ...state, - isWrongNetwork: true, - }; - case types.SET_WEB3_LOCKED: - return { - ...state, - isWeb3Locked: true, - }; - - case types.PAY_MILESTONE_PAYOUT_PENDING: - case types.REQUEST_MILESTONE_PAYOUT_PENDING: - case types.VOTE_AGAINST_MILESTONE_PAYOUT_PENDING: - return { - ...state, - milestoneActionError: null, - isMilestoneActionPending: true, - }; - - case types.PAY_MILESTONE_PAYOUT_FULFILLED: - case types.REQUEST_MILESTONE_PAYOUT_FULFILLED: - case types.VOTE_AGAINST_MILESTONE_PAYOUT_FULFILLED: - return { - ...state, - isMilestoneActionPending: false, - }; - - case types.PAY_MILESTONE_PAYOUT_REJECTED: - case types.REQUEST_MILESTONE_PAYOUT_REJECTED: - case types.VOTE_AGAINST_MILESTONE_PAYOUT_REJECTED: - return { - ...state, - milestoneActionError: payload, - isMilestoneActionPending: false, - }; - - case types.VOTE_REFUND_PENDING: - case types.WITHDRAW_REFUND_PENDING: - case types.TRIGGER_REFUND_PENDING: - return { - ...state, - isRefundActionPending: true, - refundActionError: null, - }; - case types.VOTE_REFUND_FULFILLED: - case types.WITHDRAW_REFUND_FULFILLED: - case types.TRIGGER_REFUND_FULFILLED: - return { - ...state, - isRefundActionPending: false, - }; - case types.VOTE_REFUND_REJECTED: - case types.WITHDRAW_REFUND_REJECTED: - case types.TRIGGER_REFUND_REJECTED: - return { - ...state, - refundActionError: payload, - isRefundActionPending: false, - }; - - default: - return state; - } -}; diff --git a/frontend/client/modules/web3/sagas.ts b/frontend/client/modules/web3/sagas.ts deleted file mode 100644 index a4ed337c..00000000 --- a/frontend/client/modules/web3/sagas.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { SagaIterator } from 'redux-saga'; -import { all, call, fork, put, select, take, takeLatest } from 'redux-saga/effects'; -import { checkNetwork, setAccounts, setWeb3 } from './actions'; -import { safeEnable } from 'utils/web3'; -import types from './types'; -import { selectIsMissingWeb3 } from 'modules/web3/selectors'; - -export function* bootstrapWeb3(): SagaIterator { - // Don't attempt to bootstrap web3 on SSR - if (process.env.SERVER_SIDE_RENDER) { - return; - } - yield put(setWeb3()); - yield take(types.WEB3_FULFILLED); - - yield all([put(setAccounts()), put(checkNetwork())]); -} - -export function* handleEnableWeb3(): SagaIterator { - const isMissingWeb3 = yield select(selectIsMissingWeb3); - - try { - if (isMissingWeb3) { - const web3Action = yield take([types.WEB3_FULFILLED, types.WEB3_REJECTED]); - if (web3Action.type === types.WEB3_REJECTED) { - throw new Error('No web3 instance available'); - } - } - - yield call(safeEnable); - yield put(setAccounts()); - yield put({ type: types.ENABLE_WEB3_FULFILLED }); - } catch (err) { - yield put({ - type: types.ENABLE_WEB3_REJECTED, - payload: err.message || err.toString(), - error: true, - }); - } -} - -export default function* authSaga(): SagaIterator { - yield all([fork(bootstrapWeb3)]); - yield takeLatest(types.ENABLE_WEB3_PENDING, handleEnableWeb3); -} diff --git a/frontend/client/modules/web3/selectors.ts b/frontend/client/modules/web3/selectors.ts deleted file mode 100644 index f140d231..00000000 --- a/frontend/client/modules/web3/selectors.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { AppState } from 'store/reducers'; - -export function selectIsMissingWeb3(state: AppState) { - return state.web3.isMissingWeb3; -} diff --git a/frontend/client/modules/web3/types.ts b/frontend/client/modules/web3/types.ts deleted file mode 100644 index 552ebbfc..00000000 --- a/frontend/client/modules/web3/types.ts +++ /dev/null @@ -1,73 +0,0 @@ -enum web3Types { - WEB3 = 'WEB3', - WEB3_FULFILLED = 'WEB3_FULFILLED', - WEB3_REJECTED = 'WEB3_REJECTED', - WEB3_PENDING = 'WEB3_PENDING', - - ENABLE_WEB3 = 'ENABLE_WEB3', - ENABLE_WEB3_PENDING = 'ENABLE_WEB3_PENDING', - ENABLE_WEB3_REJECTED = 'ENABLE_WEB3_REJECTED', - ENABLE_WEB3_FULFILLED = 'ENABLE_WEB3_FULFILLED', - - CONTRACT = 'CONTRACT', - CONTRACT_FULFILLED = 'CONTRACT_FULFILLED', - CONTRACT_REJECTED = 'CONTRACT_REJECTED', - CONTRACT_PENDING = 'CONTRACT_PENDING', - - CROWD_FUND = 'CROWD_FUND', - CROWD_FUND_FULFILLED = 'CROWD_FUND_FULFILLED', - CROWD_FUND_REJECTED = 'CROWD_FUND_REJECTED', - CROWD_FUND_PENDING = 'CROWD_FUND_PENDING', - CROWD_FUND_CREATED = 'CROWD_FUND_CREATED', - RESET_CROWD_FUND = 'RESET_CROWD_FUND', - - SEND = 'SEND', - SEND_FULFILLED = 'SEND_FULFILLED', - SEND_REJECTED = 'SEND_REJECTED', - SEND_PENDING = 'SEND_PENDING', - - PAY_MILESTONE_PAYOUT = 'PAY_MILESTONE_PAYOUT', - PAY_MILESTONE_PAYOUT_FULFILLED = 'PAY_MILESTONE_PAYOUT_FULFILLED', - PAY_MILESTONE_PAYOUT_REJECTED = 'PAY_MILESTONE_PAYOUT_REJECTED', - PAY_MILESTONE_PAYOUT_PENDING = 'PAY_MILESTONE_PAYOUT_PENDING', - - REQUEST_MILESTONE_PAYOUT = 'REQUEST_MILESTONE_PAYOUT', - REQUEST_MILESTONE_PAYOUT_FULFILLED = 'REQUEST_MILESTONE_PAYOUT_FULFILLED', - REQUEST_MILESTONE_PAYOUT_REJECTED = 'REQUEST_MILESTONE_PAYOUT_REJECTED', - REQUEST_MILESTONE_PAYOUT_PENDING = 'REQUEST_MILESTONE_PAYOUT_PENDING', - - VOTE_AGAINST_MILESTONE_PAYOUT = 'VOTE_AGAINST_MILESTONE_PAYOUT', - VOTE_AGAINST_MILESTONE_PAYOUT_FULFILLED = 'VOTE_AGAINST_MILESTONE_PAYOUT_FULFILLED', - VOTE_AGAINST_MILESTONE_PAYOUT_REJECTED = 'VOTE_AGAINST_MILESTONE_PAYOUT_REJECTED', - VOTE_AGAINST_MILESTONE_PAYOUT_PENDING = 'VOTE_AGAINST_MILESTONE_PAYOUT_PENDING', - - VOTE_REFUND = 'VOTE_REFUND', - VOTE_REFUND_FULFILLED = 'VOTE_REFUND_FULFILLED', - VOTE_REFUND_REJECTED = 'VOTE_REFUND_REJECTED', - VOTE_REFUND_PENDING = 'VOTE_REFUND_PENDING', - - WITHDRAW_REFUND = 'WITHDRAW_REFUND', - WITHDRAW_REFUND_FULFILLED = 'WITHDRAW_REFUND_FULFILLED', - WITHDRAW_REFUND_REJECTED = 'WITHDRAW_REFUND_REJECTED', - WITHDRAW_REFUND_PENDING = 'WITHDRAW_REFUND_PENDING', - - TRIGGER_REFUND = 'TRIGGER_REFUND', - TRIGGER_REFUND_FULFILLED = 'TRIGGER_REFUND_FULFILLED', - TRIGGER_REFUND_REJECTED = 'TRIGGER_REFUND_REJECTED', - TRIGGER_REFUND_PENDING = 'TRIGGER_REFUND_PENDING', - - ACCOUNTS = 'ACCOUNTS', - ACCOUNTS_FULFILLED = 'ACCOUNTS_FULFILLED', - ACCOUNTS_REJECTED = 'ACCOUNTS_REJECTED', - ACCOUNTS_PENDING = 'ACCOUNTS_PENDING', - - SIGN_DATA = 'SIGN_DATA', - SIGN_DATA_FULFILLED = 'SIGN_DATA_FULFILLED', - SIGN_DATA_REJECTED = 'SIGN_DATA_REJECTED', - SIGN_DATA_PENDING = 'SIGN_DATA_PENDING', - - SET_WRONG_NETWORK = 'SET_WRONG_NETWORK', - SET_WEB3_LOCKED = 'SET_WEB3_LOCKED', -} - -export default web3Types; diff --git a/frontend/client/pages/settings.tsx b/frontend/client/pages/settings.tsx index 0df42939..6664ce0a 100644 --- a/frontend/client/pages/settings.tsx +++ b/frontend/client/pages/settings.tsx @@ -1,16 +1,2 @@ -import React from 'react'; -import { connect } from 'react-redux'; -import { AppState } from 'store/reducers'; - -interface Props { - user: AppState['auth']['user']; -} - -class ProfilePage extends React.Component { - render() { - const { user } = this.props; - return

Settings for {user && user.displayName}

; - } -} - -export default connect((state: AppState) => ({ user: state.auth.user }))(ProfilePage); +import Settings from 'components/Settings'; +export default Settings; diff --git a/frontend/client/pages/sign-out.tsx b/frontend/client/pages/sign-out.tsx index cafc1a51..71a0801d 100644 --- a/frontend/client/pages/sign-out.tsx +++ b/frontend/client/pages/sign-out.tsx @@ -23,7 +23,7 @@ class SignInPage extends React.Component { <> diff --git a/frontend/client/store/configure.tsx b/frontend/client/store/configure.tsx index 76da3a24..07fd82cc 100644 --- a/frontend/client/store/configure.tsx +++ b/frontend/client/store/configure.tsx @@ -8,7 +8,7 @@ import { routerMiddleware } from 'connected-react-router'; import rootReducer, { AppState, combineInitialState } from './reducers'; import rootSaga from './sagas'; import history from './history'; -import axios from 'api/axios'; +// import axios from 'api/axios'; const sagaMiddleware = createSagaMiddleware(); @@ -51,24 +51,5 @@ export function configureStore(initialState: Partial = combineInitialS } } - // Any global listeners to the store go here - let prevState = store.getState(); - store.subscribe(() => { - const state = store.getState(); - - // Setup the API with auth credentials whenever they change - const { authSignature } = state.auth; - if (authSignature !== prevState.auth.authSignature) { - axios.defaults.headers.common.MsgSignature = authSignature - ? authSignature.signedMessage - : undefined; - axios.defaults.headers.common.RawTypedData = authSignature - ? JSON.stringify(authSignature.rawTypedData) - : undefined; - } - - prevState = state; - }); - return { store, persistor }; } diff --git a/frontend/client/store/reducers.tsx b/frontend/client/store/reducers.tsx index e649b5cd..9713b8c6 100644 --- a/frontend/client/store/reducers.tsx +++ b/frontend/client/store/reducers.tsx @@ -1,7 +1,6 @@ import { combineReducers, Reducer } from 'redux'; import { connectRouter, RouterState } from 'connected-react-router'; import { persistReducer } from 'redux-persist'; -import web3, { Web3State, INITIAL_STATE as web3InitialState } from 'modules/web3'; import proposal, { ProposalState, INITIAL_STATE as proposalInitialState, @@ -17,7 +16,6 @@ import history from './history'; export interface AppState { proposal: ProposalState; - web3: Web3State; create: CreateState; users: UsersState; auth: AuthState; @@ -26,7 +24,6 @@ export interface AppState { export const combineInitialState: Partial = { proposal: proposalInitialState, - web3: web3InitialState, create: createInitialState, users: usersInitialState, auth: authInitialState, @@ -34,7 +31,6 @@ export const combineInitialState: Partial = { export default combineReducers({ proposal, - web3, create, users, // Don't allow for redux-persist's _persist key to be touched in our code diff --git a/frontend/client/store/sagas.ts b/frontend/client/store/sagas.ts index 10db04e5..27348b0f 100644 --- a/frontend/client/store/sagas.ts +++ b/frontend/client/store/sagas.ts @@ -1,10 +1,8 @@ import { fork } from 'redux-saga/effects'; import { authSagas } from 'modules/auth'; -import { web3Sagas } from 'modules/web3'; import { createSagas } from 'modules/create'; export default function* rootSaga() { yield fork(authSagas); - yield fork(web3Sagas); yield fork(createSagas); } diff --git a/frontend/client/styles/antd-overrides.less b/frontend/client/styles/antd-overrides.less index 93554e38..88e67219 100644 --- a/frontend/client/styles/antd-overrides.less +++ b/frontend/client/styles/antd-overrides.less @@ -1,5 +1,13 @@ +@import 'variables.less'; + // Forms +.ant-form-item-label { + line-height: 1rem; +} .ant-form-label label, .ant-form-item-label label { font-size: 1rem; -} \ No newline at end of file +} +.ant-form-item-required:before { + color: @primary-color; +} diff --git a/frontend/client/utils/auth.ts b/frontend/client/utils/auth.ts deleted file mode 100644 index a97c3db5..00000000 --- a/frontend/client/utils/auth.ts +++ /dev/null @@ -1,56 +0,0 @@ -export enum AUTH_PROVIDER { - WEB3 = 'WEB3', - LEDGER = 'LEDGER', - TREZOR = 'TREZOR', - ADDRESS = 'ADDRESS', -} - -interface AuthProvider { - type: AUTH_PROVIDER; - name: string; - canSignMessage: boolean; -} - -export const AUTH_PROVIDERS: { [key in AUTH_PROVIDER]: AuthProvider } = { - [AUTH_PROVIDER.WEB3]: { - type: AUTH_PROVIDER.WEB3, - name: 'MetaMask', // TODO: Set dynamically based on provider - canSignMessage: true, - }, - [AUTH_PROVIDER.LEDGER]: { - type: AUTH_PROVIDER.LEDGER, - name: 'Ledger', - canSignMessage: true, - }, - [AUTH_PROVIDER.TREZOR]: { - type: AUTH_PROVIDER.TREZOR, - name: 'TREZOR', - canSignMessage: true, - }, - [AUTH_PROVIDER.ADDRESS]: { - type: AUTH_PROVIDER.ADDRESS, - name: 'Address', - canSignMessage: false, - }, -}; - -export function generateAuthSignatureData(address: string) { - const message = `I am proving the identity of ${address} on Grant.io`; - const time = new Date().toUTCString(); - return { - data: { message, time }, - types: { - authorization: [ - { - name: 'Message Proof', - type: 'string', - }, - { - name: 'Time', - type: 'string', - }, - ], - }, - primaryType: 'authorization', - }; -} diff --git a/frontend/client/utils/s3.ts b/frontend/client/utils/s3.ts new file mode 100644 index 00000000..46d9a869 --- /dev/null +++ b/frontend/client/utils/s3.ts @@ -0,0 +1,25 @@ +export const uploadSignedPost = (file: Blob, s3Data: any) => + new Promise((res, rej) => { + const xhr = new XMLHttpRequest(); + xhr.open('POST', s3Data.url); + + const postData = new FormData(); + for (const key in s3Data.fields) { + if (s3Data.fields[key]) { + postData.append(key, s3Data.fields[key]); + } + } + postData.append('file', file); + + xhr.onreadystatechange = () => { + if (xhr.readyState === 4) { + if (xhr.status === 200 || xhr.status === 204) { + res(); + } else { + rej({ message: `S3 Upload Problem: ${xhr.statusText} (${xhr.status})` }); + } + } + }; + + xhr.send(postData); + }); diff --git a/frontend/client/utils/units.ts b/frontend/client/utils/units.ts index d317a2b4..fd09a539 100644 --- a/frontend/client/utils/units.ts +++ b/frontend/client/utils/units.ts @@ -1,6 +1,5 @@ // From https://github.com/MyCryptoHQ/MyCrypto/blob/develop/common/libs/units.ts import BN from 'bn.js'; -import { toBuffer, addHexPrefix } from 'ethereumjs-util'; import { stripHexPrefix } from 'utils/formatters'; type UnitKey = keyof typeof Units; @@ -52,10 +51,6 @@ const handleValues = (input: string | BN) => { } }; -const Address = (input: string) => toBuffer(addHexPrefix(input)); - -const Data = (input: string) => toBuffer(addHexPrefix(input)); - const Nonce = (input: string | BN) => handleValues(input); const Wei = (input: string | BN): Wei => handleValues(input); diff --git a/frontend/client/utils/validators.ts b/frontend/client/utils/validators.ts index 3e2875a2..2c61f114 100644 --- a/frontend/client/utils/validators.ts +++ b/frontend/client/utils/validators.ts @@ -1,5 +1,3 @@ -import { toChecksumAddress } from 'ethereumjs-util'; - export function getAmountError(amount: number, max: number = Infinity) { if (amount < 0) { return 'Amount must be a positive number'; @@ -15,21 +13,11 @@ export function getAmountError(amount: number, max: number = Infinity) { return null; } -export function isValidEthAddress(addr: string): boolean { - if (addr === '0x0000000000000000000000000000000000000000') { - return false; - } - if (addr.substring(0, 2) !== '0x') { - return false; - } else if (!/^(0x)?[0-9a-f]{40}$/i.test(addr)) { - return false; - } else if (/^(0x)?[0-9a-f]{40}$/.test(addr) || /^(0x)?[0-9A-F]{40}$/.test(addr)) { - return true; - } else { - return addr === toChecksumAddress(addr); - } -} - export function isValidEmail(email: string): boolean { return /\S+@\S+\.\S+/.test(email); } + +export function isValidAddress(address: string): boolean { + console.warn('TODO - implement utils.isValidAddress', address); + return true; +} diff --git a/frontend/client/utils/wallet.ts b/frontend/client/utils/wallet.ts deleted file mode 100644 index d17ba349..00000000 --- a/frontend/client/utils/wallet.ts +++ /dev/null @@ -1,79 +0,0 @@ -import HDKey from 'hdkey'; -import { pubToAddress, toChecksumAddress } from 'ethereumjs-util'; - -interface DeriveAddressesParams { - chainCode: string; - publicKey: string; - index: number; - numAddresses: number; -} -export function deriveAddressesFromPubKey(params: DeriveAddressesParams): string[] { - const addresses = []; - const hdkey = new HDKey(); - hdkey.chainCode = new Buffer(params.chainCode, 'hex'); - hdkey.publicKey = new Buffer(params.publicKey, 'hex'); - - for (let i = params.index; i < params.index + params.numAddresses; i++) { - const dkey = hdkey.derive(`m/${i}`); - const address = (pubToAddress(dkey.publicKey, true) as Buffer).toString('hex'); - addresses.push(toChecksumAddress(address)); - } - - return addresses; -} - -// Ledger throws a few types of errors -interface U2FError { - metaData: { - type: string; - code: number; - }; -} -interface ErrorWithId { - id: string; - message: string; - name: string; - stack: string; -} -type LedgerError = U2FError | ErrorWithId | Error | string; - -const isU2FError = (err: LedgerError): err is U2FError => - !!err && !!(err as U2FError).metaData; -const isStringError = (err: LedgerError): err is string => typeof err === 'string'; -const isErrorWithId = (err: LedgerError): err is ErrorWithId => - err.hasOwnProperty('id') && err.hasOwnProperty('message'); - -export function parseLedgerError(err: LedgerError): string { - // https://developers.yubico.com/U2F/Libraries/Client_error_codes.html - if (isU2FError(err)) { - // Timeout - if (err.metaData.code === 5) { - return 'The request timed out'; - } - - return err.metaData.type; - } - - if (isStringError(err)) { - // Wrong app logged into - if (err.includes('6804')) { - return 'Wrong application selected on your ledger device. Make sure you’ve selected the ETH app.'; - } - // Ledger locked - if (err.includes('6801')) { - return 'Your Ledger device is locked'; - } - - return err; - } - - if (isErrorWithId(err)) { - // Browser doesn't support U2F - if (err.message.includes('U2F not supported')) { - return 'Your browser doesn’t support Ledger. Please try updating it, or using a different one.'; - } - } - - // Other - return err.message || err.toString(); -} diff --git a/frontend/client/utils/web3.ts b/frontend/client/utils/web3.ts deleted file mode 100644 index 40595f5c..00000000 --- a/frontend/client/utils/web3.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { TransactionObject } from 'web3/eth/types'; - -type Web3Method = (index: number) => TransactionObject; - -export async function collectArrayElements( - method: Web3Method, - account: string, -): Promise { - const arrayElements = []; - let noError = true; - let index = 0; - while (noError) { - try { - arrayElements.push(await method(index).call({ from: account })); - index += 1; - } catch (e) { - noError = false; - } - } - return arrayElements; -} - -interface Web3ErrorResponse { - code: number; - message: string; -} - -export function web3ErrorToString(err: Web3ErrorResponse): string { - return err.message - .split('\n')[0] - .split(':') - .slice(-1)[0] - .trim(); -} - -export function safeEnable(): Promise { - const w = typeof window === 'undefined' ? {} : (window as any); - if (!w.ethereum || !w.ethereum.enable) { - return Promise.reject('No web3 client installed'); - } - - return w.ethereum.enable(); -} diff --git a/frontend/client/web3interact/crowdFund.ts b/frontend/client/web3interact/crowdFund.ts deleted file mode 100644 index a22c8bb1..00000000 --- a/frontend/client/web3interact/crowdFund.ts +++ /dev/null @@ -1,149 +0,0 @@ -import Web3 from 'web3'; -import { CrowdFund, Milestone, MILESTONE_STATE } from 'types'; -import { collectArrayElements } from 'utils/web3'; -import { Wei } from 'utils/units'; -import BN from 'bn.js'; - -export async function getCrowdFundState( - crowdFundContract: any, - account: string, - web3: Web3, -): Promise { - const immediateFirstMilestonePayout = await crowdFundContract.methods - .immediateFirstMilestonePayout() - .call({ from: account }); - const target = Wei(await crowdFundContract.methods.raiseGoal().call({ from: account })); - const beneficiary = await crowdFundContract.methods - .beneficiary() - .call({ from: account }); - const isRaiseGoalReached = await crowdFundContract.methods - .isRaiseGoalReached() - .call({ from: account }); - // Types are messed up, this returns a str, not a number - // https://web3js.readthedocs.io/en/1.0/web3-eth.html#getbalance - const balance = Wei((await web3.eth.getBalance(crowdFundContract._address)) as any); - const funded = isRaiseGoalReached ? target : balance; - const percentFunded = isRaiseGoalReached - ? 100 - : balance.divn(100).isZero() - ? 0 - : balance - .mul(new BN(100)) - .div(target) - .toNumber(); - const amountVotingForRefund = isRaiseGoalReached - ? Wei(await crowdFundContract.methods.amountVotingForRefund().call({ from: account })) - : Wei('0'); - const percentVotingForRefund = amountVotingForRefund.div(target.divn(100)).toNumber(); - - const isFrozen = await crowdFundContract.methods.frozen().call({ from: account }); - const trustees = await collectArrayElements( - crowdFundContract.methods.trustees, - account, - ); - - // Format milestones - const rawMilestones = await collectArrayElements( - crowdFundContract.methods.milestones, - account, - ); - - const milestones = rawMilestones.map( - (m: any, index): Milestone => { - const amount = Wei(m.amount); - const payoutRequestVoteDeadline = parseInt(m.payoutRequestVoteDeadline, 10) * 1000; - const amountAgainstPayout = Wei(m.amountVotingAgainstPayout); - const percentAgainstPayout = amountAgainstPayout.div(target.divn(100)).toNumber(); - - // Figure out state if they've raised - let state = MILESTONE_STATE.WAITING; - if (isRaiseGoalReached) { - if (payoutRequestVoteDeadline) { - if (m.paid) { - state = MILESTONE_STATE.PAID; - } else if (payoutRequestVoteDeadline > Date.now()) { - state = MILESTONE_STATE.ACTIVE; - } else if (percentAgainstPayout >= 50) { - state = MILESTONE_STATE.REJECTED; - } else { - // Deadline is over, but not rejected, means it's basically paid out. - // isPaid can be false, but the state be paid, if they haven't actually - // received the payment. - state = MILESTONE_STATE.PAID; - } - } - } - - return { - index, - state, - amount, - amountAgainstPayout, - percentAgainstPayout, - payoutRequestVoteDeadline, - isPaid: m.paid, - isImmediatePayout: index === 0 && immediateFirstMilestonePayout, - }; - }, - ); - - // Collect & format all contributors - const contributorAddresses = await collectArrayElements( - crowdFundContract.methods.contributorList, - account, - ); - - const contributors = await Promise.all( - contributorAddresses.map(async addr => { - const contributor = await crowdFundContract.methods - .contributors(addr) - .call({ from: account }); - contributor.address = addr; - contributor.milestoneNoVotes = await Promise.all( - milestones.map( - async (_, idx) => - await crowdFundContract.methods - .getContributorMilestoneVote(addr, idx) - .call({ form: account }), - ), - ); - contributor.contributionAmount = Wei( - await crowdFundContract.methods - .getContributorContributionAmount(addr) - .call({ from: account }), - ); - return contributor; - }), - ); - - // Convert to milliseconds - const milestoneVotingPeriod = - parseInt( - await crowdFundContract.methods.milestoneVotingPeriod().call({ from: account }), - 10, - ) * - 60 * - 1000; - - const deadline = - parseInt(await crowdFundContract.methods.deadline().call({ from: account }), 10) * - 1000; - - return { - immediateFirstMilestonePayout, - balance, - funded, - percentFunded, - target, - amountVotingForRefund, - percentVotingForRefund, - beneficiary, - deadline, - trustees, - contributors, - milestones, - isFrozen, - isRaiseGoalReached, - milestoneVotingPeriod, - }; -} diff --git a/frontend/config/env.js b/frontend/config/env.js index e45f5050..6556c5e6 100644 --- a/frontend/config/env.js +++ b/frontend/config/env.js @@ -40,14 +40,6 @@ envProductionRequiredHandler( 'PUBLIC_HOST_URL', 'http://localhost:' + (process.env.PORT || 3000), ); -envProductionRequiredHandler( - 'CROWD_FUND_URL', - 'https://eip-712.herokuapp.com/contract/crowd-fund', -); -envProductionRequiredHandler( - 'CROWD_FUND_FACTORY_URL', - 'https://eip-712.herokuapp.com/contract/factory', -); if (!process.env.BACKEND_URL) { process.env.BACKEND_URL = 'http://localhost:5000'; @@ -70,8 +62,6 @@ process.env.NODE_PATH = (process.env.NODE_PATH || '') module.exports = () => { const raw = { BACKEND_URL: process.env.BACKEND_URL, - CROWD_FUND_FACTORY_URL: process.env.CROWD_FUND_FACTORY_URL, - CROWD_FUND_URL: process.env.CROWD_FUND_URL, NODE_ENV: process.env.NODE_ENV || 'development', PORT: process.env.PORT || 3000, PUBLIC_HOST_URL: process.env.PUBLIC_HOST_URL, diff --git a/frontend/config/paths.js b/frontend/config/paths.js index a02d025d..e076b1f4 100644 --- a/frontend/config/paths.js +++ b/frontend/config/paths.js @@ -3,14 +3,11 @@ const fs = require('fs'); const findRoot = require('find-root'); const appDirectory = fs.realpathSync(process.cwd()); -// truffle exec cwd moves to called js, so make sure we are on root const appRoot = findRoot(appDirectory); const resolveApp = relativePath => path.resolve(appRoot, relativePath); const paths = { clientBuild: resolveApp('build/client'), - contractsBase: resolveApp('../contract'), - contractsBuild: resolveApp('../contract/build/contracts'), dotenv: resolveApp('.env'), logs: resolveApp('logs'), publicPath: '/static/', diff --git a/frontend/config/webpack.config.js/resolvers.js b/frontend/config/webpack.config.js/resolvers.js index 7afd58d5..181a9dee 100644 --- a/frontend/config/webpack.config.js/resolvers.js +++ b/frontend/config/webpack.config.js/resolvers.js @@ -5,7 +5,6 @@ module.exports = { modules: paths.resolveModules, // tsconfig.compilerOptions.paths should sync with these alias: { - contracts: paths.contractsBuild, // truffle build contracts dir api: `${paths.srcClient}/api`, components: `${paths.srcClient}/components`, lib: `${paths.srcClient}/lib`, @@ -17,6 +16,5 @@ module.exports = { typings: `${paths.srcClient}/typings`, types: `${paths.srcTypes}`, utils: `${paths.srcClient}/utils`, - web3interact: `${paths.srcClient}/web3interact`, }, }; diff --git a/frontend/package.json b/frontend/package.json index 009047f3..3e26e026 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -11,9 +11,6 @@ "now": "npm run build && now -e BACKEND_URL=https://grant-stage.herokuapp.com", "heroku-postbuild": "yarn build", "tsc": "tsc", - "link-contracts": "cd client/lib && ln -s ../../build/contracts contracts", - "ganache": "ganache-cli -b 5 -s testGrantIo -e 1000", - "truffle": "truffle exec ./bin/init-truffle.js && cd client/lib/contracts && truffle console", "storybook": "start-storybook -p 9001 -c .storybook" }, "engines": { @@ -42,8 +39,6 @@ "@babel/preset-react": "^7.0.0", "@babel/preset-typescript": "^7.0.0", "@babel/register": "^7.0.0", - "@ledgerhq/hw-app-eth": "4.23.0", - "@ledgerhq/hw-transport-u2f": "4.21.0", "@sentry/browser": "^4.3.2", "@sentry/node": "^4.3.2", "@svgr/webpack": "^2.4.0", @@ -69,6 +64,7 @@ "@types/recompose": "^0.26.1", "@types/redux-actions": "^2.3.0", "@types/redux-logger": "^3.0.6", + "@types/underscore": "^1.8.9", "@types/webpack": "4.4.17", "@types/webpack-env": "^1.13.6", "@types/winston": "^2.4.4", @@ -92,8 +88,6 @@ "cors": "^2.8.4", "css-loader": "^1.0.0", "dotenv": "^6.0.0", - "ethereum-blockies-base64": "1.0.2", - "ethereumjs-util": "5.2.0", "express": "^4.16.3", "express-manifest-helpers": "^0.5.0", "express-sslify": "^1.2.0", @@ -104,7 +98,6 @@ "fork-ts-checker-webpack-plugin": "^0.4.2", "fs-extra": "^7.0.0", "global": "4.3.2", - "hdkey": "1.1.0", "history": "4.7.2", "http-proxy-middleware": "^0.18.0", "https-proxy": "0.0.2", @@ -147,7 +140,6 @@ "showdown": "^1.8.6", "stats-webpack-plugin": "^0.7.0", "style-loader": "^0.23.0", - "trezor-connect": "5.0.33", "ts-loader": "^5.1.1", "tslint": "^5.10.0", "tslint-config-airbnb": "^5.9.2", @@ -156,8 +148,8 @@ "tslint-react": "^3.6.0", "typescript": "3.0.3", "uglifyjs-webpack-plugin": "1.3.0", + "underscore": "^1.9.1", "url-loader": "^1.1.1", - "web3": "^1.0.0-beta.34", "webpack": "^4.19.0", "webpack-bundle-analyzer": "^3.0.2", "webpack-cli": "^3.1.0", @@ -173,12 +165,9 @@ "devDependencies": { "@storybook/react": "4.0.0-alpha.22", "@types/bn.js": "4.11.1", - "@types/ethereumjs-util": "5.2.0", - "@types/hdkey": "0.7.0", "@types/query-string": "6.1.0", "@types/showdown": "1.7.5", "@types/storybook__react": "^3.0.9", - "@types/web3": "1.0.3", "rimraf": "2.6.2", "string-hash": "1.1.3", "webapp-webpack-plugin": "2.3.1" diff --git a/frontend/stories/UserRow.story.tsx b/frontend/stories/UserRow.story.tsx index 71d64f60..004dd200 100644 --- a/frontend/stories/UserRow.story.tsx +++ b/frontend/stories/UserRow.story.tsx @@ -1,7 +1,6 @@ import * as React from 'react'; import { BrowserRouter } from 'react-router-dom'; import { storiesOf } from '@storybook/react'; -import { DONATION } from 'utils/constants'; import { User } from 'types'; import 'components/UserRow/style.less'; @@ -14,7 +13,6 @@ const user: User = { avatar: { imageUrl: 'https://randomuser.me/api/portraits/women/19.jpg', }, - accountAddress: DONATION.ETH, emailAddress: 'test@test.test', socialMedias: [], }; @@ -50,7 +48,6 @@ const cases: Case[] = [ user: { ...user, avatar: null, - accountAddress: '', }, }, }, diff --git a/frontend/stories/props.tsx b/frontend/stories/props.tsx index 82909485..27ef22d8 100644 --- a/frontend/stories/props.tsx +++ b/frontend/stories/props.tsx @@ -6,13 +6,6 @@ import { ProposalMilestone, } from 'types'; import { PROPOSAL_CATEGORY } from 'api/constants'; -import { - fundCrowdFund, - requestMilestonePayout, - payMilestonePayout, - voteMilestonePayout, -} from 'modules/web3/actions'; -import Web3 from 'web3'; import BN from 'bn.js'; const oneEth = new BN('1000000000000000000'); @@ -30,9 +23,6 @@ export function getGovernanceMilestonesProps({ ], isMilestoneActionPending: false, milestoneActionError: '', - requestMilestonePayout, - payMilestonePayout, - voteMilestonePayout, }; } @@ -170,7 +160,6 @@ export function getProposalWithCrowdFund({ userid: 123, displayName: 'Test Proposer', title: '', - accountAddress: '0x0c7C6178AD0618Bf289eFd5E1Ff9Ada25fC3bDE7', emailAddress: '', avatar: null, socialMedias: [], @@ -179,7 +168,6 @@ export function getProposalWithCrowdFund({ userid: 456, displayName: 'Test Proposer', title: '', - accountAddress: '0x4bbeEB066eD09B7AEd07bF39EEe0460DFa261520', emailAddress: '', avatar: null, socialMedias: [], @@ -188,7 +176,6 @@ export function getProposalWithCrowdFund({ userid: 789, displayName: 'Test Proposer', title: '', - accountAddress: '0x529104532a9779ea9eae0c1e325b3368e0f8add4', emailAddress: '', avatar: null, socialMedias: [], @@ -220,8 +207,6 @@ export function getProposalWithCrowdFund({ const props = { sendLoading: false, - fundCrowdFund, - web3: new Web3(), isMissingWeb3: false, proposal, ...proposal, // yeah... diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json index 712aa193..32047138 100644 --- a/frontend/tsconfig.json +++ b/frontend/tsconfig.json @@ -19,7 +19,6 @@ "baseUrl": ".", "lib": ["dom", "es2017"], "paths": { - "contracts/*": ["../contract/build/contracts/*"], "api/*": ["./client/api/*"], "components/*": ["./client/components/*"], "lib/*": ["./client/lib/*"], @@ -30,8 +29,7 @@ "styles/*": ["./client/styles/*"], "typings/*": ["./client/typings/*"], "types/*": ["./types/*"], - "utils/*": ["./client/utils/*"], - "web3interact/*": ["./client/web3interact/*"] + "utils/*": ["./client/utils/*"] } }, "include": ["./client/**/*", "./server/**/*", "./stories/**/*", "./types/**/*"], diff --git a/frontend/types/user.ts b/frontend/types/user.ts index cfd42221..2fea8ef9 100644 --- a/frontend/types/user.ts +++ b/frontend/types/user.ts @@ -2,8 +2,7 @@ import { SocialMedia } from 'types'; export interface User { userid: number; - accountAddress: string; - emailAddress: string; // TODO: Split into full user type + emailAddress?: string; // TODO: Split into full user type displayName: string; title: string; socialMedias: SocialMedia[]; diff --git a/frontend/yarn.lock b/frontend/yarn.lock index 7218fc31..487c08c9 100644 --- a/frontend/yarn.lock +++ b/frontend/yarn.lock @@ -1564,25 +1564,6 @@ dependencies: core-js "^2.5.7" -"@ledgerhq/hw-app-eth@4.23.0": - version "4.23.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-app-eth/-/hw-app-eth-4.23.0.tgz#f253faf56143403182b9701fb0b6454c255de7ff" - dependencies: - "@ledgerhq/hw-transport" "^4.21.0" - -"@ledgerhq/hw-transport-u2f@4.21.0": - version "4.21.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport-u2f/-/hw-transport-u2f-4.21.0.tgz#85695d7e853a5c21af7e7dcb0ce3919f2b65cdd9" - dependencies: - "@ledgerhq/hw-transport" "^4.21.0" - u2f-api "0.2.7" - -"@ledgerhq/hw-transport@^4.21.0": - version "4.21.0" - resolved "https://registry.yarnpkg.com/@ledgerhq/hw-transport/-/hw-transport-4.21.0.tgz#50f85cfe115ba3f9d5bf94755c701e927175794f" - dependencies: - events "^2.0.0" - "@mrmlnc/readdir-enhanced@^2.2.1": version "2.2.1" resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" @@ -1883,7 +1864,7 @@ "@svgr/core" "^2.4.0" loader-utils "^1.1.0" -"@types/bn.js@*", "@types/bn.js@4.11.1": +"@types/bn.js@4.11.1": version "4.11.1" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.1.tgz#6fd07b93490ecf0f3501a31ea9cfd330885b10fa" dependencies: @@ -1922,13 +1903,6 @@ dependencies: "@types/node" "*" -"@types/ethereumjs-util@5.2.0": - version "5.2.0" - resolved "https://registry.yarnpkg.com/@types/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#f49fe8114789ec0871721392c09318c3eb56671b" - dependencies: - "@types/bn.js" "*" - "@types/node" "*" - "@types/events@*": version "1.2.0" resolved "https://registry.yarnpkg.com/@types/events/-/events-1.2.0.tgz#81a6731ce4df43619e5c8c945383b3e62a89ea86" @@ -1956,12 +1930,6 @@ "@types/express-serve-static-core" "*" "@types/serve-static" "*" -"@types/hdkey@0.7.0": - version "0.7.0" - resolved "https://registry.yarnpkg.com/@types/hdkey/-/hdkey-0.7.0.tgz#6734d138e3c597f241be8fae2e60c2949bc3af87" - dependencies: - "@types/node" "*" - "@types/history@*": version "4.7.0" resolved "https://registry.yarnpkg.com/@types/history/-/history-4.7.0.tgz#2fac51050c68f7d6f96c5aafc631132522f4aa3f" @@ -2132,16 +2100,10 @@ dependencies: source-map "^0.6.1" -"@types/underscore@*": +"@types/underscore@^1.8.9": version "1.8.9" resolved "https://registry.yarnpkg.com/@types/underscore/-/underscore-1.8.9.tgz#fef41f800cd23db1b4f262ddefe49cd952d82323" - -"@types/web3@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@types/web3/-/web3-1.0.3.tgz#2c5f6905d46eb6e40da8eb7c1e553463862fa599" - dependencies: - "@types/bn.js" "*" - "@types/underscore" "*" + integrity sha512-vfzZGgZKRFy7KEWcBGfIFk+h6B+thDCLfkD1exMBMRlUsx2icA+J6y4kAbZs/TjSTeY1duw89QUU133TSzr60Q== "@types/webpack-env@*", "@types/webpack-env@^1.13.6": version "1.13.6" @@ -2442,6 +2404,7 @@ abab@^2.0.0: abbrev@1, abbrev@~1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== abs-svg-path@~0.1.1: version "0.1.1" @@ -2662,6 +2625,7 @@ amdefine@>=0.0.4: ansi-align@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-2.0.0.tgz#c36aeccba563b89ceb556f3690f0b1d9e3547f7f" + integrity sha1-w2rsy6VjuJzrVW82kPCx2eNUf38= dependencies: string-width "^2.0.0" @@ -2684,10 +2648,12 @@ ansi-html@0.0.7: ansi-regex@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= ansi-regex@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= ansi-styles@^2.2.1: version "2.2.1" @@ -2696,6 +2662,7 @@ ansi-styles@^2.2.1: ansi-styles@^3.2.0, ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== dependencies: color-convert "^1.9.0" @@ -2809,13 +2776,14 @@ any-observable@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/any-observable/-/any-observable-0.3.0.tgz#af933475e5806a67d0d7df090dd5e8bef65d119b" -any-promise@1.3.0, any-promise@^1.0.0, any-promise@^1.3.0: +any-promise@^1.0.0, any-promise@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/any-promise/-/any-promise-1.3.0.tgz#abc6afeedcea52e809cdc0376aed3ce39635d17f" anymatch@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== dependencies: micromatch "^3.1.4" normalize-path "^2.1.1" @@ -2849,6 +2817,7 @@ archy@~1.0.0: are-we-there-yet@~1.1.2: version "1.1.5" resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== dependencies: delegates "^1.0.0" readable-stream "^2.0.6" @@ -2868,6 +2837,7 @@ arr-diff@^2.0.0: arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= arr-flatten@^1.0.1, arr-flatten@^1.1.0: version "1.1.0" @@ -2876,6 +2846,7 @@ arr-flatten@^1.0.1, arr-flatten@^1.1.0: arr-union@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= array-differ@^1.0.0: version "1.0.0" @@ -2941,6 +2912,7 @@ array-unique@^0.2.1: array-unique@^0.3.2: version "0.3.2" resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= array.prototype.flat@^1.2.1: version "1.2.1" @@ -2995,6 +2967,7 @@ assertion-error@^1.0.1: assign-symbols@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= ast-types@0.11.5, ast-types@0.x.x: version "0.11.5" @@ -3007,6 +2980,7 @@ astral-regex@^1.0.0: async-each@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.1.tgz#19d386a1d9edc6e7c1c85d388aedbcc56d33602d" + integrity sha1-GdOGodntxufByF04iu28xW0zYC0= async-foreach@^0.1.3: version "0.1.3" @@ -3039,6 +3013,7 @@ asynckit@^0.4.0: atob@^2.1.1: version "2.1.2" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== atool-monitor@^1.0.6: version "1.0.9" @@ -3500,10 +3475,7 @@ babylon@^6.18.0: balanced-match@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" - -base64-js@0.0.8: - version "0.0.8" - resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-0.0.8.tgz#1101e9544f4a76b1bc3b26d452ca96d7a35e7978" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= base64-js@^1.0.2: version "1.2.1" @@ -3512,6 +3484,7 @@ base64-js@^1.0.2: base@^0.11.1: version "0.11.2" resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== dependencies: cache-base "^1.0.1" class-utils "^0.3.5" @@ -3573,21 +3546,12 @@ bin-links@^1.1.2: binary-extensions@^1.0.0: version "1.12.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.12.0.tgz#c2d780f53d45bba8317a8902d4ceeaf3a6385b14" + integrity sha512-DYWGk01lDcxeS/K9IHPGWfT8PsJmbXRtRd2Sx72Tnb8pcYZQFF1oSDb8hJtS1vhp212q1Rzi5dUf9+nq0o9UIg== binaryextensions@2: version "2.1.1" resolved "https://registry.yarnpkg.com/binaryextensions/-/binaryextensions-2.1.1.tgz#3209a51ca4a4ad541a3b8d3d6a6d5b83a2485935" -bindings@^1.2.1: - version "1.3.0" - resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7" - -bip66@^1.1.3: - version "1.1.5" - resolved "https://registry.yarnpkg.com/bip66/-/bip66-1.1.5.tgz#01fa8748785ca70955d5011217d1b3139969ca22" - dependencies: - safe-buffer "^5.0.1" - bizcharts-plugin-slider@^2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/bizcharts-plugin-slider/-/bizcharts-plugin-slider-2.0.4.tgz#456aac6f1638108278eed00953a7da482b571ef3" @@ -3603,22 +3567,12 @@ bizcharts@^3.1.10: prop-types "^15.6.0" warning "^3.0.0" -bl@^1.0.0: - version "1.2.1" - resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.1.tgz#cac328f7bee45730d404b692203fcb590e172d5e" - dependencies: - readable-stream "^2.0.5" - block-stream@*: version "0.0.9" resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a" dependencies: inherits "~2.0.0" -bluebird@^2.9.34: - version "2.11.0" - resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-2.11.0.tgz#534b9033c022c9579c56ba3b3e5a5caafbb650e1" - bluebird@^3.5.0, bluebird@^3.5.1, bluebird@~3.5.1: version "3.5.1" resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.5.1.tgz#d9551f9de98f1fcda1e683d17ee91a0602ee2eb9" @@ -3635,15 +3589,11 @@ bmp-js@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.1.0.tgz#e05a63f796a6c1ff25f4771ec7adadc148c07233" -bn.js@4.11.6: - version "4.11.6" - resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.6.tgz#53344adb14617a13f6e8dd2ce28905d1c0ba3215" - -bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.11.0, bn.js@^4.11.3, bn.js@^4.11.6, bn.js@^4.4.0: +bn.js@4.11.8, bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: version "4.11.8" resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" -body-parser@1.18.2, body-parser@^1.16.0: +body-parser@1.18.2: version "1.18.2" resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.18.2.tgz#87678a19d84b47d859b83199bd59bce222b10454" dependencies: @@ -3707,6 +3657,7 @@ bowser@^1.7.3: boxen@^1.2.1: version "1.3.0" resolved "https://registry.yarnpkg.com/boxen/-/boxen-1.3.0.tgz#55c6c39a8ba58d9c61ad22cd877532deb665a20b" + integrity sha512-TNPjfTr432qx7yOjQyaXm3dSR0MH9vXp7eT1BFSl/C51g+EFnOR9hTg1IreahGBmDNCehscshe45f+C1TBZbLw== dependencies: ansi-align "^2.0.0" camelcase "^4.0.0" @@ -3734,6 +3685,7 @@ braces@^1.8.2: braces@^2.3.0, braces@^2.3.1: version "2.3.2" resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== dependencies: arr-flatten "^1.1.0" array-unique "^0.3.2" @@ -3771,17 +3723,6 @@ browserify-aes@^1.0.0, browserify-aes@^1.0.4: inherits "^2.0.1" safe-buffer "^5.0.1" -browserify-aes@^1.0.6: - version "1.2.0" - resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" - dependencies: - buffer-xor "^1.0.3" - cipher-base "^1.0.0" - create-hash "^1.1.0" - evp_bytestokey "^1.0.3" - inherits "^2.0.1" - safe-buffer "^5.0.1" - browserify-cipher@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.0.tgz#9988244874bf5ed4e28da95666dcd66ac8fc363a" @@ -3805,12 +3746,6 @@ browserify-rsa@^4.0.0: bn.js "^4.1.0" randombytes "^2.0.1" -browserify-sha3@^0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/browserify-sha3/-/browserify-sha3-0.0.1.tgz#3ff34a3006ef15c0fb3567e541b91a2340123d11" - dependencies: - js-sha3 "^0.3.1" - browserify-sign@^4.0.0: version "4.0.4" resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" @@ -3850,10 +3785,6 @@ bs-logger@0.x: dependencies: fast-json-stable-stringify "^2.0.0" -bs58@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-2.0.1.tgz#55908d58f1982aba2008fa1bed8f91998a29bf8d" - bser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/bser/-/bser-2.0.0.tgz#9ac78d3ed5d915804fd87acb158bc797147a1719" @@ -3871,10 +3802,6 @@ buffer-alloc@^1.1.0, buffer-alloc@^1.2.0: buffer-alloc-unsafe "^1.1.0" buffer-fill "^1.0.0" -buffer-crc32@~0.2.3: - version "0.2.13" - resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242" - buffer-equal@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b" @@ -3891,24 +3818,10 @@ buffer-indexof@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" -buffer-to-arraybuffer@0.0.2: - version "0.0.2" - resolved "https://registry.yarnpkg.com/buffer-to-arraybuffer/-/buffer-to-arraybuffer-0.0.2.tgz#d0d80564dc31866a1976515487b3ab620db7c849" - dependencies: - tape "^3.0.3" - buffer-xor@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" -buffer@^3.0.1: - version "3.6.0" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-3.6.0.tgz#a72c936f77b96bf52f5f7e7b467180628551defb" - dependencies: - base64-js "0.0.8" - ieee754 "^1.1.4" - isarray "^1.0.0" - buffer@^4.3.0: version "4.9.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.1.tgz#6d1bb601b07a4efced97094132093027c95bc298" @@ -3917,13 +3830,6 @@ buffer@^4.3.0: ieee754 "^1.1.4" isarray "^1.0.0" -buffer@^5.0.5: - version "5.0.8" - resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.0.8.tgz#84daa52e7cf2fa8ce4195bc5cf0f7809e0930b24" - dependencies: - base64-js "^1.0.2" - ieee754 "^1.1.4" - buffer@^5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.2.1.tgz#dd57fa0f109ac59c602479044dca7b8b3d0b71d6" @@ -3995,6 +3901,7 @@ cacache@^11.0.1, cacache@^11.0.2, cacache@^11.1.0: cache-base@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== dependencies: collection-visit "^1.0.0" component-emitter "^1.2.1" @@ -4087,6 +3994,7 @@ capture-exit@^1.2.0: capture-stack-trace@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/capture-stack-trace/-/capture-stack-trace-1.0.1.tgz#a6c0bbe1f38f3aa0b92238ecb6ff42c344d4135d" + integrity sha512-mYQLZnx5Qt1JgB1WEiMCf2647plpGeQ2NMR/5L0HNZzGQo4fuSPnK+wjfPnKZV0aiJDgzmWqqkV/g7JD+DW0qw== case-sensitive-paths-webpack-plugin@^2.1.2: version "2.1.2" @@ -4197,6 +4105,7 @@ chokidar@^2.0.0, chokidar@^2.0.2, chokidar@^2.0.3, chokidar@^2.0.4: chownr@^1.0.1, chownr@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.1.tgz#54726b8b8fff4df053c42187e801fb4412df1494" + integrity sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g== chownr@~1.0.1: version "1.0.1" @@ -4211,6 +4120,7 @@ chrome-trace-event@^1.0.0: ci-info@^1.3.0, ci-info@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== cidr-regex@^2.0.8: version "2.0.9" @@ -4228,6 +4138,7 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: class-utils@^0.3.5: version "0.3.6" resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== dependencies: arr-union "^3.1.0" define-property "^0.2.5" @@ -4247,6 +4158,7 @@ clean-css@4.2.x: cli-boxes@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-1.0.0.tgz#4fa917c3e59c94a004cd61f8ee509da651687143" + integrity sha1-T6kXw+WclKAEzWH47lCdplFocUM= cli-columns@^3.1.2: version "3.1.2" @@ -4386,17 +4298,12 @@ coa@~2.0.1: code-point-at@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" - -coinstring@^2.0.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/coinstring/-/coinstring-2.3.0.tgz#cdb63363a961502404a25afb82c2e26d5ff627a4" - dependencies: - bs58 "^2.0.1" - create-hash "^1.1.1" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= collection-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= dependencies: map-visit "^1.0.0" object-visit "^1.0.0" @@ -4404,6 +4311,7 @@ collection-visit@^1.0.0: color-convert@^1.3.0, color-convert@^1.9.0, color-convert@^1.9.1: version "1.9.3" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== dependencies: color-name "1.1.3" @@ -4497,7 +4405,7 @@ commander@^2.13.0, commander@^2.17.0, commander@^2.18.0: version "2.18.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.18.0.tgz#2bf063ddee7c7891176981a2cc798e5754bc6970" -commander@^2.8.1, commander@^2.9.0: +commander@^2.9.0: version "2.11.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.11.0.tgz#157152fd1e7a6c8d98a5b715cf376df928004563" @@ -4505,12 +4413,6 @@ commander@~2.13.0: version "2.13.0" resolved "https://registry.yarnpkg.com/commander/-/commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" -commander@~2.8.1: - version "2.8.1" - resolved "https://registry.yarnpkg.com/commander/-/commander-2.8.1.tgz#06be367febfda0c330aa1e2a072d3dc9762425d4" - dependencies: - graceful-readlink ">= 1.0.0" - common-tags@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.0.tgz#8e3153e542d4a39e9b10554434afaaf98956a937" @@ -4554,6 +4456,7 @@ compression@^1.5.2: concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= concat-stream@1.6.2, concat-stream@^1.5.0: version "1.6.2" @@ -4582,6 +4485,7 @@ config-chain@~1.1.11: configstore@^3.0.0: version "3.1.2" resolved "https://registry.yarnpkg.com/configstore/-/configstore-3.1.2.tgz#c6f25defaeef26df12dd33414b001fe81a543f8f" + integrity sha512-vtv5HtGjcYUgFrXc6Kx747B83MRRVS5R1VTEQoXvuP+kMI+if6uywV0nDGoiydJRy4yk7h9od5Og0kxx4zUXmw== dependencies: dot-prop "^4.1.0" graceful-fs "^4.1.2" @@ -4619,6 +4523,7 @@ console-browserify@^1.1.0: console-control-strings@^1.0.0, console-control-strings@^1.1.0, console-control-strings@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= constants-browserify@^1.0.0: version "1.0.0" @@ -4665,7 +4570,7 @@ cookie@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.3.1.tgz#e7e0a1f9ef43b4c8ba925c5c5a96e806d16873bb" -cookiejar@^2.1.0, cookiejar@^2.1.1: +cookiejar@^2.1.0: version "2.1.2" resolved "https://registry.yarnpkg.com/cookiejar/-/cookiejar-2.1.2.tgz#dd8a235530752f988f9a0844f3fc589e3111125c" @@ -4690,6 +4595,7 @@ copy-concurrently@^1.0.0: copy-descriptor@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= copy-to-clipboard@^3: version "3.0.8" @@ -4743,7 +4649,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" -cors@^2.8.1, cors@^2.8.4: +cors@^2.8.4: version "2.8.4" resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.4.tgz#2bd381f2eb201020105cd50ea59da63090694686" dependencies: @@ -4777,6 +4683,7 @@ create-ecdh@^4.0.0: create-error-class@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/create-error-class/-/create-error-class-3.0.2.tgz#06be7abef947a3f14a30fd610671d401bca8b7b6" + integrity sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y= dependencies: capture-stack-trace "^1.0.0" @@ -4789,16 +4696,6 @@ create-hash@^1.1.0, create-hash@^1.1.2: ripemd160 "^2.0.0" sha.js "^2.4.0" -create-hash@^1.1.1: - version "1.2.0" - resolved "http://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" - dependencies: - cipher-base "^1.0.1" - inherits "^2.0.1" - md5.js "^1.3.4" - ripemd160 "^2.0.1" - sha.js "^2.4.0" - create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: version "1.1.6" resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.6.tgz#acb9e221a4e17bdb076e90657c42b93e3726cf06" @@ -4871,7 +4768,7 @@ cryptiles@3.x.x: dependencies: boom "5.x.x" -crypto-browserify@3.12.0, crypto-browserify@^3.11.0: +crypto-browserify@^3.11.0: version "3.12.0" resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" dependencies: @@ -4890,6 +4787,7 @@ crypto-browserify@3.12.0, crypto-browserify@^3.11.0: crypto-random-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/crypto-random-string/-/crypto-random-string-1.0.0.tgz#a230f64f568310e1498009940790ec99545bca7e" + integrity sha1-ojD2T1aDEOFJgAmUB5DsmVRbyn4= css-animation@1.x, css-animation@^1.2.5, css-animation@^1.3.2: version "1.4.1" @@ -5277,6 +5175,7 @@ debug@3.1.0: debug@^3.1.0: version "3.2.6" resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== dependencies: ms "^2.1.1" @@ -5297,6 +5196,7 @@ decamelize@^2.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" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= decompress-response@^3.2.0: version "3.3.0" @@ -5304,54 +5204,6 @@ decompress-response@^3.2.0: dependencies: mimic-response "^1.0.0" -decompress-tar@^4.0.0, decompress-tar@^4.1.0, decompress-tar@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tar/-/decompress-tar-4.1.1.tgz#718cbd3fcb16209716e70a26b84e7ba4592e5af1" - dependencies: - file-type "^5.2.0" - is-stream "^1.1.0" - tar-stream "^1.5.2" - -decompress-tarbz2@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-tarbz2/-/decompress-tarbz2-4.1.1.tgz#3082a5b880ea4043816349f378b56c516be1a39b" - dependencies: - decompress-tar "^4.1.0" - file-type "^6.1.0" - is-stream "^1.1.0" - seek-bzip "^1.0.5" - unbzip2-stream "^1.0.9" - -decompress-targz@^4.0.0: - version "4.1.1" - resolved "https://registry.yarnpkg.com/decompress-targz/-/decompress-targz-4.1.1.tgz#c09bc35c4d11f3de09f2d2da53e9de23e7ce1eee" - dependencies: - decompress-tar "^4.1.1" - file-type "^5.2.0" - is-stream "^1.1.0" - -decompress-unzip@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/decompress-unzip/-/decompress-unzip-4.0.1.tgz#deaaccdfd14aeaf85578f733ae8210f9b4848f69" - dependencies: - file-type "^3.8.0" - get-stream "^2.2.0" - pify "^2.3.0" - yauzl "^2.4.2" - -decompress@^4.0.0: - version "4.2.0" - resolved "https://registry.yarnpkg.com/decompress/-/decompress-4.2.0.tgz#7aedd85427e5a92dacfe55674a7c505e96d01f9d" - dependencies: - decompress-tar "^4.0.0" - decompress-tarbz2 "^4.0.0" - decompress-targz "^4.0.0" - decompress-unzip "^4.0.1" - graceful-fs "^4.1.10" - make-dir "^1.0.0" - pify "^2.3.0" - strip-dirs "^2.0.0" - dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" @@ -5370,13 +5222,10 @@ deep-equal@^1.0.1, deep-equal@~1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5" -deep-equal@~0.2.0: - version "0.2.2" - resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-0.2.2.tgz#84b745896f34c684e98f2ce0e42abaf43bba017d" - deep-extend@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== deep-is@~0.1.3: version "0.1.3" @@ -5421,26 +5270,25 @@ define-properties@^1.1.2: define-property@^0.2.5: version "0.2.5" resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= dependencies: is-descriptor "^0.1.0" define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= dependencies: is-descriptor "^1.0.0" define-property@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== dependencies: is-descriptor "^1.0.2" isobject "^3.0.1" -defined@~0.0.0: - version "0.0.0" - resolved "https://registry.yarnpkg.com/defined/-/defined-0.0.0.tgz#f35eea7d705e933baf13b2f03b3f83d921403b3e" - defined@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/defined/-/defined-1.0.0.tgz#c98d9bcef75674188e110969151199e39b1fa693" @@ -5471,6 +5319,7 @@ delayed-stream@~1.0.0: delegates@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= depd@1.1.1, depd@~1.1.1: version "1.1.1" @@ -5512,6 +5361,7 @@ detect-indent@^5.0.0, detect-indent@~5.0.0: detect-libc@^1.0.2: version "1.0.3" resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= detect-newline@^2.1.0: version "2.1.0" @@ -5716,21 +5566,15 @@ draft-js@^0.10.0, draft-js@~0.10.0: immutable "~3.7.4" object-assign "^4.1.0" -drbg.js@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/drbg.js/-/drbg.js-1.0.1.tgz#3e36b6c42b37043823cdbc332d58f31e2445480b" - dependencies: - browserify-aes "^1.0.6" - create-hash "^1.1.2" - create-hmac "^1.1.4" - duplexer3@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2" + integrity sha1-7gHdHKwO08vH/b6jfcCo8c4ALOI= duplexer@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= duplexify@^3.4.2, duplexify@^3.6.0: version "3.6.0" @@ -5790,7 +5634,7 @@ element-resize-detector@1.1.13: dependencies: batch-processor "^1.0.0" -elliptic@^6.0.0, elliptic@^6.4.0: +elliptic@^6.0.0: version "6.4.0" resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.0.tgz#cac9af8762c85836187003c8dfe193e5e2eae5df" dependencies: @@ -5802,18 +5646,6 @@ elliptic@^6.0.0, elliptic@^6.4.0: minimalistic-assert "^1.0.0" minimalistic-crypto-utils "^1.0.0" -elliptic@^6.2.3: - version "6.4.1" - resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.4.1.tgz#c2d0b7776911b86722c632c3c06c60f2f819939a" - dependencies: - bn.js "^4.4.0" - brorand "^1.0.1" - hash.js "^1.0.0" - hmac-drbg "^1.0.0" - inherits "^2.0.1" - minimalistic-assert "^1.0.0" - minimalistic-crypto-utils "^1.0.0" - emojis-list@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" @@ -5824,10 +5656,6 @@ enabled@1.0.x: dependencies: env-variable "0.0.x" -encodeurl@~1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" - encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -6012,6 +5840,7 @@ escape-html@^1.0.3, escape-html@~1.0.3: escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= escodegen@1.x.x, escodegen@^1.11.0, escodegen@^1.9.1: version "1.11.0" @@ -6068,66 +5897,10 @@ etag@~1.8.1: version "1.8.1" resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" -eth-lib@0.1.27, eth-lib@^0.1.26: - version "0.1.27" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.1.27.tgz#f0b0fd144f865d2d6bf8257a40004f2e75ca1dd6" - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - keccakjs "^0.2.1" - nano-json-stream-parser "^0.1.2" - servify "^0.1.12" - ws "^3.0.0" - xhr-request-promise "^0.1.2" - -eth-lib@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.7.tgz#2f93f17b1e23aec3759cd4a3fe20c1286a3fc1ca" - dependencies: - bn.js "^4.11.6" - elliptic "^6.4.0" - xhr-request-promise "^0.1.2" - -ethereum-blockies-base64@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/ethereum-blockies-base64/-/ethereum-blockies-base64-1.0.2.tgz#4aebca52142bf4d16a3144e6e2b59303e39ed2b3" - dependencies: - pnglib "0.0.1" - -ethereumjs-util@5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-5.2.0.tgz#3e0c0d1741471acf1036052d048623dee54ad642" - dependencies: - bn.js "^4.11.0" - create-hash "^1.1.2" - ethjs-util "^0.1.3" - keccak "^1.0.2" - rlp "^2.0.0" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - -ethjs-unit@0.1.6: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" - dependencies: - bn.js "4.11.6" - number-to-bn "1.7.0" - -ethjs-util@^0.1.3: - version "0.1.6" - resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" - dependencies: - is-hex-prefixed "1.0.0" - strip-hex-prefix "1.0.0" - event-lite@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/event-lite/-/event-lite-0.1.2.tgz#838a3e0fdddef8cc90f128006c8e55a4e4e4c11b" -eventemitter3@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-1.1.1.tgz#47786bdaa087caf7b1b75e73abc5c7d540158cd0" - eventemitter3@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-3.1.0.tgz#090b4d6cdbd645ed10bf750d4b5407942d7ba163" @@ -6136,14 +5909,10 @@ eventlistener@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/eventlistener/-/eventlistener-0.0.1.tgz#ed2baabb852227af2bcf889152c72c63ca532eb8" -events@^1.0.0, events@^1.1.1: +events@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" -events@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/events/-/events-2.1.0.tgz#2a9a1e18e6106e0e812aa9ebd4a819b3c29c0ba5" - events@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/events/-/events-3.0.0.tgz#9a0a0dfaf62893d92b875b8f2698ca4114973e88" @@ -6194,6 +5963,7 @@ execa@^0.6.1: execa@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/execa/-/execa-0.7.0.tgz#944becd34cc41ee32a63a9faf27ad5a65fc59777" + integrity sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c= dependencies: cross-spawn "^5.0.1" get-stream "^3.0.0" @@ -6252,6 +6022,7 @@ expand-brackets@^0.1.4: expand-brackets@^2.1.4: version "2.1.4" resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= dependencies: debug "^2.3.3" define-property "^0.2.5" @@ -6301,41 +6072,6 @@ express-winston@^3.0.0: chalk "^2.4.1" lodash "^4.17.10" -express@^4.14.0: - version "4.16.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.16.2.tgz#e35c6dfe2d64b7dca0a5cd4f21781be3299e076c" - dependencies: - accepts "~1.3.4" - array-flatten "1.1.1" - body-parser "1.18.2" - content-disposition "0.5.2" - content-type "~1.0.4" - cookie "0.3.1" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.1" - encodeurl "~1.0.1" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "1.1.0" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.2" - path-to-regexp "0.1.7" - proxy-addr "~2.0.2" - qs "6.5.1" - range-parser "~1.2.0" - safe-buffer "5.1.1" - send "0.16.1" - serve-static "1.13.1" - setprototypeof "1.1.0" - statuses "~1.3.1" - type-is "~1.6.15" - utils-merge "1.0.1" - vary "~1.1.2" - express@^4.16.2, express@^4.16.3: version "4.16.3" resolved "https://registry.yarnpkg.com/express/-/express-4.16.3.tgz#6af8a502350db3246ecc4becf6b5a34d22f7ed53" @@ -6374,12 +6110,14 @@ express@^4.16.2, express@^4.16.3: extend-shallow@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= dependencies: is-extendable "^0.1.0" extend-shallow@^3.0.0, extend-shallow@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= dependencies: assign-symbols "^1.0.0" is-extendable "^1.0.1" @@ -6421,6 +6159,7 @@ extglob@^0.3.1: extglob@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== dependencies: array-unique "^0.3.2" define-property "^1.0.0" @@ -6587,14 +6326,6 @@ file-type@^3.1.0, file-type@^3.8.0: version "3.9.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9" -file-type@^5.2.0: - version "5.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-5.2.0.tgz#2ddbea7c73ffe36368dfae49dc338c058c2b8ad6" - -file-type@^6.1.0: - version "6.2.0" - resolved "https://registry.yarnpkg.com/file-type/-/file-type-6.2.0.tgz#e50cd75d356ffed4e306dc4f5bcf52a79903a919" - file-type@^9.0.0: version "9.0.0" resolved "https://registry.yarnpkg.com/file-type/-/file-type-9.0.0.tgz#a68d5ad07f486414dfb2c8866f73161946714a18" @@ -6639,24 +6370,13 @@ fill-range@^2.1.0: fill-range@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= dependencies: extend-shallow "^2.0.1" is-number "^3.0.0" repeat-string "^1.6.1" to-regex-range "^2.1.0" -finalhandler@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.0.tgz#ce0b6855b45853e791b2fcc680046d88253dd7f5" - dependencies: - debug "2.6.9" - encodeurl "~1.0.1" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.2" - statuses "~1.3.1" - unpipe "~1.0.0" - finalhandler@1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.1.tgz#eebf4ed840079c83f4249038c9d703008301b105" @@ -6848,6 +6568,7 @@ forwarded@~0.1.2: fragment-cache@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= dependencies: map-cache "^0.2.2" @@ -6885,13 +6606,6 @@ fs-extra@^1.0.0: jsonfile "^2.1.0" klaw "^1.0.0" -fs-extra@^2.0.0, fs-extra@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35" - dependencies: - graceful-fs "^4.1.2" - jsonfile "^2.1.0" - fs-extra@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-3.0.1.tgz#3794f378c58b342ea7dbbb23095109c4b3b62291" @@ -6911,18 +6625,10 @@ fs-extra@^7.0.0: fs-minipass@^1.2.5: version "1.2.5" resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.5.tgz#06c277218454ec288df77ada54a03b8702aacb9d" + integrity sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ== dependencies: minipass "^2.2.1" -fs-promise@^2.0.0: - version "2.0.3" - resolved "https://registry.yarnpkg.com/fs-promise/-/fs-promise-2.0.3.tgz#f64e4f854bcf689aa8bddcba268916db3db46854" - dependencies: - any-promise "^1.3.0" - fs-extra "^2.0.0" - mz "^2.6.0" - thenify-all "^1.6.0" - fs-vacuum@^1.2.10, fs-vacuum@~1.2.10: version "1.2.10" resolved "https://registry.yarnpkg.com/fs-vacuum/-/fs-vacuum-1.2.10.tgz#b7629bec07a4031a2548fdf99f5ecf1cc8b31e36" @@ -6943,6 +6649,7 @@ fs-write-stream-atomic@^1.0.8, fs-write-stream-atomic@~1.0.10: fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= fsevents@^1.2.2, fsevents@^1.2.3: version "1.2.4" @@ -6951,7 +6658,7 @@ fsevents@^1.2.2, fsevents@^1.2.3: nan "^2.9.2" node-pre-gyp "^0.10.0" -fstream@^1.0.0, fstream@^1.0.2, fstream@^1.0.8: +fstream@^1.0.0, fstream@^1.0.2: version "1.0.11" resolved "https://registry.yarnpkg.com/fstream/-/fstream-1.0.11.tgz#5c1fb1f117477114f0632a0eb4b71b3cb0fd3171" dependencies: @@ -6986,6 +6693,7 @@ fuse.js@^3.0.1, fuse.js@^3.2.1: gauge@~2.7.3: version "2.7.4" resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= dependencies: aproba "^1.0.3" console-control-strings "^1.0.0" @@ -7047,7 +6755,7 @@ get-stdin@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b" -get-stream@^2.0.0, get-stream@^2.2.0: +get-stream@^2.0.0: version "2.3.1" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-2.3.1.tgz#5f38f93f346009666ee0150a054167f91bdd95de" dependencies: @@ -7057,6 +6765,7 @@ get-stream@^2.0.0, get-stream@^2.2.0: get-stream@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-3.0.0.tgz#8e943d1358dc37555054ecbe2edb05aa174ede14" + integrity sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= get-uri@^2.0.0: version "2.0.2" @@ -7072,6 +6781,7 @@ get-uri@^2.0.0: get-value@^2.0.3, get-value@^2.0.6: version "2.0.6" resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= getpass@^0.1.1: version "0.1.7" @@ -7108,6 +6818,7 @@ glob-parent@^2.0.0: glob-parent@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= dependencies: is-glob "^3.1.0" path-dirname "^1.0.0" @@ -7140,6 +6851,7 @@ glob@^7.0.0, glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@~7.1.1, glob@~7.1.2: glob@^7.0.5: version "7.1.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.3.tgz#3960832d3f1574108342dafd3a67b332c0969df1" + integrity sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ== dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -7148,16 +6860,10 @@ glob@^7.0.5: once "^1.3.0" path-is-absolute "^1.0.0" -glob@~3.2.9: - version "3.2.11" - resolved "https://registry.yarnpkg.com/glob/-/glob-3.2.11.tgz#4a973f635b9190f715d10987d5c00fd2815ebe3d" - dependencies: - inherits "2" - minimatch "0.3" - global-dirs@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/global-dirs/-/global-dirs-0.1.1.tgz#b319c0dd4607f353f3be9cca4c72fc148c49f445" + integrity sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU= dependencies: ini "^1.3.4" @@ -7239,7 +6945,24 @@ globule@^1.0.0: lodash "~4.17.10" minimatch "~3.0.2" -got@7.1.0, got@^7.0.0, got@^7.1.0: +got@^6.7.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" + integrity sha1-JAzQV4WpoY5WHcG0S0HHY+8ejbA= + dependencies: + create-error-class "^3.0.0" + duplexer3 "^0.1.4" + get-stream "^3.0.0" + is-redirect "^1.0.0" + is-retry-allowed "^1.0.0" + is-stream "^1.0.0" + lowercase-keys "^1.0.0" + safe-buffer "^5.0.1" + timed-out "^4.0.0" + unzip-response "^2.0.1" + url-parse-lax "^1.0.0" + +got@^7.0.0: version "7.1.0" resolved "https://registry.yarnpkg.com/got/-/got-7.1.0.tgz#05450fd84094e6bbea56f451a43a9c289166385a" dependencies: @@ -7258,33 +6981,14 @@ got@7.1.0, got@^7.0.0, got@^7.1.0: url-parse-lax "^1.0.0" url-to-options "^1.0.1" -got@^6.7.1: - version "6.7.1" - resolved "https://registry.yarnpkg.com/got/-/got-6.7.1.tgz#240cd05785a9a18e561dc1b44b41c763ef1e8db0" - dependencies: - create-error-class "^3.0.0" - duplexer3 "^0.1.4" - get-stream "^3.0.0" - is-redirect "^1.0.0" - is-retry-allowed "^1.0.0" - is-stream "^1.0.0" - lowercase-keys "^1.0.0" - safe-buffer "^5.0.1" - timed-out "^4.0.0" - unzip-response "^2.0.1" - url-parse-lax "^1.0.0" - -graceful-fs@^4.1.10, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@~4.1.11: - version "4.1.11" - resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" - graceful-fs@^4.1.11, graceful-fs@^4.1.2: version "4.1.15" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00" + integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA== -"graceful-readlink@>= 1.0.0": - version "1.0.1" - resolved "https://registry.yarnpkg.com/graceful-readlink/-/graceful-readlink-1.0.1.tgz#4cafad76bc62f02fa039b2f94e9a3dd3a391a725" +graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@~4.1.11: + version "4.1.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.11.tgz#0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658" graphlib@^2.1.5: version "2.1.5" @@ -7436,6 +7140,7 @@ has-flag@^1.0.0: has-flag@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= has-symbol-support-x@^1.4.1: version "1.4.1" @@ -7454,10 +7159,12 @@ has-to-string-tag-x@^1.2.0: has-unicode@^2.0.0, has-unicode@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= has-value@^0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= dependencies: get-value "^2.0.3" has-values "^0.1.4" @@ -7466,6 +7173,7 @@ has-value@^0.3.1: has-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= dependencies: get-value "^2.0.6" has-values "^1.0.0" @@ -7474,10 +7182,12 @@ has-value@^1.0.0: has-values@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= has-values@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= dependencies: is-number "^3.0.0" kind-of "^4.0.0" @@ -7537,14 +7247,6 @@ hawk@~6.0.2: hoek "4.x.x" sntp "2.x.x" -hdkey@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/hdkey/-/hdkey-1.1.0.tgz#e74e7b01d2c47f797fa65d1d839adb7a44639f29" - dependencies: - coinstring "^2.0.0" - safe-buffer "^5.1.1" - secp256k1 "^3.0.1" - he@1.1.x: version "1.1.1" resolved "https://registry.yarnpkg.com/he/-/he-1.1.1.tgz#93410fd21b009735151f8868c2f271f3427e23fd" @@ -7704,10 +7406,6 @@ http-errors@1.6.3, http-errors@~1.6.3: setprototypeof "1.1.0" statuses ">= 1.4.0 < 2" -http-https@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/http-https/-/http-https-1.0.0.tgz#2f908dd5f1db4068c058cd6e6d4ce392c913389b" - http-parser-js@>=0.4.0: version "0.4.13" resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.13.tgz#3bd6d6fde6e3172c9334c3b33b6c193d80fe1137" @@ -7855,10 +7553,12 @@ iferr@^1.0.2: ignore-by-default@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09" + integrity sha1-SMptcvbGo68Aqa1K5odr44ieKwk= ignore-walk@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.1.tgz#a83e62e7d272ac0e3b551aaa82831a19b69f82f8" + integrity sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ== dependencies: minimatch "^3.0.4" @@ -7897,6 +7597,7 @@ import-from@^2.1.0: import-lazy@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-2.1.0.tgz#05698e3d45c88e8d7e9d92cb0584e77f096f3e43" + integrity sha1-BWmOPUXIjo1+nZLLBYTnfwlvPkM= import-local@^1.0.0: version "1.0.0" @@ -7915,6 +7616,7 @@ import-local@^2.0.0: imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= in-publish@^2.0.0: version "2.0.0" @@ -7941,6 +7643,7 @@ indexof@0.0.1: inflight@^1.0.4, inflight@~1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= dependencies: once "^1.3.0" wrappy "1" @@ -7948,6 +7651,7 @@ inflight@^1.0.4, inflight@~1.0.6: inherits@2, inherits@2.0.3, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.0, inherits@~2.0.1, inherits@~2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= inherits@2.0.1: version "2.0.1" @@ -7956,6 +7660,7 @@ inherits@2.0.1: ini@^1.3.4, ini@^1.3.5, ini@~1.3.0: version "1.3.5" resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== init-package-json@^1.10.3: version "1.10.3" @@ -8087,10 +7792,6 @@ ip@^1.1.0, ip@^1.1.4, ip@^1.1.5: version "1.1.5" resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" -ipaddr.js@1.5.2: - version "1.5.2" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.5.2.tgz#d4b505bde9946987ccf0fc58d9010ff9607e3fa0" - ipaddr.js@1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.8.0.tgz#eaa33d6ddd7ace8f7f6fe0c9ca0440e706738b1e" @@ -8106,12 +7807,14 @@ is-absolute-url@^2.0.0: is-accessor-descriptor@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= dependencies: kind-of "^3.0.2" is-accessor-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== dependencies: kind-of "^6.0.0" @@ -8132,6 +7835,7 @@ is-arrayish@^0.3.1: is-binary-path@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= dependencies: binary-extensions "^1.0.0" @@ -8156,6 +7860,7 @@ is-callable@^1.1.1, is-callable@^1.1.3, is-callable@^1.1.4: is-ci@^1.0.10: version "1.2.1" resolved "https://registry.yarnpkg.com/is-ci/-/is-ci-1.2.1.tgz#e3779c8ee17fccf428488f6e281187f2e632841c" + integrity sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg== dependencies: ci-info "^1.5.0" @@ -8185,12 +7890,14 @@ is-color-stop@^1.0.0: is-data-descriptor@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= dependencies: kind-of "^3.0.2" is-data-descriptor@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== dependencies: kind-of "^6.0.0" @@ -8201,6 +7908,7 @@ is-date-object@^1.0.1: is-descriptor@^0.1.0: version "0.1.6" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== dependencies: is-accessor-descriptor "^0.1.6" is-data-descriptor "^0.1.4" @@ -8209,6 +7917,7 @@ is-descriptor@^0.1.0: is-descriptor@^1.0.0, is-descriptor@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== dependencies: is-accessor-descriptor "^1.0.0" is-data-descriptor "^1.0.0" @@ -8235,10 +7944,12 @@ is-equal-shallow@^0.1.3: is-extendable@^0.1.0, is-extendable@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= is-extendable@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== dependencies: is-plain-object "^2.0.4" @@ -8249,6 +7960,7 @@ is-extglob@^1.0.0: is-extglob@^2.1.0, is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= is-finite@^1.0.0: version "1.0.2" @@ -8259,12 +7971,14 @@ is-finite@^1.0.0: is-fullwidth-code-point@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= dependencies: number-is-nan "^1.0.0" is-fullwidth-code-point@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= is-function@^1.0.1, is-function@~1.0.0: version "1.0.1" @@ -8290,30 +8004,25 @@ is-glob@^2.0.0, is-glob@^2.0.1: is-glob@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= dependencies: is-extglob "^2.1.0" is-glob@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.0.tgz#9521c76845cc2610a85203ddf080a958c2ffabc0" + integrity sha1-lSHHaEXMJhCoUgPd8ICpWML/q8A= dependencies: is-extglob "^2.1.1" -is-hex-prefixed@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-hex-prefixed/-/is-hex-prefixed-1.0.0.tgz#7d8d37e6ad77e5d127148913c573e082d777f554" - is-installed-globally@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/is-installed-globally/-/is-installed-globally-0.1.0.tgz#0dfd98f5a9111716dd535dda6492f67bf3d25a80" + integrity sha1-Df2Y9akRFxbdU13aZJL2e/PSWoA= dependencies: global-dirs "^0.1.0" is-path-inside "^1.0.0" -is-natural-number@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-natural-number/-/is-natural-number-4.0.1.tgz#ab9d76e1db4ced51e35de0c72ebecf09f734cde8" - is-negative-zero@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.0.tgz#9553b121b0fac28869da9ed459e20c7543788461" @@ -8321,6 +8030,7 @@ is-negative-zero@^2.0.0: is-npm@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-npm/-/is-npm-1.0.0.tgz#f2fb63a65e4905b406c86072765a1a4dc793b9f4" + integrity sha1-8vtjpl5JBbQGyGBydloaTceTufQ= is-number-object@^1.0.3: version "1.0.3" @@ -8335,6 +8045,7 @@ is-number@^2.1.0: is-number@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= dependencies: kind-of "^3.0.2" @@ -8345,6 +8056,7 @@ is-number@^4.0.0: is-obj@^1.0.0, is-obj@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= is-object@^1.0.1: version "1.0.1" @@ -8369,6 +8081,7 @@ is-path-in-cwd@^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" + integrity sha1-jvW33lBDej/cprToZe96pVy0gDY= dependencies: path-is-inside "^1.0.1" @@ -8379,6 +8092,7 @@ is-plain-obj@^1.0.0, is-plain-obj@^1.1.0: is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== dependencies: isobject "^3.0.1" @@ -8397,6 +8111,7 @@ is-promise@^2.1.0: is-redirect@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24" + integrity sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ= is-regex@^1.0.4: version "1.0.4" @@ -8415,6 +8130,7 @@ is-resolvable@^1.0.0: is-retry-allowed@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz#11a060568b67339444033d0125a61a20d564fb34" + integrity sha1-EaBgVotnM5REAz0BJaYaINVk+zQ= is-root@1.0.0: version "1.0.0" @@ -8433,6 +8149,7 @@ is-scoped@^1.0.0: is-stream@^1.0.0, is-stream@^1.0.1, is-stream@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= is-string@^1.0.4: version "1.0.4" @@ -8452,7 +8169,7 @@ is-symbol@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.1.tgz#3cc59f00025194b6ab2e38dbae6689256b660572" -is-typedarray@^1.0.0, is-typedarray@~1.0.0: +is-typedarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" @@ -8475,6 +8192,7 @@ isarray@0.0.1, isarray@~0.0.1: isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= isbinaryfile@^3.0.2: version "3.0.3" @@ -8485,16 +8203,19 @@ isbinaryfile@^3.0.2: isexe@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= isobject@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= dependencies: isarray "1.0.0" isobject@^3.0.0, isobject@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= isomorphic-fetch@^2.1.1, isomorphic-fetch@^2.2.1: version "2.2.1" @@ -8943,10 +8664,6 @@ js-levenshtein@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.3.tgz#3ef627df48ec8cf24bacf05c0f184ff30ef413c5" -js-sha3@^0.3.1: - version "0.3.1" - resolved "https://registry.yarnpkg.com/js-sha3/-/js-sha3-0.3.1.tgz#86122802142f0828502a0d1dee1d95e253bb0243" - js-tokens@^3.0.0, js-tokens@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" @@ -9141,22 +8858,6 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" -keccak@^1.0.2: - version "1.4.0" - resolved "https://registry.yarnpkg.com/keccak/-/keccak-1.4.0.tgz#572f8a6dbee8e7b3aa421550f9e6408ca2186f80" - dependencies: - bindings "^1.2.1" - inherits "^2.0.3" - nan "^2.2.1" - safe-buffer "^5.1.0" - -keccakjs@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/keccakjs/-/keccakjs-0.2.1.tgz#1d633af907ef305bbf9f2fa616d56c44561dfa4d" - dependencies: - browserify-sha3 "^0.0.1" - sha3 "^1.1.0" - kew@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" @@ -9182,22 +8883,26 @@ kind-of@^2.0.1: kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: version "3.2.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= dependencies: is-buffer "^1.1.5" kind-of@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= dependencies: is-buffer "^1.1.5" kind-of@^5.0.0: version "5.1.0" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== kind-of@^6.0.0, kind-of@^6.0.2: version "6.0.2" resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.2.tgz#01146b36a6218e64e58f3a8d66de5d7fc6f6d051" + integrity sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA== klaw@^1.0.0: version "1.3.1" @@ -9218,6 +8923,7 @@ kuler@1.0.x: latest-version@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/latest-version/-/latest-version-3.1.0.tgz#a205383fea322b33b5ae3b18abee0dc2f356ee15" + integrity sha1-ogU4P+oyKzO1rjsYq+4NwvNW7hU= dependencies: package-json "^4.0.0" @@ -9518,6 +9224,7 @@ lodash.clonedeep@^4.3.2, lodash.clonedeep@^4.5.0, lodash.clonedeep@~4.5.0: lodash.debounce@^4.0.0, lodash.debounce@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/lodash.debounce/-/lodash.debounce-4.0.8.tgz#82d79bff30a67c4005ffd5e2515300ad9ca4d7af" + integrity sha1-gteb/zCmfEAF/9XiUVMArZyk168= lodash.defaultsdeep@^4.6.0: version "4.6.0" @@ -9702,14 +9409,12 @@ lower-case@^1.1.1: lowercase-keys@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-1.0.1.tgz#6f9e30b47084d971a7c820ff15a6c5167b74c26f" - -lru-cache@2: - version "2.7.3" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-2.7.3.tgz#6d4524e8b955f95d4f5b58851ce21dd72fb4e952" + integrity sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA== lru-cache@^4.0.1: version "4.1.5" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.5.tgz#8bbe50ea85bed59bc9e33dcab8235ee9bcf443cd" + integrity sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g== dependencies: pseudomap "^1.0.2" yallist "^2.1.2" @@ -9728,6 +9433,7 @@ lsmod@1.0.0: make-dir@^1.0.0, make-dir@^1.1.0: version "1.3.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c" + integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ== dependencies: pify "^3.0.0" @@ -9786,6 +9492,7 @@ map-age-cleaner@^0.1.1: map-cache@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= map-obj@^1.0.0, map-obj@^1.0.1: version "1.0.1" @@ -9794,6 +9501,7 @@ map-obj@^1.0.0, map-obj@^1.0.1: map-visit@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= dependencies: object-visit "^1.0.0" @@ -9977,7 +9685,7 @@ mime-db@~1.35.0: version "1.35.0" resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.35.0.tgz#0569d657466491283709663ad379a99b90d9ab47" -mime-types@^2.1.12, mime-types@^2.1.16, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17: +mime-types@^2.1.12, mime-types@~2.1.15, mime-types@~2.1.16, mime-types@~2.1.17: version "2.1.17" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.17.tgz#09d7a393f03e995a79f8af857b70a9e0ab16557a" dependencies: @@ -10056,13 +9764,6 @@ minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" -minimatch@0.3: - version "0.3.0" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-0.3.0.tgz#275d8edaac4f1bb3326472089e7949c8394699dd" - dependencies: - lru-cache "2" - sigmund "~1.0.0" - "minimatch@2 || 3", minimatch@3.0.4, minimatch@^3.0.0, minimatch@^3.0.2, minimatch@^3.0.3, minimatch@^3.0.4, minimatch@~3.0.2: version "3.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" @@ -10078,10 +9779,12 @@ minimatch@3.0.3: minimist@0.0.8: version "0.0.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= minimist@^1.1.0, minimist@^1.1.1, minimist@^1.1.3, minimist@^1.2.0, minimist@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= minimist@~0.0.1: version "0.0.10" @@ -10090,6 +9793,7 @@ minimist@~0.0.1: minipass@^2.2.1, minipass@^2.3.3, minipass@^2.3.4: version "2.3.5" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.5.tgz#cacebe492022497f656b0f0f51e2682a9ed2d848" + integrity sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA== dependencies: safe-buffer "^5.1.2" yallist "^3.0.0" @@ -10097,6 +9801,7 @@ minipass@^2.2.1, minipass@^2.3.3, minipass@^2.3.4: minizlib@^1.1.0, minizlib@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.1.1.tgz#6734acc045a46e61d596a43bb9d9cd326e19cc42" + integrity sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg== dependencies: minipass "^2.2.1" @@ -10133,6 +9838,7 @@ mississippi@^3.0.0: mixin-deep@^1.2.0: version "1.3.1" resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.1.tgz#a49e7268dce1a0d9698e45326c5626df3543d0fe" + integrity sha512-8ZItLHeEgaqEvd5lYBXfm4EZSFCX29Jb9K+lAHhDKzReKBQKj3R+7NOF6tjqYi9t4oI8VUfaWITJQm86wnXGNQ== dependencies: for-in "^1.0.2" is-extendable "^1.0.1" @@ -10144,22 +9850,13 @@ mixin-object@^2.0.1: for-in "^0.1.3" is-extendable "^0.1.1" -mkdirp-promise@^5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/mkdirp-promise/-/mkdirp-promise-5.0.1.tgz#e9b8f68e552c68a9c1713b84883f7a1dd039b8a1" - dependencies: - mkdirp "*" - -mkdirp@*, mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: +mkdirp@0.5.1, mkdirp@0.5.x, mkdirp@0.x, "mkdirp@>=0.5 0", mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.0, mkdirp@~0.5.1: version "0.5.1" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= dependencies: minimist "0.0.8" -mock-fs@^4.1.0: - version "4.4.2" - resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.4.2.tgz#09dec5313f97095a450be6aa2ad8ab6738d63d6b" - moment@2.x, moment@^2.19.3, moment@^2.22.1, moment@^2.22.2: version "2.22.2" resolved "https://registry.yarnpkg.com/moment/-/moment-2.22.2.tgz#3c257f9839fc0e93ff53149632239eb90783ff66" @@ -10168,10 +9865,6 @@ moo@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/moo/-/moo-0.4.3.tgz#3f847a26f31cf625a956a87f2b10fbc013bfd10e" -mout@^0.11.0: - version "0.11.1" - resolved "https://registry.yarnpkg.com/mout/-/mout-0.11.1.tgz#ba3611df5f0e5b1ffbfd01166b8f02d1f5fa2b99" - move-concurrently@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" @@ -10186,6 +9879,7 @@ move-concurrently@^1.0.1: ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= ms@2.1.1, ms@^2.0.0, ms@^2.1.1: version "2.1.1" @@ -10232,7 +9926,7 @@ mute-stream@0.0.7, mute-stream@~0.0.4: version "0.0.7" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" -mz@^2.6.0, mz@^2.7.0: +mz@^2.7.0: version "2.7.0" resolved "https://registry.yarnpkg.com/mz/-/mz-2.7.0.tgz#95008057a56cafadc2bc63dde7f9ff6955948e32" dependencies: @@ -10240,25 +9934,19 @@ mz@^2.6.0, mz@^2.7.0: object-assign "^4.0.1" thenify-all "^1.0.0" -nan@^2.0.5, nan@^2.0.8, nan@^2.3.3: - version "2.8.0" - resolved "https://registry.yarnpkg.com/nan/-/nan-2.8.0.tgz#ed715f3fe9de02b57a5e6252d90a96675e1f085a" - -nan@^2.10.0, nan@^2.2.1: +nan@^2.10.0: version "2.10.0" resolved "https://registry.yarnpkg.com/nan/-/nan-2.10.0.tgz#96d0cd610ebd58d4b4de9cc0c6828cda99c7548f" nan@^2.9.2: version "2.11.1" resolved "https://registry.yarnpkg.com/nan/-/nan-2.11.1.tgz#90e22bccb8ca57ea4cd37cc83d3819b52eea6766" - -nano-json-stream-parser@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" + integrity sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA== nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== dependencies: arr-diff "^4.0.0" array-unique "^0.3.2" @@ -10289,6 +9977,7 @@ nearley@^2.7.10: 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== dependencies: debug "^2.1.2" iconv-lite "^0.4.4" @@ -10410,6 +10099,7 @@ node-object-hash@^1.2.0: node-pre-gyp@^0.10.0: version "0.10.3" resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz#3070040716afdc778747b61b6887bf78880b80fc" + integrity sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A== dependencies: detect-libc "^1.0.2" mkdirp "^0.5.1" @@ -10455,6 +10145,7 @@ node-sass@^4.9.2: nodemon@^1.18.4: version "1.18.7" resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-1.18.7.tgz#716b66bf3e89ac4fcfb38a9e61887a03fc82efbb" + integrity sha512-xuC1V0F5EcEyKQ1VhHYD13owznQbUw29JKvZ8bVH7TmuvVNHvvbp9pLgE4PjTMRJVe0pJ8fGRvwR2nMiosIsPQ== dependencies: chokidar "^2.0.4" debug "^3.1.0" @@ -10490,6 +10181,7 @@ nomnom@~1.6.2: nopt@^4.0.1, nopt@~4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= dependencies: abbrev "1" osenv "^0.1.4" @@ -10497,6 +10189,7 @@ nopt@^4.0.1, nopt@~4.0.1: nopt@~1.0.10: version "1.0.10" resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= dependencies: abbrev "1" @@ -10542,6 +10235,7 @@ npm-audit-report@^1.3.1: npm-bundled@^1.0.1: version "1.0.5" resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.0.5.tgz#3c1732b7ba936b3a10325aef616467c0ccbcc979" + integrity sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g== npm-cache-filename@~1.0.2: version "1.0.2" @@ -10589,6 +10283,7 @@ npm-packlist@^1.1.10, npm-packlist@~1.1.10: npm-packlist@^1.1.6: version "1.1.12" resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.1.12.tgz#22bde2ebc12e72ca482abd67afc51eb49377243a" + integrity sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g== dependencies: ignore-walk "^3.0.1" npm-bundled "^1.0.1" @@ -10655,6 +10350,7 @@ npm-registry-fetch@^3.0.0: npm-run-path@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= dependencies: path-key "^2.0.0" @@ -10786,6 +10482,7 @@ npm@^6.1.0: "npmlog@0 || 1 || 2 || 3 || 4", "npmlog@2 || ^3.1.0 || ^4.0.0", npmlog@^4.0.0, npmlog@^4.0.2, npmlog@^4.1.2, npmlog@~4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== dependencies: are-we-there-yet "~1.1.2" console-control-strings "~1.1.0" @@ -10805,13 +10502,7 @@ num2fraction@^1.2.2: number-is-nan@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" - -number-to-bn@1.7.0: - version "1.7.0" - resolved "https://registry.yarnpkg.com/number-to-bn/-/number-to-bn-1.7.0.tgz#bb3623592f7e5f9e0030b1977bd41a0c53fe1ea0" - dependencies: - bn.js "4.11.6" - strip-hex-prefix "1.0.0" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= numeral@^2.0.6: version "2.0.6" @@ -10833,13 +10524,10 @@ object-assign@4.x, object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.0, version "4.1.1" resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" -object-assign@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-3.0.0.tgz#9bedd5ca0897949bca47e7ff408062d549f587f2" - object-copy@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= dependencies: copy-descriptor "^0.1.0" define-property "^0.2.5" @@ -10849,10 +10537,6 @@ object-inspect@^1.6.0, object-inspect@~1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.6.0.tgz#c70b6cbf72f274aab4c34c0c82f5167bf82cf15b" -object-inspect@~0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-0.4.0.tgz#f5157c116c1455b243b06ee97703392c5ad89fec" - object-is@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.1.tgz#0aa60ec9989a0b3ed795cf4d06f62cf1ad6539b6" @@ -10868,6 +10552,7 @@ object-keys@^1.0.8: object-visit@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= dependencies: isobject "^3.0.0" @@ -10915,6 +10600,7 @@ object.omit@^2.0.0: object.pick@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= dependencies: isobject "^3.0.1" @@ -10927,12 +10613,6 @@ object.values@^1.0.4: function-bind "^1.1.0" has "^1.0.1" -oboe@2.1.3: - version "2.1.3" - resolved "https://registry.yarnpkg.com/oboe/-/oboe-2.1.3.tgz#2b4865dbd46be81225713f4e9bfe4bcf4f680a4f" - dependencies: - http-https "^1.0.0" - obuf@^1.0.0, obuf@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" @@ -11043,6 +10723,7 @@ os-browserify@^0.3.0: os-homedir@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= os-locale@^1.4.0: version "1.4.0" @@ -11080,6 +10761,7 @@ os-tmpdir@^1.0.0, os-tmpdir@^1.0.1, os-tmpdir@~1.0.2: osenv@0, osenv@^0.1.4, osenv@^0.1.5: version "0.1.5" resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== dependencies: os-homedir "^1.0.0" os-tmpdir "^1.0.0" @@ -11101,6 +10783,7 @@ p-defer@^1.0.0: p-finally@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= p-is-promise@^1.1.0: version "1.1.0" @@ -11178,6 +10861,7 @@ pac-resolver@^3.0.0: package-json@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/package-json/-/package-json-4.0.1.tgz#8869a0401253661c4c4ca3da6c2121ed555f5eed" + integrity sha1-iGmgQBJTZhxMTKPabCEh7VVfXu0= dependencies: got "^6.7.1" registry-auth-token "^3.0.1" @@ -11327,6 +11011,7 @@ parseurl@~1.3.2: pascalcase@^0.1.1: version "0.1.1" resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= path-browserify@0.0.0: version "0.0.0" @@ -11335,6 +11020,7 @@ path-browserify@0.0.0: path-dirname@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= path-exists@^2.0.0: version "2.1.0" @@ -11353,6 +11039,7 @@ path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: path-is-inside@^1.0.1, path-is-inside@^1.0.2, path-is-inside@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= path-key@^2.0.0, path-key@^2.0.1: version "2.0.1" @@ -11437,6 +11124,7 @@ pify@^2.0.0, pify@^2.3.0: pify@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= pinkie-promise@^2.0.0: version "2.0.1" @@ -11492,10 +11180,6 @@ pngjs@^3.0.0, pngjs@^3.2.0, pngjs@^3.3.3: version "3.3.3" resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.3.3.tgz#85173703bde3edac8998757b96e5821d0966a21b" -pnglib@0.0.1: - version "0.0.1" - resolved "https://registry.yarnpkg.com/pnglib/-/pnglib-0.0.1.tgz#f9ab6f9c688f4a9d579ad8be28878a716e30c096" - point-at-length@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/point-at-length/-/point-at-length-1.0.2.tgz#9176d8d6d7c8162f12b646f707db9f0ea728125e" @@ -11515,6 +11199,7 @@ portfinder@^1.0.9: posix-character-classes@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= postcss-calc@^6.0.0: version "6.0.1" @@ -11883,6 +11568,7 @@ process-nextick-args@^2.0.0, process-nextick-args@~2.0.0: process-nextick-args@~1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-1.0.7.tgz#150e20b756590ad3f91093f25a4f2ad8bff30ba3" + integrity sha1-FQ4gt1ZZCtP5EJPyWk8q2L/zC6M= process@^0.11.10: version "0.11.10" @@ -11959,13 +11645,6 @@ protoduck@^5.0.0: dependencies: genfun "^4.0.1" -proxy-addr@~2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.2.tgz#6571504f47bb988ec8180253f85dd7e14952bdec" - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.5.2" - proxy-addr@~2.0.3: version "2.0.4" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.4.tgz#ecfc733bf22ff8c6f407fa275327b9ab67e48b93" @@ -12001,6 +11680,7 @@ prr@~1.0.1: pseudomap@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3" + integrity sha1-8FKijacOYYkX7wqKw0wa5aaChrM= psl@^1.1.24: version "1.1.29" @@ -12009,6 +11689,7 @@ psl@^1.1.24: pstree.remy@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.2.tgz#4448bbeb4b2af1fed242afc8dc7416a6f504951a" + integrity sha512-vL6NLxNHzkNTjGJUpMm5PLC+94/0tTlC1vkP9bdU0pOHih+EujMjgMTwfZopZvHWRFbqJ5Y73OMoau50PewDDA== public-encrypt@^4.0.0: version "4.0.0" @@ -12077,12 +11758,6 @@ query-string@6.1.0, query-string@^6.1.0: decode-uri-component "^0.2.0" strict-uri-encode "^2.0.0" -query-string@^2.4.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/query-string/-/query-string-2.4.2.tgz#7db0666420804baa92ae9f268962855a76143dfb" - dependencies: - strict-uri-encode "^1.0.0" - query-string@^4.1.0: version "4.3.4" resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" @@ -12158,10 +11833,6 @@ randomfill@^1.0.3: randombytes "^2.0.5" safe-buffer "^5.1.0" -randomhex@0.1.5: - version "0.1.5" - resolved "https://registry.yarnpkg.com/randomhex/-/randomhex-0.1.5.tgz#baceef982329091400f2a2912c6cd02f1094f585" - range-parser@^1.0.3, range-parser@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" @@ -12562,6 +12233,7 @@ rc-util@^4.0.4, rc-util@^4.1.0, rc-util@^4.1.1, rc-util@^4.3.0, rc-util@^4.4.0, rc@^1.0.1, rc@^1.1.6, rc@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== dependencies: deep-extend "^0.6.0" ini "~1.3.0" @@ -12989,7 +12661,7 @@ readable-stream@1.1.x, readable-stream@~1.1.10: isarray "0.0.1" string_decoder "~0.10.x" -readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.5, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.3.3: +readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.2.6, readable-stream@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.3.tgz#368f2512d79f9d46fdfc71349ae7878bbc1eb95c" dependencies: @@ -13013,6 +12685,7 @@ readdir-scoped-modules@^1.0.0: readdirp@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== dependencies: graceful-fs "^4.1.11" micromatch "^3.1.10" @@ -13163,6 +12836,7 @@ regex-cache@^0.4.2: regex-not@^1.0.0, regex-not@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== dependencies: extend-shallow "^3.0.2" safe-regex "^1.1.0" @@ -13195,6 +12869,7 @@ regexpu-core@^4.1.3, regexpu-core@^4.2.0: registry-auth-token@^3.0.1: version "3.3.2" resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" + integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== dependencies: rc "^1.1.6" safe-buffer "^5.0.1" @@ -13202,6 +12877,7 @@ registry-auth-token@^3.0.1: registry-url@^3.0.3: version "3.1.0" resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + integrity sha1-PU74cPc93h138M+aOBQyRE4XSUI= dependencies: rc "^1.0.1" @@ -13236,6 +12912,7 @@ relateurl@0.2.x: remove-trailing-separator@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= render-fragment@^0.1.1: version "0.1.1" @@ -13244,6 +12921,7 @@ render-fragment@^0.1.1: repeat-element@^1.1.2: version "1.1.3" resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== repeat-string@^1.5.2, repeat-string@^1.6.1: version "1.6.1" @@ -13333,7 +13011,7 @@ request@^2.65.0, request@^2.81.0, request@^2.83.0, request@^2.87.0, request@^2.8 tunnel-agent "^0.6.0" uuid "^3.3.2" -request@^2.74.0, request@^2.79.0: +request@^2.74.0: version "2.83.0" resolved "https://registry.yarnpkg.com/request/-/request-2.83.0.tgz#ca0b65da02ed62935887808e6f510381034e3356" dependencies: @@ -13433,6 +13111,7 @@ resolve-pathname@^2.2.0: resolve-url@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= resolve@1.1.7: version "1.1.7" @@ -13473,6 +13152,7 @@ resumer@~0.0.0: ret@~0.1.10: version "0.1.15" resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== retry@^0.10.0: version "0.10.1" @@ -13509,12 +13189,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^2.0.0" inherits "^2.0.1" -rlp@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.1.0.tgz#e4f9886d5a982174f314543831e36e1a658460f9" - dependencies: - safe-buffer "^5.1.1" - rmc-feedback@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/rmc-feedback/-/rmc-feedback-2.0.0.tgz#cbc6cb3ae63c7a635eef0e25e4fbaf5ac366eeaa" @@ -13590,16 +13264,19 @@ safe-buffer@5.1.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1: safe-buffer@5.1.2, safe-buffer@^5.0.1, safe-buffer@^5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== safe-regex@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= dependencies: ret "~0.1.10" "safer-buffer@>= 2.1.2 < 3": version "2.1.2" resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sane@^2.0.0: version "2.5.2" @@ -13654,25 +13331,6 @@ scoped-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" -scrypt.js@0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/scrypt.js/-/scrypt.js-0.2.0.tgz#af8d1465b71e9990110bedfc593b9479e03a8ada" - dependencies: - scrypt "^6.0.2" - scryptsy "^1.2.1" - -scrypt@^6.0.2: - version "6.0.3" - resolved "https://registry.yarnpkg.com/scrypt/-/scrypt-6.0.3.tgz#04e014a5682b53fa50c2d5cce167d719c06d870d" - dependencies: - nan "^2.0.8" - -scryptsy@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/scryptsy/-/scryptsy-1.2.1.tgz#a3225fa4b2524f802700761e2855bdf3b2d92163" - dependencies: - pbkdf2 "^3.0.3" - scss-tokenizer@^0.2.3: version "0.2.3" resolved "https://registry.yarnpkg.com/scss-tokenizer/-/scss-tokenizer-0.2.3.tgz#8eb06db9a9723333824d3f5530641149847ce5d1" @@ -13684,25 +13342,6 @@ seamless-immutable@^7.1.3: version "7.1.4" resolved "https://registry.yarnpkg.com/seamless-immutable/-/seamless-immutable-7.1.4.tgz#6e9536def083ddc4dea0207d722e0e80d0f372f8" -secp256k1@^3.0.1: - version "3.5.0" - resolved "https://registry.yarnpkg.com/secp256k1/-/secp256k1-3.5.0.tgz#677d3b8a8e04e1a5fa381a1ae437c54207b738d0" - dependencies: - bindings "^1.2.1" - bip66 "^1.1.3" - bn.js "^4.11.3" - create-hash "^1.1.2" - drbg.js "^1.0.1" - elliptic "^6.2.3" - nan "^2.2.1" - safe-buffer "^5.1.0" - -seek-bzip@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/seek-bzip/-/seek-bzip-1.0.5.tgz#cfe917cb3d274bcffac792758af53173eb1fabdc" - dependencies: - commander "~2.8.1" - select-hose@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" @@ -13720,6 +13359,7 @@ semver-compare@^1.0.0: semver-diff@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/semver-diff/-/semver-diff-2.1.0.tgz#4bbb8437c8d37e4b0cf1a68fd726ec6d645d6d36" + integrity sha1-S7uEN8jTfksM8aaP1ybsbWRdbTY= dependencies: semver "^5.0.3" @@ -13734,29 +13374,12 @@ semver-diff@^2.0.0: semver@^5.0.3, semver@^5.1.0, semver@^5.3.0, semver@^5.5.0: version "5.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.6.0.tgz#7e74256fbaa49c75aa7c7a205cc22799cac80004" + integrity sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg== semver@~5.3.0: version "5.3.0" resolved "https://registry.yarnpkg.com/semver/-/semver-5.3.0.tgz#9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f" -send@0.16.1: - version "0.16.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.16.1.tgz#a70e1ca21d1382c11d0d9f6231deb281080d7ab3" - dependencies: - debug "2.6.9" - depd "~1.1.1" - destroy "~1.0.4" - encodeurl "~1.0.1" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.6.2" - mime "1.4.1" - ms "2.0.0" - on-finished "~2.3.0" - range-parser "~1.2.0" - statuses "~1.3.1" - send@0.16.2: version "0.16.2" resolved "https://registry.yarnpkg.com/send/-/send-0.16.2.tgz#6ecca1e0f8c156d141597559848df64730a6bbc1" @@ -13801,15 +13424,6 @@ serve-index@^1.7.2: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.13.1: - version "1.13.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.1.tgz#4c57d53404a761d8f2e7c1e8a18a47dbf278a719" - dependencies: - encodeurl "~1.0.1" - escape-html "~1.0.3" - parseurl "~1.3.2" - send "0.16.1" - serve-static@1.13.2: version "1.13.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.13.2.tgz#095e8472fd5b46237db50ce486a43f4b86c6cec1" @@ -13819,16 +13433,6 @@ serve-static@1.13.2: parseurl "~1.3.2" send "0.16.2" -servify@^0.1.12: - version "0.1.12" - resolved "https://registry.yarnpkg.com/servify/-/servify-0.1.12.tgz#142ab7bee1f1d033b66d0707086085b17c06db95" - dependencies: - body-parser "^1.16.0" - cors "^2.8.1" - express "^4.14.0" - request "^2.79.0" - xhr "^2.3.3" - set-blocking@^2.0.0, set-blocking@~2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" @@ -13836,6 +13440,7 @@ set-blocking@^2.0.0, set-blocking@~2.0.0: set-value@^0.4.3: version "0.4.3" resolved "https://registry.yarnpkg.com/set-value/-/set-value-0.4.3.tgz#7db08f9d3d22dc7f78e53af3c3bf4666ecdfccf1" + integrity sha1-fbCPnT0i3H945Trzw79GZuzfzPE= dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -13845,6 +13450,7 @@ set-value@^0.4.3: set-value@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.0.tgz#71ae4a88f0feefbbf52d1ea604f3fb315ebb6274" + integrity sha512-hw0yxk9GT/Hr5yJEYnHNKYXkIA8mVJgd9ditYZCe16ZczcaELYYcfvaXesNACk2O8O0nTiPQcQhGUQj8JLzeeg== dependencies: extend-shallow "^2.0.1" is-extendable "^0.1.1" @@ -13870,12 +13476,6 @@ sha.js@^2.4.0, sha.js@^2.4.8: inherits "^2.0.1" safe-buffer "^5.0.1" -sha3@^1.1.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/sha3/-/sha3-1.2.0.tgz#6989f1b70a498705876a373e2c62ace96aa9399a" - dependencies: - nan "^2.0.5" - sha@~2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/sha/-/sha-2.0.1.tgz#6030822fbd2c9823949f8f72ed6411ee5cf25aae" @@ -13909,12 +13509,14 @@ shallowequal@^1.0.1, shallowequal@^1.0.2, shallowequal@^1.1.0: shebang-command@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= dependencies: shebang-regex "^1.0.0" shebang-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= shell-quote@1.6.1: version "1.6.1" @@ -13943,21 +13545,10 @@ showdown@^1.8.6: dependencies: yargs "^10.0.3" -sigmund@~1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" - signal-exit@^3.0.0, signal-exit@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" - -simple-get@^1.4.3: - version "1.4.3" - resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-1.4.3.tgz#e9755eda407e96da40c5e5158c9ea37b33becbeb" - dependencies: - once "^1.3.1" - unzip-response "^1.0.0" - xtend "^4.0.0" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= simple-statistics@~6.1.0: version "6.1.1" @@ -14010,6 +13601,7 @@ smart-buffer@^4.0.1: snapdragon-node@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== dependencies: define-property "^1.0.0" isobject "^3.0.0" @@ -14018,12 +13610,14 @@ snapdragon-node@^2.0.1: snapdragon-util@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== dependencies: kind-of "^3.2.0" snapdragon@^0.8.1: version "0.8.2" resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== dependencies: base "^0.11.1" debug "^2.2.0" @@ -14135,6 +13729,7 @@ source-list-map@^2.0.0: source-map-resolve@^0.5.0: version "0.5.2" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.2.tgz#72e2cc34095543e43b2c62b2c4c10d4a9054f259" + integrity sha512-MjqsvNwyz1s0k81Goz/9vRBe9SZdB09Bdw+/zYyO+3CuPk6fouTaxscHkgtE8jKvf01kVfl8riHzERQ/kefaSA== dependencies: atob "^2.1.1" decode-uri-component "^0.2.0" @@ -14164,6 +13759,7 @@ source-map-support@^0.5.6, source-map-support@^0.5.9: source-map-url@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= source-map@0.1.32: version "0.1.32" @@ -14247,6 +13843,7 @@ spdy@^3.4.1: split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== dependencies: extend-shallow "^3.0.0" @@ -14301,6 +13898,7 @@ staged-git-files@1.1.1: static-extend@^0.1.1: version "0.1.2" resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= dependencies: define-property "^0.2.5" object-copy "^0.1.0" @@ -14319,10 +13917,6 @@ stats-webpack-plugin@^0.7.0: version "1.5.0" resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" -statuses@~1.3.1: - version "1.3.1" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.3.1.tgz#faf51b9eb74aaef3b3acf4ad5f61abf24cb7b93e" - std-env@^1.1.0, std-env@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/std-env/-/std-env-1.3.1.tgz#4e1758412439e9ece1d437b1b098551911aa44ee" @@ -14418,6 +14012,7 @@ string-template@~0.2.1: string-width@^1.0.1, string-width@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= dependencies: code-point-at "^1.0.0" is-fullwidth-code-point "^1.0.0" @@ -14529,21 +14124,10 @@ strip-bom@^2.0.0: dependencies: is-utf8 "^0.2.0" -strip-dirs@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/strip-dirs/-/strip-dirs-2.1.0.tgz#4987736264fc344cf20f6c34aca9d13d1d4ed6c5" - dependencies: - is-natural-number "^4.0.1" - strip-eof@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" - -strip-hex-prefix@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/strip-hex-prefix/-/strip-hex-prefix-1.0.0.tgz#0c5f155fef1151373377de9dbb588da05500e36f" - dependencies: - is-hex-prefixed "1.0.0" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= strip-indent@^1.0.1: version "1.0.1" @@ -14605,6 +14189,7 @@ supports-color@^3.1.2: supports-color@^5.1.0, supports-color@^5.2.0, supports-color@^5.3.0: version "5.5.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== dependencies: has-flag "^3.0.0" @@ -14668,24 +14253,6 @@ svgo@^1.0.5: unquote "~1.1.1" util.promisify "~1.0.0" -swarm-js@0.1.37: - version "0.1.37" - resolved "https://registry.yarnpkg.com/swarm-js/-/swarm-js-0.1.37.tgz#27d485317a340bbeec40292af783cc10acfa4663" - dependencies: - bluebird "^3.5.0" - buffer "^5.0.5" - decompress "^4.0.0" - eth-lib "^0.1.26" - fs-extra "^2.1.2" - fs-promise "^2.0.0" - got "^7.1.0" - mime-types "^2.1.16" - mkdirp-promise "^5.0.1" - mock-fs "^4.1.0" - setimmediate "^1.0.5" - tar.gz "^1.0.5" - xhr-request-promise "^0.1.2" - symbol-observable@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.0.1.tgz#8340fc4702c3122df5d22288f88283f513d3fdd4" @@ -14723,18 +14290,6 @@ tapable@^1.0.0-beta.5, tapable@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.0.tgz#0d076a172e3d9ba088fd2272b2668fb8d194b78c" -tape@^3.0.3: - version "3.6.1" - resolved "https://registry.yarnpkg.com/tape/-/tape-3.6.1.tgz#4893dd53e280a5f58c0ceb30c2c0ebb3bcd51e1f" - dependencies: - deep-equal "~0.2.0" - defined "~0.0.0" - glob "~3.2.9" - inherits "~2.0.1" - object-inspect "~0.4.0" - resumer "~0.0.0" - through "~2.3.4" - tape@^4.5.1: version "4.9.1" resolved "https://registry.yarnpkg.com/tape/-/tape-4.9.1.tgz#1173d7337e040c76fbf42ec86fcabedc9b3805c9" @@ -14753,26 +14308,7 @@ tape@^4.5.1: string.prototype.trim "~1.1.2" through "~2.3.8" -tar-stream@^1.5.2: - version "1.5.5" - resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.5.5.tgz#5cad84779f45c83b1f2508d96b09d88c7218af55" - dependencies: - bl "^1.0.0" - end-of-stream "^1.0.0" - readable-stream "^2.0.0" - xtend "^4.0.0" - -tar.gz@^1.0.5: - version "1.0.7" - resolved "https://registry.yarnpkg.com/tar.gz/-/tar.gz-1.0.7.tgz#577ef2c595faaa73452ef0415fed41113212257b" - dependencies: - bluebird "^2.9.34" - commander "^2.8.1" - fstream "^1.0.8" - mout "^0.11.0" - tar "^2.1.1" - -tar@^2.0.0, tar@^2.1.1: +tar@^2.0.0: version "2.2.1" resolved "https://registry.yarnpkg.com/tar/-/tar-2.2.1.tgz#8e4d2a256c0e2185c6b18ad694aec968b83cb1d1" dependencies: @@ -14783,6 +14319,7 @@ tar@^2.0.0, tar@^2.1.1: tar@^4: version "4.4.8" resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.8.tgz#b19eec3fde2a96e64666df9fdb40c5ca1bc3747d" + integrity sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ== dependencies: chownr "^1.1.1" fs-minipass "^1.2.5" @@ -14807,6 +14344,7 @@ tar@^4.4.3, tar@^4.4.6: term-size@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-1.2.0.tgz#458b83887f288fc56d6fffbfad262e26638efa69" + integrity sha1-RYuDiH8oj8Vtb/+/rSYuJmOO+mk= dependencies: execa "^0.7.0" @@ -14832,7 +14370,7 @@ textextensions@2: version "2.2.0" resolved "https://registry.yarnpkg.com/textextensions/-/textextensions-2.2.0.tgz#38ac676151285b658654581987a0ce1a4490d286" -thenify-all@^1.0.0, thenify-all@^1.6.0: +thenify-all@^1.0.0: version "1.6.0" resolved "https://registry.yarnpkg.com/thenify-all/-/thenify-all-1.6.0.tgz#1a1918d402d8fc3f98fbf234db0bcc8cc10e9726" dependencies: @@ -14871,13 +14409,10 @@ thunky@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.0.2.tgz#a862e018e3fb1ea2ec3fce5d55605cf57f247371" -timed-out@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-2.0.0.tgz#f38b0ae81d3747d628001f41dafc652ace671c0a" - timed-out@^4.0.0: version "4.0.1" resolved "https://registry.yarnpkg.com/timed-out/-/timed-out-4.0.1.tgz#f32eacac5a175bea25d7fab565ab3ed8741ef56f" + integrity sha1-8y6srFoXW+ol1/q1Zas+2HQe9W8= timers-browserify@^2.0.4: version "2.0.4" @@ -14936,12 +14471,14 @@ to-ico@^1.1.5: to-object-path@^0.3.0: version "0.3.0" resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= dependencies: kind-of "^3.0.2" to-regex-range@^2.1.0: version "2.1.1" resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= dependencies: is-number "^3.0.0" repeat-string "^1.6.1" @@ -14949,6 +14486,7 @@ to-regex-range@^2.1.0: to-regex@^3.0.1, to-regex@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== dependencies: define-property "^2.0.2" extend-shallow "^3.0.2" @@ -14968,6 +14506,7 @@ topojson-client@~3.0.0: touch@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b" + integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA== dependencies: nopt "~1.0.10" @@ -14990,14 +14529,6 @@ tr46@^1.0.1: dependencies: punycode "^2.1.0" -trezor-connect@5.0.33: - version "5.0.33" - resolved "https://registry.yarnpkg.com/trezor-connect/-/trezor-connect-5.0.33.tgz#1acdb16439e03f3ef017671b5bd3be1d89b16238" - dependencies: - babel-runtime "^6.26.0" - events "^1.1.1" - whatwg-fetch "^2.0.4" - trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -15182,12 +14713,6 @@ type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" -typedarray-to-buffer@^3.1.2: - version "3.1.2" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.2.tgz#1017b32d984ff556eba100f501589aba1ace2e04" - dependencies: - is-typedarray "^1.0.0" - typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -15196,10 +14721,6 @@ typescript@3.0.3, typescript@^3.0.1: version "3.0.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.0.3.tgz#4853b3e275ecdaa27f78fda46dc273a7eb7fc1c8" -u2f-api@0.2.7: - version "0.2.7" - resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720" - ua-parser-js@^0.7.18: version "0.7.18" resolved "https://registry.yarnpkg.com/ua-parser-js/-/ua-parser-js-0.7.18.tgz#a7bfd92f56edfb117083b69e31d2aa8882d4b1ed" @@ -15252,10 +14773,6 @@ uid-number@0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/uid-number/-/uid-number-0.0.6.tgz#0ea10e8035e8eb5b8e4449f06da1c730663baa81" -ultron@~1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/ultron/-/ultron-1.1.0.tgz#b07a2e6a541a815fc6a34ccd4533baec307ca864" - umask@^1.1.0, umask@~1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/umask/-/umask-1.1.0.tgz#f29cebf01df517912bb58ff9c4e50fde8e33320d" @@ -15372,22 +14889,17 @@ umi@^2.0.0-beta.10: url "^0.11.0" yargs-parser "^10.1.0" -unbzip2-stream@^1.0.9: - version "1.2.5" - resolved "https://registry.yarnpkg.com/unbzip2-stream/-/unbzip2-stream-1.2.5.tgz#73a033a567bbbde59654b193c44d48a7e4f43c47" - dependencies: - buffer "^3.0.1" - through "^2.3.6" - undefsafe@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.2.tgz#225f6b9e0337663e0d8e7cfd686fc2836ccace76" + integrity sha1-Il9rngM3Zj4Njnz9aG/Cg2zKznY= dependencies: debug "^2.2.0" -underscore@1.8.3: - version "1.8.3" - resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.8.3.tgz#4f3fb53b106e6097fcf9cb4109f2a5e9bdfa5022" +underscore@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.9.1.tgz#06dce34a0e68a7babc29b365b8e74b8925203961" + integrity sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg== underscore@~1.4.4: version "1.4.4" @@ -15425,6 +14937,7 @@ unicode-property-aliases-ecmascript@^1.0.4: union-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.0.tgz#5c71c34cb5bad5dcebe3ea0cd08207ba5aa1aea4" + integrity sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ= dependencies: arr-union "^3.1.0" get-value "^2.0.6" @@ -15454,6 +14967,7 @@ unique-slug@^2.0.0: unique-string@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unique-string/-/unique-string-1.0.0.tgz#9e1057cca851abb93398f8b33ae187b99caec11a" + integrity sha1-nhBXzKhRq7kzmPizOuGHuZyuwRo= dependencies: crypto-random-string "^1.0.0" @@ -15482,6 +14996,7 @@ unquote@~1.1.1: unset-value@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= dependencies: has-value "^0.3.1" isobject "^3.0.0" @@ -15490,21 +15005,20 @@ untildify@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9" -unzip-response@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-1.0.2.tgz#b984f0877fc0a89c2c773cc1ef7b5b232b5b06fe" - unzip-response@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/unzip-response/-/unzip-response-2.0.1.tgz#d2f0f737d16b0615e72a6935ed04214572d56f97" + integrity sha1-0vD3N9FrBhXnKmk17QQhRXLVb5c= upath@^1.0.5: version "1.1.0" resolved "https://registry.yarnpkg.com/upath/-/upath-1.1.0.tgz#35256597e46a581db4793d0ce47fa9aebfc9fabd" + integrity sha512-bzpH/oBhoS/QI/YtbkqCg6VEiPYjSZtrHQM6/QnJS6OL9pKUFLqb3aFh4Scvwm45+7iAgiMkLhSbaZxUqmrprw== update-notifier@^2.3.0, update-notifier@^2.5.0: version "2.5.0" resolved "https://registry.yarnpkg.com/update-notifier/-/update-notifier-2.5.0.tgz#d0744593e13f161e406acb1d9408b72cad08aff6" + integrity sha512-gwMdhgJHGuj/+wHJJs9e6PcCszpxR1b236igrOkUofGhqJuG+amlIKwApH1IW1WWl7ovZxsX49lMBWLxSdm5Dw== dependencies: boxen "^1.2.1" chalk "^2.0.1" @@ -15536,6 +15050,7 @@ uri-js@^4.2.2: urix@^0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= url-join@^4.0.0: version "4.0.0" @@ -15552,6 +15067,7 @@ url-loader@^1.0.1, url-loader@^1.1.1: url-parse-lax@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/url-parse-lax/-/url-parse-lax-1.0.0.tgz#7af8f303645e9bd79a272e7a14ac68bc0609da73" + integrity sha1-evjzA2Rem9eaJy56FKxovAYJ2nM= dependencies: prepend-http "^1.0.1" @@ -15568,10 +15084,6 @@ url-regex@^3.0.0: dependencies: ip-regex "^1.0.1" -url-set-query@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/url-set-query/-/url-set-query-1.0.0.tgz#016e8cfd7c20ee05cafe7795e892bd0702faa339" - url-to-options@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/url-to-options/-/url-to-options-1.0.1.tgz#1505a03a289a48cbd7a434efbaeec5055f5633a9" @@ -15605,10 +15117,7 @@ urllib@^2.29.1: use@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" - -utf8@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/utf8/-/utf8-2.1.1.tgz#2e01db02f7d8d0944f77104f1609eb0c304cf768" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== utif@^2.0.1: version "2.0.1" @@ -15619,6 +15128,7 @@ utif@^2.0.1: util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= util-extend@^1.0.1: version "1.0.3" @@ -15657,10 +15167,6 @@ utils-merge@1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" -uuid@2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-2.0.1.tgz#c2a30dedb3e535d72ccf82e343941a50ba8533ac" - uuid@^3.0.1, uuid@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131" @@ -15831,201 +15337,6 @@ wcwidth@^1.0.0: dependencies: defaults "^1.0.3" -web3-bzz@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.0.0-beta.35.tgz#9d5e1362b3db2afd77d65619b7cd46dd5845c192" - dependencies: - got "7.1.0" - swarm-js "0.1.37" - underscore "1.8.3" - -web3-core-helpers@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.0.0-beta.35.tgz#d681d218a0c6e3283ee1f99a078ab9d3eef037f1" - dependencies: - underscore "1.8.3" - web3-eth-iban "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-core-method@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.0.0-beta.35.tgz#fc10e2d546cf4886038e6130bd5726b0952a4e5f" - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.35" - web3-core-promievent "1.0.0-beta.35" - web3-core-subscriptions "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-core-promievent@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.0.0-beta.35.tgz#4f1b24737520fa423fee3afee110fbe82bcb8691" - dependencies: - any-promise "1.3.0" - eventemitter3 "1.1.1" - -web3-core-requestmanager@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.0.0-beta.35.tgz#2b77cbf6303720ad68899b39fa7f584dc03dbc8f" - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.35" - web3-providers-http "1.0.0-beta.35" - web3-providers-ipc "1.0.0-beta.35" - web3-providers-ws "1.0.0-beta.35" - -web3-core-subscriptions@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.0.0-beta.35.tgz#c1b76a2ad3c6e80f5d40b8ba560f01e0f4628758" - dependencies: - eventemitter3 "1.1.1" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.35" - -web3-core@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.0.0-beta.35.tgz#0c44d3c50d23219b0b1531d145607a9bc7cd4b4f" - dependencies: - web3-core-helpers "1.0.0-beta.35" - web3-core-method "1.0.0-beta.35" - web3-core-requestmanager "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-eth-abi@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.0.0-beta.35.tgz#2eb9c1c7c7233db04010defcb192293e0db250e6" - dependencies: - bn.js "4.11.6" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-eth-accounts@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.0.0-beta.35.tgz#7d0e5a69f510dc93874471599eb7abfa9ddf3e63" - dependencies: - any-promise "1.3.0" - crypto-browserify "3.12.0" - eth-lib "0.2.7" - scrypt.js "0.2.0" - underscore "1.8.3" - uuid "2.0.1" - web3-core "1.0.0-beta.35" - web3-core-helpers "1.0.0-beta.35" - web3-core-method "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-eth-contract@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.0.0-beta.35.tgz#5276242d8a3358d9f1ce92b71575c74f9015935c" - dependencies: - underscore "1.8.3" - web3-core "1.0.0-beta.35" - web3-core-helpers "1.0.0-beta.35" - web3-core-method "1.0.0-beta.35" - web3-core-promievent "1.0.0-beta.35" - web3-core-subscriptions "1.0.0-beta.35" - web3-eth-abi "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-eth-iban@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.0.0-beta.35.tgz#5aa10327a9abb26bcfc4ba79d7bad18a002b332c" - dependencies: - bn.js "4.11.6" - web3-utils "1.0.0-beta.35" - -web3-eth-personal@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.0.0-beta.35.tgz#ecac95b7a53d04a567447062d5cae5f49879e89f" - dependencies: - web3-core "1.0.0-beta.35" - web3-core-helpers "1.0.0-beta.35" - web3-core-method "1.0.0-beta.35" - web3-net "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-eth@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.0.0-beta.35.tgz#c52c804afb95e6624b6f5e72a9af90fbf5005b68" - dependencies: - underscore "1.8.3" - web3-core "1.0.0-beta.35" - web3-core-helpers "1.0.0-beta.35" - web3-core-method "1.0.0-beta.35" - web3-core-subscriptions "1.0.0-beta.35" - web3-eth-abi "1.0.0-beta.35" - web3-eth-accounts "1.0.0-beta.35" - web3-eth-contract "1.0.0-beta.35" - web3-eth-iban "1.0.0-beta.35" - web3-eth-personal "1.0.0-beta.35" - web3-net "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-net@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.0.0-beta.35.tgz#5c6688e0dea71fcd910ee9dc5437b94b7f6b3354" - dependencies: - web3-core "1.0.0-beta.35" - web3-core-method "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - -web3-providers-http@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.0.0-beta.35.tgz#92059d9d6de6e9f82f4fae30b743efd841afc1e1" - dependencies: - web3-core-helpers "1.0.0-beta.35" - xhr2-cookies "1.1.0" - -web3-providers-ipc@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.0.0-beta.35.tgz#031afeb10fade2ebb0ef2fb82f5e58c04be842d9" - dependencies: - oboe "2.1.3" - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.35" - -web3-providers-ws@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.0.0-beta.35.tgz#5d38603fd450243a26aae0ff7f680644e77fa240" - dependencies: - underscore "1.8.3" - web3-core-helpers "1.0.0-beta.35" - websocket "git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible" - -web3-shh@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.0.0-beta.35.tgz#7e4a585f8beee0c1927390937c6537748a5d1a58" - dependencies: - web3-core "1.0.0-beta.35" - web3-core-method "1.0.0-beta.35" - web3-core-subscriptions "1.0.0-beta.35" - web3-net "1.0.0-beta.35" - -web3-utils@1.0.0-beta.35: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.0.0-beta.35.tgz#ced9e1df47c65581c441c5f2af76b05a37a273d7" - dependencies: - bn.js "4.11.6" - eth-lib "0.1.27" - ethjs-unit "0.1.6" - number-to-bn "1.7.0" - randomhex "0.1.5" - underscore "1.8.3" - utf8 "2.1.1" - -web3@^1.0.0-beta.34: - version "1.0.0-beta.35" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.0.0-beta.35.tgz#6475095bd451a96e50a32b997ddee82279292f11" - dependencies: - web3-bzz "1.0.0-beta.35" - web3-core "1.0.0-beta.35" - web3-eth "1.0.0-beta.35" - web3-eth-personal "1.0.0-beta.35" - web3-net "1.0.0-beta.35" - web3-shh "1.0.0-beta.35" - web3-utils "1.0.0-beta.35" - webapp-webpack-plugin@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/webapp-webpack-plugin/-/webapp-webpack-plugin-2.3.1.tgz#c158a9c80f219423e27f2fa4db8ec8e8fbdcb3ef" @@ -16379,15 +15690,6 @@ websocket-extensions@>=0.1.1: version "0.1.3" resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" -"websocket@git://github.com/frozeman/WebSocket-Node.git#browserifyCompatible": - version "1.0.24" - resolved "git://github.com/frozeman/WebSocket-Node.git#7004c39c42ac98875ab61126e5b4a925430f592c" - dependencies: - debug "^2.2.0" - nan "^2.3.3" - typedarray-to-buffer "^3.1.2" - yaeti "^0.0.6" - whatwg-encoding@^1.0.1, whatwg-encoding@^1.0.3, whatwg-encoding@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/whatwg-encoding/-/whatwg-encoding-1.0.4.tgz#63fb016b7435b795d9025632c086a5209dbd2621" @@ -16439,12 +15741,14 @@ which@1, which@^1.2.10, which@^1.2.12, which@^1.2.14, which@^1.2.9, which@^1.3.0 wide-align@^1.1.0: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== dependencies: string-width "^1.0.2 || 2" widest-line@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-2.0.1.tgz#7438764730ec7ef4381ce4df82fb98a53142a3fc" + integrity sha512-Ba5m9/Fa4Xt9eb2ELXt77JxVDV8w7qQrH0zS/TWSJdLyAwQjWoOzpzj5lwVftDz6n/EOu3tNACS84v509qwnJA== dependencies: string-width "^2.1.1" @@ -16518,6 +15822,7 @@ wrap-ansi@^3.0.1: wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= write-file-atomic@^2.0.0, write-file-atomic@^2.1.0, write-file-atomic@^2.3.0: version "2.3.0" @@ -16550,14 +15855,6 @@ write-json-file@^2.3.0: sort-keys "^2.0.0" write-file-atomic "^2.0.0" -ws@^3.0.0: - version "3.3.2" - resolved "https://registry.yarnpkg.com/ws/-/ws-3.3.2.tgz#96c1d08b3fefda1d5c1e33700d3bfaa9be2d5608" - dependencies: - async-limiter "~1.0.0" - safe-buffer "~5.1.0" - ultron "~1.1.0" - ws@^4.0.0: version "4.1.0" resolved "https://registry.yarnpkg.com/ws/-/ws-4.1.0.tgz#a979b5d7d4da68bf54efe0408967c324869a7289" @@ -16580,30 +15877,7 @@ ws@^6.0.0: xdg-basedir@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xdg-basedir/-/xdg-basedir-3.0.0.tgz#496b2cc109eca8dbacfe2dc72b603c17c5870ad4" - -xhr-request-promise@^0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/xhr-request-promise/-/xhr-request-promise-0.1.2.tgz#343c44d1ee7726b8648069682d0f840c83b4261d" - dependencies: - xhr-request "^1.0.1" - -xhr-request@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/xhr-request/-/xhr-request-1.0.1.tgz#83f08a4b20beec67a8c1c728e8102f4c9eecbdda" - dependencies: - buffer-to-arraybuffer "0.0.2" - object-assign "^3.0.0" - query-string "^2.4.0" - simple-get "^1.4.3" - timed-out "^2.0.0" - url-set-query "^1.0.0" - xhr "^2.0.4" - -xhr2-cookies@1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/xhr2-cookies/-/xhr2-cookies-1.1.0.tgz#7d77449d0999197f155cb73b23df72505ed89d48" - dependencies: - cookiejar "^2.1.1" + integrity sha1-SWsswQnsqNus/i3HK2A8F8WHCtQ= xhr@^2.0.1: version "2.5.0" @@ -16614,15 +15888,6 @@ xhr@^2.0.1: parse-headers "^2.0.0" xtend "^4.0.0" -xhr@^2.0.4, xhr@^2.3.3: - version "2.4.0" - resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.4.0.tgz#e16e66a45f869861eeefab416d5eff722dc40993" - dependencies: - global "~4.3.0" - is-function "^1.0.1" - parse-headers "^2.0.0" - xtend "^4.0.0" - xml-name-validator@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/xml-name-validator/-/xml-name-validator-3.0.0.tgz#6ae73e06de4d8c6e47f9fb181f78d648ad457c6a" @@ -16669,17 +15934,15 @@ y18n@^3.2.1: version "4.0.0" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" -yaeti@^0.0.6: - version "0.0.6" - resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" - yallist@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52" + integrity sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= yallist@^3.0.0, yallist@^3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.0.3.tgz#b4b049e314be545e3ce802236d6cd22cd91c3de9" + integrity sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A== yargs-parser@10.x, yargs-parser@^10.1.0: version "10.1.0" @@ -16813,13 +16076,6 @@ yauzl@2.4.1: dependencies: fd-slicer "~1.0.1" -yauzl@^2.4.2: - version "2.9.1" - resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.9.1.tgz#a81981ea70a57946133883f029c5821a89359a7f" - dependencies: - buffer-crc32 "~0.2.3" - fd-slicer "~1.0.1" - yeoman-environment@^2.0.5: version "2.3.3" resolved "https://registry.yarnpkg.com/yeoman-environment/-/yeoman-environment-2.3.3.tgz#1bd9720714cc49036e901503a789d809df8f51bf"