@0xobelisk/sui-cli 1.0.3 → 1.0.5

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.
@@ -0,0 +1,90 @@
1
+ import type { CommandModule } from 'yargs';
2
+ import { logError } from '../utils/errors';
3
+ import { callHandler } from '../utils';
4
+ import { loadConfig, DubheConfig } from '@0xobelisk/sui-common';
5
+
6
+ type Options = {
7
+ network: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
8
+ module: string;
9
+ function: string;
10
+ 'config-path'?: string;
11
+ 'package-id'?: string;
12
+ 'metadata-path'?: string;
13
+ params?: any[];
14
+ };
15
+
16
+ /**
17
+ * CLI command for calling a function in a module
18
+ */
19
+ const commandModule: CommandModule<Options, Options> = {
20
+ command: 'call',
21
+
22
+ describe: 'Call a function in a module',
23
+
24
+ builder: {
25
+ network: {
26
+ type: 'string',
27
+ choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
28
+ desc: 'Node network (mainnet/testnet/devnet/localnet)',
29
+ demandOption: true,
30
+ },
31
+ module: {
32
+ type: 'string',
33
+ desc: 'Module name',
34
+ demandOption: true,
35
+ },
36
+ function: {
37
+ type: 'string',
38
+ desc: 'Function name',
39
+ demandOption: true,
40
+ },
41
+ 'config-path': {
42
+ type: 'string',
43
+ default: 'dubhe.config.ts',
44
+ desc: 'Configuration file path',
45
+ },
46
+ 'package-id': {
47
+ type: 'string',
48
+ desc: 'Package ID (optional)',
49
+ },
50
+ 'metadata-path': {
51
+ type: 'string',
52
+ desc: 'Path to metadata JSON file (optional)',
53
+ },
54
+ params: {
55
+ type: 'array',
56
+ desc: 'Params for the function',
57
+ string: true,
58
+ },
59
+ },
60
+
61
+ async handler({
62
+ network,
63
+ 'config-path': configPath,
64
+ module: moduleName,
65
+ function: funcName,
66
+ 'package-id': packageId,
67
+ 'metadata-path': metadataPath,
68
+ params,
69
+ }) {
70
+ try {
71
+ const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
72
+
73
+ await callHandler({
74
+ dubheConfig,
75
+ moduleName,
76
+ funcName,
77
+ network,
78
+ packageId,
79
+ metadataFilePath: metadataPath,
80
+ params,
81
+ });
82
+ } catch (error: any) {
83
+ logError(error);
84
+ process.exit(1);
85
+ }
86
+ process.exit(0);
87
+ },
88
+ };
89
+
90
+ export default commandModule;
@@ -12,11 +12,13 @@ import generateKey from './generateKey';
12
12
  import checkBalance from './checkBalance';
13
13
  import configStore from './configStore';
14
14
  import query from './query';
15
+ import call from './call';
15
16
 
16
17
  // eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
