@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
package/src/types.ts ADDED
@@ -0,0 +1,193 @@
1
+ import type { BigIntLike, KZG, PrefixedHexString } from '@feelyourprotocol/util'
2
+ import type { secp256k1 } from '@noble/curves/secp256k1.js'
3
+ import type { ConsensusAlgorithm, ConsensusType, Hardfork } from './enums.ts'
4
+
5
+ export interface ChainName {
6
+ [chainId: string]: string
7
+ }
8
+ export interface ChainsConfig {
9
+ [key: string]: ChainConfig | ChainName
10
+ }
11
+
12
+ export interface CommonEvent {
13
+ hardforkChanged: [hardfork: string]
14
+ }
15
+
16
+ export type CliqueConfig = {
17
+ period: number
18
+ epoch: number
19
+ }
20
+
21
+ export type EthashConfig = {}
22
+
23
+ export type CasperConfig = {}
24
+
25
+ type ConsensusConfig = {
26
+ type: ConsensusType | string
27
+ algorithm: ConsensusAlgorithm | string
28
+ clique?: CliqueConfig
29
+ ethash?: EthashConfig
30
+ casper?: CasperConfig
31
+ }
32
+
33
+ export interface ChainConfig {
34
+ name: string
35
+ chainId: number | string
36
+ defaultHardfork?: string
37
+ comment?: string
38
+ url?: string
39
+ genesis: GenesisBlockConfig
40
+ hardforks: HardforkTransitionConfig[]
41
+ customHardforks?: HardforksDict
42
+ bootstrapNodes: BootstrapNodeConfig[]
43
+ dnsNetworks?: string[]
44
+ consensus: ConsensusConfig
45
+ depositContractAddress?: PrefixedHexString
46
+ }
47
+
48
+ export interface GenesisBlockConfig {
49
+ timestamp?: PrefixedHexString
50
+ gasLimit: number | PrefixedHexString
51
+ difficulty: number | PrefixedHexString
52
+ nonce: PrefixedHexString
53
+ extraData: PrefixedHexString
54
+ baseFeePerGas?: PrefixedHexString
55
+ excessBlobGas?: PrefixedHexString
56
+ requestsHash?: PrefixedHexString
57
+ }
58
+
59
+ export interface HardforkTransitionConfig {
60
+ name: Hardfork | string
61
+ block: number | null // null is used for hardforks that should not be applied -- since `undefined` isn't a valid value in JSON
62
+ timestamp?: number | string
63
+ forkHash?: PrefixedHexString | null
64
+ }
65
+
66
+ export interface BootstrapNodeConfig {
67
+ ip: string
68
+ port: number | string
69
+ network?: string
70
+ chainId?: number
71
+ id: string
72
+ location: string
73
+ comment: string
74
+ }
75
+
76
+ export interface CustomCrypto {
77
+ /**
78
+ * Interface for providing custom cryptographic primitives in place of `ethereum-cryptography` variants
79
+ */
80
+ keccak256?: (msg: Uint8Array) => Uint8Array
81
+ ecrecover?: (
82
+ msgHash: Uint8Array,
83
+ v: bigint,
84
+ r: Uint8Array,
85
+ s: Uint8Array,
86
+ chainId?: bigint,
87
+ ) => Uint8Array
88
+ sha256?: (msg: Uint8Array) => Uint8Array
89
+ ecsign?: typeof secp256k1.sign
90
+ ecdsaRecover?: (sig: Uint8Array, recId: number, hash: Uint8Array) => Uint8Array
91
+ kzg?: KZG
92
+ }
93
+
94
+ export interface BaseOpts {
95
+ /**
96
+ * String identifier ('byzantium') for hardfork or {@link Hardfork} enum.
97
+ *
98
+ * Default: Hardfork.London
99
+ */
100
+ hardfork?: string | Hardfork
101
+ /**
102
+ * Selected EIPs which can be activated, please use an array for instantiation
103
+ * (e.g. `eips: [ 2537, ]`)
104
+ *
105
+ * Currently supported:
106
+ *
107
+ * - [EIP-2537](https://eips.ethereum.org/EIPS/eip-2537) - BLS12-381 precompiles
108
+ */
109
+ eips?: number[]
110
+ /**
111
+ * Optionally pass in an EIP params dictionary, see one of the
112
+ * EthereumJS library `params.ts` files for an example (e.g. tx, evm).
113
+ * By default parameters are set by the respective library, so this
114
+ * is only relevant if you want to use EthereumJS libraries with a
115
+ * custom parameter set.
116
+ *
117
+ * Example Format:
118
+ *
119
+ * ```ts
120
+ * {
121
+ * 1559: {
122
+ * initialBaseFee: 1000000000,
123
+ * }
124
+ * }
125
+ * ```
126
+ */
127
+ params?: ParamsDict
128
+ /**
129
+ * This option can be used to replace the most common crypto primitives
130
+ * (keccak256 hashing e.g.) within the EthereumJS ecosystem libraries
131
+ * with alternative implementations (e.g. more performant WASM libraries).
132
+ *
133
+ * Note: please be aware that this is adding new dependencies for your
134
+ * system setup to be used for sensitive/core parts of the functionality
135
+ * and a choice on the libraries to add should be handled with care
136
+ * and be made with eventual security implications considered.
137
+ */
138
+ customCrypto?: CustomCrypto
139
+ }
140
+
141
+ /**
142
+ * Options for instantiating a {@link Common} instance.
143
+ */
144
+ export interface CommonOpts extends BaseOpts {
145
+ /**
146
+ * The chain configuration to be used. There are available configuration object for mainnet
147
+ * (`Mainnet`) and the currently active testnets which can be directly used.
148
+ */
149
+ chain: ChainConfig
150
+ }
151
+
152
+ export interface GethConfigOpts extends BaseOpts {
153
+ chain?: string
154
+ genesisHash?: Uint8Array
155
+ }
156
+
157
+ export interface HardforkByOpts {
158
+ blockNumber?: BigIntLike
159
+ timestamp?: BigIntLike
160
+ }
161
+
162
+ export type EIPConfig = {
163
+ minimumHardfork: Hardfork
164
+ requiredEIPs?: number[]
165
+ }
166
+
167
+ export type ParamsConfig = {
168
+ [key: string]: number | string | null
169
+ }
170
+
171
+ export type HardforkConfig = {
172
+ eips?: number[]
173
+ consensus?: ConsensusConfig
174
+ params?: ParamsConfig
175
+ }
176
+
177
+ export type EIPsDict = {
178
+ [key: string]: EIPConfig
179
+ }
180
+
181
+ export type ParamsDict = {
182
+ [key: string]: ParamsConfig
183
+ }
184
+
185
+ export type HardforksDict = {
186
+ [key: string]: HardforkConfig
187
+ }
188
+
189
+ export type BpoSchedule = {
190
+ targetBlobGasPerBlock: bigint
191
+ maxBlobGasPerBlock: bigint
192
+ blobGasPriceUpdateFraction: bigint
193
+ }
package/src/utils.ts ADDED
@@ -0,0 +1,324 @@
1
+ import {
2
+ EthereumJSErrorWithoutCode,
3
+ addHexPrefix,
4
+ intToHex,
5
+ isHexString,
6
+ stripHexPrefix,
7
+ } from '@feelyourprotocol/util'
8
+
9
+ import { Holesky, Hoodi, Mainnet, Sepolia } from './chains.ts'
10
+ import { Hardfork } from './enums.ts'
11
+ import { hardforksDict } from './hardforks.ts'
12
+
13
+ import type { PrefixedHexString } from '@feelyourprotocol/util'
14
+ import type { GethGenesis } from './gethGenesis.ts'
15
+ import type { HardforksDict } from './types.ts'
16
+
17
+ type ConfigHardfork =
18
+ | { name: string; block: null; timestamp: number }
19
+ | { name: string; block: number; timestamp?: number }
20
+ /**
21
+ * Transforms Geth formatted nonce (i.e. hex string) to 8 byte 0x-prefixed string used internally
22
+ * @param nonce string parsed from the Geth genesis file
23
+ * @returns nonce as a 0x-prefixed 8 byte string
24
+ */
25
+ function formatNonce(nonce: string): PrefixedHexString {
26
+ if (!nonce || nonce === '0x0') {
27
+ return '0x0000000000000000'
28
+ }
29
+ if (isHexString(nonce)) {
30
+ return `0x${stripHexPrefix(nonce).padStart(16, '0')}`
31
+ }
32
+ return `0x${nonce.padStart(16, '0')}`
33
+ }
34
+
35
+ /**
36
+ * Converts Geth genesis parameters to an EthereumJS compatible `CommonOpts` object
37
+ * @param gethGenesis GethGenesis object
38
+ * @returns genesis parameters in a `CommonOpts` compliant object
39
+ */
40
+ function parseGethParams(gethGenesis: GethGenesis) {
41
+ const {
42
+ name,
43
+ config,
44
+ difficulty,
45
+ mixHash,
46
+ gasLimit,
47
+ coinbase,
48
+ baseFeePerGas,
49
+ excessBlobGas,
50
+ requestsHash,
51
+ extraData: unparsedExtraData,
52
+ nonce: unparsedNonce,
53
+ timestamp: unparsedTimestamp,
54
+ } = gethGenesis
55
+ const genesisTimestamp = Number(unparsedTimestamp)
56
+ const { chainId, depositContractAddress } = config
57
+
58
+ // geth is not strictly putting empty fields with a 0x prefix
59
+ const extraData = addHexPrefix(unparsedExtraData ?? '')
60
+
61
+ // geth may use number for timestamp
62
+ const timestamp: PrefixedHexString = isHexString(unparsedTimestamp)
63
+ ? unparsedTimestamp
64
+ : intToHex(parseInt(unparsedTimestamp))
65
+
66
+ // geth may not give us a nonce strictly formatted to an 8 byte 0x-prefixed hex string
67
+ const nonce =
68
+ unparsedNonce.length !== 18 ? formatNonce(unparsedNonce) : addHexPrefix(unparsedNonce)
69
+
70
+ // EIP155 and EIP158 are both part of Spurious Dragon hardfork and must occur at the same time
71
+ // but have different configuration parameters in geth genesis parameters
72
+ if (config.eip155Block !== config.eip158Block) {
73
+ throw EthereumJSErrorWithoutCode(
74
+ 'EIP155 block number must equal EIP 158 block number since both are part of SpuriousDragon hardfork and the client only supports activating the full hardfork',
75
+ )
76
+ }
77
+
78
+ let customHardforks: HardforksDict | undefined = undefined
79
+ if (config.blobSchedule !== undefined) {
80
+ customHardforks = {}
81
+ const blobGasPerBlob = 131072
82
+ for (const [hfKey, hfSchedule] of Object.entries(config.blobSchedule)) {
83
+ const hfConfig = hardforksDict[hfKey]
84
+ if (hfConfig === undefined) {
85
+ throw EthereumJSErrorWithoutCode(`unknown hardfork=${hfKey} specified in blobSchedule`)
86
+ }
87
+ const { target, max, baseFeeUpdateFraction: blobGasPriceUpdateFraction } = hfSchedule
88
+ if (target === undefined || max === undefined || blobGasPriceUpdateFraction === undefined) {
89
+ throw EthereumJSErrorWithoutCode(
90
+ `undefined target, max or baseFeeUpdateFraction specified in blobSchedule for hardfork=${hfKey}`,
91
+ )
92
+ }
93
+
94
+ // copy current hardfork info to custom and add blob config
95
+ const customHfConfig = JSON.parse(JSON.stringify(hfConfig))
96
+ customHfConfig.params = {
97
+ ...customHardforks.params,
98
+ // removes blobGasPriceUpdateFraction key to prevent undefined overriding if undefined
99
+ ...{
100
+ targetBlobGasPerBlock: blobGasPerBlob * target,
101
+ maxBlobGasPerBlock: blobGasPerBlob * max,
102
+ blobGasPriceUpdateFraction,
103
+ },
104
+ }
105
+
106
+ customHardforks[hfKey] = customHfConfig
107
+ }
108
+ }
109
+
110
+ const params = {
111
+ name,
112
+ chainId,
113
+ depositContractAddress,
114
+ genesis: {
115
+ timestamp,
116
+ gasLimit,
117
+ difficulty,
118
+ nonce,
119
+ extraData,
120
+ mixHash,
121
+ coinbase,
122
+ baseFeePerGas,
123
+ excessBlobGas,
124
+ requestsHash,
125
+ },
126
+ hardfork: undefined as string | undefined,
127
+ hardforks: [] as ConfigHardfork[],
128
+ customHardforks,
129
+ bootstrapNodes: [],
130
+ consensus:
131
+ config.clique !== undefined
132
+ ? {
133
+ type: 'poa',
134
+ algorithm: 'clique',
135
+ clique: {
136
+ // The recent geth genesis seems to be using blockperiodseconds // cspell:disable-line
137
+ // and epochlength for clique specification
138
+ // see: https://hackmd.io/PqZgMpnkSWCWv5joJoFymQ
139
+ period: config.clique.period ?? config.clique.blockperiodseconds, // cspell:disable-line
140
+ epoch: config.clique.epoch ?? config.clique.epochlength,
141
+ },
142
+ }
143
+ : {
144
+ type: 'pow',
145
+ algorithm: 'ethash',
146
+ ethash: {},
147
+ },
148
+ }
149
+
150
+ const forkMap: { [key: string]: { name: string; postMerge?: boolean; isTimestamp?: boolean } } = {
151
+ [Hardfork.Homestead]: { name: 'homesteadBlock' },
152
+ [Hardfork.Dao]: { name: 'daoForkBlock' },
153
+ [Hardfork.TangerineWhistle]: { name: 'eip150Block' },
154
+ [Hardfork.SpuriousDragon]: { name: 'eip155Block' },
155
+ [Hardfork.Byzantium]: { name: 'byzantiumBlock' },
156
+ [Hardfork.Constantinople]: { name: 'constantinopleBlock' },
157
+ [Hardfork.Petersburg]: { name: 'petersburgBlock' },
158
+ [Hardfork.Istanbul]: { name: 'istanbulBlock' },
159
+ [Hardfork.MuirGlacier]: { name: 'muirGlacierBlock' },
160
+ [Hardfork.Berlin]: { name: 'berlinBlock' },
161
+ [Hardfork.London]: { name: 'londonBlock' },
162
+ [Hardfork.ArrowGlacier]: { name: 'arrowGlacierBlock' },
163
+ [Hardfork.GrayGlacier]: { name: 'grayGlacierBlock' },
164
+ [Hardfork.Paris]: { name: 'mergeForkBlock', postMerge: true },
165
+ [Hardfork.MergeNetsplitBlock]: { name: 'mergeNetsplitBlock', postMerge: true },
166
+ [Hardfork.Shanghai]: { name: 'shanghaiTime', postMerge: true, isTimestamp: true },
167
+ [Hardfork.Cancun]: { name: 'cancunTime', postMerge: true, isTimestamp: true },
168
+ [Hardfork.Prague]: { name: 'pragueTime', postMerge: true, isTimestamp: true },
169
+ [Hardfork.Osaka]: { name: 'osakaTime', postMerge: true, isTimestamp: true },
170
+ [Hardfork.Bpo1]: { name: 'bpo1Time', postMerge: true, isTimestamp: true },
171
+ [Hardfork.Bpo2]: { name: 'bpo2Time', postMerge: true, isTimestamp: true },
172
+ [Hardfork.Bpo3]: { name: 'bpo3Time', postMerge: true, isTimestamp: true },
173
+ [Hardfork.Bpo4]: { name: 'bpo4Time', postMerge: true, isTimestamp: true },
174
+ [Hardfork.Bpo5]: { name: 'bpo5Time', postMerge: true, isTimestamp: true },
175
+ }
176
+
177
+ // forkMapRev is the map from config field name to Hardfork
178
+ const forkMapRev = Object.keys(forkMap).reduce(
179
+ (acc, elem) => {
180
+ acc[forkMap[elem].name] = elem
181
+ return acc
182
+ },
183
+ {} as { [key: string]: string },
184
+ )
185
+
186
+ params.hardforks = Object.entries(forkMapRev)
187
+ .map(([nameBlock, hardfork]) => {
188
+ const configValue = config[nameBlock as keyof typeof config]
189
+ const isTimestamp = forkMap[hardfork].isTimestamp === true
190
+
191
+ const block = isTimestamp || typeof configValue !== 'number' ? null : configValue
192
+
193
+ const timestamp = isTimestamp && typeof configValue === 'number' ? configValue : undefined
194
+
195
+ return { name: hardfork, block, timestamp }
196
+ })
197
+ .filter(({ block, timestamp }) => block !== null || timestamp !== undefined) as ConfigHardfork[]
198
+
199
+ const mergeIndex = params.hardforks.findIndex((hf) => hf.name === Hardfork.Paris)
200
+ let mergeNetsplitBlockIndex = params.hardforks.findIndex(
201
+ (hf) => hf.name === Hardfork.MergeNetsplitBlock,
202
+ )
203
+ const firstPostMergeHFIndex = params.hardforks.findIndex(
204
+ (hf) => hf.timestamp !== undefined && hf.timestamp !== null,
205
+ )
206
+
207
+ // If we are missing a mergeNetsplitBlock, we assume it is at the same block as Paris (if present)
208
+ if (mergeIndex !== -1 && mergeNetsplitBlockIndex === -1) {
209
+ params.hardforks.splice(mergeIndex + 1, 0, {
210
+ name: Hardfork.MergeNetsplitBlock,
211
+ block: params.hardforks[mergeIndex].block!,
212
+ })
213
+ mergeNetsplitBlockIndex = mergeIndex + 1
214
+ }
215
+ // or zero if not and a postmerge hardfork is set (since testnets using the geth genesis format are all currently start postmerge)
216
+ if (firstPostMergeHFIndex !== -1) {
217
+ if (mergeNetsplitBlockIndex === -1) {
218
+ params.hardforks.splice(firstPostMergeHFIndex, 0, {
219
+ name: Hardfork.MergeNetsplitBlock,
220
+ block: 0,
221
+ })
222
+ mergeNetsplitBlockIndex = firstPostMergeHFIndex
223
+ }
224
+ if (mergeIndex === -1) {
225
+ // If we don't have a Paris hardfork, add it at the mergeNetsplitBlock
226
+ params.hardforks.splice(mergeNetsplitBlockIndex, 0, {
227
+ name: Hardfork.Paris,
228
+ block: params.hardforks[mergeNetsplitBlockIndex].block!,
229
+ })
230
+ }
231
+ // Check for terminalTotalDifficultyPassed param in genesis config if no post merge hardforks are set
232
+ } else if (config.terminalTotalDifficultyPassed === true) {
233
+ if (mergeIndex === -1) {
234
+ // If we don't have a Paris hardfork, add it at end of hardfork array
235
+ params.hardforks.push({
236
+ name: Hardfork.Paris,
237
+ block: 0,
238
+ })
239
+ }
240
+ // If we don't have a MergeNetsplitBlock hardfork, add it at end of hardfork array
241
+ if (mergeNetsplitBlockIndex === -1) {
242
+ params.hardforks.push({
243
+ name: Hardfork.MergeNetsplitBlock,
244
+ block: 0,
245
+ })
246
+ mergeNetsplitBlockIndex = firstPostMergeHFIndex
247
+ }
248
+ }
249
+
250
+ // TODO: Decide if we actually need to do this since `ForkMap` specifies the order we expect things in
251
+ params.hardforks.sort(function (a: ConfigHardfork, b: ConfigHardfork) {
252
+ return (a.block ?? Infinity) - (b.block ?? Infinity)
253
+ })
254
+
255
+ params.hardforks.sort(function (a: ConfigHardfork, b: ConfigHardfork) {
256
+ // non timestamp forks come before any timestamp forks
257
+ return (a.timestamp ?? 0) - (b.timestamp ?? 0)
258
+ })
259
+
260
+ // only set the genesis timestamp forks to zero post the above sort has happened
261
+ // to get the correct sorting
262
+ for (const hf of params.hardforks) {
263
+ if (hf.timestamp === genesisTimestamp) {
264
+ hf.timestamp = 0
265
+ }
266
+ }
267
+
268
+ const latestHardfork = params.hardforks.length > 0 ? params.hardforks.slice(-1)[0] : undefined
269
+ params.hardfork = latestHardfork?.name
270
+ params.hardforks.unshift({ name: Hardfork.Chainstart, block: 0 })
271
+
272
+ return params
273
+ }
274
+
275
+ /**
276
+ * Parses a genesis object exported from Geth into parameters for Common instance
277
+ * @param gethGenesis GethGenesis object
278
+ * @param name optional chain name
279
+ * @returns parsed params
280
+ */
281
+ export function parseGethGenesis(gethGenesis: GethGenesis, name?: string) {
282
+ try {
283
+ const required = ['config', 'difficulty', 'gasLimit', 'nonce', 'alloc']
284
+ if (required.some((field) => !(field in gethGenesis))) {
285
+ const missingField = required.filter((field) => !(field in gethGenesis))
286
+ throw EthereumJSErrorWithoutCode(
287
+ `Invalid format, expected geth genesis field "${missingField}" missing`,
288
+ )
289
+ }
290
+
291
+ // We copy the object here because it's frozen in browser and properties can't be modified
292
+ const finalGethGenesis = { ...gethGenesis }
293
+
294
+ if (name !== undefined) {
295
+ finalGethGenesis.name = name
296
+ }
297
+ return parseGethParams(finalGethGenesis)
298
+ } catch (e: any) {
299
+ throw EthereumJSErrorWithoutCode(`Error parsing parameters file: ${e.message}`)
300
+ }
301
+ }
302
+
303
+ /**
304
+ * Return the preset chain config for one of the predefined chain configurations
305
+ * @param chain the representing a network name (e.g. 'mainnet') or number representing the chain ID
306
+ * @returns a {@link ChainConfig}
307
+ */
308
+ export const getPresetChainConfig = (chain: string | number) => {
309
+ switch (chain) {
310
+ case 'holesky':
311
+ case 17000:
312
+ return Holesky
313
+ case 'hoodi':
314
+ case 560048:
315
+ return Hoodi
316
+ case 'sepolia':
317
+ case 11155111:
318
+ return Sepolia
319
+ case 'mainnet':
320
+ case 1:
321
+ default:
322
+ return Mainnet
323
+ }
324
+ }