genlayer 0.25.0 → 0.26.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/README.md +8 -0
- package/dist/index.js +30 -5
- package/package.json +1 -1
- package/src/commands/contracts/index.ts +14 -4
- package/src/commands/contracts/schema.ts +31 -0
- package/tests/actions/schema.test.ts +94 -0
- package/tests/commands/schema.test.ts +67 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.26.0 (2025-08-07)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
|
|
7
|
+
* add schema command to inspect deployed contract schema ([#244](https://github.com/yeagerai/genlayer-cli/issues/244)) ([4d66a7b](https://github.com/yeagerai/genlayer-cli/commit/4d66a7b9b2ac813cf0d47f12fc82cbc06ed25b3c))
|
|
8
|
+
|
|
3
9
|
## 0.25.0 (2025-07-23)
|
|
4
10
|
|
|
5
11
|
### Features
|
package/README.md
CHANGED
|
@@ -146,6 +146,7 @@ USAGE:
|
|
|
146
146
|
genlayer deploy [options]
|
|
147
147
|
genlayer call <contractAddress> <method> [options]
|
|
148
148
|
genlayer write <contractAddress> <method> [options]
|
|
149
|
+
genlayer schema <contractAddress> [options]
|
|
149
150
|
|
|
150
151
|
OPTIONS (deploy):
|
|
151
152
|
--contract <contractPath> (Optional) Path to the intelligent contract to deploy
|
|
@@ -160,12 +161,16 @@ OPTIONS (write):
|
|
|
160
161
|
--rpc <rpcUrl> RPC URL for the network
|
|
161
162
|
--args <args...> Positional arguments for the method (space-separated, use quotes for multi-word arguments)
|
|
162
163
|
|
|
164
|
+
OPTIONS (schema):
|
|
165
|
+
--rpc <rpcUrl> RPC URL for the network
|
|
166
|
+
|
|
163
167
|
EXAMPLES:
|
|
164
168
|
genlayer deploy
|
|
165
169
|
genlayer deploy --contract ./my_contract.gpy
|
|
166
170
|
genlayer deploy --contract ./my_contract.gpy --args "arg1" "arg2" 123
|
|
167
171
|
genlayer call 0x123456789abcdef greet --args "Hello World!"
|
|
168
172
|
genlayer write 0x123456789abcdef updateValue --args 42
|
|
173
|
+
genlayer schema 0x123456789abcdef
|
|
169
174
|
```
|
|
170
175
|
|
|
171
176
|
##### Deploy Behavior
|
|
@@ -176,6 +181,9 @@ EXAMPLES:
|
|
|
176
181
|
- `call` - Calls a contract method without sending a transaction or changing the state (read-only)
|
|
177
182
|
- `write` - Sends a transaction to a contract method that modifies the state
|
|
178
183
|
|
|
184
|
+
##### Schema
|
|
185
|
+
- `schema` - Retrieves the contract schema
|
|
186
|
+
|
|
179
187
|
#### Keypair Management
|
|
180
188
|
|
|
181
189
|
Generate and manage keypairs.
|
package/dist/index.js
CHANGED
|
@@ -17856,7 +17856,7 @@ var require_semver2 = __commonJS({
|
|
|
17856
17856
|
import { program } from "commander";
|
|
17857
17857
|
|
|
17858
17858
|
// package.json
|
|
17859
|
-
var version = "0.
|
|
17859
|
+
var version = "0.26.0";
|
|
17860
17860
|
var package_default = {
|
|
17861
17861
|
name: "genlayer",
|
|
17862
17862
|
version,
|
|
@@ -42553,6 +42553,27 @@ var WriteAction = class extends BaseAction {
|
|
|
42553
42553
|
}
|
|
42554
42554
|
};
|
|
42555
42555
|
|
|
42556
|
+
// src/commands/contracts/schema.ts
|
|
42557
|
+
var SchemaAction = class extends BaseAction {
|
|
42558
|
+
constructor() {
|
|
42559
|
+
super();
|
|
42560
|
+
}
|
|
42561
|
+
async schema({
|
|
42562
|
+
contractAddress,
|
|
42563
|
+
rpc
|
|
42564
|
+
}) {
|
|
42565
|
+
const client = await this.getClient(rpc, true);
|
|
42566
|
+
await client.initializeConsensusSmartContract();
|
|
42567
|
+
this.startSpinner(`Getting schema for contract at ${contractAddress}...`);
|
|
42568
|
+
try {
|
|
42569
|
+
const result = await client.getContractSchema(contractAddress);
|
|
42570
|
+
this.succeedSpinner("Contract schema retrieved successfully", result);
|
|
42571
|
+
} catch (error) {
|
|
42572
|
+
this.failSpinner("Error retrieving contract schema", error);
|
|
42573
|
+
}
|
|
42574
|
+
}
|
|
42575
|
+
};
|
|
42576
|
+
|
|
42556
42577
|
// src/commands/contracts/index.ts
|
|
42557
42578
|
function parseArg(value, previous = []) {
|
|
42558
42579
|
if (value === "true") return [...previous, true];
|
|
@@ -42581,8 +42602,8 @@ function initializeContractsCommands(program2) {
|
|
|
42581
42602
|
parseArg,
|
|
42582
42603
|
[]
|
|
42583
42604
|
).action(async (contractAddress, method, options) => {
|
|
42584
|
-
const
|
|
42585
|
-
await
|
|
42605
|
+
const callAction = new CallAction();
|
|
42606
|
+
await callAction.call({ contractAddress, method, ...options });
|
|
42586
42607
|
});
|
|
42587
42608
|
program2.command("write <contractAddress> <method>").description("Sends a transaction to a contract method that modifies the state").option("--rpc <rpcUrl>", "RPC URL for the network").option(
|
|
42588
42609
|
"--args <args...>",
|
|
@@ -42590,8 +42611,12 @@ function initializeContractsCommands(program2) {
|
|
|
42590
42611
|
parseArg,
|
|
42591
42612
|
[]
|
|
42592
42613
|
).action(async (contractAddress, method, options) => {
|
|
42593
|
-
const
|
|
42594
|
-
await
|
|
42614
|
+
const writeAction = new WriteAction();
|
|
42615
|
+
await writeAction.write({ contractAddress, method, ...options });
|
|
42616
|
+
});
|
|
42617
|
+
program2.command("schema <contractAddress>").description("Get the schema for a deployed contract").option("--rpc <rpcUrl>", "RPC URL for the network").action(async (contractAddress, options) => {
|
|
42618
|
+
const schemaAction = new SchemaAction();
|
|
42619
|
+
await schemaAction.schema({ contractAddress, ...options });
|
|
42595
42620
|
});
|
|
42596
42621
|
return program2;
|
|
42597
42622
|
}
|
package/package.json
CHANGED
|
@@ -2,6 +2,7 @@ import {Command} from "commander";
|
|
|
2
2
|
import {DeployAction, DeployOptions, DeployScriptsOptions} from "./deploy";
|
|
3
3
|
import {CallAction, CallOptions} from "./call";
|
|
4
4
|
import {WriteAction, WriteOptions} from "./write";
|
|
5
|
+
import {SchemaAction, SchemaOptions} from "./schema";
|
|
5
6
|
|
|
6
7
|
function parseArg(value: string, previous: any[] = []): any[] {
|
|
7
8
|
if (value === "true") return [...previous, true];
|
|
@@ -43,8 +44,8 @@ export function initializeContractsCommands(program: Command) {
|
|
|
43
44
|
[],
|
|
44
45
|
)
|
|
45
46
|
.action(async (contractAddress: string, method: string, options: CallOptions) => {
|
|
46
|
-
const
|
|
47
|
-
await
|
|
47
|
+
const callAction = new CallAction();
|
|
48
|
+
await callAction.call({contractAddress, method, ...options});
|
|
48
49
|
});
|
|
49
50
|
|
|
50
51
|
program
|
|
@@ -58,8 +59,17 @@ export function initializeContractsCommands(program: Command) {
|
|
|
58
59
|
[],
|
|
59
60
|
)
|
|
60
61
|
.action(async (contractAddress: string, method: string, options: WriteOptions) => {
|
|
61
|
-
const
|
|
62
|
-
await
|
|
62
|
+
const writeAction = new WriteAction();
|
|
63
|
+
await writeAction.write({contractAddress, method, ...options});
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
program
|
|
67
|
+
.command("schema <contractAddress>")
|
|
68
|
+
.description("Get the schema for a deployed contract")
|
|
69
|
+
.option("--rpc <rpcUrl>", "RPC URL for the network")
|
|
70
|
+
.action(async (contractAddress: string, options: SchemaOptions) => {
|
|
71
|
+
const schemaAction = new SchemaAction();
|
|
72
|
+
await schemaAction.schema({contractAddress, ...options});
|
|
63
73
|
});
|
|
64
74
|
|
|
65
75
|
return program;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
2
|
+
import type {Address} from "genlayer-js/types";
|
|
3
|
+
|
|
4
|
+
export interface SchemaOptions {
|
|
5
|
+
rpc?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export class SchemaAction extends BaseAction {
|
|
9
|
+
constructor() {
|
|
10
|
+
super();
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
async schema({
|
|
14
|
+
contractAddress,
|
|
15
|
+
rpc,
|
|
16
|
+
}: {
|
|
17
|
+
contractAddress: string;
|
|
18
|
+
rpc?: string;
|
|
19
|
+
}): Promise<void> {
|
|
20
|
+
const client = await this.getClient(rpc, true);
|
|
21
|
+
await client.initializeConsensusSmartContract();
|
|
22
|
+
this.startSpinner(`Getting schema for contract at ${contractAddress}...`);
|
|
23
|
+
|
|
24
|
+
try {
|
|
25
|
+
const result = await client.getContractSchema(contractAddress as Address);
|
|
26
|
+
this.succeedSpinner("Contract schema retrieved successfully", result);
|
|
27
|
+
} catch (error) {
|
|
28
|
+
this.failSpinner("Error retrieving contract schema", error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import {describe, test, vi, beforeEach, afterEach, expect} from "vitest";
|
|
2
|
+
import {createClient, createAccount} from "genlayer-js";
|
|
3
|
+
import {SchemaAction} from "../../src/commands/contracts/schema";
|
|
4
|
+
|
|
5
|
+
vi.mock("genlayer-js");
|
|
6
|
+
|
|
7
|
+
describe("SchemaAction", () => {
|
|
8
|
+
let schemaAction: SchemaAction;
|
|
9
|
+
const mockClient = {
|
|
10
|
+
getContractSchema: vi.fn(),
|
|
11
|
+
initializeConsensusSmartContract: vi.fn(),
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const mockPrivateKey = "mocked_private_key";
|
|
15
|
+
|
|
16
|
+
beforeEach(() => {
|
|
17
|
+
vi.clearAllMocks();
|
|
18
|
+
vi.mocked(createClient).mockReturnValue(mockClient as any);
|
|
19
|
+
vi.mocked(createAccount).mockReturnValue({privateKey: mockPrivateKey} as any);
|
|
20
|
+
schemaAction = new SchemaAction();
|
|
21
|
+
vi.spyOn(schemaAction as any, "getAccount").mockResolvedValue({privateKey: mockPrivateKey});
|
|
22
|
+
|
|
23
|
+
vi.spyOn(schemaAction as any, "startSpinner").mockImplementation(() => {});
|
|
24
|
+
vi.spyOn(schemaAction as any, "succeedSpinner").mockImplementation(() => {});
|
|
25
|
+
vi.spyOn(schemaAction as any, "failSpinner").mockImplementation(() => {});
|
|
26
|
+
vi.spyOn(schemaAction as any, "log").mockImplementation(() => {});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
vi.restoreAllMocks();
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test("gets contract schema successfully", async () => {
|
|
34
|
+
const mockResult = {
|
|
35
|
+
methods: {
|
|
36
|
+
getData: {
|
|
37
|
+
params: [["value", "int"]],
|
|
38
|
+
ret: "int",
|
|
39
|
+
readonly: true,
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
vi.mocked(mockClient.getContractSchema).mockResolvedValue(mockResult);
|
|
45
|
+
|
|
46
|
+
await schemaAction.schema({
|
|
47
|
+
contractAddress: "0xMockedContract",
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect(mockClient.getContractSchema).toHaveBeenCalledWith("0xMockedContract");
|
|
51
|
+
expect(schemaAction["succeedSpinner"]).toHaveBeenCalledWith(
|
|
52
|
+
"Contract schema retrieved successfully",
|
|
53
|
+
mockResult,
|
|
54
|
+
);
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("handles getContractSchema errors", async () => {
|
|
58
|
+
vi.mocked(mockClient.getContractSchema).mockRejectedValue(new Error("Mocked schema error"));
|
|
59
|
+
|
|
60
|
+
await schemaAction.schema({contractAddress: "0xMockedContract"});
|
|
61
|
+
|
|
62
|
+
expect(schemaAction["failSpinner"]).toHaveBeenCalledWith("Error retrieving contract schema", expect.any(Error));
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("uses custom RPC URL when provided", async () => {
|
|
66
|
+
const mockResult = {methods: {}};
|
|
67
|
+
vi.mocked(mockClient.getContractSchema).mockResolvedValue(mockResult);
|
|
68
|
+
|
|
69
|
+
await schemaAction.schema({
|
|
70
|
+
contractAddress: "0xMockedContract",
|
|
71
|
+
rpc: "https://custom-rpc-url.com",
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(createClient).toHaveBeenCalledWith(
|
|
75
|
+
expect.objectContaining({
|
|
76
|
+
endpoint: "https://custom-rpc-url.com",
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
79
|
+
expect(mockClient.getContractSchema).toHaveBeenCalledWith("0xMockedContract");
|
|
80
|
+
expect(schemaAction["succeedSpinner"]).toHaveBeenCalledWith(
|
|
81
|
+
"Contract schema retrieved successfully",
|
|
82
|
+
mockResult,
|
|
83
|
+
);
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test("initializes consensus smart contract", async () => {
|
|
87
|
+
const mockResult = {methods: {}};
|
|
88
|
+
vi.mocked(mockClient.getContractSchema).mockResolvedValue(mockResult);
|
|
89
|
+
|
|
90
|
+
await schemaAction.schema({contractAddress: "0xMockedContract"});
|
|
91
|
+
|
|
92
|
+
expect(mockClient.initializeConsensusSmartContract).toHaveBeenCalled();
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { SchemaAction } from "../../src/commands/contracts/schema";
|
|
3
|
+
import { vi, describe, beforeEach, afterEach, test, expect } from "vitest";
|
|
4
|
+
import { initializeContractsCommands } from "../../src/commands/contracts";
|
|
5
|
+
|
|
6
|
+
vi.mock("../../src/commands/contracts/schema");
|
|
7
|
+
vi.mock("esbuild", () => ({
|
|
8
|
+
buildSync: vi.fn(),
|
|
9
|
+
}));
|
|
10
|
+
|
|
11
|
+
describe("schema command", () => {
|
|
12
|
+
let program: Command;
|
|
13
|
+
|
|
14
|
+
beforeEach(() => {
|
|
15
|
+
program = new Command();
|
|
16
|
+
initializeContractsCommands(program);
|
|
17
|
+
vi.clearAllMocks();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
afterEach(() => {
|
|
21
|
+
vi.restoreAllMocks();
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
test("SchemaAction.schema is called with default options", async () => {
|
|
25
|
+
program.parse(["node", "test", "schema", "0xMockedContract"]);
|
|
26
|
+
expect(SchemaAction).toHaveBeenCalledTimes(1);
|
|
27
|
+
expect(SchemaAction.prototype.schema).toHaveBeenCalledWith({
|
|
28
|
+
contractAddress: "0xMockedContract",
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
test("SchemaAction.schema is called with custom RPC URL", async () => {
|
|
33
|
+
program.parse([
|
|
34
|
+
"node",
|
|
35
|
+
"test",
|
|
36
|
+
"schema",
|
|
37
|
+
"0xMockedContract",
|
|
38
|
+
"--rpc",
|
|
39
|
+
"https://custom-rpc-url.com"
|
|
40
|
+
]);
|
|
41
|
+
expect(SchemaAction).toHaveBeenCalledTimes(1);
|
|
42
|
+
expect(SchemaAction.prototype.schema).toHaveBeenCalledWith({
|
|
43
|
+
contractAddress: "0xMockedContract",
|
|
44
|
+
rpc: "https://custom-rpc-url.com"
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("SchemaAction is instantiated when the schema command is executed", async () => {
|
|
49
|
+
program.parse(["node", "test", "schema", "0xMockedContract"]);
|
|
50
|
+
expect(SchemaAction).toHaveBeenCalledTimes(1);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test("throws error for unrecognized options", async () => {
|
|
54
|
+
const schemaCommand = program.commands.find((cmd) => cmd.name() === "schema");
|
|
55
|
+
schemaCommand?.exitOverride();
|
|
56
|
+
expect(() => program.parse(["node", "test", "schema", "0xMockedContract", "--unknown"]))
|
|
57
|
+
.toThrowError("error: unknown option '--unknown'");
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test("SchemaAction.schema is called without throwing errors for valid options", async () => {
|
|
61
|
+
program.parse(["node", "test", "schema", "0xMockedContract"]);
|
|
62
|
+
vi.mocked(SchemaAction.prototype.schema).mockResolvedValueOnce(undefined);
|
|
63
|
+
expect(() =>
|
|
64
|
+
program.parse(["node", "test", "schema", "0xMockedContract"])
|
|
65
|
+
).not.toThrow();
|
|
66
|
+
});
|
|
67
|
+
});
|