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.
Files changed (128) hide show
  1. package/dist/index.js +13 -3
  2. package/package.json +11 -2
  3. package/.eslintignore +0 -2
  4. package/.github/workflows/cli-docs.yml +0 -121
  5. package/.github/workflows/publish-beta.yml +0 -41
  6. package/.github/workflows/publish.yml +0 -43
  7. package/.github/workflows/validate-code.yml +0 -47
  8. package/.prettierignore +0 -19
  9. package/.prettierrc +0 -12
  10. package/.release-it.json +0 -64
  11. package/CHANGELOG.md +0 -425
  12. package/CLAUDE.md +0 -55
  13. package/CONTRIBUTING.md +0 -117
  14. package/docker-compose.yml +0 -154
  15. package/docs/delegator-guide.md +0 -203
  16. package/docs/validator-guide.md +0 -329
  17. package/esbuild.config.dev.js +0 -17
  18. package/esbuild.config.js +0 -22
  19. package/esbuild.config.prod.js +0 -17
  20. package/eslint.config.js +0 -60
  21. package/renovate.json +0 -22
  22. package/src/commands/account/create.ts +0 -30
  23. package/src/commands/account/export.ts +0 -106
  24. package/src/commands/account/import.ts +0 -135
  25. package/src/commands/account/index.ts +0 -129
  26. package/src/commands/account/list.ts +0 -34
  27. package/src/commands/account/lock.ts +0 -39
  28. package/src/commands/account/remove.ts +0 -30
  29. package/src/commands/account/send.ts +0 -162
  30. package/src/commands/account/show.ts +0 -74
  31. package/src/commands/account/unlock.ts +0 -56
  32. package/src/commands/account/use.ts +0 -21
  33. package/src/commands/config/getSetReset.ts +0 -51
  34. package/src/commands/config/index.ts +0 -30
  35. package/src/commands/contracts/call.ts +0 -39
  36. package/src/commands/contracts/code.ts +0 -33
  37. package/src/commands/contracts/deploy.ts +0 -157
  38. package/src/commands/contracts/index.ts +0 -86
  39. package/src/commands/contracts/schema.ts +0 -31
  40. package/src/commands/contracts/write.ts +0 -49
  41. package/src/commands/general/index.ts +0 -45
  42. package/src/commands/general/init.ts +0 -179
  43. package/src/commands/general/start.ts +0 -116
  44. package/src/commands/general/stop.ts +0 -26
  45. package/src/commands/localnet/index.ts +0 -100
  46. package/src/commands/localnet/validators.ts +0 -269
  47. package/src/commands/network/index.ts +0 -29
  48. package/src/commands/network/setNetwork.ts +0 -77
  49. package/src/commands/scaffold/index.ts +0 -16
  50. package/src/commands/scaffold/new.ts +0 -34
  51. package/src/commands/staking/StakingAction.ts +0 -279
  52. package/src/commands/staking/delegatorClaim.ts +0 -41
  53. package/src/commands/staking/delegatorExit.ts +0 -56
  54. package/src/commands/staking/delegatorJoin.ts +0 -44
  55. package/src/commands/staking/index.ts +0 -357
  56. package/src/commands/staking/setIdentity.ts +0 -78
  57. package/src/commands/staking/setOperator.ts +0 -46
  58. package/src/commands/staking/stakingInfo.ts +0 -584
  59. package/src/commands/staking/validatorClaim.ts +0 -43
  60. package/src/commands/staking/validatorDeposit.ts +0 -48
  61. package/src/commands/staking/validatorExit.ts +0 -63
  62. package/src/commands/staking/validatorHistory.ts +0 -298
  63. package/src/commands/staking/validatorJoin.ts +0 -47
  64. package/src/commands/staking/validatorPrime.ts +0 -73
  65. package/src/commands/staking/wizard.ts +0 -809
  66. package/src/commands/transactions/appeal.ts +0 -39
  67. package/src/commands/transactions/index.ts +0 -39
  68. package/src/commands/transactions/receipt.ts +0 -90
  69. package/src/commands/update/index.ts +0 -25
  70. package/src/commands/update/ollama.ts +0 -103
  71. package/src/lib/actions/BaseAction.ts +0 -299
  72. package/src/lib/clients/jsonRpcClient.ts +0 -41
  73. package/src/lib/clients/system.ts +0 -73
  74. package/src/lib/config/ConfigFileManager.ts +0 -194
  75. package/src/lib/config/KeychainManager.ts +0 -89
  76. package/src/lib/config/simulator.ts +0 -68
  77. package/src/lib/config/text.ts +0 -2
  78. package/src/lib/errors/missingRequirement.ts +0 -9
  79. package/src/lib/errors/versionRequired.ts +0 -9
  80. package/src/lib/interfaces/ISimulatorService.ts +0 -37
  81. package/src/lib/services/simulator.ts +0 -351
  82. package/src/types/node-fetch.d.ts +0 -1
  83. package/tests/actions/appeal.test.ts +0 -99
  84. package/tests/actions/call.test.ts +0 -94
  85. package/tests/actions/code.test.ts +0 -87
  86. package/tests/actions/create.test.ts +0 -65
  87. package/tests/actions/deploy.test.ts +0 -420
  88. package/tests/actions/getSetReset.test.ts +0 -88
  89. package/tests/actions/init.test.ts +0 -467
  90. package/tests/actions/lock.test.ts +0 -86
  91. package/tests/actions/new.test.ts +0 -80
  92. package/tests/actions/ollama.test.ts +0 -193
  93. package/tests/actions/receipt.test.ts +0 -261
  94. package/tests/actions/schema.test.ts +0 -94
  95. package/tests/actions/setNetwork.test.ts +0 -160
  96. package/tests/actions/staking.test.ts +0 -279
  97. package/tests/actions/start.test.ts +0 -235
  98. package/tests/actions/stop.test.ts +0 -77
  99. package/tests/actions/unlock.test.ts +0 -139
  100. package/tests/actions/validators.test.ts +0 -750
  101. package/tests/actions/write.test.ts +0 -102
  102. package/tests/commands/account.test.ts +0 -146
  103. package/tests/commands/appeal.test.ts +0 -58
  104. package/tests/commands/call.test.ts +0 -78
  105. package/tests/commands/code.test.ts +0 -69
  106. package/tests/commands/config.test.ts +0 -54
  107. package/tests/commands/deploy.test.ts +0 -83
  108. package/tests/commands/init.test.ts +0 -101
  109. package/tests/commands/localnet.test.ts +0 -131
  110. package/tests/commands/network.test.ts +0 -60
  111. package/tests/commands/new.test.ts +0 -68
  112. package/tests/commands/receipt.test.ts +0 -142
  113. package/tests/commands/schema.test.ts +0 -67
  114. package/tests/commands/staking.test.ts +0 -329
  115. package/tests/commands/stop.test.ts +0 -27
  116. package/tests/commands/up.test.ts +0 -105
  117. package/tests/commands/update.test.ts +0 -45
  118. package/tests/commands/write.test.ts +0 -76
  119. package/tests/index.test.ts +0 -56
  120. package/tests/libs/baseAction.test.ts +0 -516
  121. package/tests/libs/configFileManager.test.ts +0 -117
  122. package/tests/libs/jsonRpcClient.test.ts +0 -59
  123. package/tests/libs/keychainManager.test.ts +0 -156
  124. package/tests/libs/system.test.ts +0 -148
  125. package/tests/services/simulator.test.ts +0 -705
  126. package/tests/utils.ts +0 -13
  127. package/tsconfig.json +0 -120
  128. 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
- }