add update ERC20 account balance

add reselect - memoizes from the state tree
This commit is contained in:
Barry Gitarts 2018-06-05 13:19:21 -04:00
parent af17134f3e
commit cb41a904c5
5 changed files with 100 additions and 60 deletions

View File

@ -1,3 +1,4 @@
import ERC20Token from 'Embark/contracts/ERC20Token';
import { actions as accountActions } from '../reducers/accounts' import { actions as accountActions } from '../reducers/accounts'
const { receiveAccounts } = accountActions const { receiveAccounts } = accountActions
@ -7,7 +8,8 @@ export const fetchAndDispatchAccountsWithBalances = (web3, dispatch) => {
const defaultAccount = web3.eth.defaultAccount || addresses[0] const defaultAccount = web3.eth.defaultAccount || addresses[0]
const accounts = addresses.map(async address => { const accounts = addresses.map(async address => {
const balance = await web3.eth.getBalance(address, 'latest') const balance = await web3.eth.getBalance(address, 'latest')
return { address, balance } const ERC20TokenBalance = await ERC20Token.methods.balanceOf(address).call()
return { address, balance, ERC20TokenBalance }
}) })
Promise.all(accounts).then(accounts => { Promise.all(accounts).then(accounts => {
dispatch(receiveAccounts(defaultAccount, accounts)) dispatch(receiveAccounts(defaultAccount, accounts))

View File

@ -1,7 +1,9 @@
import EmbarkJS from 'Embark/EmbarkJS'; import EmbarkJS from 'Embark/EmbarkJS';
import ERC20Token from 'Embark/contracts/ERC20Token'; import ERC20Token from 'Embark/contracts/ERC20Token';
import React from 'react'; import React from 'react';
import { connect } from 'react-redux';
import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap';
import { getCurrentAccount, accountsIsLoading } from '../reducers/accounts';
class ERC20TokenUI extends React.Component { class ERC20TokenUI extends React.Component {
@ -67,59 +69,64 @@ class ERC20TokenUI extends React.Component {
console.log(txt); console.log(txt);
} }
render(){ render() {
return (<React.Fragment> const { account, isLoading } = this.props;
return (
<h3> Read your account token balance </h3> <React.Fragment>
<Form inline> <h3> Read your account token balance </h3>
<FormGroup> <Form inline>
<HelpBlock>Your test token balance is <span className="accountBalance">{this.state.accountBalance}</span></HelpBlock> <FormGroup>
<Button bsStyle="primary" onClick={(e) => this.getDefaultAccountBalance()}>Get Balance</Button> {!isLoading && <HelpBlock>Your test token balance is <span className="accountBalance">{account.ERC20TokenBalance}</span></HelpBlock>}
</FormGroup> </FormGroup>
</Form> </Form>
<h3> Read account token balance</h3> <h3> Read account token balance</h3>
<Form inline> <Form inline>
<FormGroup> <FormGroup>
<label> <label>
Of: Of:
<FormControl <FormControl
type="text" type="text"
defaultValue={this.state.accountB} defaultValue={this.state.accountB}
onChange={(e) => this.balanceOf(e)} /> onChange={(e) => this.balanceOf(e)} />
</label> </label>
<label> <label>
<HelpBlock><span className="balanceOf">{this.state.balanceOf}</span></HelpBlock> <HelpBlock><span className="balanceOf">{this.state.balanceOf}</span></HelpBlock>
</label> </label>
</FormGroup> </FormGroup>
</Form> </Form>
<h3> Transfer/Approve token balance</h3> <h3> Transfer/Approve token balance</h3>
<Form inline> <Form inline>
<FormGroup> <FormGroup>
<label> <label>
To: To:
<FormControl <FormControl
type="text" type="text"
defaultValue={this.state.transferTo} defaultValue={this.state.transferTo}
onChange={(e) => this.update_transferTo(e) } /> onChange={(e) => this.update_transferTo(e) } />
</label> </label>
<label> <label>
Amount: Amount:
<FormControl <FormControl
type="text" type="text"
defaultValue={this.state.transferAmount} defaultValue={this.state.transferAmount}
onChange={(e) => this.update_transferAmount(e) } /> onChange={(e) => this.update_transferAmount(e) } />
</label> </label>
<Button bsStyle="primary" onClick={(e) => this.transfer(e)}>Transfer</Button> <Button bsStyle="primary" onClick={(e) => this.transfer(e)}>Transfer</Button>
<Button bsStyle="primary" onClick={(e) => this.approve(e)}>Approve</Button> <Button bsStyle="primary" onClick={(e) => this.approve(e)}>Approve</Button>
</FormGroup> </FormGroup>
</Form> </Form>
</React.Fragment> </React.Fragment>
); );
} }
} }
export default ERC20TokenUI; const mapStateToProps = state => ({
account: getCurrentAccount(state),
isLoading: accountsIsLoading(state),
});
export default connect(mapStateToProps)(ERC20TokenUI);

View File

@ -3,6 +3,8 @@ import TestToken from 'Embark/contracts/TestToken';
import React from 'react'; import React from 'react';
import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap';
import ERC20TokenUI from './erc20token'; import ERC20TokenUI from './erc20token';
import { connect } from 'react-redux';
import { actions as accountActions } from '../reducers/accounts';
class TestTokenUI extends React.Component { class TestTokenUI extends React.Component {
@ -17,15 +19,18 @@ class TestTokenUI extends React.Component {
this.setState({amountToMint: e.target.value}); this.setState({amountToMint: e.target.value});
} }
mint(e){ mint(e){
const { addToBalance } = this.props;
e.preventDefault(); e.preventDefault();
var value = parseInt(this.state.amountToMint, 10); var value = parseInt(this.state.amountToMint, 10);
if (EmbarkJS.isNewWeb3()) { if (EmbarkJS.isNewWeb3()) {
TestToken.methods.mint(value).send({from: web3.eth.defaultAccount}); TestToken.methods.mint(value).send({from: web3.eth.defaultAccount})
.then(r => { addToBalance(value) });
} else { } else {
TestToken.mint(value); TestToken.mint(value).send({from: web3.eth.defaultAccount})
.then(r => { addToBalance(value) });
} }
console.log(TestToken.options.address +".mint("+value+").send({from: " + web3.eth.defaultAccount + "})"); console.log(TestToken.options.address +".mint("+value+").send({from: " + web3.eth.defaultAccount + "})");
} }
@ -50,4 +55,10 @@ class TestTokenUI extends React.Component {
} }
} }
export default TestTokenUI; const mapDispatchToProps = dispatch => ({
addToBalance(amount) {
dispatch(accountActions.addToErc20TokenBalance(amount));
},
});
export default connect(null, mapDispatchToProps)(TestTokenUI);

View File

@ -1,12 +1,15 @@
import { createTypes, actionCreator } from 'redux-action-creator' import { createTypes, actionCreator } from 'redux-action-creator'
import { createSelector } from 'reselect'
export const types = createTypes([ export const types = createTypes([
'RECEIVE_ACCOUNTS', 'RECEIVE_ACCOUNTS',
'UPDATE_DEFAULT_ACCOUNT' 'UPDATE_DEFAULT_ACCOUNT',
'ADD_TO_ERC20_TOKEN_BALANCE'
], 'ACCOUNTS') ], 'ACCOUNTS')
export const actions = { export const actions = {
receiveAccounts: actionCreator(types.RECEIVE_ACCOUNTS, 'defaultAccount','accounts'), receiveAccounts: actionCreator(types.RECEIVE_ACCOUNTS, 'defaultAccount','accounts'),
updateDefaultAccount: actionCreator(types.UPDATE_DEFAULT_ACCOUNT, 'defaultAccount') updateDefaultAccount: actionCreator(types.UPDATE_DEFAULT_ACCOUNT, 'defaultAccount'),
addToErc20TokenBalance: actionCreator(types.ADD_TO_ERC20_TOKEN_BALANCE, 'amount')
} }
export default function(state = { loading: true, accounts: [] }, action) { export default function(state = { loading: true, accounts: [] }, action) {
@ -24,6 +27,17 @@ export default function(state = { loading: true, accounts: [] }, action) {
const { defaultAccount } = action.payload const { defaultAccount } = action.payload
return { ...state, defaultAccount } return { ...state, defaultAccount }
} }
case types.ADD_TO_ERC20_TOKEN_BALANCE: {
const currentAccount = { ...getCurrentAccount({accounts: state}) }
currentAccount.ERC20TokenBalance = Number(currentAccount.ERC20TokenBalance) + Number(action.payload.amount)
const accounts = [ ...state.accounts ]
const idx = accounts.findIndex(a => a.address === currentAccount.address)
accounts[idx] = currentAccount
return {
...state,
accounts
}
}
default: default:
return state; return state;
} }
@ -33,3 +47,8 @@ export const getAccountState = state => state.acounts;
export const getAccounts = state => state.accounts.accounts; export const getAccounts = state => state.accounts.accounts;
export const getDefaultAccount = state => state.accounts.defaultAccount; export const getDefaultAccount = state => state.accounts.defaultAccount;
export const accountsIsLoading = state => state.accounts.loading; export const accountsIsLoading = state => state.accounts.loading;
export const getCurrentAccount = createSelector(
getDefaultAccount,
getAccounts,
(defaultAccount, accounts) => accounts.find(a => a.address === defaultAccount)
)

View File

@ -26,7 +26,8 @@
"react-redux": "^5.0.7", "react-redux": "^5.0.7",
"redux": "^4.0.0", "redux": "^4.0.0",
"redux-action-creator": "^2.3.0", "redux-action-creator": "^2.3.0",
"redux-thunk": "^2.3.0" "redux-thunk": "^2.3.0",
"reselect": "^3.0.1"
}, },
"devDependencies": { "devDependencies": {
"babel-plugin-transform-object-rest-spread": "^6.26.0", "babel-plugin-transform-object-rest-spread": "^6.26.0",