From 10ff77477cf3163eaea5ac9485977d91bcc102c0 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sun, 17 Dec 2017 16:36:03 -0800 Subject: [PATCH 1/5] Add Recent Blocks controller Tracks recent blocks, useful for estimating recent successful gas prices. --- app/scripts/controllers/recent-blocks.js | 37 ++++++++++++++++++++++ app/scripts/metamask-controller.js | 39 +++++++++++++++--------- 2 files changed, 62 insertions(+), 14 deletions(-) create mode 100644 app/scripts/controllers/recent-blocks.js diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js new file mode 100644 index 000000000..27f9013ff --- /dev/null +++ b/app/scripts/controllers/recent-blocks.js @@ -0,0 +1,37 @@ +const ObservableStore = require('obs-store') +const extend = require('xtend') + +class RecentBlocksController { + + constructor (opts = {}) { + const { blockTracker } = opts + this.blockTracker = blockTracker + this.historyLength = opts.historyLength || 40 + + const initState = extend({ + recentBlocks: [], + }, opts.initState) + this.store = new ObservableStore(initState) + + this.blockTracker.on('block', this.processBlock.bind(this)) + } + + resetState () { + this.store.updateState({ + recentBlocks: [], + }) + } + + processBlock (newBlock) { + const state = this.store.getState() + state.recentBlocks.push(newBlock) + + while (state.recentBlocks.length > this.historyLength) { + state.recentBlocks.shift() + } + + this.store.updateState(state) + } +} + +module.exports = RecentBlocksController diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 9d126b416..23f2a1598 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -23,6 +23,7 @@ const ShapeShiftController = require('./controllers/shapeshift') const AddressBookController = require('./controllers/address-book') const InfuraController = require('./controllers/infura') const BlacklistController = require('./controllers/blacklist') +const RecentBlocksController = require('./controllers/recent-blocks') const MessageManager = require('./lib/message-manager') const PersonalMessageManager = require('./lib/personal-message-manager') const TypedMessageManager = require('./lib/typed-message-manager') @@ -91,6 +92,10 @@ module.exports = class MetamaskController extends EventEmitter { this.provider = this.initializeProvider() this.blockTracker = this.provider._blockTracker + this.recentBlocksController = new RecentBlocksController({ + blockTracker: this.blockTracker, + }) + // eth data query tools this.ethQuery = new EthQuery(this.provider) // account tracker watches balances, nonces, and any code at their address. @@ -196,25 +201,30 @@ module.exports = class MetamaskController extends EventEmitter { this.blacklistController.store.subscribe((state) => { this.store.updateState({ BlacklistController: state }) }) + this.recentBlocksController.store.subscribe((state) => { + this.store.updateState({ RecentBlocks: state }) + }) this.infuraController.store.subscribe((state) => { this.store.updateState({ InfuraController: state }) }) // manual mem state subscriptions - this.networkController.store.subscribe(this.sendUpdate.bind(this)) - this.accountTracker.store.subscribe(this.sendUpdate.bind(this)) - this.txController.memStore.subscribe(this.sendUpdate.bind(this)) - this.balancesController.store.subscribe(this.sendUpdate.bind(this)) - this.messageManager.memStore.subscribe(this.sendUpdate.bind(this)) - this.personalMessageManager.memStore.subscribe(this.sendUpdate.bind(this)) - this.typedMessageManager.memStore.subscribe(this.sendUpdate.bind(this)) - this.keyringController.memStore.subscribe(this.sendUpdate.bind(this)) - this.preferencesController.store.subscribe(this.sendUpdate.bind(this)) - this.addressBookController.store.subscribe(this.sendUpdate.bind(this)) - this.currencyController.store.subscribe(this.sendUpdate.bind(this)) - this.noticeController.memStore.subscribe(this.sendUpdate.bind(this)) - this.shapeshiftController.store.subscribe(this.sendUpdate.bind(this)) - this.infuraController.store.subscribe(this.sendUpdate.bind(this)) + const sendUpdate = this.sendUpdate.bind(this) + this.networkController.store.subscribe(sendUpdate) + this.accountTracker.store.subscribe(sendUpdate) + this.txController.memStore.subscribe(sendUpdate) + this.balancesController.store.subscribe(sendUpdate) + this.messageManager.memStore.subscribe(sendUpdate) + this.personalMessageManager.memStore.subscribe(sendUpdate) + this.typedMessageManager.memStore.subscribe(sendUpdate) + this.keyringController.memStore.subscribe(sendUpdate) + this.preferencesController.store.subscribe(sendUpdate) + this.recentBlocksController.store.subscribe(sendUpdate) + this.addressBookController.store.subscribe(sendUpdate) + this.currencyController.store.subscribe(sendUpdate) + this.noticeController.memStore.subscribe(sendUpdate) + this.shapeshiftController.store.subscribe(sendUpdate) + this.infuraController.store.subscribe(sendUpdate) } // @@ -298,6 +308,7 @@ module.exports = class MetamaskController extends EventEmitter { this.currencyController.store.getState(), this.noticeController.memStore.getState(), this.infuraController.store.getState(), + this.recentBlocksController.store.getState(), // config manager this.configManager.getConfig(), this.shapeshiftController.store.getState(), From 9bb701f0633bb117bf67f13935b5e121b6b9837a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 18 Dec 2017 15:49:55 -0800 Subject: [PATCH 2/5] Add failing test for updating token details --- test/unit/preferences-controller-test.js | 48 ++++++++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 test/unit/preferences-controller-test.js diff --git a/test/unit/preferences-controller-test.js b/test/unit/preferences-controller-test.js new file mode 100644 index 000000000..9fb5e4251 --- /dev/null +++ b/test/unit/preferences-controller-test.js @@ -0,0 +1,48 @@ +const assert = require('assert') +const PreferencesController = require('../../app/scripts/controllers/preferences') + +describe('preferences controller', function () { + let preferencesController + + before(() => { + preferencesController = new PreferencesController() + }) + + describe('addToken', function () { + it('should add that token to its state', async function () { + const address = '0xabcdef1234567' + const symbol = 'ABBR' + const decimals = 5 + + await preferencesController.addToken(address, symbol, decimals) + + const tokens = preferencesController.getTokens() + assert.equal(tokens.length, 1, 'one token added') + + const added = tokens[0] + assert.equal(added.address, address, 'set address correctly') + assert.equal(added.symbol, symbol, 'set symbol correctly') + assert.equal(added.decimals, decimals, 'set decimals correctly') + }) + + it('should allow updating a token value', async function () { + const address = '0xabcdef1234567' + const symbol = 'ABBR' + const decimals = 5 + + await preferencesController.addToken(address, symbol, decimals) + + const newDecimals = 6 + await preferencesController.addToken(address, symbol, newDecimals) + + const tokens = preferencesController.getTokens() + assert.equal(tokens.length, 1, 'one token added') + + const added = tokens[0] + assert.equal(added.address, address, 'set address correctly') + assert.equal(added.symbol, symbol, 'set symbol correctly') + assert.equal(added.decimals, newDecimals, 'updated decimals correctly') + }) + }) +}) + From 975f7279c713d88bb59205073540b2185f3a812f Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 18 Dec 2017 15:57:04 -0800 Subject: [PATCH 3/5] Allow updating token details Fixes #2173 --- app/scripts/controllers/preferences.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index bc4848421..c42f47037 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -26,23 +26,23 @@ class PreferencesController { return this.store.getState().selectedAddress } - addToken (rawAddress, symbol, decimals) { + async 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) => { + const previousEntry = tokens.find((token, index) => { return token.address === address }) + const previousIndex = tokens.indexOf(previousEntry) - if (previousIndex) { + if (previousEntry) { tokens[previousIndex] = newEntry } else { tokens.push(newEntry) } this.store.updateState({ tokens }) - return Promise.resolve() } getTokens () { From 8cc7e47369ab36c579a1996e0a119e1e27a8e8f2 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 18 Dec 2017 15:57:37 -0800 Subject: [PATCH 4/5] Bump changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b7256466..8952236d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## Current Master +- Fix bug that prevented updating custom token details. + ## 3.13.3 2017-12-14 - Show tokens that are held that have no balance. From 30b45c8a385e9ae4c6b78d0a7ec6929f7bad4d9a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 19 Dec 2017 12:22:48 -0800 Subject: [PATCH 5/5] Do not log whole txs in recent block controller. Only record gas prices, because that has a current use. --- app/scripts/controllers/recent-blocks.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js index 27f9013ff..4a906261e 100644 --- a/app/scripts/controllers/recent-blocks.js +++ b/app/scripts/controllers/recent-blocks.js @@ -23,8 +23,15 @@ class RecentBlocksController { } processBlock (newBlock) { + const block = extend(newBlock, { + gasPrices: newBlock.transactions.map((tx) => { + return tx.gasPrice + }), + }) + delete block.transactions + const state = this.store.getState() - state.recentBlocks.push(newBlock) + state.recentBlocks.push(block) while (state.recentBlocks.length > this.historyLength) { state.recentBlocks.shift()