From 24dffd53da1137f46c3c89d711d3e1d24788f364 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Sat, 1 Aug 2020 01:15:56 +0400 Subject: [PATCH 1/2] Set inclusive false for minValue validator in sendfunds form (#1193) --- .../components/Balances/SendModal/screens/SendFunds/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx index 123a13bf..6a1d376d 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx @@ -240,7 +240,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT validate={composeValidators( required, mustBeFloat, - minValue(0), + minValue(0, false), maxValue(selectedTokenRecord?.balance), )} /> From 86cbd94b0c5395146372224f3384de15afca8862 Mon Sep 17 00:00:00 2001 From: Mikhail Mikheev Date: Sat, 1 Aug 2020 02:26:10 +0400 Subject: [PATCH 2/2] Tech debt: Add types for contracts (#1118) * typechain wip * add types for multisend * type definitions improvements * type safe contract in estimateTxGasCosts * contract type definitions wip * SafeInstance truffle -> web3 migration * fix calls for version * transactions/send enhancements * fix safe recor owner type * Stepper type definitions wip * dep bump * stepper types wip * refactoring stepper component to fix bug in load safe form * stepper types wip, addressbook reducer types wip * finally make it work * Fix ownerlist component hook in load safe * dep bump * dep bump * rollback types/history * add types for gas calc * debugging... * fix using RO web3 for sending txs * update package.json generate-types command * add ts-ignore for stepperpage * db * dep bump * as unknown as AbiItem -> as AbiItem[] * use optional chaining for isExecution in gas esimations * abiITem -> AbiItem[] * fix safeVersion utils tests * fix imports, put upgradeSafe test close to the actual code * add comment about ts-ignore usage * downgrade web3 version --- .gitignore | 3 +- package.json | 39 +- src/components/Stepper/Controls/index.tsx | 21 +- src/components/Stepper/OpenPaper/index.tsx | 27 +- src/components/Stepper/Step/index.tsx | 5 - src/components/Stepper/index.tsx | 67 +- src/logic/addressBook/model/addressBook.ts | 4 +- .../addressBook/store/reducer/addressBook.ts | 4 +- .../store/reducer/types/addressBook.d.ts | 24 + .../addressBook/store/selectors/index.ts | 23 +- src/logic/contracts/safeContracts.ts | 62 +- src/logic/safe/transactions/gasNew.ts | 61 +- src/logic/safe/transactions/send.ts | 39 +- src/logic/safe/transactions/txHistory.ts | 29 +- .../safe/utils/safeVersion.test.ts} | 22 +- src/logic/safe/utils/safeVersion.ts | 9 +- .../safe/utils/upgradeSafe.test.ts} | 16 +- src/logic/safe/utils/upgradeSafe.ts | 81 ++- .../load/components/DetailsForm/index.tsx | 24 +- src/routes/load/components/Layout.tsx | 69 +- .../load/components/OwnerList/index.tsx | 10 +- .../components/ReviewInformation/index.tsx | 284 ++++----- .../components/ReviewInformation/styles.ts | 66 ++ src/routes/load/container/Load.tsx | 6 +- src/routes/open/components/Layout.tsx | 8 +- src/routes/open/container/Open.tsx | 4 +- .../CreateEditEntryModal/index.tsx | 4 +- .../safe/components/AddressBook/index.tsx | 4 +- .../screens/AddressBookInput/index.tsx | 24 +- .../ReviewCustomTx/index.tsx | 2 +- .../SendModal/screens/SendFunds/index.tsx | 13 +- .../Settings/Advanced/RemoveModuleModal.tsx | 2 +- .../ManageOwners/AddOwnerModal/index.tsx | 2 +- .../AddOwnerModal/screens/Review/index.tsx | 4 +- .../ManageOwners/RemoveOwnerModal/index.tsx | 6 +- .../RemoveOwnerModal/screens/Review/index.tsx | 4 +- .../ManageOwners/ReplaceOwnerModal/index.tsx | 6 +- .../screens/Review/index.tsx | 4 +- .../ChangeThreshold/index.tsx | 2 +- .../Settings/ThresholdSettings/index.tsx | 2 +- .../safe/store/actions/createTransaction.ts | 19 +- .../safe/store/actions/processTransaction.ts | 5 +- src/routes/safe/store/actions/utils.ts | 22 +- src/routes/safe/store/models/safe.ts | 2 +- .../safe/store/models/types/transaction.ts | 3 +- src/store/index.ts | 3 +- src/test/safe.dom.create.tsx | 4 +- src/test/utils/ethereumErrors.ts | 10 - src/test/utils/logTransactions.ts | 81 --- yarn.lock | 595 +++++++++++++----- 50 files changed, 1038 insertions(+), 792 deletions(-) delete mode 100644 src/components/Stepper/Step/index.tsx create mode 100644 src/logic/addressBook/store/reducer/types/addressBook.d.ts rename src/{test/safe.dom.version.test.ts => logic/safe/utils/safeVersion.test.ts} (61%) rename src/{test/getEncodedMultiSendCallData.ts => logic/safe/utils/upgradeSafe.test.ts} (55%) create mode 100644 src/routes/load/components/ReviewInformation/styles.ts delete mode 100644 src/test/utils/logTransactions.ts diff --git a/.gitignore b/.gitignore index 7867fb70..681e3e63 100644 --- a/.gitignore +++ b/.gitignore @@ -9,4 +9,5 @@ electron-builder.yml /.yalc yalc.lock # testing -/coverage +/coverage/ +src/types/contracts/ diff --git a/package.json b/package.json index 40f5fa81..e86e4342 100644 --- a/package.json +++ b/package.json @@ -26,9 +26,11 @@ "electron-build": "electron-builder --mac --windows --linux", "electron-dev": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"", "format:staged": "lint-staged", + "generate-types": "yarn generate-types:contracts", + "generate-types:contracts": "typechain --target=web3-v1 --outDir './src/types/contracts' './node_modules/@gnosis.pm/safe-contracts/build/contracts/*.json'", "lint:check": "eslint './src/**/*.{js,jsx,ts,tsx}'", "lint:fix": "yarn lint:check --fix", - "postinstall": "electron-builder install-app-deps", + "postinstall": "electron-builder install-app-deps && yarn generate-types", "preelectron-pack": "yarn build", "prettier:check": "yarn prettier --check", "prettier:fix": "yarn prettier --write", @@ -165,7 +167,7 @@ "@ledgerhq/hw-transport-node-hid": "5.19.1", "@material-ui/core": "4.11.0", "@material-ui/icons": "4.9.1", - "@material-ui/lab": "4.0.0-alpha.39", + "@material-ui/lab": "4.0.0-alpha.56", "@openzeppelin/contracts": "3.1.0", "async-sema": "^3.1.0", "axios": "0.19.2", @@ -183,6 +185,7 @@ "electron-updater": "4.3.1", "eth-sig-util": "^2.5.3", "ethereum-blockies-base64": "^1.0.2", + "ethereumjs-abi": "0.6.8", "exponential-backoff": "^3.0.1", "express": "^4.17.1", "final-form": "^4.20.1", @@ -206,7 +209,7 @@ "react-ga": "3.1.2", "react-hot-loader": "4.12.21", "react-qr-reader": "^2.2.1", - "react-redux": "7.2.0", + "react-redux": "7.2.1", "react-router-dom": "5.2.0", "react-scripts": "^3.4.1", "react-window": "^1.8.5", @@ -218,23 +221,27 @@ "semver": "7.3.2", "styled-components": "^5.1.1", "truffle-contract": "4.0.31", - "web3": "1.2.11" + "web3": "1.2.9", + "web3-core": "^1.2.11", + "web3-eth-contract": "^1.2.11", + "web3-utils": "^1.2.11" }, "devDependencies": { - "@testing-library/jest-dom": "5.11.1", + "@testing-library/jest-dom": "5.11.2", "@testing-library/react": "10.4.7", - "@testing-library/user-event": "12.0.13", + "@testing-library/user-event": "12.0.17", + "@typechain/web3-v1": "^1.0.0", "@types/history": "4.6.2", "@types/jest": "^26.0.7", "@types/lodash.memoize": "^4.1.6", - "@types/node": "14.0.25", + "@types/node": "14.0.27", "@types/react": "^16.9.43", - "@types/react-dom": "^16.9.8", + "@types/react-dom": "^16.9.6", "@types/react-redux": "^7.1.9", "@types/react-router-dom": "^5.1.5", "@types/styled-components": "^5.1.1", - "@typescript-eslint/eslint-plugin": "3.7.0", - "@typescript-eslint/parser": "3.7.0", + "@typescript-eslint/eslint-plugin": "3.7.1", + "@typescript-eslint/parser": "3.7.1", "autoprefixer": "9.8.5", "cross-env": "^7.0.2", "dotenv": "^8.2.0", @@ -247,7 +254,7 @@ "eslint-plugin-import": "2.22.0", "eslint-plugin-jsx-a11y": "^6.3.1", "eslint-plugin-prettier": "^3.1.4", - "eslint-plugin-react": "^7.20.3", + "eslint-plugin-react": "^7.20.5", "eslint-plugin-sort-destructure-keys": "1.3.5", "ethereumjs-abi": "0.6.8", "husky": "^4.2.5", @@ -255,11 +262,9 @@ "node-sass": "^4.14.1", "prettier": "2.0.5", "react-app-rewired": "^2.1.6", - "source-map-explorer": "^2.4.2", - "truffle": "5.1.35", - "typescript": "^3.9.7", - "wait-on": "5.1.0", - "web3-eth-contract": "^1.2.11", - "web3-utils": "^1.2.11" + "truffle": "5.1.36", + "typechain": "^2.0.0", + "typescript": "3.9.7", + "wait-on": "5.1.0" } } diff --git a/src/components/Stepper/Controls/index.tsx b/src/components/Stepper/Controls/index.tsx index 0e1757db..711d200b 100644 --- a/src/components/Stepper/Controls/index.tsx +++ b/src/components/Stepper/Controls/index.tsx @@ -20,7 +20,25 @@ const secondButtonStyle = { fontWeight: boldFont, } -const Controls = ({ buttonLabels, currentStep, disabled, firstPage, lastPage, onPrevious, penultimate }) => { +interface Props { + buttonLabels?: string[] + currentStep: number + disabled: boolean + firstPage: boolean + lastPage: boolean + penultimate: boolean + onPrevious: () => void +} + +const Controls = ({ + buttonLabels, + currentStep, + disabled, + firstPage, + lastPage, + onPrevious, + penultimate, +}: Props): React.ReactElement => { const back = firstPage ? 'Cancel' : 'Back' let next @@ -28,7 +46,6 @@ const Controls = ({ buttonLabels, currentStep, disabled, firstPage, lastPage, on // eslint-disable-next-line next = firstPage ? 'Start' : penultimate ? 'Review' : lastPage ? 'Submit' : 'Next' } else { - // $FlowFixMe next = buttonLabels[currentStep] } diff --git a/src/components/Stepper/OpenPaper/index.tsx b/src/components/Stepper/OpenPaper/index.tsx index ffedc3b5..4e19dfbc 100644 --- a/src/components/Stepper/OpenPaper/index.tsx +++ b/src/components/Stepper/OpenPaper/index.tsx @@ -1,11 +1,11 @@ import Paper from '@material-ui/core/Paper' -import { withStyles } from '@material-ui/core/styles' +import { makeStyles } from '@material-ui/core/styles' import * as React from 'react' import Block from 'src/components/layout/Block' import { lg } from 'src/theme/variables' -const styles = () => ({ +const useStyles = makeStyles({ root: { margin: '10px', maxWidth: '770px', @@ -16,11 +16,20 @@ const styles = () => ({ }, }) -const OpenPaper = ({ children, classes, controls, padding = true }) => ( - - {children} - {controls} - -) +interface Props { + padding?: boolean + controls: React.ReactNode +} -export default withStyles(styles as any)(OpenPaper) +const OpenPaper: React.FC = ({ children, controls, padding = true }) => { + const classes = useStyles() + + return ( + + {children} + {controls} + + ) +} + +export default OpenPaper diff --git a/src/components/Stepper/Step/index.tsx b/src/components/Stepper/Step/index.tsx deleted file mode 100644 index 8a061d3d..00000000 --- a/src/components/Stepper/Step/index.tsx +++ /dev/null @@ -1,5 +0,0 @@ -import * as React from 'react' - -const Step = ({ children }) =>
{children}
- -export default Step diff --git a/src/components/Stepper/index.tsx b/src/components/Stepper/index.tsx index d40fd0fc..0147677f 100644 --- a/src/components/Stepper/index.tsx +++ b/src/components/Stepper/index.tsx @@ -2,8 +2,9 @@ import FormStep from '@material-ui/core/Step' import StepContent from '@material-ui/core/StepContent' import StepLabel from '@material-ui/core/StepLabel' import Stepper from '@material-ui/core/Stepper' -import { withStyles } from '@material-ui/core/styles' -import * as React from 'react' +import { makeStyles } from '@material-ui/core/styles' +import React, { useCallback, useEffect, useState } from 'react' +import { FormApi } from 'final-form' import Controls from './Controls' @@ -11,10 +12,6 @@ import GnoForm from 'src/components/forms/GnoForm' import Hairline from 'src/components/layout/Hairline' import { history } from 'src/store' -const { useEffect, useState } = React - -export { default as Step } from './Step' - const transitionProps = { timeout: { enter: 350, @@ -22,11 +19,47 @@ const transitionProps = { }, } -export const StepperPage = ({ children }: any) => children +export interface StepperPageFormProps { + values: Record + errors: Record + form: FormApi +} -const GnoStepper = (props: any) => { +interface StepperPageProps { + validate?: (...args: unknown[]) => undefined | string[] | Promise> + component: ( + ...args: unknown[] + ) => (controls: React.ReactElement, formProps: StepperPageFormProps) => React.ReactElement + [key: string]: unknown +} + +// TODO: Remove this magic +/* eslint-disable */ +// @ts-ignore +export const StepperPage = ({}: StepperPageProps): null => null +/* eslint-enable */ + +type StepperFormValues = Record + +interface Mutators { + [key: string]: (...args: unknown[]) => void +} + +interface GnoStepperProps { + initialValues?: Partial + onSubmit: (formValues: V) => void + steps: string[] + buttonLabels?: string[] + children: React.ReactNode + disabledWhenValidating?: boolean + mutators?: Mutators + testId?: string +} + +function GnoStepper(props: GnoStepperProps): React.ReactElement { const [page, setPage] = useState(0) const [values, setValues] = useState({}) + const classes = useStyles() useEffect(() => { if (props.initialValues) { @@ -39,15 +72,15 @@ const GnoStepper = (props: any) => { return aux.props } - const updateInitialProps = (newInitialProps) => { + const updateInitialProps = useCallback((newInitialProps) => { setValues(newInitialProps) - } + }, []) const getActivePageFrom = (pages) => { const activePageProps = getPageProps(pages) - const { children, ...restProps } = activePageProps + const { component, ...restProps } = activePageProps - return children({ ...restProps, updateInitialProps }) + return component({ ...restProps, updateInitialProps }) } const validate = (valuesToValidate) => { @@ -92,12 +125,12 @@ const GnoStepper = (props: any) => { return next(formValues) } - const isLastPage = (pageNumber) => { + const isLastPage = (pageNumber: number): boolean => { const { steps } = props return pageNumber === steps.length - 1 } - const { buttonLabels, children, classes, disabledWhenValidating = false, mutators, steps, testId } = props + const { buttonLabels, children, disabledWhenValidating = false, mutators, steps, testId } = props const activePage = getActivePageFrom(children) const lastPage = isLastPage(page) @@ -157,7 +190,7 @@ const GnoStepper = (props: any) => { ) } -const styles = { +const useStyles = makeStyles({ root: { flex: '1 1 auto', backgroundColor: 'transparent', @@ -170,6 +203,6 @@ const styles = { cursor: 'pointer', }, }, -} +}) -export default withStyles(styles as any)(GnoStepper) +export default GnoStepper diff --git a/src/logic/addressBook/model/addressBook.ts b/src/logic/addressBook/model/addressBook.ts index f051fe18..1b35186c 100644 --- a/src/logic/addressBook/model/addressBook.ts +++ b/src/logic/addressBook/model/addressBook.ts @@ -1,4 +1,4 @@ -import { Record } from 'immutable' +import { Record, RecordOf } from 'immutable' export interface AddressBookEntryProps { address: string @@ -6,6 +6,8 @@ export interface AddressBookEntryProps { isOwner: boolean } +export type AddressBookEntryRecord = RecordOf + export const makeAddressBookEntry = Record({ address: '', name: '', diff --git a/src/logic/addressBook/store/reducer/addressBook.ts b/src/logic/addressBook/store/reducer/addressBook.ts index ac50d1cc..2b2d71b1 100644 --- a/src/logic/addressBook/store/reducer/addressBook.ts +++ b/src/logic/addressBook/store/reducer/addressBook.ts @@ -121,5 +121,7 @@ export default handleActions( }) }, }, - Map(), + Map({ + addressBook: Map({}), + }), ) diff --git a/src/logic/addressBook/store/reducer/types/addressBook.d.ts b/src/logic/addressBook/store/reducer/types/addressBook.d.ts new file mode 100644 index 00000000..5dba1ec0 --- /dev/null +++ b/src/logic/addressBook/store/reducer/types/addressBook.d.ts @@ -0,0 +1,24 @@ +import { AddressBookEntryRecord, AddressBookEntryProps } from 'src/logic/addressBook/model/addressBook' +import { Map, List } from 'immutable' + +export interface AddressBookReducerState { + addressBook: AddressBookMap +} + +interface AddressBookMapSerialized { + [key: string]: AddressBookEntryProps +} + +interface AddressBookReducerStateSerialized extends AddressBookReducerState { + addressBook: Record +} + +export interface AddressBookMap extends Map { + toJS(): AddressBookMapSerialized + get(key: string): List +} + +export interface AddressBookReducerMap extends Map { + toJS(): AddressBookReducerStateSerialized + get(key: K): AddressBookReducerState[K] +} diff --git a/src/logic/addressBook/store/selectors/index.ts b/src/logic/addressBook/store/selectors/index.ts index b6fe3b22..62d81409 100644 --- a/src/logic/addressBook/store/selectors/index.ts +++ b/src/logic/addressBook/store/selectors/index.ts @@ -1,37 +1,28 @@ -import { List, Map } from 'immutable' +import { AppReduxState } from 'src/store' +import { List } from 'immutable' import { createSelector } from 'reselect' import { ADDRESS_BOOK_REDUCER_ID } from 'src/logic/addressBook/store/reducer/addressBook' +import { AddressBookMap } from 'src/logic/addressBook/store/reducer/types/addressBook.d' import { safeParamAddressFromStateSelector } from 'src/routes/safe/store/selectors' -export const addressBookMapSelector = (state) => state[ADDRESS_BOOK_REDUCER_ID].get('addressBook') +export const addressBookMapSelector = (state: AppReduxState): AddressBookMap => + state[ADDRESS_BOOK_REDUCER_ID].get('addressBook') export const getAddressBook = createSelector( - addressBookMapSelector, - safeParamAddressFromStateSelector, - (addressBook, safeAddress) => { - let result = Map([]) - if (addressBook) { - result = addressBook.get(safeAddress, List([])) - } - return result - }, -) - -export const getAddressBookListSelector = createSelector( addressBookMapSelector, safeParamAddressFromStateSelector, (addressBook, safeAddress) => { let result = List([]) if (addressBook) { - result = List(addressBook.get(safeAddress)) + result = addressBook.get(safeAddress) } return result }, ) export const getNameFromAddressBook = createSelector( - getAddressBookListSelector, + getAddressBook, (_, address) => address, (addressBook, address) => { const adbkEntry = addressBook.find((addressBookItem) => addressBookItem.address === address) diff --git a/src/logic/contracts/safeContracts.ts b/src/logic/contracts/safeContracts.ts index 87621acd..d2992add 100644 --- a/src/logic/contracts/safeContracts.ts +++ b/src/logic/contracts/safeContracts.ts @@ -1,4 +1,6 @@ +import { AbiItem } from 'web3-utils' import contract from 'truffle-contract' +import Web3 from 'web3' import ProxyFactorySol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxyFactory.json' import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import SafeProxy from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafeProxy.json' @@ -8,7 +10,8 @@ import { getWeb3, getNetworkIdFrom } from 'src/logic/wallets/getWeb3' import { calculateGasOf, calculateGasPrice } from 'src/logic/wallets/ethTransactions' import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' import { isProxyCode } from 'src/logic/contracts/historicProxyCode' -import Web3 from 'web3' +import { GnosisSafeProxyFactory } from 'src/types/contracts/GnosisSafeProxyFactory.d'; +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' export const SENTINEL_ADDRESS = '0x0000000000000000000000000000000000000001' export const MULTI_SEND_ADDRESS = '0x8d29be29923b68abfdd21e541b9374737b49cdad' @@ -20,16 +23,16 @@ export const SAFE_MASTER_COPY_ADDRESS_V10 = '0xb6029EA3B2c51D09a50B53CA8012FeEB0 let proxyFactoryMaster let safeMaster -const createGnosisSafeContract = (web3: Web3): any => { +const createGnosisSafeContract = (web3: Web3) => { const gnosisSafe = contract(GnosisSafeSol) gnosisSafe.setProvider(web3.currentProvider) return gnosisSafe } -const createProxyFactoryContract = (web3, networkId) => { +const createProxyFactoryContract = (web3: Web3, networkId: number): GnosisSafeProxyFactory => { const contractAddress = ProxyFactorySol.networks[networkId].address - const proxyFactory = new web3.eth.Contract(ProxyFactorySol.abi as any, contractAddress) + const proxyFactory = new web3.eth.Contract(ProxyFactorySol.abi as AbiItem[], contractAddress) as unknown as GnosisSafeProxyFactory return proxyFactory } @@ -55,8 +58,8 @@ const createMasterCopies = async () => { const accounts = await web3.eth.getAccounts() const userAccount = accounts[0] - const ProxyFactory = getCreateProxyFactoryContract(web3, 4447) - proxyFactoryMaster = await ProxyFactory.new({ from: userAccount, gas: '5000000' }) + const ProxyFactory = getCreateProxyFactoryContract(web3, 4441) + proxyFactoryMaster = await ProxyFactory.deploy({ data: GnosisSafeSol.bytecode }).send({ from: userAccount, gas: 5000000 }) const GnosisSafe = getGnosisSafeContract(web3) safeMaster = await GnosisSafe.new({ from: userAccount, gas: '7000000' }) @@ -70,7 +73,7 @@ export const getSafeMasterContract = async () => { return safeMaster } -export const getSafeDeploymentTransaction = (safeAccounts, numConfirmations, userAccount) => { +export const getSafeDeploymentTransaction = (safeAccounts, numConfirmations) => { const gnosisSafeData = safeMaster.contract.methods .setup(safeAccounts, numConfirmations, ZERO_ADDRESS, '0x', DEFAULT_FALLBACK_HANDLER_ADDRESS, ZERO_ADDRESS, 0, ZERO_ADDRESS) .encodeABI() @@ -95,11 +98,12 @@ export const estimateGasForDeployingSafe = async ( return gas * parseInt(gasPrice, 10) } -export const getGnosisSafeInstanceAt = memoize(async (safeAddress: string): Promise => { +export const getGnosisSafeInstanceAt = async (safeAddress: string): Promise => { const web3 = getWeb3() - const GnosisSafe = await getGnosisSafeContract(web3) - return GnosisSafe.at(safeAddress) -}) + const gnosisSafe = await new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], safeAddress) as unknown as GnosisSafe + + return gnosisSafe +} const cleanByteCodeMetadata = (bytecode: string): string => { const metaData = 'a165' @@ -124,39 +128,3 @@ export const validateProxy = async (safeAddress: string): Promise => { return isProxyCode(codeWithoutMetadata) } - - -export const getEncodedMultiSendCallData = (txs, web3) => { - const multiSendAbi = [ - { - type: 'function', - name: 'multiSend', - constant: false, - payable: false, - stateMutability: 'nonpayable', - inputs: [{ type: 'bytes', name: 'transactions' }], - outputs: [], - }, - ] - const multiSend = new web3.eth.Contract(multiSendAbi, MULTI_SEND_ADDRESS) - const encodeMultiSendCallData = multiSend.methods - .multiSend( - `0x${txs - .map((tx) => [ - web3.eth.abi.encodeParameter('uint8', 0).slice(-2), - web3.eth.abi.encodeParameter('address', tx.to).slice(-40), - web3.eth.abi.encodeParameter('uint256', tx.value).slice(-64), - web3.eth.abi - .encodeParameter( - 'uint256', - web3.utils.hexToBytes(tx.data).length, - ) - .slice(-64), - tx.data.replace(/^0x/, ''), - ].join('')) - .join('')}`, - ) - .encodeABI() - - return encodeMultiSendCallData -} diff --git a/src/logic/safe/transactions/gasNew.ts b/src/logic/safe/transactions/gasNew.ts index 5f29c1e3..df2171ee 100644 --- a/src/logic/safe/transactions/gasNew.ts +++ b/src/logic/safe/transactions/gasNew.ts @@ -1,15 +1,18 @@ import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import { BigNumber } from 'bignumber.js' +import { AbiItem } from 'web3-utils' import { CALL } from '.' import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' import { generateSignaturesFromTxConfirmations } from 'src/logic/safe/safeTxSigner' +import { Transaction } from 'src/routes/safe/store/models/types/transaction' import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' import { EMPTY_DATA, calculateGasOf, calculateGasPrice } from 'src/logic/wallets/ethTransactions' import { getAccountFrom, getWeb3 } from 'src/logic/wallets/getWeb3' +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' -const estimateDataGasCosts = (data) => { +const estimateDataGasCosts = (data: string): number => { const reducer = (accumulator, currentValue) => { if (currentValue === EMPTY_DATA) { return accumulator + 0 @@ -25,33 +28,37 @@ const estimateDataGasCosts = (data) => { return data.match(/.{2}/g).reduce(reducer, 0) } -export const estimateTxGasCosts = async (safeAddress, to, data, tx?: any, preApprovingOwner?: any) => { +export const estimateTxGasCosts = async ( + safeAddress: string, + to: string, + data: string, + tx?: Transaction, + preApprovingOwner?: string, +): Promise => { try { const web3 = getWeb3() const from = await getAccountFrom(web3) - const safeInstance: any = new web3.eth.Contract(GnosisSafeSol.abi as any, safeAddress) + const safeInstance = (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[], safeAddress) as unknown) as GnosisSafe const nonce = await safeInstance.methods.nonce().call() const threshold = await safeInstance.methods.getThreshold().call() - - const isExecution = (tx && tx.confirmations.size === threshold) || !!preApprovingOwner || threshold === '1' + const isExecution = tx?.confirmations.size === Number(threshold) || !!preApprovingOwner || threshold === '1' let txData if (isExecution) { // https://docs.gnosis.io/safe/docs/docs5/#pre-validated-signatures - const signatures = - tx && tx.confirmations - ? generateSignaturesFromTxConfirmations(tx.confirmations, preApprovingOwner) - : `0x000000000000000000000000${from.replace( - '0x', - '', - )}000000000000000000000000000000000000000000000000000000000000000001` + const signatures = tx?.confirmations + ? generateSignaturesFromTxConfirmations(tx.confirmations, preApprovingOwner) + : `0x000000000000000000000000${from.replace( + '0x', + '', + )}000000000000000000000000000000000000000000000000000000000000000001` txData = await safeInstance.methods .execTransaction( to, - tx ? tx.value : 0, + tx?.value || 0, data, CALL, - tx ? tx.safeTxGas : 0, + tx?.safeTxGas || 0, 0, 0, ZERO_ADDRESS, @@ -61,7 +68,7 @@ export const estimateTxGasCosts = async (safeAddress, to, data, tx?: any, preApp .encodeABI() } else { const txHash = await safeInstance.methods - .getTransactionHash(to, tx ? tx.value : 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, nonce) + .getTransactionHash(to, tx?.value || 0, data, CALL, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, nonce) .call({ from, }) @@ -80,16 +87,23 @@ export const estimateTxGasCosts = async (safeAddress, to, data, tx?: any, preApp } } -export const estimateSafeTxGas = async (safe, safeAddress, data, to, valueInWei, operation) => { +export const estimateSafeTxGas = async ( + safe: GnosisSafe | undefined, + safeAddress: string, + data: string, + to: string, + valueInWei: string, + operation: number, +): Promise => { try { let safeInstance = safe if (!safeInstance) { safeInstance = await getGnosisSafeInstanceAt(safeAddress) } - const web3: any = await getWeb3() - const estimateData = safeInstance.contract.methods.requiredTxGas(to, valueInWei, data, operation).encodeABI() - const estimateResponse: any = await web3.eth.call({ + const web3 = await getWeb3() + const estimateData = safeInstance.methods.requiredTxGas(to, valueInWei, data, operation).encodeABI() + const estimateResponse = await web3.eth.call({ to: safeAddress, from: safeAddress, data: estimateData, @@ -98,17 +112,20 @@ export const estimateSafeTxGas = async (safe, safeAddress, data, to, valueInWei, // 21000 - additional gas costs (e.g. base tx costs, transfer costs) const dataGasEstimation = estimateDataGasCosts(estimateData) + 21000 - const additionalGasBatches = [10000, 20000, 40000, 80000, 160000, 320000, 640000, 1280000, 2560000, 5120000] const batch = new web3.BatchRequest() const estimationRequests = additionalGasBatches.map( (additionalGas) => new Promise((resolve) => { + // there are no type definitions for .request, so for now ts-ignore is there + // Issue link: https://github.com/ethereum/web3.js/issues/3144 + // eslint-disable-next-line + // @ts-ignore const request = web3.eth.call.request( { - to: safe.address, - from: safe.address, + to: safeAddress, + from: safeAddress, data: estimateData, gasPrice: 0, gasLimit: txGasEstimation + dataGasEstimation + additionalGas, diff --git a/src/logic/safe/transactions/send.ts b/src/logic/safe/transactions/send.ts index 7063e93c..deaa1b13 100644 --- a/src/logic/safe/transactions/send.ts +++ b/src/logic/safe/transactions/send.ts @@ -1,6 +1,4 @@ -import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' - -import { getWeb3 } from 'src/logic/wallets/getWeb3' +import { NonPayableTransactionObject } from 'src/types/contracts/types.d' import { TxArgs } from 'src/routes/safe/store/models/types/transaction' export const CALL = 0 @@ -21,36 +19,22 @@ export const getApprovalTransaction = async ({ sender, to, valueInWei, -}: TxArgs) => { - const txHash = await safeInstance.getTransactionHash( - to, - valueInWei, - data, - operation, - safeTxGas, - baseGas, - gasPrice, - gasToken, - refundReceiver, - nonce, - { +}: TxArgs): Promise> => { + const txHash = await safeInstance.methods + .getTransactionHash(to, valueInWei, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, nonce) + .call({ from: sender, - }, - ) + }) try { - const web3 = getWeb3() - - const contract: any = new web3.eth.Contract(GnosisSafeSol.abi as any, safeInstance.address) - - return contract.methods.approveHash(txHash) + return safeInstance.methods.approveHash(txHash) } catch (err) { console.error(`Error while approving transaction: ${err}`) throw err } } -export const getExecutionTransaction = async ({ +export const getExecutionTransaction = ({ baseGas, data, gasPrice, @@ -62,12 +46,9 @@ export const getExecutionTransaction = async ({ sigs, to, valueInWei, -}: TxArgs) => { +}: TxArgs): NonPayableTransactionObject => { try { - const web3 = getWeb3() - const contract: any = new web3.eth.Contract(GnosisSafeSol.abi as any, safeInstance.address) - - return contract.methods.execTransaction( + return safeInstance.methods.execTransaction( to, valueInWei, data, diff --git a/src/logic/safe/transactions/txHistory.ts b/src/logic/safe/transactions/txHistory.ts index d2b4042c..eeb14436 100644 --- a/src/logic/safe/transactions/txHistory.ts +++ b/src/logic/safe/transactions/txHistory.ts @@ -1,10 +1,11 @@ import axios from 'axios' +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' import { getTxServiceHost, getTxServiceUriFrom } from 'src/config' import { checksumAddress } from 'src/utils/checksumAddress' const calculateBodyFrom = async ( - safeInstance, + safeInstance: GnosisSafe, to, valueInWei, data, @@ -20,18 +21,9 @@ const calculateBodyFrom = async ( origin, signature, ) => { - const contractTransactionHash = await safeInstance.getTransactionHash( - to, - valueInWei, - data, - operation, - safeTxGas, - baseGas, - gasPrice, - gasToken, - refundReceiver, - nonce, - ) + const contractTransactionHash = await safeInstance.methods + .getTransactionHash(to, valueInWei, data, operation, safeTxGas, baseGas, gasPrice, gasToken, refundReceiver, nonce) + .call() return { to: checksumAddress(to), @@ -52,7 +44,7 @@ const calculateBodyFrom = async ( } } -export const buildTxServiceUrl = (safeAddress) => { +export const buildTxServiceUrl = (safeAddress: string): string => { const host = getTxServiceHost() const address = checksumAddress(safeAddress) const base = getTxServiceUriFrom(address) @@ -61,6 +53,11 @@ export const buildTxServiceUrl = (safeAddress) => { const SUCCESS_STATUS = 201 // CREATED status +interface SaveTxToHistoryArgs { + safeInstance: GnosisSafe + [key: string]: any +} + export const saveTxToHistory = async ({ baseGas, data, @@ -77,8 +74,8 @@ export const saveTxToHistory = async ({ to, txHash, valueInWei, -}: any) => { - const url = buildTxServiceUrl(safeInstance.address) +}: SaveTxToHistoryArgs): Promise => { + const url = buildTxServiceUrl(safeInstance.options.address) const body = await calculateBodyFrom( safeInstance, to, diff --git a/src/test/safe.dom.version.test.ts b/src/logic/safe/utils/safeVersion.test.ts similarity index 61% rename from src/test/safe.dom.version.test.ts rename to src/logic/safe/utils/safeVersion.test.ts index 1dc6cc8e..638f234f 100644 --- a/src/test/safe.dom.version.test.ts +++ b/src/logic/safe/utils/safeVersion.test.ts @@ -1,30 +1,36 @@ -// +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' +import { AbiItem } from 'web3-utils' import Web3 from 'web3' import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' import { checkIfSafeNeedsUpdate } from 'src/logic/safe/utils/safeVersion' - describe('Check safe version', () => { it('Calls checkIfSafeNeedUpdate, should return true if the safe version is bellow the target one', async () => { const web3 = new Web3(new Web3.providers.HttpProvider('')) - const safeInstance: any = new web3.eth.Contract(GnosisSafeSol.abi as any) - safeInstance.VERSION = () => '1.0.0' + const safeInstance = (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[]) as unknown) as GnosisSafe + // eslint-disable-next-line + // @ts-ignore + safeInstance.methods.VERSION = () => ({ call: async () => '1.0.0' }) const targetVersion = '1.1.1' const { needUpdate } = await checkIfSafeNeedsUpdate(safeInstance, targetVersion) expect(needUpdate).toEqual(true) }) it('Calls checkIfSafeNeedUpdate, should return false if the safe version is over the target one', async () => { const web3 = new Web3(new Web3.providers.HttpProvider('')) - const safeInstance: any = new web3.eth.Contract(GnosisSafeSol.abi as any) - safeInstance.VERSION = () => '2.0.0' + const safeInstance = (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[]) as unknown) as GnosisSafe + // eslint-disable-next-line + // @ts-ignore + safeInstance.methods.VERSION = () => ({ call: async () => '2.0.0' }) const targetVersion = '1.1.1' const { needUpdate } = await checkIfSafeNeedsUpdate(safeInstance, targetVersion) expect(needUpdate).toEqual(false) }) it('Calls checkIfSafeNeedUpdate, should return false if the safe version is equal the target one', async () => { const web3 = new Web3(new Web3.providers.HttpProvider('')) - const safeInstance: any = new web3.eth.Contract(GnosisSafeSol.abi as any) - safeInstance.VERSION = () => '1.1.1' + const safeInstance = (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[]) as unknown) as GnosisSafe + // eslint-disable-next-line + // @ts-ignore + safeInstance.methods.VERSION = () => ({ call: async () => '1.1.1' }) const targetVersion = '1.1.1' const { needUpdate } = await checkIfSafeNeedsUpdate(safeInstance, targetVersion) expect(needUpdate).toEqual(false) diff --git a/src/logic/safe/utils/safeVersion.ts b/src/logic/safe/utils/safeVersion.ts index 53d60dae..f0ab2736 100644 --- a/src/logic/safe/utils/safeVersion.ts +++ b/src/logic/safe/utils/safeVersion.ts @@ -1,6 +1,7 @@ import semverLessThan from 'semver/functions/lt' import semverSatisfies from 'semver/functions/satisfies' import semverValid from 'semver/functions/valid' +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' import { getSafeLastVersion } from 'src/config' import { getGnosisSafeInstanceAt, getSafeMasterContract } from 'src/logic/contracts/safeContracts' @@ -21,10 +22,10 @@ export const safeNeedsUpdate = (currentVersion: string, latestVersion: string): return latest ? semverLessThan(current, latest) : false } -export const getCurrentSafeVersion = (gnosisSafeInstance: { VERSION: () => Promise }): Promise => - gnosisSafeInstance.VERSION() +export const getCurrentSafeVersion = (gnosisSafeInstance: GnosisSafe): Promise => + gnosisSafeInstance.methods.VERSION().call() -export const enabledFeatures = (version: string): Array => +export const enabledFeatures = (version: string): string[] => FEATURES.reduce((acc, feature) => { if (semverSatisfies(version, feature.validVersion)) { acc.push(feature.name) @@ -39,7 +40,7 @@ interface SafeVersionInfo { } export const checkIfSafeNeedsUpdate = async ( - gnosisSafeInstance: { VERSION: () => Promise }, + gnosisSafeInstance: GnosisSafe, lastSafeVersion: string, ): Promise => { if (!gnosisSafeInstance || !lastSafeVersion) { diff --git a/src/test/getEncodedMultiSendCallData.ts b/src/logic/safe/utils/upgradeSafe.test.ts similarity index 55% rename from src/test/getEncodedMultiSendCallData.ts rename to src/logic/safe/utils/upgradeSafe.test.ts index c997b4c7..91d40db5 100644 --- a/src/test/getEncodedMultiSendCallData.ts +++ b/src/logic/safe/utils/upgradeSafe.test.ts @@ -1,19 +1,16 @@ -// +import { AbiItem } from 'web3-utils' import Web3 from 'web3' import GnosisSafeSol from '@gnosis.pm/safe-contracts/build/contracts/GnosisSafe.json' -import { - DEFAULT_FALLBACK_HANDLER_ADDRESS, - getEncodedMultiSendCallData, - SAFE_MASTER_COPY_ADDRESS, -} from 'src/logic/contracts/safeContracts' +import { DEFAULT_FALLBACK_HANDLER_ADDRESS, SAFE_MASTER_COPY_ADDRESS } from 'src/logic/contracts/safeContracts' import { ZERO_ADDRESS } from 'src/logic/wallets/ethAddresses' - +import { getEncodedMultiSendCallData } from 'src/logic/safe/utils/upgradeSafe' +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' describe('Upgrade a Safe', () => { it('Calls getEncodedMultiSendCallData with a list of MultiSendTransactionInstanceType and returns the multiSend data encoded', async () => { const safeAddress = ZERO_ADDRESS const web3 = new Web3(new Web3.providers.HttpProvider('')) - const safeInstance = new web3.eth.Contract(GnosisSafeSol.abi as any) + const safeInstance = (new web3.eth.Contract(GnosisSafeSol.abi as AbiItem[]) as unknown) as GnosisSafe const fallbackHandlerTxData = safeInstance.methods.setFallbackHandler(DEFAULT_FALLBACK_HANDLER_ADDRESS).encodeABI() const updateSafeTxData = safeInstance.methods.changeMasterCopy(SAFE_MASTER_COPY_ADDRESS).encodeABI() const txs = [ @@ -30,7 +27,8 @@ describe('Upgrade a Safe', () => { data: fallbackHandlerTxData, }, ] - const expectedEncodedData = '0x8d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247de7edef00000000000000000000000034cfac646f301356faa8b21e94227e3583fe3f5f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f08a0323000000000000000000000000d5d82b6addc9027b22dca772aa68d5d74cdbdf440000000000000000000000000000' + const expectedEncodedData = + '0x8d80ff0a000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000f2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000247de7edef00000000000000000000000034cfac646f301356faa8b21e94227e3583fe3f5f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024f08a0323000000000000000000000000d5d82b6addc9027b22dca772aa68d5d74cdbdf440000000000000000000000000000' const multiSendTxData = getEncodedMultiSendCallData(txs, web3) expect(multiSendTxData).toEqual(expectedEncodedData) }) diff --git a/src/logic/safe/utils/upgradeSafe.ts b/src/logic/safe/utils/upgradeSafe.ts index 90b01ee7..3cd86610 100644 --- a/src/logic/safe/utils/upgradeSafe.ts +++ b/src/logic/safe/utils/upgradeSafe.ts @@ -1,33 +1,58 @@ +import Web3 from 'web3' +import { AbiItem } from 'web3-utils' import { DEFAULT_FALLBACK_HANDLER_ADDRESS, MULTI_SEND_ADDRESS, SAFE_MASTER_COPY_ADDRESS, - getEncodedMultiSendCallData, getGnosisSafeInstanceAt, } from 'src/logic/contracts/safeContracts' import { DELEGATE_CALL } from 'src/logic/safe/transactions' import { getWeb3 } from 'src/logic/wallets/getWeb3' +import { MultiSend } from 'src/types/contracts/MultiSend.d' -export const upgradeSafeToLatestVersion = async (safeAddress, createTransaction) => { - const sendTransactions = async (txs) => { - const web3 = getWeb3() - const encodeMultiSendCallData = getEncodedMultiSendCallData(txs, web3) - createTransaction({ - safeAddress, - to: MULTI_SEND_ADDRESS, - valueInWei: '0', - txData: encodeMultiSendCallData, - notifiedTransaction: 'STANDARD_TX', - enqueueSnackbar: () => {}, - closeSnackbar: () => {}, - operation: DELEGATE_CALL, - }) - } - const safeInstance = await getGnosisSafeInstanceAt(safeAddress) - const fallbackHandlerTxData = safeInstance.contract.methods - .setFallbackHandler(DEFAULT_FALLBACK_HANDLER_ADDRESS) +interface MultiSendTx { + operation: number + to: string + value: number + data: string +} + +export const getEncodedMultiSendCallData = (txs: MultiSendTx[], web3: Web3): string => { + const multiSendAbi: AbiItem[] = [ + { + type: 'function', + name: 'multiSend', + constant: false, + payable: false, + stateMutability: 'nonpayable', + inputs: [{ type: 'bytes', name: 'transactions' }], + outputs: [], + }, + ] + const multiSend = (new web3.eth.Contract(multiSendAbi, MULTI_SEND_ADDRESS) as unknown) as MultiSend + const encodedMultiSendCallData = multiSend.methods + .multiSend( + `0x${txs + .map((tx) => + [ + web3.eth.abi.encodeParameter('uint8', 0).slice(-2), + web3.eth.abi.encodeParameter('address', tx.to).slice(-40), + web3.eth.abi.encodeParameter('uint256', tx.value).slice(-64), + web3.eth.abi.encodeParameter('uint256', web3.utils.hexToBytes(tx.data).length).slice(-64), + tx.data.replace(/^0x/, ''), + ].join(''), + ) + .join('')}`, + ) .encodeABI() - const updateSafeTxData = safeInstance.contract.methods.changeMasterCopy(SAFE_MASTER_COPY_ADDRESS).encodeABI() + + return encodedMultiSendCallData +} + +export const upgradeSafeToLatestVersion = async (safeAddress: string, createTransaction): Promise => { + const safeInstance = await getGnosisSafeInstanceAt(safeAddress) + const fallbackHandlerTxData = safeInstance.methods.setFallbackHandler(DEFAULT_FALLBACK_HANDLER_ADDRESS).encodeABI() + const updateSafeTxData = safeInstance.methods.changeMasterCopy(SAFE_MASTER_COPY_ADDRESS).encodeABI() const txs = [ { operation: 0, @@ -42,5 +67,19 @@ export const upgradeSafeToLatestVersion = async (safeAddress, createTransaction) data: fallbackHandlerTxData, }, ] - return sendTransactions(txs) + + const web3 = getWeb3() + const encodeMultiSendCallData = getEncodedMultiSendCallData(txs, web3) + createTransaction({ + safeAddress, + to: MULTI_SEND_ADDRESS, + valueInWei: 0, + txData: encodeMultiSendCallData, + notifiedTransaction: 'STANDARD_TX', + enqueueSnackbar: () => {}, + closeSnackbar: () => {}, + operation: DELEGATE_CALL, + }) + + return } diff --git a/src/routes/load/components/DetailsForm/index.tsx b/src/routes/load/components/DetailsForm/index.tsx index 7b19d047..e3325549 100644 --- a/src/routes/load/components/DetailsForm/index.tsx +++ b/src/routes/load/components/DetailsForm/index.tsx @@ -1,10 +1,12 @@ import InputAdornment from '@material-ui/core/InputAdornment' -import { withStyles } from '@material-ui/core/styles' +import { makeStyles } from '@material-ui/core/styles' import CheckCircle from '@material-ui/icons/CheckCircle' import * as React from 'react' +import { FormApi } from 'final-form' import { ScanQRWrapper } from 'src/components/ScanQRModal/ScanQRWrapper' import OpenPaper from 'src/components/Stepper/OpenPaper' +import { StepperPageFormProps } from 'src/components/Stepper' import AddressInput from 'src/components/forms/AddressInput' import Field from 'src/components/forms/Field' import TextField from 'src/components/forms/TextField' @@ -17,7 +19,7 @@ import { getWeb3 } from 'src/logic/wallets/getWeb3' import { FIELD_LOAD_ADDRESS, FIELD_LOAD_NAME } from 'src/routes/load/components/fields' import { secondary } from 'src/theme/variables' -const styles = () => ({ +const useStyles = makeStyles({ root: { display: 'flex', maxWidth: '460px', @@ -40,7 +42,7 @@ export const SAFE_MASTERCOPY_ERROR = 'Mastercopy used by this Safe is not the sa // In case of an error here, it will be swallowed by final-form // So if you're experiencing any strang behaviours like freeze or hanging // Don't mind to check if everything is OK inside this function :) -export const safeFieldsValidation = async (values) => { +export const safeFieldsValidation = async (values): Promise> => { const errors = {} const web3 = getWeb3() const safeAddress = values[FIELD_LOAD_ADDRESS] @@ -75,11 +77,19 @@ export const safeFieldsValidation = async (values) => { return errors } -const Details = ({ classes, errors, form }) => { - const handleScan = (value, closeQrModal) => { +interface DetailsFormProps { + errors: Record + form: FormApi +} + +const DetailsForm = ({ errors, form }: DetailsFormProps): React.ReactElement => { + const classes = useStyles() + + const handleScan = (value: string, closeQrModal: () => void): void => { form.mutators.setValue(FIELD_LOAD_ADDRESS, value) closeQrModal() } + return ( <> @@ -146,9 +156,7 @@ const Details = ({ classes, errors, form }) => { ) } -const DetailsForm = withStyles(styles as any)(Details) - -const DetailsPage = () => (controls, { errors, form }) => ( +const DetailsPage = () => (controls: React.ReactNode, { errors, form }: StepperPageFormProps): React.ReactElement => ( <> diff --git a/src/routes/load/components/Layout.tsx b/src/routes/load/components/Layout.tsx index e3029303..a1801110 100644 --- a/src/routes/load/components/Layout.tsx +++ b/src/routes/load/components/Layout.tsx @@ -14,7 +14,8 @@ import { history } from 'src/store' import { secondary, sm } from 'src/theme/variables' import { LoadFormValues } from '../container/Load' -const getSteps = () => ['Name and address', 'Owners', 'Review'] +const steps = ['Name and address', 'Owners', 'Review'] +const buttonLabels = ['Next', 'Review', 'Load'] const iconStyle = { color: secondary, @@ -32,49 +33,39 @@ const formMutators = { }, } -const buttonLabels = ['Next', 'Review', 'Load'] - -interface ILayout { +interface LayoutProps { network: string provider?: string userAddress: string onLoadSafeSubmit: (values: LoadFormValues) => void } -const Layout: React.FC = ({ network, onLoadSafeSubmit, provider, userAddress }) => { - const steps = getSteps() - const initialValues = {} - - return ( - <> - {provider ? ( - - - - - - Load existing Safe - - - {DetailsForm} - {OwnerList} - - {ReviewInformation} - - - - ) : ( -
No account detected
- )} - - ) -} +const Layout = ({ network, onLoadSafeSubmit, provider, userAddress }: LayoutProps): React.ReactElement => ( + <> + {provider ? ( + + + + + + Load existing Safe + + + buttonLabels={buttonLabels} + mutators={formMutators} + onSubmit={onLoadSafeSubmit} + steps={steps} + testId="load-safe-form" + > + + + + + + ) : ( +
No account detected
+ )} + +) export default Layout diff --git a/src/routes/load/components/OwnerList/index.tsx b/src/routes/load/components/OwnerList/index.tsx index 536550f8..57f38276 100644 --- a/src/routes/load/components/OwnerList/index.tsx +++ b/src/routes/load/components/OwnerList/index.tsx @@ -88,11 +88,11 @@ const OwnerListComponent = (props) => { const fetchSafe = async () => { const safeAddress = values[FIELD_LOAD_ADDRESS] const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) - const safeOwners = await gnosisSafe.getOwners() - const threshold = await gnosisSafe.getThreshold() + const safeOwners = await gnosisSafe.methods.getOwners().call() + const threshold = await gnosisSafe.methods.getThreshold().call() - if (isCurrent && owners) { - const sortedOwners = safeOwners.sort() + if (isCurrent) { + const sortedOwners = safeOwners.slice().sort() const initialValues = calculateSafeValues(sortedOwners, threshold, values) updateInitialProps(initialValues) setOwners(sortedOwners) @@ -104,7 +104,7 @@ const OwnerListComponent = (props) => { return () => { isCurrent = false } - }, [owners, updateInitialProps, values]) + }, [updateInitialProps, values]) return ( <> diff --git a/src/routes/load/components/ReviewInformation/index.tsx b/src/routes/load/components/ReviewInformation/index.tsx index 38707609..b52f3b65 100644 --- a/src/routes/load/components/ReviewInformation/index.tsx +++ b/src/routes/load/components/ReviewInformation/index.tsx @@ -1,7 +1,6 @@ import TableContainer from '@material-ui/core/TableContainer' -import { withStyles } from '@material-ui/core/styles' import classNames from 'classnames' -import * as React from 'react' +import React from 'react' import CopyBtn from 'src/components/CopyBtn' import EtherscanBtn from 'src/components/EtherscanBtn' @@ -16,73 +15,9 @@ import { shortVersionOf } from 'src/logic/wallets/ethAddresses' import { FIELD_LOAD_ADDRESS, FIELD_LOAD_NAME, THRESHOLD } from 'src/routes/load/components/fields' import { getNumOwnersFrom, getOwnerAddressBy, getOwnerNameBy } from 'src/routes/open/components/fields' import { getAccountsFrom } from 'src/routes/open/utils/safeDataExtractor' -import { border, lg, screenSm, sm, xs } from 'src/theme/variables' +import { useStyles } from './styles' -const styles = () => ({ - root: { - flexDirection: 'column', - minHeight: '300px', - [`@media (min-width: ${screenSm}px)`]: { - flexDirection: 'row', - }, - }, - detailsColumn: { - minWidth: '100%', - [`@media (min-width: ${screenSm}px)`]: { - minWidth: '0', - }, - }, - ownersColumn: { - minWidth: '100%', - [`@media (min-width: ${screenSm}px)`]: { - minWidth: '0', - }, - }, - details: { - padding: lg, - borderRight: `solid 1px ${border}`, - height: '100%', - }, - owners: { - padding: lg, - }, - name: { - textOverflow: 'ellipsis', - overflow: 'hidden', - }, - userName: { - whiteSpace: 'nowrap', - }, - owner: { - alignItems: 'center', - minWidth: 'fit-content', - padding: sm, - paddingLeft: lg, - }, - user: { - justifyContent: 'left', - '& > p': { - marginRight: sm, - }, - }, - open: { - paddingLeft: sm, - width: 'auto', - '&:hover': { - cursor: 'pointer', - }, - }, - container: { - marginTop: xs, - alignItems: 'center', - }, - address: { - paddingLeft: '6px', - marginRight: sm, - }, -}) - -const checkUserAddressOwner = (values, userAddress) => { +const checkIfUserAddressIsAnOwner = (values: Record, userAddress: string): boolean => { let isOwner = false for (let i = 0; i < getNumOwnersFrom(values); i += 1) { @@ -95,116 +30,119 @@ const checkUserAddressOwner = (values, userAddress) => { return isOwner } -class ReviewComponent extends React.PureComponent { - render() { - const { classes, userAddress, values } = this.props - - const isOwner = checkUserAddressOwner(values, userAddress) - const owners = getAccountsFrom(values) - const safeAddress = values[FIELD_LOAD_ADDRESS] - - return ( - <> - - - - - - Review details - - - - - Name of the Safe - - - {values[FIELD_LOAD_NAME]} - - - - - Safe address - - - - - {shortVersionOf(safeAddress, 4)} - - - - - - - - Connected wallet client is owner? - - - {isOwner ? 'Yes' : 'No (read-only)'} - - - - - Any transaction requires the confirmation of: - - - {`${values[THRESHOLD]} out of ${getNumOwnersFrom(values)} owners`} - - - - - - - - - {`${getNumOwnersFrom(values)} Safe owners`} - - - - {owners.map((address, index) => ( - <> - - - - - - - - {values[getOwnerNameBy(index)]} - - - - {address} - - - - - - - - {index !== owners.length - 1 && } - - ))} - - - - - ) - } +interface Props { + userAddress: string + values: Record } -const ReviewPage = withStyles(styles as any)(ReviewComponent) +const ReviewComponent = ({ userAddress, values }: Props): React.ReactElement => { + const classes = useStyles() + const isOwner = checkIfUserAddressIsAnOwner(values, userAddress) + const owners = getAccountsFrom(values) + const safeAddress = values[FIELD_LOAD_ADDRESS] -const Review = ({ network, userAddress }) => (controls, { values }) => ( + return ( + <> + + + + + + Review details + + + + + Name of the Safe + + + {values[FIELD_LOAD_NAME]} + + + + + Safe address + + + + + {shortVersionOf(safeAddress, 4)} + + + + + + + + Connected wallet client is owner? + + + {isOwner ? 'Yes' : 'No (read-only)'} + + + + + Any transaction requires the confirmation of: + + + {`${values[THRESHOLD]} out of ${getNumOwnersFrom(values)} owners`} + + + + + + + + + {`${getNumOwnersFrom(values)} Safe owners`} + + + + {owners.map((address, index) => ( + <> + + + + + + + + {values[getOwnerNameBy(index)]} + + + + {address} + + + + + + + + {index !== owners.length - 1 && } + + ))} + + + + + ) +} + +const Review = ({ userAddress }: { userAddress: string }) => ( + controls: React.ReactNode, + { values }: { values: Record }, +): React.ReactElement => ( <> - + ) diff --git a/src/routes/load/components/ReviewInformation/styles.ts b/src/routes/load/components/ReviewInformation/styles.ts new file mode 100644 index 00000000..53f9bcd9 --- /dev/null +++ b/src/routes/load/components/ReviewInformation/styles.ts @@ -0,0 +1,66 @@ +import { makeStyles } from '@material-ui/core/styles' +import { border, lg, screenSm, sm, xs } from 'src/theme/variables' + +export const useStyles = makeStyles({ + root: { + flexDirection: 'column', + minHeight: '300px', + [`@media (min-width: ${screenSm}px)`]: { + flexDirection: 'row', + }, + }, + detailsColumn: { + minWidth: '100%', + [`@media (min-width: ${screenSm}px)`]: { + minWidth: '0', + }, + }, + ownersColumn: { + minWidth: '100%', + [`@media (min-width: ${screenSm}px)`]: { + minWidth: '0', + }, + }, + details: { + padding: lg, + borderRight: `solid 1px ${border}`, + height: '100%', + }, + owners: { + padding: lg, + }, + name: { + textOverflow: 'ellipsis', + overflow: 'hidden', + }, + userName: { + whiteSpace: 'nowrap', + }, + owner: { + alignItems: 'center', + minWidth: 'fit-content', + padding: sm, + paddingLeft: lg, + }, + user: { + justifyContent: 'left', + '& > p': { + marginRight: sm, + }, + }, + open: { + paddingLeft: sm, + width: 'auto', + '&:hover': { + cursor: 'pointer', + }, + }, + container: { + marginTop: xs, + alignItems: 'center', + }, + address: { + paddingLeft: '6px', + marginRight: sm, + }, +}) diff --git a/src/routes/load/container/Load.tsx b/src/routes/load/container/Load.tsx index 171041c4..30f5f621 100644 --- a/src/routes/load/container/Load.tsx +++ b/src/routes/load/container/Load.tsx @@ -37,7 +37,7 @@ export const loadSafe = async ( await addSafe(safeProps) } -interface ILoad { +interface LoadProps { addSafe: Dispatch network: string provider?: string @@ -50,7 +50,7 @@ export interface LoadFormValues { threshold: string } -const Load: React.FC = ({ addSafe, network, provider, userAddress }) => { +const Load = ({ addSafe, network, provider, userAddress }: LoadProps): React.ReactElement => { const onLoadSafeSubmit = async (values: LoadFormValues) => { let safeAddress = values[FIELD_LOAD_ADDRESS] // TODO: review this check. It doesn't seems to be necessary at this point @@ -65,7 +65,7 @@ const Load: React.FC = ({ addSafe, network, provider, userAddress }) => { const ownerNames = getNamesFrom(values) const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) - const ownerAddresses = await gnosisSafe.getOwners() + const ownerAddresses = await gnosisSafe.methods.getOwners().call() const owners = getOwnersFrom(ownerNames, ownerAddresses.sort()) await loadSafe(safeName, safeAddress, owners, addSafe) diff --git a/src/routes/open/components/Layout.tsx b/src/routes/open/components/Layout.tsx index 20719b9f..7a43d735 100644 --- a/src/routes/open/components/Layout.tsx +++ b/src/routes/open/components/Layout.tsx @@ -98,11 +98,9 @@ const Layout = (props) => { steps={steps} testId="create-safe-form" > - {SafeNameField} - {SafeOwnersFields} - - {Review} - + + +
) : ( diff --git a/src/routes/open/container/Open.tsx b/src/routes/open/container/Open.tsx index 85b545ef..df3f533f 100644 --- a/src/routes/open/container/Open.tsx +++ b/src/routes/open/container/Open.tsx @@ -59,9 +59,9 @@ export const createSafe = (values, userAccount) => { const ownersNames = getNamesFrom(values) const ownerAddresses = getAccountsFrom(values) - const deploymentTxMethod = getSafeDeploymentTransaction(ownerAddresses, confirmations, userAccount) + const deploymentTx = getSafeDeploymentTransaction(ownerAddresses, confirmations) - const promiEvent = deploymentTxMethod.send({ from: userAccount, value: 0 }) + const promiEvent = deploymentTx.send({ from: userAccount, value: 0 }) promiEvent .once('transactionHash', (txHash) => { diff --git a/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx b/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx index 8c264daf..974be3e4 100644 --- a/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx +++ b/src/routes/safe/components/AddressBook/CreateEditEntryModal/index.tsx @@ -19,7 +19,7 @@ import Col from 'src/components/layout/Col' import Hairline from 'src/components/layout/Hairline' import Paragraph from 'src/components/layout/Paragraph' import Row from 'src/components/layout/Row' -import { getAddressBookListSelector } from 'src/logic/addressBook/store/selectors' +import { getAddressBook } from 'src/logic/addressBook/store/selectors' import { getAddressesListFromAdbk } from 'src/logic/addressBook/utils' export const CREATE_ENTRY_INPUT_NAME_ID = 'create-entry-input-name' @@ -42,7 +42,7 @@ const CreateEditEntryModalComponent = ({ } } - const addressBook = useSelector(getAddressBookListSelector) + const addressBook = useSelector(getAddressBook) const addressBookAddressesList = getAddressesListFromAdbk(addressBook) const entryDoesntExist = uniqueAddress(addressBookAddressesList) diff --git a/src/routes/safe/components/AddressBook/index.tsx b/src/routes/safe/components/AddressBook/index.tsx index 80ca792b..167e2e0e 100644 --- a/src/routes/safe/components/AddressBook/index.tsx +++ b/src/routes/safe/components/AddressBook/index.tsx @@ -22,7 +22,7 @@ import { makeAddressBookEntry } from 'src/logic/addressBook/model/addressBook' import { addAddressBookEntry } from 'src/logic/addressBook/store/actions/addAddressBookEntry' import { removeAddressBookEntry } from 'src/logic/addressBook/store/actions/removeAddressBookEntry' import { updateAddressBookEntry } from 'src/logic/addressBook/store/actions/updateAddressBookEntry' -import { getAddressBookListSelector } from 'src/logic/addressBook/store/selectors' +import { getAddressBook } from 'src/logic/addressBook/store/selectors' import { isUserAnOwnerOfAnySafe } from 'src/logic/wallets/ethAddresses' import CreateEditEntryModal from 'src/routes/safe/components/AddressBook/CreateEditEntryModal' import DeleteEntryModal from 'src/routes/safe/components/AddressBook/DeleteEntryModal' @@ -48,7 +48,7 @@ const AddressBookTable = ({ classes }) => { const dispatch = useDispatch() const safesList = useSelector(safesListSelector) const entryAddressToEditOrCreateNew = useSelector(addressBookQueryParamsSelector) - const addressBook = useSelector(getAddressBookListSelector) + const addressBook = useSelector(getAddressBook) const [selectedEntry, setSelectedEntry] = useState(null) const [editCreateEntryModalOpen, setEditCreateEntryModalOpen] = useState(false) const [deleteEntryModalOpen, setDeleteEntryModalOpen] = useState(false) diff --git a/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx index d0a5aa12..6079daef 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/AddressBookInput/index.tsx @@ -11,9 +11,10 @@ import { styles } from './style' import Identicon from 'src/components/Identicon' import { mustBeEthereumAddress, mustBeEthereumContractAddress } from 'src/components/forms/validator' -import { getAddressBookListSelector } from 'src/logic/addressBook/store/selectors' +import { getAddressBook } from 'src/logic/addressBook/store/selectors' import { getAddressFromENS } from 'src/logic/wallets/getWeb3' import { isValidEnsName } from 'src/logic/wallets/ethAddresses' +import { AddressBookEntryRecord } from 'src/logic/addressBook/model/addressBook' export interface AddressBookProps { fieldMutator: (address: string) => void @@ -45,11 +46,11 @@ const textFieldInputStyle = makeStyles(() => ({ })) const filterAddressBookWithContractAddresses = async ( - addressBook: List<{ address: string }>, -): Promise> => { + addressBook: List, +): Promise> => { const abFlags = await Promise.all( addressBook.map( - async ({ address }: { address: string }): Promise => { + async ({ address }: AddressBookEntryRecord): Promise => { return (await mustBeEthereumContractAddress(address)) === undefined }, ), @@ -58,6 +59,11 @@ const filterAddressBookWithContractAddresses = async ( return addressBook.filter((_, index) => abFlags[index]) } +interface FilteredAddressBookEntry { + name: string + address: string +} + const AddressBookInput = ({ fieldMutator, isCustomTx, @@ -67,12 +73,12 @@ const AddressBookInput = ({ setSelectedEntry, }: AddressBookProps) => { const classes = useStyles() - const addressBook = useSelector(getAddressBookListSelector) + const addressBook = useSelector(getAddressBook) const [isValidForm, setIsValidForm] = useState(true) const [validationText, setValidationText] = useState('') const [inputTouched, setInputTouched] = useState(false) const [blurred, setBlurred] = useState(pristine) - const [adbkList, setADBKList] = useState>(List([])) + const [adbkList, setADBKList] = useState>(List([])) const [inputAddValue, setInputAddValue] = useState(recipientAddress) @@ -146,7 +152,7 @@ const AddressBookInput = ({ <> optionsArray.filter((item) => { const inputLowerCase = inputValue.toLowerCase() @@ -158,7 +164,7 @@ const AddressBookInput = ({ freeSolo getOptionLabel={(adbkEntry) => adbkEntry.address || ''} id="free-solo-demo" - onChange={(event, value) => { + onChange={(_, value: FilteredAddressBookEntry) => { let address = '' let name = '' if (value) { @@ -220,7 +226,7 @@ const AddressBookInput = ({ }} role="listbox" style={{ display: 'flex', flexGrow: 1 }} - value={{ address: inputAddValue }} + value={{ address: inputAddValue, name: '' }} /> ) diff --git a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx index 03afed9a..56155327 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/ContractInteraction/ReviewCustomTx/index.tsx @@ -38,7 +38,7 @@ type Props = { const useStyles = makeStyles(styles) -const ReviewCustomTx = ({ onClose, onPrev, tx }: Props) => { +const ReviewCustomTx = ({ onClose, onPrev, tx }: Props): React.ReactElement => { const { enqueueSnackbar, closeSnackbar } = useSnackbar() const classes = useStyles() const dispatch = useDispatch() diff --git a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx index 6a1d376d..8b78fc79 100644 --- a/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx +++ b/src/routes/safe/components/Balances/SendModal/screens/SendFunds/index.tsx @@ -87,18 +87,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT - { - const selectedTokenRecord = tokens.find((token) => token.address === values?.token) - - return { - amount: maxValue(selectedTokenRecord?.balance)(values.amount), - } - }} - > + {(...args) => { const formState = args[2] const mutators = args[3] diff --git a/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx b/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx index a518b25d..638228ee 100644 --- a/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx +++ b/src/routes/safe/components/Settings/Advanced/RemoveModuleModal.tsx @@ -56,7 +56,7 @@ const RemoveModuleModal = ({ onClose, selectedModule }: RemoveModuleModal): Reac try { const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const [module, prevModule] = selectedModule - const txData = safeInstance.contract.methods.disableModule(prevModule, module).encodeABI() + const txData = safeInstance.methods.disableModule(prevModule, module).encodeABI() dispatch( createTransaction({ diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx index 41d03190..5e3d85dc 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/index.tsx @@ -27,7 +27,7 @@ const styles = () => ({ export const sendAddOwner = async (values, safeAddress, ownersOld, enqueueSnackbar, closeSnackbar, dispatch) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) - const txData = gnosisSafe.contract.methods.addOwnerWithThreshold(values.ownerAddress, values.threshold).encodeABI() + const txData = gnosisSafe.methods.addOwnerWithThreshold(values.ownerAddress, values.threshold).encodeABI() const txHash = await dispatch( createTransaction({ diff --git a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.tsx b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.tsx index a958cefa..750c7414 100644 --- a/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/AddOwnerModal/screens/Review/index.tsx @@ -40,9 +40,7 @@ const ReviewAddOwner = ({ classes, onClickBack, onClose, onSubmit, values }) => const { fromWei, toBN } = web3.utils const safeInstance = await getGnosisSafeInstanceAt(safeAddress) - const txData = safeInstance.contract.methods - .addOwnerWithThreshold(values.ownerAddress, values.threshold) - .encodeABI() + const txData = safeInstance.methods.addOwnerWithThreshold(values.ownerAddress, values.threshold).encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx index 5954fd7f..537cb526 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/index.tsx @@ -39,14 +39,12 @@ export const sendRemoveOwner = async ( dispatch, ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) - const safeOwners = await gnosisSafe.getOwners() + const safeOwners = await gnosisSafe.methods.getOwners().call() const index = safeOwners.findIndex( (ownerAddress) => ownerAddress.toLowerCase() === ownerAddressToRemove.toLowerCase(), ) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] - const txData = gnosisSafe.contract.methods - .removeOwner(prevAddress, ownerAddressToRemove, values.threshold) - .encodeABI() + const txData = gnosisSafe.methods.removeOwner(prevAddress, ownerAddressToRemove, values.threshold).encodeABI() const txHash = await dispatch( createTransaction({ diff --git a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.tsx b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.tsx index ebe4a2f7..ebfdf120 100644 --- a/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/RemoveOwnerModal/screens/Review/index.tsx @@ -41,10 +41,10 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre const web3 = getWeb3() const { fromWei, toBN } = web3.utils const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) - const safeOwners = await gnosisSafe.getOwners() + const safeOwners = await gnosisSafe.methods.getOwners().call() const index = safeOwners.findIndex((owner) => owner.toLowerCase() === ownerAddress.toLowerCase()) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] - const txData = gnosisSafe.contract.methods.removeOwner(prevAddress, ownerAddress, values.threshold).encodeABI() + const txData = gnosisSafe.methods.removeOwner(prevAddress, ownerAddress, values.threshold).encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx index 4f7fdfb5..46c631e8 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/index.tsx @@ -33,14 +33,12 @@ export const sendReplaceOwner = async ( dispatch, ) => { const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) - const safeOwners = await gnosisSafe.getOwners() + const safeOwners = await gnosisSafe.methods.getOwners().call() const index = safeOwners.findIndex( (ownerAddress) => ownerAddress.toLowerCase() === ownerAddressToRemove.toLowerCase(), ) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] - const txData = gnosisSafe.contract.methods - .swapOwner(prevAddress, ownerAddressToRemove, values.ownerAddress) - .encodeABI() + const txData = gnosisSafe.methods.swapOwner(prevAddress, ownerAddressToRemove, values.ownerAddress).encodeABI() const txHash = await dispatch( createTransaction({ diff --git a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.tsx b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.tsx index a666b249..809f29e1 100644 --- a/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.tsx +++ b/src/routes/safe/components/Settings/ManageOwners/ReplaceOwnerModal/screens/Review/index.tsx @@ -42,10 +42,10 @@ const ReviewRemoveOwner = ({ classes, onClickBack, onClose, onSubmit, ownerAddre const web3 = getWeb3() const { fromWei, toBN } = web3.utils const gnosisSafe = await getGnosisSafeInstanceAt(safeAddress) - const safeOwners = await gnosisSafe.getOwners() + const safeOwners = await gnosisSafe.methods.getOwners().call() const index = safeOwners.findIndex((owner) => owner.toLowerCase() === ownerAddress.toLowerCase()) const prevAddress = index === 0 ? SENTINEL_ADDRESS : safeOwners[index - 1] - const txData = gnosisSafe.contract.methods.swapOwner(prevAddress, ownerAddress, values.ownerAddress).encodeABI() + const txData = gnosisSafe.methods.swapOwner(prevAddress, ownerAddress, values.ownerAddress).encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) diff --git a/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.tsx b/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.tsx index 9c5179bd..e821d4d3 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.tsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/ChangeThreshold/index.tsx @@ -32,7 +32,7 @@ const ChangeThreshold = ({ classes, onChangeThreshold, onClose, owners, safeAddr const web3 = getWeb3() const { fromWei, toBN } = web3.utils const safeInstance = await getGnosisSafeInstanceAt(safeAddress) - const txData = safeInstance.contract.methods.changeThreshold('1').encodeABI() + const txData = safeInstance.methods.changeThreshold('1').encodeABI() const estimatedGasCosts = await estimateTxGasCosts(safeAddress, safeAddress, txData) const gasCostsAsEth = fromWei(toBN(estimatedGasCosts), 'ether') const formattedGasCosts = formatAmount(gasCostsAsEth) diff --git a/src/routes/safe/components/Settings/ThresholdSettings/index.tsx b/src/routes/safe/components/Settings/ThresholdSettings/index.tsx index d7fda083..42e19240 100644 --- a/src/routes/safe/components/Settings/ThresholdSettings/index.tsx +++ b/src/routes/safe/components/Settings/ThresholdSettings/index.tsx @@ -37,7 +37,7 @@ const ThresholdSettings = ({ classes, closeSnackbar, enqueueSnackbar }) => { const onChangeThreshold = async (newThreshold) => { const safeInstance = await getGnosisSafeInstanceAt(safeAddress) - const txData = safeInstance.contract.methods.changeThreshold(newThreshold).encodeABI() + const txData = safeInstance.methods.changeThreshold(newThreshold).encodeABI() dispatch( createTransaction({ diff --git a/src/routes/safe/store/actions/createTransaction.ts b/src/routes/safe/store/actions/createTransaction.ts index d06bbe51..c3ab58cb 100644 --- a/src/routes/safe/store/actions/createTransaction.ts +++ b/src/routes/safe/store/actions/createTransaction.ts @@ -38,6 +38,7 @@ import fetchTransactions from './transactions/fetchTransactions' import { safeTransactionsSelector } from 'src/routes/safe/store/selectors' import { Transaction, TransactionStatus, TxArgs } from 'src/routes/safe/store/models/types/transaction' import { AnyAction } from 'redux' +import { PayableTx } from 'src/types/contracts/types.d' import { AppReduxState } from 'src/store' import { Dispatch } from './types' @@ -136,7 +137,7 @@ const createTransaction = ({ const { account: from, hardwareWallet, smartContractWallet } = providerSelector(state) const safeInstance = await getGnosisSafeInstanceAt(safeAddress) const lastTx = await getLastTx(safeAddress) - const nonce = Number(await getNewTxNonce(txNonce, lastTx, safeInstance)) + const nonce = await getNewTxNonce(txNonce?.toString(), lastTx, safeInstance) const isExecution = await shouldExecuteTransaction(safeInstance, nonce, lastTx) const safeVersion = await getCurrentSafeVersion(safeInstance) const safeTxGas = await estimateSafeTxGas(safeInstance, safeAddress, txData, to, valueInWei, operation) @@ -153,14 +154,13 @@ const createTransaction = ({ let pendingExecutionKey let txHash - let tx const txArgs: TxArgs = { safeInstance, to, valueInWei, data: txData, operation, - nonce, + nonce: Number.parseInt(nonce), safeTxGas, baseGas: 0, gasPrice: '0', @@ -189,9 +189,8 @@ const createTransaction = ({ } } - tx = isExecution ? await getExecutionTransaction(txArgs) : await getApprovalTransaction(txArgs) - - const sendParams: any = { from, value: 0 } + const tx = isExecution ? await getExecutionTransaction(txArgs) : await getApprovalTransaction(txArgs) + const sendParams: PayableTx = { from, value: 0 } // if not set owner management tests will fail on ganache if (process.env.NODE_ENV === 'test') { @@ -282,7 +281,7 @@ const createTransaction = ({ ? `${notificationsQueue.afterExecutionError.message} - ${err.message}` : notificationsQueue.afterExecutionError.message - console.error(err) + console.error(`Error creating the TX: `, err) closeSnackbar(beforeExecutionKey) if (pendingExecutionKey) { @@ -291,11 +290,11 @@ const createTransaction = ({ showSnackbar(errorMsg, enqueueSnackbar, closeSnackbar) - const executeDataUsedSignatures = safeInstance.contract.methods + const executeDataUsedSignatures = safeInstance.methods .execTransaction(to, valueInWei, txData, operation, 0, 0, 0, ZERO_ADDRESS, ZERO_ADDRESS, sigs) .encodeABI() - const errMsg = await getErrorMessage(safeInstance.address, 0, executeDataUsedSignatures, from) - console.error(`Error creating the TX: ${errMsg}`) + const errMsg = await getErrorMessage(safeInstance.options.address, 0, executeDataUsedSignatures, from) + console.error(`Error creating the TX - an attempt to get the error message: ${errMsg}`) } return txHash diff --git a/src/routes/safe/store/actions/processTransaction.ts b/src/routes/safe/store/actions/processTransaction.ts index f591b02d..c5ff2e94 100644 --- a/src/routes/safe/store/actions/processTransaction.ts +++ b/src/routes/safe/store/actions/processTransaction.ts @@ -35,6 +35,7 @@ const processTransaction = ({ const { account: from, hardwareWallet, smartContractWallet } = providerSelector(state) const safeInstance = await getGnosisSafeInstanceAt(safeAddress) + const lastTx = await getLastTx(safeAddress) const nonce = await getNewTxNonce(null, lastTx, safeInstance) const isExecution = approveAndExecute || (await shouldExecuteTransaction(safeInstance, nonce, lastTx)) @@ -213,8 +214,8 @@ const processTransaction = ({ showSnackbar(errorMsg, enqueueSnackbar, closeSnackbar) - const executeData = safeInstance.contract.methods.approveHash(txHash).encodeABI() - const errMsg = await getErrorMessage(safeInstance.address, 0, executeData, from) + const executeData = safeInstance.methods.approveHash(txHash).encodeABI() + const errMsg = await getErrorMessage(safeInstance.options.address, 0, executeData, from) console.error(`Error executing the TX: ${errMsg}`) } } diff --git a/src/routes/safe/store/actions/utils.ts b/src/routes/safe/store/actions/utils.ts index c01a55bc..2dee2f09 100644 --- a/src/routes/safe/store/actions/utils.ts +++ b/src/routes/safe/store/actions/utils.ts @@ -1,8 +1,10 @@ +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' +import { TxServiceModel } from './transactions/fetchTransactions/loadOutgoingTransactions' import axios from 'axios' import { buildTxServiceUrl } from 'src/logic/safe/transactions/txHistory' -export const getLastTx = async (safeAddress) => { +export const getLastTx = async (safeAddress: string): Promise => { try { const url = buildTxServiceUrl(safeAddress) const response = await axios.get(url, { params: { limit: 1 } }) @@ -14,21 +16,29 @@ export const getLastTx = async (safeAddress) => { } } -export const getNewTxNonce = async (txNonce, lastTx, safeInstance) => { +export const getNewTxNonce = async ( + txNonce: string | null, + lastTx: TxServiceModel, + safeInstance: GnosisSafe, +): Promise => { if (!Number.isInteger(Number.parseInt(txNonce, 10))) { return lastTx === null ? // use current's safe nonce as fallback - (await safeInstance.nonce()).toString() + (await safeInstance.methods.nonce().call()).toString() : `${lastTx.nonce + 1}` } return txNonce } -export const shouldExecuteTransaction = async (safeInstance, nonce, lastTx) => { - const threshold = await safeInstance.getThreshold() +export const shouldExecuteTransaction = async ( + safeInstance: GnosisSafe, + nonce: string, + lastTx: TxServiceModel, +): Promise => { + const threshold = await safeInstance.methods.getThreshold().call() // Tx will automatically be executed if and only if the threshold is 1 - if (threshold.toNumber() === 1) { + if (Number.parseInt(threshold) === 1) { const isFirstTransaction = Number.parseInt(nonce) === 0 // if the previous tx is not executed, it's delayed using the approval mechanisms, // once the previous tx is executed, the current tx will be available to be executed diff --git a/src/routes/safe/store/models/safe.ts b/src/routes/safe/store/models/safe.ts index 5ae80e6f..0311d3be 100644 --- a/src/routes/safe/store/models/safe.ts +++ b/src/routes/safe/store/models/safe.ts @@ -12,7 +12,7 @@ export type SafeRecordProps = { address: string threshold: number ethBalance: string - owners: List<{ name: string; address: string }> + owners: List modules: ModulePair[] | null activeTokens: Set activeAssets: Set diff --git a/src/routes/safe/store/models/types/transaction.ts b/src/routes/safe/store/models/types/transaction.ts index 83815f60..3dc27c1c 100644 --- a/src/routes/safe/store/models/types/transaction.ts +++ b/src/routes/safe/store/models/types/transaction.ts @@ -1,6 +1,7 @@ import { List, Map, RecordOf } from 'immutable' import { DecodedMethods } from 'src/logic/contracts/methodIds' import { Confirmation } from './confirmation' +import { GnosisSafe } from 'src/types/contracts/GnosisSafe.d' export enum TransactionTypes { INCOMING = 'incoming', @@ -88,7 +89,7 @@ export type TxArgs = { nonce: number operation: number refundReceiver: string - safeInstance: any + safeInstance: GnosisSafe safeTxGas: number sender?: string sigs: string diff --git a/src/store/index.ts b/src/store/index.ts index 13650bb1..6d7179e8 100644 --- a/src/store/index.ts +++ b/src/store/index.ts @@ -5,6 +5,7 @@ import thunk from 'redux-thunk' import addressBookMiddleware from 'src/logic/addressBook/store/middleware/addressBookMiddleware' import addressBook, { ADDRESS_BOOK_REDUCER_ID } from 'src/logic/addressBook/store/reducer/addressBook' +import { AddressBookReducerMap } from 'src/logic/addressBook/store/reducer/types/addressBook.d' import { NFT_ASSETS_REDUCER_ID, NFT_TOKENS_REDUCER_ID, @@ -78,7 +79,7 @@ export type AppReduxState = CombinedState<{ [NOTIFICATIONS_REDUCER_ID]: Map [CURRENCY_VALUES_KEY]: Map [COOKIES_REDUCER_ID]: Map - [ADDRESS_BOOK_REDUCER_ID]: Map + [ADDRESS_BOOK_REDUCER_ID]: AddressBookReducerMap [CURRENT_SESSION_REDUCER_ID]: Map router: RouterState }> diff --git a/src/test/safe.dom.create.tsx b/src/test/safe.dom.create.tsx index 253100ba..eedf5970 100644 --- a/src/test/safe.dom.create.tsx +++ b/src/test/safe.dom.create.tsx @@ -130,9 +130,9 @@ describe('DOM > Feature > CREATE a Safe', () => { expect(address).not.toBe(undefined) const gnosisSafe = await getGnosisSafeInstanceAt(address) - const storedOwners = await gnosisSafe.getOwners() + const storedOwners = await gnosisSafe.methods.getOwners().call() expect(storedOwners.length).toEqual(4) - const safeThreshold = await gnosisSafe.getThreshold() + const safeThreshold = await gnosisSafe.methods.getThreshold().call() expect(Number(safeThreshold)).toEqual(4) }) }) diff --git a/src/test/utils/ethereumErrors.ts b/src/test/utils/ethereumErrors.ts index b5c939c1..c141e836 100644 --- a/src/test/utils/ethereumErrors.ts +++ b/src/test/utils/ethereumErrors.ts @@ -2,16 +2,6 @@ import abi from 'ethereumjs-abi' import { getWeb3 } from 'src/logic/wallets/getWeb3' -/* -console.log(`to[${to}] \n\n valieInWei[${valueInWei}] \n\n - data[${data}] \n\n operation[${operation}] \n\n sigs[${sigs}]`) - -const gnosisSafe = await getGnosisSafeInstanceAt(address) -await printOutApprove("Remove owner 3", address, await gnosisSafe.getOwners(), tx.get('data'), tx.get('nonce')) -const txData = - await gnosisSafe.contract.execTransactionIfApproved.getData(address, 0, tx.get('data'), 0, tx.get('nonce')) -const err = await getErrorMessage(address, 0, txData, accounts[2]) -*/ export const getErrorMessage = async (to, value, data, from) => { const web3 = getWeb3() const returnData: any = await web3.eth.call({ diff --git a/src/test/utils/logTransactions.ts b/src/test/utils/logTransactions.ts deleted file mode 100644 index 096d1183..00000000 --- a/src/test/utils/logTransactions.ts +++ /dev/null @@ -1,81 +0,0 @@ -import React from 'react' -import Stepper from '@material-ui/core/Stepper' -import TestUtils from 'react-dom/test-utils' -import { getGnosisSafeInstanceAt } from 'src/logic/contracts/safeContracts' -import GnoStepper from 'src/components/Stepper' - -export const printOutApprove = async ( - subject, - address, - owners, - data, - nonce, -) => { - // eslint-disable-next-line - console.log(subject) - - const gnosisSafe = await getGnosisSafeInstanceAt(address) - const transactionHash = await gnosisSafe.getTransactionHash(address, 0, data, 0, 0, 0, 0, 0, 0, nonce) - // eslint-disable-next-line - console.log(`EO transaction hash ${transactionHash}`) - - await Promise.all( - owners.map(async (owner, index) => { - const approved = await gnosisSafe.isApproved(transactionHash, owner) - // eslint-disable-next-line - console.log(`EO transaction approved by owner index ${index}: ${approved}`) - }), - ) - // eslint-disable-next-line - console.log(`EO transaction executed ${await gnosisSafe.isExecuted(transactionHash)}`) -} - -const MAX_TIMES_EXECUTED = 35 -const INTERVAL = 500 - - -export const whenExecuted = (SafeDom, ParentComponent) => new Promise((resolve, reject) => { - let times = 0 - const interval = setInterval(() => { - if (times >= MAX_TIMES_EXECUTED) { - clearInterval(interval) - reject() - } - - // $FlowFixMe - const SafeComponent = TestUtils.findRenderedComponentWithType(SafeDom, ParentComponent) - // $FlowFixMe - const StepperComponent = TestUtils.findRenderedComponentWithType(SafeComponent, GnoStepper as any) - - if (StepperComponent.props.finishedTransaction === true) { - clearInterval(interval) - resolve() - } - times += 1 - }, INTERVAL) -}) - - -export const whenOnNext = ( - SafeDom, - ParentComponent, - position, -) => new Promise((resolve, reject) => { - let times = 0 - const interval = setInterval(() => { - if (times >= MAX_TIMES_EXECUTED) { - clearInterval(interval) - reject() - } - - // $FlowFixMe - const SafeComponent = TestUtils.findRenderedComponentWithType(SafeDom, ParentComponent) - // $FlowFixMe - const StepperComponent = TestUtils.findRenderedComponentWithType(SafeComponent, Stepper as any) - if (StepperComponent.props.activeStep === position) { - clearInterval(interval) - resolve() - } - times += 1 - }, INTERVAL) -}) diff --git a/yarn.lock b/yarn.lock index 5228fdda..d204b976 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1682,13 +1682,13 @@ dependencies: "@babel/runtime" "^7.4.4" -"@material-ui/lab@4.0.0-alpha.39": - version "4.0.0-alpha.39" - resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.39.tgz#715ec621111ce876f1744bde1e55018341c4be3e" - integrity sha512-TbYfqS0zWdOzH44K7x74+dcLlMe6o5zrIvvHA2y6IZ1l9a9/qLUZGLwBIOtkBPHDDDJ32rv/bOPzOGGbnxLUDw== +"@material-ui/lab@4.0.0-alpha.56": + version "4.0.0-alpha.56" + resolved "https://registry.yarnpkg.com/@material-ui/lab/-/lab-4.0.0-alpha.56.tgz#ff63080949b55b40625e056bbda05e130d216d34" + integrity sha512-xPlkK+z/6y/24ka4gVJgwPfoCF4RCh8dXb1BNE7MtF9bXEBLN/lBxNTK8VAa0qm3V2oinA6xtUIdcRh0aeRtVw== dependencies: "@babel/runtime" "^7.4.4" - "@material-ui/utils" "^4.7.1" + "@material-ui/utils" "^4.10.2" clsx "^1.0.4" prop-types "^15.7.2" react-is "^16.8.0" @@ -1730,7 +1730,7 @@ resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.1.0.tgz#efa1c7a0b0eaa4c7c87ac0390445f0f88b0d88f2" integrity sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A== -"@material-ui/utils@^4.10.2", "@material-ui/utils@^4.7.1", "@material-ui/utils@^4.9.6": +"@material-ui/utils@^4.10.2", "@material-ui/utils@^4.9.6": version "4.10.2" resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.10.2.tgz#3fd5470ca61b7341f1e0468ac8f29a70bf6df321" integrity sha512-eg29v74P7W5r6a4tWWDAAfZldXIzfyO1am2fIsC39hdUUHm/33k6pGOKPbgDjg/U/4ifmgAePy/1OjkKN6rFRw== @@ -1946,10 +1946,10 @@ dom-accessibility-api "^0.4.6" pretty-format "^25.5.0" -"@testing-library/jest-dom@5.11.1": - version "5.11.1" - resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.1.tgz#b9541d7625cec9e5feb647f49a96c43f7c055cdd" - integrity sha512-NHOHjDwyBoqM7mXjNLieSp/6vJ17DILzhNTw7+RarluaBkyWRzWgFj+d6xnd1adMBlwfQSeR2FWGTxHXCxeMSA== +"@testing-library/jest-dom@5.11.2": + version "5.11.2" + resolved "https://registry.yarnpkg.com/@testing-library/jest-dom/-/jest-dom-5.11.2.tgz#c49de331555c70127b5d7fc97344ad5265f4c54c" + integrity sha512-s+rWJx+lanEGKqvOl4qJR0rGjCrxsEjj9qjxFlg4NV4/FRD7fnUUAWPHqwpyafNHfLYArs58FADgdn4UKmjFmw== dependencies: "@babel/runtime" "^7.9.2" "@types/testing-library__jest-dom" "^5.9.1" @@ -1970,10 +1970,10 @@ "@babel/runtime" "^7.10.3" "@testing-library/dom" "^7.17.1" -"@testing-library/user-event@12.0.13": - version "12.0.13" - resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-12.0.13.tgz#585fbb1188df005d16eabd376c3f8e8eb2f2d35c" - integrity sha512-JvodPV7CGl2Izf/qWS+vAVKBB1ZNAPGEacabfEeLGfafLmiqXoGJCxNZC1ml3mNTj9tTsIjouHGc42gvlyRTtQ== +"@testing-library/user-event@12.0.17": + version "12.0.17" + resolved "https://registry.yarnpkg.com/@testing-library/user-event/-/user-event-12.0.17.tgz#51f48905d62b3c6960fe5ea7a46152d8440f1586" + integrity sha512-Et22bfgnLdowY0VSP8MQuCP9wdrqWMrm9OCXSi3q3rx7ctSvEsC/jYNbgK/MJdDSpVhNVnB+fqm1VhVlDDRN6A== dependencies: "@babel/runtime" "^7.10.2" @@ -2144,6 +2144,11 @@ xhr "^2.2.0" xtend "^4.0.1" +"@typechain/web3-v1@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@typechain/web3-v1/-/web3-v1-1.0.0.tgz#842f925e45bdfb0d28e08c0e355f1c8efed7ea91" + integrity sha512-MM8PmsblePaxy5BCYEuPtR4ajigPf504VRQzZgFYqs6KuFnJxbOjF8jNYT12P6UvUX7us75Wc78QdbvOHbb4hA== + "@types/aria-query@^4.2.0": version "4.2.0" resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-4.2.0.tgz#14264692a9d6e2fa4db3df5e56e94b5e25647ac0" @@ -2182,7 +2187,7 @@ dependencies: "@babel/types" "^7.3.0" -"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.5": +"@types/bn.js@^4.11.3", "@types/bn.js@^4.11.4", "@types/bn.js@^4.11.5": version "4.11.6" resolved "https://registry.yarnpkg.com/@types/bn.js/-/bn.js-4.11.6.tgz#c306c70d9358aaea33cd4eda092a742b9505967c" integrity sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg== @@ -2300,26 +2305,48 @@ resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== +"@types/mkdirp@^0.5.2": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@types/mkdirp/-/mkdirp-0.5.2.tgz#503aacfe5cc2703d5484326b1b27efa67a339c1f" + integrity sha512-U5icWpv7YnZYGsN4/cmh3WD2onMY0aJIiTE6+51TwJCttdHvtCYmkBNOobHlXwrJRL0nkH9jH4kD+1FAdMN4Tg== + dependencies: + "@types/node" "*" + "@types/node@*": version "14.0.24" resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.24.tgz#b0f86f58564fa02a28b68f8b55d4cdec42e3b9d6" integrity sha512-btt/oNOiDWcSuI721MdL8VQGnjsKjlTMdrKyTcLCKeQp/n4AAMFJ961wMbp+09y8WuGPClDEv07RIItdXKIXAA== -"@types/node@14.0.25": - version "14.0.25" - resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.25.tgz#7ad8b00a1206d6c9e94810e49f3115f0bcc30456" - integrity sha512-okMqUHqrMlGOxfDZliX1yFX5MV6qcd5PpRz96XYtjkM0Ws/hwg23FMUqt6pETrVRZS+EKUB5HY19mmo54EuQbA== +"@types/node@14.0.27": + version "14.0.27" + resolved "https://registry.yarnpkg.com/@types/node/-/node-14.0.27.tgz#a151873af5a5e851b51b3b065c9e63390a9e0eb1" + integrity sha512-kVrqXhbclHNHGu9ztnAwSncIgJv/FaxmzXJvGXNdcCpV1b8u1/Mi6z6m0vwy0LzKeXFTPLH0NzwmoJ3fNCIq0g== + +"@types/node@^10.12.18": + version "10.17.28" + resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.28.tgz#0e36d718a29355ee51cec83b42d921299200f6d9" + integrity sha512-dzjES1Egb4c1a89C7lKwQh8pwjYmlOAG9dW1pBgxEk57tMrLnssOfEthz8kdkNaBd7lIqQx7APm5+mZ619IiCQ== "@types/node@^10.3.2": version "10.17.27" resolved "https://registry.yarnpkg.com/@types/node/-/node-10.17.27.tgz#391cb391c75646c8ad2a7b6ed3bbcee52d1bdf19" integrity sha512-J0oqm9ZfAXaPdwNXMMgAhylw5fhmXkToJd06vuDUSAgEDZ/n/69/69UmyBZbc+zT34UnShuDSBqvim3SPnozJg== -"@types/node@^12.0.12", "@types/node@^12.12.6": +"@types/node@^12.0.12": version "12.12.51" resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.51.tgz#446a67af8c5ff98947d7cef296484c6ad47ddb16" integrity sha512-6ILqt8iNThALrxDv2Q4LyYFQxULQz96HKNIFd4s9QRQaiHINYeUpLqeU/2IU7YMtvipG1fQVAy//vY8/fX1Y9w== +"@types/node@^12.12.6": + version "12.12.50" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.50.tgz#e9b2e85fafc15f2a8aa8fdd41091b983da5fd6ee" + integrity sha512-5ImO01Fb8YsEOYpV+aeyGYztcYcjGsBvN4D7G5r1ef2cuQOpymjWNQi5V0rKHE6PC2ru3HkoUr/Br2/8GUA84w== + +"@types/node@^12.6.1": + version "12.12.53" + resolved "https://registry.yarnpkg.com/@types/node/-/node-12.12.53.tgz#be0d375933c3d15ef2380dafb3b0350ea7021129" + integrity sha512-51MYTDTyCziHb70wtGNFRwB4l+5JNvdqzFSkbDvpbftEgVUBEE+T5f7pROhWMp/fxp07oNIEQZd5bbfAH22ohQ== + "@types/parse-json@^4.0.0": version "4.0.0" resolved "https://registry.yarnpkg.com/@types/parse-json/-/parse-json-4.0.0.tgz#2f8bb441434d163b35fb8ffdccd7138927ffb8c0" @@ -2332,6 +2359,11 @@ dependencies: "@types/node" "*" +"@types/prettier@^1.13.2": + version "1.19.1" + resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-1.19.1.tgz#33509849f8e679e4add158959fdb086440e9553f" + integrity sha512-5qOlnZscTn4xxM5MeGXAMOsIOIKIbh9e85zJWfBRVPlRMEVawzoPhINYbRGkBZCI8LxvBe7tJCdWiarA99OZfQ== + "@types/prop-types@*": version "15.7.3" resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7" @@ -2342,7 +2374,7 @@ resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24" integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug== -"@types/react-dom@^16.9.8": +"@types/react-dom@^16.9.6": version "16.9.8" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423" integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA== @@ -2398,6 +2430,13 @@ "@types/prop-types" "*" csstype "^2.2.0" +"@types/resolve@^0.0.8": + version "0.0.8" + resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-0.0.8.tgz#f26074d238e02659e323ce1a13d041eee280e194" + integrity sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ== + dependencies: + "@types/node" "*" + "@types/secp256k1@^4.0.1": version "4.0.1" resolved "https://registry.yarnpkg.com/@types/secp256k1/-/secp256k1-4.0.1.tgz#fb3aa61a1848ad97d7425ff9dcba784549fca5a4" @@ -2453,12 +2492,12 @@ dependencies: "@types/yargs-parser" "*" -"@typescript-eslint/eslint-plugin@3.7.0": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.7.0.tgz#0f91aa3c83d019591719e597fbdb73a59595a263" - integrity sha512-4OEcPON3QIx0ntsuiuFP/TkldmBGXf0uKxPQlGtS/W2F3ndYm8Vgdpj/woPJkzUc65gd3iR+qi3K8SDQP/obFg== +"@typescript-eslint/eslint-plugin@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-3.7.1.tgz#d144c49a9a0ffe8dd704bb179c243df76c111bc9" + integrity sha512-3DB9JDYkMrc8Au00rGFiJLK2Ja9CoMP6Ut0sHsXp3ZtSugjNxvSSHTnKLfo4o+QmjYBJqEznDqsG1zj4F2xnsg== dependencies: - "@typescript-eslint/experimental-utils" "3.7.0" + "@typescript-eslint/experimental-utils" "3.7.1" debug "^4.1.1" functional-red-black-tree "^1.0.1" regexpp "^3.0.0" @@ -2485,26 +2524,26 @@ eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/experimental-utils@3.7.0": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.7.0.tgz#0ee21f6c48b2b30c63211da23827725078d5169a" - integrity sha512-xpfXXAfZqhhqs5RPQBfAFrWDHoNxD5+sVB5A46TF58Bq1hRfVROrWHcQHHUM9aCBdy9+cwATcvCbRg8aIRbaHQ== +"@typescript-eslint/experimental-utils@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-3.7.1.tgz#ab036caaed4c870d22531d41f9352f3147364d61" + integrity sha512-TqE97pv7HrqWcGJbLbZt1v59tcqsSVpWTOf1AqrWK7n8nok2sGgVtYRuGXeNeLw3wXlLEbY1MKP3saB2HsO/Ng== dependencies: "@types/json-schema" "^7.0.3" - "@typescript-eslint/types" "3.7.0" - "@typescript-eslint/typescript-estree" "3.7.0" + "@typescript-eslint/types" "3.7.1" + "@typescript-eslint/typescript-estree" "3.7.1" eslint-scope "^5.0.0" eslint-utils "^2.0.0" -"@typescript-eslint/parser@3.7.0": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.7.0.tgz#3e9cd9df9ea644536feb6e5acdb8279ecff96ce9" - integrity sha512-2LZauVUt7jAWkcIW7djUc3kyW+fSarNEuM3RF2JdLHR9BfX/nDEnyA4/uWz0wseoWVZbDXDF7iF9Jc342flNqQ== +"@typescript-eslint/parser@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-3.7.1.tgz#5d9ccecb116d12d9c6073e9861c57c9b1aa88128" + integrity sha512-W4QV/gXvfIsccN8225784LNOorcm7ch68Fi3V4Wg7gmkWSQRKevO4RrRqWo6N/Z/myK1QAiGgeaXN57m+R/8iQ== dependencies: "@types/eslint-visitor-keys" "^1.0.0" - "@typescript-eslint/experimental-utils" "3.7.0" - "@typescript-eslint/types" "3.7.0" - "@typescript-eslint/typescript-estree" "3.7.0" + "@typescript-eslint/experimental-utils" "3.7.1" + "@typescript-eslint/types" "3.7.1" + "@typescript-eslint/typescript-estree" "3.7.1" eslint-visitor-keys "^1.1.0" "@typescript-eslint/parser@^2.10.0": @@ -2517,10 +2556,10 @@ "@typescript-eslint/typescript-estree" "2.34.0" eslint-visitor-keys "^1.1.0" -"@typescript-eslint/types@3.7.0": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.7.0.tgz#09897fab0cb95479c01166b10b2c03c224821077" - integrity sha512-reCaK+hyKkKF+itoylAnLzFeNYAEktB0XVfSQvf0gcVgpz1l49Lt6Vo9x4MVCCxiDydA0iLAjTF/ODH0pbfnpg== +"@typescript-eslint/types@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-3.7.1.tgz#90375606b2fd73c1224fe9e397ee151e28fa1e0c" + integrity sha512-PZe8twm5Z4b61jt7GAQDor6KiMhgPgf4XmUb9zdrwTbgtC/Sj29gXP1dws9yEn4+aJeyXrjsD9XN7AWFhmnUfg== "@typescript-eslint/typescript-estree@2.34.0": version "2.34.0" @@ -2535,13 +2574,13 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/typescript-estree@3.7.0": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.7.0.tgz#66872e6da120caa4b64e6b4ca5c8702afc74738d" - integrity sha512-xr5oobkYRebejlACGr1TJ0Z/r0a2/HUf0SXqPvlgUMwiMqOCu/J+/Dr9U3T0IxpE5oLFSkqMx1FE/dKaZ8KsOQ== +"@typescript-eslint/typescript-estree@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-3.7.1.tgz#ce1ffbd0fa53f34d4ce851a7a364e392432f6eb3" + integrity sha512-m97vNZkI08dunYOr2lVZOHoyfpqRs0KDpd6qkGaIcLGhQ2WPtgHOd/eVbsJZ0VYCQvupKrObAGTOvk3tfpybYA== dependencies: - "@typescript-eslint/types" "3.7.0" - "@typescript-eslint/visitor-keys" "3.7.0" + "@typescript-eslint/types" "3.7.1" + "@typescript-eslint/visitor-keys" "3.7.1" debug "^4.1.1" glob "^7.1.6" is-glob "^4.0.1" @@ -2549,10 +2588,10 @@ semver "^7.3.2" tsutils "^3.17.1" -"@typescript-eslint/visitor-keys@3.7.0": - version "3.7.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.7.0.tgz#ac0417d382a136e4571a0b0dcfe52088cb628177" - integrity sha512-k5PiZdB4vklUpUX4NBncn5RBKty8G3ihTY+hqJsCdMuD0v4jofI5xuqwnVcWxfv6iTm2P/dfEa2wMUnsUY8ODw== +"@typescript-eslint/visitor-keys@3.7.1": + version "3.7.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-3.7.1.tgz#b90191e74efdee656be8c5a30f428ed16dda46d1" + integrity sha512-xn22sQbEya+Utj2IqJHGLA3i1jDzR43RzWupxojbSWnj3nnPLavaQmWe5utw03CwYao3r00qzXfgJMGNkrzrAA== dependencies: eslint-visitor-keys "^1.1.0" @@ -3138,6 +3177,20 @@ arr-union@^3.1.0: resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= +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" + integrity sha1-ZEun8JX3/898Q7Xw3DnTwfA8Bjs= + 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" + integrity sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw== + dependencies: + typical "^2.6.1" + array-equal@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/array-equal/-/array-equal-1.0.0.tgz#8c2a5ef2472fd9ea742b04c77a75093ba2757c93" @@ -4774,11 +4827,16 @@ caniuse-api@^3.0.0: lodash.memoize "^4.1.2" lodash.uniq "^4.5.0" -caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001093, caniuse-lite@^1.0.30001097: +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000844, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30001035, caniuse-lite@^1.0.30001093: version "1.0.30001105" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001105.tgz#d2cb0b31e5cf2f3ce845033b61c5c01566549abf" integrity sha512-JupOe6+dGMr7E20siZHIZQwYqrllxotAhiaej96y6x00b/48rPt42o+SzOSCPbrpsDWvRja40Hwrj0g0q6LZJg== +caniuse-lite@^1.0.30001097: + version "1.0.30001104" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001104.tgz#4e3d5b3b1dd3c3529f10cb7f519c62ba3e579f5d" + integrity sha512-pkpCg7dmI/a7WcqM2yfdOiT4Xx5tzyoHAXWsX5/HxZ3TemwDZs0QXdqbE0UPLPVy/7BeK7693YfzfRYfu1YVpg== + capture-exit@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/capture-exit/-/capture-exit-2.0.0.tgz#fb953bfaebeb781f62898239dabb426d08a509a4" @@ -5149,6 +5207,15 @@ command-exists@^1.2.8: resolved "https://registry.yarnpkg.com/command-exists/-/command-exists-1.2.9.tgz#c50725af3808c8ab0260fd60b01fbfa25b954f69" integrity sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w== +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" + integrity sha512-aUdPvQRAyBvQd2n7jXcsMDz68ckBJELXNzBybCHOibUWEg0mWTnaYCSRU8h9R+aNRSvDihJtssSRCiDRpLaezA== + dependencies: + array-back "^2.0.0" + find-replace "^1.0.3" + typical "^2.6.1" + commander@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/commander/-/commander-3.0.2.tgz#6837c3fb677ad9933d1cfba42dd14d5117d6b39e" @@ -6408,7 +6475,7 @@ ee-first@1.1.1: resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= -ejs@^3.0.2, ejs@^3.1.3: +ejs@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.1.3.tgz#514d967a8894084d18d3d47bd169a1c0560f093d" integrity sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg== @@ -6730,7 +6797,7 @@ escape-goat@^2.0.0: resolved "https://registry.yarnpkg.com/escape-goat/-/escape-goat-2.1.1.tgz#1b2dc77003676c457ec760b2dc68edb648188675" integrity sha512-8/uIhbG12Csjy2JEW7D9pHbreaVaS/OpN3ycnyvElTdwM5n6GY6W6e2IPemfvGZeUMqZ9A/3GqIZMgKnBhAw/Q== -escape-html@^1.0.3, escape-html@~1.0.3: +escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= @@ -6909,10 +6976,10 @@ eslint-plugin-react@7.19.0: string.prototype.matchall "^4.0.2" xregexp "^4.3.0" -eslint-plugin-react@^7.20.3: - version "7.20.3" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.3.tgz#0590525e7eb83890ce71f73c2cf836284ad8c2f1" - integrity sha512-txbo090buDeyV0ugF3YMWrzLIUqpYTsWSDZV9xLSmExE1P/Kmgg9++PD931r+KEWS66O1c9R4srLVVHmeHpoAg== +eslint-plugin-react@^7.20.5: + version "7.20.5" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.20.5.tgz#29480f3071f64a04b2c3d99d9b460ce0f76fb857" + integrity sha512-ajbJfHuFnpVNJjhyrfq+pH1C0gLc2y94OiCbAXT5O0J0YCKaFEHDV8+3+mDOr+w8WguRX+vSs1bM2BDG0VLvCw== dependencies: array-includes "^3.1.1" array.prototype.flatmap "^1.2.3" @@ -7173,7 +7240,7 @@ eth-lib@0.2.7: elliptic "^6.4.0" xhr-request-promise "^0.1.2" -eth-lib@0.2.8: +eth-lib@0.2.8, eth-lib@^0.2.8: version "0.2.8" resolved "https://registry.yarnpkg.com/eth-lib/-/eth-lib-0.2.8.tgz#b194058bef4b220ad12ea497431d6cb6aa0623c8" integrity sha512-ArJ7x1WcWOlSpzdoTBX8vkwlkSQ85CjjifSZtV4co64vWxSV8geWfPI9x4SVYu3DSxnX4yWFVTtGL+j9DUFLNw== @@ -8004,6 +8071,14 @@ find-cache-dir@^3.2.0: make-dir "^3.0.2" pkg-dir "^4.1.0" +find-replace@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/find-replace/-/find-replace-1.0.3.tgz#b88e7364d2d9c959559f388c66670d6130441fa0" + integrity sha1-uI5zZNLZyVlVnziMZmcNYTBEH6A= + dependencies: + array-back "^1.0.4" + test-value "^2.1.0" + find-up@4.1.0, find-up@^4.0.0, find-up@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" @@ -8584,7 +8659,7 @@ growly@^1.3.0: resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081" integrity sha1-8QdIy+dq+WS3yWyTxrzCivEgwIE= -gzip-size@5.1.1, gzip-size@^5.1.1: +gzip-size@5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== @@ -12234,7 +12309,7 @@ onetime@^5.1.0: dependencies: mimic-fn "^2.1.0" -open@^7.0.2, open@^7.0.3, open@^7.1.0: +open@^7.0.2, open@^7.1.0: version "7.1.0" resolved "https://registry.yarnpkg.com/open/-/open-7.1.0.tgz#68865f7d3cb238520fa1225a63cf28bcf8368a1c" integrity sha512-lLPI5KgOwEYCDKXf4np7y1PBEkj7HYIyP2DY8mVDRnx0VIIu6bNrRB0R66TuO7Mack6EnTNLm4uvcl1UoklTpA== @@ -13537,6 +13612,11 @@ prettier@2.0.5: resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.0.5.tgz#d6d56282455243f2f92cc1716692c08aa31522d4" integrity sha512-7PtVymN48hGcO4fGjybyBSIWDsLU4H4XlvOHfq91pz9kkGlonzwTfYkaIEwiRg/dAJF9YlbsduBAgtYLi+8cFg== +prettier@^1.14.2: + version "1.19.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb" + integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew== + pretty-bytes@^5.1.0: version "5.3.0" resolved "https://registry.yarnpkg.com/pretty-bytes/-/pretty-bytes-5.3.0.tgz#f2849e27db79fb4d6cfe24764fc4134f165989f2" @@ -14022,10 +14102,10 @@ react-qr-reader@^2.2.1: prop-types "^15.7.2" webrtc-adapter "^7.2.1" -react-redux@7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" - integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA== +react-redux@7.2.1: + version "7.2.1" + resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-7.2.1.tgz#8dedf784901014db2feca1ab633864dee68ad985" + integrity sha512-T+VfD/bvgGTUA74iW9d2i5THrDQWbweXP0AVNI8tNd1Rk5ch1rnMiJkDD67ejw7YBKM4+REvcvqRuWJb7BLuEg== dependencies: "@babel/runtime" "^7.5.5" hoist-non-react-statics "^3.3.0" @@ -14744,7 +14824,7 @@ rgba-regex@^1.0.0: resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= -rimraf@2.6.3, rimraf@~2.6.2: +rimraf@2.6.3: version "2.6.3" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.6.3.tgz#b2d104fe0d8fb27cf9e0a1cda8262dd3833c6cab" integrity sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA== @@ -15433,24 +15513,6 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== -source-map-explorer@^2.4.2: - version "2.4.2" - resolved "https://registry.yarnpkg.com/source-map-explorer/-/source-map-explorer-2.4.2.tgz#fb23f86c3112eacde5683f24efaf4ddc9f677985" - integrity sha512-3ECQLffCFV8QgrTqcmddLkWL4/aQs6ljYfgWCLselo5QtizOfOeUCKnS4rFn7MIrdeZLM6TZrseOtsrWZhWKoQ== - dependencies: - btoa "^1.2.1" - chalk "^3.0.0" - convert-source-map "^1.7.0" - ejs "^3.0.2" - escape-html "^1.0.3" - glob "^7.1.6" - gzip-size "^5.1.1" - lodash "^4.17.15" - open "^7.0.3" - source-map "^0.7.3" - temp "^0.9.1" - yargs "^15.3.1" - source-map-resolve@^0.5.0, source-map-resolve@^0.5.2: version "0.5.3" resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" @@ -16206,13 +16268,6 @@ temp-file@^3.3.7: async-exit-hook "^2.0.1" fs-extra "^8.1.0" -temp@^0.9.1: - version "0.9.1" - resolved "https://registry.yarnpkg.com/temp/-/temp-0.9.1.tgz#2d666114fafa26966cd4065996d7ceedd4dd4697" - integrity sha512-WMuOgiua1xb5R56lE0eH6ivpVmg/lq2OHm4+LtT/xtEtPQ+sz6N3bBM6WZ5FvO1lO4IKIOb43qnhoc4qxP5OeA== - dependencies: - rimraf "~2.6.2" - term-size@^2.1.0: version "2.2.0" resolved "https://registry.yarnpkg.com/term-size/-/term-size-2.2.0.tgz#1f16adedfe9bdc18800e1776821734086fcc6753" @@ -16267,6 +16322,14 @@ test-exclude@^5.2.3: read-pkg-up "^4.0.0" require-main-filename "^2.0.0" +test-value@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/test-value/-/test-value-2.1.0.tgz#11da6ff670f3471a73b625ca4f3fdcf7bb748291" + integrity sha1-Edpv9nDzRxpztiXKTz/c97t0gpE= + dependencies: + array-back "^1.0.3" + typical "^2.6.0" + text-table@0.2.0, text-table@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" @@ -16499,7 +16562,16 @@ truffle-interface-adapter@^0.2.5: lodash "^4.17.13" web3 "1.2.1" -truffle@5.1.35, truffle@^5.1.21: +truffle@5.1.36: + version "5.1.36" + resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.36.tgz#d49c9e0c20558bdee76f442663f81367f62c5559" + integrity sha512-BXfDrRJmxECsHFu1ZHeQNDdv3OA3vmwQ6Wp5m9yaE0swKcHS+gd8sBdxQBoliiAI0xvUAsD62PRGowqFfT1CLg== + dependencies: + app-module-path "^2.2.0" + mocha "8.0.1" + original-require "1.0.1" + +truffle@^5.1.21: version "5.1.35" resolved "https://registry.yarnpkg.com/truffle/-/truffle-5.1.35.tgz#9b3adfd3aca1a3b6dd00874bc57d7569a3e3b89c" integrity sha512-N2b/3OF84c/4jqmPJ4JgQU1g91Cai4JMKdJ3HLUsmEKmo1LZ84+Y0UIeVBFjWHtTX6H7/oXlvZ59xUVzxXyAsg== @@ -16515,6 +16587,31 @@ truncate-utf8-bytes@^1.0.0: dependencies: utf8-byte-length "^1.0.1" +ts-essentials@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-1.0.4.tgz#ce3b5dade5f5d97cf69889c11bf7d2da8555b15a" + integrity sha512-q3N1xS4vZpRouhYHDPwO0bDW3EZ6SK9CrrDHxi/D6BPReSjpVgWIOpLS2o0gSBZm+7q/wyKp6RVM1AeeW7uyfQ== + +ts-essentials@^6.0.3: + version "6.0.7" + resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-6.0.7.tgz#5f4880911b7581a873783740ce8b94da163d18a6" + integrity sha512-2E4HIIj4tQJlIHuATRHayv0EfMGK3ris/GRk1E3CFnsZzeNV+hUmelbaTZHLtXaZppM5oLhHRtO04gINC4Jusw== + +ts-generator@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/ts-generator/-/ts-generator-0.0.8.tgz#7bd48ca064db026d9520bcb682b69efc20971d6a" + integrity sha512-Gi+aZCELpVL7Mqb+GuMgM+n8JZ/arZZib1iD/R9Ok8JDjOCOCrqS9b1lr72ku7J45WeDCFZxyJoRsiQvhokCnw== + dependencies: + "@types/mkdirp" "^0.5.2" + "@types/prettier" "^1.13.2" + "@types/resolve" "^0.0.8" + chalk "^2.4.1" + glob "^7.1.2" + mkdirp "^0.5.1" + prettier "^1.14.2" + resolve "^1.8.1" + ts-essentials "^1.0.0" + ts-pnp@1.1.6: version "1.1.6" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.1.6.tgz#389a24396d425a0d3162e96d2b4638900fdc289a" @@ -16619,6 +16716,19 @@ type@^2.0.0: resolved "https://registry.yarnpkg.com/type/-/type-2.0.0.tgz#5f16ff6ef2eb44f260494dae271033b29c09a9c3" integrity sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow== +typechain@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/typechain/-/typechain-2.0.0.tgz#62143b48cdf8f95a777f1b76617af077b2d44eee" + integrity sha512-O+hsAUwtBpqCfoq46Grm52OEdm0GBEu78LxrEzkkGdwUdCoCZpNb2HPzPoNB1MXiRnNhEOGMFyf05UbT2/bUEw== + dependencies: + command-line-args "^4.0.7" + debug "^4.1.1" + fs-extra "^7.0.0" + js-sha3 "^0.8.0" + lodash "^4.17.15" + ts-essentials "^6.0.3" + ts-generator "^0.0.8" + typedarray-to-buffer@3.1.5, typedarray-to-buffer@^3.1.5: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" @@ -16631,11 +16741,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^3.9.7: +typescript@3.9.7: version "3.9.7" resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.7.tgz#98d600a5ebdc38f40cb277522f12dc800e9e25fa" integrity sha512-BLbiRkiBzAwsjut4x/dsibSTB6yWpwT5qWmC2OfuCg3GgVQCSgMs4vEctYPhsaGtd0AeuuHMkjZ2h2WG8MSzRw== +typical@^2.6.0, typical@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/typical/-/typical-2.6.1.tgz#5c080e5d661cbbe38259d2e70a3c7253e873881d" + integrity sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0= + u2f-api@0.2.7: version "0.2.7" resolved "https://registry.yarnpkg.com/u2f-api/-/u2f-api-0.2.7.tgz#17bf196b242f6bf72353d9858e6a7566cc192720" @@ -17079,12 +17194,12 @@ web3-bzz@1.2.1: swarm-js "0.1.39" underscore "1.9.1" -web3-bzz@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.11.tgz#41bc19a77444bd5365744596d778b811880f707f" - integrity sha512-XGpWUEElGypBjeFyUhTkiPXFbDVD6Nr/S5jznE3t8cWUA0FxRf1n3n/NuIZeb0H9RkN2Ctd/jNma/k8XGa3YKg== +web3-bzz@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-bzz/-/web3-bzz-1.2.9.tgz#25f8a373bc2dd019f47bf80523546f98b93c8790" + integrity sha512-ogVQr9jHodu9HobARtvUSmWG22cv2EUQzlPeejGWZ7j5h20HX40EDuWyomGY5VclIj5DdLY76Tmq88RTf/6nxA== dependencies: - "@types/node" "^12.12.6" + "@types/node" "^10.12.18" got "9.6.0" swarm-js "^0.1.40" underscore "1.9.1" @@ -17107,6 +17222,15 @@ web3-core-helpers@1.2.11: web3-eth-iban "1.2.11" web3-utils "1.2.11" +web3-core-helpers@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-core-helpers/-/web3-core-helpers-1.2.9.tgz#6381077c3e01c127018cb9e9e3d1422697123315" + integrity sha512-t0WAG3orLCE3lqi77ZoSRNFok3VQWZXTniZigDQjyOJYMAX7BU3F3js8HKbjVnAxlX3tiKoDxI0KBk9F3AxYuw== + dependencies: + underscore "1.9.1" + web3-eth-iban "1.2.9" + web3-utils "1.2.9" + web3-core-method@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.1.tgz#9df1bafa2cd8be9d9937e01c6a47fc768d15d90a" @@ -17130,6 +17254,18 @@ web3-core-method@1.2.11: web3-core-subscriptions "1.2.11" web3-utils "1.2.11" +web3-core-method@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-core-method/-/web3-core-method-1.2.9.tgz#3fb538751029bea570e4f86731e2fa5e4945e462" + integrity sha512-bjsIoqP3gs7A/gP8+QeLUCyOKJ8bopteCSNbCX36Pxk6TYfYWNuC6hP+2GzUuqdP3xaZNe+XEElQFUNpR3oyAg== + dependencies: + "@ethersproject/transactions" "^5.0.0-beta.135" + underscore "1.9.1" + web3-core-helpers "1.2.9" + web3-core-promievent "1.2.9" + web3-core-subscriptions "1.2.9" + web3-utils "1.2.9" + web3-core-promievent@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.1.tgz#003e8a3eb82fb27b6164a6d5b9cad04acf733838" @@ -17145,6 +17281,13 @@ web3-core-promievent@1.2.11: dependencies: eventemitter3 "4.0.4" +web3-core-promievent@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-core-promievent/-/web3-core-promievent-1.2.9.tgz#bb1c56aa6fac2f4b3c598510f06554d25c11c553" + integrity sha512-0eAUA2zjgXTleSrnc1wdoKQPPIHU6KHf4fAscu4W9kKrR+mqP1KsjYrxY9wUyjNnXxfQ+5M29ipvbiaK8OqdOw== + dependencies: + eventemitter3 "3.1.2" + web3-core-requestmanager@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.1.tgz#fa2e2206c3d738db38db7c8fe9c107006f5c6e3d" @@ -17167,6 +17310,17 @@ web3-core-requestmanager@1.2.11: web3-providers-ipc "1.2.11" web3-providers-ws "1.2.11" +web3-core-requestmanager@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-core-requestmanager/-/web3-core-requestmanager-1.2.9.tgz#dd6d855256c4dd681434fe0867f8cd742fe10503" + integrity sha512-1PwKV2m46ALUnIN5VPPgjOj8yMLJhhqZYvYJE34hTN5SErOkwhzx5zScvo5MN7v7KyQGFnpVCZKKGCiEnDmtFA== + dependencies: + underscore "1.9.1" + web3-core-helpers "1.2.9" + web3-providers-http "1.2.9" + web3-providers-ipc "1.2.9" + web3-providers-ws "1.2.9" + web3-core-subscriptions@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.1.tgz#8c2368a839d4eec1c01a4b5650bbeb82d0e4a099" @@ -17185,6 +17339,15 @@ web3-core-subscriptions@1.2.11: underscore "1.9.1" web3-core-helpers "1.2.11" +web3-core-subscriptions@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-core-subscriptions/-/web3-core-subscriptions-1.2.9.tgz#335fd7d15dfce5d78b4b7bef05ce4b3d7237b0e4" + integrity sha512-Y48TvXPSPxEM33OmXjGVDMzTd0j8X0t2+sDw66haeBS8eYnrEzasWuBZZXDq0zNUsqyxItgBGDn+cszkgEnFqg== + dependencies: + eventemitter3 "3.1.2" + underscore "1.9.1" + web3-core-helpers "1.2.9" + web3-core@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.1.tgz#7278b58fb6495065e73a77efbbce781a7fddf1a9" @@ -17195,7 +17358,7 @@ web3-core@1.2.1: web3-core-requestmanager "1.2.1" web3-utils "1.2.1" -web3-core@1.2.11: +web3-core@1.2.11, web3-core@^1.2.11: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.11.tgz#1043cacc1becb80638453cc5b2a14be9050288a7" integrity sha512-CN7MEYOY5ryo5iVleIWRE3a3cZqVaLlIbIzDPsvQRUfzYnvzZQRZBm9Mq+ttDi2STOOzc1MKylspz/o3yq/LjQ== @@ -17208,6 +17371,19 @@ web3-core@1.2.11: web3-core-requestmanager "1.2.11" web3-utils "1.2.11" +web3-core@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-core/-/web3-core-1.2.9.tgz#2cba57aa259b6409db532d21bdf57db8d504fd3e" + integrity sha512-fSYv21IP658Ty2wAuU9iqmW7V+75DOYMVZsDH/c14jcF/1VXnedOcxzxSj3vArsCvXZNe6XC5/wAuGZyQwR9RA== + dependencies: + "@types/bn.js" "^4.11.4" + "@types/node" "^12.6.1" + bignumber.js "^9.0.0" + web3-core-helpers "1.2.9" + web3-core-method "1.2.9" + web3-core-requestmanager "1.2.9" + web3-utils "1.2.9" + web3-eth-abi@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.1.tgz#9b915b1c9ebf82f70cca631147035d5419064689" @@ -17226,6 +17402,15 @@ web3-eth-abi@1.2.11: underscore "1.9.1" web3-utils "1.2.11" +web3-eth-abi@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-eth-abi/-/web3-eth-abi-1.2.9.tgz#14bedd7e4be04fcca35b2ac84af1400574cd8280" + integrity sha512-3YwUYbh/DMfDbhMWEebAdjSd5bj3ZQieOjLzWFHU23CaLEqT34sUix1lba+hgUH/EN6A7bKAuKOhR3p0OvTn7Q== + dependencies: + "@ethersproject/abi" "5.0.0-beta.153" + underscore "1.9.1" + web3-utils "1.2.9" + web3-eth-accounts@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.1.tgz#2741a8ef337a7219d57959ac8bd118b9d68d63cf" @@ -17243,22 +17428,22 @@ web3-eth-accounts@1.2.1: web3-core-method "1.2.1" web3-utils "1.2.1" -web3-eth-accounts@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.11.tgz#a9e3044da442d31903a7ce035a86d8fa33f90520" - integrity sha512-6FwPqEpCfKIh3nSSGeo3uBm2iFSnFJDfwL3oS9pyegRBXNsGRVpgiW63yhNzL0796StsvjHWwQnQHsZNxWAkGw== +web3-eth-accounts@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-eth-accounts/-/web3-eth-accounts-1.2.9.tgz#7ec422df90fecb5243603ea49dc28726db7bdab6" + integrity sha512-jkbDCZoA1qv53mFcRHCinoCsgg8WH+M0YUO1awxmqWXRmCRws1wW0TsuSQ14UThih5Dxolgl+e+aGWxG58LMwg== dependencies: crypto-browserify "3.12.0" - eth-lib "0.2.8" + eth-lib "^0.2.8" ethereumjs-common "^1.3.2" ethereumjs-tx "^2.1.1" scrypt-js "^3.0.1" underscore "1.9.1" uuid "3.3.2" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" + web3-core "1.2.9" + web3-core-helpers "1.2.9" + web3-core-method "1.2.9" + web3-utils "1.2.9" web3-eth-contract@1.2.1: version "1.2.1" @@ -17274,7 +17459,22 @@ web3-eth-contract@1.2.1: web3-eth-abi "1.2.1" web3-utils "1.2.1" -web3-eth-contract@1.2.11, web3-eth-contract@^1.2.11, web3-eth-contract@^1.2.9: +web3-eth-contract@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.9.tgz#713d9c6d502d8c8f22b696b7ffd8e254444e6bfd" + integrity sha512-PYMvJf7EG/HyssUZa+pXrc8IB06K/YFfWYyW4R7ed3sab+9wWUys1TlWxBCBuiBXOokSAyM6H6P6/cKEx8FT8Q== + dependencies: + "@types/bn.js" "^4.11.4" + underscore "1.9.1" + web3-core "1.2.9" + web3-core-helpers "1.2.9" + web3-core-method "1.2.9" + web3-core-promievent "1.2.9" + web3-core-subscriptions "1.2.9" + web3-eth-abi "1.2.9" + web3-utils "1.2.9" + +web3-eth-contract@^1.2.11, web3-eth-contract@^1.2.9: version "1.2.11" resolved "https://registry.yarnpkg.com/web3-eth-contract/-/web3-eth-contract-1.2.11.tgz#917065902bc27ce89da9a1da26e62ef663663b90" integrity sha512-MzYuI/Rq2o6gn7vCGcnQgco63isPNK5lMAan2E51AJLknjSLnOxwNY3gM8BcKoy4Z+v5Dv00a03Xuk78JowFow== @@ -17303,20 +17503,20 @@ web3-eth-ens@1.2.1: web3-eth-contract "1.2.1" web3-utils "1.2.1" -web3-eth-ens@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.11.tgz#26d4d7f16d6cbcfff918e39832b939edc3162532" - integrity sha512-dbW7dXP6HqT1EAPvnniZVnmw6TmQEKF6/1KgAxbo8iBBYrVTMDGFQUUnZ+C4VETGrwwaqtX4L9d/FrQhZ6SUiA== +web3-eth-ens@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-eth-ens/-/web3-eth-ens-1.2.9.tgz#577b9358c036337833fb2bdc59c11be7f6f731b6" + integrity sha512-kG4+ZRgZ8I1WYyOBGI8QVRHfUSbbJjvJAGA1AF/NOW7JXQ+x7gBGeJw6taDWJhSshMoEKWcsgvsiuoG4870YxQ== dependencies: content-hash "^2.5.2" eth-ens-namehash "2.0.8" underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-promievent "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-contract "1.2.11" - web3-utils "1.2.11" + web3-core "1.2.9" + web3-core-helpers "1.2.9" + web3-core-promievent "1.2.9" + web3-eth-abi "1.2.9" + web3-eth-contract "1.2.9" + web3-utils "1.2.9" web3-eth-iban@1.2.1: version "1.2.1" @@ -17334,6 +17534,14 @@ web3-eth-iban@1.2.11: bn.js "^4.11.9" web3-utils "1.2.11" +web3-eth-iban@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-eth-iban/-/web3-eth-iban-1.2.9.tgz#4ebf3d8783f34d04c4740dc18938556466399f7a" + integrity sha512-RtdVvJE0pyg9dHLy0GzDiqgnLnssSzfz/JYguhC1wsj9+Gnq1M6Diy3NixACWUAp6ty/zafyOaZnNQ+JuH9TjQ== + dependencies: + bn.js "4.11.8" + web3-utils "1.2.9" + web3-eth-personal@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.1.tgz#244e9911b7b482dc17c02f23a061a627c6e47faf" @@ -17345,17 +17553,17 @@ web3-eth-personal@1.2.1: web3-net "1.2.1" web3-utils "1.2.1" -web3-eth-personal@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.11.tgz#a38b3942a1d87a62070ce0622a941553c3d5aa70" - integrity sha512-42IzUtKq9iHZ8K9VN0vAI50iSU9tOA1V7XU2BhF/tb7We2iKBVdkley2fg26TxlOcKNEHm7o6HRtiiFsVK4Ifw== +web3-eth-personal@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-eth-personal/-/web3-eth-personal-1.2.9.tgz#9b95eb159b950b83cd8ae15873e1d57711b7a368" + integrity sha512-cFiNrktxZ1C/rIdJFzQTvFn3/0zcsR3a+Jf8Y3KxeQDHszQtosjLWptP7bsUmDwEh4hzh0Cy3KpOxlYBWB8bJQ== dependencies: - "@types/node" "^12.12.6" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" + "@types/node" "^12.6.1" + web3-core "1.2.9" + web3-core-helpers "1.2.9" + web3-core-method "1.2.9" + web3-net "1.2.9" + web3-utils "1.2.9" web3-eth@1.2.1: version "1.2.1" @@ -17376,24 +17584,24 @@ web3-eth@1.2.1: web3-net "1.2.1" web3-utils "1.2.1" -web3-eth@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.11.tgz#4c81fcb6285b8caf544058fba3ae802968fdc793" - integrity sha512-REvxW1wJ58AgHPcXPJOL49d1K/dPmuw4LjPLBPStOVkQjzDTVmJEIsiLwn2YeuNDd4pfakBwT8L3bz1G1/wVsQ== +web3-eth@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-eth/-/web3-eth-1.2.9.tgz#e40e7b88baffc9b487193211c8b424dc944977b3" + integrity sha512-sIKO4iE9FEBa/CYUd6GdPd7GXt/wISqxUd8PlIld6+hvMJj02lgO7Z7p5T9mZIJcIZJGvZX81ogx8oJ9yif+Ag== dependencies: underscore "1.9.1" - web3-core "1.2.11" - web3-core-helpers "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-eth-abi "1.2.11" - web3-eth-accounts "1.2.11" - web3-eth-contract "1.2.11" - web3-eth-ens "1.2.11" - web3-eth-iban "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-utils "1.2.11" + web3-core "1.2.9" + web3-core-helpers "1.2.9" + web3-core-method "1.2.9" + web3-core-subscriptions "1.2.9" + web3-eth-abi "1.2.9" + web3-eth-accounts "1.2.9" + web3-eth-contract "1.2.9" + web3-eth-ens "1.2.9" + web3-eth-iban "1.2.9" + web3-eth-personal "1.2.9" + web3-net "1.2.9" + web3-utils "1.2.9" web3-net@1.2.1: version "1.2.1" @@ -17404,14 +17612,14 @@ web3-net@1.2.1: web3-core-method "1.2.1" web3-utils "1.2.1" -web3-net@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.11.tgz#eda68ef25e5cdb64c96c39085cdb74669aabbe1b" - integrity sha512-sjrSDj0pTfZouR5BSTItCuZ5K/oZPVdVciPQ6981PPPIwJJkCMeVjD7I4zO3qDPCnBjBSbWvVnLdwqUBPtHxyg== +web3-net@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-net/-/web3-net-1.2.9.tgz#51d248ed1bc5c37713c4ac40c0073d9beacd87d3" + integrity sha512-d2mTn8jPlg+SI2hTj2b32Qan6DmtU9ap/IUlJTeQbZQSkTLf0u9suW8Vjwyr4poJYXTurdSshE7OZsPNn30/ZA== dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-utils "1.2.11" + web3-core "1.2.9" + web3-core-method "1.2.9" + web3-utils "1.2.9" web3-provider-engine@15.0.12, web3-provider-engine@^15.0.4: version "15.0.12" @@ -17485,6 +17693,14 @@ web3-providers-http@1.2.11: web3-core-helpers "1.2.11" xhr2-cookies "1.1.0" +web3-providers-http@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-providers-http/-/web3-providers-http-1.2.9.tgz#e698aa5377e2019c24c5a1e6efa0f51018728934" + integrity sha512-F956tCIj60Ttr0UvEHWFIhx+be3He8msoPzyA44/kfzzYoMAsCFRn5cf0zQG6al0znE75g6HlWVSN6s3yAh51A== + dependencies: + web3-core-helpers "1.2.9" + xhr2-cookies "1.1.0" + web3-providers-ipc@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.1.tgz#017bfc687a8fc5398df2241eb98f135e3edd672c" @@ -17503,6 +17719,15 @@ web3-providers-ipc@1.2.11: underscore "1.9.1" web3-core-helpers "1.2.11" +web3-providers-ipc@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-providers-ipc/-/web3-providers-ipc-1.2.9.tgz#6159eacfcd7ac31edc470d93ef10814fe874763b" + integrity sha512-NQ8QnBleoHA2qTJlqoWu7EJAD/FR5uimf7Ielzk4Z2z+m+6UAuJdJMSuQNj+Umhz9L/Ys6vpS1vHx9NizFl+aQ== + dependencies: + oboe "2.1.4" + underscore "1.9.1" + web3-core-helpers "1.2.9" + web3-providers-ws@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.1.tgz#2d941eaf3d5a8caa3214eff8dc16d96252b842cb" @@ -17522,6 +17747,16 @@ web3-providers-ws@1.2.11: web3-core-helpers "1.2.11" websocket "^1.0.31" +web3-providers-ws@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-providers-ws/-/web3-providers-ws-1.2.9.tgz#22c2006655ec44b4ad2b41acae62741a6ae7a88c" + integrity sha512-6+UpvINeI//dglZoAKStUXqxDOXJy6Iitv2z3dbgInG4zb8tkYl/VBDL80UjUg3ZvzWG0g7EKY2nRPEpON2TFA== + dependencies: + eventemitter3 "^4.0.0" + underscore "1.9.1" + web3-core-helpers "1.2.9" + websocket "^1.0.31" + web3-shh@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.1.tgz#4460e3c1e07faf73ddec24ccd00da46f89152b0c" @@ -17532,15 +17767,15 @@ web3-shh@1.2.1: web3-core-subscriptions "1.2.1" web3-net "1.2.1" -web3-shh@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.11.tgz#f5d086f9621c9a47e98d438010385b5f059fd88f" - integrity sha512-B3OrO3oG1L+bv3E1sTwCx66injW1A8hhwpknDUbV+sw3fehFazA06z9SGXUefuFI1kVs4q2vRi0n4oCcI4dZDg== +web3-shh@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-shh/-/web3-shh-1.2.9.tgz#c4ba70d6142cfd61341a50752d8cace9a0370911" + integrity sha512-PWa8b/EaxaMinFaxy6cV0i0EOi2M7a/ST+9k9nhyhCjVa2vzXuNoBNo2IUOmeZ0WP2UQB8ByJ2+p4htlJaDOjA== dependencies: - web3-core "1.2.11" - web3-core-method "1.2.11" - web3-core-subscriptions "1.2.11" - web3-net "1.2.11" + web3-core "1.2.9" + web3-core-method "1.2.9" + web3-core-subscriptions "1.2.9" + web3-net "1.2.9" web3-utils@1.2.1: version "1.2.1" @@ -17569,6 +17804,20 @@ web3-utils@1.2.11, web3-utils@^1.2.11, web3-utils@^1.2.9: underscore "1.9.1" utf8 "3.0.0" +web3-utils@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3-utils/-/web3-utils-1.2.9.tgz#abe11735221627da943971ef1a630868fb9c61f3" + integrity sha512-9hcpuis3n/LxFzEVjwnVgvJzTirS2S9/MiNAa7l4WOEoywY+BSNwnRX4MuHnjkh9NY25B6QOjuNG6FNnSjTw1w== + dependencies: + bn.js "4.11.8" + eth-lib "0.2.7" + ethereum-bloom-filters "^1.0.6" + ethjs-unit "0.1.6" + number-to-bn "1.7.0" + randombytes "^2.1.0" + underscore "1.9.1" + utf8 "3.0.0" + web3@1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.1.tgz#5d8158bcca47838ab8c2b784a2dee4c3ceb4179b" @@ -17582,18 +17831,18 @@ web3@1.2.1: web3-shh "1.2.1" web3-utils "1.2.1" -web3@1.2.11: - version "1.2.11" - resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.11.tgz#50f458b2e8b11aa37302071c170ed61cff332975" - integrity sha512-mjQ8HeU41G6hgOYm1pmeH0mRAeNKJGnJEUzDMoerkpw7QUQT4exVREgF1MYPvL/z6vAshOXei25LE/t/Bxl8yQ== +web3@1.2.9: + version "1.2.9" + resolved "https://registry.yarnpkg.com/web3/-/web3-1.2.9.tgz#cbcf1c0fba5e213a6dfb1f2c1f4b37062e4ce337" + integrity sha512-Mo5aBRm0JrcNpN/g4VOrDzudymfOnHRC3s2VarhYxRA8aWgF5rnhQ0ziySaugpic1gksbXPe105pUWyRqw8HUA== dependencies: - web3-bzz "1.2.11" - web3-core "1.2.11" - web3-eth "1.2.11" - web3-eth-personal "1.2.11" - web3-net "1.2.11" - web3-shh "1.2.11" - web3-utils "1.2.11" + web3-bzz "1.2.9" + web3-core "1.2.9" + web3-eth "1.2.9" + web3-eth-personal "1.2.9" + web3-net "1.2.9" + web3-shh "1.2.9" + web3-utils "1.2.9" web3@^0.20.7: version "0.20.7"