rocketh 0.17.13 → 0.17.15

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.
@@ -0,0 +1,540 @@
1
+ import {EIP1193ProviderWithoutEvents} from 'eip-1193';
2
+
3
+ import type {
4
+ Environment,
5
+ ExecutionParams,
6
+ ResolvedExecutionParams,
7
+ UnknownDeployments,
8
+ UnresolvedNetworkSpecificData,
9
+ UnresolvedUnknownNamedAccounts,
10
+ DeployScriptModule,
11
+ EnhancedDeployScriptFunction,
12
+ EnhancedEnvironment,
13
+ ResolvedUserConfig,
14
+ ConfigOverrides,
15
+ UserConfig,
16
+ PromptExecutor,
17
+ DeploymentStore,
18
+ ModuleObject,
19
+ } from '@rocketh/core/types';
20
+ import {withEnvironment} from '@rocketh/core/environment';
21
+ import {
22
+ getChainConfigFromUserConfigAndDefaultChainInfo,
23
+ getDefaultChainInfoByName,
24
+ getDefaultChainInfoFromChainId,
25
+ } from '../environment/chains.js';
26
+ import {JSONRPCHTTPProvider} from 'eip-1193-jsonrpc-provider';
27
+ import {createEnvironment} from '../environment/index.js';
28
+ import {getRoughGasPriceEstimate} from '../utils/eth.js';
29
+ import {formatEther} from 'viem';
30
+ import {logger, spin} from '../internal/logging.js';
31
+
32
+ /**
33
+ * Setup function that creates the execute function for deploy scripts. It allow to specify a set of functions that will be available in the environment.
34
+ *
35
+ * @param functions - An object of utility functions that expect Environment as their first parameter
36
+ * @returns An execute function that provides an enhanced environment with curried functions
37
+ *
38
+ * @example
39
+ * ```typescript
40
+ * const functions = {
41
+ * deploy: (env: Environment) => ((contractName: string, args: any[]) => Promise<void>),
42
+ * verify: (env: Environment) => ((address: string) => Promise<boolean>)
43
+ * };
44
+ *
45
+ * const {deployScript} = setup(functions);
46
+ *
47
+ * export default deployScript(async (env, args) => {
48
+ * // env now includes both the original environment AND the curried functions
49
+ * await env.deploy('MyContract', []); // No need to pass env
50
+ * await env.verify('0x123...'); // No need to pass env
51
+ *
52
+ * // Original environment properties are still available
53
+ * console.log(env.network.name);
54
+ * const deployment = env.get('MyContract');
55
+ * }, { tags: ['deploy'] });
56
+ * ```
57
+ */
58
+ export function setupDeployScripts<
59
+ Extensions extends Record<string, (env: Environment<any, any, any>) => any> = {},
60
+ NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
61
+ Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
62
+ Deployments extends UnknownDeployments = UnknownDeployments,
63
+ Extra extends Record<string, unknown> = Record<string, unknown>,
64
+ >(
65
+ extensions: Extensions,
66
+ ): {
67
+ deployScript<ArgumentsType = undefined>(
68
+ callback: EnhancedDeployScriptFunction<NamedAccounts, Data, ArgumentsType, Deployments, Extensions>,
69
+ options: {tags?: string[]; dependencies?: string[]; id?: string; runAtTheEnd?: boolean},
70
+ ): DeployScriptModule<NamedAccounts, Data, ArgumentsType, Deployments, Extra>;
71
+ } {
72
+ function enhancedExecute<ArgumentsType = undefined>(
73
+ callback: EnhancedDeployScriptFunction<NamedAccounts, Data, ArgumentsType, Deployments, Extensions>,
74
+ options: {tags?: string[]; dependencies?: string[]; id?: string; runAtTheEnd?: boolean},
75
+ ): DeployScriptModule<NamedAccounts, Data, ArgumentsType, Deployments, Extra> {
76
+ const scriptModule: DeployScriptModule<NamedAccounts, Data, ArgumentsType, Deployments, Extra> = (
77
+ env: Environment<NamedAccounts, Data, Deployments, Extra>,
78
+ args?: ArgumentsType,
79
+ ) => {
80
+ // Create the enhanced environment by combining the original environment with extensions
81
+ const curriedFunctions = withEnvironment(env, extensions);
82
+ const enhancedEnv = Object.assign(
83
+ Object.create(Object.getPrototypeOf(env)),
84
+ env,
85
+ curriedFunctions,
86
+ ) as EnhancedEnvironment<NamedAccounts, Data, Deployments, Extensions, Extra>;
87
+
88
+ return callback(enhancedEnv, args);
89
+ };
90
+
91
+ scriptModule.tags = options.tags;
92
+ scriptModule.dependencies = options.dependencies;
93
+ scriptModule.id = options.id;
94
+ scriptModule.runAtTheEnd = options.runAtTheEnd;
95
+
96
+ return scriptModule;
97
+ }
98
+
99
+ return {
100
+ deployScript: enhancedExecute,
101
+ };
102
+ }
103
+
104
+ export function resolveConfig<
105
+ NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
106
+ Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
107
+ >(configFile: UserConfig, overrides?: ConfigOverrides): ResolvedUserConfig<NamedAccounts, Data> {
108
+ const config = {
109
+ deployments: 'deployments',
110
+ defaultPollingInterval: 1,
111
+ ...configFile,
112
+ scripts: configFile?.scripts
113
+ ? typeof configFile.scripts === 'string'
114
+ ? [configFile.scripts]
115
+ : configFile.scripts.length == 0
116
+ ? ['deploy']
117
+ : configFile.scripts
118
+ : ['deploy'],
119
+ };
120
+
121
+ if (overrides) {
122
+ for (const key of Object.keys(overrides)) {
123
+ if ((overrides as any)[key] !== undefined) {
124
+ (config as any)[key] = (overrides as any)[key];
125
+ }
126
+ }
127
+ }
128
+
129
+ return config;
130
+ }
131
+
132
+ export async function getChainIdForEnvironment(
133
+ config: ResolvedUserConfig,
134
+ environmentName: string,
135
+ provider?: EIP1193ProviderWithoutEvents,
136
+ ) {
137
+ let chainId: number;
138
+ const chainIdFromProvider = provider ? Number(await provider.request({method: 'eth_chainId'})) : undefined;
139
+ if (config?.environments?.[environmentName]?.chain) {
140
+ const chainAsNumber =
141
+ typeof config.environments[environmentName].chain === 'number'
142
+ ? config.environments[environmentName].chain
143
+ : parseInt(config.environments[environmentName].chain);
144
+ if (!isNaN(chainAsNumber)) {
145
+ chainId = chainAsNumber;
146
+ } else {
147
+ const chainFound = getDefaultChainInfoByName(config.environments[environmentName].chain as string);
148
+ if (chainFound) {
149
+ chainId = chainFound.id;
150
+ } else {
151
+ throw new Error(`environment ${environmentName} chain id cannot be found, specify it in the rocketh config`);
152
+ }
153
+ }
154
+ } else {
155
+ const chainFound = getDefaultChainInfoByName(environmentName);
156
+ if (chainFound) {
157
+ chainId = chainFound.id;
158
+ } else {
159
+ if (chainIdFromProvider) {
160
+ chainId = chainIdFromProvider;
161
+ } else {
162
+ throw new Error(`environment ${environmentName} chain id cannot be found, specify it in the rocketh config`);
163
+ }
164
+ }
165
+ }
166
+ if (chainIdFromProvider && chainIdFromProvider != chainId) {
167
+ console.warn(
168
+ `provider give a different chainId (${chainIdFromProvider}) than the one expected for environment named "${environmentName}" (${chainId})`,
169
+ );
170
+ }
171
+ return chainIdFromProvider || chainId;
172
+ }
173
+
174
+ export function getEnvironmentName(executionParams: ExecutionParams): {name: string; fork: boolean} {
175
+ const environmentProvided = executionParams.environment || (executionParams as any).network;
176
+ let environmentName = 'memory';
177
+ if (environmentProvided) {
178
+ if (typeof environmentProvided === 'string') {
179
+ environmentName = environmentProvided;
180
+ } else if ('fork' in environmentProvided) {
181
+ environmentName = environmentProvided.fork;
182
+ }
183
+ }
184
+ const fork = typeof environmentProvided !== 'string';
185
+ return {name: environmentName, fork};
186
+ }
187
+
188
+ export function resolveExecutionParams<Extra extends Record<string, unknown> = Record<string, unknown>>(
189
+ config: ResolvedUserConfig,
190
+ executionParameters: ExecutionParams<Extra>,
191
+ chainId: number,
192
+ ): ResolvedExecutionParams<Extra> {
193
+ const {name: environmentName, fork} = getEnvironmentName(executionParameters);
194
+
195
+ // TODO fork chainId resolution option to keep the network being used
196
+ const idToFetch = fork ? 31337 : chainId;
197
+ let chainInfoFound = getDefaultChainInfoByName(environmentName);
198
+ if (!chainInfoFound) {
199
+ const result = getDefaultChainInfoFromChainId(idToFetch);
200
+ chainInfoFound = result.success ? result.chainInfo : undefined;
201
+ if (!result.success && result.error) {
202
+ // logger.warn(`could not find chainInfo by name = "${environmentName}"\n ${result.error}`);
203
+ }
204
+ if (!chainInfoFound) {
205
+ // console.log(`could not find chainInfo by chainId = "${idToFetch}"`);
206
+ }
207
+ }
208
+
209
+ const defaultChainInfo = chainInfoFound;
210
+ const chainConfig = getChainConfigFromUserConfigAndDefaultChainInfo(config, {
211
+ id: idToFetch,
212
+ chainInfo: defaultChainInfo,
213
+ canonicalName: environmentName,
214
+ doNotRequireRpcURL: !!executionParameters.provider,
215
+ });
216
+
217
+ let chainInfo = chainConfig.info;
218
+ const environmentConfig = config?.environments?.[environmentName];
219
+ const actualChainConfig = environmentConfig?.overrides
220
+ ? {
221
+ ...chainConfig,
222
+ ...environmentConfig.overrides,
223
+ properties: {
224
+ ...chainConfig?.properties,
225
+ ...environmentConfig.overrides.properties,
226
+ },
227
+ }
228
+ : chainConfig;
229
+
230
+ if (actualChainConfig?.properties) {
231
+ chainInfo = {...chainInfo, properties: actualChainConfig.properties};
232
+ }
233
+
234
+ // let environmentTags: string[] = actualChainConfig.tags.concat(environmentConfig?.tags); // TODO
235
+ const environmentTags = actualChainConfig.tags;
236
+
237
+ let scripts = ['deploy'];
238
+ if (config.scripts) {
239
+ if (typeof config.scripts === 'string') {
240
+ scripts = [config.scripts];
241
+ } else {
242
+ scripts = [...config.scripts];
243
+ }
244
+ }
245
+
246
+ if (environmentConfig?.scripts) {
247
+ if (typeof environmentConfig.scripts === 'string') {
248
+ scripts = [environmentConfig.scripts];
249
+ } else {
250
+ scripts = [...environmentConfig.scripts];
251
+ }
252
+ }
253
+
254
+ // here we force type actualChainConfig.rpcUrl! as string
255
+ // as if provider was not available
256
+ // getChainConfigFromUserConfigAndDefaultChainInfo would throw
257
+ const provider =
258
+ executionParameters.provider ||
259
+ (new JSONRPCHTTPProvider(actualChainConfig.rpcUrl!) as EIP1193ProviderWithoutEvents);
260
+
261
+ let saveDeployments = executionParameters.saveDeployments;
262
+
263
+ if (saveDeployments === undefined) {
264
+ if (!executionParameters.provider) {
265
+ saveDeployments = true;
266
+ } else {
267
+ if (environmentName === 'memory' || environmentName === 'hardhat' || environmentName === 'default') {
268
+ // networkTags['memory'] = true;
269
+ saveDeployments = false;
270
+ } else {
271
+ saveDeployments = true;
272
+ }
273
+ }
274
+ }
275
+
276
+ return {
277
+ askBeforeProceeding: executionParameters.askBeforeProceeding || false,
278
+ chain: chainInfo,
279
+ pollingInterval: actualChainConfig.pollingInterval,
280
+ reportGasUse: executionParameters.reportGasUse || false,
281
+ saveDeployments,
282
+ tags: executionParameters.tags || [],
283
+ environment: {
284
+ name: environmentName,
285
+ tags: environmentTags,
286
+ fork,
287
+ deterministicDeployment: actualChainConfig.deterministicDeployment,
288
+ },
289
+ extra: executionParameters.extra,
290
+ provider,
291
+ scripts,
292
+ };
293
+ }
294
+
295
+ export async function loadEnvironment<
296
+ NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
297
+ Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
298
+ Extra extends Record<string, unknown> = Record<string, unknown>,
299
+ >(
300
+ config: UserConfig<NamedAccounts, Data>,
301
+ executionParams: ExecutionParams<Extra>,
302
+ deploymentStore: DeploymentStore,
303
+ ): Promise<Environment<NamedAccounts, Data, UnknownDeployments>> {
304
+ const userConfig = resolveConfig<NamedAccounts, Data>(config, executionParams.config);
305
+ const {name: environmentName, fork} = getEnvironmentName(executionParams);
306
+ const chainId = await getChainIdForEnvironment(userConfig, environmentName, executionParams.provider);
307
+ const resolvedExecutionParams = resolveExecutionParams(userConfig, executionParams, chainId);
308
+ // console.log(JSON.stringify(resolvedConfig, null, 2));
309
+ const {external, internal} = await createEnvironment<NamedAccounts, Data, UnknownDeployments>(
310
+ userConfig,
311
+ resolvedExecutionParams,
312
+ deploymentStore,
313
+ );
314
+ return external;
315
+ }
316
+
317
+ export function createExecutor(deploymentStore: DeploymentStore, promptExecutor: PromptExecutor) {
318
+ async function resolveConfigAndExecuteDeployScriptModules<
319
+ NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
320
+ Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
321
+ ArgumentsType = undefined,
322
+ Extra extends Record<string, unknown> = Record<string, unknown>,
323
+ >(
324
+ moduleObjects: ModuleObject<NamedAccounts, Data, ArgumentsType>[],
325
+ userConfig: UserConfig,
326
+ executionParams?: ExecutionParams<Extra>,
327
+ args?: ArgumentsType,
328
+ ): Promise<Environment<NamedAccounts, Data, UnknownDeployments>> {
329
+ executionParams = executionParams || {};
330
+ const resolveduserConfig = resolveConfig<NamedAccounts, Data>(userConfig, executionParams.config);
331
+ const {name: environmentName, fork} = getEnvironmentName(executionParams);
332
+ const chainId = await getChainIdForEnvironment(resolveduserConfig, environmentName, executionParams.provider);
333
+ const resolvedExecutionParams = resolveExecutionParams(resolveduserConfig, executionParams, chainId);
334
+ return executeDeployScriptModules<NamedAccounts, Data, ArgumentsType>(
335
+ moduleObjects,
336
+ resolveduserConfig,
337
+ resolvedExecutionParams,
338
+ args,
339
+ );
340
+ }
341
+
342
+ async function executeDeployScriptModules<
343
+ NamedAccounts extends UnresolvedUnknownNamedAccounts = UnresolvedUnknownNamedAccounts,
344
+ Data extends UnresolvedNetworkSpecificData = UnresolvedNetworkSpecificData,
345
+ ArgumentsType = undefined,
346
+ >(
347
+ moduleObjects: ModuleObject<NamedAccounts, Data, ArgumentsType>[],
348
+ userConfig: ResolvedUserConfig<NamedAccounts, Data>,
349
+ resolvedExecutionParams: ResolvedExecutionParams,
350
+ args?: ArgumentsType,
351
+ ): Promise<Environment<NamedAccounts, Data, UnknownDeployments>> {
352
+ const scriptModuleById: {[id: string]: DeployScriptModule<NamedAccounts, Data, ArgumentsType>} = {};
353
+ const scriptIdBags: {[tag: string]: string[]} = {};
354
+ const ids: string[] = [];
355
+
356
+ for (const moduleObject of moduleObjects) {
357
+ const id = moduleObject.id;
358
+ let scriptModule = moduleObject.module;
359
+ scriptModuleById[id] = scriptModule;
360
+
361
+ let scriptTags = scriptModule.tags;
362
+ if (scriptTags !== undefined) {
363
+ if (typeof scriptTags === 'string') {
364
+ scriptTags = [scriptTags];
365
+ }
366
+ for (const tag of scriptTags) {
367
+ if (tag.indexOf(',') >= 0) {
368
+ throw new Error('Tag cannot contains commas');
369
+ }
370
+ const bag = scriptIdBags[tag] || [];
371
+ scriptIdBags[tag] = bag;
372
+ bag.push(id);
373
+ }
374
+ }
375
+
376
+ if (resolvedExecutionParams.tags !== undefined && resolvedExecutionParams.tags.length > 0) {
377
+ let found = false;
378
+ if (scriptTags !== undefined) {
379
+ for (const tagToFind of resolvedExecutionParams.tags) {
380
+ for (const tag of scriptTags) {
381
+ if (tag === tagToFind) {
382
+ ids.push(id);
383
+ found = true;
384
+ break;
385
+ }
386
+ }
387
+ if (found) {
388
+ break;
389
+ }
390
+ }
391
+ }
392
+ } else {
393
+ ids.push(id);
394
+ }
395
+ }
396
+
397
+ const {internal, external} = await createEnvironment<NamedAccounts, Data, UnknownDeployments>(
398
+ userConfig,
399
+ resolvedExecutionParams,
400
+ deploymentStore,
401
+ );
402
+
403
+ await internal.recoverTransactionsIfAny();
404
+
405
+ const scriptsRegisteredToRun: {[filename: string]: boolean} = {};
406
+ const scriptsToRun: Array<{
407
+ func: DeployScriptModule<NamedAccounts, Data, ArgumentsType>;
408
+ id: string;
409
+ }> = [];
410
+ const scriptsToRunAtTheEnd: Array<{
411
+ func: DeployScriptModule<NamedAccounts, Data, ArgumentsType>;
412
+ id: string;
413
+ }> = [];
414
+ function recurseDependencies(id: string) {
415
+ if (scriptsRegisteredToRun[id]) {
416
+ return;
417
+ }
418
+ const scriptModule = scriptModuleById[id];
419
+ if (scriptModule.dependencies) {
420
+ for (const dependency of scriptModule.dependencies) {
421
+ const scriptFilePathsToAdd = scriptIdBags[dependency];
422
+ if (scriptFilePathsToAdd) {
423
+ for (const scriptFilenameToAdd of scriptFilePathsToAdd) {
424
+ recurseDependencies(scriptFilenameToAdd);
425
+ }
426
+ }
427
+ }
428
+ }
429
+ if (!scriptsRegisteredToRun[id]) {
430
+ if (scriptModule.runAtTheEnd) {
431
+ scriptsToRunAtTheEnd.push({
432
+ id: id,
433
+ func: scriptModule,
434
+ });
435
+ } else {
436
+ scriptsToRun.push({
437
+ id: id,
438
+ func: scriptModule,
439
+ });
440
+ }
441
+ scriptsRegisteredToRun[id] = true;
442
+ }
443
+ }
444
+ for (const id of ids) {
445
+ recurseDependencies(id);
446
+ }
447
+
448
+ // TODO store in the execution context
449
+ const gasPriceEstimate = await getRoughGasPriceEstimate(external.network.provider);
450
+ if (resolvedExecutionParams.askBeforeProceeding) {
451
+ console.log(
452
+ `Network: ${external.name} \n \t Chain: ${external.network.chain.name} \n \t Tags: ${Object.keys(
453
+ external.tags,
454
+ ).join(',')}`,
455
+ );
456
+
457
+ const prompt = await promptExecutor.prompt({
458
+ type: 'confirm',
459
+ name: 'proceed',
460
+ message: `gas price is currently in this range:
461
+ slow: ${formatEther(gasPriceEstimate.slow.maxFeePerGas)} (priority: ${formatEther(
462
+ gasPriceEstimate.slow.maxPriorityFeePerGas,
463
+ )})
464
+ average: ${formatEther(gasPriceEstimate.average.maxFeePerGas)} (priority: ${formatEther(
465
+ gasPriceEstimate.average.maxPriorityFeePerGas,
466
+ )})
467
+ fast: ${formatEther(gasPriceEstimate.fast.maxFeePerGas)} (priority: ${formatEther(
468
+ gasPriceEstimate.fast.maxPriorityFeePerGas,
469
+ )})
470
+
471
+ Do you want to proceed (note that gas price can change for each tx)`,
472
+ });
473
+
474
+ if (!prompt.proceed) {
475
+ promptExecutor.exit();
476
+ }
477
+ }
478
+
479
+ for (const deployScript of scriptsToRun.concat(scriptsToRunAtTheEnd)) {
480
+ if (deployScript.func.id && external.hasMigrationBeenDone(deployScript.func.id)) {
481
+ logger.info(`skipping ${deployScript.id} as migrations already executed and complete`);
482
+ continue;
483
+ }
484
+ let skip = false;
485
+ const spinner = spin(`- Executing ${deployScript.id}`);
486
+ // if (deployScript.func.skip) {
487
+ // const spinner = spin(` - skip?()`);
488
+ // try {
489
+ // skip = await deployScript.func.skip(external, args);
490
+ // spinner.succeed(skip ? `skipping ${filename}` : undefined);
491
+ // } catch (e) {
492
+ // spinner.fail();
493
+ // throw e;
494
+ // }
495
+ // }
496
+ if (!skip) {
497
+ let result;
498
+
499
+ try {
500
+ result = await deployScript.func(external, args);
501
+ spinner.succeed(`\n`);
502
+ } catch (e) {
503
+ spinner.fail();
504
+ throw e;
505
+ }
506
+ if (result && typeof result === 'boolean') {
507
+ if (!deployScript.func.id) {
508
+ throw new Error(
509
+ `${deployScript.id} return true to not be executed again, but does not provide an id. the script function needs to have the field "id" to be set`,
510
+ );
511
+ }
512
+ internal.recordMigration(deployScript.func.id);
513
+ }
514
+ }
515
+ }
516
+
517
+ if (resolvedExecutionParams.reportGasUse) {
518
+ const provider = external.network.provider;
519
+ const transactionHashes = provider.transactionHashes;
520
+
521
+ let totalGasUsed = 0;
522
+ for (const hash of transactionHashes) {
523
+ const transactionReceipt = await provider.request({method: 'eth_getTransactionReceipt', params: [hash]});
524
+ if (transactionReceipt) {
525
+ const gasUsed = Number(transactionReceipt.gasUsed);
526
+ totalGasUsed += gasUsed;
527
+ }
528
+ }
529
+
530
+ console.log({totalGasUsed});
531
+ }
532
+
533
+ return external;
534
+ }
535
+
536
+ return {
537
+ executeDeployScriptModules,
538
+ resolveConfigAndExecuteDeployScriptModules,
539
+ };
540
+ }
package/src/index.ts ADDED
@@ -0,0 +1,20 @@
1
+ export {
2
+ setupDeployScripts,
3
+ loadEnvironment,
4
+ resolveConfig,
5
+ resolveExecutionParams,
6
+ getChainIdForEnvironment,
7
+ getEnvironmentName,
8
+ createExecutor,
9
+ } from './executor/index.js';
10
+ export {createEnvironment, loadDeployments} from './environment/index.js';
11
+
12
+ // used by hardhat-deploy and instead of having hardhat-deploy depends on @rocketh/core we export it here as well
13
+ export {enhanceEnvIfNeeded} from '@rocketh/core/environment';
14
+
15
+ export {
16
+ getChainConfigFromUserConfigAndDefaultChainInfo,
17
+ chainByCanonicalName,
18
+ getDefaultChainInfoByName,
19
+ getDefaultChainInfoFromChainId,
20
+ } from './environment/chains.js';
@@ -0,0 +1,35 @@
1
+ import {logs} from 'named-logs';
2
+
3
+ import {ProgressIndicator} from '@rocketh/core/types';
4
+
5
+ export const logger = logs('rocketh');
6
+
7
+ const loggerProgressIndicator: ProgressIndicator = {
8
+ start(msg?: string) {
9
+ if (msg) {
10
+ logger.log(msg);
11
+ }
12
+ return this;
13
+ },
14
+ stop() {
15
+ return this;
16
+ },
17
+ succeed(msg?: string) {
18
+ if (msg) {
19
+ logger.log(msg);
20
+ }
21
+ return this;
22
+ },
23
+ fail(msg?: string) {
24
+ if (msg) {
25
+ logger.error(msg);
26
+ }
27
+ return this;
28
+ },
29
+ };
30
+
31
+ let lastSpin = loggerProgressIndicator;
32
+ export function spin(message?: string): ProgressIndicator {
33
+ lastSpin = lastSpin.start(message);
34
+ return lastSpin;
35
+ }
@@ -0,0 +1,4 @@
1
+ export type InternalEnvironment = {
2
+ recoverTransactionsIfAny(): Promise<void>;
3
+ recordMigration(id: string): void;
4
+ };
package/src/types.ts ADDED
@@ -0,0 +1,3 @@
1
+ export type * from '@rocketh/core/types';
2
+
3
+ export type * from 'eip-1193';