mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Merge pull request #1083 from MetaMask/kumavis-refactor6
Refactor round 6
This commit is contained in:
commit
66be5ff275
@ -29,11 +29,11 @@ class KeyringController extends EventEmitter {
|
||||
this.keyringTypes = keyringTypes
|
||||
this.store = new ObservableStore(initState)
|
||||
this.memStore = new ObservableStore({
|
||||
isUnlocked: false,
|
||||
keyringTypes: this.keyringTypes.map(krt => krt.type),
|
||||
keyrings: [],
|
||||
identities: {},
|
||||
})
|
||||
this.configManager = opts.configManager
|
||||
this.ethStore = opts.ethStore
|
||||
this.encryptor = encryptor
|
||||
this.keyrings = []
|
||||
@ -53,37 +53,7 @@ class KeyringController extends EventEmitter {
|
||||
// Not all methods end with this, that might be a nice refactor.
|
||||
fullUpdate () {
|
||||
this.emit('update')
|
||||
return Promise.resolve(this.getState())
|
||||
}
|
||||
|
||||
// Get State
|
||||
// returns @object state
|
||||
//
|
||||
// This method returns a hash representing the current state
|
||||
// that the keyringController manages.
|
||||
//
|
||||
// It is extended in the MetamaskController along with the EthStore
|
||||
// state, and its own state, to create the metamask state branch
|
||||
// that is passed to the UI.
|
||||
//
|
||||
// This is currently a rare example of a synchronously resolving method
|
||||
// in this class, but will need to be Promisified when we move our
|
||||
// persistence to an async model.
|
||||
getState () {
|
||||
|
||||
// old wallet
|
||||
const memState = this.memStore.getState()
|
||||
const result = {
|
||||
// computed
|
||||
isUnlocked: (!!this.password),
|
||||
// memStore
|
||||
keyringTypes: memState.keyringTypes,
|
||||
identities: memState.identities,
|
||||
keyrings: memState.keyrings,
|
||||
// configManager
|
||||
seedWords: this.configManager.getSeedWords(),
|
||||
}
|
||||
return result
|
||||
return Promise.resolve(this.memStore.getState())
|
||||
}
|
||||
|
||||
// Create New Vault And Keychain
|
||||
@ -147,7 +117,10 @@ class KeyringController extends EventEmitter {
|
||||
//
|
||||
// This method deallocates all secrets, and effectively locks metamask.
|
||||
setLocked () {
|
||||
// set locked
|
||||
this.password = null
|
||||
this.memStore.updateState({ isUnlocked: false })
|
||||
// remove keyrings
|
||||
this.keyrings = []
|
||||
this._updateMemStoreKeyrings()
|
||||
return this.fullUpdate()
|
||||
@ -385,6 +358,7 @@ class KeyringController extends EventEmitter {
|
||||
persistAllKeyrings (password = this.password) {
|
||||
if (typeof password === 'string') {
|
||||
this.password = password
|
||||
this.memStore.updateState({ isUnlocked: true })
|
||||
}
|
||||
return Promise.all(this.keyrings.map((keyring) => {
|
||||
return Promise.all([keyring.type, keyring.serialize()])
|
||||
@ -421,6 +395,7 @@ class KeyringController extends EventEmitter {
|
||||
return this.encryptor.decrypt(password, encryptedVault)
|
||||
.then((vault) => {
|
||||
this.password = password
|
||||
this.memStore.updateState({ isUnlocked: true })
|
||||
vault.forEach(this.restoreKeyring.bind(this))
|
||||
return this.keyrings
|
||||
})
|
||||
|
@ -250,53 +250,6 @@ ConfigManager.prototype.getTOSHash = function () {
|
||||
return data.TOSHash
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setCurrentFiat = function (currency) {
|
||||
var data = this.getData()
|
||||
data.fiatCurrency = currency
|
||||
this.setData(data)
|
||||
}
|
||||
|
||||
ConfigManager.prototype.getCurrentFiat = function () {
|
||||
var data = this.getData()
|
||||
return data.fiatCurrency || 'USD'
|
||||
}
|
||||
|
||||
ConfigManager.prototype.updateConversionRate = function () {
|
||||
var data = this.getData()
|
||||
return fetch(`https://www.cryptonator.com/api/ticker/eth-${data.fiatCurrency}`)
|
||||
.then(response => response.json())
|
||||
.then((parsedResponse) => {
|
||||
this.setConversionPrice(parsedResponse.ticker.price)
|
||||
this.setConversionDate(parsedResponse.timestamp)
|
||||
}).catch((err) => {
|
||||
console.warn('MetaMask - Failed to query currency conversion.')
|
||||
this.setConversionPrice(0)
|
||||
this.setConversionDate('N/A')
|
||||
})
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setConversionPrice = function (price) {
|
||||
var data = this.getData()
|
||||
data.conversionRate = Number(price)
|
||||
this.setData(data)
|
||||
}
|
||||
|
||||
ConfigManager.prototype.setConversionDate = function (datestring) {
|
||||
var data = this.getData()
|
||||
data.conversionDate = datestring
|
||||
this.setData(data)
|
||||
}
|
||||
|
||||
ConfigManager.prototype.getConversionRate = function () {
|
||||
var data = this.getData()
|
||||
return (data.conversionRate) || 0
|
||||
}
|
||||
|
||||
ConfigManager.prototype.getConversionDate = function () {
|
||||
var data = this.getData()
|
||||
return (data.conversionDate) || 'N/A'
|
||||
}
|
||||
|
||||
ConfigManager.prototype.getShapeShiftTxList = function () {
|
||||
var data = this.getData()
|
||||
var shapeShiftTxList = data.shapeShiftTxList ? data.shapeShiftTxList : []
|
||||
|
70
app/scripts/lib/controllers/currency.js
Normal file
70
app/scripts/lib/controllers/currency.js
Normal file
@ -0,0 +1,70 @@
|
||||
const ObservableStore = require('obs-store')
|
||||
const extend = require('xtend')
|
||||
|
||||
// every ten minutes
|
||||
const POLLING_INTERVAL = 600000
|
||||
|
||||
class CurrencyController {
|
||||
|
||||
constructor (opts = {}) {
|
||||
const initState = extend({
|
||||
currentCurrency: 'USD',
|
||||
conversionRate: 0,
|
||||
conversionDate: 'N/A',
|
||||
}, opts.initState)
|
||||
this.store = new ObservableStore(initState)
|
||||
}
|
||||
|
||||
//
|
||||
// PUBLIC METHODS
|
||||
//
|
||||
|
||||
getCurrentCurrency () {
|
||||
return this.store.getState().currentCurrency
|
||||
}
|
||||
|
||||
setCurrentCurrency (currentCurrency) {
|
||||
this.store.updateState({ currentCurrency })
|
||||
}
|
||||
|
||||
getConversionRate () {
|
||||
return this.store.getState().conversionRate
|
||||
}
|
||||
|
||||
setConversionRate (conversionRate) {
|
||||
this.store.updateState({ conversionRate })
|
||||
}
|
||||
|
||||
getConversionDate () {
|
||||
return this.store.getState().conversionDate
|
||||
}
|
||||
|
||||
setConversionDate (conversionDate) {
|
||||
this.store.updateState({ conversionDate })
|
||||
}
|
||||
|
||||
updateConversionRate () {
|
||||
const currentCurrency = this.getCurrentCurrency()
|
||||
return fetch(`https://www.cryptonator.com/api/ticker/eth-${currentCurrency}`)
|
||||
.then(response => response.json())
|
||||
.then((parsedResponse) => {
|
||||
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')
|
||||
})
|
||||
}
|
||||
|
||||
scheduleConversionInterval () {
|
||||
if (this.conversionInterval) {
|
||||
clearInterval(this.conversionInterval)
|
||||
}
|
||||
this.conversionInterval = setInterval(() => {
|
||||
this.updateConversionRate()
|
||||
}, POLLING_INTERVAL)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = CurrencyController
|
@ -7,140 +7,122 @@
|
||||
* on each new block.
|
||||
*/
|
||||
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const inherits = require('util').inherits
|
||||
const async = require('async')
|
||||
const clone = require('clone')
|
||||
const EthQuery = require('eth-query')
|
||||
|
||||
module.exports = EthereumStore
|
||||
|
||||
|
||||
inherits(EthereumStore, EventEmitter)
|
||||
function EthereumStore(engine) {
|
||||
const self = this
|
||||
EventEmitter.call(self)
|
||||
self._currentState = {
|
||||
accounts: {},
|
||||
transactions: {},
|
||||
}
|
||||
self._query = new EthQuery(engine)
|
||||
|
||||
engine.on('block', self._updateForBlock.bind(self))
|
||||
}
|
||||
|
||||
//
|
||||
// public
|
||||
//
|
||||
|
||||
EthereumStore.prototype.getState = function () {
|
||||
const self = this
|
||||
return clone(self._currentState)
|
||||
}
|
||||
|
||||
EthereumStore.prototype.addAccount = function (address) {
|
||||
const self = this
|
||||
self._currentState.accounts[address] = {}
|
||||
self._didUpdate()
|
||||
if (!self.currentBlockNumber) return
|
||||
self._updateAccount(address, () => {
|
||||
self._didUpdate()
|
||||
})
|
||||
}
|
||||
|
||||
EthereumStore.prototype.removeAccount = function (address) {
|
||||
const self = this
|
||||
delete self._currentState.accounts[address]
|
||||
self._didUpdate()
|
||||
}
|
||||
|
||||
EthereumStore.prototype.addTransaction = function (txHash) {
|
||||
const self = this
|
||||
self._currentState.transactions[txHash] = {}
|
||||
self._didUpdate()
|
||||
if (!self.currentBlockNumber) return
|
||||
self._updateTransaction(self.currentBlockNumber, txHash, noop)
|
||||
}
|
||||
|
||||
EthereumStore.prototype.removeTransaction = function (address) {
|
||||
const self = this
|
||||
delete self._currentState.transactions[address]
|
||||
self._didUpdate()
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// private
|
||||
//
|
||||
|
||||
EthereumStore.prototype._didUpdate = function () {
|
||||
const self = this
|
||||
var state = self.getState()
|
||||
self.emit('update', state)
|
||||
}
|
||||
|
||||
EthereumStore.prototype._updateForBlock = function (block) {
|
||||
const self = this
|
||||
var blockNumber = '0x' + block.number.toString('hex')
|
||||
self.currentBlockNumber = blockNumber
|
||||
async.parallel([
|
||||
self._updateAccounts.bind(self),
|
||||
self._updateTransactions.bind(self, blockNumber),
|
||||
], function (err) {
|
||||
if (err) return console.error(err)
|
||||
self.emit('block', self.getState())
|
||||
self._didUpdate()
|
||||
})
|
||||
}
|
||||
|
||||
EthereumStore.prototype._updateAccounts = function (cb) {
|
||||
var accountsState = this._currentState.accounts
|
||||
var addresses = Object.keys(accountsState)
|
||||
async.each(addresses, this._updateAccount.bind(this), cb)
|
||||
}
|
||||
|
||||
EthereumStore.prototype._updateAccount = function (address, cb) {
|
||||
var accountsState = this._currentState.accounts
|
||||
this.getAccount(address, function (err, result) {
|
||||
if (err) return cb(err)
|
||||
result.address = address
|
||||
// only populate if the entry is still present
|
||||
if (accountsState[address]) {
|
||||
accountsState[address] = result
|
||||
}
|
||||
cb(null, result)
|
||||
})
|
||||
}
|
||||
|
||||
EthereumStore.prototype.getAccount = function (address, cb) {
|
||||
const query = this._query
|
||||
async.parallel({
|
||||
balance: query.getBalance.bind(query, address),
|
||||
nonce: query.getTransactionCount.bind(query, address),
|
||||
code: query.getCode.bind(query, address),
|
||||
}, cb)
|
||||
}
|
||||
|
||||
EthereumStore.prototype._updateTransactions = function (block, cb) {
|
||||
const self = this
|
||||
var transactionsState = self._currentState.transactions
|
||||
var txHashes = Object.keys(transactionsState)
|
||||
async.each(txHashes, self._updateTransaction.bind(self, block), cb)
|
||||
}
|
||||
|
||||
EthereumStore.prototype._updateTransaction = function (block, txHash, cb) {
|
||||
const self = this
|
||||
// would use the block here to determine how many confirmations the tx has
|
||||
var transactionsState = self._currentState.transactions
|
||||
self._query.getTransaction(txHash, function (err, result) {
|
||||
if (err) return cb(err)
|
||||
// only populate if the entry is still present
|
||||
if (transactionsState[txHash]) {
|
||||
transactionsState[txHash] = result
|
||||
self._didUpdate()
|
||||
}
|
||||
cb(null, result)
|
||||
})
|
||||
}
|
||||
|
||||
const ObservableStore = require('obs-store')
|
||||
function noop() {}
|
||||
|
||||
|
||||
class EthereumStore extends ObservableStore {
|
||||
|
||||
constructor (opts = {}) {
|
||||
super({
|
||||
accounts: {},
|
||||
transactions: {},
|
||||
})
|
||||
this._provider = opts.provider
|
||||
this._query = new EthQuery(this._provider)
|
||||
this._blockTracker = opts.blockTracker
|
||||
// subscribe to latest block
|
||||
this._blockTracker.on('block', this._updateForBlock.bind(this))
|
||||
}
|
||||
|
||||
//
|
||||
// public
|
||||
//
|
||||
|
||||
addAccount (address) {
|
||||
const accounts = this.getState().accounts
|
||||
accounts[address] = {}
|
||||
this.updateState({ accounts })
|
||||
if (!this._currentBlockNumber) return
|
||||
this._updateAccount(address)
|
||||
}
|
||||
|
||||
removeAccount (address) {
|
||||
const accounts = this.getState().accounts
|
||||
delete accounts[address]
|
||||
this.updateState({ accounts })
|
||||
}
|
||||
|
||||
addTransaction (txHash) {
|
||||
const transactions = this.getState().transactions
|
||||
transactions[txHash] = {}
|
||||
this.updateState({ transactions })
|
||||
if (!this._currentBlockNumber) return
|
||||
this._updateTransaction(this._currentBlockNumber, txHash, noop)
|
||||
}
|
||||
|
||||
removeTransaction (txHash) {
|
||||
const transactions = this.getState().transactions
|
||||
delete transactions[txHash]
|
||||
this.updateState({ transactions })
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// private
|
||||
//
|
||||
|
||||
_updateForBlock (block) {
|
||||
const blockNumber = '0x' + block.number.toString('hex')
|
||||
this._currentBlockNumber = blockNumber
|
||||
async.parallel([
|
||||
this._updateAccounts.bind(this),
|
||||
this._updateTransactions.bind(this, blockNumber),
|
||||
], (err) => {
|
||||
if (err) return console.error(err)
|
||||
this.emit('block', this.getState())
|
||||
})
|
||||
}
|
||||
|
||||
_updateAccounts (cb = noop) {
|
||||
const accounts = this.getState().accounts
|
||||
const addresses = Object.keys(accounts)
|
||||
async.each(addresses, this._updateAccount.bind(this), cb)
|
||||
}
|
||||
|
||||
_updateAccount (address, cb = noop) {
|
||||
const accounts = this.getState().accounts
|
||||
this._getAccount(address, (err, result) => {
|
||||
if (err) return cb(err)
|
||||
result.address = address
|
||||
// only populate if the entry is still present
|
||||
if (accounts[address]) {
|
||||
accounts[address] = result
|
||||
}
|
||||
cb(null, result)
|
||||
})
|
||||
}
|
||||
|
||||
_updateTransactions (block, cb = noop) {
|
||||
const transactions = this.getState().transactions
|
||||
const txHashes = Object.keys(transactions)
|
||||
async.each(txHashes, this._updateTransaction.bind(this, block), cb)
|
||||
}
|
||||
|
||||
_updateTransaction (block, txHash, cb = noop) {
|
||||
// would use the block here to determine how many confirmations the tx has
|
||||
const transactions = this.getState().transactions
|
||||
this._query.getTransaction(txHash, (err, result) => {
|
||||
if (err) return cb(err)
|
||||
// only populate if the entry is still present
|
||||
if (transactions[txHash]) {
|
||||
transactions[txHash] = result
|
||||
}
|
||||
cb(null, result)
|
||||
})
|
||||
}
|
||||
|
||||
_getAccount (address, cb = noop) {
|
||||
const query = this._query
|
||||
async.parallel({
|
||||
balance: query.getBalance.bind(query, address),
|
||||
nonce: query.getTransactionCount.bind(query, address),
|
||||
code: query.getCode.bind(query, address),
|
||||
}, cb)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
module.exports = EthereumStore
|
@ -97,9 +97,6 @@ IdentityStore.prototype.getState = function () {
|
||||
isDisclaimerConfirmed: configManager.getConfirmedDisclaimer(),
|
||||
selectedAddress: configManager.getSelectedAccount(),
|
||||
shapeShiftTxList: configManager.getShapeShiftTxList(),
|
||||
currentFiat: configManager.getCurrentFiat(),
|
||||
conversionRate: configManager.getConversionRate(),
|
||||
conversionDate: configManager.getConversionDate(),
|
||||
gasMultiplier: configManager.getGasMultiplier(),
|
||||
}))
|
||||
}
|
||||
|
@ -6,18 +6,11 @@ const createId = require('./random-id')
|
||||
module.exports = class MessageManager extends EventEmitter{
|
||||
constructor (opts) {
|
||||
super()
|
||||
this.memStore = new ObservableStore({ messages: [] })
|
||||
}
|
||||
|
||||
getState() {
|
||||
return {
|
||||
unapprovedMsgs: this.getUnapprovedMsgs(),
|
||||
messages: this.getMsgList(),
|
||||
}
|
||||
}
|
||||
|
||||
getMsgList () {
|
||||
return this.memStore.getState().messages
|
||||
this.memStore = new ObservableStore({
|
||||
unapprovedMsgs: {},
|
||||
unapprovedMsgCount: 0,
|
||||
})
|
||||
this.messages = []
|
||||
}
|
||||
|
||||
get unapprovedMsgCount () {
|
||||
@ -25,8 +18,7 @@ module.exports = class MessageManager extends EventEmitter{
|
||||
}
|
||||
|
||||
getUnapprovedMsgs () {
|
||||
let messages = this.getMsgList()
|
||||
return messages.filter(msg => msg.status === 'unapproved')
|
||||
return this.messages.filter(msg => msg.status === 'unapproved')
|
||||
.reduce((result, msg) => { result[msg.id] = msg; return result }, {})
|
||||
}
|
||||
|
||||
@ -41,10 +33,6 @@ module.exports = class MessageManager extends EventEmitter{
|
||||
status: 'unapproved',
|
||||
}
|
||||
this.addMsg(msgData)
|
||||
console.log('addUnapprovedMessage:', msgData)
|
||||
|
||||
// keep the cb around for after approval (requires user interaction)
|
||||
// This cb fires completion to the Dapp's write operation.
|
||||
|
||||
// signal update
|
||||
this.emit('update')
|
||||
@ -52,15 +40,12 @@ module.exports = class MessageManager extends EventEmitter{
|
||||
}
|
||||
|
||||
addMsg (msg) {
|
||||
let messages = this.getMsgList()
|
||||
messages.push(msg)
|
||||
this._saveMsgList(messages)
|
||||
this.messages.push(msg)
|
||||
this._saveMsgList()
|
||||
}
|
||||
|
||||
getMsg (msgId) {
|
||||
let messages = this.getMsgList()
|
||||
let matching = messages.filter(msg => msg.id === msgId)
|
||||
return matching.length > 0 ? matching[0] : null
|
||||
return this.messages.find(msg => msg.id === msgId)
|
||||
}
|
||||
|
||||
approveMessage (msgParams) {
|
||||
@ -85,7 +70,10 @@ module.exports = class MessageManager extends EventEmitter{
|
||||
brodcastMessage (rawSig, msgId, status) {
|
||||
this.emit(`${msgId}:finished`, {status, rawSig})
|
||||
}
|
||||
// PRIVATE METHODS
|
||||
|
||||
//
|
||||
// PRIVATE METHODS
|
||||
//
|
||||
|
||||
_setMsgStatus (msgId, status) {
|
||||
let msg = this.getMsg(msgId)
|
||||
@ -94,18 +82,18 @@ module.exports = class MessageManager extends EventEmitter{
|
||||
}
|
||||
|
||||
_updateMsg (msg) {
|
||||
let messages = this.getMsgList()
|
||||
let index = messages.findIndex((message) => message.id === msg.id)
|
||||
let index = this.messages.findIndex((message) => message.id === msg.id)
|
||||
if (index !== -1) {
|
||||
messages[index] = msg
|
||||
this.messages[index] = msg
|
||||
}
|
||||
this._saveMsgList(messages)
|
||||
this._saveMsgList()
|
||||
}
|
||||
|
||||
_saveMsgList (msgList) {
|
||||
_saveMsgList () {
|
||||
const unapprovedMsgs = this.getUnapprovedMsgs()
|
||||
const unapprovedMsgCount = Object.keys(unapprovedMsgs).length
|
||||
this.memStore.updateState({ unapprovedMsgs, unapprovedMsgCount })
|
||||
this.emit('updateBadge')
|
||||
this.memStore.updateState({ messages: msgList })
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,7 @@ const MetaMaskProvider = require('web3-provider-engine/zero.js')
|
||||
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
|
||||
const KeyringController = require('./keyring-controller')
|
||||
const PreferencesController = require('./lib/controllers/preferences')
|
||||
const CurrencyController = require('./lib/controllers/currency')
|
||||
const NoticeController = require('./notice-controller')
|
||||
const MessageManager = require('./lib/message-manager')
|
||||
const TxManager = require('./transaction-manager')
|
||||
@ -29,38 +30,48 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
constructor (opts) {
|
||||
super()
|
||||
this.opts = opts
|
||||
this.state = { network: 'loading' }
|
||||
let initState = opts.initState || {}
|
||||
|
||||
// observable state store
|
||||
this.store = new ObservableStore(initState)
|
||||
|
||||
// network store
|
||||
this.networkStore = new ObservableStore({ network: 'loading' })
|
||||
|
||||
// config manager
|
||||
this.configManager = new ConfigManager({
|
||||
store: this.store,
|
||||
})
|
||||
this.configManager.updateConversionRate()
|
||||
|
||||
// preferences controller
|
||||
this.preferencesController = new PreferencesController({
|
||||
initState: initState.PreferencesController,
|
||||
})
|
||||
|
||||
// currency controller
|
||||
this.currencyController = new CurrencyController({
|
||||
initState: initState.CurrencyController,
|
||||
})
|
||||
this.currencyController.updateConversionRate()
|
||||
this.currencyController.scheduleConversionInterval()
|
||||
|
||||
// rpc provider
|
||||
this.provider = this.initializeProvider(opts)
|
||||
this.provider.on('block', this.logBlock.bind(this))
|
||||
this.provider.on('error', this.getNetwork.bind(this))
|
||||
this.provider.on('error', this.verifyNetwork.bind(this))
|
||||
|
||||
// eth data query tools
|
||||
this.ethQuery = new EthQuery(this.provider)
|
||||
this.ethStore = new EthStore(this.provider)
|
||||
this.ethStore = new EthStore({
|
||||
provider: this.provider,
|
||||
blockTracker: this.provider,
|
||||
})
|
||||
|
||||
// key mgmt
|
||||
this.keyringController = new KeyringController({
|
||||
initState: initState.KeyringController,
|
||||
ethStore: this.ethStore,
|
||||
configManager: this.configManager,
|
||||
getNetwork: this.getStateNetwork.bind(this),
|
||||
getNetwork: this.getNetworkState.bind(this),
|
||||
})
|
||||
this.keyringController.on('newAccount', (address) => {
|
||||
this.preferencesController.setSelectedAddress(address)
|
||||
@ -69,12 +80,11 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
|
||||
// tx mgmt
|
||||
this.txManager = new TxManager({
|
||||
txList: this.configManager.getTxList(),
|
||||
initState: initState.TransactionManager,
|
||||
networkStore: this.networkStore,
|
||||
preferencesStore: this.preferencesController.store,
|
||||
txHistoryLimit: 40,
|
||||
setTxList: this.configManager.setTxList.bind(this.configManager),
|
||||
getSelectedAddress: this.preferencesController.getSelectedAddress.bind(this.preferencesController),
|
||||
getGasMultiplier: this.configManager.getGasMultiplier.bind(this.configManager),
|
||||
getNetwork: this.getStateNetwork.bind(this),
|
||||
getNetwork: this.getNetworkState.bind(this),
|
||||
signTransaction: this.keyringController.signTransaction.bind(this.keyringController),
|
||||
provider: this.provider,
|
||||
blockTracker: this.provider,
|
||||
@ -82,36 +92,49 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
|
||||
// notices
|
||||
this.noticeController = new NoticeController({
|
||||
configManager: this.configManager,
|
||||
initState: initState.NoticeController,
|
||||
})
|
||||
this.noticeController.updateNoticesList()
|
||||
// to be uncommented when retrieving notices from a remote server.
|
||||
// this.noticeController.startPolling()
|
||||
|
||||
this.getNetwork()
|
||||
this.lookupNetwork()
|
||||
this.messageManager = new MessageManager()
|
||||
this.publicConfigStore = this.initPublicConfigStore()
|
||||
|
||||
this.checkTOSChange()
|
||||
|
||||
this.scheduleConversionInterval()
|
||||
|
||||
// TEMPORARY UNTIL FULL DEPRECATION:
|
||||
this.idStoreMigrator = new IdStoreMigrator({
|
||||
configManager: this.configManager,
|
||||
})
|
||||
|
||||
// manual state subscriptions
|
||||
this.ethStore.on('update', this.sendUpdate.bind(this))
|
||||
this.keyringController.on('update', this.sendUpdate.bind(this))
|
||||
this.txManager.on('update', this.sendUpdate.bind(this))
|
||||
this.messageManager.on('update', this.sendUpdate.bind(this))
|
||||
// manual disk state subscriptions
|
||||
this.txManager.store.subscribe((state) => {
|
||||
this.store.updateState({ TransactionManager: state })
|
||||
})
|
||||
this.keyringController.store.subscribe((state) => {
|
||||
this.store.updateState({ KeyringController: state })
|
||||
})
|
||||
this.preferencesController.store.subscribe((state) => {
|
||||
this.store.updateState({ PreferencesController: state })
|
||||
})
|
||||
this.currencyController.store.subscribe((state) => {
|
||||
this.store.updateState({ CurrencyController: state })
|
||||
})
|
||||
this.noticeController.store.subscribe((state) => {
|
||||
this.store.updateState({ NoticeController: state })
|
||||
})
|
||||
|
||||
// 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.messageManager.memStore.subscribe(this.sendUpdate.bind(this))
|
||||
this.keyringController.memStore.subscribe(this.sendUpdate.bind(this))
|
||||
this.preferencesController.store.subscribe(this.sendUpdate.bind(this))
|
||||
this.currencyController.store.subscribe(this.sendUpdate.bind(this))
|
||||
this.noticeController.memStore.subscribe(this.sendUpdate.bind(this))
|
||||
}
|
||||
|
||||
//
|
||||
@ -174,22 +197,21 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
{
|
||||
isInitialized,
|
||||
},
|
||||
this.state,
|
||||
this.networkStore.getState(),
|
||||
this.ethStore.getState(),
|
||||
this.txManager.getState(),
|
||||
this.messageManager.getState(),
|
||||
this.keyringController.getState(),
|
||||
this.txManager.memStore.getState(),
|
||||
this.messageManager.memStore.getState(),
|
||||
this.keyringController.memStore.getState(),
|
||||
this.preferencesController.store.getState(),
|
||||
this.noticeController.getState(),
|
||||
this.currencyController.store.getState(),
|
||||
this.noticeController.memStore.getState(),
|
||||
// config manager
|
||||
this.configManager.getConfig(),
|
||||
{
|
||||
shapeShiftTxList: this.configManager.getShapeShiftTxList(),
|
||||
lostAccounts: this.configManager.getLostAccounts(),
|
||||
currentFiat: this.configManager.getCurrentFiat(),
|
||||
conversionRate: this.configManager.getConversionRate(),
|
||||
conversionDate: this.configManager.getConversionDate(),
|
||||
isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(),
|
||||
seedWords: this.configManager.getSeedWords(),
|
||||
}
|
||||
)
|
||||
}
|
||||
@ -213,7 +235,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
useEtherscanProvider: this.useEtherscanProvider.bind(this),
|
||||
agreeToDisclaimer: this.agreeToDisclaimer.bind(this),
|
||||
resetDisclaimer: this.resetDisclaimer.bind(this),
|
||||
setCurrentFiat: this.setCurrentFiat.bind(this),
|
||||
setCurrentCurrency: this.setCurrentCurrency.bind(this),
|
||||
setTOSHash: this.setTOSHash.bind(this),
|
||||
checkTOSChange: this.checkTOSChange.bind(this),
|
||||
setGasMultiplier: this.setGasMultiplier.bind(this),
|
||||
@ -243,11 +265,13 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
saveAccountLabel: nodeify(keyringController.saveAccountLabel).bind(keyringController),
|
||||
exportAccount: nodeify(keyringController.exportAccount).bind(keyringController),
|
||||
|
||||
// signing methods
|
||||
// txManager
|
||||
approveTransaction: txManager.approveTransaction.bind(txManager),
|
||||
cancelTransaction: txManager.cancelTransaction.bind(txManager),
|
||||
signMessage: this.signMessage.bind(this),
|
||||
cancelMessage: messageManager.rejectMsg.bind(messageManager),
|
||||
|
||||
// messageManager
|
||||
signMessage: this.signMessage.bind(this),
|
||||
cancelMessage: messageManager.rejectMsg.bind(messageManager),
|
||||
|
||||
// notices
|
||||
checkNotices: noticeController.updateNoticesList.bind(noticeController),
|
||||
@ -339,7 +363,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
.then((serialized) => {
|
||||
const seedWords = serialized.mnemonic
|
||||
this.configManager.setSeedWords(seedWords)
|
||||
promiseToCallback(this.keyringController.fullUpdate())(cb)
|
||||
cb()
|
||||
})
|
||||
}
|
||||
|
||||
@ -538,44 +562,38 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
this.verifyNetwork()
|
||||
}
|
||||
|
||||
setCurrentFiat (fiat, cb) {
|
||||
setCurrentCurrency (currencyCode, cb) {
|
||||
try {
|
||||
this.configManager.setCurrentFiat(fiat)
|
||||
this.configManager.updateConversionRate()
|
||||
this.scheduleConversionInterval()
|
||||
this.currencyController.setCurrentCurrency(currencyCode)
|
||||
this.currencyController.updateConversionRate()
|
||||
const data = {
|
||||
conversionRate: this.configManager.getConversionRate(),
|
||||
currentFiat: this.configManager.getCurrentFiat(),
|
||||
conversionDate: this.configManager.getConversionDate(),
|
||||
conversionRate: this.currencyController.getConversionRate(),
|
||||
currentFiat: this.currencyController.getCurrentCurrency(),
|
||||
conversionDate: this.currencyController.getConversionDate(),
|
||||
}
|
||||
cb(data)
|
||||
cb(null, data)
|
||||
} catch (err) {
|
||||
cb(null, err)
|
||||
cb(err)
|
||||
}
|
||||
}
|
||||
|
||||
scheduleConversionInterval () {
|
||||
if (this.conversionInterval) {
|
||||
clearInterval(this.conversionInterval)
|
||||
}
|
||||
this.conversionInterval = setInterval(() => {
|
||||
this.configManager.updateConversionRate()
|
||||
}, 300000)
|
||||
}
|
||||
|
||||
buyEth (address, amount) {
|
||||
if (!amount) amount = '5'
|
||||
|
||||
var network = this.state.network
|
||||
var url = `https://buy.coinbase.com/?code=9ec56d01-7e81-5017-930c-513daa27bb6a&amount=${amount}&address=${address}&crypto_currency=ETH`
|
||||
const network = this.getNetworkState()
|
||||
let url
|
||||
|
||||
if (network === '3') {
|
||||
url = 'https://faucet.metamask.io/'
|
||||
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
|
||||
}
|
||||
|
||||
extension.tabs.create({
|
||||
url,
|
||||
})
|
||||
if (url) extension.tabs.create({ url })
|
||||
}
|
||||
|
||||
createShapeShiftTx (depositAddress, depositType) {
|
||||
@ -584,7 +602,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
|
||||
setGasMultiplier (gasMultiplier, cb) {
|
||||
try {
|
||||
this.configManager.setGasMultiplier(gasMultiplier)
|
||||
this.txManager.setGasMultiplier(gasMultiplier)
|
||||
cb()
|
||||
} catch (err) {
|
||||
cb(err)
|
||||
@ -597,21 +615,19 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
|
||||
verifyNetwork () {
|
||||
// Check network when restoring connectivity:
|
||||
if (this.state.network === 'loading') {
|
||||
this.getNetwork()
|
||||
}
|
||||
if (this.isNetworkLoading()) this.lookupNetwork()
|
||||
}
|
||||
|
||||
setRpcTarget (rpcTarget) {
|
||||
this.configManager.setRpcTarget(rpcTarget)
|
||||
extension.runtime.reload()
|
||||
this.getNetwork()
|
||||
this.lookupNetwork()
|
||||
}
|
||||
|
||||
setProviderType (type) {
|
||||
this.configManager.setProviderType(type)
|
||||
extension.runtime.reload()
|
||||
this.getNetwork()
|
||||
this.lookupNetwork()
|
||||
}
|
||||
|
||||
useEtherscanProvider () {
|
||||
@ -619,26 +635,32 @@ module.exports = class MetamaskController extends EventEmitter {
|
||||
extension.runtime.reload()
|
||||
}
|
||||
|
||||
getStateNetwork () {
|
||||
return this.state.network
|
||||
getNetworkState () {
|
||||
return this.networkStore.getState().network
|
||||
}
|
||||
|
||||
getNetwork (err) {
|
||||
setNetworkState (network) {
|
||||
return this.networkStore.updateState({ network })
|
||||
}
|
||||
|
||||
isNetworkLoading () {
|
||||
return this.getNetworkState() === 'loading'
|
||||
}
|
||||
|
||||
lookupNetwork (err) {
|
||||
if (err) {
|
||||
this.state.network = 'loading'
|
||||
this.sendUpdate()
|
||||
this.setNetworkState('loading')
|
||||
}
|
||||
|
||||
this.ethQuery.sendAsync({ method: 'net_version' }, (err, network) => {
|
||||
if (err) {
|
||||
this.state.network = 'loading'
|
||||
return this.sendUpdate()
|
||||
this.setNetworkState('loading')
|
||||
return
|
||||
}
|
||||
if (global.METAMASK_DEBUG) {
|
||||
console.log('web3.getNetwork returned ' + network)
|
||||
}
|
||||
this.state.network = network
|
||||
this.sendUpdate()
|
||||
this.setNetworkState(network)
|
||||
})
|
||||
}
|
||||
|
||||
|
38
app/scripts/migrations/007.js
Normal file
38
app/scripts/migrations/007.js
Normal file
@ -0,0 +1,38 @@
|
||||
const version = 7
|
||||
|
||||
/*
|
||||
|
||||
This migration breaks out the TransactionManager substate
|
||||
|
||||
*/
|
||||
|
||||
const extend = require('xtend')
|
||||
|
||||
module.exports = {
|
||||
version,
|
||||
|
||||
migrate: function (versionedData) {
|
||||
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 = extend(state, {
|
||||
TransactionManager: {
|
||||
transactions: state.transactions || [],
|
||||
gasMultiplier: state.gasMultiplier || 1,
|
||||
},
|
||||
})
|
||||
delete newState.transactions
|
||||
delete newState.gasMultiplier
|
||||
|
||||
return newState
|
||||
}
|
36
app/scripts/migrations/008.js
Normal file
36
app/scripts/migrations/008.js
Normal file
@ -0,0 +1,36 @@
|
||||
const version = 8
|
||||
|
||||
/*
|
||||
|
||||
This migration breaks out the NoticeController substate
|
||||
|
||||
*/
|
||||
|
||||
const extend = require('xtend')
|
||||
|
||||
module.exports = {
|
||||
version,
|
||||
|
||||
migrate: function (versionedData) {
|
||||
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 = extend(state, {
|
||||
NoticeController: {
|
||||
noticesList: state.noticesList || [],
|
||||
},
|
||||
})
|
||||
delete newState.noticesList
|
||||
|
||||
return newState
|
||||
}
|
40
app/scripts/migrations/009.js
Normal file
40
app/scripts/migrations/009.js
Normal file
@ -0,0 +1,40 @@
|
||||
const version = 9
|
||||
|
||||
/*
|
||||
|
||||
This migration breaks out the CurrencyController substate
|
||||
|
||||
*/
|
||||
|
||||
const merge = require('deep-merge')
|
||||
|
||||
module.exports = {
|
||||
version,
|
||||
|
||||
migrate: function (versionedData) {
|
||||
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 = merge(state, {
|
||||
CurrencyController: {
|
||||
currentCurrency: state.currentFiat || 'USD',
|
||||
conversionRate: state.conversionRate,
|
||||
conversionDate: state.conversionDate,
|
||||
},
|
||||
})
|
||||
delete newState.currentFiat
|
||||
delete newState.conversionRate
|
||||
delete newState.conversionDate
|
||||
|
||||
return newState
|
||||
}
|
@ -17,4 +17,7 @@ module.exports = [
|
||||
require('./004'),
|
||||
require('./005'),
|
||||
require('./006'),
|
||||
require('./007'),
|
||||
require('./008'),
|
||||
require('./009'),
|
||||
]
|
||||
|
@ -1,36 +1,37 @@
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const extend = require('xtend')
|
||||
const ObservableStore = require('obs-store')
|
||||
const hardCodedNotices = require('../../notices/notices.json')
|
||||
|
||||
module.exports = class NoticeController extends EventEmitter {
|
||||
|
||||
constructor (opts) {
|
||||
super()
|
||||
this.configManager = opts.configManager
|
||||
this.noticePoller = null
|
||||
}
|
||||
|
||||
getState () {
|
||||
var lastUnreadNotice = this.getLatestUnreadNotice()
|
||||
|
||||
return {
|
||||
lastUnreadNotice: lastUnreadNotice,
|
||||
noActiveNotices: !lastUnreadNotice,
|
||||
}
|
||||
const initState = extend({
|
||||
noticesList: [],
|
||||
}, opts.initState)
|
||||
this.store = new ObservableStore(initState)
|
||||
this.memStore = new ObservableStore({})
|
||||
this.store.subscribe(() => this._updateMemstore())
|
||||
}
|
||||
|
||||
getNoticesList () {
|
||||
var data = this.configManager.getData()
|
||||
if ('noticesList' in data) {
|
||||
return data.noticesList
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
return this.store.getState().noticesList
|
||||
}
|
||||
|
||||
setNoticesList (list) {
|
||||
var data = this.configManager.getData()
|
||||
data.noticesList = list
|
||||
this.configManager.setData(data)
|
||||
getUnreadNotices () {
|
||||
const notices = this.getNoticesList()
|
||||
return notices.filter((notice) => notice.read === false)
|
||||
}
|
||||
|
||||
getLatestUnreadNotice () {
|
||||
const unreadNotices = this.getUnreadNotices()
|
||||
return unreadNotices[unreadNotices.length - 1]
|
||||
}
|
||||
|
||||
setNoticesList (noticesList) {
|
||||
this.store.updateState({ noticesList })
|
||||
return Promise.resolve(true)
|
||||
}
|
||||
|
||||
@ -56,14 +57,6 @@ module.exports = class NoticeController extends EventEmitter {
|
||||
})
|
||||
}
|
||||
|
||||
getLatestUnreadNotice () {
|
||||
var notices = this.getNoticesList()
|
||||
var filteredNotices = notices.filter((notice) => {
|
||||
return notice.read === false
|
||||
})
|
||||
return filteredNotices[filteredNotices.length - 1]
|
||||
}
|
||||
|
||||
startPolling () {
|
||||
if (this.noticePoller) {
|
||||
clearInterval(this.noticePoller)
|
||||
@ -92,5 +85,10 @@ module.exports = class NoticeController extends EventEmitter {
|
||||
return Promise.resolve(hardCodedNotices)
|
||||
}
|
||||
|
||||
_updateMemstore () {
|
||||
const lastUnreadNotice = this.getLatestUnreadNotice()
|
||||
const noActiveNotices = !lastUnreadNotice
|
||||
this.memStore.updateState({ lastUnreadNotice, noActiveNotices })
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2,6 +2,7 @@ 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 BN = require('ethereumjs-util').BN
|
||||
const TxProviderUtil = require('./lib/tx-utils')
|
||||
@ -10,33 +11,53 @@ const createId = require('./lib/random-id')
|
||||
module.exports = class TransactionManager extends EventEmitter {
|
||||
constructor (opts) {
|
||||
super()
|
||||
this.txList = opts.txList || []
|
||||
this._setTxList = opts.setTxList
|
||||
this.store = new ObservableStore(extend({
|
||||
transactions: [],
|
||||
gasMultiplier: 1,
|
||||
}, opts.initState))
|
||||
this.memStore = new ObservableStore({})
|
||||
this.networkStore = opts.networkStore || new ObservableStore({})
|
||||
this.preferencesStore = opts.preferencesStore || new ObservableStore({})
|
||||
this.txHistoryLimit = opts.txHistoryLimit
|
||||
this.getSelectedAddress = opts.getSelectedAddress
|
||||
this.provider = opts.provider
|
||||
this.blockTracker = opts.blockTracker
|
||||
this.txProviderUtils = new TxProviderUtil(this.provider)
|
||||
this.blockTracker.on('block', this.checkForTxInBlock.bind(this))
|
||||
this.getGasMultiplier = opts.getGasMultiplier
|
||||
this.getNetwork = opts.getNetwork
|
||||
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 () {
|
||||
var selectedAddress = this.getSelectedAddress()
|
||||
return {
|
||||
transactions: this.getTxList(),
|
||||
unapprovedTxs: this.getUnapprovedTxList(),
|
||||
selectedAddressTxList: this.getFilteredTxList({metamaskNetworkId: this.getNetwork(), from: selectedAddress}),
|
||||
}
|
||||
return this.memStore.getState()
|
||||
}
|
||||
|
||||
// Returns the tx list
|
||||
getNetwork () {
|
||||
return this.networkStore.getState().network
|
||||
}
|
||||
|
||||
getSelectedAddress () {
|
||||
return this.preferencesStore.getState().selectedAddress
|
||||
}
|
||||
|
||||
// Returns the tx list
|
||||
getTxList () {
|
||||
let network = this.getNetwork()
|
||||
return this.txList.filter(txMeta => txMeta.metamaskNetworkId === network)
|
||||
let fullTxList = this.store.getState().transactions
|
||||
return fullTxList.filter(txMeta => txMeta.metamaskNetworkId === network)
|
||||
}
|
||||
|
||||
getGasMultiplier () {
|
||||
return this.store.getState().gasMultiplier
|
||||
}
|
||||
|
||||
setGasMultiplier (gasMultiplier) {
|
||||
return this.store.updateState({ gasMultiplier })
|
||||
}
|
||||
|
||||
// Adds a tx to the txlist
|
||||
@ -108,7 +129,7 @@ module.exports = class TransactionManager extends EventEmitter {
|
||||
id: txId,
|
||||
time: time,
|
||||
status: 'unapproved',
|
||||
gasMultiplier: this.getGasMultiplier() || 1,
|
||||
gasMultiplier: this.getGasMultiplier(),
|
||||
metamaskNetworkId: this.getNetwork(),
|
||||
txParams: txParams,
|
||||
}
|
||||
@ -239,7 +260,7 @@ module.exports = class TransactionManager extends EventEmitter {
|
||||
|
||||
getTxsByMetaData (key, value, txList = this.getTxList()) {
|
||||
return txList.filter((txMeta) => {
|
||||
if (key in txMeta.txParams) {
|
||||
if (txMeta.txParams[key]) {
|
||||
return txMeta.txParams[key] === value
|
||||
} else {
|
||||
return txMeta[key] === value
|
||||
@ -351,9 +372,17 @@ module.exports = class TransactionManager extends EventEmitter {
|
||||
|
||||
// Saves the new/updated txList.
|
||||
// Function is intended only for internal use
|
||||
_saveTxList (txList) {
|
||||
this.txList = txList
|
||||
this._setTxList(txList)
|
||||
_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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -11,8 +11,8 @@
|
||||
"disc": "gulp disc --debug",
|
||||
"dist": "gulp dist --disableLiveReload",
|
||||
"test": "npm run lint && npm run fastTest && npm run ci",
|
||||
"fastTest": "METAMASK_ENV=test mocha --require test/helper.js --compilers js:babel-register --recursive \"test/unit/**/*.js\"",
|
||||
"watch": "mocha watch --compilers js:babel-register --recursive \"test/unit/**/*.js\"",
|
||||
"fastTest": "METAMASK_ENV=test mocha --require test/helper.js --recursive \"test/unit/**/*.js\"",
|
||||
"watch": "mocha watch --recursive \"test/unit/**/*.js\"",
|
||||
"genStates": "node development/genStates.js",
|
||||
"ui": "npm run genStates && beefy ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./",
|
||||
"mock": "beefy mock-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./",
|
||||
@ -45,6 +45,7 @@
|
||||
"clone": "^1.0.2",
|
||||
"copy-to-clipboard": "^2.0.0",
|
||||
"debounce": "^1.0.0",
|
||||
"deep-merge": "^1.0.0",
|
||||
"denodeify": "^1.2.1",
|
||||
"disc": "^1.3.2",
|
||||
"dnode": "^1.2.2",
|
||||
@ -71,7 +72,7 @@
|
||||
"mississippi": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"multiplex": "^6.7.0",
|
||||
"obs-store": "^2.3.0",
|
||||
"obs-store": "^2.3.1",
|
||||
"once": "^1.3.3",
|
||||
"ping-pong-stream": "^1.0.0",
|
||||
"pojo-migrator": "^2.1.0",
|
||||
|
@ -15,7 +15,7 @@
|
||||
<script src="bundle.js"></script>
|
||||
<script src="/testem.js"></script>
|
||||
|
||||
<iframe src="/development/test.html" height="500px" width="360px">
|
||||
<iframe src="/development/test.html" height="800px" width="500px">
|
||||
<p>Your browser does not support iframes</p>
|
||||
</iframe>
|
||||
</body>
|
||||
|
@ -14,81 +14,6 @@ describe('config-manager', function() {
|
||||
configManager = configManagerGen()
|
||||
})
|
||||
|
||||
describe('currency conversions', function() {
|
||||
|
||||
describe('#setCurrentFiat', function() {
|
||||
it('should return USD as default', function() {
|
||||
assert.equal(configManager.getCurrentFiat(), 'USD')
|
||||
})
|
||||
|
||||
it('should be able to set to other currency', function() {
|
||||
assert.equal(configManager.getCurrentFiat(), 'USD')
|
||||
configManager.setCurrentFiat('JPY')
|
||||
var result = configManager.getCurrentFiat()
|
||||
assert.equal(result, 'JPY')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getConversionRate', function() {
|
||||
it('should return undefined if non-existent', function() {
|
||||
var result = configManager.getConversionRate()
|
||||
assert.ok(!result)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#updateConversionRate', function() {
|
||||
it('should retrieve an update for ETH to USD and set it in memory', function(done) {
|
||||
this.timeout(15000)
|
||||
var usdMock = nock('https://www.cryptonator.com')
|
||||
.get('/api/ticker/eth-USD')
|
||||
.reply(200, '{"ticker":{"base":"ETH","target":"USD","price":"11.02456145","volume":"44948.91745289","change":"-0.01472534"},"timestamp":1472072136,"success":true,"error":""}')
|
||||
|
||||
assert.equal(configManager.getConversionRate(), 0)
|
||||
var promise = new Promise(
|
||||
function (resolve, reject) {
|
||||
configManager.setCurrentFiat('USD')
|
||||
configManager.updateConversionRate().then(function() {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
promise.then(function() {
|
||||
var result = configManager.getConversionRate()
|
||||
assert.equal(typeof result, 'number')
|
||||
done()
|
||||
}).catch(function(err) {
|
||||
console.log(err)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it('should work for JPY as well.', function() {
|
||||
this.timeout(15000)
|
||||
assert.equal(configManager.getConversionRate(), 0)
|
||||
|
||||
var jpyMock = nock('https://www.cryptonator.com')
|
||||
.get('/api/ticker/eth-JPY')
|
||||
.reply(200, '{"ticker":{"base":"ETH","target":"JPY","price":"11.02456145","volume":"44948.91745289","change":"-0.01472534"},"timestamp":1472072136,"success":true,"error":""}')
|
||||
|
||||
|
||||
var promise = new Promise(
|
||||
function (resolve, reject) {
|
||||
configManager.setCurrentFiat('JPY')
|
||||
configManager.updateConversionRate().then(function() {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
promise.then(function() {
|
||||
var result = configManager.getConversionRate()
|
||||
assert.equal(typeof result, 'number')
|
||||
}).catch(function(err) {
|
||||
console.log(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe('confirmation', function() {
|
||||
|
||||
describe('#getConfirmedDisclaimer', function() {
|
||||
|
87
test/unit/currency-controller-test.js
Normal file
87
test/unit/currency-controller-test.js
Normal file
@ -0,0 +1,87 @@
|
||||
// polyfill fetch
|
||||
global.fetch = global.fetch || require('isomorphic-fetch')
|
||||
|
||||
const assert = require('assert')
|
||||
const extend = require('xtend')
|
||||
const rp = require('request-promise')
|
||||
const nock = require('nock')
|
||||
const CurrencyController = require('../../app/scripts/lib/controllers/currency')
|
||||
|
||||
describe('config-manager', function() {
|
||||
var currencyController
|
||||
|
||||
beforeEach(function() {
|
||||
currencyController = new CurrencyController()
|
||||
})
|
||||
|
||||
describe('currency conversions', function() {
|
||||
|
||||
describe('#setCurrentCurrency', function() {
|
||||
it('should return USD as default', function() {
|
||||
assert.equal(currencyController.getCurrentCurrency(), 'USD')
|
||||
})
|
||||
|
||||
it('should be able to set to other currency', function() {
|
||||
assert.equal(currencyController.getCurrentCurrency(), 'USD')
|
||||
currencyController.setCurrentCurrency('JPY')
|
||||
var result = currencyController.getCurrentCurrency()
|
||||
assert.equal(result, 'JPY')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#getConversionRate', function() {
|
||||
it('should return undefined if non-existent', function() {
|
||||
var result = currencyController.getConversionRate()
|
||||
assert.ok(!result)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#updateConversionRate', function() {
|
||||
it('should retrieve an update for ETH to USD and set it in memory', function(done) {
|
||||
this.timeout(15000)
|
||||
var usdMock = nock('https://www.cryptonator.com')
|
||||
.get('/api/ticker/eth-USD')
|
||||
.reply(200, '{"ticker":{"base":"ETH","target":"USD","price":"11.02456145","volume":"44948.91745289","change":"-0.01472534"},"timestamp":1472072136,"success":true,"error":""}')
|
||||
|
||||
assert.equal(currencyController.getConversionRate(), 0)
|
||||
currencyController.setCurrentCurrency('USD')
|
||||
currencyController.updateConversionRate()
|
||||
.then(function() {
|
||||
var result = currencyController.getConversionRate()
|
||||
console.log('currencyController.getConversionRate:', result)
|
||||
assert.equal(typeof result, 'number')
|
||||
done()
|
||||
}).catch(function(err) {
|
||||
done(err)
|
||||
})
|
||||
|
||||
})
|
||||
|
||||
it('should work for JPY as well.', function() {
|
||||
this.timeout(15000)
|
||||
assert.equal(currencyController.getConversionRate(), 0)
|
||||
|
||||
var jpyMock = nock('https://www.cryptonator.com')
|
||||
.get('/api/ticker/eth-JPY')
|
||||
.reply(200, '{"ticker":{"base":"ETH","target":"JPY","price":"11.02456145","volume":"44948.91745289","change":"-0.01472534"},"timestamp":1472072136,"success":true,"error":""}')
|
||||
|
||||
|
||||
var promise = new Promise(
|
||||
function (resolve, reject) {
|
||||
currencyController.setCurrentCurrency('JPY')
|
||||
currencyController.updateConversionRate().then(function() {
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
|
||||
promise.then(function() {
|
||||
var result = currencyController.getConversionRate()
|
||||
assert.equal(typeof result, 'number')
|
||||
}).catch(function(err) {
|
||||
done(err)
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
})
|
@ -13,7 +13,7 @@ describe('Transaction Manager', function() {
|
||||
|
||||
describe('#getMsgList', function() {
|
||||
it('when new should return empty array', function() {
|
||||
var result = messageManager.getMsgList()
|
||||
var result = messageManager.messages
|
||||
assert.ok(Array.isArray(result))
|
||||
assert.equal(result.length, 0)
|
||||
})
|
||||
@ -22,20 +22,11 @@ describe('Transaction Manager', function() {
|
||||
})
|
||||
})
|
||||
|
||||
describe('#_saveMsgList', function() {
|
||||
it('saves the submitted data to the Msg list', function() {
|
||||
var target = [{ foo: 'bar', metamaskNetworkId: 'unit test' }]
|
||||
messageManager._saveMsgList(target)
|
||||
var result = messageManager.getMsgList()
|
||||
assert.equal(result[0].foo, 'bar')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#addMsg', function() {
|
||||
it('adds a Msg returned in getMsgList', function() {
|
||||
var Msg = { id: 1, status: 'approved', metamaskNetworkId: 'unit test' }
|
||||
messageManager.addMsg(Msg)
|
||||
var result = messageManager.getMsgList()
|
||||
var result = messageManager.messages
|
||||
assert.ok(Array.isArray(result))
|
||||
assert.equal(result.length, 1)
|
||||
assert.equal(result[0].id, 1)
|
||||
@ -47,7 +38,7 @@ describe('Transaction Manager', function() {
|
||||
var Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' }
|
||||
messageManager.addMsg(Msg)
|
||||
messageManager.setMsgStatusApproved(1)
|
||||
var result = messageManager.getMsgList()
|
||||
var result = messageManager.messages
|
||||
assert.ok(Array.isArray(result))
|
||||
assert.equal(result.length, 1)
|
||||
assert.equal(result[0].status, 'approved')
|
||||
@ -59,7 +50,7 @@ describe('Transaction Manager', function() {
|
||||
var Msg = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' }
|
||||
messageManager.addMsg(Msg)
|
||||
messageManager.rejectMsg(1)
|
||||
var result = messageManager.getMsgList()
|
||||
var result = messageManager.messages
|
||||
assert.ok(Array.isArray(result))
|
||||
assert.equal(result.length, 1)
|
||||
assert.equal(result[0].status, 'rejected')
|
||||
|
@ -1,21 +1,19 @@
|
||||
const assert = require('assert')
|
||||
const extend = require('xtend')
|
||||
const EventEmitter = require('events')
|
||||
const ObservableStore = require('obs-store')
|
||||
const STORAGE_KEY = 'metamask-persistance-key'
|
||||
const TransactionManager = require('../../app/scripts/transaction-manager')
|
||||
const noop = () => true
|
||||
|
||||
describe('Transaction Manager', function() {
|
||||
let txManager
|
||||
|
||||
const onTxDoneCb = () => true
|
||||
beforeEach(function() {
|
||||
txManager = new TransactionManager ({
|
||||
txList: [],
|
||||
setTxList: () => {},
|
||||
provider: "testnet",
|
||||
txManager = new TransactionManager({
|
||||
networkStore: new ObservableStore({ network: 'unit test' }),
|
||||
txHistoryLimit: 10,
|
||||
blockTracker: new EventEmitter(),
|
||||
getNetwork: function(){ return 'unit test' }
|
||||
})
|
||||
})
|
||||
|
||||
@ -51,19 +49,10 @@ describe('Transaction Manager', function() {
|
||||
})
|
||||
})
|
||||
|
||||
describe('#_saveTxList', function() {
|
||||
it('saves the submitted data to the tx list', function() {
|
||||
var target = [{ foo: 'bar', metamaskNetworkId: 'unit test' }]
|
||||
txManager._saveTxList(target)
|
||||
var result = txManager.getTxList()
|
||||
assert.equal(result[0].foo, 'bar')
|
||||
})
|
||||
})
|
||||
|
||||
describe('#addTx', function() {
|
||||
it('adds a tx returned in getTxList', function() {
|
||||
var tx = { id: 1, status: 'confirmed', metamaskNetworkId: 'unit test' }
|
||||
txManager.addTx(tx, onTxDoneCb)
|
||||
var tx = { id: 1, status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
txManager.addTx(tx, noop)
|
||||
var result = txManager.getTxList()
|
||||
assert.ok(Array.isArray(result))
|
||||
assert.equal(result.length, 1)
|
||||
@ -73,8 +62,8 @@ describe('Transaction Manager', function() {
|
||||
it('cuts off early txs beyond a limit', function() {
|
||||
const limit = txManager.txHistoryLimit
|
||||
for (let i = 0; i < limit + 1; i++) {
|
||||
let tx = { id: i, time: new Date(), status: 'confirmed', metamaskNetworkId: 'unit test' }
|
||||
txManager.addTx(tx, onTxDoneCb)
|
||||
let tx = { id: i, time: new Date(), status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
txManager.addTx(tx, noop)
|
||||
}
|
||||
var result = txManager.getTxList()
|
||||
assert.equal(result.length, limit, `limit of ${limit} txs enforced`)
|
||||
@ -84,8 +73,8 @@ describe('Transaction Manager', function() {
|
||||
it('cuts off early txs beyond a limit whether or not it is confirmed or rejected', function() {
|
||||
const limit = txManager.txHistoryLimit
|
||||
for (let i = 0; i < limit + 1; i++) {
|
||||
let tx = { id: i, time: new Date(), status: 'rejected', metamaskNetworkId: 'unit test' }
|
||||
txManager.addTx(tx, onTxDoneCb)
|
||||
let tx = { id: i, time: new Date(), status: 'rejected', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
txManager.addTx(tx, noop)
|
||||
}
|
||||
var result = txManager.getTxList()
|
||||
assert.equal(result.length, limit, `limit of ${limit} txs enforced`)
|
||||
@ -93,12 +82,12 @@ describe('Transaction Manager', function() {
|
||||
})
|
||||
|
||||
it('cuts off early txs beyond a limit but does not cut unapproved txs', function() {
|
||||
var unconfirmedTx = { id: 0, time: new Date(), status: 'unapproved', metamaskNetworkId: 'unit test' }
|
||||
txManager.addTx(unconfirmedTx, onTxDoneCb)
|
||||
var unconfirmedTx = { id: 0, time: new Date(), status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
txManager.addTx(unconfirmedTx, noop)
|
||||
const limit = txManager.txHistoryLimit
|
||||
for (let i = 1; i < limit + 1; i++) {
|
||||
let tx = { id: i, time: new Date(), status: 'confirmed', metamaskNetworkId: 'unit test' }
|
||||
txManager.addTx(tx, onTxDoneCb)
|
||||
let tx = { id: i, time: new Date(), status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
txManager.addTx(tx, noop)
|
||||
}
|
||||
var result = txManager.getTxList()
|
||||
assert.equal(result.length, limit, `limit of ${limit} txs enforced`)
|
||||
@ -110,8 +99,8 @@ describe('Transaction Manager', function() {
|
||||
|
||||
describe('#setTxStatusSigned', function() {
|
||||
it('sets the tx status to signed', function() {
|
||||
var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' }
|
||||
txManager.addTx(tx, onTxDoneCb)
|
||||
var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
txManager.addTx(tx, noop)
|
||||
txManager.setTxStatusSigned(1)
|
||||
var result = txManager.getTxList()
|
||||
assert.ok(Array.isArray(result))
|
||||
@ -121,20 +110,20 @@ describe('Transaction Manager', function() {
|
||||
|
||||
it('should emit a signed event to signal the exciton of callback', (done) => {
|
||||
this.timeout(10000)
|
||||
var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' }
|
||||
let onTxDoneCb = function () {
|
||||
assert(true, 'event listener has been triggered and onTxDoneCb executed')
|
||||
var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
let noop = function () {
|
||||
assert(true, 'event listener has been triggered and noop executed')
|
||||
done()
|
||||
}
|
||||
txManager.addTx(tx)
|
||||
txManager.on('1:signed', onTxDoneCb)
|
||||
txManager.on('1:signed', noop)
|
||||
txManager.setTxStatusSigned(1)
|
||||
})
|
||||
})
|
||||
|
||||
describe('#setTxStatusRejected', function() {
|
||||
it('sets the tx status to rejected', function() {
|
||||
var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' }
|
||||
var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
txManager.addTx(tx)
|
||||
txManager.setTxStatusRejected(1)
|
||||
var result = txManager.getTxList()
|
||||
@ -145,13 +134,13 @@ describe('Transaction Manager', function() {
|
||||
|
||||
it('should emit a rejected event to signal the exciton of callback', (done) => {
|
||||
this.timeout(10000)
|
||||
var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test' }
|
||||
var tx = { id: 1, status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }
|
||||
txManager.addTx(tx)
|
||||
let onTxDoneCb = function (err, txId) {
|
||||
assert(true, 'event listener has been triggered and onTxDoneCb executed')
|
||||
let noop = function (err, txId) {
|
||||
assert(true, 'event listener has been triggered and noop executed')
|
||||
done()
|
||||
}
|
||||
txManager.on('1:rejected', onTxDoneCb)
|
||||
txManager.on('1:rejected', noop)
|
||||
txManager.setTxStatusRejected(1)
|
||||
})
|
||||
|
||||
@ -159,9 +148,9 @@ describe('Transaction Manager', function() {
|
||||
|
||||
describe('#updateTx', function() {
|
||||
it('replaces the tx with the same id', function() {
|
||||
txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test' }, onTxDoneCb)
|
||||
txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test' }, onTxDoneCb)
|
||||
txManager.updateTx({ id: '1', status: 'blah', hash: 'foo', metamaskNetworkId: 'unit test' })
|
||||
txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }, noop)
|
||||
txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }, noop)
|
||||
txManager.updateTx({ id: '1', status: 'blah', hash: 'foo', metamaskNetworkId: 'unit test', txParams: {} })
|
||||
var result = txManager.getTx('1')
|
||||
assert.equal(result.hash, 'foo')
|
||||
})
|
||||
@ -169,8 +158,8 @@ describe('Transaction Manager', function() {
|
||||
|
||||
describe('#getUnapprovedTxList', function() {
|
||||
it('returns unapproved txs in a hash', function() {
|
||||
txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test' }, onTxDoneCb)
|
||||
txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test' }, onTxDoneCb)
|
||||
txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }, noop)
|
||||
txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }, noop)
|
||||
let result = txManager.getUnapprovedTxList()
|
||||
assert.equal(typeof result, 'object')
|
||||
assert.equal(result['1'].status, 'unapproved')
|
||||
@ -180,8 +169,8 @@ describe('Transaction Manager', function() {
|
||||
|
||||
describe('#getTx', function() {
|
||||
it('returns a tx with the requested id', function() {
|
||||
txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test' }, onTxDoneCb)
|
||||
txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test' }, onTxDoneCb)
|
||||
txManager.addTx({ id: '1', status: 'unapproved', metamaskNetworkId: 'unit test', txParams: {} }, noop)
|
||||
txManager.addTx({ id: '2', status: 'confirmed', metamaskNetworkId: 'unit test', txParams: {} }, noop)
|
||||
assert.equal(txManager.getTx('1').status, 'unapproved')
|
||||
assert.equal(txManager.getTx('2').status, 'confirmed')
|
||||
})
|
||||
@ -189,26 +178,33 @@ describe('Transaction Manager', function() {
|
||||
|
||||
describe('#getFilteredTxList', function() {
|
||||
it('returns a tx with the requested data', function() {
|
||||
var foop = 0
|
||||
var zoop = 0
|
||||
for (let i = 0; i < 10; ++i ){
|
||||
let everyOther = i % 2
|
||||
txManager.addTx({ id: i,
|
||||
status: everyOther ? 'unapproved' : 'confirmed',
|
||||
metamaskNetworkId: 'unit test',
|
||||
txParams: {
|
||||
from: everyOther ? 'foop' : 'zoop',
|
||||
to: everyOther ? 'zoop' : 'foop',
|
||||
}
|
||||
}, onTxDoneCb)
|
||||
everyOther ? ++foop : ++zoop
|
||||
}
|
||||
assert.equal(txManager.getFilteredTxList({status: 'confirmed', from: 'zoop'}).length, zoop)
|
||||
assert.equal(txManager.getFilteredTxList({status: 'confirmed', to: 'foop'}).length, zoop)
|
||||
assert.equal(txManager.getFilteredTxList({status: 'confirmed', from: 'foop'}).length, 0)
|
||||
assert.equal(txManager.getFilteredTxList({status: 'confirmed'}).length, zoop)
|
||||
assert.equal(txManager.getFilteredTxList({from: 'foop'}).length, foop)
|
||||
assert.equal(txManager.getFilteredTxList({from: 'zoop'}).length, zoop)
|
||||
let txMetas = [
|
||||
{ id: 0, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 1, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 2, status: 'unapproved', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 3, status: 'unapproved', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 4, status: 'unapproved', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 5, status: 'confirmed', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 6, status: 'confirmed', txParams: { from: '0xaa', to: '0xbb' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 7, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 8, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' },
|
||||
{ id: 9, status: 'confirmed', txParams: { from: '0xbb', to: '0xaa' }, metamaskNetworkId: 'unit test' },
|
||||
]
|
||||
txMetas.forEach((txMeta) => txManager.addTx(txMeta, noop))
|
||||
let filterParams
|
||||
|
||||
filterParams = { status: 'unapproved', from: '0xaa' }
|
||||
assert.equal(txManager.getFilteredTxList(filterParams).length, 3, `getFilteredTxList - ${JSON.stringify(filterParams)}`)
|
||||
filterParams = { status: 'unapproved', to: '0xaa' }
|
||||
assert.equal(txManager.getFilteredTxList(filterParams).length, 2, `getFilteredTxList - ${JSON.stringify(filterParams)}`)
|
||||
filterParams = { status: 'confirmed', from: '0xbb' }
|
||||
assert.equal(txManager.getFilteredTxList(filterParams).length, 3, `getFilteredTxList - ${JSON.stringify(filterParams)}`)
|
||||
filterParams = { status: 'confirmed' }
|
||||
assert.equal(txManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`)
|
||||
filterParams = { from: '0xaa' }
|
||||
assert.equal(txManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`)
|
||||
filterParams = { to: '0xaa' }
|
||||
assert.equal(txManager.getFilteredTxList(filterParams).length, 5, `getFilteredTxList - ${JSON.stringify(filterParams)}`)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -158,6 +158,7 @@ var actions = {
|
||||
showNewKeychain: showNewKeychain,
|
||||
|
||||
callBackgroundThenUpdate,
|
||||
forceUpdateMetamaskState,
|
||||
}
|
||||
|
||||
module.exports = actions
|
||||
@ -179,13 +180,14 @@ function tryUnlockMetamask (password) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
dispatch(actions.unlockInProgress())
|
||||
background.submitPassword(password, (err, newState) => {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.submitPassword`)
|
||||
background.submitPassword(password, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) {
|
||||
dispatch(actions.unlockFailed(err.message))
|
||||
} else {
|
||||
dispatch(actions.transitionForward())
|
||||
dispatch(actions.updateMetamaskState(newState))
|
||||
forceUpdateMetamaskState(dispatch)
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -206,6 +208,7 @@ function transitionBackward () {
|
||||
function confirmSeedWords () {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
if (global.METAMASK_DEBUG) console.log(`background.clearSeedWordCache`)
|
||||
background.clearSeedWordCache((err, account) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) {
|
||||
@ -221,6 +224,7 @@ function confirmSeedWords () {
|
||||
function createNewVaultAndRestore (password, seed) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
if (global.METAMASK_DEBUG) console.log(`background.createNewVaultAndRestore`)
|
||||
background.createNewVaultAndRestore(password, seed, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) return dispatch(actions.displayWarning(err.message))
|
||||
@ -232,16 +236,18 @@ function createNewVaultAndRestore (password, seed) {
|
||||
function createNewVaultAndKeychain (password) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
background.createNewVaultAndKeychain(password, (err, newState) => {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.createNewVaultAndKeychain`)
|
||||
background.createNewVaultAndKeychain(password, (err) => {
|
||||
if (err) {
|
||||
return dispatch(actions.displayWarning(err.message))
|
||||
}
|
||||
background.placeSeedWords((err, newState) => {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.placeSeedWords`)
|
||||
background.placeSeedWords((err) => {
|
||||
if (err) {
|
||||
return dispatch(actions.displayWarning(err.message))
|
||||
}
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
dispatch(actions.updateMetamaskState(newState))
|
||||
forceUpdateMetamaskState(dispatch)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -256,8 +262,10 @@ function revealSeedConfirmation () {
|
||||
function requestRevealSeed (password) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
if (global.METAMASK_DEBUG) console.log(`background.submitPassword`)
|
||||
background.submitPassword(password, (err) => {
|
||||
if (err) return dispatch(actions.displayWarning(err.message))
|
||||
if (global.METAMASK_DEBUG) console.log(`background.placeSeedWords`)
|
||||
background.placeSeedWords((err) => {
|
||||
if (err) return dispatch(actions.displayWarning(err.message))
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
@ -269,6 +277,7 @@ function requestRevealSeed (password) {
|
||||
function addNewKeyring (type, opts) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
if (global.METAMASK_DEBUG) console.log(`background.addNewKeyring`)
|
||||
background.addNewKeyring(type, opts, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) return dispatch(actions.displayWarning(err.message))
|
||||
@ -280,13 +289,20 @@ function addNewKeyring (type, opts) {
|
||||
function importNewAccount (strategy, args) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication('This may take a while, be patient.'))
|
||||
background.importAccountWithStrategy(strategy, args, (err, newState) => {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.importAccountWithStrategy`)
|
||||
background.importAccountWithStrategy(strategy, args, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) return dispatch(actions.displayWarning(err.message))
|
||||
dispatch(actions.updateMetamaskState(newState))
|
||||
dispatch({
|
||||
type: actions.SHOW_ACCOUNT_DETAIL,
|
||||
value: newState.selectedAddress,
|
||||
if (global.METAMASK_DEBUG) console.log(`background.getState`)
|
||||
background.getState((err, newState) => {
|
||||
if (err) {
|
||||
return dispatch(actions.displayWarning(err.message))
|
||||
}
|
||||
dispatch(actions.updateMetamaskState(newState))
|
||||
dispatch({
|
||||
type: actions.SHOW_ACCOUNT_DETAIL,
|
||||
value: newState.selectedAddress,
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -299,6 +315,7 @@ function navigateToNewAccountScreen() {
|
||||
}
|
||||
|
||||
function addNewAccount () {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.addNewAccount`)
|
||||
return callBackgroundThenUpdate(background.addNewAccount)
|
||||
}
|
||||
|
||||
@ -308,11 +325,16 @@ function showInfoPage () {
|
||||
}
|
||||
}
|
||||
|
||||
function setCurrentFiat (fiat) {
|
||||
function setCurrentFiat (currencyCode) {
|
||||
return (dispatch) => {
|
||||
dispatch(this.showLoadingIndication())
|
||||
background.setCurrentFiat(fiat, (data, err) => {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.setCurrentFiat`)
|
||||
background.setCurrentCurrency(currencyCode, (err, data) => {
|
||||
dispatch(this.hideLoadingIndication())
|
||||
if (err) {
|
||||
console.error(err.stack)
|
||||
return dispatch(actions.displayWarning(err.message))
|
||||
}
|
||||
dispatch({
|
||||
type: this.SET_CURRENT_FIAT,
|
||||
value: {
|
||||
@ -329,6 +351,7 @@ function signMsg (msgData) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
|
||||
if (global.METAMASK_DEBUG) console.log(`background.signMessage`)
|
||||
background.signMessage(msgData, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
|
||||
@ -340,6 +363,7 @@ function signMsg (msgData) {
|
||||
|
||||
function signTx (txData) {
|
||||
return (dispatch) => {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.setGasMultiplier`)
|
||||
background.setGasMultiplier(txData.gasMultiplier, (err) => {
|
||||
if (err) return dispatch(actions.displayWarning(err.message))
|
||||
web3.eth.sendTransaction(txData, (err, data) => {
|
||||
@ -355,6 +379,7 @@ function signTx (txData) {
|
||||
|
||||
function sendTx (txData) {
|
||||
return (dispatch) => {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.approveTransaction`)
|
||||
background.approveTransaction(txData.id, (err) => {
|
||||
if (err) {
|
||||
alert(err.message)
|
||||
@ -381,11 +406,13 @@ function txError (err) {
|
||||
}
|
||||
|
||||
function cancelMsg (msgData) {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.cancelMessage`)
|
||||
background.cancelMessage(msgData.id)
|
||||
return actions.completedTx(msgData.id)
|
||||
}
|
||||
|
||||
function cancelTx (txData) {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.cancelTransaction`)
|
||||
background.cancelTransaction(txData.id)
|
||||
return actions.completedTx(txData.id)
|
||||
}
|
||||
@ -427,6 +454,7 @@ function showImportPage () {
|
||||
function agreeToDisclaimer () {
|
||||
return (dispatch) => {
|
||||
dispatch(this.showLoadingIndication())
|
||||
if (global.METAMASK_DEBUG) console.log(`background.agreeToDisclaimer`)
|
||||
background.agreeToDisclaimer((err) => {
|
||||
if (err) {
|
||||
return dispatch(actions.displayWarning(err.message))
|
||||
@ -497,12 +525,14 @@ function updateMetamaskState (newState) {
|
||||
}
|
||||
|
||||
function lockMetamask () {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.setLocked`)
|
||||
return callBackgroundThenUpdate(background.setLocked)
|
||||
}
|
||||
|
||||
function showAccountDetail (address) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
if (global.METAMASK_DEBUG) console.log(`background.setSelectedAddress`)
|
||||
background.setSelectedAddress(address, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) {
|
||||
@ -575,6 +605,7 @@ function goBackToInitView () {
|
||||
function markNoticeRead (notice) {
|
||||
return (dispatch) => {
|
||||
dispatch(this.showLoadingIndication())
|
||||
if (global.METAMASK_DEBUG) console.log(`background.markNoticeRead`)
|
||||
background.markNoticeRead(notice, (err, notice) => {
|
||||
dispatch(this.hideLoadingIndication())
|
||||
if (err) {
|
||||
@ -606,6 +637,7 @@ function clearNotices () {
|
||||
}
|
||||
|
||||
function markAccountsFound() {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.markAccountsFound`)
|
||||
return callBackgroundThenUpdate(background.markAccountsFound)
|
||||
}
|
||||
|
||||
@ -614,6 +646,7 @@ function markAccountsFound() {
|
||||
//
|
||||
|
||||
function setRpcTarget (newRpc) {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.setRpcTarget`)
|
||||
background.setRpcTarget(newRpc)
|
||||
return {
|
||||
type: actions.SET_RPC_TARGET,
|
||||
@ -622,6 +655,7 @@ function setRpcTarget (newRpc) {
|
||||
}
|
||||
|
||||
function setProviderType (type) {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.setProviderType`)
|
||||
background.setProviderType(type)
|
||||
return {
|
||||
type: actions.SET_PROVIDER_TYPE,
|
||||
@ -630,6 +664,7 @@ function setProviderType (type) {
|
||||
}
|
||||
|
||||
function useEtherscanProvider () {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.useEtherscanProvider`)
|
||||
background.useEtherscanProvider()
|
||||
return {
|
||||
type: actions.USE_ETHERSCAN_PROVIDER,
|
||||
@ -686,6 +721,7 @@ function exportAccount (address) {
|
||||
return function (dispatch) {
|
||||
dispatch(self.showLoadingIndication())
|
||||
|
||||
if (global.METAMASK_DEBUG) console.log(`background.exportAccount`)
|
||||
background.exportAccount(address, function (err, result) {
|
||||
dispatch(self.hideLoadingIndication())
|
||||
|
||||
@ -709,6 +745,7 @@ function showPrivateKey (key) {
|
||||
function saveAccountLabel (account, label) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
if (global.METAMASK_DEBUG) console.log(`background.saveAccountLabel`)
|
||||
background.saveAccountLabel(account, label, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) {
|
||||
@ -730,6 +767,7 @@ function showSendPage () {
|
||||
|
||||
function buyEth (address, amount) {
|
||||
return (dispatch) => {
|
||||
if (global.METAMASK_DEBUG) console.log(`background.buyEth`)
|
||||
background.buyEth(address, amount)
|
||||
dispatch({
|
||||
type: actions.BUY_ETH,
|
||||
@ -808,6 +846,7 @@ function coinShiftRquest (data, marketData) {
|
||||
if (response.error) return dispatch(actions.displayWarning(response.error))
|
||||
var message = `
|
||||
Deposit your ${response.depositType} to the address bellow:`
|
||||
if (global.METAMASK_DEBUG) console.log(`background.createShapeShiftTx`)
|
||||
background.createShapeShiftTx(response.deposit, response.depositType)
|
||||
dispatch(actions.showQrView(response.deposit, [message].concat(marketData)))
|
||||
})
|
||||
@ -876,12 +915,22 @@ function shapeShiftRequest (query, options, cb) {
|
||||
function callBackgroundThenUpdate (method, ...args) {
|
||||
return (dispatch) => {
|
||||
dispatch(actions.showLoadingIndication())
|
||||
method.call(background, ...args, (err, newState) => {
|
||||
method.call(background, ...args, (err) => {
|
||||
dispatch(actions.hideLoadingIndication())
|
||||
if (err) {
|
||||
return dispatch(actions.displayWarning(err.message))
|
||||
}
|
||||
dispatch(actions.updateMetamaskState(newState))
|
||||
forceUpdateMetamaskState(dispatch)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function forceUpdateMetamaskState(dispatch){
|
||||
if (global.METAMASK_DEBUG) console.log(`background.getState`)
|
||||
background.getState((err, newState) => {
|
||||
if (err) {
|
||||
return dispatch(actions.displayWarning(err.message))
|
||||
}
|
||||
dispatch(actions.updateMetamaskState(newState))
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user