WA-521 Refactor ethereum modules under logic folder

This commit is contained in:
apanizo 2018-08-13 18:35:55 +02:00
parent 933b93f5e1
commit be9bdd25c1
84 changed files with 299 additions and 401 deletions

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { fetchProvider } from '~/wallets/store/actions' import { fetchProvider } from '~/logic/wallets/store/actions'
export default { export default {
fetchProvider, fetchProvider,

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { providerNameSelector } from '~/wallets/store/selectors/index' import { providerNameSelector } from '~/logic/wallets/store/selectors'
export default createStructuredSelector({ export default createStructuredSelector({
provider: providerNameSelector, provider: providerNameSelector,

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { getWeb3 } from '~/wallets/getWeb3'
import { type FieldValidator } from 'final-form' import { type FieldValidator } from 'final-form'
import { getWeb3 } from '~/logic/wallets/getWeb3'
type Field = boolean | string | null | typeof undefined type Field = boolean | string | null | typeof undefined

View File

@ -0,0 +1,48 @@
// @flow
import { getWeb3 } from '~/logic/wallets/getWeb3'
import { getGnosisSafeContract, getCreateDailyLimitExtensionContract } from '~/logic/contracts/safeContracts'
import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit'
export const LIMIT_POSITION = 0
export const SPENT_TODAY_POS = 1
export const getDailyLimitModuleFrom = async (safeAddress: string) => {
const web3 = getWeb3()
const gnosisSafe = getGnosisSafeContract(web3).at(safeAddress)
const modules = await gnosisSafe.getModules()
const dailyAddress = modules[0]
const dailyLimitModule = getCreateDailyLimitExtensionContract(web3).at(dailyAddress)
if (await dailyLimitModule.manager.call() !== gnosisSafe.address) {
throw new Error('Using an extension of different safe')
}
return dailyLimitModule
}
export const getDailyLimitFrom = async (safeAddress: string, tokenAddress: number): Promise<DailyLimitProps> => {
const web3 = getWeb3()
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)
const dailyLimitEth = await dailyLimitModule.dailyLimits(tokenAddress)
const limit = web3.fromWei(dailyLimitEth[LIMIT_POSITION].valueOf(), 'ether').toString()
const spentToday = web3.fromWei(dailyLimitEth[SPENT_TODAY_POS].valueOf(), 'ether').toString()
return { value: Number(limit), spentToday: Number(spentToday) }
}
export const getDailyLimitAddress = async (safeAddress: string) => {
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)
return dailyLimitModule.address
}
export const getEditDailyLimitData = async (safeAddress: string, token: number, dailyLimit: number) => {
const web3 = getWeb3()
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)
const dailyLimitInWei = web3.toWei(dailyLimit, 'ether')
return dailyLimitModule.contract.changeDailyLimit.getData(token, dailyLimitInWei)
}

View File

@ -1,13 +1,13 @@
// @flow // @flow
import contract from 'truffle-contract' import contract from 'truffle-contract'
import { ensureOnce } from '~/utils/singleton' import { ensureOnce } from '~/utils/singleton'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import GnosisSafeSol from '#/GnosisSafeTeamEdition.json' import GnosisSafeSol from '#/GnosisSafeTeamEdition.json'
import ProxyFactorySol from '#/ProxyFactory.json' import ProxyFactorySol from '#/ProxyFactory.json'
import CreateAndAddModules from '#/CreateAndAddModules.json' import CreateAndAddModules from '#/CreateAndAddModules.json'
import DailyLimitModule from '#/DailyLimitModule.json' import DailyLimitModule from '#/DailyLimitModule.json'
import { calculateGasOf, calculateGasPrice, EMPTY_DATA } from '~/wallets/ethTransactions' import { calculateGasOf, calculateGasPrice, EMPTY_DATA } from '~/logic/wallets/ethTransactions'
let proxyFactoryMaster let proxyFactoryMaster
let createAndAddModuleMaster let createAndAddModuleMaster

View File

@ -1,7 +1,8 @@
// @flow // @flow
import { getSafeEthereumInstance } from '~/wallets/createTransactions' import { calculateGasOf, checkReceiptStatus, calculateGasPrice } from '~/logic/wallets/ethTransactions'
import { calculateGasOf, checkReceiptStatus, calculateGasPrice } from '~/wallets/ethTransactions' import { type Operation, submitOperation } from '~/logic/safe/safeTxHistory'
import { type Operation, submitOperation } from '~/wallets/safeTxHistory' import { getDailyLimitModuleFrom } from '~/logic/contracts/dailyLimitContracts'
import { getSafeEthereumInstance } from '~/logic/safe/safeFrontendOperations'
export const approveTransaction = async ( export const approveTransaction = async (
safeAddress: string, safeAddress: string,
@ -52,3 +53,25 @@ export const executeTransaction = async (
return txHash return txHash
} }
export const executeDailyLimit = async (
safeAddress: string,
to: string,
valueInWei: number,
sender: string,
) => {
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)
const dailyLimitData = dailyLimitModule.contract.executeDailyLimit.getData(0, to, valueInWei)
const gas = await calculateGasOf(dailyLimitData, sender, dailyLimitModule.address)
const gasPrice = await calculateGasPrice()
const txHash = await dailyLimitModule.executeDailyLimit(0, to, valueInWei, { from: sender, gas, gasPrice })
checkReceiptStatus(txHash.tx)
const nonce = Date.now()
const operation = 0 // CALL for all currencies
const data = '' // empty for ETH
await submitOperation(safeAddress, to, valueInWei, data, operation, nonce, txHash, sender, 'execution')
return txHash
}

View File

@ -0,0 +1,81 @@
// @flow
import { type Transaction } from '~/routes/safe/store/model/transaction'
import { executeDailyLimit, executeTransaction, approveTransaction } from '~/logic/safe/safeBlockchainOperations'
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
import { getWeb3 } from '~/logic/wallets/getWeb3'
import { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/WithdrawForm'
import { type Safe } from '~/routes/safe/store/model/safe'
import { getGnosisSafeContract } from '~/logic/contracts/safeContracts'
export const TX_NAME_PARAM = 'txName'
export const TX_DESTINATION_PARAM = 'txDestination'
export const TX_VALUE_PARAM = 'txValue'
export const EXECUTED_CONFIRMATION_HASH = 'EXECUTED'
const hasOneOwner = (safe: Safe) => {
const owners = safe.get('owners')
if (!owners) {
throw new Error('Received a Safe without owners when creating a tx')
}
return owners.count() === 1
}
export const getSafeEthereumInstance = async (safeAddress: string) => {
const web3 = getWeb3()
const GnosisSafe = await getGnosisSafeContract(web3)
return GnosisSafe.at(safeAddress)
}
export const createTransaction = async (
safe: Safe,
name: string,
to: string,
value: number,
nonce: number,
sender: string,
data: string = EMPTY_DATA,
) => {
const web3 = getWeb3()
const safeAddress = safe.get('address')
const threshold = safe.get('threshold')
const valueInWei = web3.toWei(value, 'ether')
const CALL = 0
const isExecution = hasOneOwner(safe) || threshold === 1
return isExecution
? executeTransaction(safeAddress, to, valueInWei, data, CALL, nonce, sender)
: approveTransaction(safeAddress, to, valueInWei, data, CALL, nonce, sender)
}
export const processTransaction = async (
safeAddress: string,
tx: Transaction,
alreadyConfirmed: number,
sender: string,
threshold: number,
) => {
const web3 = getWeb3()
const nonce = tx.get('nonce')
const valueInWei = web3.toWei(tx.get('value'), 'ether')
const to = tx.get('destination')
const data = tx.get('data')
const CALL = 0
const thresholdReached = threshold === alreadyConfirmed + 1
return thresholdReached
? executeTransaction(safeAddress, to, valueInWei, data, CALL, nonce, sender)
: approveTransaction(safeAddress, to, valueInWei, data, CALL, nonce, sender)
}
export const withdraw = async (values: Object, safe: Safe, sender: string): Promise<void> => {
const safeAddress = safe.get('address')
const destination = values[DESTINATION_PARAM]
const valueInEth = values[VALUE_PARAM]
const valueInWei = getWeb3().toWei(valueInEth, 'ether')
// TODO write subject `Withdraw movement of ${valueInEth}`
return executeDailyLimit(safeAddress, destination, valueInWei, sender)
}

View File

@ -1,9 +1,9 @@
// @flow // @flow
import { getSafeEthereumInstance } from '~/wallets/createTransactions' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { getWeb3 } from '~/wallets/getWeb3'
import { getTxServiceUriFrom, getTxServiceHost } from '~/config' import { getTxServiceUriFrom, getTxServiceHost } from '~/config'
import { getSafeEthereumInstance } from '~/logic/safe/safeFrontendOperations'
export type TxServiceType = 'confirmation' | 'execution' export type TxServiceType = 'confirmation' | 'execution' | 'initialised'
export type Operation = 0 | 1 | 2 export type Operation = 0 | 1 | 2
const calculateBodyFrom = async ( const calculateBodyFrom = async (
@ -32,6 +32,7 @@ const calculateBodyFrom = async (
type, type,
}) })
} }
export const buildTxServiceUrlFrom = (safeAddress: string) => { export const buildTxServiceUrlFrom = (safeAddress: string) => {
const host = getTxServiceHost() const host = getTxServiceHost()
const address = getWeb3().toChecksumAddress(safeAddress) const address = getWeb3().toChecksumAddress(safeAddress)

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { BigNumber } from 'bignumber.js' import { BigNumber } from 'bignumber.js'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { enhancedFetch } from '~/utils/fetch' import { enhancedFetch } from '~/utils/fetch'

View File

@ -1,7 +1,7 @@
// @flow // @flow
import { BigNumber } from 'bignumber.js' import { BigNumber } from 'bignumber.js'
import Web3 from 'web3' import Web3 from 'web3'
import type { ProviderProps } from '~/wallets/store/model/provider' import type { ProviderProps } from '~/logic/wallets/store/model/provider'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
let web3 let web3

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createAction } from 'redux-actions' import { createAction } from 'redux-actions'
import { type Provider } from '~/wallets/store/model/provider' import { type Provider } from '~/logic/wallets/store/model/provider'
export const ADD_PROVIDER = 'ADD_PROVIDER' export const ADD_PROVIDER = 'ADD_PROVIDER'

View File

@ -1,8 +1,8 @@
// @flow // @flow
import type { Dispatch as ReduxDispatch } from 'redux' import type { Dispatch as ReduxDispatch } from 'redux'
import { getProviderInfo } from '~/wallets/getWeb3' import { getProviderInfo } from '~/logic/wallets/getWeb3'
import type { ProviderProps } from '~/wallets/store/model/provider' import type { ProviderProps } from '~/logic/wallets/store/model/provider'
import { makeProvider } from '~/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider'
import addProvider from './addProvider' import addProvider from './addProvider'
export const processProviderResponse = (dispatch: ReduxDispatch<*>, response: ProviderProps) => { export const processProviderResponse = (dispatch: ReduxDispatch<*>, response: ProviderProps) => {

View File

@ -1,7 +1,7 @@
// @flow // @flow
import { handleActions, type ActionType } from 'redux-actions' import { handleActions, type ActionType } from 'redux-actions'
import { makeProvider, type Provider } from '~/wallets/store/model/provider' import { makeProvider, type Provider } from '~/logic/wallets/store/model/provider'
import addProvider, { ADD_PROVIDER } from '~/wallets/store/actions/addProvider' import addProvider, { ADD_PROVIDER } from '~/logic/wallets/store/actions/addProvider'
export const PROVIDER_REDUCER_ID = 'providers' export const PROVIDER_REDUCER_ID = 'providers'

View File

@ -1,7 +1,7 @@
// @flow // @flow
import { createSelector } from 'reselect' import { createSelector } from 'reselect'
import type { Provider } from '~/wallets/store/model/provider' import type { Provider } from '~/logic/wallets/store/model/provider'
import { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider' import { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider'
const providerSelector = (state: any): Provider => state[PROVIDER_REDUCER_ID] const providerSelector = (state: any): Provider => state[PROVIDER_REDUCER_ID]

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider' import { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider'
import { userAccountSelector } from '../selectors' import { userAccountSelector } from '../selectors'
import { ProviderFactory } from './builder/index.builder' import { ProviderFactory } from './builder/index.builder'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import type { Provider } from '~/wallets/store/model/provider' import type { Provider } from '~/logic/wallets/store/model/provider'
import { makeProvider } from '~/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider'
class ProviderBuilder { class ProviderBuilder {
provider: Provider provider: Provider

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider' import { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider'
import { providerNameSelector } from '../selectors' import { providerNameSelector } from '../selectors'
import { ProviderFactory } from './builder/index.builder' import { ProviderFactory } from './builder/index.builder'

View File

@ -1,9 +1,9 @@
// @flow // @flow
import { combineReducers, createStore, applyMiddleware, compose } from 'redux' import { combineReducers, createStore, applyMiddleware, compose } from 'redux'
import thunk from 'redux-thunk' import thunk from 'redux-thunk'
import providerReducer, { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider' import providerReducer, { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider'
import type { ProviderProps } from '~/wallets/store/model/provider' import type { ProviderProps } from '~/logic/wallets/store/model/provider'
import { makeProvider } from '~/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider'
import { processProviderResponse } from '../actions/fetchProvider' import { processProviderResponse } from '../actions/fetchProvider'
const providerReducerTests = () => { const providerReducerTests = () => {

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { BigNumber } from 'bignumber.js' import { BigNumber } from 'bignumber.js'
export const toNative = async (amt: string | number | BigNumber, decimal: number): Promise<BigNumber> => { export const toNative = async (amt: string | number | BigNumber, decimal: number): Promise<BigNumber> => {

View File

@ -4,7 +4,7 @@ import { State, Store } from '@sambego/storybook-state'
import * as React from 'react' import * as React from 'react'
import styles from '~/components/layout/PageFrame/index.scss' import styles from '~/components/layout/PageFrame/index.scss'
import { getAccountsFrom, getThresholdFrom } from '~/routes/open/utils/safeDataExtractor' import { getAccountsFrom, getThresholdFrom } from '~/routes/open/utils/safeDataExtractor'
import { getProviderInfo } from '~/wallets/getWeb3' import { getProviderInfo } from '~/logic/wallets/getWeb3'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import Component from './Layout' import Component from './Layout'

View File

@ -4,7 +4,7 @@ import * as React from 'react'
import * as TestUtils from 'react-dom/test-utils' import * as TestUtils from 'react-dom/test-utils'
import Layout from '~/routes/open/components/Layout' import Layout from '~/routes/open/components/Layout'
import { FIELD_CONFIRMATIONS, FIELD_OWNERS } from '~/routes/open/components/fields' import { FIELD_CONFIRMATIONS, FIELD_OWNERS } from '~/routes/open/components/fields'
import { getProviderInfo } from '~/wallets/getWeb3' import { getProviderInfo } from '~/logic/wallets/getWeb3'
import Wrapper from '~/test/utils/Wrapper' import Wrapper from '~/test/utils/Wrapper'
import { CONFIRMATIONS_ERROR } from '~/routes/open/components/SafeForm' import { CONFIRMATIONS_ERROR } from '~/routes/open/components/SafeForm'

View File

@ -5,7 +5,7 @@ import * as TestUtils from 'react-dom/test-utils'
import GnoForm from '~/components/forms/GnoForm' import GnoForm from '~/components/forms/GnoForm'
import { FIELD_OWNERS } from '~/routes/open/components/fields' import { FIELD_OWNERS } from '~/routes/open/components/fields'
import { getAccountsFrom } from '~/routes/open/utils/safeDataExtractor' import { getAccountsFrom } from '~/routes/open/utils/safeDataExtractor'
import { getProviderInfo } from '~/wallets/getWeb3' import { getProviderInfo } from '~/logic/wallets/getWeb3'
import Wrapper from '~/test/utils/Wrapper' import Wrapper from '~/test/utils/Wrapper'
import { ADDRESS_REPEATED_ERROR } from '~/components/forms/validator' import { ADDRESS_REPEATED_ERROR } from '~/components/forms/validator'
import Owners from './index' import Owners from './index'

View File

@ -4,9 +4,9 @@ import { connect } from 'react-redux'
import Page from '~/components/layout/Page' import Page from '~/components/layout/Page'
import { getAccountsFrom, getThresholdFrom, getNamesFrom, getSafeNameFrom, getDailyLimitFrom } from '~/routes/open/utils/safeDataExtractor' import { getAccountsFrom, getThresholdFrom, getNamesFrom, getSafeNameFrom, getDailyLimitFrom } from '~/routes/open/utils/safeDataExtractor'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { getGnosisSafeContract, deploySafeContract, initContracts } from '~/wallets/safeContracts' import { getGnosisSafeContract, deploySafeContract, initContracts } from '~/logic/contracts/safeContracts'
import { checkReceiptStatus } from '~/wallets/ethTransactions' import { checkReceiptStatus } from '~/logic/wallets/ethTransactions'
import selector from './selector' import selector from './selector'
import actions, { type Actions, type AddSafe } from './actions' import actions, { type Actions, type AddSafe } from './actions'
import Layout from '../components/Layout' import Layout from '../components/Layout'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { providerNameSelector, userAccountSelector } from '~/wallets/store/selectors/index' import { providerNameSelector, userAccountSelector } from '~/logic/wallets/store/selectors'
export default createStructuredSelector({ export default createStructuredSelector({
provider: providerNameSelector, provider: providerNameSelector,

View File

@ -5,8 +5,8 @@ import Stepper from '~/components/Stepper'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { type Owner, makeOwner } from '~/routes/safe/store/model/owner' import { type Owner, makeOwner } from '~/routes/safe/store/model/owner'
import { getSafeEthereumInstance, createTransaction } from '~/wallets/createTransactions'
import { setOwners } from '~/utils/localStorage' import { setOwners } from '~/utils/localStorage'
import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations'
import AddOwnerForm, { NAME_PARAM, OWNER_ADDRESS_PARAM, INCREASE_PARAM } from './AddOwnerForm' import AddOwnerForm, { NAME_PARAM, OWNER_ADDRESS_PARAM, INCREASE_PARAM } from './AddOwnerForm'
import Review from './Review' import Review from './Review'
import selector, { type SelectorProps } from './selector' import selector, { type SelectorProps } from './selector'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { userAccountSelector } from '~/wallets/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors'
export type SelectorProps = { export type SelectorProps = {
userAddress: userAccountSelector, userAddress: userAccountSelector,

View File

@ -2,9 +2,9 @@
import * as React from 'react' import * as React from 'react'
import Stepper from '~/components/Stepper' import Stepper from '~/components/Stepper'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { createTransaction } from '~/wallets/createTransactions'
import { getEditDailyLimitData, getDailyLimitAddress } from '~/routes/safe/component/Withdraw/withdraw'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { createTransaction } from '~/logic/safe/safeFrontendOperations'
import { getEditDailyLimitData, getDailyLimitAddress } from '~/logic/contracts/dailyLimitContracts'
import EditDailyLimitForm, { EDIT_DAILY_LIMIT_PARAM } from './EditDailyLimitForm' import EditDailyLimitForm, { EDIT_DAILY_LIMIT_PARAM } from './EditDailyLimitForm'
import selector, { type SelectorProps } from './selector' import selector, { type SelectorProps } from './selector'
import actions, { type Actions } from './actions' import actions, { type Actions } from './actions'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { userAccountSelector } from '~/wallets/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors'
export type SelectorProps = { export type SelectorProps = {
userAddress: userAccountSelector, userAddress: userAccountSelector,

View File

@ -3,7 +3,7 @@ import * as React from 'react'
import Stepper from '~/components/Stepper' import Stepper from '~/components/Stepper'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { getSafeEthereumInstance, createTransaction } from '~/wallets/createTransactions' import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations'
import RemoveOwnerForm, { DECREASE_PARAM } from './RemoveOwnerForm' import RemoveOwnerForm, { DECREASE_PARAM } from './RemoveOwnerForm'
import Review from './Review' import Review from './Review'
import selector, { type SelectorProps } from './selector' import selector, { type SelectorProps } from './selector'

View File

@ -1,7 +1,7 @@
// @flow // @flow
import { List } from 'immutable' import { List } from 'immutable'
import { createStructuredSelector, createSelector } from 'reselect' import { createStructuredSelector, createSelector } from 'reselect'
import { userAccountSelector } from '~/wallets/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors'
import { type Transaction } from '~/routes/safe/store/model/transaction' import { type Transaction } from '~/routes/safe/store/model/transaction'
import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index' import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index'

View File

@ -17,7 +17,7 @@ import ExpandLess from '@material-ui/icons/ExpandLess'
import ExpandMore from '@material-ui/icons/ExpandMore' import ExpandMore from '@material-ui/icons/ExpandMore'
import { type OwnerProps } from '~/routes/safe/store/model/owner' import { type OwnerProps } from '~/routes/safe/store/model/owner'
import { type WithStyles } from '~/theme/mui' import { type WithStyles } from '~/theme/mui'
import { sameAddress } from '~/wallets/ethAddresses' import { sameAddress } from '~/logic/wallets/ethAddresses'
const styles = { const styles = {
nested: { nested: {

View File

@ -7,10 +7,10 @@ import { sleep } from '~/utils/timer'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { getStandardTokenContract } from '~/routes/tokens/store/actions/fetchTokens' import { getStandardTokenContract } from '~/routes/tokens/store/actions/fetchTokens'
import { type Token } from '~/routes/tokens/store/model/token' import { type Token } from '~/routes/tokens/store/model/token'
import { createTransaction } from '~/wallets/createTransactions'
import { EMPTY_DATA } from '~/wallets/ethTransactions'
import { toNative } from '~/wallets/tokens'
import { isEther } from '~/utils/tokens' import { isEther } from '~/utils/tokens'
import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
import { toNative } from '~/logic/wallets/tokens'
import { createTransaction } from '~/logic/safe/safeFrontendOperations'
import actions, { type Actions } from './actions' import actions, { type Actions } from './actions'
import selector, { type SelectorProps } from './selector' import selector, { type SelectorProps } from './selector'
import SendTokenForm, { TKN_DESTINATION_PARAM, TKN_VALUE_PARAM } from './SendTokenForm' import SendTokenForm, { TKN_DESTINATION_PARAM, TKN_VALUE_PARAM } from './SendTokenForm'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { userAccountSelector } from '~/wallets/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors'
export type SelectorProps = { export type SelectorProps = {
userAddress: userAccountSelector, userAddress: userAccountSelector,

View File

@ -2,7 +2,7 @@
import * as React from 'react' import * as React from 'react'
import Stepper from '~/components/Stepper' import Stepper from '~/components/Stepper'
import { connect } from 'react-redux' import { connect } from 'react-redux'
import { getSafeEthereumInstance, createTransaction } from '~/wallets/createTransactions' import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import ThresholdForm, { THRESHOLD_PARAM } from './ThresholdForm' import ThresholdForm, { THRESHOLD_PARAM } from './ThresholdForm'
import selector, { type SelectorProps } from './selector' import selector, { type SelectorProps } from './selector'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { userAccountSelector } from '~/wallets/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors'
export type SelectorProps = { export type SelectorProps = {
userAddress: userAccountSelector, userAddress: userAccountSelector,

View File

@ -19,7 +19,7 @@ import Collapsed from '~/routes/safe/component/Transactions/Collapsed'
import { type Transaction } from '~/routes/safe/store/model/transaction' import { type Transaction } from '~/routes/safe/store/model/transaction'
import Hairline from '~/components/layout/Hairline/index' import Hairline from '~/components/layout/Hairline/index'
import Button from '~/components/layout/Button' import Button from '~/components/layout/Button'
import { sameAddress } from '~/wallets/ethAddresses' import { sameAddress } from '~/logic/wallets/ethAddresses'
import { type Confirmation } from '~/routes/safe/store/model/confirmation' import { type Confirmation } from '~/routes/safe/store/model/confirmation'
import selector, { type SelectorProps } from './selector' import selector, { type SelectorProps } from './selector'

View File

@ -1,7 +1,7 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index' import { confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index'
import { userAccountSelector } from '~/wallets/store/selectors' import { userAccountSelector } from '~/logic/wallets/store/selectors'
import { type Transaction } from '~/routes/safe/store/model/transaction' import { type Transaction } from '~/routes/safe/store/model/transaction'
import { type GlobalState } from '~/store' import { type GlobalState } from '~/store'
import { type Confirmation } from '~/routes/safe/store/model/confirmation' import { type Confirmation } from '~/routes/safe/store/model/confirmation'

View File

@ -4,7 +4,9 @@ import { connect } from 'react-redux'
import { type Transaction } from '~/routes/safe/store/model/transaction' import { type Transaction } from '~/routes/safe/store/model/transaction'
import NoTransactions from '~/routes/safe/component/Transactions/NoTransactions' import NoTransactions from '~/routes/safe/component/Transactions/NoTransactions'
import GnoTransaction from '~/routes/safe/component/Transactions/Transaction' import GnoTransaction from '~/routes/safe/component/Transactions/Transaction'
import { processTransaction } from './processTransactions' import { sameAddress } from '~/logic/wallets/ethAddresses'
import { type Confirmation } from '~/routes/safe/store/model/confirmation'
import { processTransaction } from '~/logic/safe/safeFrontendOperations'
import selector, { type SelectorProps } from './selector' import selector, { type SelectorProps } from './selector'
import actions, { type Actions } from './actions' import actions, { type Actions } from './actions'
@ -17,10 +19,22 @@ type Props = SelectorProps & Actions & {
class Transactions extends React.Component<Props, {}> { class Transactions extends React.Component<Props, {}> {
onProcessTx = async (tx: Transaction, alreadyConfirmed: number) => { onProcessTx = async (tx: Transaction, alreadyConfirmed: number) => {
const { const {
fetchTransactions, safeAddress, userAddress, fetchTransactions, safeAddress, userAddress, threshold,
} = this.props } = this.props
await processTransaction(safeAddress, tx, alreadyConfirmed, userAddress) const confirmations = tx.get('confirmations')
const userHasAlreadyConfirmed = confirmations.filter((confirmation: Confirmation) => {
const ownerAddress = confirmation.get('owner').get('address')
const samePerson = sameAddress(ownerAddress, userAddress)
return samePerson && confirmation.get('type') === 'confirmed'
}).count() > 0
if (userHasAlreadyConfirmed) {
throw new Error('Owner has already confirmed this transaction')
}
await processTransaction(safeAddress, tx, alreadyConfirmed, userAddress, threshold)
fetchTransactions() fetchTransactions()
} }

View File

@ -1,146 +0,0 @@
// @flow
import { List } from 'immutable'
import { type Owner } from '~/routes/safe/store/model/owner'
import { load, TX_KEY } from '~/utils/localStorage'
import { type Confirmation, makeConfirmation } from '~/routes/safe/store/model/confirmation'
import { makeTransaction, type Transaction, type TransactionProps } from '~/routes/safe/store/model/transaction'
import { getGnosisSafeContract } from '~/wallets/safeContracts'
import { getWeb3 } from '~/wallets/getWeb3'
import { sameAddress } from '~/wallets/ethAddresses'
import { EXECUTED_CONFIRMATION_HASH } from '~/wallets/createTransactions'
import { checkReceiptStatus, calculateGasOf, calculateGasPrice } from '~/wallets/ethTransactions'
export const updateTransaction = (
name: string,
nonce: number,
destination: string,
value: number,
creator: string,
confirmations: List<Confirmation>,
tx: string,
safeAddress: string,
safeThreshold: number,
data: string,
) => {
const transaction: Transaction = makeTransaction({
name, nonce, value, confirmations, destination, threshold: safeThreshold, tx, data,
})
const safeTransactions = load(TX_KEY) || {}
const transactions = safeTransactions[safeAddress]
const txsRecord = transactions ? List(transactions) : List([])
const index = txsRecord.findIndex((trans: TransactionProps) => trans.nonce === nonce)
safeTransactions[safeAddress] = txsRecord.remove(index).push(transaction)
localStorage.setItem(TX_KEY, JSON.stringify(safeTransactions))
}
const getOperation = () => 0
const execTransaction = async (
gnosisSafe: any,
destination: string,
txValue: number,
nonce: number,
executor: string,
data: string,
) => {
const CALL = getOperation()
const web3 = getWeb3()
const valueInWei = web3.toWei(txValue, 'ether')
const txData = await gnosisSafe.contract.execTransactionIfApproved.getData(destination, valueInWei, data, CALL, nonce)
const owners = await gnosisSafe.getOwners()
const gas = await calculateGasOf(txData, executor, gnosisSafe.address) + (17000 * owners.length)
const gasPrice = await calculateGasPrice()
return gnosisSafe
.execTransactionIfApproved(destination, valueInWei, data, CALL, nonce, { from: executor, gas, gasPrice })
}
const execConfirmation = async (
gnosisSafe: any,
txDestination: string,
txValue: number,
nonce: number,
executor: string,
data: string,
) => {
const CALL = getOperation()
const web3 = getWeb3()
const valueInWei = web3.toWei(txValue, 'ether')
const txData = await gnosisSafe.contract
.approveTransactionWithParameters.getData(txDestination, valueInWei, data, CALL, nonce)
const gas = await calculateGasOf(txData, executor, gnosisSafe.address)
const gasPrice = await calculateGasPrice()
return gnosisSafe
.approveTransactionWithParameters(txDestination, valueInWei, data, CALL, nonce, { from: executor, gas, gasPrice })
}
const updateConfirmations = (confirmations: List<Confirmation>, userAddress: string, txHash: string) =>
confirmations.map((confirmation: Confirmation) => {
const owner: Owner = confirmation.get('owner')
const samePerson = sameAddress(owner.get('address'), userAddress)
const status: boolean = samePerson ? true : confirmation.get('status')
const hash: string = samePerson ? txHash : confirmation.get('hash')
return makeConfirmation({ owner, status, hash })
})
export const processTransaction = async (
safeAddress: string,
tx: Transaction,
alreadyConfirmed: number,
userAddress: string,
) => {
const web3 = getWeb3()
const GnosisSafe = await getGnosisSafeContract(web3)
const gnosisSafe = GnosisSafe.at(safeAddress)
const confirmations = tx.get('confirmations')
const userHasAlreadyConfirmed = confirmations.filter((confirmation: Confirmation) => {
const ownerAddress = confirmation.get('owner').get('address')
const samePerson = sameAddress(ownerAddress, userAddress)
return samePerson && confirmation.get('status')
}).count() > 0
if (userHasAlreadyConfirmed) {
throw new Error('Owner has already confirmed this transaction')
}
const threshold = tx.get('threshold')
const thresholdReached = threshold === alreadyConfirmed + 1
const nonce = tx.get('nonce')
const txName = tx.get('name')
const txValue = tx.get('value')
const txDestination = tx.get('destination')
const data = tx.get('data')
const txHash = thresholdReached
? await execTransaction(gnosisSafe, txDestination, txValue, nonce, userAddress, data)
: await execConfirmation(gnosisSafe, txDestination, txValue, nonce, userAddress, data)
checkReceiptStatus(txHash.tx)
const confirmationHash =
thresholdReached ? EXECUTED_CONFIRMATION_HASH : txHash.tx
const executedConfirmations: List<Confirmation> =
updateConfirmations(tx.get('confirmations'), userAddress, confirmationHash)
return updateTransaction(
txName,
nonce,
txDestination,
txValue,
userAddress,
executedConfirmations,
thresholdReached ? txHash.tx : '',
safeAddress,
threshold,
data,
)
}

View File

@ -3,7 +3,7 @@ import { List } from 'immutable'
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { type Transaction } from '~/routes/safe/store/model/transaction' import { type Transaction } from '~/routes/safe/store/model/transaction'
import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index' import { safeTransactionsSelector } from '~/routes/safe/store/selectors/index'
import { userAccountSelector } from '~/wallets/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors'
export type SelectorProps = { export type SelectorProps = {
transactions: List<Transaction>, transactions: List<Transaction>,

View File

@ -5,7 +5,7 @@ import Block from '~/components/layout/Block'
import Bold from '~/components/layout/Bold' import Bold from '~/components/layout/Bold'
import Heading from '~/components/layout/Heading' import Heading from '~/components/layout/Heading'
import Paragraph from '~/components/layout/Paragraph' import Paragraph from '~/components/layout/Paragraph'
import { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/withdraw' import { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/WithdrawForm'
type FormProps = { type FormProps = {
values: Object, values: Object,

View File

@ -5,9 +5,10 @@ import TextField from '~/components/forms/TextField'
import { composeValidators, inLimit, mustBeFloat, required, greaterThan, mustBeEthereumAddress } from '~/components/forms/validator' import { composeValidators, inLimit, mustBeFloat, required, greaterThan, mustBeEthereumAddress } from '~/components/forms/validator'
import Block from '~/components/layout/Block' import Block from '~/components/layout/Block'
import Heading from '~/components/layout/Heading' import Heading from '~/components/layout/Heading'
import { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/withdraw'
export const CONFIRMATIONS_ERROR = 'Number of confirmations can not be higher than the number of owners' export const CONFIRMATIONS_ERROR = 'Number of confirmations can not be higher than the number of owners'
export const DESTINATION_PARAM = 'destination'
export const VALUE_PARAM = 'ether'
export const safeFieldsValidation = (values: Object) => { export const safeFieldsValidation = (values: Object) => {
const errors = {} const errors = {}

View File

@ -4,8 +4,8 @@ import { connect } from 'react-redux'
import Stepper from '~/components/Stepper' import Stepper from '~/components/Stepper'
import { type DailyLimit } from '~/routes/safe/store/model/dailyLimit' import { type DailyLimit } from '~/routes/safe/store/model/dailyLimit'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { withdraw } from '~/logic/safe/safeFrontendOperations'
import selector, { type SelectorProps } from './selector' import selector, { type SelectorProps } from './selector'
import withdraw from './withdraw'
import WithdrawForm from './WithdrawForm' import WithdrawForm from './WithdrawForm'
import Review from './Review' import Review from './Review'
import actions, { type Actions } from './actions' import actions, { type Actions } from './actions'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { userAccountSelector } from '~/wallets/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors'
export type SelectorProps = { export type SelectorProps = {
userAddress: userAccountSelector, userAddress: userAccountSelector,

View File

@ -1,78 +0,0 @@
// @flow
import { List } from 'immutable'
import { getWeb3 } from '~/wallets/getWeb3'
import { getGnosisSafeContract, getCreateDailyLimitExtensionContract } from '~/wallets/safeContracts'
import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit'
import { checkReceiptStatus, calculateGasOf, calculateGasPrice, EMPTY_DATA } from '~/wallets/ethTransactions'
import { type Safe } from '~/routes/safe/store/model/safe'
import { buildExecutedConfirmationFrom, storeTransaction } from '~/wallets/createTransactions'
import { type Confirmation } from '~/routes/safe/store/model/confirmation'
export const LIMIT_POSITION = 0
export const SPENT_TODAY_POS = 1
export const DESTINATION_PARAM = 'destination'
export const VALUE_PARAM = 'ether'
const getDailyLimitModuleFrom = async (safeAddress) => {
const web3 = getWeb3()
const gnosisSafe = getGnosisSafeContract(web3).at(safeAddress)
const modules = await gnosisSafe.getModules()
const dailyAddress = modules[0]
const dailyLimitModule = getCreateDailyLimitExtensionContract(web3).at(dailyAddress)
if (await dailyLimitModule.manager.call() !== gnosisSafe.address) {
throw new Error('Using an extension of different safe')
}
return dailyLimitModule
}
export const getDailyLimitFrom = async (safeAddress: string, tokenAddress: number): Promise<DailyLimitProps> => {
const web3 = getWeb3()
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)
const dailyLimitEth = await dailyLimitModule.dailyLimits(tokenAddress)
const limit = web3.fromWei(dailyLimitEth[LIMIT_POSITION].valueOf(), 'ether').toString()
const spentToday = web3.fromWei(dailyLimitEth[SPENT_TODAY_POS].valueOf(), 'ether').toString()
return { value: Number(limit), spentToday: Number(spentToday) }
}
export const getDailyLimitAddress = async (safeAddress: string) => {
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)
return dailyLimitModule.address
}
export const getEditDailyLimitData = async (safeAddress: string, token: number, dailyLimit: number) => {
const web3 = getWeb3()
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)
const dailyLimitInWei = web3.toWei(dailyLimit, 'ether')
return dailyLimitModule.contract.changeDailyLimit.getData(token, dailyLimitInWei)
}
const withdraw = async (values: Object, safe: Safe, userAccount: string): Promise<void> => {
const web3 = getWeb3()
const safeAddress = safe.get('address')
const dailyLimitModule = await getDailyLimitModuleFrom(safeAddress)
const destination = values[DESTINATION_PARAM]
const valueInEth = values[VALUE_PARAM]
const value = web3.toWei(valueInEth, 'ether')
const dailyLimitData = dailyLimitModule.contract.executeDailyLimit.getData(0, destination, value)
const gas = await calculateGasOf(dailyLimitData, userAccount, dailyLimitModule.address)
const gasPrice = await calculateGasPrice()
const txHash = await dailyLimitModule.executeDailyLimit(0, destination, value, { from: userAccount, gas, gasPrice })
checkReceiptStatus(txHash.tx)
const nonce = Date.now()
const executedConfirmations: List<Confirmation> = buildExecutedConfirmationFrom(safe.get('owners'), userAccount)
return storeTransaction(`Withdraw movement of ${valueInEth}`, nonce, destination, valueInEth, userAccount, executedConfirmations, txHash.tx, safeAddress, safe.get('threshold'), EMPTY_DATA)
}
export default withdraw

View File

@ -2,11 +2,11 @@
import { List } from 'immutable' import { List } from 'immutable'
import { createSelector, createStructuredSelector, type Selector } from 'reselect' import { createSelector, createStructuredSelector, type Selector } from 'reselect'
import { safeSelector, type RouterProps, type SafeSelectorProps } from '~/routes/safe/store/selectors' import { safeSelector, type RouterProps, type SafeSelectorProps } from '~/routes/safe/store/selectors'
import { providerNameSelector, userAccountSelector } from '~/wallets/store/selectors/index' import { providerNameSelector, userAccountSelector } from '~/logic/wallets/store/selectors'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { type Owner } from '~/routes/safe/store/model/owner' import { type Owner } from '~/routes/safe/store/model/owner'
import { type GlobalState } from '~/store' import { type GlobalState } from '~/store'
import { sameAddress } from '~/wallets/ethAddresses' import { sameAddress } from '~/logic/wallets/ethAddresses'
import { activeTokensSelector } from '~/routes/tokens/store/selectors' import { activeTokensSelector } from '~/routes/tokens/store/selectors'
import { type Token } from '~/routes/tokens/store/model/token' import { type Token } from '~/routes/tokens/store/model/token'

View File

@ -5,10 +5,10 @@ import { type GlobalState } from '~/store/index'
import { makeOwner } from '~/routes/safe/store/model/owner' import { makeOwner } from '~/routes/safe/store/model/owner'
import { type SafeProps, type Safe, makeSafe } from '~/routes/safe/store/model/safe' import { type SafeProps, type Safe, makeSafe } from '~/routes/safe/store/model/safe'
import { makeDailyLimit } from '~/routes/safe/store/model/dailyLimit' import { makeDailyLimit } from '~/routes/safe/store/model/dailyLimit'
import { getDailyLimitFrom } from '~/routes/safe/component/Withdraw/withdraw'
import { getGnosisSafeInstanceAt } from '~/wallets/safeContracts'
import updateSafe from '~/routes/safe/store/actions/updateSafe' import updateSafe from '~/routes/safe/store/actions/updateSafe'
import { getOwners } from '~/utils/localStorage' import { getOwners } from '~/utils/localStorage'
import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts'
import { getDailyLimitFrom } from '~/logic/contracts/dailyLimitContracts'
const buildOwnersFrom = (safeOwners: string[], storedOwners: Map<string, string>) => ( const buildOwnersFrom = (safeOwners: string[], storedOwners: Map<string, string>) => (
safeOwners.map((ownerAddress: string) => { safeOwners.map((ownerAddress: string) => {

View File

@ -7,7 +7,7 @@ import { makeTransaction, type Transaction } from '~/routes/safe/store/model/tra
import { load, TX_KEY } from '~/utils/localStorage' import { load, TX_KEY } from '~/utils/localStorage'
import { makeConfirmation } from '~/routes/safe/store/model/confirmation' import { makeConfirmation } from '~/routes/safe/store/model/confirmation'
import { loadSafeSubjects } from '~/utils/localStorage/transactions' import { loadSafeSubjects } from '~/utils/localStorage/transactions'
import { buildTxServiceUrlFrom, type TxServiceType } from '~/wallets/safeTxHistory' import { buildTxServiceUrlFrom, type TxServiceType } from '~/logic/safe/safeTxHistory'
import { enhancedFetch } from '~/utils/fetch' import { enhancedFetch } from '~/utils/fetch'
import addTransactions from './addTransactions' import addTransactions from './addTransactions'

View File

@ -2,7 +2,7 @@
import { Record } from 'immutable' import { Record } from 'immutable'
import type { RecordFactory, RecordOf } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable'
import { makeOwner, type Owner } from '~/routes/safe/store/model/owner' import { makeOwner, type Owner } from '~/routes/safe/store/model/owner'
import { type TxServiceType } from '~/wallets/safeTxHistory' import { type TxServiceType } from '~/logic/safe/safeTxHistory'
export type ConfirmationProps = { export type ConfirmationProps = {
owner: Owner, owner: Owner,
@ -12,7 +12,7 @@ export type ConfirmationProps = {
export const makeConfirmation: RecordFactory<ConfirmationProps> = Record({ export const makeConfirmation: RecordFactory<ConfirmationProps> = Record({
owner: makeOwner(), owner: makeOwner(),
type: 'confirmation', type: 'initialised',
hash: '', hash: '',
}) })

View File

@ -8,12 +8,13 @@ import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation
import Open from '~/routes/open/container/Open' import Open from '~/routes/open/container/Open'
import { history, type GlobalState } from '~/store' import { history, type GlobalState } from '~/store'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import { getProviderInfo, getWeb3 } from '~/wallets/getWeb3' import { getProviderInfo, getWeb3 } from '~/logic/wallets/getWeb3'
import addProvider from '~/wallets/store/actions/addProvider' import addProvider from '~/logic/wallets/store/actions/addProvider'
import { makeProvider } from '~/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider'
import withdraw, { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/withdraw'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/WithdrawForm'
import { withdraw } from '~/logic/safe/safeFrontendOperations'
export const renderSafe = async (localStore: Store<GlobalState>) => { export const renderSafe = async (localStore: Store<GlobalState>) => {
const provider = await getProviderInfo() const provider = await getProviderInfo()

View File

@ -5,9 +5,9 @@ import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder' import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder'
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps' import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
import { getProviderInfo } from '~/wallets/getWeb3' import { getProviderInfo } from '~/logic/wallets/getWeb3'
import { grantedSelector } from '~/routes/safe/container/selector' import { grantedSelector } from '~/routes/safe/container/selector'
import { makeProvider } from '~/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider'
const grantedSelectorTests = () => { const grantedSelectorTests = () => {
let provider let provider

View File

@ -2,7 +2,7 @@
/* /*
import { aNewStore } from '~/store' import { aNewStore } from '~/store'
import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder' import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import { type Match } from 'react-router-dom' import { type Match } from 'react-router-dom'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'

View File

@ -1,7 +1,7 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { safesByOwnerSelector } from '~/routes/safeList/store/selectors' import { safesByOwnerSelector } from '~/routes/safeList/store/selectors'
import { providerNameSelector } from '~/wallets/store/selectors/index' import { providerNameSelector } from '~/logic/wallets/store/selectors'
export default createStructuredSelector({ export default createStructuredSelector({
safes: safesByOwnerSelector, safes: safesByOwnerSelector,

View File

@ -3,9 +3,9 @@ import { List, Map } from 'immutable'
import { createSelector, type Selector } from 'reselect' import { createSelector, type Selector } from 'reselect'
import { type GlobalState } from '~/store/index' import { type GlobalState } from '~/store/index'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { userAccountSelector } from '~/wallets/store/selectors/index' import { userAccountSelector } from '~/logic/wallets/store/selectors'
import { type Owner } from '~/routes/safe/store/model/owner' import { type Owner } from '~/routes/safe/store/model/owner'
import { sameAddress } from '~/wallets/ethAddresses' import { sameAddress } from '~/logic/wallets/ethAddresses'
export const safesMapSelector = (state: GlobalState): Map<string, Safe> => state.safes export const safesMapSelector = (state: GlobalState): Map<string, Safe> => state.safes
const safesListSelector: Selector<GlobalState, {}, List<Safe>> = createSelector( const safesListSelector: Selector<GlobalState, {}, List<Safe>> = createSelector(

View File

@ -2,10 +2,10 @@
import { List, Map } from 'immutable' import { List, Map } from 'immutable'
import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { getProviderInfo } from '~/wallets/getWeb3' import { getProviderInfo } from '~/logic/wallets/getWeb3'
import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder' import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder'
import { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider' import { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider'
import { makeProvider, type Provider } from '~/wallets/store/model/provider' import { makeProvider, type Provider } from '~/logic/wallets/store/model/provider'
import { safesByOwnerSelector } from '../selectors' import { safesByOwnerSelector } from '../selectors'
const safesListSelectorTests = () => { const safesListSelectorTests = () => {

View File

@ -6,8 +6,8 @@ import { composeValidators, required, mustBeEthereumAddress, uniqueAddress } fro
import Block from '~/components/layout/Block' import Block from '~/components/layout/Block'
import Heading from '~/components/layout/Heading' import Heading from '~/components/layout/Heading'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { EMPTY_DATA } from '~/wallets/ethTransactions' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
import { getStandardTokenContract } from '~/routes/tokens/store/actions/fetchTokens' import { getStandardTokenContract } from '~/routes/tokens/store/actions/fetchTokens'
type Props = { type Props = {

View File

@ -6,9 +6,9 @@ import FirstPage, { TOKEN_ADRESS_PARAM } from '~/routes/tokens/component/AddToke
import SecondPage, { TOKEN_SYMBOL_PARAM, TOKEN_DECIMALS_PARAM, TOKEN_LOGO_URL_PARAM, TOKEN_NAME_PARAM } from '~/routes/tokens/component/AddToken/SecondPage' import SecondPage, { TOKEN_SYMBOL_PARAM, TOKEN_DECIMALS_PARAM, TOKEN_LOGO_URL_PARAM, TOKEN_NAME_PARAM } from '~/routes/tokens/component/AddToken/SecondPage'
import { makeToken, type Token } from '~/routes/tokens/store/model/token' import { makeToken, type Token } from '~/routes/tokens/store/model/token'
import addTokenAction from '~/routes/tokens/store/actions/addToken' import addTokenAction from '~/routes/tokens/store/actions/addToken'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { EMPTY_DATA } from '~/wallets/ethTransactions' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
import Review from './Review' import Review from './Review'
export const getSteps = () => [ export const getSteps = () => [

View File

@ -4,7 +4,7 @@ import contract from 'truffle-contract'
import type { Dispatch as ReduxDispatch } from 'redux' import type { Dispatch as ReduxDispatch } from 'redux'
import StandardToken from '@gnosis.pm/util-contracts/build/contracts/StandardToken.json' import StandardToken from '@gnosis.pm/util-contracts/build/contracts/StandardToken.json'
import HumanFriendlyToken from '@gnosis.pm/util-contracts/build/contracts/HumanFriendlyToken.json' import HumanFriendlyToken from '@gnosis.pm/util-contracts/build/contracts/HumanFriendlyToken.json'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { type GlobalState } from '~/store/index' import { type GlobalState } from '~/store/index'
import { makeToken, type Token, type TokenProps } from '~/routes/tokens/store/model/token' import { makeToken, type Token, type TokenProps } from '~/routes/tokens/store/model/token'
import { ensureOnce } from '~/utils/singleton' import { ensureOnce } from '~/utils/singleton'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { createStructuredSelector } from 'reselect' import { createStructuredSelector } from 'reselect'
import { providerNameSelector } from '~/wallets/store/selectors/index' import { providerNameSelector } from '~/logic/wallets/store/selectors'
export default createStructuredSelector({ export default createStructuredSelector({
provider: providerNameSelector, provider: providerNameSelector,

View File

@ -3,7 +3,7 @@ import { createBrowserHistory } from 'history'
import { routerMiddleware, routerReducer } from 'react-router-redux' import { routerMiddleware, routerReducer } from 'react-router-redux'
import { combineReducers, createStore, applyMiddleware, compose, type Reducer, type Store } from 'redux' import { combineReducers, createStore, applyMiddleware, compose, type Reducer, type Store } from 'redux'
import thunk from 'redux-thunk' import thunk from 'redux-thunk'
import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/wallets/store/reducer/provider' import provider, { PROVIDER_REDUCER_ID, type State as ProviderState } from '~/logic/wallets/store/reducer/provider'
import safe, { SAFE_REDUCER_ID, type State as SafeState } from '~/routes/safe/store/reducer/safe' import safe, { SAFE_REDUCER_ID, type State as SafeState } from '~/routes/safe/store/reducer/safe'
import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/routes/tokens/store/reducer/tokens' import tokens, { TOKEN_REDUCER_ID, type State as TokensState } from '~/routes/tokens/store/reducer/tokens'
import transactions, { type State as TransactionsState, transactionsInitialState, TRANSACTIONS_REDUCER_ID } from '~/routes/safe/store/reducer/transactions' import transactions, { type State as TransactionsState, transactionsInitialState, TRANSACTIONS_REDUCER_ID } from '~/routes/safe/store/reducer/transactions'

View File

@ -4,7 +4,7 @@ import TestUtils from 'react-dom/test-utils'
import SafeView from '~/routes/safe/component/Safe' import SafeView from '~/routes/safe/component/Safe'
import { aNewStore, type GlobalState } from '~/store' import { aNewStore, type GlobalState } from '~/store'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { addEtherTo } from '~/test/utils/tokenMovements' import { addEtherTo } from '~/test/utils/tokenMovements'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'

View File

@ -10,7 +10,7 @@ import { ConnectedRouter } from 'react-router-redux'
import AppRoutes from '~/routes' import AppRoutes from '~/routes'
import { SAFELIST_ADDRESS, SETTINS_ADDRESS } from '~/routes/routes' import { SAFELIST_ADDRESS, SETTINS_ADDRESS } from '~/routes/routes'
import { history, type GlobalState } from '~/store' import { history, type GlobalState } from '~/store'
import { EMPTY_DATA } from '~/wallets/ethTransactions' import { EMPTY_DATA } from '~/logic/wallets/ethTransactions'
export const EXPAND_BALANCE_INDEX = 0 export const EXPAND_BALANCE_INDEX = 0
export const EXPAND_OWNERS_INDEX = 1 export const EXPAND_OWNERS_INDEX = 1

View File

@ -2,13 +2,13 @@
import { makeSafe, type Safe } from '~/routes/safe/store/model/safe' import { makeSafe, type Safe } from '~/routes/safe/store/model/safe'
import { buildOwnersFrom, buildDailyLimitFrom } from '~/routes/safe/store/actions' import { buildOwnersFrom, buildDailyLimitFrom } from '~/routes/safe/store/actions'
import { FIELD_NAME, FIELD_CONFIRMATIONS, FIELD_OWNERS, getOwnerNameBy, getOwnerAddressBy, FIELD_DAILY_LIMIT } from '~/routes/open/components/fields' import { FIELD_NAME, FIELD_CONFIRMATIONS, FIELD_OWNERS, getOwnerNameBy, getOwnerAddressBy, FIELD_DAILY_LIMIT } from '~/routes/open/components/fields'
import { getWeb3, getProviderInfo } from '~/wallets/getWeb3' import { getWeb3, getProviderInfo } from '~/logic/wallets/getWeb3'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import addSafe from '~/routes/safe/store/actions/addSafe' import addSafe from '~/routes/safe/store/actions/addSafe'
import { createSafe, type OpenState } from '~/routes/open/container/Open' import { createSafe, type OpenState } from '~/routes/open/container/Open'
import { type GlobalState } from '~/store/index' import { type GlobalState } from '~/store/index'
import { makeProvider } from '~/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider'
import addProvider from '~/wallets/store/actions/addProvider' import addProvider from '~/logic/wallets/store/actions/addProvider'
class SafeBuilder { class SafeBuilder {
safe: Safe safe: Safe

View File

@ -8,9 +8,9 @@ import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation
import Open from '~/routes/open/container/Open' import Open from '~/routes/open/container/Open'
import { aNewStore, history, type GlobalState } from '~/store' import { aNewStore, history, type GlobalState } from '~/store'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import { getProviderInfo, getWeb3 } from '~/wallets/getWeb3' import { getProviderInfo, getWeb3 } from '~/logic/wallets/getWeb3'
import addProvider from '~/wallets/store/actions/addProvider' import addProvider from '~/logic/wallets/store/actions/addProvider'
import { makeProvider } from '~/wallets/store/model/provider' import { makeProvider } from '~/logic/wallets/store/model/provider'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
const fillOpenSafeForm = async (localStore: Store<GlobalState>) => { const fillOpenSafeForm = async (localStore: Store<GlobalState>) => {

View File

@ -7,7 +7,7 @@ import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { addTknTo, getFirstTokenContract } from '~/test/utils/tokenMovements' import { addTknTo, getFirstTokenContract } from '~/test/utils/tokenMovements'
import { EXPAND_BALANCE_INDEX, travelToSafe } from '~/test/builder/safe.dom.utils' import { EXPAND_BALANCE_INDEX, travelToSafe } from '~/test/builder/safe.dom.utils'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { sendMoveTokensForm, dispatchTknBalance } from '~/test/utils/transactions/moveTokens.helper' import { sendMoveTokensForm, dispatchTknBalance } from '~/test/utils/transactions/moveTokens.helper'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'

View File

@ -8,9 +8,9 @@ import { sendAddOwnerForm, checkMinedAddOwnerTx, checkPendingAddOwnerTx } from '
import { sendRemoveOwnerForm, checkMinedRemoveOwnerTx, checkPendingRemoveOwnerTx } from '~/test/utils/transactions/removeOwner.helper' import { sendRemoveOwnerForm, checkMinedRemoveOwnerTx, checkPendingRemoveOwnerTx } from '~/test/utils/transactions/removeOwner.helper'
import { checkMinedThresholdTx, sendChangeThresholdForm, checkThresholdOf } from '~/test/utils/transactions/threshold.helper' import { checkMinedThresholdTx, sendChangeThresholdForm, checkThresholdOf } from '~/test/utils/transactions/threshold.helper'
import { sendWithdrawForm, checkMinedWithdrawTx } from '~/test/utils/transactions/withdraw.helper' import { sendWithdrawForm, checkMinedWithdrawTx } from '~/test/utils/transactions/withdraw.helper'
import { processTransaction } from '~/routes/safe/component/Transactions/processTransactions'
import { checkBalanceOf } from '~/test/utils/tokenMovements' import { checkBalanceOf } from '~/test/utils/tokenMovements'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import { processTransaction } from '~/logic/safe/safeFrontendOperations'
describe('DOM > Feature > SAFE MULTISIG Transactions', () => { describe('DOM > Feature > SAFE MULTISIG Transactions', () => {
let domSafe: DomSafe let domSafe: DomSafe
@ -71,10 +71,11 @@ describe('DOM > Feature > SAFE MULTISIG Transactions', () => {
let transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction) let transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction)
expect(transactions.length).toBe(7) expect(transactions.length).toBe(7)
await checkThresholdOf(address, 3)
// WHEN... processing pending TXs // WHEN... processing pending TXs
await processTransaction(address, transactions[4].props.transaction, 1, accounts[1]) await processTransaction(address, transactions[4].props.transaction, 1, accounts[1], 3)
await processTransaction(address, transactions[5].props.transaction, 1, accounts[1]) await processTransaction(address, transactions[5].props.transaction, 1, accounts[1], 3)
await refreshTransactions(store) await refreshTransactions(store)
// THEN // THEN
@ -93,14 +94,14 @@ describe('DOM > Feature > SAFE MULTISIG Transactions', () => {
let statusses = ['Adol Metamask 3 [Not confirmed]', 'Adol Metamask 2 [Not confirmed]', 'Adol 1 Eth Account [Confirmed]'] let statusses = ['Adol Metamask 3 [Not confirmed]', 'Adol Metamask 2 [Not confirmed]', 'Adol 1 Eth Account [Confirmed]']
await checkPendingRemoveOwnerTx(transactions[7], 3, 'Remove Owner Adol Metamask 3', statusses) await checkPendingRemoveOwnerTx(transactions[7], 3, 'Remove Owner Adol Metamask 3', statusses)
await processTransaction(address, transactions[7].props.transaction, 1, accounts[1]) await processTransaction(address, transactions[7].props.transaction, 1, accounts[1], 3)
await refreshTransactions(store) await refreshTransactions(store)
transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction) transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction)
statusses = ['Adol Metamask 3 [Not confirmed]', 'Adol Metamask 2 [Confirmed]', 'Adol 1 Eth Account [Confirmed]'] statusses = ['Adol Metamask 3 [Not confirmed]', 'Adol Metamask 2 [Confirmed]', 'Adol 1 Eth Account [Confirmed]']
await checkPendingRemoveOwnerTx(transactions[7], 2, 'Remove Owner Adol Metamask 3', statusses) await checkPendingRemoveOwnerTx(transactions[7], 2, 'Remove Owner Adol Metamask 3', statusses)
await checkThresholdOf(address, 3) await checkThresholdOf(address, 3)
await processTransaction(address, transactions[7].props.transaction, 2, accounts[2]) await processTransaction(address, transactions[7].props.transaction, 2, accounts[2], 3)
await refreshTransactions(store) await refreshTransactions(store)
await checkThresholdOf(address, 2) await checkThresholdOf(address, 2)
transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction) transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction)
@ -112,7 +113,7 @@ describe('DOM > Feature > SAFE MULTISIG Transactions', () => {
// THEN // THEN
transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction) transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction)
await processTransaction(address, transactions[8].props.transaction, 1, accounts[1]) await processTransaction(address, transactions[8].props.transaction, 1, accounts[1], 2)
await checkThresholdOf(address, 1) await checkThresholdOf(address, 1)
}) })
}) })

View File

@ -1,13 +1,12 @@
// @flow // @flow
import { aNewStore } from '~/store' import { aNewStore } from '~/store'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { processTransaction } from '~/routes/safe/component/Transactions/processTransactions'
import { confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index' import { confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index'
import { getTransactionFromReduxStore } from '~/routes/safe/test/testMultisig' import { getTransactionFromReduxStore } from '~/routes/safe/test/testMultisig'
import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { getGnosisSafeInstanceAt } from '~/wallets/safeContracts' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { NAME_PARAM, OWNER_ADDRESS_PARAM, INCREASE_PARAM } from '~/routes/safe/component/AddOwner/AddOwnerForm' import { NAME_PARAM, OWNER_ADDRESS_PARAM, INCREASE_PARAM } from '~/routes/safe/component/AddOwner/AddOwnerForm'
import { addOwner } from '~/routes/safe/component/AddOwner/index' import { addOwner } from '~/routes/safe/component/AddOwner/index'
@ -15,9 +14,10 @@ import fetchSafe from '~/routes/safe/store/actions/fetchSafe'
import { removeOwner, shouldDecrease, initialValuesFrom } from '~/routes/safe/component/RemoveOwner' import { removeOwner, shouldDecrease, initialValuesFrom } from '~/routes/safe/component/RemoveOwner'
import { DECREASE_PARAM } from '~/routes/safe/component/RemoveOwner/RemoveOwnerForm/index' import { DECREASE_PARAM } from '~/routes/safe/component/RemoveOwner/RemoveOwnerForm/index'
import { getSafeFrom } from '~/test/utils/safeHelper' import { getSafeFrom } from '~/test/utils/safeHelper'
import { processTransaction } from '~/logic/safe/safeFrontendOperations'
describe('React DOM TESTS > Add and remove owners', () => { describe('React DOM TESTS > Add and remove owners', () => {
const processOwnerModification = async (store, safeAddress, executor) => { const processOwnerModification = async (store, safeAddress, executor, threshold) => {
const tx = getTransactionFromReduxStore(store, safeAddress) const tx = getTransactionFromReduxStore(store, safeAddress)
if (!tx) throw new Error() if (!tx) throw new Error()
const confirmed = confirmationsTransactionSelector(store.getState(), { transaction: tx }) const confirmed = confirmationsTransactionSelector(store.getState(), { transaction: tx })
@ -25,7 +25,7 @@ describe('React DOM TESTS > Add and remove owners', () => {
expect(data).not.toBe(null) expect(data).not.toBe(null)
expect(data).not.toBe(undefined) expect(data).not.toBe(undefined)
expect(data).not.toBe('') expect(data).not.toBe('')
return processTransaction(safeAddress, tx, confirmed, executor) return processTransaction(safeAddress, tx, confirmed, executor, threshold)
} }
const assureThresholdIs = async (gnosisSafe, threshold: number) => { const assureThresholdIs = async (gnosisSafe, threshold: number) => {
@ -116,9 +116,9 @@ describe('React DOM TESTS > Add and remove owners', () => {
let safe = getSafeFrom(store.getState(), address) let safe = getSafeFrom(store.getState(), address)
await removeOwner(values, safe, threshold, accounts[1], 'Adol Metamask 2', accounts[0]) await removeOwner(values, safe, threshold, accounts[1], 'Adol Metamask 2', accounts[0])
await store.dispatch(fetchTransactions()) await store.dispatch(fetchTransactions())
await processOwnerModification(store, address, accounts[1]) await processOwnerModification(store, address, accounts[1], 2)
await assureThresholdIs(gnosisSafe, 1) await assureThresholdIs(gnosisSafe, 2)
await assureOwnersAre(gnosisSafe, accounts[0]) await assureOwnersAre(gnosisSafe, accounts[0])
await store.dispatch(fetchSafe(safe)) await store.dispatch(fetchSafe(safe))
@ -141,9 +141,9 @@ describe('React DOM TESTS > Add and remove owners', () => {
let safe = getSafeFrom(store.getState(), address) let safe = getSafeFrom(store.getState(), address)
await removeOwner(values, safe, threshold, accounts[2], 'Adol Metamask 3', accounts[0]) await removeOwner(values, safe, threshold, accounts[2], 'Adol Metamask 3', accounts[0])
await store.dispatch(fetchTransactions()) await store.dispatch(fetchTransactions())
await processOwnerModification(store, address, accounts[1]) await processOwnerModification(store, address, accounts[1], 2)
await assureThresholdIs(gnosisSafe, 1) await assureThresholdIs(gnosisSafe, 2)
await assureOwnersAre(gnosisSafe, accounts[0], accounts[1]) await assureOwnersAre(gnosisSafe, accounts[0], accounts[1])
await store.dispatch(fetchSafe(safe)) await store.dispatch(fetchSafe(safe))
@ -167,7 +167,7 @@ describe('React DOM TESTS > Add and remove owners', () => {
let safe = getSafeFrom(store.getState(), address) let safe = getSafeFrom(store.getState(), address)
await removeOwner(values, safe, threshold, accounts[2], 'Adol Metamask 3', accounts[0]) await removeOwner(values, safe, threshold, accounts[2], 'Adol Metamask 3', accounts[0])
await store.dispatch(fetchTransactions()) await store.dispatch(fetchTransactions())
await processOwnerModification(store, address, accounts[1]) await processOwnerModification(store, address, accounts[1], 2)
await assureThresholdIs(gnosisSafe, 2) await assureThresholdIs(gnosisSafe, 2)
await assureOwnersAre(gnosisSafe, accounts[0], accounts[1]) await assureOwnersAre(gnosisSafe, accounts[0], accounts[1])

View File

@ -1,6 +1,6 @@
// @flow // @flow
import { List } from 'immutable' import { List } from 'immutable'
import { getSafeEthereumInstance, createTransaction } from '~/wallets/createTransactions' import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import { makeOwner } from '~/routes/safe/store/model/owner' import { makeOwner } from '~/routes/safe/store/model/owner'
import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions'
@ -9,7 +9,7 @@ import { aNewStore } from '~/store'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { getSafeFrom } from '~/test/utils/safeHelper' import { getSafeFrom } from '~/test/utils/safeHelper'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { safeTransactionsSelector } from '~/routes/safe/store/selectors' import { safeTransactionsSelector } from '~/routes/safe/store/selectors'
import { testTransactionFrom, testSizeOfTransactions } from './utils/historyServiceHelper' import { testTransactionFrom, testSizeOfTransactions } from './utils/historyServiceHelper'

View File

@ -10,15 +10,15 @@ import { SAFELIST_ADDRESS } from '~/routes/routes'
import SafeView from '~/routes/safe/component/Safe' import SafeView from '~/routes/safe/component/Safe'
import AppRoutes from '~/routes' import AppRoutes from '~/routes'
import { WITHDRAW_BUTTON_TEXT } from '~/routes/safe/component/Safe/DailyLimit' import { WITHDRAW_BUTTON_TEXT } from '~/routes/safe/component/Safe/DailyLimit'
import { getBalanceInEtherOf } from '~/wallets/getWeb3' import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import { getDailyLimitFrom } from '~/routes/safe/component/Withdraw/withdraw'
import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit' import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit'
import { WITHDRAW_INDEX } from '~/test/builder/safe.dom.utils' import { WITHDRAW_INDEX } from '~/test/builder/safe.dom.utils'
import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { aMinedSafe } from '~/test/builder/safe.redux.builder'
import { getSafeFrom } from '~/test/utils/safeHelper' import { getSafeFrom } from '~/test/utils/safeHelper'
import { filterMoveButtonsFrom } from '~/test/builder/safe.dom.builder' import { filterMoveButtonsFrom } from '~/test/builder/safe.dom.builder'
import { fetchTokens } from '~/routes/tokens/store/actions/fetchTokens' import { fetchTokens } from '~/routes/tokens/store/actions/fetchTokens'
import { getDailyLimitFrom } from '~/logic/contracts/dailyLimitContracts'
describe('React DOM TESTS > Withdraw funds from safe', () => { describe('React DOM TESTS > Withdraw funds from safe', () => {
let store let store

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as TestUtils from 'react-dom/test-utils' import * as TestUtils from 'react-dom/test-utils'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { type Match } from 'react-router-dom' import { type Match } from 'react-router-dom'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import TokenComponent from '~/routes/tokens/component/Token' import TokenComponent from '~/routes/tokens/component/Token'

View File

@ -1,7 +1,7 @@
// @flow // @flow
import * as TestUtils from 'react-dom/test-utils' import * as TestUtils from 'react-dom/test-utils'
import { List } from 'immutable' import { List } from 'immutable'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { type Match } from 'react-router-dom' import { type Match } from 'react-router-dom'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import TokenComponent from '~/routes/tokens/component/Token' import TokenComponent from '~/routes/tokens/component/Token'

View File

@ -1,6 +1,6 @@
// @flow // @flow
import * as TestUtils from 'react-dom/test-utils' import * as TestUtils from 'react-dom/test-utils'
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements' import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements'
import { aNewStore } from '~/store' import { aNewStore } from '~/store'

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { type Match } from 'react-router-dom' import { type Match } from 'react-router-dom'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements' import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements'

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import { type Match } from 'react-router-dom' import { type Match } from 'react-router-dom'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements' import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements'

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { getWeb3 } from '~/wallets/getWeb3' import { getWeb3 } from '~/logic/wallets/getWeb3'
import abi from 'ethereumjs-abi' import abi from 'ethereumjs-abi'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'

View File

@ -1,5 +1,5 @@
// @flow // @flow
import { getGnosisSafeInstanceAt } from '~/wallets/safeContracts' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts'
import GnoStepper from '~/components/Stepper' import GnoStepper from '~/components/Stepper'
import Stepper from '@material-ui/core/Stepper' import Stepper from '@material-ui/core/Stepper'
import TestUtils from 'react-dom/test-utils' import TestUtils from 'react-dom/test-utils'

View File

@ -1,12 +1,13 @@
// @flow // @flow
import contract from 'truffle-contract' import contract from 'truffle-contract'
import { getProviderInfo, getBalanceInEtherOf, getWeb3 } from '~/wallets/getWeb3' import { getProviderInfo, getBalanceInEtherOf, getWeb3 } from '~/logic/wallets/getWeb3'
import { promisify } from '~/utils/promisify' import { promisify } from '~/utils/promisify'
import withdraw, { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/withdraw'
import { type Safe } from '~/routes/safe/store/model/safe' import { type Safe } from '~/routes/safe/store/model/safe'
import Token from '#/test/TestToken.json' import Token from '#/test/TestToken.json'
import { ensureOnce } from '~/utils/singleton' import { ensureOnce } from '~/utils/singleton'
import { toNative } from '~/wallets/tokens' import { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/WithdrawForm'
import { withdraw } from '~/logic/safe/safeFrontendOperations'
import { toNative } from '~/logic/wallets/tokens'
export const addEtherTo = async (address: string, eth: string) => { export const addEtherTo = async (address: string, eth: string) => {
const web3 = getWeb3() const web3 = getWeb3()

View File

@ -2,7 +2,7 @@
import TestUtils from 'react-dom/test-utils' import TestUtils from 'react-dom/test-utils'
import { sleep } from '~/utils/timer' import { sleep } from '~/utils/timer'
import { checkMinedTx } from '~/test/builder/safe.dom.utils' import { checkMinedTx } from '~/test/builder/safe.dom.utils'
import { getGnosisSafeInstanceAt } from '~/wallets/safeContracts' import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts'
import Threshold from '~/routes/safe/component/Threshold' import Threshold from '~/routes/safe/component/Threshold'
import { whenExecuted } from '~/test/utils/logTransactions' import { whenExecuted } from '~/test/utils/logTransactions'

View File

@ -1,7 +1,7 @@
// @flow // @flow
import { List } from 'immutable' import { List } from 'immutable'
import logo from '~/assets/icons/icon_etherTokens.svg' import logo from '~/assets/icons/icon_etherTokens.svg'
import { getBalanceInEtherOf } from '~/wallets/getWeb3' import { getBalanceInEtherOf } from '~/logic/wallets/getWeb3'
import { makeToken, type Token } from '~/routes/tokens/store/model/token' import { makeToken, type Token } from '~/routes/tokens/store/model/token'
export const ETH_ADDRESS = '0' export const ETH_ADDRESS = '0'

View File

@ -1,49 +0,0 @@
// @flow
import { getGnosisSafeContract } from '~/wallets/safeContracts'
import { getWeb3 } from '~/wallets/getWeb3'
import { type Safe } from '~/routes/safe/store/model/safe'
import { EMPTY_DATA } from '~/wallets/ethTransactions'
import { executeTransaction, approveTransaction } from '~/wallets/safeOperations'
export const TX_NAME_PARAM = 'txName'
export const TX_DESTINATION_PARAM = 'txDestination'
export const TX_VALUE_PARAM = 'txValue'
export const EXECUTED_CONFIRMATION_HASH = 'EXECUTED'
const hasOneOwner = (safe: Safe) => {
const owners = safe.get('owners')
if (!owners) {
throw new Error('Received a Safe without owners when creating a tx')
}
return owners.count() === 1
}
export const getSafeEthereumInstance = async (safeAddress: string) => {
const web3 = getWeb3()
const GnosisSafe = await getGnosisSafeContract(web3)
return GnosisSafe.at(safeAddress)
}
export const createTransaction = async (
safe: Safe,
name: string,
to: string,
value: number,
nonce: number,
sender: string,
data: string = EMPTY_DATA,
) => {
const web3 = getWeb3()
const safeAddress = safe.get('address')
const threshold = safe.get('threshold')
const valueInWei = web3.toWei(value, 'ether')
const CALL = 0
const isExecution = hasOneOwner(safe) || threshold === 1
return isExecution
? executeTransaction(safeAddress, to, valueInWei, data, CALL, nonce, sender)
: approveTransaction(safeAddress, to, valueInWei, data, CALL, nonce, sender)
}