@0xobelisk/sui-cli 1.2.0-pre.3 → 1.2.0-pre.33

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.
@@ -4,19 +4,17 @@ import chalk from 'chalk';
4
4
  import {
5
5
  saveContractData,
6
6
  updateDubheDependency,
7
+ updateMoveTomlAddress,
7
8
  switchEnv,
8
9
  delay,
9
- getDubheSchemaId,
10
- initializeDubhe
10
+ getDubheDappHub,
11
+ initializeDubhe,
12
+ saveMetadata
11
13
  } from './utils';
12
14
  import { DubheConfig } from '@0xobelisk/sui-common';
13
15
  import * as fs from 'fs';
14
16
  import * as path from 'path';
15
17
 
16
- const MAX_RETRIES = 60; // 60s timeout
17
- const RETRY_INTERVAL = 1000; // 1s retry interval
18
- const SPINNER = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
19
-
20
18
  async function removeEnvContent(
21
19
  filePath: string,
22
20
  networkType: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
@@ -154,132 +152,28 @@ interface ObjectChange {
154
152
  }
155
153
 
156
154
  async function waitForNode(dubhe: Dubhe): Promise<string> {
157
- let retryCount = 0;
158
- let spinnerIndex = 0;
159
- const startTime = Date.now();
160
- let isInterrupted = false;
161
- let chainId = '';
162
- let hasShownBalanceWarning = false;
163
-
164
- const handleInterrupt = () => {
165
- isInterrupted = true;
166
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
167
- console.log('\n └─ Operation cancelled by user');
168
- process.exit(0);
169
- };
170
- process.on('SIGINT', handleInterrupt);
171
-
172
- try {
173
- // 第一阶段:等待获取 chainId
174
- while (retryCount < MAX_RETRIES && !isInterrupted && !chainId) {
175
- try {
176
- chainId = await dubhe.suiInteractor.currentClient.getChainIdentifier();
177
- } catch (error) {
178
- // 忽略错误,继续重试
179
- }
180
-
181
- if (isInterrupted) break;
182
-
183
- if (!chainId) {
184
- retryCount++;
185
- if (retryCount === MAX_RETRIES) {
186
- console.log(chalk.red(` └─ Failed to connect to node after ${MAX_RETRIES} attempts`));
187
- console.log(chalk.red(' └─ Please check if the Sui node is running.'));
188
- process.exit(1);
189
- }
190
-
191
- const elapsedTime = Math.floor((Date.now() - startTime) / 1000);
192
- const spinner = SPINNER[spinnerIndex % SPINNER.length];
193
- spinnerIndex++;
194
-
195
- process.stdout.write(`\r ├─ ${spinner} Waiting for node... (${elapsedTime}s)`);
196
- await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL));
197
- }
198
- }
155
+ const chainId = await dubhe.suiInteractor.currentClient.getChainIdentifier();
156
+ console.log(` ├─ ChainId: ${chainId}`);
157
+ const address = dubhe.getAddress();
158
+ const coins = await dubhe.suiInteractor.currentClient.getCoins({
159
+ owner: address,
160
+ coinType: '0x2::sui::SUI'
161
+ });
199
162
 
200
- // 显示 chainId
201
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
202
- console.log(` ├─ ChainId: ${chainId}`);
203
-
204
- // 第二阶段:检查部署账户余额
205
- retryCount = 0;
206
- while (retryCount < MAX_RETRIES && !isInterrupted) {
207
- try {
208
- const address = dubhe.getAddress();
209
- const coins = await dubhe.suiInteractor.currentClient.getCoins({
210
- owner: address,
211
- coinType: '0x2::sui::SUI'
212
- });
213
-
214
- if (coins.data.length > 0) {
215
- const balance = coins.data.reduce((sum, coin) => sum + Number(coin.balance), 0);
216
- if (balance > 0) {
217
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
218
- console.log(` ├─ Deployer balance: ${balance / 10 ** 9} SUI`);
219
- return chainId;
220
- } else if (!hasShownBalanceWarning) {
221
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
222
- console.log(
223
- chalk.yellow(
224
- ` ├─ Deployer balance: 0 SUI, please ensure your account has sufficient SUI balance`
225
- )
226
- );
227
- hasShownBalanceWarning = true;
228
- }
229
- } else if (!hasShownBalanceWarning) {
230
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
231
- console.log(
232
- chalk.yellow(
233
- ` ├─ No SUI coins found in deployer account, please ensure your account has sufficient SUI balance`
234
- )
235
- );
236
- hasShownBalanceWarning = true;
237
- }
238
-
239
- retryCount++;
240
- if (retryCount === MAX_RETRIES) {
241
- console.log(
242
- chalk.red(` └─ Deployer account has no SUI balance after ${MAX_RETRIES} attempts`)
243
- );
244
- console.log(chalk.red(' └─ Please ensure your account has sufficient SUI balance.'));
245
- process.exit(1);
246
- }
247
-
248
- const elapsedTime = Math.floor((Date.now() - startTime) / 1000);
249
- const spinner = SPINNER[spinnerIndex % SPINNER.length];
250
- spinnerIndex++;
251
-
252
- process.stdout.write(`\r ├─ ${spinner} Checking deployer balance... (${elapsedTime}s)`);
253
- await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL));
254
- } catch (error) {
255
- if (isInterrupted) break;
256
-
257
- retryCount++;
258
- if (retryCount === MAX_RETRIES) {
259
- console.log(
260
- chalk.red(` └─ Failed to check deployer balance after ${MAX_RETRIES} attempts`)
261
- );
262
- console.log(chalk.red(' └─ Please check your account and network connection.'));
263
- process.exit(1);
264
- }
265
-
266
- const elapsedTime = Math.floor((Date.now() - startTime) / 1000);
267
- const spinner = SPINNER[spinnerIndex % SPINNER.length];
268
- spinnerIndex++;
269
-
270
- process.stdout.write(`\r ├─ ${spinner} Checking deployer balance... (${elapsedTime}s)`);
271
- await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL));
272
- }
163
+ if (coins.data.length > 0) {
164
+ const balance = coins.data.reduce((sum, coin) => sum + Number(coin.balance), 0);
165
+ if (balance > 0) {
166
+ console.log(` ├─ Deployer balance: ${balance / 10 ** 9} SUI`);
167
+ return chainId;
168
+ } else {
169
+ console.log(
170
+ chalk.yellow(
171
+ ` ├─ Deployer balance: 0 SUI, please ensure your account has sufficient SUI balance`
172
+ )
173
+ );
273
174
  }
274
- } finally {
275
- process.removeListener('SIGINT', handleInterrupt);
276
- }
277
-
278
- if (isInterrupted) {
279
- process.exit(0);
280
175
  }
