diff options
author | kumavis <kumavis@users.noreply.github.com> | 2018-06-19 06:11:16 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-06-19 06:11:16 +0800 |
commit | 4598554fea7b9435e5cbecc4735c479ffbadf37e (patch) | |
tree | 338aaee17d433383c9a57b385489cbc8df3f82d0 /app/scripts | |
parent | 39a7702c8f0aa2c2e7fdf2bcf913e76bb8b827f4 (diff) | |
parent | 0e3ecbbc4f7ab0579a33bf315af4dfafeb43f339 (diff) | |
download | tangerine-wallet-browser-4598554fea7b9435e5cbecc4735c479ffbadf37e.tar tangerine-wallet-browser-4598554fea7b9435e5cbecc4735c479ffbadf37e.tar.gz tangerine-wallet-browser-4598554fea7b9435e5cbecc4735c479ffbadf37e.tar.bz2 tangerine-wallet-browser-4598554fea7b9435e5cbecc4735c479ffbadf37e.tar.lz tangerine-wallet-browser-4598554fea7b9435e5cbecc4735c479ffbadf37e.tar.xz tangerine-wallet-browser-4598554fea7b9435e5cbecc4735c479ffbadf37e.tar.zst tangerine-wallet-browser-4598554fea7b9435e5cbecc4735c479ffbadf37e.zip |
Merge pull request #4603 from MetaMask/v4.8.0
V4.8.0
Diffstat (limited to 'app/scripts')
-rw-r--r-- | app/scripts/account-import-strategies/index.js | 13 | ||||
-rw-r--r-- | app/scripts/background.js | 14 | ||||
-rw-r--r-- | app/scripts/contentscript.js | 1 | ||||
-rw-r--r-- | app/scripts/controllers/network/network.js | 11 | ||||
-rw-r--r-- | app/scripts/controllers/preferences.js | 1 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/index.js | 15 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js | 24 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/lib/recipient-blacklist.js | 17 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/nonce-tracker.js | 54 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/pending-tx-tracker.js | 4 | ||||
-rw-r--r-- | app/scripts/inpage.js | 23 | ||||
-rw-r--r-- | app/scripts/lib/createStreamSink.js | 24 | ||||
-rw-r--r-- | app/scripts/lib/get-first-preferred-lang-code.js | 20 | ||||
-rw-r--r-- | app/scripts/metamask-controller.js | 50 | ||||
-rw-r--r-- | app/scripts/notice-controller.js | 33 |
15 files changed, 214 insertions, 90 deletions
diff --git a/app/scripts/account-import-strategies/index.js b/app/scripts/account-import-strategies/index.js index 96e2b5912..16ae224ea 100644 --- a/app/scripts/account-import-strategies/index.js +++ b/app/scripts/account-import-strategies/index.js @@ -16,7 +16,18 @@ const accountImporter = { strategies: { 'Private Key': (privateKey) => { - const stripped = ethUtil.stripHexPrefix(privateKey) + if (!privateKey) { + throw new Error('Cannot import an empty key.') + } + + const prefixed = ethUtil.addHexPrefix(privateKey) + const buffer = ethUtil.toBuffer(prefixed) + + if (!ethUtil.isValidPrivate(buffer)) { + throw new Error('Cannot import invalid private key.') + } + + const stripped = ethUtil.stripHexPrefix(prefixed) return stripped }, 'JSON File': (input, password) => { diff --git a/app/scripts/background.js b/app/scripts/background.js index 56e190f97..2451cddb6 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -16,6 +16,7 @@ const ExtensionPlatform = require('./platforms/extension') const Migrator = require('./lib/migrator/') const migrations = require('./migrations/') const PortStream = require('./lib/port-stream.js') +const createStreamSink = require('./lib/createStreamSink') const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') const firstTimeState = require('./first-time-state') @@ -273,7 +274,7 @@ function setupController (initState, initLangCode) { asStream(controller.store), debounce(1000), storeTransform(versionifyData), - storeTransform(persistData), + createStreamSink(persistData), (error) => { log.error('MetaMask - Persistence pipeline failed', error) } @@ -289,7 +290,7 @@ function setupController (initState, initLangCode) { return versionedData } - function persistData (state) { + async function persistData (state) { if (!state) { throw new Error('MetaMask - updated state is missing', state) } @@ -297,12 +298,13 @@ function setupController (initState, initLangCode) { throw new Error('MetaMask - updated state does not have data', state) } if (localStore.isSupported) { - localStore.set(state) - .catch((err) => { + try { + await localStore.set(state) + } catch (err) { + // log error so we dont break the pipeline log.error('error setting state in local store:', err) - }) + } } - return state } // diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 555902ddf..75e0a95b3 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -176,6 +176,7 @@ function blacklistedDomainCheck () { 'webbyawards.com', 'cdn.shopify.com/s/javascripts/tricorder/xtld-read-only-frame.html', 'adyen.com', + 'gravityforms.com', ] var currentUrl = window.location.href var currentRegex diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js index 93fde7c57..5e0c63e7d 100644 --- a/app/scripts/controllers/network/network.js +++ b/app/scripts/controllers/network/network.js @@ -89,14 +89,21 @@ module.exports = class NetworkController extends EventEmitter { type: 'rpc', rpcTarget, } - this.providerStore.updateState(providerConfig) - this._switchNetwork(providerConfig) + this.providerConfig = providerConfig } async setProviderType (type) { assert.notEqual(type, 'rpc', `NetworkController - cannot call "setProviderType" with type 'rpc'. use "setRpcTarget"`) assert(INFURA_PROVIDER_TYPES.includes(type) || type === LOCALHOST, `NetworkController - Unknown rpc type "${type}"`) const providerConfig = { type } + this.providerConfig = providerConfig + } + + resetConnection () { + this.providerConfig = this.getProviderConfig() + } + + set providerConfig (providerConfig) { this.providerStore.updateState(providerConfig) this._switchNetwork(providerConfig) } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index a5d8cc27b..8411e3a28 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -247,6 +247,7 @@ class PreferencesController { * @return {Promise<string>} */ setAccountLabel (account, label) { + if (!account) throw new Error('setAccountLabel requires a valid address, got ' + String(account)) const address = normalizeAddress(account) const {identities} = this.store.getState() identities[address] = identities[address] || {} diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index aff5db984..8e2288aed 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -10,6 +10,7 @@ const NonceTracker = require('./nonce-tracker') const txUtils = require('./lib/util') const cleanErrorStack = require('../../lib/cleanErrorStack') const log = require('loglevel') +const recipientBlacklistChecker = require('./lib/recipient-blacklist-checker') /** Transaction Controller is an aggregate of sub-controllers and trackers @@ -157,11 +158,14 @@ class TransactionController extends EventEmitter { let txMeta = this.txStateManager.generateTxMeta({ txParams: normalizedTxParams }) this.addTx(txMeta) this.emit('newUnapprovedTx', txMeta) - // add default tx params + try { + // check whether recipient account is blacklisted + recipientBlacklistChecker.checkAccount(txMeta.metamaskNetworkId, normalizedTxParams.to) + // add default tx params txMeta = await this.addTxGasDefaults(txMeta) } catch (error) { - console.log(error) + log.warn(error) this.txStateManager.setTxStatusFailed(txMeta.id, error) throw error } @@ -260,7 +264,12 @@ class TransactionController extends EventEmitter { // must set transaction to submitted/failed before releasing lock nonceLock.releaseLock() } catch (err) { - this.txStateManager.setTxStatusFailed(txId, err) + // this is try-catch wrapped so that we can guarantee that the nonceLock is released + try { + this.txStateManager.setTxStatusFailed(txId, err) + } catch (err) { + log.error(err) + } // must set transaction to submitted/failed before releasing lock if (nonceLock) nonceLock.releaseLock() // continue with error chain diff --git a/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js b/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js new file mode 100644 index 000000000..e4df2367e --- /dev/null +++ b/app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js @@ -0,0 +1,24 @@ +const Config = require('./recipient-blacklist.js') + +/** @module*/ +module.exports = { + checkAccount, +} + +/** + * Checks if a specified account on a specified network is blacklisted. + @param networkId {number} + @param account {string} +*/ +function checkAccount (networkId, account) { + + const mainnetId = 1 + if (networkId !== mainnetId) { + return + } + + const accountToCheck = account.toLowerCase() + if (Config.blacklist.includes(accountToCheck)) { + throw new Error('Recipient is a public account') + } +} diff --git a/app/scripts/controllers/transactions/lib/recipient-blacklist.js b/app/scripts/controllers/transactions/lib/recipient-blacklist.js new file mode 100644 index 000000000..08e1a2ccd --- /dev/null +++ b/app/scripts/controllers/transactions/lib/recipient-blacklist.js @@ -0,0 +1,17 @@ +module.exports = { + 'blacklist': [ + // IDEX phisher + '0x9bcb0A9d99d815Bb87ee3191b1399b1Bcc46dc77', + // Ganache default seed phrases + '0x627306090abab3a6e1400e9345bc60c78a8bef57', + '0xf17f52151ebef6c7334fad080c5704d77216b732', + '0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef', + '0x821aea9a577a9b44299b9c15c88cf3087f3b5544', + '0x0d1d4e623d10f9fba5db95830f7d3839406c6af2', + '0x2932b7a2355d6fecc4b5c0b6bd44cc31df247a2e', + '0x2191ef87e392377ec08e7c08eb105ef5448eced5', + '0x0f4f2ac550a1b4e2280d04c21cea7ebd822934b5', + '0x6330a553fc93768f612722bb8c2ec78ac90b3bbc', + '0x5aeda56215b167893e80b4fe645ba6d5bab767de', + ], +} diff --git a/app/scripts/controllers/transactions/nonce-tracker.js b/app/scripts/controllers/transactions/nonce-tracker.js index f8cdc5523..35ca08d6c 100644 --- a/app/scripts/controllers/transactions/nonce-tracker.js +++ b/app/scripts/controllers/transactions/nonce-tracker.js @@ -49,29 +49,35 @@ class NonceTracker { await this._globalMutexFree() // await lock free, then take lock const releaseLock = await this._takeMutex(address) - // evaluate multiple nextNonce strategies - const nonceDetails = {} - const networkNonceResult = await this._getNetworkNextNonce(address) - const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address) - const nextNetworkNonce = networkNonceResult.nonce - const highestSuggested = Math.max(nextNetworkNonce, highestLocallyConfirmed) - - const pendingTxs = this.getPendingTransactions(address) - const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestSuggested) || 0 - - nonceDetails.params = { - highestLocallyConfirmed, - highestSuggested, - nextNetworkNonce, + try { + // evaluate multiple nextNonce strategies + const nonceDetails = {} + const networkNonceResult = await this._getNetworkNextNonce(address) + const highestLocallyConfirmed = this._getHighestLocallyConfirmed(address) + const nextNetworkNonce = networkNonceResult.nonce + const highestSuggested = Math.max(nextNetworkNonce, highestLocallyConfirmed) + + const pendingTxs = this.getPendingTransactions(address) + const localNonceResult = this._getHighestContinuousFrom(pendingTxs, highestSuggested) || 0 + + nonceDetails.params = { + highestLocallyConfirmed, + highestSuggested, + nextNetworkNonce, + } + nonceDetails.local = localNonceResult + nonceDetails.network = networkNonceResult + + const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce) + assert(Number.isInteger(nextNonce), `nonce-tracker - nextNonce is not an integer - got: (${typeof nextNonce}) "${nextNonce}"`) + + // return nonce and release cb + return { nextNonce, nonceDetails, releaseLock } + } catch (err) { + // release lock if we encounter an error + releaseLock() + throw err } - nonceDetails.local = localNonceResult - nonceDetails.network = networkNonceResult - - const nextNonce = Math.max(networkNonceResult.nonce, localNonceResult.nonce) - assert(Number.isInteger(nextNonce), `nonce-tracker - nextNonce is not an integer - got: (${typeof nextNonce}) "${nextNonce}"`) - - // return nonce and release cb - return { nextNonce, nonceDetails, releaseLock } } async _getCurrentBlock () { @@ -85,8 +91,8 @@ class NonceTracker { async _globalMutexFree () { const globalMutex = this._lookupMutex('global') - const release = await globalMutex.acquire() - release() + const releaseLock = await globalMutex.acquire() + releaseLock() } async _takeMutex (lockId) { diff --git a/app/scripts/controllers/transactions/pending-tx-tracker.js b/app/scripts/controllers/transactions/pending-tx-tracker.js index 6e2fcb40b..4e41cdaf8 100644 --- a/app/scripts/controllers/transactions/pending-tx-tracker.js +++ b/app/scripts/controllers/transactions/pending-tx-tracker.js @@ -196,14 +196,14 @@ class PendingTransactionTracker extends EventEmitter { async _checkPendingTxs () { const signedTxList = this.getPendingTransactions() // in order to keep the nonceTracker accurate we block it while updating pending transactions - const nonceGlobalLock = await this.nonceTracker.getGlobalLock() + const { releaseLock } = await this.nonceTracker.getGlobalLock() try { await Promise.all(signedTxList.map((txMeta) => this._checkPendingTx(txMeta))) } catch (err) { log.error('PendingTransactionWatcher - Error updating pending transactions') log.error(err) } - nonceGlobalLock.releaseLock() + releaseLock() } /** diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 6d16eebd4..7dd7fda02 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -38,9 +38,30 @@ web3.setProvider = function () { log.debug('MetaMask - overrode web3.setProvider') } log.debug('MetaMask - injected web3') -// export global web3, with usage-detection + setupDappAutoReload(web3, inpageProvider.publicConfigStore) +// export global web3, with usage-detection and deprecation warning + +/* TODO: Uncomment this area once auto-reload.js has been deprecated: +let hasBeenWarned = false +global.web3 = new Proxy(web3, { + get: (_web3, key) => { + // show warning once on web3 access + if (!hasBeenWarned && key !== 'currentProvider') { + console.warn('MetaMask: web3 will be deprecated in the near future in favor of the ethereumProvider \nhttps://github.com/MetaMask/faq/blob/master/detecting_metamask.md#web3-deprecation') + hasBeenWarned = true + } + // return value normally + return _web3[key] + }, + set: (_web3, key, value) => { + // set value normally + _web3[key] = value + }, +}) +*/ + // set web3 defaultAccount inpageProvider.publicConfigStore.subscribe(function (state) { web3.eth.defaultAccount = state.selectedAddress diff --git a/app/scripts/lib/createStreamSink.js b/app/scripts/lib/createStreamSink.js new file mode 100644 index 000000000..cf9416fea --- /dev/null +++ b/app/scripts/lib/createStreamSink.js @@ -0,0 +1,24 @@ +const WritableStream = require('readable-stream').Writable +const promiseToCallback = require('promise-to-callback') + +module.exports = createStreamSink + + +function createStreamSink(asyncWriteFn, _opts) { + return new AsyncWritableStream(asyncWriteFn, _opts) +} + +class AsyncWritableStream extends WritableStream { + + constructor (asyncWriteFn, _opts) { + const opts = Object.assign({ objectMode: true }, _opts) + super(opts) + this._asyncWriteFn = asyncWriteFn + } + + // write from incomming stream to state + _write (chunk, encoding, callback) { + promiseToCallback(this._asyncWriteFn(chunk, encoding))(callback) + } + +} diff --git a/app/scripts/lib/get-first-preferred-lang-code.js b/app/scripts/lib/get-first-preferred-lang-code.js index 1e6a83ba6..41a886d74 100644 --- a/app/scripts/lib/get-first-preferred-lang-code.js +++ b/app/scripts/lib/get-first-preferred-lang-code.js @@ -2,8 +2,7 @@ const extension = require('extensionizer') const promisify = require('pify') const allLocales = require('../../_locales/index.json') -const isSupported = extension.i18n && extension.i18n.getAcceptLanguages -const getPreferredLocales = isSupported ? promisify( +const getPreferredLocales = extension.i18n ? promisify( extension.i18n.getAcceptLanguages, { errorFirst: false } ) : async () => [] @@ -18,7 +17,21 @@ const existingLocaleCodes = allLocales.map(locale => locale.code.toLowerCase().r * */ async function getFirstPreferredLangCode () { - const userPreferredLocaleCodes = await getPreferredLocales() + let userPreferredLocaleCodes + + try { + userPreferredLocaleCodes = await getPreferredLocales() + } catch (e) { + // Brave currently throws when calling getAcceptLanguages, so this handles that. + userPreferredLocaleCodes = [] + } + + // safeguard for Brave Browser until they implement chrome.i18n.getAcceptLanguages + // https://github.com/MetaMask/metamask-extension/issues/4270 + if (!userPreferredLocaleCodes){ + userPreferredLocaleCodes = [] + } + const firstPreferredLangCode = userPreferredLocaleCodes .map(code => code.toLowerCase()) .find(code => existingLocaleCodes.includes(code)) @@ -26,3 +39,4 @@ async function getFirstPreferredLangCode () { } module.exports = getFirstPreferredLangCode + diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 1bb0af5ee..d40a351a5 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -46,7 +46,6 @@ const GWEI_BN = new BN('1000000000') const percentile = require('percentile') const seedPhraseVerifier = require('./lib/seed-phrase-verifier') const cleanErrorStack = require('./lib/cleanErrorStack') -const DiagnosticsReporter = require('./lib/diagnostics-reporter') const log = require('loglevel') module.exports = class MetamaskController extends EventEmitter { @@ -65,12 +64,6 @@ module.exports = class MetamaskController extends EventEmitter { const initState = opts.initState || {} this.recordFirstTimeInfo(initState) - // metamask diagnostics reporter - this.diagnostics = opts.diagnostics || new DiagnosticsReporter({ - firstTimeInfo: initState.firstTimeInfo, - version, - }) - // platform-specific api this.platform = opts.platform @@ -92,7 +85,6 @@ module.exports = class MetamaskController extends EventEmitter { this.preferencesController = new PreferencesController({ initState: initState.PreferencesController, initLangCode: opts.initLangCode, - diagnostics: this.diagnostics, }) // currency controller @@ -189,9 +181,6 @@ module.exports = class MetamaskController extends EventEmitter { version, firstVersion: initState.firstTimeInfo.version, }) - this.noticeController.updateNoticesList() - // to be uncommented when retrieving notices from a remote server. - // this.noticeController.startPolling() this.shapeshiftController = new ShapeShiftController({ initState: initState.ShapeShiftController, @@ -394,6 +383,8 @@ module.exports = class MetamaskController extends EventEmitter { updateAndApproveTransaction: nodeify(txController.updateAndApproveTransaction, txController), retryTransaction: nodeify(this.retryTransaction, this), getFilteredTxList: nodeify(txController.getFilteredTxList, txController), + isNonceTaken: nodeify(txController.isNonceTaken, txController), + estimateGas: nodeify(this.estimateGas, this), // messageManager signMessage: nodeify(this.signMessage, this), @@ -434,28 +425,24 @@ module.exports = class MetamaskController extends EventEmitter { * @returns {Object} vault */ async createNewVaultAndKeychain (password) { - const release = await this.createVaultMutex.acquire() - let vault - + const releaseLock = await this.createVaultMutex.acquire() try { + let vault const accounts = await this.keyringController.getAccounts() - if (accounts.length > 0) { vault = await this.keyringController.fullUpdate() - } else { vault = await this.keyringController.createNewVaultAndKeychain(password) const accounts = await this.keyringController.getAccounts() this.preferencesController.setAddresses(accounts) this.selectFirstIdentity() } - release() + releaseLock() + return vault } catch (err) { - release() + releaseLock() throw err } - - return vault } /** @@ -464,7 +451,7 @@ module.exports = class MetamaskController extends EventEmitter { * @param {} seed */ async createNewVaultAndRestore (password, seed) { - const release = await this.createVaultMutex.acquire() + const releaseLock = await this.createVaultMutex.acquire() try { // clear known identities this.preferencesController.setAddresses([]) @@ -474,10 +461,10 @@ module.exports = class MetamaskController extends EventEmitter { const accounts = await this.keyringController.getAccounts() this.preferencesController.setAddresses(accounts) this.selectFirstIdentity() - release() + releaseLock() return vault } catch (err) { - release() + releaseLock() throw err } } @@ -628,10 +615,7 @@ module.exports = class MetamaskController extends EventEmitter { async resetAccount () { const selectedAddress = this.preferencesController.getSelectedAddress() this.txController.wipeTransactions(selectedAddress) - - const networkController = this.networkController - const oldType = networkController.getProviderConfig().type - await networkController.setProviderType(oldType, true) + this.networkController.resetConnection() return selectedAddress } @@ -958,6 +942,18 @@ module.exports = class MetamaskController extends EventEmitter { return state } + estimateGas (estimateGasParams) { + return new Promise((resolve, reject) => { + return this.txController.txGasUtil.query.estimateGas(estimateGasParams, (err, res) => { + if (err) { + return reject(err) + } + + return resolve(res) + }) + }) + } + //============================================================================= // PASSWORD MANAGEMENT //============================================================================= diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index 14a63eae7..2def4371e 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -2,7 +2,7 @@ const EventEmitter = require('events').EventEmitter const semver = require('semver') const extend = require('xtend') const ObservableStore = require('obs-store') -const hardCodedNotices = require('../../notices/notices.json') +const hardCodedNotices = require('../../notices/notices.js') const uniqBy = require('lodash.uniqby') module.exports = class NoticeController extends EventEmitter { @@ -16,8 +16,12 @@ module.exports = class NoticeController extends EventEmitter { noticesList: [], }, opts.initState) this.store = new ObservableStore(initState) + // setup memStore this.memStore = new ObservableStore({}) this.store.subscribe(() => this._updateMemstore()) + this._updateMemstore() + // pull in latest notices + this.updateNoticesList() } getNoticesList () { @@ -29,9 +33,9 @@ module.exports = class NoticeController extends EventEmitter { return notices.filter((notice) => notice.read === false) } - getLatestUnreadNotice () { + getNextUnreadNotice () { const unreadNotices = this.getUnreadNotices() - return unreadNotices[unreadNotices.length - 1] + return unreadNotices[0] } async setNoticesList (noticesList) { @@ -47,7 +51,7 @@ module.exports = class NoticeController extends EventEmitter { notices[index].read = true notices[index].body = '' this.setNoticesList(notices) - const latestNotice = this.getLatestUnreadNotice() + const latestNotice = this.getNextUnreadNotice() cb(null, latestNotice) } catch (err) { cb(err) @@ -64,15 +68,6 @@ module.exports = class NoticeController extends EventEmitter { return result } - startPolling () { - if (this.noticePoller) { - clearInterval(this.noticePoller) - } - this.noticePoller = setInterval(() => { - this.noticeController.updateNoticesList() - }, 300000) - } - _mergeNotices (oldNotices, newNotices) { return uniqBy(oldNotices.concat(newNotices), 'id') } @@ -91,19 +86,15 @@ module.exports = class NoticeController extends EventEmitter { }) } - _mapNoticeIds (notices) { - return notices.map((notice) => notice.id) - } - async _retrieveNoticeData () { - // Placeholder for the API. + // Placeholder for remote notice API. return hardCodedNotices } _updateMemstore () { - const lastUnreadNotice = this.getLatestUnreadNotice() - const noActiveNotices = !lastUnreadNotice - this.memStore.updateState({ lastUnreadNotice, noActiveNotices }) + const nextUnreadNotice = this.getNextUnreadNotice() + const noActiveNotices = !nextUnreadNotice + this.memStore.updateState({ nextUnreadNotice, noActiveNotices }) } } |