@0xobelisk/sui-cli 0.5.28 → 0.5.30

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.
@@ -3,9 +3,9 @@ import { schemaGen, loadConfig, DubheConfig } from '@0xobelisk/sui-common';
3
3
  import chalk from 'chalk';
4
4
 
5
5
  type Options = {
6
- configPath?: string;
6
+ 'config-path'?: string;
7
7
  network?: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
8
- frameworkId?: string;
8
+ 'framework-id'?: string;
9
9
  };
10
10
 
11
11
  const commandModule: CommandModule<Options, Options> = {
@@ -14,7 +14,7 @@ const commandModule: CommandModule<Options, Options> = {
14
14
  describe: 'Autogenerate Dubhe schemas based on the config file',
15
15
 
16
16
  builder: {
17
- configPath: {
17
+ 'config-path': {
18
18
  type: 'string',
19
19
  default: 'dubhe.config.ts',
20
20
  desc: 'Path to the config file',
@@ -24,17 +24,19 @@ const commandModule: CommandModule<Options, Options> = {
24
24
  choices: ['mainnet', 'testnet', 'devnet', 'localnet'] as const,
25
25
  desc: 'Node network (mainnet/testnet/devnet/localnet)',
26
26
  },
27
- frameworkId: {
27
+ 'framework-id': {
28
28
  type: 'string',
29
29
  desc: 'Framework Package ID',
30
30
  },
31
31
  },
32
32
 
33
- async handler({ configPath, network, frameworkId }) {
33
+ async handler({
34
+ 'config-path': configPath,
35
+ network,
36
+ 'framework-id': frameworkId,
37
+ }) {
34
38
  try {
35
- const dubheConfig = (await loadConfig(
36
- configPath
37
- )) as DubheConfig;
39
+ const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
38
40
  await schemaGen(dubheConfig, undefined, network, frameworkId);
39
41
  process.exit(0);
40
42
  } catch (error: any) {
@@ -1,9 +1,11 @@
1
1
  import type { CommandModule } from "yargs";
2
2
  import { execSync } from "child_process";
3
3
  import chalk from "chalk";
4
+ import { DubheConfig, loadConfig } from '@0xobelisk/sui-common';
4
5
 
5
6
  type Options = {
6
- packagePath: string;
7
+ 'config-path': string;
8
+ 'test'?: string;
7
9
  };
8
10
 
9
11
  const commandModule: CommandModule<Options, Options> = {
@@ -13,20 +15,28 @@ const commandModule: CommandModule<Options, Options> = {
13
15
 
14
16
  builder(yargs) {
15
17
  return yargs.options({
16
- packagePath: {
18
+ 'config-path': {
17
19
  type: "string",
18
- default: ".",
20
+ default: "dubhe.config.ts",
19
21
  description: "Options to pass to forge test",
20
22
  },
23
+ test: {
24
+ type: 'string',
25
+ desc: 'Run a specific test',
26
+ },
21
27
  });
22
28
  },
23
29
 
24
- async handler({ packagePath }) {
30
+ async handler({ 'config-path': configPath, test }) {
25
31
  // Start an internal anvil process if no world address is provided
26
32
  try {
27
- execSync(`sui move test --path ${packagePath}`, {
28
- encoding: "utf-8",
29
- });
33
+ console.log('šŸš€ Running move test');
34
+ const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
35
+ const path = process.cwd();
36
+ const projectPath = `${path}/contracts/${dubheConfig.name}`;
37
+ const command = `sui move test --path ${projectPath} ${test ? ` --test ${test}` : ''}`;
38
+ const output = execSync(command, { encoding: "utf-8" });
39
+ console.log(output);
30
40
  } catch (error: any) {
31
41
  console.error(chalk.red("Error executing sui move test:"));
32
42
  console.log(error.stdout);
@@ -1,43 +1,43 @@
1
- import type { CommandModule } from "yargs";
2
- import { logError } from "../utils/errors";
3
- import { upgradeHandler } from "../utils/upgradeHandler";
4
- import { DubheConfig, loadConfig } from "@0xobelisk/sui-common";
1
+ import type { CommandModule } from 'yargs';
2
+ import { logError } from '../utils/errors';
3
+ import { upgradeHandler } from '../utils/upgradeHandler';
4
+ import { DubheConfig, loadConfig } from '@0xobelisk/sui-common';
5
5
 
6
6
  type Options = {
7
- network: any;
8
- configPath: string;
7
+ network: any;
8
+ 'config-path': string;
9
9
  };
10
10
 
11
11
  const commandModule: CommandModule<Options, Options> = {
12
- command: "upgrade",
12
+ command: 'upgrade',
13
13
 
14
- describe: "Upgrade your move contracts",
14
+ describe: 'Upgrade your move contracts',
15
15
 
16
- builder(yargs) {
17
- return yargs.options({
18
- network: {
19
- type: "string",
20
- choices: ["mainnet", "testnet", "devnet", "localnet"],
21
- desc: "Network of the node (mainnet/testnet/devnet/localnet)",
22
- },
23
- configPath: {
24
- type: "string",
25
- default: "dubhe.config.ts",
26
- decs: "Path to the config file",
27
- },
28
- });
29
- },
16
+ builder(yargs) {
17
+ return yargs.options({
18
+ network: {
19
+ type: 'string',
20
+ choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
21
+ desc: 'Network of the node (mainnet/testnet/devnet/localnet)',
22
+ },
23
+ 'config-path': {
24
+ type: 'string',
25
+ default: 'dubhe.config.ts',
26
+ decs: 'Path to the config file',
27
+ },
28
+ });
29
+ },
30
30
 
31
- async handler({ network, configPath }) {
32
- try {
33
- const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
34
- await upgradeHandler(dubheConfig, dubheConfig.name, network);
35
- } catch (error: any) {
36
- logError(error);
37
- process.exit(1);
38
- }
39
- process.exit(0);
40
- },
31
+ async handler({ network, 'config-path': configPath }) {
32
+ try {
33
+ const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
34
+ await upgradeHandler(dubheConfig, dubheConfig.name, network);
35
+ } catch (error: any) {
36
+ logError(error);
37
+ process.exit(1);
38
+ }
39
+ process.exit(0);
40
+ },
41
41
  };
42
42
 
43
43
  export default commandModule;
@@ -145,6 +145,7 @@ function buildContract(projectPath: string): string[][] {
145
145
  `sui move build --dump-bytecode-as-base64 --path ${projectPath}`,
146
146
  {
147
147
  encoding: 'utf-8',
148
+ stdio: 'pipe',
148
149
  }
149
150
  )
150
151
  );
@@ -315,7 +316,7 @@ async function publishContract(
315
316
  }
316
317
  }
317
318
 
318
- async function publishDubheFramework(
319
+ export async function publishDubheFramework(
319
320
  client: SuiClient,
320
321
  dubhe: Dubhe,
321
322
  network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
@@ -0,0 +1,117 @@
1
+ import { execSync, spawn } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import { printDubhe } from './printDubhe';
4
+ import { delay, DubheCliError, publishDubheFramework, validatePrivateKey } from '../utils';
5
+ import { Dubhe } from '@0xobelisk/sui-client';
6
+ import { getFullnodeUrl, SuiClient } from '@mysten/sui/client';
7
+
8
+ function isSuiStartRunning(): boolean {
9
+ try {
10
+ const cmd =
11
+ process.platform === 'win32'
12
+ ? `tasklist /FI "IMAGENAME eq sui.exe" /FO CSV /NH`
13
+ : 'pgrep -f "sui start"';
14
+
15
+ const result = execSync(cmd).toString().trim();
16
+ return process.platform === 'win32'
17
+ ? result.toLowerCase().includes('sui.exe')
18
+ : result.length > 0;
19
+ } catch (error) {
20
+ return false;
21
+ }
22
+ }
23
+
24
+ async function printAccounts() {
25
+ // These private keys are used for testing purposes only, do not use them in production.
26
+ const privateKeys = [
27
+ "suiprivkey1qq3ez3dje66l8pypgxynr7yymwps6uhn7vyczespj84974j3zya0wdpu76v",
28
+ "suiprivkey1qp6vcyg8r2x88fllmjmxtpzjl95gd9dugqrgz7xxf50w6rqdqzetg7x4d7s",
29
+ "suiprivkey1qpy3a696eh3m55fwa8h38ss063459u4n2dm9t24w2hlxxzjp2x34q8sdsnc",
30
+ "suiprivkey1qzxwp29favhzrjd95f6uj9nskjwal6nh9g509jpun395y6g72d6jqlmps4c",
31
+ "suiprivkey1qzhq4lv38sesah4uzsqkkmeyjx860xqjdz8qgw36tmrdd5tnle3evxpng57",
32
+ "suiprivkey1qzez45sjjsepjgtksqvpq6jw7dzw3zq0dx7a4sulfypd73acaynw5jl9x2c",
33
+ ]
34
+ console.log("šŸ“Accounts")
35
+ console.log("==========")
36
+ privateKeys.forEach((privateKey, index) => {
37
+ const dubhe = new Dubhe({ secretKey: privateKey });
38
+ const keypair = dubhe.getKeypair();
39
+ spawn(
40
+ 'curl',
41
+ ['--location', '--request', 'POST', 'http://127.0.0.1:9123/gas', '--header', 'Content-Type: application/json', '--data-raw', `{"FixedAmountRequest": {"recipient": "${keypair.toSuiAddress()}"}}`],
42
+ {
43
+ env: { ...process.env },
44
+ stdio: 'ignore',
45
+ detached: true,
46
+ }
47
+ )
48
+ console.log(` ā”Œā”€ Account #${index}: ${keypair.toSuiAddress()}(1000 SUI)`);
49
+ console.log(` └─ Private Key: ${privateKey}`);
50
+ });
51
+ console.log("==========")
52
+ console.log(chalk.yellow("āš ļøWARNING: These accounts, and their private keys, are publicly known."));
53
+ console.log(chalk.yellow("Any funds sent to them on Mainnet or any other live network WILL BE LOST."));
54
+ }
55
+ export async function startLocalNode() {
56
+ if (isSuiStartRunning()) {
57
+ console.log(chalk.yellow('\nāš ļø Warning: Local Node Already Running'));
58
+ console.log(chalk.yellow(' ā”œā”€ Cannot start a new instance'));
59
+ console.log(
60
+ chalk.yellow(' └─ Please stop the existing process first')
61
+ );
62
+ return;
63
+ }
64
+
65
+ printDubhe();
66
+ console.log('šŸš€ Starting Local Node...');
67
+ try {
68
+ const suiProcess = spawn(
69
+ 'sui',
70
+ ['start', '--with-faucet', '--force-regenesis'],
71
+ {
72
+ env: { ...process.env, RUST_LOG: 'off,sui_node=info' },
73
+ stdio: 'ignore',
74
+ detached: true,
75
+ }
76
+ );
77
+
78
+ suiProcess.on('error', error => {
79
+ console.error(chalk.red('\nāŒ Failed to Start Local Node'));
80
+ console.error(chalk.red(` └─ Error: ${error.message}`));
81
+ });
82
+ await delay(5000);
83
+ console.log(' ā”œā”€ Faucet: Enabled');
84
+ console.log(' └─ Force Regenesis: Yes');
85
+ console.log(' └─ HTTP server: http://127.0.0.1:9000/');
86
+ console.log(' └─ Faucet server: http://127.0.0.1:9123/');
87
+
88
+ await printAccounts();
89
+
90
+ await delay(2000);
91
+
92
+ const privateKeyFormat = validatePrivateKey("suiprivkey1qzez45sjjsepjgtksqvpq6jw7dzw3zq0dx7a4sulfypd73acaynw5jl9x2c");
93
+ if (privateKeyFormat === false) {
94
+ throw new DubheCliError(`Please check your privateKey.`);
95
+ }
96
+
97
+ const dubhe = new Dubhe({ secretKey: privateKeyFormat });
98
+ const client = new SuiClient({ url: getFullnodeUrl('localnet') });
99
+ const originalLog = console.log;
100
+
101
+ console.log = () => {};
102
+ await publishDubheFramework(client, dubhe, 'localnet');
103
+ console.log = originalLog;
104
+
105
+ process.on('SIGINT', () => {
106
+ console.log(chalk.yellow('\nšŸ”” Stopping Local Node...'));
107
+ if (suiProcess) {
108
+ suiProcess.kill();
109
+ console.log(chalk.green('āœ… Local Node Stopped'));
110
+ }
111
+ process.exit();
112
+ });
113
+ } catch (error: any) {
114
+ console.error(chalk.red('\nāŒ Failed to Start Local Node'));
115
+ console.error(chalk.red(` └─ Error: ${error.message}`));
116
+ }
117
+ }
@@ -3,7 +3,6 @@ import { mkdirSync, writeFileSync } from 'fs';
3
3
  import { dirname } from 'path';
4
4
  import { SUI_PRIVATE_KEY_PREFIX } from '@mysten/sui/cryptography';
5
5
  import { FsIibError } from './errors';
6
- export * from './localnode';
7
6
  import * as fs from 'fs';
8
7
  import chalk from 'chalk';
9
8
  import { spawn } from 'child_process';
@@ -231,7 +230,6 @@ export async function switchEnv(network: 'mainnet' | 'testnet' | 'devnet' | 'loc
231
230
  console.error(chalk.red(`\nāŒ Process exited with code: ${code}`));
232
231
  reject(new Error(`Process exited with code: ${code}`));
233
232
  } else {
234
- console.log(chalk.green('\nāœ… Environment switched successfully.'));
235
233
  resolve(); // Resolve promise on successful exit
236
234
  }
237
235
  });
@@ -1,3 +0,0 @@
1
- export { startLocalnode } from './start';
2
- export { checkLocalNodeStatus } from './status';
3
- export { stopLocalnode } from './stop';
@@ -1,87 +0,0 @@
1
- import { execSync, spawn } from 'child_process';
2
- import chalk from 'chalk';
3
-
4
- function isSuiStartRunning(): boolean {
5
- try {
6
- const cmd =
7
- process.platform === 'win32'
8
- ? `tasklist /FI "IMAGENAME eq sui.exe" /FO CSV /NH`
9
- : 'pgrep -f "sui start"';
10
-
11
- const result = execSync(cmd).toString().trim();
12
- return process.platform === 'win32'
13
- ? result.toLowerCase().includes('sui.exe')
14
- : result.length > 0;
15
- } catch (error) {
16
- return false;
17
- }
18
- }
19
-
20
- export async function startLocalnode(background: boolean = false) {
21
- console.log('\nšŸ” Checking Local Node Status...');
22
- console.log(' ā”œā”€ Scanning running processes');
23
-
24
- if (isSuiStartRunning()) {
25
- console.log(chalk.yellow('\nāš ļø Warning: Local Node Already Running'));
26
- console.log(chalk.yellow(' ā”œā”€ Cannot start a new instance'));
27
- console.log(
28
- chalk.yellow(' └─ Please stop the existing process first')
29
- );
30
- return;
31
- }
32
-
33
- console.log('\nšŸš€ Starting Local Node...');
34
- console.log(' ā”œā”€ Mode: ' + (background ? 'Background' : 'Foreground'));
35
- console.log(' ā”œā”€ Faucet: Enabled');
36
- console.log(' └─ Force Regenesis: Yes');
37
-
38
- try {
39
- const suiProcess = spawn(
40
- 'sui',
41
- ['start', '--with-faucet', '--force-regenesis'],
42
- {
43
- env: { ...process.env, RUST_LOG: 'off,sui_node=info' },
44
- stdio: background ? 'ignore' : 'inherit',
45
- detached: background,
46
- }
47
- );
48
-
49
- suiProcess.on('error', error => {
50
- console.error(chalk.red('\nāŒ Failed to Start Local Node'));
51
- console.error(chalk.red(` └─ Error: ${error.message}`));
52
- });
53
-
54
- if (!background) {
55
- suiProcess.on('exit', code => {
56
- if (code === 0) {
57
- console.log(chalk.green('\nāœ… Local Node Stopped'));
58
- console.log(chalk.green(' └─ Exit Status: Normal'));
59
- } else {
60
- console.error(chalk.red('\nāŒ Local Node Crashed'));
61
- console.error(chalk.red(` └─ Exit Code: ${code}`));
62
- }
63
- });
64
-
65
- console.log(chalk.cyan('\nšŸ“” Local Node Running'));
66
- console.log(chalk.cyan(' └─ Press Ctrl+C to stop'));
67
-
68
- await new Promise(() => {});
69
- } else {
70
- suiProcess.unref();
71
- console.log(chalk.green('\nāœ… Local Node Started in Background'));
72
-
73
- if (process.platform === 'win32') {
74
- console.log('\nšŸ’” Helpful Commands:');
75
- console.log(' ā”œā”€ Check Process: tasklist | findstr sui.exe');
76
- console.log(' └─ Stop Node: taskkill /PID <process_id> /F');
77
- } else {
78
- console.log('\nšŸ’” Helpful Commands:');
79
- console.log(" ā”œā”€ Check Process: pgrep -f 'sui start'");
80
- console.log(' └─ Stop Node: kill <process_id>');
81
- }
82
- }
83
- } catch (error: any) {
84
- console.error(chalk.red('\nāŒ Failed to Start Local Node'));
85
- console.error(chalk.red(` └─ Error: ${error.message}`));
86
- }
87
- }
@@ -1,38 +0,0 @@
1
- import { execSync } from 'child_process';
2
- import chalk from 'chalk';
3
-
4
- export async function checkLocalNodeStatus() {
5
- console.log('\nšŸ” Checking Local Node Status...');
6
-
7
- try {
8
- const cmd =
9
- process.platform === 'win32'
10
- ? `tasklist /FI "IMAGENAME eq sui.exe" /FO CSV /NH`
11
- : "ps aux | grep '[s]ui start --with-faucet --force-regenesis'";
12
-
13
- const output = execSync(cmd, {
14
- encoding: 'utf8',
15
- });
16
-
17
- const isRunning =
18
- process.platform === 'win32'
19
- ? output.toLowerCase().includes('sui.exe')
20
- : output.split('\n').filter(Boolean).length > 0;
21
-
22
- if (isRunning) {
23
- console.log(chalk.green('\nāœ… Node Status: Running'));
24
- console.log(chalk.gray('\nšŸ“Š Process Details:'));
25
- console.log(chalk.gray(` └─ ${output.trim()}`));
26
- } else {
27
- console.log(chalk.red('\nāŒ Node Status: Not Running'));
28
- console.log(chalk.yellow('\nšŸ’” Quick Start:'));
29
- console.log(chalk.yellow(' └─ Run `dubhe localnode start`'));
30
- }
31
- } catch (error) {
32
- console.log(chalk.red('\nāŒ Node Status: Not Running'));
33
- console.log(chalk.yellow('\nšŸ’” Quick Start:'));
34
- console.log(chalk.yellow(' └─ Run `dubhe localnode start`'));
35
- }
36
- }
37
-
38
- // checkLocalNodeStatus();
@@ -1,58 +0,0 @@
1
- import { execSync } from 'child_process';
2
-
3
- export async function stopLocalnode() {
4
- console.log('Stopping local node...');
5
-
6
- try {
7
- // Choose different commands based on the operating system
8
- const cmd =
9
- process.platform === 'win32'
10
- ? `tasklist /FI "IMAGENAME eq sui.exe" /FO CSV /NH`
11
- : "ps aux | grep '[s]ui start --with-faucet --force-regenesis'";
12
-
13
- const output = execSync(cmd, {
14
- encoding: 'utf8',
15
- });
16
-
17
- if (!output) {
18
- console.log('No running local node process found');
19
- return;
20
- }
21
-
22
- // Parse process ID based on the operating system
23
- let pid;
24
- if (process.platform === 'win32') {
25
- // Windows output format: "sui.exe","1234",... (CSV format)
26
- const match = output.match(/"sui\.exe",["']?(\d+)/i);
27
- pid = match ? match[1] : null;
28
- } else {
29
- // Unix system output format: user pid %cpu ...
30
- pid = output.toString().split(/\s+/)[1];
31
- }
32
-
33
- if (!pid) {
34
- console.log('No running local node process found');
35
- return;
36
- }
37
-
38
- // Choose the command to terminate the process based on the operating system
39
- if (process.platform === 'win32') {
40
- execSync(`taskkill /PID ${pid} /F`);
41
- } else {
42
- process.kill(Number(pid));
43
- }
44
-
45
- console.log('āœ… Local node stopped successfully');
46
- } catch (error: any) {
47
- if (
48
- error.code === 'ESRCH' ||
49
- error.message.includes('no running tasks')
50
- ) {
51
- console.log('No running local node process found');
52
- } else {
53
- console.error('āŒ Error stopping local node:', error.message);
54
- }
55
- }
56
- }
57
-
58
- // stopLocalnode();