genlayer 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -24,7 +24,7 @@ jobs:
24
24
  - name: Setup Node.js
25
25
  uses: actions/setup-node@v4
26
26
  with:
27
- node-version: "18"
27
+ node-version: "22"
28
28
  - name: Install the dependencies
29
29
  run: npm ci
30
30
  - name: Initialize Git User
@@ -24,7 +24,7 @@ jobs:
24
24
  - name: Setup Node.js
25
25
  uses: actions/setup-node@v4
26
26
  with:
27
- node-version: "18"
27
+ node-version: "22"
28
28
  - name: Install the dependencies
29
29
  run: npm ci
30
30
  - name: Initialize Git User
@@ -36,7 +36,7 @@ jobs:
36
36
 
37
37
  - name: Upload coverage report
38
38
  if: success()
39
- uses: codecov/codecov-action@v5.3.1
39
+ uses: codecov/codecov-action@v5.4.2
40
40
  with:
41
41
  verbose: true
42
42
  token: ${{ secrets.CODECOV_TOKEN }}
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.15.0 (2025-04-29)
4
+
5
+ ### Features
6
+
7
+ * custom rpc for interacting with contracts ([#218](https://github.com/yeagerai/genlayer-cli/issues/218)) ([138babd](https://github.com/yeagerai/genlayer-cli/commit/138babd76b24d2333356ec64cfdb712add312585))
8
+
9
+ ## 0.14.1 (2025-04-25)
10
+
3
11
  ## 0.14.0 (2025-04-25)
4
12
 
5
13
  ### Features
package/dist/index.js CHANGED
@@ -16853,7 +16853,7 @@ var require_semver2 = __commonJS({
16853
16853
  import { program } from "commander";
16854
16854
 
16855
16855
  // package.json
16856
- var version = "0.14.0";
16856
+ var version = "0.15.0";
16857
16857
  var package_default = {
16858
16858
  name: "genlayer",
16859
16859
  version,
@@ -16891,7 +16891,7 @@ var package_default = {
16891
16891
  },
16892
16892
  homepage: "https://github.com/yeagerai/genlayer-cli#readme",
16893
16893
  devDependencies: {
16894
- "@release-it/conventional-changelog": "^10.0.0",
16894
+ "@release-it/conventional-changelog": "^10.0.1",
16895
16895
  "@types/dockerode": "^3.3.31",
16896
16896
  "@types/fs-extra": "^11.0.4",
16897
16897
  "@types/inquirer": "^9.0.7",
@@ -16905,11 +16905,11 @@ var package_default = {
16905
16905
  esbuild: ">=0.25.0",
16906
16906
  eslint: "^9.0.0",
16907
16907
  "eslint-config-prettier": "^10.0.0",
16908
- "eslint-import-resolver-typescript": "^3.6.1",
16908
+ "eslint-import-resolver-typescript": "^4.0.0",
16909
16909
  "eslint-plugin-import": "^2.29.1",
16910
16910
  jsdom: "^26.0.0",
16911
16911
  prettier: "^3.2.5",
16912
- "release-it": "^18.0.0",
16912
+ "release-it": "^19.0.0",
16913
16913
  "ts-node": "^10.9.2",
16914
16914
  typescript: "^5.4.5"
16915
16915
  },
@@ -27755,11 +27755,11 @@ var BaseAction = class extends ConfigFileManager {
27755
27755
  this.spinner = ora({ text: "", spinner: "dots" });
27756
27756
  this.keypairManager = new KeypairManager();
27757
27757
  }
27758
- async getClient() {
27758
+ async getClient(rpcUrl) {
27759
27759
  if (!this._genlayerClient) {
27760
27760
  this._genlayerClient = createClient2({
27761
27761
  chain: localnet,
27762
- endpoint: process.env.VITE_JSON_RPC_SERVER_URL,
27762
+ endpoint: rpcUrl,
27763
27763
  account: createAccount(await this.getPrivateKey())
27764
27764
  });
27765
27765
  }
@@ -28213,6 +28213,7 @@ var baseOpen = async (options) => {
28213
28213
  "firefox.desktop": "firefox",
28214
28214
  "com.microsoft.msedge": "edge",
28215
28215
  "com.microsoft.edge": "edge",
28216
+ "com.microsoft.edgemac": "edge",
28216
28217
  "microsoft-edge.desktop": "edge"
28217
28218
  };
28218
28219
  const flags = {
@@ -28951,7 +28952,7 @@ var DeployAction = class extends BaseAction {
28951
28952
  }
28952
28953
  return fs8.readFileSync(contractPath, "utf-8");
28953
28954
  }
28954
- async executeTsScript(filePath) {
28955
+ async executeTsScript(filePath, rpcUrl) {
28955
28956
  const outFile = filePath.replace(/\.ts$/, ".compiled.js");
28956
28957
  this.startSpinner(`Transpiling TypeScript file: ${filePath}`);
28957
28958
  try {
@@ -28964,14 +28965,14 @@ var DeployAction = class extends BaseAction {
28964
28965
  target: "es2020",
28965
28966
  sourcemap: false
28966
28967
  });
28967
- await this.executeJsScript(filePath, outFile);
28968
+ await this.executeJsScript(filePath, outFile, rpcUrl);
28968
28969
  } catch (error) {
28969
28970
  this.failSpinner(`Error executing: ${filePath}`, error);
28970
28971
  } finally {
28971
28972
  fs8.unlinkSync(outFile);
28972
28973
  }
28973
28974
  }
28974
- async executeJsScript(filePath, transpiledFilePath) {
28975
+ async executeJsScript(filePath, transpiledFilePath, rpcUrl) {
28975
28976
  this.startSpinner(`Executing file: ${filePath}`);
28976
28977
  try {
28977
28978
  const module = await import(pathToFileURL(transpiledFilePath || filePath).href);
@@ -28979,14 +28980,14 @@ var DeployAction = class extends BaseAction {
28979
28980
  this.failSpinner(`No "default" function found in: ${filePath}`);
28980
28981
  return;
28981
28982
  }
28982
- const client = await this.getClient();
28983
+ const client = await this.getClient(rpcUrl);
28983
28984
  await module.default(client);
28984
28985
  this.succeedSpinner(`Successfully executed: ${filePath}`);
28985
28986
  } catch (error) {
28986
28987
  this.failSpinner(`Error executing: ${filePath}`, error);
28987
28988
  }
28988
28989
  }
28989
- async deployScripts() {
28990
+ async deployScripts(options) {
28990
28991
  this.startSpinner("Searching for deploy scripts...");
28991
28992
  if (!fs8.existsSync(this.deployDir)) {
28992
28993
  this.failSpinner("No deploy folder found.");
@@ -29010,9 +29011,9 @@ var DeployAction = class extends BaseAction {
29010
29011
  this.setSpinnerText(`Executing script: ${filePath}`);
29011
29012
  try {
29012
29013
  if (file.endsWith(".ts")) {
29013
- await this.executeTsScript(filePath);
29014
+ await this.executeTsScript(filePath, options?.rpc);
29014
29015
  } else {
29015
- await this.executeJsScript(filePath);
29016
+ await this.executeJsScript(filePath, void 0, options?.rpc);
29016
29017
  }
29017
29018
  } catch (error) {
29018
29019
  this.failSpinner(`Error executing script: ${filePath}`, error);
@@ -29021,7 +29022,7 @@ var DeployAction = class extends BaseAction {
29021
29022
  }
29022
29023
  async deploy(options) {
29023
29024
  try {
29024
- const client = await this.getClient();
29025
+ const client = await this.getClient(options.rpc);
29025
29026
  this.startSpinner("Setting up the deployment environment...");
29026
29027
  await client.initializeConsensusSmartContract();
29027
29028
  if (!options.contract) {
@@ -29064,9 +29065,11 @@ var CallAction = class extends BaseAction {
29064
29065
  async call({
29065
29066
  contractAddress,
29066
29067
  method,
29067
- args
29068
+ args,
29069
+ rpc
29068
29070
  }) {
29069
- const client = await this.getClient();
29071
+ const client = await this.getClient(rpc);
29072
+ await client.initializeConsensusSmartContract();
29070
29073
  this.startSpinner(`Calling method ${method} on contract at ${contractAddress}...`);
29071
29074
  const contractSchema = await client.getContractSchema(contractAddress);
29072
29075
  if (!contractSchema.methods.hasOwnProperty(method)) {
@@ -29123,15 +29126,16 @@ function parseArg(value, previous = []) {
29123
29126
  return [...previous, value];
29124
29127
  }
29125
29128
  function initializeContractsCommands(program2) {
29126
- 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)", parseArg, []).action(async (options) => {
29129
+ program2.command("deploy").description("Deploy intelligent contracts").option("--contract <contractPath>", "Path to the smart contract to deploy").option("--rpc <rpcUrl>", "RPC URL for the network").option("--args <args...>", "Positional arguments for the contract (space-separated, use quotes for multi-word arguments)", parseArg, []).action(async (options) => {
29127
29130
  const deployer = new DeployAction();
29128
29131
  if (options.contract) {
29129
29132
  await deployer.deploy(options);
29130
29133
  } else {
29131
- await deployer.deployScripts();
29134
+ const deployScriptsOptions = { rpc: options.rpc };
29135
+ await deployer.deployScripts(deployScriptsOptions);
29132
29136
  }
29133
29137
  });
29134
- 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)", parseArg, []).action(async (contractAddress, method, options) => {
29138
+ program2.command("call <contractAddress> <method>").description("Call a contract method").option("--rpc <rpcUrl>", "RPC URL for the network").option("--args <args...>", "Positional arguments for the method (space-separated, use quotes for multi-word arguments)", parseArg, []).action(async (contractAddress, method, options) => {
29135
29139
  const caller = new CallAction();
29136
29140
  await caller.call({ contractAddress, method, ...options });
29137
29141
  });
@@ -93,7 +93,7 @@ services:
93
93
  max-file: "3"
94
94
 
95
95
  ollama:
96
- image: ollama/ollama:0.5.11
96
+ image: ollama/ollama:0.6.6
97
97
  ports:
98
98
  - 11434:11434
99
99
  container_name: ollama
@@ -108,7 +108,7 @@ services:
108
108
  max-file: "3"
109
109
 
110
110
  postgres:
111
- image: postgres:16-alpine
111
+ image: postgres:17-alpine
112
112
  ports:
113
113
  - "${DBPORT:-5432}:5432"
114
114
  environment:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "genlayer",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "GenLayer Command Line Tool",
5
5
  "main": "src/index.ts",
6
6
  "type": "module",
@@ -35,7 +35,7 @@
35
35
  },
36
36
  "homepage": "https://github.com/yeagerai/genlayer-cli#readme",
37
37
  "devDependencies": {
38
- "@release-it/conventional-changelog": "^10.0.0",
38
+ "@release-it/conventional-changelog": "^10.0.1",
39
39
  "@types/dockerode": "^3.3.31",
40
40
  "@types/fs-extra": "^11.0.4",
41
41
  "@types/inquirer": "^9.0.7",
@@ -49,11 +49,11 @@
49
49
  "esbuild": ">=0.25.0",
50
50
  "eslint": "^9.0.0",
51
51
  "eslint-config-prettier": "^10.0.0",
52
- "eslint-import-resolver-typescript": "^3.6.1",
52
+ "eslint-import-resolver-typescript": "^4.0.0",
53
53
  "eslint-plugin-import": "^2.29.1",
54
54
  "jsdom": "^26.0.0",
55
55
  "prettier": "^3.2.5",
56
- "release-it": "^18.0.0",
56
+ "release-it": "^19.0.0",
57
57
  "ts-node": "^10.9.2",
58
58
  "typescript": "^5.4.5"
59
59
  },
@@ -4,6 +4,7 @@ import { BaseAction } from "../../lib/actions/BaseAction";
4
4
 
5
5
  export interface CallOptions {
6
6
  args: any[];
7
+ rpc?: string;
7
8
  }
8
9
 
9
10
  export class CallAction extends BaseAction{
@@ -15,12 +16,15 @@ export class CallAction extends BaseAction{
15
16
  contractAddress,
16
17
  method,
17
18
  args,
19
+ rpc,
18
20
  }: {
19
21
  contractAddress: string;
20
22
  method: string;
21
23
  args: any[];
24
+ rpc?: string;
22
25
  }): Promise<void> {
23
- const client = await this.getClient();
26
+ const client = await this.getClient(rpc);
27
+ await client.initializeConsensusSmartContract();
24
28
  this.startSpinner(`Calling method ${method} on contract at ${contractAddress}...`);
25
29
 
26
30
  const contractSchema = await client.getContractSchema(contractAddress);
@@ -10,6 +10,11 @@ import { buildSync } from "esbuild";
10
10
  export interface DeployOptions {
11
11
  contract?: string;
12
12
  args?: any[];
13
+ rpc?: string;
14
+ }
15
+
16
+ export interface DeployScriptsOptions {
17
+ rpc?: string;
13
18
  }
14
19
 
15
20
  export class DeployAction extends BaseAction {
@@ -26,7 +31,7 @@ export class DeployAction extends BaseAction {
26
31
  return fs.readFileSync(contractPath, "utf-8");
27
32
  }
28
33
 
29
- private async executeTsScript(filePath: string): Promise<void> {
34
+ private async executeTsScript(filePath: string, rpcUrl?: string): Promise<void> {
30
35
  const outFile = filePath.replace(/\.ts$/, ".compiled.js");
31
36
  this.startSpinner(`Transpiling TypeScript file: ${filePath}`);
32
37
  try {
@@ -39,7 +44,7 @@ export class DeployAction extends BaseAction {
39
44
  target: "es2020",
40
45
  sourcemap: false,
41
46
  });
42
- await this.executeJsScript(filePath, outFile);
47
+ await this.executeJsScript(filePath, outFile, rpcUrl);
43
48
  } catch (error) {
44
49
  this.failSpinner(`Error executing: ${filePath}`, error);
45
50
  } finally {
@@ -47,7 +52,7 @@ export class DeployAction extends BaseAction {
47
52
  }
48
53
  }
49
54
 
50
- private async executeJsScript(filePath: string, transpiledFilePath?: string): Promise<void> {
55
+ private async executeJsScript(filePath: string, transpiledFilePath?: string, rpcUrl?: string): Promise<void> {
51
56
  this.startSpinner(`Executing file: ${filePath}`);
52
57
  try {
53
58
  const module = await import(pathToFileURL(transpiledFilePath || filePath).href);
@@ -55,7 +60,7 @@ export class DeployAction extends BaseAction {
55
60
  this.failSpinner(`No "default" function found in: ${filePath}`);
56
61
  return
57
62
  }
58
- const client = await this.getClient();
63
+ const client = await this.getClient(rpcUrl);
59
64
  await module.default(client);
60
65
  this.succeedSpinner(`Successfully executed: ${filePath}`);
61
66
  } catch (error) {
@@ -63,7 +68,7 @@ export class DeployAction extends BaseAction {
63
68
  }
64
69
  }
65
70
 
66
- async deployScripts() {
71
+ async deployScripts(options?: DeployScriptsOptions) {
67
72
  this.startSpinner("Searching for deploy scripts...");
68
73
  if (!fs.existsSync(this.deployDir)) {
69
74
  this.failSpinner("No deploy folder found.");
@@ -93,9 +98,9 @@ export class DeployAction extends BaseAction {
93
98
  this.setSpinnerText(`Executing script: ${filePath}`);
94
99
  try {
95
100
  if (file.endsWith(".ts")) {
96
- await this.executeTsScript(filePath);
101
+ await this.executeTsScript(filePath, options?.rpc);
97
102
  } else {
98
- await this.executeJsScript(filePath);
103
+ await this.executeJsScript(filePath, undefined, options?.rpc);
99
104
  }
100
105
  } catch (error) {
101
106
  this.failSpinner(`Error executing script: ${filePath}`, error);
@@ -105,7 +110,7 @@ export class DeployAction extends BaseAction {
105
110
 
106
111
  async deploy(options: DeployOptions): Promise<void> {
107
112
  try {
108
- const client = await this.getClient();
113
+ const client = await this.getClient(options.rpc);
109
114
  this.startSpinner("Setting up the deployment environment...");
110
115
  await client.initializeConsensusSmartContract();
111
116
 
@@ -1,5 +1,5 @@
1
1
  import { Command } from "commander";
2
- import { DeployAction, DeployOptions } from "./deploy";
2
+ import { DeployAction, DeployOptions, DeployScriptsOptions } from "./deploy";
3
3
  import { CallAction, CallOptions } from "./call";
4
4
 
5
5
  function parseArg(value: string, previous: any[] = []): any[] {
@@ -15,20 +15,22 @@ export function initializeContractsCommands(program: Command) {
15
15
  .command("deploy")
16
16
  .description("Deploy intelligent contracts")
17
17
  .option("--contract <contractPath>", "Path to the smart contract to deploy")
18
- // .option("--network <networkName>", "Specify the network (e.g., testnet)", "localnet")
18
+ .option("--rpc <rpcUrl>", "RPC URL for the network")
19
19
  .option("--args <args...>", "Positional arguments for the contract (space-separated, use quotes for multi-word arguments)", parseArg, [])
20
20
  .action(async (options: DeployOptions) => {
21
21
  const deployer = new DeployAction();
22
22
  if(options.contract){
23
23
  await deployer.deploy(options);
24
24
  }else {
25
- await deployer.deployScripts();
25
+ const deployScriptsOptions: DeployScriptsOptions = { rpc: options.rpc };
26
+ await deployer.deployScripts(deployScriptsOptions);
26
27
  }
27
28
  });
28
29
 
29
30
  program
30
31
  .command("call <contractAddress> <method>")
31
32
  .description("Call a contract method")
33
+ .option("--rpc <rpcUrl>", "RPC URL for the network")
32
34
  .option("--args <args...>", "Positional arguments for the method (space-separated, use quotes for multi-word arguments)", parseArg, [])
33
35
  .action(async (contractAddress: string, method: string, options: CallOptions) => {
34
36
  const caller = new CallAction();
@@ -18,11 +18,11 @@ export class BaseAction extends ConfigFileManager {
18
18
  this.keypairManager = new KeypairManager();
19
19
  }
20
20
 
21
- protected async getClient(): Promise<GenLayerClient<typeof localnet>> {
21
+ protected async getClient(rpcUrl?: string): Promise<GenLayerClient<typeof localnet>> {
22
22
  if (!this._genlayerClient) {
23
23
  this._genlayerClient = createClient({
24
24
  chain: localnet,
25
- endpoint: process.env.VITE_JSON_RPC_SERVER_URL,
25
+ endpoint: rpcUrl,
26
26
  account: createAccount(await this.getPrivateKey() as any),
27
27
  });
28
28
  }
@@ -9,8 +9,8 @@
9
9
  "preview": "vite preview"
10
10
  },
11
11
  "dependencies": {
12
- "genlayer-js": "^0.6.4",
13
- "lucide-vue-next": "^0.446.0",
12
+ "genlayer-js": "0.8.0",
13
+ "lucide-vue-next": "^0.503.0",
14
14
  "vue": "^3.4.37"
15
15
  },
16
16
  "devDependencies": {
@@ -6,7 +6,7 @@
6
6
  "": {
7
7
  "name": "genlayer-project",
8
8
  "devDependencies": {
9
- "genlayer-js": "^0.6.0"
9
+ "genlayer-js": "^0.9.0"
10
10
  }
11
11
  },
12
12
  "node_modules/@adraffy/ens-normalize": {
@@ -1403,9 +1403,9 @@
1403
1403
  }
1404
1404
  },
1405
1405
  "node_modules/genlayer-js": {
1406
- "version": "0.6.4",
1407
- "resolved": "https://registry.npmjs.org/genlayer-js/-/genlayer-js-0.6.4.tgz",
1408
- "integrity": "sha512-tbsBRyVUGZ0a+661ML6wu3U3p5CtHkik7a4qTc68OZgf1pX1G4JBs7CzAmqAkMt8HUyD/J413raDs9Q5s3psWw==",
1406
+ "version": "0.9.0",
1407
+ "resolved": "https://registry.npmjs.org/genlayer-js/-/genlayer-js-0.9.0.tgz",
1408
+ "integrity": "sha512-PBG9k7g9/uvl33DIs9bVTb+bdaHnbmXwphsh4fAUmv5CLTLKQtfLqQ7+OXFFVq56txs9geldr+g7ulgd8YtCGQ==",
1409
1409
  "dev": true,
1410
1410
  "license": "MIT",
1411
1411
  "dependencies": {
@@ -2,6 +2,6 @@
2
2
  "name": "genlayer-project",
3
3
  "type": "module",
4
4
  "devDependencies": {
5
- "genlayer-js": "^0.6.0"
5
+ "genlayer-js": "^0.9.0"
6
6
  }
7
7
  }
@@ -1,6 +1,6 @@
1
- requests==2.31.0
2
- python-dotenv==1.0.1
3
- pytest==8.2.1
1
+ requests==2.32.2
2
+ python-dotenv==1.1.0
3
+ pytest==8.3.5
4
4
  pytest-mock==3.14.0
5
- eth-account==0.13.3
6
- eth-utils==5.0.0
5
+ eth-account==0.13.7
6
+ eth-utils==5.3.0
@@ -11,6 +11,7 @@ describe("CallAction", () => {
11
11
  writeContract: vi.fn(),
12
12
  waitForTransactionReceipt: vi.fn(),
13
13
  getContractSchema: vi.fn(),
14
+ initializeConsensusSmartContract: vi.fn()
14
15
  };
15
16
 
16
17
  const mockPrivateKey = "mocked_private_key";
@@ -103,4 +104,55 @@ describe("CallAction", () => {
103
104
 
104
105
  expect(callActions["failSpinner"]).toHaveBeenCalledWith("Error during write operation", expect.any(Error));
105
106
  });
107
+
108
+ test("uses custom RPC URL when provided", async () => {
109
+ const options = { args: [1, 2, "Hello"], rpc: "https://custom-rpc-url.com" };
110
+ const mockResult = "mocked_result";
111
+
112
+ vi.mocked(mockClient.getContractSchema).mockResolvedValue({ methods: { getData: { readonly: true } } });
113
+ vi.mocked(mockClient.readContract).mockResolvedValue(mockResult);
114
+
115
+ await callActions.call({
116
+ contractAddress: "0xMockedContract",
117
+ method: "getData",
118
+ ...options,
119
+ });
120
+
121
+ expect(createClient).toHaveBeenCalledWith(expect.objectContaining({
122
+ endpoint: "https://custom-rpc-url.com"
123
+ }));
124
+ expect(mockClient.readContract).toHaveBeenCalledWith({
125
+ address: "0xMockedContract",
126
+ functionName: "getData",
127
+ args: [1, 2, "Hello"],
128
+ });
129
+ expect(callActions["succeedSpinner"]).toHaveBeenCalledWith("Read operation successfully executed", "mocked_result");
130
+ });
131
+
132
+ test("uses custom RPC URL for write operations", async () => {
133
+ const options = { args: [42, "Update"], rpc: "https://custom-rpc-url.com" };
134
+ const mockHash = "0xMockedTransactionHash";
135
+ const mockReceipt = { status: "success" };
136
+
137
+ vi.mocked(mockClient.getContractSchema).mockResolvedValue({ methods: { updateData: { readonly: false } } });
138
+ vi.mocked(mockClient.writeContract).mockResolvedValue(mockHash);
139
+ vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue(mockReceipt);
140
+
141
+ await callActions.call({
142
+ contractAddress: "0xMockedContract",
143
+ method: "updateData",
144
+ ...options,
145
+ });
146
+
147
+ expect(createClient).toHaveBeenCalledWith(expect.objectContaining({
148
+ endpoint: "https://custom-rpc-url.com"
149
+ }));
150
+ expect(mockClient.writeContract).toHaveBeenCalledWith({
151
+ address: "0xMockedContract",
152
+ functionName: "updateData",
153
+ args: [42, "Update"],
154
+ value: 0n,
155
+ });
156
+ expect(callActions["succeedSpinner"]).toHaveBeenCalledWith("Write operation successfully executed", mockReceipt);
157
+ });
106
158
  });
@@ -143,9 +143,9 @@ describe("DeployAction", () => {
143
143
  await deployer.deployScripts();
144
144
 
145
145
  expect(deployer["setSpinnerText"]).toHaveBeenCalledWith("Found 3 deploy scripts. Executing...");
146
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringMatching(/1_first.ts/));
147
- expect(deployer["executeJsScript"]).toHaveBeenCalledWith(expect.stringMatching(/2_second.js/));
148
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringMatching(/10_last.ts/));
146
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringMatching(/1_first.ts/), undefined);
147
+ expect(deployer["executeJsScript"]).toHaveBeenCalledWith(expect.stringMatching(/2_second.js/), undefined, undefined);
148
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringMatching(/10_last.ts/), undefined);
149
149
  });
150
150
 
151
151
  test("executeTsScript transpiles and executes TypeScript", async () => {
@@ -168,7 +168,7 @@ describe("DeployAction", () => {
168
168
  sourcemap: false,
169
169
  });
170
170
 
171
- expect(deployer["executeJsScript"]).toHaveBeenCalledWith(filePath, outFile);
171
+ expect(deployer["executeJsScript"]).toHaveBeenCalledWith(filePath, outFile, undefined);
172
172
  expect(fs.unlinkSync).toHaveBeenCalledWith(outFile);
173
173
  });
174
174
 
@@ -193,9 +193,9 @@ describe("DeployAction", () => {
193
193
 
194
194
  await deployer.deployScripts();
195
195
 
196
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("1_first.ts"));
197
- expect(deployer["executeJsScript"]).toHaveBeenCalledWith(expect.stringContaining("2_second.js"));
198
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("10_last.ts"));
196
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("1_first.ts"), undefined);
197
+ expect(deployer["executeJsScript"]).toHaveBeenCalledWith(expect.stringContaining("2_second.js"), undefined, undefined);
198
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("10_last.ts"), undefined);
199
199
  });
200
200
 
201
201
  test("deployScripts fails when no scripts are found", async () => {
@@ -257,11 +257,11 @@ describe("DeployAction", () => {
257
257
 
258
258
  await deployer.deployScripts();
259
259
 
260
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("script.ts"));
261
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("2alpha_script.ts"));
262
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("3alpha_script.ts"));
263
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("blpha_script.ts"));
264
- expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("clpha_script.ts"));
260
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("script.ts"), undefined);
261
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("2alpha_script.ts"), undefined);
262
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("3alpha_script.ts"), undefined);
263
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("blpha_script.ts"), undefined);
264
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(expect.stringContaining("clpha_script.ts"), undefined);
265
265
  });
266
266
 
267
267
  test("executeJsScript fails if module has no default export", async () => {
@@ -304,4 +304,98 @@ describe("DeployAction", () => {
304
304
  error
305
305
  );
306
306
  });
307
+
308
+ test("deploys contract with rpc option", async () => {
309
+ const options: DeployOptions = {
310
+ contract: "/mocked/contract/path",
311
+ args: [1, 2, 3],
312
+ rpc: "https://custom-rpc-url.com"
313
+ };
314
+ const contractContent = "contract code";
315
+
316
+ vi.mocked(fs.existsSync).mockReturnValue(true);
317
+ vi.mocked(fs.readFileSync).mockReturnValue(contractContent);
318
+ vi.mocked(mockClient.deployContract).mockResolvedValue("mocked_tx_hash");
319
+ vi.mocked(mockClient.waitForTransactionReceipt).mockResolvedValue({
320
+ data: { contract_address: "0xdasdsadasdasdada" },
321
+ });
322
+
323
+ await deployer.deploy(options);
324
+
325
+ expect(createClient).toHaveBeenCalledWith(expect.objectContaining({
326
+ endpoint: "https://custom-rpc-url.com"
327
+ }));
328
+ expect(fs.readFileSync).toHaveBeenCalledWith(options.contract, "utf-8");
329
+ expect(mockClient.deployContract).toHaveBeenCalledWith({
330
+ code: contractContent,
331
+ args: [1, 2, 3],
332
+ leaderOnly: false,
333
+ });
334
+ });
335
+
336
+ test("executeJsScript uses rpc url when provided", async () => {
337
+ const filePath = "/mocked/script.js";
338
+ const rpcUrl = "https://custom-rpc-url.com";
339
+ const mockFn = vi.fn();
340
+
341
+ vi.doMock(pathToFileURL(filePath).href, () => ({ default: mockFn }));
342
+
343
+ await deployer["executeJsScript"](filePath, undefined, rpcUrl);
344
+
345
+ expect(createClient).toHaveBeenCalledWith(expect.objectContaining({
346
+ endpoint: rpcUrl
347
+ }));
348
+ expect(mockFn).toHaveBeenCalledWith(mockClient);
349
+ expect(deployer["succeedSpinner"]).toHaveBeenCalledWith(`Successfully executed: ${filePath}`);
350
+ });
351
+
352
+ test("executeTsScript passes rpc url to executeJsScript", async () => {
353
+ const filePath = "/mocked/script.ts";
354
+ const outFile = "/mocked/script.compiled.js";
355
+ const rpcUrl = "https://custom-rpc-url.com";
356
+
357
+ vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
358
+ vi.mocked(buildSync).mockImplementation((() => {}) as any);
359
+
360
+ await deployer["executeTsScript"](filePath, rpcUrl);
361
+
362
+ expect(deployer["startSpinner"]).toHaveBeenCalledWith(`Transpiling TypeScript file: ${filePath}`);
363
+ expect(buildSync).toHaveBeenCalledWith({
364
+ entryPoints: [filePath],
365
+ outfile: outFile,
366
+ bundle: false,
367
+ platform: "node",
368
+ format: "esm",
369
+ target: "es2020",
370
+ sourcemap: false,
371
+ });
372
+
373
+ expect(deployer["executeJsScript"]).toHaveBeenCalledWith(filePath, outFile, rpcUrl);
374
+ expect(fs.unlinkSync).toHaveBeenCalledWith(outFile);
375
+ });
376
+
377
+ test("deployScripts passes rpc url to script execution methods", async () => {
378
+ const rpcUrl = "https://custom-rpc-url.com";
379
+
380
+ vi.mocked(fs.existsSync).mockReturnValue(true);
381
+ vi.mocked(fs.readdirSync).mockReturnValue([
382
+ "1_first.ts",
383
+ "2_second.js",
384
+ ] as any);
385
+
386
+ vi.spyOn(deployer as any, "executeTsScript").mockResolvedValue(undefined);
387
+ vi.spyOn(deployer as any, "executeJsScript").mockResolvedValue(undefined);
388
+
389
+ await deployer.deployScripts({ rpc: rpcUrl });
390
+
391
+ expect(deployer["executeTsScript"]).toHaveBeenCalledWith(
392
+ expect.stringMatching(/1_first.ts/),
393
+ rpcUrl
394
+ );
395
+ expect(deployer["executeJsScript"]).toHaveBeenCalledWith(
396
+ expect.stringMatching(/2_second.js/),
397
+ undefined,
398
+ rpcUrl
399
+ );
400
+ });
307
401
  });