genlayer 0.18.5 → 0.19.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.
- package/CHANGELOG.md +6 -0
- package/dist/index.js +39 -1
- package/package.json +1 -1
- package/src/commands/transactions/appeal.ts +39 -0
- package/src/commands/transactions/index.ts +16 -0
- package/src/index.ts +2 -0
- package/tests/actions/appeal.test.ts +99 -0
- package/tests/commands/appeal.test.ts +58 -0
- package/tests/index.test.ts +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.0 (2025-07-09)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* appeal command ([#233](https://github.com/yeagerai/genlayer-cli/issues/233)) ([a33f882](https://github.com/yeagerai/genlayer-cli/commit/a33f882ec7f1e7758bbf6daef67b425be10e87f2))
|
|
8
|
+
|
|
3
9
|
## 0.18.5 (2025-07-09)
|
|
4
10
|
|
|
5
11
|
## 0.18.4 (2025-06-27)
|
package/dist/index.js
CHANGED
|
@@ -17723,7 +17723,7 @@ var require_semver2 = __commonJS({
|
|
|
17723
17723
|
import { program } from "commander";
|
|
17724
17724
|
|
|
17725
17725
|
// package.json
|
|
17726
|
-
var version = "0.
|
|
17726
|
+
var version = "0.19.0";
|
|
17727
17727
|
var package_default = {
|
|
17728
17728
|
name: "genlayer",
|
|
17729
17729
|
version,
|
|
@@ -42779,6 +42779,43 @@ function initializeNetworkCommands(program2) {
|
|
|
42779
42779
|
return program2;
|
|
42780
42780
|
}
|
|
42781
42781
|
|
|
42782
|
+
// src/commands/transactions/appeal.ts
|
|
42783
|
+
var AppealAction = class extends BaseAction {
|
|
42784
|
+
constructor() {
|
|
42785
|
+
super();
|
|
42786
|
+
}
|
|
42787
|
+
async appeal({
|
|
42788
|
+
txId,
|
|
42789
|
+
rpc
|
|
42790
|
+
}) {
|
|
42791
|
+
const client = await this.getClient(rpc);
|
|
42792
|
+
await client.initializeConsensusSmartContract();
|
|
42793
|
+
this.startSpinner(`Appealing transaction ${txId}...`);
|
|
42794
|
+
try {
|
|
42795
|
+
const hash2 = await client.appealTransaction({
|
|
42796
|
+
txId
|
|
42797
|
+
});
|
|
42798
|
+
const result = await client.waitForTransactionReceipt({
|
|
42799
|
+
hash: hash2,
|
|
42800
|
+
retries: 100,
|
|
42801
|
+
interval: 5e3
|
|
42802
|
+
});
|
|
42803
|
+
this.succeedSpinner("Appeal operation successfully executed", result);
|
|
42804
|
+
} catch (error) {
|
|
42805
|
+
this.failSpinner("Error during appeal operation", error);
|
|
42806
|
+
}
|
|
42807
|
+
}
|
|
42808
|
+
};
|
|
42809
|
+
|
|
42810
|
+
// src/commands/transactions/index.ts
|
|
42811
|
+
function initializeTransactionsCommands(program2) {
|
|
42812
|
+
program2.command("appeal <txId>").description("Appeal a transaction by its hash").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (txId, options) => {
|
|
42813
|
+
const appealAction = new AppealAction();
|
|
42814
|
+
await appealAction.appeal({ txId, ...options });
|
|
42815
|
+
});
|
|
42816
|
+
return program2;
|
|
42817
|
+
}
|
|
42818
|
+
|
|
42782
42819
|
// src/index.ts
|
|
42783
42820
|
function initializeCLI() {
|
|
42784
42821
|
program.version(version).description(CLI_DESCRIPTION);
|
|
@@ -42790,6 +42827,7 @@ function initializeCLI() {
|
|
|
42790
42827
|
initializeValidatorCommands(program);
|
|
42791
42828
|
initializeScaffoldCommands(program);
|
|
42792
42829
|
initializeNetworkCommands(program);
|
|
42830
|
+
initializeTransactionsCommands(program);
|
|
42793
42831
|
program.parse(process.argv);
|
|
42794
42832
|
}
|
|
42795
42833
|
initializeCLI();
|
package/package.json
CHANGED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import {TransactionHash} from "genlayer-js/types";
|
|
2
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
3
|
+
|
|
4
|
+
export interface AppealOptions {
|
|
5
|
+
rpc?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class AppealAction extends BaseAction {
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async appeal({
|
|
14
|
+
txId,
|
|
15
|
+
rpc,
|
|
16
|
+
}: {
|
|
17
|
+
txId: TransactionHash;
|
|
18
|
+
rpc?: string;
|
|
19
|
+
}): Promise<void> {
|
|
20
|
+
const client = await this.getClient(rpc);
|
|
21
|
+
await client.initializeConsensusSmartContract();
|
|
22
|
+
this.startSpinner(`Appealing transaction ${txId}...`);
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const hash = await client.appealTransaction({
|
|
26
|
+
txId,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const result = await client.waitForTransactionReceipt({
|
|
30
|
+
hash,
|
|
31
|
+
retries: 100,
|
|
32
|
+
interval: 5000,
|
|
33
|
+
});
|
|
34
|
+
this.succeedSpinner("Appeal operation successfully executed", result);
|
|
35
|
+
} catch (error) {
|
|
36
|
+
this.failSpinner("Error during appeal operation", error);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {Command} from "commander";
|
|
2
|
+
import {TransactionHash} from "genlayer-js/types";
|
|
3
|
+
import {AppealAction, AppealOptions} from "./appeal";
|
|
4
|
+
|
|
5
|
+
export function initializeTransactionsCommands(program: Command) {
|
|
6
|
+
program
|
|
7
|
+
.command("appeal <txId>")
|
|
8
|
+
.description("Appeal a transaction by its hash")
|
|
9
|
+
.option("--rpc <rpcUrl>", "RPC URL for the network")
|
|
10
|
+
.action(async (txId: TransactionHash, options: AppealOptions) => {
|
|
11
|
+
const appealAction = new AppealAction();
|
|
12
|
+
await appealAction.appeal({txId, ...options});
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
return program;
|
|
16
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,7 @@ import {initializeValidatorCommands} from "../src/commands/validators";
|
|
|
10
10
|
import {initializeUpdateCommands} from "../src/commands/update";
|
|
11
11
|
import {initializeScaffoldCommands} from "../src/commands/scaffold";
|
|
12
12
|
import {initializeNetworkCommands} from "../src/commands/network";
|
|
13
|
+
import {initializeTransactionsCommands} from "../src/commands/transactions";
|
|
13
14
|
|
|
14
15
|
export function initializeCLI() {
|
|
15
16
|
program.version(version).description(CLI_DESCRIPTION);
|
|
@@ -21,6 +22,7 @@ export function initializeCLI() {
|
|
|
21
22
|
initializeValidatorCommands(program);
|
|
22
23
|
initializeScaffoldCommands(program);
|
|
23
24
|
initializeNetworkCommands(program);
|
|
25
|
+
initializeTransactionsCommands(program);
|
|
24
26
|
program.parse(process.argv);
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {describe, test, vi, beforeEach, afterEach, expect} from "vitest";
|
|
2
|
+
import {createClient, createAccount} from "genlayer-js";
|
|
3
|
+
import type {TransactionHash} from "genlayer-js/types";
|
|
4
|
+
import {AppealAction} from "../../src/commands/transactions/appeal";
|
|
5
|
+
|
|
6
|
+
vi.mock("genlayer-js");
|
|
7
|
+
|
|
8
|
+
describe("AppealAction", () => {
|
|
9
|
+
let appealAction: AppealAction;
|
|
10
|
+
const mockClient = {
|
|
11
|
+
appealTransaction: vi.fn(),
|
|
12
|
+
waitForTransactionReceipt: vi.fn(),
|
|
13
|
+
initializeConsensusSmartContract: vi.fn(),
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const mockPrivateKey = "mocked_private_key";
|
|
17
|
+
const mockTxId = "0x1234567890123456789012345678901234567890123456789012345678901234" as TransactionHash;
|
|
18
|
+
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
vi.clearAllMocks();
|
|
21
|
+
vi.mocked(createClient).mockReturnValue(mockClient as any);
|
|
22
|
+
vi.mocked(createAccount).mockReturnValue({privateKey: mockPrivateKey} as any);
|
|
23
|
+
appealAction = new AppealAction();
|
|
24
|
+
vi.spyOn(appealAction as any, "getPrivateKey").mockResolvedValue(mockPrivateKey);
|
|
25
|
+
|
|
26
|
+
vi.spyOn(appealAction as any, "startSpinner").mockImplementation(() => {});
|
|
27
|
+
vi.spyOn(appealAction as any, "succeedSpinner").mockImplementation(() => {});
|
|
28
|
+
vi.spyOn(appealAction as any, "failSpinner").mockImplementation(() => {});
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
afterEach(() => {
|
|
32
|
+
vi.restoreAllMocks();
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("calls appealTransaction successfully", async () => {
|
|
36
|
+
const mockReceipt = {status: "success"};
|
|
37
|
+
|
|
38
|
+
vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue(mockReceipt);
|
|
39
|
+
|
|
40
|
+
await appealAction.appeal({
|
|
41
|
+
txId: mockTxId,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
expect(mockClient.appealTransaction).toHaveBeenCalledWith({
|
|
45
|
+
txId: mockTxId,
|
|
46
|
+
});
|
|
47
|
+
expect(appealAction["succeedSpinner"]).toHaveBeenCalledWith(
|
|
48
|
+
"Appeal operation successfully executed",
|
|
49
|
+
mockReceipt,
|
|
50
|
+
);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("handles appealTransaction errors", async () => {
|
|
54
|
+
vi.mocked(mockClient.appealTransaction).mockRejectedValue(new Error("Mocked appeal error"));
|
|
55
|
+
|
|
56
|
+
await appealAction.appeal({txId: mockTxId});
|
|
57
|
+
|
|
58
|
+
expect(appealAction["failSpinner"]).toHaveBeenCalledWith(
|
|
59
|
+
"Error during appeal operation",
|
|
60
|
+
expect.any(Error),
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("uses custom RPC URL for appeal operations", async () => {
|
|
65
|
+
const rpcUrl = "https://custom-rpc-url.com";
|
|
66
|
+
const mockReceipt = {status: "success"};
|
|
67
|
+
|
|
68
|
+
vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue(mockReceipt);
|
|
69
|
+
|
|
70
|
+
await appealAction.appeal({
|
|
71
|
+
txId: mockTxId,
|
|
72
|
+
rpc: rpcUrl,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
expect(createClient).toHaveBeenCalledWith(
|
|
76
|
+
expect.objectContaining({
|
|
77
|
+
endpoint: rpcUrl,
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
expect(mockClient.appealTransaction).toHaveBeenCalledWith({
|
|
81
|
+
txId: mockTxId,
|
|
82
|
+
});
|
|
83
|
+
expect(appealAction["succeedSpinner"]).toHaveBeenCalledWith(
|
|
84
|
+
"Appeal operation successfully executed",
|
|
85
|
+
mockReceipt,
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test("initializes consensus smart contract before appeal", async () => {
|
|
90
|
+
const mockReceipt = {status: "success"};
|
|
91
|
+
|
|
92
|
+
vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue(mockReceipt);
|
|
93
|
+
|
|
94
|
+
await appealAction.appeal({txId: mockTxId});
|
|
95
|
+
|
|
96
|
+
expect(mockClient.initializeConsensusSmartContract).toHaveBeenCalledTimes(1);
|
|
97
|
+
expect(mockClient.appealTransaction).toHaveBeenCalled();
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import {Command} from "commander";
|
|
2
|
+
import {AppealAction} from "../../src/commands/transactions/appeal";
|
|
3
|
+
import {vi, describe, beforeEach, afterEach, test, expect} from "vitest";
|
|
4
|
+
import {initializeTransactionsCommands} from "../../src/commands/transactions";
|
|
5
|
+
|
|
6
|
+
vi.mock("../../src/commands/transactions/appeal");
|
|
7
|
+
|
|
8
|
+
describe("appeal command", () => {
|
|
9
|
+
let program: Command;
|
|
10
|
+
const mockTxId = "0x1234567890123456789012345678901234567890123456789012345678901234";
|
|
11
|
+
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
program = new Command();
|
|
14
|
+
initializeTransactionsCommands(program);
|
|
15
|
+
vi.clearAllMocks();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
afterEach(() => {
|
|
19
|
+
vi.restoreAllMocks();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test("AppealAction.appeal is called with default options", async () => {
|
|
23
|
+
program.parse(["node", "test", "appeal", mockTxId]);
|
|
24
|
+
expect(AppealAction).toHaveBeenCalledTimes(1);
|
|
25
|
+
expect(AppealAction.prototype.appeal).toHaveBeenCalledWith({
|
|
26
|
+
txId: mockTxId,
|
|
27
|
+
});
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
test("AppealAction.appeal is called with custom RPC URL", async () => {
|
|
31
|
+
program.parse([
|
|
32
|
+
"node",
|
|
33
|
+
"test",
|
|
34
|
+
"appeal",
|
|
35
|
+
mockTxId,
|
|
36
|
+
"--rpc",
|
|
37
|
+
"https://custom-rpc-url-for-appeal.com",
|
|
38
|
+
]);
|
|
39
|
+
expect(AppealAction).toHaveBeenCalledTimes(1);
|
|
40
|
+
expect(AppealAction.prototype.appeal).toHaveBeenCalledWith({
|
|
41
|
+
txId: mockTxId,
|
|
42
|
+
rpc: "https://custom-rpc-url-for-appeal.com",
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test("AppealAction is instantiated when the appeal command is executed", async () => {
|
|
47
|
+
program.parse(["node", "test", "appeal", mockTxId]);
|
|
48
|
+
expect(AppealAction).toHaveBeenCalledTimes(1);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
test("throws error for unrecognized options", async () => {
|
|
52
|
+
const appealCommand = program.commands.find(cmd => cmd.name() === "appeal");
|
|
53
|
+
appealCommand?.exitOverride();
|
|
54
|
+
expect(() =>
|
|
55
|
+
program.parse(["node", "test", "appeal", mockTxId, "--invalid-option"]),
|
|
56
|
+
).toThrowError("error: unknown option '--invalid-option'");
|
|
57
|
+
});
|
|
58
|
+
});
|
package/tests/index.test.ts
CHANGED
|
@@ -41,6 +41,10 @@ vi.mock("../src/commands/network", () => ({
|
|
|
41
41
|
initializeNetworkCommands: vi.fn(),
|
|
42
42
|
}));
|
|
43
43
|
|
|
44
|
+
vi.mock("../src/commands/transactions", () => ({
|
|
45
|
+
initializeTransactionsCommands: vi.fn(),
|
|
46
|
+
}));
|
|
47
|
+
|
|
44
48
|
describe("CLI", () => {
|
|
45
49
|
it("should initialize CLI", () => {
|
|
46
50
|
expect(initializeCLI).not.toThrow();
|