@0xobelisk/sui-cli 1.2.0-pre.12 → 1.2.0-pre.120

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +7 -7
  2. package/dist/dubhe.js +152 -51
  3. package/dist/dubhe.js.map +1 -1
  4. package/package.json +31 -19
  5. package/src/commands/build.ts +61 -18
  6. package/src/commands/call.ts +83 -83
  7. package/src/commands/checkBalance.ts +27 -12
  8. package/src/commands/convertJson.ts +84 -0
  9. package/src/commands/doctor.ts +1515 -0
  10. package/src/commands/faucet.ts +20 -10
  11. package/src/commands/generate.ts +61 -0
  12. package/src/commands/generateKey.ts +3 -2
  13. package/src/commands/index.ts +20 -11
  14. package/src/commands/info.ts +61 -0
  15. package/src/commands/loadMetadata.ts +68 -0
  16. package/src/commands/localnode.ts +22 -6
  17. package/src/commands/publish.ts +55 -7
  18. package/src/commands/query.ts +101 -101
  19. package/src/commands/shell.ts +208 -0
  20. package/src/commands/{configStore.ts → storeConfig.ts} +13 -5
  21. package/src/commands/switchEnv.ts +33 -0
  22. package/src/commands/test.ts +143 -31
  23. package/src/commands/upgrade.ts +46 -6
  24. package/src/commands/wait.ts +333 -22
  25. package/src/commands/watch.ts +9 -8
  26. package/src/dubhe.ts +12 -4
  27. package/src/utils/axios-downloader.ts +116 -0
  28. package/src/utils/callHandler.ts +118 -118
  29. package/src/utils/checkBalance.ts +6 -2
  30. package/src/utils/constants.ts +9 -0
  31. package/src/utils/generateAccount.ts +1 -1
  32. package/src/utils/index.ts +4 -3
  33. package/src/utils/metadataHandler.ts +17 -0
  34. package/src/utils/publishHandler.ts +404 -289
  35. package/src/utils/queryStorage.ts +141 -141
  36. package/src/utils/startNode.ts +115 -16
  37. package/src/utils/storeConfig.ts +50 -10
  38. package/src/utils/upgradeHandler.ts +210 -86
  39. package/src/utils/utils.ts +1025 -63
  40. package/src/commands/schemagen.ts +0 -40
@@ -1,11 +1,13 @@
1
1
  import type { CommandModule } from 'yargs';
2
- import { requestSuiFromFaucetV0, getFaucetHost } from '@mysten/sui/faucet';
2
+ import { requestSuiFromFaucetV2, getFaucetHost } from '@mysten/sui/faucet';
3
3
  import { SuiClient, getFullnodeUrl, GetBalanceParams } from '@mysten/sui/client';
4
4
  import { initializeDubhe } from '../utils';
5
+ import { handlerExit } from './shell';
5
6
 
6
7
  type Options = {
7
8
  network: any;
8
9
  recipient?: string;
10
+ 'rpc-url'?: string;
9
11
  };
10
12
 
11
13
  const MAX_RETRIES = 60; // 60s timeout
@@ -27,15 +29,20 @@ const commandModule: CommandModule<Options, Options> = {
27
29
  },
28
30
  recipient: {
29
31
  type: 'string',
32
+ alias: 'r',
30
33
  desc: 'Sui address to fund'
34
+ },
35
+ 'rpc-url': {
36
+ type: 'string',
37
+ desc: 'Custom RPC endpoint URL for balance check (overrides the default for the selected network)'
31
38
  }
32
39
  });
33
40
  },
34
41
 
