aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/controllers
diff options
context:
space:
mode:
Diffstat (limited to 'app/scripts/controllers')
-rw-r--r--app/scripts/controllers/balance.js4
-rw-r--r--app/scripts/controllers/blacklist.js2
-rw-r--r--app/scripts/controllers/computed-balances.js2
-rw-r--r--app/scripts/controllers/currency.js8
-rw-r--r--app/scripts/controllers/network/network.js13
-rw-r--r--app/scripts/controllers/preferences.js81
-rw-r--r--app/scripts/controllers/recent-blocks.js2
-rw-r--r--app/scripts/controllers/transactions/index.js15
-rw-r--r--app/scripts/controllers/transactions/lib/recipient-blacklist-checker.js24
-rw-r--r--app/scripts/controllers/transactions/lib/recipient-blacklist.js17
-rw-r--r--app/scripts/controllers/transactions/nonce-tracker.js54
-rw-r--r--app/scripts/controllers/transactions/pending-tx-tracker.js4
-rw-r--r--app/scripts/controllers/transactions/tx-gas-utils.js2
-rw-r--r--app/scripts/controllers/user-actions.js17
14 files changed, 200 insertions, 45 deletions
diff --git a/app/scripts/controllers/balance.js b/app/scripts/controllers/balance.js
index 86619fce1..4c97810a3 100644
--- a/app/scripts/controllers/balance.js
+++ b/app/scripts/controllers/balance.js
@@ -60,7 +60,7 @@ class BalanceController {
* Sets up listeners and subscriptions which should trigger an update of ethBalance. These updates include:
* - when a transaction changes state to 'submitted', 'confirmed' or 'failed'
* - when the current account changes (i.e. a new account is selected)
- * - when there is a block update
+ * - when there is a block update
*
* @private
*
@@ -100,7 +100,7 @@ class BalanceController {
/**
* Gets the pending transactions (i.e. those with a 'submitted' status). These are accessed from the
- * TransactionController passed to this BalanceController during construction.
+ * TransactionController passed to this BalanceController during construction.
*
* @private
* @returns {Promise<array>} Promises an array of transaction objects.
diff --git a/app/scripts/controllers/blacklist.js b/app/scripts/controllers/blacklist.js
index f100c4525..1d2191433 100644
--- a/app/scripts/controllers/blacklist.js
+++ b/app/scripts/controllers/blacklist.js
@@ -87,7 +87,7 @@ class BlacklistController {
*
* @private
* @param {object} config A config object like that found at {@link https://github.com/MetaMask/eth-phishing-detect/blob/master/src/config.json}
- *
+ *
*/
_setupPhishingDetector (config) {
this._phishingDetector = new PhishingDetector(config)
diff --git a/app/scripts/controllers/computed-balances.js b/app/scripts/controllers/computed-balances.js
index 1a6802f9a..e04ce2ef7 100644
--- a/app/scripts/controllers/computed-balances.js
+++ b/app/scripts/controllers/computed-balances.js
@@ -18,7 +18,7 @@ class ComputedbalancesController {
/**
* Creates a new controller instance
*
- * @param {ComputedBalancesOptions} [opts] Controller configuration parameters
+ * @param {ComputedBalancesOptions} [opts] Controller configuration parameters
*/
constructor (opts = {}) {
const { accountTracker, txController, blockTracker } = opts
diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js
index 480c08b1c..a93aff49b 100644
--- a/app/scripts/controllers/currency.js
+++ b/app/scripts/controllers/currency.js
@@ -16,9 +16,9 @@ class CurrencyController {
* currentCurrency, conversionRate and conversionDate properties
* @property {string} currentCurrency A 2-4 character shorthand that describes a specific currency, currently
* selected by the user
- * @property {number} conversionRate The conversion rate from ETH to the selected currency.
+ * @property {number} conversionRate The conversion rate from ETH to the selected currency.
* @property {string} conversionDate The date at which the conversion rate was set. Expressed in in milliseconds
- * since midnight of January 1, 1970
+ * since midnight of January 1, 1970
* @property {number} conversionInterval The id of the interval created by the scheduleConversionInterval method.
* Used to clear an existing interval on subsequent calls of that method.
*
@@ -59,7 +59,7 @@ class CurrencyController {
/**
* A getter for the conversionRate property
*
- * @returns {string} The conversion rate from ETH to the selected currency.
+ * @returns {string} The conversion rate from ETH to the selected currency.
*
*/
getConversionRate () {
@@ -80,7 +80,7 @@ class CurrencyController {
* A getter for the conversionDate property
*
* @returns {string} The date at which the conversion rate was set. Expressed in milliseconds since midnight of
- * January 1, 1970
+ * January 1, 1970
*
*/
getConversionDate () {
diff --git a/app/scripts/controllers/network/network.js b/app/scripts/controllers/network/network.js
index 93fde7c57..a50f6dc45 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)
}
@@ -125,7 +132,7 @@ module.exports = class NetworkController extends EventEmitter {
} else if (type === LOCALHOST) {
this._configureStandardProvider({ rpcUrl: LOCALHOST_RPC_URL })
// url-based rpc endpoints
- } else if (type === 'rpc'){
+ } else if (type === 'rpc') {
this._configureStandardProvider({ rpcUrl: rpcTarget })
} else {
throw new Error(`NetworkController - _configureProvider - unknown type "${type}"`)
diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js
index a4ff1207e..b314745f5 100644
--- a/app/scripts/controllers/preferences.js
+++ b/app/scripts/controllers/preferences.js
@@ -2,6 +2,7 @@ const ObservableStore = require('obs-store')
const normalizeAddress = require('eth-sig-util').normalize
const extend = require('xtend')
+
class PreferencesController {
/**
@@ -28,7 +29,11 @@ class PreferencesController {
featureFlags: {},
currentLocale: opts.initLangCode,
identities: {},
+ lostIdentities: {},
}, opts.initState)
+
+ this.diagnostics = opts.diagnostics
+
this.store = new ObservableStore(initState)
}
// PUBLIC METHODS
@@ -63,6 +68,13 @@ class PreferencesController {
this.store.updateState({ currentLocale: key })
}
+ /**
+ * Updates identities to only include specified addresses. Removes identities
+ * not included in addresses array
+ *
+ * @param {string[]} addresses An array of hex addresses
+ *
+ */
setAddresses (addresses) {
const oldIdentities = this.store.getState().identities
const identities = addresses.reduce((ids, address, index) => {
@@ -74,6 +86,68 @@ class PreferencesController {
}
/**
+ * Adds addresses to the identities object without removing identities
+ *
+ * @param {string[]} addresses An array of hex addresses
+ *
+ */
+ addAddresses (addresses) {
+ const identities = this.store.getState().identities
+ addresses.forEach((address) => {
+ // skip if already exists
+ if (identities[address]) return
+ // add missing identity
+ const identityCount = Object.keys(identities).length
+ identities[address] = { name: `Account ${identityCount + 1}`, address }
+ })
+ this.store.updateState({ identities })
+ }
+
+ /*
+ * Synchronizes identity entries with known accounts.
+ * Removes any unknown identities, and returns the resulting selected address.
+ *
+ * @param {Array<string>} addresses known to the vault.
+ * @returns {Promise<string>} selectedAddress the selected address.
+ */
+ syncAddresses (addresses) {
+ const { identities, lostIdentities } = this.store.getState()
+
+ const newlyLost = {}
+ Object.keys(identities).forEach((identity) => {
+ if (!addresses.includes(identity)) {
+ newlyLost[identity] = identities[identity]
+ delete identities[identity]
+ }
+ })
+
+ // Identities are no longer present.
+ if (Object.keys(newlyLost).length > 0) {
+
+ // Notify our servers:
+ if (this.diagnostics) this.diagnostics.reportOrphans(newlyLost)
+
+ // store lost accounts
+ for (const key in newlyLost) {
+ lostIdentities[key] = newlyLost[key]
+ }
+ }
+
+ this.store.updateState({ identities, lostIdentities })
+ this.addAddresses(addresses)
+
+ // If the selected account is no longer valid,
+ // select an arbitrary other account:
+ let selected = this.getSelectedAddress()
+ if (!addresses.includes(selected)) {
+ selected = addresses[0]
+ this.setSelectedAddress(selected)
+ }
+
+ return selected
+ }
+
+ /**
* Setter for the `selectedAddress` property
*
* @param {string} _address A new hex address for an account
@@ -111,7 +185,7 @@ class PreferencesController {
/**
* Adds a new token to the token array, or updates the token if passed an address that already exists.
* Modifies the existing tokens array from the store. All objects in the tokens array array AddedToken objects.
- * @see AddedToken {@link AddedToken}
+ * @see AddedToken {@link AddedToken}
*
* @param {string} rawAddress Hex address of the token contract. May or may not be a checksum address.
* @param {string} symbol The symbol of the token
@@ -173,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] || {}
@@ -197,7 +272,7 @@ class PreferencesController {
}
/**
- * Setter for the `currentAccountTab` property
+ * Setter for the `currentAccountTab` property
*
* @param {string} currentAccountTab Specifies the new tab to be marked as current
* @returns {Promise<void>} Promise resolves with undefined
@@ -215,7 +290,7 @@ class PreferencesController {
* The returned list will have a max length of 2. If the _url currently exists it the list, it will be moved to the
* end of the list. The current list is modified and returned as a promise.
*
- * @param {string} _url The rpc url to add to the frequentRpcList.
+ * @param {string} _url The rpc url to add to the frequentRpcList.
* @returns {Promise<array>} The updated frequentRpcList.
*
*/
diff --git a/app/scripts/controllers/recent-blocks.js b/app/scripts/controllers/recent-blocks.js
index 033ef1d7e..926268691 100644
--- a/app/scripts/controllers/recent-blocks.js
+++ b/app/scripts/controllers/recent-blocks.js
@@ -117,7 +117,7 @@ class RecentBlocksController {
*
* @returns {Promise<void>} Promises undefined
*/
- async backfill() {
+ async backfill () {
this.blockTracker.once('block', async (block) => {
const currentBlockNumber = Number.parseInt(block.number, 16)
const blocksToFetch = Math.min(currentBlockNumber, this.historyLength)
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/controllers/transactions/tx-gas-utils.js b/app/scripts/controllers/transactions/tx-gas-utils.js
index 36b5cdbc9..ab4031faa 100644
--- a/app/scripts/controllers/transactions/tx-gas-utils.js
+++ b/app/scripts/controllers/transactions/tx-gas-utils.js
@@ -126,4 +126,4 @@ class TxGasUtil {
}
}
-module.exports = TxGasUtil \ No newline at end of file
+module.exports = TxGasUtil
diff --git a/app/scripts/controllers/user-actions.js b/app/scripts/controllers/user-actions.js
new file mode 100644
index 000000000..f777054b8
--- /dev/null
+++ b/app/scripts/controllers/user-actions.js
@@ -0,0 +1,17 @@
+const MessageManager = require('./lib/message-manager')
+const PersonalMessageManager = require('./lib/personal-message-manager')
+const TypedMessageManager = require('./lib/typed-message-manager')
+
+class UserActionController {
+
+ constructor (opts = {}) {
+
+ this.messageManager = new MessageManager()
+ this.personalMessageManager = new PersonalMessageManager()
+ this.typedMessageManager = new TypedMessageManager()
+
+ }
+
+}
+
+module.exports = UserActionController