mirror of
https://github.com/status-im/safe-react.git
synced 2025-02-17 12:07:09 +00:00
WA-232 Fix get balance of custom tokens
This commit is contained in:
parent
3e2636b02b
commit
9ca0f2e41a
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { aNewStore } from '~/store'
|
import { aNewStore } from '~/store'
|
||||||
import { addEtherTo } from '~/test/utils/etherMovements'
|
import { addEtherTo } from '~/test/utils/tokenMovements'
|
||||||
import { aDeployedSafe, executeWithdrawOn } from '~/routes/safe/store/test/builder/deployedSafe.builder'
|
import { aDeployedSafe, executeWithdrawOn } from '~/routes/safe/store/test/builder/deployedSafe.builder'
|
||||||
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
|
import { buildMathPropsFrom } from '~/test/utils/buildReactRouterProps'
|
||||||
import { safeSelector } from '~/routes/safe/store/selectors/index'
|
import { safeSelector } from '~/routes/safe/store/selectors/index'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import fetchSafe from '~/routes/safe/store/actions/fetchSafe'
|
import fetchSafe from '~/routes/safe/store/actions/fetchSafe'
|
||||||
import fetchBalances from '~/routes/safe/store/actions/fetchBalances'
|
import { fetchBalances } from '~/routes/safe/store/actions/fetchBalances'
|
||||||
|
|
||||||
export type Actions = {
|
export type Actions = {
|
||||||
fetchSafe: typeof fetchSafe,
|
fetchSafe: typeof fetchSafe,
|
||||||
|
@ -1,12 +1,24 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import { Map } from 'immutable'
|
import { Map } from 'immutable'
|
||||||
|
import contract from 'truffle-contract'
|
||||||
import type { Dispatch as ReduxDispatch } from 'redux'
|
import type { Dispatch as ReduxDispatch } from 'redux'
|
||||||
import { getBalanceInEtherOf } from '~/wallets/getWeb3'
|
import ERC20Token from '#/ERC20Token.json'
|
||||||
|
import { getBalanceInEtherOf, getWeb3 } from '~/wallets/getWeb3'
|
||||||
import { type GlobalState } from '~/store/index'
|
import { type GlobalState } from '~/store/index'
|
||||||
import { makeBalance, type Balance } from '~/routes/safe/store/model/balance'
|
import { makeBalance, type Balance, type BalanceProps } from '~/routes/safe/store/model/balance'
|
||||||
import addBalances from './addBalances'
|
import addBalances from './addBalances'
|
||||||
|
|
||||||
export default (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
|
export const calculateBalanceOf = async (tokenAddress: string, address: string) => {
|
||||||
|
const web3 = getWeb3()
|
||||||
|
const erc20Token = await contract(ERC20Token)
|
||||||
|
erc20Token.setProvider(web3.currentProvider)
|
||||||
|
|
||||||
|
return erc20Token.at(tokenAddress)
|
||||||
|
.then(instance => instance.balanceOf(address).then(funds => funds.toString()))
|
||||||
|
.catch(() => '0')
|
||||||
|
}
|
||||||
|
|
||||||
|
export const fetchBalances = (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalState>) => {
|
||||||
const balance = await getBalanceInEtherOf(safeAddress)
|
const balance = await getBalanceInEtherOf(safeAddress)
|
||||||
const ethBalance = makeBalance({
|
const ethBalance = makeBalance({
|
||||||
address: '0',
|
address: '0',
|
||||||
@ -32,8 +44,13 @@ export default (safeAddress: string) => async (dispatch: ReduxDispatch<GlobalSta
|
|||||||
}
|
}
|
||||||
|
|
||||||
const json = await response.json()
|
const json = await response.json()
|
||||||
|
const balancesRecords = await Promise.all(json.map(async (item: BalanceProps) => {
|
||||||
|
const funds = await calculateBalanceOf(item.address, safeAddress)
|
||||||
|
return makeBalance({ ...item, funds })
|
||||||
|
}))
|
||||||
|
|
||||||
const balances: Map<string, Balance> = Map().withMutations((map) => {
|
const balances: Map<string, Balance> = Map().withMutations((map) => {
|
||||||
json.forEach(item => map.set(item.symbol, makeBalance(item)))
|
balancesRecords.forEach(record => map.set(record.get('symbol'), record))
|
||||||
map.set('ETH', ethBalance)
|
map.set('ETH', ethBalance)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import { Provider } from 'react-redux'
|
|||||||
import { ConnectedRouter } from 'react-router-redux'
|
import { ConnectedRouter } from 'react-router-redux'
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import { aNewStore, history } from '~/store'
|
import { aNewStore, history } from '~/store'
|
||||||
import { addEtherTo } from '~/test/utils/etherMovements'
|
import { addEtherTo } from '~/test/utils/tokenMovements'
|
||||||
import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder'
|
import { aDeployedSafe } from '~/routes/safe/store/test/builder/deployedSafe.builder'
|
||||||
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
||||||
import SafeView from '~/routes/safe/component/Safe'
|
import SafeView from '~/routes/safe/component/Safe'
|
||||||
|
@ -6,7 +6,7 @@ import { ConnectedRouter } from 'react-router-redux'
|
|||||||
import { type Match } from 'react-router-dom'
|
import { type Match } from 'react-router-dom'
|
||||||
import Button from '~/components/layout/Button'
|
import Button from '~/components/layout/Button'
|
||||||
import { aNewStore, history } from '~/store'
|
import { aNewStore, history } from '~/store'
|
||||||
import { addEtherTo } from '~/test/utils/etherMovements'
|
import { addEtherTo } from '~/test/utils/tokenMovements'
|
||||||
import { aDeployedSafe, executeWithdrawOn } from '~/routes/safe/store/test/builder/deployedSafe.builder'
|
import { aDeployedSafe, executeWithdrawOn } from '~/routes/safe/store/test/builder/deployedSafe.builder'
|
||||||
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
||||||
import SafeView from '~/routes/safe/component/Safe'
|
import SafeView from '~/routes/safe/component/Safe'
|
||||||
|
@ -3,7 +3,7 @@ import TestUtils from 'react-dom/test-utils'
|
|||||||
import { sleep } from '~/utils/timer'
|
import { sleep } from '~/utils/timer'
|
||||||
import { getBalanceInEtherOf } from '~/wallets/getWeb3'
|
import { getBalanceInEtherOf } from '~/wallets/getWeb3'
|
||||||
import { ADD_MULTISIG_BUTTON_TEXT, SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/component/Safe/MultisigTx'
|
import { ADD_MULTISIG_BUTTON_TEXT, SEE_MULTISIG_BUTTON_TEXT } from '~/routes/safe/component/Safe/MultisigTx'
|
||||||
import { addEtherTo } from '~/test/utils/etherMovements'
|
import { addEtherTo } from '~/test/utils/tokenMovements'
|
||||||
import SafeView from '~/routes/safe/component/Safe'
|
import SafeView from '~/routes/safe/component/Safe'
|
||||||
import TransactionsComponent from '~/routes/safe/component/Transactions'
|
import TransactionsComponent from '~/routes/safe/component/Transactions'
|
||||||
import TransactionComponent from '~/routes/safe/component/Transactions/Transaction'
|
import TransactionComponent from '~/routes/safe/component/Transactions/Transaction'
|
||||||
|
@ -15,7 +15,7 @@ import { makeProvider } from '~/wallets/store/model/provider'
|
|||||||
import AppRoutes from '~/routes'
|
import AppRoutes from '~/routes'
|
||||||
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
import { SAFELIST_ADDRESS } from '~/routes/routes'
|
||||||
import { promisify } from '~/utils/promisify'
|
import { promisify } from '~/utils/promisify'
|
||||||
import { addEtherTo } from '~/test/utils/etherMovements'
|
import { addEtherTo } from '~/test/utils/tokenMovements'
|
||||||
|
|
||||||
const fillOpenSafeForm = async (localStore: Store<GlobalState>) => {
|
const fillOpenSafeForm = async (localStore: Store<GlobalState>) => {
|
||||||
const provider = await getProviderInfo()
|
const provider = await getProviderInfo()
|
||||||
|
@ -9,7 +9,7 @@ import { sendRemoveOwnerForm, checkMinedRemoveOwnerTx, checkPendingRemoveOwnerTx
|
|||||||
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 { processTransaction } from '~/routes/safe/component/Transactions/processTransactions'
|
||||||
import { checkBalanceOf } from '~/test/utils/etherMovements'
|
import { checkBalanceOf } from '~/test/utils/tokenMovements'
|
||||||
|
|
||||||
describe('DOM > Feature > SAFE MULTISIG TX 1 Owner 1 Threshold', () => {
|
describe('DOM > Feature > SAFE MULTISIG TX 1 Owner 1 Threshold', () => {
|
||||||
let domSafe: DomSafe
|
let domSafe: DomSafe
|
||||||
|
@ -1,15 +1,12 @@
|
|||||||
// @flow
|
// @flow
|
||||||
import contract from 'truffle-contract'
|
|
||||||
import { Map } from 'immutable'
|
import { Map } from 'immutable'
|
||||||
import { BALANCE_REDUCER_ID } from '~/routes/safe/store/reducer/balances'
|
import { BALANCE_REDUCER_ID } from '~/routes/safe/store/reducer/balances'
|
||||||
import fetchBalances from '~/routes/safe/store/actions/fetchBalances'
|
import * as fetchBalancesAction from '~/routes/safe/store/actions/fetchBalances'
|
||||||
import { aNewStore } from '~/store'
|
import { aNewStore } from '~/store'
|
||||||
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
import { aMinedSafe } from '~/test/builder/safe.redux.builder'
|
||||||
import { type Balance } from '~/routes/safe/store/model/balance'
|
import { type Balance, makeBalance } from '~/routes/safe/store/model/balance'
|
||||||
import { addEtherTo } from '~/test/utils/etherMovements'
|
import addBalances from '~/routes/safe/store/actions/addBalances'
|
||||||
import Token from '#/test/Token.json'
|
import { addEtherTo, addTknTo } from '~/test/utils/tokenMovements'
|
||||||
import { getWeb3 } from '~/wallets/getWeb3'
|
|
||||||
import { promisify } from '~/utils/promisify'
|
|
||||||
|
|
||||||
describe('Safe Actions[fetchBalance]', () => {
|
describe('Safe Actions[fetchBalance]', () => {
|
||||||
let store
|
let store
|
||||||
@ -24,7 +21,7 @@ describe('Safe Actions[fetchBalance]', () => {
|
|||||||
const tokenList = ['WE', '<3', 'GNO', 'OMG', 'RDN']
|
const tokenList = ['WE', '<3', 'GNO', 'OMG', 'RDN']
|
||||||
|
|
||||||
// WHEN
|
// WHEN
|
||||||
await store.dispatch(fetchBalances(address))
|
await store.dispatch(fetchBalancesAction.fetchBalances(address))
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
const balances: Map<string, Map<string, Balance>> | typeof undefined = store.getState()[BALANCE_REDUCER_ID]
|
const balances: Map<string, Map<string, Balance>> | typeof undefined = store.getState()[BALANCE_REDUCER_ID]
|
||||||
@ -44,7 +41,7 @@ describe('Safe Actions[fetchBalance]', () => {
|
|||||||
it('reducer should return 0.03456 ETH as funds to safe with 0.03456 ETH', async () => {
|
it('reducer should return 0.03456 ETH as funds to safe with 0.03456 ETH', async () => {
|
||||||
// WHEN
|
// WHEN
|
||||||
await addEtherTo(address, '0.03456')
|
await addEtherTo(address, '0.03456')
|
||||||
await store.dispatch(fetchBalances(address))
|
await store.dispatch(fetchBalancesAction.fetchBalances(address))
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
const balances: Map<string, Map<string, Balance>> | typeof undefined = store.getState()[BALANCE_REDUCER_ID]
|
const balances: Map<string, Map<string, Balance>> | typeof undefined = store.getState()[BALANCE_REDUCER_ID]
|
||||||
@ -59,29 +56,32 @@ describe('Safe Actions[fetchBalance]', () => {
|
|||||||
expect(ethBalance.get('funds')).toBe('0.03456')
|
expect(ethBalance.get('funds')).toBe('0.03456')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('reducer should return 2 GNO when safe has 2 GNO', async () => {
|
it('reducer should return 100 TKN when safe has 100 TKN', async () => {
|
||||||
// GIVEN
|
// GIVEN
|
||||||
const web3 = getWeb3()
|
const numTokens = 100
|
||||||
const token = contract(Token)
|
const tokenAddress = await addTknTo(address, numTokens)
|
||||||
token.setProvider(web3.currentProvider)
|
|
||||||
const accounts = await promisify(cb => getWeb3().eth.getAccounts(cb))
|
|
||||||
const myToken = await token.new({ from: accounts[0], gas: '5000000' })
|
|
||||||
await myToken.transfer(address, 100, { from: accounts[0], gas: '5000000' })
|
|
||||||
|
|
||||||
// console.log(await myToken.totalSupply())
|
|
||||||
// WHEN
|
// WHEN
|
||||||
await store.dispatch(fetchBalances(address))
|
const fetchBalancesMock = jest.spyOn(fetchBalancesAction, 'fetchBalances')
|
||||||
|
const funds = await fetchBalancesAction.calculateBalanceOf(tokenAddress, address)
|
||||||
|
|
||||||
|
const balances: Map<string, Balance> = Map().set('TKN', makeBalance({
|
||||||
|
address: tokenAddress,
|
||||||
|
name: 'Token',
|
||||||
|
symbol: 'TKN',
|
||||||
|
decimals: 18,
|
||||||
|
logoUrl: 'https://github.com/TrustWallet/tokens/blob/master/images/0x6810e776880c02933d47db1b9fc05908e5386b96.png?raw=true',
|
||||||
|
funds,
|
||||||
|
}))
|
||||||
|
fetchBalancesMock.mockImplementation(() => store.dispatch(addBalances(address, balances)))
|
||||||
|
await store.dispatch(fetchBalancesAction.fetchBalances(address))
|
||||||
|
fetchBalancesMock.mockRestore()
|
||||||
|
|
||||||
// THEN
|
// THEN
|
||||||
const balances: Map<string, Map<string, Balance>> | typeof undefined = store.getState()[BALANCE_REDUCER_ID]
|
const safeBalances = store.getState()[BALANCE_REDUCER_ID].get(address)
|
||||||
if (!balances) throw new Error()
|
expect(safeBalances.size).toBe(1)
|
||||||
|
|
||||||
const safeBalances: Map<string, Balance> | typeof undefined = balances.get(address)
|
const tknBalance = safeBalances.get('TKN')
|
||||||
if (!safeBalances) throw new Error()
|
expect(tknBalance.get('funds')).toBe(String(numTokens))
|
||||||
expect(safeBalances.size).toBe(6)
|
|
||||||
|
|
||||||
const ethBalance = safeBalances.get('ETH')
|
|
||||||
if (!ethBalance) throw new Error()
|
|
||||||
expect(ethBalance.get('funds')).toBe('0.03456')
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
// @flow
|
// @flow
|
||||||
|
import contract from 'truffle-contract'
|
||||||
import { getProviderInfo, getBalanceInEtherOf, getWeb3 } from '~/wallets/getWeb3'
|
import { getProviderInfo, getBalanceInEtherOf, getWeb3 } from '~/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 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/Token.json'
|
||||||
|
|
||||||
export const addEtherTo = async (address: string, eth: string) => {
|
export const addEtherTo = async (address: string, eth: string) => {
|
||||||
const web3 = getWeb3()
|
const web3 = getWeb3()
|
||||||
@ -27,3 +29,14 @@ export const checkBalanceOf = async (addressToTest: string, value: string) => {
|
|||||||
const safeBalance = await getBalanceInEtherOf(addressToTest)
|
const safeBalance = await getBalanceInEtherOf(addressToTest)
|
||||||
expect(safeBalance).toBe(value)
|
expect(safeBalance).toBe(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const addTknTo = async (safe: string, value: number) => {
|
||||||
|
const web3 = getWeb3()
|
||||||
|
const token = contract(Token)
|
||||||
|
token.setProvider(web3.currentProvider)
|
||||||
|
const accounts = await promisify(cb => getWeb3().eth.getAccounts(cb))
|
||||||
|
const myToken = await token.new({ from: accounts[0], gas: '5000000' })
|
||||||
|
await myToken.transfer(safe, value, { from: accounts[0], gas: '5000000' })
|
||||||
|
|
||||||
|
return myToken.address
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
// @flow
|
// @flow
|
||||||
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 { checkBalanceOf } from '~/test/utils/etherMovements'
|
import { checkBalanceOf } from '~/test/utils/tokenMovements'
|
||||||
import { checkMinedTx } from '~/test/builder/safe.dom.utils'
|
import { checkMinedTx } from '~/test/builder/safe.dom.utils'
|
||||||
|
|
||||||
export const sendWithdrawForm = (
|
export const sendWithdrawForm = (
|
||||||
|
@ -2921,14 +2921,14 @@ bignumber.js@^7.2.1:
|
|||||||
version "7.2.1"
|
version "7.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
|
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-7.2.1.tgz#80c048759d826800807c4bfd521e50edbba57a5f"
|
||||||
|
|
||||||
|
"bignumber.js@git+https://github.com/debris/bignumber.js#master":
|
||||||
|
version "2.0.7"
|
||||||
|
resolved "git+https://github.com/debris/bignumber.js#c7a38de919ed75e6fb6ba38051986e294b328df9"
|
||||||
|
|
||||||
"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2":
|
"bignumber.js@git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2":
|
||||||
version "2.0.7"
|
version "2.0.7"
|
||||||
resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
|
resolved "git+https://github.com/debris/bignumber.js.git#94d7146671b9719e00a09c29b01a691bc85048c2"
|
||||||
|
|
||||||
"bignumber.js@git+https://github.com/debris/bignumber.js.git#master":
|
|
||||||
version "2.0.7"
|
|
||||||
resolved "git+https://github.com/debris/bignumber.js.git#c7a38de919ed75e6fb6ba38051986e294b328df9"
|
|
||||||
|
|
||||||
binary-extensions@^1.0.0:
|
binary-extensions@^1.0.0:
|
||||||
version "1.11.0"
|
version "1.11.0"
|
||||||
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
|
resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.11.0.tgz#46aa1751fb6a2f93ee5e689bb1087d4b14c6c205"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user