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
This commit is contained in:
parent
24dffd53da
commit
86cbd94b0c
|
@ -9,4 +9,5 @@ electron-builder.yml
|
|||
/.yalc
|
||||
yalc.lock
|
||||
# testing
|
||||
/coverage
|
||||
/coverage/
|
||||
src/types/contracts/
|
||||
|
|
39
package.json
39
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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
}
|
||||
|
||||
|
|
|
@ -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 }) => (
|
||||
<Paper className={classes.root} elevation={1}>
|
||||
<Block className={padding ? classes.padding : ''}>{children}</Block>
|
||||
{controls}
|
||||
</Paper>
|
||||
)
|
||||
interface Props {
|
||||
padding?: boolean
|
||||
controls: React.ReactNode
|
||||
}
|
||||
|
||||
export default withStyles(styles as any)(OpenPaper)
|
||||
const OpenPaper: React.FC<Props> = ({ children, controls, padding = true }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<Paper className={classes.root} elevation={1}>
|
||||
<Block className={padding ? classes.padding : ''}>{children}</Block>
|
||||
{controls}
|
||||
</Paper>
|
||||
)
|
||||
}
|
||||
|
||||
export default OpenPaper
|
||||
|
|
|
@ -1,5 +0,0 @@
|
|||
import * as React from 'react'
|
||||
|
||||
const Step = ({ children }) => <div>{children}</div>
|
||||
|
||||
export default Step
|
|
@ -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<string, string>
|
||||
errors: Record<string, string>
|
||||
form: FormApi
|
||||
}
|
||||
|
||||
const GnoStepper = (props: any) => {
|
||||
interface StepperPageProps {
|
||||
validate?: (...args: unknown[]) => undefined | string[] | Promise<undefined | Record<string, string>>
|
||||
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<string, string>
|
||||
|
||||
interface Mutators {
|
||||
[key: string]: (...args: unknown[]) => void
|
||||
}
|
||||
|
||||
interface GnoStepperProps<V = StepperFormValues> {
|
||||
initialValues?: Partial<V>
|
||||
onSubmit: (formValues: V) => void
|
||||
steps: string[]
|
||||
buttonLabels?: string[]
|
||||
children: React.ReactNode
|
||||
disabledWhenValidating?: boolean
|
||||
mutators?: Mutators
|
||||
testId?: string
|
||||
}
|
||||
|
||||
function GnoStepper<V>(props: GnoStepperProps<V>): 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
|
||||
|
|
|
@ -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<AddressBookEntryProps>
|
||||
|
||||
export const makeAddressBookEntry = Record<AddressBookEntryProps>({
|
||||
address: '',
|
||||
name: '',
|
||||
|
|
|
@ -121,5 +121,7 @@ export default handleActions(
|
|||
})
|
||||
},
|
||||
},
|
||||
Map(),
|
||||
Map({
|
||||
addressBook: Map({}),
|
||||
}),
|
||||
)
|
||||
|
|
|
@ -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<string, AddressBookEntryProps[]>
|
||||
}
|
||||
|
||||
export interface AddressBookMap extends Map<string> {
|
||||
toJS(): AddressBookMapSerialized
|
||||
get(key: string): List<AddressBookEntryRecord>
|
||||
}
|
||||
|
||||
export interface AddressBookReducerMap extends Map<string, any> {
|
||||
toJS(): AddressBookReducerStateSerialized
|
||||
get<K extends keyof AddressBookReducerState>(key: K): AddressBookReducerState[K]
|
||||
}
|
|
@ -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)
|
||||
|
|
|
@ -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<any> => {
|
||||
export const getGnosisSafeInstanceAt = async (safeAddress: string): Promise<GnosisSafe> => {
|
||||
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<boolean> => {
|
|||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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<number> => {
|
||||
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<number> => {
|
||||
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,
|
||||
|
|
|
@ -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<NonPayableTransactionObject<void>> => {
|
||||
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<boolean> => {
|
||||
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,
|
||||
|
|
|
@ -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<void> => {
|
||||
const url = buildTxServiceUrl(safeInstance.options.address)
|
||||
const body = await calculateBodyFrom(
|
||||
safeInstance,
|
||||
to,
|
||||
|
|
|
@ -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)
|
|
@ -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<string> }): Promise<string> =>
|
||||
gnosisSafeInstance.VERSION()
|
||||
export const getCurrentSafeVersion = (gnosisSafeInstance: GnosisSafe): Promise<string> =>
|
||||
gnosisSafeInstance.methods.VERSION().call()
|
||||
|
||||
export const enabledFeatures = (version: string): Array<string> =>
|
||||
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<string> },
|
||||
gnosisSafeInstance: GnosisSafe,
|
||||
lastSafeVersion: string,
|
||||
): Promise<SafeVersionInfo> => {
|
||||
if (!gnosisSafeInstance || !lastSafeVersion) {
|
||||
|
|
|
@ -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)
|
||||
})
|
|
@ -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<void> => {
|
||||
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
|
||||
}
|
||||
|
|
|
@ -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<Record<string, string>> => {
|
||||
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<string, string>
|
||||
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 (
|
||||
<>
|
||||
<Block margin="md">
|
||||
|
@ -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 => (
|
||||
<>
|
||||
<OpenPaper controls={controls}>
|
||||
<DetailsForm errors={errors} form={form} />
|
||||
|
|
|
@ -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<ILayout> = ({ network, onLoadSafeSubmit, provider, userAddress }) => {
|
||||
const steps = getSteps()
|
||||
const initialValues = {}
|
||||
|
||||
return (
|
||||
<>
|
||||
{provider ? (
|
||||
<Block>
|
||||
<Row align="center">
|
||||
<IconButton disableRipple onClick={back} style={iconStyle}>
|
||||
<ChevronLeft />
|
||||
</IconButton>
|
||||
<Heading tag="h2">Load existing Safe</Heading>
|
||||
</Row>
|
||||
<Stepper
|
||||
buttonLabels={buttonLabels}
|
||||
initialValues={initialValues}
|
||||
mutators={formMutators}
|
||||
onSubmit={onLoadSafeSubmit}
|
||||
steps={steps}
|
||||
testId="load-safe-form"
|
||||
>
|
||||
<StepperPage validate={safeFieldsValidation}>{DetailsForm}</StepperPage>
|
||||
<StepperPage network={network}>{OwnerList}</StepperPage>
|
||||
<StepperPage network={network} userAddress={userAddress}>
|
||||
{ReviewInformation}
|
||||
</StepperPage>
|
||||
</Stepper>
|
||||
</Block>
|
||||
) : (
|
||||
<div>No account detected</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
const Layout = ({ network, onLoadSafeSubmit, provider, userAddress }: LayoutProps): React.ReactElement => (
|
||||
<>
|
||||
{provider ? (
|
||||
<Block>
|
||||
<Row align="center">
|
||||
<IconButton disableRipple onClick={back} style={iconStyle}>
|
||||
<ChevronLeft />
|
||||
</IconButton>
|
||||
<Heading tag="h2">Load existing Safe</Heading>
|
||||
</Row>
|
||||
<Stepper<LoadFormValues>
|
||||
buttonLabels={buttonLabels}
|
||||
mutators={formMutators}
|
||||
onSubmit={onLoadSafeSubmit}
|
||||
steps={steps}
|
||||
testId="load-safe-form"
|
||||
>
|
||||
<StepperPage validate={safeFieldsValidation} component={DetailsForm} />
|
||||
<StepperPage network={network} component={OwnerList} />
|
||||
<StepperPage network={network} userAddress={userAddress} component={ReviewInformation} />
|
||||
</Stepper>
|
||||
</Block>
|
||||
) : (
|
||||
<div>No account detected</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
|
||||
export default Layout
|
||||
|
|
|
@ -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 (
|
||||
<>
|
||||
|
|
|
@ -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<string, string>, 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<any> {
|
||||
render() {
|
||||
const { classes, userAddress, values } = this.props
|
||||
|
||||
const isOwner = checkUserAddressOwner(values, userAddress)
|
||||
const owners = getAccountsFrom(values)
|
||||
const safeAddress = values[FIELD_LOAD_ADDRESS]
|
||||
|
||||
return (
|
||||
<>
|
||||
<Row className={classes.root}>
|
||||
<Col className={classes.detailsColumn} layout="column" xs={4}>
|
||||
<Block className={classes.details}>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="primary" noMargin size="lg" data-testid="load-safe-step-three">
|
||||
Review details
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="disabled" noMargin size="sm">
|
||||
Name of the Safe
|
||||
</Paragraph>
|
||||
<Paragraph
|
||||
className={classes.name}
|
||||
color="primary"
|
||||
noMargin
|
||||
size="lg"
|
||||
weight="bolder"
|
||||
data-testid="load-form-review-safe-name"
|
||||
>
|
||||
{values[FIELD_LOAD_NAME]}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="disabled" noMargin size="sm">
|
||||
Safe address
|
||||
</Paragraph>
|
||||
<Row className={classes.container}>
|
||||
<Identicon address={safeAddress} diameter={32} />
|
||||
<Paragraph className={classes.address} color="disabled" noMargin size="md">
|
||||
{shortVersionOf(safeAddress, 4)}
|
||||
</Paragraph>
|
||||
<CopyBtn content={safeAddress} />
|
||||
<EtherscanBtn type="address" value={safeAddress} />
|
||||
</Row>
|
||||
</Block>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="disabled" noMargin size="sm">
|
||||
Connected wallet client is owner?
|
||||
</Paragraph>
|
||||
<Paragraph className={classes.name} color="primary" noMargin size="lg" weight="bolder">
|
||||
{isOwner ? 'Yes' : 'No (read-only)'}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="disabled" noMargin size="sm">
|
||||
Any transaction requires the confirmation of:
|
||||
</Paragraph>
|
||||
<Paragraph className={classes.name} color="primary" noMargin size="lg" weight="bolder">
|
||||
{`${values[THRESHOLD]} out of ${getNumOwnersFrom(values)} owners`}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
</Block>
|
||||
</Col>
|
||||
<Col className={classes.ownersColumn} layout="column" xs={8}>
|
||||
<TableContainer>
|
||||
<Block className={classes.owners}>
|
||||
<Paragraph color="primary" noMargin size="lg">
|
||||
{`${getNumOwnersFrom(values)} Safe owners`}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Hairline />
|
||||
{owners.map((address, index) => (
|
||||
<>
|
||||
<Row className={classes.owner}>
|
||||
<Col align="center" xs={1}>
|
||||
<Identicon address={address} diameter={32} />
|
||||
</Col>
|
||||
<Col xs={11}>
|
||||
<Block className={classNames(classes.name, classes.userName)}>
|
||||
<Paragraph noMargin size="lg" data-testid="load-safe-review-owner-name">
|
||||
{values[getOwnerNameBy(index)]}
|
||||
</Paragraph>
|
||||
<Block className={classes.user} justify="center">
|
||||
<Paragraph color="disabled" noMargin size="md">
|
||||
{address}
|
||||
</Paragraph>
|
||||
<CopyBtn content={address} />
|
||||
<EtherscanBtn type="address" value={address} />
|
||||
</Block>
|
||||
</Block>
|
||||
</Col>
|
||||
</Row>
|
||||
{index !== owners.length - 1 && <Hairline />}
|
||||
</>
|
||||
))}
|
||||
</TableContainer>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
)
|
||||
}
|
||||
interface Props {
|
||||
userAddress: string
|
||||
values: Record<string, string>
|
||||
}
|
||||
|
||||
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 (
|
||||
<>
|
||||
<Row className={classes.root}>
|
||||
<Col className={classes.detailsColumn} layout="column" xs={4}>
|
||||
<Block className={classes.details}>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="primary" noMargin size="lg" data-testid="load-safe-step-three">
|
||||
Review details
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="disabled" noMargin size="sm">
|
||||
Name of the Safe
|
||||
</Paragraph>
|
||||
<Paragraph
|
||||
className={classes.name}
|
||||
color="primary"
|
||||
noMargin
|
||||
size="lg"
|
||||
weight="bolder"
|
||||
data-testid="load-form-review-safe-name"
|
||||
>
|
||||
{values[FIELD_LOAD_NAME]}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="disabled" noMargin size="sm">
|
||||
Safe address
|
||||
</Paragraph>
|
||||
<Row className={classes.container}>
|
||||
<Identicon address={safeAddress} diameter={32} />
|
||||
<Paragraph className={classes.address} color="disabled" noMargin size="md">
|
||||
{shortVersionOf(safeAddress, 4)}
|
||||
</Paragraph>
|
||||
<CopyBtn content={safeAddress} />
|
||||
<EtherscanBtn type="address" value={safeAddress} />
|
||||
</Row>
|
||||
</Block>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="disabled" noMargin size="sm">
|
||||
Connected wallet client is owner?
|
||||
</Paragraph>
|
||||
<Paragraph className={classes.name} color="primary" noMargin size="lg" weight="bolder">
|
||||
{isOwner ? 'Yes' : 'No (read-only)'}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Block margin="lg">
|
||||
<Paragraph color="disabled" noMargin size="sm">
|
||||
Any transaction requires the confirmation of:
|
||||
</Paragraph>
|
||||
<Paragraph className={classes.name} color="primary" noMargin size="lg" weight="bolder">
|
||||
{`${values[THRESHOLD]} out of ${getNumOwnersFrom(values)} owners`}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
</Block>
|
||||
</Col>
|
||||
<Col className={classes.ownersColumn} layout="column" xs={8}>
|
||||
<TableContainer>
|
||||
<Block className={classes.owners}>
|
||||
<Paragraph color="primary" noMargin size="lg">
|
||||
{`${getNumOwnersFrom(values)} Safe owners`}
|
||||
</Paragraph>
|
||||
</Block>
|
||||
<Hairline />
|
||||
{owners.map((address, index) => (
|
||||
<>
|
||||
<Row className={classes.owner}>
|
||||
<Col align="center" xs={1}>
|
||||
<Identicon address={address} diameter={32} />
|
||||
</Col>
|
||||
<Col xs={11}>
|
||||
<Block className={classNames(classes.name, classes.userName)}>
|
||||
<Paragraph noMargin size="lg" data-testid="load-safe-review-owner-name">
|
||||
{values[getOwnerNameBy(index)]}
|
||||
</Paragraph>
|
||||
<Block className={classes.user} justify="center">
|
||||
<Paragraph color="disabled" noMargin size="md">
|
||||
{address}
|
||||
</Paragraph>
|
||||
<CopyBtn content={address} />
|
||||
<EtherscanBtn type="address" value={address} />
|
||||
</Block>
|
||||
</Block>
|
||||
</Col>
|
||||
</Row>
|
||||
{index !== owners.length - 1 && <Hairline />}
|
||||
</>
|
||||
))}
|
||||
</TableContainer>
|
||||
</Col>
|
||||
</Row>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const Review = ({ userAddress }: { userAddress: string }) => (
|
||||
controls: React.ReactNode,
|
||||
{ values }: { values: Record<string, string> },
|
||||
): React.ReactElement => (
|
||||
<>
|
||||
<OpenPaper controls={controls} padding={false}>
|
||||
<ReviewPage network={network} userAddress={userAddress} values={values} />
|
||||
<ReviewComponent userAddress={userAddress} values={values} />
|
||||
</OpenPaper>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -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,
|
||||
},
|
||||
})
|
|
@ -37,7 +37,7 @@ export const loadSafe = async (
|
|||
await addSafe(safeProps)
|
||||
}
|
||||
|
||||
interface ILoad {
|
||||
interface LoadProps {
|
||||
addSafe: Dispatch<any>
|
||||
network: string
|
||||
provider?: string
|
||||
|
@ -50,7 +50,7 @@ export interface LoadFormValues {
|
|||
threshold: string
|
||||
}
|
||||
|
||||
const Load: React.FC<ILoad> = ({ 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<ILoad> = ({ 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)
|
||||
|
|
|
@ -98,11 +98,9 @@ const Layout = (props) => {
|
|||
steps={steps}
|
||||
testId="create-safe-form"
|
||||
>
|
||||
<StepperPage>{SafeNameField}</StepperPage>
|
||||
<StepperPage>{SafeOwnersFields}</StepperPage>
|
||||
<StepperPage network={network} userAccount={userAccount}>
|
||||
{Review}
|
||||
</StepperPage>
|
||||
<StepperPage component={SafeNameField} />
|
||||
<StepperPage component={SafeOwnersFields} />
|
||||
<StepperPage network={network} userAccount={userAccount} component={Review} />
|
||||
</Stepper>
|
||||
</Block>
|
||||
) : (
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<List<{ address: string }>> => {
|
||||
addressBook: List<AddressBookEntryRecord>,
|
||||
): Promise<List<AddressBookEntryRecord>> => {
|
||||
const abFlags = await Promise.all(
|
||||
addressBook.map(
|
||||
async ({ address }: { address: string }): Promise<boolean> => {
|
||||
async ({ address }: AddressBookEntryRecord): Promise<boolean> => {
|
||||
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<string>('')
|
||||
const [inputTouched, setInputTouched] = useState(false)
|
||||
const [blurred, setBlurred] = useState(pristine)
|
||||
const [adbkList, setADBKList] = useState<List<{ address: string }>>(List([]))
|
||||
const [adbkList, setADBKList] = useState<List<FilteredAddressBookEntry>>(List([]))
|
||||
|
||||
const [inputAddValue, setInputAddValue] = useState(recipientAddress)
|
||||
|
||||
|
@ -146,7 +152,7 @@ const AddressBookInput = ({
|
|||
<>
|
||||
<Autocomplete
|
||||
closeIcon={null}
|
||||
disableOpenOnFocus
|
||||
openOnFocus={false}
|
||||
filterOptions={(optionsArray, { inputValue }) =>
|
||||
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: '' }}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -87,18 +87,7 @@ const SendFunds = ({ initialValues, onClose, onNext, recipientAddress, selectedT
|
|||
</IconButton>
|
||||
</Row>
|
||||
<Hairline />
|
||||
<GnoForm
|
||||
formMutators={formMutators}
|
||||
initialValues={initialValues}
|
||||
onSubmit={handleSubmit}
|
||||
validation={(values) => {
|
||||
const selectedTokenRecord = tokens.find((token) => token.address === values?.token)
|
||||
|
||||
return {
|
||||
amount: maxValue(selectedTokenRecord?.balance)(values.amount),
|
||||
}
|
||||
}}
|
||||
>
|
||||
<GnoForm formMutators={formMutators} initialValues={initialValues} onSubmit={handleSubmit}>
|
||||
{(...args) => {
|
||||
const formState = args[2]
|
||||
const mutators = args[3]
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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')
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}`)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<TxServiceModel> => {
|
||||
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<string> => {
|
||||
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<boolean> => {
|
||||
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
|
||||
|
|
|
@ -12,7 +12,7 @@ export type SafeRecordProps = {
|
|||
address: string
|
||||
threshold: number
|
||||
ethBalance: string
|
||||
owners: List<{ name: string; address: string }>
|
||||
owners: List<SafeOwner>
|
||||
modules: ModulePair[] | null
|
||||
activeTokens: Set<string>
|
||||
activeAssets: Set<string>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<string, any>
|
||||
[CURRENCY_VALUES_KEY]: Map<string, CurrencyRateValueRecord>
|
||||
[COOKIES_REDUCER_ID]: Map<string, any>
|
||||
[ADDRESS_BOOK_REDUCER_ID]: Map<string, any>
|
||||
[ADDRESS_BOOK_REDUCER_ID]: AddressBookReducerMap
|
||||
[CURRENT_SESSION_REDUCER_ID]: Map<string, any>
|
||||
router: RouterState
|
||||
}>
|
||||
|
|
|
@ -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)
|
||||
})
|
||||
})
|
||||
|
|
|
@ -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({
|
||||
|
|
|
@ -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)
|
||||
})
|
595
yarn.lock
595
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"
|
||||
|
|
Loading…
Reference in New Issue