281
-
282
- throw new Error('Failed to connect to node');
176
+ return chainId;
283
177
  }
284
178
 
285
179
  async function publishContract(
@@ -311,52 +205,15 @@ async function publishContract(
311
205
  const [upgradeCap] = tx.publish({ modules, dependencies });
312
206
  tx.transferObjects([upgradeCap], dubhe.getAddress());
313
207
 
314
- let result: any = null;
315
- let retryCount = 0;
316
- let spinnerIndex = 0;
317
- const startTime = Date.now();
318
- let isInterrupted = false;
319
-
320
- const handleInterrupt = () => {
321
- isInterrupted = true;
322
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
323
- console.log('\n └─ Operation cancelled by user');
324
- process.exit(0);
325
- };
326
- process.on('SIGINT', handleInterrupt);
327
-
208
+ let result;
328
209
  try {
329
- while (retryCount < MAX_RETRIES && !result && !isInterrupted) {
330
- try {
331
- result = await dubhe.signAndSendTxn({ tx });
332
- } catch (error) {
333
- if (isInterrupted) break;
334
-
335
- retryCount++;
336
- if (retryCount === MAX_RETRIES) {
337
- console.log(chalk.red(` └─ Publication failed after ${MAX_RETRIES} attempts`));
338
- console.log(chalk.red(' └─ Please check your network connection and try again later.'));
339
- process.exit(1);
340
- }
341
-
342
- const elapsedTime = Math.floor((Date.now() - startTime) / 1000);
343
- const spinner = SPINNER[spinnerIndex % SPINNER.length];
344
- spinnerIndex++;
345
-
346
- process.stdout.write(`\r ├─ ${spinner} Retrying... (${elapsedTime}s)`);
347
- await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL));
348
- }
349
- }
350
- } finally {
351
- process.removeListener('SIGINT', handleInterrupt);
352
- }
353
-
354
- if (isInterrupted) {
355
- process.exit(0);
210
+ result = await dubhe.signAndSendTxn({ tx });
211
+ } catch (error: any) {
212
+ console.error(chalk.red(' └─ Publication failed'));
213
+ console.error(error.message);
214
+ process.exit(1);
356
215
  }
