diff options
-rw-r--r-- | app/scripts/controllers/network/contract-addresses.js | 11 | ||||
-rw-r--r-- | app/scripts/lib/account-tracker.js | 61 | ||||
-rw-r--r-- | app/scripts/metamask-controller.js | 1 |
3 files changed, 70 insertions, 3 deletions
diff --git a/app/scripts/controllers/network/contract-addresses.js b/app/scripts/controllers/network/contract-addresses.js new file mode 100644 index 000000000..5cd7da1d0 --- /dev/null +++ b/app/scripts/controllers/network/contract-addresses.js @@ -0,0 +1,11 @@ +const SINGLE_CALL_BALANCES_ADDRESS = '0xb1f8e55c7f64d203c1400b9d8555d050f94adf39' +const SINGLE_CALL_BALANCES_ADDRESS_RINKEBY = '0x9f510b19f1ad66f0dcf6e45559fab0d6752c1db7' +const SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN = '0xb8e671734ce5c8d7dfbbea5574fa4cf39f7a54a4' +const SINGLE_CALL_BALANCES_ADDRESS_KOVAN = '0xb1d3fbb2f83aecd196f474c16ca5d9cffa0d0ffc' + +module.exports = { + SINGLE_CALL_BALANCES_ADDRESS, + SINGLE_CALL_BALANCES_ADDRESS_RINKEBY, + SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, + SINGLE_CALL_BALANCES_ADDRESS_KOVAN, +} diff --git a/app/scripts/lib/account-tracker.js b/app/scripts/lib/account-tracker.js index 2e9340018..24c5ef7ee 100644 --- a/app/scripts/lib/account-tracker.js +++ b/app/scripts/lib/account-tracker.js @@ -11,6 +11,12 @@ const EthQuery = require('eth-query') const ObservableStore = require('obs-store') const log = require('loglevel') const pify = require('pify') +const Web3 = require('web3') +const SINGLE_CALL_BALANCES_ABI = require('single-call-balance-checker-abi') + +const { bnToHex } = require('./util') +const { MAINNET_CODE, RINKEYBY_CODE, ROPSTEN_CODE, KOVAN_CODE } = require('../controllers/network/enums') +const { SINGLE_CALL_BALANCES_ADDRESS, SINGLE_CALL_BALANCES_ADDRESS_RINKEBY, SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN, SINGLE_CALL_BALANCES_ADDRESS_KOVAN } = require('../controllers/network/contract-addresses') class AccountTracker { @@ -50,6 +56,9 @@ class AccountTracker { }) // bind function for easier listener syntax this._updateForBlock = this._updateForBlock.bind(this) + this.network = opts.network + + this.web3 = new Web3(this._provider) } start () { @@ -116,7 +125,7 @@ class AccountTracker { this.store.updateState({ accounts }) // fetch balances for the accounts if there is block number ready if (!this._currentBlockNumber) return - addresses.forEach(address => this._updateAccount(address)) + this._updateAccounts() } /** @@ -161,7 +170,8 @@ class AccountTracker { } /** - * Calls this._updateAccount for each account in this.store + * balanceChecker is deployed on main eth (test)nets and requires a single call + * for all other networks, calls this._updateAccount for each account in this.store * * @returns {Promise} after all account balances updated * @@ -169,7 +179,28 @@ class AccountTracker { async _updateAccounts () { const accounts = this.store.getState().accounts const addresses = Object.keys(accounts) - await Promise.all(addresses.map(this._updateAccount.bind(this))) + const currentNetwork = parseInt(this.network.getNetworkState()) + + switch (currentNetwork) { + case MAINNET_CODE: + await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS) + break + + case RINKEYBY_CODE: + await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_RINKEBY) + break + + case ROPSTEN_CODE: + await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_ROPSTEN) + break + + case KOVAN_CODE: + await this._updateAccountsViaBalanceChecker(addresses, SINGLE_CALL_BALANCES_ADDRESS_KOVAN) + break + + default: + await Promise.all(addresses.map(this._updateAccount.bind(this))) + } } /** @@ -192,6 +223,30 @@ class AccountTracker { this.store.updateState({ accounts }) } + /** + * Updates current address balances from balanceChecker deployed contract instance + * @param {*} addresses + * @param {*} deployedContractAddress + */ + async _updateAccountsViaBalanceChecker (addresses, deployedContractAddress) { + const accounts = this.store.getState().accounts + this.web3.setProvider(this._provider) + const ethContract = this.web3.eth.contract(SINGLE_CALL_BALANCES_ABI).at(deployedContractAddress) + const ethBalance = ['0x0'] + + ethContract.balances(addresses, ethBalance, (error, result) => { + if (error) { + log.warn(`MetaMask - Account Tracker single call balance fetch failed`, error) + return Promise.all(addresses.map(this._updateAccount.bind(this))) + } + addresses.forEach((address, index) => { + const balance = bnToHex(result[index]) + accounts[address] = { address, balance } + }) + this.store.updateState({ accounts }) + }) + } + } module.exports = AccountTracker diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b75f95d01..6555f179d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -133,6 +133,7 @@ module.exports = class MetamaskController extends EventEmitter { this.accountTracker = new AccountTracker({ provider: this.provider, blockTracker: this.blockTracker, + network: this.networkController, }) // start and stop polling for balances based on activeControllerConnections |