From b5e3c4be34c5f133d20c12444de4d9da27d9b65b Mon Sep 17 00:00:00 2001 From: Barry Gitarts Date: Mon, 21 May 2018 13:57:52 -0400 Subject: [PATCH 1/5] simplify address lookup --- test/minimetoken.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/minimetoken.js b/test/minimetoken.js index d911652..6af6975 100644 --- a/test/minimetoken.js +++ b/test/minimetoken.js @@ -61,9 +61,7 @@ describe("MiniMeToken", async function() { 'MMTc', 0, true).send({ from: accounts[0]}); - let addr = miniMeTokenCloneTx.events.NewCloneToken.raw.topics[1]; - addr = `0x${addr.slice(26)}`; - addr = web3.utils.toChecksumAddress(addr); + let addr = miniMeTokenCloneTx.events.NewCloneToken.returnValues[0]; miniMeTokenClone = new web3.eth.Contract(MiniMeToken._jsonInterface, addr); b[3] = await web3.eth.getBlockNumber(); From fcad9c9acffbf22af82eb53689ca8172b6179e65 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Sat, 30 Jun 2018 02:13:36 -0300 Subject: [PATCH 2/5] merge bootstrap-embark31 --- .babelrc | 4 + .eslintrc.json | 9 ++ README.md | 4 +- app/actions/accounts.js | 19 ++++ app/components/accountlist.js | 162 +++++++++++------------------ app/components/erc20token.js | 141 ++++++++++++------------- app/components/testtoken.js | 68 ++++-------- app/dapp.js | 6 +- app/index.html | 2 +- app/index.js | 16 +++ app/reducers/accounts.js | 54 ++++++++++ app/reducers/rootReducer.js | 8 ++ app/store/configureStore.js | 11 ++ app/store/init.js | 12 +++ config/blockchain.js | 62 +++++++++++ config/blockchain.json | 56 ---------- config/communication.js | 12 +++ config/communication.json | 12 --- config/contracts.js | 33 ++++++ config/namesystem.js | 6 ++ config/storage.js | 35 +++++++ config/storage.json | 20 ---- config/webserver.js | 5 + config/webserver.json | 5 - contracts/common/MessageSigned.sol | 2 +- contracts/token/StandardToken.sol | 6 +- embark.json | 3 +- package.json | 20 +++- test/abstract/controlled.js | 25 +++++ test/abstract/erc20tokenspec.js | 85 +++++++++++++++ test/controlled.js | 29 ------ test/erc20token.js | 78 -------------- test/testtoken.js | 60 +++++++---- utils/testUtils.js | 4 +- 34 files changed, 618 insertions(+), 456 deletions(-) create mode 100644 .babelrc create mode 100644 .eslintrc.json create mode 100644 app/actions/accounts.js create mode 100644 app/index.js create mode 100644 app/reducers/accounts.js create mode 100644 app/reducers/rootReducer.js create mode 100644 app/store/configureStore.js create mode 100644 app/store/init.js create mode 100644 config/blockchain.js delete mode 100644 config/blockchain.json create mode 100644 config/communication.js delete mode 100644 config/communication.json create mode 100644 config/contracts.js create mode 100644 config/namesystem.js create mode 100644 config/storage.js delete mode 100644 config/storage.json create mode 100644 config/webserver.js delete mode 100644 config/webserver.json create mode 100644 test/abstract/controlled.js create mode 100644 test/abstract/erc20tokenspec.js delete mode 100644 test/controlled.js delete mode 100644 test/erc20token.js diff --git a/.babelrc b/.babelrc new file mode 100644 index 0000000..577b026 --- /dev/null +++ b/.babelrc @@ -0,0 +1,4 @@ +{ + "plugins": ["transform-object-rest-spread"], + "presets": ["stage-2"] +} diff --git a/.eslintrc.json b/.eslintrc.json new file mode 100644 index 0000000..f8ab647 --- /dev/null +++ b/.eslintrc.json @@ -0,0 +1,9 @@ +{ + "extends": "airbnb", + "plugins": [ + "react" + ], + "rules": { + "react/prop-types": 0 + } +} diff --git a/README.md b/README.md index fc827f3..5cc9088 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,9 @@ # status.im contracts - +Requires https://github.com/creationix/nvm Usage: ``` + nvm install v8.9.4 + nvm use v8.9.4 npm install -g embark git clone https://github.com/status-im/contracts.git cd contracts diff --git a/app/actions/accounts.js b/app/actions/accounts.js new file mode 100644 index 0000000..6e5323a --- /dev/null +++ b/app/actions/accounts.js @@ -0,0 +1,19 @@ +import ERC20Token from 'Embark/contracts/ERC20Token'; +import { actions as accountActions } from '../reducers/accounts' + +const { receiveAccounts } = accountActions +export const fetchAndDispatchAccountsWithBalances = (web3, dispatch) => { + web3.eth.getAccounts((err, addresses) => { + if (addresses) { + const defaultAccount = web3.eth.defaultAccount || addresses[0] + const accounts = addresses.map(async address => { + const balance = await web3.eth.getBalance(address, 'latest') + const ERC20TokenBalance = await ERC20Token.methods.balanceOf(address).call() + return { address, balance, ERC20TokenBalance } + }) + Promise.all(accounts).then(accounts => { + dispatch(receiveAccounts(defaultAccount, accounts)) + }) + } + }) +} diff --git a/app/components/accountlist.js b/app/components/accountlist.js index fbd3cc7..adcd873 100644 --- a/app/components/accountlist.js +++ b/app/components/accountlist.js @@ -1,112 +1,66 @@ -import web3 from "Embark/web3" -import EmbarkJS from 'Embark/EmbarkJS'; +import web3 from 'Embark/web3' import React from 'react'; -import { Nav, MenuItem , NavDropdown} from 'react-bootstrap'; +import { connect } from 'react-redux'; +import { Nav, MenuItem, NavDropdown } from 'react-bootstrap'; import Blockies from 'react-blockies'; - +import { string, bool, func, arrayOf, shape } from 'prop-types'; +import { getAccounts, getDefaultAccount, accountsIsLoading, actions as accountActions } from '../reducers/accounts'; import './accountlist.css'; -class AccList extends React.Component { - - constructor(props) { - super(props); - this.state = { - classNameNavDropdown: props.classNameNavDropdown, - defaultAccount: "0x0000000000000000000000000000000000000000", - addresses: [], - balances: [] - } - __embarkContext.execWhenReady(() => { - this.load() - }); - } - - - load() { - web3.eth.getAccounts((err, addresses) => { - if (addresses) { - var defaultAccount = web3.eth.defaultAccount; - if(!defaultAccount){ - web3.eth.defaultAccount = addresses[0]; - } - - var balances = []; - balances.length == addresses.length; - addresses.forEach((address, index) => { - web3.eth.getBalance(address, 'latest', (err, balance) => { - balances[index] = balance; - if(index+1 == balances.length){ - this.setState({ - balances: balances - }); - } - }) - }) - this.setState({ - defaultAccount: defaultAccount, - addresses: addresses - }); - - } else { - console.log("No addresses available."); - } - - }) - } - setDefaultAccount(index) { - var defaultAcc = this.state.addresses[index]; - if(defaultAcc){ - web3.eth.defaultAccount = defaultAcc; - this.setState({defaultAccount: defaultAcc }); - } else { - console.log("invalid account") - } - } - - render() { - - var accsTitle; - var accsList = []; - if (this.state.addresses) { - accsTitle = this.state.defaultAccount; - this.state.addresses.forEach( - (name, index) => { - accsList.push( - this.setDefaultAccount(index) }> -
-
- -
-
- {name} -
-
- Ξ {this.state.balances[index] / (10**18)} -
-
-
); - } - ) - } - - return ( - -
-
- +const AccList = ({ + accounts, defaultAccount, changeAccount, isLoading, classNameNavDropdown, +}) => ( + + {!isLoading ? +
+
+ +
+
+ +
+
+ :
Loading...
} +
+); - } +AccList.propTypes = { + accounts: arrayOf(shape({ address: string, balance: string })).isRequired, + defaultAccount: string, + changeAccount: func.isRequired, + isLoading: bool.isRequired, + classNameNavDropdown: string +} - export default AccList; \ No newline at end of file +const mapStateToProps = state => ({ + accounts: getAccounts(state), + defaultAccount: getDefaultAccount(state), + isLoading: accountsIsLoading(state), +}); + +const mapDispatchToProps = dispatch => ({ + changeAccount(address) { + web3.eth.defaultAccount = address; + dispatch(accountActions.updateDefaultAccount(address)); + }, +}); + +export default connect(mapStateToProps, mapDispatchToProps)(AccList); diff --git a/app/components/erc20token.js b/app/components/erc20token.js index 6695adf..173b706 100644 --- a/app/components/erc20token.js +++ b/app/components/erc20token.js @@ -1,27 +1,24 @@ import EmbarkJS from 'Embark/EmbarkJS'; import ERC20Token from 'Embark/contracts/ERC20Token'; import React from 'react'; +import { connect } from 'react-redux'; import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; +import { getCurrentAccount, accountsIsLoading } from '../reducers/accounts'; class ERC20TokenUI extends React.Component { constructor(props) { super(props); + ERC20Token.options.address = props.address; this.state = { - balanceOf: 0, transferTo: "", transferAmount: 0, - logs: [] + accountBalance: 0, + accountB: web3.eth.defaultAccount, } } - contractAddress(e){ - e.preventDefault(); - var tokenAddress = e.target.value; - ERC20Token.options.address = tokenAddress; - } - update_transferTo(e){ this.setState({transferTo: e.target.value}); } @@ -50,7 +47,6 @@ class ERC20TokenUI extends React.Component { if (EmbarkJS.isNewWeb3()) { ERC20Token.methods.balanceOf(who).call() .then(_value => this.setState({balanceOf: _value})) - } else { ERC20Token.balanceOf(who) .then(_value => this.x({balanceOf: _value})); @@ -58,74 +54,79 @@ class ERC20TokenUI extends React.Component { this._addToLog(ERC20Token.options.address+".balanceOf(" + who + ")"); } + getDefaultAccountBalance(){ + if (EmbarkJS.isNewWeb3()) { + ERC20Token.methods.balanceOf(web3.eth.defaultAccount).call() + .then(_value => this.setState({accountBalance: _value})) + } else { + ERC20Token.balanceOf(web3.eth.defaultAccount) + .then(_value => this.x({valueGet: _value})) + } + this._addToLog(ERC20Token.options.address + ".balanceOf(" + web3.eth.defaultAccount + ")"); + } _addToLog(txt){ - this.state.logs.push(txt); - this.setState({logs: this.state.logs}); + console.log(txt); } - render(){ - return ( - -

Set token contract address

-
- + render() { + const { account, isLoading } = this.props; + return ( + +

Read your account token balance

+ + + {!isLoading && Your test token balance is {account.ERC20TokenBalance}} + + + +

Read account token balance

+
+ + -
+ defaultValue={this.state.accountB} + onChange={(e) => this.balanceOf(e)} /> + + + +
+ - -

Read account token balance

-
- - - - - -
- -

Transfer/Approve token balance

-
- - - - - - -
- -

Contract Calls

-

Javascript calls being made:

-
- { - this.state.logs.map((item, i) =>

{item}

) - } -
+

Transfer/Approve token balance

+
+ + + + + + +
+
- ); - } + ); + } } - export default ERC20TokenUI; \ No newline at end of file +const mapStateToProps = state => ({ + account: getCurrentAccount(state), + isLoading: accountsIsLoading(state), +}); + +export default connect(mapStateToProps)(ERC20TokenUI); diff --git a/app/components/testtoken.js b/app/components/testtoken.js index 3618caa..0670abc 100644 --- a/app/components/testtoken.js +++ b/app/components/testtoken.js @@ -2,17 +2,16 @@ import EmbarkJS from 'Embark/EmbarkJS'; import TestToken from 'Embark/contracts/TestToken'; import React from 'react'; import { Form, FormGroup, FormControl, HelpBlock, Button } from 'react-bootstrap'; - +import ERC20TokenUI from './erc20token'; +import { connect } from 'react-redux'; +import { actions as accountActions } from '../reducers/accounts'; + class TestTokenUI extends React.Component { constructor(props) { super(props); this.state = { amountToMint: 100, - accountBalance: 0, - accountB: web3.eth.defaultAccount, - balanceOf: 0, - logs: [] } } @@ -20,41 +19,25 @@ class TestTokenUI extends React.Component { this.setState({amountToMint: e.target.value}); } - mint(e){ + mint(e){ + const { addToBalance } = this.props; e.preventDefault(); var value = parseInt(this.state.amountToMint, 10); 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 { - TestToken.mint(value); - this._addToLog("#blockchain", "TestToken.mint(" + value + ")"); + TestToken.mint(value).send({from: web3.eth.defaultAccount}) + .then(r => { addToBalance(value) }); } - this._addToLog(TestToken.options.address +".mint("+value+").send({from: " + web3.eth.defaultAccount + "})"); + console.log(TestToken.options.address +".mint("+value+").send({from: " + web3.eth.defaultAccount + "})"); } - - getBalance(e){ - e.preventDefault(); - - if (EmbarkJS.isNewWeb3()) { - TestToken.methods.balanceOf(web3.eth.defaultAccount).call() - .then(_value => this.setState({accountBalance: _value})) - } else { - TestToken.balanceOf(web3.eth.defaultAccount) - .then(_value => this.x({valueGet: _value})) - } - this._addToLog(TestToken.options.address + ".balanceOf(" + web3.eth.defaultAccount + ")"); - } - - _addToLog(txt){ - this.state.logs.push(txt); - this.setState({logs: this.state.logs}); - } - + render(){ return ( -

1. Mint Test Token

+

Mint Test Token

-

2. Read your account token balance

-
- - Your test token balance is {this.state.accountBalance} - - -
- -

3. Contract Calls

-

Javascript calls being made:

-
- { - this.state.logs.map((item, i) =>

{item}

) - } -
+ +
); } } - export default TestTokenUI; \ No newline at end of file +const mapDispatchToProps = dispatch => ({ + addToBalance(amount) { + dispatch(accountActions.addToErc20TokenBalance(amount)); + }, +}); + +export default connect(null, mapDispatchToProps)(TestTokenUI); diff --git a/app/dapp.js b/app/dapp.js index a0744b3..ca9825c 100644 --- a/app/dapp.js +++ b/app/dapp.js @@ -5,7 +5,6 @@ import { Tabs, Tab } from 'react-bootstrap'; import EmbarkJS from 'Embark/EmbarkJS'; import TopNavbar from './components/topnavbar'; import TestTokenUI from './components/testtoken'; -import ERC20TokenUI from './components/erc20token'; import './dapp.css'; @@ -40,12 +39,9 @@ class App extends React.Component { - - -
); } } -ReactDOM.render(, document.getElementById('app')); +export default App; diff --git a/app/index.html b/app/index.html index 1fb8607..43438ee 100644 --- a/app/index.html +++ b/app/index.html @@ -7,6 +7,6 @@
- + diff --git a/app/index.js b/app/index.js new file mode 100644 index 0000000..71ad7c2 --- /dev/null +++ b/app/index.js @@ -0,0 +1,16 @@ +import React from 'react'; +import { render } from 'react-dom'; +import { Provider } from 'react-redux'; +import store from './store/configureStore'; +import App from './dapp'; +import init from './store/init' +import './dapp.css'; + +init(); + +render( + + + , + document.getElementById('app') +); diff --git a/app/reducers/accounts.js b/app/reducers/accounts.js new file mode 100644 index 0000000..4ca8dc9 --- /dev/null +++ b/app/reducers/accounts.js @@ -0,0 +1,54 @@ +import { createTypes, actionCreator } from 'redux-action-creator' +import { createSelector } from 'reselect' + +export const types = createTypes([ + 'RECEIVE_ACCOUNTS', + 'UPDATE_DEFAULT_ACCOUNT', + 'ADD_TO_ERC20_TOKEN_BALANCE' +], 'ACCOUNTS') +export const actions = { + receiveAccounts: actionCreator(types.RECEIVE_ACCOUNTS, 'defaultAccount','accounts'), + updateDefaultAccount: actionCreator(types.UPDATE_DEFAULT_ACCOUNT, 'defaultAccount'), + addToErc20TokenBalance: actionCreator(types.ADD_TO_ERC20_TOKEN_BALANCE, 'amount') +} + +export default function(state = { loading: true, accounts: [] }, action) { + switch (action.type) { + case types.RECEIVE_ACCOUNTS: { + const { defaultAccount, accounts } = action.payload + return { + ...state, + loading: false, + defaultAccount, + accounts + } + } + case types.UPDATE_DEFAULT_ACCOUNT: { + const { defaultAccount } = action.payload + 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: + return state; + } +} + +export const getAccountState = state => state.acounts; +export const getAccounts = state => state.accounts.accounts; +export const getDefaultAccount = state => state.accounts.defaultAccount; +export const accountsIsLoading = state => state.accounts.loading; +export const getCurrentAccount = createSelector( + getDefaultAccount, + getAccounts, + (defaultAccount, accounts) => accounts.find(a => a.address === defaultAccount) +) diff --git a/app/reducers/rootReducer.js b/app/reducers/rootReducer.js new file mode 100644 index 0000000..244ee3e --- /dev/null +++ b/app/reducers/rootReducer.js @@ -0,0 +1,8 @@ +import { combineReducers } from 'redux'; +import accounts from './accounts' + +const rootReducer = combineReducers({ + accounts +}); + +export default rootReducer; diff --git a/app/store/configureStore.js b/app/store/configureStore.js new file mode 100644 index 0000000..d5ee806 --- /dev/null +++ b/app/store/configureStore.js @@ -0,0 +1,11 @@ +import { createStore, applyMiddleware } from 'redux'; +import rootReducer from '../reducers/rootReducer'; +import thunk from 'redux-thunk'; + +const store = createStore( + rootReducer, + window.__REDUX_DEVTOOLS_EXTENSION__ && window.__REDUX_DEVTOOLS_EXTENSION__(), + applyMiddleware(thunk) +); + +export default store; diff --git a/app/store/init.js b/app/store/init.js new file mode 100644 index 0000000..b7fabd0 --- /dev/null +++ b/app/store/init.js @@ -0,0 +1,12 @@ +import web3 from "Embark/web3" +import EmbarkJS from 'Embark/EmbarkJS' +import store from './configureStore' +import { fetchAndDispatchAccountsWithBalances } from '../actions/accounts' + +const dispatch = action => store.dispatch(action) + +export default () => { + __embarkContext.execWhenReady(async () => { + fetchAndDispatchAccountsWithBalances(web3, dispatch) + }) +} diff --git a/config/blockchain.js b/config/blockchain.js new file mode 100644 index 0000000..322754e --- /dev/null +++ b/config/blockchain.js @@ -0,0 +1,62 @@ +module.exports = { + development: { + enabled: true, + networkType: "custom", // Can be: testnet, rinkeby, livenet or custom, in which case, it will use the specified networkId + networkId: "1337", // Network id used when networkType is custom + isDev: true, // Uses and ephemeral proof-of-authority network with a pre-funded developer account, mining enabled + genesisBlock: "config/development/genesis.json", // Genesis block to initiate on first creation of a development node + datadir: ".embark/development/datadir", // Data directory for the databases and keystore + mineWhenNeeded: true, // Uses our custom script (if isDev is false) to mine only when needed + nodiscover: true, // Disables the peer discovery mechanism (manual peer addition) + maxpeers: 0, // Maximum number of network peers (network disabled if set to 0) (default: 25) + rpcHost: "localhost", // HTTP-RPC server listening interface (default: "localhost") + rpcPort: 8545, // HTTP-RPC server listening port (default: 8545) + rpcCorsDomain: "auto", // Comma separated list of domains from which to accept cross origin requests (browser enforced) + // When set to "auto", Embark will automatically set the cors to the address of the webserver + proxy: true, // Proxy is used to present meaningful information about transactions + account: { + // "address": "", // When specified, uses that address instead of the default one for the network + password: "config/development/password" // Password to unlock the account + }, + targetGasLimit: 8000000, // Target gas limit sets the artificial target gas floor for the blocks to mine + wsRPC: true, // Enable the WS-RPC server + wsOrigins: "auto", // Origins from which to accept websockets requests + // When set to "auto", Embark will automatically set the cors to the address of the webserver + wsHost: "localhost", // WS-RPC server listening interface (default: "localhost") + wsPort: 8546, // WS-RPC server listening port (default: 8546) + simulatorMnemonic: "example exile argue silk regular smile grass bomb merge arm assist farm", // Mnemonic used by the simulator to generate a wallet + simulatorBlocktime: 0 // Specify blockTime in seconds for automatic mining. Default is 0 and no auto-mining. + }, + testnet: { + enabled: true, + networkType: "testnet", + light: true, + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + account: { + password: "config/testnet/password" + } + }, + livenet: { + enabled: true, + networkType: "livenet", + light: true, + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + account: { + password: "config/livenet/password" + } + }, + privatenet: { + enabled: true, + networkType: "custom", + rpcHost: "localhost", + rpcPort: 8545, + rpcCorsDomain: "http://localhost:8000", + datadir: "yourdatadir", + networkId: "123", + bootnodes: "" + } +}; diff --git a/config/blockchain.json b/config/blockchain.json deleted file mode 100644 index 638c816..0000000 --- a/config/blockchain.json +++ /dev/null @@ -1,56 +0,0 @@ -{ - "development": { - "enabled": true, - "networkType": "custom", - "genesisBlock": "config/development/genesis.json", - "datadir": ".embark/development/datadir", - "mineWhenNeeded": true, - "nodiscover": true, - "maxpeers": 0, - "rpcHost": "localhost", - "rpcPort": 8545, - "rpcCorsDomain": "auto", - "account": { - "password": "config/development/password" - }, - "targetGasLimit": 8000000, - "wsOrigins": "auto", - "wsRPC": true, - "wsHost": "localhost", - "wsPort": 8546, - "simulatorMnemonic": "example exile argue silk regular smile grass bomb merge arm assist farm", - "simulatorBlocktime": 0 - }, - "testnet": { - "enabled": true, - "networkType": "testnet", - "light": true, - "rpcHost": "localhost", - "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", - "account": { - "password": "config/testnet/password" - } - }, - "livenet": { - "enabled": true, - "networkType": "livenet", - "light": true, - "rpcHost": "localhost", - "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", - "account": { - "password": "config/livenet/password" - } - }, - "privatenet": { - "enabled": true, - "networkType": "custom", - "rpcHost": "localhost", - "rpcPort": 8545, - "rpcCorsDomain": "http://localhost:8000", - "datadir": "yourdatadir", - "networkId": "123", - "bootnodes": "" - } -} diff --git a/config/communication.js b/config/communication.js new file mode 100644 index 0000000..8c4d1f9 --- /dev/null +++ b/config/communication.js @@ -0,0 +1,12 @@ +module.exports = { + default: { + enabled: true, + provider: "whisper", // Communication provider. Currently, Embark only supports whisper + available_providers: ["whisper"], // Array of available providers + connection: { + host: "localhost", // Host of the blockchain node + port: 8546, // Port of the blockchain node + type: "ws" // Type of connection (ws or rpc) + } + } +}; diff --git a/config/communication.json b/config/communication.json deleted file mode 100644 index 80ec2f8..0000000 --- a/config/communication.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "default": { - "enabled": true, - "provider": "whisper", - "available_providers": ["whisper", "orbit"], - "connection": { - "host": "localhost", - "port": 8546, - "type": "ws" - } - } -} diff --git a/config/contracts.js b/config/contracts.js new file mode 100644 index 0000000..19264aa --- /dev/null +++ b/config/contracts.js @@ -0,0 +1,33 @@ +module.exports = { + // default applies to all environments + default: { + // Blockchain node to deploy the contracts + deployment: { + host: "localhost", // Host of the blockchain node + port: 8545, // Port of the blockchain node + type: "rpc" // Type of connection (ws or rpc), + }, + // order of connections the dapp should connect to + dappConnection: [ + "$WEB3", // uses pre existing web3 object if available (e.g in Mist) + "ws://localhost:8546", + "http://localhost:8545" + ], + gas: "auto", + contracts: { + TestToken: { + deploy: false + }, + ERC20Receiver: { + deploy: false + } + } + }, + development: { + contracts: { + TestToken: { + deploy: true + } + } + } +}; diff --git a/config/namesystem.js b/config/namesystem.js new file mode 100644 index 0000000..10e20d6 --- /dev/null +++ b/config/namesystem.js @@ -0,0 +1,6 @@ +module.exports = { + default: { + available_providers: ["ens"], + provider: "ens" + } +}; diff --git a/config/storage.js b/config/storage.js new file mode 100644 index 0000000..59ef12b --- /dev/null +++ b/config/storage.js @@ -0,0 +1,35 @@ +module.exports = { + default: { + enabled: true, + ipfs_bin: "ipfs", + provider: "ipfs", + available_providers: ["ipfs"], + upload: { + host: "localhost", + port: 5001 + }, + dappConnection: [ + { + provider:"ipfs", + host: "localhost", + port: 5001, + getUrl: "http://localhost:8080/ipfs/" + } + ] + // Configuration to start Swarm in the same terminal as `embark run` + /*,account: { + address: "YOUR_ACCOUNT_ADDRESS", // Address of account accessing Swarm + password: "PATH/TO/PASSWORD/FILE" // File containing the password of the account + }, + swarmPath: "PATH/TO/SWARM/EXECUTABLE" // Path to swarm executable (default: swarm)*/ + }, + development: { + enabled: true, + provider: "ipfs", + upload: { + host: "localhost", + port: 5001, + getUrl: "http://localhost:8080/ipfs/" + } + } +}; diff --git a/config/storage.json b/config/storage.json deleted file mode 100644 index b286558..0000000 --- a/config/storage.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "default": { - "versions": { - "ipfs-api": "17.2.4" - }, - "enabled": true, - "ipfs_bin": "ipfs", - "provider": "ipfs", - "available_providers": ["ipfs"], - "host": "localhost", - "port": 5001 - }, - "development": { - "enabled": true, - "provider": "ipfs", - "host": "localhost", - "port": 5001, - "getUrl": "http://localhost:8080/ipfs/" - } -} diff --git a/config/webserver.js b/config/webserver.js new file mode 100644 index 0000000..1814065 --- /dev/null +++ b/config/webserver.js @@ -0,0 +1,5 @@ +module.exports = { + enabled: true, + host: "localhost", + port: 8000 +}; diff --git a/config/webserver.json b/config/webserver.json deleted file mode 100644 index c28a311..0000000 --- a/config/webserver.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "enabled": true, - "host": "localhost", - "port": 8000 -} diff --git a/contracts/common/MessageSigned.sol b/contracts/common/MessageSigned.sol index 5a5a262..95d2f14 100644 --- a/contracts/common/MessageSigned.sol +++ b/contracts/common/MessageSigned.sol @@ -46,7 +46,7 @@ contract MessageSigned { internal returns (bytes32 signHash) { - signHash = keccak256("\x19Ethereum Signed Message:\n32", _hash); + signHash = keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", _hash)); } /** diff --git a/contracts/token/StandardToken.sol b/contracts/token/StandardToken.sol index b80c513..2f4ede8 100644 --- a/contracts/token/StandardToken.sol +++ b/contracts/token/StandardToken.sol @@ -92,7 +92,11 @@ contract StandardToken is ERC20Token { { if (balances[_from] >= _value && _value > 0) { balances[_from] -= _value; - balances[_to] += _value; + if(_to == address(0)) { + supply -= _value; + } else { + balances[_to] += _value; + } emit Transfer(_from, _to, _value); return true; } else { diff --git a/embark.json b/embark.json index 7bd3d48..13e7e73 100644 --- a/embark.json +++ b/embark.json @@ -2,6 +2,7 @@ "contracts": ["contracts/**"], "app": { "js/dapp.js": ["app/dapp.js"], + "js/index.js": ["app/index.js"], "index.html": "app/index.html", "images/": ["app/images/**"] }, @@ -9,7 +10,7 @@ "config": "config/", "versions": { "web3": "1.0.0-beta", - "solc": "0.4.23", + "solc": "0.4.24", "ipfs-api": "17.2.4" }, "plugins": { diff --git a/package.json b/package.json index fb83081..2f8ae8c 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "", "scripts": { "solidity-coverage": "./node_modules/.bin/solidity-coverage", - "test": "embark test" + "test": "embark test", + "lint": "eslint" }, "repository": { "type": "git", @@ -17,9 +18,24 @@ }, "homepage": "https://github.com/status-im/contracts#readme", "dependencies": { + "prop-types": "^15.6.1", "react": "^16.3.2", "react-blockies": "^1.3.0", "react-bootstrap": "^0.32.1", - "react-dom": "^16.3.2" + "react-dom": "^16.3.2", + "react-redux": "^5.0.7", + "redux": "^4.0.0", + "redux-action-creator": "^2.3.0", + "redux-thunk": "^2.3.0", + "reselect": "^3.0.1" + }, + "devDependencies": { + "babel-plugin-transform-object-rest-spread": "^6.26.0", + "babel-preset-stage-2": "^6.24.1", + "eslint": "^4.19.1", + "eslint-config-airbnb": "^16.1.0", + "eslint-plugin-import": "^2.12.0", + "eslint-plugin-jsx-a11y": "^6.0.3", + "eslint-plugin-react": "^7.8.2" } } diff --git a/test/abstract/controlled.js b/test/abstract/controlled.js new file mode 100644 index 0000000..0d5ba8d --- /dev/null +++ b/test/abstract/controlled.js @@ -0,0 +1,25 @@ + +exports.Test = (Controlled) => { + describe("Controlled", async function() { + this.timeout(0); + var accounts; + before(function(done) { + web3.eth.getAccounts().then(function (res) { + accounts = res; + done(); + }); + }); + + + it("should start with msg.sender as controller", async function() { + var controller = await Controlled.methods.controller().call(); + assert(controller, accounts[0]); + }); + + it("should allow controller to set new controller", async function() { + await Controlled.methods.changeController(accounts[1]).send({from: accounts[0]}); + var controller = await Controlled.methods.controller().call(); + assert(controller, accounts[1]); + }); + }); +} \ No newline at end of file diff --git a/test/abstract/erc20tokenspec.js b/test/abstract/erc20tokenspec.js new file mode 100644 index 0000000..e5f0637 --- /dev/null +++ b/test/abstract/erc20tokenspec.js @@ -0,0 +1,85 @@ + +const ERC20Receiver = require('Embark/contracts/ERC20Receiver'); + +exports.config = { + contracts : { + "ERC20Receiver": { + } + } +} + +exports.Test = (ERC20Token) => { + describe("ERC20Token", function() { + + var accounts; + before(function(done) { + web3.eth.getAccounts().then(function (res) { + accounts = res; + done(); + }); + }); + + it("should transfer 1 token", async function() { + let initialBalance0 = await ERC20Token.methods.balanceOf(accounts[0]).call(); + let initialBalance1 = await ERC20Token.methods.balanceOf(accounts[1]).call(); + await ERC20Token.methods.transfer(accounts[1],1).send({from: accounts[0]}); + let result0 = await ERC20Token.methods.balanceOf(accounts[0]).call(); + let result1 = await ERC20Token.methods.balanceOf(accounts[1]).call(); + + assert.equal(result0, +initialBalance0-1, "account 0 balance unexpected"); + assert.equal(result1, +initialBalance1+1, "account 1 balance unexpected"); + }); + + it("should set approved amount", async function() { + await ERC20Token.methods.approve(accounts[2],10000000).send({from: accounts[0]}); + let result = await ERC20Token.methods.allowance(accounts[0], accounts[2]).call(); + assert.equal(result, 10000000); + }); + + it("should consume allowance amount", async function() { + let initialAllowance = await ERC20Token.methods.allowance(accounts[0], accounts[2]).call(); + await ERC20Token.methods.transferFrom(accounts[0], accounts[0],1).send({from: accounts[2]}); + let result = await ERC20Token.methods.allowance(accounts[0], accounts[2]).call(); + + assert.equal(result, +initialAllowance-1); + }); + + it("should transfer approved amount", async function() { + let initialBalance0 = await ERC20Token.methods.balanceOf(accounts[0]).call(); + let initialBalance1 = await ERC20Token.methods.balanceOf(accounts[1]).call(); + await ERC20Token.methods.transferFrom(accounts[0], accounts[1],1).send({from: accounts[2]}); + let result0 = await ERC20Token.methods.balanceOf(accounts[0]).call(); + let result1 = await ERC20Token.methods.balanceOf(accounts[1]).call(); + + assert.equal(result0, +initialBalance0-1); + assert.equal(result1, +initialBalance1+1); + }); + + + it("should unset approved amount", async function() { + await ERC20Token.methods.approve(accounts[2],0).send({from: accounts[0]}); + let result = await ERC20Token.methods.allowance(accounts[0], accounts[2]).call(); + assert.equal(result, 0); + }); + + it("should deposit approved amount to contract ERC20Receiver", async function() { + //ERC20Receiver = await ERC20Receiver.deploy().send(); + //console.log(ERC20Receiver.address); + await ERC20Token.methods.approve(ERC20Receiver.address, 10).send({from: accounts[0]}); + await ERC20Receiver.methods.depositToken(ERC20Token.address, 10).send({from: accounts[0]}); + let result = await ERC20Receiver.methods.tokenBalanceOf(ERC20Token.address, accounts[0]).call(); + assert.equal(result, 10, "ERC20Receiver.tokenBalanceOf("+ERC20Token.address+","+accounts[0]+") wrong"); + }); + + it("should witdraw approved amount from contract ERC20Receiver", async function() { + let tokenBalance = await ERC20Receiver.methods.tokenBalanceOf(ERC20Token.address, accounts[0]).call(); + await ERC20Receiver.methods.withdrawToken(ERC20Token.address, tokenBalance).send({from: accounts[0]}); + tokenBalance = await ERC20Receiver.methods.tokenBalanceOf(ERC20Token.address, accounts[0]).call(); + assert.equal(tokenBalance, 0, "ERC20Receiver.tokenBalanceOf("+ERC20Token.address+","+accounts[0]+") wrong"); + }); + + //TODO: include checks for expected events fired + + + }); +} \ No newline at end of file diff --git a/test/controlled.js b/test/controlled.js deleted file mode 100644 index d2b14b4..0000000 --- a/test/controlled.js +++ /dev/null @@ -1,29 +0,0 @@ - -exports.Test = (contractsConfig, afterDeploy) => { - - describe("Controlled", async function() { - this.timeout(0); - var Controlled; - var accountsArr; - before(function(done) { - EmbarkSpec.deployAll(contractsConfig, async function(accounts) { - Controlled = Contract; - accountsArr = accounts; - await afterDeploy(accounts, Contract); - done() - }); - }); - - - it("should start with msg.sender as controller", async function() { - var controller = await Controlled.methods.controller().call(); - assert(controller, accountsArr[0]); - }); - - it("should allow controller to set new controller", async function() { - await Controlled.methods.changeController(accountsArr[1]).send({from: accountsArr[0]}); - var controller = await Controlled.methods.controller().call(); - assert(controller, accountsArr[1]); - }); - }); -} \ No newline at end of file diff --git a/test/erc20token.js b/test/erc20token.js deleted file mode 100644 index 6889734..0000000 --- a/test/erc20token.js +++ /dev/null @@ -1,78 +0,0 @@ - -exports.Test = (contractsConfig, afterDeploy) => { - describe("ERC20Token", async function() { - this.timeout(0); - var ERC20Token; - var accountsArr; - before(function(done) { - contractsConfig["ERC20Receiver"] = {}; - EmbarkSpec.deployAll(contractsConfig, async function(accounts) { - ERC20Token = Contract; - accountsArr = accounts; - await afterDeploy(accounts, Contract); - done() - }); - }); - - it("should transfer 1 token", async function() { - let initialBalance0 = await ERC20Token.methods.balanceOf(accountsArr[0]).call(); - let initialBalance1 = await ERC20Token.methods.balanceOf(accountsArr[1]).call(); - await ERC20Token.methods.transfer(accountsArr[1],1).send({from: accountsArr[0]}); - let result0 = await ERC20Token.methods.balanceOf(accountsArr[0]).call(); - let result1 = await ERC20Token.methods.balanceOf(accountsArr[1]).call(); - - assert.equal(result0, +initialBalance0-1, "account 0 balance unexpected"); - assert.equal(result1, +initialBalance1+1, "account 1 balance unexpected"); - }); - - it("should set approved amount", async function() { - await ERC20Token.methods.approve(accountsArr[2],10000000).send({from: accountsArr[0]}); - let result = await ERC20Token.methods.allowance(accountsArr[0], accountsArr[2]).call(); - assert.equal(result, 10000000); - }); - - it("should consume allowance amount", async function() { - let initialAllowance = await ERC20Token.methods.allowance(accountsArr[0], accountsArr[2]).call(); - await ERC20Token.methods.transferFrom(accountsArr[0], accountsArr[0],1).send({from: accountsArr[2]}); - let result = await ERC20Token.methods.allowance(accountsArr[0], accountsArr[2]).call(); - - assert.equal(result, +initialAllowance-1); - }); - - it("should transfer approved amount", async function() { - let initialBalance0 = await ERC20Token.methods.balanceOf(accountsArr[0]).call(); - let initialBalance1 = await ERC20Token.methods.balanceOf(accountsArr[1]).call(); - await ERC20Token.methods.transferFrom(accountsArr[0], accountsArr[1],1).send({from: accountsArr[2]}); - let result0 = await ERC20Token.methods.balanceOf(accountsArr[0]).call(); - let result1 = await ERC20Token.methods.balanceOf(accountsArr[1]).call(); - - assert.equal(result0, +initialBalance0-1); - assert.equal(result1, +initialBalance1+1); - }); - - - it("should unset approved amount", async function() { - await ERC20Token.methods.approve(accountsArr[2],0).send({from: accountsArr[0]}); - let result = await ERC20Token.methods.allowance(accountsArr[0], accountsArr[2]).call(); - assert.equal(result, 0); - }); - - it("should deposit approved amount to contract ERC20Receiver", async function() { - await ERC20Token.methods.approve(ERC20Receiver.address,10).send({from: accountsArr[0]}); - await ERC20Receiver.methods.depositToken(ERC20Token.address).send({from: accountsArr[0]}); - let result = await ERC20Receiver.methods.tokenBalanceOf(ERC20Token.address, accountsArr[0]).call(); - assert.equal(result, 10, "ERC20Receiver.tokenBalanceOf("+ERC20Token.address+","+accountsArr[0]+") wrong"); - }); - - it("should witdraw approved amount from contract ERC20Receiver", async function() { - let tokenBalance = await ERC20Receiver.methods.tokenBalanceOf(ERC20Token.address, accountsArr[0]).call(); - await ERC20Receiver.methods.withdrawToken(ERC20Token.address, tokenBalance).send({from: accountsArr[0]}); - tokenBalance = await ERC20Receiver.methods.tokenBalanceOf(ERC20Token.address, accountsArr[0]).call(); - assert.equal(tokenBalance, 0, "ERC20Receiver.tokenBalanceOf("+ERC20Token.address+","+accountsArr[0]+") wrong"); - }); - - //TODO: include checks for expected events fired - - - }); -} \ No newline at end of file diff --git a/test/testtoken.js b/test/testtoken.js index 15fcd15..3e17461 100644 --- a/test/testtoken.js +++ b/test/testtoken.js @@ -1,39 +1,55 @@ -const ERC20Token = require('./erc20token'); +const Utils = require('../utils/testUtils'); +const TestToken = require('Embark/contracts/TestToken'); +const ERC20TokenSpec = require('./abstract/erc20tokenspec'); -describe("TestToken", async function() { +config({ + contracts: { + "TestToken": { + }, + ...ERC20TokenSpec.config.contracts + } +}); + +contract("TestToken", function() { this.timeout(0); - var accountsArr; - + var accounts; before(function(done) { - var contractsConfig = { - "TestToken": { - } - }; - EmbarkSpec.deployAll(contractsConfig, async function(accounts) { - accountsArr = accounts - done() + web3.eth.getAccounts().then(function (res) { + accounts = res; + done(); }); }); it("should increase totalSupply in mint", async function() { let initialSupply = await TestToken.methods.totalSupply().call(); - await TestToken.methods.mint(100).send({from: accountsArr[0]}); + await TestToken.methods.mint(100).send(); let result = await TestToken.methods.totalSupply().call(); assert.equal(result, +initialSupply+100); }); it("should increase accountBalance in mint", async function() { - let initialBalance = await TestToken.methods.balanceOf(accountsArr[0]).call(); - await TestToken.methods.mint(100).send({from: accountsArr[0]}); - let result = await TestToken.methods.balanceOf(accountsArr[0]).call(); + let initialBalance = await TestToken.methods.balanceOf(accounts[0]).call(); + await TestToken.methods.mint(100).send({from: accounts[0]}); + let result = await TestToken.methods.balanceOf(accounts[0]).call(); assert.equal(result, +initialBalance+100); }); - var erc20tokenConfig = { - "Contract": { "instanceOf" : "TestToken" } - } - ERC20Token.Test(erc20tokenConfig, async function (accounts, TestToken) { + + it("should burn account supply", async function() { + let initialBalance = await TestToken.methods.balanceOf(accounts[0]).call(); + await TestToken.methods.transfer(Utils.zeroAddress, initialBalance).send({from: accounts[0]}); + assert.equal(await TestToken.methods.totalSupply().call(), 0); + assert.equal(await TestToken.methods.balanceOf(accounts[0]).call(), 0); + }) + + it("should mint balances for ERC20TokenSpec", async function() { + let initialBalance = 7 * 10 ^ 18; for(i=0;i { params: [+amount], id: new Date().getSeconds() }, - (error) => { + async (error) => { if (error) { console.log(error); return reject(err); } - web3.currentProvider.sendAsync( + await web3.currentProvider.sendAsync( { jsonrpc: '2.0', method: 'evm_mine', From 92fe38a547d194cb831592f9fd3e4832f97fc0ce Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Sat, 30 Jun 2018 02:24:56 -0300 Subject: [PATCH 3/5] tests for embark31 --- test/minimetoken.js | 88 ++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 49 deletions(-) diff --git a/test/minimetoken.js b/test/minimetoken.js index 6af6975..1e63096 100644 --- a/test/minimetoken.js +++ b/test/minimetoken.js @@ -1,35 +1,40 @@ const utils = require('../utils/testUtils') -const ERC20Token = require('./erc20token'); -const Controlled = require('./controlled'); -describe("MiniMeToken", async function() { +const MiniMeToken = require('Embark/contracts/MiniMeToken'); +const ERC20TokenSpec = require('./abstract/erc20tokenspec'); +const ControlledSpec = require('./abstract/controlled'); + +config({ + contracts: { + "MiniMeTokenFactory": { + }, + "MiniMeToken": { + "args": [ + "$MiniMeTokenFactory", + utils.zeroAddress, + 0, + "TestMiniMeToken", + 18, + "TST", + true + ] + }, + ...ERC20TokenSpec.config.contracts + } +}); + + +contract("MiniMeToken", function() { this.timeout(0); var accounts; - var miniMeTokenClone; - const b = []; - before(function(done) { - var contractsConfig = { - "MiniMeTokenFactory": { - }, - "MiniMeToken": { - "args": [ - "$MiniMeTokenFactory", - utils.zeroAddress, - 0, - "TestMiniMeToken", - 18, - "TST", - true - ] - } - }; - EmbarkSpec.deployAll(contractsConfig, async function(accountsArr) { - accounts = accountsArr - done() + web3.eth.getAccounts().then(function (res) { + accounts = res; + done(); }); }); - + var miniMeTokenClone; + const b = []; it('should generate tokens for address 1', async () => { await MiniMeToken.methods.generateTokens(accounts[1], 10).send(); @@ -99,32 +104,17 @@ describe("MiniMeToken", async function() { assert.equal(await miniMeTokenClone.methods.balanceOf(accounts[1]).call(), 12); assert.equal(await miniMeTokenClone.methods.balanceOf(accounts[2]).call(), 4); }); + - var erc20tokenConfig = { - "MiniMeTokenFactory": { - }, - "Contract": { - "instanceOf" : "MiniMeToken", - "args": [ - "$MiniMeTokenFactory", - utils.zeroAddress, - 0, - "TestMiniMeToken", - 18, - "TST", - true - ] - } - } - - ERC20Token.Test(erc20tokenConfig, async function (accounts, MiniMeToken) { + it("should mint balances for ERC20TokenSpec", async function() { + let initialBalance = 7 * 10 ^ 18; for(i=0;i Date: Sat, 30 Jun 2018 02:25:07 -0300 Subject: [PATCH 4/5] use js config --- config/contracts.js | 6 ++++++ config/contracts.json | 29 ----------------------------- 2 files changed, 6 insertions(+), 29 deletions(-) delete mode 100644 config/contracts.json diff --git a/config/contracts.js b/config/contracts.js index 19264aa..3bc0485 100644 --- a/config/contracts.js +++ b/config/contracts.js @@ -20,6 +20,12 @@ module.exports = { }, ERC20Receiver: { deploy: false + }, + MiniMeToken: { + deploy: false + }, + MiniMeTokenFactory: { + deploy: true } } }, diff --git a/config/contracts.json b/config/contracts.json deleted file mode 100644 index 87eb4db..0000000 --- a/config/contracts.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "default": { - "versions": { - "web3.js": "1.0.0-beta", - "solc": "0.4.23" - }, - "deployment": { - "host": "localhost", - "port": 8545, - "type": "rpc" - }, - "dappConnection": [ - "$WEB3", - "http://localhost:8545" - ], - "gas": "auto", - "contracts": { - "ERC20Receiver": { - "deploy": false - }, - "MiniMeToken": { - "deploy": false - }, - "MiniMeTokenFactory": { - "deploy": true - } - } - } -} From c3add476c985f347de46c92abc348b700f813e55 Mon Sep 17 00:00:00 2001 From: Ricardo Guilherme Schmidt <3esmit@gmail.com> Date: Sat, 30 Jun 2018 02:33:32 -0300 Subject: [PATCH 5/5] merge bootstrap --- app/components/accountList.js | 66 +++++++++++++++++++++++++++++++++++ test/abstract/controlled.js | 6 ++++ 2 files changed, 72 insertions(+) create mode 100644 app/components/accountList.js diff --git a/app/components/accountList.js b/app/components/accountList.js new file mode 100644 index 0000000..adcd873 --- /dev/null +++ b/app/components/accountList.js @@ -0,0 +1,66 @@ +import web3 from 'Embark/web3' +import React from 'react'; +import { connect } from 'react-redux'; +import { Nav, MenuItem, NavDropdown } from 'react-bootstrap'; +import Blockies from 'react-blockies'; +import { string, bool, func, arrayOf, shape } from 'prop-types'; +import { getAccounts, getDefaultAccount, accountsIsLoading, actions as accountActions } from '../reducers/accounts'; +import './accountlist.css'; + +const AccList = ({ + accounts, defaultAccount, changeAccount, isLoading, classNameNavDropdown, +}) => ( + + {!isLoading ? +
+
+ +
+
+ +
+
+ :
Loading...
} +
+); + +AccList.propTypes = { + accounts: arrayOf(shape({ address: string, balance: string })).isRequired, + defaultAccount: string, + changeAccount: func.isRequired, + isLoading: bool.isRequired, + classNameNavDropdown: string +} + +const mapStateToProps = state => ({ + accounts: getAccounts(state), + defaultAccount: getDefaultAccount(state), + isLoading: accountsIsLoading(state), +}); + +const mapDispatchToProps = dispatch => ({ + changeAccount(address) { + web3.eth.defaultAccount = address; + dispatch(accountActions.updateDefaultAccount(address)); + }, +}); + +export default connect(mapStateToProps, mapDispatchToProps)(AccList); diff --git a/test/abstract/controlled.js b/test/abstract/controlled.js index 0d5ba8d..95e0197 100644 --- a/test/abstract/controlled.js +++ b/test/abstract/controlled.js @@ -21,5 +21,11 @@ exports.Test = (Controlled) => { var controller = await Controlled.methods.controller().call(); assert(controller, accounts[1]); }); + + it("should set back to original controller", async function() { + await Controlled.methods.changeController(accounts[0]).send({from: accounts[1]}); + var controller = await Controlled.methods.controller().call(); + assert(controller, accounts[0]); + }); }); } \ No newline at end of file