@feelyourprotocol/common 8141.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +409 -0
  3. package/dist/cjs/chains.d.ts +6 -0
  4. package/dist/cjs/chains.d.ts.map +1 -0
  5. package/dist/cjs/chains.js +637 -0
  6. package/dist/cjs/chains.js.map +1 -0
  7. package/dist/cjs/common.d.ts +318 -0
  8. package/dist/cjs/common.d.ts.map +1 -0
  9. package/dist/cjs/common.js +789 -0
  10. package/dist/cjs/common.js.map +1 -0
  11. package/dist/cjs/constructors.d.ts +27 -0
  12. package/dist/cjs/constructors.d.ts.map +1 -0
  13. package/dist/cjs/constructors.js +53 -0
  14. package/dist/cjs/constructors.js.map +1 -0
  15. package/dist/cjs/crc.d.ts +8 -0
  16. package/dist/cjs/crc.d.ts.map +1 -0
  17. package/dist/cjs/crc.js +63 -0
  18. package/dist/cjs/crc.js.map +1 -0
  19. package/dist/cjs/eips.d.ts +3 -0
  20. package/dist/cjs/eips.d.ts.map +1 -0
  21. package/dist/cjs/eips.js +589 -0
  22. package/dist/cjs/eips.js.map +1 -0
  23. package/dist/cjs/enums.d.ts +65 -0
  24. package/dist/cjs/enums.d.ts.map +1 -0
  25. package/dist/cjs/enums.js +80 -0
  26. package/dist/cjs/enums.js.map +1 -0
  27. package/dist/cjs/gethGenesis.d.ts +145 -0
  28. package/dist/cjs/gethGenesis.d.ts.map +1 -0
  29. package/dist/cjs/gethGenesis.js +26 -0
  30. package/dist/cjs/gethGenesis.js.map +1 -0
  31. package/dist/cjs/hardforks.d.ts +3 -0
  32. package/dist/cjs/hardforks.d.ts.map +1 -0
  33. package/dist/cjs/hardforks.js +207 -0
  34. package/dist/cjs/hardforks.js.map +1 -0
  35. package/dist/cjs/index.d.ts +9 -0
  36. package/dist/cjs/index.d.ts.map +1 -0
  37. package/dist/cjs/index.js +25 -0
  38. package/dist/cjs/index.js.map +1 -0
  39. package/dist/cjs/interfaces.d.ts +132 -0
  40. package/dist/cjs/interfaces.d.ts.map +1 -0
  41. package/dist/cjs/interfaces.js +13 -0
  42. package/dist/cjs/interfaces.js.map +1 -0
  43. package/dist/cjs/package.json +3 -0
  44. package/dist/cjs/types.d.ts +167 -0
  45. package/dist/cjs/types.d.ts.map +1 -0
  46. package/dist/cjs/types.js +3 -0
  47. package/dist/cjs/types.js.map +1 -0
  48. package/dist/cjs/utils.d.ts +60 -0
  49. package/dist/cjs/utils.d.ts.map +1 -0
  50. package/dist/cjs/utils.js +263 -0
  51. package/dist/cjs/utils.js.map +1 -0
  52. package/dist/esm/chains.d.ts +6 -0
  53. package/dist/esm/chains.d.ts.map +1 -0
  54. package/dist/esm/chains.js +634 -0
  55. package/dist/esm/chains.js.map +1 -0
  56. package/dist/esm/common.d.ts +318 -0
  57. package/dist/esm/common.d.ts.map +1 -0
  58. package/dist/esm/common.js +785 -0
  59. package/dist/esm/common.js.map +1 -0
  60. package/dist/esm/constructors.d.ts +27 -0
  61. package/dist/esm/constructors.d.ts.map +1 -0
  62. package/dist/esm/constructors.js +49 -0
  63. package/dist/esm/constructors.js.map +1 -0
  64. package/dist/esm/crc.d.ts +8 -0
  65. package/dist/esm/crc.d.ts.map +1 -0
  66. package/dist/esm/crc.js +59 -0
  67. package/dist/esm/crc.js.map +1 -0
  68. package/dist/esm/eips.d.ts +3 -0
  69. package/dist/esm/eips.d.ts.map +1 -0
  70. package/dist/esm/eips.js +586 -0
  71. package/dist/esm/eips.js.map +1 -0
  72. package/dist/esm/enums.d.ts +65 -0
  73. package/dist/esm/enums.d.ts.map +1 -0
  74. package/dist/esm/enums.js +77 -0
  75. package/dist/esm/enums.js.map +1 -0
  76. package/dist/esm/gethGenesis.d.ts +145 -0
  77. package/dist/esm/gethGenesis.d.ts.map +1 -0
  78. package/dist/esm/gethGenesis.js +23 -0
  79. package/dist/esm/gethGenesis.js.map +1 -0
  80. package/dist/esm/hardforks.d.ts +3 -0
  81. package/dist/esm/hardforks.d.ts.map +1 -0
  82. package/dist/esm/hardforks.js +204 -0
  83. package/dist/esm/hardforks.js.map +1 -0
  84. package/dist/esm/index.d.ts +9 -0
  85. package/dist/esm/index.d.ts.map +1 -0
  86. package/dist/esm/index.js +9 -0
  87. package/dist/esm/index.js.map +1 -0
  88. package/dist/esm/interfaces.d.ts +132 -0
  89. package/dist/esm/interfaces.d.ts.map +1 -0
  90. package/dist/esm/interfaces.js +10 -0
  91. package/dist/esm/interfaces.js.map +1 -0
  92. package/dist/esm/package.json +3 -0
  93. package/dist/esm/types.d.ts +167 -0
  94. package/dist/esm/types.d.ts.map +1 -0
  95. package/dist/esm/types.js +2 -0
  96. package/dist/esm/types.js.map +1 -0
  97. package/dist/esm/utils.d.ts +60 -0
  98. package/dist/esm/utils.d.ts.map +1 -0
  99. package/dist/esm/utils.js +258 -0
  100. package/dist/esm/utils.js.map +1 -0
  101. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -0
  102. package/dist/tsconfig.prod.esm.tsbuildinfo +1 -0
  103. package/package.json +77 -0
  104. package/src/chains.ts +638 -0
  105. package/src/common.ts +913 -0
  106. package/src/constructors.ts +60 -0
  107. package/src/crc.ts +63 -0
  108. package/src/eips.ts +588 -0
  109. package/src/enums.ts +104 -0
  110. package/src/gethGenesis.ts +175 -0
  111. package/src/hardforks.ts +205 -0
  112. package/src/index.ts +8 -0
  113. package/src/interfaces.ts +191 -0
  114. package/src/types.ts +193 -0
  115. package/src/utils.ts +324 -0