17
18
  export const commands: CommandModule<any, any>[] = [
18
19
  localnode,
19
20
  publish,
21
+ call,
20
22
  query,
21
23
  faucet,
22
24
  schemagen,
@@ -5,9 +5,9 @@ import { loadConfig, DubheConfig } from '@0xobelisk/sui-common';
5
5
 
6
6
  type Options = {
7
7
  network: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
8
- 'config-path': string;
8
+ 'config-path'?: string;
9
9
  schema: string;
10
- struct: string;
10
+ field: string;
11
11
  'object-id'?: string;
12
12
  'package-id'?: string;
13
13
  'metadata-path'?: string;
@@ -21,18 +21,18 @@ type Options = {
21
21
  *
22
22
  * 1. Query StorageValue (no params required):
23
23
  * ```bash
24
- * dubhe query --config-path dubhe.config.ts --network devnet --schema counter --struct value
24
+ * dubhe query --config-path dubhe.config.ts --network devnet --schema counter --field value
25
25
  * ```
26
26
  *
27
27
  * 2. Query StorageMap (one param required):
28
28
  * ```bash
29
- * dubhe query --config-path dubhe.config.ts --network devnet --schema token --struct balances \
29
+ * dubhe query --config-path dubhe.config.ts --network devnet --schema token --field balances \
30
30
  * --params "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef"
31
31
  * ```
32
32
  *
33
33
  * 3. Query StorageDoubleMap (two params required):
34
34
  * ```bash
35
- * dubhe query --config-path dubhe.config.ts --network devnet --schema game --struct player_relations \
35
+ * dubhe query --config-path dubhe.config.ts --network devnet --schema game --field player_relations \
36
36
  * --params "0x123...456" "0x789...abc"
37
37
  * ```
38
38
  */
@@ -58,9 +58,9 @@ const commandModule: CommandModule<Options, Options> = {
58
58
  desc: 'Schema name',
59
59
  demandOption: true,
60
60
  },
61
- struct: {
61
+ field: {
62
62
  type: 'string',
63
- desc: 'Struct name',
63
+ desc: 'Field name',
64
64
  demandOption: true,
65
65
  },
66
66
  'object-id': {
@@ -78,6 +78,7 @@ const commandModule: CommandModule<Options, Options> = {
78
78
  params: {
79
79
  type: 'array',
80
80
  desc: 'Params for storage type: StorageValue(no params), StorageMap(1 param), StorageDoubleMap(2 params)',
81
+ string: true,
81
82
  },
82
83
  },
83
84
 
@@ -85,7 +86,7 @@ const commandModule: CommandModule<Options, Options> = {
85
86
  network,
86
87
  'config-path': configPath,
87
88
  schema,
88
- struct,
89
+ field,
89
90
  'object-id': objectId,
90
91
  'package-id': packageId,
91
92
  'metadata-path': metadataPath,
@@ -97,7 +98,7 @@ const commandModule: CommandModule<Options, Options> = {
97
98
  await queryStorage({
98
99
  dubheConfig,
99
100
  schema,
100
- struct,
101
+ field,
101
102
  objectId,
102
103
  network,
103
104
  packageId,
@@ -6,6 +6,7 @@ import { DubheConfig, loadConfig } from '@0xobelisk/sui-common';
6
6
  type Options = {
7
7
  'config-path': string;
8
8
  'test'?: string;
9
+ 'gas-limit'?: string;
9
10
  };
10
11
 
11
12
  const commandModule: CommandModule<Options, Options> = {
@@ -24,19 +25,22 @@ const commandModule: CommandModule<Options, Options> = {
24
25
  type: 'string',
25
26
  desc: 'Run a specific test',
26
27
  },
28
+ 'gas-limit': {
29
+ type: 'string',
30
+ desc: 'Set the gas limit for the test',
31
+ },
27
32
  });
28
33
  },
29
34
 
30
- async handler({ 'config-path': configPath, test }) {
35
+ async handler({ 'config-path': configPath, test, 'gas-limit': gasLimit }) {
31
36
  // Start an internal anvil process if no world address is provided
32
37
  try {
33
38
  console.log('🚀 Running move test');
34
39
  const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
35
40
  const path = process.cwd();
36
41
  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);
42
+ const command = `sui move test --path ${projectPath} ${test ? ` --test ${test}` : ''} ${gasLimit ? ` --gas-limit ${gasLimit}` : ''}`;
43
+ execSync(command, { stdio: 'inherit', encoding: "utf-8" });
40
44
  } catch (error: any) {
41
45
  console.error(chalk.red("Error executing sui move test:"));
42
46
  console.log(error.stdout);
@@ -0,0 +1,166 @@
1
+ import {
2
+ Dubhe,
3
+ loadMetadata,
4
+ Transaction,
5
+ TransactionResult,
6
+ } from '@0xobelisk/sui-client';
7
+ import { DubheCliError } from './errors';
8
+ import { validatePrivateKey, getOldPackageId, getObjectId } from './utils';
9
+ import { DubheConfig } from '@0xobelisk/sui-common';
10
+ import { loadMetadataFromFile } from './queryStorage';
11
+
12
+ const BaseTxType = [
13
+ 'u8',
14
+ 'u16',
15
+ 'u32',
16
+ 'u64',
17
+ 'u128',
18
+ 'u256',
19
+ 'bool',
20
+ 'id',
21
+ 'string',
22
+ 'address',
23
+ 'object',
24
+ ];
25
+
26
+ function validateParams(params: any[]) {
27
+ try {
28
+ params.forEach(param => {
29
+ const [type, value] = param.split(':');
30
+ if (!BaseTxType.includes(type)) {
31
+ throw new Error(`Invalid param type: ${type}`);
32
+ }
33
+ });
34
+ } catch (error) {
35
+ throw new Error(`Invalid params: ${error}`);
36
+ }
37
+ }
38
+
39
+ // param:
40
+ // u8:1
41
+ // u16:1
42
+ // u32:1
43
+ // u64:1
44
+ // u128:1
45
+ // u256:1
46
+ // object:0x1
47
+ // address:0x1
48
+ // bool:true
49
+ // string:"hello"
50
+ function formatBCS(tx: Transaction, param: string) {
51
+ const [type, value] = param.split(':');
52
+ switch (type) {
53
+ case 'u8':
54
+ return tx.pure.u8(parseInt(value));
55
+ case 'u16':
56
+ return tx.pure.u16(parseInt(value));
57
+ case 'u32':
58
+ return tx.pure.u32(parseInt(value));
59
+ case 'u64':
60
+ return tx.pure.u64(parseInt(value));
61
+ case 'u128':
62
+ return tx.pure.u128(parseInt(value));
63
+ case 'u256':
64
+ return tx.pure.u256(parseInt(value));
65
+ case 'object':
66
+ return tx.object(value);
67
+ case 'address':
68
+ return tx.pure.address(value);
69
+ case 'bool':
70
+ return tx.pure.bool(value === 'true');
71
+ case 'string':
72
+ return tx.pure.string(value);
73
+ default:
74
+ throw new Error(`Invalid param type: ${type}`);
75
+ }
76
+ }
77
+
78
+ function formatBCSParams(tx: Transaction, params: any[]) {
79
+ return params.map(param => formatBCS(tx, param));
80
+ }
81
+
82
+ export async function callHandler({
83
+ dubheConfig,
84
+ moduleName,
85
+ funcName,
86
+ params,
87
+ network,
88
+ packageId,
89
+ metadataFilePath,
90
+ }: {
91
+ dubheConfig: DubheConfig;
92
+ moduleName: string;
93
+ funcName: string;
94
+ params?: any[];
95
+ network: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
96
+ packageId?: string;
97
+ metadataFilePath?: string;
98
+ }) {
99
+ const privateKey = process.env.PRIVATE_KEY;
100
+ if (!privateKey) {
101
+ throw new DubheCliError(
102
+ `Missing PRIVATE_KEY environment variable.
103
+ Run 'echo "PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
104
+ in your contracts directory to use the default sui private key.`
105
+ );
106
+ }
107
+ const privateKeyFormat = validatePrivateKey(privateKey);
108
+ if (privateKeyFormat === false) {
109
+ throw new DubheCliError(`Please check your privateKey.`);
110
+ }
111
+
112
+ const path = process.cwd();
113
+ const projectPath = `${path}/contracts/${dubheConfig.name}`;
114
+
115
+ packageId = packageId || (await getOldPackageId(projectPath, network));
116
+
117
+ // objectId = objectId || (await getObjectId(projectPath, network, schema));
118
+
119
+ let metadata;
120
+ if (metadataFilePath) {
121
+ metadata = await loadMetadataFromFile(metadataFilePath);
122
+ } else {
123
+ metadata = await loadMetadata(network, packageId);
124
+ }
125
+ if (!metadata) {
126
+ throw new DubheCliError(
127
+ `Metadata file not found. Please provide a metadata file path or set the packageId.`
128
+ );
129
+ }
130
+
131
+ // if (!dubheConfig.schemas[schema]) {
132
+ // throw new DubheCliError(
133
+ // `Schema "${schema}" not found in dubhe config. Available schemas: ${Object.keys(
134
+ // dubheConfig.schemas
135
+ // ).join(', ')}`
136
+ // );
137
+ // }
138
+
139
+ // if (!dubheConfig.schemas[schema].structure[struct]) {
140
+ // throw new DubheCliError(
141
+ // `Struct "${struct}" not found in schema "${schema}". Available structs: ${Object.keys(
142
+ // dubheConfig.schemas[schema].structure
143
+ // ).join(', ')}`
144
+ // );
145
+ // }
146
+
147
+ // const storageType = dubheConfig.schemas[schema].structure[struct];
148
+
149
+ const processedParams = params || [];
150
+ validateParams(processedParams);
151
+ const dubhe = new Dubhe({
152
+ secretKey: privateKeyFormat,
153
+ networkType: network,
154
+ packageId,
155
+ metadata,
156
+ });
157
+ const tx = new Transaction();
158
+ const formattedParams = formatBCSParams(tx, processedParams);
159
+
160
+ const result = (await dubhe.tx[moduleName][funcName]({
161
+ tx,
162
+ params: formattedParams,
163
+ })) as TransactionResult;
164
+
165
+ console.log(result);
166
+ }
@@ -4,3 +4,4 @@ export * from './errors';
4
4
  export * from './printDubhe';
5
5
  export * from './utils';
6
6
  export * from './queryStorage';
7
+ export * from './callHandler';
@@ -36,7 +36,7 @@ function getExpectedParamsCount(storageType: string): number {
36
36
  export async function queryStorage({
37
37
  dubheConfig,
38
38
  schema,
39
- struct,
39
+ field,
40
40
  params,
41
41
  network,
42
42
  objectId,
@@ -45,7 +45,7 @@ export async function queryStorage({
45
45
  }: {
46
46
  dubheConfig: DubheConfig;
47
47
  schema: string;
48
- struct: string;
48
+ field: string;
49
49
  params?: any[];
50
50
  network: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
51
51
  objectId?: string;
@@ -92,15 +92,15 @@ in your contracts directory to use the default sui private key.`
92
92
  );
93
93
  }
94
94
 
95
- if (!dubheConfig.schemas[schema].structure[struct]) {
95
+ if (!dubheConfig.schemas[schema][field]) {
96
96
  throw new DubheCliError(
97
- `Struct "${struct}" not found in schema "${schema}". Available structs: ${Object.keys(
98
- dubheConfig.schemas[schema].structure
97
+ `Field "${field}" not found in schema "${schema}". Available fields: ${Object.keys(
98
+ dubheConfig.schemas[schema]
99
99
  ).join(', ')}`
100
100
  );
101
101
  }
102
102
 
103
- const storageType = dubheConfig.schemas[schema].structure[struct];
103
+ const storageType = dubheConfig.schemas[schema][field];
104
104
 
105
105
  const processedParams = params || [];
106
106
  if (!validateParams(storageType, processedParams)) {
@@ -119,7 +119,7 @@ in your contracts directory to use the default sui private key.`
119
119
  });
120
120
  const result = await dubhe.state({
121
121
  schema,
122
- struct,
122
+ field,
123
123
  objectId,
124
124
  storageType,
125
125
  params: processedParams,