1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-03 14:44:27 +01:00
metamask-extension/app/scripts/lib/pending-tx-tracker.js
Daijiro Wachi 43b1cb9100 Fix lint warnings
Fixed warnings:
```md
app/scripts/controllers/computed-balances.js
+ 35:27  warning  Missing space before function parentheses            space-before-function-paren
+ 41:14  warning  'address' is never reassigned. Use 'const' instead   prefer-const
+ 61:9   warning  'updater' is never reassigned. Use 'const' instead   prefer-const
+ 68:11  warning  'newState' is never reassigned. Use 'const' instead  prefer-const

app/scripts/controllers/network.js
+ 104:29  warning  Missing space before function parentheses  space-before-function-paren

app/scripts/lib/createLoggerMiddleware.js
+ 4:32  warning  Missing space before function parentheses      space-before-function-paren
+ 15:2   warning  Newline required at end of file but not found  eol-last

app/scripts/lib/createOriginMiddleware.js
+ 4:32  warning  Missing space before function parentheses      space-before-function-paren
+ 9:2   warning  Newline required at end of file but not found  eol-last

app/scripts/lib/createProviderMiddleware.js
+ 5:34  warning  Missing space before function parentheses      space-before-function-paren
+ 13:2   warning  Newline required at end of file but not found  eol-last

app/scripts/lib/events-proxy.js
+ 1:50  warning  Missing space before function parentheses      space-before-function-paren
+ 31:2   warning  Newline required at end of file but not found  eol-last

app/scripts/lib/nodeify.js
+ 2:22  warning  Missing space before function parentheses  space-before-function-paren
+ 2:24  warning  Missing space before opening brace         space-before-blocks
+ 5:18  warning  Missing space before function parentheses  space-before-function-paren
+ 5:20  warning  Missing space before opening brace         space-before-blocks

app/scripts/lib/pending-balance-calculator.js
+ 16:19  warning  Missing space before function parentheses  space-before-function-paren

app/scripts/lib/pending-tx-tracker.js
+ 85:11  warning  '||' should be placed at the end of the line  operator-linebreak
+ 87:11  warning  '||' should be placed at the end of the line  operator-linebreak
+ 88:11  warning  '||' should be placed at the end of the line  operator-linebreak
+ 90:11  warning  '||' should be placed at the end of the line  operator-linebreak
+ 91:11  warning  '||' should be placed at the end of the line  operator-linebreak

app/scripts/lib/port-stream.js
+ 3:22  warning  Missing space before function parentheses  space-before-function-paren
+ 3:24  warning  Missing space before opening brace         space-before-blocks

app/scripts/lib/tx-gas-utils.js
+ 84:2  warning  Newline required at end of file but not found  eol-last

app/scripts/lib/tx-state-history-helper.js
+ 12:37  warning  Missing space before function parentheses      space-before-function-paren
+ 23:30  warning  Missing space before function parentheses      space-before-function-paren
+ 30:23  warning  Missing space before function parentheses      space-before-function-paren
+ 35:28  warning  Missing space before function parentheses      space-before-function-paren
+ 41:2   warning  Newline required at end of file but not found  eol-last

app/scripts/lib/tx-state-manager.js
+ 94:13  warning  'value' is never reassigned. Use 'const' instead  prefer-const

ui/app/reducers.js
+ 45:7  warning  'state' is never reassigned. Use 'const' instead        prefer-const
+ 53:7  warning  'stateString' is never reassigned. Use 'const' instead  prefer-const

ui/lib/tx-helper.js
+ 27:2  warning  Newline required at end of file but not found  eol-last

ui/app/components/account-dropdowns.js
+ 163:1  warning  More than 2 blank lines not allowed  no-multiple-empty-lines

ui/app/components/menu-droppo.js
+ 22:7  warning  'style' is never reassigned. Use 'const' instead  prefer-const

ui/app/components/shapeshift-form.js
+ 135:11  warning  '&&' should be placed at the end of the line  operator-linebreak

ui/app/components/typed-message-renderer.js
+ 35:25  warning  Missing space before function parentheses      space-before-function-paren
+ 42:2   warning  Newline required at end of file but not found  eol-last

mascara/server/index.js
+ 11:42  warning  Use path.join() or path.resolve() instead of + to create paths  no-path-concat
+ 12:36  warning  Use path.join() or path.resolve() instead of + to create paths  no-path-concat
+ 13:33  warning  Use path.join() or path.resolve() instead of + to create paths  no-path-concat
+ 14:40  warning  Use path.join() or path.resolve() instead of + to create paths  no-path-concat
+ 20:29  warning  Use path.join() or path.resolve() instead of + to create paths  no-path-concat
+ 21:29  warning  Use path.join() or path.resolve() instead of + to create paths  no-path-concat
+ 26:40  warning  Use path.join() or path.resolve() instead of + to create paths  no-path-concat
```
2017-10-21 21:06:39 +02:00

184 lines
6.1 KiB
JavaScript

