aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrances Pangilinan <frankie.diamond@gmail.com>2016-12-15 04:55:41 +0800
committerFrances Pangilinan <frankie.diamond@gmail.com>2016-12-15 04:55:41 +0800
commit090935f90aa3c2589fee7bc038c8f4fcf77da03c (patch)
tree82a21bd7d0df26d6de637892cbd9322d52b7785b
parent9e3fa3cfba20299413df87d18158180c7798d2ac (diff)
downloadtangerine-wallet-browser-090935f90aa3c2589fee7bc038c8f4fcf77da03c.tar
tangerine-wallet-browser-090935f90aa3c2589fee7bc038c8f4fcf77da03c.tar.gz
tangerine-wallet-browser-090935f90aa3c2589fee7bc038c8f4fcf77da03c.tar.bz2
tangerine-wallet-browser-090935f90aa3c2589fee7bc038c8f4fcf77da03c.tar.lz
tangerine-wallet-browser-090935f90aa3c2589fee7bc038c8f4fcf77da03c.tar.xz
tangerine-wallet-browser-090935f90aa3c2589fee7bc038c8f4fcf77da03c.tar.zst
tangerine-wallet-browser-090935f90aa3c2589fee7bc038c8f4fcf77da03c.zip
Create a TxManager
-rw-r--r--app/scripts/background.js26
-rw-r--r--app/scripts/keyring-controller.js118
-rw-r--r--app/scripts/lib/config-manager.js51
-rw-r--r--app/scripts/lib/idStore.js13
-rw-r--r--app/scripts/lib/provider-utils.js106
-rw-r--r--app/scripts/metamask-controller.js16
-rw-r--r--app/scripts/transaction-manager.js179
7 files changed, 350 insertions, 159 deletions
diff --git a/app/scripts/background.js b/app/scripts/background.js
index 7cb25d8bf..854b679da 100644
--- a/app/scripts/background.js
+++ b/app/scripts/background.js
@@ -23,7 +23,7 @@ const controller = new MetamaskController({
loadData,
})
const keyringController = controller.keyringController
-
+const txManager = controller.txManager
function triggerUi () {
if (!popupIsOpen) notification.show()
}
@@ -97,12 +97,11 @@ function setupControllerConnection (stream) {
// plugin badge text
//
-keyringController.on('update', updateBadge)
+txManager.on('update', updateBadge)
function updateBadge () {
var label = ''
- var unconfTxs = controller.configManager.unconfirmedTxs()
- var unconfTxLen = Object.keys(unconfTxs).length
+ var unconfTxLen = controller.txManager.unConftxCount
var unconfMsgs = messageManager.unconfirmedMsgs()
var unconfMsgLen = Object.keys(unconfMsgs).length
var count = unconfTxLen + unconfMsgLen
@@ -113,6 +112,25 @@ function updateBadge () {
extension.browserAction.setBadgeBackgroundColor({ color: '#506F8B' })
}
+// txManger :: tx approvals and rejection cb's
+
+txManager.on('signed', function (txId) {
+ var approvalCb = this._unconfTxCbs[txId]
+
+ approvalCb(null, true)
+ // clean up
+ delete this._unconfTxCbs[txId]
+})
+
+txManager.on('rejected', function (txId) {
+ var approvalCb = this._unconfTxCbs[txId]
+ approvalCb(null, false)
+ // clean up
+ delete this._unconfTxCbs[txId]
+})
+
+// data :: setters/getters
+
function loadData () {
var oldData = getOldStyleData()
var newData
diff --git a/app/scripts/keyring-controller.js b/app/scripts/keyring-controller.js
index 40c9695dd..37b3a947f 100644
--- a/app/scripts/keyring-controller.js
+++ b/app/scripts/keyring-controller.js
@@ -1,6 +1,4 @@
-const async = require('async')
const ethUtil = require('ethereumjs-util')
-const EthQuery = require('eth-query')
const bip39 = require('bip39')
const Transaction = require('ethereumjs-tx')
const EventEmitter = require('events').EventEmitter
@@ -36,7 +34,7 @@ module.exports = class KeyringController extends EventEmitter {
this.ethStore = opts.ethStore
this.encryptor = encryptor
this.keyringTypes = keyringTypes
-
+ this.txManager = opts.txManager
this.keyrings = []
this.identities = {} // Essentially a name hash
@@ -73,7 +71,7 @@ module.exports = class KeyringController extends EventEmitter {
// or accept a state-resolving promise to consume their results.
//
// Not all methods end with this, that might be a nice refactor.
- fullUpdate() {
+ fullUpdate () {
this.emit('update')
return Promise.resolve(this.getState())
}
@@ -102,8 +100,8 @@ module.exports = class KeyringController extends EventEmitter {
isInitialized: (!!wallet || !!vault),
isUnlocked: Boolean(this.password),
isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(), // AUDIT this.configManager.getConfirmedDisclaimer(),
- unconfTxs: this.configManager.unconfirmedTxs(),
- transactions: this.configManager.getTxList(),
+ transactions: this.txManager.getTxList(),
+ unconfTxs: this.txManager.getUnapprovedTxList(),
unconfMsgs: messageManager.unconfirmedMsgs(),
messages: messageManager.getMsgList(),
selectedAccount: address,
@@ -341,7 +339,7 @@ module.exports = class KeyringController extends EventEmitter {
// Caches the requesting Dapp's callback, `onTxDoneCb`, for resolution later.
addUnconfirmedTransaction (txParams, onTxDoneCb, cb) {
const configManager = this.configManager
-
+ const txManager = this.txManager
// create txData obj with parameters and meta data
var time = (new Date()).getTime()
var txId = createId()
@@ -351,95 +349,26 @@ module.exports = class KeyringController extends EventEmitter {
id: txId,
txParams: txParams,
time: time,
- status: 'unconfirmed',
+ status: 'unapproved',
gasMultiplier: configManager.getGasMultiplier() || 1,
metamaskNetworkId: this.getNetwork(),
}
-
// keep the onTxDoneCb around for after approval/denial (requires user interaction)
// This onTxDoneCb fires completion to the Dapp's write operation.
- this._unconfTxCbs[txId] = onTxDoneCb
-
- var provider = this.ethStore._query.currentProvider
- var query = new EthQuery(provider)
-
+ txManager.txProviderUtils.analyzeGasUsage(txData, this.txDidComplete.bind(this, txData, onTxDoneCb, cb))
// calculate metadata for tx
- this.analyzeTxGasUsage(query, txData, this.txDidComplete.bind(this, txData, cb))
- }
-
- estimateTxGas (query, txData, blockGasLimitHex, cb) {
- const txParams = txData.txParams
- // check if gasLimit is already specified
- txData.gasLimitSpecified = Boolean(txParams.gas)
- // if not, fallback to block gasLimit
- if (!txData.gasLimitSpecified) {
- txParams.gas = blockGasLimitHex
- }
- // run tx, see if it will OOG
- query.estimateGas(txParams, cb)
- }
-
- checkForTxGasError (txData, estimatedGasHex, cb) {
- txData.estimatedGas = estimatedGasHex
- // all gas used - must be an error
- if (estimatedGasHex === txData.txParams.gas) {
- txData.simulationFails = true
- }
- cb()
- }
-
- setTxGas (txData, blockGasLimitHex, cb) {
- const txParams = txData.txParams
- // if OOG, nothing more to do
- if (txData.simulationFails) {
- cb()
- return
- }
- // if gasLimit was specified and doesnt OOG,
- // use original specified amount
- if (txData.gasLimitSpecified) {
- txData.estimatedGas = txParams.gas
- cb()
- return
- }
- // if gasLimit not originally specified,
- // try adding an additional gas buffer to our estimation for safety
- const estimatedGasBn = new BN(ethUtil.stripHexPrefix(txData.estimatedGas), 16)
- const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16)
- const estimationWithBuffer = new BN(this.addGasBuffer(estimatedGasBn), 16)
- // added gas buffer is too high
- if (estimationWithBuffer.gt(blockGasLimitBn)) {
- txParams.gas = txData.estimatedGas
- // added gas buffer is safe
- } else {
- const gasWithBufferHex = ethUtil.intToHex(estimationWithBuffer)
- txParams.gas = gasWithBufferHex
- }
- cb()
- return
}
- txDidComplete (txData, cb, err) {
+ txDidComplete (txData, onTxDoneCb, cb, err) {
if (err) return cb(err)
- const configManager = this.configManager
- configManager.addTx(txData)
+ const txManager = this.txManager
+ txManager.addTx(txData, onTxDoneCb)
// signal update
this.emit('update')
// signal completion of add tx
cb(null, txData)
}
- analyzeTxGasUsage (query, txData, cb) {
- query.getBlockByNumber('latest', true, (err, block) => {
- if (err) return cb(err)
- async.waterfall([
- this.estimateTxGas.bind(this, query, txData, block.gasLimit),
- this.checkForTxGasError.bind(this, txData),
- this.setTxGas.bind(this, txData, block.gasLimit),
- ], cb)
- })
- }
-
// Cancel Transaction
// @string txId
// @function cb
@@ -448,14 +377,8 @@ module.exports = class KeyringController extends EventEmitter {
//
// Forgets any tx matching `txId`.
cancelTransaction (txId, cb) {
- const configManager = this.configManager
- var approvalCb = this._unconfTxCbs[txId] || noop
-
- // reject tx
- approvalCb(null, false)
- // clean up
- configManager.rejectTx(txId)
- delete this._unconfTxCbs[txId]
+ const txManager = this.txManager
+ txManager.setTxStatusRejected(txId)
if (cb && typeof cb === 'function') {
cb()
@@ -473,16 +396,10 @@ module.exports = class KeyringController extends EventEmitter {
//
// Calls back the cached Dapp's confirmation callback, also.
approveTransaction (txId, cb) {
- const configManager = this.configManager
- var approvalCb = this._unconfTxCbs[txId] || noop
-
- // accept tx
- cb()
- approvalCb(null, true)
- // clean up
- configManager.confirmTx(txId)
- delete this._unconfTxCbs[txId]
+ const txManager = this.txManager
+ txManager.setTxStatusSigned(txId)
this.emit('update')
+ cb()
}
signTransaction (txParams, cb) {
@@ -510,9 +427,9 @@ module.exports = class KeyringController extends EventEmitter {
.then((tx) => {
// Add the tx hash to the persisted meta-tx object
var txHash = ethUtil.bufferToHex(tx.hash())
- var metaTx = this.configManager.getTx(txParams.metamaskId)
+ var metaTx = this.txManager.getTx(txParams.metamaskId)
metaTx.hash = txHash
- this.configManager.updateTx(metaTx)
+ this.txManager.updateTx(metaTx)
// return raw serialized tx
var rawTx = ethUtil.bufferToHex(tx.serialize())
@@ -586,7 +503,6 @@ module.exports = class KeyringController extends EventEmitter {
// Attempts to sign the provided @object msgParams.
signMessage (msgParams, cb) {
try {
-
const msgId = msgParams.metamaskId
delete msgParams.metamaskId
const approvalCb = this._unconfMsgCbs[msgId] || noop
diff --git a/app/scripts/lib/config-manager.js b/app/scripts/lib/config-manager.js
index 59cc2b63c..913a76a6e 100644
--- a/app/scripts/lib/config-manager.js
+++ b/app/scripts/lib/config-manager.js
@@ -209,61 +209,12 @@ ConfigManager.prototype.getTxList = function () {
}
}
-ConfigManager.prototype.unconfirmedTxs = function () {
- var transactions = this.getTxList()
- return transactions.filter(tx => tx.status === 'unconfirmed')
- .reduce((result, tx) => { result[tx.id] = tx; return result }, {})
-}
-
-ConfigManager.prototype._saveTxList = function (txList) {
+ConfigManager.prototype.setTxList = function (txList) {
var data = this.migrator.getData()
data.transactions = txList
this.setData(data)
}
-ConfigManager.prototype.addTx = function (tx) {
- var transactions = this.getTxList()
- while (transactions.length > this.txLimit - 1) {
- transactions.shift()
- }
- transactions.push(tx)
- this._saveTxList(transactions)
-}
-
-ConfigManager.prototype.getTx = function (txId) {
- var transactions = this.getTxList()
- var matching = transactions.filter(tx => tx.id === txId)
- return matching.length > 0 ? matching[0] : null
-}
-
-ConfigManager.prototype.confirmTx = function (txId) {
- this._setTxStatus(txId, 'confirmed')
-}
-
-ConfigManager.prototype.rejectTx = function (txId) {
- this._setTxStatus(txId, 'rejected')
-}
-
-ConfigManager.prototype._setTxStatus = function (txId, status) {
- var tx = this.getTx(txId)
- tx.status = status
- this.updateTx(tx)
-}
-
-ConfigManager.prototype.updateTx = function (tx) {
- var transactions = this.getTxList()
- var found, index
- transactions.forEach((otherTx, i) => {
- if (otherTx.id === tx.id) {
- found = true
- index = i
- }
- })
- if (found) {
- transactions[index] = tx
- }
- this._saveTxList(transactions)
-}
// wallet nickname methods
diff --git a/app/scripts/lib/idStore.js b/app/scripts/lib/idStore.js
index d36504f13..71bee8026 100644
--- a/app/scripts/lib/idStore.js
+++ b/app/scripts/lib/idStore.js
@@ -13,6 +13,8 @@ const autoFaucet = require('./auto-faucet')
const messageManager = require('./message-manager')
const DEFAULT_RPC = 'https://testrpc.metamask.io/'
const IdManagement = require('./id-management')
+const TxManager = require('../transaction-manager')
+
module.exports = IdentityStore
@@ -36,6 +38,11 @@ function IdentityStore (opts = {}) {
}
// not part of serilized metamask state - only kept in memory
+ this.txManager = new TxManager({
+ TxListFromStore: opts.configManager.getTxList(),
+ setTxList: opts.configManager.setTxList.bind(opts.configManager),
+ txLimit: 40,
+ })
this._unconfTxCbs = {}
this._unconfMsgCbs = {}
}
@@ -87,6 +94,7 @@ IdentityStore.prototype.recoverFromSeed = function (password, seed, cb) {
IdentityStore.prototype.setStore = function (store) {
this._ethStore = store
+ this.txManager.setProvider(this._ethStore._query.currentProvider)
}
IdentityStore.prototype.clearSeedWordCache = function (cb) {
@@ -97,14 +105,15 @@ IdentityStore.prototype.clearSeedWordCache = function (cb) {
IdentityStore.prototype.getState = function () {
const configManager = this.configManager
+ const TxManager = this.txManager
var seedWords = this.getSeedIfUnlocked()
return clone(extend(this._currentState, {
isInitialized: !!configManager.getWallet() && !seedWords,
isUnlocked: this._isUnlocked(),
seedWords: seedWords,
isDisclaimerConfirmed: configManager.getConfirmedDisclaimer(),
- unconfTxs: configManager.unconfirmedTxs(),
- transactions: configManager.getTxList(),
+ unconfTxs: TxManager.getUnapprovedTxList(),
+ transactions: TxManager.getTxList(),
unconfMsgs: messageManager.unconfirmedMsgs(),
messages: messageManager.getMsgList(),
selectedAddress: configManager.getSelectedAccount(),
diff --git a/app/scripts/lib/provider-utils.js b/app/scripts/lib/provider-utils.js
new file mode 100644
index 000000000..d1678c964
--- /dev/null
+++ b/app/scripts/lib/provider-utils.js
@@ -0,0 +1,106 @@
+const async = require('async')
+const EthQuery = require('eth-query')
+const ethUtil = require('ethereumjs-util')
+const BN = ethUtil.BN
+const ethBinToOps = require('eth-bin-to-ops')
+
+module.exports = class txProviderUtils {
+ constructor (provider) {
+ this.provider = provider
+ this.query = new EthQuery(provider)
+ }
+ analyzeGasUsage (txData, 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.checkForTxGasError.bind(self, txData),
+ self.setTxGas.bind(self, txData, block.gasLimit),
+ ], cb)
+ })
+ }
+
+ // perform static analyis on the target contract code
+ analyzeForDelegateCall (txParams, cb) {
+ if (txParams.to) {
+ this.query.getCode(txParams.to, function (err, result) {
+ if (err) return cb(err)
+
+ var code = ethUtil.toBuffer(result)
+ if (code !== '0x') {
+ var ops = ethBinToOps(code)
+ var containsDelegateCall = ops.some((op) => op.name === 'DELEGATECALL')
+ cb(containsDelegateCall)
+ } else {
+ cb()
+ }
+ })
+ } else {
+ cb()
+ }
+ }
+
+ estimateTxGas (txData, blockGasLimitHex, cb) {
+ const txParams = txData.txParams
+ // check if gasLimit is already specified
+ txData.gasLimitSpecified = Boolean(txParams.gas)
+ // if not, fallback to block gasLimit
+ if (!txData.gasLimitSpecified) {
+ txParams.gas = blockGasLimitHex
+ }
+ // run tx, see if it will OOG
+ this.query.estimateGas(txParams, cb)
+ }
+
+ checkForTxGasError (txData, estimatedGasHex, cb) {
+ txData.estimatedGas = estimatedGasHex
+ // all gas used - must be an error
+ if (estimatedGasHex === txData.txParams.gas) {
+ txData.simulationFails = true
+ }
+ cb()
+ }
+
+ handleFork (block) {
+
+ }
+
+ setTxGas (txData, blockGasLimitHex, cb) {
+ const txParams = txData.txParams
+ // if OOG, nothing more to do
+ if (txData.simulationFails) {
+ cb()
+ return
+ }
+ // if gasLimit was specified and doesnt OOG,
+ // use original specified amount
+ if (txData.gasLimitSpecified) {
+ txData.estimatedGas = txParams.gas
+ cb()
+ return
+ }
+ // if gasLimit not originally specified,
+ // try adding an additional gas buffer to our estimation for safety
+ const estimatedGasBn = new BN(ethUtil.stripHexPrefix(txData.estimatedGas), 16)
+ const blockGasLimitBn = new BN(ethUtil.stripHexPrefix(blockGasLimitHex), 16)
+ const estimationWithBuffer = new BN(this.addGasBuffer(estimatedGasBn), 16)
+ // added gas buffer is too high
+ if (estimationWithBuffer.gt(blockGasLimitBn)) {
+ txParams.gas = txData.estimatedGas
+ // added gas buffer is safe
+ } else {
+ const gasWithBufferHex = ethUtil.intToHex(estimationWithBuffer)
+ txParams.gas = gasWithBufferHex
+ }
+ cb()
+ return
+ }
+
+ addGasBuffer (gas) {
+ const gasBuffer = new BN('100000', 10)
+ const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16)
+ const correct = bnGas.add(gasBuffer)
+ return ethUtil.addHexPrefix(correct.toString(16))
+ }
+}
diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js
index ae761c753..3b70f63db 100644
--- a/app/scripts/metamask-controller.js
+++ b/app/scripts/metamask-controller.js
@@ -3,6 +3,7 @@ const EthStore = require('eth-store')
const MetaMaskProvider = require('web3-provider-engine/zero.js')
const KeyringController = require('./keyring-controller')
const messageManager = require('./lib/message-manager')
+const TxManager = require('./transaction-manager')
const HostStore = require('./lib/remote-store.js').HostStore
const Web3 = require('web3')
const ConfigManager = require('./lib/config-manager')
@@ -18,13 +19,21 @@ module.exports = class MetamaskController {
this.opts = opts
this.listeners = []
this.configManager = new ConfigManager(opts)
+ this.txManager = new TxManager({
+ TxListFromStore: this.configManager.getTxList(),
+ txLimit: this.configManager.txLimit,
+ setTxList: this.configManager.setTxList.bind(this.configManager),
+ })
+
this.keyringController = new KeyringController({
configManager: this.configManager,
+ txManager: this.txManager,
getNetwork: this.getStateNetwork.bind(this),
})
this.provider = this.initializeProvider(opts)
this.ethStore = new EthStore(this.provider)
this.keyringController.setStore(this.ethStore)
+ this.txManager.setProvider(this.provider)
this.getNetwork()
this.messageManager = messageManager
this.publicConfigStore = this.initPublicConfigStore()
@@ -49,7 +58,7 @@ module.exports = class MetamaskController {
getApi () {
const keyringController = this.keyringController
-
+ const txManager = this.txManager
return {
getState: (cb) => { cb(null, this.getState()) },
setRpcTarget: this.setRpcTarget.bind(this),
@@ -81,6 +90,9 @@ module.exports = class MetamaskController {
signMessage: keyringController.signMessage.bind(keyringController),
cancelMessage: keyringController.cancelMessage.bind(keyringController),
+ // forward directly to txManager
+ getUnapprovedTxList: txManager.getTxList.bind(txManager),
+ getFilterdTxList: txManager.getFilterdTxList.bind(txManager),
// coinbase
buyEth: this.buyEth.bind(this),
// shapeshift
@@ -154,7 +166,7 @@ module.exports = class MetamaskController {
var web3 = new Web3(provider)
this.web3 = web3
keyringController.web3 = web3
-
+ this.txManager.web3 = web3
provider.on('block', this.processBlock.bind(this))
provider.on('error', this.getNetwork.bind(this))
diff --git a/app/scripts/transaction-manager.js b/app/scripts/transaction-manager.js
new file mode 100644
index 000000000..07e588679
--- /dev/null
+++ b/app/scripts/transaction-manager.js
@@ -0,0 +1,179 @@
+const EventEmitter = require('events')
+const extend = require('xtend')
+const TxProviderUtil = require('./lib/provider-utils')
+
+module.exports = class TransactionManager extends EventEmitter {
+ constructor (opts) {
+ super()
+ this.txList = opts.TxListFromStore || []
+ this._persistTxList = opts.setTxList
+ this._unconfTxCbs = {}
+ this.txLimit = opts.txLimit
+ this.provider = opts.provider
+ }
+
+// Returns the tx list
+ getTxList () {
+ return this.txList
+ }
+
+ // Saves the new/updated txList.
+ // Function is intended only for internal use
+ _saveTxList (txList) {
+ this.txList = txList
+ this._persistTxList(txList)
+ }
+
+ // Adds a tx to the txlist
+ addTx (txData, onTxDoneCb) {
+ var txList = this.getTxList()
+ var txLimit = this.txLimit
+ if (txList.length > txLimit - 1) {
+ txList.shift()
+ }
+ txList.push(txData)
+ this._saveTxList(txList)
+ this.addOnTxDoneCb(txData.id, onTxDoneCb)
+ this.emit('unapproved', txData)
+ this.emit('update')
+ }
+
+ getTx (txId, cb) {
+ var txList = this.getTxList()
+ var tx = txList.find((tx) => tx.id === txId)
+ return cb ? cb(tx) : tx
+ }
+
+ updateTx (txData) {
+ var txId = txData.id
+ var txList = this.getTxList()
+
+ var updatedTxList = txList.map((tx) => {
+ if (tx.id === txId) {
+ tx = txData
+ }
+ return tx
+ })
+ this._saveTxList(updatedTxList)
+ }
+
+ get unConftxCount () {
+ return Object.keys(this.getUnapprovedTxList()).length
+ }
+
+ get pendingTxCount () {
+ return this.getTxsByMetaData('status', 'signed').length
+ }
+
+ getUnapprovedTxList () {
+ var txList = this.getTxList()
+ return txList.filter((tx) => {
+ return tx.status === 'unapproved'
+ }).reduce((result, tx) => {
+ result[tx.id] = tx
+ return result
+ }, {})
+ }
+
+ getFilterdTxList (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((tx) => {
+ if (key in tx.txParams) {
+ return tx.txParams[key] === value
+ } else {
+ return tx[key] === value
+ }
+ })
+ }
+
+ addOnTxDoneCb (txId, cb) {
+ this._unconfTxCbs[txId] = cb || noop
+ }
+
+ // should return the tx
+
+ // 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!
+ // // - `'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 txData = this.getTx(txId)
+ txData.status = status
+ this.emit(status, txId)
+ this.updateTx(txData, status)
+ }
+
+
+ // should return the status of the tx.
+ getTxStatus (txId, cb) {
+ const txData = this.getTx(txId)
+ return cb ? cb(txData.staus) : txData.status
+ }
+
+
+ // should update the status of the tx to 'signed'.
+ setTxStatusSigned (txId) {
+ this.setTxStatus(txId, 'signed')
+ this.emit('update')
+ }
+
+ // should update the status of the tx to 'rejected'.
+ setTxStatusRejected (txId) {
+ this.setTxStatus(txId, 'rejected')
+ this.emit('update')
+ }
+
+ setTxStatusConfirmed (txId) {
+ this.setTxStatus(txId, 'confirmed')
+ // this.removeListener(`check${txId}`, this.checkForTxInBlock)
+ }
+
+ // merges txParams obj onto txData.txParams
+ // use extend to ensure that all fields are filled
+ updateTxParams (txId, txParams) {
+ var txData = this.getTx(txId)
+ txData.txParams = extend(txData, txParams)
+ this.updateTx(txData)
+ }
+
+ setProvider (provider) {
+ this.provider = provider
+ this.txProviderUtils = new TxProviderUtil(provider)
+ this.provider.on('block', this.checkForTxInBlock.bind(this))
+ }
+
+ checkForTxInBlock () {
+ var signedTxList = this.getFilterdTxList({status: 'signed'})
+ if (!signedTxList.length) return
+ var self = this
+ signedTxList.forEach((tx) => {
+ var txHash = tx.hash
+ var txId = tx.id
+ if (!txHash) return
+ // var d
+ this.txProviderUtils.query.getTransactionByHash(txHash, (err, txData) => {
+ if (err) {
+ tx
+
+ return console.error(err)
+ }
+ if (txData.blockNumber !== null) {
+ self.setTxStatusConfirmed(txId)
+ }
+ })
+ })
+ }
+}
+
+function noop () {}