@@ -0,0 +1,789 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Common = void 0;
4
+ const util_1 = require("@feelyourprotocol/util");
5
+ const eventemitter3_1 = require("eventemitter3");
6
+ const crc_ts_1 = require("./crc.js");
7
+ const eips_ts_1 = require("./eips.js");
8
+ const enums_ts_1 = require("./enums.js");
9
+ const hardforks_ts_1 = require("./hardforks.js");
10
+ /**
11
+ * Common class to access chain and hardfork parameters and to provide
12
+ * a unified and shared view on the network and hardfork state.
13
+ *
14
+ * Use the {@link createCustomCommon} constructor for creating simple
15
+ * custom chain {@link Common} objects (more complete custom chain setups
16
+ * can be created via the main constructor).
17
+ *
18
+ * Use the {@link createCommonFromGethGenesis} constructor for creating
19
+ * a Common object from a Geth genesis file.
20
+ */
21
+ class Common {
22
+ constructor(opts) {
23
+ this._eips = [];
24
+ this._paramsCache = {};
25
+ this._activatedEIPsCache = [];
26
+ this.events = new eventemitter3_1.EventEmitter();
27
+ this._chainParams = JSON.parse(JSON.stringify(opts.chain)); // copy
28
+ this.DEFAULT_HARDFORK = this._chainParams.defaultHardfork ?? enums_ts_1.Hardfork.Prague;
29
+ // Assign hardfork changes in the sequence of the applied hardforks
30
+ this.HARDFORK_CHANGES = this.hardforks().map((hf) => [
31
+ hf.name,
32
+ // Allow to even override an existing hardfork specification
33
+ (this._chainParams.customHardforks && this._chainParams.customHardforks[hf.name]) ??
34
+ hardforks_ts_1.hardforksDict[hf.name],
35
+ ]);
36
+ this._hardfork = this.DEFAULT_HARDFORK;
37
+ this._params = opts.params ? JSON.parse(JSON.stringify(opts.params)) : {}; // copy
38
+ if (opts.hardfork !== undefined) {
39
+ this.setHardfork(opts.hardfork);
40
+ }
41
+ if (opts.eips) {
42
+ this.setEIPs(opts.eips);
43
+ }
44
+ this.customCrypto = opts.customCrypto ?? {};
45
+ if (Object.keys(this._paramsCache).length === 0) {
46
+ this._buildParamsCache();
47
+ this._buildActivatedEIPsCache();
48
+ }
49
+ }
50
+ /**
51
+ * Update the internal Common EIP params set. Existing values
52
+ * will get preserved unless there is a new value for a parameter
53
+ * provided with params.
54
+ *
55
+ * Example Format:
56
+ *
57
+ * ```ts
58
+ * {
59
+ * 1559: {
60
+ * initialBaseFee: 1000000000,
61
+ * }
62
+ * }
63
+ * ```
64
+ *
65
+ * @param params
66
+ */
67
+ updateParams(params) {
68
+ for (const [eip, paramsConfig] of Object.entries(params)) {
69
+ if (!(eip in this._params)) {
70
+ this._params[eip] = JSON.parse(JSON.stringify(paramsConfig)); // copy
71
+ }
72
+ else {
73
+ this._params[eip] = JSON.parse(JSON.stringify({ ...this._params[eip], ...params[eip] })); // copy
74
+ }
75
+ }
76
+ this._buildParamsCache();
77
+ }
78
+ /**
79
+ * Fully resets the internal Common EIP params set with the values provided.
80
+ *
81
+ * Example Format:
82
+ *
83
+ * ```ts
84
+ * {
85
+ * 1559: {
86
+ * initialBaseFee: 1000000000,
87
+ * }
88
+ * }
89
+ * ```
90
+ *
91
+ * @param params
92
+ */
93
+ resetParams(params) {
94
+ this._params = JSON.parse(JSON.stringify(params)); // copy
95
+ this._buildParamsCache();
96
+ }
97
+ /**
98
+ * Sets the hardfork to get params for
99
+ * @param hardfork String identifier (e.g. 'byzantium') or {@link Hardfork} enum
100
+ */
101
+ setHardfork(hardfork) {
102
+ let existing = false;
103
+ for (const hfChanges of this.HARDFORK_CHANGES) {
104
+ if (hfChanges[0] === hardfork) {
105
+ if (this._hardfork !== hardfork) {
106
+ this._hardfork = hardfork;
107
+ this._buildParamsCache();
108
+ this._buildActivatedEIPsCache();
109
+ this.events.emit('hardforkChanged', hardfork);
110
+ }
111
+ existing = true;
112
+ }
113
+ }
114
+ if (!existing) {
115
+ throw (0, util_1.EthereumJSErrorWithoutCode)(`Hardfork with name ${hardfork} not supported`);
116
+ }
117
+ }
118
+ /**
119
+ * Returns the hardfork either based on block number (older HFs) or
120
+ * timestamp (Shanghai upwards).
121
+ *
122
+ * @param opts Block number or timestamp
123
+ * @returns The name of the HF
124
+ */
125
+ getHardforkBy(opts) {
126
+ const blockNumber = (0, util_1.toType)(opts.blockNumber, util_1.TypeOutput.BigInt);
127
+ const timestamp = (0, util_1.toType)(opts.timestamp, util_1.TypeOutput.BigInt);
128
+ // Filter out hardforks with no block number, no timestamp (i.e. unapplied hardforks)
129
+ const hfs = this.hardforks().filter((hf) => hf.block !== null || hf.timestamp !== undefined);
130
+ // Find the first hardfork that has a block number greater than `blockNumber`
131
+ // If timestamp is not provided, it also skips timestamps hardforks to continue
132
+ // discovering/checking number hardforks.
133
+ let hfIndex = hfs.findIndex((hf) => (blockNumber !== undefined && hf.block !== null && BigInt(hf.block) > blockNumber) ||
134
+ (timestamp !== undefined && hf.timestamp !== undefined && BigInt(hf.timestamp) > timestamp));
135
+ if (hfIndex === -1) {
136
+ // all hardforks apply, set hfIndex to the last one as that's the candidate
137
+ hfIndex = hfs.length;
138
+ }
139
+ else if (hfIndex === 0) {
140
+ // cannot have a case where a block number is before all applied hardforks
141
+ // since the chain has to start with a hardfork
142
+ throw Error('Must have at least one hardfork at block 0');
143
+ }
144
+ // If timestamp is not provided, we need to rollback to the last hf with block
145
+ if (timestamp === undefined) {
146
+ const stepBack = hfs
147
+ .slice(0, hfIndex)
148
+ .reverse()
149
+ .findIndex((hf) => hf.block !== null);
150
+ hfIndex = hfIndex - stepBack;
151
+ }
152
+ // Move hfIndex one back to arrive at candidate hardfork
153
+ hfIndex = hfIndex - 1;
154
+ const hfStartIndex = hfIndex;
155
+ // Move the hfIndex to the end of the hardforks that might be scheduled on the same block/timestamp
156
+ // This won't anyway be the case with Merge hfs
157
+ for (; hfIndex < hfs.length - 1; hfIndex++) {
158
+ // break out if hfIndex + 1 is not scheduled at hfIndex
159
+ if (hfs[hfIndex].block !== hfs[hfIndex + 1].block ||
160
+ hfs[hfIndex].timestamp !== hfs[hfIndex + 1].timestamp) {
161
+ break;
162
+ }
163
+ }
164
+ if (timestamp !== undefined) {
165
+ const minTimeStamp = hfs
166
+ .slice(0, hfStartIndex)
167
+ .reduce((acc, hf) => Math.max(Number(hf.timestamp ?? '0'), acc), 0);
168
+ if (minTimeStamp > timestamp) {
169
+ throw Error(`Maximum HF determined by timestamp is lower than the block number HF`);
170
+ }
171
+ const maxTimeStamp = hfs
172
+ .slice(hfIndex + 1)
173
+ .reduce((acc, hf) => Math.min(Number(hf.timestamp ?? timestamp), acc), Number(timestamp));
174
+ if (maxTimeStamp < timestamp) {
175
+ throw Error(`Maximum HF determined by block number is lower than timestamp HF`);
176
+ }
177
+ }
178
+ const hardfork = hfs[hfIndex];
179
+ return hardfork.name;
180
+ }
181
+ /**
182
+ * Sets a new hardfork either based on block number (older HFs) or
183
+ * timestamp (Shanghai upwards).
184
+ *
185
+ * @param opts Block number or timestamp
186
+ * @returns The name of the HF set
187
+ */
188
+ setHardforkBy(opts) {
189
+ const hardfork = this.getHardforkBy(opts);
190
+ this.setHardfork(hardfork);
191
+ return hardfork;
192
+ }
193
+ /**
194
+ * Internal helper function, returns the params for the given hardfork for the chain set
195
+ * @param hardfork Hardfork name
196
+ * @returns Dictionary with hardfork params or null if hardfork not on chain
197
+ */
198
+ _getHardfork(hardfork) {
199
+ const hfs = this.hardforks();
200
+ for (const hf of hfs) {
201
+ if (hf['name'] === hardfork)
202
+ return hf;
203
+ }
204
+ return null;
205
+ }
206
+ /**
207
+ * Sets the active EIPs
208
+ * @param eips
209
+ */
210
+ setEIPs(eips = []) {
211
+ for (const eip of eips) {
212
+ if (!(eip in eips_ts_1.eipsDict)) {
213
+ throw (0, util_1.EthereumJSErrorWithoutCode)(`${eip} not supported`);
214
+ }
215
+ const minHF = this.gteHardfork(eips_ts_1.eipsDict[eip]['minimumHardfork']);
216
+ if (!minHF) {
217
+ throw (0, util_1.EthereumJSErrorWithoutCode)(`${eip} cannot be activated on hardfork ${this.hardfork()}, minimumHardfork: ${minHF}`);
218
+ }
219
+ }
220
+ this._eips = eips;
221
+ this._buildParamsCache();
222
+ this._buildActivatedEIPsCache();
223
+ for (const eip of eips) {
224
+ if (eips_ts_1.eipsDict[eip].requiredEIPs !== undefined) {
225
+ for (const elem of eips_ts_1.eipsDict[eip].requiredEIPs) {
226
+ if (!(eips.includes(elem) || this.isActivatedEIP(elem))) {
227
+ throw (0, util_1.EthereumJSErrorWithoutCode)(`${eip} requires EIP ${elem}, but is not included in the EIP list`);
228
+ }
229
+ }
230
+ }
231
+ }
232
+ }
233
+ /**
234
+ * Internal helper for _buildParamsCache()
235
+ */
236
+ _mergeWithParamsCache(params) {
237
+ for (const [key, value] of Object.entries(params)) {
238
+ this._paramsCache[key] = value;
239
+ }
240
+ }
241
+ /**
242
+ * Build up a cache for all parameter values for the current HF and all activated EIPs
243
+ */
244
+ _buildParamsCache() {
245
+ this._paramsCache = {};
246
+ // Iterate through all hardforks up to hardfork set
247
+ const hardfork = this.hardfork();
248
+ for (const hfChanges of this.HARDFORK_CHANGES) {
249
+ // EIP-referencing HF config (e.g. for berlin)
250
+ if ('eips' in hfChanges[1]) {
251
+ const hfEIPs = hfChanges[1].eips ?? [];
252
+ for (const eip of hfEIPs) {
253
+ if (this._params[eip] !== undefined && this._params[eip] !== null) {
254
+ this._mergeWithParamsCache(this._params[eip]);
255
+ }
256
+ }
257
+ }
258
+ // Hardfork-scoped params (e.g. for bpo1, bpo2)
259
+ // override the baseline EIP values when present
260
+ const hfScopedParams = this._params[hfChanges[0]];
261
+ if (hfScopedParams !== undefined && hfScopedParams !== null) {
262
+ this._mergeWithParamsCache(hfScopedParams);
263
+ }
264
+ // Parameter-inlining HF config (e.g. for istanbul or custom blobSchedule)
265
+ if (hfChanges[1].params !== undefined && hfChanges[1].params !== null) {
266
+ this._mergeWithParamsCache(hfChanges[1].params);
267
+ }
268
+ if (hfChanges[0] === hardfork)
269
+ break;
270
+ }
271
+ // Iterate through all additionally activated EIPs
272
+ for (const eip of this._eips) {
273
+ if (this._params[eip] !== undefined && this._params[eip] !== null) {
274
+ this._mergeWithParamsCache(this._params[eip]);
275
+ }
276
+ }
277
+ }
278
+ /**
279
+ * Builds the cache of EIPs activated either via hardforks or constructor `eips`.
280
+ */
281
+ _buildActivatedEIPsCache() {
282
+ this._activatedEIPsCache = [];
283
+ for (const [name, hf] of this.HARDFORK_CHANGES) {
284
+ if (this.gteHardfork(name) && 'eips' in hf) {
285
+ this._activatedEIPsCache = this._activatedEIPsCache.concat(hf.eips ?? []);
286
+ }
287
+ }
288
+ this._activatedEIPsCache = this._activatedEIPsCache.concat(this._eips);
289
+ }
290
+ /**
291
+ * Returns a parameter for the current chain setup
292
+ *
293
+ * If the parameter is present in an EIP, the EIP always takes precedence.
294
+ * Otherwise the parameter is taken from the latest applied HF with
295
+ * a change on the respective parameter.
296
+ *
297
+ * @param name Parameter name (e.g. 'minGasLimit')
298
+ * @returns The value requested (throws if not found)
299
+ */
300
+ param(name) {
301
+ // TODO: consider the case that different active EIPs
302
+ // can change the same parameter
303
+ if (!(name in this._paramsCache)) {
304
+ throw (0, util_1.EthereumJSErrorWithoutCode)(`Missing parameter value for ${name}`);
305
+ }
306
+ const value = this._paramsCache[name];
307
+ return BigInt(value ?? 0);
308
+ }
309
+ /**
310
+ * Returns the parameter corresponding to a hardfork
311
+ * @param name Parameter name (e.g. 'minGasLimit')
312
+ * @param hardfork Hardfork name
313
+ * @returns The value requested (throws if not found)
314
+ */
315
+ paramByHardfork(name, hardfork) {
316
+ let value;
317
+ for (const hfChanges of this.HARDFORK_CHANGES) {
318
+ // EIP-referencing HF config (e.g. for berlin)
319
+ if ('eips' in hfChanges[1]) {
320
+ const hfEIPs = hfChanges[1]['eips'];
321
+ for (const eip of hfEIPs) {
322
+ const eipParams = this._params[eip];
323
+ const eipValue = eipParams?.[name];
324
+ if (eipValue !== undefined) {
325
+ value = eipValue;
326
+ }
327
+ }
328
+ // Parameter-inlining HF config (e.g. for istanbul)
329
+ }
330
+ else {
331
+ const hfValue = hfChanges[1].params?.[name];
332
+ if (hfValue !== undefined) {
333
+ value = hfValue;
334
+ }
335
+ }
336
+ if (hfChanges[0] === hardfork)
337
+ break;
338
+ }
339
+ if (value === undefined) {
340
+ throw (0, util_1.EthereumJSErrorWithoutCode)(`Missing parameter value for ${name}`);
341
+ }
342
+ return BigInt(value ?? 0);
343
+ }
344
+ /**
345
+ * Returns a parameter corresponding to an EIP
346
+ * @param name Parameter name (e.g. 'minGasLimit' for 'gasConfig' topic)
347
+ * @param eip Number of the EIP
348
+ * @returns The value requested (throws if not found)
349
+ */
350
+ paramByEIP(name, eip) {
351
+ if (!(eip in eips_ts_1.eipsDict)) {
352
+ throw (0, util_1.EthereumJSErrorWithoutCode)(`${eip} not supported`);
353
+ }
354
+ const eipParams = this._params[eip];
355
+ if (eipParams?.[name] === undefined) {
356
+ throw (0, util_1.EthereumJSErrorWithoutCode)(`Missing parameter value for ${name}`);
357
+ }
358
+ const value = eipParams[name];
359
+ return BigInt(value ?? 0);
360
+ }
361
+ /**
362
+ * Returns a parameter for the hardfork active on block number or
363
+ * optional provided total difficulty (Merge HF)
364
+ * @param name Parameter name
365
+ * @param blockNumber Block number
366
+ * @returns The value requested or `BigInt(0)` if not found
367
+ */
368
+ paramByBlock(name, blockNumber, timestamp) {
369
+ const hardfork = this.getHardforkBy({ blockNumber, timestamp });
370
+ return this.paramByHardfork(name, hardfork);
371
+ }
372
+ /**
373
+ * Returns the blob gas schedule for the current hardfork
374
+ * @returns The blob gas schedule
375
+ */
376
+ getBlobGasSchedule() {
377
+ if (this.gteHardfork(enums_ts_1.Hardfork.Bpo1)) {
378
+ return {
379
+ targetBlobGasPerBlock: this.param('target') * this.param('blobGasPerBlob'),
380
+ maxBlobGasPerBlock: this.param('max') * this.param('blobGasPerBlob'),
381
+ blobGasPriceUpdateFraction: this.param('blobGasPriceUpdateFraction'),
382
+ };
383
+ }
384
+ return {
385
+ targetBlobGasPerBlock: this.param('targetBlobGasPerBlock'),
386
+ maxBlobGasPerBlock: this.param('maxBlobGasPerBlock'),
387
+ blobGasPriceUpdateFraction: this.param('blobGasPriceUpdateFraction'),
388
+ };
389
+ }
390
+ /**
391
+ * Checks if an EIP is activated by either being included in the EIPs
392
+ * manually passed in with the {@link CommonOpts.eips} or in a
393
+ * hardfork currently being active
394
+ *
395
+ * Note: this method only works for EIPs being supported
396
+ * by the {@link CommonOpts.eips} constructor option
397
+ * @param eip
398
+ */
399
+ isActivatedEIP(eip) {
400
+ if (this._activatedEIPsCache.includes(eip)) {
401
+ return true;
402
+ }
403
+ return false;
404
+ }
405
+ /**
406
+ * Checks if set or provided hardfork is active on block number
407
+ * @param hardfork Hardfork name or null (for HF set)
408
+ * @param blockNumber
409
+ * @returns True if HF is active on block number
410
+ */
411
+ hardforkIsActiveOnBlock(hardfork, blockNumber) {
412
+ blockNumber = (0, util_1.toType)(blockNumber, util_1.TypeOutput.BigInt);
413
+ hardfork = hardfork ?? this._hardfork;
414
+ const hfBlock = this.hardforkBlock(hardfork);
415
+ if (typeof hfBlock === 'bigint' && hfBlock !== util_1.BIGINT_0 && blockNumber >= hfBlock) {
416
+ return true;
417
+ }
418
+ return false;
419
+ }
420
+ /**
421
+ * Alias to hardforkIsActiveOnBlock when hardfork is set
422
+ * @param blockNumber
423
+ * @returns True if HF is active on block number
424
+ */
425
+ activeOnBlock(blockNumber) {
426
+ return this.hardforkIsActiveOnBlock(null, blockNumber);
427
+ }
428
+ /**
429
+ * Sequence based check if given or set HF1 is greater than or equal HF2
430
+ * @param hardfork1 Hardfork name or null (if set)
431
+ * @param hardfork2 Hardfork name
432
+ * @returns True if HF1 gte HF2
433
+ */
434
+ hardforkGteHardfork(hardfork1, hardfork2) {
435
+ hardfork1 = hardfork1 ?? this._hardfork;
436
+ const hardforks = this.hardforks();
437
+ let posHf1 = -1, posHf2 = -1;
438
+ let index = 0;
439
+ for (const hf of hardforks) {
440
+ if (hf['name'] === hardfork1)
441
+ posHf1 = index;
442
+ if (hf['name'] === hardfork2)
443
+ posHf2 = index;
444
+ index += 1;
445
+ }
446
+ return posHf1 >= posHf2 && posHf2 !== -1;
447
+ }
448
+ /**
449
+ * Alias to hardforkGteHardfork when hardfork is set
450
+ * @param hardfork Hardfork name
451
+ * @returns True if hardfork set is greater than hardfork provided
452
+ */
453
+ gteHardfork(hardfork) {
454
+ return this.hardforkGteHardfork(null, hardfork);
455
+ }
456
+ /**
457
+ * Returns the hardfork change block for hardfork provided or set
458
+ * @param hardfork Hardfork name, optional if HF set
459
+ * @returns Block number or null if unscheduled
460
+ */
461
+ hardforkBlock(hardfork) {
462
+ hardfork = hardfork ?? this._hardfork;
463
+ const block = this._getHardfork(hardfork)?.['block'];
464
+ if (block === undefined || block === null) {
465
+ return null;
466
+ }
467
+ return BigInt(block);
468
+ }
469
+ /**
470
+ * Returns the timestamp at which a given hardfork is scheduled (if any).
471
+ * @param hardfork Hardfork name, optional if HF set
472
+ * @returns Timestamp or null if the hardfork is not timestamp-based
473
+ */
474
+ hardforkTimestamp(hardfork) {
475
+ hardfork = hardfork ?? this._hardfork;
476
+ const timestamp = this._getHardfork(hardfork)?.['timestamp'];
477
+ if (timestamp === undefined || timestamp === null) {
478
+ return null;
479
+ }
480
+ return BigInt(timestamp);
481
+ }
482
+ /**
483
+ * Returns the hardfork change block for eip
484
+ * @param eip EIP number
485
+ * @returns Block number or null if unscheduled
486
+ */
487
+ eipBlock(eip) {
488
+ for (const hfChanges of this.HARDFORK_CHANGES) {
489
+ const hf = hfChanges[1];
490
+ if ('eips' in hf) {
491
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
492
+ if (hf['eips'].includes(eip)) {
493
+ return this.hardforkBlock(hfChanges[0]);
494
+ }
495
+ }
496
+ }
497
+ return null;
498
+ }
499
+ /**
500
+ * Returns the scheduled timestamp of the EIP (if scheduled and scheduled by timestamp)
501
+ * @param eip EIP number
502
+ * @returns Scheduled timestamp. If this EIP is unscheduled, or the EIP is scheduled by block number, then it returns `null`.
503
+ */
504
+ eipTimestamp(eip) {
505
+ for (const hfChanges of this.HARDFORK_CHANGES) {
506
+ const hf = hfChanges[1];
507
+ if ('eips' in hf) {
508
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
509
+ if (hf['eips'].includes(eip)) {
510
+ return this.hardforkTimestamp(hfChanges[0]);
511
+ }
512
+ }
513
+ }
514
+ return null;
515
+ }
516
+ /**
517
+ * Returns the block number or timestamp at which the next hardfork will occur.
518
+ * For pre-merge hardforks, returns the block number.
519
+ * For post-merge hardforks, returns the timestamp.
520
+ * Returns null if there is no next hardfork.
521
+ * @param hardfork Hardfork name, optional if HF set
522
+ * @returns Block number or timestamp, or null if not available
523
+ */
524
+ nextHardforkBlockOrTimestamp(hardfork) {
525
+ const targetHardfork = hardfork ?? this._hardfork;
526
+ const hfs = this.hardforks();
527
+ // Find the index of the target hardfork
528
+ let targetHfIndex = hfs.findIndex((hf) => hf.name === targetHardfork);
529
+ // Special handling for The Merge (Paris) hardfork
530
+ if (targetHardfork === enums_ts_1.Hardfork.Paris) {
531
+ // The Merge is determined by total difficulty, not block number
532
+ // So we look at the previous hardfork's parameters instead
533
+ targetHfIndex -= 1;
534
+ }
535
+ // If we couldn't find a valid hardfork index, return null
536
+ if (targetHfIndex < 0) {
537
+ return null;
538
+ }
539
+ // Get the current hardfork's block/timestamp
540
+ const currentHf = hfs[targetHfIndex];
541
+ const currentBlockOrTimestamp = currentHf.timestamp ?? currentHf.block;
542
+ if (currentBlockOrTimestamp === null || currentBlockOrTimestamp === undefined) {
543
+ return null;
544
+ }
545
+ // Find the next hardfork that has a different block/timestamp
546
+ const nextHf = hfs.slice(targetHfIndex + 1).find((hf) => {
547
+ const nextBlockOrTimestamp = hf.timestamp ?? hf.block;
548
+ return (nextBlockOrTimestamp !== null &&
549
+ nextBlockOrTimestamp !== undefined &&
550
+ nextBlockOrTimestamp !== currentBlockOrTimestamp);
551
+ });
552
+ // If no next hf found with valid block or timestamp return null
553
+ if (nextHf === undefined) {
554
+ return null;
555
+ }
556
+ // Get the block/timestamp for the next hardfork
557
+ const nextBlockOrTimestamp = nextHf.timestamp ?? nextHf.block;
558
+ if (nextBlockOrTimestamp === null || nextBlockOrTimestamp === undefined) {
559
+ return null;
560
+ }
561
+ return BigInt(nextBlockOrTimestamp);
562
+ }
563
+ /**
564
+ * Internal helper function to calculate a fork hash
565
+ * @param hardfork Hardfork name
566
+ * @param genesisHash Genesis block hash of the chain
567
+ * @returns Fork hash as hex string
568
+ */
569
+ _calcForkHash(hardfork, genesisHash) {
570
+ let hfBytes = new Uint8Array(0);
571
+ let prevBlockOrTime = 0;
572
+ for (const hf of this.hardforks()) {
573
+ const { block, timestamp, name } = hf;
574
+ // Timestamp to be used for timestamp based hfs even if we may bundle
575
+ // block number with them retrospectively
576
+ let blockOrTime = timestamp ?? block;
577
+ blockOrTime = blockOrTime !== null ? Number(blockOrTime) : null;
578
+ // Skip for chainstart (0), not applied HFs (null) and
579
+ // when already applied on same blockOrTime HFs
580
+ // and on the merge since forkhash doesn't change on merge hf
581
+ if (typeof blockOrTime === 'number' &&
582
+ blockOrTime !== 0 &&
583
+ blockOrTime !== prevBlockOrTime &&
584
+ name !== enums_ts_1.Hardfork.Paris) {
585
+ const hfBlockBytes = (0, util_1.hexToBytes)(`0x${blockOrTime.toString(16).padStart(16, '0')}`);
586
+ hfBytes = (0, util_1.concatBytes)(hfBytes, hfBlockBytes);
587
+ prevBlockOrTime = blockOrTime;
588
+ }
589
+ if (hf.name === hardfork)
590
+ break;
591
+ }
592
+ const inputBytes = (0, util_1.concatBytes)(genesisHash, hfBytes);
593
+ // CRC32 delivers result as signed (negative) 32-bit integer,
594
+ // convert to hex string
595
+ const forkhash = (0, util_1.bytesToHex)((0, util_1.intToBytes)((0, crc_ts_1.crc32)(inputBytes) >>> 0));
596
+ return forkhash;
597
+ }
598
+ /**
599
+ * Returns an eth/64 compliant fork hash (EIP-2124)
600
+ * @param hardfork Hardfork name, optional if HF set
601
+ * @param genesisHash Genesis block hash of the network, optional if already defined and not needed to be calculated
602
+ * @returns Fork hash as a hex string
603
+ */
604
+ forkHash(hardfork, genesisHash) {
605
+ hardfork = hardfork ?? this._hardfork;
606
+ const data = this._getHardfork(hardfork);
607
+ if (data === null || (data?.block === null && data?.timestamp === undefined)) {
608
+ const msg = 'No fork hash calculation possible for future hardfork';
609
+ throw (0, util_1.EthereumJSErrorWithoutCode)(msg);
610
+ }
611
+ if (data?.forkHash !== null && data?.forkHash !== undefined) {
612
+ return data.forkHash;
613
+ }
614
+ if (!genesisHash)
615
+ throw (0, util_1.EthereumJSErrorWithoutCode)('genesisHash required for forkHash calculation');
616
+ return this._calcForkHash(hardfork, genesisHash);
617
+ }
618
+ /**
619
+ *
620
+ * @param forkHash Fork hash as a hex string
621
+ * @returns Array with hardfork data (name, block, forkHash)
622
+ */
623
+ hardforkForForkHash(forkHash) {
624
+ const resArray = this.hardforks().filter((hf) => {
625
+ return hf.forkHash === forkHash;
626
+ });
627
+ return resArray.length >= 1 ? resArray[resArray.length - 1] : null;
628
+ }
629
+ /**
630
+ * Sets any missing forkHashes on this {@link Common} instance.
631
+ * @param genesisHash The genesis block hash
632
+ */
633
+ setForkHashes(genesisHash) {
634
+ for (const hf of this.hardforks()) {
635
+ const blockOrTime = hf.timestamp ?? hf.block;
636
+ if ((hf.forkHash === null || hf.forkHash === undefined) &&
637
+ blockOrTime !== null &&
638
+ blockOrTime !== undefined) {
639
+ hf.forkHash = this.forkHash(hf.name, genesisHash);
640
+ }
641
+ }
642
+ }
643
+ /**
644
+ * Returns the Genesis parameters of the current chain
645
+ * @returns Genesis dictionary
646
+ */
647
+ genesis() {
648
+ return this._chainParams.genesis;
649
+ }
650
+ /**
651
+ * Returns the hardfork definitions for the current chain.
652
+ * @returns Array of hardfork transition configs
653
+ */
654
+ hardforks() {
655
+ const hfs = this._chainParams.hardforks;
656
+ if (this._chainParams.customHardforks !== undefined) {
657
+ // Add transition configs for custom hardforks that aren't already in the hardforks array
658
+ const existingNames = new Set(hfs.map((hf) => hf.name));
659
+ const customHfEntries = Object.keys(this._chainParams.customHardforks)
660
+ .filter((name) => !existingNames.has(name))
661
+ .map((name) => ({
662
+ name,
663
+ block: null, // Custom hardforks without explicit transition config default to null (inactive by block)
664
+ }));
665
+ return [...hfs, ...customHfEntries];
666
+ }
667
+ return hfs;
668
+ }
669
+ /**
670
+ * Returns bootstrap nodes for the current chain.
671
+ * @returns Array of bootstrap node configs
672
+ */
673
+ bootstrapNodes() {
674
+ return this._chainParams.bootstrapNodes;
675
+ }
676
+ /**
677
+ * Returns DNS networks for the current chain
678
+ * @returns {String[]} Array of DNS ENR urls
679
+ */
680
+ dnsNetworks() {
681
+ return this._chainParams.dnsNetworks;
682
+ }
683
+ /**
684
+ * Returns the hardfork set
685
+ * @returns Hardfork name
686
+ */
687
+ hardfork() {
688
+ return this._hardfork;
689
+ }
690
+ /**
691
+ * Returns the Id of current chain
692
+ * @returns chain Id
693
+ */
694
+ chainId() {
695
+ return BigInt(this._chainParams.chainId);
696
+ }
697
+ /**
698
+ * Returns the name of current chain
699
+ * @returns chain name (lower case)
700
+ */
701
+ chainName() {
702
+ return this._chainParams.name;
703
+ }
704
+ /**
705
+ * Returns the additionally activated EIPs
706
+ * (by using the `eips` constructor option)
707
+ * @returns List of EIPs
708
+ */
709
+ eips() {
710
+ return this._eips;
711
+ }
712
+ /**
713
+ * Returns the consensus type of the network
714
+ * Possible values: "pow"|"poa"|"pos"
715
+ *
716
+ * Note: This value can update along a Hardfork.
717
+ */
718
+ consensusType() {
719
+ const hardfork = this.hardfork();
720
+ let value;
721
+ for (const hfChanges of this.HARDFORK_CHANGES) {
722
+ if ('consensus' in hfChanges[1]) {
723
+ value = hfChanges[1]['consensus']['type'];
724
+ }
725
+ if (hfChanges[0] === hardfork)
726
+ break;
727
+ }
728
+ return value ?? this._chainParams['consensus']['type'];
729
+ }
730
+ /**
731
+ * Returns the concrete consensus implementation
732
+ * algorithm or protocol for the network
733
+ * e.g. "ethash" for "pow" consensus type,
734
+ * "clique" for "poa" consensus type or
735
+ * "casper" for "pos" consensus type.
736
+ *
737
+ * Note: This value can update along a Hardfork.
738
+ */
739
+ consensusAlgorithm() {
740
+ const hardfork = this.hardfork();
741
+ let value;
742
+ for (const hfChanges of this.HARDFORK_CHANGES) {
743
+ if ('consensus' in hfChanges[1]) {
744
+ value = hfChanges[1]['consensus']['algorithm'];
745
+ }
746
+ if (hfChanges[0] === hardfork)
747
+ break;
748
+ }
749
+ return value ?? this._chainParams['consensus']['algorithm'];
750
+ }
751
+ /**
752
+ * Returns a dictionary with consensus configuration
753
+ * parameters based on the consensus algorithm
754
+ *
755
+ * Expected returns (parameters must be present in
756
+ * the respective chain JSON files):
757
+ *
758
+ * ethash: empty object
759
+ * clique: period, epoch
760
+ * casper: empty object
761
+ *
762
+ * Note: This value can update along a Hardfork.
763
+ */
764
+ consensusConfig() {
765
+ const hardfork = this.hardfork();
766
+ let value;
767
+ for (const hfChanges of this.HARDFORK_CHANGES) {
768
+ if ('consensus' in hfChanges[1]) {
769
+ // The config parameter is named after the respective consensus algorithm
770
+ const config = hfChanges[1];
771
+ const algorithm = config['consensus']['algorithm'];
772
+ value = config['consensus'][algorithm];
773
+ }
774
+ if (hfChanges[0] === hardfork)
775
+ break;
776
+ }
777
+ return (value ?? this._chainParams['consensus'][this.consensusAlgorithm()] ?? {});
778
+ }
779
+ /**
780
+ * Returns a deep copy of this {@link Common} instance.
781
+ */
782
+ copy() {
783
+ const copy = Object.assign(Object.create(Object.getPrototypeOf(this)), this);
784
+ copy.events = new eventemitter3_1.EventEmitter();
785
+ return copy;
786
+ }
787
+ }
788
+ exports.Common = Common;
789
+ //# sourceMappingURL=common.js.map