diff --git a/app/scripts/controllers/balance.js b/app/scripts/controllers/balance.js new file mode 100644 index 000000000..5dfe266e3 --- /dev/null +++ b/app/scripts/controllers/balance.js @@ -0,0 +1,28 @@ +const ObservableStore = require('obs-store') +const normalizeAddress = require('eth-sig-util').normalize +const extend = require('xtend') +const PendingBalanceCalculator = require('../lib/pending-balance-calculator') + +class BalanceController { + + constructor (opts = {}) { + const { address, ethQuery, txController } = opts + this.ethQuery = ethQuery + this.txController = txController + + const initState = extend({ + ethBalance: undefined, + }, opts.initState) + this.store = new ObservableStore(initState) + + const { getBalance, getPendingTransactions } = opts + this.balanceCalc = new PendingBalanceCalculator({ + getBalance, + getPendingTransactions, + }) + this.updateBalance() + } + +} + +module.exports = BalanceController diff --git a/app/scripts/controllers/balances.js b/app/scripts/controllers/balances.js new file mode 100644 index 000000000..b0b366628 --- /dev/null +++ b/app/scripts/controllers/balances.js @@ -0,0 +1,108 @@ +const ObservableStore = require('obs-store') +const normalizeAddress = require('eth-sig-util').normalize +const extend = require('xtend') +const BalanceController = require('./balance') + +class BalancesController { + + constructor (opts = {}) { + const { ethStore, txController } = opts + this.ethStore = ethStore + this.txController = txController + + const initState = extend({ + balances: [], + }, opts.initState) + this.store = new ObservableStore(initState) + + this._initBalanceUpdating() + } + + // PUBLIC METHODS + + setSelectedAddress (_address) { + return new Promise((resolve, reject) => { + const address = normalizeAddress(_address) + this.store.updateState({ selectedAddress: address }) + resolve() + }) + } + + getSelectedAddress (_address) { + return this.store.getState().selectedAddress + } + + addToken (rawAddress, symbol, decimals) { + const address = normalizeAddress(rawAddress) + const newEntry = { address, symbol, decimals } + + const tokens = this.store.getState().tokens + const previousIndex = tokens.find((token, index) => { + return token.address === address + }) + + if (previousIndex) { + tokens[previousIndex] = newEntry + } else { + tokens.push(newEntry) + } + + this.store.updateState({ tokens }) + return Promise.resolve() + } + + getTokens () { + return this.store.getState().tokens + } + + updateFrequentRpcList (_url) { + return this.addToFrequentRpcList(_url) + .then((rpcList) => { + this.store.updateState({ frequentRpcList: rpcList }) + return Promise.resolve() + }) + } + + setCurrentAccountTab (currentAccountTab) { + return new Promise((resolve, reject) => { + this.store.updateState({ currentAccountTab }) + resolve() + }) + } + + addToFrequentRpcList (_url) { + const rpcList = this.getFrequentRpcList() + const index = rpcList.findIndex((element) => { return element === _url }) + if (index !== -1) { + rpcList.splice(index, 1) + } + if (_url !== 'http://localhost:8545') { + rpcList.push(_url) + } + if (rpcList.length > 2) { + rpcList.shift() + } + return Promise.resolve(rpcList) + } + + getFrequentRpcList () { + return this.store.getState().frequentRpcList + } + // + // PRIVATE METHODS + // + _initBalanceUpdating () { + const store = this.ethStore.getState() + const balances = store.accounts + + for (let address in balances) { + let updater = new BalancesController({ + address, + ethQuery: this.ethQuery, + txController: this.txController, + }) + } + } +} + +module.exports = BalancesController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a007d6fc5..81e31a556 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -115,6 +115,12 @@ module.exports = class MetamaskController extends EventEmitter { }) this.txController.on('newUnaprovedTx', opts.showUnapprovedTx.bind(opts)) + // computed balances (accounting for pending transactions) + this.balancesController = new BalancesController({ + ethStore: this.ethStore, + txController: this.txController, + }) + // notices this.noticeController = new NoticeController({ initState: initState.NoticeController, @@ -647,4 +653,4 @@ module.exports = class MetamaskController extends EventEmitter { return Promise.resolve(rpcTarget) }) } -} \ No newline at end of file +} diff --git a/test/unit/pending-balance-test.js b/test/unit/pending-balance-test.js index 17be0306b..dde30fecc 100644 --- a/test/unit/pending-balance-test.js +++ b/test/unit/pending-balance-test.js @@ -96,3 +96,4 @@ function generateBalanceCalcWith (transactions, providerStub = zeroBn) { getPendingTransactions, }) } +