357
216
 
358
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
359
-
360
217
  if (!result || result.effects?.status.status === 'failure') {
361
218
  console.log(chalk.red(' └─ Publication failed'));
362
219
  process.exit(1);
@@ -365,10 +222,12 @@ async function publishContract(
365
222
  console.log(' ├─ Processing publication results...');
366
223
  let version = 1;
367
224
  let packageId = '';
368
- let schemaId = '';
369
- let schemas = dubheConfig.schemas;
225
+ let dappHub = '';
226
+ let components = dubheConfig.components;
370
227
  let upgradeCapId = '';
371
228
 
229
+ let printObjects: any[] = [];
230
+
372
231
  result.objectChanges!.map((object: ObjectChange) => {
373
232
  if (object.type === 'published') {
374
233
  console.log(` ├─ Package ID: ${object.packageId}`);
@@ -382,6 +241,16 @@ async function publishContract(
382
241
  console.log(` ├─ Upgrade Cap: ${object.objectId}`);
383
242
  upgradeCapId = object.objectId || '';
384
243
  }
244
+ if (
245
+ object.type === 'created' &&
246
+ object.objectType &&
247
+ object.objectType.includes('dapp_hub::DappHub')
248
+ ) {
249
+ dappHub = object.objectId || '';
250
+ }
251
+ if (object.type === 'created') {
252
+ printObjects.push(object);
253
+ }
385
254
  });
386
255
 
387
256
  console.log(` └─ Transaction: ${result.digest}`);
@@ -393,13 +262,11 @@ async function publishContract(
393
262
 
394
263
  const deployHookTx = new Transaction();
395
264
  let args = [];
396
- if (dubheConfig.name !== 'dubhe') {
397
- let dubheSchemaId = await getDubheSchemaId(network);
398
- args.push(deployHookTx.object(dubheSchemaId));
399
- }
265
+ let dubheDappHub = dubheConfig.name === 'dubhe' ? dappHub : await getDubheDappHub(network);
266
+ args.push(deployHookTx.object(dubheDappHub));
400
267
  args.push(deployHookTx.object('0x6'));
401
268
  deployHookTx.moveCall({
402
- target: `${packageId}::${dubheConfig.name}_genesis::run`,
269
+ target: `${packageId}::genesis::run`,
403
270
  arguments: args
404
271
  });
405
272
 
@@ -416,35 +283,29 @@ async function publishContract(
416
283
  console.log(' ├─ Hook execution successful');
417
284
  console.log(` ├─ Transaction: ${deployHookResult.digest}`);
418
285
 
419
- console.log('\n📋 Created Schemas:');
420
- deployHookResult.objectChanges?.map((object: ObjectChange) => {
421
- if (
422
- object.type === 'created' &&
423
- object.objectType &&
424
- object.objectType.includes('schema::Schema')
425
- ) {
426
- schemaId = object.objectId || '';
427
- }
428
- if (
429
- object.type === 'created' &&
430
- object.objectType &&
431
- object.objectType.includes('schema') &&
432
- !object.objectType.includes('dynamic_field')
433
- ) {
434
- console.log(` ├─ Type: ${object.objectType}`);
435
- console.log(` └─ ID: ${object.objectId}`);
436
- }
286
+ console.log('\n📋 Created Objects:');
287
+ printObjects.map((object: ObjectChange) => {
288
+ console.log(` ├─ Type: ${object.objectType}`);
289
+ console.log(` └─ ID: ${object.objectId}`);
437
290
  });
438
291
 
439
- saveContractData(
292
+ await saveContractData(
440
293
  dubheConfig.name,
441
294
  network,
442
295
  packageId,
443
- schemaId,
296
+ dappHub,
444
297
  upgradeCapId,
445
298
  version,
446
- schemas
299
+ components
447
300
  );
301
+
302
+ await saveMetadata(dubheConfig.name, network, packageId);
303
+
304
+ // Insert package id to dubhe config
305
+ let config = JSON.parse(fs.readFileSync(`${process.cwd()}/dubhe.config.json`, 'utf-8'));
306
+ config.package_id = packageId;
307
+ fs.writeFileSync(`${process.cwd()}/dubhe.config.json`, JSON.stringify(config, null, 2));
308
+
448
309
  console.log('\n✅ Contract Publication Complete\n');
449
310
  } else {
450
311
  console.log(chalk.yellow(' └─ Deploy hook execution failed'));
@@ -460,15 +321,13 @@ async function checkDubheFramework(projectPath: string): Promise<boolean> {
460
321
  console.log(chalk.yellow('\nℹ️ Dubhe Framework Files Not Found'));
461
322
  console.log(chalk.yellow(' ├─ Expected Path:'), projectPath);
462
323
  console.log(chalk.yellow(' ├─ To set up Dubhe Framework:'));
463
- console.log(chalk.yellow(' │ 1. Create directory: mkdir -p contracts/dubhe-framework'));
324
+ console.log(chalk.yellow(' │ 1. Create directory: mkdir -p contracts/dubhe'));
464
325
  console.log(
465
326
  chalk.yellow(
466
- ' │ 2. Clone repository: git clone https://github.com/0xobelisk/dubhe-framework contracts/dubhe-framework'
327
+ ' │ 2. Clone repository: git clone https://github.com/0xobelisk/dubhe contracts/dubhe'
467
328
  )
468
329
  );
469
- console.log(
470
- chalk.yellow(' │ 3. Or download from: https://github.com/0xobelisk/dubhe-framework')
471
- );
330
+ console.log(chalk.yellow(' │ 3. Or download from: https://github.com/0xobelisk/dubhe'));
472
331
  console.log(chalk.yellow(' └─ After setup, restart the local node'));
473
332
  return false;
474
333
  }
@@ -480,7 +339,7 @@ export async function publishDubheFramework(
480
339
  network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
481
340
  ) {
482
341
  const path = process.cwd();
483
- const projectPath = `${path}/contracts/dubhe-framework`;
342
+ const projectPath = `${path}/src/dubhe`;
484
343
 
485
344
  if (!(await checkDubheFramework(projectPath))) {
486
345
  return;
@@ -492,57 +351,22 @@ export async function publishDubheFramework(
492
351
  const chainId = await waitForNode(dubhe);
493
352
 
494
353
  await removeEnvContent(`${projectPath}/Move.lock`, network);
354
+ await updateMoveTomlAddress(projectPath, "0x0");
355
+
495
356
  const [modules, dependencies] = buildContract(projectPath);
496
357
  const tx = new Transaction();
497
358
  const [upgradeCap] = tx.publish({ modules, dependencies });
498
359
  tx.transferObjects([upgradeCap], dubhe.getAddress());
499
360
 
500
- let result: any = null;
501
- let retryCount = 0;
502
- let spinnerIndex = 0;
503
- const startTime = Date.now();
504
- let isInterrupted = false;
505
-
506
- const handleInterrupt = () => {
507
- isInterrupted = true;
508
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
509
- console.log('\n └─ Operation cancelled by user');
510
- process.exit(0);
511
- };
512
- process.on('SIGINT', handleInterrupt);
513
-
361
+ let result;
514
362
  try {
515
- while (retryCount < MAX_RETRIES && !result && !isInterrupted) {
516
- try {
517
- result = await dubhe.signAndSendTxn({ tx });
518
- } catch (error) {
519
- if (isInterrupted) break;
520
-
521
- retryCount++;
522
- if (retryCount === MAX_RETRIES) {
523
- console.log(chalk.red(` └─ Publication failed after ${MAX_RETRIES} attempts`));
524
- console.log(chalk.red(' └─ Please check your network connection and try again later.'));
525
- process.exit(1);
526
- }
527
-
528
- const elapsedTime = Math.floor((Date.now() - startTime) / 1000);
529
- const spinner = SPINNER[spinnerIndex % SPINNER.length];
530
- spinnerIndex++;
531
-
532
- process.stdout.write(`\r ├─ ${spinner} Retrying... (${elapsedTime}s)`);
533
- await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL));
534
- }
535
- }
536
- } finally {
537
- process.removeListener('SIGINT', handleInterrupt);
538
- }
539
-
540
- if (isInterrupted) {
541
- process.exit(0);
363
+ result = await dubhe.signAndSendTxn({ tx });
364
+ } catch (error: any) {
365
+ console.error(chalk.red(' └─ Publication failed'));
366
+ console.error(error.message);
367
+ process.exit(1);
542
368
  }
543
369
 
544
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
545
-
546
370
  if (!result || result.effects?.status.status === 'failure') {
547
371
  console.log(chalk.red(' └─ Publication failed'));
548
372
  process.exit(1);
@@ -550,8 +374,8 @@ export async function publishDubheFramework(
550
374
 
551
375
  let version = 1;
552
376
  let packageId = '';
553
- let schemaId = '';
554
- let schemas: Record<string, string> = {};
377
+ let dappHub = '';
378
+ let components = {};
555
379
  let upgradeCapId = '';
556
380
 
557
381
  result.objectChanges!.map((object: ObjectChange) => {
@@ -565,14 +389,20 @@ export async function publishDubheFramework(
565
389
  ) {
566
390
  upgradeCapId = object.objectId || '';
567
391
  }
392
+ if (
393
+ object.type === 'created' &&
394
+ object.objectType &&
395
+ object.objectType.includes('dapp_hub::DappHub')
396
+ ) {
397
+ dappHub = object.objectId || '';
398
+ }
568
399
  });
569
400
 
570
401
  await delay(3000);
571
-
572
402
  const deployHookTx = new Transaction();
573
403
  deployHookTx.moveCall({
574
404
  target: `${packageId}::dubhe_genesis::run`,
575
- arguments: [deployHookTx.object('0x6')]
405
+ arguments: [deployHookTx.object(dappHub), deployHookTx.object('0x6')]
576
406
  });
577
407
 
578
408
  let deployHookResult;
@@ -584,22 +414,14 @@ export async function publishDubheFramework(
584
414
  process.exit(1);
585
415
  }
586
416
 
587
- if (deployHookResult.effects?.status.status === 'success') {
588
- deployHookResult.objectChanges?.map((object: ObjectChange) => {
589
- if (
590
- object.type === 'created' &&
591
- object.objectType &&
592
- object.objectType.includes('dubhe_schema::Schema')
593
- ) {
594
- schemaId = object.objectId || '';
595
- }
596
- });
417
+ if (deployHookResult.effects?.status.status !== 'success') {
418
+ throw new Error('Deploy hook execution failed');
597
419
  }
598
420
 
599
- saveContractData('dubhe-framework', network, packageId, schemaId, upgradeCapId, version, schemas);
421
+ await updateMoveTomlAddress(projectPath, packageId);
422
+ await saveContractData('dubhe', network, packageId, dappHub, upgradeCapId, version, components);
600
423
 
601
424
  updateEnvFile(`${projectPath}/Move.lock`, network, 'publish', chainId, packageId);
602
- await delay(1000);
603
425
  }
604
426
 
605
427
  export async function publishHandler(
@@ -613,12 +435,15 @@ export async function publishHandler(
613
435
  network
614
436
  });
615
437
 
616
- if (network === 'localnet') {
438
+ const path = process.cwd();
439
+ const projectPath = `${path}/src/${dubheConfig.name}`;
440
+
441
+ if (network === 'localnet' && dubheConfig.name !== 'dubhe') {
617
442
  await publishDubheFramework(dubhe, network);
618
443
  }
619
444
 
620
- const path = process.cwd();
621
- const projectPath = `${path}/contracts/${dubheConfig.name}`;
622
- await updateDubheDependency(`${projectPath}/Move.toml`, network);
445
+ if (dubheConfig.name !== 'dubhe') {
446
+ await updateDubheDependency(`${projectPath}/Move.toml`, network);
447
+ }
623
448
  await publishContract(dubhe, dubheConfig, network, projectPath, gasBudget);
624
449
  }