genlayer 0.12.2-beta.2 → 0.12.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/CHANGELOG.md +4 -2
- package/dist/index.js +27 -116
- package/esbuild.config.dev.js +1 -1
- package/esbuild.config.prod.js +1 -1
- package/package.json +2 -2
- package/src/commands/contracts/deploy.ts +25 -105
- package/src/commands/contracts/index.ts +1 -5
- package/src/commands/general/init.ts +1 -0
- package/src/lib/config/simulator.ts +2 -2
- package/tests/actions/deploy.test.ts +30 -200
- package/tests/commands/call.test.ts +0 -3
- package/tests/commands/deploy.test.ts +0 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
## 0.12.
|
|
3
|
+
## 0.12.3 (2025-03-07)
|
|
4
4
|
|
|
5
5
|
### Bug Fixes
|
|
6
6
|
|
|
7
|
-
*
|
|
7
|
+
* production build ([#204](https://github.com/yeagerai/genlayer-cli/issues/204)) ([ceed97b](https://github.com/yeagerai/genlayer-cli/commit/ceed97be6f0b6720d3d243cc41326d6b98569f26))
|
|
8
|
+
|
|
9
|
+
## 0.12.2 (2025-03-07)
|
|
8
10
|
|
|
9
11
|
## 0.12.1 (2025-02-20)
|
|
10
12
|
|
package/dist/index.js
CHANGED
|
@@ -16853,7 +16853,7 @@ var init_call = __esm({
|
|
|
16853
16853
|
import { program } from "commander";
|
|
16854
16854
|
|
|
16855
16855
|
// package.json
|
|
16856
|
-
var version = "0.12.
|
|
16856
|
+
var version = "0.12.3";
|
|
16857
16857
|
var package_default = {
|
|
16858
16858
|
name: "genlayer",
|
|
16859
16859
|
version,
|
|
@@ -16901,7 +16901,7 @@ var package_default = {
|
|
|
16901
16901
|
"@typescript-eslint/parser": "^8.0.0",
|
|
16902
16902
|
"@vitest/coverage-v8": "^2.1.4",
|
|
16903
16903
|
"cross-env": "^7.0.3",
|
|
16904
|
-
esbuild: "
|
|
16904
|
+
esbuild: "^0.25.0",
|
|
16905
16905
|
eslint: "^9.0.0",
|
|
16906
16906
|
"eslint-config-prettier": "^10.0.0",
|
|
16907
16907
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
@@ -16942,7 +16942,7 @@ var CLI_DESCRIPTION = "GenLayer CLI is a development environment for the GenLaye
|
|
|
16942
16942
|
import inquirer2 from "inquirer";
|
|
16943
16943
|
|
|
16944
16944
|
// src/lib/config/simulator.ts
|
|
16945
|
-
var localnetCompatibleVersion = "v0.
|
|
16945
|
+
var localnetCompatibleVersion = "v0.42.0";
|
|
16946
16946
|
var DEFAULT_JSON_RPC_URL = "http://localhost:4000/api";
|
|
16947
16947
|
var CONTAINERS_NAME_PREFIX = "/genlayer-";
|
|
16948
16948
|
var IMAGES_NAME_PREFIX = "yeagerai";
|
|
@@ -16966,7 +16966,7 @@ var STARTING_TIMEOUT_ATTEMPTS = 120;
|
|
|
16966
16966
|
var AI_PROVIDERS_CONFIG = {
|
|
16967
16967
|
ollama: {
|
|
16968
16968
|
name: "Ollama",
|
|
16969
|
-
hint: "(
|
|
16969
|
+
hint: "(This will download and run a local instance of Llama 3)",
|
|
16970
16970
|
cliOptionValue: "ollama"
|
|
16971
16971
|
},
|
|
16972
16972
|
openai: {
|
|
@@ -20723,6 +20723,7 @@ var InitAction = class extends BaseAction {
|
|
|
20723
20723
|
const llmProvidersAnswer = await inquirer2.prompt(llmQuestions);
|
|
20724
20724
|
const selectedLlmProviders = llmProvidersAnswer.selectedLlmProviders;
|
|
20725
20725
|
let defaultOllamaModel = this.getConfig().defaultOllamaModel;
|
|
20726
|
+
AI_PROVIDERS_CONFIG.ollama.hint = `(This will download and run a local instance of ${defaultOllamaModel})`;
|
|
20726
20727
|
const aiProvidersEnvVars = {};
|
|
20727
20728
|
const configurableAiProviders = selectedLlmProviders.filter(
|
|
20728
20729
|
(provider) => AI_PROVIDERS_CONFIG[provider].envVar
|
|
@@ -20950,7 +20951,6 @@ function initializeKeygenCommands(program2) {
|
|
|
20950
20951
|
|
|
20951
20952
|
// src/commands/contracts/deploy.ts
|
|
20952
20953
|
import fs9 from "fs";
|
|
20953
|
-
import path4 from "path";
|
|
20954
20954
|
|
|
20955
20955
|
// node_modules/genlayer-js/dist/chunk-MLKGABMK.js
|
|
20956
20956
|
var __defProp2 = Object.defineProperty;
|
|
@@ -27932,17 +27932,6 @@ var CalldataAddress = class {
|
|
|
27932
27932
|
this.bytes = addr;
|
|
27933
27933
|
}
|
|
27934
27934
|
};
|
|
27935
|
-
var TransactionStatus = /* @__PURE__ */ ((TransactionStatus2) => {
|
|
27936
|
-
TransactionStatus2["PENDING"] = "PENDING";
|
|
27937
|
-
TransactionStatus2["CANCELED"] = "CANCELED";
|
|
27938
|
-
TransactionStatus2["PROPOSING"] = "PROPOSING";
|
|
27939
|
-
TransactionStatus2["COMMITTING"] = "COMMITTING";
|
|
27940
|
-
TransactionStatus2["REVEALING"] = "REVEALING";
|
|
27941
|
-
TransactionStatus2["ACCEPTED"] = "ACCEPTED";
|
|
27942
|
-
TransactionStatus2["FINALIZED"] = "FINALIZED";
|
|
27943
|
-
TransactionStatus2["UNDETERMINED"] = "UNDETERMINED";
|
|
27944
|
-
return TransactionStatus2;
|
|
27945
|
-
})(TransactionStatus || {});
|
|
27946
27935
|
|
|
27947
27936
|
// node_modules/viem/_esm/accounts/generatePrivateKey.js
|
|
27948
27937
|
init_secp256k1();
|
|
@@ -28703,13 +28692,9 @@ function getPrivateKey() {
|
|
|
28703
28692
|
}
|
|
28704
28693
|
|
|
28705
28694
|
// src/commands/contracts/deploy.ts
|
|
28706
|
-
|
|
28707
|
-
import { buildSync } from "esbuild";
|
|
28708
|
-
var DeployAction = class extends BaseAction {
|
|
28695
|
+
var DeployAction = class {
|
|
28709
28696
|
constructor() {
|
|
28710
|
-
super();
|
|
28711
28697
|
__publicField(this, "genlayerClient");
|
|
28712
|
-
__publicField(this, "deployDir", path4.resolve(process.cwd(), "deploy"));
|
|
28713
28698
|
this.genlayerClient = createClient2({
|
|
28714
28699
|
chain: simulator,
|
|
28715
28700
|
endpoint: process.env.VITE_JSON_RPC_SERVER_URL,
|
|
@@ -28722,104 +28707,34 @@ var DeployAction = class extends BaseAction {
|
|
|
28722
28707
|
}
|
|
28723
28708
|
return fs9.readFileSync(contractPath, "utf-8");
|
|
28724
28709
|
}
|
|
28725
|
-
async
|
|
28726
|
-
const
|
|
28727
|
-
|
|
28728
|
-
|
|
28729
|
-
|
|
28730
|
-
entryPoints: [filePath],
|
|
28731
|
-
outfile: outFile,
|
|
28732
|
-
bundle: false,
|
|
28733
|
-
platform: "node",
|
|
28734
|
-
format: "esm",
|
|
28735
|
-
target: "es2020",
|
|
28736
|
-
sourcemap: false
|
|
28737
|
-
});
|
|
28738
|
-
await this.executeJsScript(filePath, outFile);
|
|
28739
|
-
} catch (error) {
|
|
28740
|
-
this.failSpinner(`Error executing: ${filePath}`, error);
|
|
28741
|
-
} finally {
|
|
28742
|
-
fs9.unlinkSync(outFile);
|
|
28743
|
-
}
|
|
28744
|
-
}
|
|
28745
|
-
async executeJsScript(filePath, transpiledFilePath) {
|
|
28746
|
-
this.startSpinner(`Executing file: ${filePath}`);
|
|
28747
|
-
try {
|
|
28748
|
-
const module = await import(pathToFileURL(transpiledFilePath || filePath).href);
|
|
28749
|
-
if (!module.default || typeof module.default !== "function") {
|
|
28750
|
-
this.failSpinner(`No "default" function found in: ${filePath}`);
|
|
28751
|
-
return;
|
|
28752
|
-
}
|
|
28753
|
-
await module.default(this.genlayerClient);
|
|
28754
|
-
this.succeedSpinner(`Successfully executed: ${filePath}`);
|
|
28755
|
-
} catch (error) {
|
|
28756
|
-
this.failSpinner(`Error executing: ${filePath}`, error);
|
|
28710
|
+
async deploy(options) {
|
|
28711
|
+
const argsUsed = options.args && options.args.length > 0;
|
|
28712
|
+
const kwargsUsed = options.kwargs && options.kwargs.trim() !== "";
|
|
28713
|
+
if (argsUsed && kwargsUsed) {
|
|
28714
|
+
throw new Error("Invalid usage: Please specify either `args` or `kwargs`, but not both.");
|
|
28757
28715
|
}
|
|
28758
|
-
|
|
28759
|
-
|
|
28760
|
-
this.startSpinner("Searching for deploy scripts...");
|
|
28761
|
-
if (!fs9.existsSync(this.deployDir)) {
|
|
28762
|
-
this.failSpinner("No deploy folder found.");
|
|
28716
|
+
if (!options.contract) {
|
|
28717
|
+
console.error("No contract specified for deployment.");
|
|
28763
28718
|
return;
|
|
28764
28719
|
}
|
|
28765
|
-
const
|
|
28766
|
-
|
|
28767
|
-
|
|
28768
|
-
if (!isNaN(numA) && !isNaN(numB)) return numA - numB;
|
|
28769
|
-
if (!isNaN(numA)) return -1;
|
|
28770
|
-
if (!isNaN(numB)) return 1;
|
|
28771
|
-
return a.localeCompare(b);
|
|
28772
|
-
});
|
|
28773
|
-
if (files.length === 0) {
|
|
28774
|
-
this.failSpinner("No deploy scripts found.");
|
|
28720
|
+
const contractCode = this.readContractCode(options.contract);
|
|
28721
|
+
if (!contractCode) {
|
|
28722
|
+
console.error("Contract code is empty.");
|
|
28775
28723
|
return;
|
|
28776
28724
|
}
|
|
28777
|
-
|
|
28778
|
-
|
|
28779
|
-
|
|
28780
|
-
|
|
28781
|
-
try {
|
|
28782
|
-
if (file.endsWith(".ts")) {
|
|
28783
|
-
await this.executeTsScript(filePath);
|
|
28784
|
-
} else {
|
|
28785
|
-
await this.executeJsScript(filePath);
|
|
28786
|
-
}
|
|
28787
|
-
} catch (error) {
|
|
28788
|
-
this.failSpinner(`Error executing script: ${filePath}`, error);
|
|
28789
|
-
}
|
|
28790
|
-
}
|
|
28791
|
-
}
|
|
28792
|
-
async deploy(options) {
|
|
28725
|
+
const leaderOnly = false;
|
|
28726
|
+
let deployParams = { code: contractCode, args: options.args, leaderOnly };
|
|
28727
|
+
console.log("Starting contract deployment...");
|
|
28728
|
+
console.log("Deployment Parameters:", deployParams);
|
|
28793
28729
|
try {
|
|
28794
|
-
this.startSpinner("Setting up the deployment environment...");
|
|
28795
|
-
await this.genlayerClient.initializeConsensusSmartContract();
|
|
28796
|
-
if (!options.contract) {
|
|
28797
|
-
this.failSpinner("No contract specified for deployment.");
|
|
28798
|
-
return;
|
|
28799
|
-
}
|
|
28800
|
-
this.setSpinnerText("Reading contract code...");
|
|
28801
|
-
const contractCode = this.readContractCode(options.contract);
|
|
28802
|
-
if (!contractCode) {
|
|
28803
|
-
this.failSpinner("Contract code is empty.");
|
|
28804
|
-
return;
|
|
28805
|
-
}
|
|
28806
|
-
const leaderOnly = false;
|
|
28807
|
-
const deployParams = { code: contractCode, args: options.args, leaderOnly };
|
|
28808
|
-
this.setSpinnerText("Starting contract deployment...");
|
|
28809
|
-
this.log("Deployment Parameters:", deployParams);
|
|
28810
28730
|
const hash2 = await this.genlayerClient.deployContract(deployParams);
|
|
28811
|
-
const result = await this.genlayerClient.waitForTransactionReceipt({
|
|
28812
|
-
|
|
28813
|
-
|
|
28814
|
-
|
|
28815
|
-
status: TransactionStatus.ACCEPTED
|
|
28816
|
-
});
|
|
28817
|
-
this.succeedSpinner("Contract deployed successfully.", {
|
|
28818
|
-
"Transaction Hash": hash2,
|
|
28819
|
-
"Contract Address": result.data?.contract_address
|
|
28820
|
-
});
|
|
28731
|
+
const result = await this.genlayerClient.waitForTransactionReceipt({ hash: hash2, retries: 15, interval: 2e3 });
|
|
28732
|
+
console.log("Contract deployed successfully.");
|
|
28733
|
+
console.log("Transaction Hash:", hash2);
|
|
28734
|
+
console.log("Contract Address:", result.data?.contract_address);
|
|
28821
28735
|
} catch (error) {
|
|
28822
|
-
|
|
28736
|
+
console.error("Error deploying contract:", error);
|
|
28737
|
+
throw new Error("Contract deployment failed.");
|
|
28823
28738
|
}
|
|
28824
28739
|
}
|
|
28825
28740
|
};
|
|
@@ -28896,11 +28811,7 @@ var CallAction = class {
|
|
|
28896
28811
|
function initializeContractsCommands(program2) {
|
|
28897
28812
|
program2.command("deploy").description("Deploy intelligent contracts").option("--contract <contractPath>", "Path to the smart contract to deploy").option("--args <args...>", "Positional arguments for the contract (space-separated, use quotes for multi-word arguments)", []).action(async (options) => {
|
|
28898
28813
|
const deployer = new DeployAction();
|
|
28899
|
-
|
|
28900
|
-
await deployer.deploy(options);
|
|
28901
|
-
} else {
|
|
28902
|
-
await deployer.deployScripts();
|
|
28903
|
-
}
|
|
28814
|
+
await deployer.deploy(options);
|
|
28904
28815
|
});
|
|
28905
28816
|
program2.command("call <contractAddress> <method>").description("Call a contract method").option("--args <args...>", "Positional arguments for the method (space-separated, use quotes for multi-word arguments)", []).action(async (contractAddress, method, options) => {
|
|
28906
28817
|
const caller = new CallAction();
|
package/esbuild.config.dev.js
CHANGED
|
@@ -11,7 +11,7 @@ export default {
|
|
|
11
11
|
banner: {
|
|
12
12
|
js: `const _importMetaUrl = new URL(import.meta.url).pathname;`,
|
|
13
13
|
},
|
|
14
|
-
external: ["commander", "dockerode", "dotenv", "ethers", "inquirer", "update-check", "ssh2"
|
|
14
|
+
external: ["commander", "dockerode", "dotenv", "ethers", "inquirer", "update-check", "ssh2"]
|
|
15
15
|
|
|
16
16
|
},
|
|
17
17
|
watch: true,
|
package/esbuild.config.prod.js
CHANGED
|
@@ -11,7 +11,7 @@ export default {
|
|
|
11
11
|
banner: {
|
|
12
12
|
js: `const _importMetaUrl = new URL(import.meta.url).pathname;`,
|
|
13
13
|
},
|
|
14
|
-
external: ["commander", "dockerode", "dotenv", "ethers", "inquirer", "update-check", "ssh2"
|
|
14
|
+
external: ["commander", "dockerode", "dotenv", "ethers", "inquirer", "update-check", "ssh2"]
|
|
15
15
|
},
|
|
16
16
|
watch: false,
|
|
17
17
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "genlayer",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.3",
|
|
4
4
|
"description": "GenLayer Command Line Tool",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@typescript-eslint/parser": "^8.0.0",
|
|
46
46
|
"@vitest/coverage-v8": "^2.1.4",
|
|
47
47
|
"cross-env": "^7.0.3",
|
|
48
|
-
"esbuild": "
|
|
48
|
+
"esbuild": "^0.25.0",
|
|
49
49
|
"eslint": "^9.0.0",
|
|
50
50
|
"eslint-config-prettier": "^10.0.0",
|
|
51
51
|
"eslint-import-resolver-typescript": "^3.6.1",
|
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
2
|
import { createClient, createAccount } from "genlayer-js";
|
|
4
3
|
import { simulator } from "genlayer-js/chains";
|
|
5
4
|
import type { GenLayerClient } from "genlayer-js/types";
|
|
6
5
|
import { getPrivateKey } from "../../lib/accounts/getPrivateKey";
|
|
7
|
-
import { BaseAction } from "../../lib/actions/BaseAction";
|
|
8
|
-
import { pathToFileURL } from "url";
|
|
9
|
-
import { TransactionStatus } from "genlayer-js/types";
|
|
10
|
-
import { buildSync } from "esbuild";
|
|
11
6
|
|
|
12
7
|
export interface DeployOptions {
|
|
13
8
|
contract?: string;
|
|
9
|
+
// network: string;
|
|
14
10
|
args?: any[];
|
|
11
|
+
kwargs?: string;
|
|
15
12
|
}
|
|
16
13
|
|
|
17
|
-
export class DeployAction
|
|
14
|
+
export class DeployAction {
|
|
18
15
|
private genlayerClient: GenLayerClient<typeof simulator>;
|
|
19
|
-
private readonly deployDir = path.resolve(process.cwd(), "deploy");
|
|
20
16
|
|
|
21
17
|
constructor() {
|
|
22
|
-
super();
|
|
23
18
|
this.genlayerClient = createClient({
|
|
24
19
|
chain: simulator,
|
|
25
20
|
endpoint: process.env.VITE_JSON_RPC_SERVER_URL,
|
|
@@ -34,119 +29,44 @@ export class DeployAction extends BaseAction {
|
|
|
34
29
|
return fs.readFileSync(contractPath, "utf-8");
|
|
35
30
|
}
|
|
36
31
|
|
|
37
|
-
|
|
38
|
-
const outFile = filePath.replace(/\.ts$/, ".compiled.js");
|
|
39
|
-
this.startSpinner(`Transpiling TypeScript file: ${filePath}`);
|
|
40
|
-
try {
|
|
41
|
-
buildSync({
|
|
42
|
-
entryPoints: [filePath],
|
|
43
|
-
outfile: outFile,
|
|
44
|
-
bundle: false,
|
|
45
|
-
platform: "node",
|
|
46
|
-
format: "esm",
|
|
47
|
-
target: "es2020",
|
|
48
|
-
sourcemap: false,
|
|
49
|
-
});
|
|
50
|
-
await this.executeJsScript(filePath, outFile);
|
|
51
|
-
} catch (error) {
|
|
52
|
-
this.failSpinner(`Error executing: ${filePath}`, error);
|
|
53
|
-
} finally {
|
|
54
|
-
fs.unlinkSync(outFile);
|
|
55
|
-
}
|
|
56
|
-
}
|
|
32
|
+
async deploy(options: DeployOptions): Promise<void> {
|
|
57
33
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
this.failSpinner(`No "default" function found in: ${filePath}`);
|
|
64
|
-
return
|
|
65
|
-
}
|
|
66
|
-
await module.default(this.genlayerClient);
|
|
67
|
-
this.succeedSpinner(`Successfully executed: ${filePath}`);
|
|
68
|
-
} catch (error) {
|
|
69
|
-
this.failSpinner(`Error executing: ${filePath}`, error);
|
|
34
|
+
const argsUsed = options.args && options.args.length > 0;
|
|
35
|
+
const kwargsUsed = options.kwargs && options.kwargs.trim() !== "";
|
|
36
|
+
|
|
37
|
+
if (argsUsed && kwargsUsed) {
|
|
38
|
+
throw new Error("Invalid usage: Please specify either `args` or `kwargs`, but not both.");
|
|
70
39
|
}
|
|
71
|
-
}
|
|
72
40
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
if (!fs.existsSync(this.deployDir)) {
|
|
76
|
-
this.failSpinner("No deploy folder found.");
|
|
41
|
+
if (!options.contract) {
|
|
42
|
+
console.error("No contract specified for deployment.");
|
|
77
43
|
return;
|
|
78
44
|
}
|
|
79
|
-
const files = fs.readdirSync(this.deployDir)
|
|
80
|
-
.filter(file => file.endsWith(".ts") || file.endsWith(".js"))
|
|
81
|
-
.sort((a, b) => {
|
|
82
|
-
const numA = parseInt(a.split("_")[0]);
|
|
83
|
-
const numB = parseInt(b.split("_")[0]);
|
|
84
45
|
|
|
85
|
-
|
|
86
|
-
if (!isNaN(numA)) return -1;
|
|
87
|
-
if (!isNaN(numB)) return 1;
|
|
88
|
-
return a.localeCompare(b);
|
|
89
|
-
});
|
|
46
|
+
const contractCode = this.readContractCode(options.contract);
|
|
90
47
|
|
|
91
|
-
if (
|
|
92
|
-
|
|
48
|
+
if (!contractCode) {
|
|
49
|
+
console.error("Contract code is empty.");
|
|
93
50
|
return;
|
|
94
51
|
}
|
|
95
52
|
|
|
96
|
-
|
|
53
|
+
const leaderOnly = false;
|
|
54
|
+
let deployParams: any = { code: contractCode, args: options.args, leaderOnly };
|
|
97
55
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
this.setSpinnerText(`Executing script: ${filePath}`);
|
|
101
|
-
try {
|
|
102
|
-
if (file.endsWith(".ts")) {
|
|
103
|
-
await this.executeTsScript(filePath);
|
|
104
|
-
} else {
|
|
105
|
-
await this.executeJsScript(filePath);
|
|
106
|
-
}
|
|
107
|
-
} catch (error) {
|
|
108
|
-
this.failSpinner(`Error executing script: ${filePath}`, error);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
56
|
+
console.log("Starting contract deployment...");
|
|
57
|
+
console.log("Deployment Parameters:", deployParams);
|
|
112
58
|
|
|
113
|
-
async deploy(options: DeployOptions): Promise<void> {
|
|
114
59
|
try {
|
|
115
|
-
this.
|
|
116
|
-
await this.genlayerClient.initializeConsensusSmartContract();
|
|
117
|
-
|
|
118
|
-
if (!options.contract) {
|
|
119
|
-
this.failSpinner("No contract specified for deployment.");
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
this.setSpinnerText("Reading contract code...");
|
|
123
|
-
const contractCode = this.readContractCode(options.contract);
|
|
124
|
-
|
|
125
|
-
if (!contractCode) {
|
|
126
|
-
this.failSpinner("Contract code is empty.");
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const leaderOnly = false;
|
|
131
|
-
const deployParams: any = { code: contractCode, args: options.args, leaderOnly };
|
|
132
|
-
|
|
133
|
-
this.setSpinnerText("Starting contract deployment...");
|
|
134
|
-
this.log("Deployment Parameters:", deployParams);
|
|
60
|
+
const hash = await this.genlayerClient.deployContract(deployParams) as any;
|
|
135
61
|
|
|
136
|
-
const
|
|
137
|
-
const result = await this.genlayerClient.waitForTransactionReceipt({
|
|
138
|
-
hash,
|
|
139
|
-
retries: 15,
|
|
140
|
-
interval: 2000,
|
|
141
|
-
status: TransactionStatus.ACCEPTED,
|
|
142
|
-
});
|
|
62
|
+
const result = await this.genlayerClient.waitForTransactionReceipt({hash, retries: 15, interval: 2000})
|
|
143
63
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
});
|
|
64
|
+
console.log("Contract deployed successfully.");
|
|
65
|
+
console.log("Transaction Hash:", hash);
|
|
66
|
+
console.log("Contract Address:", result.data?.contract_address);
|
|
148
67
|
} catch (error) {
|
|
149
|
-
|
|
68
|
+
console.error("Error deploying contract:", error);
|
|
69
|
+
throw new Error("Contract deployment failed.");
|
|
150
70
|
}
|
|
151
71
|
}
|
|
152
72
|
}
|
|
@@ -12,11 +12,7 @@ export function initializeContractsCommands(program: Command) {
|
|
|
12
12
|
.option("--args <args...>", "Positional arguments for the contract (space-separated, use quotes for multi-word arguments)", [])
|
|
13
13
|
.action(async (options: DeployOptions) => {
|
|
14
14
|
const deployer = new DeployAction();
|
|
15
|
-
|
|
16
|
-
await deployer.deploy(options);
|
|
17
|
-
}else {
|
|
18
|
-
await deployer.deployScripts();
|
|
19
|
-
}
|
|
15
|
+
await deployer.deploy(options);
|
|
20
16
|
});
|
|
21
17
|
|
|
22
18
|
program
|
|
@@ -94,6 +94,7 @@ export class InitAction extends BaseAction {
|
|
|
94
94
|
const selectedLlmProviders = llmProvidersAnswer.selectedLlmProviders as AiProviders[];
|
|
95
95
|
|
|
96
96
|
let defaultOllamaModel = this.getConfig().defaultOllamaModel;
|
|
97
|
+
AI_PROVIDERS_CONFIG.ollama.hint = `(This will download and run a local instance of ${defaultOllamaModel})`;
|
|
97
98
|
const aiProvidersEnvVars: Record<string, string> = {};
|
|
98
99
|
const configurableAiProviders = selectedLlmProviders.filter(
|
|
99
100
|
(provider: AiProviders) => AI_PROVIDERS_CONFIG[provider].envVar
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const localnetCompatibleVersion = "v0.
|
|
1
|
+
export const localnetCompatibleVersion = "v0.42.0";
|
|
2
2
|
export const DEFAULT_JSON_RPC_URL = "http://localhost:4000/api";
|
|
3
3
|
export const CONTAINERS_NAME_PREFIX = "/genlayer-";
|
|
4
4
|
export const IMAGES_NAME_PREFIX = "yeagerai";
|
|
@@ -32,7 +32,7 @@ export type AiProvidersConfigType = {
|
|
|
32
32
|
export const AI_PROVIDERS_CONFIG: AiProvidersConfigType = {
|
|
33
33
|
ollama: {
|
|
34
34
|
name: "Ollama",
|
|
35
|
-
hint: "(
|
|
35
|
+
hint: "(This will download and run a local instance of Llama 3)",
|
|
36
36
|
cliOptionValue: "ollama",
|
|
37
37
|
},
|
|
38
38
|
openai: {
|
|
@@ -3,22 +3,16 @@ import fs from "fs";
|
|
|
3
3
|
import { createClient, createAccount } from "genlayer-js";
|
|
4
4
|
import { DeployAction, DeployOptions } from "../../src/commands/contracts/deploy";
|
|
5
5
|
import { getPrivateKey } from "../../src/lib/accounts/getPrivateKey";
|
|
6
|
-
import { buildSync } from "esbuild";
|
|
7
|
-
import { pathToFileURL } from "url";
|
|
8
6
|
|
|
9
7
|
vi.mock("fs");
|
|
10
8
|
vi.mock("genlayer-js");
|
|
11
|
-
vi.mock("esbuild", () => ({
|
|
12
|
-
buildSync: vi.fn(),
|
|
13
|
-
}));
|
|
14
9
|
vi.mock("../../src/lib/accounts/getPrivateKey");
|
|
15
10
|
|
|
16
|
-
describe("
|
|
11
|
+
describe("Deploy Action", () => {
|
|
17
12
|
let deployer: DeployAction;
|
|
18
13
|
const mockClient = {
|
|
19
14
|
deployContract: vi.fn(),
|
|
20
|
-
waitForTransactionReceipt: vi.fn()
|
|
21
|
-
initializeConsensusSmartContract: vi.fn(),
|
|
15
|
+
waitForTransactionReceipt: vi.fn()
|
|
22
16
|
};
|
|
23
17
|
|
|
24
18
|
const mockPrivateKey = "mocked_private_key";
|
|
@@ -29,12 +23,6 @@ describe("DeployAction", () => {
|
|
|
29
23
|
vi.mocked(createAccount).mockReturnValue({ privateKey: mockPrivateKey } as any);
|
|
30
24
|
vi.mocked(getPrivateKey).mockReturnValue(mockPrivateKey);
|
|
31
25
|
deployer = new DeployAction();
|
|
32
|
-
|
|
33
|
-
vi.spyOn(deployer as any, "startSpinner").mockImplementation(() => {});
|
|
34
|
-
vi.spyOn(deployer as any, "succeedSpinner").mockImplementation(() => {});
|
|
35
|
-
vi.spyOn(deployer as any, "failSpinner").mockImplementation(() => {});
|
|
36
|
-
vi.spyOn(deployer as any, "setSpinnerText").mockImplementation(() => {});
|
|
37
|
-
vi.spyOn(deployer as any, "log").mockImplementation(() => {});
|
|
38
26
|
});
|
|
39
27
|
|
|
40
28
|
afterEach(() => {
|
|
@@ -64,6 +52,7 @@ describe("DeployAction", () => {
|
|
|
64
52
|
expect(fs.existsSync).toHaveBeenCalledWith(contractPath);
|
|
65
53
|
});
|
|
66
54
|
|
|
55
|
+
|
|
67
56
|
test("deploys contract with args", async () => {
|
|
68
57
|
const options: DeployOptions = {
|
|
69
58
|
contract: "/mocked/contract/path",
|
|
@@ -74,9 +63,7 @@ describe("DeployAction", () => {
|
|
|
74
63
|
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
75
64
|
vi.mocked(fs.readFileSync).mockReturnValue(contractContent);
|
|
76
65
|
vi.mocked(mockClient.deployContract).mockResolvedValue("mocked_tx_hash");
|
|
77
|
-
vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue({
|
|
78
|
-
data: { contract_address: "0xdasdsadasdasdada" },
|
|
79
|
-
});
|
|
66
|
+
vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue({data: {contractAddress: '0xdasdsadasdasdada'}});
|
|
80
67
|
|
|
81
68
|
await deployer.deploy(options);
|
|
82
69
|
|
|
@@ -86,15 +73,31 @@ describe("DeployAction", () => {
|
|
|
86
73
|
args: [1, 2, 3],
|
|
87
74
|
leaderOnly: false,
|
|
88
75
|
});
|
|
89
|
-
expect(mockClient.deployContract).
|
|
76
|
+
expect(mockClient.deployContract).toHaveResolvedWith("mocked_tx_hash");
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("throws error for both args and kwargs", async () => {
|
|
80
|
+
const options: DeployOptions = {
|
|
81
|
+
contract: "/mocked/contract/path",
|
|
82
|
+
args: [1, 2, 3],
|
|
83
|
+
kwargs: "key1=value1,key2=42",
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
await expect(deployer.deploy(options)).rejects.toThrowError(
|
|
87
|
+
"Invalid usage: Please specify either `args` or `kwargs`, but not both."
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
expect(fs.readFileSync).not.toHaveBeenCalled();
|
|
91
|
+
expect(mockClient.deployContract).not.toHaveBeenCalled();
|
|
90
92
|
});
|
|
91
93
|
|
|
92
94
|
test("throws error for missing contract", async () => {
|
|
93
|
-
const options: DeployOptions = {
|
|
95
|
+
const options: DeployOptions = {
|
|
96
|
+
};
|
|
94
97
|
|
|
95
98
|
await deployer.deploy(options);
|
|
96
99
|
|
|
97
|
-
expect(
|
|
100
|
+
expect(fs.readFileSync).not.toHaveBeenCalled();
|
|
98
101
|
expect(mockClient.deployContract).not.toHaveBeenCalled();
|
|
99
102
|
});
|
|
100
103
|
|
|
@@ -111,13 +114,15 @@ describe("DeployAction", () => {
|
|
|
111
114
|
new Error("Mocked deployment error")
|
|
112
115
|
);
|
|
113
116
|
|
|
114
|
-
await deployer.deploy(options)
|
|
117
|
+
await expect(deployer.deploy(options)).rejects.toThrowError(
|
|
118
|
+
"Contract deployment failed."
|
|
119
|
+
);
|
|
115
120
|
|
|
116
|
-
expect(
|
|
121
|
+
expect(fs.readFileSync).toHaveBeenCalledWith(options.contract, "utf-8");
|
|
117
122
|
expect(mockClient.deployContract).toHaveBeenCalled();
|
|
118
123
|
});
|
|
119
124
|
|
|
120
|
-
test("
|
|
125
|
+
test("throws error if contract code is empty", async () => {
|
|
121
126
|
const options: DeployOptions = {
|
|
122
127
|
contract: "/mocked/contract/path",
|
|
123
128
|
};
|
|
@@ -127,183 +132,8 @@ describe("DeployAction", () => {
|
|
|
127
132
|
|
|
128
133
|
await deployer.deploy(options);
|
|
129
134
|
|
|
130
|
-
expect(
|
|
135
|
+
expect(fs.existsSync).toHaveBeenCalledWith(options.contract);
|
|
136
|
+
expect(fs.readFileSync).toHaveBeenCalledWith(options.contract, "utf-8");
|
|
131
137
|
expect(mockClient.deployContract).not.toHaveBeenCalled();
|
|
132
138
|
});
|
|
133
|
-
|
|
134
|
-
test("deployScripts executes scripts in order", async () => {
|
|
135
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
136
|
-
vi.mocked(fs.readdirSync).mockReturnValue([
|
|
137
|
-
"1_first.ts",
|
|
138
|
-
"2_second.js",
|
|
139
|
-
"10_last.ts",
|
|
140
|
-
] as any);
|
|
141
|
-
|
|
142
|
-
vi.spyOn(deployer as any, "executeTsScript").mockResolvedValue(undefined);
|
|
143
|
-
vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
|
|
144
|
-
|
|
145
|
-
await deployer.deployScripts();
|
|
146
|
-
|
|
147
|
-
expect(deployer["setSpinnerText"]).toHaveBeenCalledWith("Found 3 deploy scripts. Executing...");
|
|
148
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringMatching(/1_first.ts/));
|
|
149
|
-
expect(deployer["executeJsScript"]).toHaveBeenCalledWith(expect.stringMatching(/2_second.js/));
|
|
150
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringMatching(/10_last.ts/));
|
|
151
|
-
});
|
|
152
|
-
|
|
153
|
-
test("executeTsScript transpiles and executes TypeScript", async () => {
|
|
154
|
-
const filePath = "/mocked/script.ts";
|
|
155
|
-
const outFile = "/mocked/script.compiled.js";
|
|
156
|
-
|
|
157
|
-
vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
|
|
158
|
-
vi.mocked(buildSync).mockImplementation((() => {}) as any);
|
|
159
|
-
|
|
160
|
-
await deployer["executeTsScript"](filePath);
|
|
161
|
-
|
|
162
|
-
expect(deployer["startSpinner"]).toHaveBeenCalledWith(`Transpiling TypeScript file: ${filePath}`);
|
|
163
|
-
expect(buildSync).toHaveBeenCalledWith({
|
|
164
|
-
entryPoints: [filePath],
|
|
165
|
-
outfile: outFile,
|
|
166
|
-
bundle: false,
|
|
167
|
-
platform: "node",
|
|
168
|
-
format: "esm",
|
|
169
|
-
target: "es2020",
|
|
170
|
-
sourcemap: false,
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
expect(deployer["executeJsScript"]).toHaveBeenCalledWith(filePath, outFile);
|
|
174
|
-
expect(fs.unlinkSync).toHaveBeenCalledWith(outFile);
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
test("deployScripts fails when deploy folder is missing", async () => {
|
|
178
|
-
vi.mocked(fs.existsSync).mockReturnValue(false);
|
|
179
|
-
|
|
180
|
-
await deployer.deployScripts();
|
|
181
|
-
|
|
182
|
-
expect(deployer["failSpinner"]).toHaveBeenCalledWith("No deploy folder found.");
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
test("deployScripts sorts and executes scripts correctly", async () => {
|
|
186
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
187
|
-
vi.mocked(fs.readdirSync).mockReturnValue([
|
|
188
|
-
"10_last.ts",
|
|
189
|
-
"2_second.js",
|
|
190
|
-
"1_first.ts"
|
|
191
|
-
] as any);
|
|
192
|
-
|
|
193
|
-
vi.spyOn(deployer as any, "executeTsScript").mockResolvedValue(undefined);
|
|
194
|
-
vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
|
|
195
|
-
|
|
196
|
-
await deployer.deployScripts();
|
|
197
|
-
|
|
198
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("1_first.ts"));
|
|
199
|
-
expect(deployer["executeJsScript"]).toHaveBeenCalledWith(expect.stringContaining("2_second.js"));
|
|
200
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("10_last.ts"));
|
|
201
|
-
});
|
|
202
|
-
|
|
203
|
-
test("deployScripts fails when no scripts are found", async () => {
|
|
204
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
205
|
-
vi.mocked(fs.readdirSync).mockReturnValue([]);
|
|
206
|
-
|
|
207
|
-
await deployer.deployScripts();
|
|
208
|
-
|
|
209
|
-
expect(deployer["failSpinner"]).toHaveBeenCalledWith("No deploy scripts found.");
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
test("deployScripts handles script execution errors", async () => {
|
|
213
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
214
|
-
vi.mocked(fs.readdirSync).mockReturnValue(["1_failing.ts"] as any);
|
|
215
|
-
vi.spyOn(deployer as any, "executeTsScript").mockRejectedValue(new Error("Script error"));
|
|
216
|
-
|
|
217
|
-
await deployer.deployScripts();
|
|
218
|
-
|
|
219
|
-
expect(deployer["failSpinner"]).toHaveBeenCalledWith(
|
|
220
|
-
expect.stringContaining("Error executing script:"),
|
|
221
|
-
expect.any(Error)
|
|
222
|
-
);
|
|
223
|
-
});
|
|
224
|
-
|
|
225
|
-
test("executeJsScript fails gracefully", async () => {
|
|
226
|
-
const filePath = "/mocked/script.js";
|
|
227
|
-
|
|
228
|
-
await deployer["executeJsScript"](filePath);
|
|
229
|
-
|
|
230
|
-
expect(deployer["failSpinner"]).toHaveBeenCalledWith(
|
|
231
|
-
expect.stringContaining("Error executing:"),
|
|
232
|
-
expect.any(Error)
|
|
233
|
-
);
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
test("deploy fails when contract code is empty", async () => {
|
|
237
|
-
const options: DeployOptions = { contract: "/mocked/contract/path" };
|
|
238
|
-
|
|
239
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
240
|
-
vi.mocked(fs.readFileSync).mockReturnValue("");
|
|
241
|
-
|
|
242
|
-
await deployer.deploy(options);
|
|
243
|
-
|
|
244
|
-
expect(deployer["failSpinner"]).toHaveBeenCalledWith("Contract code is empty.");
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
test("deployScripts correctly sorts mixed numbered and non-numbered scripts", async () => {
|
|
248
|
-
vi.mocked(fs.existsSync).mockReturnValue(true);
|
|
249
|
-
vi.mocked(fs.readdirSync).mockReturnValue([
|
|
250
|
-
"script.ts",
|
|
251
|
-
"2alpha_script.ts",
|
|
252
|
-
"3alpha_script.ts",
|
|
253
|
-
"blpha_script.ts",
|
|
254
|
-
"clpha_script.ts"
|
|
255
|
-
] as any);
|
|
256
|
-
|
|
257
|
-
vi.spyOn(deployer as any, "executeTsScript").mockResolvedValue(undefined);
|
|
258
|
-
vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
|
|
259
|
-
|
|
260
|
-
await deployer.deployScripts();
|
|
261
|
-
|
|
262
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("script.ts"));
|
|
263
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("2alpha_script.ts"));
|
|
264
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("3alpha_script.ts"));
|
|
265
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("blpha_script.ts"));
|
|
266
|
-
expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("clpha_script.ts"));
|
|
267
|
-
});
|
|
268
|
-
|
|
269
|
-
test("executeJsScript fails if module has no default export", async () => {
|
|
270
|
-
const filePath = "/mocked/script.js";
|
|
271
|
-
|
|
272
|
-
vi.doMock(pathToFileURL(filePath).href, () => ({ default: "Not a function" }));
|
|
273
|
-
|
|
274
|
-
await deployer["executeJsScript"](filePath);
|
|
275
|
-
|
|
276
|
-
expect(deployer["failSpinner"]).toHaveBeenCalledWith(
|
|
277
|
-
expect.stringContaining("No \"default\" function found in:"),
|
|
278
|
-
);
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
test("executeJsScript successfully executes a script", async () => {
|
|
282
|
-
const filePath = "/mocked/script.js";
|
|
283
|
-
const mockFn = vi.fn(); // This mock function simulates the script execution
|
|
284
|
-
|
|
285
|
-
vi.doMock(pathToFileURL(filePath).href, () => ({ default: mockFn }));
|
|
286
|
-
|
|
287
|
-
await deployer["executeJsScript"](filePath);
|
|
288
|
-
|
|
289
|
-
expect(mockFn).toHaveBeenCalledWith(deployer["genlayerClient"]);
|
|
290
|
-
|
|
291
|
-
expect(deployer["succeedSpinner"]).toHaveBeenCalledWith(`Successfully executed: ${filePath}`);
|
|
292
|
-
});
|
|
293
|
-
|
|
294
|
-
test("executeTsScript fails when buildSync throws an error", async () => {
|
|
295
|
-
const filePath = "/mocked/script.ts";
|
|
296
|
-
const error = new Error("Build failed");
|
|
297
|
-
|
|
298
|
-
vi.mocked(buildSync).mockImplementation(() => {
|
|
299
|
-
throw error; // Simulate an error during transpilation
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
await deployer["executeTsScript"](filePath);
|
|
303
|
-
|
|
304
|
-
expect(deployer["failSpinner"]).toHaveBeenCalledWith(
|
|
305
|
-
`Error executing: ${filePath}`,
|
|
306
|
-
error
|
|
307
|
-
);
|
|
308
|
-
});
|
|
309
139
|
});
|
|
@@ -4,9 +4,6 @@ import { vi, describe, beforeEach, afterEach, test, expect } from "vitest";
|
|
|
4
4
|
import { initializeContractsCommands } from "../../src/commands/contracts";
|
|
5
5
|
|
|
6
6
|
vi.mock("../../src/commands/contracts/call");
|
|
7
|
-
vi.mock("esbuild", () => ({
|
|
8
|
-
buildSync: vi.fn(),
|
|
9
|
-
}));
|
|
10
7
|
|
|
11
8
|
describe("call command", () => {
|
|
12
9
|
let program: Command;
|
|
@@ -4,9 +4,6 @@ import { initializeContractsCommands } from "../../src/commands/contracts";
|
|
|
4
4
|
import { DeployAction } from "../../src/commands/contracts/deploy";
|
|
5
5
|
|
|
6
6
|
vi.mock("../../src/commands/contracts/deploy");
|
|
7
|
-
vi.mock("esbuild", () => ({
|
|
8
|
-
buildSync: vi.fn(),
|
|
9
|
-
}));
|
|
10
7
|
|
|
11
8
|
describe("deploy command", () => {
|
|
12
9
|
let program: Command;
|
|
@@ -69,12 +66,4 @@ describe("deploy command", () => {
|
|
|
69
66
|
program.parse(["node", "test", "deploy", "--contract", "./path/to/contract"])
|
|
70
67
|
).not.toThrow();
|
|
71
68
|
});
|
|
72
|
-
|
|
73
|
-
test("DeployAction.deployScripts is called without throwing errors", async () => {
|
|
74
|
-
program.parse(["node", "test", "deploy"]);
|
|
75
|
-
vi.mocked(DeployAction.prototype.deployScripts).mockResolvedValueOnce(undefined);
|
|
76
|
-
expect(() =>
|
|
77
|
-
program.parse(["node", "test", "deploy"])
|
|
78
|
-
).not.toThrow();
|
|
79
|
-
});
|
|
80
69
|
});
|