Skip to content

Commit 96fc2f9

Browse files
authored
[1.2.2] Fix etherscan prompt missing (#26)
* fix etherscan again * save * update changelog
1 parent bcf114c commit 96fc2f9

File tree

7 files changed

+104
-21
lines changed

7 files changed

+104
-21
lines changed

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11

22
**[Current]**
3+
1.2.2:
4+
- A bug which resulted in etherscanApiKey not being prompted.
35

46
1.2.1:
57
- Minor bugfixes / improvements.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@layr-labs/zeus",
3-
"version": "1.2.1",
3+
"version": "1.2.2",
44
"description": "web3 deployer / metadata manager",
55
"main": "src/index.ts",
66
"scripts": {

src/commands/deploy/cmd/run.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ export async function handler(_user: TState, args: {env: string, resume: boolean
188188
anvil,
189189
testClient,
190190
overrideEoaPk,
191-
etherscanApiKey: !args.fork,
191+
etherscanApiKey: args.fork ? false : undefined,
192192
},
193193
nonInteractive: !!args.fork
194194
});
@@ -237,7 +237,7 @@ export async function handler(_user: TState, args: {env: string, resume: boolean
237237
anvil,
238238
testClient,
239239
overrideEoaPk,
240-
etherscanApiKey: !args.fork,
240+
etherscanApiKey: args.fork ? false : undefined,
241241
},
242242
nonInteractive: !!args.fork
243243
});

src/deploy/handlers/eoa.ts

+10-6
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ import { existsSync, readFileSync } from "fs";
2121
import * as prompts from '../../commands/prompts';
2222

