aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/controllers
diff options
context:
space:
mode:
authorThomas Huang <tmashuang@users.noreply.github.com>2018-12-04 07:16:19 +0800
committerGitHub <noreply@github.com>2018-12-04 07:16:19 +0800
commited9bfdcebd5eed1d749f275f9d388ea0dd8f8275 (patch)
tree786b66ff556bc30a7f6136ba130e889408dcebb4 /app/scripts/controllers
parentbe3619cd802536894097d81e7f31d38b0c2b3e9f (diff)
parent35670e926116b19e66931dace838d785adffac09 (diff)
downloadtangerine-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.js83
-rw-r--r--app/scripts/controllers/provider-approval.js8
-rw-r--r--app/scripts/controllers/token-rates.js4
-rw-r--r--app/scripts/controllers/transactions/index.js21
-rw-r--r--app/scripts/controllers/transactions/tx-gas-utils.js9
-rw-r--r--app/scripts/controllers/transactions/tx-state-manager.js10
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')
}