@0xobelisk/sui-cli 0.5.17 → 0.5.19

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.
@@ -1,36 +1,47 @@
1
- import type { CommandModule } from "yargs";
2
- import { worldgen, loadConfig, ObeliskConfig } from "@0xobelisk/sui-common";
3
- import chalk from "chalk";
1
+ import type { CommandModule } from 'yargs';
2
+ import { schemaGen, loadConfig, ObeliskConfig } from '@0xobelisk/sui-common';
3
+ import chalk from 'chalk';
4
4
 
5
5
  type Options = {
6
- configPath?: string;
6
+ configPath?: string;
7
+ network?: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
8
+ frameworkId?: string;
7
9
  };
8
10
 
9
11
  const commandModule: CommandModule<Options, Options> = {
10
- command: "schemagen",
12
+ command: 'schemagen',
11
13
 
12
- describe: "Autogenerate Obelisk schemas based on the config file",
14
+ describe: 'Autogenerate Obelisk schemas based on the config file',
13
15
 
14
- builder(yargs) {
15
- return yargs.options({
16
- configPath: {
17
- type: "string",
18
- default: "obelisk.config.ts",
19
- desc: "Path to the config file"
20
- },
21
- });
22
- },
16
+ builder: {
17
+ configPath: {
18
+ type: 'string',
19
+ default: 'obelisk.config.ts',
20
+ desc: 'Path to the config file',
21
+ },
22
+ network: {
23
+ type: 'string',
24
+ choices: ['mainnet', 'testnet', 'devnet', 'localnet'] as const,
25
+ desc: 'Node network (mainnet/testnet/devnet/localnet)',
26
+ },
27
+ frameworkId: {
28
+ type: 'string',
29
+ desc: 'Framework Package ID',
30
+ },
31
+ },
23
32
 
24
- async handler({ configPath }) {
25
- try {
26
- const obeliskConfig = (await loadConfig(configPath)) as ObeliskConfig;
27
- await worldgen(obeliskConfig);
28
- process.exit(0);
29
- } catch (error: any) {
30
- console.log(chalk.red("Schemagen failed!"));
31
- console.error(error.message);
32
- }
33
- },
33
+ async handler({ configPath, network, frameworkId }) {
34
+ try {
35
+ const obeliskConfig = (await loadConfig(
36
+ configPath
37
+ )) as ObeliskConfig;
38
+ await schemaGen(obeliskConfig, undefined, network, frameworkId);
39
+ process.exit(0);
40
+ } catch (error: any) {
41
+ console.log(chalk.red('Schemagen failed!'));
42
+ console.error(error.message);
43
+ }
44
+ },
34
45
  };
35
46
 
36
47
  export default commandModule;
