-
-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathanvil.ts
294 lines (290 loc) · 7.59 KB
/
anvil.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
import { defineInstance } from '../instance.js'
import { execa } from '../processes/execa.js'
import { toArgs } from '../utils.js'
export type AnvilParameters = {
/**
* Number of dev accounts to generate and configure.
*
* @defaultValue 10
*/
accounts?: number | undefined
/**
* Set the Access-Control-Allow-Origin response header (CORS).
*
* @defaultValue *
*/
allowOrigin?: string | undefined
/**
* Enable autoImpersonate on startup
*/
autoImpersonate?: boolean | undefined
/**
* The balance of every dev account in Ether.
*
* @defaultValue 10000
*/
balance?: number | bigint | undefined
/**
* The base fee in a block.
*/
blockBaseFeePerGas?: number | bigint | undefined
/**
* Block time in seconds for interval mining.
*/
blockTime?: number | undefined
/**
* Path or alias to the Anvil binary.
*/
binary?: string | undefined
/**
* The chain id.
*/
chainId?: number | undefined
/**
* EIP-170: Contract code size limit in bytes. Useful to increase this because of tests.
*
* @defaultValue 0x6000 (~25kb)
*/
codeSizeLimit?: number | undefined
/**
* Sets the number of assumed available compute units per second for this fork provider.
*
* @defaultValue 350
* @see https://github.com/alchemyplatform/alchemy-docs/blob/master/documentation/compute-units.md#rate-limits-cups
*/
computeUnitsPerSecond?: number | undefined
/**
* Writes output of `anvil` as json to user-specified file.
*/
configOut?: string | undefined
/**
* Sets the derivation path of the child key to be derived.
*
* @defaultValue m/44'/60'/0'/0/
*/
derivationPath?: string | undefined
/**
* Disable the `call.gas_limit <= block.gas_limit` constraint.
*/
disableBlockGasLimit?: boolean | undefined
/**
* Dump the state of chain on exit to the given file. If the value is a directory, the state will be
* written to `<VALUE>/state.json`.
*/
dumpState?: string | undefined
/**
* Fetch state over a remote endpoint instead of starting from an empty state.
*
* If you want to fetch state from a specific block number, add a block number like `http://localhost:8545@1400000`
* or use the `forkBlockNumber` option.
*/
forkUrl?: string | undefined
/**
* Fetch state from a specific block number over a remote endpoint.
*
* Requires `forkUrl` to be set.
*/
forkBlockNumber?: number | bigint | undefined
/**
* Specify chain id to skip fetching it from remote endpoint. This enables offline-start mode.
*
* You still must pass both `forkUrl` and `forkBlockNumber`, and already have your required state cached
* on disk, anything missing locally would be fetched from the remote.
*/
forkChainId?: number | undefined
/**
* Specify headers to send along with any request to the remote JSON-RPC server in forking mode.
*
* e.g. "User-Agent: test-agent"
*
* Requires `forkUrl` to be set.
*/
forkHeader?: Record<string, string> | undefined
/**
* Initial retry backoff on encountering errors.
*/
forkRetryBackoff?: number | undefined
/**
* The block gas limit.
*/
gasLimit?: number | bigint | undefined
/**
* The gas price.
*/
gasPrice?: number | bigint | undefined
/**
* The EVM hardfork to use.
*/
hardfork?:
| 'Frontier'
| 'Homestead'
| 'Dao'
| 'Tangerine'
| 'SpuriousDragon'
| 'Byzantium'
| 'Constantinople'
| 'Petersburg'
| 'Istanbul'
| 'Muirglacier'
| 'Berlin'
| 'London'
| 'ArrowGlacier'
| 'GrayGlacier'
| 'Paris'
| 'Shanghai'
| 'Cancun'
| 'Latest'
| undefined
/**
* The host the server will listen on.
*/
host?: string | undefined
/**
* Initialize the genesis block with the given `genesis.json` file.
*/
init?: string | undefined
/**
* Launch an ipc server at the given path or default path = `/tmp/anvil.ipc`.
*/
ipc?: string | undefined
/**
* Initialize the chain from a previously saved state snapshot.
*/
loadState?: string | undefined
/**
* BIP39 mnemonic phrase used for generating accounts.
*/
mnemonic?: string | undefined
/**
* Automatically generates a BIP39 mnemonic phrase, and derives accounts from it.
*/
mnemonicRandom?: boolean | undefined
/**
* Disable CORS.
*/
noCors?: boolean | undefined
/**
* Disable auto and interval mining, and mine on demand instead.
*/
noMining?: boolean | undefined
/**
* Disables rate limiting for this node's provider.
*
* @defaultValue false
* @see https://github.com/alchemyplatform/alchemy-docs/blob/master/documentation/compute-units.md#rate-limits-cups
*/
noRateLimit?: boolean | undefined
/**
* Explicitly disables the use of RPC caching.
*
* All storage slots are read entirely from the endpoint.
*/
noStorageCaching?: boolean | undefined
/**
* How transactions are sorted in the mempool.
*
* @defaultValue fees
*/
order?: string | undefined
/**
* Run an Optimism chain.
*/
optimism?: boolean | undefined
/**
* Port number to listen on.
*
* @defaultValue 8545
*/
port?: number | undefined
/**
* Don't keep full chain history. If a number argument is specified, at most this number of states is kept in memory.
*/
pruneHistory?: number | undefined | boolean
/**
* Number of retry requests for spurious networks (timed out requests).
*
* @defaultValue 5
*/
retries?: number | undefined
/**
* Don't print anything on startup and don't print logs.
*/
silent?: boolean | undefined
/**
* Slots in an epoch.
*/
slotsInAnEpoch?: number | undefined
/**
* Enable steps tracing used for debug calls returning geth-style traces.
*/
stepsTracing?: boolean | undefined
/**
* Interval in seconds at which the status is to be dumped to disk.
*/
stateInterval?: number | undefined
/**
* This is an alias for both `loadState` and `dumpState`. It initializes the chain with the state stored at the
* file, if it exists, and dumps the chain's state on exit
*/
state?: string | undefined
/**
* Timeout in ms for requests sent to remote JSON-RPC server in forking mode.
*
* @defaultValue 45000
*/
timeout?: number | undefined
/**
* The timestamp of the genesis block.
*/
timestamp?: number | bigint | undefined
/**
* Number of blocks with transactions to keep in memory.
*/
transactionBlockKeeper?: number | undefined
}
/**
* Defines an Anvil instance.
*
* @example
* ```ts
* const instance = anvil({ forkRpcUrl: 'https://cloudflare-eth.com', port: 8546 })
* await instance.start()
* // ...
* await instance.stop()
* ```
*/
export const anvil = defineInstance((parameters?: AnvilParameters) => {
const { binary = 'anvil', ...args } = parameters || {}
const name = 'anvil'
const process = execa({ name })
return {
_internal: {
args,
get process() {
return process._internal.process
},
},
host: args.host ?? 'localhost',
name,
port: args.port ?? 8545,
async start({ port = args.port }, options) {
return await process.start(
($) => $`${binary} ${toArgs({ ...args, port })}`,
{
...options,
// Resolve when the process is listening via a "Listening on" message.
resolver({ process, reject, resolve }) {
process.stdout.on('data', (data) => {
const message = data.toString()
if (message.includes('Listening on')) resolve()
})
process.stderr.on('data', reject)
},
},
)
},
async stop() {
await process.stop()
},
}
})