35
- async handler({ network, recipient }) {
42
+ async handler({ network, recipient, 'rpc-url': rpcUrl }) {
36
43
  let faucet_address = '';
37
44
  if (recipient === undefined) {
38
- const dubhe = initializeDubhe(network);
45
+ const dubhe = initializeDubhe({ network });
39
46
  faucet_address = dubhe.getAddress();
40
47
  } else {
41
48
  faucet_address = recipient;
@@ -63,26 +70,29 @@ const commandModule: CommandModule<Options, Options> = {
63
70
  isInterrupted = true;
64
71
  process.stdout.write('\r' + ' '.repeat(50) + '\r');
65
72
  console.log('\n └─ Operation cancelled by user');
66
- process.exit(0);
73
+ handlerExit(1);
67
74
  };
68
75
  process.on('SIGINT', handleInterrupt);
69
76
 
70
77
  try {
71
78
  while (retryCount < MAX_RETRIES && !success && !isInterrupted) {
72
79
  try {
73
- await requestSuiFromFaucetV0({
80
+ await requestSuiFromFaucetV2({
74
81
  host: getFaucetHost(network),
75
82
  recipient: faucet_address
76
83
  });
77
84
  success = true;
78
- } catch (error) {
85
+ } catch (_error) {
79
86
  if (isInterrupted) break;
80
87
 
81
88
  retryCount++;
82
89
  if (retryCount === MAX_RETRIES) {
83
90
  console.log(` └─ Failed to request funds after ${MAX_RETRIES} attempts.`);
84
91
  console.log(' └─ Please check your network connection and try again later.');
85
- process.exit(1);
92
+ console.log(
93
+ ' └─ You can visit https://faucet.testnet.sui.io/ to request funds manually.'
94
+ );
95
+ handlerExit(1);
86
96
  }
87
97
 
88
98
  const elapsedTime = Math.floor((Date.now() - startTime) / 1000);
@@ -98,12 +108,12 @@ const commandModule: CommandModule<Options, Options> = {
98
108
  }
99
109
 
100
110
  if (isInterrupted) {
101
- process.exit(0);
111
+ handlerExit(1);
102
112
  }
103
113
  process.stdout.write('\r' + ' '.repeat(50) + '\r');
104
114
 
105
115
  console.log(' └─ Checking balance...');
106
- const client = new SuiClient({ url: getFullnodeUrl(network) });
116
+ const client = new SuiClient({ url: rpcUrl || getFullnodeUrl(network) });
107
117
  let params = {
108
118
  owner: faucet_address
109
119
  } as GetBalanceParams;
@@ -115,7 +125,7 @@ const commandModule: CommandModule<Options, Options> = {
115
125
  console.log(` └─ Balance: ${(Number(balance.totalBalance) / 1_000_000_000).toFixed(4)} SUI`);
116
126
 
117
127
  console.log('\n✅ Faucet Operation Complete\n');
118
- process.exit(0);
128
+ handlerExit();
119
129
  }
120
130
  };
121
131
 
@@ -0,0 +1,61 @@
1
+ import type { CommandModule } from 'yargs';
2
+ import { codegen, loadConfig, DubheConfig } from '@0xobelisk/sui-common';
3
+ import chalk from 'chalk';
4
+ import path from 'node:path';
5
+ import { handlerExit } from './shell';
6
+ import { getDefaultNetwork } from '../utils';
7
+
8
+ type Options = {
9
+ 'config-path'?: string;
10
+ network?: 'mainnet' | 'testnet' | 'devnet' | 'localnet' | 'default';
11
+ mode?: 'user_pays' | 'dapp_subsidizes';
12
+ };
13
+
14
+ const commandModule: CommandModule<Options, Options> = {
15
+ command: 'generate',
16
+ // 'schemagen' kept as a deprecated alias for backward compatibility
17
+ aliases: ['schemagen'],
18
+
19
+ describe: 'Generate Move code from dubhe.config.ts',
20
+
21
+ builder: {
22
+ 'config-path': {
23
+ type: 'string',
24
+ default: 'dubhe.config.ts',
25
+ desc: 'Path to the config file'
26
+ },
27
+ network: {
28
+ type: 'string',
29
+ choices: ['mainnet', 'testnet', 'devnet', 'localnet', 'default'] as const,
30
+ default: 'default',
31
+ desc: 'Node network (mainnet/testnet/devnet/localnet)'
32
+ },
33
+ mode: {
34
+ type: 'string',
35
+ choices: ['user_pays', 'dapp_subsidizes'] as const,
36
+ default: 'user_pays',
37
+ desc: 'Initial settlement mode for this DApp (only applies on first generate)'
38
+ }
39
+ },
40
+
41
+ async handler({ 'config-path': configPath, network, mode }) {
42
+ try {
43
+ if (!configPath) throw new Error('Config path is required');
44
+ if (network == 'default') {
45
+ network = await getDefaultNetwork();
46
+ console.log(chalk.yellow(`Use default network: [${network}]`));
47
+ }
48
+ const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
49
+ const rootDir = path.dirname(configPath);
50
+ const initialMode: 0 | 1 = mode === 'dapp_subsidizes' ? 0 : 1;
51
+ await codegen(rootDir, dubheConfig, network, initialMode);
52
+ handlerExit();
53
+ } catch (error: any) {
54
+ console.log(chalk.red('Generate failed!'));
55
+ console.error(error.message);
56
+ handlerExit(1);
57
+ }
58
+ }
59
+ };
60
+
61
+ export default commandModule;
@@ -1,5 +1,6 @@
1
1
  import type { CommandModule } from 'yargs';
2
2
  import { generateAccountHandler } from '../utils/generateAccount';
3
+ import { handlerExit } from './shell';
3
4
 
4
5
  type Options = {
5
6
  force?: boolean;
@@ -26,9 +27,9 @@ const commandModule: CommandModule<Options, Options> = {
26
27
  await generateAccountHandler(force, useNextPublic);
27
28
  } catch (error) {
28
29
  console.error('Error generating account:', error);
29
- process.exit(1);
30
+ handlerExit(1);
30
31
  }
31
- process.exit(0);
32
+ handlerExit();
32
33
  }
33
34
  };
34
35
 
@@ -2,35 +2,44 @@ import { CommandModule } from 'yargs';
2
2
 
3
3
  import localnode from './localnode';
4
4
  import faucet from './faucet';
5
- import schemagen from './schemagen';
5
+ import generate from './generate';
6
6
  import publish from './publish';
7
- import upgrade from './upgrade';
8
7
  import test from './test';
9
8
  import build from './build';
10
9
  import hello from './hello';
11
10
  import generateKey from './generateKey';
12
11
  import checkBalance from './checkBalance';
13
- import configStore from './configStore';
14
- import query from './query';
15
- import call from './call';
12
+ import storeConfig from './storeConfig';
16
13
  import watch from './watch';
17
14
  import wait from './wait';
15
+ import switchEnv from './switchEnv';
16
+ import info from './info';
17
+ import loadMetadata from './loadMetadata';
18
+ import doctor from './doctor';
19
+ import convertJson from './convertJson';
20
+ import upgrade from './upgrade';
21
+ import shell from './shell';
18
22
 
19
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
20
23
  export const commands: CommandModule<any, any>[] = [
21
24
  localnode,
22
25
  publish,
23
- call,
24
- query,
26
+ // call,
27
+ // query,
25
28
  faucet,
26
- schemagen,
29
+ generate,
27
30
  upgrade,
28
31
  test,
29
32
  build,
30
33
  hello,
31
34
  generateKey,
32
35
  checkBalance,
33
- configStore,
36
+ storeConfig,
34
37
  watch,
35
- wait
38
+ wait,
39
+ switchEnv,
40
+ info,
41
+ loadMetadata,
42
+ doctor,
43
+ convertJson,
44
+ shell
36
45
  ];
@@ -0,0 +1,61 @@
1
+ import { CommandModule } from 'yargs';
2
+ import { logError, initializeDubhe, getDefaultNetwork } from '../utils';
3
+ import dotenv from 'dotenv';
4
+ import chalk from 'chalk';
5
+ import { handlerExit } from './shell';
6
+ dotenv.config();
7
+
8
+ type Options = {
9
+ network: any;
10
+ 'rpc-url'?: string;
11
+ };
12
+
13
+ const InfoCommand: CommandModule<Options, Options> = {
14
+ command: 'info',
15
+ describe: 'Get information about the current Sui node',
16
+ builder(yargs) {
17
+ return yargs.options({
18
+ network: {
19
+ type: 'string',
20
+ choices: ['mainnet', 'testnet', 'devnet', 'localnet', 'default'],
21
+ default: 'default',
22
+ desc: 'Node network (mainnet/testnet/devnet/localnet)'
23
+ },
24
+ 'rpc-url': {
25
+ type: 'string',
26
+ desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
27
+ }
28
+ });
29
+ },
30
+ handler: async ({ network, 'rpc-url': rpcUrl }) => {
31
+ try {
32
+ if (network == 'default') {
33
+ network = await getDefaultNetwork();
34
+ console.log(chalk.yellow(`Use default network: [${network}]`));
35
+ }
36
+ const fullnodeUrls = rpcUrl ? [rpcUrl] : undefined;
37
+ const dubhe = initializeDubhe({ network, fullnodeUrls });
38
+ const keypair = dubhe.getSigner();
39
+
40
+ console.log(chalk.blue('Account Information:'));
41
+ console.log(` Network: ${chalk.green(network)}`);
42
+ console.log(` Address: ${chalk.green(keypair.toSuiAddress())}`);
43
+
44
+ try {
45
+ const balance = await dubhe.getBalance('0x2::sui::SUI');
46
+ const suiBalance = (Number(balance.totalBalance) / 10 ** 9).toFixed(4);
47
+ console.log(` Balance: ${chalk.green(suiBalance)} SUI`);
48
+ } catch (_error) {
49
+ console.log(
50
+ ` Balance: ${chalk.red('Failed to fetch balance')} ${chalk.gray('(Network error)')}`
51
+ );
52
+ }
53
+ handlerExit();
54
+ } catch (error) {
55
+ logError(error);
56
+ handlerExit(1);
57
+ }
58
+ }
59
+ };
60
+
61
+ export default InfoCommand;
@@ -0,0 +1,68 @@
1
+ import type { CommandModule } from 'yargs';
2
+ import { logError } from '../utils/errors';
3
+ import { loadConfig, DubheConfig } from '@0xobelisk/sui-common';
4
+ import { loadMetadataHandler } from '../utils/metadataHandler';
5
+ import { handlerExit } from './shell';
6
+ import { getDefaultNetwork } from '../utils';
7
+ import chalk from 'chalk';
8
+
9
+ type Options = {
10
+ network: any;
11
+ 'config-path': string;
12
+ 'package-id'?: string;
13
+ 'rpc-url'?: string;
14
+ };
15
+
16
+ const commandModule: CommandModule<Options, Options> = {
17
+ command: 'load-metadata',
18
+
19
+ describe: 'Load metadata for a package',
20
+
21
+ builder(yargs) {
22
+ return yargs.options({
23
+ network: {
24
+ type: 'string',
25
+ choices: ['mainnet', 'testnet', 'devnet', 'localnet', 'default'],
26
+ default: 'default',
27
+ desc: 'Node network (mainnet/testnet/devnet/localnet)'
28
+ },
29
+ 'config-path': {
30
+ type: 'string',
31
+ desc: 'Configuration file path',
32
+ default: 'dubhe.config.ts'
33
+ },
34
+ 'package-id': {
35
+ type: 'string',
36
+ desc: 'Package ID to load metadata for',
37
+ optional: true
38
+ },
39
+ 'rpc-url': {
40
+ type: 'string',
41
+ desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
42
+ }
43
+ });
44
+ },
45
+
46
+ async handler({
47
+ network,
48
+ 'config-path': configPath,
49
+ 'package-id': packageId,
50
+ 'rpc-url': rpcUrl
51
+ }) {
52
+ try {
53
+ if (network == 'default') {
54
+ network = await getDefaultNetwork();
55
+ console.log(chalk.yellow(`Use default network: [${network}]`));
56
+ }
57
+ const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
58
+ const fullnodeUrls = rpcUrl ? [rpcUrl] : undefined;
59
+ await loadMetadataHandler(dubheConfig, network, packageId, fullnodeUrls);
60
+ } catch (error: any) {
61
+ logError(error);
62
+ handlerExit(1);
63
+ }
64
+ handlerExit();
65
+ }
66
+ };
67
+
68
+ export default commandModule;
@@ -1,22 +1,38 @@
1
1
  import type { CommandModule } from 'yargs';
2
2
  import { startLocalNode } from '../utils/startNode';
3
+ import { handlerExit } from './shell';
3
4
 
4
- const commandModule: CommandModule = {
5
+ type Options = {
6
+ 'data-dir': string;
7
+ force: boolean;
8
+ };
9
+
10
+ const commandModule: CommandModule<Options, Options> = {
5
11
  command: 'node',
6
12
 
7
13
  describe: 'Manage local Sui node',
8
14
 
9
- builder(yargs) {
10
- return yargs
15
+ builder: {
16
+ 'data-dir': {
17
+ type: 'string',
18
+ default: '.chk',
19
+ desc: 'Path to the data directory'
20
+ },
21
+ force: {
22
+ type: 'boolean',
23
+ default: false,
24
+ desc: 'Force restart: stop existing node and remove data directory'
25
+ }
11
26
  },
12
27
 
13
- async handler() {
28
+ async handler({ 'data-dir': data_dir, force }) {
14
29
  try {
15
- await startLocalNode();
30
+ await startLocalNode(data_dir, force);
16
31
  } catch (error) {
17
32
  console.error('Error executing command:', error);
18
- process.exit(1);
33
+ handlerExit(1);
19
34
  }
35
+ handlerExit();
20
36
  }
21
37
  };
22
38
 
@@ -1,12 +1,24 @@
1
1
  import type { CommandModule } from 'yargs';
2
2
  import { logError } from '../utils/errors';
3
- import { publishHandler } from '../utils';
3
+ import {
4
+ getDefaultNetwork,
5
+ publishHandler,
6
+ lintSystemGuards,
7
+ formatLintWarnings,
8
+ confirm
9
+ } from '../utils';
4
10
  import { loadConfig, DubheConfig } from '@0xobelisk/sui-common';
11
+ import { execSync } from 'child_process';
12
+ import { join as pathJoin } from 'path';
13
+ import { handlerExit } from './shell';
14
+ import chalk from 'chalk';
5
15
 
6
16
  type Options = {
7
17
  network: any;
8
18
  'config-path': string;
19
+ force: boolean;
9
20
  'gas-budget'?: number;
21
+ 'rpc-url'?: string;
10
22
  };
11
23
 
12
24
  const commandModule: CommandModule<Options, Options> = {
@@ -18,8 +30,8 @@ const commandModule: CommandModule<Options, Options> = {
18
30
  return yargs.options({
19
31
  network: {
20
32
  type: 'string',
21
- choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
22
- default: 'localnet',
33
+ choices: ['mainnet', 'testnet', 'devnet', 'localnet', 'default'],
34
+ default: 'default',
23
35
  desc: 'Node network (mainnet/testnet/devnet/localnet)'
24
36
  },
25
37
  'config-path': {
@@ -31,19 +43,55 @@ const commandModule: CommandModule<Options, Options> = {
31
43
  type: 'number',
32
44
  desc: 'Optional gas budget for the transaction',
33
45
  optional: true
46
+ },
47
+ force: {
48
+ type: 'boolean',
49
+ default: false,
50
+ desc: 'Clear existing published state for this network before build (use when re-publishing or to fix PublishErrorNonZeroAddress)'
51
+ },
52
+ 'rpc-url': {
53
+ type: 'string',
54
+ desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
34
55
  }
35
56
  });
36
57
  },
37
58
 
38
- async handler({ network, 'config-path': configPath, 'gas-budget': gasBudget }) {
59
+ async handler({
60
+ network,
61
+ 'config-path': configPath,
62
+ 'gas-budget': gasBudget,
63
+ force,
64
+ 'rpc-url': rpcUrl
65
+ }) {
39
66
  try {
67
+ if (network == 'default') {
68
+ network = await getDefaultNetwork();
69
+ console.log(chalk.yellow(`Use default network: [${network}]`));
70
+ }
40
71
  const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
41
- await publishHandler(dubheConfig, network, gasBudget);
72
+
73
+ const projectPath = pathJoin(process.cwd(), 'src', dubheConfig.name);
74
+ const lintResults = lintSystemGuards(projectPath);
75
+ if (lintResults.length > 0) {
76
+ process.stdout.write(formatLintWarnings(lintResults));
77
+ const proceed = await confirm(
78
+ 'Some entry functions are missing ensure_latest_version. Proceed with publish anyway?'
79
+ );
80
+ if (!proceed) {
81
+ console.log(chalk.red('Publish cancelled.'));
82
+ handlerExit(1);
83
+ return;
84
+ }
85
+ }
86
+
87
+ const fullnodeUrls = rpcUrl ? [rpcUrl] : undefined;
88
+ execSync(`pnpm dubhe convert-json --config-path ${configPath}`, { encoding: 'utf-8' });
89
+ await publishHandler(dubheConfig, network, force, gasBudget, fullnodeUrls);
42
90
  } catch (error: any) {
43
91
  logError(error);
44
- process.exit(1);
92
+ handlerExit(1);
45
93
  }
46
- process.exit(0);
94
+ handlerExit();
47
95
  }
48
96
  };
49
97