From b6e2eaf7b1d14fcca8ed614791937a5ccbfc00dd Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 16 Mar 2017 11:16:03 -0700 Subject: Remove eth-lightwallet --- app/scripts/lib/id-management.js | 90 ---------- app/scripts/lib/idStore-migrator.js | 80 --------- app/scripts/lib/idStore.js | 343 ------------------------------------ app/scripts/metamask-controller.js | 38 +--- 4 files changed, 1 insertion(+), 550 deletions(-) delete mode 100644 app/scripts/lib/id-management.js delete mode 100644 app/scripts/lib/idStore-migrator.js delete mode 100644 app/scripts/lib/idStore.js (limited to 'app') diff --git a/app/scripts/lib/id-management.js b/app/scripts/lib/id-management.js deleted file mode 100644 index 90b3fdb13..000000000 --- a/app/scripts/lib/id-management.js +++ /dev/null @@ -1,90 +0,0 @@ -/* ID Management - * - * This module exists to hold the decrypted credentials for the current session. - * It therefore exposes sign methods, because it is able to perform these - * with noa dditional authentication, because its very instantiation - * means the vault is unlocked. - */ - -const ethUtil = require('ethereumjs-util') -const Transaction = require('ethereumjs-tx') - -module.exports = IdManagement - -function IdManagement (opts) { - if (!opts) opts = {} - - this.keyStore = opts.keyStore - this.derivedKey = opts.derivedKey - this.configManager = opts.configManager - this.hdPathString = "m/44'/60'/0'/0" - - this.getAddresses = function () { - return this.keyStore.getAddresses(this.hdPathString).map(function (address) { return '0x' + address }) - } - - this.signTx = function (txParams) { - - // normalize values - txParams.gasPrice = ethUtil.intToHex(txParams.gasPrice) - txParams.to = ethUtil.addHexPrefix(txParams.to) - txParams.from = ethUtil.addHexPrefix(txParams.from.toLowerCase()) - txParams.value = ethUtil.addHexPrefix(txParams.value) - txParams.data = ethUtil.addHexPrefix(txParams.data) - txParams.gasLimit = ethUtil.addHexPrefix(txParams.gasLimit || txParams.gas) - txParams.nonce = ethUtil.addHexPrefix(txParams.nonce) - var tx = new Transaction(txParams) - - // sign tx - var privKeyHex = this.exportPrivateKey(txParams.from) - var privKey = ethUtil.toBuffer(privKeyHex) - tx.sign(privKey) - - // Add the tx hash to the persisted meta-tx object - var txHash = ethUtil.bufferToHex(tx.hash()) - var metaTx = this.configManager.getTx(txParams.metamaskId) - metaTx.hash = txHash - this.configManager.updateTx(metaTx) - - // return raw serialized tx - var rawTx = ethUtil.bufferToHex(tx.serialize()) - return rawTx - } - - this.signMsg = function (address, message) { - // sign message - var privKeyHex = this.exportPrivateKey(address.toLowerCase()) - var privKey = ethUtil.toBuffer(privKeyHex) - var msgSig = ethUtil.ecsign(new Buffer(message.replace('0x', ''), 'hex'), privKey) - var rawMsgSig = ethUtil.bufferToHex(concatSig(msgSig.v, msgSig.r, msgSig.s)) - return rawMsgSig - } - - this.getSeed = function () { - return this.keyStore.getSeed(this.derivedKey) - } - - this.exportPrivateKey = function (address) { - var privKeyHex = ethUtil.addHexPrefix(this.keyStore.exportPrivateKey(address, this.derivedKey, this.hdPathString)) - return privKeyHex - } -} - -function padWithZeroes (number, length) { - var myString = '' + number - while (myString.length < length) { - myString = '0' + myString - } - return myString -} - -function concatSig (v, r, s) { - const rSig = ethUtil.fromSigned(r) - const sSig = ethUtil.fromSigned(s) - const vSig = ethUtil.bufferToInt(v) - const rStr = padWithZeroes(ethUtil.toUnsigned(rSig).toString('hex'), 64) - const sStr = padWithZeroes(ethUtil.toUnsigned(sSig).toString('hex'), 64) - const vStr = ethUtil.stripHexPrefix(ethUtil.intToHex(vSig)) - return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex') -} - diff --git a/app/scripts/lib/idStore-migrator.js b/app/scripts/lib/idStore-migrator.js deleted file mode 100644 index 62d21eee7..000000000 --- a/app/scripts/lib/idStore-migrator.js +++ /dev/null @@ -1,80 +0,0 @@ -const IdentityStore = require('./idStore') -const HdKeyring = require('eth-hd-keyring') -const sigUtil = require('eth-sig-util') -const normalize = sigUtil.normalize -const denodeify = require('denodeify') - -module.exports = class IdentityStoreMigrator { - - constructor ({ configManager }) { - this.configManager = configManager - const hasOldVault = this.hasOldVault() - if (!hasOldVault) { - this.idStore = new IdentityStore({ configManager }) - } - } - - migratedVaultForPassword (password) { - const hasOldVault = this.hasOldVault() - const configManager = this.configManager - - if (!this.idStore) { - this.idStore = new IdentityStore({ configManager }) - } - - if (!hasOldVault) { - return Promise.resolve(null) - } - - const idStore = this.idStore - const submitPassword = denodeify(idStore.submitPassword.bind(idStore)) - - return submitPassword(password) - .then(() => { - const serialized = this.serializeVault() - return this.checkForLostAccounts(serialized) - }) - } - - serializeVault () { - const mnemonic = this.idStore._idmgmt.getSeed() - const numberOfAccounts = this.idStore._getAddresses().length - - return { - type: 'HD Key Tree', - data: { mnemonic, numberOfAccounts }, - } - } - - checkForLostAccounts (serialized) { - const hd = new HdKeyring() - return hd.deserialize(serialized.data) - .then((hexAccounts) => { - const newAccounts = hexAccounts.map(normalize) - const oldAccounts = this.idStore._getAddresses().map(normalize) - const lostAccounts = oldAccounts.reduce((result, account) => { - if (newAccounts.includes(account)) { - return result - } else { - result.push(account) - return result - } - }, []) - - return { - serialized, - lostAccounts: lostAccounts.map((address) => { - return { - address, - privateKey: this.idStore.exportAccount(address), - } - }), - } - }) - } - - hasOldVault () { - const wallet = this.configManager.getWallet() - return wallet - } -} diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js deleted file mode 100644 index 01474035e..000000000 --- a/app/scripts/lib/idStore.js +++ /dev/null @@ -1,343 +0,0 @@ -const EventEmitter = require('events').EventEmitter -const inherits = require('util').inherits -const ethUtil = require('ethereumjs-util') -const KeyStore = require('eth-lightwallet').keystore -const clone = require('clone') -const extend = require('xtend') -const autoFaucet = require('./auto-faucet') -const DEFAULT_RPC = 'https://testrpc.metamask.io/' -const IdManagement = require('./id-management') - - -module.exports = IdentityStore - -inherits(IdentityStore, EventEmitter) -function IdentityStore (opts = {}) { - EventEmitter.call(this) - - // we just use the ethStore to auto-add accounts - this._ethStore = opts.ethStore - this.configManager = opts.configManager - // lightwallet key store - this._keyStore = null - // lightwallet wrapper - this._idmgmt = null - - this.hdPathString = "m/44'/60'/0'/0" - - this._currentState = { - selectedAddress: null, - identities: {}, - } - // not part of serilized metamask state - only kept in memory -} - -// -// public -// - -IdentityStore.prototype.createNewVault = function (password, cb) { - delete this._keyStore - var serializedKeystore = this.configManager.getWallet() - - if (serializedKeystore) { - this.configManager.setData({}) - } - - this.purgeCache() - this._createVault(password, null, (err) => { - if (err) return cb(err) - - this._autoFaucet() - - this.configManager.setShowSeedWords(true) - var seedWords = this._idmgmt.getSeed() - - this._loadIdentities() - - cb(null, seedWords) - }) -} - -IdentityStore.prototype.recoverSeed = function (cb) { - this.configManager.setShowSeedWords(true) - if (!this._idmgmt) return cb(new Error('Unauthenticated. Please sign in.')) - var seedWords = this._idmgmt.getSeed() - cb(null, seedWords) -} - -IdentityStore.prototype.recoverFromSeed = function (password, seed, cb) { - this.purgeCache() - - this._createVault(password, seed, (err) => { - if (err) return cb(err) - - this._loadIdentities() - cb(null, this.getState()) - }) -} - -IdentityStore.prototype.setStore = function (store) { - this._ethStore = store -} - -IdentityStore.prototype.clearSeedWordCache = function (cb) { - const configManager = this.configManager - configManager.setShowSeedWords(false) - cb(null, configManager.getSelectedAccount()) -} - -IdentityStore.prototype.getState = function () { - const configManager = this.configManager - var seedWords = this.getSeedIfUnlocked() - return clone(extend(this._currentState, { - isInitialized: !!configManager.getWallet() && !seedWords, - isUnlocked: this._isUnlocked(), - seedWords: seedWords, - selectedAddress: configManager.getSelectedAccount(), - })) -} - -IdentityStore.prototype.getSeedIfUnlocked = function () { - const configManager = this.configManager - var showSeed = configManager.getShouldShowSeedWords() - var idmgmt = this._idmgmt - var shouldShow = showSeed && !!idmgmt - var seedWords = shouldShow ? idmgmt.getSeed() : null - return seedWords -} - -IdentityStore.prototype.getSelectedAddress = function () { - const configManager = this.configManager - return configManager.getSelectedAccount() -} - -IdentityStore.prototype.setSelectedAddressSync = function (address) { - const configManager = this.configManager - if (!address) { - var addresses = this._getAddresses() - address = addresses[0] - } - - configManager.setSelectedAccount(address) - return address -} - -IdentityStore.prototype.setSelectedAddress = function (address, cb) { - const resultAddress = this.setSelectedAddressSync(address) - if (cb) return cb(null, resultAddress) -} - -IdentityStore.prototype.revealAccount = function (cb) { - const derivedKey = this._idmgmt.derivedKey - const keyStore = this._keyStore - const configManager = this.configManager - - keyStore.setDefaultHdDerivationPath(this.hdPathString) - keyStore.generateNewAddress(derivedKey, 1) - const addresses = keyStore.getAddresses() - const address = addresses[ addresses.length - 1 ] - - this._ethStore.addAccount(ethUtil.addHexPrefix(address)) - - configManager.setWallet(keyStore.serialize()) - - this._loadIdentities() - this._didUpdate() - cb(null) -} - -IdentityStore.prototype.getNetwork = function (err) { - if (err) { - this._currentState.network = 'loading' - this._didUpdate() - } - - this.web3.version.getNetwork((err, network) => { - if (err) { - this._currentState.network = 'loading' - return this._didUpdate() - } - if (global.METAMASK_DEBUG) { - console.log('web3.getNetwork returned ' + network) - } - this._currentState.network = network - this._didUpdate() - }) -} - -IdentityStore.prototype.setLocked = function (cb) { - delete this._keyStore - delete this._idmgmt - cb() -} - -IdentityStore.prototype.submitPassword = function (password, cb) { - const configManager = this.configManager - this.tryPassword(password, (err) => { - if (err) return cb(err) - // load identities before returning... - this._loadIdentities() - cb(null, configManager.getSelectedAccount()) - }) -} - -IdentityStore.prototype.exportAccount = function (address, cb) { - var privateKey = this._idmgmt.exportPrivateKey(address) - if (cb) cb(null, privateKey) - return privateKey -} - -// private -// - -IdentityStore.prototype._didUpdate = function () { - this.emit('update', this.getState()) -} - -IdentityStore.prototype._isUnlocked = function () { - var result = Boolean(this._keyStore) && Boolean(this._idmgmt) - return result -} - -// load identities from keyStoreet -IdentityStore.prototype._loadIdentities = function () { - const configManager = this.configManager - if (!this._isUnlocked()) throw new Error('not unlocked') - - var addresses = this._getAddresses() - addresses.forEach((address, i) => { - // // add to ethStore - if (this._ethStore) { - this._ethStore.addAccount(ethUtil.addHexPrefix(address)) - } - // add to identities - const defaultLabel = 'Account ' + (i + 1) - const nickname = configManager.nicknameForWallet(address) - var identity = { - name: nickname || defaultLabel, - address: address, - mayBeFauceting: this._mayBeFauceting(i), - } - this._currentState.identities[address] = identity - }) - this._didUpdate() -} - -IdentityStore.prototype.saveAccountLabel = function (account, label, cb) { - const configManager = this.configManager - configManager.setNicknameForWallet(account, label) - this._loadIdentities() - cb(null, label) -} - -// mayBeFauceting -// If on testnet, index 0 may be fauceting. -// The UI will have to check the balance to know. -// If there is no balance and it mayBeFauceting, -// then it is in fact fauceting. -IdentityStore.prototype._mayBeFauceting = function (i) { - const configManager = this.configManager - var config = configManager.getProvider() - if (i === 0 && - config.type === 'rpc' && - config.rpcTarget === DEFAULT_RPC) { - return true - } - return false -} - -// -// keyStore managment - unlocking + deserialization -// - -IdentityStore.prototype.tryPassword = function (password, cb) { - var serializedKeystore = this.configManager.getWallet() - var keyStore = KeyStore.deserialize(serializedKeystore) - - keyStore.keyFromPassword(password, (err, pwDerivedKey) => { - if (err) return cb(err) - - const isCorrect = keyStore.isDerivedKeyCorrect(pwDerivedKey) - if (!isCorrect) return cb(new Error('Lightwallet - password incorrect')) - - this._keyStore = keyStore - this._createIdMgmt(pwDerivedKey) - cb() - }) -} - -IdentityStore.prototype._createVault = function (password, seedPhrase, cb) { - const opts = { - password, - hdPathString: this.hdPathString, - } - - if (seedPhrase) { - opts.seedPhrase = seedPhrase - } - - KeyStore.createVault(opts, (err, keyStore) => { - if (err) return cb(err) - - this._keyStore = keyStore - - keyStore.keyFromPassword(password, (err, derivedKey) => { - if (err) return cb(err) - - this.purgeCache() - - keyStore.addHdDerivationPath(this.hdPathString, derivedKey, {curve: 'secp256k1', purpose: 'sign'}) - - this._createFirstWallet(derivedKey) - this._createIdMgmt(derivedKey) - this.setSelectedAddressSync() - - cb() - }) - }) -} - -IdentityStore.prototype._createIdMgmt = function (derivedKey) { - this._idmgmt = new IdManagement({ - keyStore: this._keyStore, - derivedKey: derivedKey, - configManager: this.configManager, - }) -} - -IdentityStore.prototype.purgeCache = function () { - this._currentState.identities = {} - let accounts - try { - accounts = Object.keys(this._ethStore._currentState.accounts) - } catch (e) { - accounts = [] - } - accounts.forEach((address) => { - this._ethStore.removeAccount(address) - }) -} - -IdentityStore.prototype._createFirstWallet = function (derivedKey) { - const keyStore = this._keyStore - keyStore.setDefaultHdDerivationPath(this.hdPathString) - keyStore.generateNewAddress(derivedKey, 1) - this.configManager.setWallet(keyStore.serialize()) - var addresses = keyStore.getAddresses() - this._ethStore.addAccount(ethUtil.addHexPrefix(addresses[0])) -} - -// get addresses and normalize address hexString -IdentityStore.prototype._getAddresses = function () { - return this._keyStore.getAddresses(this.hdPathString).map((address) => { - return ethUtil.addHexPrefix(address) - }) -} - -IdentityStore.prototype._autoFaucet = function () { - var addresses = this._getAddresses() - autoFaucet(addresses[0]) -} - -// util diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 25f9d9e5d..92533e022 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -23,7 +23,6 @@ const ConfigManager = require('./lib/config-manager') const extension = require('./lib/extension') const autoFaucet = require('./lib/auto-faucet') const nodeify = require('./lib/nodeify') -const IdStoreMigrator = require('./lib/idStore-migrator') const accountImporter = require('./account-import-strategies') const version = require('../manifest.json').version @@ -115,11 +114,6 @@ module.exports = class MetamaskController extends EventEmitter { this.personalMessageManager = new PersonalMessageManager() this.publicConfigStore = this.initPublicConfigStore() - // TEMPORARY UNTIL FULL DEPRECATION: - this.idStoreMigrator = new IdStoreMigrator({ - configManager: this.configManager, - }) - // manual disk state subscriptions this.txManager.store.subscribe((state) => { this.store.updateState({ TransactionManager: state }) @@ -366,8 +360,7 @@ module.exports = class MetamaskController extends EventEmitter { // submitPassword (password, cb) { - this.migrateOldVaultIfAny(password) - .then(this.keyringController.submitPassword.bind(this.keyringController, password)) + return this.keyringController.submitPassword(password) .then((newState) => { cb(null, newState) }) .catch((reason) => { cb(reason) }) } @@ -562,35 +555,6 @@ module.exports = class MetamaskController extends EventEmitter { cb(null, this.getState()) } - // Migrate Old Vault If Any - // @string password - // - // returns Promise() - // - // Temporary step used when logging in. - // Checks if old style (pre-3.0.0) Metamask Vault exists. - // If so, persists that vault in the new vault format - // with the provided password, so the other unlock steps - // may be completed without interruption. - migrateOldVaultIfAny (password) { - - if (!this.checkIfShouldMigrate()) { - return Promise.resolve(password) - } - - const keyringController = this.keyringController - - return this.idStoreMigrator.migratedVaultForPassword(password) - .then(this.restoreOldVaultAccounts.bind(this)) - .then(this.restoreOldLostAccounts.bind(this)) - .then(keyringController.persistAllKeyrings.bind(keyringController, password)) - .then(() => password) - } - - checkIfShouldMigrate() { - return !!this.configManager.getWallet() && !this.configManager.getVault() - } - restoreOldVaultAccounts(migratorOutput) { const { serialized } = migratorOutput return this.keyringController.restoreKeyring(serialized) -- cgit From 8c7be4340349032655503b4137147e1978b0f0bd Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 22 Mar 2017 09:48:41 -0700 Subject: Have better error messages --- app/scripts/transaction-manager.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index c6cfdf11d..31c1c8431 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -172,7 +172,10 @@ module.exports = class TransactionManager extends EventEmitter { ], (err) => { self.nonceLock.leave() if (err) { - this.setTxStatusFailed(txId) + this.setTxStatusFailed(txId, { + errCode: err.errCode || err, + message: err.message || 'Transaction failed during approval', + }) return cb(err) } cb() @@ -291,7 +294,10 @@ module.exports = class TransactionManager extends EventEmitter { this._setTxStatus(txId, 'confirmed') } - setTxStatusFailed (txId) { + setTxStatusFailed (txId, reason) { + let txMeta = this.getTx(txId) + txMeta.err = reason + this.updateTx(txMeta) this._setTxStatus(txId, 'failed') } @@ -312,12 +318,11 @@ module.exports = class TransactionManager extends EventEmitter { var txHash = txMeta.hash var txId = txMeta.id if (!txHash) { - txMeta.err = { + let errReason = { errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.', } - this.updateTx(txMeta) - return this.setTxStatusFailed(txId) + return this.setTxStatusFailed(txId, errReason) } this.txProviderUtils.query.getTransactionByHash(txHash, (err, txParams) => { if (err || !txParams) { -- cgit From 9906da86a4669c1eaf7f693398de380b2973bfe8 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Mar 2017 14:25:56 -0400 Subject: Modify logic for injection conditions. --- app/scripts/contentscript.js | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index ab64dc9fa..020208ceb 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -69,14 +69,10 @@ function shouldInjectWeb3 () { } function isAllowedSuffix (testCase) { - var prohibitedTypes = ['xml', 'pdf'] - var currentUrl = window.location.href - var currentRegex - for (let i = 0; i < prohibitedTypes.length; i++) { - currentRegex = new RegExp(`\.${prohibitedTypes[i]}$`) - if (currentRegex.test(currentUrl)) { - return false - } + const doctype = window.document.doctype + if (doctype) { + return doctype.name === 'html' + } else { + return false } - return true } -- cgit From c5f96be98d7fe36a369c48b775d0b1fe857844c6 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Mar 2017 15:59:46 -0400 Subject: Add kovan to config file. --- app/scripts/config.js | 2 ++ 1 file changed, 2 insertions(+) (limited to 'app') diff --git a/app/scripts/config.js b/app/scripts/config.js index b4541a04a..ec421744d 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -1,5 +1,6 @@ const MAINET_RPC_URL = 'https://mainnet.infura.io/metamask' const TESTNET_RPC_URL = 'https://ropsten.infura.io/metamask' +const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask' const DEFAULT_RPC_URL = TESTNET_RPC_URL global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -10,5 +11,6 @@ module.exports = { mainnet: MAINET_RPC_URL, testnet: TESTNET_RPC_URL, morden: TESTNET_RPC_URL, + kovan: KOVAN_RPC_URL, }, } -- cgit From 33dd7954a72797d23a0d8ed652a626addb1af55d Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Mar 2017 16:00:50 -0400 Subject: Add kovan config settings to config manager. --- app/scripts/lib/config-manager.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 6868637e5..e31cb45ed 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -5,6 +5,7 @@ const normalize = require('eth-sig-util').normalize const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet const MORDEN_RPC = MetamaskConfig.network.morden +const KOVAN_RPC = MetamaskConfig.network.kovan /* The config-manager is a convenience object * wrapping a pojo-migrator. @@ -150,6 +151,9 @@ ConfigManager.prototype.getCurrentRpcAddress = function () { case 'morden': return MORDEN_RPC + case 'kovan': + return KOVAN_RPC + default: return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC } -- cgit From 1b7326048db25afc36baea84ebcf9ece0847f3c3 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 22 Mar 2017 16:41:19 -0400 Subject: Add current block number and hash to the state. --- app/scripts/lib/eth-store.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/eth-store.js b/app/scripts/lib/eth-store.js index 8812a507b..243253df2 100644 --- a/app/scripts/lib/eth-store.js +++ b/app/scripts/lib/eth-store.js @@ -19,6 +19,8 @@ class EthereumStore extends ObservableStore { super({ accounts: {}, transactions: {}, + currentBlockNumber: '0', + currentBlockHash: '', }) this._provider = opts.provider this._query = new EthQuery(this._provider) @@ -69,6 +71,8 @@ class EthereumStore extends ObservableStore { _updateForBlock (block) { const blockNumber = '0x' + block.number.toString('hex') this._currentBlockNumber = blockNumber + this.updateState({ currentBlockNumber: parseInt(blockNumber) }) + this.updateState({ currentBlockHash: `0x${block.hash.toString('hex')}`}) async.parallel([ this._updateAccounts.bind(this), this._updateTransactions.bind(this, blockNumber), @@ -129,4 +133,4 @@ class EthereumStore extends ObservableStore { } -module.exports = EthereumStore \ No newline at end of file +module.exports = EthereumStore -- cgit From bcaf0864c18df4f8d8cb92c739669447fa5aa059 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 23 Mar 2017 09:58:57 -0400 Subject: Remove notice body after reading. --- app/scripts/notice-controller.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/notice-controller.js b/app/scripts/notice-controller.js index 0d72760fe..57aad40c5 100644 --- a/app/scripts/notice-controller.js +++ b/app/scripts/notice-controller.js @@ -41,6 +41,7 @@ module.exports = class NoticeController extends EventEmitter { var notices = this.getNoticesList() var index = notices.findIndex((currentNotice) => currentNotice.id === noticeToMark.id) notices[index].read = true + notices[index].body = '' this.setNoticesList(notices) const latestNotice = this.getLatestUnreadNotice() cb(null, latestNotice) -- cgit From 16c76d522960298476492b53a02d1b490b84b858 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 23 Mar 2017 10:15:59 -0400 Subject: Create migration to erase body in read notices. --- app/scripts/migrations/012.js | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 app/scripts/migrations/012.js (limited to 'app') diff --git a/app/scripts/migrations/012.js b/app/scripts/migrations/012.js new file mode 100644 index 000000000..8361b3793 --- /dev/null +++ b/app/scripts/migrations/012.js @@ -0,0 +1,36 @@ +const version = 12 + +/* + +This migration modifies our notices to delete their body after being read. + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + let versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + newState.NoticeController.noticesList.forEach((notice) => { + if (notice.read) { + notice.body = '' + } + }) + return newState +} -- cgit From fa0bbd66b6896188c5a47ed6978fc992068ae22c Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 23 Mar 2017 11:28:06 -0400 Subject: Fix persistence of transactions between networks. --- app/scripts/transaction-manager.js | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) (limited to 'app') diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index 31c1c8431..7227bdc87 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -47,27 +47,39 @@ module.exports = class TransactionManager extends EventEmitter { // Returns the tx list getTxList () { let network = this.getNetwork() - let fullTxList = this.store.getState().transactions + let fullTxList = this.getFullTxList() return fullTxList.filter(txMeta => txMeta.metamaskNetworkId === network) } + // Returns the number of txs for the current network. + getTxCount () { + return this.getTxList().length + } + + // Returns the full tx list across all networks + getFullTxList () { + return this.store.getState().transactions + } + // Adds a tx to the txlist addTx (txMeta) { - var txList = this.getTxList() - var txHistoryLimit = this.txHistoryLimit + let txCount = this.getTxCount() + let network = this.getNetwork() + let fullTxList = this.getFullTxList() + let txHistoryLimit = this.txHistoryLimit - // checks if the length of th tx history is + // checks if the length of the tx history is // longer then desired persistence limit // and then if it is removes only confirmed // or rejected tx's. // not tx's that are pending or unapproved - if (txList.length > txHistoryLimit - 1) { - var index = txList.findIndex((metaTx) => metaTx.status === 'confirmed' || metaTx.status === 'rejected') - txList.splice(index, 1) + if (txCount > txHistoryLimit - 1) { + var index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) + fullTxList.splice(index, 1) } - txList.push(txMeta) + fullTxList.push(txMeta) - this._saveTxList(txList) + this._saveTxList(fullTxList) this.once(`${txMeta.id}:signed`, function (txId) { this.removeAllListeners(`${txMeta.id}:rejected`) }) @@ -89,7 +101,7 @@ module.exports = class TransactionManager extends EventEmitter { // updateTx (txMeta) { var txId = txMeta.id - var txList = this.getTxList() + var txList = this.getFullTxList() var index = txList.findIndex(txData => txData.id === txId) txList[index] = txMeta this._saveTxList(txList) -- cgit From 45ab81fb45ec1043d617f66c308e2e7911c8e0ad Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 23 Mar 2017 11:06:38 -0700 Subject: WIP: streams->indexdb --- app/scripts/metamask-controller.js | 1 - app/scripts/popup-core.js | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 536891dc6..a26c0e45d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -204,7 +204,6 @@ module.exports = class MetamaskController extends EventEmitter { // getState () { - const wallet = this.configManager.getWallet() const vault = this.keyringController.store.getState().vault const isInitialized = (!!wallet || !!vault) diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index b1e521a7a..7ade66922 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -11,6 +11,7 @@ module.exports = initializePopup function initializePopup (connectionStream) { // setup app + debugger connectToAccountManager(connectionStream, setupApp) } -- cgit From 197e6e0b77868b0bec76cef303b2eeffda5797bf Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 23 Mar 2017 11:41:32 -0700 Subject: WIP: indexdb is at an err state "provider is undefined" --- app/scripts/popup-core.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 7ade66922..b1e521a7a 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -11,7 +11,6 @@ module.exports = initializePopup function initializePopup (connectionStream) { // setup app - debugger connectToAccountManager(connectionStream, setupApp) } -- cgit From 2cab2f767c4cfe6d42899ca51ef5aa36d5eaf456 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 23 Mar 2017 13:56:32 -0700 Subject: Remove gas limit param Fixes #1256 by removing redundant param. --- app/scripts/lib/tx-utils.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index c6814c05f..7988f83e9 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -63,7 +63,7 @@ module.exports = class txProviderUtils { const initialGasLimitBn = hexToBn(initialGasLimitHex) const blockGasLimitBn = hexToBn(blockGasLimitHex) const bufferedGasLimitBn = initialGasLimitBn.muln(1.5) - + // if initialGasLimit is above blockGasLimit, dont modify it if (initialGasLimitBn.gt(blockGasLimitBn)) return bnToHex(initialGasLimitBn) // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit @@ -99,7 +99,7 @@ module.exports = class txProviderUtils { txParams.from = normalize(txParams.from) txParams.value = normalize(txParams.value) txParams.data = normalize(txParams.data) - txParams.gasLimit = normalize(txParams.gasLimit || txParams.gas) + txParams.gas = normalize(txParams.gas || txParams.gasLimit) txParams.nonce = normalize(txParams.nonce) // build ethTx log.info(`Prepared tx for signing: ${JSON.stringify(txParams)}`) @@ -134,4 +134,4 @@ function bnToHex(inputBn) { function hexToBn(inputHex) { return new BN(ethUtil.stripHexPrefix(inputHex), 16) -} \ No newline at end of file +} -- cgit From 0faddb2ed2a2161be5b2af1630d583e04b750f94 Mon Sep 17 00:00:00 2001 From: Stefaan Ponnet Date: Sun, 26 Mar 2017 13:57:44 +0200 Subject: Allow injection in IFrames + dynamic IFrames --- app/manifest.json | 2 +- app/scripts/contentscript.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 910a5701e..bc1d2f866 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -51,7 +51,7 @@ "scripts/contentscript.js" ], "run_at": "document_start", - "all_frames": false + "all_frames": true } ], "permissions": [ diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 020208ceb..09c1841bf 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -73,6 +73,6 @@ function isAllowedSuffix (testCase) { if (doctype) { return doctype.name === 'html' } else { - return false + return true } } -- cgit From d9c2f4f5e8dc9ec8a88a02eb5a73ea78b4a564ac Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 27 Mar 2017 11:48:10 -0700 Subject: Version 3.5.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 910a5701e..70d701fc5 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.4.0", + "version": "3.5.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From c1136a6317399ec033bf17a9ce0b13a2a1c4b0d2 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Mon, 27 Mar 2017 16:05:21 -0400 Subject: Add link to kovan faucet instructions. --- app/scripts/metamask-controller.js | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 92533e022..bab17dabd 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -623,6 +623,10 @@ module.exports = class MetamaskController extends EventEmitter { case '3': url = 'https://faucet.metamask.io/' break + + case '42': + url = 'https://github.com/kovan-testnet/faucet' + break } if (url) extension.tabs.create({ url }) -- cgit From d41c8ef5986e1f39350f4ea1f7664415ea236c7d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 27 Mar 2017 13:39:19 -0700 Subject: Version 3.5.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 70d701fc5..97cc7dd6d 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.5.0", + "version": "3.5.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From a95d96d507b9b20e0457baae9f9d38e26b23d8b3 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 28 Mar 2017 11:23:25 -0400 Subject: Assure that seed words are placed into state tree upon request. --- app/scripts/metamask-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 92533e022..c0c113a45 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -386,7 +386,7 @@ module.exports = class MetamaskController extends EventEmitter { .then((serialized) => { const seedWords = serialized.mnemonic this.configManager.setSeedWords(seedWords) - cb() + cb(null, seedWords) }) } -- cgit From 0625b4a11038307673a4fcd9689e0955e10ebacf Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 28 Mar 2017 14:30:39 -0400 Subject: Fix injection logic. --- app/scripts/contentscript.js | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 09c1841bf..9a390e580 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -65,14 +65,27 @@ function setupStreams () { } function shouldInjectWeb3 () { - return isAllowedSuffix(window.location.href) + return doctypeCheck() || suffixCheck() } -function isAllowedSuffix (testCase) { +function doctypeCheck () { const doctype = window.document.doctype if (doctype) { return doctype.name === 'html' } else { - return true + return false } } + +function suffixCheck() { + var prohibitedTypes = ['xml', 'pdf'] + var currentUrl = window.location.href + var currentRegex + for (let i = 0; i < prohibitedTypes.length; i++) { + currentRegex = new RegExp(`\.${prohibitedTypes[i]}$`) + if (currentRegex.test(currentUrl)) { + return false + } + } + return true +} -- cgit From 81d3658343bbdf8dd85b175f759c372d9ee00fb8 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 28 Mar 2017 11:46:33 -0700 Subject: Improve UI gas calculation logic - Now striping hex prefixed gas values, which may have been causing mis-estimation. - Unified calculation logic to be entirely functional. - Greatly simplified how the pending-tx form keeps updated form state. Still needs a commit from @kumavis to ensure the background passes in a txMeta.txParams.gasPrice value. --- app/scripts/lib/hex-to-bn.js | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 app/scripts/lib/hex-to-bn.js (limited to 'app') diff --git a/app/scripts/lib/hex-to-bn.js b/app/scripts/lib/hex-to-bn.js new file mode 100644 index 000000000..184217279 --- /dev/null +++ b/app/scripts/lib/hex-to-bn.js @@ -0,0 +1,7 @@ +const ethUtil = require('ethereumjs-util') +const BN = ethUtil.BN + +module.exports = function hexToBn (hex) { + return new BN(ethUtil.stripHexPrefix(hex), 16) +} + -- cgit From 1495240969f8b4931259f487c3eb75aca36c68d7 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 28 Mar 2017 13:35:27 -0700 Subject: tx manager - adjust new tx flow and txMeta decorations --- app/scripts/lib/tx-utils.js | 32 ++++++++++++++--------------- app/scripts/transaction-manager.js | 41 ++++++++++++++++---------------------- 2 files changed, 32 insertions(+), 41 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 7988f83e9..72df53631 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -12,48 +12,49 @@ and used to do things like calculate gas of a tx. */ module.exports = class txProviderUtils { + constructor (provider) { this.provider = provider this.query = new EthQuery(provider) } - analyzeGasUsage (txData, cb) { + analyzeGasUsage (txMeta, cb) { var self = this this.query.getBlockByNumber('latest', true, (err, block) => { if (err) return cb(err) async.waterfall([ - self.estimateTxGas.bind(self, txData, block.gasLimit), - self.setTxGas.bind(self, txData, block.gasLimit), + self.estimateTxGas.bind(self, txMeta, block.gasLimit), + self.setTxGas.bind(self, txMeta, block.gasLimit), ], cb) }) } - estimateTxGas (txData, blockGasLimitHex, cb) { - const txParams = txData.txParams + estimateTxGas (txMeta, blockGasLimitHex, cb) { + const txParams = txMeta.txParams // check if gasLimit is already specified - txData.gasLimitSpecified = Boolean(txParams.gas) + txMeta.gasLimitSpecified = Boolean(txParams.gas) // if not, fallback to block gasLimit - if (!txData.gasLimitSpecified) { + if (!txMeta.gasLimitSpecified) { txParams.gas = blockGasLimitHex } // run tx, see if it will OOG this.query.estimateGas(txParams, cb) } - setTxGas (txData, blockGasLimitHex, estimatedGasHex, cb) { - txData.estimatedGas = estimatedGasHex - const txParams = txData.txParams + setTxGas (txMeta, blockGasLimitHex, estimatedGasHex, cb) { + txMeta.estimatedGas = estimatedGasHex + const txParams = txMeta.txParams // if gasLimit was specified and doesnt OOG, // use original specified amount - if (txData.gasLimitSpecified) { - txData.estimatedGas = txParams.gas + if (txMeta.gasLimitSpecified) { + txMeta.estimatedGas = txParams.gas cb() return } // if gasLimit not originally specified, // try adding an additional gas buffer to our estimation for safety - const recommendedGasHex = this.addGasBuffer(txData.estimatedGas, blockGasLimitHex) + const recommendedGasHex = this.addGasBuffer(txMeta.estimatedGas, blockGasLimitHex) txParams.gas = recommendedGasHex cb() return @@ -90,16 +91,13 @@ module.exports = class txProviderUtils { // builds ethTx from txParams object buildEthTxFromParams (txParams) { - // apply gas multiplyer - let gasPrice = hexToBn(txParams.gasPrice) - // multiply and divide by 100 so as to add percision to integer mul - txParams.gasPrice = ethUtil.intToHex(gasPrice.toNumber()) // normalize values txParams.to = normalize(txParams.to) txParams.from = normalize(txParams.from) txParams.value = normalize(txParams.value) txParams.data = normalize(txParams.data) txParams.gas = normalize(txParams.gas || txParams.gasLimit) + txParams.gasPrice = normalize(txParams.gasPrice) txParams.nonce = normalize(txParams.nonce) // build ethTx log.info(`Prepared tx for signing: ${JSON.stringify(txParams)}`) diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index 7227bdc87..571fb8ae0 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -4,7 +4,6 @@ const extend = require('xtend') const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const BN = require('ethereumjs-util').BN const TxProviderUtil = require('./lib/tx-utils') const createId = require('./lib/random-id') @@ -121,44 +120,38 @@ module.exports = class TransactionManager extends EventEmitter { async.waterfall([ // validate (cb) => this.txProviderUtils.validateTxParams(txParams, cb), - // prepare txMeta + // construct txMeta (cb) => { - // create txMeta obj with parameters and meta data - let time = (new Date()).getTime() - let txId = createId() - txParams.metamaskId = txId - txParams.metamaskNetworkId = this.getNetwork() txMeta = { - id: txId, - time: time, + id: createId(), + time: (new Date()).getTime(), status: 'unapproved', metamaskNetworkId: this.getNetwork(), txParams: txParams, } - // calculate metadata for tx - this.txProviderUtils.analyzeGasUsage(txMeta, cb) + cb() }, + // add default tx params + (cb) => this.addTxDefaults(txMeta, cb), // save txMeta (cb) => { this.addTx(txMeta) - this.setMaxTxCostAndFee(txMeta) cb(null, txMeta) }, ], done) } - setMaxTxCostAndFee (txMeta) { - var txParams = txMeta.txParams - var gasCost = new BN(ethUtil.stripHexPrefix(txParams.gas || txMeta.estimatedGas), 16) - var gasPrice = new BN(ethUtil.stripHexPrefix(txParams.gasPrice || '0x4a817c800'), 16) - var txFee = gasCost.mul(gasPrice) - var txValue = new BN(ethUtil.stripHexPrefix(txParams.value || '0x0'), 16) - var maxCost = txValue.add(txFee) - txMeta.txFee = txFee - txMeta.txValue = txValue - txMeta.maxCost = maxCost - txMeta.gasPrice = gasPrice - this.updateTx(txMeta) + addTxDefaults (txMeta, cb) { + const txParams = txMeta.txParams + // ensure value + txParams.value = txParams.value || '0x0' + this.query.gasPrice((err, gasPrice) => { + if (err) return cb(err) + // set gasPrice + txParams.gasPrice = gasPrice + // set gasLimit + this.txProviderUtils.analyzeGasUsage(txMeta, cb) + }) } getUnapprovedTxList () { -- cgit From e864623d3cfc70ff10ef1b84d5853dc7aa50fa36 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 28 Mar 2017 13:56:35 -0700 Subject: tx manager - add eth-query --- app/scripts/transaction-manager.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index 571fb8ae0..690d44808 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -4,6 +4,7 @@ const extend = require('xtend') const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') +const EthQuery = require('eth-query') const TxProviderUtil = require('./lib/tx-utils') const createId = require('./lib/random-id') @@ -19,6 +20,7 @@ module.exports = class TransactionManager extends EventEmitter { this.txHistoryLimit = opts.txHistoryLimit this.provider = opts.provider this.blockTracker = opts.blockTracker + this.query = new EthQuery(this.provider) this.txProviderUtils = new TxProviderUtil(this.provider) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) this.signEthTx = opts.signTransaction @@ -329,7 +331,7 @@ module.exports = class TransactionManager extends EventEmitter { } return this.setTxStatusFailed(txId, errReason) } - this.txProviderUtils.query.getTransactionByHash(txHash, (err, txParams) => { + this.query.getTransactionByHash(txHash, (err, txParams) => { if (err || !txParams) { if (!txParams) return txMeta.err = { -- cgit From 6310a05daeb6a4934de6976a6a9a38be85044aa0 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 28 Mar 2017 14:39:29 -0700 Subject: tx manager - emit update on new unapproved tx --- app/scripts/transaction-manager.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index 690d44808..a70159680 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -79,8 +79,9 @@ module.exports = class TransactionManager extends EventEmitter { fullTxList.splice(index, 1) } fullTxList.push(txMeta) - this._saveTxList(fullTxList) + this.emit('update') + this.once(`${txMeta.id}:signed`, function (txId) { this.removeAllListeners(`${txMeta.id}:rejected`) }) -- cgit From 3b6b06db9276968acf5af35f9e855991bfb5b8ec Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 28 Mar 2017 15:01:01 -0700 Subject: Version 2.5.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a163d4c06..75e72c295 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.5.1", + "version": "3.5.2", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 576fb26c1558e7e639f28bed07da72d662a5039e Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 29 Mar 2017 11:08:15 -0400 Subject: Add missing migration. --- app/scripts/migrations/index.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index a3dd48c17..019b4d13d 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -22,4 +22,5 @@ module.exports = [ require('./009'), require('./010'), require('./011'), + require('./012'), ] -- cgit From 610ec2bdf5841c8275073992e67c59fb47faa48c Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 29 Mar 2017 10:40:57 -0700 Subject: Fix popup behavior for Firefox Firefox does not support the `focused` parameter when opening a new window, and we don't actually require it for Chrome either, new popups are at the foreground by default already. --- app/scripts/lib/extension.js | 5 ++++- app/scripts/lib/notifications.js | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/extension.js b/app/scripts/lib/extension.js index 4b670490f..6f8b5d800 100644 --- a/app/scripts/lib/extension.js +++ b/app/scripts/lib/extension.js @@ -11,4 +11,7 @@ */ const Extension = require('./extension-instance') -module.exports = new Extension() +const instance = new Extension() +window.METAMASK_EXTENSION = instance +module.exports = instance + diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index 3db1ac6b5..33914846c 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -22,10 +22,12 @@ function show () { extension.windows.create({ url: 'notification.html', type: 'popup', - focused: true, width, height, }) + .catch((reason) => { + log.error("failed to create poupup", reason) + }) } }) } -- cgit From 98dd684524fde7548442830fe01e1f3e24a6e67d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 29 Mar 2017 10:42:43 -0700 Subject: Linted --- app/scripts/lib/notifications.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index 33914846c..0ec01f3a7 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -26,7 +26,7 @@ function show () { height, }) .catch((reason) => { - log.error("failed to create poupup", reason) + log.error('failed to create poupup', reason) }) } }) -- cgit From 84b3415b4479eb849b69d77a7e178c67fcaaf3fb Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 29 Mar 2017 10:53:43 -0700 Subject: WIP: lost enital call from dapp to getAccounts --- app/scripts/controllers/preferences.js | 1 + app/scripts/metamask-controller.js | 1 + 2 files changed, 2 insertions(+) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index c7f675a41..dbd5aeaaa 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -24,6 +24,7 @@ class PreferencesController { } getSelectedAddress (_address) { + console.log('PREFERNCES: getSelectedAddress was called') return this.store.getState().selectedAddress } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 0393caeab..db80d5f1b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -165,6 +165,7 @@ module.exports = class MetamaskController extends EventEmitter { rpcUrl: this.configManager.getCurrentRpcAddress(), // account mgmt getAccounts: (cb) => { + console.log('METAMASK CONTROLLER: getAccounts was called') let selectedAddress = this.preferencesController.getSelectedAddress() let result = selectedAddress ? [selectedAddress] : [] cb(null, result) -- cgit From 8ade8bdf32933ea9449d06aa6a1fc71c10b461c4 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 29 Mar 2017 13:35:51 -0700 Subject: Fix currency checking for firefox By adding cryptonator to our permitted CORS hosts. Fixes #1285. Will probably trigger additional permissions requests to our users. --- app/manifest.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 75e72c295..a3242149b 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -57,7 +57,8 @@ "permissions": [ "storage", "clipboardWrite", - "http://localhost:8545/" + "http://localhost:8545/", + "https://www.cryptonator.com/" ], "web_accessible_resources": [ "scripts/inpage.js" -- cgit From ff49e5e5cf3aadf63dbdf6570407c23e1ae6cdb9 Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 29 Mar 2017 23:21:31 -0700 Subject: tx-utils - gas buffer ceiling at 90% of block gas limit --- app/scripts/lib/tx-utils.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 72df53631..e8e23f8b5 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -63,14 +63,15 @@ module.exports = class txProviderUtils { addGasBuffer (initialGasLimitHex, blockGasLimitHex) { const initialGasLimitBn = hexToBn(initialGasLimitHex) const blockGasLimitBn = hexToBn(blockGasLimitHex) + const upperGasLimitBn = blockGasLimitBn.muln(0.9) const bufferedGasLimitBn = initialGasLimitBn.muln(1.5) // if initialGasLimit is above blockGasLimit, dont modify it - if (initialGasLimitBn.gt(blockGasLimitBn)) return bnToHex(initialGasLimitBn) + if (initialGasLimitBn.gt(upperGasLimitBn)) return bnToHex(initialGasLimitBn) // if bufferedGasLimit is below blockGasLimit, use bufferedGasLimit - if (bufferedGasLimitBn.lt(blockGasLimitBn)) return bnToHex(bufferedGasLimitBn) + if (bufferedGasLimitBn.lt(upperGasLimitBn)) return bnToHex(bufferedGasLimitBn) // otherwise use blockGasLimit - return bnToHex(blockGasLimitBn) + return bnToHex(upperGasLimitBn) } fillInTxParams (txParams, cb) { -- cgit From 29a602a89b176e7af3f15297c2f586a4ece0a726 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 30 Mar 2017 11:28:22 -0700 Subject: Clean up --- app/scripts/controllers/preferences.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index dbd5aeaaa..c7f675a41 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -24,7 +24,6 @@ class PreferencesController { } getSelectedAddress (_address) { - console.log('PREFERNCES: getSelectedAddress was called') return this.store.getState().selectedAddress } -- cgit From 1dce352523a1f79f052ef79c707d9bc44787b706 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 30 Mar 2017 14:23:23 -0700 Subject: tx-manager - add eip155 support --- app/scripts/transaction-manager.js | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index a70159680..d7051b2cb 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -205,11 +205,23 @@ module.exports = class TransactionManager extends EventEmitter { }) } + getChainId() { + const networkState = this.networkStore.getState() + const getChainId = parseInt(networkState.network) + if (Number.isNaN(getChainId)) { + return 0 + } else { + return getChainId + } + } + signTransaction (txId, cb) { - let txMeta = this.getTx(txId) - let txParams = txMeta.txParams - let fromAddress = txParams.from - let ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) + const txMeta = this.getTx(txId) + const txParams = txMeta.txParams + const fromAddress = txParams.from + // add network/chain id + txParams.chainId = this.getChainId() + const ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) this.signEthTx(ethTx, fromAddress).then(() => { this.setTxStatusSigned(txMeta.id) cb(null, ethUtil.bufferToHex(ethTx.serialize())) -- cgit From be88c87b2560f0ae2afd668d9c10cadde0a4ebc3 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 30 Mar 2017 18:30:24 -0700 Subject: extension - prefer extensionizer module --- app/scripts/contentscript.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 9a390e580..4d7e682d3 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -2,7 +2,7 @@ const LocalMessageDuplexStream = require('post-message-stream') const PongStream = require('ping-pong-stream/pong') const PortStream = require('./lib/port-stream.js') const ObjectMultiplex = require('./lib/obj-multiplex') -const extension = require('./lib/extension') +const extension = require('extensionizer') const fs = require('fs') const path = require('path') -- cgit From 5036263f88a1f61957982b64d27472a516c28def Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 30 Mar 2017 18:33:19 -0700 Subject: introduce platform api and rename notifications to notification-manager --- app/scripts/background.js | 13 ++++-- app/scripts/lib/notification-manager.js | 74 +++++++++++++++++++++++++++++++++ app/scripts/lib/notifications.js | 67 ----------------------------- app/scripts/metamask-controller.js | 14 ++++--- app/scripts/platforms/extension.js | 19 +++++++++ app/scripts/popup.js | 8 ++-- 6 files changed, 116 insertions(+), 79 deletions(-) create mode 100644 app/scripts/lib/notification-manager.js delete mode 100644 app/scripts/lib/notifications.js create mode 100644 app/scripts/platforms/extension.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 254737dec..5fb56d497 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -4,12 +4,13 @@ const asyncQ = require('async-q') const pipe = require('pump') const LocalStorageStore = require('obs-store/lib/localStorage') const storeTransform = require('obs-store/lib/transform') +const ExtensionPlatform = require('./platforms/extension') const Migrator = require('./lib/migrator/') const migrations = require('./migrations/') const PortStream = require('./lib/port-stream.js') -const notification = require('./lib/notifications.js') +const NotificationManager = require('./lib/notification-manager.js') const MetamaskController = require('./metamask-controller') -const extension = require('./lib/extension') +const extension = require('extensionizer') const firstTimeState = require('./first-time-state') const STORAGE_KEY = 'metamask-config' @@ -19,6 +20,10 @@ const log = require('loglevel') window.log = log log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn') +const platform = new ExtensionPlatform() +const notificationManager = new NotificationManager() +global.METAMASK_NOTIFIER = notificationManager + let popupIsOpen = false // state persistence @@ -68,6 +73,8 @@ function setupController (initState) { showUnapprovedTx: triggerUi, // initial state initState, + // platform specific api + platform, }) global.metamaskController = controller @@ -140,7 +147,7 @@ function setupController (initState) { // popup trigger function triggerUi () { - if (!popupIsOpen) notification.show() + if (!popupIsOpen) notificationManager.show() } // On first install, open a window to MetaMask website to how-it-works. diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js new file mode 100644 index 000000000..ff8a4b2e5 --- /dev/null +++ b/app/scripts/lib/notification-manager.js @@ -0,0 +1,74 @@ +const extension = require('extensionizer') +const height = 520 +const width = 360 + + +class NotificationManager { + + // + // Public + // + + show () { + this.getPopup((err, popup) => { + if (err) throw err + + if (popup) { + // bring focus to existing popup + extension.windows.update(popup.id, { focused: true }) + } else { + // create new popup + extension.windows.create({ + url: 'notification.html', + type: 'popup', + width, + height, + }) + .catch((reason) => { + log.error('failed to create poupup', reason) + }) + } + }) + } + + getPopup (cb) { + this._getWindows((err, windows) => { + if (err) throw err + cb(null, this._getPopupIn(windows)) + }) + } + + closePopup () { + this.getPopup((err, popup) => { + if (err) throw err + if (!popup) return + extension.windows.remove(popup.id, console.error) + }) + } + + // + // Private + // + + _getWindows (cb) { + // Ignore in test environment + if (!extension.windows) { + return cb() + } + + extension.windows.getAll({}, (windows) => { + cb(null, windows) + }) + } + + _getPopupIn (windows) { + return windows ? windows.find((win) => { + return (win && win.type === 'popup' && + win.height === height && + win.width === width) + }) : null + } + +} + +module.exports = NotificationManager \ No newline at end of file diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js deleted file mode 100644 index 0ec01f3a7..000000000 --- a/app/scripts/lib/notifications.js +++ /dev/null @@ -1,67 +0,0 @@ -const extension = require('./extension') -const height = 520 -const width = 360 - -const notifications = { - show, - getPopup, - closePopup, -} -module.exports = notifications -window.METAMASK_NOTIFIER = notifications - -function show () { - getPopup((err, popup) => { - if (err) throw err - - if (popup) { - // bring focus to existing popup - extension.windows.update(popup.id, { focused: true }) - } else { - // create new popup - extension.windows.create({ - url: 'notification.html', - type: 'popup', - width, - height, - }) - .catch((reason) => { - log.error('failed to create poupup', reason) - }) - } - }) -} - -function getWindows (cb) { - // Ignore in test environment - if (!extension.windows) { - return cb() - } - - extension.windows.getAll({}, (windows) => { - cb(null, windows) - }) -} - -function getPopup (cb) { - getWindows((err, windows) => { - if (err) throw err - cb(null, getPopupIn(windows)) - }) -} - -function getPopupIn (windows) { - return windows ? windows.find((win) => { - return (win && win.type === 'popup' && - win.height === height && - win.width === width) - }) : null -} - -function closePopup () { - getPopup((err, popup) => { - if (err) throw err - if (!popup) return - extension.windows.remove(popup.id, console.error) - }) -} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 03ea104e0..af8b4688d 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -20,7 +20,6 @@ const MessageManager = require('./lib/message-manager') const PersonalMessageManager = require('./lib/personal-message-manager') const TxManager = require('./transaction-manager') const ConfigManager = require('./lib/config-manager') -const extension = require('./lib/extension') const autoFaucet = require('./lib/auto-faucet') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') @@ -34,6 +33,9 @@ module.exports = class MetamaskController extends EventEmitter { this.opts = opts let initState = opts.initState || {} + // platform-specific api + this.platform = opts.platform + // observable state store this.store = new ObservableStore(initState) @@ -629,7 +631,7 @@ module.exports = class MetamaskController extends EventEmitter { break } - if (url) extension.tabs.create({ url }) + if (url) this.platform.openWindow({ url }) } createShapeShiftTx (depositAddress, depositType) { @@ -647,7 +649,7 @@ module.exports = class MetamaskController extends EventEmitter { setDefaultRpc () { this.configManager.setRpcTarget('http://localhost:8545') - extension.runtime.reload() + this.platform.reload() this.lookupNetwork() return Promise.resolve('http://localhost:8545') } @@ -656,7 +658,7 @@ module.exports = class MetamaskController extends EventEmitter { this.configManager.setRpcTarget(rpcTarget) return this.preferencesController.updateFrequentRpcList(rpcTarget) .then(() => { - extension.runtime.reload() + this.platform.reload() this.lookupNetwork() return Promise.resolve(rpcTarget) }) @@ -664,13 +666,13 @@ module.exports = class MetamaskController extends EventEmitter { setProviderType (type) { this.configManager.setProviderType(type) - extension.runtime.reload() + this.platform.reload() this.lookupNetwork() } useEtherscanProvider () { this.configManager.useEtherscanProvider() - extension.runtime.reload() + this.platform.reload() } getNetworkState () { diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js new file mode 100644 index 000000000..cbb35768e --- /dev/null +++ b/app/scripts/platforms/extension.js @@ -0,0 +1,19 @@ +const extension = require('extensionizer') + +class ExtensionPlatform { + + // + // Public + // + + reload () { + extension.runtime.reload() + } + + openWindow ({ url }) { + extension.tabs.create({ url }) + } + +} + +module.exports = ExtensionPlatform diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 62db68c10..6606c9584 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -3,8 +3,10 @@ const MetaMaskUiCss = require('../../ui/css') const startPopup = require('./popup-core') const PortStream = require('./lib/port-stream.js') const isPopupOrNotification = require('./lib/is-popup-or-notification') -const extension = require('./lib/extension') -const notification = require('./lib/notifications') +const extension = require('extensionizer') +const NotificationManager = require('./lib/notification-manager') + +const notificationManager = new NotificationManager() var css = MetaMaskUiCss() injectCss(css) @@ -20,6 +22,6 @@ startPopup(portStream) function closePopupIfOpen (name) { if (name !== 'notification') { - notification.closePopup() + notificationManager.closePopup() } } -- cgit From 6259ffaef4f2045d2de069ea83de47b64b5fba86 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 30 Mar 2017 18:35:22 -0700 Subject: extension - remove local extension files, we use extensionizer --- app/scripts/lib/extension-instance.js | 68 ----------------------------------- app/scripts/lib/extension.js | 17 --------- 2 files changed, 85 deletions(-) delete mode 100644 app/scripts/lib/extension-instance.js delete mode 100644 app/scripts/lib/extension.js (limited to 'app') diff --git a/app/scripts/lib/extension-instance.js b/app/scripts/lib/extension-instance.js deleted file mode 100644 index 628b62e3f..000000000 --- a/app/scripts/lib/extension-instance.js +++ /dev/null @@ -1,68 +0,0 @@ -const apis = [ - 'alarms', - 'bookmarks', - 'browserAction', - 'commands', - 'contextMenus', - 'cookies', - 'downloads', - 'events', - 'extension', - 'extensionTypes', - 'history', - 'i18n', - 'idle', - 'notifications', - 'pageAction', - 'runtime', - 'storage', - 'tabs', - 'webNavigation', - 'webRequest', - 'windows', -] - -function Extension () { - const _this = this - - apis.forEach(function (api) { - - _this[api] = null - - try { - if (chrome[api]) { - _this[api] = chrome[api] - } - } catch (e) {} - - try { - if (window[api]) { - _this[api] = window[api] - } - } catch (e) {} - - try { - if (browser[api]) { - _this[api] = browser[api] - } - } catch (e) {} - try { - _this.api = browser.extension[api] - } catch (e) {} - }) - - try { - if (browser && browser.runtime) { - this.runtime = browser.runtime - } - } catch (e) {} - - try { - if (browser && browser.browserAction) { - this.browserAction = browser.browserAction - } - } catch (e) {} - -} - -module.exports = Extension diff --git a/app/scripts/lib/extension.js b/app/scripts/lib/extension.js deleted file mode 100644 index 6f8b5d800..000000000 --- a/app/scripts/lib/extension.js +++ /dev/null @@ -1,17 +0,0 @@ -/* Extension.js - * - * A module for unifying browser differences in the WebExtension API. - * - * Initially implemented because Chrome hides all of their WebExtension API - * behind a global `chrome` variable, but we'd like to start grooming - * the code-base for cross-browser extension support. - * - * You can read more about the WebExtension API here: - * https://developer.mozilla.org/en-US/Add-ons/WebExtensions - */ - -const Extension = require('./extension-instance') -const instance = new Extension() -window.METAMASK_EXTENSION = instance -module.exports = instance - -- cgit From 49d8877fd78b8251b6856292ca71a55773a74b0e Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 31 Mar 2017 13:20:16 -0700 Subject: ui - startPopup returns store after boot --- app/scripts/popup-core.js | 27 ++++++++------------------- app/scripts/popup.js | 34 ++++++++++++++++++++++++---------- 2 files changed, 32 insertions(+), 29 deletions(-) (limited to 'app') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index b1e521a7a..1e5d70e8b 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -1,7 +1,8 @@ const EventEmitter = require('events').EventEmitter +const async = require('async') const Dnode = require('dnode') const Web3 = require('web3') -const MetaMaskUi = require('../../ui') +const launchMetamaskUi = require('../../ui') const StreamProvider = require('web3-stream-provider') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex @@ -9,9 +10,13 @@ const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex module.exports = initializePopup -function initializePopup (connectionStream) { +function initializePopup ({ container, connectionStream }, cb) { // setup app - connectToAccountManager(connectionStream, setupApp) + async.waterfall([ + (cb) => connectToAccountManager(connectionStream, cb), + (accountManager, cb) => launchMetamaskUi({ container, accountManager }, cb), + ], cb) + } function connectToAccountManager (connectionStream, cb) { @@ -47,19 +52,3 @@ function setupControllerConnection (connectionStream, cb) { cb(null, accountManager) }) } - -function setupApp (err, accountManager) { - var container = document.getElementById('app-content') - if (err) { - container.innerHTML = '
The MetaMask app failed to load: please open and close MetaMask again to restart.
' - container.style.height = '80px' - log.error(err.stack) - throw err - } - - - MetaMaskUi({ - container: container, - accountManager: accountManager, - }) -} diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 6606c9584..f6dcb829b 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -5,23 +5,37 @@ const PortStream = require('./lib/port-stream.js') const isPopupOrNotification = require('./lib/is-popup-or-notification') const extension = require('extensionizer') const NotificationManager = require('./lib/notification-manager') - const notificationManager = new NotificationManager() -var css = MetaMaskUiCss() +// inject css +const css = MetaMaskUiCss() injectCss(css) -var name = isPopupOrNotification() -closePopupIfOpen(name) -window.METAMASK_UI_TYPE = name +// identify window type (popup, notification) +const windowType = isPopupOrNotification() +global.METAMASK_UI_TYPE = windowType +closePopupIfOpen(windowType) + +// setup stream to background +const extensionPort = extension.runtime.connect({ windowType }) +const connectionStream = new PortStream(extensionPort) -var pluginPort = extension.runtime.connect({ name }) -var portStream = new PortStream(pluginPort) +// start ui +const container = document.getElementById('app-content') +startPopup({ container, connectionStream }, (err, store) => { + if (err) return displayCriticalError(err) +}) -startPopup(portStream) -function closePopupIfOpen (name) { - if (name !== 'notification') { +function closePopupIfOpen (windowType) { + if (windowType !== 'notification') { notificationManager.closePopup() } } + +function displayCriticalError(err) { + container.innerHTML = '
The MetaMask app failed to load: please open and close MetaMask again to restart.
' + container.style.height = '80px' + log.error(err.stack) + throw err +} -- cgit From 60a48e713fb341c0eba893bd0c37e02315c8b320 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 31 Mar 2017 13:32:47 -0700 Subject: ui - move popup auto-close after tx conf to ui entrypoint --- app/scripts/popup.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/popup.js b/app/scripts/popup.js index f6dcb829b..ce18dc422 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -17,13 +17,17 @@ global.METAMASK_UI_TYPE = windowType closePopupIfOpen(windowType) // setup stream to background -const extensionPort = extension.runtime.connect({ windowType }) +const extensionPort = extension.runtime.connect({ name: windowType }) const connectionStream = new PortStream(extensionPort) // start ui const container = document.getElementById('app-content') startPopup({ container, connectionStream }, (err, store) => { if (err) return displayCriticalError(err) + store.subscribe(() => { + const state = store.getState() + if (state.appState.shouldClose) notificationManager.closePopup() + }) }) -- cgit From aa06183c64b79316a4622e25791c29e785c7bce0 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 31 Mar 2017 18:04:13 -0700 Subject: ui - use global.platform for extension interaction --- app/scripts/platforms/extension.js | 4 ++++ app/scripts/popup.js | 4 ++++ 2 files changed, 8 insertions(+) (limited to 'app') diff --git a/app/scripts/platforms/extension.js b/app/scripts/platforms/extension.js index cbb35768e..00c2aa275 100644 --- a/app/scripts/platforms/extension.js +++ b/app/scripts/platforms/extension.js @@ -14,6 +14,10 @@ class ExtensionPlatform { extension.tabs.create({ url }) } + getVersion () { + return extension.runtime.getManifest().version + } + } module.exports = ExtensionPlatform diff --git a/app/scripts/popup.js b/app/scripts/popup.js index ce18dc422..0fbde54b3 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -4,9 +4,13 @@ const startPopup = require('./popup-core') const PortStream = require('./lib/port-stream.js') const isPopupOrNotification = require('./lib/is-popup-or-notification') const extension = require('extensionizer') +const ExtensionPlatform = require('./platforms/extension') const NotificationManager = require('./lib/notification-manager') const notificationManager = new NotificationManager() +// create platform global +global.platform = new ExtensionPlatform() + // inject css const css = MetaMaskUiCss() injectCss(css) -- cgit From 86e882c51afca3a44bf20bcd1025161e214e6998 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 31 Mar 2017 18:41:51 -0700 Subject: notification-manager - rename show -> showPoup + make getPopup private --- app/scripts/background.js | 2 +- app/scripts/lib/notification-manager.js | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 5fb56d497..7211f1e0c 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -147,7 +147,7 @@ function setupController (initState) { // popup trigger function triggerUi () { - if (!popupIsOpen) notificationManager.show() + if (!popupIsOpen) notificationManager.showPopup() } // On first install, open a window to MetaMask website to how-it-works. diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index ff8a4b2e5..55e5b8dd2 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -9,8 +9,8 @@ class NotificationManager { // Public // - show () { - this.getPopup((err, popup) => { + showPopup () { + this._getPopup((err, popup) => { if (err) throw err if (popup) { @@ -31,15 +31,8 @@ class NotificationManager { }) } - getPopup (cb) { - this._getWindows((err, windows) => { - if (err) throw err - cb(null, this._getPopupIn(windows)) - }) - } - closePopup () { - this.getPopup((err, popup) => { + this._getPopup((err, popup) => { if (err) throw err if (!popup) return extension.windows.remove(popup.id, console.error) @@ -50,6 +43,13 @@ class NotificationManager { // Private // + _getPopup (cb) { + this._getWindows((err, windows) => { + if (err) throw err + cb(null, this._getPopupIn(windows)) + }) + } + _getWindows (cb) { // Ignore in test environment if (!extension.windows) { -- cgit From f80d1ce3e61fec8948d418a470c00226773b3b38 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 4 Apr 2017 14:55:48 +0200 Subject: Switch auto-faucet from XMLHttpRequest to fetch --- app/scripts/lib/auto-faucet.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/auto-faucet.js b/app/scripts/lib/auto-faucet.js index 1e86f735e..73b73dfe6 100644 --- a/app/scripts/lib/auto-faucet.js +++ b/app/scripts/lib/auto-faucet.js @@ -4,9 +4,15 @@ const env = process.env.METAMASK_ENV module.exports = function (address) { if (METAMASK_DEBUG || env === 'test') return // Don't faucet in development or test - var http = new XMLHttpRequest() - var data = address - http.open('POST', uri, true) - http.setRequestHeader('Content-type', 'application/rawdata') - http.send(data) + let data = address + let headers = new Headers() + headers.append('Content-type', 'application/rawdata') + fetch(uri, { + method: 'POST', + headers, + body: data, + }) + .catch((err) => { + console.error(err) + }) } -- cgit From 0a7b388b39d86039e4e4cf5df8dfe5104e7b6137 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 4 Apr 2017 18:38:56 +0200 Subject: Fix faucet to only autoFaucet first account --- app/scripts/keyring-controller.js | 1 + app/scripts/metamask-controller.js | 2 ++ 2 files changed, 3 insertions(+) (limited to 'app') diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 72f613641..16df6efa6 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -324,6 +324,7 @@ class KeyringController extends EventEmitter { if (!firstAccount) throw new Error('KeyringController - No account found on keychain.') const hexAccount = normalizeAddress(firstAccount) this.emit('newAccount', hexAccount) + this.emit('newVault', hexAccount) return this.setupAccounts(accounts) }) .then(this.persistAllKeyrings.bind(this)) diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index af8b4688d..5f71fc369 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -79,6 +79,8 @@ module.exports = class MetamaskController extends EventEmitter { }) this.keyringController.on('newAccount', (address) => { this.preferencesController.setSelectedAddress(address) + }) + this.keyringController.on('newVault', (address) => { autoFaucet(address) }) -- cgit From 4779999bfc7e03eedf3fd2702f7f448d751218f8 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 4 Apr 2017 11:13:07 -0700 Subject: clean - metamask controller - remove log --- app/scripts/metamask-controller.js | 1 - 1 file changed, 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index d360e7d95..040c093df 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -167,7 +167,6 @@ module.exports = class MetamaskController extends EventEmitter { rpcUrl: this.configManager.getCurrentRpcAddress(), // account mgmt getAccounts: (cb) => { - console.log('METAMASK CONTROLLER: getAccounts was called') let selectedAddress = this.preferencesController.getSelectedAddress() let result = selectedAddress ? [selectedAddress] : [] cb(null, result) -- cgit From 5a91adf7d802097805938e3d54fe7256b19724d1 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 4 Apr 2017 18:23:46 -0700 Subject: add platforms to mascara + move buyEther window open to ui --- app/scripts/lib/auto-faucet.js | 8 +++++--- app/scripts/lib/buy-eth-url.js | 19 +++++++++++++++++++ app/scripts/metamask-controller.js | 19 ++----------------- app/scripts/platforms/sw.js | 24 ++++++++++++++++++++++++ app/scripts/platforms/window.js | 22 ++++++++++++++++++++++ 5 files changed, 72 insertions(+), 20 deletions(-) create mode 100644 app/scripts/lib/buy-eth-url.js create mode 100644 app/scripts/platforms/sw.js create mode 100644 app/scripts/platforms/window.js (limited to 'app') diff --git a/app/scripts/lib/auto-faucet.js b/app/scripts/lib/auto-faucet.js index 73b73dfe6..1e059cf73 100644 --- a/app/scripts/lib/auto-faucet.js +++ b/app/scripts/lib/auto-faucet.js @@ -3,9 +3,11 @@ const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' const env = process.env.METAMASK_ENV module.exports = function (address) { - if (METAMASK_DEBUG || env === 'test') return // Don't faucet in development or test - let data = address - let headers = new Headers() + // Don't faucet in development or test + if (METAMASK_DEBUG || env === 'test') return + global.log.info('auto-fauceting:', address) + const data = address + const headers = new Headers() headers.append('Content-type', 'application/rawdata') fetch(uri, { method: 'POST', diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js new file mode 100644 index 000000000..91a1ec322 --- /dev/null +++ b/app/scripts/lib/buy-eth-url.js @@ -0,0 +1,19 @@ +module.exports = getBuyEthUrl + +function getBuyEthUrl({ network, amount, address }){ + let url + switch (network) { + case '1': + url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH` + break + + case '3': + url = 'https://faucet.metamask.io/' + break + + case '42': + url = 'https://github.com/kovan-testnet/faucet' + break + } + return url +} \ No newline at end of file diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index edb9bbbd9..2b8fc9cb8 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -23,6 +23,7 @@ const ConfigManager = require('./lib/config-manager') const autoFaucet = require('./lib/auto-faucet') const nodeify = require('./lib/nodeify') const accountImporter = require('./account-import-strategies') +const getBuyEthUrl = require('./lib/buy-eth-url') const version = require('../manifest.json').version @@ -614,24 +615,8 @@ module.exports = class MetamaskController extends EventEmitter { buyEth (address, amount) { if (!amount) amount = '5' - const network = this.getNetworkState() - let url - - switch (network) { - case '1': - url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH` - break - - case '3': - url = 'https://faucet.metamask.io/' - break - - case '42': - url = 'https://github.com/kovan-testnet/faucet' - break - } - + const url = getBuyEthUrl({ network, address, amount }) if (url) this.platform.openWindow({ url }) } diff --git a/app/scripts/platforms/sw.js b/app/scripts/platforms/sw.js new file mode 100644 index 000000000..007d8dc5b --- /dev/null +++ b/app/scripts/platforms/sw.js @@ -0,0 +1,24 @@ + +class SwPlatform { + + // + // Public + // + + reload () { + // you cant actually do this + global.location.reload() + } + + openWindow ({ url }) { + // this doesnt actually work + global.open(url, '_blank') + } + + getVersion () { + return '' + } + +} + +module.exports = SwPlatform diff --git a/app/scripts/platforms/window.js b/app/scripts/platforms/window.js new file mode 100644 index 000000000..1527c008b --- /dev/null +++ b/app/scripts/platforms/window.js @@ -0,0 +1,22 @@ + +class WindowPlatform { + + // + // Public + // + + reload () { + global.location.reload() + } + + openWindow ({ url }) { + global.open(url, '_blank') + } + + getVersion () { + return '' + } + +} + +module.exports = WindowPlatform -- cgit From 9b9570fd2be5a7bdaf37a663628147976d8c94b4 Mon Sep 17 00:00:00 2001 From: kumavis Date: Tue, 4 Apr 2017 18:48:33 -0700 Subject: auto-faucet - only skip faucet on explicit test environment --- app/scripts/lib/auto-faucet.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/auto-faucet.js b/app/scripts/lib/auto-faucet.js index 1e059cf73..38d54ba5e 100644 --- a/app/scripts/lib/auto-faucet.js +++ b/app/scripts/lib/auto-faucet.js @@ -4,7 +4,7 @@ const env = process.env.METAMASK_ENV module.exports = function (address) { // Don't faucet in development or test - if (METAMASK_DEBUG || env === 'test') return + if (METAMASK_DEBUG === true || env === 'test') return global.log.info('auto-fauceting:', address) const data = address const headers = new Headers() -- cgit From c3746e62ec50de87a85bd2af0bfaf66fb19fbc1b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 24 Apr 2017 13:58:46 -0700 Subject: Version 3.5.3 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a3242149b..aeb47dfe3 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.5.2", + "version": "3.5.3", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From f1beb0720a0964e45a71b473f173f62c6abdac6e Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 25 Apr 2017 10:55:00 -0700 Subject: Version 3.5.4 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index aeb47dfe3..6ef428d2c 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.5.3", + "version": "3.5.4", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From e9aa37b699a105019384cbde88a114965ff1e2cd Mon Sep 17 00:00:00 2001 From: Nickyg Date: Wed, 26 Apr 2017 01:40:33 +0530 Subject: add rinkeby network --- app/scripts/config.js | 2 ++ app/scripts/lib/config-manager.js | 5 +++++ 2 files changed, 7 insertions(+) (limited to 'app') diff --git a/app/scripts/config.js b/app/scripts/config.js index ec421744d..4f62268e1 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -1,6 +1,7 @@ const MAINET_RPC_URL = 'https://mainnet.infura.io/metamask' const TESTNET_RPC_URL = 'https://ropsten.infura.io/metamask' const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask' +const RINKEBY_RPC_URL = 'https://rinkeby.infura.io' const DEFAULT_RPC_URL = TESTNET_RPC_URL global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -12,5 +13,6 @@ module.exports = { testnet: TESTNET_RPC_URL, morden: TESTNET_RPC_URL, kovan: KOVAN_RPC_URL, + rinkeby: RINKEBY_RPC_URL, }, } diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index e31cb45ed..340ad4292 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -6,6 +6,8 @@ const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet const MORDEN_RPC = MetamaskConfig.network.morden const KOVAN_RPC = MetamaskConfig.network.kovan +const RINKEBY_RPC = MetamaskConfig.network.rinkeby + /* The config-manager is a convenience object * wrapping a pojo-migrator. @@ -153,6 +155,9 @@ ConfigManager.prototype.getCurrentRpcAddress = function () { case 'kovan': return KOVAN_RPC + + case 'rinkeby': + return RINKEBY_RPC default: return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC -- cgit From 242dc1e99f1dd53e2bec9deefb5da0c8329b5f00 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Tue, 25 Apr 2017 14:39:01 -0700 Subject: Add missing changes. Create unique style for rinkeby icon. --- app/scripts/config.js | 2 +- app/scripts/lib/buy-eth-url.js | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/config.js b/app/scripts/config.js index 4f62268e1..391c67230 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -1,7 +1,7 @@ const MAINET_RPC_URL = 'https://mainnet.infura.io/metamask' const TESTNET_RPC_URL = 'https://ropsten.infura.io/metamask' const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask' -const RINKEBY_RPC_URL = 'https://rinkeby.infura.io' +const RINKEBY_RPC_URL = 'https://rinkeby.infura.io/metamask' const DEFAULT_RPC_URL = TESTNET_RPC_URL global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 91a1ec322..957a00211 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -11,9 +11,13 @@ function getBuyEthUrl({ network, amount, address }){ url = 'https://faucet.metamask.io/' break + case '4': + url = 'https://www.rinkeby.io/' + break + case '42': url = 'https://github.com/kovan-testnet/faucet' break } return url -} \ No newline at end of file +} -- cgit From 6bdb4c87288a522d9ea2e984bc1f6436d6c7369a Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Wed, 26 Apr 2017 21:05:45 -0700 Subject: Fix linting warnings --- app/scripts/account-import-strategies/index.js | 2 +- app/scripts/background.js | 12 ++-- app/scripts/contentscript.js | 2 +- app/scripts/controllers/address-book.js | 8 +-- app/scripts/controllers/currency.js | 8 ++- app/scripts/controllers/preferences.js | 8 +-- app/scripts/first-time-state.js | 2 +- app/scripts/keyring-controller.js | 4 +- app/scripts/lib/buy-eth-url.js | 4 +- app/scripts/lib/eth-store.js | 2 +- app/scripts/lib/inpage-provider.js | 4 +- app/scripts/lib/message-manager.js | 4 +- app/scripts/lib/migrator/index.js | 12 ++-- app/scripts/lib/notification-manager.js | 2 +- app/scripts/lib/personal-message-manager.js | 4 +- app/scripts/lib/tx-utils.js | 12 ++-- app/scripts/metamask-controller.js | 77 +++++++++++++------------- app/scripts/migrations/002.js | 2 +- app/scripts/migrations/003.js | 2 +- app/scripts/migrations/004.js | 2 +- app/scripts/migrations/005.js | 2 +- app/scripts/migrations/006.js | 2 +- app/scripts/migrations/007.js | 2 +- app/scripts/migrations/008.js | 2 +- app/scripts/migrations/009.js | 2 +- app/scripts/migrations/010.js | 2 +- app/scripts/migrations/011.js | 2 +- app/scripts/migrations/012.js | 2 +- app/scripts/migrations/_multi-keyring.js | 11 ++-- app/scripts/popup-core.js | 1 - app/scripts/popup.js | 2 +- app/scripts/transaction-manager.js | 28 +++++----- 32 files changed, 112 insertions(+), 119 deletions(-) (limited to 'app') diff --git a/app/scripts/account-import-strategies/index.js b/app/scripts/account-import-strategies/index.js index d5124eb7f..96e2b5912 100644 --- a/app/scripts/account-import-strategies/index.js +++ b/app/scripts/account-import-strategies/index.js @@ -4,7 +4,7 @@ const ethUtil = require('ethereumjs-util') const accountImporter = { - importAccount(strategy, args) { + importAccount (strategy, args) { try { const importer = this.strategies[strategy] const privateKeyHex = importer.apply(null, args) diff --git a/app/scripts/background.js b/app/scripts/background.js index 7211f1e0c..58f8e7556 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -41,10 +41,10 @@ asyncQ.waterfall([ // State and Persistence // -function loadStateFromPersistence() { +function loadStateFromPersistence () { // migrations - let migrator = new Migrator({ migrations }) - let initialState = migrator.generateInitialState(firstTimeState) + const migrator = new Migrator({ migrations }) + const initialState = migrator.generateInitialState(firstTimeState) return asyncQ.waterfall([ // read from disk () => Promise.resolve(diskStore.getState() || initialState), @@ -61,7 +61,6 @@ function loadStateFromPersistence() { } function setupController (initState) { - // // MetaMask Controller // @@ -85,8 +84,8 @@ function setupController (initState) { diskStore ) - function versionifyData(state) { - let versionedData = diskStore.getState() + function versionifyData (state) { + const versionedData = diskStore.getState() versionedData.data = state return versionedData } @@ -138,7 +137,6 @@ function setupController (initState) { } return Promise.resolve() - } // diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 4d7e682d3..f7237b32e 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -77,7 +77,7 @@ function doctypeCheck () { } } -function suffixCheck() { +function suffixCheck () { var prohibitedTypes = ['xml', 'pdf'] var currentUrl = window.location.href var currentRegex diff --git a/app/scripts/controllers/address-book.js b/app/scripts/controllers/address-book.js index c66eb2bd4..6fb4ee114 100644 --- a/app/scripts/controllers/address-book.js +++ b/app/scripts/controllers/address-book.js @@ -39,11 +39,11 @@ class AddressBookController { // pushed object is an object of two fields. Current behavior does not set an // upper limit to the number of addresses. _addToAddressBook (address, name) { - let addressBook = this._getAddressBook() - let identities = this._getIdentities() + const addressBook = this._getAddressBook() + const identities = this._getIdentities() - let addressBookIndex = addressBook.findIndex((element) => { return element.address.toLowerCase() === address.toLowerCase() || element.name === name }) - let identitiesIndex = Object.keys(identities).findIndex((element) => { return element.toLowerCase() === address.toLowerCase() }) + const addressBookIndex = addressBook.findIndex((element) => { return element.address.toLowerCase() === address.toLowerCase() || element.name === name }) + const identitiesIndex = Object.keys(identities).findIndex((element) => { return element.toLowerCase() === address.toLowerCase() }) // trigger this condition if we own this address--no need to overwrite. if (identitiesIndex !== -1) { return Promise.resolve(addressBook) diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index c4904f8ac..fb130ed76 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -51,9 +51,11 @@ class CurrencyController { this.setConversionRate(Number(parsedResponse.ticker.price)) this.setConversionDate(Number(parsedResponse.timestamp)) }).catch((err) => { - console.warn('MetaMask - Failed to query currency conversion.') - this.setConversionRate(0) - this.setConversionDate('N/A') + if (err) { + console.warn('MetaMask - Failed to query currency conversion.') + this.setConversionRate(0) + this.setConversionDate('N/A') + } }) } diff --git a/app/scripts/controllers/preferences.js b/app/scripts/controllers/preferences.js index c7f675a41..7212c7c43 100644 --- a/app/scripts/controllers/preferences.js +++ b/app/scripts/controllers/preferences.js @@ -36,8 +36,8 @@ class PreferencesController { } addToFrequentRpcList (_url) { - let rpcList = this.getFrequentRpcList() - let index = rpcList.findIndex((element) => { return element === _url }) + const rpcList = this.getFrequentRpcList() + const index = rpcList.findIndex((element) => { return element === _url }) if (index !== -1) { rpcList.splice(index, 1) } @@ -53,13 +53,9 @@ class PreferencesController { getFrequentRpcList () { return this.store.getState().frequentRpcList } - // // PRIVATE METHODS // - - - } module.exports = PreferencesController diff --git a/app/scripts/first-time-state.js b/app/scripts/first-time-state.js index 3196981ba..87a7bb7b5 100644 --- a/app/scripts/first-time-state.js +++ b/app/scripts/first-time-state.js @@ -8,4 +8,4 @@ module.exports = { type: 'testnet', }, }, -} \ No newline at end of file +} diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 16df6efa6..5b3c80e40 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -187,7 +187,7 @@ class KeyringController extends EventEmitter { .then((accounts) => { switch (type) { case 'Simple Key Pair': - let isNotIncluded = !accounts.find((key) => key === newAccount[0] || key === ethUtil.stripHexPrefix(newAccount[0])) + const isNotIncluded = !accounts.find((key) => key === newAccount[0] || key === ethUtil.stripHexPrefix(newAccount[0])) return (isNotIncluded) ? Promise.resolve(newAccount) : Promise.reject(new Error('The account you\'re are trying to import is a duplicate')) default: return Promise.resolve(newAccount) @@ -582,7 +582,7 @@ class KeyringController extends EventEmitter { }) } - _updateMemStoreKeyrings() { + _updateMemStoreKeyrings () { Promise.all(this.keyrings.map(this.displayForKeyring)) .then((keyrings) => { this.memStore.updateState({ keyrings }) diff --git a/app/scripts/lib/buy-eth-url.js b/app/scripts/lib/buy-eth-url.js index 91a1ec322..30db78a6c 100644 --- a/app/scripts/lib/buy-eth-url.js +++ b/app/scripts/lib/buy-eth-url.js @@ -1,6 +1,6 @@ module.exports = getBuyEthUrl -function getBuyEthUrl({ network, amount, address }){ +function getBuyEthUrl ({ network, amount, address }) { let url switch (network) { case '1': @@ -16,4 +16,4 @@ function getBuyEthUrl({ network, amount, address }){ break } return url -} \ No newline at end of file +} diff --git a/app/scripts/lib/eth-store.js b/app/scripts/lib/eth-store.js index 243253df2..6f04a9dd6 100644 --- a/app/scripts/lib/eth-store.js +++ b/app/scripts/lib/eth-store.js @@ -10,7 +10,7 @@ const async = require('async') const EthQuery = require('eth-query') const ObservableStore = require('obs-store') -function noop() {} +function noop () {} class EthereumStore extends ObservableStore { diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 92936de2f..e5e398e24 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -85,7 +85,7 @@ MetamaskInpageProvider.prototype.send = function (payload) { break case 'net_version': - let networkVersion = self.publicConfigStore.getState().networkVersion + const networkVersion = self.publicConfigStore.getState().networkVersion result = networkVersion break @@ -125,7 +125,7 @@ function eachJsonMessage (payload, transformFn) { } } -function logStreamDisconnectWarning(remoteLabel, err){ +function logStreamDisconnectWarning (remoteLabel, err) { let warningMsg = `MetamaskInpageProvider - lost connection to ${remoteLabel}` if (err) warningMsg += '\n' + err.stack console.warn(warningMsg) diff --git a/app/scripts/lib/message-manager.js b/app/scripts/lib/message-manager.js index 711d5f159..f52e048e0 100644 --- a/app/scripts/lib/message-manager.js +++ b/app/scripts/lib/message-manager.js @@ -4,7 +4,7 @@ const ethUtil = require('ethereumjs-util') const createId = require('./random-id') -module.exports = class MessageManager extends EventEmitter{ +module.exports = class MessageManager extends EventEmitter { constructor (opts) { super() this.memStore = new ObservableStore({ @@ -108,7 +108,7 @@ module.exports = class MessageManager extends EventEmitter{ } -function normalizeMsgData(data) { +function normalizeMsgData (data) { if (data.slice(0, 2) === '0x') { // data is already hex return data diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index 312345263..c40c347b5 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -3,17 +3,17 @@ const asyncQ = require('async-q') class Migrator { constructor (opts = {}) { - let migrations = opts.migrations || [] + const migrations = opts.migrations || [] this.migrations = migrations.sort((a, b) => a.version - b.version) - let lastMigration = this.migrations.slice(-1)[0] + const lastMigration = this.migrations.slice(-1)[0] // use specified defaultVersion or highest migration version this.defaultVersion = opts.defaultVersion || (lastMigration && lastMigration.version) || 0 } // run all pending migrations on meta in place migrateData (versionedData = this.generateInitialState()) { - let remaining = this.migrations.filter(migrationIsPending) - + const remaining = this.migrations.filter(migrationIsPending) + return ( asyncQ.eachSeries(remaining, (migration) => this.runMigration(versionedData, migration)) .then(() => versionedData) @@ -21,12 +21,12 @@ class Migrator { // migration is "pending" if hit has a higher // version number than currentVersion - function migrationIsPending(migration) { + function migrationIsPending (migration) { return migration.version > versionedData.meta.version } } - runMigration(versionedData, migration) { + runMigration (versionedData, migration) { return ( migration.migrate(versionedData) .then((versionedData) => { diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index 55e5b8dd2..799282f6d 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -71,4 +71,4 @@ class NotificationManager { } -module.exports = NotificationManager \ No newline at end of file +module.exports = NotificationManager diff --git a/app/scripts/lib/personal-message-manager.js b/app/scripts/lib/personal-message-manager.js index bbc978446..6602f5aa8 100644 --- a/app/scripts/lib/personal-message-manager.js +++ b/app/scripts/lib/personal-message-manager.js @@ -5,7 +5,7 @@ const createId = require('./random-id') const hexRe = /^[0-9A-Fa-f]+$/g -module.exports = class PersonalMessageManager extends EventEmitter{ +module.exports = class PersonalMessageManager extends EventEmitter { constructor (opts) { super() this.memStore = new ObservableStore({ @@ -108,7 +108,7 @@ module.exports = class PersonalMessageManager extends EventEmitter{ this.emit('updateBadge') } - normalizeMsgData(data) { + normalizeMsgData (data) { try { const stripped = ethUtil.stripHexPrefix(data) if (stripped.match(hexRe)) { diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index e8e23f8b5..084ca3721 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -75,14 +75,14 @@ module.exports = class txProviderUtils { } fillInTxParams (txParams, cb) { - let fromAddress = txParams.from - let reqs = {} + const fromAddress = txParams.from + const reqs = {} if (isUndef(txParams.gas)) reqs.gas = (cb) => this.query.estimateGas(txParams, cb) if (isUndef(txParams.gasPrice)) reqs.gasPrice = (cb) => this.query.gasPrice(cb) if (isUndef(txParams.nonce)) reqs.nonce = (cb) => this.query.getTransactionCount(fromAddress, 'pending', cb) - async.parallel(reqs, function(err, result) { + async.parallel(reqs, function (err, result) { if (err) return cb(err) // write results to txParams obj Object.assign(txParams, result) @@ -123,14 +123,14 @@ module.exports = class txProviderUtils { // util -function isUndef(value) { +function isUndef (value) { return value === undefined } -function bnToHex(inputBn) { +function bnToHex (inputBn) { return ethUtil.addHexPrefix(inputBn.toString(16)) } -function hexToBn(inputHex) { +function hexToBn (inputHex) { return new BN(ethUtil.stripHexPrefix(inputHex), 16) } diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 2b8fc9cb8..b91b5efe8 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -32,7 +32,7 @@ module.exports = class MetamaskController extends EventEmitter { constructor (opts) { super() this.opts = opts - let initState = opts.initState || {} + const initState = opts.initState || {} // platform-specific api this.platform = opts.platform @@ -161,8 +161,7 @@ module.exports = class MetamaskController extends EventEmitter { // initializeProvider () { - - let provider = MetaMaskProvider({ + const provider = MetaMaskProvider({ static: { eth_syncing: false, web3_clientVersion: `MetaMask/v${version}`, @@ -170,8 +169,8 @@ module.exports = class MetamaskController extends EventEmitter { rpcUrl: this.configManager.getCurrentRpcAddress(), // account mgmt getAccounts: (cb) => { - let selectedAddress = this.preferencesController.getSelectedAddress() - let result = selectedAddress ? [selectedAddress] : [] + const selectedAddress = this.preferencesController.getSelectedAddress() + const result = selectedAddress ? [selectedAddress] : [] cb(null, result) }, // tx signing @@ -196,7 +195,7 @@ module.exports = class MetamaskController extends EventEmitter { publicConfigStore ) - function selectPublicState(state) { + function selectPublicState (state) { const result = { selectedAddress: undefined } try { result.selectedAddress = state.PreferencesController.selectedAddress @@ -253,56 +252,56 @@ module.exports = class MetamaskController extends EventEmitter { return { // etc - getState: (cb) => cb(null, this.getState()), - setProviderType: this.setProviderType.bind(this), - useEtherscanProvider: this.useEtherscanProvider.bind(this), - setCurrentCurrency: this.setCurrentCurrency.bind(this), - markAccountsFound: this.markAccountsFound.bind(this), + getState: (cb) => cb(null, this.getState()), + setProviderType: this.setProviderType.bind(this), + useEtherscanProvider: this.useEtherscanProvider.bind(this), + setCurrentCurrency: this.setCurrentCurrency.bind(this), + markAccountsFound: this.markAccountsFound.bind(this), // coinbase buyEth: this.buyEth.bind(this), // shapeshift createShapeShiftTx: this.createShapeShiftTx.bind(this), // primary HD keyring management - addNewAccount: this.addNewAccount.bind(this), - placeSeedWords: this.placeSeedWords.bind(this), - clearSeedWordCache: this.clearSeedWordCache.bind(this), - importAccountWithStrategy: this.importAccountWithStrategy.bind(this), + addNewAccount: this.addNewAccount.bind(this), + placeSeedWords: this.placeSeedWords.bind(this), + clearSeedWordCache: this.clearSeedWordCache.bind(this), + importAccountWithStrategy: this.importAccountWithStrategy.bind(this), // vault management submitPassword: this.submitPassword.bind(this), // PreferencesController - setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController), - setDefaultRpc: nodeify(this.setDefaultRpc).bind(this), - setCustomRpc: nodeify(this.setCustomRpc).bind(this), + setSelectedAddress: nodeify(preferencesController.setSelectedAddress).bind(preferencesController), + setDefaultRpc: nodeify(this.setDefaultRpc).bind(this), + setCustomRpc: nodeify(this.setCustomRpc).bind(this), // AddressController - setAddressBook: nodeify(addressBookController.setAddressBook).bind(addressBookController), + setAddressBook: nodeify(addressBookController.setAddressBook).bind(addressBookController), // KeyringController - setLocked: nodeify(keyringController.setLocked).bind(keyringController), + setLocked: nodeify(keyringController.setLocked).bind(keyringController), createNewVaultAndKeychain: nodeify(keyringController.createNewVaultAndKeychain).bind(keyringController), - createNewVaultAndRestore: nodeify(keyringController.createNewVaultAndRestore).bind(keyringController), - addNewKeyring: nodeify(keyringController.addNewKeyring).bind(keyringController), - saveAccountLabel: nodeify(keyringController.saveAccountLabel).bind(keyringController), - exportAccount: nodeify(keyringController.exportAccount).bind(keyringController), + createNewVaultAndRestore: nodeify(keyringController.createNewVaultAndRestore).bind(keyringController), + addNewKeyring: nodeify(keyringController.addNewKeyring).bind(keyringController), + saveAccountLabel: nodeify(keyringController.saveAccountLabel).bind(keyringController), + exportAccount: nodeify(keyringController.exportAccount).bind(keyringController), // txManager - approveTransaction: txManager.approveTransaction.bind(txManager), - cancelTransaction: txManager.cancelTransaction.bind(txManager), + approveTransaction: txManager.approveTransaction.bind(txManager), + cancelTransaction: txManager.cancelTransaction.bind(txManager), updateAndApproveTransaction: this.updateAndApproveTx.bind(this), // messageManager - signMessage: nodeify(this.signMessage).bind(this), - cancelMessage: this.cancelMessage.bind(this), + signMessage: nodeify(this.signMessage).bind(this), + cancelMessage: this.cancelMessage.bind(this), // personalMessageManager - signPersonalMessage: nodeify(this.signPersonalMessage).bind(this), - cancelPersonalMessage: this.cancelPersonalMessage.bind(this), + signPersonalMessage: nodeify(this.signPersonalMessage).bind(this), + cancelPersonalMessage: this.cancelPersonalMessage.bind(this), // notices - checkNotices: noticeController.updateNoticesList.bind(noticeController), + checkNotices: noticeController.updateNoticesList.bind(noticeController), markNoticeRead: noticeController.markNoticeRead.bind(noticeController), } } @@ -441,7 +440,7 @@ module.exports = class MetamaskController extends EventEmitter { } newUnsignedMessage (msgParams, cb) { - let msgId = this.messageManager.addUnapprovedMessage(msgParams) + const msgId = this.messageManager.addUnapprovedMessage(msgParams) this.sendUpdate() this.opts.showUnconfirmedMessage() this.messageManager.once(`${msgId}:finished`, (data) => { @@ -461,7 +460,7 @@ module.exports = class MetamaskController extends EventEmitter { return cb(new Error('MetaMask Message Signature: from field is required.')) } - let msgId = this.personalMessageManager.addUnapprovedMessage(msgParams) + const msgId = this.personalMessageManager.addUnapprovedMessage(msgParams) this.sendUpdate() this.opts.showUnconfirmedMessage() this.personalMessageManager.once(`${msgId}:finished`, (data) => { @@ -476,7 +475,7 @@ module.exports = class MetamaskController extends EventEmitter { }) } - updateAndApproveTx(txMeta, cb) { + updateAndApproveTx (txMeta, cb) { log.debug(`MetaMaskController - updateAndApproveTx: ${JSON.stringify(txMeta)}`) const txManager = this.txManager txManager.updateTx(txMeta) @@ -502,7 +501,7 @@ module.exports = class MetamaskController extends EventEmitter { }) } - cancelMessage(msgId, cb) { + cancelMessage (msgId, cb) { const messageManager = this.messageManager messageManager.rejectMsg(msgId) if (cb && typeof cb === 'function') { @@ -512,7 +511,7 @@ module.exports = class MetamaskController extends EventEmitter { // Prefixed Style Message Signing Methods: approvePersonalMessage (msgParams, cb) { - let msgId = this.personalMessageManager.addUnapprovedMessage(msgParams) + const msgId = this.personalMessageManager.addUnapprovedMessage(msgParams) this.sendUpdate() this.opts.showUnconfirmedMessage() this.personalMessageManager.once(`${msgId}:finished`, (data) => { @@ -545,7 +544,7 @@ module.exports = class MetamaskController extends EventEmitter { }) } - cancelPersonalMessage(msgId, cb) { + cancelPersonalMessage (msgId, cb) { const messageManager = this.personalMessageManager messageManager.rejectMsg(msgId) if (cb && typeof cb === 'function') { @@ -559,13 +558,13 @@ module.exports = class MetamaskController extends EventEmitter { cb(null, this.getState()) } - restoreOldVaultAccounts(migratorOutput) { + restoreOldVaultAccounts (migratorOutput) { const { serialized } = migratorOutput return this.keyringController.restoreKeyring(serialized) .then(() => migratorOutput) } - restoreOldLostAccounts(migratorOutput) { + restoreOldLostAccounts (migratorOutput) { const { lostAccounts } = migratorOutput if (lostAccounts) { this.configManager.setLostAccounts(lostAccounts.map(acct => acct.address)) diff --git a/app/scripts/migrations/002.js b/app/scripts/migrations/002.js index 36a870342..b1d88f2ef 100644 --- a/app/scripts/migrations/002.js +++ b/app/scripts/migrations/002.js @@ -7,7 +7,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { if (versionedData.data.config.provider.type === 'etherscan') { diff --git a/app/scripts/migrations/003.js b/app/scripts/migrations/003.js index 1893576ad..140f81d40 100644 --- a/app/scripts/migrations/003.js +++ b/app/scripts/migrations/003.js @@ -8,7 +8,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { if (versionedData.data.config.provider.rpcTarget === oldTestRpc) { diff --git a/app/scripts/migrations/004.js b/app/scripts/migrations/004.js index 405d932f8..cd558300c 100644 --- a/app/scripts/migrations/004.js +++ b/app/scripts/migrations/004.js @@ -6,7 +6,7 @@ module.exports = { version, migrate: function (versionedData) { - let safeVersionedData = clone(versionedData) + const safeVersionedData = clone(versionedData) safeVersionedData.meta.version = version try { if (safeVersionedData.data.config.provider.type !== 'rpc') return Promise.resolve(safeVersionedData) diff --git a/app/scripts/migrations/005.js b/app/scripts/migrations/005.js index e4b84f460..f7b68dfe4 100644 --- a/app/scripts/migrations/005.js +++ b/app/scripts/migrations/005.js @@ -14,7 +14,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/006.js b/app/scripts/migrations/006.js index 94d1b6ecd..51ea6e3e7 100644 --- a/app/scripts/migrations/006.js +++ b/app/scripts/migrations/006.js @@ -13,7 +13,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/007.js b/app/scripts/migrations/007.js index 236e35224..d9887b9c8 100644 --- a/app/scripts/migrations/007.js +++ b/app/scripts/migrations/007.js @@ -13,7 +13,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/008.js b/app/scripts/migrations/008.js index cd5e95d22..da7cb2e60 100644 --- a/app/scripts/migrations/008.js +++ b/app/scripts/migrations/008.js @@ -13,7 +13,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/009.js b/app/scripts/migrations/009.js index 4612fefdc..f47db55ac 100644 --- a/app/scripts/migrations/009.js +++ b/app/scripts/migrations/009.js @@ -13,7 +13,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/010.js b/app/scripts/migrations/010.js index c0cc56ae4..e4b9ac07e 100644 --- a/app/scripts/migrations/010.js +++ b/app/scripts/migrations/010.js @@ -13,7 +13,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/011.js b/app/scripts/migrations/011.js index 0d5d6d307..782ec809d 100644 --- a/app/scripts/migrations/011.js +++ b/app/scripts/migrations/011.js @@ -12,7 +12,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/012.js b/app/scripts/migrations/012.js index 8361b3793..f69ccbb02 100644 --- a/app/scripts/migrations/012.js +++ b/app/scripts/migrations/012.js @@ -12,7 +12,7 @@ module.exports = { version, migrate: function (originalVersionedData) { - let versionedData = clone(originalVersionedData) + const versionedData = clone(originalVersionedData) versionedData.meta.version = version try { const state = versionedData.data diff --git a/app/scripts/migrations/_multi-keyring.js b/app/scripts/migrations/_multi-keyring.js index 04c966d4d..253aa3d9d 100644 --- a/app/scripts/migrations/_multi-keyring.js +++ b/app/scripts/migrations/_multi-keyring.js @@ -15,15 +15,15 @@ const KeyringController = require('../../app/scripts/lib/keyring-controller') const password = 'obviously not correct' module.exports = { - version, + version, migrate: function (versionedData) { versionedData.meta.version = version - let store = new ObservableStore(versionedData.data) - let configManager = new ConfigManager({ store }) - let idStoreMigrator = new IdentityStoreMigrator({ configManager }) - let keyringController = new KeyringController({ + const store = new ObservableStore(versionedData.data) + const configManager = new ConfigManager({ store }) + const idStoreMigrator = new IdentityStoreMigrator({ configManager }) + const keyringController = new KeyringController({ configManager: configManager, }) @@ -46,6 +46,5 @@ module.exports = { return Promise.resolve(versionedData) }) }) - }, } diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 1e5d70e8b..f9ac4d052 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -16,7 +16,6 @@ function initializePopup ({ container, connectionStream }, cb) { (cb) => connectToAccountManager(connectionStream, cb), (accountManager, cb) => launchMetamaskUi({ container, accountManager }, cb), ], cb) - } function connectToAccountManager (connectionStream, cb) { diff --git a/app/scripts/popup.js b/app/scripts/popup.js index 0fbde54b3..5f17f0651 100644 --- a/app/scripts/popup.js +++ b/app/scripts/popup.js @@ -41,7 +41,7 @@ function closePopupIfOpen (windowType) { } } -function displayCriticalError(err) { +function displayCriticalError (err) { container.innerHTML = '
The MetaMask app failed to load: please open and close MetaMask again to restart.
' container.style.height = '80px' log.error(err.stack) diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index d7051b2cb..9f267160f 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -28,9 +28,9 @@ module.exports = class TransactionManager extends EventEmitter { // memstore is computed from a few different stores this._updateMemstore() - this.store.subscribe(() => this._updateMemstore() ) - this.networkStore.subscribe(() => this._updateMemstore() ) - this.preferencesStore.subscribe(() => this._updateMemstore() ) + this.store.subscribe(() => this._updateMemstore()) + this.networkStore.subscribe(() => this._updateMemstore()) + this.preferencesStore.subscribe(() => this._updateMemstore()) } getState () { @@ -47,8 +47,8 @@ module.exports = class TransactionManager extends EventEmitter { // Returns the tx list getTxList () { - let network = this.getNetwork() - let fullTxList = this.getFullTxList() + const network = this.getNetwork() + const fullTxList = this.getFullTxList() return fullTxList.filter(txMeta => txMeta.metamaskNetworkId === network) } @@ -64,10 +64,10 @@ module.exports = class TransactionManager extends EventEmitter { // Adds a tx to the txlist addTx (txMeta) { - let txCount = this.getTxCount() - let network = this.getNetwork() - let fullTxList = this.getFullTxList() - let txHistoryLimit = this.txHistoryLimit + const txCount = this.getTxCount() + const network = this.getNetwork() + const fullTxList = this.getFullTxList() + const txHistoryLimit = this.txHistoryLimit // checks if the length of the tx history is // longer then desired persistence limit @@ -197,7 +197,7 @@ module.exports = class TransactionManager extends EventEmitter { } fillInTxParams (txId, cb) { - let txMeta = this.getTx(txId) + const txMeta = this.getTx(txId) this.txProviderUtils.fillInTxParams(txMeta.txParams, (err) => { if (err) return cb(err) this.updateTx(txMeta) @@ -205,7 +205,7 @@ module.exports = class TransactionManager extends EventEmitter { }) } - getChainId() { + getChainId () { const networkState = this.networkStore.getState() const getChainId = parseInt(networkState.network) if (Number.isNaN(getChainId)) { @@ -242,7 +242,7 @@ module.exports = class TransactionManager extends EventEmitter { // receives a txHash records the tx as signed setTxHash (txId, txHash) { // Add the tx hash to the persisted meta-tx object - let txMeta = this.getTx(txId) + const txMeta = this.getTx(txId) txMeta.hash = txHash this.updateTx(txMeta) } @@ -315,7 +315,7 @@ module.exports = class TransactionManager extends EventEmitter { } setTxStatusFailed (txId, reason) { - let txMeta = this.getTx(txId) + const txMeta = this.getTx(txId) txMeta.err = reason this.updateTx(txMeta) this._setTxStatus(txId, 'failed') @@ -338,7 +338,7 @@ module.exports = class TransactionManager extends EventEmitter { var txHash = txMeta.hash var txId = txMeta.id if (!txHash) { - let errReason = { + const errReason = { errCode: 'No hash was provided', message: 'We had an error while submitting this transaction, please try again.', } -- cgit From 6d1fe7845c3e74858bbc9c7181348153dfcd55e9 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 27 Apr 2017 15:11:01 -0700 Subject: Version 3.6.0 t # Explicit paths specified without -i or -o; assuming --only paths... --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 6ef428d2c..d5f66173c 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.5.4", + "version": "3.6.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 6ace0c9afbf7d71415bcf0608977d40210651d39 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 28 Apr 2017 16:04:00 -0700 Subject: notification-manager - remove promise listener seems chrome changed their API? MDN suggests that a Promise should be returned but getting `undefined` https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/windows/create Chrome docs suggest its a callback API lolwut https://developer.chrome.com/extensions/windows#method-create --- app/scripts/lib/notification-manager.js | 3 --- 1 file changed, 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/notification-manager.js b/app/scripts/lib/notification-manager.js index 799282f6d..7846ef7f0 100644 --- a/app/scripts/lib/notification-manager.js +++ b/app/scripts/lib/notification-manager.js @@ -24,9 +24,6 @@ class NotificationManager { width, height, }) - .catch((reason) => { - log.error('failed to create poupup', reason) - }) } }) } -- cgit From a3149c17526c320f0cfdbe07a54ca1c2f01a6fad Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sun, 30 Apr 2017 12:38:38 -0700 Subject: Use loglevel for more logs --- app/scripts/metamask-controller.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b91b5efe8..2e4bf07e1 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -341,9 +341,7 @@ module.exports = class MetamaskController extends EventEmitter { console.error('Error in RPC response:\n', response.error) } if (request.isMetamaskInternal) return - if (global.METAMASK_DEBUG) { - console.log(`RPC (${originDomain}):`, request, '->', response) - } + log.info(`RPC (${originDomain}):`, request, '->', response) } } @@ -591,9 +589,7 @@ module.exports = class MetamaskController extends EventEmitter { // Log blocks logBlock (block) { - if (global.METAMASK_DEBUG) { - console.log(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`) - } + log.info(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`) this.verifyNetwork() } @@ -682,9 +678,7 @@ module.exports = class MetamaskController extends EventEmitter { this.setNetworkState('loading') return } - if (global.METAMASK_DEBUG) { - console.log('web3.getNetwork returned ' + network) - } + log.info('web3.getNetwork returned ' + network) this.setNetworkState(network) }) } -- cgit From 7ddbd1a193ed4e6d087480cf17a6b486bcd10826 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sun, 30 Apr 2017 12:39:17 -0700 Subject: Version 3.6.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index d5f66173c..3a9b0b29f 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.6.0", + "version": "3.6.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 833b9f183fca17599d4d225eeec077ddbc7bc7b0 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 3 May 2017 07:22:36 -0700 Subject: Minor lint --- app/scripts/lib/config-manager.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 340ad4292..ab9410842 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -155,7 +155,7 @@ ConfigManager.prototype.getCurrentRpcAddress = function () { case 'kovan': return KOVAN_RPC - + case 'rinkeby': return RINKEBY_RPC -- cgit From 10ba760ed32be6e23186bd9f9a025e28bd757042 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 4 May 2017 17:50:59 -0700 Subject: metamask - selected accounts - dont reveal when locked --- app/scripts/metamask-controller.js | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 2e4bf07e1..497b661d4 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -4,7 +4,6 @@ const promiseToCallback = require('promise-to-callback') const pipe = require('pump') const Dnode = require('dnode') const ObservableStore = require('obs-store') -const storeTransform = require('obs-store/lib/transform') const EthStore = require('./lib/eth-store') const EthQuery = require('eth-query') const streamIntoProvider = require('web3-stream-provider/handler') @@ -169,8 +168,13 @@ module.exports = class MetamaskController extends EventEmitter { rpcUrl: this.configManager.getCurrentRpcAddress(), // account mgmt getAccounts: (cb) => { + const isUnlocked = this.keyringController.memStore.getState().isUnlocked + const result = [] const selectedAddress = this.preferencesController.getSelectedAddress() - const result = selectedAddress ? [selectedAddress] : [] + // only show address if account is unlocked + if (isUnlocked && selectedAddress) { + result.push(selectedAddress) + } cb(null, result) }, // tx signing @@ -186,21 +190,19 @@ module.exports = class MetamaskController extends EventEmitter { initPublicConfigStore () { // get init state - const publicConfigStore = new ObservableStore() + const publicConfigStore = new ObservableStore(this.store.getState()) - // sync publicConfigStore with transform - pipe( - this.store, - storeTransform(selectPublicState.bind(this)), - publicConfigStore - ) + // memStore -> transform -> publicConfigStore + this.on('update', (memState) => { + const publicState = selectPublicState(memState) + publicConfigStore.putState(publicState) + }) - function selectPublicState (state) { - const result = { selectedAddress: undefined } - try { - result.selectedAddress = state.PreferencesController.selectedAddress - result.networkVersion = this.getNetworkState() - } catch (_) {} + function selectPublicState (memState) { + const result = { + selectedAddress: memState.isUnlocked ? memState.selectedAddress : undefined, + networkVersion: memState.network, + } return result } -- cgit From fb08c4a1316248485710a277d397fb5d4f395231 Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 4 May 2017 17:56:30 -0700 Subject: metamask - publicConfig - fix init state --- app/scripts/metamask-controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 497b661d4..175602ec1 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -190,7 +190,7 @@ module.exports = class MetamaskController extends EventEmitter { initPublicConfigStore () { // get init state - const publicConfigStore = new ObservableStore(this.store.getState()) + const publicConfigStore = new ObservableStore() // memStore -> transform -> publicConfigStore this.on('update', (memState) => { -- cgit From 68be86abe959afd26ea50e0833c552c442bfce51 Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 8 May 2017 12:29:08 -0700 Subject: ui - remove web3, use eth-query --- app/scripts/popup-core.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index f9ac4d052..f1eb394d7 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -1,7 +1,7 @@ const EventEmitter = require('events').EventEmitter const async = require('async') const Dnode = require('dnode') -const Web3 = require('web3') +const EthQuery = require('eth-query') const launchMetamaskUi = require('../../ui') const StreamProvider = require('web3-stream-provider') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex @@ -32,7 +32,8 @@ function setupWeb3Connection (connectionStream) { providerStream.pipe(connectionStream).pipe(providerStream) connectionStream.on('error', console.error.bind(console)) providerStream.on('error', console.error.bind(console)) - global.web3 = new Web3(providerStream) + global.ethereumProvider = providerStream + global.ethQuery = new EthQuery(providerStream) } function setupControllerConnection (connectionStream, cb) { -- cgit From 662a646fa92479e30b492520bd0edd753179bbdd Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 8 May 2017 16:20:37 -0700 Subject: Version 3.6.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 3a9b0b29f..faceea60b 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.6.1", + "version": "3.6.2", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From ff1a1284cc768a0e7d179083d360a5579373e256 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 8 May 2017 22:05:38 -0700 Subject: Version 3.6.3 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index faceea60b..cef44446e 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.6.2", + "version": "3.6.3", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 3ed7205b7505133a1dd6a278665070eb83bd4a32 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 9 May 2017 17:08:33 -0700 Subject: Version 3.6.4 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index cef44446e..a1f6d7855 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.6.3", + "version": "3.6.4", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 1772d34e947ec5e940cc99f53ff0a102e048d69c Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 11 May 2017 10:10:50 +0200 Subject: fix migrator --- app/scripts/lib/migrator/index.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index c40c347b5..caa0ef318 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -13,10 +13,10 @@ class Migrator { // run all pending migrations on meta in place migrateData (versionedData = this.generateInitialState()) { const remaining = this.migrations.filter(migrationIsPending) - + if (remaining.length === 0) return versionedData return ( asyncQ.eachSeries(remaining, (migration) => this.runMigration(versionedData, migration)) - .then(() => versionedData) + .then((migratedData) => migratedData.pop()) ) // migration is "pending" if hit has a higher @@ -27,14 +27,13 @@ class Migrator { } runMigration (versionedData, migration) { - return ( - migration.migrate(versionedData) - .then((versionedData) => { - if (!versionedData.data) return Promise.reject(new Error('Migrator - Migration returned empty data')) - if (migration.version !== undefined && versionedData.meta.version !== migration.version) return Promise.reject(new Error('Migrator - Migration did not update version number correctly')) - return Promise.resolve(versionedData) + return migration.migrate(versionedData) + .then((migratedData) => { + if (!migratedData.data) return Promise.reject(new Error('Migrator - Migration returned empty data')) + if (migration.version !== undefined && migratedData.meta.version !== migration.version) return Promise.reject(new Error('Migrator - Migration did not update version number correctly')) + + return Promise.resolve(migratedData) }) - ) } generateInitialState (initState) { -- cgit From 73e1cd2317db4366a6e29aa9f8119cc871747a1b Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 11 May 2017 12:30:39 -0700 Subject: Trim currency list. --- app/currencies.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 app/currencies.json (limited to 'app') diff --git a/app/currencies.json b/app/currencies.json deleted file mode 100644 index 07889798b..000000000 --- a/app/currencies.json +++ /dev/null @@ -1 +0,0 @@ -{"rows":[{"code":"007","name":"007","statuses":["primary"]},{"code":"1337","name":"1337","statuses":["primary"]},{"code":"1CR","name":"1CR","statuses":["primary"]},{"code":"256","name":"256","statuses":["primary"]},{"code":"2FLAV","name":"2FLAV","statuses":["primary"]},{"code":"2GIVE","name":"2GIVE","statuses":["primary"]},{"code":"404","name":"404","statuses":["primary"]},{"code":"611","name":"611","statuses":["primary"]},{"code":"888","name":"888","statuses":["primary"]},{"code":"8BIT","name":"8Bit","statuses":["primary"]},{"code":"ACLR","name":"ACLR","statuses":["primary"]},{"code":"ACOIN","name":"ACOIN","statuses":["primary"]},{"code":"ACP","name":"ACP","statuses":["primary"]},{"code":"ADC","name":"ADC","statuses":["primary"]},{"code":"ADZ","name":"Adzcoin","statuses":["primary"]},{"code":"AEC","name":"AEC","statuses":["primary"]},{"code":"AEON","name":"Aeon","statuses":["primary"]},{"code":"AGRS","name":"Agoras Tokens","statuses":["primary"]},{"code":"AIB","name":"AIB","statuses":["primary"]},{"code":"ADN","name":"Aiden","statuses":["primary"]},{"code":"AIR","name":"AIR","statuses":["primary"]},{"code":"ALC","name":"ALC","statuses":["primary"]},{"code":"ALTC","name":"ALTC","statuses":["primary"]},{"code":"AM","name":"AM","statuses":["primary"]},{"code":"AMBER","name":"AMBER","statuses":["primary"]},{"code":"AMS","name":"AMS","statuses":["primary"]},{"code":"ANAL","name":"ANAL","statuses":["primary"]},{"code":"AND","name":"AND","statuses":["primary"]},{"code":"ANI","name":"ANI","statuses":["primary"]},{"code":"ANC","name":"Anoncoin","statuses":["primary"]},{"code":"ANTI","name":"AntiBitcoin","statuses":["primary"]},{"code":"APEX","name":"APEX","statuses":["primary"]},{"code":"APC","name":"Applecoin","statuses":["primary"]},{"code":"APT","name":"APT","statuses":["primary"]},{"code":"AR2","name":"AR2","statuses":["primary"]},{"code":"ARB","name":"ARB","statuses":["primary"]},{"code":"ARC","name":"ARC","statuses":["primary"]},{"code":"ARCH","name":"ARCH","statuses":["primary"]},{"code":"ABY","name":"ArtByte","statuses":["primary"]},{"code":"ARTC","name":"ARTC","statuses":["primary"]},{"code":"ADCN","name":"Asiadigicoin","statuses":["primary"]},{"code":"ATEN","name":"ATEN","statuses":["primary"]},{"code":"REP","name":"Augur","statuses":["primary"]},{"code":"AUR","name":"Auroracoin","statuses":["primary"]},{"code":"AUD","name":"Australian Dollar","statuses":["secondary"]},{"code":"AV","name":"AV","statuses":["primary"]},{"code":"BA","name":"BA","statuses":["primary"]},{"code":"BAC","name":"BAC","statuses":["primary"]},{"code":"BTA","name":"Bata","statuses":["primary"]},{"code":"BAY","name":"BAY","statuses":["primary"]},{"code":"BBCC","name":"BBCC","statuses":["primary"]},{"code":"BQC","name":"BBQCoin","statuses":["primary"]},{"code":"BDC","name":"BDC","statuses":["primary"]},{"code":"BEC","name":"BEC","statuses":["primary"]},{"code":"BEEZ","name":"BEEZ","statuses":["primary"]},{"code":"BELA","name":"BellaCoin","statuses":["primary"]},{"code":"BERN","name":"BERNcash","statuses":["primary"]},{"code":"BILL","name":"BILL","statuses":["primary"]},{"code":"BILS","name":"BILS","statuses":["primary"]},{"code":"BIOS","name":"BiosCrypto","statuses":["primary"]},{"code":"BIT","name":"BIT","statuses":["primary"]},{"code":"BIT16","name":"BIT16","statuses":["primary"]},{"code":"BITB","name":"BitBean","statuses":["primary"]},{"code":"BTC","name":"Bitcoin","statuses":["primary","secondary"]},{"code":"XBC","name":"Bitcoin Plus","statuses":["primary"]},{"code":"BTCD","name":"BitcoinDark","statuses":["primary"]},{"code":"BCY","name":"Bitcrystals","statuses":["primary"]},{"code":"BTM","name":"Bitmark","statuses":["primary"]},{"code":"BTQ","name":"BitQuark","statuses":["primary"]},{"code":"BITS","name":"BITS","statuses":["primary"]},{"code":"BSD","name":"BitSend","statuses":["primary"]},{"code":"BTS","name":"BitShares","statuses":["primary"]},{"code":"PTS","name":"BitShares PTS","statuses":["primary"]},{"code":"SWIFT","name":"BitSwift","statuses":["primary"]},{"code":"BITZ","name":"Bitz","statuses":["primary"]},{"code":"BLK","name":"Blackcoin","statuses":["primary"]},{"code":"JACK","name":"BlackJack","statuses":["primary"]},{"code":"BLC","name":"Blakecoin","statuses":["primary"]},{"code":"BLEU","name":"BLEU","statuses":["primary"]},{"code":"BLITZ","name":"Blitzcoin","statuses":["primary"]},{"code":"BLOCK","name":"Blocknet","statuses":["primary"]},{"code":"BLRY","name":"BLRY","statuses":["primary"]},{"code":"BLU","name":"BLU","statuses":["primary"]},{"code":"BM","name":"BM","statuses":["primary"]},{"code":"BNT","name":"BNT","statuses":["primary"]},{"code":"BOB","name":"BOB","statuses":["primary"]},{"code":"BON","name":"BON","statuses":["primary"]},{"code":"BBR","name":"Boolberry","statuses":["primary"]},{"code":"BOST","name":"BoostCoin","statuses":["primary"]},{"code":"BOSS","name":"BOSS","statuses":["primary"]},{"code":"BPOK","name":"BPOK","statuses":["primary"]},{"code":"BRAIN","name":"BRAIN","statuses":["primary"]},{"code":"BRC","name":"BRC","statuses":["primary"]},{"code":"BRDD","name":"BRDD","statuses":["primary"]},{"code":"BRIT","name":"BRIT","statuses":["primary"]},{"code":"GBP","name":"British Pound Sterling","statuses":["secondary"]},{"code":"BRK","name":"BRK","statuses":["primary"]},{"code":"BRX","name":"BRX","statuses":["primary"]},{"code":"BSC","name":"BSC","statuses":["primary"]},{"code":"BST","name":"BST","statuses":["primary"]},{"code":"BTCHC","name":"BTCHC","statuses":["primary"]},{"code":"BTCR","name":"BTCR","statuses":["primary"]},{"code":"BTCS","name":"BTCS","statuses":["primary"]},{"code":"BTCU","name":"BTCU","statuses":["primary"]},{"code":"BTTF","name":"BTTF","statuses":["primary"]},{"code":"BTX","name":"BTX","statuses":["primary"]},{"code":"BUCKS","name":"BUCKS","statuses":["primary"]},{"code":"BUN","name":"BUN","statuses":["primary"]},{"code":"BURST","name":"Burst","statuses":["primary"]},{"code":"BUZZ","name":"BUZZ","statuses":["primary"]},{"code":"BVC","name":"BVC","statuses":["primary"]},{"code":"BYC","name":"Bytecent","statuses":["primary"]},{"code":"BCN","name":"Bytecoin","statuses":["primary"]},{"code":"XCT","name":"C-Bit","statuses":["primary"]},{"code":"C0C0","name":"C0C0","statuses":["primary"]},{"code":"CAB","name":"Cabbage Unit","statuses":["primary"]},{"code":"CAD","name":"CAD","statuses":["primary","secondary"]},{"code":"CAGE","name":"CAGE","statuses":["primary"]},{"code":"CANN","name":"CannabisCoin","statuses":["primary"]},{"code":"CCN","name":"Cannacoin","statuses":["primary"]},{"code":"CPC","name":"Capricoin","statuses":["primary"]},{"code":"DIEM","name":"CarpeDiemCoin","statuses":["primary"]},{"code":"CASH","name":"CASH","statuses":["primary"]},{"code":"CBIT","name":"CBIT","statuses":["primary"]},{"code":"CC","name":"CC","statuses":["primary"]},{"code":"CCB","name":"CCB","statuses":["primary"]},{"code":"CD","name":"CD","statuses":["primary"]},{"code":"CDN","name":"CDN","statuses":["primary"]},{"code":"CF","name":"CF","statuses":["primary"]},{"code":"CFC","name":"CFC","statuses":["primary"]},{"code":"CGA","name":"CGA","statuses":["primary"]},{"code":"CHC","name":"CHC","statuses":["primary"]},{"code":"CKC","name":"Checkcoin","statuses":["primary"]},{"code":"CHEMX","name":"CHEMX","statuses":["primary"]},{"code":"CHESS","name":"CHESS","statuses":["primary"]},{"code":"CHF","name":"CHF","statuses":["primary","secondary"]},{"code":"CNY","name":"Chinese Yuan","statuses":["secondary"]},{"code":"CHRG","name":"CHRG","statuses":["primary"]},{"code":"CJ","name":"CJ","statuses":["primary"]},{"code":"CLAM","name":"Clams","statuses":["primary"]},{"code":"CLICK","name":"CLICK","statuses":["primary"]},{"code":"CLINT","name":"CLINT","statuses":["primary"]},{"code":"CLOAK","name":"Cloakcoin","statuses":["primary"]},{"code":"CLR","name":"CLR","statuses":["primary"]},{"code":"CLUB","name":"CLUB","statuses":["primary"]},{"code":"CLUD","name":"CLUD","statuses":["primary"]},{"code":"CMT","name":"CMT","statuses":["primary"]},{"code":"CNC","name":"CNC","statuses":["primary"]},{"code":"COXST","name":"CoExistCoin","statuses":["primary"]},{"code":"COIN","name":"COIN","statuses":["primary"]},{"code":"C2","name":"Coin2.1","statuses":["primary"]},{"code":"CNMT","name":"Coinomat","statuses":["primary"]},{"code":"CV2","name":"Colossuscoin2.0","statuses":["primary"]},{"code":"CON","name":"CON","statuses":["primary"]},{"code":"XCP","name":"Counterparty","statuses":["primary"]},{"code":"COV","name":"COV","statuses":["primary"]},{"code":"CRAFT","name":"CRAFT","statuses":["primary"]},{"code":"CRAVE","name":"CRAVE","statuses":["primary"]},{"code":"CRC","name":"CRC","statuses":["primary"]},{"code":"CRE","name":"CRE","statuses":["primary"]},{"code":"CRBIT","name":"Creditbit","statuses":["primary"]},{"code":"CREVA","name":"CrevaCoin","statuses":["primary"]},{"code":"CRIME","name":"CRIME","statuses":["primary"]},{"code":"CRT","name":"CRT","statuses":["primary"]},{"code":"CRW","name":"CRW","statuses":["primary"]},{"code":"CRY","name":"CRY","statuses":["primary"]},{"code":"XCR","name":"Crypti","statuses":["primary"]},{"code":"CBX","name":"Crypto Bullion","statuses":["primary"]},{"code":"CESC","name":"CryptoEscudo","statuses":["primary"]},{"code":"XCN","name":"Cryptonite","statuses":["primary"]},{"code":"CSMIC","name":"CSMIC","statuses":["primary"]},{"code":"CST","name":"CST","statuses":["primary"]},{"code":"CTC","name":"CTC","statuses":["primary"]},{"code":"CTO","name":"CTO","statuses":["primary"]},{"code":"CURE","name":"Curecoin","statuses":["primary"]},{"code":"CYP","name":"Cypher","statuses":["primary"]},{"code":"CZC","name":"CZC","statuses":["primary"]},{"code":"CZECO","name":"CZECO","statuses":["primary"]},{"code":"CZR","name":"CZR","statuses":["primary"]},{"code":"DAO","name":"DAO","statuses":["primary"]},{"code":"DGD","name":"DarkGoldCoin","statuses":["primary"]},{"code":"DNET","name":"Darknet","statuses":["primary"]},{"code":"DASH","name":"Dash","statuses":["primary"]},{"code":"DTC","name":"Datacoin","statuses":["primary"]},{"code":"DBG","name":"DBG","statuses":["primary"]},{"code":"DBLK","name":"DBLK","statuses":["primary"]},{"code":"DBTC","name":"DBTC","statuses":["primary"]},{"code":"DCK","name":"DCK","statuses":["primary"]},{"code":"DCR","name":"Decred","statuses":["primary"]},{"code":"DES","name":"Destiny","statuses":["primary"]},{"code":"DETH","name":"DETH","statuses":["primary"]},{"code":"DEUR","name":"DEUR","statuses":["primary"]},{"code":"DEM","name":"Deutsche eMark","statuses":["primary"]},{"code":"DVC","name":"Devcoin","statuses":["primary"]},{"code":"DGCS","name":"DGCS","statuses":["primary"]},{"code":"DGMS","name":"DGMS","statuses":["primary"]},{"code":"DGORE","name":"DGORE","statuses":["primary"]},{"code":"DMD","name":"Diamond","statuses":["primary"]},{"code":"DGB","name":"Digibyte","statuses":["primary"]},{"code":"CUBE","name":"DigiCube","statuses":["primary"]},{"code":"DGC","name":"Digitalcoin","statuses":["primary"]},{"code":"XDN","name":"DigitalNote","statuses":["primary"]},{"code":"DP","name":"DigitalPrice","statuses":["primary"]},{"code":"DIGS","name":"DIGS","statuses":["primary"]},{"code":"DIME","name":"Dimecoin","statuses":["primary"]},{"code":"DISK","name":"DISK","statuses":["primary"]},{"code":"DLISK","name":"DLISK","statuses":["primary"]},{"code":"NOTE","name":"DNotes","statuses":["primary"]},{"code":"DOGE","name":"DOGE","statuses":["primary","secondary"]},{"code":"DOGE","name":"Dogecoin","statuses":["primary","secondary"]},{"code":"DON","name":"DON","statuses":["primary"]},{"code":"DOPE","name":"DopeCoin","statuses":["primary"]},{"code":"DOX","name":"DOX","statuses":["primary"]},{"code":"DRACO","name":"DRACO","statuses":["primary"]},{"code":"DRM","name":"DRM","statuses":["primary"]},{"code":"DROP","name":"DROP","statuses":["primary"]},{"code":"DRZ","name":"DRZ","statuses":["primary"]},{"code":"DSH","name":"DSH","statuses":["primary"]},{"code":"DBIC","name":"DubaiCoin","statuses":["primary"]},{"code":"DUO","name":"DUO","statuses":["primary"]},{"code":"DUST","name":"DUST","statuses":["primary"]},{"code":"EAC","name":"Earthcoin","statuses":["primary"]},{"code":"ECCHI","name":"ECCHI","statuses":["primary"]},{"code":"ECC","name":"ECCoin","statuses":["primary"]},{"code":"ECOS","name":"ECOS","statuses":["primary"]},{"code":"EDC","name":"EDC","statuses":["primary"]},{"code":"EDRC","name":"EDRC","statuses":["primary"]},{"code":"EGG","name":"EGG","statuses":["primary"]},{"code":"EMC2","name":"Einsteinium","statuses":["primary"]},{"code":"EKO","name":"EKO","statuses":["primary"]},{"code":"EL","name":"EL","statuses":["primary"]},{"code":"ELCO","name":"ELcoin","statuses":["primary"]},{"code":"ELE","name":"ELE","statuses":["primary"]},{"code":"EFL","name":"Electronic Gulden","statuses":["primary"]},{"code":"EMC","name":"Emercoin","statuses":["primary"]},{"code":"EMIRG","name":"EMIRG","statuses":["primary"]},{"code":"ENE","name":"ENE","statuses":["primary"]},{"code":"ENRG","name":"Energycoin","statuses":["primary"]},{"code":"EPC","name":"EPC","statuses":["primary"]},{"code":"EPY","name":"EPY","statuses":["primary"]},{"code":"ERC","name":"ERC","statuses":["primary"]},{"code":"ERC3","name":"ERC3","statuses":["primary"]},{"code":"ESC","name":"ESC","statuses":["primary"]},{"code":"ETH","name":"Ethereum","statuses":["primary","secondary"]},{"code":"ETC","name":"Ethereum Classic","statuses":["primary"]},{"code":"ETHS","name":"ETHS","statuses":["primary"]},{"code":"EURC","name":"EURC","statuses":["primary"]},{"code":"EUR","name":"Euro","statuses":["primary","secondary"]},{"code":"EGC","name":"EvergreenCoin","statuses":["primary"]},{"code":"EVIL","name":"EVIL","statuses":["primary"]},{"code":"EVO","name":"EVO","statuses":["primary"]},{"code":"EXCL","name":"EXCL","statuses":["primary"]},{"code":"EXIT","name":"EXIT","statuses":["primary"]},{"code":"EXP","name":"Expanse","statuses":["primary"]},{"code":"FCT","name":"Factom","statuses":["primary"]},{"code":"FAIR","name":"Faircoin","statuses":["primary"]},{"code":"FC2","name":"FC2","statuses":["primary"]},{"code":"FCN","name":"FCN","statuses":["primary"]},{"code":"FTC","name":"Feathercoin","statuses":["primary"]},{"code":"TIPS","name":"Fedoracoin","statuses":["primary"]},{"code":"FFC","name":"FFC","statuses":["primary"]},{"code":"FIBRE","name":"Fibre","statuses":["primary"]},{"code":"FIT","name":"FIT","statuses":["primary"]},{"code":"FJC","name":"FJC","statuses":["primary"]},{"code":"FLO","name":"Florincoin","statuses":["primary"]},{"code":"FLOZ","name":"FLOZ","statuses":["primary"]},{"code":"FLT","name":"FlutterCoin","statuses":["primary"]},{"code":"FLX","name":"FLX","statuses":["primary"]},{"code":"FLY","name":"Flycoin","statuses":["primary"]},{"code":"FLDC","name":"FoldingCoin","statuses":["primary"]},{"code":"FONZ","name":"FONZ","statuses":["primary"]},{"code":"FRK","name":"Franko","statuses":["primary"]},{"code":"FRC","name":"Freicoin","statuses":["primary"]},{"code":"FRN","name":"FRN","statuses":["primary"]},{"code":"FRWC","name":"FRWC","statuses":["primary"]},{"code":"FSC2","name":"FSC2","statuses":["primary"]},{"code":"FST","name":"FST","statuses":["primary"]},{"code":"FTP","name":"FTP","statuses":["primary"]},{"code":"FUN","name":"FUN","statuses":["primary"]},{"code":"FUTC","name":"FUTC","statuses":["primary"]},{"code":"FUZZ","name":"FUZZ","statuses":["primary"]},{"code":"GAIA","name":"GAIA","statuses":["primary"]},{"code":"GAIN","name":"GAIN","statuses":["primary"]},{"code":"GAKH","name":"GAKH","statuses":["primary"]},{"code":"GAM","name":"GAM","statuses":["primary"]},{"code":"GBT","name":"GameBet Coin","statuses":["primary"]},{"code":"GAME","name":"GameCredits","statuses":["primary"]},{"code":"GAP","name":"Gapcoin","statuses":["primary"]},{"code":"GARY","name":"GARY","statuses":["primary"]},{"code":"GB","name":"GB","statuses":["primary"]},{"code":"GBC","name":"GBC","statuses":["primary"]},{"code":"GBIT","name":"GBIT","statuses":["primary"]},{"code":"GCC","name":"GCC","statuses":["primary"]},{"code":"GCN","name":"GCN","statuses":["primary"]},{"code":"GEO","name":"GeoCoin","statuses":["primary"]},{"code":"GEMZ","name":"GetGems","statuses":["primary"]},{"code":"GHOST","name":"GHOST","statuses":["primary"]},{"code":"GHS","name":"GHS","statuses":["primary"]},{"code":"GIFT","name":"GIFT","statuses":["primary"]},{"code":"GIG","name":"GIG","statuses":["primary"]},{"code":"GLC","name":"GLC","statuses":["primary"]},{"code":"BSTY","name":"GlobalBoost-Y","statuses":["primary"]},{"code":"GML","name":"GML","statuses":["primary"]},{"code":"GMX","name":"GMX","statuses":["primary"]},{"code":"GCR","name":"GoCoineR","statuses":["primary"]},{"code":"GLD","name":"GoldCoin","statuses":["primary"]},{"code":"GOON","name":"GOON","statuses":["primary"]},{"code":"GP","name":"GP","statuses":["primary"]},{"code":"GPU","name":"GPU","statuses":["primary"]},{"code":"GRAM","name":"GRAM","statuses":["primary"]},{"code":"GRT","name":"Grantcoin","statuses":["primary"]},{"code":"GRE","name":"GRE","statuses":["primary"]},{"code":"GRC","name":"Gridcoin","statuses":["primary"]},{"code":"GRN","name":"GRN","statuses":["primary"]},{"code":"GRS","name":"Groestlcoin","statuses":["primary"]},{"code":"GRW","name":"GRW","statuses":["primary"]},{"code":"GSM","name":"GSM","statuses":["primary"]},{"code":"GSX","name":"GSX","statuses":["primary"]},{"code":"GUA","name":"GUA","statuses":["primary"]},{"code":"NLG","name":"Gulden","statuses":["primary"]},{"code":"GUN","name":"GUN","statuses":["primary"]},{"code":"HAM","name":"HAM","statuses":["primary"]},{"code":"HAWK","name":"HAWK","statuses":["primary"]},{"code":"HCC","name":"HCC","statuses":["primary"]},{"code":"HEAT","name":"HEAT","statuses":["primary"]},{"code":"HMP","name":"HempCoin","statuses":["primary"]},{"code":"XHI","name":"HiCoin","statuses":["primary"]},{"code":"HIFUN","name":"HIFUN","statuses":["primary"]},{"code":"HILL","name":"HILL","statuses":["primary"]},{"code":"HIRE","name":"HIRE","statuses":["primary"]},{"code":"HNC","name":"HNC","statuses":["primary"]},{"code":"HODL","name":"HOdlcoin","statuses":["primary"]},{"code":"HKD","name":"Hong Kong Dollar","statuses":["secondary"]},{"code":"HZ","name":"Horizon","statuses":["primary"]},{"code":"HTC","name":"HTC","statuses":["primary"]},{"code":"HTML5","name":"HTMLCOIN","statuses":["primary"]},{"code":"HUC","name":"HUC","statuses":["primary"]},{"code":"HVCO","name":"HVCO","statuses":["primary"]},{"code":"HYPER","name":"Hyper","statuses":["primary"]},{"code":"HYP","name":"HyperStake","statuses":["primary"]},{"code":"I0C","name":"I0C","statuses":["primary"]},{"code":"IBANK","name":"IBANK","statuses":["primary"]},{"code":"ICASH","name":"iCash","statuses":["primary"]},{"code":"ICN","name":"ICN","statuses":["primary"]},{"code":"IEC","name":"IEC","statuses":["primary"]},{"code":"IFC","name":"Infinitecoin","statuses":["primary"]},{"code":"INFX","name":"Influxcoin","statuses":["primary"]},{"code":"INV","name":"INV","statuses":["primary"]},{"code":"IOC","name":"IO Coin","statuses":["primary"]},{"code":"ION","name":"ION","statuses":["primary"]},{"code":"IRL","name":"IRL","statuses":["primary"]},{"code":"ISL","name":"IslaCoin","statuses":["primary"]},{"code":"IVZ","name":"IVZ","statuses":["primary"]},{"code":"IXC","name":"IXC","statuses":["primary"]},{"code":"JIF","name":"JIF","statuses":["primary"]},{"code":"JPC","name":"JPC","statuses":["primary"]},{"code":"JPY","name":"JPY","statuses":["primary","secondary"]},{"code":"JBS","name":"Jumbucks","statuses":["primary"]},{"code":"KAT","name":"KAT","statuses":["primary"]},{"code":"KGC","name":"KGC","statuses":["primary"]},{"code":"KNC","name":"KhanCoin","statuses":["primary"]},{"code":"KLC","name":"KLC","statuses":["primary"]},{"code":"KOBO","name":"KOBO","statuses":["primary"]},{"code":"KORE","name":"KoreCoin","statuses":["primary"]},{"code":"KRAK","name":"KRAK","statuses":["primary"]},{"code":"KRYP","name":"KRYP","statuses":["primary"]},{"code":"KR","name":"Krypton","statuses":["primary"]},{"code":"KTK","name":"KTK","statuses":["primary"]},{"code":"KUBO","name":"KUBO","statuses":["primary"]},{"code":"LANA","name":"LANA","statuses":["primary"]},{"code":"LBC","name":"LBC","statuses":["primary"]},{"code":"LC","name":"LC","statuses":["primary"]},{"code":"LEA","name":"LeaCoin","statuses":["primary"]},{"code":"LEMON","name":"LEMON","statuses":["primary"]},{"code":"LEO","name":"LEO","statuses":["primary"]},{"code":"LFC","name":"LFC","statuses":["primary"]},{"code":"LFO","name":"LFO","statuses":["primary"]},{"code":"LFTC","name":"LFTC","statuses":["primary"]},{"code":"LQD","name":"LIQUID","statuses":["primary"]},{"code":"LIR","name":"LIR","statuses":["primary"]},{"code":"LSK","name":"Lisk","statuses":["primary"]},{"code":"LTC","name":"Litecoin","statuses":["primary","secondary"]},{"code":"LTCR","name":"Litecred","statuses":["primary"]},{"code":"LDOGE","name":"LiteDoge","statuses":["primary"]},{"code":"LKC","name":"LKC","statuses":["primary"]},{"code":"LOC","name":"LOC","statuses":["primary"]},{"code":"LOOT","name":"LOOT","statuses":["primary"]},{"code":"LTBC","name":"LTBcoin","statuses":["primary"]},{"code":"LTC","name":"LTC","statuses":["primary","secondary"]},{"code":"LTH","name":"LTH","statuses":["primary"]},{"code":"LTS","name":"LTS","statuses":["primary"]},{"code":"LUN","name":"LUN","statuses":["primary"]},{"code":"LXC","name":"LXC","statuses":["primary"]},{"code":"LYB","name":"LYB","statuses":["primary"]},{"code":"M1","name":"M1","statuses":["primary"]},{"code":"MAD","name":"MAD","statuses":["primary"]},{"code":"XMG","name":"Magi","statuses":["primary"]},{"code":"MAID","name":"MaidSafeCoin","statuses":["primary"]},{"code":"MXT","name":"MarteXcoin","statuses":["primary"]},{"code":"MARV","name":"MARV","statuses":["primary"]},{"code":"MARYJ","name":"MARYJ","statuses":["primary"]},{"code":"OMNI","name":"Mastercoin (Omni)","statuses":["primary"]},{"code":"MTR","name":"MasterTraderCoin","statuses":["primary"]},{"code":"MAX","name":"Maxcoin","statuses":["primary"]},{"code":"MZC","name":"Mazacoin","statuses":["primary"]},{"code":"MBL","name":"MBL","statuses":["primary"]},{"code":"MCAR","name":"MCAR","statuses":["primary"]},{"code":"MCN","name":"MCN","statuses":["primary"]},{"code":"MCZ","name":"MCZ","statuses":["primary"]},{"code":"MED","name":"MediterraneanCoin","statuses":["primary"]},{"code":"MEC","name":"Megacoin","statuses":["primary"]},{"code":"MEME","name":"Memetic","statuses":["primary"]},{"code":"METAL","name":"METAL","statuses":["primary"]},{"code":"MND","name":"MindCoin","statuses":["primary"]},{"code":"MINT","name":"Mintcoin","statuses":["primary"]},{"code":"MIS","name":"MIS","statuses":["primary"]},{"code":"MM","name":"MM","statuses":["primary"]},{"code":"MMC","name":"MMC","statuses":["primary"]},{"code":"MMNXT","name":"MMNXT","statuses":["primary"]},{"code":"MMXVI","name":"MMXVI","statuses":["primary"]},{"code":"MNM","name":"MNM","statuses":["primary"]},{"code":"MOIN","name":"MOIN","statuses":["primary"]},{"code":"MOJO","name":"MojoCoin","statuses":["primary"]},{"code":"MONA","name":"MonaCoin","statuses":["primary"]},{"code":"XMR","name":"Monero","statuses":["primary","secondary"]},{"code":"MNTA","name":"Moneta","statuses":["primary"]},{"code":"MUE","name":"MonetaryUnit","statuses":["primary"]},{"code":"MOON","name":"Mooncoin","statuses":["primary"]},{"code":"MOOND","name":"MOOND","statuses":["primary"]},{"code":"MOTO","name":"MOTO","statuses":["primary"]},{"code":"MPRO","name":"MPRO","statuses":["primary"]},{"code":"MRB","name":"MRB","statuses":["primary"]},{"code":"MRP","name":"MRP","statuses":["primary"]},{"code":"MSC","name":"MSC","statuses":["primary"]},{"code":"MYR","name":"Myriadcoin","statuses":["primary"]},{"code":"NMC","name":"Namecoin","statuses":["primary"]},{"code":"NAUT","name":"Nautiluscoin","statuses":["primary"]},{"code":"NAV","name":"NAV Coin","statuses":["primary"]},{"code":"NCS","name":"NCS","statuses":["primary"]},{"code":"XEM","name":"NEM","statuses":["primary"]},{"code":"NEOS","name":"NeosCoin","statuses":["primary"]},{"code":"NETC","name":"NETC","statuses":["primary"]},{"code":"NET","name":"NetCoin","statuses":["primary"]},{"code":"NEU","name":"NeuCoin","statuses":["primary"]},{"code":"NTRN","name":"Neutron","statuses":["primary"]},{"code":"NEVA","name":"NevaCoin","statuses":["primary"]},{"code":"NEWB","name":"NEWB","statuses":["primary"]},{"code":"NIRO","name":"Nexus","statuses":["primary"]},{"code":"NIC","name":"NIC","statuses":["primary"]},{"code":"NKA","name":"NKA","statuses":["primary"]},{"code":"NKC","name":"NKC","statuses":["primary"]},{"code":"NOBL","name":"NobleCoin","statuses":["primary"]},{"code":"NODE","name":"NODE","statuses":["primary"]},{"code":"NODES","name":"NODES","statuses":["primary"]},{"code":"NOO","name":"NOO","statuses":["primary"]},{"code":"NVC","name":"Novacoin","statuses":["primary"]},{"code":"NRC","name":"NRC","statuses":["primary"]},{"code":"NRS","name":"NRS","statuses":["primary"]},{"code":"NUBIS","name":"NUBIS","statuses":["primary"]},{"code":"NBT","name":"NuBits","statuses":["primary"]},{"code":"NUM","name":"NUM","statuses":["primary"]},{"code":"NSR","name":"NuShares","statuses":["primary"]},{"code":"NXE","name":"NXE","statuses":["primary"]},{"code":"NXT","name":"NXT","statuses":["primary"]},{"code":"NXTTY","name":"Nxttycoin","statuses":["primary"]},{"code":"NYC","name":"NYC","statuses":["primary"]},{"code":"NZC","name":"NZC","statuses":["primary"]},{"code":"NZD","name":"NZD","statuses":["primary","secondary"]},{"code":"OC","name":"OC","statuses":["primary"]},{"code":"OCOW","name":"OCOW","statuses":["primary"]},{"code":"OK","name":"OKCash","statuses":["primary"]},{"code":"OMA","name":"OMA","statuses":["primary"]},{"code":"ONE","name":"ONE","statuses":["primary"]},{"code":"ONEC","name":"ONEC","statuses":["primary"]},{"code":"OP","name":"OP","statuses":["primary"]},{"code":"OPAL","name":"OPAL","statuses":["primary"]},{"code":"OPES","name":"OPES","statuses":["primary"]},{"code":"ORB","name":"Orbitcoin","statuses":["primary"]},{"code":"ORLY","name":"Orlycoin","statuses":["primary"]},{"code":"OS76","name":"OS76","statuses":["primary"]},{"code":"OZC","name":"OZC","statuses":["primary"]},{"code":"PAC","name":"PAC","statuses":["primary"]},{"code":"PAK","name":"PAK","statuses":["primary"]},{"code":"PND","name":"Pandacoin","statuses":["primary"]},{"code":"PAPAF","name":"PAPAF","statuses":["primary"]},{"code":"XPY","name":"Paycoin","statuses":["primary"]},{"code":"PBC","name":"PBC","statuses":["primary"]},{"code":"PDC","name":"PDC","statuses":["primary"]},{"code":"XPB","name":"Pebblecoin","statuses":["primary"]},{"code":"PPC","name":"Peercoin","statuses":["primary"]},{"code":"PEN","name":"PEN","statuses":["primary"]},{"code":"PHR","name":"PHR","statuses":["primary"]},{"code":"PIGGY","name":"Piggycoin","statuses":["primary"]},{"code":"PC","name":"Pinkcoin","statuses":["primary"]},{"code":"PKB","name":"PKB","statuses":["primary"]},{"code":"PLN","name":"PLN","statuses":["primary","secondary"]},{"code":"PLNC","name":"PLNC","statuses":["primary"]},{"code":"PNC","name":"PNC","statuses":["primary"]},{"code":"PNK","name":"PNK","statuses":["primary"]},{"code":"POKE","name":"POKE","statuses":["primary"]},{"code":"PONZ2","name":"PONZ2","statuses":["primary"]},{"code":"PONZI","name":"PONZI","statuses":["primary"]},{"code":"PEX","name":"PosEx","statuses":["primary"]},{"code":"POST","name":"POST","statuses":["primary"]},{"code":"POT","name":"Potcoin","statuses":["primary"]},{"code":"PRES","name":"PRES","statuses":["primary"]},{"code":"PXI","name":"Prime-XI","statuses":["primary"]},{"code":"PRIME","name":"PrimeChain","statuses":["primary"]},{"code":"XPM","name":"Primecoin","statuses":["primary"]},{"code":"PRM","name":"PRM","statuses":["primary"]},{"code":"PRT","name":"PRT","statuses":["primary"]},{"code":"PSP","name":"PSP","statuses":["primary"]},{"code":"PTC","name":"PTC","statuses":["primary"]},{"code":"PULSE","name":"PULSE","statuses":["primary"]},{"code":"PURE","name":"PURE","statuses":["primary"]},{"code":"PUTIN","name":"PUTIN","statuses":["primary"]},{"code":"PWR","name":"PWR","statuses":["primary"]},{"code":"PXL","name":"PXL","statuses":["primary"]},{"code":"QBC","name":"QBC","statuses":["primary"]},{"code":"QBK","name":"QBK","statuses":["primary"]},{"code":"QCN","name":"QCN","statuses":["primary"]},{"code":"QORA","name":"Qora","statuses":["primary"]},{"code":"QTZ","name":"QTZ","statuses":["primary"]},{"code":"QRK","name":"Quark","statuses":["primary"]},{"code":"QTL","name":"Quatloo","statuses":["primary"]},{"code":"RADI","name":"RADI","statuses":["primary"]},{"code":"RADS","name":"Radium","statuses":["primary"]},{"code":"RED","name":"RED","statuses":["primary"]},{"code":"RDD","name":"Reddcoin","statuses":["primary"]},{"code":"REE","name":"REE","statuses":["primary"]},{"code":"REV","name":"Revenu","statuses":["primary"]},{"code":"RBR","name":"RibbitRewards","statuses":["primary"]},{"code":"RICHX","name":"RICHX","statuses":["primary"]},{"code":"RIC","name":"Riecoin","statuses":["primary"]},{"code":"RBT","name":"Rimbit","statuses":["primary"]},{"code":"RIO","name":"RIO","statuses":["primary"]},{"code":"XRP","name":"Ripple","statuses":["primary"]},{"code":"RISE","name":"RISE","statuses":["primary"]},{"code":"RMS","name":"RMS","statuses":["primary"]},{"code":"RONIN","name":"RONIN","statuses":["primary"]},{"code":"ROOT","name":"ROOT","statuses":["primary"]},{"code":"ROS","name":"RosCoin","statuses":["primary"]},{"code":"RPC","name":"RPC","statuses":["primary"]},{"code":"RBIES","name":"Rubies","statuses":["primary"]},{"code":"RUBIT","name":"RUBIT","statuses":["primary"]},{"code":"RUR","name":"Ruble","statuses":["secondary"]},{"code":"RBY","name":"Rubycoin","statuses":["primary"]},{"code":"RUST","name":"RUST","statuses":["primary"]},{"code":"SEC","name":"Safe Exchange Coin","statuses":["primary"]},{"code":"SAK","name":"SAK","statuses":["primary"]},{"code":"SAR","name":"SAR","statuses":["primary"]},{"code":"SBD","name":"SBD","statuses":["primary"]},{"code":"SBIT","name":"SBIT","statuses":["primary"]},{"code":"SCAN","name":"SCAN","statuses":["primary"]},{"code":"SCOT","name":"Scotcoin","statuses":["primary"]},{"code":"SCRPT","name":"SCRPT","statuses":["primary"]},{"code":"SCRT","name":"SCRT","statuses":["primary"]},{"code":"SRC","name":"SecureCoin","statuses":["primary"]},{"code":"SXC","name":"Sexcoin","statuses":["primary"]},{"code":"SFE","name":"SFE","statuses":["primary"]},{"code":"SFR","name":"SFR","statuses":["primary"]},{"code":"SGD","name":"SGD","statuses":["primary","secondary"]},{"code":"SDC","name":"ShadowCash","statuses":["primary"]},{"code":"SHELL","name":"SHELL","statuses":["primary"]},{"code":"SHF","name":"SHF","statuses":["primary"]},{"code":"SHI","name":"SHI","statuses":["primary"]},{"code":"SHIFT","name":"Shift","statuses":["primary"]},{"code":"SHREK","name":"SHREK","statuses":["primary"]},{"code":"SC","name":"Siacoin","statuses":["primary"]},{"code":"SIB","name":"Siberian chervonets","statuses":["primary"]},{"code":"SIC","name":"SIC","statuses":["primary"]},{"code":"SIGU","name":"SIGU","statuses":["primary"]},{"code":"SILK","name":"Silkcoin","statuses":["primary"]},{"code":"SIX","name":"SIX","statuses":["primary"]},{"code":"SLING","name":"Sling","statuses":["primary"]},{"code":"SLS","name":"SLS","statuses":["primary"]},{"code":"SMBR","name":"SMBR","statuses":["primary"]},{"code":"SMC","name":"SMC","statuses":["primary"]},{"code":"SMLY","name":"SmileyCoin","statuses":["primary"]},{"code":"SNRG","name":"SNRG","statuses":["primary"]},{"code":"SOIL","name":"SOILcoin","statuses":["primary"]},{"code":"SLR","name":"Solarcoin","statuses":["primary"]},{"code":"SOLO","name":"SOLO","statuses":["primary"]},{"code":"SONG","name":"SongCoin","statuses":["primary"]},{"code":"SOON","name":"SOON","statuses":["primary"]},{"code":"SPC","name":"SPC","statuses":["primary"]},{"code":"SPEX","name":"SPEX","statuses":["primary"]},{"code":"SPHR","name":"Sphere","statuses":["primary"]},{"code":"SPM","name":"SPM","statuses":["primary"]},{"code":"SPN","name":"SPN","statuses":["primary"]},{"code":"SPOTS","name":"SPOTS","statuses":["primary"]},{"code":"SPR","name":"SpreadCoin","statuses":["primary"]},{"code":"SPRTS","name":"Sprouts","statuses":["primary"]},{"code":"SQC","name":"SQC","statuses":["primary"]},{"code":"SSC","name":"SSC","statuses":["primary"]},{"code":"SSTC","name":"SSTC","statuses":["primary"]},{"code":"STA","name":"STA","statuses":["primary"]},{"code":"START","name":"Startcoin","statuses":["primary"]},{"code":"XST","name":"Stealthcoin","statuses":["primary"]},{"code":"STEEM","name":"Steem","statuses":["primary"]},{"code":"XLM","name":"Stellar","statuses":["primary"]},{"code":"STR","name":"Stellar","statuses":["primary"]},{"code":"STEPS","name":"Steps","statuses":["primary"]},{"code":"SLG","name":"Sterlingcoin","statuses":["primary"]},{"code":"STL","name":"STL","statuses":["primary"]},{"code":"SJCX","name":"Storjcoin X","statuses":["primary"]},{"code":"STP","name":"STP","statuses":["primary"]},{"code":"STRB","name":"STRB","statuses":["primary"]},{"code":"STS","name":"Stress","statuses":["primary"]},{"code":"STRP","name":"STRP","statuses":["primary"]},{"code":"STV","name":"STV","statuses":["primary"]},{"code":"SUB","name":"Subcriptio","statuses":["primary"]},{"code":"SUPER","name":"SUPER","statuses":["primary"]},{"code":"UNITY","name":"SuperNET","statuses":["primary"]},{"code":"SWARM","name":"Swarm","statuses":["primary"]},{"code":"SWING","name":"SWING","statuses":["primary"]},{"code":"SDP","name":"SydPak Coin","statuses":["primary"]},{"code":"SYNC","name":"SYNC","statuses":["primary"]},{"code":"AMP","name":"Synereo","statuses":["primary"]},{"code":"SYS","name":"Syscoin","statuses":["primary"]},{"code":"TAG","name":"TagCoin","statuses":["primary"]},{"code":"TAJ","name":"TAJ","statuses":["primary"]},{"code":"TAK","name":"TAK","statuses":["primary"]},{"code":"TAM","name":"TAM","statuses":["primary"]},{"code":"TAO","name":"TAO","statuses":["primary"]},{"code":"TBC","name":"TBC","statuses":["primary"]},{"code":"TBCX","name":"TBCX","statuses":["primary"]},{"code":"TCR","name":"TCR","statuses":["primary"]},{"code":"TDFB","name":"TDFB","statuses":["primary"]},{"code":"TDY","name":"TDY","statuses":["primary"]},{"code":"TEK","name":"TEKcoin","statuses":["primary"]},{"code":"TRC","name":"Terracoin","statuses":["primary"]},{"code":"TESLA","name":"TESLA","statuses":["primary"]},{"code":"TES","name":"TeslaCoin","statuses":["primary"]},{"code":"TET","name":"TET","statuses":["primary"]},{"code":"USDT","name":"Tether","statuses":["primary","secondary"]},{"code":"THC","name":"THC","statuses":["primary"]},{"code":"THS","name":"THS","statuses":["primary"]},{"code":"TIX","name":"Tickets","statuses":["primary"]},{"code":"XTC","name":"TileCoin","statuses":["primary"]},{"code":"TIT","name":"Titcoin","statuses":["primary"]},{"code":"TTC","name":"TittieCoin","statuses":["primary"]},{"code":"TMC","name":"TMC","statuses":["primary"]},{"code":"TODAY","name":"TODAY","statuses":["primary"]},{"code":"TOKEN","name":"TOKEN","statuses":["primary"]},{"code":"TP1","name":"TP1","statuses":["primary"]},{"code":"TPC","name":"TPC","statuses":["primary"]},{"code":"TPG","name":"TPG","statuses":["primary"]},{"code":"TX","name":"Transfercoin","statuses":["primary"]},{"code":"TRAP","name":"TRAP","statuses":["primary"]},{"code":"TRICK","name":"TRICK","statuses":["primary"]},{"code":"TROLL","name":"TROLL","statuses":["primary"]},{"code":"TRK","name":"Truckcoin","statuses":["primary"]},{"code":"TRUMP","name":"TrumpCoin","statuses":["primary"]},{"code":"TRUST","name":"TRUST","statuses":["primary"]},{"code":"UAE","name":"UAE","statuses":["primary"]},{"code":"UFO","name":"UFO Coin","statuses":["primary"]},{"code":"UIS","name":"UIS","statuses":["primary"]},{"code":"UTC","name":"UltraCoin","statuses":["primary"]},{"code":"UNC","name":"UNC","statuses":["primary"]},{"code":"UNIQ","name":"UNIQ","statuses":["primary"]},{"code":"UNIT","name":"Universal Currency","statuses":["primary"]},{"code":"UNO","name":"Unobtanium","statuses":["primary"]},{"code":"URO","name":"Uro","statuses":["primary"]},{"code":"USD","name":"US Dollar","statuses":["primary","secondary"]},{"code":"USDE","name":"USDE","statuses":["primary"]},{"code":"UTH","name":"UTH","statuses":["primary"]},{"code":"VAL","name":"VAL","statuses":["primary"]},{"code":"XVC","name":"Vcash","statuses":["primary"]},{"code":"VCN","name":"VCN","statuses":["primary"]},{"code":"VEG","name":"VEG","statuses":["primary"]},{"code":"VENE","name":"VENE","statuses":["primary"]},{"code":"XVG","name":"Verge","statuses":["primary"]},{"code":"VRC","name":"VeriCoin","statuses":["primary"]},{"code":"VTC","name":"Vertcoin","statuses":["primary"]},{"code":"VIA","name":"Viacoin","statuses":["primary"]},{"code":"VIOR","name":"Viorcoin","statuses":["primary"]},{"code":"VIP","name":"VIP Tokens","statuses":["primary"]},{"code":"VIRAL","name":"Viral","statuses":["primary"]},{"code":"VOOT","name":"VootCoin","statuses":["primary"]},{"code":"VOX","name":"Voxels","statuses":["primary"]},{"code":"VOYA","name":"VOYA","statuses":["primary"]},{"code":"VPN","name":"VPNCoin","statuses":["primary"]},{"code":"VPRC","name":"VPRC","statuses":["primary"]},{"code":"VTA","name":"VTA","statuses":["primary"]},{"code":"VTN","name":"VTN","statuses":["primary"]},{"code":"VTR","name":"VTR","statuses":["primary"]},{"code":"WAC","name":"WAC","statuses":["primary"]},{"code":"WARP","name":"WARP","statuses":["primary"]},{"code":"WAVES","name":"WAVES","statuses":["primary"]},{"code":"WGC","name":"WGC","statuses":["primary"]},{"code":"XWC","name":"Whitecoin","statuses":["primary"]},{"code":"WBB","name":"Wild Beast Block","statuses":["primary"]},{"code":"WLC","name":"WLC","statuses":["primary"]},{"code":"WMC","name":"WMC","statuses":["primary"]},{"code":"LOG","name":"Woodcoin","statuses":["primary"]},{"code":"WOP","name":"WOP","statuses":["primary"]},{"code":"WDC","name":"Worldcoin","statuses":["primary"]},{"code":"XAB","name":"XAB","statuses":["primary"]},{"code":"XAI","name":"XAI","statuses":["primary"]},{"code":"XAU","name":"Xaurum","statuses":["primary"]},{"code":"XBS","name":"XBS","statuses":["primary"]},{"code":"XBU","name":"XBU","statuses":["primary"]},{"code":"XCO","name":"XCO","statuses":["primary"]},{"code":"XC","name":"XCurrency","statuses":["primary"]},{"code":"XDB","name":"XDB","statuses":["primary"]},{"code":"XEMP","name":"XEMP","statuses":["primary"]},{"code":"XFC","name":"XFC","statuses":["primary"]},{"code":"MI","name":"Xiaomicoin","statuses":["primary"]},{"code":"XID","name":"XID","statuses":["primary"]},{"code":"XJO","name":"XJO","statuses":["primary"]},{"code":"XLTCG","name":"XLTCG","statuses":["primary"]},{"code":"XMS","name":"XMS","statuses":["primary"]},{"code":"XNX","name":"XNX","statuses":["primary"]},{"code":"XPD","name":"XPD","statuses":["primary"]},{"code":"XPOKE","name":"XPOKE","statuses":["primary"]},{"code":"XPRO","name":"XPRO","statuses":["primary"]},{"code":"XQN","name":"XQN","statuses":["primary"]},{"code":"XSEED","name":"XSEED","statuses":["primary"]},{"code":"XSP","name":"XSP","statuses":["primary"]},{"code":"XT","name":"XT","statuses":["primary"]},{"code":"XTP","name":"XTP","statuses":["primary"]},{"code":"XUSD","name":"XUSD","statuses":["primary"]},{"code":"YACC","name":"YACC","statuses":["primary"]},{"code":"YAC","name":"Yacoin","statuses":["primary"]},{"code":"YAY","name":"YAY","statuses":["primary"]},{"code":"YBC","name":"Ybcoin","statuses":["primary"]},{"code":"YOC","name":"YOC","statuses":["primary"]},{"code":"YOVI","name":"YOVI","statuses":["primary"]},{"code":"YUM","name":"YUM","statuses":["primary"]},{"code":"ZCC","name":"ZCC","statuses":["primary"]},{"code":"ZEIT","name":"Zeitcoin","statuses":["primary"]},{"code":"ZET","name":"Zetacoin","statuses":["primary"]},{"code":"ZRC","name":"ZiftrCOIN","statuses":["primary"]},{"code":"ZMC","name":"ZMC","statuses":["primary"]},{"code":"ZNY","name":"ZNY","statuses":["primary"]},{"code":"ZS","name":"ZS","statuses":["primary"]}]} \ No newline at end of file -- cgit From 6c01b26845cfb8e113d3016ebd595a9098623f62 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 11 May 2017 10:46:17 +0200 Subject: use asyncQ.waterfall instead of asyncQ.eachSeries --- app/scripts/lib/migrator/index.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index caa0ef318..0bf88dbec 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -14,9 +14,15 @@ class Migrator { migrateData (versionedData = this.generateInitialState()) { const remaining = this.migrations.filter(migrationIsPending) if (remaining.length === 0) return versionedData + + const migrations = remaining.map((migration, i) => { + if (i === 0) return this.runMigration.bind(this, migration, versionedData) + return this.runMigration.bind(this, migration) + }) + return ( - asyncQ.eachSeries(remaining, (migration) => this.runMigration(versionedData, migration)) - .then((migratedData) => migratedData.pop()) + asyncQ.waterfall(migrations) + .then((migratedData) => Promise.resolve(migratedData)) ) // migration is "pending" if hit has a higher @@ -26,10 +32,10 @@ class Migrator { } } - runMigration (versionedData, migration) { + runMigration (migration, versionedData) { return migration.migrate(versionedData) .then((migratedData) => { - if (!migratedData.data) return Promise.reject(new Error('Migrator - Migration returned empty data')) + if (!migratedData.data) return Promise.reject(new Error('Migrator - migration returned empty data')) if (migration.version !== undefined && migratedData.meta.version !== migration.version) return Promise.reject(new Error('Migrator - Migration did not update version number correctly')) return Promise.resolve(migratedData) -- cgit From 70a328e028230f8bffbd88a28d961fde6a4b819f Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 11 May 2017 18:15:59 -0700 Subject: migrator - cleaner migration runner with es7 --- app/scripts/lib/migrator/index.js | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index 0bf88dbec..ed07a0c60 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -1,47 +1,35 @@ -const asyncQ = require('async-q') - class Migrator { constructor (opts = {}) { const migrations = opts.migrations || [] + // sort migrations by version this.migrations = migrations.sort((a, b) => a.version - b.version) + // grab migration with highest version const lastMigration = this.migrations.slice(-1)[0] // use specified defaultVersion or highest migration version this.defaultVersion = opts.defaultVersion || (lastMigration && lastMigration.version) || 0 } // run all pending migrations on meta in place - migrateData (versionedData = this.generateInitialState()) { - const remaining = this.migrations.filter(migrationIsPending) - if (remaining.length === 0) return versionedData - - const migrations = remaining.map((migration, i) => { - if (i === 0) return this.runMigration.bind(this, migration, versionedData) - return this.runMigration.bind(this, migration) - }) + async migrateData (versionedData = this.generateInitialState()) { + const pendingMigrations = this.migrations.filter(migrationIsPending) + + for (let index in pendingMigrations) { + let migration = pendingMigrations[index] + versionedData = await migration.migrate(versionedData) + if (!versionedData.data) throw new Error('Migrator - migration returned empty data') + if (versionedData.version !== undefined && migratedData.meta.version !== migration.version) throw new Error('Migrator - Migration did not update version number correctly') + } - return ( - asyncQ.waterfall(migrations) - .then((migratedData) => Promise.resolve(migratedData)) - ) + return versionedData - // migration is "pending" if hit has a higher + // migration is "pending" if it has a higher // version number than currentVersion function migrationIsPending (migration) { return migration.version > versionedData.meta.version } } - runMigration (migration, versionedData) { - return migration.migrate(versionedData) - .then((migratedData) => { - if (!migratedData.data) return Promise.reject(new Error('Migrator - migration returned empty data')) - if (migration.version !== undefined && migratedData.meta.version !== migration.version) return Promise.reject(new Error('Migrator - Migration did not update version number correctly')) - - return Promise.resolve(migratedData) - }) - } - generateInitialState (initState) { return { meta: { -- cgit From 2c8bbe3b25c726b8a0cebb572c3c9d962136a693 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 12 May 2017 12:27:40 -0700 Subject: migrator - fix typo --- app/scripts/lib/migrator/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/migrator/index.js b/app/scripts/lib/migrator/index.js index ed07a0c60..de6f5d5cd 100644 --- a/app/scripts/lib/migrator/index.js +++ b/app/scripts/lib/migrator/index.js @@ -18,7 +18,7 @@ class Migrator { let migration = pendingMigrations[index] versionedData = await migration.migrate(versionedData) if (!versionedData.data) throw new Error('Migrator - migration returned empty data') - if (versionedData.version !== undefined && migratedData.meta.version !== migration.version) throw new Error('Migrator - Migration did not update version number correctly') + if (versionedData.version !== undefined && versionedData.meta.version !== migration.version) throw new Error('Migrator - Migration did not update version number correctly') } return versionedData -- cgit From 5c9449dec1a4662ebb3e1ce18ede018a9e874c39 Mon Sep 17 00:00:00 2001 From: kumavis Date: Fri, 12 May 2017 13:09:23 -0700 Subject: background - drop async-q in favor of async/await --- app/scripts/background.js | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index 58f8e7556..e738a9712 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -1,6 +1,5 @@ const urlUtil = require('url') const endOfStream = require('end-of-stream') -const asyncQ = require('async-q') const pipe = require('pump') const LocalStorageStore = require('obs-store/lib/localStorage') const storeTransform = require('obs-store/lib/transform') @@ -30,34 +29,29 @@ let popupIsOpen = false const diskStore = new LocalStorageStore({ storageKey: STORAGE_KEY }) // initialization flow -asyncQ.waterfall([ - () => loadStateFromPersistence(), - (initState) => setupController(initState), -]) -.then(() => console.log('MetaMask initialization complete.')) -.catch((err) => { console.error(err) }) +initialize().catch(console.error) + +async function initialize() { + const initState = await loadStateFromPersistence() + await setupController(initState) + console.log('MetaMask initialization complete.') +} // // State and Persistence // -function loadStateFromPersistence () { +async function loadStateFromPersistence () { // migrations const migrator = new Migrator({ migrations }) - const initialState = migrator.generateInitialState(firstTimeState) - return asyncQ.waterfall([ - // read from disk - () => Promise.resolve(diskStore.getState() || initialState), - // migrate data - (versionedData) => migrator.migrateData(versionedData), - // write to disk - (versionedData) => { - diskStore.putState(versionedData) - return Promise.resolve(versionedData) - }, - // resolve to just data - (versionedData) => Promise.resolve(versionedData.data), - ]) + // read from disk + let versionedData = diskStore.getState() || migrator.generateInitialState(firstTimeState) + // migrate data + versionedData = await migrator.migrateData(versionedData) + // write to disk + diskStore.putState(versionedData) + // return just the data + return versionedData.data } function setupController (initState) { -- cgit From 4c10e2021aa0cdc4f34a22368a37c76e0e1fea22 Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Mon, 15 May 2017 18:05:11 -0700 Subject: Change default network to rinkeby --- app/scripts/config.js | 6 +++--- app/scripts/lib/config-manager.js | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'app') diff --git a/app/scripts/config.js b/app/scripts/config.js index 391c67230..67067cfd7 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -1,7 +1,7 @@ const MAINET_RPC_URL = 'https://mainnet.infura.io/metamask' -const TESTNET_RPC_URL = 'https://ropsten.infura.io/metamask' +const TESTNET_RPC_URL = 'https://rinkeby.infura.io/metamask' const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask' -const RINKEBY_RPC_URL = 'https://rinkeby.infura.io/metamask' +const ROPSTEN_RPC_URL = 'https://ropsten.infura.io/metamask' const DEFAULT_RPC_URL = TESTNET_RPC_URL global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' @@ -13,6 +13,6 @@ module.exports = { testnet: TESTNET_RPC_URL, morden: TESTNET_RPC_URL, kovan: KOVAN_RPC_URL, - rinkeby: RINKEBY_RPC_URL, + ropsten: ROPSTEN_RPC_URL, }, } diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index ab9410842..4ca02135a 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -6,7 +6,7 @@ const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet const MORDEN_RPC = MetamaskConfig.network.morden const KOVAN_RPC = MetamaskConfig.network.kovan -const RINKEBY_RPC = MetamaskConfig.network.rinkeby +const ROPSTEN_RPC = MetamaskConfig.network.ropsten /* The config-manager is a convenience object @@ -147,8 +147,8 @@ ConfigManager.prototype.getCurrentRpcAddress = function () { case 'mainnet': return MAINNET_RPC - case 'testnet': - return TESTNET_RPC + case 'ropsten': + return ROPSTEN_RPC case 'morden': return MORDEN_RPC @@ -156,8 +156,8 @@ ConfigManager.prototype.getCurrentRpcAddress = function () { case 'kovan': return KOVAN_RPC - case 'rinkeby': - return RINKEBY_RPC + case 'testnet': + return TESTNET_RPC default: return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC -- cgit From 3367363b1234a076695758762d7f1220fe4a7f8c Mon Sep 17 00:00:00 2001 From: Thomas Huang Date: Mon, 15 May 2017 19:11:16 -0700 Subject: Remove all traces of testnet --- app/scripts/config.js | 11 ++++------- app/scripts/first-time-state.js | 2 +- app/scripts/lib/config-manager.js | 15 +++++---------- 3 files changed, 10 insertions(+), 18 deletions(-) (limited to 'app') diff --git a/app/scripts/config.js b/app/scripts/config.js index 67067cfd7..8e28db80e 100644 --- a/app/scripts/config.js +++ b/app/scripts/config.js @@ -1,18 +1,15 @@ const MAINET_RPC_URL = 'https://mainnet.infura.io/metamask' -const TESTNET_RPC_URL = 'https://rinkeby.infura.io/metamask' -const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask' const ROPSTEN_RPC_URL = 'https://ropsten.infura.io/metamask' -const DEFAULT_RPC_URL = TESTNET_RPC_URL +const KOVAN_RPC_URL = 'https://kovan.infura.io/metamask' +const RINKEBY_RPC_URL = 'https://rinkeby.infura.io/metamask' global.METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' module.exports = { network: { - default: DEFAULT_RPC_URL, mainnet: MAINET_RPC_URL, - testnet: TESTNET_RPC_URL, - morden: TESTNET_RPC_URL, - kovan: KOVAN_RPC_URL, ropsten: ROPSTEN_RPC_URL, + kovan: KOVAN_RPC_URL, + rinkeby: RINKEBY_RPC_URL, }, } diff --git a/app/scripts/first-time-state.js b/app/scripts/first-time-state.js index 87a7bb7b5..29ec1d8d3 100644 --- a/app/scripts/first-time-state.js +++ b/app/scripts/first-time-state.js @@ -5,7 +5,7 @@ module.exports = { config: { provider: { - type: 'testnet', + type: 'rinkeby', }, }, } diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 4ca02135a..d77cd2126 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -2,12 +2,10 @@ const MetamaskConfig = require('../config.js') const ethUtil = require('ethereumjs-util') const normalize = require('eth-sig-util').normalize -const TESTNET_RPC = MetamaskConfig.network.testnet const MAINNET_RPC = MetamaskConfig.network.mainnet -const MORDEN_RPC = MetamaskConfig.network.morden -const KOVAN_RPC = MetamaskConfig.network.kovan const ROPSTEN_RPC = MetamaskConfig.network.ropsten - +const KOVAN_RPC = MetamaskConfig.network.kovan +const RINKEBY_RPC = MetamaskConfig.network.rinkeby /* The config-manager is a convenience object * wrapping a pojo-migrator. @@ -150,17 +148,14 @@ ConfigManager.prototype.getCurrentRpcAddress = function () { case 'ropsten': return ROPSTEN_RPC - case 'morden': - return MORDEN_RPC - case 'kovan': return KOVAN_RPC - case 'testnet': - return TESTNET_RPC + case 'rinkeby': + return RINKEBY_RPC default: - return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC + return provider && provider.rpcTarget ? provider.rpcTarget : RINKEBY_RPC } } -- cgit From 28aba6e9dea52b66534d6ecb9713a7d20947c57c Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 15 May 2017 23:56:13 -0700 Subject: migration 13 - change provider from testnet to ropsten --- app/scripts/migrations/013.js | 34 ++++++++++++++++++++++++++++++++++ app/scripts/migrations/index.js | 1 + 2 files changed, 35 insertions(+) create mode 100644 app/scripts/migrations/013.js (limited to 'app') diff --git a/app/scripts/migrations/013.js b/app/scripts/migrations/013.js new file mode 100644 index 000000000..8f11e510e --- /dev/null +++ b/app/scripts/migrations/013.js @@ -0,0 +1,34 @@ +const version = 13 + +/* + +This migration modifies the network config from ambiguous 'testnet' to explicit 'ropsten' + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + if (newState.config.provider.type === 'testnet') { + newState.config.provider.type = 'ropsten' + } + return newState +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 019b4d13d..3a95cf88e 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -23,4 +23,5 @@ module.exports = [ require('./010'), require('./011'), require('./012'), + require('./013'), ] -- cgit From 2df9344be5bf1c65daae2ca7ea47982fe2a1c2fb Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 May 2017 10:27:41 -0700 Subject: Rename tx manager to tx controller --- app/scripts/background.js | 4 +- app/scripts/controllers/transactions.js | 404 ++++++++++++++++++++++++++++++++ app/scripts/metamask-controller.js | 32 +-- app/scripts/transaction-manager.js | 404 -------------------------------- 4 files changed, 422 insertions(+), 422 deletions(-) create mode 100644 app/scripts/controllers/transactions.js delete mode 100644 app/scripts/transaction-manager.js (limited to 'app') diff --git a/app/scripts/background.js b/app/scripts/background.js index e738a9712..63c8a7252 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -114,13 +114,13 @@ function setupController (initState) { // updateBadge() - controller.txManager.on('updateBadge', updateBadge) + controller.txController.on('updateBadge', updateBadge) controller.messageManager.on('updateBadge', updateBadge) // plugin badge text function updateBadge () { var label = '' - var unapprovedTxCount = controller.txManager.unapprovedTxCount + var unapprovedTxCount = controller.txController.unapprovedTxCount var unapprovedMsgCount = controller.messageManager.unapprovedMsgCount var count = unapprovedTxCount + unapprovedMsgCount if (count) { diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js new file mode 100644 index 000000000..9f267160f --- /dev/null +++ b/app/scripts/controllers/transactions.js @@ -0,0 +1,404 @@ +const EventEmitter = require('events') +const async = require('async') +const extend = require('xtend') +const Semaphore = require('semaphore') +const ObservableStore = require('obs-store') +const ethUtil = require('ethereumjs-util') +const EthQuery = require('eth-query') +const TxProviderUtil = require('./lib/tx-utils') +const createId = require('./lib/random-id') + +module.exports = class TransactionManager extends EventEmitter { + constructor (opts) { + super() + this.store = new ObservableStore(extend({ + transactions: [], + }, opts.initState)) + this.memStore = new ObservableStore({}) + this.networkStore = opts.networkStore || new ObservableStore({}) + this.preferencesStore = opts.preferencesStore || new ObservableStore({}) + this.txHistoryLimit = opts.txHistoryLimit + this.provider = opts.provider + this.blockTracker = opts.blockTracker + this.query = new EthQuery(this.provider) + this.txProviderUtils = new TxProviderUtil(this.provider) + this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) + this.signEthTx = opts.signTransaction + this.nonceLock = Semaphore(1) + + // memstore is computed from a few different stores + this._updateMemstore() + this.store.subscribe(() => this._updateMemstore()) + this.networkStore.subscribe(() => this._updateMemstore()) + this.preferencesStore.subscribe(() => this._updateMemstore()) + } + + getState () { + return this.memStore.getState() + } + + getNetwork () { + return this.networkStore.getState().network + } + + getSelectedAddress () { + return this.preferencesStore.getState().selectedAddress + } + + // Returns the tx list + getTxList () { + const network = this.getNetwork() + const fullTxList = this.getFullTxList() + return fullTxList.filter(txMeta => txMeta.metamaskNetworkId === network) + } + + // Returns the number of txs for the current network. + getTxCount () { + return this.getTxList().length + } + + // Returns the full tx list across all networks + getFullTxList () { + return this.store.getState().transactions + } + + // Adds a tx to the txlist + addTx (txMeta) { + const txCount = this.getTxCount() + const network = this.getNetwork() + const fullTxList = this.getFullTxList() + const txHistoryLimit = this.txHistoryLimit + + // checks if the length of the tx history is + // longer then desired persistence limit + // and then if it is removes only confirmed + // or rejected tx's. + // not tx's that are pending or unapproved + if (txCount > txHistoryLimit - 1) { + var index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) + fullTxList.splice(index, 1) + } + fullTxList.push(txMeta) + this._saveTxList(fullTxList) + this.emit('update') + + this.once(`${txMeta.id}:signed`, function (txId) { + this.removeAllListeners(`${txMeta.id}:rejected`) + }) + this.once(`${txMeta.id}:rejected`, function (txId) { + this.removeAllListeners(`${txMeta.id}:signed`) + }) + + this.emit('updateBadge') + this.emit(`${txMeta.id}:unapproved`, txMeta) + } + + // gets tx by Id and returns it + getTx (txId, cb) { + var txList = this.getTxList() + var txMeta = txList.find(txData => txData.id === txId) + return cb ? cb(txMeta) : txMeta + } + + // + updateTx (txMeta) { + var txId = txMeta.id + var txList = this.getFullTxList() + var index = txList.findIndex(txData => txData.id === txId) + txList[index] = txMeta + this._saveTxList(txList) + this.emit('update') + } + + get unapprovedTxCount () { + return Object.keys(this.getUnapprovedTxList()).length + } + + get pendingTxCount () { + return this.getTxsByMetaData('status', 'signed').length + } + + addUnapprovedTransaction (txParams, done) { + let txMeta + async.waterfall([ + // validate + (cb) => this.txProviderUtils.validateTxParams(txParams, cb), + // construct txMeta + (cb) => { + txMeta = { + id: createId(), + time: (new Date()).getTime(), + status: 'unapproved', + metamaskNetworkId: this.getNetwork(), + txParams: txParams, + } + cb() + }, + // add default tx params + (cb) => this.addTxDefaults(txMeta, cb), + // save txMeta + (cb) => { + this.addTx(txMeta) + cb(null, txMeta) + }, + ], done) + } + + addTxDefaults (txMeta, cb) { + const txParams = txMeta.txParams + // ensure value + txParams.value = txParams.value || '0x0' + this.query.gasPrice((err, gasPrice) => { + if (err) return cb(err) + // set gasPrice + txParams.gasPrice = gasPrice + // set gasLimit + this.txProviderUtils.analyzeGasUsage(txMeta, cb) + }) + } + + getUnapprovedTxList () { + var txList = this.getTxList() + return txList.filter((txMeta) => txMeta.status === 'unapproved') + .reduce((result, tx) => { + result[tx.id] = tx + return result + }, {}) + } + + approveTransaction (txId, cb = warn) { + const self = this + // approve + self.setTxStatusApproved(txId) + // only allow one tx at a time for atomic nonce usage + self.nonceLock.take(() => { + // begin signature process + async.waterfall([ + (cb) => self.fillInTxParams(txId, cb), + (cb) => self.signTransaction(txId, cb), + (rawTx, cb) => self.publishTransaction(txId, rawTx, cb), + ], (err) => { + self.nonceLock.leave() + if (err) { + this.setTxStatusFailed(txId, { + errCode: err.errCode || err, + message: err.message || 'Transaction failed during approval', + }) + return cb(err) + } + cb() + }) + }) + } + + cancelTransaction (txId, cb = warn) { + this.setTxStatusRejected(txId) + cb() + } + + fillInTxParams (txId, cb) { + const txMeta = this.getTx(txId) + this.txProviderUtils.fillInTxParams(txMeta.txParams, (err) => { + if (err) return cb(err) + this.updateTx(txMeta) + cb() + }) + } + + getChainId () { + const networkState = this.networkStore.getState() + const getChainId = parseInt(networkState.network) + if (Number.isNaN(getChainId)) { + return 0 + } else { + return getChainId + } + } + + signTransaction (txId, cb) { + const txMeta = this.getTx(txId) + const txParams = txMeta.txParams + const fromAddress = txParams.from + // add network/chain id + txParams.chainId = this.getChainId() + const ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) + this.signEthTx(ethTx, fromAddress).then(() => { + this.setTxStatusSigned(txMeta.id) + cb(null, ethUtil.bufferToHex(ethTx.serialize())) + }).catch((err) => { + cb(err) + }) + } + + publishTransaction (txId, rawTx, cb) { + this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { + if (err) return cb(err) + this.setTxHash(txId, txHash) + this.setTxStatusSubmitted(txId) + cb() + }) + } + + // receives a txHash records the tx as signed + setTxHash (txId, txHash) { + // Add the tx hash to the persisted meta-tx object + const txMeta = this.getTx(txId) + txMeta.hash = txHash + this.updateTx(txMeta) + } + + /* + Takes an object of fields to search for eg: + var thingsToLookFor = { + to: '0x0..', + from: '0x0..', + status: 'signed', + } + and returns a list of tx with all + options matching + + this is for things like filtering a the tx list + for only tx's from 1 account + or for filltering for all txs from one account + and that have been 'confirmed' + */ + getFilteredTxList (opts) { + var filteredTxList + Object.keys(opts).forEach((key) => { + filteredTxList = this.getTxsByMetaData(key, opts[key], filteredTxList) + }) + return filteredTxList + } + + getTxsByMetaData (key, value, txList = this.getTxList()) { + return txList.filter((txMeta) => { + if (txMeta.txParams[key]) { + return txMeta.txParams[key] === value + } else { + return txMeta[key] === value + } + }) + } + + // STATUS METHODS + // get::set status + + // should return the status of the tx. + getTxStatus (txId) { + const txMeta = this.getTx(txId) + return txMeta.status + } + + // should update the status of the tx to 'rejected'. + setTxStatusRejected (txId) { + this._setTxStatus(txId, 'rejected') + } + + // should update the status of the tx to 'approved'. + setTxStatusApproved (txId) { + this._setTxStatus(txId, 'approved') + } + + // should update the status of the tx to 'signed'. + setTxStatusSigned (txId) { + this._setTxStatus(txId, 'signed') + } + + // should update the status of the tx to 'submitted'. + setTxStatusSubmitted (txId) { + this._setTxStatus(txId, 'submitted') + } + + // should update the status of the tx to 'confirmed'. + setTxStatusConfirmed (txId) { + this._setTxStatus(txId, 'confirmed') + } + + setTxStatusFailed (txId, reason) { + const txMeta = this.getTx(txId) + txMeta.err = reason + this.updateTx(txMeta) + this._setTxStatus(txId, 'failed') + } + + // merges txParams obj onto txData.txParams + // use extend to ensure that all fields are filled + updateTxParams (txId, txParams) { + var txMeta = this.getTx(txId) + txMeta.txParams = extend(txMeta.txParams, txParams) + this.updateTx(txMeta) + } + + // checks if a signed tx is in a block and + // if included sets the tx status as 'confirmed' + checkForTxInBlock () { + var signedTxList = this.getFilteredTxList({status: 'submitted'}) + if (!signedTxList.length) return + signedTxList.forEach((txMeta) => { + var txHash = txMeta.hash + var txId = txMeta.id + if (!txHash) { + const errReason = { + errCode: 'No hash was provided', + message: 'We had an error while submitting this transaction, please try again.', + } + return this.setTxStatusFailed(txId, errReason) + } + this.query.getTransactionByHash(txHash, (err, txParams) => { + if (err || !txParams) { + if (!txParams) return + txMeta.err = { + isWarning: true, + errorCode: err, + message: 'There was a problem loading this transaction.', + } + this.updateTx(txMeta) + return console.error(err) + } + if (txParams.blockNumber) { + this.setTxStatusConfirmed(txId) + } + }) + }) + } + + // PRIVATE METHODS + + // Should find the tx in the tx list and + // update it. + // should set the status in txData + // - `'unapproved'` the user has not responded + // - `'rejected'` the user has responded no! + // - `'approved'` the user has approved the tx + // - `'signed'` the tx is signed + // - `'submitted'` the tx is sent to a server + // - `'confirmed'` the tx has been included in a block. + _setTxStatus (txId, status) { + var txMeta = this.getTx(txId) + txMeta.status = status + this.emit(`${txMeta.id}:${status}`, txId) + if (status === 'submitted' || status === 'rejected') { + this.emit(`${txMeta.id}:finished`, txMeta) + } + this.updateTx(txMeta) + this.emit('updateBadge') + } + + // Saves the new/updated txList. + // Function is intended only for internal use + _saveTxList (transactions) { + this.store.updateState({ transactions }) + } + + _updateMemstore () { + const unapprovedTxs = this.getUnapprovedTxList() + const selectedAddressTxList = this.getFilteredTxList({ + from: this.getSelectedAddress(), + metamaskNetworkId: this.getNetwork(), + }) + this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) + } +} + + +const warn = () => console.warn('warn was used no cb provided') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 175602ec1..f18da9033 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -17,7 +17,7 @@ const ShapeShiftController = require('./controllers/shapeshift') const AddressBookController = require('./controllers/address-book') const MessageManager = require('./lib/message-manager') const PersonalMessageManager = require('./lib/personal-message-manager') -const TxManager = require('./transaction-manager') +const TransactionController = require('./controllers/transactions') const ConfigManager = require('./lib/config-manager') const autoFaucet = require('./lib/auto-faucet') const nodeify = require('./lib/nodeify') @@ -90,8 +90,8 @@ module.exports = class MetamaskController extends EventEmitter { }, this.keyringController) // tx mgmt - this.txManager = new TxManager({ - initState: initState.TransactionManager, + this.txController = new TransactionController({ + initState: initState.TransactionController || initState.TransactionManager, networkStore: this.networkStore, preferencesStore: this.preferencesController.store, txHistoryLimit: 40, @@ -119,8 +119,8 @@ module.exports = class MetamaskController extends EventEmitter { this.publicConfigStore = this.initPublicConfigStore() // manual disk state subscriptions - this.txManager.store.subscribe((state) => { - this.store.updateState({ TransactionManager: state }) + this.txController.store.subscribe((state) => { + this.store.updateState({ TransactionController: state }) }) this.keyringController.store.subscribe((state) => { this.store.updateState({ KeyringController: state }) @@ -144,7 +144,7 @@ module.exports = class MetamaskController extends EventEmitter { // manual mem state subscriptions this.networkStore.subscribe(this.sendUpdate.bind(this)) this.ethStore.subscribe(this.sendUpdate.bind(this)) - this.txManager.memStore.subscribe(this.sendUpdate.bind(this)) + this.txController.memStore.subscribe(this.sendUpdate.bind(this)) this.messageManager.memStore.subscribe(this.sendUpdate.bind(this)) this.personalMessageManager.memStore.subscribe(this.sendUpdate.bind(this)) this.keyringController.memStore.subscribe(this.sendUpdate.bind(this)) @@ -223,7 +223,7 @@ module.exports = class MetamaskController extends EventEmitter { }, this.networkStore.getState(), this.ethStore.getState(), - this.txManager.memStore.getState(), + this.txController.memStore.getState(), this.messageManager.memStore.getState(), this.personalMessageManager.memStore.getState(), this.keyringController.memStore.getState(), @@ -248,7 +248,7 @@ module.exports = class MetamaskController extends EventEmitter { getApi () { const keyringController = this.keyringController const preferencesController = this.preferencesController - const txManager = this.txManager + const txController = this.txController const noticeController = this.noticeController const addressBookController = this.addressBookController @@ -289,9 +289,9 @@ module.exports = class MetamaskController extends EventEmitter { saveAccountLabel: nodeify(keyringController.saveAccountLabel).bind(keyringController), exportAccount: nodeify(keyringController.exportAccount).bind(keyringController), - // txManager - approveTransaction: txManager.approveTransaction.bind(txManager), - cancelTransaction: txManager.cancelTransaction.bind(txManager), + // txController + approveTransaction: txController.approveTransaction.bind(txController), + cancelTransaction: txController.cancelTransaction.bind(txController), updateAndApproveTransaction: this.updateAndApproveTx.bind(this), // messageManager @@ -421,12 +421,12 @@ module.exports = class MetamaskController extends EventEmitter { newUnapprovedTransaction (txParams, cb) { log.debug(`MetaMaskController newUnapprovedTransaction ${JSON.stringify(txParams)}`) const self = this - self.txManager.addUnapprovedTransaction(txParams, (err, txMeta) => { + self.txController.addUnapprovedTransaction(txParams, (err, txMeta) => { if (err) return cb(err) self.sendUpdate() self.opts.showUnapprovedTx(txMeta) // listen for tx completion (success, fail) - self.txManager.once(`${txMeta.id}:finished`, (completedTx) => { + self.txController.once(`${txMeta.id}:finished`, (completedTx) => { switch (completedTx.status) { case 'submitted': return cb(null, completedTx.hash) @@ -477,9 +477,9 @@ module.exports = class MetamaskController extends EventEmitter { updateAndApproveTx (txMeta, cb) { log.debug(`MetaMaskController - updateAndApproveTx: ${JSON.stringify(txMeta)}`) - const txManager = this.txManager - txManager.updateTx(txMeta) - txManager.approveTransaction(txMeta.id, cb) + const txController = this.txController + txController.updateTx(txMeta) + txController.approveTransaction(txMeta.id, cb) } signMessage (msgParams, cb) { diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js deleted file mode 100644 index 9f267160f..000000000 --- a/app/scripts/transaction-manager.js +++ /dev/null @@ -1,404 +0,0 @@ -const EventEmitter = require('events') -const async = require('async') -const extend = require('xtend') -const Semaphore = require('semaphore') -const ObservableStore = require('obs-store') -const ethUtil = require('ethereumjs-util') -const EthQuery = require('eth-query') -const TxProviderUtil = require('./lib/tx-utils') -const createId = require('./lib/random-id') - -module.exports = class TransactionManager extends EventEmitter { - constructor (opts) { - super() - this.store = new ObservableStore(extend({ - transactions: [], - }, opts.initState)) - this.memStore = new ObservableStore({}) - this.networkStore = opts.networkStore || new ObservableStore({}) - this.preferencesStore = opts.preferencesStore || new ObservableStore({}) - this.txHistoryLimit = opts.txHistoryLimit - this.provider = opts.provider - this.blockTracker = opts.blockTracker - this.query = new EthQuery(this.provider) - this.txProviderUtils = new TxProviderUtil(this.provider) - this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) - this.signEthTx = opts.signTransaction - this.nonceLock = Semaphore(1) - - // memstore is computed from a few different stores - this._updateMemstore() - this.store.subscribe(() => this._updateMemstore()) - this.networkStore.subscribe(() => this._updateMemstore()) - this.preferencesStore.subscribe(() => this._updateMemstore()) - } - - getState () { - return this.memStore.getState() - } - - getNetwork () { - return this.networkStore.getState().network - } - - getSelectedAddress () { - return this.preferencesStore.getState().selectedAddress - } - - // Returns the tx list - getTxList () { - const network = this.getNetwork() - const fullTxList = this.getFullTxList() - return fullTxList.filter(txMeta => txMeta.metamaskNetworkId === network) - } - - // Returns the number of txs for the current network. - getTxCount () { - return this.getTxList().length - } - - // Returns the full tx list across all networks - getFullTxList () { - return this.store.getState().transactions - } - - // Adds a tx to the txlist - addTx (txMeta) { - const txCount = this.getTxCount() - const network = this.getNetwork() - const fullTxList = this.getFullTxList() - const txHistoryLimit = this.txHistoryLimit - - // checks if the length of the tx history is - // longer then desired persistence limit - // and then if it is removes only confirmed - // or rejected tx's. - // not tx's that are pending or unapproved - if (txCount > txHistoryLimit - 1) { - var index = fullTxList.findIndex((metaTx) => ((metaTx.status === 'confirmed' || metaTx.status === 'rejected') && network === txMeta.metamaskNetworkId)) - fullTxList.splice(index, 1) - } - fullTxList.push(txMeta) - this._saveTxList(fullTxList) - this.emit('update') - - this.once(`${txMeta.id}:signed`, function (txId) { - this.removeAllListeners(`${txMeta.id}:rejected`) - }) - this.once(`${txMeta.id}:rejected`, function (txId) { - this.removeAllListeners(`${txMeta.id}:signed`) - }) - - this.emit('updateBadge') - this.emit(`${txMeta.id}:unapproved`, txMeta) - } - - // gets tx by Id and returns it - getTx (txId, cb) { - var txList = this.getTxList() - var txMeta = txList.find(txData => txData.id === txId) - return cb ? cb(txMeta) : txMeta - } - - // - updateTx (txMeta) { - var txId = txMeta.id - var txList = this.getFullTxList() - var index = txList.findIndex(txData => txData.id === txId) - txList[index] = txMeta - this._saveTxList(txList) - this.emit('update') - } - - get unapprovedTxCount () { - return Object.keys(this.getUnapprovedTxList()).length - } - - get pendingTxCount () { - return this.getTxsByMetaData('status', 'signed').length - } - - addUnapprovedTransaction (txParams, done) { - let txMeta - async.waterfall([ - // validate - (cb) => this.txProviderUtils.validateTxParams(txParams, cb), - // construct txMeta - (cb) => { - txMeta = { - id: createId(), - time: (new Date()).getTime(), - status: 'unapproved', - metamaskNetworkId: this.getNetwork(), - txParams: txParams, - } - cb() - }, - // add default tx params - (cb) => this.addTxDefaults(txMeta, cb), - // save txMeta - (cb) => { - this.addTx(txMeta) - cb(null, txMeta) - }, - ], done) - } - - addTxDefaults (txMeta, cb) { - const txParams = txMeta.txParams - // ensure value - txParams.value = txParams.value || '0x0' - this.query.gasPrice((err, gasPrice) => { - if (err) return cb(err) - // set gasPrice - txParams.gasPrice = gasPrice - // set gasLimit - this.txProviderUtils.analyzeGasUsage(txMeta, cb) - }) - } - - getUnapprovedTxList () { - var txList = this.getTxList() - return txList.filter((txMeta) => txMeta.status === 'unapproved') - .reduce((result, tx) => { - result[tx.id] = tx - return result - }, {}) - } - - approveTransaction (txId, cb = warn) { - const self = this - // approve - self.setTxStatusApproved(txId) - // only allow one tx at a time for atomic nonce usage - self.nonceLock.take(() => { - // begin signature process - async.waterfall([ - (cb) => self.fillInTxParams(txId, cb), - (cb) => self.signTransaction(txId, cb), - (rawTx, cb) => self.publishTransaction(txId, rawTx, cb), - ], (err) => { - self.nonceLock.leave() - if (err) { - this.setTxStatusFailed(txId, { - errCode: err.errCode || err, - message: err.message || 'Transaction failed during approval', - }) - return cb(err) - } - cb() - }) - }) - } - - cancelTransaction (txId, cb = warn) { - this.setTxStatusRejected(txId) - cb() - } - - fillInTxParams (txId, cb) { - const txMeta = this.getTx(txId) - this.txProviderUtils.fillInTxParams(txMeta.txParams, (err) => { - if (err) return cb(err) - this.updateTx(txMeta) - cb() - }) - } - - getChainId () { - const networkState = this.networkStore.getState() - const getChainId = parseInt(networkState.network) - if (Number.isNaN(getChainId)) { - return 0 - } else { - return getChainId - } - } - - signTransaction (txId, cb) { - const txMeta = this.getTx(txId) - const txParams = txMeta.txParams - const fromAddress = txParams.from - // add network/chain id - txParams.chainId = this.getChainId() - const ethTx = this.txProviderUtils.buildEthTxFromParams(txParams) - this.signEthTx(ethTx, fromAddress).then(() => { - this.setTxStatusSigned(txMeta.id) - cb(null, ethUtil.bufferToHex(ethTx.serialize())) - }).catch((err) => { - cb(err) - }) - } - - publishTransaction (txId, rawTx, cb) { - this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { - if (err) return cb(err) - this.setTxHash(txId, txHash) - this.setTxStatusSubmitted(txId) - cb() - }) - } - - // receives a txHash records the tx as signed - setTxHash (txId, txHash) { - // Add the tx hash to the persisted meta-tx object - const txMeta = this.getTx(txId) - txMeta.hash = txHash - this.updateTx(txMeta) - } - - /* - Takes an object of fields to search for eg: - var thingsToLookFor = { - to: '0x0..', - from: '0x0..', - status: 'signed', - } - and returns a list of tx with all - options matching - - this is for things like filtering a the tx list - for only tx's from 1 account - or for filltering for all txs from one account - and that have been 'confirmed' - */ - getFilteredTxList (opts) { - var filteredTxList - Object.keys(opts).forEach((key) => { - filteredTxList = this.getTxsByMetaData(key, opts[key], filteredTxList) - }) - return filteredTxList - } - - getTxsByMetaData (key, value, txList = this.getTxList()) { - return txList.filter((txMeta) => { - if (txMeta.txParams[key]) { - return txMeta.txParams[key] === value - } else { - return txMeta[key] === value - } - }) - } - - // STATUS METHODS - // get::set status - - // should return the status of the tx. - getTxStatus (txId) { - const txMeta = this.getTx(txId) - return txMeta.status - } - - // should update the status of the tx to 'rejected'. - setTxStatusRejected (txId) { - this._setTxStatus(txId, 'rejected') - } - - // should update the status of the tx to 'approved'. - setTxStatusApproved (txId) { - this._setTxStatus(txId, 'approved') - } - - // should update the status of the tx to 'signed'. - setTxStatusSigned (txId) { - this._setTxStatus(txId, 'signed') - } - - // should update the status of the tx to 'submitted'. - setTxStatusSubmitted (txId) { - this._setTxStatus(txId, 'submitted') - } - - // should update the status of the tx to 'confirmed'. - setTxStatusConfirmed (txId) { - this._setTxStatus(txId, 'confirmed') - } - - setTxStatusFailed (txId, reason) { - const txMeta = this.getTx(txId) - txMeta.err = reason - this.updateTx(txMeta) - this._setTxStatus(txId, 'failed') - } - - // merges txParams obj onto txData.txParams - // use extend to ensure that all fields are filled - updateTxParams (txId, txParams) { - var txMeta = this.getTx(txId) - txMeta.txParams = extend(txMeta.txParams, txParams) - this.updateTx(txMeta) - } - - // checks if a signed tx is in a block and - // if included sets the tx status as 'confirmed' - checkForTxInBlock () { - var signedTxList = this.getFilteredTxList({status: 'submitted'}) - if (!signedTxList.length) return - signedTxList.forEach((txMeta) => { - var txHash = txMeta.hash - var txId = txMeta.id - if (!txHash) { - const errReason = { - errCode: 'No hash was provided', - message: 'We had an error while submitting this transaction, please try again.', - } - return this.setTxStatusFailed(txId, errReason) - } - this.query.getTransactionByHash(txHash, (err, txParams) => { - if (err || !txParams) { - if (!txParams) return - txMeta.err = { - isWarning: true, - errorCode: err, - message: 'There was a problem loading this transaction.', - } - this.updateTx(txMeta) - return console.error(err) - } - if (txParams.blockNumber) { - this.setTxStatusConfirmed(txId) - } - }) - }) - } - - // PRIVATE METHODS - - // Should find the tx in the tx list and - // update it. - // should set the status in txData - // - `'unapproved'` the user has not responded - // - `'rejected'` the user has responded no! - // - `'approved'` the user has approved the tx - // - `'signed'` the tx is signed - // - `'submitted'` the tx is sent to a server - // - `'confirmed'` the tx has been included in a block. - _setTxStatus (txId, status) { - var txMeta = this.getTx(txId) - txMeta.status = status - this.emit(`${txMeta.id}:${status}`, txId) - if (status === 'submitted' || status === 'rejected') { - this.emit(`${txMeta.id}:finished`, txMeta) - } - this.updateTx(txMeta) - this.emit('updateBadge') - } - - // Saves the new/updated txList. - // Function is intended only for internal use - _saveTxList (transactions) { - this.store.updateState({ transactions }) - } - - _updateMemstore () { - const unapprovedTxs = this.getUnapprovedTxList() - const selectedAddressTxList = this.getFilteredTxList({ - from: this.getSelectedAddress(), - metamaskNetworkId: this.getNetwork(), - }) - this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) - } -} - - -const warn = () => console.warn('warn was used no cb provided') -- cgit From 68d6ea44a0c9f3d75415ccadefe182f9a0872db1 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 16 May 2017 11:39:00 -0700 Subject: Fix path references --- app/scripts/controllers/transactions.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 9f267160f..21dd25b30 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -5,8 +5,8 @@ const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') const EthQuery = require('eth-query') -const TxProviderUtil = require('./lib/tx-utils') -const createId = require('./lib/random-id') +const TxProviderUtil = require('../lib/tx-utils') +const createId = require('../lib/random-id') module.exports = class TransactionManager extends EventEmitter { constructor (opts) { -- cgit From 2a25f99461c01ac9e0aec3d90f73675c58303860 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 17 May 2017 14:36:50 -0700 Subject: Version 3.6.5 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index a1f6d7855..31e4598c7 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.6.4", + "version": "3.6.5", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From f87ea49b5ac2d66d8f281f08f42e8cfd2d701ba7 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Thu, 18 May 2017 23:54:02 +0200 Subject: Create a network controller to manage switcing networks an updating the provider --- app/scripts/controllers/network.js | 152 +++++++++++++++++++++++++++++++++++++ app/scripts/keyring-controller.js | 6 ++ app/scripts/lib/config-manager.js | 67 ---------------- app/scripts/lib/tx-utils.js | 8 +- app/scripts/metamask-controller.js | 124 +++++++++++++----------------- app/scripts/transaction-manager.js | 25 ++++-- 6 files changed, 232 insertions(+), 150 deletions(-) create mode 100644 app/scripts/controllers/network.js (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js new file mode 100644 index 000000000..82eabb573 --- /dev/null +++ b/app/scripts/controllers/network.js @@ -0,0 +1,152 @@ +const EventEmitter = require('events') +const MetaMaskProvider = require('web3-provider-engine/zero.js') +const ObservableStore = require('obs-store') +const extend = require('xtend') +const EthQuery = require('eth-query') +const MetamaskConfig = require('../config.js') + +const TESTNET_RPC = MetamaskConfig.network.testnet +const MAINNET_RPC = MetamaskConfig.network.mainnet +const MORDEN_RPC = MetamaskConfig.network.morden +const KOVAN_RPC = MetamaskConfig.network.kovan +const RINKEBY_RPC = MetamaskConfig.network.rinkeby + +module.exports = class NetworkController extends EventEmitter { + constructor (providerOpts) { + super() + this.networkStore = new ObservableStore({ network: 'loading' }) + providerOpts.provider.rpcTarget = this.getRpcAddressForType(providerOpts.provider.type) + this.providerStore = new ObservableStore(providerOpts) + this._claimed = 0 + } + + getState () { + return extend({}, + this.networkStore.getState(), + this.providerStore.getState() + ) + } + + initializeProvider (opts) { + this.providerConfig = opts + this.provider = MetaMaskProvider(opts) + this.ethQuery = new EthQuery(this.provider) + this.lookupNetwork() + return Promise.resolve(this.provider) + } + switchNetwork (providerConfig) { + delete this.provider + delete this.ethQuery + const newConfig = extend(this.providerConfig, providerConfig) + this.providerConfig = newConfig + this.provider = MetaMaskProvider(newConfig) + this.ethQuery = new EthQuery(this.provider) + this.emit('networkSwitch', { + provider: this.provider, + ethQuery: this.ethQuery, + }, this.claim.bind(this)) + } + + subscribe (cb) { + this.networkStore.subscribe(cb) + this.providerStore.subscribe(cb) + } + + verifyNetwork () { + // Check network when restoring connectivity: + if (this.isNetworkLoading()) this.lookupNetwork() + } + + getNetworkState () { + return this.networkStore.getState().network + } + + setNetworkState (network) { + return this.networkStore.updateState({ network }) + } + + isNetworkLoading () { + return this.getNetworkState() === 'loading' + } + + lookupNetwork (err) { + if (err) this.setNetworkState('loading') + + this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { + if (err) return this.setNetworkState('loading') + + log.info('web3.getNetwork returned ' + network) + this.setNetworkState(network) + }) + } + + setRpcTarget (rpcUrl) { + this.providerStore.updateState({ + provider: { + type: 'rpc', + rpcTarget: rpcUrl, + }, + }) + } + + getCurrentRpcAddress () { + var provider = this.getProvider() + if (!provider) return null + return this.getRpcAddressForType(provider.type) + } + + setProviderType (type) { + if (type === this.getProvider().type) return + const rpcTarget = this.getRpcAddressForType(type) + this.networkStore.updateState({network: 'loading'}) + this.switchNetwork({ + rpcUrl: rpcTarget, + }) + this.once('claimed', () => { + this.providerStore.updateState({provider: {type, rpcTarget}}) + console.log('CLAIMED') + this.lookupNetwork() + }) + + } + + useEtherscanProvider () { + this.setProviderType('etherscan') + } + + getProvider () { + return this.providerStore.getState().provider + } + + getRpcAddressForType (type) { + const provider = this.getProvider() + switch (type) { + + case 'mainnet': + return MAINNET_RPC + + case 'testnet': + return TESTNET_RPC + + case 'morden': + return MORDEN_RPC + + case 'kovan': + return KOVAN_RPC + + case 'rinkeby': + return RINKEBY_RPC + + default: + return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC + } + } + + claim () { + this._claimed += 1 + if (this._claimed === this.listenerCount('networkSwitch')) { + this.emit('claimed') + this._claimed = 0 + } + } +} diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index 5b3c80e40..bb699ca8b 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -41,6 +41,12 @@ class KeyringController extends EventEmitter { this.getNetwork = opts.getNetwork } + setEthStore (ethStore) { + delete this.ethStore + this.ethStore = ethStore + return this.setupAccounts() + } + // Full Update // returns Promise( @object state ) // diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index ab9410842..1098cc474 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -1,14 +1,6 @@ -const MetamaskConfig = require('../config.js') const ethUtil = require('ethereumjs-util') const normalize = require('eth-sig-util').normalize -const TESTNET_RPC = MetamaskConfig.network.testnet -const MAINNET_RPC = MetamaskConfig.network.mainnet -const MORDEN_RPC = MetamaskConfig.network.morden -const KOVAN_RPC = MetamaskConfig.network.kovan -const RINKEBY_RPC = MetamaskConfig.network.rinkeby - - /* The config-manager is a convenience object * wrapping a pojo-migrator. * @@ -35,36 +27,6 @@ ConfigManager.prototype.getConfig = function () { return data.config } -ConfigManager.prototype.setRpcTarget = function (rpcUrl) { - var config = this.getConfig() - config.provider = { - type: 'rpc', - rpcTarget: rpcUrl, - } - this.setConfig(config) -} - -ConfigManager.prototype.setProviderType = function (type) { - var config = this.getConfig() - config.provider = { - type: type, - } - this.setConfig(config) -} - -ConfigManager.prototype.useEtherscanProvider = function () { - var config = this.getConfig() - config.provider = { - type: 'etherscan', - } - this.setConfig(config) -} - -ConfigManager.prototype.getProvider = function () { - var config = this.getConfig() - return config.provider -} - ConfigManager.prototype.setData = function (data) { this.store.putState(data) } @@ -139,35 +101,6 @@ ConfigManager.prototype.getSeedWords = function () { return data.seedWords } -ConfigManager.prototype.getCurrentRpcAddress = function () { - var provider = this.getProvider() - if (!provider) return null - switch (provider.type) { - - case 'mainnet': - return MAINNET_RPC - - case 'testnet': - return TESTNET_RPC - - case 'morden': - return MORDEN_RPC - - case 'kovan': - return KOVAN_RPC - - case 'rinkeby': - return RINKEBY_RPC - - default: - return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC - } -} - -// -// Tx -// - ConfigManager.prototype.getTxList = function () { var data = this.getData() if (data.transactions !== undefined) { diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 084ca3721..76b311653 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -1,5 +1,4 @@ const async = require('async') -const EthQuery = require('eth-query') const ethUtil = require('ethereumjs-util') const Transaction = require('ethereumjs-tx') const normalize = require('eth-sig-util').normalize @@ -7,15 +6,14 @@ const BN = ethUtil.BN /* tx-utils are utility methods for Transaction manager -its passed a provider and that is passed to ethquery +its passed ethquery and used to do things like calculate gas of a tx. */ module.exports = class txProviderUtils { - constructor (provider) { - this.provider = provider - this.query = new EthQuery(provider) + constructor (ethQuery) { + this.query = ethQuery } analyzeGasUsage (txMeta, cb) { diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index 175602ec1..71293d05f 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -7,9 +7,9 @@ const ObservableStore = require('obs-store') const EthStore = require('./lib/eth-store') const EthQuery = require('eth-query') const streamIntoProvider = require('web3-stream-provider/handler') -const MetaMaskProvider = require('web3-provider-engine/zero.js') const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex const KeyringController = require('./keyring-controller') +const NetworkController = require('./controllers/network') const PreferencesController = require('./controllers/preferences') const CurrencyController = require('./controllers/currency') const NoticeController = require('./notice-controller') @@ -40,8 +40,7 @@ module.exports = class MetamaskController extends EventEmitter { this.store = new ObservableStore(initState) // network store - this.networkStore = new ObservableStore({ network: 'loading' }) - + this.networkController = new NetworkController(initState.NetworkController) // config manager this.configManager = new ConfigManager({ store: this.store, @@ -62,7 +61,7 @@ module.exports = class MetamaskController extends EventEmitter { // rpc provider this.provider = this.initializeProvider() this.provider.on('block', this.logBlock.bind(this)) - this.provider.on('error', this.verifyNetwork.bind(this)) + this.provider.on('error', this.networkController.verifyNetwork.bind(this.networkController)) // eth data query tools this.ethQuery = new EthQuery(this.provider) @@ -75,7 +74,7 @@ module.exports = class MetamaskController extends EventEmitter { this.keyringController = new KeyringController({ initState: initState.KeyringController, ethStore: this.ethStore, - getNetwork: this.getNetworkState.bind(this), + getNetwork: this.networkController.getNetworkState.bind(this.networkController), }) this.keyringController.on('newAccount', (address) => { this.preferencesController.setSelectedAddress(address) @@ -92,10 +91,10 @@ module.exports = class MetamaskController extends EventEmitter { // tx mgmt this.txManager = new TxManager({ initState: initState.TransactionManager, - networkStore: this.networkStore, + networkStore: this.networkController.networkStore, preferencesStore: this.preferencesController.store, txHistoryLimit: 40, - getNetwork: this.getNetworkState.bind(this), + getNetwork: this.networkController.getNetworkState.bind(this), signTransaction: this.keyringController.signTransaction.bind(this.keyringController), provider: this.provider, blockTracker: this.provider, @@ -112,8 +111,34 @@ module.exports = class MetamaskController extends EventEmitter { this.shapeshiftController = new ShapeShiftController({ initState: initState.ShapeShiftController, }) + this.networkController.on('networkSwitch', (providerUtil, claimed) => { + delete this.provider + delete this.ethQuery + delete this.ethStore + console.log('order:@? 1') + this.provider = providerUtil.provider + this.provider.on('block', this.logBlock.bind(this)) + this.provider.on('error', this.networkController.verifyNetwork.bind(this.networkController)) + + this.ethQuery = providerUtil.ethQuery + this.ethStore = new EthStore({ + provider: this.provider, + blockTracker: this.provider, + }) + this.provider.once('block', claimed) + }) + this.networkController.on('networkSwitch', (_, claimed) => { + console.log('order:@? 2') + this.txManager.setupProviderAndEthQuery({ + provider: this.provider, + blockTracker: this.provider, + ethQuery: this.ethQuery, + }) + this.keyringController.setEthStore(this.ethStore) + .then(claimed) + }) - this.lookupNetwork() + this.networkController.lookupNetwork() this.messageManager = new MessageManager() this.personalMessageManager = new PersonalMessageManager() this.publicConfigStore = this.initPublicConfigStore() @@ -140,9 +165,12 @@ module.exports = class MetamaskController extends EventEmitter { this.shapeshiftController.store.subscribe((state) => { this.store.updateState({ ShapeShiftController: state }) }) + this.networkController.providerStore.subscribe((state) => { + this.store.updateState({ NetworkController: state }) + }) // manual mem state subscriptions - this.networkStore.subscribe(this.sendUpdate.bind(this)) + this.networkController.subscribe(this.sendUpdate.bind(this)) this.ethStore.subscribe(this.sendUpdate.bind(this)) this.txManager.memStore.subscribe(this.sendUpdate.bind(this)) this.messageManager.memStore.subscribe(this.sendUpdate.bind(this)) @@ -160,12 +188,12 @@ module.exports = class MetamaskController extends EventEmitter { // initializeProvider () { - const provider = MetaMaskProvider({ + this.networkController.initializeProvider({ static: { eth_syncing: false, web3_clientVersion: `MetaMask/v${version}`, }, - rpcUrl: this.configManager.getCurrentRpcAddress(), + rpcUrl: this.networkController.getCurrentRpcAddress(), // account mgmt getAccounts: (cb) => { const isUnlocked = this.keyringController.memStore.getState().isUnlocked @@ -185,7 +213,7 @@ module.exports = class MetamaskController extends EventEmitter { // new style msg signing processPersonalMessage: this.newUnsignedPersonalMessage.bind(this), }) - return provider + return this.networkController.provider } initPublicConfigStore () { @@ -221,7 +249,7 @@ module.exports = class MetamaskController extends EventEmitter { { isInitialized, }, - this.networkStore.getState(), + this.networkController.getState(), this.ethStore.getState(), this.txManager.memStore.getState(), this.messageManager.memStore.getState(), @@ -255,8 +283,8 @@ module.exports = class MetamaskController extends EventEmitter { return { // etc getState: (cb) => cb(null, this.getState()), - setProviderType: this.setProviderType.bind(this), - useEtherscanProvider: this.useEtherscanProvider.bind(this), + setProviderType: this.networkController.setProviderType.bind(this.networkController), + useEtherscanProvider: this.networkController.useEtherscanProvider.bind(this.networkController), setCurrentCurrency: this.setCurrentCurrency.bind(this), markAccountsFound: this.markAccountsFound.bind(this), // coinbase @@ -592,7 +620,7 @@ module.exports = class MetamaskController extends EventEmitter { // Log blocks logBlock (block) { log.info(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`) - this.verifyNetwork() + this.networkController.verifyNetwork() } setCurrentCurrency (currencyCode, cb) { @@ -612,7 +640,7 @@ module.exports = class MetamaskController extends EventEmitter { buyEth (address, amount) { if (!amount) amount = '5' - const network = this.getNetworkState() + const network = this.networkController.getNetworkState() const url = getBuyEthUrl({ network, address, amount }) if (url) this.platform.openWindow({ url }) } @@ -620,69 +648,21 @@ module.exports = class MetamaskController extends EventEmitter { createShapeShiftTx (depositAddress, depositType) { this.shapeshiftController.createShapeShiftTx(depositAddress, depositType) } - - // - // network - // - - verifyNetwork () { - // Check network when restoring connectivity: - if (this.isNetworkLoading()) this.lookupNetwork() - } +// network setDefaultRpc () { - this.configManager.setRpcTarget('http://localhost:8545') - this.platform.reload() - this.lookupNetwork() + this.networkController.setRpcTarget('http://localhost:8545') return Promise.resolve('http://localhost:8545') } setCustomRpc (rpcTarget, rpcList) { - this.configManager.setRpcTarget(rpcTarget) - return this.preferencesController.updateFrequentRpcList(rpcTarget) - .then(() => { - this.platform.reload() - this.lookupNetwork() - return Promise.resolve(rpcTarget) - }) - } - - setProviderType (type) { - this.configManager.setProviderType(type) - this.platform.reload() - this.lookupNetwork() - } - - useEtherscanProvider () { - this.configManager.useEtherscanProvider() - this.platform.reload() - } - - getNetworkState () { - return this.networkStore.getState().network - } - - setNetworkState (network) { - return this.networkStore.updateState({ network }) - } + this.networkController.setRpcTarget(rpcTarget) - isNetworkLoading () { - return this.getNetworkState() === 'loading' - } - - lookupNetwork (err) { - if (err) { - this.setNetworkState('loading') - } - - this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { - if (err) { - this.setNetworkState('loading') - return - } - log.info('web3.getNetwork returned ' + network) - this.setNetworkState(network) + return this.preferencesController.updateFrequentRpcList(rpcTarget) + .then(() => { + return Promise.resolve(rpcTarget) }) } + } diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js index 9f267160f..1e15128f9 100644 --- a/app/scripts/transaction-manager.js +++ b/app/scripts/transaction-manager.js @@ -4,7 +4,6 @@ const extend = require('xtend') const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const EthQuery = require('eth-query') const TxProviderUtil = require('./lib/tx-utils') const createId = require('./lib/random-id') @@ -18,11 +17,11 @@ module.exports = class TransactionManager extends EventEmitter { this.networkStore = opts.networkStore || new ObservableStore({}) this.preferencesStore = opts.preferencesStore || new ObservableStore({}) this.txHistoryLimit = opts.txHistoryLimit - this.provider = opts.provider - this.blockTracker = opts.blockTracker - this.query = new EthQuery(this.provider) - this.txProviderUtils = new TxProviderUtil(this.provider) - this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) + this.setupProviderAndEthQuery({ + provider: opts.provider, + blockTracker: opts.blockTracker, + ethQuery: opts.ethQuery, + }) this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -41,6 +40,20 @@ module.exports = class TransactionManager extends EventEmitter { return this.networkStore.getState().network } + setupProviderAndEthQuery ({provider, blockTracker, ethQuery}) { + if (this.provider) { + delete this.provider + delete this.blockTracker + delete this.query + delete this.txProviderUtils + } + this.provider = provider + this.query = ethQuery + this.txProviderUtils = new TxProviderUtil(ethQuery) + blockTracker ? this.blockTracker = blockTracker : this.blockTracker = provider + this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) + } + getSelectedAddress () { return this.preferencesStore.getState().selectedAddress } -- cgit From c5432da567b9953c1294e0bf598a0310127bf808 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Sat, 20 May 2017 20:37:47 -0700 Subject: Add new streaming subprovider but getting a loop Regarding #1458 Uses a new streaming subprovider architecture on an experimental branch of StreamProvider: https://github.com/flyswatter/web3-stream-provider/tree/StreamSubprovider --- app/scripts/lib/inpage-provider.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index e5e398e24..88d81cca5 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,5 +1,6 @@ const pipe = require('pump') -const StreamProvider = require('web3-stream-provider') +const StreamSubprovider = require('web3-stream-provider/stream-subprovider') +const ProviderEngine = require('web3-provider-engine') const LocalStorageStore = require('obs-store') const ObjectMultiplex = require('./obj-multiplex') const createRandomId = require('./random-id') @@ -27,14 +28,21 @@ function MetamaskInpageProvider (connectionStream) { ) // connect to async provider - const asyncProvider = self.asyncProvider = new StreamProvider() + const engine = self.asyncProvider = new ProviderEngine() + + const stream = self.stream = new StreamSubprovider() + engine.addProvider(stream) + pipe( - asyncProvider, + stream, multiStream.createStream('provider'), - asyncProvider, + stream, (err) => logStreamDisconnectWarning('MetaMask RpcProvider', err) ) + // start polling + engine.start() + self.idMap = {} // handle sendAsync requests via asyncProvider self.sendAsync = function (payload, cb) { @@ -46,7 +54,9 @@ function MetamaskInpageProvider (connectionStream) { return message }) // forward to asyncProvider - asyncProvider.sendAsync(request, function (err, res) { + console.log('sending async to engine', request) + engine.sendAsync(request, function (err, res) { + console.log('send async returned !!', err, res) if (err) return cb(err) // transform messages to original ids eachJsonMessage(res, (message) => { -- cgit From 709c0eb307e2cda9aa16b67191a43e99e1b22fa0 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 22 May 2017 15:21:25 -0700 Subject: Use stream-provider v3 api --- app/scripts/popup-core.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index f1eb394d7..7de1a6fda 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -29,9 +29,9 @@ function connectToAccountManager (connectionStream, cb) { function setupWeb3Connection (connectionStream) { var providerStream = new StreamProvider() - providerStream.pipe(connectionStream).pipe(providerStream) + providerStream.stream.pipe(connectionStream).pipe(providerStream.stream) connectionStream.on('error', console.error.bind(console)) - providerStream.on('error', console.error.bind(console)) + providerStream.stream.on('error', console.error.bind(console)) global.ethereumProvider = providerStream global.ethQuery = new EthQuery(providerStream) } -- cgit From 48d9a2107130e3850077c6c1789b29a09634b168 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 22 May 2017 15:23:29 -0700 Subject: Use filter subprovider in-page to avoid filter leaks --- app/scripts/lib/inpage-provider.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 88d81cca5..9dea05dbb 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,6 +1,7 @@ const pipe = require('pump') -const StreamSubprovider = require('web3-stream-provider/stream-subprovider') const ProviderEngine = require('web3-provider-engine') +const FilterSubprovider = require('web3-provider-engine/subproviders/filters') +const StreamSubprovider = require('web3-stream-provider/stream-subprovider') const LocalStorageStore = require('obs-store') const ObjectMultiplex = require('./obj-multiplex') const createRandomId = require('./random-id') @@ -28,7 +29,10 @@ function MetamaskInpageProvider (connectionStream) { ) // connect to async provider - const engine = self.asyncProvider = new ProviderEngine() + const engine = new ProviderEngine() + + const filterSubprovider = new FilterSubprovider() + engine.addProvider(filterSubprovider) const stream = self.stream = new StreamSubprovider() engine.addProvider(stream) -- cgit From cbfaa6f56f685d515e170de2bf305da76b8ec1e0 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 22 May 2017 15:41:13 -0700 Subject: Rename stream to streamSubprovider --- app/scripts/lib/inpage-provider.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 9dea05dbb..3b60756b9 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -34,13 +34,13 @@ function MetamaskInpageProvider (connectionStream) { const filterSubprovider = new FilterSubprovider() engine.addProvider(filterSubprovider) - const stream = self.stream = new StreamSubprovider() - engine.addProvider(stream) + const streamSubprovider = new StreamSubprovider() + engine.addProvider(streamSubprovider) pipe( - stream, + streamSubprovider, multiStream.createStream('provider'), - stream, + streamSubprovider, (err) => logStreamDisconnectWarning('MetaMask RpcProvider', err) ) -- cgit From 1c1400b584a97e05e3f39748e5f44f076328d89b Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 22 May 2017 15:59:07 -0700 Subject: deps - use stream-subprovider from provider-engine --- app/scripts/lib/inpage-provider.js | 2 +- app/scripts/popup-core.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 3b60756b9..d24121ade 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,7 +1,7 @@ const pipe = require('pump') const ProviderEngine = require('web3-provider-engine') const FilterSubprovider = require('web3-provider-engine/subproviders/filters') -const StreamSubprovider = require('web3-stream-provider/stream-subprovider') +const StreamSubprovider = require('web3-provider-engine/subproviders/stream') const LocalStorageStore = require('obs-store') const ObjectMultiplex = require('./obj-multiplex') const createRandomId = require('./random-id') diff --git a/app/scripts/popup-core.js b/app/scripts/popup-core.js index 7de1a6fda..f1eb394d7 100644 --- a/app/scripts/popup-core.js +++ b/app/scripts/popup-core.js @@ -29,9 +29,9 @@ function connectToAccountManager (connectionStream, cb) { function setupWeb3Connection (connectionStream) { var providerStream = new StreamProvider() - providerStream.stream.pipe(connectionStream).pipe(providerStream.stream) + providerStream.pipe(connectionStream).pipe(providerStream) connectionStream.on('error', console.error.bind(console)) - providerStream.stream.on('error', console.error.bind(console)) + providerStream.on('error', console.error.bind(console)) global.ethereumProvider = providerStream global.ethQuery = new EthQuery(providerStream) } -- cgit From b217ad1ae8109e9648da948bde06cdc88317396a Mon Sep 17 00:00:00 2001 From: kumavis Date: Mon, 22 May 2017 16:06:22 -0700 Subject: clean - remove console logs --- app/scripts/lib/inpage-provider.js | 2 -- 1 file changed, 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index d24121ade..e54f547bd 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -58,9 +58,7 @@ function MetamaskInpageProvider (connectionStream) { return message }) // forward to asyncProvider - console.log('sending async to engine', request) engine.sendAsync(request, function (err, res) { - console.log('send async returned !!', err, res) if (err) return cb(err) // transform messages to original ids eachJsonMessage(res, (message) => { -- cgit From e08c1541e5a91d7958b15753982d22066c1a0a7d Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 23 May 2017 01:55:20 -0400 Subject: Add a migration for the network controller --- app/scripts/migrations/014.js | 34 ++++++++++++++++++++++++++++++++++ app/scripts/migrations/index.js | 1 + 2 files changed, 35 insertions(+) create mode 100644 app/scripts/migrations/014.js (limited to 'app') diff --git a/app/scripts/migrations/014.js b/app/scripts/migrations/014.js new file mode 100644 index 000000000..0fe92125b --- /dev/null +++ b/app/scripts/migrations/014.js @@ -0,0 +1,34 @@ +const version = 14 + +/* + +This migration removes provider from config and moves it too NetworkController. + +*/ + +const clone = require('clone') + +module.exports = { + version, + + migrate: function (originalVersionedData) { + const versionedData = clone(originalVersionedData) + versionedData.meta.version = version + try { + const state = versionedData.data + const newState = transformState(state) + versionedData.data = newState + } catch (err) { + console.warn(`MetaMask Migration #${version}` + err.stack) + } + return Promise.resolve(versionedData) + }, +} + +function transformState (state) { + const newState = state + newState.NetworkController = {} + newState.NetworkController.provider = newState.config.provider + delete newState.config.provider + return newState +} diff --git a/app/scripts/migrations/index.js b/app/scripts/migrations/index.js index 3a95cf88e..fb1ad7863 100644 --- a/app/scripts/migrations/index.js +++ b/app/scripts/migrations/index.js @@ -24,4 +24,5 @@ module.exports = [ require('./011'), require('./012'), require('./013'), + require('./014'), ] -- cgit From 529304c005318852b60bb93846a58d6eb3da2066 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 23 May 2017 01:56:10 -0400 Subject: Wrap the provider in a proxy --- app/scripts/controllers/network.js | 110 +++++++++++++++----------------- app/scripts/controllers/transactions.js | 27 ++------ app/scripts/keyring-controller.js | 6 -- app/scripts/lib/config-manager.js | 5 +- app/scripts/metamask-controller.js | 42 ++---------- 5 files changed, 64 insertions(+), 126 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 82eabb573..97c2ccbc2 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -3,21 +3,29 @@ const MetaMaskProvider = require('web3-provider-engine/zero.js') const ObservableStore = require('obs-store') const extend = require('xtend') const EthQuery = require('eth-query') -const MetamaskConfig = require('../config.js') - -const TESTNET_RPC = MetamaskConfig.network.testnet -const MAINNET_RPC = MetamaskConfig.network.mainnet -const MORDEN_RPC = MetamaskConfig.network.morden -const KOVAN_RPC = MetamaskConfig.network.kovan -const RINKEBY_RPC = MetamaskConfig.network.rinkeby +const RPC_ADDRESS_LIST = require('../config.js').network module.exports = class NetworkController extends EventEmitter { constructor (providerOpts) { super() this.networkStore = new ObservableStore({ network: 'loading' }) - providerOpts.provider.rpcTarget = this.getRpcAddressForType(providerOpts.provider.type) + providerOpts.provider.rpcTarget = this.getRpcAddressForType(providerOpts.provider.type, providerOpts.provider) this.providerStore = new ObservableStore(providerOpts) - this._claimed = 0 + this.store = new ObservableStore(extend(this.networkStore.getState(), this.providerStore.getState())) + + this._providerListners = {} + + this.networkStore.subscribe((state) => this.store.updateState(state)) + this.providerStore.subscribe((state) => this.store.updateState(state)) + this.on('networkSwitch', this.lookupNetwork) + } + + get provider () { + return this._proxy + } + + set provider (provider) { + this._provider = provider } getState () { @@ -29,28 +37,35 @@ module.exports = class NetworkController extends EventEmitter { initializeProvider (opts) { this.providerConfig = opts - this.provider = MetaMaskProvider(opts) + this._provider = MetaMaskProvider(opts) + this._proxy = new Proxy(this._provider, { + get: (obj, name) => { + if (name === 'on') return this._on.bind(this) + return this._provider[name] + }, + set: (obj, name, value) => { + this._provider[name] = value + }, + }) + this.provider.on('block', this._logBlock.bind(this)) + this.provider.on('error', this.verifyNetwork.bind(this)) this.ethQuery = new EthQuery(this.provider) this.lookupNetwork() - return Promise.resolve(this.provider) + return this.provider } + switchNetwork (providerConfig) { - delete this.provider - delete this.ethQuery const newConfig = extend(this.providerConfig, providerConfig) this.providerConfig = newConfig + this.provider = MetaMaskProvider(newConfig) - this.ethQuery = new EthQuery(this.provider) - this.emit('networkSwitch', { - provider: this.provider, - ethQuery: this.ethQuery, - }, this.claim.bind(this)) + // apply the listners created by other controllers + Object.keys(this._providerListners).forEach((key) => { + this._providerListners[key].forEach((handler) => this._provider.addListener(key, handler)) + }) + this.emit('networkSwitch', this.provider) } - subscribe (cb) { - this.networkStore.subscribe(cb) - this.providerStore.subscribe(cb) - } verifyNetwork () { // Check network when restoring connectivity: @@ -74,7 +89,6 @@ module.exports = class NetworkController extends EventEmitter { this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { if (err) return this.setNetworkState('loading') - log.info('web3.getNetwork returned ' + network) this.setNetworkState(network) }) @@ -102,51 +116,27 @@ module.exports = class NetworkController extends EventEmitter { this.switchNetwork({ rpcUrl: rpcTarget, }) - this.once('claimed', () => { - this.providerStore.updateState({provider: {type, rpcTarget}}) - console.log('CLAIMED') - this.lookupNetwork() - }) - - } - - useEtherscanProvider () { - this.setProviderType('etherscan') + this.providerStore.updateState({provider: {type, rpcTarget}}) } getProvider () { return this.providerStore.getState().provider } - getRpcAddressForType (type) { - const provider = this.getProvider() - switch (type) { - - case 'mainnet': - return MAINNET_RPC - - case 'testnet': - return TESTNET_RPC - - case 'morden': - return MORDEN_RPC - - case 'kovan': - return KOVAN_RPC - - case 'rinkeby': - return RINKEBY_RPC + getRpcAddressForType (type, provider = this.getProvider()) { + console.log(`#getRpcAddressForType: ${type}`) + if (type in RPC_ADDRESS_LIST) return RPC_ADDRESS_LIST[type] + return provider && provider.rpcTarget ? provider.rpcTarget : RPC_ADDRESS_LIST['rinkeby'] + } - default: - return provider && provider.rpcTarget ? provider.rpcTarget : TESTNET_RPC - } + _logBlock (block) { + log.info(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`) + this.verifyNetwork() } - claim () { - this._claimed += 1 - if (this._claimed === this.listenerCount('networkSwitch')) { - this.emit('claimed') - this._claimed = 0 - } + _on (event, handler) { + if (!this._providerListners[event]) this._providerListners[event] = [] + this._providerListners[event].push(handler) + this._provider.on(event, handler) } } diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index cfeeab6e6..b9bea2f1c 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -4,7 +4,6 @@ const extend = require('xtend') const Semaphore = require('semaphore') const ObservableStore = require('obs-store') const ethUtil = require('ethereumjs-util') -const EthQuery = require('eth-query') const TxProviderUtil = require('../lib/tx-utils') const createId = require('../lib/random-id') @@ -18,11 +17,13 @@ module.exports = class TransactionManager extends EventEmitter { this.networkStore = opts.networkStore || new ObservableStore({}) this.preferencesStore = opts.preferencesStore || new ObservableStore({}) this.txHistoryLimit = opts.txHistoryLimit - this.setupProviderAndEthQuery({ - provider: opts.provider, - blockTracker: opts.blockTracker, - ethQuery: opts.ethQuery, - }) + this.provider = opts.provider + this.blockTracker = opts.blockTracker + this.query = opts.ethQuery + this.txProviderUtils = new TxProviderUtil(this.query) + this.networkStore.subscribe((_) => this.blockTracker.on('block', this.checkForTxInBlock.bind(this))) + this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) + this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -41,20 +42,6 @@ module.exports = class TransactionManager extends EventEmitter { return this.networkStore.getState().network } - setupProviderAndEthQuery ({provider, blockTracker, ethQuery}) { - if (this.provider) { - delete this.provider - delete this.blockTracker - delete this.query - delete this.txProviderUtils - } - this.provider = provider - this.query = ethQuery - this.txProviderUtils = new TxProviderUtil(ethQuery) - blockTracker ? this.blockTracker = blockTracker : this.blockTracker = provider - this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) - } - getSelectedAddress () { return this.preferencesStore.getState().selectedAddress } diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js index bb699ca8b..5b3c80e40 100644 --- a/app/scripts/keyring-controller.js +++ b/app/scripts/keyring-controller.js @@ -41,12 +41,6 @@ class KeyringController extends EventEmitter { this.getNetwork = opts.getNetwork } - setEthStore (ethStore) { - delete this.ethStore - this.ethStore = ethStore - return this.setupAccounts() - } - // Full Update // returns Promise( @object state ) // diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index 6ca9bd9ea..fee8423fa 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -1,14 +1,13 @@ const ethUtil = require('ethereumjs-util') const normalize = require('eth-sig-util').normalize +const MetamaskConfig = require('../config.js') + -<<<<<<< HEAD -======= const MAINNET_RPC = MetamaskConfig.network.mainnet const ROPSTEN_RPC = MetamaskConfig.network.ropsten const KOVAN_RPC = MetamaskConfig.network.kovan const RINKEBY_RPC = MetamaskConfig.network.rinkeby ->>>>>>> master /* The config-manager is a convenience object * wrapping a pojo-migrator. * diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index b93f627bb..ef82da0d3 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -40,6 +40,7 @@ module.exports = class MetamaskController extends EventEmitter { this.store = new ObservableStore(initState) // network store + this.networkController = new NetworkController(initState.NetworkController) // config manager this.configManager = new ConfigManager({ @@ -60,12 +61,11 @@ module.exports = class MetamaskController extends EventEmitter { // rpc provider this.provider = this.initializeProvider() - this.provider.on('block', this.logBlock.bind(this)) - this.provider.on('error', this.networkController.verifyNetwork.bind(this.networkController)) // eth data query tools this.ethQuery = new EthQuery(this.provider) this.ethStore = new EthStore({ + network: this.networkController.networkStore, provider: this.provider, blockTracker: this.provider, }) @@ -111,32 +111,6 @@ module.exports = class MetamaskController extends EventEmitter { this.shapeshiftController = new ShapeShiftController({ initState: initState.ShapeShiftController, }) - this.networkController.on('networkSwitch', (providerUtil, claimed) => { - delete this.provider - delete this.ethQuery - delete this.ethStore - console.log('order:@? 1') - this.provider = providerUtil.provider - this.provider.on('block', this.logBlock.bind(this)) - this.provider.on('error', this.networkController.verifyNetwork.bind(this.networkController)) - - this.ethQuery = providerUtil.ethQuery - this.ethStore = new EthStore({ - provider: this.provider, - blockTracker: this.provider, - }) - this.provider.once('block', claimed) - }) - this.networkController.on('networkSwitch', (_, claimed) => { - console.log('order:@? 2') - this.txManager.setupProviderAndEthQuery({ - provider: this.provider, - blockTracker: this.provider, - ethQuery: this.ethQuery, - }) - this.keyringController.setEthStore(this.ethStore) - .then(claimed) - }) this.networkController.lookupNetwork() this.messageManager = new MessageManager() @@ -170,7 +144,7 @@ module.exports = class MetamaskController extends EventEmitter { }) // manual mem state subscriptions - this.networkController.subscribe(this.sendUpdate.bind(this)) + this.networkController.store.subscribe(this.sendUpdate.bind(this)) this.ethStore.subscribe(this.sendUpdate.bind(this)) this.txController.memStore.subscribe(this.sendUpdate.bind(this)) this.messageManager.memStore.subscribe(this.sendUpdate.bind(this)) @@ -188,7 +162,7 @@ module.exports = class MetamaskController extends EventEmitter { // initializeProvider () { - this.networkController.initializeProvider({ + return this.networkController.initializeProvider({ static: { eth_syncing: false, web3_clientVersion: `MetaMask/v${version}`, @@ -213,7 +187,6 @@ module.exports = class MetamaskController extends EventEmitter { // new style msg signing processPersonalMessage: this.newUnsignedPersonalMessage.bind(this), }) - return this.networkController.provider } initPublicConfigStore () { @@ -249,7 +222,7 @@ module.exports = class MetamaskController extends EventEmitter { { isInitialized, }, - this.networkController.getState(), + this.networkController.store.getState(), this.ethStore.getState(), this.txController.memStore.getState(), this.messageManager.memStore.getState(), @@ -284,7 +257,6 @@ module.exports = class MetamaskController extends EventEmitter { // etc getState: (cb) => cb(null, this.getState()), setProviderType: this.networkController.setProviderType.bind(this.networkController), - useEtherscanProvider: this.networkController.useEtherscanProvider.bind(this.networkController), setCurrentCurrency: this.setCurrentCurrency.bind(this), markAccountsFound: this.markAccountsFound.bind(this), // coinbase @@ -618,10 +590,6 @@ module.exports = class MetamaskController extends EventEmitter { // // Log blocks - logBlock (block) { - log.info(`BLOCK CHANGED: #${block.number.toString('hex')} 0x${block.hash.toString('hex')}`) - this.networkController.verifyNetwork() - } setCurrentCurrency (currencyCode, cb) { try { -- cgit From cd2ad1733da16aa3d84158e5df9fbf33f51450aa Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 May 2017 11:49:25 -0700 Subject: Continually resubmit pending txs --- app/scripts/controllers/transactions.js | 54 +++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 21dd25b30..3d86a171e 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -7,6 +7,10 @@ const ethUtil = require('ethereumjs-util') const EthQuery = require('eth-query') const TxProviderUtil = require('../lib/tx-utils') const createId = require('../lib/random-id') +const denodeify = require('denodeify') + +const RETRY_LIMIT = 200 +const RESUBMIT_INTERVAL = 10000 // Ten seconds module.exports = class TransactionManager extends EventEmitter { constructor (opts) { @@ -31,6 +35,8 @@ module.exports = class TransactionManager extends EventEmitter { this.store.subscribe(() => this._updateMemstore()) this.networkStore.subscribe(() => this._updateMemstore()) this.preferencesStore.subscribe(() => this._updateMemstore()) + + this.continuallyResubmitPendingTxs() } getState () { @@ -230,7 +236,11 @@ module.exports = class TransactionManager extends EventEmitter { }) } - publishTransaction (txId, rawTx, cb) { + publishTransaction (txId, rawTx, cb = warn) { + const txMeta = this.getTx(txId) + txMeta.rawTx = rawTx + this.updateTx(txMeta) + this.txProviderUtils.publishTransaction(rawTx, (err, txHash) => { if (err) return cb(err) this.setTxHash(txId, txHash) @@ -353,7 +363,7 @@ module.exports = class TransactionManager extends EventEmitter { message: 'There was a problem loading this transaction.', } this.updateTx(txMeta) - return console.error(err) + return log.error(err) } if (txParams.blockNumber) { this.setTxStatusConfirmed(txId) @@ -379,6 +389,7 @@ module.exports = class TransactionManager extends EventEmitter { this.emit(`${txMeta.id}:${status}`, txId) if (status === 'submitted' || status === 'rejected') { this.emit(`${txMeta.id}:finished`, txMeta) + } this.updateTx(txMeta) this.emit('updateBadge') @@ -398,6 +409,45 @@ module.exports = class TransactionManager extends EventEmitter { }) this.memStore.updateState({ unapprovedTxs, selectedAddressTxList }) } + + continuallyResubmitPendingTxs () { + const pending = this.getTxsByMetaData('status', 'submitted') + const resubmit = denodeify(this.resubmitTx.bind(this)) + Promise.all(pending.map(txMeta => resubmit(txMeta))) + .catch((reason) => { + log.info('Problem resubmitting tx', reason) + }) + .then(() => { + global.setTimeout(() => { + this.continuallyResubmitPendingTxs() + }, RESUBMIT_INTERVAL) + }) + } + + resubmitTx (txMeta, cb) { + // Increment a try counter. + if (!('retryCount' in txMeta)) { + txMeta.retryCount = 0 + } + + // Only auto-submit already-signed txs: + if (!('rawTx' in txMeta)) { + return cb() + } + + if (txMeta.retryCount > RETRY_LIMIT) { + txMeta.err = { + isWarning: true, + message: 'Gave up submitting tx.', + } + this.updateTx(txMeta) + return log.error(txMeta.err.message) + } + + txMeta.retryCount++ + const rawTx = txMeta.rawTx + this.txProviderUtils.publishTransaction(rawTx, cb) + } } -- cgit From e4d09aebf470f9c014f2b658ccf5042a3995d708 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 May 2017 14:49:10 -0700 Subject: Cleanup --- app/scripts/controllers/transactions.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index 3d86a171e..4d3197cba 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -12,7 +12,7 @@ const denodeify = require('denodeify') const RETRY_LIMIT = 200 const RESUBMIT_INTERVAL = 10000 // Ten seconds -module.exports = class TransactionManager extends EventEmitter { +module.exports = class TransactionController extends EventEmitter { constructor (opts) { super() this.store = new ObservableStore(extend({ @@ -448,7 +448,8 @@ module.exports = class TransactionManager extends EventEmitter { const rawTx = txMeta.rawTx this.txProviderUtils.publishTransaction(rawTx, cb) } + } -const warn = () => console.warn('warn was used no cb provided') +const warn = () => log.warn('warn was used no cb provided') -- cgit From 17604f1ef5c880a391026aa02d19493d05c1dd18 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Tue, 23 May 2017 14:49:45 -0700 Subject: Version 3.7.0 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 31e4598c7..5fd4420be 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.6.5", + "version": "3.7.0", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 243eeff7cb0d4c5d613a9250d234f81fdccbbf15 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 23 May 2017 02:12:28 -0400 Subject: Fix for tests --- app/scripts/controllers/network.js | 84 ++++++++++++++------------------- app/scripts/controllers/transactions.js | 4 +- app/scripts/first-time-state.js | 3 +- app/scripts/lib/config-manager.js | 29 ++++++++++++ app/scripts/metamask-controller.js | 3 +- 5 files changed, 68 insertions(+), 55 deletions(-) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 97c2ccbc2..4fdd92921 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -1,23 +1,23 @@ const EventEmitter = require('events') const MetaMaskProvider = require('web3-provider-engine/zero.js') const ObservableStore = require('obs-store') +const ComposedStore = require('obs-store/lib/composed') const extend = require('xtend') const EthQuery = require('eth-query') const RPC_ADDRESS_LIST = require('../config.js').network +const DEFAULT_RPC = RPC_ADDRESS_LIST['rinkeby'] module.exports = class NetworkController extends EventEmitter { - constructor (providerOpts) { + constructor (config) { super() - this.networkStore = new ObservableStore({ network: 'loading' }) - providerOpts.provider.rpcTarget = this.getRpcAddressForType(providerOpts.provider.type, providerOpts.provider) - this.providerStore = new ObservableStore(providerOpts) - this.store = new ObservableStore(extend(this.networkStore.getState(), this.providerStore.getState())) + this.networkStore = new ObservableStore('loading') + config.provider.rpcTarget = this.getRpcAddressForType(config.provider.type, config.provider) + this.providerStore = new ObservableStore(config.provider) + this.store = new ComposedStore({ provider: this.providerStore, network: this.networkStore }) + this._providerListeners = {} - this._providerListners = {} - - this.networkStore.subscribe((state) => this.store.updateState(state)) - this.providerStore.subscribe((state) => this.store.updateState(state)) - this.on('networkSwitch', this.lookupNetwork) + this.on('networkDidChange', this.lookupNetwork) + this.providerStore.subscribe((state) => this.switchNetwork({rpcUrl: state.rpcTarget})) } get provider () { @@ -28,15 +28,8 @@ module.exports = class NetworkController extends EventEmitter { this._provider = provider } - getState () { - return extend({}, - this.networkStore.getState(), - this.providerStore.getState() - ) - } - initializeProvider (opts) { - this.providerConfig = opts + this.providerInit = opts this._provider = MetaMaskProvider(opts) this._proxy = new Proxy(this._provider, { get: (obj, name) => { @@ -54,16 +47,18 @@ module.exports = class NetworkController extends EventEmitter { return this.provider } - switchNetwork (providerConfig) { - const newConfig = extend(this.providerConfig, providerConfig) - this.providerConfig = newConfig + switchNetwork (providerInit) { + this.setNetworkState('loading') + const newInit = extend(this.providerInit, providerInit) + this.providerInit = newInit - this.provider = MetaMaskProvider(newConfig) + this._provider.removeAllListeners() + this.provider = MetaMaskProvider(newInit) // apply the listners created by other controllers - Object.keys(this._providerListners).forEach((key) => { - this._providerListners[key].forEach((handler) => this._provider.addListener(key, handler)) + Object.keys(this._providerListeners).forEach((key) => { + this._providerListeners[key].forEach((handler) => this._provider.addListener(key, handler)) }) - this.emit('networkSwitch', this.provider) + this.emit('networkDidChange') } @@ -73,20 +68,18 @@ module.exports = class NetworkController extends EventEmitter { } getNetworkState () { - return this.networkStore.getState().network + return this.networkStore.getState() } setNetworkState (network) { - return this.networkStore.updateState({ network }) + return this.networkStore.putState(network) } isNetworkLoading () { return this.getNetworkState() === 'loading' } - lookupNetwork (err) { - if (err) this.setNetworkState('loading') - + lookupNetwork () { this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => { if (err) return this.setNetworkState('loading') log.info('web3.getNetwork returned ' + network) @@ -96,37 +89,30 @@ module.exports = class NetworkController extends EventEmitter { setRpcTarget (rpcUrl) { this.providerStore.updateState({ - provider: { - type: 'rpc', - rpcTarget: rpcUrl, - }, + type: 'rpc', + rpcTarget: rpcUrl, }) } getCurrentRpcAddress () { - var provider = this.getProvider() + const provider = this.getProviderConfig() if (!provider) return null return this.getRpcAddressForType(provider.type) } setProviderType (type) { - if (type === this.getProvider().type) return + if (type === this.getProviderConfig().type) return const rpcTarget = this.getRpcAddressForType(type) - this.networkStore.updateState({network: 'loading'}) - this.switchNetwork({ - rpcUrl: rpcTarget, - }) - this.providerStore.updateState({provider: {type, rpcTarget}}) + this.providerStore.updateState({type, rpcTarget}) } - getProvider () { - return this.providerStore.getState().provider + getProviderConfig () { + return this.providerStore.getState() } - getRpcAddressForType (type, provider = this.getProvider()) { - console.log(`#getRpcAddressForType: ${type}`) - if (type in RPC_ADDRESS_LIST) return RPC_ADDRESS_LIST[type] - return provider && provider.rpcTarget ? provider.rpcTarget : RPC_ADDRESS_LIST['rinkeby'] + getRpcAddressForType (type, provider = this.getProviderConfig()) { + if (RPC_ADDRESS_LIST[type]) return RPC_ADDRESS_LIST[type] + return provider && provider.rpcTarget ? provider.rpcTarget : DEFAULT_RPC } _logBlock (block) { @@ -135,8 +121,8 @@ module.exports = class NetworkController extends EventEmitter { } _on (event, handler) { - if (!this._providerListners[event]) this._providerListners[event] = [] - this._providerListners[event].push(handler) + if (!this._providerListeners[event]) this._providerListeners[event] = [] + this._providerListeners[event].push(handler) this._provider.on(event, handler) } } diff --git a/app/scripts/controllers/transactions.js b/app/scripts/controllers/transactions.js index b9bea2f1c..2ebeed3ab 100644 --- a/app/scripts/controllers/transactions.js +++ b/app/scripts/controllers/transactions.js @@ -21,9 +21,7 @@ module.exports = class TransactionManager extends EventEmitter { this.blockTracker = opts.blockTracker this.query = opts.ethQuery this.txProviderUtils = new TxProviderUtil(this.query) - this.networkStore.subscribe((_) => this.blockTracker.on('block', this.checkForTxInBlock.bind(this))) this.blockTracker.on('block', this.checkForTxInBlock.bind(this)) - this.signEthTx = opts.signTransaction this.nonceLock = Semaphore(1) @@ -39,7 +37,7 @@ module.exports = class TransactionManager extends EventEmitter { } getNetwork () { - return this.networkStore.getState().network + return this.networkStore.getState() } getSelectedAddress () { diff --git a/app/scripts/first-time-state.js b/app/scripts/first-time-state.js index 29ec1d8d3..dc7788311 100644 --- a/app/scripts/first-time-state.js +++ b/app/scripts/first-time-state.js @@ -3,7 +3,8 @@ // module.exports = { - config: { + config: {}, + NetworkController: { provider: { type: 'rinkeby', }, diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js index fee8423fa..9c0dffe9c 100644 --- a/app/scripts/lib/config-manager.js +++ b/app/scripts/lib/config-manager.js @@ -107,6 +107,35 @@ ConfigManager.prototype.getSeedWords = function () { var data = this.getData() return data.seedWords } +ConfigManager.prototype.setRpcTarget = function (rpcUrl) { + var config = this.getConfig() + config.provider = { + type: 'rpc', + rpcTarget: rpcUrl, + } + this.setConfig(config) +} + +ConfigManager.prototype.setProviderType = function (type) { + var config = this.getConfig() + config.provider = { + type: type, + } + this.setConfig(config) +} + +ConfigManager.prototype.useEtherscanProvider = function () { + var config = this.getConfig() + config.provider = { + type: 'etherscan', + } + this.setConfig(config) +} + +ConfigManager.prototype.getProvider = function () { + var config = this.getConfig() + return config.provider +} ConfigManager.prototype.getCurrentRpcAddress = function () { var provider = this.getProvider() diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index ef82da0d3..c0ad1e93b 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -65,7 +65,6 @@ module.exports = class MetamaskController extends EventEmitter { // eth data query tools this.ethQuery = new EthQuery(this.provider) this.ethStore = new EthStore({ - network: this.networkController.networkStore, provider: this.provider, blockTracker: this.provider, }) @@ -139,7 +138,7 @@ module.exports = class MetamaskController extends EventEmitter { this.shapeshiftController.store.subscribe((state) => { this.store.updateState({ ShapeShiftController: state }) }) - this.networkController.providerStore.subscribe((state) => { + this.networkController.store.subscribe((state) => { this.store.updateState({ NetworkController: state }) }) -- cgit From c5d74e6421486140eba801375eaeeb3c9c0a3091 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 23 May 2017 20:06:19 -0400 Subject: include ethQuery in txController --- app/scripts/metamask-controller.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index c0ad1e93b..a7eb3d056 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -97,6 +97,7 @@ module.exports = class MetamaskController extends EventEmitter { signTransaction: this.keyringController.signTransaction.bind(this.keyringController), provider: this.provider, blockTracker: this.provider, + ethQuery: this.ethQuery, }) // notices -- cgit From e55329d28b61b2d1066cf794a2099a18a94be7a4 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 24 May 2017 00:15:59 -0700 Subject: Version 3.7.1 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 31e4598c7..c3e2b7511 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.6.5", + "version": "3.7.1", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From db982cf795d30dd32b4722249daea9296430b5b9 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 24 May 2017 11:52:18 -0400 Subject: stop polling when switching networks --- app/scripts/controllers/network.js | 1 + 1 file changed, 1 insertion(+) (limited to 'app') diff --git a/app/scripts/controllers/network.js b/app/scripts/controllers/network.js index 4fdd92921..c07f13b8d 100644 --- a/app/scripts/controllers/network.js +++ b/app/scripts/controllers/network.js @@ -53,6 +53,7 @@ module.exports = class NetworkController extends EventEmitter { this.providerInit = newInit this._provider.removeAllListeners() + this._provider.stop() this.provider = MetaMaskProvider(newInit) // apply the listners created by other controllers Object.keys(this._providerListeners).forEach((key) => { -- cgit From e6b278569ea072aa88416e769d4803a73b77194c Mon Sep 17 00:00:00 2001 From: kumavis Date: Wed, 24 May 2017 11:34:26 -0700 Subject: inpage-provider - disable polling after first block --- app/scripts/lib/inpage-provider.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index e54f547bd..39196e240 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -44,8 +44,9 @@ function MetamaskInpageProvider (connectionStream) { (err) => logStreamDisconnectWarning('MetaMask RpcProvider', err) ) - // start polling + // start and stop polling to unblock first block lock engine.start() + engine.once('latest', () => engine.stop()) self.idMap = {} // handle sendAsync requests via asyncProvider -- cgit From 26fd016b63c4f3a15436d08dff9e94f72d2b4041 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Wed, 24 May 2017 16:17:03 -0700 Subject: Add new blockGasLimit property to txMeta object. --- app/scripts/lib/tx-utils.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'app') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 76b311653..8cf304d0b 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -21,19 +21,30 @@ module.exports = class txProviderUtils { this.query.getBlockByNumber('latest', true, (err, block) => { if (err) return cb(err) async.waterfall([ + self.setBlockGasLimit.bind(self, txMeta, block.gasLimit), self.estimateTxGas.bind(self, txMeta, block.gasLimit), self.setTxGas.bind(self, txMeta, block.gasLimit), ], cb) }) } + setBlockGasLimit (txMeta, blockGasLimitHex, cb) { + const blockGasLimitBN = hexToBn(blockGasLimitHex) + const saferGasLimitBN = blockGasLimitBN.muln(0.95) + txMeta.blockGasLimit = bnToHex(saferGasLimitBN) + cb() + return + } + estimateTxGas (txMeta, blockGasLimitHex, cb) { const txParams = txMeta.txParams // check if gasLimit is already specified txMeta.gasLimitSpecified = Boolean(txParams.gas) // if not, fallback to block gasLimit if (!txMeta.gasLimitSpecified) { - txParams.gas = blockGasLimitHex + const blockGasLimitBN = hexToBn(blockGasLimitHex) + const saferGasLimitBN = blockGasLimitBN.muln(0.95) + txParams.gas = bnToHex(saferGasLimitBN) } // run tx, see if it will OOG this.query.estimateGas(txParams, cb) -- cgit From 473b88f399478b47bfa53d44ef9981aeb6d9960b Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 24 May 2017 22:13:35 -0400 Subject: Reload the page when switching networks for sites that use web3 --- app/scripts/contentscript.js | 1 - app/scripts/inpage.js | 21 +++---------------- app/scripts/lib/auto-reload.js | 47 ++++++++++++++++++++++-------------------- 3 files changed, 28 insertions(+), 41 deletions(-) (limited to 'app') diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index f7237b32e..291b922e8 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -61,7 +61,6 @@ function setupStreams () { // ignore unused channels (handled by background) mx.ignoreStream('provider') mx.ignoreStream('publicConfig') - mx.ignoreStream('reload') } function shouldInjectWeb3 () { diff --git a/app/scripts/inpage.js b/app/scripts/inpage.js index 419f78cd6..ec764535e 100644 --- a/app/scripts/inpage.js +++ b/app/scripts/inpage.js @@ -31,26 +31,11 @@ web3.setProvider = function () { console.log('MetaMask - overrode web3.setProvider') } console.log('MetaMask - injected web3') -// export global web3, with usage-detection reload fn -var triggerReload = setupDappAutoReload(web3) - -// listen for reset requests from metamask -var reloadStream = inpageProvider.multiStream.createStream('reload') -reloadStream.once('data', triggerReload) - -// setup ping timeout autoreload -// LocalMessageDuplexStream does not self-close, so reload if pingStream fails -// var pingChannel = inpageProvider.multiStream.createStream('pingpong') -// var pingStream = new PingStream({ objectMode: true }) -// wait for first successful reponse - -// disable pingStream until https://github.com/MetaMask/metamask-plugin/issues/746 is resolved more gracefully -// metamaskStream.once('data', function(){ -// pingStream.pipe(pingChannel).pipe(pingStream) -// }) -// endOfStream(pingStream, triggerReload) +// export global web3, with usage-detection +setupDappAutoReload(web3, inpageProvider.publicConfigStore) // set web3 defaultAccount + inpageProvider.publicConfigStore.subscribe(function (state) { web3.eth.defaultAccount = state.selectedAddress }) diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index 1302df35f..30ddd2395 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -1,30 +1,33 @@ -const once = require('once') -const ensnare = require('ensnare') - module.exports = setupDappAutoReload -function setupDappAutoReload (web3) { +function setupDappAutoReload (web3, observable) { // export web3 as a global, checking for usage - var pageIsUsingWeb3 = false - var resetWasRequested = false - global.web3 = ensnare(web3, once(function () { - // if web3 usage happened after a reset request, trigger reset late - if (resetWasRequested) return triggerReset() - // mark web3 as used - pageIsUsingWeb3 = true - // reset web3 reference - global.web3 = web3 - })) + global.web3 = new Proxy(web3, { + get: (_web3, name) => { + // get the time of use + if (name !== '_used') _web3._used = Date.now() + return _web3[name] + }, + set: (_web3, name, value) => { + _web3[name] = value + }, + }) + var networkVersion - return handleResetRequest + observable.subscribe(function (state) { + // get the initial network + const curentNetVersion = state.networkVersion + if (!networkVersion) networkVersion = curentNetVersion - function handleResetRequest () { - resetWasRequested = true - // ignore if web3 was not used - if (!pageIsUsingWeb3) return - // reload after short timeout - setTimeout(triggerReset, 500) - } + if (curentNetVersion !== networkVersion && web3._used) { + const timeSenseUse = Date.now() - web3._used + // if web3 was recently used then delay the reloading of the page + timeSenseUse > 500 ? triggerReset() : setTimeout(triggerReset, 500) + // prevent reentry into if statement if state updates again before + // reload + networkVersion = curentNetVersion + } + }) } // reload the page -- cgit From 717dceede84980050420fc3e3ff015caf2bcd553 Mon Sep 17 00:00:00 2001 From: frankiebee Date: Wed, 24 May 2017 23:36:10 -0400 Subject: fix spelling --- app/scripts/lib/auto-reload.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/auto-reload.js b/app/scripts/lib/auto-reload.js index 30ddd2395..534047330 100644 --- a/app/scripts/lib/auto-reload.js +++ b/app/scripts/lib/auto-reload.js @@ -20,9 +20,9 @@ function setupDappAutoReload (web3, observable) { if (!networkVersion) networkVersion = curentNetVersion if (curentNetVersion !== networkVersion && web3._used) { - const timeSenseUse = Date.now() - web3._used + const timeSinceUse = Date.now() - web3._used // if web3 was recently used then delay the reloading of the page - timeSenseUse > 500 ? triggerReset() : setTimeout(triggerReset, 500) + timeSinceUse > 500 ? triggerReset() : setTimeout(triggerReset, 500) // prevent reentry into if statement if state updates again before // reload networkVersion = curentNetVersion -- cgit From ad40e4d2608e0b1e329a6f9af851fbe2cc54e747 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 25 May 2017 12:37:04 -0700 Subject: Remove stream subprovider Since the polling leak seems to be coming from elsewhere, and new bugs came from this, I'm rolling back this change so that we can push the other improvements sooner and fix the bug at its true root. --- app/scripts/lib/inpage-provider.js | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/inpage-provider.js b/app/scripts/lib/inpage-provider.js index 39196e240..8b8623974 100644 --- a/app/scripts/lib/inpage-provider.js +++ b/app/scripts/lib/inpage-provider.js @@ -1,7 +1,5 @@ const pipe = require('pump') -const ProviderEngine = require('web3-provider-engine') -const FilterSubprovider = require('web3-provider-engine/subproviders/filters') -const StreamSubprovider = require('web3-provider-engine/subproviders/stream') +const StreamProvider = require('web3-stream-provider') const LocalStorageStore = require('obs-store') const ObjectMultiplex = require('./obj-multiplex') const createRandomId = require('./random-id') @@ -29,24 +27,14 @@ function MetamaskInpageProvider (connectionStream) { ) // connect to async provider - const engine = new ProviderEngine() - - const filterSubprovider = new FilterSubprovider() - engine.addProvider(filterSubprovider) - - const streamSubprovider = new StreamSubprovider() - engine.addProvider(streamSubprovider) - + const asyncProvider = self.asyncProvider = new StreamProvider() pipe( - streamSubprovider, + asyncProvider, multiStream.createStream('provider'), - streamSubprovider, + asyncProvider, (err) => logStreamDisconnectWarning('MetaMask RpcProvider', err) ) - // start and stop polling to unblock first block lock - engine.start() - engine.once('latest', () => engine.stop()) self.idMap = {} // handle sendAsync requests via asyncProvider @@ -59,7 +47,7 @@ function MetamaskInpageProvider (connectionStream) { return message }) // forward to asyncProvider - engine.sendAsync(request, function (err, res) { + asyncProvider.sendAsync(request, function (err, res) { if (err) return cb(err) // transform messages to original ids eachJsonMessage(res, (message) => { -- cgit From 76a78fdb3b4d5341682a37ef523651ca163bfe15 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Wed, 31 May 2017 14:06:13 -0700 Subject: Version 3.7.2 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index c3e2b7511..2b59002b0 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.7.1", + "version": "3.7.2", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From d59021f7548e5b6c4cedc39b753b41840340398a Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Thu, 1 Jun 2017 10:18:20 -0700 Subject: Version 3.7.3 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 2b59002b0..4dcd6df31 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.7.2", + "version": "3.7.3", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 82cbfaa826cc4d731dfbeab7482420c66c0e832b Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Thu, 1 Jun 2017 12:53:16 -0700 Subject: Convert gasLimit to not use muln in BN --- app/scripts/lib/tx-utils.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 8cf304d0b..658f3bedc 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -30,7 +30,7 @@ module.exports = class txProviderUtils { setBlockGasLimit (txMeta, blockGasLimitHex, cb) { const blockGasLimitBN = hexToBn(blockGasLimitHex) - const saferGasLimitBN = blockGasLimitBN.muln(0.95) + const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20) txMeta.blockGasLimit = bnToHex(saferGasLimitBN) cb() return @@ -43,7 +43,7 @@ module.exports = class txProviderUtils { // if not, fallback to block gasLimit if (!txMeta.gasLimitSpecified) { const blockGasLimitBN = hexToBn(blockGasLimitHex) - const saferGasLimitBN = blockGasLimitBN.muln(0.95) + const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20) txParams.gas = bnToHex(saferGasLimitBN) } // run tx, see if it will OOG @@ -143,3 +143,9 @@ function bnToHex (inputBn) { function hexToBn (inputHex) { return new BN(ethUtil.stripHexPrefix(inputHex), 16) } + +function BnMultiplyByFraction (targetBN, numerator, denominator) { + const numBN = new BN(numerator) + const denomBN = new BN(denominator) + return targetBN.mul(numBN).div(denomBN) +} -- cgit From 611cb7ad930955bbc1691eafbe961a313557f17b Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Fri, 2 Jun 2017 11:08:59 -0700 Subject: Version 3.7.4 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 4dcd6df31..99a083f0f 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.7.3", + "version": "3.7.4", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 2b7d8424981fbbd0f6306b5ee7abf8754f9f7092 Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Fri, 2 Jun 2017 15:18:14 -0700 Subject: Update gasblocklimit params with every block. --- app/scripts/lib/eth-store.js | 2 ++ app/scripts/lib/tx-utils.js | 9 --------- 2 files changed, 2 insertions(+), 9 deletions(-) (limited to 'app') diff --git a/app/scripts/lib/eth-store.js b/app/scripts/lib/eth-store.js index 6f04a9dd6..ebba98f5c 100644 --- a/app/scripts/lib/eth-store.js +++ b/app/scripts/lib/eth-store.js @@ -21,6 +21,7 @@ class EthereumStore extends ObservableStore { transactions: {}, currentBlockNumber: '0', currentBlockHash: '', + currentBlockGasLimit: '', }) this._provider = opts.provider this._query = new EthQuery(this._provider) @@ -73,6 +74,7 @@ class EthereumStore extends ObservableStore { this._currentBlockNumber = blockNumber this.updateState({ currentBlockNumber: parseInt(blockNumber) }) this.updateState({ currentBlockHash: `0x${block.hash.toString('hex')}`}) + this.updateState({ currentBlockGasLimit: `0x${block.gasLimit.toString('hex')}` }) async.parallel([ this._updateAccounts.bind(this), this._updateTransactions.bind(this, blockNumber), diff --git a/app/scripts/lib/tx-utils.js b/app/scripts/lib/tx-utils.js index 658f3bedc..149d93102 100644 --- a/app/scripts/lib/tx-utils.js +++ b/app/scripts/lib/tx-utils.js @@ -21,21 +21,12 @@ module.exports = class txProviderUtils { this.query.getBlockByNumber('latest', true, (err, block) => { if (err) return cb(err) async.waterfall([ - self.setBlockGasLimit.bind(self, txMeta, block.gasLimit), self.estimateTxGas.bind(self, txMeta, block.gasLimit), self.setTxGas.bind(self, txMeta, block.gasLimit), ], cb) }) } - setBlockGasLimit (txMeta, blockGasLimitHex, cb) { - const blockGasLimitBN = hexToBn(blockGasLimitHex) - const saferGasLimitBN = BnMultiplyByFraction(blockGasLimitBN, 19, 20) - txMeta.blockGasLimit = bnToHex(saferGasLimitBN) - cb() - return - } - estimateTxGas (txMeta, blockGasLimitHex, cb) { const txParams = txMeta.txParams // check if gasLimit is already specified -- cgit From c92afef91dc08982ab12b19fcc81c14439aaa808 Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 5 Jun 2017 13:40:26 -0700 Subject: Version 3.7.5 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 99a083f0f..acdb3795e 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.7.4", + "version": "3.7.5", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 838ffb62ee59a36d1dbfdafca0dc6727aeb6985d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 5 Jun 2017 15:36:18 -0700 Subject: Version 3.7.6 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index acdb3795e..2d321e862 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.7.5", + "version": "3.7.6", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit From 203a573f3fa8cf636c846a0a467318f6767d05fe Mon Sep 17 00:00:00 2001 From: Kevin Serrano Date: Mon, 5 Jun 2017 16:23:56 -0700 Subject: Use new URL for currency API from cryptonator. --- app/manifest.json | 2 +- app/scripts/controllers/currency.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 99a083f0f..01ee173a6 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -58,7 +58,7 @@ "storage", "clipboardWrite", "http://localhost:8545/", - "https://www.cryptonator.com/" + "https://api.cryptonator.com/" ], "web_accessible_resources": [ "scripts/inpage.js" diff --git a/app/scripts/controllers/currency.js b/app/scripts/controllers/currency.js index fb130ed76..1f20dc005 100644 --- a/app/scripts/controllers/currency.js +++ b/app/scripts/controllers/currency.js @@ -45,7 +45,7 @@ class CurrencyController { updateConversionRate () { const currentCurrency = this.getCurrentCurrency() - return fetch(`https://www.cryptonator.com/api/ticker/eth-${currentCurrency}`) + return fetch(`https://api.cryptonator.com/api/ticker/eth-${currentCurrency}`) .then(response => response.json()) .then((parsedResponse) => { this.setConversionRate(Number(parsedResponse.ticker.price)) -- cgit From 017c7c4c006d3e6041d33ae815d83faf43ec21bb Mon Sep 17 00:00:00 2001 From: kumavis Date: Thu, 8 Jun 2017 16:42:00 -0700 Subject: 3.7.7 --- app/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app') diff --git a/app/manifest.json b/app/manifest.json index 2d321e862..a0d1500c2 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -1,7 +1,7 @@ { "name": "MetaMask", "short_name": "Metamask", - "version": "3.7.6", + "version": "3.7.7", "manifest_version": 2, "author": "https://metamask.io", "description": "Ethereum Browser Extension", -- cgit