@@ -1,53 +1,53 @@
1
- import type { CommandModule } from "yargs";
2
- import { logError } from "../utils/errors";
3
- import { upgradeHandler } from "../utils";
4
- import { ObeliskConfig, loadConfig, ValueType } from "@0xobelisk/sui-common";
5
-
6
- type Options = {
7
- network: any;
8
- configPath: string;
9
- };
10
-
11
- const commandModule: CommandModule<Options, Options> = {
12
- command: "upgrade",
13
-
14
- describe: "Upgrade your move contracts",
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: "obelisk.config.ts",
26
- decs: "Path to the config file",
27
- },
28
- });
29
- },
30
-
31
- async handler({ network, configPath }) {
32
- try {
33
- const obeliskConfig = (await loadConfig(configPath)) as ObeliskConfig;
34
-
35
- let schemaNames = Object.keys(obeliskConfig.schemas).filter(
36
- (key) =>
37
- !(
38
- typeof obeliskConfig.schemas === "object" &&
39
- "ephemeral" in obeliskConfig.schemas &&
40
- (obeliskConfig.schemas[key] as ValueType).ephemeral
41
- )
42
- );
43
-
44
- await upgradeHandler(obeliskConfig.name, network, schemaNames);
45
- } catch (error: any) {
46
- logError(error);
47
- process.exit(1);
48
- }
49
- process.exit(0);
50
- },
51
- };
52
-
53
- export default commandModule;
1
+ // import type { CommandModule } from "yargs";
2
+ // import { logError } from "../utils/errors";
3
+ // import { upgradeHandler } from "../utils";
4
+ // import { ObeliskConfig, loadConfig, ValueType } from "@0xobelisk/sui-common";
5
+
6
+ // type Options = {
7
+ // network: any;
8
+ // configPath: string;
9
+ // };
10
+
11
+ // const commandModule: CommandModule<Options, Options> = {
12
+ // command: "upgrade",
13
+
14
+ // describe: "Upgrade your move contracts",
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: "obelisk.config.ts",
26
+ // decs: "Path to the config file",
27
+ // },
28
+ // });
29
+ // },
30
+
31
+ // async handler({ network, configPath }) {
32
+ // try {
33
+ // const obeliskConfig = (await loadConfig(configPath)) as ObeliskConfig;
34
+
35
+ // let schemaNames = Object.keys(obeliskConfig.schemas).filter(
36
+ // (key) =>
37
+ // !(
38
+ // typeof obeliskConfig.schemas === "object" &&
39
+ // "ephemeral" in obeliskConfig.schemas &&
40
+ // (obeliskConfig.schemas[key] as ValueType).ephemeral
41
+ // )
42
+ // );
43
+
44
+ // await upgradeHandler(obeliskConfig.name, network, schemaNames);
45
+ // } catch (error: any) {
46
+ // logError(error);
47
+ // process.exit(1);
48
+ // }
49
+ // process.exit(0);
50
+ // },
51
+ // };
52
+
53
+ // export default commandModule;
@@ -1,5 +1,5 @@
1
- export * from "./publishHandler";
2
- export * from "./upgradeHandler";
3
- export * from "./errors";
4
- export * from "./printObelisk";
5
- export * from "./utils";
1
+ export * from './publishHandler';
2
+ // export * from "./upgradeHandler";
3
+ export * from './errors';
4
+ export * from './printObelisk';
5
+ export * from './utils';
@@ -0,0 +1,3 @@
1
+ export { startLocalnode } from './start';
2
+ export { checkLocalNodeStatus } from './status';
3
+ export { stopLocalnode } from './stop';
@@ -0,0 +1,87 @@
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
+ }
@@ -0,0 +1,38 @@
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 `obelisk 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 `obelisk localnode start`'));
35
+ }
36
+ }
37
+
38
+ // checkLocalNodeStatus();
@@ -0,0 +1,58 @@
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();
@@ -11,44 +11,59 @@ import { ObeliskCliError } from './errors';
11
11
  import {
12
12
  updateVersionInFile,
13
13
  saveContractData,
14
- validatePrivateKey, schema,
14
+ validatePrivateKey,
15
+ schema,
15
16
  } from './utils';
16
- import {log} from "node:util";
17
+
18
+ async function getDappsObjectId(
19
+ network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
20
+ ) {
21
+ switch (network) {
22
+ case 'testnet':
23
+ return '0xa66942c08d9fc318a70ab9d0cfd7e75f1a2dd1ac31aff12fde008d25bfa9604b';
24
+ default:
25
+ return '0xa66942c08d9fc318a70ab9d0cfd7e75f1a2dd1ac31aff12fde008d25bfa9604b';
26
+ }
27
+ }
17
28
 
18
29
  export async function publishHandler(
19
30
  name: string,
20
- network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
31
+ network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
32
+ dappsObjectId?: string
21
33
  ) {
34
+ console.log('\n🚀 Starting Contract Publication...');
35
+ console.log(` ├─ Project: ${name}`);
36
+ console.log(` ├─ Network: ${network}`);
37
+
22
38
  const path = process.cwd();
23
39
  const projectPath = `${path}/contracts/${name}`;
40
+ dappsObjectId = dappsObjectId || (await getDappsObjectId(network));
24
41
 
42
+ console.log(' ├─ Validating Environment...');
25
43
  const privateKey = process.env.PRIVATE_KEY;
26
- if (!privateKey)
44
+ if (!privateKey) {
27
45
  throw new ObeliskCliError(
28
46
  `Missing PRIVATE_KEY environment variable.