2323
export async function executeEOAPhase(deploy: SavebleDocument<TDeploy>, metatxn: Transaction, options: TStrategyOptions | undefined): Promise<void> {
24-
let eoaStrategy: EOABaseSigningStrategy | undefined = undefined;
24+
let fallbackEoaStrategy: EOABaseSigningStrategy | undefined = undefined;
2525

2626
if (options?.nonInteractive || options?.defaultArgs?.fork) {
27-
eoaStrategy = new EOASigningStrategy(deploy, metatxn, options);
27+
fallbackEoaStrategy = new EOASigningStrategy(deploy, metatxn, options);
2828
}
2929

30+
let eoaStrategy: EOABaseSigningStrategy | undefined = undefined;
31+
3032
const rpcUrl = await (async () => {
3133
if (options?.defaultArgs?.rpcUrl) {
3234
return options?.defaultArgs?.rpcUrl;
@@ -64,8 +66,8 @@ export async function executeEOAPhase(deploy: SavebleDocument<TDeploy>, metatxn:
6466

6567
if (!options?.defaultArgs?.nonInteractive && !options?.defaultArgs?.fork) {
6668
console.log(`Zeus would like to simulate this EOA transaction before attempting it for real. Please choose the method you'll use to sign:`)
67-
eoaStrategy = (await strategies.promptForStrategyWithOptions(deploy, metatxn, undefined, {nonInteractive: !!options?.nonInteractive, defaultArgs: {...(options?.defaultArgs ?? {}), rpcUrl}})) as unknown as EOABaseSigningStrategy;
68-
const sigRequest = await eoaStrategy.prepare(script, deploy._) as TForgeRequest;
69+
const strategy = (await strategies.promptForStrategyWithOptions(deploy, metatxn, undefined, {nonInteractive: !!options?.nonInteractive, defaultArgs: {...(options?.defaultArgs ?? {}), rpcUrl}})) as unknown as EOABaseSigningStrategy;
70+
const sigRequest = await strategy.prepare(script, deploy._) as TForgeRequest;
6971
console.log(chalk.yellow(`Please reviewing the following: `))
7072
console.log(chalk.yellow(`=====================================================================================`))
7173
console.log(chalk.bold.underline(`Forge output: `))
@@ -99,8 +101,8 @@ export async function executeEOAPhase(deploy: SavebleDocument<TDeploy>, metatxn:
99101
case "eoa_start": {
100102
const script = join(deploy._.upgradePath, deploy._.segments[deploy._.segmentId].filename);
101103
if (existsSync(script)) {
102-
const strategy = eoaStrategy ?? await strategies.promptForStrategyWithOptions(deploy, metatxn, undefined, {...options, nonInteractive: !!options?.nonInteractive, defaultArgs: {...(options?.defaultArgs ?? {}), rpcUrl}});
103-
const sigRequest = await strategy.requestNew(script, deploy._) as TForgeRequest;
104+
eoaStrategy = fallbackEoaStrategy ?? await strategies.promptForStrategyWithOptions(deploy, metatxn, undefined, {...options, nonInteractive: !!options?.nonInteractive, defaultArgs: {...(options?.defaultArgs ?? {}), rpcUrl}}) as EOABaseSigningStrategy;
105+
const sigRequest = await eoaStrategy.requestNew(script, deploy._) as TForgeRequest;
104106
if (sigRequest?.ready) {
105107
deploy._.metadata[deploy._.segmentId] = {
106108
type: "eoa",
@@ -189,6 +191,8 @@ export async function executeEOAPhase(deploy: SavebleDocument<TDeploy>, metatxn:
189191
break;
190192
}
191193
case "eoa_wait_confirm": {
194+
eoaStrategy = eoaStrategy ?? fallbackEoaStrategy ?? await strategies.promptForStrategyWithOptions(deploy, metatxn, undefined, {...options, nonInteractive: !!options?.nonInteractive, defaultArgs: {...(options?.defaultArgs ?? {}), rpcUrl}}) as EOABaseSigningStrategy;
195+
192196
const foundryDeploy = await metatxn.getJSONFile<TFoundryDeploy>(
193197
canonicalPaths.foundryDeploy({deployEnv: deploy._.env, deployName: deploy._.name, segmentId: deploy._.segmentId})
194198
);

src/tests/deploy/eoa.spec.ts

+48-9
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ import { SavebleDocument, Transaction } from '../../metadata/metadataStore';
33
import { TStrategyOptions } from '../../signing/strategy';
44
import { TDeploy } from '../../metadata/schema';
55
import type { PublicClient, TransactionReceipt } from 'viem';
6-
import {mockDeployDocument, mockTransaction} from './mock';
6+
import {mockDeployDocument, mockTransaction, mockNextSelectedStrategy} from './mock';
7+
import { mockForgeScriptOutput, MockStrategy } from './mockStrategy';
78

89
const {runTest} = await import('../../signing/strategies/test');
910
const prompts = await import('../../commands/prompts')
1011
const {executeEOAPhase} = await import('../../deploy/handlers/eoa');
1112
const { createPublicClient, TransactionReceiptNotFoundError } = await import('viem');
13+
const EOASigningStrategyMod = await import('../../signing/strategies/eoa/privateKey');
14+
15+
import type EOASigningStrategy from '../../signing/strategies/eoa/privateKey'
1216

1317
describe('executeEOAPhase', () => {
1418
let deploy: SavebleDocument<TDeploy>;
@@ -57,14 +61,14 @@ describe('executeEOAPhase', () => {
5761

5862
it('should run tests and advance if all goes well (non-interactive = false)', async () => {
5963
(runTest as jest.Mock<typeof runTest>).mockResolvedValue({ forge: undefined, code: 0, stdout: '', stderr: '' }); // test pass
60-
// We'll let wouldYouLikeToContinue = true (since it's mocked by default)
61-
62-
// mock strategy out.
64+
6365
const txn = mockTransaction({
6466
"environment/testEnv/manifest.json": {id: "testEnv"}
6567
});
66-
(prompts.pickStrategy as jest.Mock<typeof prompts.pickStrategy>).mockResolvedValue('ledger');
68+
const mockStrategy = new MockStrategy(deploy, txn, options);
69+
mockNextSelectedStrategy(mockStrategy);
6770
(prompts.wouldYouLikeToContinue as jest.Mock<typeof prompts.wouldYouLikeToContinue>).mockResolvedValue(true);
71+
6872
await executeEOAPhase(deploy, txn, options);
6973

7074
// It should have invoked runTest
@@ -81,13 +85,14 @@ describe('executeEOAPhase', () => {
8185
});
8286

8387
it('should throw an error if tests fail', async () => {
84-
(runTest as jest.Mock<typeof runTest>).mockResolvedValue({ code: 1, stdout: '', stderr: '', forge: undefined }); // test fail
88+
(runTest as jest.Mock<typeof runTest>).mockResolvedValue({ code: 1, stdout: '', stderr: '', forge: undefined }); // test failure
8589

86-
await expect(executeEOAPhase(deploy, metatxn, options)).rejects.toThrowError('One or more tests failed.');
90+
await expect(executeEOAPhase(deploy, metatxn, options)).rejects.toThrowError(`The deploy halted: One or more tests failed.`);
8791

8892
// Should have tried to run tests
8993
expect(runTest).toHaveBeenCalled();
90-
// The function should throw before saving or committing
94+
95+
// Doesn't save
9196
expect(deploy.save).not.toHaveBeenCalled();
9297
expect(metatxn.commit).not.toHaveBeenCalled();
9398
});
@@ -109,6 +114,41 @@ describe('executeEOAPhase', () => {
109114
expect(metatxn.commit).not.toHaveBeenCalled();
110115
});
111116

117+
it('should complete successfully', async () => {
118+
const metatxn = mockTransaction({
119+
"environment/testEnv/manifest.json": {id: "testEnv"}
120+
});
121+
122+
(runTest as jest.Mock<typeof runTest>).mockResolvedValue({ code: 0, stdout: '', stderr: '', forge: undefined }); // test success
123+
(prompts.etherscanApiKey as jest.Mock<typeof prompts.etherscanApiKey>).mockResolvedValue('123');
124+
const options = {
125+
nonInteractive: false,
126+
defaultArgs: {rpcUrl: 'https://google.com', overrideEoaPk: `0x04ba7e1737815037a348ec201b6433868f8c297d007b5ca605387fbb21f80516`}
127+
} as const;
128+
129+
const deploy = mockDeployDocument('eoa_start', '1-eoa.s.sol') as SavebleDocument<TDeploy>;
130+
const strat = new EOASigningStrategyMod.default(deploy, metatxn, options);
131+
132+
jest.spyOn(strat, 'runForgeScript');
133+
(strat.runForgeScript as jest.Mock<typeof strat['runForgeScript']>).mockImplementation(async function (this: EOASigningStrategy) {
134+
await this.forgeArgs(); // mock runForgeScript as accessing the args.
135+
// TODO: this mocking could mock something within runForgeScript instead to be more accurate.
136+
return mockForgeScriptOutput;
137+
});
138+
139+
mockNextSelectedStrategy(strat);
140+
141+
await expect(executeEOAPhase(deploy, metatxn, options)).resolves.toBeUndefined()
142+
143+
expect(deploy.save).toHaveBeenCalled();
144+
expect(metatxn.commit).toHaveBeenCalled();
145+
146+
// should prompt for etherscan api key.
147+
expect(strat.runForgeScript).toHaveBeenCalled();
148+
expect(prompts.etherscanApiKey).toHaveBeenCalled();
149+
});
150+
})
151+
112152
describe('phase: "eoa_wait_confirm"', () => {
113153
beforeEach(() => {
114154
deploy._.phase = 'eoa_wait_confirm';
@@ -189,5 +229,4 @@ describe('executeEOAPhase', () => {
189229
);
190230
});
191231
});
192-
})
193232
});

src/tests/deploy/mock.ts

+15
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { MockStrategy } from './mockStrategy';
33
import { TDeployPhase, TEnvironmentManifest } from '../../metadata/schema';
44
import { SavebleDocument, Transaction } from '../../metadata/metadataStore';
55
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
6+
import { promptForStrategyWithOptions } from '../../commands/deploy/cmd/utils-strategies';
7+
import type { Strategy } from '../../signing/strategy';
68

79
jest.unstable_mockModule('../../signing/strategies/ledger/account', () => ({
810
// replace ledger with a hardcoded account
@@ -11,6 +13,19 @@ jest.unstable_mockModule('../../signing/strategies/ledger/account', () => ({
1113
BASE_DERIVATION_PATH: ``
1214
}))
1315

16+
17+
jest.unstable_mockModule(`../../commands/deploy/cmd/utils-strategies`, () => ({
18+
promptForStrategy: jest.fn<typeof import("../../commands/deploy/cmd/utils-strategies").promptForStrategy>(),
19+
promptForStrategyWithOptions: jest.fn<typeof import("../../commands/deploy/cmd/utils-strategies").promptForStrategyWithOptions>()
20+
}))
21+
22+
const utilsStrategies = await import(`../../commands/deploy/cmd/utils-strategies`);
23+
24+
export function mockNextSelectedStrategy(strategy: Strategy) {
25+
(utilsStrategies.promptForStrategy as jest.Mock<typeof import("../../commands/deploy/cmd/utils-strategies").promptForStrategy>).mockResolvedValueOnce(strategy);
26+
(utilsStrategies.promptForStrategyWithOptions as jest.Mock<typeof import("../../commands/deploy/cmd/utils-strategies").promptForStrategyWithOptions>).mockResolvedValueOnce(strategy);
27+
}
28+
1429
export function mockEnvManifest(): TEnvironmentManifest {
1530
return {
1631
id: "testenv",

src/tests/deploy/mockStrategy.ts

+26-3
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,30 @@ import { Strategy, TForgeRequest, TStrategyOptions } from "../../signing/strateg
44
import { jest } from '@jest/globals';
55
import { TForgeOutput, TForgeRun } from "../../signing/utils";
66

7-
const forgeSampleRun: TForgeRun = {
7+
export const mockForgeScriptOutput = {
8+
stateUpdates: [],
9+
contractDeploys: [],
10+
output: {
11+
timestamp: 0,
12+
chain: 0,
13+
success: true,
14+
returns: {
15+
'0': {
16+
value: ''
17+
}
18+
},
19+
transactions: [],
20+
logs: [],
21+
raw_logs: [],
22+
traces: [],
23+
gas_used: 0,
24+
labeled_addresses: {},
25+
returned: null,
26+
address: null
27+
}
28+
}
29+
30+
export const forgeSampleRun: TForgeRun = {
831
timestamp: 0,
932
chain: 1,
1033
transactions: [{
@@ -23,7 +46,7 @@ const forgeSampleRun: TForgeRun = {
2346
address: '0x123'
2447
};
2548

26-
const mockForgeOutput: TForgeRequest = {
49+
export const mockForgeOutput: TForgeRequest = {
2750
output: forgeSampleRun,
2851
stateUpdates: [],
2952
forge: {
@@ -36,7 +59,7 @@ const mockForgeOutput: TForgeRequest = {
3659
ready: true
3760
};
3861

39-
export abstract class MockStrategy extends Strategy {
62+
export class MockStrategy extends Strategy {
4063
id = "ledger";
4164
description = "mock";
4265

0 commit comments

Comments
 (0)