diff options
author | Thomas Huang <tmashuang@users.noreply.github.com> | 2018-12-04 07:16:19 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-04 07:16:19 +0800 |
commit | ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275 (patch) | |
tree | 786b66ff556bc30a7f6136ba130e889408dcebb4 /app/scripts/controllers | |
parent | be3619cd802536894097d81e7f31d38b0c2b3e9f (diff) | |
parent | 35670e926116b19e66931dace838d785adffac09 (diff) | |
download | tangerine-wallet-browser-ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275.tar tangerine-wallet-browser-ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275.tar.gz tangerine-wallet-browser-ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275.tar.bz2 tangerine-wallet-browser-ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275.tar.lz tangerine-wallet-browser-ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275.tar.xz tangerine-wallet-browser-ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275.tar.zst tangerine-wallet-browser-ed9bfdcebd5eed1d749f275f9d388ea0dd8f8275.zip |
Merge pull request #5879 from MetaMask/develop
Version 5.1.0
Diffstat (limited to 'app/scripts/controllers')
-rw-r--r-- | app/scripts/controllers/cached-balances.js | 83 | ||||
-rw-r--r-- | app/scripts/controllers/provider-approval.js | 8 | ||||
-rw-r--r-- | app/scripts/controllers/token-rates.js | 4 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/index.js | 21 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/tx-gas-utils.js | 9 | ||||
-rw-r--r-- | app/scripts/controllers/transactions/tx-state-manager.js | 10 |
6 files changed, 125 insertions, 10 deletions
diff --git a/app/scripts/controllers/cached-balances.js b/app/scripts/controllers/cached-balances.js new file mode 100644 index 000000000..925c45334 --- /dev/null +++ b/app/scripts/controllers/cached-balances.js @@ -0,0 +1,83 @@ +const ObservableStore = require('obs-store') +const extend = require('xtend') + +/** + * @typedef {Object} CachedBalancesOptions + * @property {Object} accountTracker An {@code AccountTracker} reference + * @property {Function} getNetwork A function to get the current network + * @property {Object} initState The initial controller state + */ + +/** + * Background controller responsible for maintaining + * a cache of account balances in local storage + */ +class CachedBalancesController { + /** + * Creates a new controller instance + * + * @param {CachedBalancesOptions} [opts] Controller configuration parameters + */ + constructor (opts = {}) { + const { accountTracker, getNetwork } = opts + + this.accountTracker = accountTracker + this.getNetwork = getNetwork + + const initState = extend({ + cachedBalances: {}, + }, opts.initState) + this.store = new ObservableStore(initState) + + this._registerUpdates() + } + + /** + * Updates the cachedBalances property for the current network. Cached balances will be updated to those in the passed accounts + * if balances in the passed accounts are truthy. + * + * @param {Object} obj The the recently updated accounts object for the current network + * @returns {Promise<void>} + */ + async updateCachedBalances ({ accounts }) { + const network = await this.getNetwork() + const balancesToCache = await this._generateBalancesToCache(accounts, network) + this.store.updateState({ + cachedBalances: balancesToCache, + }) + } + + _generateBalancesToCache (newAccounts, currentNetwork) { + const { cachedBalances } = this.store.getState() + const currentNetworkBalancesToCache = { ...cachedBalances[currentNetwork] } + + Object.keys(newAccounts).forEach(accountID => { + const account = newAccounts[accountID] + + if (account.balance) { + currentNetworkBalancesToCache[accountID] = account.balance + } + }) + const balancesToCache = { + ...cachedBalances, + [currentNetwork]: currentNetworkBalancesToCache, + } + + return balancesToCache + } + + /** + * Sets up listeners and subscriptions which should trigger an update of cached balances. These updates will + * happen when the current account changes. Which happens on block updates, as well as on network and account + * selections. + * + * @private + * + */ + _registerUpdates () { + const update = this.updateCachedBalances.bind(this) + this.accountTracker.store.subscribe(update) + } +} + +module.exports = CachedBalancesController diff --git a/app/scripts/controllers/provider-approval.js b/app/scripts/controllers/provider-approval.js index 21d7fd22e..53172c069 100644 --- a/app/scripts/controllers/provider-approval.js +++ b/app/scripts/controllers/provider-approval.js @@ -22,7 +22,9 @@ class ProviderApprovalController { this.platform = platform this.preferencesController = preferencesController this.publicConfigStore = publicConfigStore - this.store = new ObservableStore() + this.store = new ObservableStore({ + providerRequests: [], + }) if (platform && platform.addMessageListener) { platform.addMessageListener(({ action = '', force, origin, siteTitle, siteImage }) => { @@ -103,7 +105,7 @@ class ProviderApprovalController { */ approveProviderRequest (origin) { this.closePopup && this.closePopup() - const requests = this.store.getState().providerRequests || [] + const requests = this.store.getState().providerRequests this.platform && this.platform.sendMessage({ action: 'approve-provider-request', selectedAddress: this.publicConfigStore.getState().selectedAddress, @@ -121,7 +123,7 @@ class ProviderApprovalController { */ rejectProviderRequest (origin) { this.closePopup && this.closePopup() - const requests = this.store.getState().providerRequests || [] + const requests = this.store.getState().providerRequests this.platform && this.platform.sendMessage({ action: 'reject-provider-request' }, { active: true }) const providerRequests = requests.filter(request => request.origin !== origin) this.store.updateState({ providerRequests }) diff --git a/app/scripts/controllers/token-rates.js b/app/scripts/controllers/token-rates.js index a8936f13b..3f9482856 100644 --- a/app/scripts/controllers/token-rates.js +++ b/app/scripts/controllers/token-rates.js @@ -1,5 +1,6 @@ const ObservableStore = require('obs-store') const log = require('loglevel') +const normalizeAddress = require('eth-sig-util').normalize // By default, poll every 3 minutes const DEFAULT_INTERVAL = 180 * 1000 @@ -35,7 +36,8 @@ class TokenRatesController { const response = await fetch(`https://exchanges.balanc3.net/pie?${query}&autoConversion=true`) const { prices = [] } = await response.json() prices.forEach(({ pair, price }) => { - contractExchangeRates[pair.split('/')[0]] = typeof price === 'number' ? price : 0 + const address = pair.split('/')[0] + contractExchangeRates[normalizeAddress(address)] = typeof price === 'number' ? price : 0 }) } catch (error) { log.warn(`MetaMask - TokenRatesController exchange rate fetch failed.`, error) diff --git a/app/scripts/controllers/transactions/index.js b/app/scripts/controllers/transactions/index.js index b44f66f14..9cd8429fb 100644 --- a/app/scripts/controllers/transactions/index.js +++ b/app/scripts/controllers/transactions/index.js @@ -96,7 +96,10 @@ class TransactionController extends EventEmitter { // memstore is computed from a few different stores this._updateMemstore() this.txStateManager.store.subscribe(() => this._updateMemstore()) - this.networkStore.subscribe(() => this._updateMemstore()) + this.networkStore.subscribe(() => { + this._onBootCleanUp() + this._updateMemstore() + }) this.preferencesStore.subscribe(() => this._updateMemstore()) // request state update to finalize initialization @@ -191,10 +194,13 @@ class TransactionController extends EventEmitter { txMeta = await this.addTxGasDefaults(txMeta) } catch (error) { log.warn(error) - this.txStateManager.setTxStatusFailed(txMeta.id, error) + txMeta.loadingDefaults = false + this.txStateManager.updateTx(txMeta, 'Failed to calculate gas defaults.') throw error } + txMeta.loadingDefaults = false + // save txMeta this.txStateManager.updateTx(txMeta) @@ -229,7 +235,16 @@ class TransactionController extends EventEmitter { async retryTransaction (originalTxId) { const originalTxMeta = this.txStateManager.getTx(originalTxId) + const { txParams } = originalTxMeta const lastGasPrice = originalTxMeta.txParams.gasPrice + const suggestedGasPriceBN = new ethUtil.BN(ethUtil.stripHexPrefix(this.getGasPrice()), 16) + const lastGasPriceBN = new ethUtil.BN(ethUtil.stripHexPrefix(lastGasPrice), 16) + // essentially lastGasPrice * 1.1 but + // dont trust decimals so a round about way of doing that + const lastGasPriceBNBumped = lastGasPriceBN.mul(new ethUtil.BN(110, 10)).div(new ethUtil.BN(100, 10)) + // transactions that are being retried require a >=%10 bump or the clients will throw an error + txParams.gasPrice = suggestedGasPriceBN.gt(lastGasPriceBNBumped) ? `0x${suggestedGasPriceBN.toString(16)}` : `0x${lastGasPriceBNBumped.toString(16)}` + const txMeta = this.txStateManager.generateTxMeta({ txParams: originalTxMeta.txParams, lastGasPrice, @@ -476,6 +491,8 @@ class TransactionController extends EventEmitter { txMeta.loadingDefaults = false this.txStateManager.updateTx(txMeta, 'transactions: gas estimation for tx on boot') }).catch((error) => { + tx.loadingDefaults = false + this.txStateManager.updateTx(tx, 'failed to estimate gas during boot cleanup.') this.txStateManager.setTxStatusFailed(tx.id, error) }) }) diff --git a/app/scripts/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js index def67c2c3..b296dc5eb 100644 --- a/app/scripts/controllers/transactions/tx-gas-utils.js +++ b/app/scripts/controllers/transactions/tx-gas-utils.js @@ -35,7 +35,13 @@ class TxGasUtil { txMeta.simulationFails = { reason: err.message, errorKey: err.errorKey, + debug: { blockNumber: block.number, blockGasLimit: block.gasLimit }, } + + if (err.errorKey === TRANSACTION_NO_CONTRACT_ERROR_KEY) { + txMeta.simulationFails.debug.getCodeResponse = err.getCodeResponse + } + return txMeta } this.setTxGas(txMeta, block.gasLimit, estimatedGasHex) @@ -74,6 +80,9 @@ class TxGasUtil { const err = new Error('TxGasUtil - Trying to call a function on a non-contract address') // set error key so ui can display localized error message err.errorKey = TRANSACTION_NO_CONTRACT_ERROR_KEY + + // set the response on the error so that we can see in logs what the actual response was + err.getCodeResponse = code throw err } diff --git a/app/scripts/controllers/transactions/tx-state-manager.js b/app/scripts/controllers/transactions/tx-state-manager.js index 151082452..72d869fa8 100644 --- a/app/scripts/controllers/transactions/tx-state-manager.js +++ b/app/scripts/controllers/transactions/tx-state-manager.js @@ -361,13 +361,15 @@ class TransactionStateManager extends EventEmitter { @param err {erroObject} - error object */ setTxStatusFailed (txId, err) { + const error = !err ? new Error('Internal metamask failure') : err + const txMeta = this.getTx(txId) txMeta.err = { - message: err.toString(), - rpc: err.value, - stack: err.stack, + message: error.toString(), + rpc: error.value, + stack: error.stack, } - this.updateTx(txMeta) + this.updateTx(txMeta, 'transactions:tx-state-manager#fail - add error') this._setTxStatus(txId, 'failed') } |