29
47
  Run 'echo "PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
30
48
  in your contracts directory to use the default sui private key.`
31
49
  );
50
+ }
32
51
 
33
52
  const privateKeyFormat = validatePrivateKey(privateKey);
34
53
  if (privateKeyFormat === false) {
35
54
  throw new ObeliskCliError(`Please check your privateKey.`);
36
55
  }
37
- const obelisk = new Obelisk({
38
- secretKey: privateKeyFormat,
39
- });
56
+
57
+ const obelisk = new Obelisk({ secretKey: privateKeyFormat });
40
58
  const keypair = obelisk.getKeypair();
59
+ console.log(` └─ Account: ${keypair.toSuiAddress()}`);
41
60
 
42
- const client = new SuiClient({
43
- url: getFullnodeUrl(network),
44
- });
61
+ const client = new SuiClient({ url: getFullnodeUrl(network) });
45
62
 
63
+ console.log('\n📦 Building Contract...');
46
64
  let modules: any, dependencies: any;
47
65
  try {
48
- const {
49
- modules: extractedModules,
50
- dependencies: extractedDependencies,
51
- } = JSON.parse(
66
+ const buildResult = JSON.parse(
52
67
  execSync(
53
68
  `sui move build --dump-bytecode-as-base64 --path ${projectPath}`,
54
69
  {
@@ -56,78 +71,69 @@ in your contracts directory to use the default sui private key.`
56
71
  }
57
72
  )
58
73
  );
59
- modules = extractedModules;
60
- dependencies = extractedDependencies;
74
+ modules = buildResult.modules;
75
+ dependencies = buildResult.dependencies;
76
+ console.log(' └─ Build successful');
61
77
  } catch (error: any) {
62
- console.error(chalk.red('Error executing sui move build:'));
78
+ console.error(chalk.red(' └─ Build failed'));
63
79
  console.error(error.stdout);
64
- process.exit(1); // You might want to exit with a non-zero status code to indicate an error
80
+ process.exit(1);
65
81
  }
66
82
 
67
- console.log(chalk.blue(`Account: ${keypair.toSuiAddress()}`));
68
-
83
+ console.log('\n🔄 Publishing Contract...');
69
84
  const tx = new Transaction();
70
- const [upgradeCap] = tx.publish({
71
- modules,
72
- dependencies,
73
- });
74
- tx.transferObjects(
75
- [upgradeCap],
76
- keypair.toSuiAddress()
77
- );
85
+ const [upgradeCap] = tx.publish({ modules, dependencies });
86
+ tx.transferObjects([upgradeCap], keypair.toSuiAddress());
78
87
 
79
88
  let result: SuiTransactionBlockResponse;
80
89
  try {
81
90
  result = await client.signAndExecuteTransaction({
82
91
  signer: keypair,
83
92
  transaction: tx,
84
- options: {
85
- showObjectChanges: true,
86
- },
93
+ options: { showObjectChanges: true },
87
94
  });
88
95
  } catch (error: any) {
89
- console.error(chalk.red(`Failed to execute publish, please republish`));
96
+ console.error(chalk.red(' └─ Publication failed'));
90
97
  console.error(error.message);
91
98
  process.exit(1);
92
99
  }
93
100
 
94
101
  if (result.effects?.status.status === 'failure') {
95
- console.log(chalk.red(`Failed to execute publish, please republish`));
102
+ console.log(chalk.red(' └─ Publication failed'));
96
103
  process.exit(1);
97
104
  }
98
105
 
106
+ console.log(' ├─ Processing publication results...');
99
107
  let version = 1;
100
108
  let packageId = '';
101
109
  let schemas: schema[] = [];
102
110
  let upgradeCapId = '';
