Adds a transactionCategory to txMeta for use in UI (#6567)

* Adds a transactionCategory to txMeta for use in UI

* Update transaction controller and tx-gas-util documentation on new code param in multiple functions.
feature/default_network_editable
Dan J Miller 6 years ago committed by GitHub
parent 56ed189aeb
commit ef8a07c2ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 55
      app/scripts/controllers/transactions/index.js
  2. 11
      app/scripts/controllers/transactions/tx-gas-utils.js

@ -3,6 +3,17 @@ const ObservableStore = require('obs-store')
const ethUtil = require('ethereumjs-util') const ethUtil = require('ethereumjs-util')
const Transaction = require('ethereumjs-tx') const Transaction = require('ethereumjs-tx')
const EthQuery = require('ethjs-query') const EthQuery = require('ethjs-query')
const abi = require('human-standard-token-abi')
const abiDecoder = require('abi-decoder')
abiDecoder.addABI(abi)
const {
TOKEN_METHOD_APPROVE,
TOKEN_METHOD_TRANSFER,
TOKEN_METHOD_TRANSFER_FROM,
SEND_ETHER_ACTION_KEY,
DEPLOY_CONTRACT_ACTION_KEY,
CONTRACT_INTERACTION_KEY,
} = require('../../../../ui/app/helpers/constants/transactions.js')
const TransactionStateManager = require('./tx-state-manager') const TransactionStateManager = require('./tx-state-manager')
const TxGasUtil = require('./tx-gas-utils') const TxGasUtil = require('./tx-gas-utils')
const PendingTransactionTracker = require('./pending-tx-tracker') const PendingTransactionTracker = require('./pending-tx-tracker')
@ -180,9 +191,11 @@ class TransactionController extends EventEmitter {
} }
txUtils.validateTxParams(normalizedTxParams) txUtils.validateTxParams(normalizedTxParams)
// construct txMeta // construct txMeta
const { transactionCategory, code } = await this._determineTransactionCategory(txParams)
let txMeta = this.txStateManager.generateTxMeta({ let txMeta = this.txStateManager.generateTxMeta({
txParams: normalizedTxParams, txParams: normalizedTxParams,
type: TRANSACTION_TYPE_STANDARD, type: TRANSACTION_TYPE_STANDARD,
transactionCategory,
}) })
this.addTx(txMeta) this.addTx(txMeta)
this.emit('newUnapprovedTx', txMeta) this.emit('newUnapprovedTx', txMeta)
@ -191,7 +204,7 @@ class TransactionController extends EventEmitter {
// check whether recipient account is blacklisted // check whether recipient account is blacklisted
recipientBlacklistChecker.checkAccount(txMeta.metamaskNetworkId, normalizedTxParams.to) recipientBlacklistChecker.checkAccount(txMeta.metamaskNetworkId, normalizedTxParams.to)
// add default tx params // add default tx params
txMeta = await this.addTxGasDefaults(txMeta) txMeta = await this.addTxGasDefaults(txMeta, code)
} catch (error) { } catch (error) {
log.warn(error) log.warn(error)
txMeta.loadingDefaults = false txMeta.loadingDefaults = false
@ -211,7 +224,7 @@ class TransactionController extends EventEmitter {
@param txMeta {Object} - the txMeta object @param txMeta {Object} - the txMeta object
@returns {Promise<object>} resolves with txMeta @returns {Promise<object>} resolves with txMeta
*/ */
async addTxGasDefaults (txMeta) { async addTxGasDefaults (txMeta, code) {
const txParams = txMeta.txParams const txParams = txMeta.txParams
// ensure value // ensure value
txParams.value = txParams.value ? ethUtil.addHexPrefix(txParams.value) : '0x0' txParams.value = txParams.value ? ethUtil.addHexPrefix(txParams.value) : '0x0'
@ -222,7 +235,7 @@ class TransactionController extends EventEmitter {
} }
txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16)) txParams.gasPrice = ethUtil.addHexPrefix(gasPrice.toString(16))
// set gasLimit // set gasLimit
return await this.txGasUtil.analyzeGasUsage(txMeta) return await this.txGasUtil.analyzeGasUsage(txMeta, code)
} }
/** /**
@ -555,6 +568,42 @@ class TransactionController extends EventEmitter {
}) })
} }
/**
Returns a "type" for a transaction out of the following list: simpleSend, tokenTransfer, tokenApprove,
contractDeployment, contractMethodCall
*/
async _determineTransactionCategory (txParams) {
const { data, to } = txParams
const { name } = data && abiDecoder.decodeMethod(data) || {}
const tokenMethodName = [
TOKEN_METHOD_APPROVE,
TOKEN_METHOD_TRANSFER,
TOKEN_METHOD_TRANSFER_FROM,
].find(tokenMethodName => tokenMethodName === name && name.toLowerCase())
let result
let code
if (!txParams.data) {
result = SEND_ETHER_ACTION_KEY
} else if (tokenMethodName) {
result = tokenMethodName
} else if (!to) {
result = DEPLOY_CONTRACT_ACTION_KEY
} else {
try {
code = await this.query.getCode(to)
} catch (e) {
log.warn(e)
}
// For an address with no code, geth will return '0x', and ganache-core v2.2.1 will return '0x0'
const codeIsEmpty = !code || code === '0x' || code === '0x0'
result = codeIsEmpty ? SEND_ETHER_ACTION_KEY : CONTRACT_INTERACTION_KEY
}
return { transactionCategory: result, code }
}
/** /**
Sets other txMeta statuses to dropped if the txMeta that has been confirmed has other transactions Sets other txMeta statuses to dropped if the txMeta that has been confirmed has other transactions
in the list have the same nonce in the list have the same nonce

@ -4,6 +4,7 @@ const {
BnMultiplyByFraction, BnMultiplyByFraction,
bnToHex, bnToHex,
} = require('../../lib/util') } = require('../../lib/util')
const log = require('loglevel')
const { addHexPrefix } = require('ethereumjs-util') const { addHexPrefix } = require('ethereumjs-util')
const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send. const SIMPLE_GAS_COST = '0x5208' // Hex for 21000, cost of a simple send.
@ -24,14 +25,16 @@ class TxGasUtil {
/** /**
@param txMeta {Object} - the txMeta object @param txMeta {Object} - the txMeta object
@param code {string} - the code at the txs address, as returned by this.query.getCode(to)
@returns {object} the txMeta object with the gas written to the txParams @returns {object} the txMeta object with the gas written to the txParams
*/ */
async analyzeGasUsage (txMeta) { async analyzeGasUsage (txMeta, code) {
const block = await this.query.getBlockByNumber('latest', false) const block = await this.query.getBlockByNumber('latest', false)
let estimatedGasHex let estimatedGasHex
try { try {
estimatedGasHex = await this.estimateTxGas(txMeta, block.gasLimit) estimatedGasHex = await this.estimateTxGas(txMeta, block.gasLimit, code)
} catch (err) { } catch (err) {
log.warn(err)
txMeta.simulationFails = { txMeta.simulationFails = {
reason: err.message, reason: err.message,
errorKey: err.errorKey, errorKey: err.errorKey,
@ -52,9 +55,10 @@ class TxGasUtil {
Estimates the tx's gas usage Estimates the tx's gas usage
@param txMeta {Object} - the txMeta object @param txMeta {Object} - the txMeta object
@param blockGasLimitHex {string} - hex string of the block's gas limit @param blockGasLimitHex {string} - hex string of the block's gas limit
@param code {string} - the code at the txs address, as returned by this.query.getCode(to)
@returns {string} the estimated gas limit as a hex string @returns {string} the estimated gas limit as a hex string
*/ */
async estimateTxGas (txMeta, blockGasLimitHex) { async estimateTxGas (txMeta, blockGasLimitHex, code) {
const txParams = txMeta.txParams const txParams = txMeta.txParams
// check if gasLimit is already specified // check if gasLimit is already specified
@ -70,7 +74,6 @@ class TxGasUtil {
// see if we can set the gas based on the recipient // see if we can set the gas based on the recipient
if (hasRecipient) { if (hasRecipient) {
const code = await this.query.getCode(recipient)
// For an address with no code, geth will return '0x', and ganache-core v2.2.1 will return '0x0' // For an address with no code, geth will return '0x', and ganache-core v2.2.1 will return '0x0'
const codeIsEmpty = !code || code === '0x' || code === '0x0' const codeIsEmpty = !code || code === '0x' || code === '0x0'

Loading…
Cancel
Save