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,162 +0,0 @@
|
|
|
1
|
-
import {BaseAction, BUILT_IN_NETWORKS, resolveNetwork} from "../../lib/actions/BaseAction";
|
|
2
|
-
import {parseEther, formatEther} from "viem";
|
|
3
|
-
import {createClient, createAccount} from "genlayer-js";
|
|
4
|
-
import type {GenLayerChain, Address, Hash} from "genlayer-js/types";
|
|
5
|
-
import {readFileSync, existsSync} from "fs";
|
|
6
|
-
import {ethers} from "ethers";
|
|
7
|
-
|
|
8
|
-
export interface SendOptions {
|
|
9
|
-
to: string;
|
|
10
|
-
amount: string;
|
|
11
|
-
rpc?: string;
|
|
12
|
-
network?: string;
|
|
13
|
-
account?: string;
|
|
14
|
-
password?: string;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
export class SendAction extends BaseAction {
|
|
18
|
-
constructor() {
|
|
19
|
-
super();
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
private getNetwork(networkOption?: string): GenLayerChain {
|
|
23
|
-
if (networkOption) {
|
|
24
|
-
const network = BUILT_IN_NETWORKS[networkOption];
|
|
25
|
-
if (!network) {
|
|
26
|
-
throw new Error(`Unknown network: ${networkOption}. Available: ${Object.keys(BUILT_IN_NETWORKS).join(", ")}`);
|
|
27
|
-
}
|
|
28
|
-
return network;
|
|
29
|
-
}
|
|
30
|
-
return resolveNetwork(this.getConfig().network);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
private parseAmount(amount: string): bigint {
|
|
34
|
-
// Support "10gen" or "10" (assumes gen) or wei values
|
|
35
|
-
const lowerAmount = amount.toLowerCase();
|
|
36
|
-
if (lowerAmount.endsWith("gen")) {
|
|
37
|
-
const value = lowerAmount.slice(0, -3);
|
|
38
|
-
return parseEther(value);
|
|
39
|
-
}
|
|
40
|
-
// If it's a large number (likely wei), use as-is
|
|
41
|
-
if (BigInt(amount) > 1_000_000_000_000n) {
|
|
42
|
-
return BigInt(amount);
|
|
43
|
-
}
|
|
44
|
-
// Otherwise assume it's in GEN
|
|
45
|
-
return parseEther(amount);
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async execute(options: SendOptions): Promise<void> {
|
|
49
|
-
this.startSpinner("Preparing transfer...");
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
if (options.account) {
|
|
53
|
-
this.accountOverride = options.account;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
const accountName = this.resolveAccountName();
|
|
57
|
-
const keystorePath = this.getKeystorePath(accountName);
|
|
58
|
-
|
|
59
|
-
if (!existsSync(keystorePath)) {
|
|
60
|
-
this.failSpinner(`Account '${accountName}' not found. Run 'genlayer account create --name ${accountName}' first.`);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const keystoreJson = readFileSync(keystorePath, "utf-8");
|
|
65
|
-
const keystoreData = JSON.parse(keystoreJson);
|
|
66
|
-
|
|
67
|
-
if (!this.isValidKeystoreFormat(keystoreData)) {
|
|
68
|
-
this.failSpinner("Invalid keystore format.");
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Get private key
|
|
73
|
-
const cachedKey = await this.keychainManager.getPrivateKey(accountName);
|
|
74
|
-
let privateKey: string;
|
|
75
|
-
|
|
76
|
-
if (cachedKey) {
|
|
77
|
-
privateKey = cachedKey;
|
|
78
|
-
} else {
|
|
79
|
-
let password: string;
|
|
80
|
-
if (options.password) {
|
|
81
|
-
password = options.password;
|
|
82
|
-
} else {
|
|
83
|
-
this.stopSpinner();
|
|
84
|
-
password = await this.promptPassword(`Enter password to unlock account '${accountName}':`);
|
|
85
|
-
this.startSpinner("Preparing transfer...");
|
|
86
|
-
}
|
|
87
|
-
const wallet = await ethers.Wallet.fromEncryptedJson(keystoreJson, password);
|
|
88
|
-
privateKey = wallet.privateKey;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
const network = this.getNetwork(options.network);
|
|
92
|
-
const account = createAccount(privateKey as Hash);
|
|
93
|
-
const amount = this.parseAmount(options.amount);
|
|
94
|
-
|
|
95
|
-
const client = createClient({
|
|
96
|
-
chain: network,
|
|
97
|
-
account,
|
|
98
|
-
endpoint: options.rpc,
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
this.setSpinnerText(`Sending ${formatEther(amount)} GEN to ${options.to}...`);
|
|
102
|
-
|
|
103
|
-
// Get nonce
|
|
104
|
-
const nonce = await client.getCurrentNonce({address: account.address});
|
|
105
|
-
|
|
106
|
-
// Prepare and sign transaction (let prepareTransactionRequest estimate gas)
|
|
107
|
-
const transactionRequest = await client.prepareTransactionRequest({
|
|
108
|
-
account,
|
|
109
|
-
to: options.to as Address,
|
|
110
|
-
value: amount,
|
|
111
|
-
type: "legacy",
|
|
112
|
-
nonce: Number(nonce),
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
const serializedTransaction = await account.signTransaction(transactionRequest);
|
|
116
|
-
const txHash = await client.sendRawTransaction({serializedTransaction});
|
|
117
|
-
|
|
118
|
-
this.setSpinnerText(`Transaction submitted: ${txHash}\nWaiting for confirmation...`);
|
|
119
|
-
|
|
120
|
-
// Poll for receipt (standard ETH transfer, not GenVM tx)
|
|
121
|
-
let receipt = null;
|
|
122
|
-
for (let i = 0; i < 60; i++) {
|
|
123
|
-
try {
|
|
124
|
-
receipt = await client.getTransactionReceipt({hash: txHash});
|
|
125
|
-
if (receipt) break;
|
|
126
|
-
} catch {
|
|
127
|
-
// Receipt not available yet, continue polling
|
|
128
|
-
}
|
|
129
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (!receipt) {
|
|
133
|
-
// Tx submitted but receipt not found yet - still success
|
|
134
|
-
this.succeedSpinner("Transfer submitted (pending confirmation)", {
|
|
135
|
-
transactionHash: txHash,
|
|
136
|
-
from: account.address,
|
|
137
|
-
to: options.to,
|
|
138
|
-
amount: `${formatEther(amount)} GEN`,
|
|
139
|
-
});
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
if (receipt.status === "reverted") {
|
|
144
|
-
this.failSpinner("Transaction reverted");
|
|
145
|
-
return;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
const result = {
|
|
149
|
-
transactionHash: txHash,
|
|
150
|
-
from: account.address,
|
|
151
|
-
to: options.to,
|
|
152
|
-
amount: `${formatEther(amount)} GEN`,
|
|
153
|
-
blockNumber: receipt.blockNumber.toString(),
|
|
154
|
-
gasUsed: receipt.gasUsed.toString(),
|
|
155
|
-
};
|
|
156
|
-
|
|
157
|
-
this.succeedSpinner("Transfer successful!", result);
|
|
158
|
-
} catch (error: any) {
|
|
159
|
-
this.failSpinner("Transfer failed", error.message || error);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
}
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import {BaseAction, resolveNetwork} from "../../lib/actions/BaseAction";
|
|
2
|
-
import {formatEther} from "viem";
|
|
3
|
-
import {createClient} from "genlayer-js";
|
|
4
|
-
import type {GenLayerChain, Address} from "genlayer-js/types";
|
|
5
|
-
import {readFileSync, existsSync} from "fs";
|
|
6
|
-
|
|
7
|
-
export interface ShowAccountOptions {
|
|
8
|
-
rpc?: string;
|
|
9
|
-
account?: string;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export class ShowAccountAction extends BaseAction {
|
|
13
|
-
constructor() {
|
|
14
|
-
super();
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
private getNetwork(): GenLayerChain {
|
|
18
|
-
return resolveNetwork(this.getConfig().network);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
async execute(options?: ShowAccountOptions): Promise<void> {
|
|
22
|
-
this.startSpinner("Fetching account info...");
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
if (options?.account) {
|
|
26
|
-
this.accountOverride = options.account;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const accountName = this.resolveAccountName();
|
|
30
|
-
const keystorePath = this.getKeystorePath(accountName);
|
|
31
|
-
|
|
32
|
-
if (!existsSync(keystorePath)) {
|
|
33
|
-
this.failSpinner(`Account '${accountName}' not found. Run 'genlayer account create --name ${accountName}' first.`);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const keystoreData = JSON.parse(readFileSync(keystorePath, "utf-8"));
|
|
38
|
-
|
|
39
|
-
if (!this.isValidKeystoreFormat(keystoreData)) {
|
|
40
|
-
this.failSpinner("Invalid keystore format.");
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
const rawAddr = keystoreData.address;
|
|
45
|
-
const address = (rawAddr.startsWith("0x") ? rawAddr : `0x${rawAddr}`) as Address;
|
|
46
|
-
const network = this.getNetwork();
|
|
47
|
-
|
|
48
|
-
const client = createClient({
|
|
49
|
-
chain: network,
|
|
50
|
-
account: address,
|
|
51
|
-
endpoint: options?.rpc,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
const balance = await client.getBalance({address});
|
|
55
|
-
const formattedBalance = formatEther(balance);
|
|
56
|
-
|
|
57
|
-
const isUnlocked = await this.keychainManager.isAccountUnlocked(accountName);
|
|
58
|
-
const isActive = this.getActiveAccount() === accountName;
|
|
59
|
-
|
|
60
|
-
const result = {
|
|
61
|
-
name: accountName,
|
|
62
|
-
address,
|
|
63
|
-
balance: `${formattedBalance} GEN`,
|
|
64
|
-
network: network.name || "localnet",
|
|
65
|
-
status: isUnlocked ? "unlocked" : "locked",
|
|
66
|
-
active: isActive,
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
this.succeedSpinner("Account info", result);
|
|
70
|
-
} catch (error: any) {
|
|
71
|
-
this.failSpinner("Failed to get account info", error.message || error);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
2
|
-
import {readFileSync, existsSync} from "fs";
|
|
3
|
-
import {ethers} from "ethers";
|
|
4
|
-
|
|
5
|
-
export interface UnlockAccountOptions {
|
|
6
|
-
account?: string;
|
|
7
|
-
password?: string;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export class UnlockAccountAction extends BaseAction {
|
|
11
|
-
async execute(options?: UnlockAccountOptions): Promise<void> {
|
|
12
|
-
this.startSpinner("Checking keychain availability...");
|
|
13
|
-
|
|
14
|
-
const keychainAvailable = await this.keychainManager.isKeychainAvailable();
|
|
15
|
-
if (!keychainAvailable) {
|
|
16
|
-
this.failSpinner("OS keychain is not available. This command requires a supported keychain (e.g. macOS Keychain, Windows Credential Manager, or GNOME Keyring).");
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (options?.account) {
|
|
21
|
-
this.accountOverride = options.account;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const accountName = this.resolveAccountName();
|
|
25
|
-
this.setSpinnerText(`Checking for account '${accountName}'...`);
|
|
26
|
-
|
|
27
|
-
const keystorePath = this.getKeystorePath(accountName);
|
|
28
|
-
if (!existsSync(keystorePath)) {
|
|
29
|
-
this.failSpinner(`Account '${accountName}' not found. Run 'genlayer account create --name ${accountName}' first.`);
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const keystoreJson = readFileSync(keystorePath, "utf-8");
|
|
34
|
-
const keystoreData = JSON.parse(keystoreJson);
|
|
35
|
-
if (!this.isValidKeystoreFormat(keystoreData)) {
|
|
36
|
-
this.failSpinner("Invalid keystore format.");
|
|
37
|
-
return;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
let password: string;
|
|
42
|
-
if (options?.password) {
|
|
43
|
-
password = options.password;
|
|
44
|
-
} else {
|
|
45
|
-
this.stopSpinner();
|
|
46
|
-
password = await this.promptPassword(`Enter password to unlock '${accountName}':`);
|
|
47
|
-
}
|
|
48
|
-
const wallet = await ethers.Wallet.fromEncryptedJson(keystoreJson, password);
|
|
49
|
-
|
|
50
|
-
await this.keychainManager.storePrivateKey(accountName, wallet.privateKey);
|
|
51
|
-
this.succeedSpinner(`Account '${accountName}' unlocked! Private key cached in OS keychain.`);
|
|
52
|
-
} catch (error) {
|
|
53
|
-
this.failSpinner("Failed to unlock account.", error);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
2
|
-
|
|
3
|
-
export class UseAccountAction extends BaseAction {
|
|
4
|
-
constructor() {
|
|
5
|
-
super();
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
async execute(name: string): Promise<void> {
|
|
9
|
-
try {
|
|
10
|
-
if (!this.accountExists(name)) {
|
|
11
|
-
this.failSpinner(`Account '${name}' does not exist. Run 'genlayer account list' to see available accounts.`);
|
|
12
|
-
return;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
this.setActiveAccount(name);
|
|
16
|
-
this.logSuccess(`Active account set to '${name}'`);
|
|
17
|
-
} catch (error) {
|
|
18
|
-
this.failSpinner("Failed to set active account", error);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { BaseAction } from "../../lib/actions/BaseAction";
|
|
2
|
-
|
|
3
|
-
export class ConfigActions extends BaseAction {
|
|
4
|
-
|
|
5
|
-
constructor() {
|
|
6
|
-
super();
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
set(keyValue: string): void {
|
|
10
|
-
const [key, value] = keyValue.split("=");
|
|
11
|
-
this.startSpinner(`Updating configuration: ${key}`);
|
|
12
|
-
|
|
13
|
-
if (!key || value === undefined) {
|
|
14
|
-
this.failSpinner("Invalid format. Use 'key=value'.");
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
this.writeConfig(key, value);
|
|
19
|
-
this.succeedSpinner(`Configuration successfully updated`);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
get(key?: string): void {
|
|
23
|
-
this.startSpinner(key ? `Retrieving value for: ${key}` : "Retrieving all configurations");
|
|
24
|
-
|
|
25
|
-
if (key) {
|
|
26
|
-
const value = this.getConfigByKey(key);
|
|
27
|
-
if (value === null) {
|
|
28
|
-
this.failSpinner(`No configuration found for '${key}'.`);
|
|
29
|
-
} else {
|
|
30
|
-
this.succeedSpinner(`Configuration successfully retrieved`, `${key}=${value}`);
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
const config = this.getConfig();
|
|
34
|
-
this.succeedSpinner("All configurations successfully retrieved", JSON.stringify(config, null, 2));
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
reset(key: string): void {
|
|
39
|
-
this.startSpinner(`Resetting configuration: ${key}`);
|
|
40
|
-
|
|
41
|
-
const config = this.getConfig();
|
|
42
|
-
if (!(key in config)) {
|
|
43
|
-
this.failSpinner(`Configuration key '${key}' does not exist.`);
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
delete config[key];
|
|
48
|
-
this.writeConfig(key, undefined);
|
|
49
|
-
this.succeedSpinner(`Configuration successfully reset`);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Command } from "commander";
|
|
2
|
-
import { ConfigActions } from "./getSetReset";
|
|
3
|
-
|
|
4
|
-
export function initializeConfigCommands(program: Command) {
|
|
5
|
-
const configActions = new ConfigActions();
|
|
6
|
-
|
|
7
|
-
const configCommand = program
|
|
8
|
-
.command("config")
|
|
9
|
-
.description("Manage CLI configuration, including the default network");
|
|
10
|
-
|
|
11
|
-
configCommand
|
|
12
|
-
.command("set")
|
|
13
|
-
.description("Set a configuration value")
|
|
14
|
-
.argument("<key=value>", "Configuration key-value pair to set")
|
|
15
|
-
.action((keyValue: string) => configActions.set(keyValue));
|
|
16
|
-
|
|
17
|
-
configCommand
|
|
18
|
-
.command("get")
|
|
19
|
-
.description("Get the current configuration")
|
|
20
|
-
.argument("[key]", "Configuration key to retrieve")
|
|
21
|
-
.action((key?: string) => configActions.get(key));
|
|
22
|
-
|
|
23
|
-
configCommand
|
|
24
|
-
.command("reset")
|
|
25
|
-
.description("Reset a configuration value to its default")
|
|
26
|
-
.argument("<key>", "Configuration key to reset")
|
|
27
|
-
.action((key: string) => configActions.reset(key));
|
|
28
|
-
|
|
29
|
-
return program;
|
|
30
|
-
}
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
2
|
-
|
|
3
|
-
export interface CallOptions {
|
|
4
|
-
args: any[];
|
|
5
|
-
rpc?: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export class CallAction extends BaseAction {
|
|
9
|
-
constructor() {
|
|
10
|
-
super();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async call({
|
|
14
|
-
contractAddress,
|
|
15
|
-
method,
|
|
16
|
-
args,
|
|
17
|
-
rpc,
|
|
18
|
-
}: {
|
|
19
|
-
contractAddress: string;
|
|
20
|
-
method: string;
|
|
21
|
-
args: any[];
|
|
22
|
-
rpc?: string;
|
|
23
|
-
}): Promise<void> {
|
|
24
|
-
const client = await this.getClient(rpc, true);
|
|
25
|
-
await client.initializeConsensusSmartContract();
|
|
26
|
-
this.startSpinner(`Calling method ${method} on contract at ${contractAddress}...`);
|
|
27
|
-
|
|
28
|
-
try {
|
|
29
|
-
const result = await client.readContract({
|
|
30
|
-
address: contractAddress as any,
|
|
31
|
-
functionName: method,
|
|
32
|
-
args,
|
|
33
|
-
});
|
|
34
|
-
this.succeedSpinner("Read operation successfully executed", result);
|
|
35
|
-
} catch (error) {
|
|
36
|
-
this.failSpinner("Error during read operation", error);
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
2
|
-
import type {Address} from "genlayer-js/types";
|
|
3
|
-
|
|
4
|
-
export interface CodeOptions {
|
|
5
|
-
rpc?: string;
|
|
6
|
-
}
|
|
7
|
-
|
|
8
|
-
export class CodeAction extends BaseAction {
|
|
9
|
-
constructor() {
|
|
10
|
-
super();
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
async code({
|
|
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 code for contract at ${contractAddress}...`);
|
|
23
|
-
|
|
24
|
-
try {
|
|
25
|
-
const result = await client.getContractCode(contractAddress as Address);
|
|
26
|
-
this.succeedSpinner("Contract code retrieved successfully", result);
|
|
27
|
-
} catch (error) {
|
|
28
|
-
this.failSpinner("Error retrieving contract code", error);
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
@@ -1,157 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import {BaseAction} from "../../lib/actions/BaseAction";
|
|
4
|
-
import {pathToFileURL} from "url";
|
|
5
|
-
import {TransactionStatus} from "genlayer-js/types";
|
|
6
|
-
import {buildSync} from "esbuild";
|
|
7
|
-
|
|
8
|
-
export interface DeployOptions {
|
|
9
|
-
contract?: string;
|
|
10
|
-
args?: any[];
|
|
11
|
-
rpc?: string;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export interface DeployScriptsOptions {
|
|
15
|
-
rpc?: string;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export class DeployAction extends BaseAction {
|
|
19
|
-
private readonly deployDir = path.resolve(process.cwd(), "deploy");
|
|
20
|
-
|
|
21
|
-
constructor() {
|
|
22
|
-
super();
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
private readContractCode(contractPath: string): string {
|
|
26
|
-
if (!fs.existsSync(contractPath)) {
|
|
27
|
-
throw new Error(`Contract file not found: ${contractPath}`);
|
|
28
|
-
}
|
|
29
|
-
return fs.readFileSync(contractPath, "utf-8");
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
private async executeTsScript(filePath: string, rpcUrl?: string): Promise<void> {
|
|
33
|
-
const outFile = filePath.replace(/\.ts$/, ".compiled.js");
|
|
34
|
-
this.startSpinner(`Transpiling TypeScript file: ${filePath}`);
|
|
35
|
-
try {
|
|
36
|
-
buildSync({
|
|
37
|
-
entryPoints: [filePath],
|
|
38
|
-
outfile: outFile,
|
|
39
|
-
bundle: false,
|
|
40
|
-
platform: "node",
|
|
41
|
-
format: "esm",
|
|
42
|
-
target: "es2020",
|
|
43
|
-
sourcemap: false,
|
|
44
|
-
});
|
|
45
|
-
await this.executeJsScript(filePath, outFile, rpcUrl);
|
|
46
|
-
} catch (error) {
|
|
47
|
-
this.failSpinner(`Error executing: ${filePath}`, error);
|
|
48
|
-
} finally {
|
|
49
|
-
fs.unlinkSync(outFile);
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
private async executeJsScript(
|
|
54
|
-
filePath: string,
|
|
55
|
-
transpiledFilePath?: string,
|
|
56
|
-
rpcUrl?: string,
|
|
57
|
-
): Promise<void> {
|
|
58
|
-
this.startSpinner(`Executing file: ${filePath}`);
|
|
59
|
-
try {
|
|
60
|
-
const module = await import(pathToFileURL(transpiledFilePath || filePath).href);
|
|
61
|
-
if (!module.default || typeof module.default !== "function") {
|
|
62
|
-
this.failSpinner(`No "default" function found in: ${filePath}`);
|
|
63
|
-
return;
|
|
64
|
-
}
|
|
65
|
-
const client = await this.getClient(rpcUrl);
|
|
66
|
-
await module.default(client);
|
|
67
|
-
this.succeedSpinner(`Successfully executed: ${filePath}`);
|
|
68
|
-
} catch (error) {
|
|
69
|
-
this.failSpinner(`Error executing: ${filePath}`, error);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
async deployScripts(options?: DeployScriptsOptions) {
|
|
74
|
-
this.startSpinner("Searching for deploy scripts...");
|
|
75
|
-
if (!fs.existsSync(this.deployDir)) {
|
|
76
|
-
this.failSpinner("No deploy folder found.");
|
|
77
|
-
return;
|
|
78
|
-
}
|
|
79
|
-
const files = fs
|
|
80
|
-
.readdirSync(this.deployDir)
|
|
81
|
-
.filter(file => file.endsWith(".ts") || file.endsWith(".js"))
|
|
82
|
-
.sort((a, b) => {
|
|
83
|
-
const numA = parseInt(a.split("_")[0]);
|
|
84
|
-
const numB = parseInt(b.split("_")[0]);
|
|
85
|
-
|
|
86
|
-
if (!isNaN(numA) && !isNaN(numB)) return numA - numB;
|
|
87
|
-
if (!isNaN(numA)) return -1;
|
|
88
|
-
if (!isNaN(numB)) return 1;
|
|
89
|
-
return a.localeCompare(b);
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
if (files.length === 0) {
|
|
93
|
-
this.failSpinner("No deploy scripts found.");
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
this.setSpinnerText(`Found ${files.length} deploy scripts. Executing...`);
|
|
98
|
-
|
|
99
|
-
for (const file of files) {
|
|
100
|
-
const filePath = path.resolve(this.deployDir, file);
|
|
101
|
-
this.setSpinnerText(`Executing script: ${filePath}`);
|
|
102
|
-
try {
|
|
103
|
-
if (file.endsWith(".ts")) {
|
|
104
|
-
await this.executeTsScript(filePath, options?.rpc);
|
|
105
|
-
} else {
|
|
106
|
-
await this.executeJsScript(filePath, undefined, options?.rpc);
|
|
107
|
-
}
|
|
108
|
-
} catch (error) {
|
|
109
|
-
this.failSpinner(`Error executing script: ${filePath}`, error);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async deploy(options: DeployOptions): Promise<void> {
|
|
115
|
-
try {
|
|
116
|
-
const client = await this.getClient(options.rpc);
|
|
117
|
-
this.startSpinner("Setting up the deployment environment...");
|
|
118
|
-
await client.initializeConsensusSmartContract();
|
|
119
|
-
|
|
120
|
-
if (!options.contract) {
|
|
121
|
-
this.failSpinner("No contract specified for deployment.");
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
this.setSpinnerText("Reading contract code...");
|
|
125
|
-
const contractCode = this.readContractCode(options.contract);
|
|
126
|
-
|
|
127
|
-
if (!contractCode) {
|
|
128
|
-
this.failSpinner("Contract code is empty.");
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const leaderOnly = false;
|
|
133
|
-
const deployParams: any = {code: contractCode, args: options.args, leaderOnly};
|
|
134
|
-
|
|
135
|
-
this.setSpinnerText("Starting contract deployment...");
|
|
136
|
-
this.log("Deployment Parameters:", deployParams);
|
|
137
|
-
|
|
138
|
-
const hash = (await client.deployContract(deployParams)) as any;
|
|
139
|
-
this.log("Deployment Transaction Hash:", hash);
|
|
140
|
-
const result = await client.waitForTransactionReceipt({
|
|
141
|
-
hash,
|
|
142
|
-
retries: 50,
|
|
143
|
-
interval: 5000,
|
|
144
|
-
status: TransactionStatus.ACCEPTED,
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
this.log("Deployment Receipt:", result);
|
|
148
|
-
|
|
149
|
-
this.succeedSpinner("Contract deployed successfully.", {
|
|
150
|
-
"Transaction Hash": hash,
|
|
151
|
-
"Contract Address": result.data?.contract_address,
|
|
152
|
-
});
|
|
153
|
-
} catch (error) {
|
|
154
|
-
this.failSpinner("Error deploying contract", error);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
}
|