genlayer 0.34.0 → 0.34.3
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.
- package/dist/index.js +13 -3
- package/package.json +11 -2
- package/.eslintignore +0 -2
- package/.github/workflows/cli-docs.yml +0 -121
- package/.github/workflows/publish-beta.yml +0 -41
- package/.github/workflows/publish.yml +0 -43
- package/.github/workflows/validate-code.yml +0 -47
- package/.prettierignore +0 -19
- package/.prettierrc +0 -12
- package/.release-it.json +0 -64
- package/CHANGELOG.md +0 -425
- package/CLAUDE.md +0 -55
- package/CONTRIBUTING.md +0 -117
- package/docker-compose.yml +0 -154
- package/docs/delegator-guide.md +0 -203
- package/docs/validator-guide.md +0 -329
- package/esbuild.config.dev.js +0 -17
- package/esbuild.config.js +0 -22
- package/esbuild.config.prod.js +0 -17
- package/eslint.config.js +0 -60
- package/renovate.json +0 -22
- package/src/commands/account/create.ts +0 -30
- package/src/commands/account/export.ts +0 -106
- package/src/commands/account/import.ts +0 -135
- package/src/commands/account/index.ts +0 -129
- package/src/commands/account/list.ts +0 -34
- package/src/commands/account/lock.ts +0 -39
- package/src/commands/account/remove.ts +0 -30
- package/src/commands/account/send.ts +0 -162
- package/src/commands/account/show.ts +0 -74
- package/src/commands/account/unlock.ts +0 -56
- package/src/commands/account/use.ts +0 -21
- package/src/commands/config/getSetReset.ts +0 -51
- package/src/commands/config/index.ts +0 -30
- package/src/commands/contracts/call.ts +0 -39
- package/src/commands/contracts/code.ts +0 -33
- package/src/commands/contracts/deploy.ts +0 -157
- package/src/commands/contracts/index.ts +0 -86
- package/src/commands/contracts/schema.ts +0 -31
- package/src/commands/contracts/write.ts +0 -49
- package/src/commands/general/index.ts +0 -45
- package/src/commands/general/init.ts +0 -179
- package/src/commands/general/start.ts +0 -116
- package/src/commands/general/stop.ts +0 -26
- package/src/commands/localnet/index.ts +0 -100
- package/src/commands/localnet/validators.ts +0 -269
- package/src/commands/network/index.ts +0 -29
- package/src/commands/network/setNetwork.ts +0 -77
- package/src/commands/scaffold/index.ts +0 -16
- package/src/commands/scaffold/new.ts +0 -34
- package/src/commands/staking/StakingAction.ts +0 -279
- package/src/commands/staking/delegatorClaim.ts +0 -41
- package/src/commands/staking/delegatorExit.ts +0 -56
- package/src/commands/staking/delegatorJoin.ts +0 -44
- package/src/commands/staking/index.ts +0 -357
- package/src/commands/staking/setIdentity.ts +0 -78
- package/src/commands/staking/setOperator.ts +0 -46
- package/src/commands/staking/stakingInfo.ts +0 -584
- package/src/commands/staking/validatorClaim.ts +0 -43
- package/src/commands/staking/validatorDeposit.ts +0 -48
- package/src/commands/staking/validatorExit.ts +0 -63
- package/src/commands/staking/validatorHistory.ts +0 -298
- package/src/commands/staking/validatorJoin.ts +0 -47
- package/src/commands/staking/validatorPrime.ts +0 -73
- package/src/commands/staking/wizard.ts +0 -809
- package/src/commands/transactions/appeal.ts +0 -39
- package/src/commands/transactions/index.ts +0 -39
- package/src/commands/transactions/receipt.ts +0 -90
- package/src/commands/update/index.ts +0 -25
- package/src/commands/update/ollama.ts +0 -103
- package/src/lib/actions/BaseAction.ts +0 -299
- package/src/lib/clients/jsonRpcClient.ts +0 -41
- package/src/lib/clients/system.ts +0 -73
- package/src/lib/config/ConfigFileManager.ts +0 -194
- package/src/lib/config/KeychainManager.ts +0 -89
- package/src/lib/config/simulator.ts +0 -68
- package/src/lib/config/text.ts +0 -2
- package/src/lib/errors/missingRequirement.ts +0 -9
- package/src/lib/errors/versionRequired.ts +0 -9
- package/src/lib/interfaces/ISimulatorService.ts +0 -37
- package/src/lib/services/simulator.ts +0 -351
- package/src/types/node-fetch.d.ts +0 -1
- package/tests/actions/appeal.test.ts +0 -99
- package/tests/actions/call.test.ts +0 -94
- package/tests/actions/code.test.ts +0 -87
- package/tests/actions/create.test.ts +0 -65
- package/tests/actions/deploy.test.ts +0 -420
- package/tests/actions/getSetReset.test.ts +0 -88
- package/tests/actions/init.test.ts +0 -467
- package/tests/actions/lock.test.ts +0 -86
- package/tests/actions/new.test.ts +0 -80
- package/tests/actions/ollama.test.ts +0 -193
- package/tests/actions/receipt.test.ts +0 -261
- package/tests/actions/schema.test.ts +0 -94
- package/tests/actions/setNetwork.test.ts +0 -160
- package/tests/actions/staking.test.ts +0 -279
- package/tests/actions/start.test.ts +0 -235
- package/tests/actions/stop.test.ts +0 -77
- package/tests/actions/unlock.test.ts +0 -139
- package/tests/actions/validators.test.ts +0 -750
- package/tests/actions/write.test.ts +0 -102
- package/tests/commands/account.test.ts +0 -146
- package/tests/commands/appeal.test.ts +0 -58
- package/tests/commands/call.test.ts +0 -78
- package/tests/commands/code.test.ts +0 -69
- package/tests/commands/config.test.ts +0 -54
- package/tests/commands/deploy.test.ts +0 -83
- package/tests/commands/init.test.ts +0 -101
- package/tests/commands/localnet.test.ts +0 -131
- package/tests/commands/network.test.ts +0 -60
- package/tests/commands/new.test.ts +0 -68
- package/tests/commands/receipt.test.ts +0 -142
- package/tests/commands/schema.test.ts +0 -67
- package/tests/commands/staking.test.ts +0 -329
- package/tests/commands/stop.test.ts +0 -27
- package/tests/commands/up.test.ts +0 -105
- package/tests/commands/update.test.ts +0 -45
- package/tests/commands/write.test.ts +0 -76
- package/tests/index.test.ts +0 -56
- package/tests/libs/baseAction.test.ts +0 -516
- package/tests/libs/configFileManager.test.ts +0 -117
- package/tests/libs/jsonRpcClient.test.ts +0 -59
- package/tests/libs/keychainManager.test.ts +0 -156
- package/tests/libs/system.test.ts +0 -148
- package/tests/services/simulator.test.ts +0 -705
- package/tests/utils.ts +0 -13
- package/tsconfig.json +0 -120
- package/vitest.config.ts +0 -12
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import {describe, test, vi, beforeEach, afterEach, expect} from "vitest";
|
|
2
|
-
import {NetworkActions} from "../../src/commands/network/setNetwork";
|
|
3
|
-
import {ConfigFileManager} from "../../src/lib/config/ConfigFileManager";
|
|
4
|
-
import inquirer from "inquirer";
|
|
5
|
-
import {localnet, studionet, testnetAsimov} from "genlayer-js/chains";
|
|
6
|
-
|
|
7
|
-
vi.mock("../../src/lib/config/ConfigFileManager");
|
|
8
|
-
vi.mock("inquirer");
|
|
9
|
-
|
|
10
|
-
describe("NetworkActions", () => {
|
|
11
|
-
let networkActions: NetworkActions;
|
|
12
|
-
|
|
13
|
-
beforeEach(() => {
|
|
14
|
-
networkActions = new NetworkActions();
|
|
15
|
-
vi.clearAllMocks();
|
|
16
|
-
|
|
17
|
-
vi.spyOn(networkActions as any, "succeedSpinner").mockImplementation(() => {});
|
|
18
|
-
vi.spyOn(networkActions as any, "failSpinner").mockImplementation(() => {});
|
|
19
|
-
vi.spyOn(networkActions as any, "writeConfig").mockImplementation(() => {});
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
afterEach(() => {
|
|
23
|
-
vi.restoreAllMocks();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
test("setNetwork method sets network by valid name", async () => {
|
|
27
|
-
await networkActions.setNetwork(localnet.name);
|
|
28
|
-
|
|
29
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "localnet");
|
|
30
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
31
|
-
`Network successfully set to ${localnet.name}`,
|
|
32
|
-
);
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
test("setNetwork method sets network by valid alias", async () => {
|
|
36
|
-
await networkActions.setNetwork("localnet");
|
|
37
|
-
|
|
38
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "localnet");
|
|
39
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
40
|
-
`Network successfully set to ${localnet.name}`,
|
|
41
|
-
);
|
|
42
|
-
});
|
|
43
|
-
|
|
44
|
-
test("setNetwork method sets studionet by name", async () => {
|
|
45
|
-
await networkActions.setNetwork(studionet.name);
|
|
46
|
-
|
|
47
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "studionet");
|
|
48
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
49
|
-
`Network successfully set to ${studionet.name}`,
|
|
50
|
-
);
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
test("setNetwork method sets studionet by alias", async () => {
|
|
54
|
-
await networkActions.setNetwork("studionet");
|
|
55
|
-
|
|
56
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "studionet");
|
|
57
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
58
|
-
`Network successfully set to ${studionet.name}`,
|
|
59
|
-
);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
test("setNetwork method sets testnet-asimov by name", async () => {
|
|
63
|
-
await networkActions.setNetwork(testnetAsimov.name);
|
|
64
|
-
|
|
65
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "testnet-asimov");
|
|
66
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
67
|
-
`Network successfully set to ${testnetAsimov.name}`,
|
|
68
|
-
);
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
test("setNetwork method sets testnet-asimov by alias", async () => {
|
|
72
|
-
await networkActions.setNetwork("testnet-asimov");
|
|
73
|
-
|
|
74
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "testnet-asimov");
|
|
75
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
76
|
-
`Network successfully set to ${testnetAsimov.name}`,
|
|
77
|
-
);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
test("setNetwork method fails for invalid network name", async () => {
|
|
81
|
-
await networkActions.setNetwork("invalidNetwork");
|
|
82
|
-
|
|
83
|
-
expect(networkActions["failSpinner"]).toHaveBeenCalledWith("Network invalidNetwork not found");
|
|
84
|
-
expect(networkActions["writeConfig"]).not.toHaveBeenCalled();
|
|
85
|
-
expect(networkActions["succeedSpinner"]).not.toHaveBeenCalled();
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
test("setNetwork method fails for empty network name", async () => {
|
|
89
|
-
await networkActions.setNetwork("");
|
|
90
|
-
|
|
91
|
-
expect(networkActions["failSpinner"]).toHaveBeenCalledWith("Network not found");
|
|
92
|
-
expect(networkActions["writeConfig"]).not.toHaveBeenCalled();
|
|
93
|
-
expect(networkActions["succeedSpinner"]).not.toHaveBeenCalled();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test("setNetwork method prompts user when no network name provided", async () => {
|
|
97
|
-
vi.mocked(inquirer.prompt).mockResolvedValue({
|
|
98
|
-
selectedNetwork: "localnet",
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
await networkActions.setNetwork();
|
|
102
|
-
|
|
103
|
-
expect(inquirer.prompt).toHaveBeenCalledWith([
|
|
104
|
-
{
|
|
105
|
-
type: "list",
|
|
106
|
-
name: "selectedNetwork",
|
|
107
|
-
message: "Select which network do you want to use:",
|
|
108
|
-
choices: [
|
|
109
|
-
{name: localnet.name, value: "localnet"},
|
|
110
|
-
{name: studionet.name, value: "studionet"},
|
|
111
|
-
{name: testnetAsimov.name, value: "testnet-asimov"},
|
|
112
|
-
],
|
|
113
|
-
},
|
|
114
|
-
]);
|
|
115
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "localnet");
|
|
116
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
117
|
-
`Network successfully set to ${localnet.name}`,
|
|
118
|
-
);
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test("setNetwork method handles interactive selection of studionet", async () => {
|
|
122
|
-
vi.mocked(inquirer.prompt).mockResolvedValue({
|
|
123
|
-
selectedNetwork: "studionet",
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
await networkActions.setNetwork();
|
|
127
|
-
|
|
128
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "studionet");
|
|
129
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
130
|
-
`Network successfully set to ${studionet.name}`,
|
|
131
|
-
);
|
|
132
|
-
});
|
|
133
|
-
|
|
134
|
-
test("setNetwork method handles interactive selection of testnet-asimov", async () => {
|
|
135
|
-
vi.mocked(inquirer.prompt).mockResolvedValue({
|
|
136
|
-
selectedNetwork: "testnet-asimov",
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
await networkActions.setNetwork();
|
|
140
|
-
|
|
141
|
-
expect(networkActions["writeConfig"]).toHaveBeenCalledWith("network", "testnet-asimov");
|
|
142
|
-
expect(networkActions["succeedSpinner"]).toHaveBeenCalledWith(
|
|
143
|
-
`Network successfully set to ${testnetAsimov.name}`,
|
|
144
|
-
);
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
test("setNetwork method handles case-sensitive network names", async () => {
|
|
148
|
-
await networkActions.setNetwork("LOCALNET");
|
|
149
|
-
|
|
150
|
-
expect(networkActions["failSpinner"]).toHaveBeenCalledWith("Network LOCALNET not found");
|
|
151
|
-
expect(networkActions["writeConfig"]).not.toHaveBeenCalled();
|
|
152
|
-
});
|
|
153
|
-
|
|
154
|
-
test("setNetwork method handles partial network names", async () => {
|
|
155
|
-
await networkActions.setNetwork("local");
|
|
156
|
-
|
|
157
|
-
expect(networkActions["failSpinner"]).toHaveBeenCalledWith("Network local not found");
|
|
158
|
-
expect(networkActions["writeConfig"]).not.toHaveBeenCalled();
|
|
159
|
-
});
|
|
160
|
-
});
|
|
@@ -1,279 +0,0 @@
|
|
|
1
|
-
import {describe, test, vi, beforeEach, afterEach, expect} from "vitest";
|
|
2
|
-
import {ValidatorJoinAction} from "../../src/commands/staking/validatorJoin";
|
|
3
|
-
import {ValidatorDepositAction} from "../../src/commands/staking/validatorDeposit";
|
|
4
|
-
import {ValidatorExitAction} from "../../src/commands/staking/validatorExit";
|
|
5
|
-
import {ValidatorClaimAction} from "../../src/commands/staking/validatorClaim";
|
|
6
|
-
import {DelegatorJoinAction} from "../../src/commands/staking/delegatorJoin";
|
|
7
|
-
import {DelegatorExitAction} from "../../src/commands/staking/delegatorExit";
|
|
8
|
-
import {DelegatorClaimAction} from "../../src/commands/staking/delegatorClaim";
|
|
9
|
-
import {StakingInfoAction} from "../../src/commands/staking/stakingInfo";
|
|
10
|
-
|
|
11
|
-
// Mock genlayer-js
|
|
12
|
-
vi.mock("genlayer-js", () => ({
|
|
13
|
-
createClient: vi.fn(),
|
|
14
|
-
createAccount: vi.fn(() => ({address: "0xMockedAddress"})),
|
|
15
|
-
formatStakingAmount: vi.fn((val: bigint) => `${Number(val) / 1e18} GEN`),
|
|
16
|
-
parseStakingAmount: vi.fn((val: string) => {
|
|
17
|
-
if (val.toLowerCase().endsWith("gen") || val.toLowerCase().endsWith("eth")) {
|
|
18
|
-
return BigInt(parseFloat(val.slice(0, -3)) * 1e18);
|
|
19
|
-
}
|
|
20
|
-
return BigInt(val);
|
|
21
|
-
}),
|
|
22
|
-
abi: {
|
|
23
|
-
STAKING_ABI: [],
|
|
24
|
-
},
|
|
25
|
-
}));
|
|
26
|
-
|
|
27
|
-
vi.mock("genlayer-js/chains", () => ({
|
|
28
|
-
localnet: {id: 1, name: "localnet", rpcUrls: {default: {http: ["http://localhost:8545"]}}},
|
|
29
|
-
studionet: {id: 2, name: "studionet", rpcUrls: {default: {http: ["https://studionet.genlayer.com"]}}},
|
|
30
|
-
testnetAsimov: {id: 3, name: "testnet-asimov", rpcUrls: {default: {http: ["https://testnet.genlayer.com"]}}},
|
|
31
|
-
}));
|
|
32
|
-
|
|
33
|
-
const mockTxResult = {
|
|
34
|
-
transactionHash: "0xMockedHash" as `0x${string}`,
|
|
35
|
-
blockNumber: 123n,
|
|
36
|
-
gasUsed: 21000n,
|
|
37
|
-
};
|
|
38
|
-
|
|
39
|
-
const mockValidatorJoinResult = {
|
|
40
|
-
...mockTxResult,
|
|
41
|
-
validatorWallet: "0xValidatorWallet",
|
|
42
|
-
operator: "0xOperator",
|
|
43
|
-
amount: "42000 GEN",
|
|
44
|
-
amountRaw: 42000n * BigInt(1e18),
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
const mockDelegatorJoinResult = {
|
|
48
|
-
...mockTxResult,
|
|
49
|
-
validator: "0xValidator",
|
|
50
|
-
delegator: "0xDelegator",
|
|
51
|
-
amount: "42 GEN",
|
|
52
|
-
amountRaw: 42n * BigInt(1e18),
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const mockClient = {
|
|
56
|
-
validatorJoin: vi.fn(),
|
|
57
|
-
validatorDeposit: vi.fn(),
|
|
58
|
-
validatorExit: vi.fn(),
|
|
59
|
-
validatorClaim: vi.fn(),
|
|
60
|
-
delegatorJoin: vi.fn(),
|
|
61
|
-
delegatorExit: vi.fn(),
|
|
62
|
-
delegatorClaim: vi.fn(),
|
|
63
|
-
isValidator: vi.fn(),
|
|
64
|
-
getValidatorInfo: vi.fn(),
|
|
65
|
-
getStakeInfo: vi.fn(),
|
|
66
|
-
getEpochInfo: vi.fn(),
|
|
67
|
-
getEpochData: vi.fn(),
|
|
68
|
-
getActiveValidators: vi.fn(),
|
|
69
|
-
formatStakingAmount: vi.fn((val: bigint) => `${Number(val) / 1e18} GEN`),
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
function setupActionMocks(action: any) {
|
|
73
|
-
vi.spyOn(action as any, "getStakingClient").mockResolvedValue(mockClient);
|
|
74
|
-
vi.spyOn(action as any, "getReadOnlyStakingClient").mockResolvedValue(mockClient);
|
|
75
|
-
vi.spyOn(action as any, "getSignerAddress").mockResolvedValue("0xMockedSigner");
|
|
76
|
-
vi.spyOn(action as any, "startSpinner").mockImplementation(() => {});
|
|
77
|
-
vi.spyOn(action as any, "setSpinnerText").mockImplementation(() => {});
|
|
78
|
-
vi.spyOn(action as any, "succeedSpinner").mockImplementation(() => {});
|
|
79
|
-
vi.spyOn(action as any, "failSpinner").mockImplementation(() => {});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
describe("ValidatorJoinAction", () => {
|
|
83
|
-
let action: ValidatorJoinAction;
|
|
84
|
-
|
|
85
|
-
beforeEach(() => {
|
|
86
|
-
vi.clearAllMocks();
|
|
87
|
-
action = new ValidatorJoinAction();
|
|
88
|
-
setupActionMocks(action);
|
|
89
|
-
mockClient.validatorJoin.mockResolvedValue(mockValidatorJoinResult);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
afterEach(() => {
|
|
93
|
-
vi.restoreAllMocks();
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
test("joins as validator without operator", async () => {
|
|
97
|
-
await action.execute({amount: "42000gen", stakingAddress: "0xStaking"});
|
|
98
|
-
|
|
99
|
-
expect(mockClient.validatorJoin).toHaveBeenCalledWith({
|
|
100
|
-
amount: expect.any(BigInt),
|
|
101
|
-
operator: undefined,
|
|
102
|
-
});
|
|
103
|
-
expect(action["succeedSpinner"]).toHaveBeenCalledWith("Validator created successfully!", expect.any(Object));
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
test("joins as validator with operator", async () => {
|
|
107
|
-
await action.execute({amount: "42000gen", operator: "0xOperator", stakingAddress: "0xStaking"});
|
|
108
|
-
|
|
109
|
-
expect(mockClient.validatorJoin).toHaveBeenCalledWith({
|
|
110
|
-
amount: expect.any(BigInt),
|
|
111
|
-
operator: "0xOperator",
|
|
112
|
-
});
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
test("handles errors", async () => {
|
|
116
|
-
mockClient.validatorJoin.mockRejectedValue(new Error("Join failed"));
|
|
117
|
-
|
|
118
|
-
await action.execute({amount: "42000gen", stakingAddress: "0xStaking"});
|
|
119
|
-
|
|
120
|
-
expect(action["failSpinner"]).toHaveBeenCalledWith("Failed to create validator", "Join failed");
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
// ValidatorDepositAction, ValidatorExitAction, ValidatorClaimAction tests
|
|
125
|
-
// are covered by command-level tests. These actions now use viem directly
|
|
126
|
-
// to call ValidatorWallet contracts and require complex viem mocking.
|
|
127
|
-
|
|
128
|
-
describe("DelegatorJoinAction", () => {
|
|
129
|
-
let action: DelegatorJoinAction;
|
|
130
|
-
|
|
131
|
-
beforeEach(() => {
|
|
132
|
-
vi.clearAllMocks();
|
|
133
|
-
action = new DelegatorJoinAction();
|
|
134
|
-
setupActionMocks(action);
|
|
135
|
-
mockClient.delegatorJoin.mockResolvedValue(mockDelegatorJoinResult);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test("joins as delegator successfully", async () => {
|
|
139
|
-
await action.execute({validator: "0xValidator", amount: "42gen", stakingAddress: "0xStaking"});
|
|
140
|
-
|
|
141
|
-
expect(mockClient.delegatorJoin).toHaveBeenCalledWith({
|
|
142
|
-
validator: "0xValidator",
|
|
143
|
-
amount: expect.any(BigInt),
|
|
144
|
-
});
|
|
145
|
-
expect(action["succeedSpinner"]).toHaveBeenCalledWith("Successfully joined as delegator!", expect.any(Object));
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
|
|
149
|
-
describe("DelegatorExitAction", () => {
|
|
150
|
-
let action: DelegatorExitAction;
|
|
151
|
-
|
|
152
|
-
beforeEach(() => {
|
|
153
|
-
vi.clearAllMocks();
|
|
154
|
-
action = new DelegatorExitAction();
|
|
155
|
-
setupActionMocks(action);
|
|
156
|
-
mockClient.delegatorExit.mockResolvedValue(mockTxResult);
|
|
157
|
-
mockClient.getEpochInfo.mockResolvedValue(mockEpochInfo);
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
test("exits successfully", async () => {
|
|
161
|
-
await action.execute({validator: "0xValidator", shares: "50", stakingAddress: "0xStaking"});
|
|
162
|
-
|
|
163
|
-
expect(mockClient.delegatorExit).toHaveBeenCalledWith({validator: "0xValidator", shares: 50n});
|
|
164
|
-
expect(action["succeedSpinner"]).toHaveBeenCalledWith("Exit initiated successfully!", expect.any(Object));
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
describe("DelegatorClaimAction", () => {
|
|
169
|
-
let action: DelegatorClaimAction;
|
|
170
|
-
|
|
171
|
-
beforeEach(() => {
|
|
172
|
-
vi.clearAllMocks();
|
|
173
|
-
action = new DelegatorClaimAction();
|
|
174
|
-
setupActionMocks(action);
|
|
175
|
-
mockClient.delegatorClaim.mockResolvedValue(mockTxResult);
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
test("claims successfully", async () => {
|
|
179
|
-
await action.execute({validator: "0xValidator", delegator: "0xDelegator", stakingAddress: "0xStaking"});
|
|
180
|
-
|
|
181
|
-
expect(mockClient.delegatorClaim).toHaveBeenCalledWith({validator: "0xValidator", delegator: "0xDelegator"});
|
|
182
|
-
expect(action["succeedSpinner"]).toHaveBeenCalledWith("Claim successful!", expect.any(Object));
|
|
183
|
-
});
|
|
184
|
-
});
|
|
185
|
-
|
|
186
|
-
const mockEpochInfo = {
|
|
187
|
-
currentEpoch: 10n,
|
|
188
|
-
currentEpochStart: new Date("2024-01-01T00:00:00Z"),
|
|
189
|
-
currentEpochEnd: new Date("2024-01-01T01:00:00Z"),
|
|
190
|
-
nextEpochEstimate: new Date("2024-01-01T02:00:00Z"),
|
|
191
|
-
epochMinDuration: 3600n,
|
|
192
|
-
validatorMinStake: "42000 GEN",
|
|
193
|
-
validatorMinStakeRaw: 42000n * BigInt(1e18),
|
|
194
|
-
delegatorMinStake: "42 GEN",
|
|
195
|
-
delegatorMinStakeRaw: 42n * BigInt(1e18),
|
|
196
|
-
activeValidatorsCount: 5n,
|
|
197
|
-
inflation: "1000 GEN",
|
|
198
|
-
inflationRaw: 1000n * BigInt(1e18),
|
|
199
|
-
totalWeight: 100000n * BigInt(1e18),
|
|
200
|
-
totalClaimed: "500 GEN",
|
|
201
|
-
totalClaimedRaw: 500n * BigInt(1e18),
|
|
202
|
-
};
|
|
203
|
-
|
|
204
|
-
describe("StakingInfoAction", () => {
|
|
205
|
-
let action: StakingInfoAction;
|
|
206
|
-
|
|
207
|
-
beforeEach(() => {
|
|
208
|
-
vi.clearAllMocks();
|
|
209
|
-
action = new StakingInfoAction();
|
|
210
|
-
setupActionMocks(action);
|
|
211
|
-
mockClient.getEpochInfo.mockResolvedValue(mockEpochInfo);
|
|
212
|
-
mockClient.getEpochData.mockResolvedValue({
|
|
213
|
-
start: BigInt(Math.floor(Date.now() / 1000) - 3600),
|
|
214
|
-
end: 0n,
|
|
215
|
-
vcount: 5n,
|
|
216
|
-
weight: 100000n,
|
|
217
|
-
inflation: 1000n * BigInt(1e18),
|
|
218
|
-
claimed: 500n * BigInt(1e18),
|
|
219
|
-
slashed: 0n,
|
|
220
|
-
});
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
test("gets validator info", async () => {
|
|
224
|
-
mockClient.isValidator.mockResolvedValue(true);
|
|
225
|
-
mockClient.getValidatorInfo.mockResolvedValue({
|
|
226
|
-
address: "0xValidator",
|
|
227
|
-
owner: "0xOwner",
|
|
228
|
-
operator: "0xOperator",
|
|
229
|
-
vStake: "1000 GEN",
|
|
230
|
-
vStakeRaw: 1000n,
|
|
231
|
-
vShares: 100n,
|
|
232
|
-
dStake: "500 GEN",
|
|
233
|
-
dStakeRaw: 500n,
|
|
234
|
-
dShares: 50n,
|
|
235
|
-
vDeposit: "0 GEN",
|
|
236
|
-
vDepositRaw: 0n,
|
|
237
|
-
vWithdrawal: "0 GEN",
|
|
238
|
-
vWithdrawalRaw: 0n,
|
|
239
|
-
ePrimed: 5n,
|
|
240
|
-
needsPriming: false,
|
|
241
|
-
live: true,
|
|
242
|
-
banned: false,
|
|
243
|
-
bannedEpoch: null,
|
|
244
|
-
pendingDeposits: [],
|
|
245
|
-
pendingWithdrawals: [],
|
|
246
|
-
identity: null,
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
await action.getValidatorInfo({validator: "0xValidator", stakingAddress: "0xStaking"});
|
|
250
|
-
|
|
251
|
-
expect(mockClient.isValidator).toHaveBeenCalledWith("0xValidator");
|
|
252
|
-
expect(action["succeedSpinner"]).toHaveBeenCalledWith("Validator info retrieved", expect.any(Object));
|
|
253
|
-
});
|
|
254
|
-
|
|
255
|
-
test("fails if not a validator", async () => {
|
|
256
|
-
mockClient.isValidator.mockResolvedValue(false);
|
|
257
|
-
|
|
258
|
-
await action.getValidatorInfo({validator: "0xNotValidator", stakingAddress: "0xStaking"});
|
|
259
|
-
|
|
260
|
-
expect(action["failSpinner"]).toHaveBeenCalledWith("Address 0xNotValidator is not a validator");
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
test("gets epoch info", async () => {
|
|
264
|
-
await action.getEpochInfo({stakingAddress: "0xStaking"});
|
|
265
|
-
|
|
266
|
-
expect(action["succeedSpinner"]).toHaveBeenCalledWith("Epoch info");
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
test("lists active validators", async () => {
|
|
270
|
-
mockClient.getActiveValidators.mockResolvedValue(["0xV1", "0xV2", "0xV3"]);
|
|
271
|
-
|
|
272
|
-
await action.listActiveValidators({stakingAddress: "0xStaking"});
|
|
273
|
-
|
|
274
|
-
expect(action["succeedSpinner"]).toHaveBeenCalledWith("Active validators retrieved", {
|
|
275
|
-
count: 3,
|
|
276
|
-
validators: ["0xV1", "0xV2", "0xV3"],
|
|
277
|
-
});
|
|
278
|
-
});
|
|
279
|
-
});
|
|
@@ -1,235 +0,0 @@
|
|
|
1
|
-
import {describe, beforeEach, afterEach, test, expect, vi, Mock} from "vitest";
|
|
2
|
-
import inquirer from "inquirer";
|
|
3
|
-
import {StartAction, StartActionOptions} from "../../src/commands/general/start";
|
|
4
|
-
import {SimulatorService} from "../../src/lib/services/simulator";
|
|
5
|
-
|
|
6
|
-
vi.mock("../../src/lib/services/simulator");
|
|
7
|
-
vi.mock("inquirer");
|
|
8
|
-
|
|
9
|
-
describe("StartAction", () => {
|
|
10
|
-
let startAction: StartAction;
|
|
11
|
-
let mockSimulatorService: SimulatorService;
|
|
12
|
-
let mockConfirmPrompt: any;
|
|
13
|
-
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
vi.clearAllMocks();
|
|
16
|
-
|
|
17
|
-
mockSimulatorService = new SimulatorService();
|
|
18
|
-
startAction = new StartAction();
|
|
19
|
-
startAction["simulatorService"] = mockSimulatorService;
|
|
20
|
-
|
|
21
|
-
mockSimulatorService.waitForSimulatorToBeReady = vi.fn().mockResolvedValue({initialized: true});
|
|
22
|
-
mockSimulatorService.stopDockerContainers = vi.fn().mockResolvedValue(undefined);
|
|
23
|
-
mockSimulatorService.getAiProvidersOptions = vi.fn().mockResolvedValue(undefined);
|
|
24
|
-
|
|
25
|
-
mockConfirmPrompt = vi.spyOn(startAction as any, "confirmPrompt").mockResolvedValue(undefined);
|
|
26
|
-
vi.spyOn(startAction as any, "startSpinner").mockImplementation(() => {});
|
|
27
|
-
vi.spyOn(startAction as any, "setSpinnerText").mockImplementation(() => {});
|
|
28
|
-
vi.spyOn(startAction as any, "succeedSpinner").mockImplementation(() => {});
|
|
29
|
-
vi.spyOn(startAction as any, "failSpinner").mockImplementation(() => {});
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
afterEach(() => {
|
|
33
|
-
vi.restoreAllMocks();
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
const defaultOptions: StartActionOptions = {
|
|
37
|
-
resetValidators: false,
|
|
38
|
-
numValidators: 5,
|
|
39
|
-
headless: false,
|
|
40
|
-
resetDb: false,
|
|
41
|
-
ollama: false
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
test("should check if localnet is running and proceed without confirmation when not running", async () => {
|
|
45
|
-
mockSimulatorService.isLocalnetRunning = vi.fn().mockResolvedValue(false);
|
|
46
|
-
|
|
47
|
-
await startAction.execute(defaultOptions);
|
|
48
|
-
|
|
49
|
-
expect(mockSimulatorService.isLocalnetRunning).toHaveBeenCalled();
|
|
50
|
-
expect(mockConfirmPrompt).not.toHaveBeenCalled();
|
|
51
|
-
expect(mockSimulatorService.runSimulator).toHaveBeenCalled();
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
test("should prompt for confirmation when localnet is already running", async () => {
|
|
55
|
-
mockSimulatorService.isLocalnetRunning = vi.fn().mockResolvedValue(true);
|
|
56
|
-
|
|
57
|
-
await startAction.execute(defaultOptions);
|
|
58
|
-
|
|
59
|
-
expect(mockSimulatorService.isLocalnetRunning).toHaveBeenCalled();
|
|
60
|
-
expect(mockConfirmPrompt).toHaveBeenCalledWith(
|
|
61
|
-
"GenLayer Localnet is already running. Do you want to proceed?",
|
|
62
|
-
);
|
|
63
|
-
expect(mockSimulatorService.runSimulator).toHaveBeenCalled();
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
test("should start the simulator successfully", async () => {
|
|
67
|
-
mockSimulatorService.checkCliVersion = vi.fn().mockResolvedValue(undefined);
|
|
68
|
-
mockSimulatorService.runSimulator = vi.fn().mockResolvedValue(undefined);
|
|
69
|
-
mockSimulatorService.getFrontendUrl = vi.fn().mockReturnValue("http://localhost:8080");
|
|
70
|
-
|
|
71
|
-
await startAction.execute(defaultOptions);
|
|
72
|
-
|
|
73
|
-
expect(startAction["startSpinner"]).toHaveBeenCalledWith("Checking CLI version...");
|
|
74
|
-
expect(mockSimulatorService.checkCliVersion).toHaveBeenCalled();
|
|
75
|
-
|
|
76
|
-
expect(startAction["setSpinnerText"]).toHaveBeenCalledWith(
|
|
77
|
-
"Starting GenLayer Localnet (keeping the existing validators)...",
|
|
78
|
-
);
|
|
79
|
-
expect(mockSimulatorService.runSimulator).toHaveBeenCalled();
|
|
80
|
-
|
|
81
|
-
expect(startAction["setSpinnerText"]).toHaveBeenCalledWith("Waiting for the simulator to be ready...");
|
|
82
|
-
expect(mockSimulatorService.waitForSimulatorToBeReady).toHaveBeenCalled();
|
|
83
|
-
|
|
84
|
-
expect(startAction["succeedSpinner"]).toHaveBeenCalledWith(
|
|
85
|
-
"GenLayer simulator initialized successfully! Go to http://localhost:8080 in your browser to access it.",
|
|
86
|
-
);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
test("should fail when simulator fails to start", async () => {
|
|
90
|
-
const errorMsg = new Error("runSimulator error");
|
|
91
|
-
(mockSimulatorService.runSimulator as Mock).mockRejectedValueOnce(errorMsg);
|
|
92
|
-
|
|
93
|
-
await startAction.execute(defaultOptions);
|
|
94
|
-
|
|
95
|
-
expect(startAction["failSpinner"]).toHaveBeenCalledWith("Error starting the simulator", errorMsg);
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
test("should fail when waiting for simulator initialization times out", async () => {
|
|
99
|
-
(mockSimulatorService.waitForSimulatorToBeReady as Mock).mockResolvedValue({
|
|
100
|
-
initialized: false,
|
|
101
|
-
errorCode: "TIMEOUT",
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
await startAction.execute(defaultOptions);
|
|
105
|
-
|
|
106
|
-
expect(startAction["failSpinner"]).toHaveBeenCalledWith(
|
|
107
|
-
"The simulator is taking too long to initialize. Please try again later.",
|
|
108
|
-
);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test("should reset the database if resetDb is true", async () => {
|
|
112
|
-
const options: StartActionOptions = {...defaultOptions, resetDb: true};
|
|
113
|
-
|
|
114
|
-
mockSimulatorService.cleanDatabase = vi.fn().mockResolvedValue(undefined);
|
|
115
|
-
|
|
116
|
-
await startAction.execute(options);
|
|
117
|
-
|
|
118
|
-
expect(startAction["setSpinnerText"]).toHaveBeenCalledWith("Resetting database...");
|
|
119
|
-
expect(mockSimulatorService.cleanDatabase).toHaveBeenCalled();
|
|
120
|
-
});
|
|
121
|
-
|
|
122
|
-
test("should initialize validators when resetValidators is true", async () => {
|
|
123
|
-
const options: StartActionOptions = {...defaultOptions, resetValidators: true};
|
|
124
|
-
|
|
125
|
-
mockSimulatorService.deleteAllValidators = vi.fn().mockResolvedValue(undefined);
|
|
126
|
-
mockSimulatorService.createRandomValidators = vi.fn().mockResolvedValue(undefined);
|
|
127
|
-
mockSimulatorService.getAiProvidersOptions = vi.fn().mockReturnValue(["Provider1", "Provider2"]);
|
|
128
|
-
|
|
129
|
-
vi.mocked(inquirer.prompt).mockResolvedValue({selectedLlmProviders: ["Provider1"]});
|
|
130
|
-
|
|
131
|
-
await startAction.execute(options);
|
|
132
|
-
|
|
133
|
-
expect(startAction["setSpinnerText"]).toHaveBeenCalledWith("Initializing validators...");
|
|
134
|
-
expect(mockSimulatorService.deleteAllValidators).toHaveBeenCalled();
|
|
135
|
-
expect(mockSimulatorService.createRandomValidators).toHaveBeenCalledWith(5, ["Provider1"]);
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
test("should fail when initializing validators fails", async () => {
|
|
139
|
-
const options: StartActionOptions = {...defaultOptions, resetValidators: true};
|
|
140
|
-
|
|
141
|
-
mockSimulatorService.deleteAllValidators = vi
|
|
142
|
-
.fn()
|
|
143
|
-
.mockRejectedValue(new Error("Failed to delete validators"));
|
|
144
|
-
|
|
145
|
-
await startAction.execute(options);
|
|
146
|
-
|
|
147
|
-
expect(startAction["failSpinner"]).toHaveBeenCalledWith(
|
|
148
|
-
"Unable to initialize the validators",
|
|
149
|
-
expect.any(Error),
|
|
150
|
-
);
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test("should open frontend when not in headless mode", async () => {
|
|
154
|
-
mockSimulatorService.checkCliVersion = vi.fn().mockResolvedValue(undefined);
|
|
155
|
-
mockSimulatorService.runSimulator = vi.fn().mockResolvedValue(undefined);
|
|
156
|
-
mockSimulatorService.getFrontendUrl = vi.fn().mockReturnValue("http://localhost:8080");
|
|
157
|
-
mockSimulatorService.openFrontend = vi.fn().mockResolvedValue(undefined);
|
|
158
|
-
|
|
159
|
-
await startAction.execute(defaultOptions);
|
|
160
|
-
|
|
161
|
-
expect(startAction["startSpinner"]).toHaveBeenCalledWith("Opening frontend...");
|
|
162
|
-
expect(mockSimulatorService.openFrontend).toHaveBeenCalled();
|
|
163
|
-
expect(startAction["succeedSpinner"]).toHaveBeenCalledWith("Frontend opened successfully");
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test("should handle errors when opening frontend", async () => {
|
|
167
|
-
const errorMsg = new Error("Failed to open frontend");
|
|
168
|
-
(mockSimulatorService.openFrontend as Mock).mockRejectedValueOnce(errorMsg);
|
|
169
|
-
|
|
170
|
-
await startAction.execute(defaultOptions);
|
|
171
|
-
|
|
172
|
-
expect(startAction["failSpinner"]).toHaveBeenCalledWith("Error opening the frontend", errorMsg);
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
test("should log specific message if waitForSimulatorToBeReady returns TIMEOUT errorCode", async () => {
|
|
176
|
-
(mockSimulatorService.waitForSimulatorToBeReady as Mock).mockResolvedValue({
|
|
177
|
-
initialized: false,
|
|
178
|
-
errorCode: "TIMEOUT",
|
|
179
|
-
errorMessage: "Initialization timed out",
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
await startAction.execute(defaultOptions);
|
|
183
|
-
|
|
184
|
-
expect(startAction["failSpinner"]).toHaveBeenCalledWith(
|
|
185
|
-
"The simulator is taking too long to initialize. Please try again later.",
|
|
186
|
-
);
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
test("should log error message if simulator fails to initialize with ERROR code", async () => {
|
|
190
|
-
(mockSimulatorService.waitForSimulatorToBeReady as Mock).mockResolvedValue({
|
|
191
|
-
initialized: false,
|
|
192
|
-
errorCode: "ERROR",
|
|
193
|
-
errorMessage: "Initialization failed",
|
|
194
|
-
});
|
|
195
|
-
|
|
196
|
-
await startAction.execute(defaultOptions);
|
|
197
|
-
|
|
198
|
-
expect(startAction["failSpinner"]).toHaveBeenCalledWith(
|
|
199
|
-
"Unable to initialize the GenLayer simulator.",
|
|
200
|
-
"Initialization failed",
|
|
201
|
-
);
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
test("catches and logs error if waitForSimulatorToBeReady throws an exception", async () => {
|
|
205
|
-
const errorMsg = new Error("Unexpected initialization error");
|
|
206
|
-
(mockSimulatorService.waitForSimulatorToBeReady as Mock).mockRejectedValueOnce(errorMsg);
|
|
207
|
-
|
|
208
|
-
await startAction.execute(defaultOptions);
|
|
209
|
-
|
|
210
|
-
expect(startAction["failSpinner"]).toHaveBeenCalledWith(
|
|
211
|
-
"Error waiting for the simulator to be ready",
|
|
212
|
-
errorMsg,
|
|
213
|
-
);
|
|
214
|
-
});
|
|
215
|
-
|
|
216
|
-
test("should not append frontend URL when in headless mode", async () => {
|
|
217
|
-
await startAction.execute({...defaultOptions, headless: true});
|
|
218
|
-
|
|
219
|
-
expect(startAction["succeedSpinner"]).toHaveBeenCalledWith(
|
|
220
|
-
"GenLayer simulator initialized successfully! ",
|
|
221
|
-
);
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
test("should exclude ollama from choices when ollama option is false", async () => {
|
|
225
|
-
await startAction.execute({ ...defaultOptions, resetValidators: true, ollama: false });
|
|
226
|
-
|
|
227
|
-
expect(mockSimulatorService.getAiProvidersOptions).toHaveBeenCalledWith(false, ["ollama"]);
|
|
228
|
-
});
|
|
229
|
-
|
|
230
|
-
test("should include ollama in choices when ollama option is true", async () => {
|
|
231
|
-
await startAction.execute({ ...defaultOptions, resetValidators: true, ollama: true });
|
|
232
|
-
|
|
233
|
-
expect(mockSimulatorService.getAiProvidersOptions).toHaveBeenCalledWith(false, []);
|
|
234
|
-
});
|
|
235
|
-
});
|