@0xobelisk/sui-cli 1.2.0-pre.21 → 1.2.0-pre.24

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,8 +222,8 @@ 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
 
372
229
  let printObjects: any[] = [];
@@ -384,6 +241,13 @@ async function publishContract(
384
241
  console.log(` ├─ Upgrade Cap: ${object.objectId}`);
385
242
  upgradeCapId = object.objectId || '';
386
243
  }
244
+ if (
245
+ object.type === 'created' &&
246
+ object.objectType &&
247
+ object.objectType.includes('dapp_hub::DappHub')
248
+ ) {
249
+ dappHub = object.objectId || '';
250
+ }
387
251
  if (object.type === 'created') {
388
252
  printObjects.push(object);
389
253
  }
@@ -398,13 +262,11 @@ async function publishContract(
398
262
 
399
263
  const deployHookTx = new Transaction();
400
264
  let args = [];
401
- if (dubheConfig.name !== 'dubhe') {
402
- let dubheSchemaId = await getDubheSchemaId(network);
403
- args.push(deployHookTx.object(dubheSchemaId));
404
- }
265
+ let dubheDappHub = dubheConfig.name === 'dubhe' ? dappHub : await getDubheDappHub(network);
266
+ args.push(deployHookTx.object(dubheDappHub));
405
267
  args.push(deployHookTx.object('0x6'));
406
268
  deployHookTx.moveCall({
407
- target: `${packageId}::${dubheConfig.name}_genesis::run`,
269
+ target: `${packageId}::genesis::run`,
408
270
  arguments: args
409
271
  });
410
272
 
@@ -422,38 +284,28 @@ async function publishContract(
422
284
  console.log(` ├─ Transaction: ${deployHookResult.digest}`);
423
285
 
424
286
  console.log('\n📋 Created Objects:');
425
- deployHookResult.objectChanges?.map((object: ObjectChange) => {
426
- if (
427
- object.type === 'created' &&
428
- object.objectType &&
429
- object.objectType.includes('schema::Schema')
430
- ) {
431
- schemaId = object.objectId || '';
432
- }
433
- if (
434
- object.type === 'created' &&
435
- object.objectType &&
436
- object.objectType.includes('schema') &&
437
- !object.objectType.includes('dynamic_field')
438
- ) {
439
- printObjects.push(object);
440
- }
441
- });
442
-
443
287
  printObjects.map((object: ObjectChange) => {
444
288
  console.log(` ├─ Type: ${object.objectType}`);
445
289
  console.log(` └─ ID: ${object.objectId}`);
446
290
  });
447
291
 
448
- saveContractData(
292
+ await saveContractData(
449
293
  dubheConfig.name,
450
294
  network,
451
295
  packageId,
452
- schemaId,
296
+ dappHub,
453
297
  upgradeCapId,
454
298
  version,
455
- schemas
299
+ components
456
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
+
457
309
  console.log('\n✅ Contract Publication Complete\n');
458
310
  } else {
459
311
  console.log(chalk.yellow(' └─ Deploy hook execution failed'));
@@ -475,9 +327,7 @@ async function checkDubheFramework(projectPath: string): Promise<boolean> {
475
327
  ' │ 2. Clone repository: git clone https://github.com/0xobelisk/dubhe contracts/dubhe'
476
328
  )
477
329
  );
478
- console.log(
479
- chalk.yellow(' │ 3. Or download from: https://github.com/0xobelisk/dubhe')
480
- );
330
+ console.log(chalk.yellow(' │ 3. Or download from: https://github.com/0xobelisk/dubhe'));
481
331
  console.log(chalk.yellow(' └─ After setup, restart the local node'));
482
332
  return false;
483
333
  }
@@ -501,57 +351,22 @@ export async function publishDubheFramework(
501
351
  const chainId = await waitForNode(dubhe);
502
352
 
503
353
  await removeEnvContent(`${projectPath}/Move.lock`, network);
354
+ await updateMoveTomlAddress(projectPath, "0x0");
355
+
504
356
  const [modules, dependencies] = buildContract(projectPath);
505
357
  const tx = new Transaction();
506
358
  const [upgradeCap] = tx.publish({ modules, dependencies });
507
359
  tx.transferObjects([upgradeCap], dubhe.getAddress());
508
360
 
509
- let result: any = null;
510
- let retryCount = 0;
511
- let spinnerIndex = 0;
512
- const startTime = Date.now();
513
- let isInterrupted = false;
514
-
515
- const handleInterrupt = () => {
516
- isInterrupted = true;
517
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
518
- console.log('\n └─ Operation cancelled by user');
519
- process.exit(0);
520
- };
521
- process.on('SIGINT', handleInterrupt);
522
-
361
+ let result;
523
362
  try {
524
- while (retryCount < MAX_RETRIES && !result && !isInterrupted) {
525
- try {
526
- result = await dubhe.signAndSendTxn({ tx });
527
- } catch (error) {
528
- if (isInterrupted) break;
529
-
530
- retryCount++;
531
- if (retryCount === MAX_RETRIES) {
532
- console.log(chalk.red(` └─ Publication failed after ${MAX_RETRIES} attempts`));
533
- console.log(chalk.red(' └─ Please check your network connection and try again later.'));
534
- process.exit(1);
535
- }
536
-
537
- const elapsedTime = Math.floor((Date.now() - startTime) / 1000);
538
- const spinner = SPINNER[spinnerIndex % SPINNER.length];
539
- spinnerIndex++;
540
-
541
- process.stdout.write(`\r ├─ ${spinner} Retrying... (${elapsedTime}s)`);
542
- await new Promise((resolve) => setTimeout(resolve, RETRY_INTERVAL));
543
- }
544
- }
545
- } finally {
546
- process.removeListener('SIGINT', handleInterrupt);
547
- }
548
-
549
- if (isInterrupted) {
550
- 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);
551
368
  }
552
369
 
553
- process.stdout.write('\r' + ' '.repeat(50) + '\r');
554
-
555
370
  if (!result || result.effects?.status.status === 'failure') {
556
371
  console.log(chalk.red(' └─ Publication failed'));
557
372
  process.exit(1);
@@ -559,8 +374,8 @@ export async function publishDubheFramework(
559
374
 
560
375
  let version = 1;
561
376
  let packageId = '';
562
- let schemaId = '';
563
- let schemas: Record<string, string> = {};
377
+ let dappHub = '';
378
+ let components = {};
564
379
  let upgradeCapId = '';
565
380
 
566
381
  result.objectChanges!.map((object: ObjectChange) => {
@@ -574,14 +389,20 @@ export async function publishDubheFramework(
574
389
  ) {
575
390
  upgradeCapId = object.objectId || '';
576
391
  }
392
+ if (
393
+ object.type === 'created' &&
394
+ object.objectType &&
395
+ object.objectType.includes('dapp_hub::DappHub')
396
+ ) {
397
+ dappHub = object.objectId || '';
398
+ }
577
399
  });
578
400
 
579
401
  await delay(3000);
580
-
581
402
  const deployHookTx = new Transaction();
582
403
  deployHookTx.moveCall({
583
404
  target: `${packageId}::dubhe_genesis::run`,
584
- arguments: [deployHookTx.object('0x6')]
405
+ arguments: [deployHookTx.object(dappHub), deployHookTx.object('0x6')]
585
406
  });
586
407
 
587
408
  let deployHookResult;
@@ -593,22 +414,14 @@ export async function publishDubheFramework(
593
414
  process.exit(1);
594
415
  }
595
416
 
596
- if (deployHookResult.effects?.status.status === 'success') {
597
- deployHookResult.objectChanges?.map((object: ObjectChange) => {
598
- if (
599
- object.type === 'created' &&
600
- object.objectType &&
601
- object.objectType.includes('dubhe_schema::Schema')
602
- ) {
603
- schemaId = object.objectId || '';
604
- }
605
- });
417
+ if (deployHookResult.effects?.status.status !== 'success') {
418
+ throw new Error('Deploy hook execution failed');
606
419
  }
607
420
 
608
- saveContractData('dubhe', network, packageId, schemaId, upgradeCapId, version, schemas);
421
+ await updateMoveTomlAddress(projectPath, packageId);
422
+ await saveContractData('dubhe', network, packageId, dappHub, upgradeCapId, version, components);
609
423
 
610
424
  updateEnvFile(`${projectPath}/Move.lock`, network, 'publish', chainId, packageId);
611
- await delay(1000);
612
425
  }
613
426
 
614
427
  export async function publishHandler(
@@ -622,12 +435,15 @@ export async function publishHandler(
622
435
  network
623
436
  });
624
437
 
625
- if (network === 'localnet') {
438
+ const path = process.cwd();
439
+ const projectPath = `${path}/src/${dubheConfig.name}`;
440
+
441
+ if (network === 'localnet' && dubheConfig.name !== 'dubhe') {
626
442
  await publishDubheFramework(dubhe, network);
627
443
  }
628
444
 
629
- const path = process.cwd();
630
- const projectPath = `${path}/src/${dubheConfig.name}`;
631
- await updateDubheDependency(`${projectPath}/Move.toml`, network);
445
+ if (dubheConfig.name !== 'dubhe') {
446
+ await updateDubheDependency(`${projectPath}/Move.toml`, network);
447
+ }
632
448
  await publishContract(dubhe, dubheConfig, network, projectPath, gasBudget);
633
449
  }