@0xobelisk/sui-cli 1.1.13 โ†’ 1.2.0-pre.1

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,8 +1,8 @@
1
1
  import { execSync, spawn } from 'child_process';
2
2
  import chalk from 'chalk';
3
3
  import { printDubhe } from './printDubhe';
4
- import { delay, DubheCliError, validatePrivateKey } from '../utils';
5
- import { Dubhe } from '@0xobelisk/sui-client';
4
+ import { existsSync, mkdirSync, appendFileSync } from 'fs';
5
+ import { join } from 'path';
6
6
 
7
7
  function isSuiStartRunning(): boolean {
8
8
  try {
@@ -22,39 +22,37 @@ function isSuiStartRunning(): boolean {
22
22
 
23
23
  async function printAccounts() {
24
24
  // These private keys are used for testing purposes only, do not use them in production.
25
- const privateKeys = [
26
- 'suiprivkey1qq3ez3dje66l8pypgxynr7yymwps6uhn7vyczespj84974j3zya0wdpu76v',
27
- 'suiprivkey1qp6vcyg8r2x88fllmjmxtpzjl95gd9dugqrgz7xxf50w6rqdqzetg7x4d7s',
28
- 'suiprivkey1qpy3a696eh3m55fwa8h38ss063459u4n2dm9t24w2hlxxzjp2x34q8sdsnc',
29
- 'suiprivkey1qzxwp29favhzrjd95f6uj9nskjwal6nh9g509jpun395y6g72d6jqlmps4c',
30
- 'suiprivkey1qzhq4lv38sesah4uzsqkkmeyjx860xqjdz8qgw36tmrdd5tnle3evxpng57',
31
- 'suiprivkey1qzez45sjjsepjgtksqvpq6jw7dzw3zq0dx7a4sulfypd73acaynw5jl9x2c'
25
+ const accounts = [
26
+ {
27
+ privateKey: 'suiprivkey1qq3ez3dje66l8pypgxynr7yymwps6uhn7vyczespj84974j3zya0wdpu76v',
28
+ address: '0xe7f93ad7493035bcd674f287f78526091e195a6df9d64f23def61a7ce3adada9'
29
+ },
30
+ {
31
+ privateKey: 'suiprivkey1qp6vcyg8r2x88fllmjmxtpzjl95gd9dugqrgz7xxf50w6rqdqzetg7x4d7s',
32
+ address: '0x492404a537c32b46610bd6ae9f7f16ba16ff5a607d272543fe86cada69d8cf44'
33
+ },
34
+ {
35
+ privateKey: 'suiprivkey1qpy3a696eh3m55fwa8h38ss063459u4n2dm9t24w2hlxxzjp2x34q8sdsnc',
36
+ address: '0xd27e203483700d837a462d159ced6104619d8e36f737bf2a20c251153bf39f24'
37
+ },
38
+ {
39
+ privateKey: 'suiprivkey1qzxwp29favhzrjd95f6uj9nskjwal6nh9g509jpun395y6g72d6jqlmps4c',
40
+ address: '0x018f1f175c9b6739a14bc9c81e7984c134ebf9031015cf796fefcef04b8c4990'
41
+ },
42
+ {
43
+ privateKey: 'suiprivkey1qzhq4lv38sesah4uzsqkkmeyjx860xqjdz8qgw36tmrdd5tnle3evxpng57',
44
+ address: '0x932f6aab2bc636a25374f99794dc8451c4e27c91e87083e301816ed08bc98ed0'
45
+ },
46
+ {
47
+ privateKey: 'suiprivkey1qzez45sjjsepjgtksqvpq6jw7dzw3zq0dx7a4sulfypd73acaynw5jl9x2c',
48
+ address: '0x9a66b2da3036badd22529e3de8a00b0cd7dbbfe589873aa03d5f885f5f8c6501'
49
+ }
32
50
  ];
33
51
  console.log('๐Ÿ“Accounts');
34
52
  console.log('==========');
35
- privateKeys.forEach((privateKey, index) => {
36
- const dubhe = new Dubhe({ secretKey: privateKey });
37
- const keypair = dubhe.getSigner();
38
- spawn(
39
- 'curl',
40
- [
41
- '--location',
42
- '--request',
43
- 'POST',
44
- 'http://127.0.0.1:9123/gas',
45
- '--header',
46
- 'Content-Type: application/json',
47
- '--data-raw',
48
- `{"FixedAmountRequest": {"recipient": "${keypair.toSuiAddress()}"}}`
49
- ],
50
- {
51
- env: { ...process.env },
52
- stdio: 'ignore',
53
- detached: true
54
- }
55
- );
56
- console.log(` โ”Œโ”€ Account #${index}: ${keypair.toSuiAddress()}(1000 SUI)`);
57
- console.log(` โ””โ”€ Private Key: ${privateKey}`);
53
+ accounts.forEach((account, index) => {
54
+ console.log(` โ”Œโ”€ Account #${index}: ${account.address}(100000 SUI)`);
55
+ console.log(` โ””โ”€ Private Key: ${account.privateKey}`);
58
56
  });
59
57
  console.log('==========');
60
58
  console.log(
@@ -64,7 +62,66 @@ async function printAccounts() {
64
62
  chalk.yellow('Any funds sent to them on Mainnet or any other live network WILL BE LOST.')
65
63
  );
66
64
  }
67
- export async function startLocalNode() {
65
+
66
+ async function setupDirectories() {
67
+ const nodeLogsDir = join(process.cwd(), 'node_logs');
68
+ const logsDir = join(nodeLogsDir, 'logs');
69
+
70
+ if (!existsSync(nodeLogsDir)) {
71
+ mkdirSync(nodeLogsDir, { recursive: true });
72
+ }
73
+
74
+ if (!existsSync(logsDir)) {
75
+ mkdirSync(logsDir, { recursive: true });
76
+ }
77
+
78
+ return { nodeLogsDir, logsDir };
79
+ }
80
+
81
+ async function generateGenesisConfig(nodeLogsDir: string, logsDir: string) {
82
+ console.log(' โ”œโ”€ Generating genesis configuration...');
83
+ execSync(`sui genesis --write-config ${join(nodeLogsDir, 'sui.yaml')}`);
84
+
85
+ const additionalConfig = `
86
+ - address: "0xe7f93ad7493035bcd674f287f78526091e195a6df9d64f23def61a7ce3adada9"
87
+ gas_amounts:
88
+ - 100000000000000
89
+ - address: "0x492404a537c32b46610bd6ae9f7f16ba16ff5a607d272543fe86cada69d8cf44"
90
+ gas_amounts:
91
+ - 100000000000000
92
+ - address: "0xd27e203483700d837a462d159ced6104619d8e36f737bf2a20c251153bf39f24"
93
+ gas_amounts:
94
+ - 100000000000000
95
+ - address: "0x018f1f175c9b6739a14bc9c81e7984c134ebf9031015cf796fefcef04b8c4990"
96
+ gas_amounts:
97
+ - 100000000000000
98
+ - address: "0x932f6aab2bc636a25374f99794dc8451c4e27c91e87083e301816ed08bc98ed0"
99
+ gas_amounts:
100
+ - 100000000000000
101
+ - address: "0x9a66b2da3036badd22529e3de8a00b0cd7dbbfe589873aa03d5f885f5f8c6501"
102
+ gas_amounts:
103
+ - 100000000000000
104
+ `;
105
+ appendFileSync(join(nodeLogsDir, 'sui.yaml'), additionalConfig);
106
+
107
+ console.log(' โ”œโ”€ Initializing genesis...');
108
+ execSync(`sui genesis --working-dir ${logsDir} -f --from-config ${join(nodeLogsDir, 'sui.yaml')}`);
109
+ }
110
+
111
+ function handleProcessSignals(suiProcess: ReturnType<typeof spawn> | null) {
112
+ const cleanup = () => {
113
+ console.log(chalk.yellow('\n๐Ÿ”” Stopping Local Node...'));
114
+ if (suiProcess) {
115
+ suiProcess.kill('SIGINT');
116
+ }
117
+ process.exit(0);
118
+ };
119
+
120
+ process.on('SIGINT', cleanup);
121
+ process.on('SIGTERM', cleanup);
122
+ }
123
+
124
+ export async function startLocalNode(options: { forceRegenesis?: boolean } = {}) {
68
125
  if (isSuiStartRunning()) {
69
126
  console.log(chalk.yellow('\nโš ๏ธ Warning: Local Node Already Running'));
70
127
  console.log(chalk.yellow(' โ”œโ”€ Cannot start a new instance'));
@@ -74,47 +131,46 @@ export async function startLocalNode() {
74
131
 
75
132
  printDubhe();
76
133
  console.log('๐Ÿš€ Starting Local Node...');
134
+
135
+ let suiProcess: ReturnType<typeof spawn> | null = null;
136
+
77
137
  try {
78
- const suiProcess = spawn('sui', ['start', '--with-faucet', '--force-regenesis'], {
79
- env: { ...process.env, RUST_LOG: 'off,sui_node=info' },
80
- stdio: 'ignore',
81
- detached: true
82
- });
138
+ const { nodeLogsDir, logsDir } = await setupDirectories();
83
139
 
84
- suiProcess.on('error', (error) => {
85
- console.error(chalk.red('\nโŒ Failed to Start Local Node'));
86
- console.error(chalk.red(` โ””โ”€ Error: ${error.message}`));
87
- });
88
- await delay(5000);
140
+ if (options.forceRegenesis) {
141
+ console.log(' โ”œโ”€ Force Regenesis: Yes');
142
+ await generateGenesisConfig(nodeLogsDir, logsDir);
143
+ } else {
144
+ console.log(' โ”œโ”€ Force Regenesis: No');
145
+ }
146
+
89
147
  console.log(' โ”œโ”€ Faucet: Enabled');
90
- console.log(' โ””โ”€ Force Regenesis: Yes');
91
148
  console.log(' โ””โ”€ HTTP server: http://127.0.0.1:9000/');
92
149
  console.log(' โ””โ”€ Faucet server: http://127.0.0.1:9123/');
93
-
94
150
  await printAccounts();
151
+ console.log(chalk.green('๐ŸŽ‰ Local environment is ready!'));
95
152
 
96
- await delay(2000);
97
-
98
- const privateKeyFormat = validatePrivateKey(
99
- 'suiprivkey1qzez45sjjsepjgtksqvpq6jw7dzw3zq0dx7a4sulfypd73acaynw5jl9x2c'
100
- );
101
- if (privateKeyFormat === false) {
102
- throw new DubheCliError(`Please check your privateKey.`);
103
- }
153
+ suiProcess = spawn('sui', [
154
+ 'start',
155
+ '--with-faucet',
156
+ '--network.config',
157
+ join(logsDir, 'network.yaml')
158
+ ], {
159
+ env: { ...process.env, RUST_LOG: 'off,sui_node=info' },
160
+ stdio: 'ignore'
161
+ });
104
162
 
105
- console.log(chalk.green('๐ŸŽ‰ Local environment is ready!'));
163
+ handleProcessSignals(suiProcess);
106
164
 
107
- process.on('SIGINT', () => {
108
- console.log(chalk.yellow('\n๐Ÿ”” Stopping Local Node...'));
109
- if (suiProcess) {
110
- suiProcess.kill();
111
- console.log(chalk.green('โœ… Local Node Stopped'));
112
- }
113
- process.exit();
165
+ await new Promise<void>((resolve) => {
166
+ suiProcess?.on('exit', () => resolve());
114
167
  });
115
168
  } catch (error: any) {
116
169
  console.error(chalk.red('\nโŒ Failed to Start Local Node'));
117
170
  console.error(chalk.red(` โ””โ”€ Error: ${error.message}`));
171
+ if (suiProcess) {
172
+ suiProcess.kill('SIGINT');
173
+ }
118
174
  process.exit(1);
119
175
  }
120
176
  }
@@ -1,36 +1,24 @@
1
- import * as fsAsync from 'fs/promises';
2
1
  import { mkdirSync, writeFileSync } from 'fs';
3
2
  import { dirname } from 'path';
4
- import { DeploymentJsonType } from './utils';
5
3
  import { DubheConfig } from '@0xobelisk/sui-common';
4
+ import { getDeploymentJson, getDubheSchemaId } from './utils';
6
5
 
7
- async function getDeploymentJson(
8
- projectPath: string,
9
- network: string
10
- ): Promise<DeploymentJsonType> {
11
- try {
12
- const data = await fsAsync.readFile(
13
- `${projectPath}/.history/sui_${network}/latest.json`,
14
- 'utf8'
15
- );
16
- return JSON.parse(data) as DeploymentJsonType;
17
- } catch (error) {
18
- throw new Error(`read .history/sui_${network}/latest.json failed. ${error}`);
19
- }
20
- }
21
-
22
- function storeConfig(network: string, packageId: string, schemaId: string, outputPath: string) {
6
+ async function storeConfig(
7
+ network: string,
8
+ packageId: string,
9
+ schemaId: string,
10
+ outputPath: string
11
+ ) {
12
+ const dubheSchemaId = await getDubheSchemaId(network);
23
13
  let code = `type NetworkType = 'testnet' | 'mainnet' | 'devnet' | 'localnet';
24
14
 
25
15
  export const NETWORK: NetworkType = '${network}';
26
- export const PACKAGE_ID = '${packageId}'
27
- export const SCHEMA_ID = '${schemaId}'
16
+ export const PACKAGE_ID = '${packageId}';
17
+ export const SCHEMA_ID = '${schemaId}';
18
+ export const DUBHE_SCHEMA_ID = '${dubheSchemaId}';
28
19
  `;
29
20
 
30
- // if (outputPath) {
31
21
  writeOutput(code, outputPath, 'storeConfig');
32
- // writeOutput(code, `${path}/src/chain/config.ts`, 'storeConfig');
33
- // }
34
22
  }
35
23
 
36
24
  async function writeOutput(
@@ -54,5 +42,5 @@ export async function storeConfigHandler(
54
42
  const path = process.cwd();
55
43
  const contractPath = `${path}/contracts/${dubheConfig.name}`;
56
44
  const deployment = await getDeploymentJson(contractPath, network);
57
- storeConfig(deployment.network, deployment.packageId, deployment.schemaId, outputPath);
45
+ await storeConfig(deployment.network, deployment.packageId, deployment.schemaId, outputPath);
58
46
  }
@@ -1,16 +1,16 @@
1
- import { Dubhe, Transaction, UpgradePolicy } from '@0xobelisk/sui-client';
1
+ import { Transaction, UpgradePolicy } from '@0xobelisk/sui-client';
2
2
  import { execSync } from 'child_process';
3
3
  import chalk from 'chalk';
4
- import { DubheCliError, UpgradeError } from './errors';
4
+ import { UpgradeError } from './errors';
5
5
  import {
6
6
  getOldPackageId,
7
7
  getVersion,
8
8
  getUpgradeCap,
9
9
  saveContractData,
10
- validatePrivateKey,
11
10
  getOnchainSchemas,
12
11
  switchEnv,
13
- getSchemaId
12
+ getSchemaId,
13
+ initializeDubhe
14
14
  } from './utils';
15
15
  import * as fs from 'fs';
16
16
  import * as path from 'path';
@@ -97,21 +97,9 @@ export async function upgradeHandler(
97
97
 
98
98
  const path = process.cwd();
99
99
  const projectPath = `${path}/contracts/${name}`;
100
- const privateKey = process.env.PRIVATE_KEY;
101
- if (!privateKey)
102
- throw new DubheCliError(
103
- `Missing PRIVATE_KEY environment variable.
104
- Run 'echo "PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
105
- in your contracts directory to use the default sui private key.`
106
- );
107
100
 
108
- const privateKeyFormat = validatePrivateKey(privateKey);
109
- if (privateKeyFormat === false) {
110
- throw new DubheCliError(`Please check your privateKey.`);
111
- }
112
- const dubhe = new Dubhe({
113
- networkType: network,
114
- secretKey: privateKeyFormat
101
+ const dubhe = initializeDubhe({
102
+ network
115
103
  });
116
104
 
117
105
  let oldVersion = Number(await getVersion(projectPath, network));
@@ -248,7 +236,9 @@ in your contracts directory to use the default sui private key.`
248
236
  console.log(chalk.green(`Migration Transaction Digest: ${result.digest}`));
249
237
  },
250
238
  onError: (error) => {
251
- console.log(chalk.red('Migration Transaction failed!, Please execute the migration manually.'));
239
+ console.log(
240
+ chalk.red('Migration Transaction failed!, Please execute the migration manually.')
241
+ );
252
242
  console.error(error);
253
243
  }
254
244
  });
@@ -6,6 +6,8 @@ import { FsIibError } from './errors';
6
6
  import * as fs from 'fs';
7
7
  import chalk from 'chalk';
8
8
  import { spawn } from 'child_process';
9
+ import { Dubhe, NetworkType, SuiMoveNormalizedModules } from '@0xobelisk/sui-client';
10
+ import { DubheCliError } from './errors';
9
11
 
10
12
  export type DeploymentJsonType = {
11
13
  projectName: string;
@@ -58,15 +60,49 @@ export async function updateVersionInFile(projectPath: string, newVersion: strin
58
60
  }
59
61
  }
60
62
 
61
- async function getDeploymentJson(projectPath: string, network: string) {
63
+ export async function getDeploymentJson(
64
+ projectPath: string,
65
+ network: string
66
+ ): Promise<DeploymentJsonType> {
62
67
  try {
63
68
  const data = await fsAsync.readFile(
64
69
  `${projectPath}/.history/sui_${network}/latest.json`,
65
70
  'utf8'
66
71
  );
67
72
  return JSON.parse(data) as DeploymentJsonType;
68
- } catch {
69
- throw new FsIibError('Fs read deployment file failed.');
73
+ } catch (error) {
74
+ throw new Error(`read .history/sui_${network}/latest.json failed. ${error}`);
75
+ }
76
+ }
77
+
78
+ export async function getDeploymentSchemaId(projectPath: string, network: string): Promise<string> {
79
+ try {
80
+ const data = await fsAsync.readFile(
81
+ `${projectPath}/.history/sui_${network}/latest.json`,
82
+ 'utf8'
83
+ );
84
+ const deployment = JSON.parse(data) as DeploymentJsonType;
85
+ return deployment.schemaId;
86
+ } catch (error) {
87
+ return '';
88
+ }
89
+ }
90
+
91
+ export async function getDubheSchemaId(network: string) {
92
+ const path = process.cwd();
93
+ const contractPath = `${path}/contracts/dubhe-framework`;
94
+
95
+ switch (network) {
96
+ case 'mainnet':
97
+ return await getDeploymentSchemaId(contractPath, 'mainnet');
98
+ case 'testnet':
99
+ return '0xa565cbb3641fff8f7e8ef384b215808db5f1837aa72c1cca1803b5d973699aac';
100
+ case 'devnet':
101
+ return await getDeploymentSchemaId(contractPath, 'devnet');
102
+ case 'localnet':
103
+ return await getDeploymentSchemaId(contractPath, 'localnet');
104
+ default:
105
+ throw new Error(`Invalid network: ${network}`);
70
106
  }
71
107
  }
72
108
 
@@ -200,3 +236,38 @@ export async function switchEnv(network: 'mainnet' | 'testnet' | 'devnet' | 'loc
200
236
  }
201
237
 
202
238
  export const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
239
+
240
+ export function loadKey(): string {
241
+ const privateKey = process.env.PRIVATE_KEY || process.env.NEXT_PUBLIC_PRIVATE_KEY;
242
+ if (!privateKey) {
243
+ throw new DubheCliError(
244
+ `Missing private key environment variable.
245
+ Run 'echo "PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
246
+ or 'echo "NEXT_PUBLIC_PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
247
+ in your contracts directory to use the default sui private key.`
248
+ );
249
+ }
250
+ const privateKeyFormat = validatePrivateKey(privateKey);
251
+ if (privateKeyFormat === false) {
252
+ throw new DubheCliError(`Please check your privateKey.`);
253
+ }
254
+ return privateKeyFormat;
255
+ }
256
+
257
+ export function initializeDubhe({
258
+ network,
259
+ packageId,
260
+ metadata
261
+ }: {
262
+ network: NetworkType;
263
+ packageId?: string;
264
+ metadata?: SuiMoveNormalizedModules;
265
+ }): Dubhe {
266
+ const privateKey = loadKey();
267
+ return new Dubhe({
268
+ networkType: network,
269
+ secretKey: privateKey,
270
+ packageId,
271
+ metadata
272
+ });
273
+ }
@@ -1,56 +0,0 @@
1
- import type { CommandModule } from 'yargs';
2
- import { logError } from '../utils/errors';
3
- import { indexerHandler } from '../utils';
4
- import { loadConfig, DubheConfig } from '@0xobelisk/sui-common';
5
-
6
- type Options = {
7
- network: any;
8
- 'config-path': string;
9
- db: string;
10
- schemaId?: string;
11
- };
12
-
13
- const commandModule: CommandModule<Options, Options> = {
14
- command: 'indexer',
15
-
16
- describe: 'Dubhe indexer',
17
-
18
- builder(yargs) {
19
- return yargs.options({
20
- network: {
21
- type: 'string',
22
- choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
23
- desc: 'Node network (mainnet/testnet/devnet/localnet)',
24
- default: 'localnet'
25
- },
26
- 'config-path': {
27
- type: 'string',
28
- default: 'dubhe.config.ts',
29
- desc: 'Configuration file path'
30
- },
31
- schemaId: {
32
- type: 'string',
33
- desc: 'Schema ID'
34
- },
35
- db: {
36
- type: 'string',
37
- choices: ['sqlite', 'postgres'],
38
- desc: 'Optional gas budget for the transaction',
39
- default: 'sqlite'
40
- }
41
- });
42
- },
43
-
44
- async handler({ network, 'config-path': configPath, db, schemaId: schemaId }) {
45
- try {
46
- const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
47
- await indexerHandler(dubheConfig, network, db, schemaId);
48
- } catch (error: any) {
49
- logError(error);
50
- process.exit(1);
51
- }
52
- process.exit(0);
53
- }
54
- };
55
-
56
- export default commandModule;