diff options
author | Frances Pangilinan <frankie.diamond@gmail.com> | 2016-12-15 04:55:41 +0800 |
---|---|---|
committer | Frances Pangilinan <frankie.diamond@gmail.com> | 2016-12-15 04:55:41 +0800 |
commit | 090935f90aa3c2589fee7bc038c8f4fcf77da03c (patch) | |
tree | 82a21bd7d0df26d6de637892cbd9322d52b7785b /app/scripts/lib | |
parent | 9e3fa3cfba20299413df87d18158180c7798d2ac (diff) | |
download | tangerine-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
Diffstat (limited to 'app/scripts/lib')
-rw-r--r-- | app/scripts/lib/config-manager.js | 51 | ||||
-rw-r--r-- | app/scripts/lib/idStore.js | 13 | ||||
-rw-r--r-- | app/scripts/lib/provider-utils.js | 106 |
3 files changed, 118 insertions, 52 deletions
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)) + } +} |