111
+
103
112
  result.objectChanges!.map(object => {
104
113
  if (object.type === 'published') {
105
- console.log(chalk.blue(`${name} PackageId: ${object.packageId}`));
114
+ console.log(` ├─ Package ID: ${object.packageId}`);
106
115
  packageId = object.packageId;
107
116
  }
108
117
  if (
109
118
  object.type === 'created' &&
110
119
  object.objectType === '0x2::package::UpgradeCap'
111
120
  ) {
112
- console.log(chalk.blue(`${name} UpgradeCap: ${object.objectId}`));
121
+ console.log(` ├─ Upgrade Cap: ${object.objectId}`);
113
122
  upgradeCapId = object.objectId;
114
123
  }
115
124
  });
116
125
 
117
- console.log(chalk.green(`Publish transaction digest: ${result.digest}`));
126
+ console.log(` └─ Transaction: ${result.digest}`);
118
127
 
119
- console.log('Executing the deployHook: ');
120
- const delay = (ms: number) =>
121
- new Promise(resolve => setTimeout(resolve, ms));
122
- await delay(5000);
128
+ console.log('\n⚡ Executing Deploy Hook...');
129
+ await new Promise(resolve => setTimeout(resolve, 5000));
123
130
 
124
131
  const deployHookTx = new Transaction();
125
-
126
132
  deployHookTx.moveCall({
127
133
  target: `${packageId}::deploy_hook::run`,
128
134
  arguments: [
129
- deployHookTx.object("0xa66942c08d9fc318a70ab9d0cfd7e75f1a2dd1ac31aff12fde008d25bfa9604b"),
130
- deployHookTx.object("0x6"),
135
+ deployHookTx.object(dappsObjectId),
136
+ deployHookTx.object('0x6'),
131
137
  ],
132
138
  });
133
139
 
@@ -136,39 +142,33 @@ in your contracts directory to use the default sui private key.`
136
142
  deployHookResult = await client.signAndExecuteTransaction({
137
143
  signer: keypair,
138
144
  transaction: deployHookTx,
139
- options: {
140
- showEffects: true,
141
- showObjectChanges: true
142
- },
145
+ options: { showEffects: true, showObjectChanges: true },
143
146
  });
144
147
  } catch (error: any) {
145
- console.error(
146
- chalk.red(
147
- `Failed to execute deployHook, please republish or manually call deploy_hook::run`
148
- )
149
- );
148
+ console.error(chalk.red(' └─ Deploy hook execution failed'));
150
149
  console.error(error.message);
151
150
  process.exit(1);
152
151
  }
153
152
 
154
153
  if (deployHookResult.effects?.status.status === 'success') {
155
- console.log(
156
- chalk.green(
157
- `Successful auto-execution of deployHook, please check the transaction digest: ${deployHookResult.digest}`
158
- )
159
- );
154
+ console.log(' ├─ Hook execution successful');
155
+ console.log(` ├─ Transaction: ${deployHookResult.digest}`);
156
+
157
+ console.log('\n📋 Created Schemas:');
160
158
  deployHookResult.objectChanges?.map(object => {
161
159
  if (
162
- object.type === 'created' && object.objectType.includes("schema")
160
+ object.type === 'created' &&
161
+ object.objectType.includes('schema')
163
162
  ) {
164
- console.log(chalk.blue(`${name} Schema Object id: ${object.objectId}`));
165
- console.log(chalk.blue(`${name} Schema Object type: ${object.objectType}`));
163
+ console.log(` ├─ ${object.objectType}`);
164
+ console.log(` └─ ID: ${object.objectId}`);
166
165
  schemas.push({
167
166
  name: object.objectType,
168
167
  objectId: object.objectId,
169
168
  });
170
169
  }
171
170
  });
171
+
172
172
  saveContractData(
173
173
  name,
174
174
  network,
@@ -177,10 +177,12 @@ in your contracts directory to use the default sui private key.`
177
177
  upgradeCapId,
178
178
  version
179
179
  );
180
+ console.log('\n✅ Contract Publication Complete\n');
180
181
  } else {
182
+ console.log(chalk.yellow(' └─ Deploy hook execution failed'));
181
183
  console.log(
182
184
  chalk.yellow(
183
- `Failed to execute deployHook, please republish or manually call deploy_hook::run`
185
+ ' Please republish or manually call deploy_hook::run'
184
186
  )
185
187
  );
186
188
  }