@machinomy/hdwallet-provider
Version:
HD Wallet-enabled Web3 provider
110 lines • 4.69 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.NonceSubprovider = void 0;
const subprovider_1 = require("./subprovider");
const util_1 = require("./util");
const ethUtil = __importStar(require("ethereumjs-util"));
const transaction_util_1 = require("./util/transaction.util");
class NonceSubprovider extends subprovider_1.SubProvider {
constructor() {
super(...arguments);
this.nonceCache = new Map();
}
updateNonce(address, nonce, cb) {
const cached = this.nonceCache.get(address);
const isNewerNonce = typeof cached === "number" && nonce > cached;
if (!cached || isNewerNonce) {
this.nonceCache.set(address, nonce);
}
cb();
}
handleRequest(payload, next, end) {
switch (payload.method) {
case "eth_getTransactionCount":
const blockTag = util_1.blockTagForPayload(payload);
const address = payload.params[0].toLowerCase();
const cachedResult = this.nonceCache.get(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((err, result, cb) => {
if (err)
return cb();
this.updateNonce(address, ethUtil.bufferToInt(result), () => {
cb();
});
});
}
}
else {
next();
}
return;
case "eth_sendRawTransaction":
if (!this.engine)
throw new Error("Should have set engine");
this.engine.sendAsync(util_1.createPayload({ method: "net_version" }), (err, result) => {
if (err) {
end(err);
}
else {
const networkId = Number(result.result);
// allow the request to continue normally
next((err, result, cb) => {
// only update local nonce if tx was submitted correctly
if (err)
return cb();
// parse raw tx
const rawTx = ethUtil.toBuffer(payload.params[0]);
const tx = transaction_util_1.buildTransaction(rawTx, networkId);
// extract address
const address = ethUtil.bufferToHex(tx.getSenderAddress());
// extract nonce and increment
let nonce = ethUtil.bufferToInt(tx.nonce);
nonce++;
// dont update our record on the nonce until the submit was successful
// update cache
this.updateNonce(address, nonce, () => {
cb();
});
});
}
});
return;
// Clear cache on a testrpc revert
case "evm_revert":
this.nonceCache = new Map();
next();
return;
default:
next();
return;
}
}
}
exports.NonceSubprovider = NonceSubprovider;
//# sourceMappingURL=nonce.subprovider.js.map