1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-23 09:52:26 +01:00

Add txReceipt data to transaction details (#5513)

This commit is contained in:
Alexander Tseung 2018-10-16 06:00:47 +08:00 committed by GitHub
parent 61dec4ea46
commit c821a8354c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 126 additions and 6 deletions

View File

@ -424,6 +424,9 @@
"gasLimitTooLow": {
"message": "Gas limit must be at least 21000"
},
"gasUsed": {
"message": "Gas Used"
},
"generatingSeed": {
"message": "Generating Seed..."
},

View File

@ -366,7 +366,40 @@ class TransactionController extends EventEmitter {
this.txStateManager.setTxStatusSubmitted(txId)
}
confirmTransaction (txId) {
/**
* Sets the status of the transaction to confirmed and sets the status of nonce duplicates as
* dropped if the txParams have data it will fetch the txReceipt
* @param {number} txId - The tx's ID
* @returns {Promise<void>}
*/
async confirmTransaction (txId) {
// get the txReceipt before marking the transaction confirmed
// to ensure the receipt is gotten before the ui revives the tx
const txMeta = this.txStateManager.getTx(txId)
if (!txMeta) {
return
}
try {
const txReceipt = await this.query.getTransactionReceipt(txMeta.hash)
// It seems that sometimes the numerical values being returned from
// this.query.getTransactionReceipt are BN instances and not strings.
const gasUsed = typeof txReceipt.gasUsed !== 'string'
? txReceipt.gasUsed.toString(16)
: txReceipt.gasUsed
txMeta.txReceipt = {
...txReceipt,
gasUsed,
}
this.txStateManager.updateTx(txMeta, 'transactions#confirmTransaction - add txReceipt')
} catch (err) {
log.error(err)
}
this.txStateManager.setTxStatusConfirmed(txId)
this._markNonceDuplicatesDropped(txId)
}

View File

@ -400,6 +400,11 @@ class TransactionStateManager extends EventEmitter {
*/
_setTxStatus (txId, status) {
const txMeta = this.getTx(txId)
if (!txMeta) {
return
}
txMeta.status = status
setTimeout(() => {
try {

View File

@ -46,11 +46,15 @@ export function getActivities (transaction) {
if (!Array.isArray(base) && base.status === UNAPPROVED_STATUS && base.txParams) {
const { time, txParams: { value } = {} } = base
return acc.concat(eventCreator(TRANSACTION_CREATED_EVENT, time, value))
// An entry in the history may be an array of more sub-entries.
} else if (Array.isArray(base)) {
const events = []
base.forEach(entry => {
const { op, path, value, timestamp } = entry
const { op, path, value, timestamp: entryTimestamp } = entry
// Not all sub-entries in a history entry have a timestamp. If the sub-entry does not have a
// timestamp, the first sub-entry in a history entry should.
const timestamp = entryTimestamp || base[0] && base[0].timestamp
if (path in eventPathsHash && op === REPLACE_OP) {
switch (path) {

View File

@ -26,8 +26,11 @@ export default class TransactionBreakdown extends PureComponent {
render () {
const { t } = this.context
const { transaction, className } = this.props
const { txParams: { gas, gasPrice, value } = {} } = transaction
const hexGasTotal = getHexGasTotal({ gasLimit: gas, gasPrice })
const { txParams: { gas, gasPrice, value } = {}, txReceipt: { gasUsed } = {} } = transaction
const gasLimit = typeof gasUsed === 'string' ? gasUsed : gas
const hexGasTotal = getHexGasTotal({ gasLimit, gasPrice })
const totalInHex = sumHexes(hexGasTotal, value)
return (
@ -52,6 +55,19 @@ export default class TransactionBreakdown extends PureComponent {
value={gas}
/>
</TransactionBreakdownRow>
{
typeof gasUsed === 'string' && (
<TransactionBreakdownRow
title={`${t('gasUsed')} (${t('units')})`}
className="transaction-breakdown__row-title"
>
<HexToDecimal
className="transaction-breakdown__value"
value={gasUsed}
/>
</TransactionBreakdownRow>
)
}
<TransactionBreakdownRow title={t('gasPrice')}>
<CurrencyDisplay
className="transaction-breakdown__value"

View File

@ -11,6 +11,7 @@ import { CONFIRM_TRANSACTION_ROUTE } from '../../routes'
import { UNAPPROVED_STATUS, TOKEN_METHOD_TRANSFER } from '../../constants/transactions'
import { ETH } from '../../constants/common'
import { ENVIRONMENT_TYPE_FULLSCREEN } from '../../../../app/scripts/lib/enums'
import { getStatusKey } from '../../helpers/transactions.util'
export default class TransactionListItem extends PureComponent {
static propTypes = {
@ -167,7 +168,7 @@ export default class TransactionListItem extends PureComponent {
</div>
<TransactionStatus
className="transaction-list-item__status"
statusKey={transaction.status}
statusKey={getStatusKey(transaction)}
title={(
(transaction.err && transaction.err.rpc)
? transaction.err.rpc.message

View File

@ -25,4 +25,9 @@
background-color: #FFF2DB;
color: #CA810A;
}
&--failed {
background: lighten($monzo, 56%);
color: $monzo;
}
}

View File

@ -19,4 +19,39 @@ describe('Transactions utils', () => {
assert.doesNotThrow(() => utils.getTokenData())
})
})
describe('getStatusKey', () => {
it('should return the correct status', () => {
const tests = [
{
transaction: {
status: 'confirmed',
txReceipt: {
status: '0x0',
},
},
expected: 'failed',
},
{
transaction: {
status: 'confirmed',
txReceipt: {
status: '0x1',
},
},
expected: 'confirmed',
},
{
transaction: {
status: 'pending',
},
expected: 'pending',
},
]
tests.forEach(({ transaction, expected }) => {
assert.equal(utils.getStatusKey(transaction), expected)
})
})
})
})

View File

@ -126,3 +126,21 @@ export function sumHexes (...args) {
return ethUtil.addHexPrefix(total)
}
/**
* Returns a status key for a transaction. Requires parsing the txMeta.txReceipt on top of
* txMeta.status because txMeta.status does not reflect on-chain errors.
* @param {Object} transaction - The txMeta object of a transaction.
* @param {Object} transaction.txReceipt - The transaction receipt.
* @returns {string}
*/
export function getStatusKey (transaction) {
const { txReceipt: { status } = {} } = transaction
// There was an on-chain failure
if (status === '0x0') {
return 'failed'
}
return transaction.status
}