web3-provider-engine
Version:
A JavaScript library for composing Ethereum provider objects using middleware modules
1,278 lines (1,253 loc) • 2.56 MB
JavaScript
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ZeroClientProvider = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
"use strict";
var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;
var ethUtil = require('@ethereumjs/util');
var _require = require('eth-block-tracker'),
PollingBlockTracker = _require.PollingBlockTracker;
var map = require('async/map');
var eachSeries = require('async/eachSeries');
var Stoplight = require('./util/stoplight.js');
var cacheUtils = require('./util/rpc-cache-utils.js');
var createPayload = require('./util/create-payload.js');
var noop = function noop() {};
module.exports = Web3ProviderEngine;
inherits(Web3ProviderEngine, EventEmitter);
function Web3ProviderEngine(opts) {
var self = this;
EventEmitter.call(self);
self.setMaxListeners(30);
// parse options
opts = opts || {};
// block polling
var directProvider = {
sendAsync: self._handleAsync.bind(self)
};
var blockTrackerProvider = opts.blockTrackerProvider || directProvider;
self._blockTracker = opts.blockTracker || new PollingBlockTracker({
provider: blockTrackerProvider,
pollingInterval: opts.pollingInterval || 4000,
setSkipCacheFlag: true
});
// set initialization blocker
self._ready = new Stoplight();
// local state
self.currentBlock = null;
self._providers = [];
}
// public
Web3ProviderEngine.prototype.start = function () {
var _this = this;
var cb = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : noop;
var self = this;
// trigger start
self._ready.go();
// on new block, request block body and emit as events
self._blockTracker.on('latest', function (blockNumber) {
// get block body
self._getBlockByNumberWithRetry(blockNumber, function (err, block) {
if (err) {
_this.emit('error', err);
return;
}
if (!block) {
console.log(block);
_this.emit('error', new Error("Could not find block"));
return;
}
var bufferBlock = toBufferBlock(block);
// set current + emit "block" event
self._setCurrentBlock(bufferBlock);
// emit other events
self.emit('rawBlock', block);
self.emit('latest', block);
});
});
// forward other events
self._blockTracker.on('sync', self.emit.bind(self, 'sync'));
self._blockTracker.on('error', self.emit.bind(self, 'error'));
// update state
self._running = true;
// signal that we started
self.emit('start');
};
Web3ProviderEngine.prototype.stop = function () {
var self = this;
// stop block polling by removing event listeners
self._blockTracker.removeAllListeners();
// update state
self._running = false;
// signal that we stopped
self.emit('stop');
};
Web3ProviderEngine.prototype.isRunning = function () {
var self = this;
return self._running;
};
Web3ProviderEngine.prototype.addProvider = function (source, index) {
var self = this;
if (typeof index === 'number') {
self._providers.splice(index, 0, source);
} else {
self._providers.push(source);
}
source.setEngine(this);
};
Web3ProviderEngine.prototype.removeProvider = function (source) {
var self = this;
var index = self._providers.indexOf(source);
if (index < 0) throw new Error('Provider not found.');
self._providers.splice(index, 1);
};
Web3ProviderEngine.prototype.send = function (payload) {
throw new Error('Web3ProviderEngine does not support synchronous requests.');
};
Web3ProviderEngine.prototype.sendAsync = function (payload, cb) {
var self = this;
self._ready["await"](function () {
if (Array.isArray(payload)) {
// handle batch
map(payload, self._handleAsync.bind(self), cb);
} else {
// handle single
self._handleAsync(payload, cb);
}
});
};
// private
Web3ProviderEngine.prototype._getBlockByNumberWithRetry = function (blockNumber, cb) {
var self = this;
var retriesRemaining = 5;
attemptRequest();
return;
function attemptRequest() {
self._getBlockByNumber(blockNumber, afterRequest);
}
function afterRequest(err, block) {
// anomalous error occurred
if (err) return cb(err);
// block not ready yet
if (!block) {
if (retriesRemaining > 0) {
// wait 1s then try again
retriesRemaining--;
setTimeout(function () {
attemptRequest();
}, 1000);
return;
} else {
// give up, return a null block
cb(null, null);
return;
}
}
// otherwise return result
cb(null, block);
return;
}
};
Web3ProviderEngine.prototype._getBlockByNumber = function (blockNumber, cb) {
var req = createPayload({
method: 'eth_getBlockByNumber',
params: [blockNumber, false],
skipCache: true
});
this._handleAsync(req, function (err, res) {
if (err) return cb(err);
return cb(null, res.result);
});
};
Web3ProviderEngine.prototype._handleAsync = function (payload, finished) {
var self = this;
var currentProvider = -1;
var result = null;
var error = null;
var stack = [];
next();
function next(after) {
currentProvider += 1;
stack.unshift(after);
// Bubbled down as far as we could go, and the request wasn't
// handled. Return an error.
if (currentProvider >= self._providers.length) {
end(new Error('Request for method "' + payload.method + '" not handled by any subprovider. Please check your subprovider configuration to ensure this method is handled.'));
} else {
try {
var provider = self._providers[currentProvider];
provider.handleRequest(payload, next, end);
} catch (e) {
end(e);
}
}
}
function end(_error, _result) {
error = _error;
result = _result;
eachSeries(stack, function (fn, callback) {
if (fn) {
fn(error, result, callback);
} else {
callback();
}
}, function () {
var resultObj = {
id: payload.id,
jsonrpc: payload.jsonrpc,
result: result
};
if (error != null) {
resultObj.error = {
message: error.stack || error.message || error,
code: -32000
};
// respond with both error formats
finished(error, resultObj);
} else {
finished(null, resultObj);
}
});
}
};
//
// from remote-data
//
Web3ProviderEngine.prototype._setCurrentBlock = function (block) {
var self = this;
self.currentBlock = block;
self.emit('block', block);
};
// util
function toBufferBlock(jsonBlock) {
return {
number: ethUtil.toBuffer(jsonBlock.number),
hash: ethUtil.toBuffer(jsonBlock.hash),
parentHash: ethUtil.toBuffer(jsonBlock.parentHash),
nonce: ethUtil.toBuffer(jsonBlock.nonce),
mixHash: ethUtil.toBuffer(jsonBlock.mixHash),
sha3Uncles: ethUtil.toBuffer(jsonBlock.sha3Uncles),
logsBloom: ethUtil.toBuffer(jsonBlock.logsBloom),
transactionsRoot: ethUtil.toBuffer(jsonBlock.transactionsRoot),
stateRoot: ethUtil.toBuffer(jsonBlock.stateRoot),
receiptsRoot: ethUtil.toBuffer(jsonBlock.receiptRoot || jsonBlock.receiptsRoot),
miner: ethUtil.toBuffer(jsonBlock.miner),
difficulty: ethUtil.toBuffer(jsonBlock.difficulty),
totalDifficulty: ethUtil.toBuffer(jsonBlock.totalDifficulty),
size: ethUtil.toBuffer(jsonBlock.size),
extraData: ethUtil.toBuffer(jsonBlock.extraData),
gasLimit: ethUtil.toBuffer(jsonBlock.gasLimit),
gasUsed: ethUtil.toBuffer(jsonBlock.gasUsed),
timestamp: ethUtil.toBuffer(jsonBlock.timestamp),
transactions: jsonBlock.transactions
};
}
},{"./util/create-payload.js":450,"./util/rpc-cache-utils.js":453,"./util/stoplight.js":454,"@ethereumjs/util":74,"async/eachSeries":256,"async/map":272,"eth-block-tracker":306,"events":311,"util":431}],2:[function(require,module,exports){
module.exports={
"name": "goerli",
"chainId": 5,
"networkId": 5,
"defaultHardfork": "merge",
"consensus": {
"type": "poa",
"algorithm": "clique",
"clique": {
"period": 15,
"epoch": 30000
}
},
"comment": "Cross-client PoA test network",
"url": "https://github.com/goerli/testnet",
"genesis": {
"timestamp": "0x5c51a607",
"gasLimit": 10485760,
"difficulty": 1,
"nonce": "0x0000000000000000",
"extraData": "0x22466c6578692069732061207468696e6722202d204166726900000000000000e0a2bd4258d2768837baa26a28fe71dc079f84c70000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"hardforks": [
{
"name": "chainstart",
"block": 0,
"forkHash": "0xa3f5ab08"
},
{
"name": "homestead",
"block": 0,
"forkHash": "0xa3f5ab08"
},
{
"name": "tangerineWhistle",
"block": 0,
"forkHash": "0xa3f5ab08"
},
{
"name": "spuriousDragon",
"block": 0,
"forkHash": "0xa3f5ab08"
},
{
"name": "byzantium",
"block": 0,
"forkHash": "0xa3f5ab08"
},
{
"name": "constantinople",
"block": 0,
"forkHash": "0xa3f5ab08"
},
{
"name": "petersburg",
"block": 0,
"forkHash": "0xa3f5ab08"
},
{
"name": "istanbul",
"block": 1561651,
"forkHash": "0xc25efa5c"
},
{
"name": "berlin",
"block": 4460644,
"forkHash": "0x757a1c47"
},
{
"name": "london",
"block": 5062605,
"forkHash": "0xb8c6299d"
},
{
"//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://goerli.etherscan.io/block/7382818",
"name": "merge",
"ttd": "10790000",
"block": 7382819,
"forkHash": "0xb8c6299d"
},
{
"name": "mergeForkIdTransition",
"block": null,
"forkHash": null
},
{
"name": "shanghai",
"block": null,
"timestamp": "1678832736",
"forkHash": "0xf9843abf"
}
],
"bootstrapNodes": [
{
"ip": "51.141.78.53",
"port": 30303,
"id": "011f758e6552d105183b1761c5e2dea0111bc20fd5f6422bc7f91e0fabbec9a6595caf6239b37feb773dddd3f87240d99d859431891e4a642cf2a0a9e6cbb98a",
"location": "",
"comment": "Upstream bootnode 1"
},
{
"ip": "13.93.54.137",
"port": 30303,
"id": "176b9417f511d05b6b2cf3e34b756cf0a7096b3094572a8f6ef4cdcb9d1f9d00683bf0f83347eebdf3b81c3521c2332086d9592802230bf528eaf606a1d9677b",
"location": "",
"comment": "Upstream bootnode 2"
},
{
"ip": "94.237.54.114",
"port": 30313,
"id": "46add44b9f13965f7b9875ac6b85f016f341012d84f975377573800a863526f4da19ae2c620ec73d11591fa9510e992ecc03ad0751f53cc02f7c7ed6d55c7291",
"location": "",
"comment": "Upstream bootnode 3"
},
{
"ip": "18.218.250.66",
"port": 30313,
"id": "b5948a2d3e9d486c4d75bf32713221c2bd6cf86463302339299bd227dc2e276cd5a1c7ca4f43a0e9122fe9af884efed563bd2a1fd28661f3b5f5ad7bf1de5949",
"location": "",
"comment": "Upstream bootnode 4"
},
{
"ip": "3.11.147.67",
"port": 30303,
"id": "a61215641fb8714a373c80edbfa0ea8878243193f57c96eeb44d0bc019ef295abd4e044fd619bfc4c59731a73fb79afe84e9ab6da0c743ceb479cbb6d263fa91",
"location": "",
"comment": "Ethereum Foundation bootnode"
},
{
"ip": "51.15.116.226",
"port": 30303,
"id": "a869b02cec167211fb4815a82941db2e7ed2936fd90e78619c53eb17753fcf0207463e3419c264e2a1dd8786de0df7e68cf99571ab8aeb7c4e51367ef186b1dd",
"location": "",
"comment": "Goerli Initiative bootnode"
},
{
"ip": "51.15.119.157",
"port": 30303,
"id": "807b37ee4816ecf407e9112224494b74dd5933625f655962d892f2f0f02d7fbbb3e2a94cf87a96609526f30c998fd71e93e2f53015c558ffc8b03eceaf30ee33",
"location": "",
"comment": "Goerli Initiative bootnode"
},
{
"ip": "51.15.119.157",
"port": 40303,
"id": "a59e33ccd2b3e52d578f1fbd70c6f9babda2650f0760d6ff3b37742fdcdfdb3defba5d56d315b40c46b70198c7621e63ffa3f987389c7118634b0fefbbdfa7fd",
"location": "",
"comment": "Goerli Initiative bootnode"
}
],
"dnsNetworks": [
"enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.goerli.ethdisco.net"
]
}
},{}],3:[function(require,module,exports){
module.exports={
"name": "mainnet",
"chainId": 1,
"networkId": 1,
"defaultHardfork": "merge",
"consensus": {
"type": "pow",
"algorithm": "ethash",
"ethash": {}
},
"comment": "The Ethereum main chain",
"url": "https://ethstats.net/",
"genesis": {
"gasLimit": 5000,
"difficulty": 17179869184,
"nonce": "0x0000000000000042",
"extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa"
},
"hardforks": [
{
"name": "chainstart",
"block": 0,
"forkHash": "0xfc64ec04"
},
{
"name": "homestead",
"block": 1150000,
"forkHash": "0x97c2c34c"
},
{
"name": "dao",
"block": 1920000,
"forkHash": "0x91d1f948"
},
{
"name": "tangerineWhistle",
"block": 2463000,
"forkHash": "0x7a64da13"
},
{
"name": "spuriousDragon",
"block": 2675000,
"forkHash": "0x3edd5b10"
},
{
"name": "byzantium",
"block": 4370000,
"forkHash": "0xa00bc324"
},
{
"name": "constantinople",
"block": 7280000,
"forkHash": "0x668db0af"
},
{
"name": "petersburg",
"block": 7280000,
"forkHash": "0x668db0af"
},
{
"name": "istanbul",
"block": 9069000,
"forkHash": "0x879d6e30"
},
{
"name": "muirGlacier",
"block": 9200000,
"forkHash": "0xe029e991"
},
{
"name": "berlin",
"block": 12244000,
"forkHash": "0x0eb440f6"
},
{
"name": "london",
"block": 12965000,
"forkHash": "0xb715077d"
},
{
"name": "arrowGlacier",
"block": 13773000,
"forkHash": "0x20c327fc"
},
{
"name": "grayGlacier",
"block": 15050000,
"forkHash": "0xf0afd0e3"
},
{
"//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://etherscan.io/block/15537393",
"name": "merge",
"ttd": "58750000000000000000000",
"block": 15537394,
"forkHash": "0xf0afd0e3"
},
{
"name": "mergeForkIdTransition",
"block": null,
"forkHash": null
},
{
"name": "shanghai",
"block": null,
"timestamp": "1681338455",
"forkHash": "0xdce96c2d"
}
],
"bootstrapNodes": [
{
"ip": "18.138.108.67",
"port": 30303,
"id": "d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666",
"location": "ap-southeast-1-001",
"comment": "bootnode-aws-ap-southeast-1-001"
},
{
"ip": "3.209.45.79",
"port": 30303,
"id": "22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de",
"location": "us-east-1-001",
"comment": "bootnode-aws-us-east-1-001"
},
{
"ip": "65.108.70.101",
"port": 30303,
"id": "2b252ab6a1d0f971d9722cb839a42cb81db019ba44c08754628ab4a823487071b5695317c8ccd085219c3a03af063495b2f1da8d18218da2d6a82981b45e6ffc",
"location": "eu-west-1-001",
"comment": "bootnode-hetzner-hel"
},
{
"ip": "157.90.35.166",
"port": 30303,
"id": "4aeb4ab6c14b23e2c4cfdce879c04b0748a20d8e9b59e25ded2a08143e265c6c25936e74cbc8e641e3312ca288673d91f2f93f8e277de3cfa444ecdaaf982052",
"location": "eu-central-1-001",
"comment": "bootnode-hetzner-fsn"
}
],
"dnsNetworks": [
"enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.mainnet.ethdisco.net"
]
}
},{}],4:[function(require,module,exports){
module.exports={
"name": "rinkeby",
"chainId": 4,
"networkId": 4,
"defaultHardfork": "london",
"consensus": {
"type": "poa",
"algorithm": "clique",
"clique": {
"period": 15,
"epoch": 30000
}
},
"comment": "PoA test network",
"url": "https://www.rinkeby.io",
"genesis": {
"timestamp": "0x58ee40ba",
"gasLimit": 4700000,
"difficulty": 1,
"nonce": "0x0000000000000000",
"extraData": "0x52657370656374206d7920617574686f7269746168207e452e436172746d616e42eb768f2244c8811c63729a21a3569731535f067ffc57839b00206d1ad20c69a1981b489f772031b279182d99e65703f0076e4812653aab85fca0f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"
},
"hardforks": [
{
"name": "chainstart",
"block": 0,
"forkHash": "0x3b8e0691"
},
{
"name": "homestead",
"block": 1,
"forkHash": "0x60949295"
},
{
"name": "tangerineWhistle",
"block": 2,
"forkHash": "0x8bde40dd"
},
{
"name": "spuriousDragon",
"block": 3,
"forkHash": "0xcb3a64bb"
},
{
"name": "byzantium",
"block": 1035301,
"forkHash": "0x8d748b57"
},
{
"name": "constantinople",
"block": 3660663,
"forkHash": "0xe49cab14"
},
{
"name": "petersburg",
"block": 4321234,
"forkHash": "0xafec6b27"
},
{
"name": "istanbul",
"block": 5435345,
"forkHash": "0xcbdb8838"
},
{
"name": "berlin",
"block": 8290928,
"forkHash": "0x6910c8bd"
},
{
"name": "london",
"block": 8897988,
"forkHash": "0x8e29f2f3"
},
{
"name": "merge",
"block": null,
"forkHash": null
},
{
"name": "shanghai",
"block": null,
"forkHash": null
}
],
"bootstrapNodes": [
{
"ip": "52.169.42.101",
"port": 30303,
"id": "a24ac7c5484ef4ed0c5eb2d36620ba4e4aa13b8c84684e1b4aab0cebea2ae45cb4d375b77eab56516d34bfbd3c1a833fc51296ff084b770b94fb9028c4d25ccf",
"location": "",
"comment": "IE"
},
{
"ip": "52.3.158.184",
"port": 30303,
"id": "343149e4feefa15d882d9fe4ac7d88f885bd05ebb735e547f12e12080a9fa07c8014ca6fd7f373123488102fe5e34111f8509cf0b7de3f5b44339c9f25e87cb8",
"location": "",
"comment": "INFURA"
},
{
"ip": "159.89.28.211",
"port": 30303,
"id": "b6b28890b006743680c52e64e0d16db57f28124885595fa03a562be1d2bf0f3a1da297d56b13da25fb992888fd556d4c1a27b1f39d531bde7de1921c90061cc6",
"location": "",
"comment": "AKASHA"
}
],
"dnsNetworks": [
"enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.rinkeby.ethdisco.net"
]
}
},{}],5:[function(require,module,exports){
module.exports={
"name": "ropsten",
"chainId": 3,
"networkId": 3,
"defaultHardfork": "merge",
"consensus": {
"type": "pow",
"algorithm": "ethash",
"ethash": {}
},
"comment": "PoW test network",
"url": "https://github.com/ethereum/ropsten",
"genesis": {
"gasLimit": 16777216,
"difficulty": 1048576,
"nonce": "0x0000000000000042",
"extraData": "0x3535353535353535353535353535353535353535353535353535353535353535"
},
"hardforks": [
{
"name": "chainstart",
"block": 0,
"forkHash": "0x30c7ddbc"
},
{
"name": "homestead",
"block": 0,
"forkHash": "0x30c7ddbc"
},
{
"name": "tangerineWhistle",
"block": 0,
"forkHash": "0x30c7ddbc"
},
{
"name": "spuriousDragon",
"block": 10,
"forkHash": "0x63760190"
},
{
"name": "byzantium",
"block": 1700000,
"forkHash": "0x3ea159c7"
},
{
"name": "constantinople",
"block": 4230000,
"forkHash": "0x97b544f3"
},
{
"name": "petersburg",
"block": 4939394,
"forkHash": "0xd6e2149b"
},
{
"name": "istanbul",
"block": 6485846,
"forkHash": "0x4bc66396"
},
{
"name": "muirGlacier",
"block": 7117117,
"forkHash": "0x6727ef90"
},
{
"name": "berlin",
"block": 9812189,
"forkHash": "0xa157d377"
},
{
"name": "london",
"block": 10499401,
"forkHash": "0x7119b6b3"
},
{
"//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge",
"name": "merge",
"ttd": "50000000000000000",
"block": null,
"forkHash": "0x7119b6b3"
},
{
"name": "mergeForkIdTransition",
"block": null,
"forkHash": null
},
{
"name": "shanghai",
"block": null,
"forkHash": null
}
],
"bootstrapNodes": [
{
"ip": "52.176.7.10",
"port": 30303,
"id": "30b7ab30a01c124a6cceca36863ece12c4f5fa68e3ba9b0b51407ccc002eeed3b3102d20a88f1c1d3c3154e2449317b8ef95090e77b312d5cc39354f86d5d606",
"location": "",
"comment": "US-Azure geth"
},
{
"ip": "52.176.100.77",
"port": 30303,
"id": "865a63255b3bb68023b6bffd5095118fcc13e79dcf014fe4e47e065c350c7cc72af2e53eff895f11ba1bbb6a2b33271c1116ee870f266618eadfc2e78aa7349c",
"location": "",
"comment": "US-Azure parity"
},
{
"ip": "52.232.243.152",
"port": 30303,
"id": "6332792c4a00e3e4ee0926ed89e0d27ef985424d97b6a45bf0f23e51f0dcb5e66b875777506458aea7af6f9e4ffb69f43f3778ee73c81ed9d34c51c4b16b0b0f",
"location": "",
"comment": "Parity"
},
{
"ip": "192.81.208.223",
"port": 30303,
"id": "94c15d1b9e2fe7ce56e458b9a3b672ef11894ddedd0c6f247e0f1d3487f52b66208fb4aeb8179fce6e3a749ea93ed147c37976d67af557508d199d9594c35f09",
"location": "",
"comment": "@gpip"
}
],
"dnsNetworks": [
"enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.ropsten.ethdisco.net"
]
}
},{}],6:[function(require,module,exports){
module.exports={
"name": "sepolia",
"chainId": 11155111,
"networkId": 11155111,
"defaultHardfork": "merge",
"consensus": {
"type": "pow",
"algorithm": "ethash",
"ethash": {}
},
"comment": "PoW test network to replace Ropsten",
"url": "https://github.com/ethereum/go-ethereum/pull/23730",
"genesis": {
"timestamp": "0x6159af19",
"gasLimit": 30000000,
"difficulty": 131072,
"nonce": "0x0000000000000000",
"extraData": "0x5365706f6c69612c20417468656e732c204174746963612c2047726565636521"
},
"hardforks": [
{
"name": "chainstart",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "homestead",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "tangerineWhistle",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "spuriousDragon",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "byzantium",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "constantinople",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "petersburg",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "istanbul",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "muirGlacier",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "berlin",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"name": "london",
"block": 0,
"forkHash": "0xfe3366e7"
},
{
"//_comment": "The forkHash will remain same as mergeForkIdTransition is post merge, terminal block: https://sepolia.etherscan.io/block/1450408",
"name": "merge",
"ttd": "17000000000000000",
"block": 1450409,
"forkHash": "0xfe3366e7"
},
{
"name": "mergeForkIdTransition",
"block": 1735371,
"forkHash": "0xb96cbd13"
},
{
"name": "shanghai",
"block": null,
"timestamp": "1677557088",
"forkHash": "0xf7f9bc08"
}
],
"bootstrapNodes": [
{
"ip": "18.168.182.86",
"port": 30303,
"id": "9246d00bc8fd1742e5ad2428b80fc4dc45d786283e05ef6edbd9002cbc335d40998444732fbe921cb88e1d2c73d1b1de53bae6a2237996e9bfe14f871baf7066",
"location": "",
"comment": "geth"
},
{
"ip": "52.14.151.177",
"port": 30303,
"id": "ec66ddcf1a974950bd4c782789a7e04f8aa7110a72569b6e65fcd51e937e74eed303b1ea734e4d19cfaec9fbff9b6ee65bf31dcb50ba79acce9dd63a6aca61c7",
"location": "",
"comment": "besu"
},
{
"ip": "165.22.196.173",
"port": 30303,
"id": "ce970ad2e9daa9e14593de84a8b49da3d54ccfdf83cbc4fe519cb8b36b5918ed4eab087dedd4a62479b8d50756b492d5f762367c8d20329a7854ec01547568a6",
"location": "",
"comment": "EF"
},
{
"ip": "65.108.95.67",
"port": 30303,
"id": "075503b13ed736244896efcde2a992ec0b451357d46cb7a8132c0384721742597fc8f0d91bbb40bb52e7d6e66728d36a1fda09176294e4a30cfac55dcce26bc6",
"location": "",
"comment": "lodestar"
}
],
"dnsNetworks": [
"enrtree://AKA3AM6LPBYEUDMVNU3BSVQJ5AD45Y7YPOHJLEF6W26QOE4VTUDPE@all.sepolia.ethdisco.net"
]
}
},{}],7:[function(require,module,exports){
(function (Buffer){(function (){
"use strict";
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t["return"] && (u = t["return"](), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it["return"] != null) it["return"](); } finally { if (didErr) throw err; } } }; }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return _typeof(key) === "symbol" ? key : String(key); }
function _toPrimitive(input, hint) { if (_typeof(input) !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (_typeof(res) !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); Object.defineProperty(subClass, "prototype", { writable: false }); if (superClass) _setPrototypeOf(subClass, superClass); }
function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
function _createSuper(Derived) { var hasNativeReflectConstruct = _isNativeReflectConstruct(); return function _createSuperInternal() { var Super = _getPrototypeOf(Derived), result; if (hasNativeReflectConstruct) { var NewTarget = _getPrototypeOf(this).constructor; result = Reflect.construct(Super, arguments, NewTarget); } else { result = Super.apply(this, arguments); } return _possibleConstructorReturn(this, result); }; }
function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } else if (call !== void 0) { throw new TypeError("Derived constructors may only return object or undefined"); } return _assertThisInitialized(self); }
function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
function _isNativeReflectConstruct() { if (typeof Reflect === "undefined" || !Reflect.construct) return false; if (Reflect.construct.sham) return false; if (typeof Proxy === "function") return true; try { Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); return true; } catch (e) { return false; } }
function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.Common = void 0;
var util_1 = require("@ethereumjs/util");
var crc_32_1 = require("crc-32");
var events_1 = require("events");
var goerli = require("./chains/goerli.json");
var mainnet = require("./chains/mainnet.json");
var rinkeby = require("./chains/rinkeby.json");
var ropsten = require("./chains/ropsten.json");
var sepolia = require("./chains/sepolia.json");
var eips_1 = require("./eips");
var enums_1 = require("./enums");
var hardforks_1 = require("./hardforks");
var utils_1 = require("./utils");
/**
* Common class to access chain and hardfork parameters and to provide
* a unified and shared view on the network and hardfork state.
*
* Use the {@link Common.custom} static constructor for creating simple
* custom chain {@link Common} objects (more complete custom chain setups
* can be created via the main constructor and the {@link CommonOpts.customChains} parameter).
*/
var Common = /*#__PURE__*/function (_events_1$EventEmitte) {
_inherits(Common, _events_1$EventEmitte);
var _super = _createSuper(Common);
function Common(opts) {
var _opts$customChains, _this$_chainParams$de;
var _this;
_classCallCheck(this, Common);
_this = _super.call(this);
_this._eips = [];
_this._customChains = (_opts$customChains = opts.customChains) !== null && _opts$customChains !== void 0 ? _opts$customChains : [];
_this._chainParams = _this.setChain(opts.chain);
_this.DEFAULT_HARDFORK = (_this$_chainParams$de = _this._chainParams.defaultHardfork) !== null && _this$_chainParams$de !== void 0 ? _this$_chainParams$de : enums_1.Hardfork.Merge;
// Assign hardfork changes in the sequence of the applied hardforks
_this.HARDFORK_CHANGES = _this.hardforks().map(function (hf) {
return [hf.name, hardforks_1.hardforks[hf.name]];
});
_this._hardfork = _this.DEFAULT_HARDFORK;
if (opts.hardfork !== undefined) {
_this.setHardfork(opts.hardfork);
}
if (opts.eips) {
_this.setEIPs(opts.eips);
}
return _this;
}
/**
* Creates a {@link Common} object for a custom chain, based on a standard one.
*
* It uses all the {@link Chain} parameters from the {@link baseChain} option except the ones overridden
* in a provided {@link chainParamsOrName} dictionary. Some usage example:
*
* ```javascript
* Common.custom({chainId: 123})
* ```
*
* There are also selected supported custom chains which can be initialized by using one of the
* {@link CustomChains} for {@link chainParamsOrName}, e.g.:
*
* ```javascript
* Common.custom(CustomChains.MaticMumbai)
* ```
*
* Note that these supported custom chains only provide some base parameters (usually the chain and
* network ID and a name) and can only be used for selected use cases (e.g. sending a tx with
* the `@ethereumjs/tx` library to a Layer-2 chain).
*
* @param chainParamsOrName Custom parameter dict (`name` will default to `custom-chain`) or string with name of a supported custom chain
* @param opts Custom chain options to set the {@link CustomCommonOpts.baseChain}, selected {@link CustomCommonOpts.hardfork} and others
*/
_createClass(Common, [{
key: "setChain",
value:
/**
* Sets the chain
* @param chain String ('mainnet') or Number (1) chain representation.
* Or, a Dictionary of chain parameters for a private network.
* @returns The dictionary with parameters set as chain
*/
function setChain(chain) {
if (typeof chain === 'number' || typeof chain === 'bigint' || typeof chain === 'string') {
this._chainParams = Common._getChainParams(chain, this._customChains);
} else if (_typeof(chain) === 'object') {
if (this._customChains.length > 0) {
throw new Error('Chain must be a string, number, or bigint when initialized with customChains passed in');
}
var required = ['networkId', 'genesis', 'hardforks', 'bootstrapNodes'];
for (var _i = 0, _required = required; _i < _required.length; _i++) {
var param = _required[_i];
if (!(param in chain)) {
throw new Error("Missing required chain parameter: ".concat(param));
}
}
this._chainParams = chain;
} else {
throw new Error('Wrong input format');
}
var _iterator = _createForOfIteratorHelper(this.hardforks()),
_step;
try {
for (_iterator.s(); !(_step = _iterator.n()).done;) {
var hf = _step.value;
if (hf.block === undefined) {
throw new Error("Hardfork cannot have undefined block number");
}
}
} catch (err) {
_iterator.e(err);
} finally {
_iterator.f();
}
return this._chainParams;
}
/**
* Sets the hardfork to get params for
* @param hardfork String identifier (e.g. 'byzantium') or {@link Hardfork} enum
*/
}, {
key: "setHardfork",
value: function setHardfork(hardfork) {
var existing = false;
var _iterator2 = _createForOfIteratorHelper(this.HARDFORK_CHANGES),
_step2;
try {
for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
var hfChanges = _step2.value;
if (hfChanges[0] === hardfork) {
if (this._hardfork !== hardfork) {
this._hardfork = hardfork;
this.emit('hardforkChanged', hardfork);
}
existing = true;
}
}
} catch (err) {
_iterator2.e(err);
} finally {
_iterator2.f();
}
if (!existing) {
throw new Error("Hardfork with name ".concat(hardfork, " not supported"));
}
}
/**
* Returns the hardfork based on the block number or an optional
* total difficulty (Merge HF) provided.
*
* An optional TD takes precedence in case the corresponding HF block
* is set to `null` or otherwise needs to match (if not an error
* will be thrown).
*
* @param blockNumber
* @param td : total difficulty of the parent block (for block hf) OR of the chain latest (for chain hf)
* @param timestamp: timestamp in seconds at which block was/is to be minted
* @returns The name of the HF
*/
}, {
key: "getHardforkByBlockNumber",
value: function getHardforkByBlockNumber(blockNumber, td, timestamp) {
blockNumber = (0, util_1.toType)(blockNumber, util_1.TypeOutput.BigInt);
td = (0, util_1.toType)(td, util_1.TypeOutput.BigInt);
timestamp = (0, util_1.toType)(timestamp, util_1.TypeOutput.Number);
// Filter out hardforks with no block number, no ttd or no timestamp (i.e. unapplied hardforks)
var hfs = this.hardforks().filter(function (hf) {
return hf.block !== null || hf.ttd !== null && hf.ttd !== undefined || hf.timestamp !== undefined;
});
var mergeIndex = hfs.findIndex(function (hf) {
return hf.ttd !== null && hf.ttd !== undefined;
});
var doubleTTDHF = hfs.slice(mergeIndex + 1).findIndex(function (hf) {
return hf.ttd !== null && hf.ttd !== undefined;
});
if (doubleTTDHF >= 0) {
throw Error("More than one merge hardforks found with ttd specified");
}
// Find the first hardfork that has a block number greater than `blockNumber`
// (skips the merge hardfork since it cannot have a block number specified).
// If timestamp is not provided, it also skips timestamps hardforks to continue
// discovering/checking number hardforks.
var hfIndex = hfs.findIndex(function (hf) {
return hf.block !== null && hf.block > blockNumber || timestamp !== undefined && Number(hf.timestamp) > timestamp;
});
if (hfIndex === -1) {
// all hardforks apply, set hfIndex to the last one as that's the candidate
hfIndex = hfs.length;
} else if (hfIndex === 0) {
// cannot have a case where a block number is before all applied hardforks
// since the chain has to start with a hardfork
throw Error('Must have at least one hardfork at block 0');
}
// If timestamp is not provided, we need to rollback to the last hf with block or ttd
if (timestamp === undefined) {
var stepBack = hfs.slice(0, hfIndex).reverse().findIndex(function (hf) {
return hf.block !== null || hf.ttd !== undefined;
});
hfIndex = hfIndex - stepBack;
}
// Move hfIndex one back to arrive at candidate hardfork
hfIndex = hfIndex - 1;
// If the timestamp was not provided, we could have skipped timestamp hardforks to look for number
// hardforks. so it will now be needed to rollback
if (hfs[hfIndex].block === null && hfs[hfIndex].timestamp === undefined) {
// We're on the merge hardfork. Let's check the TTD
if (td === undefined || td === null || BigInt(hfs[hfIndex].ttd) > td) {
// Merge ttd greater than current td so we're on hardfork before merge
hfIndex -= 1;
}
} else {
if (mergeIndex >= 0 && td !== undefined && td !== null) {
if (hfIndex >= mergeIndex && BigInt(hfs[mergeIndex].ttd) > td) {
throw Error('Maximum HF determined by total difficulty is lower than the block number HF');
} else if (hfIndex < mergeIndex && BigInt(hfs[mergeIndex].ttd) <= td) {
throw Error('HF determined by block number is lower than the minimum total difficulty HF');
}
}
}
var hfStartIndex = hfIndex;
// Move the hfIndex to the end of the hardforks that might be scheduled on the same block/timestamp
// This won't anyway be the case with Merge hfs
for (; hfIndex < hfs.length - 1; hfIndex++) {
// break out if hfIndex + 1 is not scheduled at hfIndex
if (hfs[hfIndex].block !== hfs[hfIndex + 1].block || hfs[hfIndex].timestamp !== hfs[hfIndex + 1].timestamp) {
break;
}
}
if (timestamp) {
var minTimeStamp = hfs.slice(0, hfStartIndex).reduce(function (acc, hf) {
var _hf$timestamp;
return Math.max(Number((_hf$timestamp = hf.timestamp) !== null && _hf$timestamp !== void 0 ? _hf$timestamp : '0'), acc);
}, 0);
if (minTimeStamp > timestamp) {
throw Error("Maximum HF determined by timestamp is lower than the block number/ttd HF");
}
var maxTimeStamp = hfs.slice(hfIndex + 1).reduce(function (acc, hf) {
var _hf$timestamp2;
return Math.min(Number((_hf$timestamp2 = hf.timestamp) !== null && _hf$timestamp2 !== void 0 ? _hf$timestamp2 : timestamp), acc);
}, timestamp);
if (maxTimeStamp < timestamp) {
throw Error("Maximum HF determined by block number/ttd is lower than timestamp HF");
}
}
var hardfork = hfs[hfIndex];
return hardfork.name;
}
/**
* Sets a new hardfork based on the block number or an optional
* total difficulty (Merge HF) provided.
*
* An optional TD takes precedence in case the corresponding HF block
* is set to `null` or otherwise needs to match (if not an error
* will be thrown).
*
* @param blockNumber
* @param td
* @param timestamp
* @returns The name of the HF set
*/
}, {
key: "setHardforkByBlockNumber",
value: function setHardforkByBlockNumber(blockNumber, td, timestamp) {
var hardfork = this.getHardforkByBlockNumber(blockNumber, td, timestamp);
this.setHardfork(hardfork);
return hardfork;
}
/**
* Internal helper function, returns the params for the given hardfork for the chain set
* @param hardfork Hardfork name
* @returns Dictionary with hardfork params or null if hardfork not on chain
*/
}, {
key: "_getHardfork",
value: function _getHardfork(hardfork) {
var hfs = this.hardforks();
var _iterator3 = _createForOfIteratorHelper(hfs),
_step3;
try {
for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
var hf = _step3.value;
if (hf['name'] === hardfork) return hf;
}
} catch (err) {
_iterator3.e(err);
} finally {
_iterator3.f();
}
return null;
}
/**
* Sets the active EIPs
* @param eips
*/
}, {
key: "setEIPs",
value: function setEIPs() {
var eips = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
var _iterator4 = _createForOfIteratorHelper(eips),
_step4;
try {
for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
var eip = _step4.value;
if (!(eip in eips_1.EIPs)) {
throw new Error("".concat(eip, " not supported"));
}
var minHF = this.gteHardfork(eips_1.EIPs[eip]['minimumHardfork']);
if (!minHF) {
throw new Error("".concat(eip, " cannot be activated on hardfork ").concat(this.hardfork(), ", minimumHardfork: ").concat(minHF));
}
if (eips_1.EIPs[eip].requiredEIPs !== undefined) {
var _iterator5 = _createForOfIteratorHelper(eips_1.EIPs[eip].requiredEIPs),
_step5;
try {
for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
var elem = _step5.value;
if (!(eips.includes(elem) || this.isActivatedEIP(elem))) {
throw new Error("".concat(eip, " requires EIP ").concat(elem, ", but is not included in the EIP list"));
}