diff --git a/src/components/Header/actions.js b/src/components/Header/actions.js index aa2884a1..32069043 100644 --- a/src/components/Header/actions.js +++ b/src/components/Header/actions.js @@ -1,5 +1,5 @@ // @flow -import { fetchProvider } from '~/wallets/store/actions' +import { fetchProvider } from '~/logic/wallets/store/actions' export default { fetchProvider, diff --git a/src/components/Header/selector.js b/src/components/Header/selector.js index 86ce5978..11b9dd34 100644 --- a/src/components/Header/selector.js +++ b/src/components/Header/selector.js @@ -1,6 +1,6 @@ // @flow import { createStructuredSelector } from 'reselect' -import { providerNameSelector } from '~/wallets/store/selectors/index' +import { providerNameSelector } from '~/logic/wallets/store/selectors' export default createStructuredSelector({ provider: providerNameSelector, diff --git a/src/components/forms/validator.js b/src/components/forms/validator.js index b921f103..0d0e5956 100644 --- a/src/components/forms/validator.js +++ b/src/components/forms/validator.js @@ -1,6 +1,6 @@ // @flow -import { getWeb3 } from '~/wallets/getWeb3' import { type FieldValidator } from 'final-form' +import { getWeb3 } from '~/logic/wallets/getWeb3' type Field = boolean | string | null | typeof undefined diff --git a/src/logic/contracts/dailyLimitContracts.js b/src/logic/contracts/dailyLimitContracts.js new file mode 100644 index 00000000..7d24f7cb --- /dev/null +++ b/src/logic/contracts/dailyLimitContracts.js @@ -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 => { + 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) +} diff --git a/src/wallets/safeContracts.js b/src/logic/contracts/safeContracts.js similarity index 98% rename from src/wallets/safeContracts.js rename to src/logic/contracts/safeContracts.js index 16910a62..a3b16d72 100644 --- a/src/wallets/safeContracts.js +++ b/src/logic/contracts/safeContracts.js @@ -1,13 +1,13 @@ // @flow import contract from 'truffle-contract' import { ensureOnce } from '~/utils/singleton' -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { promisify } from '~/utils/promisify' import GnosisSafeSol from '#/GnosisSafeTeamEdition.json' import ProxyFactorySol from '#/ProxyFactory.json' import CreateAndAddModules from '#/CreateAndAddModules.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 createAndAddModuleMaster diff --git a/src/wallets/safeOperations.js b/src/logic/safe/safeBlockchainOperations.js similarity index 61% rename from src/wallets/safeOperations.js rename to src/logic/safe/safeBlockchainOperations.js index a563dc60..1539cc9c 100644 --- a/src/wallets/safeOperations.js +++ b/src/logic/safe/safeBlockchainOperations.js @@ -1,7 +1,8 @@ // @flow -import { getSafeEthereumInstance } from '~/wallets/createTransactions' -import { calculateGasOf, checkReceiptStatus, calculateGasPrice } from '~/wallets/ethTransactions' -import { type Operation, submitOperation } from '~/wallets/safeTxHistory' +import { calculateGasOf, checkReceiptStatus, calculateGasPrice } from '~/logic/wallets/ethTransactions' +import { type Operation, submitOperation } from '~/logic/safe/safeTxHistory' +import { getDailyLimitModuleFrom } from '~/logic/contracts/dailyLimitContracts' +import { getSafeEthereumInstance } from '~/logic/safe/safeFrontendOperations' export const approveTransaction = async ( safeAddress: string, @@ -52,3 +53,25 @@ export const executeTransaction = async ( 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 +} diff --git a/src/logic/safe/safeFrontendOperations.js b/src/logic/safe/safeFrontendOperations.js new file mode 100644 index 00000000..547c7584 --- /dev/null +++ b/src/logic/safe/safeFrontendOperations.js @@ -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 => { + 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) +} diff --git a/src/wallets/safeTxHistory.js b/src/logic/safe/safeTxHistory.js similarity index 89% rename from src/wallets/safeTxHistory.js rename to src/logic/safe/safeTxHistory.js index b904e2e1..3f766fa1 100644 --- a/src/wallets/safeTxHistory.js +++ b/src/logic/safe/safeTxHistory.js @@ -1,9 +1,9 @@ // @flow -import { getSafeEthereumInstance } from '~/wallets/createTransactions' -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' 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 const calculateBodyFrom = async ( @@ -32,6 +32,7 @@ const calculateBodyFrom = async ( type, }) } + export const buildTxServiceUrlFrom = (safeAddress: string) => { const host = getTxServiceHost() const address = getWeb3().toChecksumAddress(safeAddress) diff --git a/src/wallets/ethAddresses.js b/src/logic/wallets/ethAddresses.js similarity index 100% rename from src/wallets/ethAddresses.js rename to src/logic/wallets/ethAddresses.js diff --git a/src/wallets/ethTransactions.js b/src/logic/wallets/ethTransactions.js similarity index 96% rename from src/wallets/ethTransactions.js rename to src/logic/wallets/ethTransactions.js index 430dbdb5..a16dc121 100644 --- a/src/wallets/ethTransactions.js +++ b/src/logic/wallets/ethTransactions.js @@ -1,6 +1,6 @@ // @flow import { BigNumber } from 'bignumber.js' -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { promisify } from '~/utils/promisify' import { enhancedFetch } from '~/utils/fetch' diff --git a/src/wallets/getWeb3.js b/src/logic/wallets/getWeb3.js similarity index 95% rename from src/wallets/getWeb3.js rename to src/logic/wallets/getWeb3.js index 8b5e43d3..9ffdcba1 100644 --- a/src/wallets/getWeb3.js +++ b/src/logic/wallets/getWeb3.js @@ -1,7 +1,7 @@ // @flow import { BigNumber } from 'bignumber.js' 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' let web3 diff --git a/src/wallets/store/actions/addProvider.js b/src/logic/wallets/store/actions/addProvider.js similarity index 75% rename from src/wallets/store/actions/addProvider.js rename to src/logic/wallets/store/actions/addProvider.js index eb8aea45..7cff10ab 100644 --- a/src/wallets/store/actions/addProvider.js +++ b/src/logic/wallets/store/actions/addProvider.js @@ -1,6 +1,6 @@ // @flow 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' diff --git a/src/wallets/store/actions/fetchProvider.js b/src/logic/wallets/store/actions/fetchProvider.js similarity index 74% rename from src/wallets/store/actions/fetchProvider.js rename to src/logic/wallets/store/actions/fetchProvider.js index 1463d70c..2fdb2962 100644 --- a/src/wallets/store/actions/fetchProvider.js +++ b/src/logic/wallets/store/actions/fetchProvider.js @@ -1,8 +1,8 @@ // @flow import type { Dispatch as ReduxDispatch } from 'redux' -import { getProviderInfo } from '~/wallets/getWeb3' -import type { ProviderProps } from '~/wallets/store/model/provider' -import { makeProvider } from '~/wallets/store/model/provider' +import { getProviderInfo } from '~/logic/wallets/getWeb3' +import type { ProviderProps } from '~/logic/wallets/store/model/provider' +import { makeProvider } from '~/logic/wallets/store/model/provider' import addProvider from './addProvider' export const processProviderResponse = (dispatch: ReduxDispatch<*>, response: ProviderProps) => { diff --git a/src/wallets/store/actions/index.js b/src/logic/wallets/store/actions/index.js similarity index 100% rename from src/wallets/store/actions/index.js rename to src/logic/wallets/store/actions/index.js diff --git a/src/wallets/store/model/provider.js b/src/logic/wallets/store/model/provider.js similarity index 100% rename from src/wallets/store/model/provider.js rename to src/logic/wallets/store/model/provider.js diff --git a/src/wallets/store/reducer/provider.js b/src/logic/wallets/store/reducer/provider.js similarity index 64% rename from src/wallets/store/reducer/provider.js rename to src/logic/wallets/store/reducer/provider.js index ed3bd1af..90fc43ca 100644 --- a/src/wallets/store/reducer/provider.js +++ b/src/logic/wallets/store/reducer/provider.js @@ -1,7 +1,7 @@ // @flow import { handleActions, type ActionType } from 'redux-actions' -import { makeProvider, type Provider } from '~/wallets/store/model/provider' -import addProvider, { ADD_PROVIDER } from '~/wallets/store/actions/addProvider' +import { makeProvider, type Provider } from '~/logic/wallets/store/model/provider' +import addProvider, { ADD_PROVIDER } from '~/logic/wallets/store/actions/addProvider' export const PROVIDER_REDUCER_ID = 'providers' diff --git a/src/wallets/store/selectors/index.js b/src/logic/wallets/store/selectors/index.js similarity index 80% rename from src/wallets/store/selectors/index.js rename to src/logic/wallets/store/selectors/index.js index 3aaafa80..208acf3a 100644 --- a/src/wallets/store/selectors/index.js +++ b/src/logic/wallets/store/selectors/index.js @@ -1,7 +1,7 @@ // @flow import { createSelector } from 'reselect' -import type { Provider } from '~/wallets/store/model/provider' -import { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider' +import type { Provider } from '~/logic/wallets/store/model/provider' +import { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider' const providerSelector = (state: any): Provider => state[PROVIDER_REDUCER_ID] diff --git a/src/wallets/store/test/account.selector.js b/src/logic/wallets/store/test/account.selector.js similarity index 93% rename from src/wallets/store/test/account.selector.js rename to src/logic/wallets/store/test/account.selector.js index 3c40b133..514a0566 100644 --- a/src/wallets/store/test/account.selector.js +++ b/src/logic/wallets/store/test/account.selector.js @@ -1,5 +1,5 @@ // @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 { ProviderFactory } from './builder/index.builder' diff --git a/src/wallets/store/test/builder/index.builder.js b/src/logic/wallets/store/test/builder/index.builder.js similarity index 89% rename from src/wallets/store/test/builder/index.builder.js rename to src/logic/wallets/store/test/builder/index.builder.js index e78af2e5..2815e5a5 100644 --- a/src/wallets/store/test/builder/index.builder.js +++ b/src/logic/wallets/store/test/builder/index.builder.js @@ -1,6 +1,6 @@ // @flow -import type { Provider } from '~/wallets/store/model/provider' -import { makeProvider } from '~/wallets/store/model/provider' +import type { Provider } from '~/logic/wallets/store/model/provider' +import { makeProvider } from '~/logic/wallets/store/model/provider' class ProviderBuilder { provider: Provider diff --git a/src/wallets/store/test/name.selector.js b/src/logic/wallets/store/test/name.selector.js similarity index 94% rename from src/wallets/store/test/name.selector.js rename to src/logic/wallets/store/test/name.selector.js index 3fae794b..212242a6 100644 --- a/src/wallets/store/test/name.selector.js +++ b/src/logic/wallets/store/test/name.selector.js @@ -1,5 +1,5 @@ // @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 { ProviderFactory } from './builder/index.builder' diff --git a/src/wallets/store/test/provider.reducer.js b/src/logic/wallets/store/test/provider.reducer.js similarity index 89% rename from src/wallets/store/test/provider.reducer.js rename to src/logic/wallets/store/test/provider.reducer.js index 4750a2bf..e9791bb3 100644 --- a/src/wallets/store/test/provider.reducer.js +++ b/src/logic/wallets/store/test/provider.reducer.js @@ -1,9 +1,9 @@ // @flow import { combineReducers, createStore, applyMiddleware, compose } from 'redux' import thunk from 'redux-thunk' -import providerReducer, { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider' -import type { ProviderProps } from '~/wallets/store/model/provider' -import { makeProvider } from '~/wallets/store/model/provider' +import providerReducer, { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider' +import type { ProviderProps } from '~/logic/wallets/store/model/provider' +import { makeProvider } from '~/logic/wallets/store/model/provider' import { processProviderResponse } from '../actions/fetchProvider' const providerReducerTests = () => { diff --git a/src/wallets/store/test/provider.spec.js b/src/logic/wallets/store/test/provider.spec.js similarity index 100% rename from src/wallets/store/test/provider.spec.js rename to src/logic/wallets/store/test/provider.spec.js diff --git a/src/wallets/tokens.js b/src/logic/wallets/tokens.js similarity index 82% rename from src/wallets/tokens.js rename to src/logic/wallets/tokens.js index b8e6be97..3088b8fe 100644 --- a/src/wallets/tokens.js +++ b/src/logic/wallets/tokens.js @@ -1,5 +1,5 @@ // @flow -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { BigNumber } from 'bignumber.js' export const toNative = async (amt: string | number | BigNumber, decimal: number): Promise => { diff --git a/src/routes/open/components/Layout.stories.js b/src/routes/open/components/Layout.stories.js index c3a6af90..c03bc3fc 100644 --- a/src/routes/open/components/Layout.stories.js +++ b/src/routes/open/components/Layout.stories.js @@ -4,7 +4,7 @@ import { State, Store } from '@sambego/storybook-state' import * as React from 'react' import styles from '~/components/layout/PageFrame/index.scss' 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 Component from './Layout' diff --git a/src/routes/open/components/SafeForm/Confirmations/index.test.js b/src/routes/open/components/SafeForm/Confirmations/index.test.js index 3296dea3..9e2cf46d 100644 --- a/src/routes/open/components/SafeForm/Confirmations/index.test.js +++ b/src/routes/open/components/SafeForm/Confirmations/index.test.js @@ -4,7 +4,7 @@ import * as React from 'react' import * as TestUtils from 'react-dom/test-utils' import Layout from '~/routes/open/components/Layout' 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 { CONFIRMATIONS_ERROR } from '~/routes/open/components/SafeForm' diff --git a/src/routes/open/components/SafeForm/Owners/index.test.js b/src/routes/open/components/SafeForm/Owners/index.test.js index 09519333..d42acdf1 100644 --- a/src/routes/open/components/SafeForm/Owners/index.test.js +++ b/src/routes/open/components/SafeForm/Owners/index.test.js @@ -5,7 +5,7 @@ import * as TestUtils from 'react-dom/test-utils' import GnoForm from '~/components/forms/GnoForm' import { FIELD_OWNERS } from '~/routes/open/components/fields' 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 { ADDRESS_REPEATED_ERROR } from '~/components/forms/validator' import Owners from './index' diff --git a/src/routes/open/container/Open.jsx b/src/routes/open/container/Open.jsx index 0c0e0e50..a44e0e08 100644 --- a/src/routes/open/container/Open.jsx +++ b/src/routes/open/container/Open.jsx @@ -4,9 +4,9 @@ import { connect } from 'react-redux' import Page from '~/components/layout/Page' import { getAccountsFrom, getThresholdFrom, getNamesFrom, getSafeNameFrom, getDailyLimitFrom } from '~/routes/open/utils/safeDataExtractor' -import { getWeb3 } from '~/wallets/getWeb3' -import { getGnosisSafeContract, deploySafeContract, initContracts } from '~/wallets/safeContracts' -import { checkReceiptStatus } from '~/wallets/ethTransactions' +import { getWeb3 } from '~/logic/wallets/getWeb3' +import { getGnosisSafeContract, deploySafeContract, initContracts } from '~/logic/contracts/safeContracts' +import { checkReceiptStatus } from '~/logic/wallets/ethTransactions' import selector from './selector' import actions, { type Actions, type AddSafe } from './actions' import Layout from '../components/Layout' diff --git a/src/routes/open/container/selector.js b/src/routes/open/container/selector.js index 2b16c085..efa0903e 100644 --- a/src/routes/open/container/selector.js +++ b/src/routes/open/container/selector.js @@ -1,6 +1,6 @@ // @flow import { createStructuredSelector } from 'reselect' -import { providerNameSelector, userAccountSelector } from '~/wallets/store/selectors/index' +import { providerNameSelector, userAccountSelector } from '~/logic/wallets/store/selectors' export default createStructuredSelector({ provider: providerNameSelector, diff --git a/src/routes/safe/component/AddOwner/index.jsx b/src/routes/safe/component/AddOwner/index.jsx index dcc3fb53..4848882d 100644 --- a/src/routes/safe/component/AddOwner/index.jsx +++ b/src/routes/safe/component/AddOwner/index.jsx @@ -5,8 +5,8 @@ import Stepper from '~/components/Stepper' import { connect } from 'react-redux' import { type Safe } from '~/routes/safe/store/model/safe' import { type Owner, makeOwner } from '~/routes/safe/store/model/owner' -import { getSafeEthereumInstance, createTransaction } from '~/wallets/createTransactions' import { setOwners } from '~/utils/localStorage' +import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations' import AddOwnerForm, { NAME_PARAM, OWNER_ADDRESS_PARAM, INCREASE_PARAM } from './AddOwnerForm' import Review from './Review' import selector, { type SelectorProps } from './selector' diff --git a/src/routes/safe/component/AddOwner/selector.js b/src/routes/safe/component/AddOwner/selector.js index 9e7bfef1..cefe3460 100644 --- a/src/routes/safe/component/AddOwner/selector.js +++ b/src/routes/safe/component/AddOwner/selector.js @@ -1,6 +1,6 @@ // @flow import { createStructuredSelector } from 'reselect' -import { userAccountSelector } from '~/wallets/store/selectors/index' +import { userAccountSelector } from '~/logic/wallets/store/selectors' export type SelectorProps = { userAddress: userAccountSelector, diff --git a/src/routes/safe/component/EditDailyLimit/index.jsx b/src/routes/safe/component/EditDailyLimit/index.jsx index fed1ef4e..3458b944 100644 --- a/src/routes/safe/component/EditDailyLimit/index.jsx +++ b/src/routes/safe/component/EditDailyLimit/index.jsx @@ -2,9 +2,9 @@ import * as React from 'react' import Stepper from '~/components/Stepper' 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 { createTransaction } from '~/logic/safe/safeFrontendOperations' +import { getEditDailyLimitData, getDailyLimitAddress } from '~/logic/contracts/dailyLimitContracts' import EditDailyLimitForm, { EDIT_DAILY_LIMIT_PARAM } from './EditDailyLimitForm' import selector, { type SelectorProps } from './selector' import actions, { type Actions } from './actions' diff --git a/src/routes/safe/component/EditDailyLimit/selector.js b/src/routes/safe/component/EditDailyLimit/selector.js index 9e7bfef1..cefe3460 100644 --- a/src/routes/safe/component/EditDailyLimit/selector.js +++ b/src/routes/safe/component/EditDailyLimit/selector.js @@ -1,6 +1,6 @@ // @flow import { createStructuredSelector } from 'reselect' -import { userAccountSelector } from '~/wallets/store/selectors/index' +import { userAccountSelector } from '~/logic/wallets/store/selectors' export type SelectorProps = { userAddress: userAccountSelector, diff --git a/src/routes/safe/component/RemoveOwner/index.jsx b/src/routes/safe/component/RemoveOwner/index.jsx index 25af2595..05bf46b7 100644 --- a/src/routes/safe/component/RemoveOwner/index.jsx +++ b/src/routes/safe/component/RemoveOwner/index.jsx @@ -3,7 +3,7 @@ import * as React from 'react' import Stepper from '~/components/Stepper' import { connect } from 'react-redux' import { type Safe } from '~/routes/safe/store/model/safe' -import { getSafeEthereumInstance, createTransaction } from '~/wallets/createTransactions' +import { getSafeEthereumInstance, createTransaction } from '~/logic/safe/safeFrontendOperations' import RemoveOwnerForm, { DECREASE_PARAM } from './RemoveOwnerForm' import Review from './Review' import selector, { type SelectorProps } from './selector' diff --git a/src/routes/safe/component/RemoveOwner/selector.js b/src/routes/safe/component/RemoveOwner/selector.js index bbacdf85..54a4104a 100644 --- a/src/routes/safe/component/RemoveOwner/selector.js +++ b/src/routes/safe/component/RemoveOwner/selector.js @@ -1,7 +1,7 @@ // @flow import { List } from 'immutable' 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 { safeTransactionsSelector } from '~/routes/safe/store/selectors/index' diff --git a/src/routes/safe/component/Safe/Owners.jsx b/src/routes/safe/component/Safe/Owners.jsx index 74a8802a..e4082eba 100644 --- a/src/routes/safe/component/Safe/Owners.jsx +++ b/src/routes/safe/component/Safe/Owners.jsx @@ -17,7 +17,7 @@ import ExpandLess from '@material-ui/icons/ExpandLess' import ExpandMore from '@material-ui/icons/ExpandMore' import { type OwnerProps } from '~/routes/safe/store/model/owner' import { type WithStyles } from '~/theme/mui' -import { sameAddress } from '~/wallets/ethAddresses' +import { sameAddress } from '~/logic/wallets/ethAddresses' const styles = { nested: { diff --git a/src/routes/safe/component/SendToken/index.jsx b/src/routes/safe/component/SendToken/index.jsx index 4807d9dd..5adfcaa4 100644 --- a/src/routes/safe/component/SendToken/index.jsx +++ b/src/routes/safe/component/SendToken/index.jsx @@ -7,10 +7,10 @@ import { sleep } from '~/utils/timer' import { type Safe } from '~/routes/safe/store/model/safe' import { getStandardTokenContract } from '~/routes/tokens/store/actions/fetchTokens' 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 { 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 selector, { type SelectorProps } from './selector' import SendTokenForm, { TKN_DESTINATION_PARAM, TKN_VALUE_PARAM } from './SendTokenForm' diff --git a/src/routes/safe/component/SendToken/selector.js b/src/routes/safe/component/SendToken/selector.js index 9e7bfef1..cefe3460 100644 --- a/src/routes/safe/component/SendToken/selector.js +++ b/src/routes/safe/component/SendToken/selector.js @@ -1,6 +1,6 @@ // @flow import { createStructuredSelector } from 'reselect' -import { userAccountSelector } from '~/wallets/store/selectors/index' +import { userAccountSelector } from '~/logic/wallets/store/selectors' export type SelectorProps = { userAddress: userAccountSelector, diff --git a/src/routes/safe/component/Threshold/index.jsx b/src/routes/safe/component/Threshold/index.jsx index d90f831d..e78c0929 100644 --- a/src/routes/safe/component/Threshold/index.jsx +++ b/src/routes/safe/component/Threshold/index.jsx @@ -2,7 +2,7 @@ import * as React from 'react' import Stepper from '~/components/Stepper' 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 ThresholdForm, { THRESHOLD_PARAM } from './ThresholdForm' import selector, { type SelectorProps } from './selector' diff --git a/src/routes/safe/component/Threshold/selector.js b/src/routes/safe/component/Threshold/selector.js index 9e7bfef1..cefe3460 100644 --- a/src/routes/safe/component/Threshold/selector.js +++ b/src/routes/safe/component/Threshold/selector.js @@ -1,6 +1,6 @@ // @flow import { createStructuredSelector } from 'reselect' -import { userAccountSelector } from '~/wallets/store/selectors/index' +import { userAccountSelector } from '~/logic/wallets/store/selectors' export type SelectorProps = { userAddress: userAccountSelector, diff --git a/src/routes/safe/component/Transactions/Transaction/index.jsx b/src/routes/safe/component/Transactions/Transaction/index.jsx index 3d28ff40..de6c03ae 100644 --- a/src/routes/safe/component/Transactions/Transaction/index.jsx +++ b/src/routes/safe/component/Transactions/Transaction/index.jsx @@ -19,7 +19,7 @@ import Collapsed from '~/routes/safe/component/Transactions/Collapsed' import { type Transaction } from '~/routes/safe/store/model/transaction' import Hairline from '~/components/layout/Hairline/index' 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 selector, { type SelectorProps } from './selector' diff --git a/src/routes/safe/component/Transactions/Transaction/selector.js b/src/routes/safe/component/Transactions/Transaction/selector.js index 09d286cd..e78a79b3 100644 --- a/src/routes/safe/component/Transactions/Transaction/selector.js +++ b/src/routes/safe/component/Transactions/Transaction/selector.js @@ -1,7 +1,7 @@ // @flow import { createStructuredSelector } from 'reselect' 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 GlobalState } from '~/store' import { type Confirmation } from '~/routes/safe/store/model/confirmation' diff --git a/src/routes/safe/component/Transactions/index.jsx b/src/routes/safe/component/Transactions/index.jsx index 663a1067..181a73c3 100644 --- a/src/routes/safe/component/Transactions/index.jsx +++ b/src/routes/safe/component/Transactions/index.jsx @@ -4,7 +4,9 @@ import { connect } from 'react-redux' import { type Transaction } from '~/routes/safe/store/model/transaction' import NoTransactions from '~/routes/safe/component/Transactions/NoTransactions' 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 actions, { type Actions } from './actions' @@ -17,10 +19,22 @@ type Props = SelectorProps & Actions & { class Transactions extends React.Component { onProcessTx = async (tx: Transaction, alreadyConfirmed: number) => { const { - fetchTransactions, safeAddress, userAddress, + fetchTransactions, safeAddress, userAddress, threshold, } = 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() } diff --git a/src/routes/safe/component/Transactions/processTransactions.js b/src/routes/safe/component/Transactions/processTransactions.js deleted file mode 100644 index 0ef47b58..00000000 --- a/src/routes/safe/component/Transactions/processTransactions.js +++ /dev/null @@ -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, - 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, 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 = - updateConfirmations(tx.get('confirmations'), userAddress, confirmationHash) - - return updateTransaction( - txName, - nonce, - txDestination, - txValue, - userAddress, - executedConfirmations, - thresholdReached ? txHash.tx : '', - safeAddress, - threshold, - data, - ) -} diff --git a/src/routes/safe/component/Transactions/selector.js b/src/routes/safe/component/Transactions/selector.js index 4d3c1a6f..4097dc64 100644 --- a/src/routes/safe/component/Transactions/selector.js +++ b/src/routes/safe/component/Transactions/selector.js @@ -3,7 +3,7 @@ import { List } from 'immutable' import { createStructuredSelector } from 'reselect' import { type Transaction } from '~/routes/safe/store/model/transaction' 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 = { transactions: List, diff --git a/src/routes/safe/component/Withdraw/Review/index.jsx b/src/routes/safe/component/Withdraw/Review/index.jsx index 6fa35221..3c08d580 100644 --- a/src/routes/safe/component/Withdraw/Review/index.jsx +++ b/src/routes/safe/component/Withdraw/Review/index.jsx @@ -5,7 +5,7 @@ import Block from '~/components/layout/Block' import Bold from '~/components/layout/Bold' import Heading from '~/components/layout/Heading' 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 = { values: Object, diff --git a/src/routes/safe/component/Withdraw/WithdrawForm/index.jsx b/src/routes/safe/component/Withdraw/WithdrawForm/index.jsx index ac69aac4..e093e847 100644 --- a/src/routes/safe/component/Withdraw/WithdrawForm/index.jsx +++ b/src/routes/safe/component/Withdraw/WithdrawForm/index.jsx @@ -5,9 +5,10 @@ import TextField from '~/components/forms/TextField' import { composeValidators, inLimit, mustBeFloat, required, greaterThan, mustBeEthereumAddress } from '~/components/forms/validator' import Block from '~/components/layout/Block' 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 DESTINATION_PARAM = 'destination' +export const VALUE_PARAM = 'ether' export const safeFieldsValidation = (values: Object) => { const errors = {} diff --git a/src/routes/safe/component/Withdraw/index.jsx b/src/routes/safe/component/Withdraw/index.jsx index 9368cadd..999e643e 100644 --- a/src/routes/safe/component/Withdraw/index.jsx +++ b/src/routes/safe/component/Withdraw/index.jsx @@ -4,8 +4,8 @@ import { connect } from 'react-redux' import Stepper from '~/components/Stepper' import { type DailyLimit } from '~/routes/safe/store/model/dailyLimit' import { type Safe } from '~/routes/safe/store/model/safe' +import { withdraw } from '~/logic/safe/safeFrontendOperations' import selector, { type SelectorProps } from './selector' -import withdraw from './withdraw' import WithdrawForm from './WithdrawForm' import Review from './Review' import actions, { type Actions } from './actions' diff --git a/src/routes/safe/component/Withdraw/selector.js b/src/routes/safe/component/Withdraw/selector.js index 9e7bfef1..cefe3460 100644 --- a/src/routes/safe/component/Withdraw/selector.js +++ b/src/routes/safe/component/Withdraw/selector.js @@ -1,6 +1,6 @@ // @flow import { createStructuredSelector } from 'reselect' -import { userAccountSelector } from '~/wallets/store/selectors/index' +import { userAccountSelector } from '~/logic/wallets/store/selectors' export type SelectorProps = { userAddress: userAccountSelector, diff --git a/src/routes/safe/component/Withdraw/withdraw.js b/src/routes/safe/component/Withdraw/withdraw.js deleted file mode 100644 index ecbe9828..00000000 --- a/src/routes/safe/component/Withdraw/withdraw.js +++ /dev/null @@ -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 => { - 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 => { - 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 = 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 diff --git a/src/routes/safe/container/selector.js b/src/routes/safe/container/selector.js index 01276699..8c565663 100644 --- a/src/routes/safe/container/selector.js +++ b/src/routes/safe/container/selector.js @@ -2,11 +2,11 @@ import { List } from 'immutable' import { createSelector, createStructuredSelector, type Selector } from 'reselect' 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 Owner } from '~/routes/safe/store/model/owner' import { type GlobalState } from '~/store' -import { sameAddress } from '~/wallets/ethAddresses' +import { sameAddress } from '~/logic/wallets/ethAddresses' import { activeTokensSelector } from '~/routes/tokens/store/selectors' import { type Token } from '~/routes/tokens/store/model/token' diff --git a/src/routes/safe/store/actions/fetchSafe.js b/src/routes/safe/store/actions/fetchSafe.js index 7f41f8b9..5c94997f 100644 --- a/src/routes/safe/store/actions/fetchSafe.js +++ b/src/routes/safe/store/actions/fetchSafe.js @@ -5,10 +5,10 @@ import { type GlobalState } from '~/store/index' import { makeOwner } from '~/routes/safe/store/model/owner' import { type SafeProps, type Safe, makeSafe } from '~/routes/safe/store/model/safe' 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 { getOwners } from '~/utils/localStorage' +import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' +import { getDailyLimitFrom } from '~/logic/contracts/dailyLimitContracts' const buildOwnersFrom = (safeOwners: string[], storedOwners: Map) => ( safeOwners.map((ownerAddress: string) => { diff --git a/src/routes/safe/store/actions/fetchTransactions.js b/src/routes/safe/store/actions/fetchTransactions.js index 9282d582..db0dd14d 100644 --- a/src/routes/safe/store/actions/fetchTransactions.js +++ b/src/routes/safe/store/actions/fetchTransactions.js @@ -7,7 +7,7 @@ import { makeTransaction, type Transaction } from '~/routes/safe/store/model/tra import { load, TX_KEY } from '~/utils/localStorage' import { makeConfirmation } from '~/routes/safe/store/model/confirmation' 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 addTransactions from './addTransactions' diff --git a/src/routes/safe/store/model/confirmation.js b/src/routes/safe/store/model/confirmation.js index d0d4018d..46227df4 100644 --- a/src/routes/safe/store/model/confirmation.js +++ b/src/routes/safe/store/model/confirmation.js @@ -2,7 +2,7 @@ import { Record } from 'immutable' import type { RecordFactory, RecordOf } from 'immutable' 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 = { owner: Owner, @@ -12,7 +12,7 @@ export type ConfirmationProps = { export const makeConfirmation: RecordFactory = Record({ owner: makeOwner(), - type: 'confirmation', + type: 'initialised', hash: '', }) diff --git a/src/routes/safe/store/test/builder/deployedSafe.builder.js b/src/routes/safe/store/test/builder/deployedSafe.builder.js index bd8253d1..3ad683ac 100644 --- a/src/routes/safe/store/test/builder/deployedSafe.builder.js +++ b/src/routes/safe/store/test/builder/deployedSafe.builder.js @@ -8,12 +8,13 @@ import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation import Open from '~/routes/open/container/Open' import { history, type GlobalState } from '~/store' import { sleep } from '~/utils/timer' -import { getProviderInfo, getWeb3 } from '~/wallets/getWeb3' -import addProvider from '~/wallets/store/actions/addProvider' -import { makeProvider } from '~/wallets/store/model/provider' -import withdraw, { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/withdraw' +import { getProviderInfo, getWeb3 } from '~/logic/wallets/getWeb3' +import addProvider from '~/logic/wallets/store/actions/addProvider' +import { makeProvider } from '~/logic/wallets/store/model/provider' import { promisify } from '~/utils/promisify' 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) => { const provider = await getProviderInfo() diff --git a/src/routes/safe/store/test/granted.selector.js b/src/routes/safe/store/test/granted.selector.js index cf51cd68..9db2e965 100644 --- a/src/routes/safe/store/test/granted.selector.js +++ b/src/routes/safe/store/test/granted.selector.js @@ -5,9 +5,9 @@ import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' import { type Safe } from '~/routes/safe/store/model/safe' import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder' 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 { makeProvider } from '~/wallets/store/model/provider' +import { makeProvider } from '~/logic/wallets/store/model/provider' const grantedSelectorTests = () => { let provider diff --git a/src/routes/safe/test/Safe.threshold.test.js b/src/routes/safe/test/Safe.threshold.test.js index 9576b597..edcd2627 100644 --- a/src/routes/safe/test/Safe.threshold.test.js +++ b/src/routes/safe/test/Safe.threshold.test.js @@ -2,7 +2,7 @@ /* import { aNewStore } from '~/store' 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 { type Match } from 'react-router-dom' import { promisify } from '~/utils/promisify' diff --git a/src/routes/safeList/container/selector.js b/src/routes/safeList/container/selector.js index e71e7cb7..101e6bfc 100644 --- a/src/routes/safeList/container/selector.js +++ b/src/routes/safeList/container/selector.js @@ -1,7 +1,7 @@ // @flow import { createStructuredSelector } from 'reselect' import { safesByOwnerSelector } from '~/routes/safeList/store/selectors' -import { providerNameSelector } from '~/wallets/store/selectors/index' +import { providerNameSelector } from '~/logic/wallets/store/selectors' export default createStructuredSelector({ safes: safesByOwnerSelector, diff --git a/src/routes/safeList/store/selectors/index.js b/src/routes/safeList/store/selectors/index.js index 40ed28b4..8832de63 100644 --- a/src/routes/safeList/store/selectors/index.js +++ b/src/routes/safeList/store/selectors/index.js @@ -3,9 +3,9 @@ import { List, Map } from 'immutable' import { createSelector, type Selector } from 'reselect' import { type GlobalState } from '~/store/index' import { type Safe } from '~/routes/safe/store/model/safe' -import { userAccountSelector } from '~/wallets/store/selectors/index' +import { userAccountSelector } from '~/logic/wallets/store/selectors' 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 => state.safes const safesListSelector: Selector> = createSelector( diff --git a/src/routes/safeList/store/test/safes.selector.js b/src/routes/safeList/store/test/safes.selector.js index a5f20230..2ce17dc8 100644 --- a/src/routes/safeList/store/test/safes.selector.js +++ b/src/routes/safeList/store/test/safes.selector.js @@ -2,10 +2,10 @@ import { List, Map } from 'immutable' import { SAFE_REDUCER_ID } from '~/routes/safe/store/reducer/safe' import { type Safe } from '~/routes/safe/store/model/safe' -import { getProviderInfo } from '~/wallets/getWeb3' +import { getProviderInfo } from '~/logic/wallets/getWeb3' import { SafeFactory } from '~/routes/safe/store/test/builder/safe.builder' -import { PROVIDER_REDUCER_ID } from '~/wallets/store/reducer/provider' -import { makeProvider, type Provider } from '~/wallets/store/model/provider' +import { PROVIDER_REDUCER_ID } from '~/logic/wallets/store/reducer/provider' +import { makeProvider, type Provider } from '~/logic/wallets/store/model/provider' import { safesByOwnerSelector } from '../selectors' const safesListSelectorTests = () => { diff --git a/src/routes/tokens/component/AddToken/FirstPage.jsx b/src/routes/tokens/component/AddToken/FirstPage.jsx index 05535ff1..6bd7e89e 100644 --- a/src/routes/tokens/component/AddToken/FirstPage.jsx +++ b/src/routes/tokens/component/AddToken/FirstPage.jsx @@ -6,8 +6,8 @@ import { composeValidators, required, mustBeEthereumAddress, uniqueAddress } fro import Block from '~/components/layout/Block' import Heading from '~/components/layout/Heading' import { promisify } from '~/utils/promisify' -import { getWeb3 } from '~/wallets/getWeb3' -import { EMPTY_DATA } from '~/wallets/ethTransactions' +import { getWeb3 } from '~/logic/wallets/getWeb3' +import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import { getStandardTokenContract } from '~/routes/tokens/store/actions/fetchTokens' type Props = { diff --git a/src/routes/tokens/component/AddToken/index.jsx b/src/routes/tokens/component/AddToken/index.jsx index 79435080..82580cd9 100644 --- a/src/routes/tokens/component/AddToken/index.jsx +++ b/src/routes/tokens/component/AddToken/index.jsx @@ -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 { makeToken, type Token } from '~/routes/tokens/store/model/token' 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 { EMPTY_DATA } from '~/wallets/ethTransactions' +import { EMPTY_DATA } from '~/logic/wallets/ethTransactions' import Review from './Review' export const getSteps = () => [ diff --git a/src/routes/tokens/store/actions/fetchTokens.js b/src/routes/tokens/store/actions/fetchTokens.js index 60c40979..35899c49 100644 --- a/src/routes/tokens/store/actions/fetchTokens.js +++ b/src/routes/tokens/store/actions/fetchTokens.js @@ -4,7 +4,7 @@ import contract from 'truffle-contract' import type { Dispatch as ReduxDispatch } from 'redux' import StandardToken from '@gnosis.pm/util-contracts/build/contracts/StandardToken.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 { makeToken, type Token, type TokenProps } from '~/routes/tokens/store/model/token' import { ensureOnce } from '~/utils/singleton' diff --git a/src/routes/welcome/container/selector.js b/src/routes/welcome/container/selector.js index 86ce5978..11b9dd34 100644 --- a/src/routes/welcome/container/selector.js +++ b/src/routes/welcome/container/selector.js @@ -1,6 +1,6 @@ // @flow import { createStructuredSelector } from 'reselect' -import { providerNameSelector } from '~/wallets/store/selectors/index' +import { providerNameSelector } from '~/logic/wallets/store/selectors' export default createStructuredSelector({ provider: providerNameSelector, diff --git a/src/store/index.js b/src/store/index.js index 48924c8a..cb93ed1e 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,7 +3,7 @@ import { createBrowserHistory } from 'history' import { routerMiddleware, routerReducer } from 'react-router-redux' import { combineReducers, createStore, applyMiddleware, compose, type Reducer, type Store } from 'redux' 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 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' diff --git a/src/test/builder/safe.dom.builder.js b/src/test/builder/safe.dom.builder.js index 02aa2f82..70674d7b 100644 --- a/src/test/builder/safe.dom.builder.js +++ b/src/test/builder/safe.dom.builder.js @@ -4,7 +4,7 @@ import TestUtils from 'react-dom/test-utils' import SafeView from '~/routes/safe/component/Safe' import { aNewStore, type GlobalState } from '~/store' import { sleep } from '~/utils/timer' -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { promisify } from '~/utils/promisify' import { addEtherTo } from '~/test/utils/tokenMovements' import { aMinedSafe } from '~/test/builder/safe.redux.builder' diff --git a/src/test/builder/safe.dom.utils.js b/src/test/builder/safe.dom.utils.js index 3b50c0d6..461b1960 100644 --- a/src/test/builder/safe.dom.utils.js +++ b/src/test/builder/safe.dom.utils.js @@ -10,7 +10,7 @@ import { ConnectedRouter } from 'react-router-redux' import AppRoutes from '~/routes' import { SAFELIST_ADDRESS, SETTINS_ADDRESS } from '~/routes/routes' 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_OWNERS_INDEX = 1 diff --git a/src/test/builder/safe.redux.builder.js b/src/test/builder/safe.redux.builder.js index 9c467981..0fe8c34b 100644 --- a/src/test/builder/safe.redux.builder.js +++ b/src/test/builder/safe.redux.builder.js @@ -2,13 +2,13 @@ import { makeSafe, type Safe } from '~/routes/safe/store/model/safe' 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 { getWeb3, getProviderInfo } from '~/wallets/getWeb3' +import { getWeb3, getProviderInfo } from '~/logic/wallets/getWeb3' import { promisify } from '~/utils/promisify' import addSafe from '~/routes/safe/store/actions/addSafe' import { createSafe, type OpenState } from '~/routes/open/container/Open' import { type GlobalState } from '~/store/index' -import { makeProvider } from '~/wallets/store/model/provider' -import addProvider from '~/wallets/store/actions/addProvider' +import { makeProvider } from '~/logic/wallets/store/model/provider' +import addProvider from '~/logic/wallets/store/actions/addProvider' class SafeBuilder { safe: Safe diff --git a/src/test/safe.dom.create.test.js b/src/test/safe.dom.create.test.js index e3ed3d4b..67086964 100644 --- a/src/test/safe.dom.create.test.js +++ b/src/test/safe.dom.create.test.js @@ -8,9 +8,9 @@ import { DEPLOYED_COMPONENT_ID } from '~/routes/open/components/FormConfirmation import Open from '~/routes/open/container/Open' import { aNewStore, history, type GlobalState } from '~/store' import { sleep } from '~/utils/timer' -import { getProviderInfo, getWeb3 } from '~/wallets/getWeb3' -import addProvider from '~/wallets/store/actions/addProvider' -import { makeProvider } from '~/wallets/store/model/provider' +import { getProviderInfo, getWeb3 } from '~/logic/wallets/getWeb3' +import addProvider from '~/logic/wallets/store/actions/addProvider' +import { makeProvider } from '~/logic/wallets/store/model/provider' import { promisify } from '~/utils/promisify' const fillOpenSafeForm = async (localStore: Store) => { diff --git a/src/test/safe.dom.tokens.test.js b/src/test/safe.dom.tokens.test.js index 858524ea..3174373f 100644 --- a/src/test/safe.dom.tokens.test.js +++ b/src/test/safe.dom.tokens.test.js @@ -7,7 +7,7 @@ import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { addTknTo, getFirstTokenContract } from '~/test/utils/tokenMovements' import { EXPAND_BALANCE_INDEX, travelToSafe } from '~/test/builder/safe.dom.utils' 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 { sleep } from '~/utils/timer' diff --git a/src/test/safe.dom.transactions.test.js b/src/test/safe.dom.transactions.test.js index 517e0428..71a88841 100644 --- a/src/test/safe.dom.transactions.test.js +++ b/src/test/safe.dom.transactions.test.js @@ -8,9 +8,9 @@ import { sendAddOwnerForm, checkMinedAddOwnerTx, checkPendingAddOwnerTx } from ' import { sendRemoveOwnerForm, checkMinedRemoveOwnerTx, checkPendingRemoveOwnerTx } from '~/test/utils/transactions/removeOwner.helper' import { checkMinedThresholdTx, sendChangeThresholdForm, checkThresholdOf } from '~/test/utils/transactions/threshold.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 { sleep } from '~/utils/timer' +import { processTransaction } from '~/logic/safe/safeFrontendOperations' describe('DOM > Feature > SAFE MULTISIG Transactions', () => { let domSafe: DomSafe @@ -71,10 +71,11 @@ describe('DOM > Feature > SAFE MULTISIG Transactions', () => { let transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction) expect(transactions.length).toBe(7) + await checkThresholdOf(address, 3) // WHEN... processing pending TXs - await processTransaction(address, transactions[4].props.transaction, 1, accounts[1]) - await processTransaction(address, transactions[5].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], 3) await refreshTransactions(store) // 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]'] 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) transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction) 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 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 checkThresholdOf(address, 2) transactions = TestUtils.scryRenderedComponentsWithType(SafeDom, Transaction) @@ -112,7 +113,7 @@ describe('DOM > Feature > SAFE MULTISIG Transactions', () => { // THEN 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) }) }) diff --git a/src/test/safe.redux.owners.test.js b/src/test/safe.redux.owners.test.js index a6f533a2..ce83dbd7 100644 --- a/src/test/safe.redux.owners.test.js +++ b/src/test/safe.redux.owners.test.js @@ -1,13 +1,12 @@ // @flow import { aNewStore } from '~/store' -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { promisify } from '~/utils/promisify' -import { processTransaction } from '~/routes/safe/component/Transactions/processTransactions' import { confirmationsTransactionSelector } from '~/routes/safe/store/selectors/index' import { getTransactionFromReduxStore } from '~/routes/safe/test/testMultisig' import fetchTransactions from '~/routes/safe/store/actions/fetchTransactions' 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 { NAME_PARAM, OWNER_ADDRESS_PARAM, INCREASE_PARAM } from '~/routes/safe/component/AddOwner/AddOwnerForm' 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 { DECREASE_PARAM } from '~/routes/safe/component/RemoveOwner/RemoveOwnerForm/index' import { getSafeFrom } from '~/test/utils/safeHelper' +import { processTransaction } from '~/logic/safe/safeFrontendOperations' 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) if (!tx) throw new Error() 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(undefined) expect(data).not.toBe('') - return processTransaction(safeAddress, tx, confirmed, executor) + return processTransaction(safeAddress, tx, confirmed, executor, threshold) } const assureThresholdIs = async (gnosisSafe, threshold: number) => { @@ -116,9 +116,9 @@ describe('React DOM TESTS > Add and remove owners', () => { let safe = getSafeFrom(store.getState(), address) await removeOwner(values, safe, threshold, accounts[1], 'Adol Metamask 2', accounts[0]) 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 store.dispatch(fetchSafe(safe)) @@ -141,9 +141,9 @@ describe('React DOM TESTS > Add and remove owners', () => { let safe = getSafeFrom(store.getState(), address) await removeOwner(values, safe, threshold, accounts[2], 'Adol Metamask 3', accounts[0]) 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 store.dispatch(fetchSafe(safe)) @@ -167,7 +167,7 @@ describe('React DOM TESTS > Add and remove owners', () => { let safe = getSafeFrom(store.getState(), address) await removeOwner(values, safe, threshold, accounts[2], 'Adol Metamask 3', accounts[0]) await store.dispatch(fetchTransactions()) - await processOwnerModification(store, address, accounts[1]) + await processOwnerModification(store, address, accounts[1], 2) await assureThresholdIs(gnosisSafe, 2) await assureOwnersAre(gnosisSafe, accounts[0], accounts[1]) diff --git a/src/test/safe.redux.transactions.test.js b/src/test/safe.redux.transactions.test.js index 004a328b..59250a34 100644 --- a/src/test/safe.redux.transactions.test.js +++ b/src/test/safe.redux.transactions.test.js @@ -1,6 +1,6 @@ // @flow 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 { makeOwner } from '~/routes/safe/store/model/owner' 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 { getSafeFrom } from '~/test/utils/safeHelper' import { promisify } from '~/utils/promisify' -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { safeTransactionsSelector } from '~/routes/safe/store/selectors' import { testTransactionFrom, testSizeOfTransactions } from './utils/historyServiceHelper' diff --git a/src/test/safe.redux.withdraw.test.js b/src/test/safe.redux.withdraw.test.js index af8a1a80..7b45cc80 100644 --- a/src/test/safe.redux.withdraw.test.js +++ b/src/test/safe.redux.withdraw.test.js @@ -10,15 +10,15 @@ import { SAFELIST_ADDRESS } from '~/routes/routes' import SafeView from '~/routes/safe/component/Safe' import AppRoutes from '~/routes' 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 { getDailyLimitFrom } from '~/routes/safe/component/Withdraw/withdraw' import { type DailyLimitProps } from '~/routes/safe/store/model/dailyLimit' import { WITHDRAW_INDEX } from '~/test/builder/safe.dom.utils' import { aMinedSafe } from '~/test/builder/safe.redux.builder' import { getSafeFrom } from '~/test/utils/safeHelper' import { filterMoveButtonsFrom } from '~/test/builder/safe.dom.builder' import { fetchTokens } from '~/routes/tokens/store/actions/fetchTokens' +import { getDailyLimitFrom } from '~/logic/contracts/dailyLimitContracts' describe('React DOM TESTS > Withdraw funds from safe', () => { let store diff --git a/src/test/tokens.dom.adding.test.js b/src/test/tokens.dom.adding.test.js index a39312ab..0869bc74 100644 --- a/src/test/tokens.dom.adding.test.js +++ b/src/test/tokens.dom.adding.test.js @@ -1,6 +1,6 @@ // @flow 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 { promisify } from '~/utils/promisify' import TokenComponent from '~/routes/tokens/component/Token' diff --git a/src/test/tokens.dom.enabling.test.js b/src/test/tokens.dom.enabling.test.js index fc2b012e..08bd190c 100644 --- a/src/test/tokens.dom.enabling.test.js +++ b/src/test/tokens.dom.enabling.test.js @@ -1,7 +1,7 @@ // @flow import * as TestUtils from 'react-dom/test-utils' import { List } from 'immutable' -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { type Match } from 'react-router-dom' import { promisify } from '~/utils/promisify' import TokenComponent from '~/routes/tokens/component/Token' diff --git a/src/test/tokens.dom.removing.test.js b/src/test/tokens.dom.removing.test.js index 06a8dd1d..23a42867 100644 --- a/src/test/tokens.dom.removing.test.js +++ b/src/test/tokens.dom.removing.test.js @@ -1,6 +1,6 @@ // @flow 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 { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements' import { aNewStore } from '~/store' diff --git a/src/test/tokens.redux.adding.test.js b/src/test/tokens.redux.adding.test.js index 954c9037..f89b2409 100644 --- a/src/test/tokens.redux.adding.test.js +++ b/src/test/tokens.redux.adding.test.js @@ -1,5 +1,5 @@ // @flow -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { type Match } from 'react-router-dom' import { promisify } from '~/utils/promisify' import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements' diff --git a/src/test/tokens.redux.remove.test.js b/src/test/tokens.redux.remove.test.js index 1c08934c..b8d5188a 100644 --- a/src/test/tokens.redux.remove.test.js +++ b/src/test/tokens.redux.remove.test.js @@ -1,5 +1,5 @@ // @flow -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import { type Match } from 'react-router-dom' import { promisify } from '~/utils/promisify' import { getFirstTokenContract, getSecondTokenContract } from '~/test/utils/tokenMovements' diff --git a/src/test/utils/ethereumErrors.js b/src/test/utils/ethereumErrors.js index b28a3b7d..e2aeef63 100644 --- a/src/test/utils/ethereumErrors.js +++ b/src/test/utils/ethereumErrors.js @@ -1,5 +1,5 @@ // @flow -import { getWeb3 } from '~/wallets/getWeb3' +import { getWeb3 } from '~/logic/wallets/getWeb3' import abi from 'ethereumjs-abi' import { promisify } from '~/utils/promisify' diff --git a/src/test/utils/logTransactions.js b/src/test/utils/logTransactions.js index 2ed5d336..d668c861 100644 --- a/src/test/utils/logTransactions.js +++ b/src/test/utils/logTransactions.js @@ -1,5 +1,5 @@ // @flow -import { getGnosisSafeInstanceAt } from '~/wallets/safeContracts' +import { getGnosisSafeInstanceAt } from '~/logic/contracts/safeContracts' import GnoStepper from '~/components/Stepper' import Stepper from '@material-ui/core/Stepper' import TestUtils from 'react-dom/test-utils' diff --git a/src/test/utils/tokenMovements.js b/src/test/utils/tokenMovements.js index 933ab8a9..5838f46d 100644 --- a/src/test/utils/tokenMovements.js +++ b/src/test/utils/tokenMovements.js @@ -1,12 +1,13 @@ // @flow 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 withdraw, { DESTINATION_PARAM, VALUE_PARAM } from '~/routes/safe/component/Withdraw/withdraw' import { type Safe } from '~/routes/safe/store/model/safe' import Token from '#/test/TestToken.json' 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) => { const web3 = getWeb3() diff --git a/src/test/utils/transactions/threshold.helper.js b/src/test/utils/transactions/threshold.helper.js index 7d396c67..4ebd5c04 100644 --- a/src/test/utils/transactions/threshold.helper.js +++ b/src/test/utils/transactions/threshold.helper.js @@ -2,7 +2,7 @@ import TestUtils from 'react-dom/test-utils' import { sleep } from '~/utils/timer' 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 { whenExecuted } from '~/test/utils/logTransactions' diff --git a/src/utils/tokens.js b/src/utils/tokens.js index 6dc1f89c..dc0b33e5 100644 --- a/src/utils/tokens.js +++ b/src/utils/tokens.js @@ -1,7 +1,7 @@ // @flow import { List } from 'immutable' 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' export const ETH_ADDRESS = '0' diff --git a/src/wallets/createTransactions.js b/src/wallets/createTransactions.js deleted file mode 100644 index f22f052e..00000000 --- a/src/wallets/createTransactions.js +++ /dev/null @@ -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) -}