This repository has been archived by the owner on Apr 22, 2024. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 328
/
Copy pathnonce-tracker.js
89 lines (77 loc) · 2.55 KB
/
nonce-tracker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
const inherits = require('util').inherits
const { TransactionFactory } = require('@ethereumjs/tx')
const ethUtil = require('@ethereumjs/util')
const Subprovider = require('./subprovider.js')
const blockTagForPayload = require('../util/rpc-cache-utils').blockTagForPayload
module.exports = NonceTrackerSubprovider
// handles the following RPC methods:
// eth_getTransactionCount (pending only)
//
// observes the following RPC methods:
// eth_sendRawTransaction
// evm_revert (to clear the nonce cache)
inherits(NonceTrackerSubprovider, Subprovider)
function NonceTrackerSubprovider(){
const self = this
self.nonceCache = {}
}
NonceTrackerSubprovider.prototype.handleRequest = function(payload, next, end){
const self = this
switch(payload.method) {
case 'eth_getTransactionCount':
var blockTag = blockTagForPayload(payload)
var address = payload.params[0].toLowerCase()
var cachedResult = self.nonceCache[address]
// only handle requests against the 'pending' blockTag
if (blockTag === 'pending') {
// has a result
if (cachedResult) {
end(null, cachedResult)
// fallthrough then populate cache
} else {
next(function(err, result, cb){
if (err) return cb()
if (self.nonceCache[address] === undefined) {
self.nonceCache[address] = result
}
cb()
})
}
} else {
next()
}
return
case 'eth_sendRawTransaction':
// allow the request to continue normally
next(function(err, result, cb){
// only update local nonce if tx was submitted correctly
if (err) return cb()
// parse raw tx
var rawTx = payload.params[0]
var rawData = Buffer.from(ethUtil.stripHexPrefix(rawTx), 'hex')
const tx = TransactionFactory.fromSerializedData(rawData)
// extract address
var address = tx.getSenderAddress().toString('hex').toLowerCase()
// extract nonce and increment
var nonce = ethUtil.bufferToInt(tx.nonce)
nonce++
// hexify and normalize
var hexNonce = nonce.toString(16)
if (hexNonce.length%2) hexNonce = '0'+hexNonce
hexNonce = '0x'+hexNonce
// dont update our record on the nonce until the submit was successful
// update cache
self.nonceCache[address] = hexNonce
cb()
})
return
// Clear cache on a testrpc revert
case 'evm_revert':
self.nonceCache = {}
next()
return
default:
next()
return
}
}