web3-provider-engine
Version:
A JavaScript library for composing Ethereum provider objects using middleware modules
83 lines (79 loc) • 2.7 kB
JavaScript
;
var inherits = require('util').inherits;
var _require = require('@ethereumjs/tx'),
TransactionFactory = _require.TransactionFactory;
var ethUtil = require('@ethereumjs/util');
var Subprovider = require('./subprovider.js');
var 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() {
var self = this;
self.nonceCache = {};
}
NonceTrackerSubprovider.prototype.handleRequest = function (payload, next, end) {
var 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');
var 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;
}
};