const EventEmitter = require('events')
const EthQuery = require('ethjs-query')
/*
Utility class for tracking the transactions as they
go from a pending state to a confirmed (mined in a block) state
As well as continues broadcast while in the pending state
~config is not optional~
requires a: {
provider: //,
nonceTracker: //see nonce tracker,
getPendingTransactions: //() a function for getting an array of transactions,
publishTransaction: //(rawTx) a async function for publishing raw transactions,
}
*/
module.exports = class PendingTransactionTracker extends EventEmitter {
constructor (config) {
super()
this.query = new EthQuery(config.provider)
this.nonceTracker = config.nonceTracker
// default is one day
this.retryTimePeriod = config.retryTimePeriod || 86400000
this.getPendingTransactions = config.getPendingTransactions
this.getCompletedTransactions = config.getCompletedTransactions
this.publishTransaction = config.publishTransaction
this._checkPendingTxs()
}
// checks if a signed tx is in a block and
// if included sets the tx status as 'confirmed'
checkForTxInBlock (block) {
const signedTxList = this.getPendingTransactions()
if (!signedTxList.length) return
signedTxList.forEach((txMeta) => {
const txHash = txMeta.hash
const txId = txMeta.id
if (!txHash) {
const noTxHashErr = new Error('We had an error while submitting this transaction, please try again.')
noTxHashErr.name = 'NoTxHashError'
this.emit('tx:failed', txId, noTxHashErr)
return
}
block.transactions.forEach((tx) => {
if (tx.hash === txHash) this.emit('tx:confirmed', txId)
})
})
}
queryPendingTxs ({ oldBlock, newBlock }) {
// check pending transactions on start
if (!oldBlock) {
this._checkPendingTxs()
return
}
// if we synced by more than one block, check for missed pending transactions
const diff = Number.parseInt(newBlock.number, 16) - Number.parseInt(oldBlock.number, 16)
if (diff > 1) this._checkPendingTxs()
}
resubmitPendingTxs () {
const pending = this.getPendingTransactions()
// only try resubmitting if their are transactions to resubmit
if (!pending.length) return
pending.forEach((txMeta) => this._resubmitTx(txMeta).catch((err) => {
/*
Dont marked as failed if the error is a "known" transaction warning
"there is already a transaction with the same sender-nonce
but higher/same gas price"
Also don't mark as failed if it has ever been broadcast successfully.
A successful broadcast means it may still be mined.
*/
const errorMessage = err.message.toLowerCase()
const isKnownTx = (
// geth
errorMessage.includes('replacement transaction underpriced') ||
errorMessage.includes('known transaction') ||
// parity
errorMessage.includes('gas price too low to replace') ||
errorMessage.includes('transaction with the same hash was already imported') ||
// other
errorMessage.includes('gateway timeout') ||
errorMessage.includes('nonce too low')
)
// ignore resubmit warnings, return early
if (isKnownTx) return
// encountered real error - transition to error state
txMeta.warning = {
error: errorMessage,
message: 'There was an error when resubmitting this transaction.',
}
this.emit('tx:warning', txMeta, err)
}))
}
async _resubmitTx (txMeta) {
if (Date.now() > txMeta.time + this.retryTimePeriod) {
const hours = (this.retryTimePeriod / 3.6e+6).toFixed(1)
const err = new Error(`Gave up submitting after ${hours} hours.`)
return this.emit('tx:failed', txMeta.id, err)
}
// Only auto-submit already-signed txs:
if (!('rawTx' in txMeta)) return
const rawTx = txMeta.rawTx
const txHash = await this.publishTransaction(rawTx)
// Increment successful tries:
this.emit('tx:retry', txMeta)
return txHash
}
async _checkPendingTx (txMeta) {
const txHash = txMeta.hash
const txId = txMeta.id
// extra check in case there was an uncaught error during the
// signature and submission process
if (!txHash) {
const noTxHashErr = new Error('We had an error while submitting this transaction, please try again.')
noTxHashErr.name = 'NoTxHashError'
this.emit('tx:failed', txId, noTxHashErr)
return
}
// If another tx with the same nonce is mined, set as failed.
const taken = await this._checkIfNonceIsTaken(txMeta)
if (taken) {
const nonceTakenErr = new Error('Another transaction with this nonce has been mined.')
nonceTakenErr.name = 'NonceTakenErr'
return this.emit('tx:failed', txId, nonceTakenErr)
}
// get latest transaction status
let txParams
try {
txParams = await this.query.getTransactionByHash(txHash)
if (!txParams) return
if (txParams.blockNumber) {
this.emit('tx:confirmed', txId)
}
} catch (err) {
txMeta.warning = {
error: err.message,
message: 'There was a problem loading this transaction.',
}
this.emit('tx:warning', txMeta, err)
}
}
// checks the network for signed txs and
// if confirmed sets the tx status as 'confirmed'
async _checkPendingTxs () {
const signedTxList = this.getPendingTransactions()
// in order to keep the nonceTracker accurate we block it while updating pending transactions
const nonceGlobalLock = await this.nonceTracker.getGlobalLock()
try {
await Promise.all(signedTxList.map((txMeta) => this._checkPendingTx(txMeta)))
} catch (err) {
console.error('PendingTransactionWatcher - Error updating pending transactions')
console.error(err)
}
nonceGlobalLock.releaseLock()
}
async _checkIfNonceIsTaken (txMeta) {
const completed = this.getCompletedTransactions()
const sameNonce = completed.filter((otherMeta) => {
return otherMeta.txParams.nonce === txMeta.txParams.nonce
})
return sameNonce.length > 0
}
}