@offckb/cli 0.4.8 → 0.4.9-canary-807f2ef.0
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.
- package/README.md +79 -16
- package/build/index.js +2473 -301
- package/package.json +2 -2
package/build/index.js
CHANGED
|
@@ -235,16 +235,23 @@ exports.defaultSettings = {
|
|
|
235
235
|
transactionsPath: path.resolve(exports.dataPath, 'mainnet/transactions'),
|
|
236
236
|
},
|
|
237
237
|
tools: {
|
|
238
|
+
rootFolder: path.resolve(exports.dataPath, 'tools'),
|
|
238
239
|
ckbDebugger: {
|
|
239
240
|
minVersion: '0.200.0',
|
|
240
241
|
},
|
|
242
|
+
ckbTui: {
|
|
243
|
+
version: 'v0.1.3',
|
|
244
|
+
},
|
|
241
245
|
},
|
|
242
246
|
};
|
|
243
247
|
function readSettings() {
|
|
244
248
|
try {
|
|
245
249
|
if (fs.existsSync(exports.configPath)) {
|
|
246
250
|
const data = fs.readFileSync(exports.configPath, 'utf8');
|
|
247
|
-
|
|
251
|
+
const parsed = JSON.parse(data);
|
|
252
|
+
validateSettings(parsed);
|
|
253
|
+
// Deep-clone defaults before merging to prevent mutation of the shared default
|
|
254
|
+
return deepMerge(deepClone(exports.defaultSettings), parsed);
|
|
248
255
|
}
|
|
249
256
|
else {
|
|
250
257
|
return exports.defaultSettings;
|
|
@@ -274,10 +281,26 @@ function getCKBBinaryPath(version) {
|
|
|
274
281
|
const binaryName = platform === 'win32' ? 'ckb.exe' : 'ckb';
|
|
275
282
|
return path.join(getCKBBinaryInstallPath(version), binaryName);
|
|
276
283
|
}
|
|
284
|
+
function deepClone(obj) {
|
|
285
|
+
if (obj === null || typeof obj !== 'object') {
|
|
286
|
+
return obj;
|
|
287
|
+
}
|
|
288
|
+
if (Array.isArray(obj)) {
|
|
289
|
+
return obj.map(deepClone);
|
|
290
|
+
}
|
|
291
|
+
const clone = {};
|
|
292
|
+
for (const key in obj) {
|
|
293
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
294
|
+
clone[key] = deepClone(obj[key]);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return clone;
|
|
298
|
+
}
|
|
299
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
277
300
|
function deepMerge(target, source) {
|
|
278
301
|
for (const key in source) {
|
|
279
|
-
if (source[key] && typeof source[key] === 'object') {
|
|
280
|
-
if (!target[key]) {
|
|
302
|
+
if (source[key] !== null && typeof source[key] === 'object' && !Array.isArray(source[key])) {
|
|
303
|
+
if (!target[key] || typeof target[key] !== 'object') {
|
|
281
304
|
target[key] = {};
|
|
282
305
|
}
|
|
283
306
|
deepMerge(target[key], source[key]);
|
|
@@ -288,6 +311,29 @@ function deepMerge(target, source) {
|
|
|
288
311
|
}
|
|
289
312
|
return target;
|
|
290
313
|
}
|
|
314
|
+
function validateSettings(raw) {
|
|
315
|
+
if (!raw || typeof raw !== 'object') {
|
|
316
|
+
throw new Error('Settings must be a JSON object');
|
|
317
|
+
}
|
|
318
|
+
const obj = raw;
|
|
319
|
+
if (obj.tools && typeof obj.tools === 'object') {
|
|
320
|
+
const tools = obj.tools;
|
|
321
|
+
if (tools.rootFolder !== undefined && typeof tools.rootFolder !== 'string') {
|
|
322
|
+
throw new Error('tools.rootFolder must be a string path');
|
|
323
|
+
}
|
|
324
|
+
if (tools.ckbTui && typeof tools.ckbTui === 'object') {
|
|
325
|
+
const ckbTui = tools.ckbTui;
|
|
326
|
+
if (ckbTui.version !== undefined && typeof ckbTui.version !== 'string') {
|
|
327
|
+
throw new Error('tools.ckbTui.version must be a string');
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
if (obj.proxy !== undefined && obj.proxy !== null) {
|
|
332
|
+
if (typeof obj.proxy !== 'object') {
|
|
333
|
+
throw new Error('proxy must be an object');
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
291
337
|
|
|
292
338
|
|
|
293
339
|
/***/ }),
|
|
@@ -316,29 +362,45 @@ const deposit_1 = __nccwpck_require__(48598);
|
|
|
316
362
|
const deploy_1 = __nccwpck_require__(79617);
|
|
317
363
|
const transfer_1 = __nccwpck_require__(40265);
|
|
318
364
|
const balance_1 = __nccwpck_require__(77640);
|
|
365
|
+
const udt_1 = __nccwpck_require__(50703);
|
|
319
366
|
const create_1 = __nccwpck_require__(51534);
|
|
320
367
|
const config_1 = __nccwpck_require__(93004);
|
|
321
368
|
const devnet_config_1 = __nccwpck_require__(10015);
|
|
369
|
+
const devnet_fork_1 = __nccwpck_require__(36709);
|
|
322
370
|
const debug_1 = __nccwpck_require__(39591);
|
|
323
371
|
const system_scripts_1 = __nccwpck_require__(86198);
|
|
324
372
|
const transfer_all_1 = __nccwpck_require__(92039);
|
|
325
373
|
const gen_1 = __nccwpck_require__(750);
|
|
326
374
|
const ckb_debugger_1 = __nccwpck_require__(14815);
|
|
327
375
|
const logger_1 = __nccwpck_require__(65370);
|
|
376
|
+
const status_1 = __nccwpck_require__(71420);
|
|
377
|
+
const validator_1 = __nccwpck_require__(39534);
|
|
328
378
|
const version = (__nccwpck_require__(8330)/* .version */ .rE);
|
|
329
379
|
const description = (__nccwpck_require__(8330)/* .description */ .h_);
|
|
330
380
|
// fix windows terminal encoding of simplified chinese text
|
|
331
381
|
(0, encoding_1.setUTF8EncodingForWindows)();
|
|
332
382
|
const program = new commander_1.Command();
|
|
333
383
|
program.name('offckb').description(description).version(version).enablePositionalOptions();
|
|
334
|
-
program
|
|
384
|
+
program.option('--json', 'Output logs in JSON format for agent/programmatic consumption');
|
|
385
|
+
program.hook('preAction', (thisCommand) => {
|
|
386
|
+
const opts = thisCommand.opts();
|
|
387
|
+
if (opts.json) {
|
|
388
|
+
logger_1.logger.setJsonMode(true);
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
const nodeCommand = program
|
|
335
392
|
.command('node [CKB-Version]')
|
|
336
393
|
.description('Use the CKB to start devnet')
|
|
337
394
|
.option('--network <network>', 'Specify the network to deploy to', 'devnet')
|
|
338
395
|
.option('-b, --binary-path <binaryPath>', 'Specify the CKB binary path to use, only for devnet, when set, will ignore version and network')
|
|
396
|
+
.option('--daemon', 'Run the node in the background as a daemon (devnet only)')
|
|
339
397
|
.action((version, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
340
|
-
return (0, node_1.startNode)({ version, network: options.network, binaryPath: options.binaryPath });
|
|
398
|
+
return (0, node_1.startNode)({ version, network: options.network, binaryPath: options.binaryPath, daemon: options.daemon });
|
|
341
399
|
}));
|
|
400
|
+
nodeCommand
|
|
401
|
+
.command('stop')
|
|
402
|
+
.description('Stop the running CKB devnet daemon')
|
|
403
|
+
.action(() => __awaiter(void 0, void 0, void 0, function* () { return (0, node_1.stopNode)(); }));
|
|
342
404
|
program
|
|
343
405
|
.command('create [project-name]')
|
|
344
406
|
.description('Create a new CKB Smart Contract project in JavaScript.')
|
|
@@ -412,13 +474,15 @@ program
|
|
|
412
474
|
return (0, deposit_1.deposit)(toAddress, amountInCKB, options);
|
|
413
475
|
}));
|
|
414
476
|
program
|
|
415
|
-
.command('transfer [toAddress] [
|
|
416
|
-
.description('Transfer CKB tokens to address, only devnet and testnet')
|
|
477
|
+
.command('transfer [toAddress] [amount]')
|
|
478
|
+
.description('Transfer CKB or UDT tokens to address, only devnet and testnet')
|
|
417
479
|
.option('--network <network>', 'Specify the network to transfer to', 'devnet')
|
|
418
|
-
.option('--privkey <privkey>', 'Specify the private key to transfer
|
|
480
|
+
.option('--privkey <privkey>', 'Specify the private key to transfer')
|
|
481
|
+
.addOption(new commander_1.Option('--udt-kind <kind>', 'Specify the UDT kind').choices(['sudt', 'xudt']).default('sudt'))
|
|
482
|
+
.option('--udt-type-args <typeArgs>', 'Specify the UDT type script args to transfer UDT')
|
|
419
483
|
.option('-r, --proxy-rpc', 'Use Proxy RPC to connect to blockchain')
|
|
420
|
-
.action((toAddress,
|
|
421
|
-
return (0, transfer_1.transfer)(toAddress,
|
|
484
|
+
.action((toAddress, amount, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
485
|
+
return (0, transfer_1.transfer)(toAddress, amount, options);
|
|
422
486
|
}));
|
|
423
487
|
program
|
|
424
488
|
.command('transfer-all [toAddress]')
|
|
@@ -431,11 +495,36 @@ program
|
|
|
431
495
|
}));
|
|
432
496
|
program
|
|
433
497
|
.command('balance [toAddress]')
|
|
434
|
-
.description('Check account balance, only devnet and testnet')
|
|
498
|
+
.description('Check account balance (CKB + detected SUDT/xUDT), only devnet and testnet')
|
|
435
499
|
.option('--network <network>', 'Specify the network to check', 'devnet')
|
|
500
|
+
.addOption(new commander_1.Option('--udt-kind <kind>', 'Filter by UDT kind').choices(['sudt', 'xudt']))
|
|
501
|
+
.option('--udt-type-args <typeArgs>', 'Filter by UDT type script args')
|
|
502
|
+
.option('--no-udt', 'Skip UDT balance scan')
|
|
436
503
|
.action((toAddress, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
437
504
|
return (0, balance_1.balanceOf)(toAddress, options);
|
|
438
505
|
}));
|
|
506
|
+
const udtCommand = program.command('udt').description('UDT token commands');
|
|
507
|
+
udtCommand
|
|
508
|
+
.command('issue <amount>')
|
|
509
|
+
.description('Issue new UDT tokens, only devnet and testnet')
|
|
510
|
+
.option('--network <network>', 'Specify the network', 'devnet')
|
|
511
|
+
.addOption(new commander_1.Option('--udt-kind <kind>', 'Specify the UDT kind').choices(['sudt', 'xudt']).default('sudt'))
|
|
512
|
+
.option('--type-args <typeArgs>', 'Specify the UDT type script args (xudt only; defaults to signer lock hash)')
|
|
513
|
+
.option('--to <toAddress>', 'Specify the receiver address (defaults to signer)')
|
|
514
|
+
.option('--privkey <privkey>', 'Specify the private key to issue UDT')
|
|
515
|
+
.action((amount, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
516
|
+
return (0, udt_1.udtIssue)(amount, options);
|
|
517
|
+
}));
|
|
518
|
+
udtCommand
|
|
519
|
+
.command('destroy <amount>')
|
|
520
|
+
.description('Destroy UDT tokens, only devnet and testnet')
|
|
521
|
+
.option('--network <network>', 'Specify the network', 'devnet')
|
|
522
|
+
.addOption(new commander_1.Option('--udt-kind <kind>', 'Specify the UDT kind').choices(['sudt', 'xudt']).default('sudt'))
|
|
523
|
+
.requiredOption('--type-args <typeArgs>', 'Specify the UDT type script args')
|
|
524
|
+
.option('--privkey <privkey>', 'Specify the private key to destroy UDT')
|
|
525
|
+
.action((amount, options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
526
|
+
return (0, udt_1.udtDestroy)(amount, options);
|
|
527
|
+
}));
|
|
439
528
|
program
|
|
440
529
|
.command('debugger')
|
|
441
530
|
.description('Port of the raw CKB Standalone Debugger')
|
|
@@ -445,6 +534,14 @@ program
|
|
|
445
534
|
.action(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
446
535
|
return ckb_debugger_1.CKBDebugger.runWithArgs(process.argv.slice(2));
|
|
447
536
|
}));
|
|
537
|
+
program
|
|
538
|
+
.command('status')
|
|
539
|
+
.description('Show ckb-tui status interface')
|
|
540
|
+
.option('--network <network>', 'Specify the network whose node status to monitor', 'devnet')
|
|
541
|
+
.action((option) => __awaiter(void 0, void 0, void 0, function* () {
|
|
542
|
+
(0, validator_1.validateNetworkOpt)(option.network);
|
|
543
|
+
return yield (0, status_1.status)({ network: option.network });
|
|
544
|
+
}));
|
|
448
545
|
program
|
|
449
546
|
.command('config <action> [item] [value]')
|
|
450
547
|
.description('do a configuration action')
|
|
@@ -455,6 +552,14 @@ devnetCommand
|
|
|
455
552
|
.description('Open a full-screen editor to tweak devnet config files')
|
|
456
553
|
.option('-s, --set <key=value>', 'Set a devnet config field non-interactively (repeatable), e.g. --set ckb.logger.filter=info', (value, previous = []) => [...previous, value], [])
|
|
457
554
|
.action(devnet_config_1.devnetConfig);
|
|
555
|
+
devnetCommand
|
|
556
|
+
.command('fork')
|
|
557
|
+
.description('Fork an existing mainnet/testnet chain data directory into the local devnet')
|
|
558
|
+
.requiredOption('--from <dir>', 'Path to the source CKB node directory (the one passed to ckb -C)')
|
|
559
|
+
.option('--source <source>', 'Source chain: mainnet or testnet (auto-detected from the source ckb.toml when omitted)')
|
|
560
|
+
.option('--spec-file <path>', 'Use a local chain spec file instead of downloading it')
|
|
561
|
+
.option('--force', 'Replace the existing devnet (or a previous fork)')
|
|
562
|
+
.action(devnet_fork_1.devnetFork);
|
|
458
563
|
program.parse(process.argv);
|
|
459
564
|
// If no command is specified, display help
|
|
460
565
|
if (!process.argv.slice(2).length) {
|
|
@@ -534,11 +639,31 @@ function balanceOf(address_1) {
|
|
|
534
639
|
const network = opt.network;
|
|
535
640
|
(0, validator_1.validateNetworkOpt)(network);
|
|
536
641
|
const ckb = new ckb_1.CKB({ network });
|
|
537
|
-
const balanceInCKB = yield
|
|
538
|
-
|
|
642
|
+
const [balanceInCKB, udtBalances] = yield Promise.all([
|
|
643
|
+
ckb.balance(address),
|
|
644
|
+
opt.udt !== false ? ckb.detectUdtBalances(address) : Promise.resolve([]),
|
|
645
|
+
]);
|
|
646
|
+
logger_1.logger.info(`CKB: ${balanceInCKB}`);
|
|
647
|
+
const filtered = filterUdtBalances(udtBalances, opt);
|
|
648
|
+
if (filtered.length > 0) {
|
|
649
|
+
logger_1.logger.info('UDT:');
|
|
650
|
+
for (const udt of filtered) {
|
|
651
|
+
logger_1.logger.info(` ${udt.kind} (args=${udt.args}): ${udt.balance}`);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
539
654
|
process.exit(0);
|
|
540
655
|
});
|
|
541
656
|
}
|
|
657
|
+
function filterUdtBalances(balances, opt) {
|
|
658
|
+
if (!opt.udtKind && !opt.udtTypeArgs) {
|
|
659
|
+
return balances;
|
|
660
|
+
}
|
|
661
|
+
return balances.filter((udt) => {
|
|
662
|
+
const kindMatch = opt.udtKind ? udt.kind === opt.udtKind : true;
|
|
663
|
+
const argsMatch = opt.udtTypeArgs ? udt.args === opt.udtTypeArgs : true;
|
|
664
|
+
return kindMatch && argsMatch;
|
|
665
|
+
});
|
|
666
|
+
}
|
|
542
667
|
|
|
543
668
|
|
|
544
669
|
/***/ }),
|
|
@@ -973,6 +1098,7 @@ const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
|
973
1098
|
const advanced_1 = __nccwpck_require__(98486);
|
|
974
1099
|
const base_1 = __nccwpck_require__(69951);
|
|
975
1100
|
const encoding_1 = __nccwpck_require__(6851);
|
|
1101
|
+
const json_rpc_1 = __nccwpck_require__(51726);
|
|
976
1102
|
const logger_1 = __nccwpck_require__(65370);
|
|
977
1103
|
function debugTransaction(txHash, network) {
|
|
978
1104
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -1043,8 +1169,8 @@ function buildTxFileOptionBy(txHash, network) {
|
|
|
1043
1169
|
if (!fs_1.default.existsSync(outputFilePath)) {
|
|
1044
1170
|
const rpc = settings[network].rpcUrl;
|
|
1045
1171
|
const txJsonFilePath = buildTransactionJsonFilePath(network, txHash);
|
|
1046
|
-
if (!fs_1.default.existsSync(
|
|
1047
|
-
|
|
1172
|
+
if (!fs_1.default.existsSync(txJsonFilePath)) {
|
|
1173
|
+
yield fetchTransactionIntoCache(rpc, txHash, txJsonFilePath);
|
|
1048
1174
|
}
|
|
1049
1175
|
yield (0, ckb_tx_dumper_1.dumpTransaction)({ rpc, txJsonFilePath, outputFilePath });
|
|
1050
1176
|
}
|
|
@@ -1052,6 +1178,23 @@ function buildTxFileOptionBy(txHash, network) {
|
|
|
1052
1178
|
return opt;
|
|
1053
1179
|
});
|
|
1054
1180
|
}
|
|
1181
|
+
// Fallback for transactions that never went through the local RPC proxy
|
|
1182
|
+
// (e.g. historical transactions on a forked devnet): pull the transaction
|
|
1183
|
+
// from the node and cache it in the same JSON-RPC format the proxy stores.
|
|
1184
|
+
function fetchTransactionIntoCache(rpc, txHash, txJsonFilePath) {
|
|
1185
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1186
|
+
logger_1.logger.info(`Transaction ${txHash} not found in local cache, fetching from ${rpc} ..`);
|
|
1187
|
+
const result = yield (0, json_rpc_1.callJsonRpc)(rpc, 'get_transaction', [txHash]).catch((error) => {
|
|
1188
|
+
throw new Error(`Failed to fetch transaction ${txHash} from ${rpc}: ${error.message}`);
|
|
1189
|
+
});
|
|
1190
|
+
if (!(result === null || result === void 0 ? void 0 : result.transaction)) {
|
|
1191
|
+
throw new Error(`Transaction ${txHash} not found on ${rpc}. ` +
|
|
1192
|
+
`Check the hash and the --network option, or send the transaction through the offckb RPC proxy first.`);
|
|
1193
|
+
}
|
|
1194
|
+
fs_1.default.mkdirSync(path_1.default.dirname(txJsonFilePath), { recursive: true });
|
|
1195
|
+
fs_1.default.writeFileSync(txJsonFilePath, JSON.stringify(result.transaction, null, 2));
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1055
1198
|
function buildTransactionJsonFilePath(network, txHash) {
|
|
1056
1199
|
const settings = (0, setting_1.readSettings)();
|
|
1057
1200
|
if (network === base_1.Network.devnet) {
|
|
@@ -1393,6 +1536,43 @@ function devnetConfig() {
|
|
|
1393
1536
|
}
|
|
1394
1537
|
|
|
1395
1538
|
|
|
1539
|
+
/***/ }),
|
|
1540
|
+
|
|
1541
|
+
/***/ 36709:
|
|
1542
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
1543
|
+
|
|
1544
|
+
"use strict";
|
|
1545
|
+
|
|
1546
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
1547
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1548
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
1549
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
1550
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
1551
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
1552
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
1553
|
+
});
|
|
1554
|
+
};
|
|
1555
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1556
|
+
exports.devnetFork = devnetFork;
|
|
1557
|
+
const fork_1 = __nccwpck_require__(77912);
|
|
1558
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
1559
|
+
function devnetFork(options) {
|
|
1560
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1561
|
+
if (options.source && options.source !== 'mainnet' && options.source !== 'testnet') {
|
|
1562
|
+
logger_1.logger.error(`Invalid --source value: ${options.source}. Expected mainnet or testnet.`);
|
|
1563
|
+
process.exit(1);
|
|
1564
|
+
}
|
|
1565
|
+
try {
|
|
1566
|
+
yield (0, fork_1.forkDevnet)(options);
|
|
1567
|
+
}
|
|
1568
|
+
catch (error) {
|
|
1569
|
+
logger_1.logger.error(error.message);
|
|
1570
|
+
process.exit(1);
|
|
1571
|
+
}
|
|
1572
|
+
});
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
|
|
1396
1576
|
/***/ }),
|
|
1397
1577
|
|
|
1398
1578
|
/***/ 998:
|
|
@@ -1400,6 +1580,39 @@ function devnetConfig() {
|
|
|
1400
1580
|
|
|
1401
1581
|
"use strict";
|
|
1402
1582
|
|
|
1583
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
1584
|
+
if (k2 === undefined) k2 = k;
|
|
1585
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
1586
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
1587
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
1588
|
+
}
|
|
1589
|
+
Object.defineProperty(o, k2, desc);
|
|
1590
|
+
}) : (function(o, m, k, k2) {
|
|
1591
|
+
if (k2 === undefined) k2 = k;
|
|
1592
|
+
o[k2] = m[k];
|
|
1593
|
+
}));
|
|
1594
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
1595
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
1596
|
+
}) : function(o, v) {
|
|
1597
|
+
o["default"] = v;
|
|
1598
|
+
});
|
|
1599
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
1600
|
+
var ownKeys = function(o) {
|
|
1601
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
1602
|
+
var ar = [];
|
|
1603
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
1604
|
+
return ar;
|
|
1605
|
+
};
|
|
1606
|
+
return ownKeys(o);
|
|
1607
|
+
};
|
|
1608
|
+
return function (mod) {
|
|
1609
|
+
if (mod && mod.__esModule) return mod;
|
|
1610
|
+
var result = {};
|
|
1611
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
1612
|
+
__setModuleDefault(result, mod);
|
|
1613
|
+
return result;
|
|
1614
|
+
};
|
|
1615
|
+
})();
|
|
1403
1616
|
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
1404
1617
|
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
1405
1618
|
return new (P || (P = Promise))(function (resolve, reject) {
|
|
@@ -1412,23 +1625,35 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
1412
1625
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
1413
1626
|
exports.startNode = startNode;
|
|
1414
1627
|
exports.nodeDevnet = nodeDevnet;
|
|
1628
|
+
exports.stopNode = stopNode;
|
|
1415
1629
|
exports.nodeTestnet = nodeTestnet;
|
|
1416
1630
|
exports.nodeMainnet = nodeMainnet;
|
|
1417
1631
|
const child_process_1 = __nccwpck_require__(35317);
|
|
1632
|
+
const fs = __importStar(__nccwpck_require__(79896));
|
|
1633
|
+
const path = __importStar(__nccwpck_require__(16928));
|
|
1418
1634
|
const init_chain_1 = __nccwpck_require__(1360);
|
|
1419
1635
|
const install_1 = __nccwpck_require__(65611);
|
|
1420
1636
|
const setting_1 = __nccwpck_require__(25546);
|
|
1421
1637
|
const encoding_1 = __nccwpck_require__(6851);
|
|
1422
1638
|
const rpc_proxy_1 = __nccwpck_require__(46589);
|
|
1639
|
+
const fork_1 = __nccwpck_require__(77912);
|
|
1640
|
+
const json_rpc_1 = __nccwpck_require__(51726);
|
|
1423
1641
|
const base_1 = __nccwpck_require__(69951);
|
|
1424
1642
|
const logger_1 = __nccwpck_require__(65370);
|
|
1425
|
-
|
|
1643
|
+
const DAEMON_LOG_DIR = 'logs';
|
|
1644
|
+
const DAEMON_LOG_FILE = 'daemon.log';
|
|
1645
|
+
const DAEMON_PID_FILE = 'daemon.pid';
|
|
1646
|
+
const DAEMON_CHILD_ENV = 'OFFCKB_DAEMON_CHILD';
|
|
1647
|
+
function startNode({ version, network = base_1.Network.devnet, binaryPath, daemon }) {
|
|
1426
1648
|
if (binaryPath && network !== base_1.Network.devnet) {
|
|
1427
1649
|
logger_1.logger.warn('Custom binaryPath is only supported for devnet. The provided binaryPath will be ignored.');
|
|
1428
1650
|
}
|
|
1651
|
+
if (daemon && network !== base_1.Network.devnet) {
|
|
1652
|
+
logger_1.logger.warn('Daemon mode is only supported for devnet. The daemon flag will be ignored.');
|
|
1653
|
+
}
|
|
1429
1654
|
switch (network) {
|
|
1430
1655
|
case base_1.Network.devnet:
|
|
1431
|
-
return nodeDevnet({ version, binaryPath });
|
|
1656
|
+
return nodeDevnet({ version, binaryPath, daemon });
|
|
1432
1657
|
case base_1.Network.testnet:
|
|
1433
1658
|
return nodeTestnet();
|
|
1434
1659
|
case base_1.Network.mainnet:
|
|
@@ -1438,8 +1663,11 @@ function startNode({ version, network = base_1.Network.devnet, binaryPath }) {
|
|
|
1438
1663
|
}
|
|
1439
1664
|
}
|
|
1440
1665
|
function nodeDevnet(_a) {
|
|
1441
|
-
return __awaiter(this, arguments, void 0, function* ({ version, binaryPath }) {
|
|
1666
|
+
return __awaiter(this, arguments, void 0, function* ({ version, binaryPath, daemon }) {
|
|
1442
1667
|
var _b, _c;
|
|
1668
|
+
if (daemon) {
|
|
1669
|
+
return startDaemon();
|
|
1670
|
+
}
|
|
1443
1671
|
const settings = (0, setting_1.readSettings)();
|
|
1444
1672
|
const ckbVersion = version || settings.bins.defaultCKBVersion;
|
|
1445
1673
|
let ckbBinPath = '';
|
|
@@ -1453,7 +1681,14 @@ function nodeDevnet(_a) {
|
|
|
1453
1681
|
}
|
|
1454
1682
|
yield (0, init_chain_1.initChainIfNeeded)();
|
|
1455
1683
|
const devnetConfigPath = (0, encoding_1.encodeBinPathForTerminal)(settings.devnet.configPath);
|
|
1456
|
-
|
|
1684
|
+
// A forked devnet must boot once with --skip-spec-check --overwrite-spec so
|
|
1685
|
+
// the imported (and patched) spec replaces the source chain's stored spec.
|
|
1686
|
+
const forkState = (0, fork_1.readForkState)(settings.devnet.configPath);
|
|
1687
|
+
const firstRunFlags = (forkState === null || forkState === void 0 ? void 0 : forkState.firstRunPending) ? ' --skip-spec-check --overwrite-spec' : '';
|
|
1688
|
+
if (forkState === null || forkState === void 0 ? void 0 : forkState.firstRunPending) {
|
|
1689
|
+
logger_1.logger.info(`Forked devnet (${forkState.source}) detected, first run uses --skip-spec-check --overwrite-spec.`);
|
|
1690
|
+
}
|
|
1691
|
+
const ckbCmd = `${ckbBinPath} run -C ${devnetConfigPath}${firstRunFlags}`;
|
|
1457
1692
|
const minerCmd = `${ckbBinPath} miner -C ${devnetConfigPath}`;
|
|
1458
1693
|
logger_1.logger.info(`Launching CKB devnet Node...`);
|
|
1459
1694
|
try {
|
|
@@ -1466,6 +1701,11 @@ function nodeDevnet(_a) {
|
|
|
1466
1701
|
(_c = ckbProcess.stderr) === null || _c === void 0 ? void 0 : _c.on('data', (data) => {
|
|
1467
1702
|
logger_1.logger.error(['CKB error:', data.toString()]);
|
|
1468
1703
|
});
|
|
1704
|
+
if (forkState === null || forkState === void 0 ? void 0 : forkState.firstRunPending) {
|
|
1705
|
+
// Only clear the flag once the spawned node is actually up and reports
|
|
1706
|
+
// the fork's genesis; if startup fails, the next run retries the flags.
|
|
1707
|
+
void clearForkFirstRunWhenNodeUp(ckbProcess, settings.devnet.rpcUrl, settings.devnet.configPath, forkState.genesisHash);
|
|
1708
|
+
}
|
|
1469
1709
|
// Start the second command after 3 seconds
|
|
1470
1710
|
setTimeout(() => __awaiter(this, void 0, void 0, function* () {
|
|
1471
1711
|
var _a, _b;
|
|
@@ -1494,6 +1734,354 @@ function nodeDevnet(_a) {
|
|
|
1494
1734
|
}
|
|
1495
1735
|
});
|
|
1496
1736
|
}
|
|
1737
|
+
function resolveDaemonPaths() {
|
|
1738
|
+
const settings = (0, setting_1.readSettings)();
|
|
1739
|
+
const logDir = path.join(settings.devnet.dataPath, DAEMON_LOG_DIR);
|
|
1740
|
+
const logFile = path.join(logDir, DAEMON_LOG_FILE);
|
|
1741
|
+
const pidFile = path.join(logDir, DAEMON_PID_FILE);
|
|
1742
|
+
return { logDir, logFile, pidFile };
|
|
1743
|
+
}
|
|
1744
|
+
// Poll the devnet RPC until the spawned node answers with the fork's genesis
|
|
1745
|
+
// hash, then mark the first run as done so subsequent `offckb node` runs boot
|
|
1746
|
+
// normally. Two guards against clearing the flag on the wrong signal:
|
|
1747
|
+
// - the poll aborts when the spawned ckb process exits (e.g. failed boot),
|
|
1748
|
+
// - an answering node is only trusted when its genesis matches the fork
|
|
1749
|
+
// state — an unrelated node occupying the port must not clear the flag.
|
|
1750
|
+
function clearForkFirstRunWhenNodeUp(ckbProcess, rpcUrl, configPath, expectedGenesisHash) {
|
|
1751
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1752
|
+
let processExited = false;
|
|
1753
|
+
const markExited = () => {
|
|
1754
|
+
processExited = true;
|
|
1755
|
+
};
|
|
1756
|
+
ckbProcess.once('exit', markExited);
|
|
1757
|
+
ckbProcess.once('error', markExited);
|
|
1758
|
+
const timeoutMs = 10 * 60 * 1000; // large forks take a while to boot
|
|
1759
|
+
const start = Date.now();
|
|
1760
|
+
while (!processExited && Date.now() - start < timeoutMs) {
|
|
1761
|
+
try {
|
|
1762
|
+
const genesisHash = String(yield (0, json_rpc_1.callJsonRpc)(rpcUrl, 'get_block_hash', ['0x0'], 5000)).toLowerCase();
|
|
1763
|
+
if (genesisHash !== expectedGenesisHash.toLowerCase()) {
|
|
1764
|
+
logger_1.logger.warn(`A node is answering at ${rpcUrl} but reports a different genesis (${genesisHash}); ` +
|
|
1765
|
+
'leaving the first-run flags in place.');
|
|
1766
|
+
return;
|
|
1767
|
+
}
|
|
1768
|
+
(0, fork_1.markForkFirstRunComplete)(configPath);
|
|
1769
|
+
logger_1.logger.success('Forked devnet is up; first-run spec flags cleared.');
|
|
1770
|
+
return;
|
|
1771
|
+
}
|
|
1772
|
+
catch (_a) {
|
|
1773
|
+
yield new Promise((resolve) => setTimeout(resolve, 1000));
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
if (processExited) {
|
|
1777
|
+
logger_1.logger.warn('The CKB process exited before the forked devnet came up; first-run flags will be retried next time.');
|
|
1778
|
+
}
|
|
1779
|
+
else {
|
|
1780
|
+
logger_1.logger.warn('Timed out waiting for the forked devnet to start; first-run flags will be retried next time.');
|
|
1781
|
+
}
|
|
1782
|
+
});
|
|
1783
|
+
}
|
|
1784
|
+
function readPidFile(pidFile) {
|
|
1785
|
+
var _a, _b;
|
|
1786
|
+
let raw;
|
|
1787
|
+
try {
|
|
1788
|
+
raw = fs.readFileSync(pidFile, 'utf8').trim();
|
|
1789
|
+
}
|
|
1790
|
+
catch (error) {
|
|
1791
|
+
// Treat a missing or unreadable PID file as "no daemon".
|
|
1792
|
+
return null;
|
|
1793
|
+
}
|
|
1794
|
+
if (!raw) {
|
|
1795
|
+
return null;
|
|
1796
|
+
}
|
|
1797
|
+
// Backward compatibility: plain integer PID written by older versions.
|
|
1798
|
+
const plainPid = Number(raw);
|
|
1799
|
+
if (Number.isInteger(plainPid) && plainPid > 0) {
|
|
1800
|
+
return { pid: plainPid, scriptPath: (_a = resolveCliEntry()) !== null && _a !== void 0 ? _a : '', startedAt: new Date(0).toISOString() };
|
|
1801
|
+
}
|
|
1802
|
+
try {
|
|
1803
|
+
const parsed = JSON.parse(raw);
|
|
1804
|
+
const pid = Number(parsed.pid);
|
|
1805
|
+
if (Number.isInteger(pid) && pid > 0 && typeof parsed.scriptPath === 'string') {
|
|
1806
|
+
return {
|
|
1807
|
+
pid,
|
|
1808
|
+
scriptPath: parsed.scriptPath,
|
|
1809
|
+
startedAt: (_b = parsed.startedAt) !== null && _b !== void 0 ? _b : new Date(0).toISOString(),
|
|
1810
|
+
};
|
|
1811
|
+
}
|
|
1812
|
+
}
|
|
1813
|
+
catch (_c) {
|
|
1814
|
+
// fall through to sentinel below
|
|
1815
|
+
}
|
|
1816
|
+
// Content exists but is neither a valid plain PID nor valid metadata.
|
|
1817
|
+
// Return a sentinel so stopNode can report an invalid PID and clean up.
|
|
1818
|
+
return { pid: NaN, scriptPath: '', startedAt: new Date(0).toISOString() };
|
|
1819
|
+
}
|
|
1820
|
+
function writePidFile(pidFile, metadata) {
|
|
1821
|
+
fs.writeFileSync(pidFile, JSON.stringify(metadata, null, 2));
|
|
1822
|
+
}
|
|
1823
|
+
function resolveCliEntry() {
|
|
1824
|
+
var _a;
|
|
1825
|
+
// In priority order. process.argv[1] is the most reliable for a Node CLI.
|
|
1826
|
+
// OFFCKB_CLI_PATH is an escape hatch for packaged/npx/weird environments.
|
|
1827
|
+
// require.main?.filename is a final fallback when argv is unavailable.
|
|
1828
|
+
const candidates = [process.env.OFFCKB_CLI_PATH, process.argv[1], (_a = require.main) === null || _a === void 0 ? void 0 : _a.filename].filter((c) => typeof c === 'string' && c.length > 0);
|
|
1829
|
+
for (const candidate of candidates) {
|
|
1830
|
+
try {
|
|
1831
|
+
const resolved = path.resolve(candidate);
|
|
1832
|
+
const stats = fs.statSync(resolved);
|
|
1833
|
+
if (stats.isFile()) {
|
|
1834
|
+
return resolved;
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
catch (_b) {
|
|
1838
|
+
// Candidate is missing or not a file; try the next one.
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
return null;
|
|
1842
|
+
}
|
|
1843
|
+
function isProcessAlive(pid) {
|
|
1844
|
+
try {
|
|
1845
|
+
process.kill(pid, 0);
|
|
1846
|
+
return true;
|
|
1847
|
+
}
|
|
1848
|
+
catch (_a) {
|
|
1849
|
+
return false;
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1852
|
+
function cleanupPidFile(pidFile) {
|
|
1853
|
+
try {
|
|
1854
|
+
fs.unlinkSync(pidFile);
|
|
1855
|
+
}
|
|
1856
|
+
catch (error) {
|
|
1857
|
+
logger_1.logger.warn(`Failed to remove PID file ${pidFile}:`, error);
|
|
1858
|
+
}
|
|
1859
|
+
}
|
|
1860
|
+
function waitForProcessExit(pid, timeoutMs) {
|
|
1861
|
+
const start = Date.now();
|
|
1862
|
+
return new Promise((resolve) => {
|
|
1863
|
+
const check = () => {
|
|
1864
|
+
if (!isProcessAlive(pid)) {
|
|
1865
|
+
resolve(true);
|
|
1866
|
+
return;
|
|
1867
|
+
}
|
|
1868
|
+
if (Date.now() - start >= timeoutMs) {
|
|
1869
|
+
resolve(false);
|
|
1870
|
+
return;
|
|
1871
|
+
}
|
|
1872
|
+
setTimeout(check, 100);
|
|
1873
|
+
};
|
|
1874
|
+
check();
|
|
1875
|
+
});
|
|
1876
|
+
}
|
|
1877
|
+
function getProcessCommandLine(pid) {
|
|
1878
|
+
return new Promise((resolve) => {
|
|
1879
|
+
if (process.platform === 'win32') {
|
|
1880
|
+
(0, child_process_1.exec)(`wmic process where ProcessId=${pid} get CommandLine /format:list`, (error, stdout) => {
|
|
1881
|
+
if (error) {
|
|
1882
|
+
resolve(null);
|
|
1883
|
+
return;
|
|
1884
|
+
}
|
|
1885
|
+
const match = stdout.match(/CommandLine=(.+)/);
|
|
1886
|
+
resolve(match ? match[1].trim() : null);
|
|
1887
|
+
});
|
|
1888
|
+
}
|
|
1889
|
+
else {
|
|
1890
|
+
(0, child_process_1.exec)(`ps -p ${pid} -o args=`, (error, stdout) => {
|
|
1891
|
+
if (error) {
|
|
1892
|
+
resolve(null);
|
|
1893
|
+
return;
|
|
1894
|
+
}
|
|
1895
|
+
resolve(stdout.trim());
|
|
1896
|
+
});
|
|
1897
|
+
}
|
|
1898
|
+
});
|
|
1899
|
+
}
|
|
1900
|
+
function verifyDaemonIdentity(pid, metadata) {
|
|
1901
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
1902
|
+
const cmdline = yield getProcessCommandLine(pid);
|
|
1903
|
+
if (!cmdline) {
|
|
1904
|
+
return false;
|
|
1905
|
+
}
|
|
1906
|
+
// The daemon child re-runs the same CLI entry point, so its command line
|
|
1907
|
+
// should reference the same script and should be a Node process.
|
|
1908
|
+
const scriptName = path.basename(metadata.scriptPath);
|
|
1909
|
+
const scriptDir = path.dirname(metadata.scriptPath);
|
|
1910
|
+
const looksLikeNode = cmdline.includes('node') || cmdline.includes('nodejs');
|
|
1911
|
+
const looksLikeOurScript = cmdline.includes(metadata.scriptPath) || (scriptName !== '' && cmdline.includes(scriptName));
|
|
1912
|
+
const looksLikeOffckb = cmdline.includes('offckb') || scriptDir.includes('offckb');
|
|
1913
|
+
return looksLikeNode && (looksLikeOurScript || looksLikeOffckb);
|
|
1914
|
+
});
|
|
1915
|
+
}
|
|
1916
|
+
function terminateProcess(pid, signal) {
|
|
1917
|
+
return new Promise((resolve, reject) => {
|
|
1918
|
+
if (process.platform === 'win32') {
|
|
1919
|
+
// Windows has no POSIX signals and process.kill(pid) only terminates the
|
|
1920
|
+
// single process. Use taskkill to terminate the whole tree.
|
|
1921
|
+
// /T kills the process and all child processes.
|
|
1922
|
+
// /F forces termination when SIGKILL is requested.
|
|
1923
|
+
const args = signal === 'SIGKILL' ? ['/T', '/F', '/PID', String(pid)] : ['/T', '/PID', String(pid)];
|
|
1924
|
+
const taskkill = (0, child_process_1.spawn)('taskkill', args, { stdio: 'ignore' });
|
|
1925
|
+
taskkill.on('error', reject);
|
|
1926
|
+
taskkill.on('exit', () => {
|
|
1927
|
+
// taskkill may return non-zero if the process is already gone, which
|
|
1928
|
+
// is acceptable for our purposes.
|
|
1929
|
+
resolve();
|
|
1930
|
+
});
|
|
1931
|
+
return;
|
|
1932
|
+
}
|
|
1933
|
+
// On POSIX, detached: true makes the child a session/process group leader.
|
|
1934
|
+
// A negative pid sends the signal to the entire process group, ensuring
|
|
1935
|
+
// the CKB node, miner and RPC proxy all receive it.
|
|
1936
|
+
try {
|
|
1937
|
+
process.kill(-pid, signal);
|
|
1938
|
+
resolve();
|
|
1939
|
+
}
|
|
1940
|
+
catch (error) {
|
|
1941
|
+
reject(error);
|
|
1942
|
+
}
|
|
1943
|
+
});
|
|
1944
|
+
}
|
|
1945
|
+
function startDaemon() {
|
|
1946
|
+
const { logDir, logFile, pidFile } = resolveDaemonPaths();
|
|
1947
|
+
// Prevent duplicate daemon starts. If a daemon is already running, refuse
|
|
1948
|
+
// to overwrite its PID file.
|
|
1949
|
+
const existing = readPidFile(pidFile);
|
|
1950
|
+
if (existing && isProcessAlive(existing.pid)) {
|
|
1951
|
+
logger_1.logger.error(`A CKB devnet daemon is already running (PID ${existing.pid}). Stop it first with: offckb node stop`);
|
|
1952
|
+
return;
|
|
1953
|
+
}
|
|
1954
|
+
if (existing && !isProcessAlive(existing.pid)) {
|
|
1955
|
+
// Stale PID file from a crashed daemon; clean it up before starting anew.
|
|
1956
|
+
cleanupPidFile(pidFile);
|
|
1957
|
+
}
|
|
1958
|
+
let out;
|
|
1959
|
+
let err;
|
|
1960
|
+
try {
|
|
1961
|
+
fs.mkdirSync(logDir, { recursive: true });
|
|
1962
|
+
out = fs.openSync(logFile, 'a');
|
|
1963
|
+
err = fs.openSync(logFile, 'a');
|
|
1964
|
+
}
|
|
1965
|
+
catch (error) {
|
|
1966
|
+
logger_1.logger.error(`Failed to prepare daemon log directory or log file at ${logFile}:`, error);
|
|
1967
|
+
return;
|
|
1968
|
+
}
|
|
1969
|
+
const scriptPath = resolveCliEntry();
|
|
1970
|
+
if (!scriptPath) {
|
|
1971
|
+
logger_1.logger.error('Unable to determine the CLI entry point for daemon mode. Set OFFCKB_CLI_PATH to the offckb script.');
|
|
1972
|
+
closeFileDescriptors(out, err);
|
|
1973
|
+
return;
|
|
1974
|
+
}
|
|
1975
|
+
const childArgs = process.argv.slice(2).filter((arg) => arg !== '--daemon');
|
|
1976
|
+
const childEnv = Object.assign(Object.assign({}, process.env), { [DAEMON_CHILD_ENV]: '1' });
|
|
1977
|
+
let child;
|
|
1978
|
+
try {
|
|
1979
|
+
child = (0, child_process_1.spawn)(process.execPath, [scriptPath, ...childArgs], {
|
|
1980
|
+
detached: true,
|
|
1981
|
+
stdio: ['ignore', out, err],
|
|
1982
|
+
env: childEnv,
|
|
1983
|
+
});
|
|
1984
|
+
}
|
|
1985
|
+
catch (error) {
|
|
1986
|
+
logger_1.logger.error('Failed to spawn daemon process:', error);
|
|
1987
|
+
closeFileDescriptors(out, err);
|
|
1988
|
+
return;
|
|
1989
|
+
}
|
|
1990
|
+
if (!child.pid) {
|
|
1991
|
+
logger_1.logger.error('Failed to spawn daemon process: no PID returned.');
|
|
1992
|
+
closeFileDescriptors(out, err);
|
|
1993
|
+
return;
|
|
1994
|
+
}
|
|
1995
|
+
child.unref();
|
|
1996
|
+
child.on('error', (error) => {
|
|
1997
|
+
logger_1.logger.error('Daemon child process failed to start:', error);
|
|
1998
|
+
cleanupPidFile(pidFile);
|
|
1999
|
+
});
|
|
2000
|
+
const metadata = {
|
|
2001
|
+
pid: child.pid,
|
|
2002
|
+
scriptPath,
|
|
2003
|
+
startedAt: new Date().toISOString(),
|
|
2004
|
+
};
|
|
2005
|
+
writePidFile(pidFile, metadata);
|
|
2006
|
+
// File descriptors are now owned by the spawned child; close our copies.
|
|
2007
|
+
closeFileDescriptors(out, err);
|
|
2008
|
+
logger_1.logger.success(`CKB devnet daemon started with PID ${child.pid}.`);
|
|
2009
|
+
logger_1.logger.info(`Logs: ${logFile}`);
|
|
2010
|
+
logger_1.logger.info(`PID file: ${pidFile}`);
|
|
2011
|
+
logger_1.logger.info('Stop the daemon with: offckb node stop');
|
|
2012
|
+
}
|
|
2013
|
+
function closeFileDescriptors(...fds) {
|
|
2014
|
+
for (const fd of fds) {
|
|
2015
|
+
if (fd === undefined)
|
|
2016
|
+
continue;
|
|
2017
|
+
try {
|
|
2018
|
+
fs.closeSync(fd);
|
|
2019
|
+
}
|
|
2020
|
+
catch (_a) {
|
|
2021
|
+
// ignore
|
|
2022
|
+
}
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
function stopNode() {
|
|
2026
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2027
|
+
const { pidFile } = resolveDaemonPaths();
|
|
2028
|
+
const metadata = readPidFile(pidFile);
|
|
2029
|
+
if (!metadata) {
|
|
2030
|
+
logger_1.logger.warn(`No daemon PID file found at ${pidFile}. Is the devnet daemon running?`);
|
|
2031
|
+
return;
|
|
2032
|
+
}
|
|
2033
|
+
const pid = metadata.pid;
|
|
2034
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
2035
|
+
logger_1.logger.error(`Invalid PID in ${pidFile}: ${pid}`);
|
|
2036
|
+
cleanupPidFile(pidFile);
|
|
2037
|
+
return;
|
|
2038
|
+
}
|
|
2039
|
+
if (!isProcessAlive(pid)) {
|
|
2040
|
+
logger_1.logger.warn(`Daemon process ${pid} is not running.`);
|
|
2041
|
+
cleanupPidFile(pidFile);
|
|
2042
|
+
return;
|
|
2043
|
+
}
|
|
2044
|
+
const identityOk = yield verifyDaemonIdentity(pid, metadata);
|
|
2045
|
+
if (!identityOk) {
|
|
2046
|
+
logger_1.logger.error(`Process ${pid} does not appear to be the offckb daemon. Refusing to send signals to avoid killing an unrelated process. ` +
|
|
2047
|
+
`If you are sure this is the daemon, stop it manually and remove ${pidFile}.`);
|
|
2048
|
+
return;
|
|
2049
|
+
}
|
|
2050
|
+
logger_1.logger.info(`Stopping CKB devnet daemon (PID ${pid})...`);
|
|
2051
|
+
try {
|
|
2052
|
+
yield terminateProcess(pid, 'SIGTERM');
|
|
2053
|
+
}
|
|
2054
|
+
catch (error) {
|
|
2055
|
+
const err = error;
|
|
2056
|
+
if (err.code === 'ESRCH') {
|
|
2057
|
+
logger_1.logger.warn(`Daemon process ${pid} is not running.`);
|
|
2058
|
+
cleanupPidFile(pidFile);
|
|
2059
|
+
return;
|
|
2060
|
+
}
|
|
2061
|
+
if (err.code === 'EPERM') {
|
|
2062
|
+
logger_1.logger.error(`Permission denied when sending SIGTERM to daemon process ${pid}.`);
|
|
2063
|
+
}
|
|
2064
|
+
else {
|
|
2065
|
+
logger_1.logger.error(`Failed to send SIGTERM to daemon process ${pid}:`, error);
|
|
2066
|
+
}
|
|
2067
|
+
// Still try to clean up the PID file so the user can recover.
|
|
2068
|
+
cleanupPidFile(pidFile);
|
|
2069
|
+
return;
|
|
2070
|
+
}
|
|
2071
|
+
const exited = yield waitForProcessExit(pid, 5000);
|
|
2072
|
+
if (!exited) {
|
|
2073
|
+
logger_1.logger.warn(`Daemon process ${pid} did not exit gracefully, sending SIGKILL...`);
|
|
2074
|
+
try {
|
|
2075
|
+
yield terminateProcess(pid, 'SIGKILL');
|
|
2076
|
+
}
|
|
2077
|
+
catch (error) {
|
|
2078
|
+
logger_1.logger.error(`Failed to send SIGKILL to daemon process ${pid}:`, error);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
cleanupPidFile(pidFile);
|
|
2082
|
+
logger_1.logger.success('CKB devnet daemon stopped.');
|
|
2083
|
+
});
|
|
2084
|
+
}
|
|
1497
2085
|
function nodeTestnet() {
|
|
1498
2086
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1499
2087
|
// todo: maybe we can actually start a node for testnet later
|
|
@@ -1518,6 +2106,130 @@ function nodeMainnet() {
|
|
|
1518
2106
|
}
|
|
1519
2107
|
|
|
1520
2108
|
|
|
2109
|
+
/***/ }),
|
|
2110
|
+
|
|
2111
|
+
/***/ 71420:
|
|
2112
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
2113
|
+
|
|
2114
|
+
"use strict";
|
|
2115
|
+
|
|
2116
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
2117
|
+
if (k2 === undefined) k2 = k;
|
|
2118
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
2119
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
2120
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
2121
|
+
}
|
|
2122
|
+
Object.defineProperty(o, k2, desc);
|
|
2123
|
+
}) : (function(o, m, k, k2) {
|
|
2124
|
+
if (k2 === undefined) k2 = k;
|
|
2125
|
+
o[k2] = m[k];
|
|
2126
|
+
}));
|
|
2127
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
2128
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
2129
|
+
}) : function(o, v) {
|
|
2130
|
+
o["default"] = v;
|
|
2131
|
+
});
|
|
2132
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
2133
|
+
var ownKeys = function(o) {
|
|
2134
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
2135
|
+
var ar = [];
|
|
2136
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
2137
|
+
return ar;
|
|
2138
|
+
};
|
|
2139
|
+
return ownKeys(o);
|
|
2140
|
+
};
|
|
2141
|
+
return function (mod) {
|
|
2142
|
+
if (mod && mod.__esModule) return mod;
|
|
2143
|
+
var result = {};
|
|
2144
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
2145
|
+
__setModuleDefault(result, mod);
|
|
2146
|
+
return result;
|
|
2147
|
+
};
|
|
2148
|
+
})();
|
|
2149
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2150
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
2151
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
2152
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
2153
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
2154
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
2155
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
2156
|
+
});
|
|
2157
|
+
};
|
|
2158
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2159
|
+
exports.status = status;
|
|
2160
|
+
const setting_1 = __nccwpck_require__(25546);
|
|
2161
|
+
const ckb_tui_1 = __nccwpck_require__(7020);
|
|
2162
|
+
const base_1 = __nccwpck_require__(69951);
|
|
2163
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
2164
|
+
const net = __importStar(__nccwpck_require__(69278));
|
|
2165
|
+
const NETWORK_SETTINGS_KEY = {
|
|
2166
|
+
[base_1.Network.devnet]: 'devnet',
|
|
2167
|
+
[base_1.Network.testnet]: 'testnet',
|
|
2168
|
+
[base_1.Network.mainnet]: 'mainnet',
|
|
2169
|
+
};
|
|
2170
|
+
function status(_a) {
|
|
2171
|
+
return __awaiter(this, arguments, void 0, function* ({ network }) {
|
|
2172
|
+
var _b;
|
|
2173
|
+
// ckb-tui is an interactive terminal UI. Running it without a TTY
|
|
2174
|
+
// (pipe, redirect, CI) would hang or produce garbage output.
|
|
2175
|
+
if (!process.stdout.isTTY || !process.stdin.isTTY) {
|
|
2176
|
+
logger_1.logger.error('The status command requires an interactive terminal (TTY). ' +
|
|
2177
|
+
'It cannot be used in pipes, redirects, or non-interactive environments like CI.');
|
|
2178
|
+
process.exit(1);
|
|
2179
|
+
}
|
|
2180
|
+
const settings = (0, setting_1.readSettings)();
|
|
2181
|
+
const networkKey = NETWORK_SETTINGS_KEY[network];
|
|
2182
|
+
const port = settings[networkKey].rpcProxyPort;
|
|
2183
|
+
const url = `http://127.0.0.1:${port}`;
|
|
2184
|
+
const isListening = yield isRPCPortListening(port);
|
|
2185
|
+
if (!isListening) {
|
|
2186
|
+
logger_1.logger.error(`RPC port ${port} is not listening. Please make sure the ${network} node is running and Proxy RPC is enabled.`);
|
|
2187
|
+
return;
|
|
2188
|
+
}
|
|
2189
|
+
const result = ckb_tui_1.CKBTui.run(['-r', url]);
|
|
2190
|
+
// Propagate ckb-tui exit code so scripts can detect TUI failure
|
|
2191
|
+
if (result.status !== 0) {
|
|
2192
|
+
process.exitCode = (_b = result.status) !== null && _b !== void 0 ? _b : 1;
|
|
2193
|
+
}
|
|
2194
|
+
});
|
|
2195
|
+
}
|
|
2196
|
+
function isRPCPortListening(port) {
|
|
2197
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
2198
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) {
|
|
2199
|
+
return false;
|
|
2200
|
+
}
|
|
2201
|
+
const client = new net.Socket();
|
|
2202
|
+
return new Promise((resolve) => {
|
|
2203
|
+
let settled = false;
|
|
2204
|
+
const TIMEOUT_MS = 2000;
|
|
2205
|
+
const timeout = setTimeout(() => {
|
|
2206
|
+
if (!settled) {
|
|
2207
|
+
settled = true;
|
|
2208
|
+
client.destroy();
|
|
2209
|
+
resolve(false);
|
|
2210
|
+
}
|
|
2211
|
+
}, TIMEOUT_MS);
|
|
2212
|
+
client.once('error', () => {
|
|
2213
|
+
if (!settled) {
|
|
2214
|
+
settled = true;
|
|
2215
|
+
clearTimeout(timeout);
|
|
2216
|
+
resolve(false);
|
|
2217
|
+
}
|
|
2218
|
+
});
|
|
2219
|
+
client.once('connect', () => {
|
|
2220
|
+
if (!settled) {
|
|
2221
|
+
settled = true;
|
|
2222
|
+
clearTimeout(timeout);
|
|
2223
|
+
client.end();
|
|
2224
|
+
resolve(true);
|
|
2225
|
+
}
|
|
2226
|
+
});
|
|
2227
|
+
client.connect(port, '127.0.0.1');
|
|
2228
|
+
});
|
|
2229
|
+
});
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
|
|
1521
2233
|
/***/ }),
|
|
1522
2234
|
|
|
1523
2235
|
/***/ 86198:
|
|
@@ -1540,7 +2252,6 @@ exports.printSystemScripts = printSystemScripts;
|
|
|
1540
2252
|
exports.printInSystemStyle = printInSystemStyle;
|
|
1541
2253
|
exports.printInLumosConfigStyle = printInLumosConfigStyle;
|
|
1542
2254
|
exports.printInCCCStyle = printInCCCStyle;
|
|
1543
|
-
exports.systemCellToScriptInfo = systemCellToScriptInfo;
|
|
1544
2255
|
exports.toLumosConfig = toLumosConfig;
|
|
1545
2256
|
const base_1 = __nccwpck_require__(69951);
|
|
1546
2257
|
const public_1 = __nccwpck_require__(84535);
|
|
@@ -1554,26 +2265,41 @@ var PrintStyle;
|
|
|
1554
2265
|
})(PrintStyle || (exports.PrintStyle = PrintStyle = {}));
|
|
1555
2266
|
function printSystemScripts(_a) {
|
|
1556
2267
|
return __awaiter(this, arguments, void 0, function* ({ style = PrintStyle.system, network = base_1.Network.devnet }) {
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
2268
|
+
var _b;
|
|
2269
|
+
let systemScripts;
|
|
2270
|
+
// Display label and address prefix follow the chain the devnet actually
|
|
2271
|
+
// runs: a fork carries the source chain's genesis, scripts and prefix.
|
|
2272
|
+
let label = network.toUpperCase();
|
|
2273
|
+
let addressPrefix = network === base_1.Network.mainnet ? 'ckb' : 'ckt';
|
|
2274
|
+
if (network === base_1.Network.mainnet) {
|
|
2275
|
+
systemScripts = public_1.MAINNET_SYSTEM_SCRIPTS;
|
|
2276
|
+
}
|
|
2277
|
+
else if (network === base_1.Network.testnet) {
|
|
2278
|
+
systemScripts = public_1.TESTNET_SYSTEM_SCRIPTS;
|
|
2279
|
+
}
|
|
2280
|
+
else {
|
|
2281
|
+
const resolved = (0, private_1.resolveDevnetSystemScripts)();
|
|
2282
|
+
systemScripts = (_b = resolved === null || resolved === void 0 ? void 0 : resolved.scripts) !== null && _b !== void 0 ? _b : null;
|
|
2283
|
+
if (resolved === null || resolved === void 0 ? void 0 : resolved.forkedFrom) {
|
|
2284
|
+
label = `DEVNET (fork of ${resolved.forkedFrom.toUpperCase()})`;
|
|
2285
|
+
addressPrefix = resolved.forkedFrom === 'mainnet' ? 'ckb' : 'ckt';
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
1562
2288
|
if (!systemScripts)
|
|
1563
2289
|
return logger_1.logger.info(`SystemScripts is null, ${network}`);
|
|
1564
2290
|
if (style === PrintStyle.system) {
|
|
1565
|
-
return printInSystemStyle(systemScripts,
|
|
2291
|
+
return printInSystemStyle(systemScripts, label);
|
|
1566
2292
|
}
|
|
1567
2293
|
if (style === PrintStyle.lumos) {
|
|
1568
|
-
return printInLumosConfigStyle(systemScripts,
|
|
2294
|
+
return printInLumosConfigStyle(systemScripts, label, addressPrefix);
|
|
1569
2295
|
}
|
|
1570
2296
|
if (style === PrintStyle.ccc) {
|
|
1571
|
-
return printInCCCStyle(systemScripts,
|
|
2297
|
+
return printInCCCStyle(systemScripts, label);
|
|
1572
2298
|
}
|
|
1573
2299
|
});
|
|
1574
2300
|
}
|
|
1575
|
-
function printInSystemStyle(systemScripts,
|
|
1576
|
-
logger_1.logger.info(`*** CKB ${
|
|
2301
|
+
function printInSystemStyle(systemScripts, label) {
|
|
2302
|
+
logger_1.logger.info(`*** CKB ${label} System Scripts ***\n`);
|
|
1577
2303
|
for (const [name, script] of Object.entries(systemScripts)) {
|
|
1578
2304
|
logger_1.logger.info(`- name: ${name}`);
|
|
1579
2305
|
if (script == null) {
|
|
@@ -1586,67 +2312,16 @@ function printInSystemStyle(systemScripts, network) {
|
|
|
1586
2312
|
logger_1.logger.info(` cellDeps: ${JSON.stringify(script.script.cellDeps, null, 2)}\n`);
|
|
1587
2313
|
}
|
|
1588
2314
|
}
|
|
1589
|
-
function printInLumosConfigStyle(scripts,
|
|
1590
|
-
const config = toLumosConfig(scripts,
|
|
1591
|
-
logger_1.logger.info(`*** CKB ${
|
|
2315
|
+
function printInLumosConfigStyle(scripts, label, addressPrefix) {
|
|
2316
|
+
const config = toLumosConfig(scripts, addressPrefix);
|
|
2317
|
+
logger_1.logger.info(`*** CKB ${label} System Scripts As LumosConfig ***\n`);
|
|
1592
2318
|
logger_1.logger.info(JSON.stringify(config, null, 2));
|
|
1593
2319
|
}
|
|
1594
|
-
function printInCCCStyle(scripts,
|
|
2320
|
+
function printInCCCStyle(scripts, label) {
|
|
1595
2321
|
const knownsScripts = (0, private_1.toCCCKnownScripts)(scripts);
|
|
1596
|
-
logger_1.logger.info(`*** CKB ${
|
|
2322
|
+
logger_1.logger.info(`*** CKB ${label} System Scripts As CCC KnownScripts ***\n`);
|
|
1597
2323
|
logger_1.logger.info(JSON.stringify(knownsScripts, null, 2));
|
|
1598
2324
|
}
|
|
1599
|
-
function systemCellToScriptInfo({ cell, depType, depGroup, extraCellDeps, }) {
|
|
1600
|
-
// todo: we left the type in cellDepsInfo since it requires async fetching and
|
|
1601
|
-
// chain running to get the full type script of the type-id deps.
|
|
1602
|
-
// Also, in devnet there is no real need to auto upgrade the system scripts with type-id
|
|
1603
|
-
if (depType === 'code') {
|
|
1604
|
-
let cellDeps = [
|
|
1605
|
-
{
|
|
1606
|
-
cellDep: {
|
|
1607
|
-
outPoint: {
|
|
1608
|
-
txHash: cell.tx_hash,
|
|
1609
|
-
index: cell.index,
|
|
1610
|
-
},
|
|
1611
|
-
depType,
|
|
1612
|
-
},
|
|
1613
|
-
},
|
|
1614
|
-
];
|
|
1615
|
-
if (extraCellDeps && extraCellDeps.length > 0) {
|
|
1616
|
-
cellDeps = [...extraCellDeps, ...cellDeps];
|
|
1617
|
-
}
|
|
1618
|
-
return {
|
|
1619
|
-
codeHash: (cell.type_hash || cell.data_hash),
|
|
1620
|
-
hashType: cell.type_hash ? 'type' : 'data2',
|
|
1621
|
-
cellDeps,
|
|
1622
|
-
};
|
|
1623
|
-
}
|
|
1624
|
-
if (depType === 'depGroup') {
|
|
1625
|
-
if (!depGroup) {
|
|
1626
|
-
throw new Error('require depGroup info since the dep type is depGroup');
|
|
1627
|
-
}
|
|
1628
|
-
let cellDeps = [
|
|
1629
|
-
{
|
|
1630
|
-
cellDep: {
|
|
1631
|
-
outPoint: {
|
|
1632
|
-
txHash: depGroup.txHash,
|
|
1633
|
-
index: depGroup.index,
|
|
1634
|
-
},
|
|
1635
|
-
depType,
|
|
1636
|
-
},
|
|
1637
|
-
},
|
|
1638
|
-
];
|
|
1639
|
-
if (extraCellDeps && extraCellDeps.length > 0) {
|
|
1640
|
-
cellDeps = [...extraCellDeps, ...cellDeps];
|
|
1641
|
-
}
|
|
1642
|
-
return {
|
|
1643
|
-
codeHash: (cell.type_hash || cell.data_hash),
|
|
1644
|
-
hashType: cell.type_hash ? 'type' : 'data2',
|
|
1645
|
-
cellDeps,
|
|
1646
|
-
};
|
|
1647
|
-
}
|
|
1648
|
-
throw new Error(`unknown DepType ${depType}`);
|
|
1649
|
-
}
|
|
1650
2325
|
function toLumosConfig(scripts, addressPrefix = 'ckt') {
|
|
1651
2326
|
const config = {
|
|
1652
2327
|
PREFIX: addressPrefix,
|
|
@@ -1829,9 +2504,9 @@ const ckb_1 = __nccwpck_require__(83748);
|
|
|
1829
2504
|
const base_1 = __nccwpck_require__(69951);
|
|
1830
2505
|
const link_1 = __nccwpck_require__(27814);
|
|
1831
2506
|
const validator_1 = __nccwpck_require__(39534);
|
|
1832
|
-
|
|
1833
|
-
function
|
|
1834
|
-
|
|
2507
|
+
function transfer(toAddress_1, amount_1) {
|
|
2508
|
+
return __awaiter(this, arguments, void 0, function* (toAddress, amount, opt = { network: base_1.Network.devnet }) {
|
|
2509
|
+
var _a;
|
|
1835
2510
|
const network = opt.network;
|
|
1836
2511
|
(0, validator_1.validateNetworkOpt)(network);
|
|
1837
2512
|
if (opt.privkey == null) {
|
|
@@ -1839,16 +2514,89 @@ function transfer(toAddress_1, amountInCKB_1) {
|
|
|
1839
2514
|
}
|
|
1840
2515
|
const privateKey = opt.privkey;
|
|
1841
2516
|
const ckb = new ckb_1.CKB({ network });
|
|
2517
|
+
if (opt.udtTypeArgs) {
|
|
2518
|
+
const kind = (_a = opt.udtKind) !== null && _a !== void 0 ? _a : 'sudt';
|
|
2519
|
+
(0, validator_1.validateUdtKind)(kind);
|
|
2520
|
+
const udtTypeArgs = (0, validator_1.validateUdtTypeArgs)(kind, opt.udtTypeArgs);
|
|
2521
|
+
const udtType = yield ckb.buildUdtTypeScript(kind, udtTypeArgs);
|
|
2522
|
+
const txHash = yield ckb.udtTransfer({
|
|
2523
|
+
toAddress,
|
|
2524
|
+
amount,
|
|
2525
|
+
privateKey,
|
|
2526
|
+
udtType,
|
|
2527
|
+
kind,
|
|
2528
|
+
});
|
|
2529
|
+
(0, link_1.logTxSuccess)(network, txHash, 'transfer UDT');
|
|
2530
|
+
return;
|
|
2531
|
+
}
|
|
1842
2532
|
const txHash = yield ckb.transfer({
|
|
1843
2533
|
toAddress,
|
|
1844
|
-
amountInCKB,
|
|
2534
|
+
amountInCKB: amount,
|
|
1845
2535
|
privateKey,
|
|
1846
2536
|
});
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
2537
|
+
(0, link_1.logTxSuccess)(network, txHash, 'transfer');
|
|
2538
|
+
});
|
|
2539
|
+
}
|
|
2540
|
+
|
|
2541
|
+
|
|
2542
|
+
/***/ }),
|
|
2543
|
+
|
|
2544
|
+
/***/ 50703:
|
|
2545
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
2546
|
+
|
|
2547
|
+
"use strict";
|
|
2548
|
+
|
|
2549
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2550
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
2551
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
2552
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
2553
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
2554
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
2555
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
2556
|
+
});
|
|
2557
|
+
};
|
|
2558
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
2559
|
+
exports.udtIssue = udtIssue;
|
|
2560
|
+
exports.udtDestroy = udtDestroy;
|
|
2561
|
+
const ckb_1 = __nccwpck_require__(83748);
|
|
2562
|
+
const base_1 = __nccwpck_require__(69951);
|
|
2563
|
+
const link_1 = __nccwpck_require__(27814);
|
|
2564
|
+
const validator_1 = __nccwpck_require__(39534);
|
|
2565
|
+
function udtIssue(amount_1) {
|
|
2566
|
+
return __awaiter(this, arguments, void 0, function* (amount, opt = { network: base_1.Network.devnet, udtKind: 'sudt', privkey: '' }) {
|
|
2567
|
+
const network = opt.network;
|
|
2568
|
+
(0, validator_1.validateNetworkOpt)(network);
|
|
2569
|
+
(0, validator_1.validateUdtKind)(opt.udtKind);
|
|
2570
|
+
if (!opt.privkey) {
|
|
2571
|
+
throw new Error('--privkey is required!');
|
|
1850
2572
|
}
|
|
1851
|
-
|
|
2573
|
+
const ckb = new ckb_1.CKB({ network });
|
|
2574
|
+
const txHash = yield ckb.udtIssue({
|
|
2575
|
+
privateKey: opt.privkey,
|
|
2576
|
+
kind: opt.udtKind,
|
|
2577
|
+
amount,
|
|
2578
|
+
typeArgs: opt.typeArgs ? (0, validator_1.validateUdtTypeArgs)(opt.udtKind, opt.typeArgs) : undefined,
|
|
2579
|
+
toAddress: opt.to,
|
|
2580
|
+
});
|
|
2581
|
+
(0, link_1.logTxSuccess)(network, txHash, 'issued UDT');
|
|
2582
|
+
});
|
|
2583
|
+
}
|
|
2584
|
+
function udtDestroy(amount_1) {
|
|
2585
|
+
return __awaiter(this, arguments, void 0, function* (amount, opt = { network: base_1.Network.devnet, udtKind: 'sudt', typeArgs: '', privkey: '' }) {
|
|
2586
|
+
const network = opt.network;
|
|
2587
|
+
(0, validator_1.validateNetworkOpt)(network);
|
|
2588
|
+
(0, validator_1.validateUdtKind)(opt.udtKind);
|
|
2589
|
+
if (!opt.privkey) {
|
|
2590
|
+
throw new Error('--privkey is required!');
|
|
2591
|
+
}
|
|
2592
|
+
const ckb = new ckb_1.CKB({ network });
|
|
2593
|
+
const txHash = yield ckb.udtDestroy({
|
|
2594
|
+
privateKey: opt.privkey,
|
|
2595
|
+
kind: opt.udtKind,
|
|
2596
|
+
amount,
|
|
2597
|
+
typeArgs: (0, validator_1.validateUdtTypeArgs)(opt.udtKind, opt.typeArgs),
|
|
2598
|
+
});
|
|
2599
|
+
(0, link_1.logTxSuccess)(network, txHash, 'destroyed UDT');
|
|
1852
2600
|
});
|
|
1853
2601
|
}
|
|
1854
2602
|
|
|
@@ -2820,6 +3568,397 @@ class InitializationError extends Error {
|
|
|
2820
3568
|
exports.InitializationError = InitializationError;
|
|
2821
3569
|
|
|
2822
3570
|
|
|
3571
|
+
/***/ }),
|
|
3572
|
+
|
|
3573
|
+
/***/ 77912:
|
|
3574
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
3575
|
+
|
|
3576
|
+
"use strict";
|
|
3577
|
+
|
|
3578
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3579
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3580
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
3581
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
3582
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
3583
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
3584
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
3585
|
+
});
|
|
3586
|
+
};
|
|
3587
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3588
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
3589
|
+
};
|
|
3590
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3591
|
+
exports.FORK_STATE_FILE = void 0;
|
|
3592
|
+
exports.getForkStatePath = getForkStatePath;
|
|
3593
|
+
exports.readForkState = readForkState;
|
|
3594
|
+
exports.writeForkState = writeForkState;
|
|
3595
|
+
exports.markForkFirstRunComplete = markForkFirstRunComplete;
|
|
3596
|
+
exports.detectSourceFromCkbToml = detectSourceFromCkbToml;
|
|
3597
|
+
exports.parseGenesisHashFromInitOutput = parseGenesisHashFromInitOutput;
|
|
3598
|
+
exports.parseGenesisHashFromListHashes = parseGenesisHashFromListHashes;
|
|
3599
|
+
exports.expectedGenesisHash = expectedGenesisHash;
|
|
3600
|
+
exports.patchDevSpecForFork = patchDevSpecForFork;
|
|
3601
|
+
exports.forkDevnet = forkDevnet;
|
|
3602
|
+
const child_process_1 = __nccwpck_require__(35317);
|
|
3603
|
+
const fs_1 = __importDefault(__nccwpck_require__(79896));
|
|
3604
|
+
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
3605
|
+
const toml_1 = __importDefault(__nccwpck_require__(2811));
|
|
3606
|
+
const setting_1 = __nccwpck_require__(25546);
|
|
3607
|
+
const install_1 = __nccwpck_require__(65611);
|
|
3608
|
+
const fs_2 = __nccwpck_require__(37293);
|
|
3609
|
+
const request_1 = __nccwpck_require__(65897);
|
|
3610
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
3611
|
+
const const_1 = __nccwpck_require__(75587);
|
|
3612
|
+
exports.FORK_STATE_FILE = 'fork.json';
|
|
3613
|
+
// The official guide requires genesis_epoch_length to stay at 1743 for a
|
|
3614
|
+
// mainnet fork, and to fall back to the default 1000 for a testnet fork
|
|
3615
|
+
// (i.e. the key must be absent). Getting this wrong produces a different
|
|
3616
|
+
// genesis hash and the node refuses to start. See nervosnetwork/ckb#5205.
|
|
3617
|
+
const MAINNET_GENESIS_EPOCH_LENGTH = 1743;
|
|
3618
|
+
function getForkStatePath(configPath) {
|
|
3619
|
+
return path_1.default.join(configPath, exports.FORK_STATE_FILE);
|
|
3620
|
+
}
|
|
3621
|
+
function readForkState(configPath) {
|
|
3622
|
+
const statePath = getForkStatePath(configPath);
|
|
3623
|
+
let raw;
|
|
3624
|
+
try {
|
|
3625
|
+
raw = fs_1.default.readFileSync(statePath, 'utf8');
|
|
3626
|
+
}
|
|
3627
|
+
catch (_a) {
|
|
3628
|
+
return null;
|
|
3629
|
+
}
|
|
3630
|
+
try {
|
|
3631
|
+
const parsed = JSON.parse(raw);
|
|
3632
|
+
if (typeof parsed.source !== 'string' || typeof parsed.firstRunPending !== 'boolean') {
|
|
3633
|
+
return null;
|
|
3634
|
+
}
|
|
3635
|
+
return parsed;
|
|
3636
|
+
}
|
|
3637
|
+
catch (_b) {
|
|
3638
|
+
return null;
|
|
3639
|
+
}
|
|
3640
|
+
}
|
|
3641
|
+
function writeForkState(configPath, state) {
|
|
3642
|
+
const statePath = getForkStatePath(configPath);
|
|
3643
|
+
const tempPath = `${statePath}.tmp`;
|
|
3644
|
+
fs_1.default.writeFileSync(tempPath, JSON.stringify(state, null, 2));
|
|
3645
|
+
fs_1.default.renameSync(tempPath, statePath);
|
|
3646
|
+
}
|
|
3647
|
+
function markForkFirstRunComplete(configPath) {
|
|
3648
|
+
const state = readForkState(configPath);
|
|
3649
|
+
if (!state || !state.firstRunPending)
|
|
3650
|
+
return;
|
|
3651
|
+
writeForkState(configPath, Object.assign(Object.assign({}, state), { firstRunPending: false }));
|
|
3652
|
+
}
|
|
3653
|
+
function detectSourceFromCkbToml(ckbTomlContent) {
|
|
3654
|
+
let parsed;
|
|
3655
|
+
try {
|
|
3656
|
+
parsed = toml_1.default.parse(ckbTomlContent);
|
|
3657
|
+
}
|
|
3658
|
+
catch (_a) {
|
|
3659
|
+
return null;
|
|
3660
|
+
}
|
|
3661
|
+
const chain = parsed.chain;
|
|
3662
|
+
if (chain == null || typeof chain !== 'object')
|
|
3663
|
+
return null;
|
|
3664
|
+
const spec = chain.spec;
|
|
3665
|
+
if (spec == null || typeof spec !== 'object')
|
|
3666
|
+
return null;
|
|
3667
|
+
const bundled = spec.bundled;
|
|
3668
|
+
if (typeof bundled !== 'string')
|
|
3669
|
+
return null;
|
|
3670
|
+
if (bundled.includes('mainnet'))
|
|
3671
|
+
return 'mainnet';
|
|
3672
|
+
if (bundled.includes('testnet'))
|
|
3673
|
+
return 'testnet';
|
|
3674
|
+
return null;
|
|
3675
|
+
}
|
|
3676
|
+
function parseGenesisHashFromInitOutput(output) {
|
|
3677
|
+
const match = output.match(/Genesis Hash:\s*(0x[0-9a-fA-F]{64})/);
|
|
3678
|
+
return match ? match[1].toLowerCase() : null;
|
|
3679
|
+
}
|
|
3680
|
+
// `ckb list-hashes` prints TOML with a single table whose `genesis` field is
|
|
3681
|
+
// the chain's genesis hash.
|
|
3682
|
+
function parseGenesisHashFromListHashes(output) {
|
|
3683
|
+
const match = output.match(/^\s*genesis\s*=\s*"(0x[0-9a-fA-F]{64})"\s*$/m);
|
|
3684
|
+
return match ? match[1].toLowerCase() : null;
|
|
3685
|
+
}
|
|
3686
|
+
function expectedGenesisHash(source) {
|
|
3687
|
+
return source === 'mainnet' ? const_1.MAINNET_GENESIS_HASH : const_1.TESTNET_GENESIS_HASH;
|
|
3688
|
+
}
|
|
3689
|
+
// Patch the imported chain spec into a minable dev chain, following
|
|
3690
|
+
// https://docs.nervos.org/docs/node/devnet-from-existing-data
|
|
3691
|
+
function patchDevSpecForFork(spec, source) {
|
|
3692
|
+
var _a, _b;
|
|
3693
|
+
const pow = Object.assign(Object.assign({}, ((_a = spec.pow) !== null && _a !== void 0 ? _a : {})), { func: 'Dummy' });
|
|
3694
|
+
const params = Object.assign({}, ((_b = spec.params) !== null && _b !== void 0 ? _b : {}));
|
|
3695
|
+
params.cellbase_maturity = 0;
|
|
3696
|
+
params.permanent_difficulty_in_dummy = true;
|
|
3697
|
+
if (source === 'mainnet') {
|
|
3698
|
+
params.genesis_epoch_length = MAINNET_GENESIS_EPOCH_LENGTH;
|
|
3699
|
+
}
|
|
3700
|
+
else if (source === 'testnet') {
|
|
3701
|
+
// testnet derives genesis_epoch_length from the default (1000); a leftover
|
|
3702
|
+
// mainnet value here is exactly the nervosnetwork/ckb#5205 trap.
|
|
3703
|
+
delete params.genesis_epoch_length;
|
|
3704
|
+
}
|
|
3705
|
+
// custom specs keep whatever genesis_epoch_length they declared
|
|
3706
|
+
return Object.assign(Object.assign({}, spec), { pow, params });
|
|
3707
|
+
}
|
|
3708
|
+
function validateSourceDir(sourceDir) {
|
|
3709
|
+
if (!(0, fs_2.isFolderExists)(sourceDir)) {
|
|
3710
|
+
throw new Error(`Source directory does not exist: ${sourceDir}`);
|
|
3711
|
+
}
|
|
3712
|
+
if (!(0, fs_2.isFolderExists)(path_1.default.join(sourceDir, 'data', 'db'))) {
|
|
3713
|
+
throw new Error(`${sourceDir} does not look like a CKB node directory (missing data/db). ` +
|
|
3714
|
+
`Point --from at the directory the source node runs with (-C).`);
|
|
3715
|
+
}
|
|
3716
|
+
}
|
|
3717
|
+
// Best-effort detection of a running ckb process using the given directory.
|
|
3718
|
+
// Returns null when the check cannot be performed (Windows, no ps).
|
|
3719
|
+
function isCkbNodeRunningOn(dir) {
|
|
3720
|
+
if (process.platform === 'win32')
|
|
3721
|
+
return null;
|
|
3722
|
+
let processes = '';
|
|
3723
|
+
try {
|
|
3724
|
+
processes = (0, child_process_1.execSync)('ps -eo args', { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
|
|
3725
|
+
}
|
|
3726
|
+
catch (_a) {
|
|
3727
|
+
return null;
|
|
3728
|
+
}
|
|
3729
|
+
return processes.split('\n').some((line) => {
|
|
3730
|
+
var _a;
|
|
3731
|
+
const tokens = line.trim().split(/\s+/);
|
|
3732
|
+
// The program itself must be a ckb binary — a looser match would flag
|
|
3733
|
+
// unrelated processes that merely mention the directory.
|
|
3734
|
+
const program = path_1.default.basename((_a = tokens[0]) !== null && _a !== void 0 ? _a : '');
|
|
3735
|
+
if (program !== 'ckb' && program !== 'ckb.exe')
|
|
3736
|
+
return false;
|
|
3737
|
+
return tokens.includes('run') && line.includes(dir);
|
|
3738
|
+
});
|
|
3739
|
+
}
|
|
3740
|
+
function assertSourceNodeStopped(sourceDir) {
|
|
3741
|
+
const running = isCkbNodeRunningOn(sourceDir);
|
|
3742
|
+
if (running === null) {
|
|
3743
|
+
logger_1.logger.warn('Make sure the source CKB node is stopped; copying a live database produces corrupted data.');
|
|
3744
|
+
return;
|
|
3745
|
+
}
|
|
3746
|
+
if (running) {
|
|
3747
|
+
throw new Error(`A CKB node appears to be running on ${sourceDir}. Stop it first; ` +
|
|
3748
|
+
`copying a live database produces corrupted data.`);
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
function assertOffckbDevnetStopped() {
|
|
3752
|
+
const settings = (0, setting_1.readSettings)();
|
|
3753
|
+
// Foreground `offckb node` (no daemon pid file): look for the ckb process.
|
|
3754
|
+
if (isCkbNodeRunningOn(settings.devnet.configPath) === true) {
|
|
3755
|
+
throw new Error('An offckb devnet node appears to be running. Stop it before forking.');
|
|
3756
|
+
}
|
|
3757
|
+
// Daemon mode: check the pid file.
|
|
3758
|
+
const pidFile = path_1.default.join(settings.devnet.dataPath, 'logs', 'daemon.pid');
|
|
3759
|
+
let raw;
|
|
3760
|
+
try {
|
|
3761
|
+
raw = fs_1.default.readFileSync(pidFile, 'utf8').trim();
|
|
3762
|
+
}
|
|
3763
|
+
catch (_a) {
|
|
3764
|
+
return;
|
|
3765
|
+
}
|
|
3766
|
+
let pid = Number(raw);
|
|
3767
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
3768
|
+
try {
|
|
3769
|
+
pid = Number(JSON.parse(raw).pid);
|
|
3770
|
+
}
|
|
3771
|
+
catch (_b) {
|
|
3772
|
+
return;
|
|
3773
|
+
}
|
|
3774
|
+
}
|
|
3775
|
+
if (!Number.isInteger(pid) || pid <= 0)
|
|
3776
|
+
return;
|
|
3777
|
+
let alive = true;
|
|
3778
|
+
try {
|
|
3779
|
+
process.kill(pid, 0);
|
|
3780
|
+
}
|
|
3781
|
+
catch (_c) {
|
|
3782
|
+
alive = false; // ESRCH: stale pid file, no daemon running
|
|
3783
|
+
}
|
|
3784
|
+
if (alive) {
|
|
3785
|
+
throw new Error(`The offckb devnet daemon is running (PID ${pid}). Stop it first with: offckb node stop`);
|
|
3786
|
+
}
|
|
3787
|
+
}
|
|
3788
|
+
function resolveSpecFile(options, source, ckbVersion) {
|
|
3789
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3790
|
+
if (options.specFile) {
|
|
3791
|
+
const specFile = path_1.default.resolve(options.specFile);
|
|
3792
|
+
if (!fs_1.default.existsSync(specFile)) {
|
|
3793
|
+
throw new Error(`Spec file not found: ${specFile}`);
|
|
3794
|
+
}
|
|
3795
|
+
return specFile;
|
|
3796
|
+
}
|
|
3797
|
+
const cacheDir = path_1.default.join(setting_1.cachePath, 'specs', ckbVersion);
|
|
3798
|
+
const cachedSpec = path_1.default.join(cacheDir, `${source}.toml`);
|
|
3799
|
+
if (fs_1.default.existsSync(cachedSpec)) {
|
|
3800
|
+
logger_1.logger.debug(`Using cached ${source} spec: ${cachedSpec}`);
|
|
3801
|
+
return cachedSpec;
|
|
3802
|
+
}
|
|
3803
|
+
const url = `https://raw.githubusercontent.com/nervosnetwork/ckb/v${ckbVersion}/resource/specs/${source}.toml`;
|
|
3804
|
+
logger_1.logger.info(`Downloading ${source} chain spec from ${url} ..`);
|
|
3805
|
+
try {
|
|
3806
|
+
const response = yield request_1.Request.send(url);
|
|
3807
|
+
const content = yield response.text();
|
|
3808
|
+
fs_1.default.mkdirSync(cacheDir, { recursive: true });
|
|
3809
|
+
fs_1.default.writeFileSync(cachedSpec, content);
|
|
3810
|
+
return cachedSpec;
|
|
3811
|
+
}
|
|
3812
|
+
catch (error) {
|
|
3813
|
+
throw new Error(`Failed to download the ${source} chain spec for CKB v${ckbVersion}: ${error.message}. ` +
|
|
3814
|
+
`Pass a local copy with --spec-file.`);
|
|
3815
|
+
}
|
|
3816
|
+
});
|
|
3817
|
+
}
|
|
3818
|
+
function copySourceData(sourceDir, configPath) {
|
|
3819
|
+
const sourceData = path_1.default.join(sourceDir, 'data');
|
|
3820
|
+
const targetData = path_1.default.join(configPath, 'data');
|
|
3821
|
+
logger_1.logger.info(`Copying chain data from ${sourceData} to ${targetData} ..`);
|
|
3822
|
+
logger_1.logger.info('This can take a while for large chains.');
|
|
3823
|
+
fs_1.default.mkdirSync(configPath, { recursive: true });
|
|
3824
|
+
// Full copy on purpose: never hardlink — RocksDB appends to WAL/MANIFEST in
|
|
3825
|
+
// place, and linked files would corrupt the source chain.
|
|
3826
|
+
fs_1.default.cpSync(sourceData, targetData, { recursive: true });
|
|
3827
|
+
}
|
|
3828
|
+
function runCkbInit(ckbBinPath, configPath, specFile) {
|
|
3829
|
+
// argv form, never a shell: --spec-file is user input and quote-wrapping
|
|
3830
|
+
// alone does not stop shell expansion (command substitution still runs
|
|
3831
|
+
// inside double quotes).
|
|
3832
|
+
const args = ['init', '-C', configPath, '--chain', 'dev', '--import-spec', specFile, '--force'];
|
|
3833
|
+
logger_1.logger.debug(`Running: ${ckbBinPath} ${args.join(' ')}`);
|
|
3834
|
+
return (0, child_process_1.execFileSync)(ckbBinPath, args, { encoding: 'utf8', maxBuffer: 16 * 1024 * 1024 });
|
|
3835
|
+
}
|
|
3836
|
+
// Best-effort read of the source directory's own chain identity. `ckb
|
|
3837
|
+
// list-hashes` resolves the chain spec of the given config dir (no database
|
|
3838
|
+
// access needed), which tells us which chain the source node was configured
|
|
3839
|
+
// for. Returns null when the source is not a standard config dir.
|
|
3840
|
+
function readSourceGenesisHash(ckbBinPath, sourceDir) {
|
|
3841
|
+
try {
|
|
3842
|
+
const output = (0, child_process_1.execFileSync)(ckbBinPath, ['list-hashes', '-C', sourceDir], {
|
|
3843
|
+
encoding: 'utf8',
|
|
3844
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
3845
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
3846
|
+
});
|
|
3847
|
+
return parseGenesisHashFromListHashes(output);
|
|
3848
|
+
}
|
|
3849
|
+
catch (_a) {
|
|
3850
|
+
return null;
|
|
3851
|
+
}
|
|
3852
|
+
}
|
|
3853
|
+
// Overwrite the ckb-init-generated configs with offckb's own devnet configs so
|
|
3854
|
+
// the fork behaves like a normal offckb devnet (miner account as block
|
|
3855
|
+
// assembler, RPC on 8114 with the Indexer module, proxy on 28114). The
|
|
3856
|
+
// imported specs/dev.toml is kept.
|
|
3857
|
+
function alignConfigsWithOffckb(configPath) {
|
|
3858
|
+
const settings = (0, setting_1.readSettings)();
|
|
3859
|
+
const devnetSourcePath = path_1.default.resolve(setting_1.packageRootPath, './ckb/devnet');
|
|
3860
|
+
fs_1.default.copyFileSync(path_1.default.join(devnetSourcePath, 'ckb.toml'), path_1.default.join(configPath, 'ckb.toml'));
|
|
3861
|
+
fs_1.default.copyFileSync(path_1.default.join(devnetSourcePath, 'default.db-options'), path_1.default.join(configPath, 'default.db-options'));
|
|
3862
|
+
const minerToml = fs_1.default.readFileSync(path_1.default.join(devnetSourcePath, 'ckb-miner.toml'), 'utf8');
|
|
3863
|
+
fs_1.default.writeFileSync(path_1.default.join(configPath, 'ckb-miner.toml'), minerToml.replace('http://ckb:8114/', settings.devnet.rpcUrl));
|
|
3864
|
+
}
|
|
3865
|
+
function forkDevnet(options) {
|
|
3866
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
3867
|
+
var _a, _b;
|
|
3868
|
+
const settings = (0, setting_1.readSettings)();
|
|
3869
|
+
const configPath = settings.devnet.configPath;
|
|
3870
|
+
const ckbVersion = settings.bins.defaultCKBVersion;
|
|
3871
|
+
const sourceDir = path_1.default.resolve(options.from);
|
|
3872
|
+
validateSourceDir(sourceDir);
|
|
3873
|
+
assertSourceNodeStopped(sourceDir);
|
|
3874
|
+
assertOffckbDevnetStopped();
|
|
3875
|
+
if ((0, fs_2.isFolderExists)(configPath)) {
|
|
3876
|
+
if (!options.force) {
|
|
3877
|
+
throw new Error(`A devnet already exists at ${configPath}. Re-run with --force to replace it, ` +
|
|
3878
|
+
`or reset it first with: offckb clean`);
|
|
3879
|
+
}
|
|
3880
|
+
logger_1.logger.info(`Removing existing devnet at ${configPath} ..`);
|
|
3881
|
+
fs_1.default.rmSync(configPath, { recursive: true, force: true });
|
|
3882
|
+
}
|
|
3883
|
+
// Identify the source chain: explicit flag > ckb.toml bundled spec.
|
|
3884
|
+
let source = (_a = options.source) !== null && _a !== void 0 ? _a : null;
|
|
3885
|
+
if (source == null) {
|
|
3886
|
+
const sourceCkbToml = path_1.default.join(sourceDir, 'ckb.toml');
|
|
3887
|
+
if (fs_1.default.existsSync(sourceCkbToml)) {
|
|
3888
|
+
source = detectSourceFromCkbToml(fs_1.default.readFileSync(sourceCkbToml, 'utf8'));
|
|
3889
|
+
}
|
|
3890
|
+
}
|
|
3891
|
+
if (source == null && !options.specFile) {
|
|
3892
|
+
throw new Error('Could not identify the source chain from the source directory. ' +
|
|
3893
|
+
'Pass --source mainnet|testnet, or provide the chain spec with --spec-file.');
|
|
3894
|
+
}
|
|
3895
|
+
yield (0, install_1.installCKBBinary)(ckbVersion);
|
|
3896
|
+
const ckbBinPath = (0, setting_1.getCKBBinaryPath)(ckbVersion);
|
|
3897
|
+
try {
|
|
3898
|
+
// Inside the try so a failed copy (disk full, permissions, I/O) gets the
|
|
3899
|
+
// same rollback: a partial configPath would otherwise block the next
|
|
3900
|
+
// attempt as an "existing devnet".
|
|
3901
|
+
copySourceData(sourceDir, configPath);
|
|
3902
|
+
const specFile = yield resolveSpecFile(options, source !== null && source !== void 0 ? source : 'mainnet', ckbVersion);
|
|
3903
|
+
const initOutput = runCkbInit(ckbBinPath, configPath, specFile);
|
|
3904
|
+
const genesisHash = parseGenesisHashFromInitOutput(initOutput);
|
|
3905
|
+
if (!genesisHash) {
|
|
3906
|
+
throw new Error(`Could not parse the genesis hash from ckb init output:\n${initOutput}`);
|
|
3907
|
+
}
|
|
3908
|
+
// A custom spec may still be a well-known chain; let the chain data
|
|
3909
|
+
// self-identify via its genesis hash.
|
|
3910
|
+
if (source == null) {
|
|
3911
|
+
source = (_b = (0, const_1.identifyPublicChainByGenesisHash)(genesisHash)) !== null && _b !== void 0 ? _b : 'custom';
|
|
3912
|
+
}
|
|
3913
|
+
if (source !== 'custom') {
|
|
3914
|
+
const expected = expectedGenesisHash(source);
|
|
3915
|
+
if (genesisHash !== expected) {
|
|
3916
|
+
throw new Error(`Genesis hash mismatch: expected ${expected} for ${source}, got ${genesisHash}. ` +
|
|
3917
|
+
`This usually means the chain spec does not match the source data. ` +
|
|
3918
|
+
`(Importing a testnet spec with a CKB older than v0.207.0 sets a wrong genesis_epoch_length, ` +
|
|
3919
|
+
`see nervosnetwork/ckb#5205.)`);
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3922
|
+
// The genesis above comes from the imported spec alone — it cannot see
|
|
3923
|
+
// that --source/--spec-file contradicts the copied data (e.g. a mainnet
|
|
3924
|
+
// spec over testnet data would pass and only fail when the node boots).
|
|
3925
|
+
// Cross-check the source directory's own configured genesis and reject
|
|
3926
|
+
// mismatches now. Skipped (null) when the source is not a standard
|
|
3927
|
+
// config dir; the node's boot-time genesis check remains the backstop.
|
|
3928
|
+
const sourceGenesisHash = readSourceGenesisHash(ckbBinPath, sourceDir);
|
|
3929
|
+
if (sourceGenesisHash && sourceGenesisHash !== genesisHash) {
|
|
3930
|
+
throw new Error(`The source directory is configured for a different chain (genesis ${sourceGenesisHash}) ` +
|
|
3931
|
+
`than the imported spec (genesis ${genesisHash}). Pass a matching --source or --spec-file.`);
|
|
3932
|
+
}
|
|
3933
|
+
const devSpecPath = path_1.default.join(configPath, 'specs', 'dev.toml');
|
|
3934
|
+
const spec = toml_1.default.parse(fs_1.default.readFileSync(devSpecPath, 'utf8'));
|
|
3935
|
+
const patched = patchDevSpecForFork(spec, source);
|
|
3936
|
+
const tempSpecPath = `${devSpecPath}.tmp`;
|
|
3937
|
+
fs_1.default.writeFileSync(tempSpecPath, toml_1.default.stringify(patched));
|
|
3938
|
+
fs_1.default.renameSync(tempSpecPath, devSpecPath);
|
|
3939
|
+
alignConfigsWithOffckb(configPath);
|
|
3940
|
+
const state = {
|
|
3941
|
+
source,
|
|
3942
|
+
sourceDir,
|
|
3943
|
+
ckbVersion,
|
|
3944
|
+
genesisHash,
|
|
3945
|
+
forkedAt: new Date().toISOString(),
|
|
3946
|
+
firstRunPending: true,
|
|
3947
|
+
};
|
|
3948
|
+
writeForkState(configPath, state);
|
|
3949
|
+
logger_1.logger.success(`Devnet forked from ${sourceDir} (${source}, genesis ${genesisHash}).`);
|
|
3950
|
+
logger_1.logger.info('Start it with: offckb node');
|
|
3951
|
+
logger_1.logger.info('The first run applies --skip-spec-check --overwrite-spec automatically.');
|
|
3952
|
+
}
|
|
3953
|
+
catch (error) {
|
|
3954
|
+
// Leave no half-forked devnet behind.
|
|
3955
|
+
fs_1.default.rmSync(configPath, { recursive: true, force: true });
|
|
3956
|
+
throw error;
|
|
3957
|
+
}
|
|
3958
|
+
});
|
|
3959
|
+
}
|
|
3960
|
+
|
|
3961
|
+
|
|
2823
3962
|
/***/ }),
|
|
2824
3963
|
|
|
2825
3964
|
/***/ 1360:
|
|
@@ -2934,7 +4073,7 @@ const fs = __importStar(__nccwpck_require__(79896));
|
|
|
2934
4073
|
const path = __importStar(__nccwpck_require__(16928));
|
|
2935
4074
|
const semver_1 = __importDefault(__nccwpck_require__(89939));
|
|
2936
4075
|
const os_1 = __importDefault(__nccwpck_require__(70857));
|
|
2937
|
-
const adm_zip_1 = __importDefault(__nccwpck_require__(
|
|
4076
|
+
const adm_zip_1 = __importDefault(__nccwpck_require__(3858));
|
|
2938
4077
|
const tar = __importStar(__nccwpck_require__(80228));
|
|
2939
4078
|
const request_1 = __nccwpck_require__(65897);
|
|
2940
4079
|
const setting_1 = __nccwpck_require__(25546);
|
|
@@ -3154,7 +4293,8 @@ function buildDownloadUrl(version, opt = {}) {
|
|
|
3154
4293
|
"use strict";
|
|
3155
4294
|
|
|
3156
4295
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3157
|
-
exports.TYPE_ID_SCRIPT = void 0;
|
|
4296
|
+
exports.TESTNET_GENESIS_HASH = exports.MAINNET_GENESIS_HASH = exports.TYPE_ID_SCRIPT = void 0;
|
|
4297
|
+
exports.identifyPublicChainByGenesisHash = identifyPublicChainByGenesisHash;
|
|
3158
4298
|
exports.TYPE_ID_SCRIPT = {
|
|
3159
4299
|
name: 'type_id',
|
|
3160
4300
|
script: {
|
|
@@ -3163,6 +4303,18 @@ exports.TYPE_ID_SCRIPT = {
|
|
|
3163
4303
|
cellDeps: [],
|
|
3164
4304
|
},
|
|
3165
4305
|
};
|
|
4306
|
+
// Well-known genesis block hashes, used to identify which chain a devnet
|
|
4307
|
+
// actually runs (a forked devnet carries the source chain's genesis).
|
|
4308
|
+
// https://github.com/nervosnetwork/ckb/tree/master/resource/specs
|
|
4309
|
+
exports.MAINNET_GENESIS_HASH = '0x92b197aa1fba0f63633922c61c92375c9c074a93e85963554f5499fe1450d0e5';
|
|
4310
|
+
exports.TESTNET_GENESIS_HASH = '0x10639e0895502b5688a6be8cf69460d76541bfa4821629d86d62ba0aae3f9606';
|
|
4311
|
+
function identifyPublicChainByGenesisHash(genesisHash) {
|
|
4312
|
+
if (genesisHash === exports.MAINNET_GENESIS_HASH)
|
|
4313
|
+
return 'mainnet';
|
|
4314
|
+
if (genesisHash === exports.TESTNET_GENESIS_HASH)
|
|
4315
|
+
return 'testnet';
|
|
4316
|
+
return null;
|
|
4317
|
+
}
|
|
3166
4318
|
|
|
3167
4319
|
|
|
3168
4320
|
/***/ }),
|
|
@@ -3250,30 +4402,21 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3250
4402
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
3251
4403
|
};
|
|
3252
4404
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
4405
|
+
exports.resolveDevnetSystemScripts = resolveDevnetSystemScripts;
|
|
3253
4406
|
exports.getDevnetSystemScriptsFromListHashes = getDevnetSystemScriptsFromListHashes;
|
|
3254
4407
|
exports.toCCCKnownScripts = toCCCKnownScripts;
|
|
3255
4408
|
exports.buildCCCDevnetKnownScripts = buildCCCDevnetKnownScripts;
|
|
4409
|
+
exports.buildDevnetCCCClient = buildDevnetCCCClient;
|
|
3256
4410
|
const core_1 = __nccwpck_require__(39842);
|
|
3257
4411
|
const setting_1 = __nccwpck_require__(25546);
|
|
3258
|
-
const system_scripts_1 = __nccwpck_require__(86198);
|
|
3259
4412
|
const list_hashes_1 = __nccwpck_require__(31603);
|
|
3260
4413
|
const logger_1 = __nccwpck_require__(65370);
|
|
3261
4414
|
const const_1 = __nccwpck_require__(75587);
|
|
4415
|
+
const public_1 = __nccwpck_require__(84535);
|
|
3262
4416
|
const toml_1 = __importDefault(__nccwpck_require__(2811));
|
|
3263
4417
|
const util_1 = __nccwpck_require__(58642);
|
|
3264
|
-
function
|
|
4418
|
+
function buildSystemScriptsFromSpecHashes(chainSpecHashes) {
|
|
3265
4419
|
var _a;
|
|
3266
|
-
const settings = (0, setting_1.readSettings)();
|
|
3267
|
-
const listHashesString = (0, list_hashes_1.getDevnetListHashes)(settings.bins.defaultCKBVersion);
|
|
3268
|
-
if (!listHashesString) {
|
|
3269
|
-
logger_1.logger.info(`list-hashes not found!`);
|
|
3270
|
-
return null;
|
|
3271
|
-
}
|
|
3272
|
-
const listHashes = toml_1.default.parse(listHashesString);
|
|
3273
|
-
const chainSpecHashes = Object.values(listHashes)[0];
|
|
3274
|
-
if (chainSpecHashes == null) {
|
|
3275
|
-
throw new Error(`invalid chain spec hashes file ${listHashesString}`);
|
|
3276
|
-
}
|
|
3277
4420
|
const systemScriptArray = chainSpecHashes.system_cells
|
|
3278
4421
|
.map((cell) => {
|
|
3279
4422
|
// Extract the file name from the path using the helper function
|
|
@@ -3286,7 +4429,7 @@ function getDevnetSystemScriptsFromListHashes() {
|
|
|
3286
4429
|
txHash: chainSpecHashes.dep_groups[depGroupIndex].tx_hash,
|
|
3287
4430
|
index: chainSpecHashes.dep_groups[depGroupIndex].index,
|
|
3288
4431
|
};
|
|
3289
|
-
const scriptInfo = (0,
|
|
4432
|
+
const scriptInfo = (0, util_1.systemCellToScriptInfo)({ cell, depType, depGroup });
|
|
3290
4433
|
return {
|
|
3291
4434
|
name,
|
|
3292
4435
|
file: cell.path,
|
|
@@ -3306,6 +4449,46 @@ function getDevnetSystemScriptsFromListHashes() {
|
|
|
3306
4449
|
systemScripts.type_id = const_1.TYPE_ID_SCRIPT;
|
|
3307
4450
|
return systemScripts;
|
|
3308
4451
|
}
|
|
4452
|
+
// `ckb list-hashes` only reports what the chain spec declares in genesis.
|
|
4453
|
+
// Post-genesis deployments (sudt/xudt/omnilock/spore on mainnet and testnet)
|
|
4454
|
+
// can never appear there, so for a forked devnet we fill the gaps from the
|
|
4455
|
+
// well-known static records of the chain the genesis belongs to. Genesis
|
|
4456
|
+
// scripts always come from list-hashes — the chain's own spec wins.
|
|
4457
|
+
function supplementFromStaticRecord(scripts, staticRecord) {
|
|
4458
|
+
for (const [name, script] of Object.entries(staticRecord)) {
|
|
4459
|
+
const key = name;
|
|
4460
|
+
if (scripts[key] == null && script != null) {
|
|
4461
|
+
// deep clone so callers can never mutate the shared static record
|
|
4462
|
+
scripts[key] = JSON.parse(JSON.stringify(script));
|
|
4463
|
+
}
|
|
4464
|
+
}
|
|
4465
|
+
}
|
|
4466
|
+
function resolveDevnetSystemScripts() {
|
|
4467
|
+
const settings = (0, setting_1.readSettings)();
|
|
4468
|
+
const listHashesString = (0, list_hashes_1.getDevnetListHashes)(settings.bins.defaultCKBVersion);
|
|
4469
|
+
if (!listHashesString) {
|
|
4470
|
+
logger_1.logger.info(`list-hashes not found!`);
|
|
4471
|
+
return null;
|
|
4472
|
+
}
|
|
4473
|
+
const listHashes = toml_1.default.parse(listHashesString);
|
|
4474
|
+
const chainSpecHashes = Object.values(listHashes)[0];
|
|
4475
|
+
if (chainSpecHashes == null) {
|
|
4476
|
+
throw new Error(`invalid chain spec hashes file ${listHashesString}`);
|
|
4477
|
+
}
|
|
4478
|
+
const scripts = buildSystemScriptsFromSpecHashes(chainSpecHashes);
|
|
4479
|
+
const forkedFrom = (0, const_1.identifyPublicChainByGenesisHash)(chainSpecHashes.genesis);
|
|
4480
|
+
if (forkedFrom === 'mainnet') {
|
|
4481
|
+
supplementFromStaticRecord(scripts, public_1.MAINNET_SYSTEM_SCRIPTS);
|
|
4482
|
+
}
|
|
4483
|
+
else if (forkedFrom === 'testnet') {
|
|
4484
|
+
supplementFromStaticRecord(scripts, public_1.TESTNET_SYSTEM_SCRIPTS);
|
|
4485
|
+
}
|
|
4486
|
+
return { scripts, forkedFrom, genesisHash: chainSpecHashes.genesis };
|
|
4487
|
+
}
|
|
4488
|
+
function getDevnetSystemScriptsFromListHashes() {
|
|
4489
|
+
var _a, _b;
|
|
4490
|
+
return (_b = (_a = resolveDevnetSystemScripts()) === null || _a === void 0 ? void 0 : _a.scripts) !== null && _b !== void 0 ? _b : null;
|
|
4491
|
+
}
|
|
3309
4492
|
function toCCCKnownScripts(scripts) {
|
|
3310
4493
|
const DEVNET_SCRIPTS = {
|
|
3311
4494
|
[core_1.KnownScript.Secp256k1Blake160]: scripts.secp256k1_blake160_sighash_all.script,
|
|
@@ -3333,6 +4516,19 @@ function buildCCCDevnetKnownScripts() {
|
|
|
3333
4516
|
const devnetKnownScripts = toCCCKnownScripts(devnetSystemScripts);
|
|
3334
4517
|
return devnetKnownScripts;
|
|
3335
4518
|
}
|
|
4519
|
+
// Build the ccc client for the devnet. A forked devnet carries the source
|
|
4520
|
+
// chain's genesis, so a mainnet fork must use the `ckb` address prefix
|
|
4521
|
+
// (ClientPublicMainnet); everything else uses the `ckt` prefix. Known scripts
|
|
4522
|
+
// always come from the fork-aware resolver above.
|
|
4523
|
+
function buildDevnetCCCClient(url, fallbacks = []) {
|
|
4524
|
+
const resolved = resolveDevnetSystemScripts();
|
|
4525
|
+
if (resolved == null) {
|
|
4526
|
+
throw new Error('can not getSystemScriptsFromListHashes in devnet');
|
|
4527
|
+
}
|
|
4528
|
+
const scripts = toCCCKnownScripts(resolved.scripts);
|
|
4529
|
+
const ClientCtor = resolved.forkedFrom === 'mainnet' ? core_1.ccc.ClientPublicMainnet : core_1.ccc.ClientPublicTestnet;
|
|
4530
|
+
return new ClientCtor({ url, scripts, fallbacks });
|
|
4531
|
+
}
|
|
3336
4532
|
|
|
3337
4533
|
|
|
3338
4534
|
/***/ }),
|
|
@@ -3717,6 +4913,7 @@ Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
|
3717
4913
|
exports.readDeployedScriptInfoFrom = readDeployedScriptInfoFrom;
|
|
3718
4914
|
exports.getScriptInfoFrom = getScriptInfoFrom;
|
|
3719
4915
|
exports.extractScriptNameFromPath = extractScriptNameFromPath;
|
|
4916
|
+
exports.systemCellToScriptInfo = systemCellToScriptInfo;
|
|
3720
4917
|
const fs = __importStar(__nccwpck_require__(79896));
|
|
3721
4918
|
const migration_1 = __nccwpck_require__(76679);
|
|
3722
4919
|
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
@@ -3807,6 +5004,57 @@ function extractScriptNameFromPath(pathString) {
|
|
|
3807
5004
|
// On Windows, it handles backslashes; on Unix, it handles forward slashes
|
|
3808
5005
|
return path_1.default.basename(pathString);
|
|
3809
5006
|
}
|
|
5007
|
+
function systemCellToScriptInfo({ cell, depType, depGroup, extraCellDeps, }) {
|
|
5008
|
+
// todo: we left the type in cellDepsInfo since it requires async fetching and
|
|
5009
|
+
// chain running to get the full type script of the type-id deps.
|
|
5010
|
+
// Also, in devnet there is no real need to auto upgrade the system scripts with type-id
|
|
5011
|
+
if (depType === 'code') {
|
|
5012
|
+
let cellDeps = [
|
|
5013
|
+
{
|
|
5014
|
+
cellDep: {
|
|
5015
|
+
outPoint: {
|
|
5016
|
+
txHash: cell.tx_hash,
|
|
5017
|
+
index: cell.index,
|
|
5018
|
+
},
|
|
5019
|
+
depType,
|
|
5020
|
+
},
|
|
5021
|
+
},
|
|
5022
|
+
];
|
|
5023
|
+
if (extraCellDeps && extraCellDeps.length > 0) {
|
|
5024
|
+
cellDeps = [...extraCellDeps, ...cellDeps];
|
|
5025
|
+
}
|
|
5026
|
+
return {
|
|
5027
|
+
codeHash: (cell.type_hash || cell.data_hash),
|
|
5028
|
+
hashType: cell.type_hash ? 'type' : 'data2',
|
|
5029
|
+
cellDeps,
|
|
5030
|
+
};
|
|
5031
|
+
}
|
|
5032
|
+
if (depType === 'depGroup') {
|
|
5033
|
+
if (!depGroup) {
|
|
5034
|
+
throw new Error('require depGroup info since the dep type is depGroup');
|
|
5035
|
+
}
|
|
5036
|
+
let cellDeps = [
|
|
5037
|
+
{
|
|
5038
|
+
cellDep: {
|
|
5039
|
+
outPoint: {
|
|
5040
|
+
txHash: depGroup.txHash,
|
|
5041
|
+
index: depGroup.index,
|
|
5042
|
+
},
|
|
5043
|
+
depType,
|
|
5044
|
+
},
|
|
5045
|
+
},
|
|
5046
|
+
];
|
|
5047
|
+
if (extraCellDeps && extraCellDeps.length > 0) {
|
|
5048
|
+
cellDeps = [...extraCellDeps, ...cellDeps];
|
|
5049
|
+
}
|
|
5050
|
+
return {
|
|
5051
|
+
codeHash: (cell.type_hash || cell.data_hash),
|
|
5052
|
+
hashType: cell.type_hash ? 'type' : 'data2',
|
|
5053
|
+
cellDeps,
|
|
5054
|
+
};
|
|
5055
|
+
}
|
|
5056
|
+
throw new Error(`unknown DepType ${depType}`);
|
|
5057
|
+
}
|
|
3810
5058
|
|
|
3811
5059
|
|
|
3812
5060
|
/***/ }),
|
|
@@ -3827,18 +5075,36 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
3827
5075
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
3828
5076
|
});
|
|
3829
5077
|
};
|
|
5078
|
+
var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
5079
|
+
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
|
|
5080
|
+
var m = o[Symbol.asyncIterator], i;
|
|
5081
|
+
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
|
|
5082
|
+
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
5083
|
+
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
5084
|
+
};
|
|
3830
5085
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
3831
5086
|
exports.CKB = exports.CKBProps = void 0;
|
|
3832
5087
|
const core_1 = __nccwpck_require__(39842);
|
|
3833
5088
|
const validator_1 = __nccwpck_require__(39534);
|
|
3834
5089
|
const network_1 = __nccwpck_require__(5370);
|
|
3835
5090
|
const private_1 = __nccwpck_require__(5835);
|
|
5091
|
+
const public_1 = __nccwpck_require__(84535);
|
|
3836
5092
|
const migration_1 = __nccwpck_require__(76679);
|
|
3837
5093
|
const base_1 = __nccwpck_require__(69951);
|
|
3838
5094
|
const logger_1 = __nccwpck_require__(65370);
|
|
5095
|
+
const DEFAULT_UDT_SCAN_MAX_CELLS = 1000;
|
|
5096
|
+
const DEFAULT_UDT_DESTROY_MAX_INPUT_CELLS = 100;
|
|
3839
5097
|
class CKBProps {
|
|
3840
5098
|
}
|
|
3841
5099
|
exports.CKBProps = CKBProps;
|
|
5100
|
+
function readUdtBalance(outputData) {
|
|
5101
|
+
try {
|
|
5102
|
+
return BigInt(core_1.ccc.udtBalanceFrom(outputData));
|
|
5103
|
+
}
|
|
5104
|
+
catch (_a) {
|
|
5105
|
+
return null;
|
|
5106
|
+
}
|
|
5107
|
+
}
|
|
3842
5108
|
class CKB {
|
|
3843
5109
|
constructor({ network = base_1.Network.devnet, feeRate = 1000, isEnableProxyRpc = true }) {
|
|
3844
5110
|
if (!(0, validator_1.isValidNetworkString)(network)) {
|
|
@@ -3856,11 +5122,7 @@ class CKB {
|
|
|
3856
5122
|
url: network_1.networks.testnet.proxy_rpc_url,
|
|
3857
5123
|
fallbacks: [network_1.networks.testnet.rpc_url],
|
|
3858
5124
|
}) // we keep the fallbacks in case the proxy rpc is not started
|
|
3859
|
-
:
|
|
3860
|
-
url: network_1.networks.devnet.proxy_rpc_url,
|
|
3861
|
-
scripts: (0, private_1.buildCCCDevnetKnownScripts)(),
|
|
3862
|
-
fallbacks: [network_1.networks.devnet.rpc_url],
|
|
3863
|
-
});
|
|
5125
|
+
: (0, private_1.buildDevnetCCCClient)(network_1.networks.devnet.proxy_rpc_url, [network_1.networks.devnet.rpc_url]);
|
|
3864
5126
|
}
|
|
3865
5127
|
else {
|
|
3866
5128
|
this.client =
|
|
@@ -3874,11 +5136,7 @@ class CKB {
|
|
|
3874
5136
|
url: network_1.networks.testnet.rpc_url,
|
|
3875
5137
|
fallbacks: [],
|
|
3876
5138
|
}) // pass it to avoid using websocket and fallback RPCs
|
|
3877
|
-
:
|
|
3878
|
-
url: network_1.networks.devnet.rpc_url,
|
|
3879
|
-
scripts: (0, private_1.buildCCCDevnetKnownScripts)(),
|
|
3880
|
-
fallbacks: [], // pass it to avoid using websocket and fallback RPCs
|
|
3881
|
-
});
|
|
5139
|
+
: (0, private_1.buildDevnetCCCClient)(network_1.networks.devnet.rpc_url);
|
|
3882
5140
|
}
|
|
3883
5141
|
}
|
|
3884
5142
|
buildSigner(privateKey) {
|
|
@@ -3972,6 +5230,286 @@ class CKB {
|
|
|
3972
5230
|
return txHash;
|
|
3973
5231
|
});
|
|
3974
5232
|
}
|
|
5233
|
+
getSystemScripts() {
|
|
5234
|
+
if (this.network === base_1.Network.mainnet) {
|
|
5235
|
+
return public_1.MAINNET_SYSTEM_SCRIPTS;
|
|
5236
|
+
}
|
|
5237
|
+
if (this.network === base_1.Network.testnet) {
|
|
5238
|
+
return public_1.TESTNET_SYSTEM_SCRIPTS;
|
|
5239
|
+
}
|
|
5240
|
+
const scripts = (0, private_1.getDevnetSystemScriptsFromListHashes)();
|
|
5241
|
+
if (!scripts) {
|
|
5242
|
+
throw new Error(`Failed to load devnet system scripts`);
|
|
5243
|
+
}
|
|
5244
|
+
return scripts;
|
|
5245
|
+
}
|
|
5246
|
+
buildUdtTypeScript(kind, args) {
|
|
5247
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
5248
|
+
if (kind === 'xudt') {
|
|
5249
|
+
return core_1.ccc.Script.fromKnownScript(this.client, core_1.ccc.KnownScript.XUdt, args);
|
|
5250
|
+
}
|
|
5251
|
+
const scriptInfo = yield this.getUdtScriptInfo(kind);
|
|
5252
|
+
return core_1.ccc.Script.from({
|
|
5253
|
+
codeHash: scriptInfo.codeHash,
|
|
5254
|
+
hashType: scriptInfo.hashType,
|
|
5255
|
+
args,
|
|
5256
|
+
});
|
|
5257
|
+
});
|
|
5258
|
+
}
|
|
5259
|
+
getUdtScriptInfo(kind) {
|
|
5260
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
5261
|
+
var _a;
|
|
5262
|
+
if (kind === 'xudt') {
|
|
5263
|
+
return this.client.getKnownScript(core_1.ccc.KnownScript.XUdt);
|
|
5264
|
+
}
|
|
5265
|
+
const systemScripts = this.getSystemScripts();
|
|
5266
|
+
const sudtScript = (_a = systemScripts.sudt) === null || _a === void 0 ? void 0 : _a.script;
|
|
5267
|
+
if (!sudtScript) {
|
|
5268
|
+
throw new Error(`SUDT script not found on ${this.network}`);
|
|
5269
|
+
}
|
|
5270
|
+
return sudtScript;
|
|
5271
|
+
});
|
|
5272
|
+
}
|
|
5273
|
+
detectUdtBalances(address_1) {
|
|
5274
|
+
return __awaiter(this, arguments, void 0, function* (address, { maxCells = DEFAULT_UDT_SCAN_MAX_CELLS } = {}) {
|
|
5275
|
+
const lock = (yield core_1.ccc.Address.fromString(address, this.client)).script;
|
|
5276
|
+
const sudtScriptInfo = yield this.getUdtScriptInfo('sudt').catch(() => null);
|
|
5277
|
+
const xudtScriptInfo = yield this.getUdtScriptInfo('xudt').catch(() => null);
|
|
5278
|
+
const balances = new Map();
|
|
5279
|
+
let scanned = 0;
|
|
5280
|
+
const scan = (scriptInfo, kind) => __awaiter(this, void 0, void 0, function* () {
|
|
5281
|
+
var _a, e_1, _b, _c;
|
|
5282
|
+
var _d, _e;
|
|
5283
|
+
try {
|
|
5284
|
+
for (var _f = true, _g = __asyncValues(this.client.findCells({
|
|
5285
|
+
script: {
|
|
5286
|
+
codeHash: scriptInfo.codeHash,
|
|
5287
|
+
hashType: scriptInfo.hashType,
|
|
5288
|
+
args: '0x',
|
|
5289
|
+
},
|
|
5290
|
+
scriptType: 'type',
|
|
5291
|
+
scriptSearchMode: 'prefix',
|
|
5292
|
+
filter: { script: lock },
|
|
5293
|
+
withData: true,
|
|
5294
|
+
}, 'asc')), _h; _h = yield _g.next(), _a = _h.done, !_a; _f = true) {
|
|
5295
|
+
_c = _h.value;
|
|
5296
|
+
_f = false;
|
|
5297
|
+
const cell = _c;
|
|
5298
|
+
if (scanned >= maxCells) {
|
|
5299
|
+
logger_1.logger.warn(`UDT balance scan stopped after ${maxCells} cells; balances may be incomplete`);
|
|
5300
|
+
break;
|
|
5301
|
+
}
|
|
5302
|
+
scanned++;
|
|
5303
|
+
const type = cell.cellOutput.type;
|
|
5304
|
+
if (!type) {
|
|
5305
|
+
continue;
|
|
5306
|
+
}
|
|
5307
|
+
const cellBalance = readUdtBalance(cell.outputData);
|
|
5308
|
+
if (cellBalance == null) {
|
|
5309
|
+
logger_1.logger.debug(`Skipping corrupted UDT cell ${(_d = cell.outPoint) === null || _d === void 0 ? void 0 : _d.txHash}:${(_e = cell.outPoint) === null || _e === void 0 ? void 0 : _e.index}`);
|
|
5310
|
+
continue;
|
|
5311
|
+
}
|
|
5312
|
+
const key = `${kind}:${type.codeHash}:${type.hashType}:${type.args}`;
|
|
5313
|
+
const entry = balances.get(key);
|
|
5314
|
+
if (entry) {
|
|
5315
|
+
entry.balance += cellBalance;
|
|
5316
|
+
}
|
|
5317
|
+
else {
|
|
5318
|
+
balances.set(key, {
|
|
5319
|
+
kind,
|
|
5320
|
+
codeHash: type.codeHash,
|
|
5321
|
+
hashType: String(type.hashType),
|
|
5322
|
+
args: type.args,
|
|
5323
|
+
balance: cellBalance,
|
|
5324
|
+
});
|
|
5325
|
+
}
|
|
5326
|
+
}
|
|
5327
|
+
}
|
|
5328
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
5329
|
+
finally {
|
|
5330
|
+
try {
|
|
5331
|
+
if (!_f && !_a && (_b = _g.return)) yield _b.call(_g);
|
|
5332
|
+
}
|
|
5333
|
+
finally { if (e_1) throw e_1.error; }
|
|
5334
|
+
}
|
|
5335
|
+
});
|
|
5336
|
+
if (sudtScriptInfo) {
|
|
5337
|
+
yield scan(sudtScriptInfo, 'sudt');
|
|
5338
|
+
}
|
|
5339
|
+
if (xudtScriptInfo) {
|
|
5340
|
+
yield scan(xudtScriptInfo, 'xudt');
|
|
5341
|
+
}
|
|
5342
|
+
return Array.from(balances.values()).map((item) => (Object.assign(Object.assign({}, item), { balance: item.balance.toString() })));
|
|
5343
|
+
});
|
|
5344
|
+
}
|
|
5345
|
+
udtBalance(address_1, udtType_1) {
|
|
5346
|
+
return __awaiter(this, arguments, void 0, function* (address, udtType, { maxCells = DEFAULT_UDT_SCAN_MAX_CELLS } = {}) {
|
|
5347
|
+
var _a, e_2, _b, _c;
|
|
5348
|
+
const lock = (yield core_1.ccc.Address.fromString(address, this.client)).script;
|
|
5349
|
+
let balance = BigInt(0);
|
|
5350
|
+
let scanned = 0;
|
|
5351
|
+
try {
|
|
5352
|
+
for (var _d = true, _e = __asyncValues(this.client.findCellsByLock(lock, udtType, true)), _f; _f = yield _e.next(), _a = _f.done, !_a; _d = true) {
|
|
5353
|
+
_c = _f.value;
|
|
5354
|
+
_d = false;
|
|
5355
|
+
const cell = _c;
|
|
5356
|
+
scanned++;
|
|
5357
|
+
if (scanned > maxCells) {
|
|
5358
|
+
logger_1.logger.warn(`UDT balance scan stopped after ${maxCells} cells; balances may be incomplete`);
|
|
5359
|
+
break;
|
|
5360
|
+
}
|
|
5361
|
+
const cellBalance = readUdtBalance(cell.outputData);
|
|
5362
|
+
if (cellBalance != null) {
|
|
5363
|
+
balance += cellBalance;
|
|
5364
|
+
}
|
|
5365
|
+
}
|
|
5366
|
+
}
|
|
5367
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
5368
|
+
finally {
|
|
5369
|
+
try {
|
|
5370
|
+
if (!_d && !_a && (_b = _e.return)) yield _b.call(_e);
|
|
5371
|
+
}
|
|
5372
|
+
finally { if (e_2) throw e_2.error; }
|
|
5373
|
+
}
|
|
5374
|
+
return balance.toString();
|
|
5375
|
+
});
|
|
5376
|
+
}
|
|
5377
|
+
udtTransfer(_a) {
|
|
5378
|
+
return __awaiter(this, arguments, void 0, function* ({ privateKey, toAddress, amount, udtType, kind }) {
|
|
5379
|
+
const signer = this.buildSigner(privateKey);
|
|
5380
|
+
const to = yield core_1.ccc.Address.fromString(toAddress, this.client);
|
|
5381
|
+
const amountBigInt = (0, validator_1.validateUdtAmount)(amount);
|
|
5382
|
+
const outputsData = [core_1.ccc.hexFrom(core_1.ccc.numToBytes(amountBigInt, 16))];
|
|
5383
|
+
const tx = core_1.ccc.Transaction.from({
|
|
5384
|
+
outputs: [
|
|
5385
|
+
{
|
|
5386
|
+
lock: to.script,
|
|
5387
|
+
type: udtType,
|
|
5388
|
+
capacity: core_1.ccc.fixedPointFrom(0),
|
|
5389
|
+
},
|
|
5390
|
+
],
|
|
5391
|
+
outputsData,
|
|
5392
|
+
});
|
|
5393
|
+
const scriptInfo = yield this.getUdtScriptInfo(kind);
|
|
5394
|
+
tx.addCellDeps(scriptInfo.cellDeps.map((dep) => dep.cellDep));
|
|
5395
|
+
yield tx.completeInputsByUdt(signer, udtType);
|
|
5396
|
+
const inputsUdtBalance = yield tx.getInputsUdtBalance(this.client, udtType);
|
|
5397
|
+
const outputsUdtBalance = tx.getOutputsUdtBalance(udtType);
|
|
5398
|
+
const changeAmount = inputsUdtBalance - outputsUdtBalance;
|
|
5399
|
+
if (changeAmount > BigInt(0)) {
|
|
5400
|
+
const from = yield signer.getAddressObjSecp256k1();
|
|
5401
|
+
tx.outputs.push(core_1.ccc.CellOutput.from({
|
|
5402
|
+
lock: from.script,
|
|
5403
|
+
type: udtType,
|
|
5404
|
+
capacity: core_1.ccc.fixedPointFrom(0),
|
|
5405
|
+
}, core_1.ccc.hexFrom(core_1.ccc.numToBytes(changeAmount, 16))));
|
|
5406
|
+
tx.outputsData.push(core_1.ccc.hexFrom(core_1.ccc.numToBytes(changeAmount, 16)));
|
|
5407
|
+
}
|
|
5408
|
+
yield tx.completeFeeBy(signer, this.feeRate);
|
|
5409
|
+
const txHash = yield signer.sendTransaction(tx);
|
|
5410
|
+
return txHash;
|
|
5411
|
+
});
|
|
5412
|
+
}
|
|
5413
|
+
udtIssue(_a) {
|
|
5414
|
+
return __awaiter(this, arguments, void 0, function* ({ privateKey, kind, amount, typeArgs, toAddress }) {
|
|
5415
|
+
const signer = this.buildSigner(privateKey);
|
|
5416
|
+
const signerAddress = yield signer.getAddressObjSecp256k1();
|
|
5417
|
+
const to = toAddress ? yield core_1.ccc.Address.fromString(toAddress, this.client) : signerAddress;
|
|
5418
|
+
const amountBigInt = (0, validator_1.validateUdtAmount)(amount);
|
|
5419
|
+
let resolvedTypeArgs;
|
|
5420
|
+
if (kind === 'sudt') {
|
|
5421
|
+
if (typeArgs) {
|
|
5422
|
+
logger_1.logger.warn('SUDT type args are derived from the issuer lock hash; --type-args is ignored');
|
|
5423
|
+
}
|
|
5424
|
+
const issuerLockHash = signerAddress.script.hash();
|
|
5425
|
+
resolvedTypeArgs = ('0x' + issuerLockHash.slice(2, 42));
|
|
5426
|
+
}
|
|
5427
|
+
else {
|
|
5428
|
+
if (typeArgs) {
|
|
5429
|
+
resolvedTypeArgs = (0, validator_1.validateUdtTypeArgs)(kind, typeArgs);
|
|
5430
|
+
}
|
|
5431
|
+
else {
|
|
5432
|
+
const issuerLockHash = signerAddress.script.hash();
|
|
5433
|
+
resolvedTypeArgs = issuerLockHash;
|
|
5434
|
+
}
|
|
5435
|
+
}
|
|
5436
|
+
const udtType = yield this.buildUdtTypeScript(kind, resolvedTypeArgs);
|
|
5437
|
+
const outputsData = [core_1.ccc.hexFrom(core_1.ccc.numToBytes(amountBigInt, 16))];
|
|
5438
|
+
const tx = core_1.ccc.Transaction.from({
|
|
5439
|
+
outputs: [
|
|
5440
|
+
{
|
|
5441
|
+
lock: to.script,
|
|
5442
|
+
type: udtType,
|
|
5443
|
+
capacity: core_1.ccc.fixedPointFrom(0),
|
|
5444
|
+
},
|
|
5445
|
+
],
|
|
5446
|
+
outputsData,
|
|
5447
|
+
});
|
|
5448
|
+
const scriptInfo = yield this.getUdtScriptInfo(kind);
|
|
5449
|
+
tx.addCellDeps(scriptInfo.cellDeps.map((dep) => dep.cellDep));
|
|
5450
|
+
yield tx.completeInputsByCapacity(signer);
|
|
5451
|
+
yield tx.completeFeeBy(signer, this.feeRate);
|
|
5452
|
+
const txHash = yield signer.sendTransaction(tx);
|
|
5453
|
+
return txHash;
|
|
5454
|
+
});
|
|
5455
|
+
}
|
|
5456
|
+
udtDestroy(_a) {
|
|
5457
|
+
return __awaiter(this, arguments, void 0, function* ({ privateKey, kind, typeArgs, amount }, { maxInputCells = DEFAULT_UDT_DESTROY_MAX_INPUT_CELLS } = {}) {
|
|
5458
|
+
var _b, e_3, _c, _d;
|
|
5459
|
+
const signer = this.buildSigner(privateKey);
|
|
5460
|
+
const from = yield signer.getAddressObjSecp256k1();
|
|
5461
|
+
const validatedTypeArgs = (0, validator_1.validateUdtTypeArgs)(kind, typeArgs);
|
|
5462
|
+
const udtType = yield this.buildUdtTypeScript(kind, validatedTypeArgs);
|
|
5463
|
+
const destroyAmount = (0, validator_1.validateUdtAmount)(amount);
|
|
5464
|
+
const cells = [];
|
|
5465
|
+
let totalBalance = BigInt(0);
|
|
5466
|
+
try {
|
|
5467
|
+
for (var _e = true, _f = __asyncValues(this.client.findCellsByLock(from.script, udtType, true)), _g; _g = yield _f.next(), _b = _g.done, !_b; _e = true) {
|
|
5468
|
+
_d = _g.value;
|
|
5469
|
+
_e = false;
|
|
5470
|
+
const cell = _d;
|
|
5471
|
+
if (cells.length >= maxInputCells) {
|
|
5472
|
+
throw new Error(`Too many UDT cells to destroy (limit: ${maxInputCells}); split into smaller operations`);
|
|
5473
|
+
}
|
|
5474
|
+
const cellBalance = readUdtBalance(cell.outputData);
|
|
5475
|
+
if (cellBalance == null) {
|
|
5476
|
+
continue;
|
|
5477
|
+
}
|
|
5478
|
+
cells.push(cell);
|
|
5479
|
+
totalBalance += cellBalance;
|
|
5480
|
+
}
|
|
5481
|
+
}
|
|
5482
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
5483
|
+
finally {
|
|
5484
|
+
try {
|
|
5485
|
+
if (!_e && !_b && (_c = _f.return)) yield _c.call(_f);
|
|
5486
|
+
}
|
|
5487
|
+
finally { if (e_3) throw e_3.error; }
|
|
5488
|
+
}
|
|
5489
|
+
if (totalBalance < destroyAmount) {
|
|
5490
|
+
throw new Error(`Insufficient UDT balance: ${totalBalance} < ${destroyAmount}`);
|
|
5491
|
+
}
|
|
5492
|
+
if (destroyAmount === totalBalance) {
|
|
5493
|
+
throw new Error('Destroying the entire UDT balance may be rejected by the UDT script. Leave at least 1 token or use a smaller amount.');
|
|
5494
|
+
}
|
|
5495
|
+
const tx = core_1.ccc.Transaction.from({});
|
|
5496
|
+
for (const cell of cells) {
|
|
5497
|
+
tx.addInput({ previousOutput: cell.outPoint });
|
|
5498
|
+
}
|
|
5499
|
+
const remaining = totalBalance - destroyAmount;
|
|
5500
|
+
tx.addOutput(core_1.ccc.CellOutput.from({
|
|
5501
|
+
lock: from.script,
|
|
5502
|
+
type: udtType,
|
|
5503
|
+
capacity: core_1.ccc.fixedPointFrom(0),
|
|
5504
|
+
}, core_1.ccc.hexFrom(core_1.ccc.numToBytes(remaining, 16))), core_1.ccc.hexFrom(core_1.ccc.numToBytes(remaining, 16)));
|
|
5505
|
+
const scriptInfo = yield this.getUdtScriptInfo(kind);
|
|
5506
|
+
tx.addCellDeps(scriptInfo.cellDeps.map((dep) => dep.cellDep));
|
|
5507
|
+
yield tx.completeInputsByCapacity(signer);
|
|
5508
|
+
yield tx.completeFeeBy(signer, this.feeRate);
|
|
5509
|
+
const txHash = yield signer.sendTransaction(tx);
|
|
5510
|
+
return txHash;
|
|
5511
|
+
});
|
|
5512
|
+
}
|
|
3975
5513
|
deployScript(scriptBinBytes, privateKey) {
|
|
3976
5514
|
return __awaiter(this, void 0, void 0, function* () {
|
|
3977
5515
|
const signer = this.buildSigner(privateKey);
|
|
@@ -5321,6 +6859,314 @@ exports.CKBDebugger = CKBDebugger;
|
|
|
5321
6859
|
CKBDebugger.wasmDebugger = null;
|
|
5322
6860
|
|
|
5323
6861
|
|
|
6862
|
+
/***/ }),
|
|
6863
|
+
|
|
6864
|
+
/***/ 7020:
|
|
6865
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
6866
|
+
|
|
6867
|
+
"use strict";
|
|
6868
|
+
|
|
6869
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6870
|
+
if (k2 === undefined) k2 = k;
|
|
6871
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6872
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6873
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
6874
|
+
}
|
|
6875
|
+
Object.defineProperty(o, k2, desc);
|
|
6876
|
+
}) : (function(o, m, k, k2) {
|
|
6877
|
+
if (k2 === undefined) k2 = k;
|
|
6878
|
+
o[k2] = m[k];
|
|
6879
|
+
}));
|
|
6880
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
6881
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
6882
|
+
}) : function(o, v) {
|
|
6883
|
+
o["default"] = v;
|
|
6884
|
+
});
|
|
6885
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
6886
|
+
var ownKeys = function(o) {
|
|
6887
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
6888
|
+
var ar = [];
|
|
6889
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
6890
|
+
return ar;
|
|
6891
|
+
};
|
|
6892
|
+
return ownKeys(o);
|
|
6893
|
+
};
|
|
6894
|
+
return function (mod) {
|
|
6895
|
+
if (mod && mod.__esModule) return mod;
|
|
6896
|
+
var result = {};
|
|
6897
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
6898
|
+
__setModuleDefault(result, mod);
|
|
6899
|
+
return result;
|
|
6900
|
+
};
|
|
6901
|
+
})();
|
|
6902
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6903
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
6904
|
+
};
|
|
6905
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
6906
|
+
exports.CKBTui = void 0;
|
|
6907
|
+
const child_process_1 = __nccwpck_require__(35317);
|
|
6908
|
+
const path = __importStar(__nccwpck_require__(16928));
|
|
6909
|
+
const fs = __importStar(__nccwpck_require__(79896));
|
|
6910
|
+
const os = __importStar(__nccwpck_require__(70857));
|
|
6911
|
+
const crypto = __importStar(__nccwpck_require__(76982));
|
|
6912
|
+
const adm_zip_1 = __importDefault(__nccwpck_require__(3858));
|
|
6913
|
+
const setting_1 = __nccwpck_require__(25546);
|
|
6914
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
6915
|
+
const fs_1 = __nccwpck_require__(37293);
|
|
6916
|
+
const DOWNLOAD_TIMEOUT_MS = 120000;
|
|
6917
|
+
const EXTRACT_TIMEOUT_MS = 60000;
|
|
6918
|
+
// Strict semver regex: v<major>.<minor>.<patch> (no leading zeros on digits)
|
|
6919
|
+
const STRICT_VERSION_REGEX = /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
|
|
6920
|
+
class CKBTui {
|
|
6921
|
+
/**
|
|
6922
|
+
* Pure lookup — returns the expected binary path without triggering any
|
|
6923
|
+
* download or installation side effects. May return null if not yet computed.
|
|
6924
|
+
*/
|
|
6925
|
+
static getBinaryPath() {
|
|
6926
|
+
if (!this.binaryPath) {
|
|
6927
|
+
const settings = (0, setting_1.readSettings)();
|
|
6928
|
+
const binDir = this.resolveAndValidateBinDir(settings.tools.rootFolder);
|
|
6929
|
+
const binaryName = process.platform === 'win32' ? 'ckb-tui.exe' : 'ckb-tui';
|
|
6930
|
+
this.binaryPath = path.join(binDir, binaryName);
|
|
6931
|
+
}
|
|
6932
|
+
return this.binaryPath;
|
|
6933
|
+
}
|
|
6934
|
+
/**
|
|
6935
|
+
* Returns the binary path, downloading and installing if the binary
|
|
6936
|
+
* does not already exist.
|
|
6937
|
+
*/
|
|
6938
|
+
static ensureInstalled() {
|
|
6939
|
+
const binaryPath = this.getBinaryPath();
|
|
6940
|
+
if (binaryPath && fs.existsSync(binaryPath)) {
|
|
6941
|
+
return binaryPath;
|
|
6942
|
+
}
|
|
6943
|
+
// Reset and re-install
|
|
6944
|
+
this.binaryPath = null;
|
|
6945
|
+
this.installSync();
|
|
6946
|
+
return this.binaryPath;
|
|
6947
|
+
}
|
|
6948
|
+
static isInstalled() {
|
|
6949
|
+
try {
|
|
6950
|
+
const binPath = this.getBinaryPath();
|
|
6951
|
+
return binPath !== null && fs.existsSync(binPath);
|
|
6952
|
+
}
|
|
6953
|
+
catch (_a) {
|
|
6954
|
+
return false;
|
|
6955
|
+
}
|
|
6956
|
+
}
|
|
6957
|
+
static run(args = []) {
|
|
6958
|
+
const binaryPath = this.ensureInstalled();
|
|
6959
|
+
return (0, child_process_1.spawnSync)(binaryPath, args, { stdio: 'inherit' });
|
|
6960
|
+
}
|
|
6961
|
+
// --- private helpers ---
|
|
6962
|
+
/**
|
|
6963
|
+
* Resolve and validate that the configured rootFolder is under the
|
|
6964
|
+
* OffCKB data directory. Rejects paths that resolve outside.
|
|
6965
|
+
*/
|
|
6966
|
+
static resolveAndValidateBinDir(configuredRoot) {
|
|
6967
|
+
const resolved = path.resolve(configuredRoot);
|
|
6968
|
+
const resolvedData = path.resolve(setting_1.dataPath);
|
|
6969
|
+
// Require the resolved path to be within the resolved data directory
|
|
6970
|
+
const relative = path.relative(resolvedData, resolved);
|
|
6971
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
6972
|
+
throw new Error(`tools.rootFolder ("${configuredRoot}") resolves outside the OffCKB data directory ` +
|
|
6973
|
+
`("${resolvedData}"). For security, tool binaries must be stored under the data path.`);
|
|
6974
|
+
}
|
|
6975
|
+
return resolved;
|
|
6976
|
+
}
|
|
6977
|
+
static validateVersion(version) {
|
|
6978
|
+
if (!STRICT_VERSION_REGEX.test(version)) {
|
|
6979
|
+
throw new Error(`Invalid version format: "${version}". Expected format: vX.Y.Z (e.g., v0.1.3)`);
|
|
6980
|
+
}
|
|
6981
|
+
}
|
|
6982
|
+
static getAssetName() {
|
|
6983
|
+
const platform = process.platform;
|
|
6984
|
+
const arch = process.arch;
|
|
6985
|
+
if (platform === 'darwin') {
|
|
6986
|
+
if (arch !== 'arm64') {
|
|
6987
|
+
throw new Error(`Unsupported architecture for macOS: ${arch}. Only Apple Silicon (arm64) is supported.`);
|
|
6988
|
+
}
|
|
6989
|
+
return 'ckb-tui-with-node-macos-aarch64.tar.gz';
|
|
6990
|
+
}
|
|
6991
|
+
else if (platform === 'linux') {
|
|
6992
|
+
if (arch !== 'x64') {
|
|
6993
|
+
throw new Error(`Unsupported architecture for Linux: ${arch}. Only x86_64 is supported.`);
|
|
6994
|
+
}
|
|
6995
|
+
return 'ckb-tui-with-node-linux-amd64.tar.gz';
|
|
6996
|
+
}
|
|
6997
|
+
else if (platform === 'win32') {
|
|
6998
|
+
if (arch !== 'x64') {
|
|
6999
|
+
throw new Error(`Unsupported architecture for Windows: ${arch}. Only x86_64 is supported.`);
|
|
7000
|
+
}
|
|
7001
|
+
return 'ckb-tui-with-node-windows-amd64.zip';
|
|
7002
|
+
}
|
|
7003
|
+
throw new Error(`Unsupported platform: ${platform}`);
|
|
7004
|
+
}
|
|
7005
|
+
/**
|
|
7006
|
+
* Synchronously download and install the ckb-tui binary.
|
|
7007
|
+
* Uses spawnSync with array arguments (no shell interpolation) for security.
|
|
7008
|
+
*/
|
|
7009
|
+
static installSync() {
|
|
7010
|
+
const settings = (0, setting_1.readSettings)();
|
|
7011
|
+
const version = settings.tools.ckbTui.version;
|
|
7012
|
+
this.validateVersion(version);
|
|
7013
|
+
const assetName = this.getAssetName();
|
|
7014
|
+
const binDir = this.resolveAndValidateBinDir(settings.tools.rootFolder);
|
|
7015
|
+
const binaryName = process.platform === 'win32' ? 'ckb-tui.exe' : 'ckb-tui';
|
|
7016
|
+
this.binaryPath = path.join(binDir, binaryName);
|
|
7017
|
+
const downloadUrl = `https://github.com/Officeyutong/ckb-tui/releases/download/${version}/${assetName}`;
|
|
7018
|
+
// Ensure the target directory exists
|
|
7019
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
7020
|
+
// Use a temp directory for atomic download & extraction
|
|
7021
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'offckb-ckb-tui-'));
|
|
7022
|
+
const archivePath = path.join(tempDir, assetName);
|
|
7023
|
+
try {
|
|
7024
|
+
// 1. Download
|
|
7025
|
+
logger_1.logger.info(`Downloading ckb-tui from ${downloadUrl}...`);
|
|
7026
|
+
const curlResult = (0, child_process_1.spawnSync)('curl', ['-fsSL', '--max-time', '300', '-o', archivePath, downloadUrl], {
|
|
7027
|
+
stdio: 'inherit',
|
|
7028
|
+
timeout: DOWNLOAD_TIMEOUT_MS,
|
|
7029
|
+
});
|
|
7030
|
+
if (curlResult.error) {
|
|
7031
|
+
throw new Error(`Failed to download ckb-tui: ${curlResult.error.message}`);
|
|
7032
|
+
}
|
|
7033
|
+
if (curlResult.status !== 0) {
|
|
7034
|
+
throw new Error(`curl exited with code ${curlResult.status}`);
|
|
7035
|
+
}
|
|
7036
|
+
// 2. Verify checksum (best-effort: warns if checksum file is unavailable)
|
|
7037
|
+
this.verifyChecksum(version, assetName, archivePath);
|
|
7038
|
+
// 3. Extract to temp directory
|
|
7039
|
+
logger_1.logger.info('Extracting...');
|
|
7040
|
+
const extractDir = path.join(tempDir, 'extracted');
|
|
7041
|
+
fs.mkdirSync(extractDir, { recursive: true });
|
|
7042
|
+
this.extractArchive(archivePath, extractDir);
|
|
7043
|
+
// 4. Locate the extracted binary
|
|
7044
|
+
const extractedBinary = (0, fs_1.findFileInFolder)(extractDir, binaryName);
|
|
7045
|
+
if (!extractedBinary) {
|
|
7046
|
+
throw new Error(`ckb-tui binary ("${binaryName}") was not found after extraction.`);
|
|
7047
|
+
}
|
|
7048
|
+
// 5. Atomically move to the final location
|
|
7049
|
+
fs.renameSync(extractedBinary, this.binaryPath);
|
|
7050
|
+
// 6. Make executable on Unix
|
|
7051
|
+
if (process.platform !== 'win32') {
|
|
7052
|
+
fs.chmodSync(this.binaryPath, 0o755);
|
|
7053
|
+
}
|
|
7054
|
+
logger_1.logger.info('ckb-tui installed successfully.');
|
|
7055
|
+
}
|
|
7056
|
+
catch (error) {
|
|
7057
|
+
// Reset cached path on failure so a subsequent call retries
|
|
7058
|
+
this.binaryPath = null;
|
|
7059
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7060
|
+
logger_1.logger.error('Failed to download/install ckb-tui:', message, '\nPlease check your network connectivity, verify that the specified version exists in the releases, ' +
|
|
7061
|
+
'and ensure you have sufficient file system permissions.');
|
|
7062
|
+
throw error;
|
|
7063
|
+
}
|
|
7064
|
+
finally {
|
|
7065
|
+
// Clean up the temp directory
|
|
7066
|
+
try {
|
|
7067
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
7068
|
+
}
|
|
7069
|
+
catch (_a) {
|
|
7070
|
+
// Best-effort cleanup — temp dir will be cleaned by the OS eventually
|
|
7071
|
+
}
|
|
7072
|
+
}
|
|
7073
|
+
}
|
|
7074
|
+
/**
|
|
7075
|
+
* Best-effort SHA-256 checksum verification.
|
|
7076
|
+
* Downloads the checksum file published alongside the release asset and
|
|
7077
|
+
* verifies the downloaded archive. Logs a warning (but does not fail) if
|
|
7078
|
+
* the checksum file is unavailable — this maintains compatibility while
|
|
7079
|
+
* the upstream project adopts checksum publishing.
|
|
7080
|
+
*/
|
|
7081
|
+
static verifyChecksum(version, assetName, archivePath) {
|
|
7082
|
+
const checksumUrl = `https://github.com/Officeyutong/ckb-tui/releases/download/${version}/checksums-sha256.txt`;
|
|
7083
|
+
const checksumPath = path.join(path.dirname(archivePath), 'checksums-sha256.txt');
|
|
7084
|
+
const fetchResult = (0, child_process_1.spawnSync)('curl', ['-fsSL', '--max-time', '30', '-o', checksumPath, checksumUrl], {
|
|
7085
|
+
stdio: 'pipe',
|
|
7086
|
+
timeout: 30000,
|
|
7087
|
+
});
|
|
7088
|
+
if (fetchResult.status !== 0) {
|
|
7089
|
+
logger_1.logger.warn(`SHA-256 checksum file not available for version ${version}. ` +
|
|
7090
|
+
'Skipping integrity verification. Consider asking the upstream maintainer to publish checksum files.');
|
|
7091
|
+
return;
|
|
7092
|
+
}
|
|
7093
|
+
try {
|
|
7094
|
+
const checksumContent = fs.readFileSync(checksumPath, 'utf8');
|
|
7095
|
+
const expectedHash = this.parseChecksumFile(checksumContent, assetName);
|
|
7096
|
+
if (!expectedHash) {
|
|
7097
|
+
logger_1.logger.warn(`Checksum entry for "${assetName}" not found in checksums file. Skipping verification.`);
|
|
7098
|
+
return;
|
|
7099
|
+
}
|
|
7100
|
+
const actualHash = crypto.createHash('sha256').update(fs.readFileSync(archivePath)).digest('hex');
|
|
7101
|
+
if (actualHash !== expectedHash) {
|
|
7102
|
+
throw new Error(`SHA-256 checksum mismatch for ${assetName}.\n` +
|
|
7103
|
+
`Expected: ${expectedHash}\nActual: ${actualHash}\n` +
|
|
7104
|
+
'The downloaded file may be corrupted or tampered with.');
|
|
7105
|
+
}
|
|
7106
|
+
logger_1.logger.info('SHA-256 checksum verified successfully.');
|
|
7107
|
+
}
|
|
7108
|
+
finally {
|
|
7109
|
+
try {
|
|
7110
|
+
fs.unlinkSync(checksumPath);
|
|
7111
|
+
}
|
|
7112
|
+
catch (_a) {
|
|
7113
|
+
// Best effort
|
|
7114
|
+
}
|
|
7115
|
+
}
|
|
7116
|
+
}
|
|
7117
|
+
/**
|
|
7118
|
+
* Parse a standard SHA-256 checksum file (format: "<hash> <filename>" per line)
|
|
7119
|
+
* and return the hex hash for the given asset name, or null if not found.
|
|
7120
|
+
*/
|
|
7121
|
+
static parseChecksumFile(content, assetName) {
|
|
7122
|
+
for (const line of content.split('\n')) {
|
|
7123
|
+
const trimmed = line.trim();
|
|
7124
|
+
if (!trimmed || trimmed.startsWith('#'))
|
|
7125
|
+
continue;
|
|
7126
|
+
const match = trimmed.match(/^([0-9a-fA-F]{64})\s+[*]?(.+)$/);
|
|
7127
|
+
if (match && match[2] === assetName) {
|
|
7128
|
+
return match[1].toLowerCase();
|
|
7129
|
+
}
|
|
7130
|
+
}
|
|
7131
|
+
return null;
|
|
7132
|
+
}
|
|
7133
|
+
/**
|
|
7134
|
+
* Extract a downloaded archive to the given directory.
|
|
7135
|
+
* Uses AdmZip for .zip files (Node-native, no shell) and spawnSync with array
|
|
7136
|
+
* arguments for .tar.gz (no shell interpolation).
|
|
7137
|
+
*/
|
|
7138
|
+
static extractArchive(archivePath, extractDir) {
|
|
7139
|
+
if (archivePath.endsWith('.tar.gz')) {
|
|
7140
|
+
const result = (0, child_process_1.spawnSync)('tar', ['-xzf', archivePath, '-C', extractDir], {
|
|
7141
|
+
stdio: 'inherit',
|
|
7142
|
+
timeout: EXTRACT_TIMEOUT_MS,
|
|
7143
|
+
});
|
|
7144
|
+
if (result.error) {
|
|
7145
|
+
throw new Error(`tar extraction failed: ${result.error.message}`);
|
|
7146
|
+
}
|
|
7147
|
+
if (result.status !== 0) {
|
|
7148
|
+
throw new Error(`tar exited with code ${result.status}`);
|
|
7149
|
+
}
|
|
7150
|
+
}
|
|
7151
|
+
else if (archivePath.endsWith('.zip')) {
|
|
7152
|
+
try {
|
|
7153
|
+
const zip = new adm_zip_1.default(archivePath);
|
|
7154
|
+
zip.extractAllTo(extractDir, true);
|
|
7155
|
+
}
|
|
7156
|
+
catch (error) {
|
|
7157
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
7158
|
+
throw new Error(`ZIP extraction failed: ${message}`);
|
|
7159
|
+
}
|
|
7160
|
+
}
|
|
7161
|
+
else {
|
|
7162
|
+
throw new Error(`Unsupported archive format: ${path.extname(archivePath)}`);
|
|
7163
|
+
}
|
|
7164
|
+
}
|
|
7165
|
+
}
|
|
7166
|
+
exports.CKBTui = CKBTui;
|
|
7167
|
+
CKBTui.binaryPath = null;
|
|
7168
|
+
|
|
7169
|
+
|
|
5324
7170
|
/***/ }),
|
|
5325
7171
|
|
|
5326
7172
|
/***/ 20924:
|
|
@@ -5346,6 +7192,7 @@ const fs_1 = __importDefault(__nccwpck_require__(79896));
|
|
|
5346
7192
|
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
5347
7193
|
const core_1 = __nccwpck_require__(39842);
|
|
5348
7194
|
const advanced_1 = __nccwpck_require__(98486);
|
|
7195
|
+
const json_rpc_1 = __nccwpck_require__(51726);
|
|
5349
7196
|
const logger_1 = __nccwpck_require__(65370);
|
|
5350
7197
|
const OutPointCodec = core_1.ccc.mol.struct({
|
|
5351
7198
|
txHash: core_1.ccc.mol.Byte32,
|
|
@@ -5470,6 +7317,19 @@ function resolveInputs(client, inputs) {
|
|
|
5470
7317
|
return resolved;
|
|
5471
7318
|
});
|
|
5472
7319
|
}
|
|
7320
|
+
function resolveHeaderDeps(rpc, headerDeps) {
|
|
7321
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
7322
|
+
const headers = [];
|
|
7323
|
+
for (const hash of headerDeps) {
|
|
7324
|
+
const header = yield (0, json_rpc_1.callJsonRpc)(rpc, 'get_header', [hash]);
|
|
7325
|
+
if (!header) {
|
|
7326
|
+
throw new Error(`Header not found: ${hash}`);
|
|
7327
|
+
}
|
|
7328
|
+
headers.push(header);
|
|
7329
|
+
}
|
|
7330
|
+
return headers;
|
|
7331
|
+
});
|
|
7332
|
+
}
|
|
5473
7333
|
function dumpTransaction(_a) {
|
|
5474
7334
|
return __awaiter(this, arguments, void 0, function* ({ rpc, txJsonFilePath, outputFilePath }) {
|
|
5475
7335
|
try {
|
|
@@ -5485,15 +7345,16 @@ function dumpTransaction(_a) {
|
|
|
5485
7345
|
});
|
|
5486
7346
|
const txJson = JSON.parse(fs_1.default.readFileSync(txJsonFilePath, 'utf-8'));
|
|
5487
7347
|
const tx = advanced_1.cccA.JsonRpcTransformers.transactionTo(txJson);
|
|
5488
|
-
const [cell_deps, inputs] = yield Promise.all([
|
|
7348
|
+
const [cell_deps, inputs, header_deps] = yield Promise.all([
|
|
5489
7349
|
resolveCellDeps(client, tx.cellDeps),
|
|
5490
7350
|
resolveInputs(client, tx.inputs),
|
|
7351
|
+
resolveHeaderDeps(rpc, tx.headerDeps),
|
|
5491
7352
|
]);
|
|
5492
7353
|
const mockTx = {
|
|
5493
7354
|
mock_info: {
|
|
5494
7355
|
inputs,
|
|
5495
7356
|
cell_deps,
|
|
5496
|
-
header_deps
|
|
7357
|
+
header_deps,
|
|
5497
7358
|
},
|
|
5498
7359
|
tx: {
|
|
5499
7360
|
version: '0x' + tx.version.toString(16),
|
|
@@ -7746,18 +9607,107 @@ function getSubfolders(folderPath) {
|
|
|
7746
9607
|
}
|
|
7747
9608
|
|
|
7748
9609
|
|
|
9610
|
+
/***/ }),
|
|
9611
|
+
|
|
9612
|
+
/***/ 51726:
|
|
9613
|
+
/***/ (function(__unused_webpack_module, exports, __nccwpck_require__) {
|
|
9614
|
+
|
|
9615
|
+
"use strict";
|
|
9616
|
+
|
|
9617
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
9618
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
9619
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
9620
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
9621
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
9622
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
9623
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9624
|
+
});
|
|
9625
|
+
};
|
|
9626
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
9627
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
9628
|
+
};
|
|
9629
|
+
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
9630
|
+
exports.callJsonRpc = callJsonRpc;
|
|
9631
|
+
const http_1 = __importDefault(__nccwpck_require__(58611));
|
|
9632
|
+
const https_1 = __importDefault(__nccwpck_require__(65692));
|
|
9633
|
+
// Minimal raw JSON-RPC caller. Unlike Request.send it never goes through the
|
|
9634
|
+
// configured proxy, which makes it safe for talking to the local devnet node.
|
|
9635
|
+
function callJsonRpc(rpcUrl_1, method_1, params_1) {
|
|
9636
|
+
return __awaiter(this, arguments, void 0, function* (rpcUrl, method, params, timeoutMs = 30000) {
|
|
9637
|
+
const body = JSON.stringify({ id: 1, jsonrpc: '2.0', method, params });
|
|
9638
|
+
const url = new URL(rpcUrl);
|
|
9639
|
+
const transport = url.protocol === 'https:' ? https_1.default : http_1.default;
|
|
9640
|
+
return new Promise((resolve, reject) => {
|
|
9641
|
+
const req = transport.request({
|
|
9642
|
+
hostname: url.hostname,
|
|
9643
|
+
port: url.port || (url.protocol === 'https:' ? 443 : 80),
|
|
9644
|
+
path: url.pathname + url.search,
|
|
9645
|
+
method: 'POST',
|
|
9646
|
+
headers: {
|
|
9647
|
+
'content-type': 'application/json',
|
|
9648
|
+
'content-length': Buffer.byteLength(body),
|
|
9649
|
+
},
|
|
9650
|
+
timeout: timeoutMs,
|
|
9651
|
+
}, (res) => {
|
|
9652
|
+
const chunks = [];
|
|
9653
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
9654
|
+
// The response stream can error or close before `end` (connection
|
|
9655
|
+
// reset, truncated body). Without these listeners the promise would
|
|
9656
|
+
// hang until the request timeout — or the process would crash on an
|
|
9657
|
+
// unhandled stream error.
|
|
9658
|
+
res.once('error', reject);
|
|
9659
|
+
res.on('close', () => {
|
|
9660
|
+
if (!res.complete) {
|
|
9661
|
+
reject(new Error(`JSON-RPC ${method} to ${rpcUrl} returned a truncated response`));
|
|
9662
|
+
}
|
|
9663
|
+
});
|
|
9664
|
+
res.on('end', () => {
|
|
9665
|
+
try {
|
|
9666
|
+
const parsed = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
9667
|
+
if (parsed.error) {
|
|
9668
|
+
reject(new Error(`JSON-RPC ${method} failed: ${JSON.stringify(parsed.error)}`));
|
|
9669
|
+
return;
|
|
9670
|
+
}
|
|
9671
|
+
resolve(parsed.result);
|
|
9672
|
+
}
|
|
9673
|
+
catch (error) {
|
|
9674
|
+
reject(new Error(`Invalid JSON-RPC response from ${rpcUrl}: ${error.message}`));
|
|
9675
|
+
}
|
|
9676
|
+
});
|
|
9677
|
+
});
|
|
9678
|
+
req.on('timeout', () => {
|
|
9679
|
+
req.destroy(new Error(`JSON-RPC ${method} to ${rpcUrl} timed out`));
|
|
9680
|
+
});
|
|
9681
|
+
req.on('error', reject);
|
|
9682
|
+
req.write(body);
|
|
9683
|
+
req.end();
|
|
9684
|
+
});
|
|
9685
|
+
});
|
|
9686
|
+
}
|
|
9687
|
+
|
|
9688
|
+
|
|
7749
9689
|
/***/ }),
|
|
7750
9690
|
|
|
7751
9691
|
/***/ 27814:
|
|
7752
|
-
/***/ ((__unused_webpack_module, exports) => {
|
|
9692
|
+
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
7753
9693
|
|
|
7754
9694
|
"use strict";
|
|
7755
9695
|
|
|
7756
9696
|
Object.defineProperty(exports, "__esModule", ({ value: true }));
|
|
7757
9697
|
exports.buildTestnetTxLink = buildTestnetTxLink;
|
|
9698
|
+
exports.logTxSuccess = logTxSuccess;
|
|
9699
|
+
const logger_1 = __nccwpck_require__(65370);
|
|
7758
9700
|
function buildTestnetTxLink(txHash) {
|
|
7759
9701
|
return `https://pudge.explorer.nervos.org/transaction/${txHash}`;
|
|
7760
9702
|
}
|
|
9703
|
+
function logTxSuccess(network, txHash, action) {
|
|
9704
|
+
if (network === 'testnet') {
|
|
9705
|
+
logger_1.logger.info(`Successfully ${action}, check ${buildTestnetTxLink(txHash)} for details.`);
|
|
9706
|
+
}
|
|
9707
|
+
else {
|
|
9708
|
+
logger_1.logger.info(`Successfully ${action}, txHash:`, txHash);
|
|
9709
|
+
}
|
|
9710
|
+
}
|
|
7761
9711
|
|
|
7762
9712
|
|
|
7763
9713
|
/***/ }),
|
|
@@ -7819,6 +9769,7 @@ class UnifiedLogger {
|
|
|
7819
9769
|
constructor(options = {}) {
|
|
7820
9770
|
this.enableColors = options.enableColors !== false;
|
|
7821
9771
|
this.showLevel = options.showLevel !== false;
|
|
9772
|
+
this.jsonMode = options.jsonMode === true;
|
|
7822
9773
|
// Create Winston logger with custom format and levels
|
|
7823
9774
|
this.logger = winston_1.default.createLogger({
|
|
7824
9775
|
level: options.level || node_process_1.default.env.LOG_LEVEL || 'info',
|
|
@@ -7832,17 +9783,33 @@ class UnifiedLogger {
|
|
|
7832
9783
|
format: winston_1.default.format.combine(winston_1.default.format.timestamp(), winston_1.default.format.errors({ stack: true }), winston_1.default.format.printf(({ level, message, timestamp }) => {
|
|
7833
9784
|
return this.formatMessage(level, message, timestamp);
|
|
7834
9785
|
})),
|
|
7835
|
-
transports: [
|
|
9786
|
+
transports: options.transports || [
|
|
7836
9787
|
new winston_1.default.transports.Console({
|
|
7837
9788
|
stderrLevels: ['error', 'warn'],
|
|
7838
9789
|
}),
|
|
7839
9790
|
],
|
|
7840
9791
|
});
|
|
7841
9792
|
}
|
|
9793
|
+
/**
|
|
9794
|
+
* Toggle JSON output mode. When enabled, every log line is emitted as a
|
|
9795
|
+
* structured JSON object, which is easier for agents and scripts to parse.
|
|
9796
|
+
*/
|
|
9797
|
+
setJsonMode(enabled) {
|
|
9798
|
+
this.jsonMode = enabled;
|
|
9799
|
+
}
|
|
7842
9800
|
/**
|
|
7843
9801
|
* Format the message with appropriate colors and structure
|
|
7844
9802
|
*/
|
|
7845
|
-
formatMessage(level, message,
|
|
9803
|
+
formatMessage(level, message, timestamp) {
|
|
9804
|
+
// Agent-friendly JSON output: one JSON object per log line
|
|
9805
|
+
if (this.jsonMode) {
|
|
9806
|
+
const normalizedMessage = Array.isArray(message) ? message.join('\n') : String(message);
|
|
9807
|
+
return JSON.stringify({
|
|
9808
|
+
level,
|
|
9809
|
+
message: normalizedMessage,
|
|
9810
|
+
timestamp,
|
|
9811
|
+
});
|
|
9812
|
+
}
|
|
7846
9813
|
// If showLevel is false, return just the message
|
|
7847
9814
|
if (!this.showLevel) {
|
|
7848
9815
|
if (Array.isArray(message)) {
|
|
@@ -7925,6 +9892,12 @@ class UnifiedLogger {
|
|
|
7925
9892
|
* Log a message with the specified level
|
|
7926
9893
|
*/
|
|
7927
9894
|
log(level, message) {
|
|
9895
|
+
// In JSON mode, emit multi-line messages as a single structured log entry
|
|
9896
|
+
// so agents can parse one complete JSON object per line.
|
|
9897
|
+
if (this.jsonMode && Array.isArray(message)) {
|
|
9898
|
+
this.logger.log(level, message.join('\n'));
|
|
9899
|
+
return;
|
|
9900
|
+
}
|
|
7928
9901
|
if (Array.isArray(message)) {
|
|
7929
9902
|
message.forEach((line) => this.logger.log(level, line));
|
|
7930
9903
|
}
|
|
@@ -8091,6 +10064,11 @@ exports.isValidNetworkString = isValidNetworkString;
|
|
|
8091
10064
|
exports.validateNetworkOpt = validateNetworkOpt;
|
|
8092
10065
|
exports.isValidVersion = isValidVersion;
|
|
8093
10066
|
exports.normalizePrivKey = normalizePrivKey;
|
|
10067
|
+
exports.isValidUdtKind = isValidUdtKind;
|
|
10068
|
+
exports.validateUdtKind = validateUdtKind;
|
|
10069
|
+
exports.validateUdtAmount = validateUdtAmount;
|
|
10070
|
+
exports.validateHexString = validateHexString;
|
|
10071
|
+
exports.validateUdtTypeArgs = validateUdtTypeArgs;
|
|
8094
10072
|
const path_1 = __importDefault(__nccwpck_require__(16928));
|
|
8095
10073
|
const fs_1 = __importDefault(__nccwpck_require__(79896));
|
|
8096
10074
|
const base_1 = __nccwpck_require__(69951);
|
|
@@ -8179,6 +10157,46 @@ function normalizePrivKey(privKey) {
|
|
|
8179
10157
|
// Return the formally strictly padded ckb format `0x` string
|
|
8180
10158
|
return '0x' + key;
|
|
8181
10159
|
}
|
|
10160
|
+
function isValidUdtKind(kind) {
|
|
10161
|
+
return kind === 'sudt' || kind === 'xudt';
|
|
10162
|
+
}
|
|
10163
|
+
function validateUdtKind(kind) {
|
|
10164
|
+
if (!kind) {
|
|
10165
|
+
throw new Error('UDT kind is required');
|
|
10166
|
+
}
|
|
10167
|
+
if (!isValidUdtKind(kind)) {
|
|
10168
|
+
throw new Error(`invalid UDT kind "${kind}", must be "sudt" or "xudt"`);
|
|
10169
|
+
}
|
|
10170
|
+
}
|
|
10171
|
+
const U128_MAX = (BigInt(1) << BigInt(128)) - BigInt(1);
|
|
10172
|
+
function validateUdtAmount(amount) {
|
|
10173
|
+
if (!/^\d+$/.test(amount)) {
|
|
10174
|
+
throw new Error(`invalid UDT amount "${amount}", must be a non-negative decimal integer`);
|
|
10175
|
+
}
|
|
10176
|
+
const value = BigInt(amount);
|
|
10177
|
+
if (value > U128_MAX) {
|
|
10178
|
+
throw new Error(`UDT amount exceeds 128-bit max: ${amount}`);
|
|
10179
|
+
}
|
|
10180
|
+
return value;
|
|
10181
|
+
}
|
|
10182
|
+
const HEX_REGEX = /^0x[0-9a-fA-F]*$/;
|
|
10183
|
+
function validateHexString(value, name) {
|
|
10184
|
+
if (!value || !HEX_REGEX.test(value)) {
|
|
10185
|
+
throw new Error(`invalid ${name} "${value}", must be a hex string starting with 0x`);
|
|
10186
|
+
}
|
|
10187
|
+
return value;
|
|
10188
|
+
}
|
|
10189
|
+
function validateUdtTypeArgs(kind, typeArgs) {
|
|
10190
|
+
const hex = validateHexString(typeArgs, 'type args');
|
|
10191
|
+
const byteLength = (hex.length - 2) / 2;
|
|
10192
|
+
if (kind === 'sudt' && byteLength !== 20) {
|
|
10193
|
+
throw new Error(`invalid SUDT type args length: expected 20 bytes, got ${byteLength}`);
|
|
10194
|
+
}
|
|
10195
|
+
if (kind === 'xudt' && byteLength !== 32) {
|
|
10196
|
+
throw new Error(`invalid xUDT type args length: expected 32 bytes, got ${byteLength}`);
|
|
10197
|
+
}
|
|
10198
|
+
return hex;
|
|
10199
|
+
}
|
|
8182
10200
|
|
|
8183
10201
|
|
|
8184
10202
|
/***/ }),
|
|
@@ -15922,13 +17940,13 @@ exports.randomBytes = randomBytes;
|
|
|
15922
17940
|
|
|
15923
17941
|
/***/ }),
|
|
15924
17942
|
|
|
15925
|
-
/***/
|
|
17943
|
+
/***/ 3858:
|
|
15926
17944
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
15927
17945
|
|
|
15928
|
-
const Utils = __nccwpck_require__(
|
|
17946
|
+
const Utils = __nccwpck_require__(91373);
|
|
15929
17947
|
const pth = __nccwpck_require__(16928);
|
|
15930
|
-
const ZipEntry = __nccwpck_require__(
|
|
15931
|
-
const ZipFile = __nccwpck_require__(
|
|
17948
|
+
const ZipEntry = __nccwpck_require__(58851);
|
|
17949
|
+
const ZipFile = __nccwpck_require__(46593);
|
|
15932
17950
|
|
|
15933
17951
|
const get_Bool = (...val) => Utils.findLast(val, (c) => typeof c === "boolean");
|
|
15934
17952
|
const get_Str = (...val) => Utils.findLast(val, (c) => typeof c === "string");
|
|
@@ -15974,6 +17992,18 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
15974
17992
|
// instanciate utils filesystem
|
|
15975
17993
|
const filetools = new Utils(opts);
|
|
15976
17994
|
|
|
17995
|
+
// Restore the archived permissions on extracted directories. This has to run
|
|
17996
|
+
// after a directory's contents are written: applying a restrictive mode
|
|
17997
|
+
// (e.g. 0o500) up front would stop us writing the files it contains. Applying
|
|
17998
|
+
// the deepest paths first keeps parent directories traversable while their
|
|
17999
|
+
// children are updated (issue #530).
|
|
18000
|
+
const applyDirAttributes = (dirEntries) => {
|
|
18001
|
+
dirEntries
|
|
18002
|
+
.filter((d) => d.attr)
|
|
18003
|
+
.sort((a, b) => b.path.length - a.path.length)
|
|
18004
|
+
.forEach((d) => filetools.fs.chmodSync(d.path, d.attr));
|
|
18005
|
+
};
|
|
18006
|
+
|
|
15977
18007
|
if (typeof opts.decoder !== "object" || typeof opts.decoder.encode !== "function" || typeof opts.decoder.decode !== "function") {
|
|
15978
18008
|
opts.decoder = Utils.decoder;
|
|
15979
18009
|
}
|
|
@@ -16013,7 +18043,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16013
18043
|
function fixPath(zipPath) {
|
|
16014
18044
|
const { join, normalize, sep } = pth.posix;
|
|
16015
18045
|
// convert windows file separators and normalize
|
|
16016
|
-
return join(".
|
|
18046
|
+
return join(pth.isAbsolute(zipPath) ? "/": '.', normalize(sep + zipPath.split("\\").join(sep) + sep));
|
|
16017
18047
|
}
|
|
16018
18048
|
|
|
16019
18049
|
function filenameFilter(filterfn) {
|
|
@@ -16128,6 +18158,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16128
18158
|
* Remove the entry from the file or the entry and all it's nested directories and files if the given entry is a directory
|
|
16129
18159
|
*
|
|
16130
18160
|
* @param {ZipEntry|string} entry
|
|
18161
|
+
* @param {boolean} withsubfolders
|
|
16131
18162
|
* @returns {void}
|
|
16132
18163
|
*/
|
|
16133
18164
|
deleteFile: function (entry, withsubfolders = true) {
|
|
@@ -16412,7 +18443,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16412
18443
|
addLocalFolderAsync2: function (options, callback) {
|
|
16413
18444
|
const self = this;
|
|
16414
18445
|
options = typeof options === "object" ? options : { localPath: options };
|
|
16415
|
-
localPath = pth.resolve(fixPath(options.localPath));
|
|
18446
|
+
const localPath = pth.resolve(fixPath(options.localPath));
|
|
16416
18447
|
let { zipPath, filter, namefix } = options;
|
|
16417
18448
|
|
|
16418
18449
|
if (filter instanceof RegExp) {
|
|
@@ -16431,7 +18462,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16431
18462
|
zipPath = zipPath ? fixPath(zipPath) : "";
|
|
16432
18463
|
|
|
16433
18464
|
// Check Namefix function
|
|
16434
|
-
if (namefix
|
|
18465
|
+
if (namefix === "latin1") {
|
|
16435
18466
|
namefix = (str) =>
|
|
16436
18467
|
str
|
|
16437
18468
|
.normalize("NFD")
|
|
@@ -16607,7 +18638,7 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16607
18638
|
|
|
16608
18639
|
var entryName = canonical(item.entryName);
|
|
16609
18640
|
|
|
16610
|
-
var target = sanitize(targetPath, outFileName && !item.isDirectory ? outFileName : maintainEntryPath ? entryName : pth.basename(entryName));
|
|
18641
|
+
var target = sanitize(targetPath, outFileName && !item.isDirectory ? canonical(outFileName) : maintainEntryPath ? entryName : pth.basename(entryName));
|
|
16611
18642
|
|
|
16612
18643
|
if (item.isDirectory) {
|
|
16613
18644
|
var children = _zip.getEntryChildren(item);
|
|
@@ -16617,8 +18648,12 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16617
18648
|
if (!content) {
|
|
16618
18649
|
throw Utils.Errors.CANT_EXTRACT_FILE();
|
|
16619
18650
|
}
|
|
16620
|
-
|
|
16621
|
-
|
|
18651
|
+
// When not maintaining the full entry path, keep each child's path
|
|
18652
|
+
// relative to the extracted directory (drop the directory's own
|
|
18653
|
+
// prefix) instead of flattening every file to its basename, which
|
|
18654
|
+
// collapsed subdirectories together (issue #306).
|
|
18655
|
+
var name = canonical(maintainEntryPath ? child.entryName : child.entryName.substring(item.entryName.length));
|
|
18656
|
+
var childName = sanitize(targetPath, name);
|
|
16622
18657
|
// The reverse operation for attr depend on method addFile()
|
|
16623
18658
|
const fileAttr = keepOriginalPermission ? child.header.fileAttr : undefined;
|
|
16624
18659
|
filetools.writeFileTo(childName, content, overwrite, fileAttr);
|
|
@@ -16648,12 +18683,14 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16648
18683
|
return false;
|
|
16649
18684
|
}
|
|
16650
18685
|
|
|
16651
|
-
for (var entry
|
|
18686
|
+
for (var entry of _zip.entries) {
|
|
16652
18687
|
try {
|
|
16653
18688
|
if (entry.isDirectory) {
|
|
16654
18689
|
continue;
|
|
16655
18690
|
}
|
|
16656
|
-
|
|
18691
|
+
// was `_zip.entries[entry]` (indexing the array with an entry
|
|
18692
|
+
// object -> undefined -> threw -> test() always returned false)
|
|
18693
|
+
var content = entry.getData(pass);
|
|
16657
18694
|
if (!content) {
|
|
16658
18695
|
return false;
|
|
16659
18696
|
}
|
|
@@ -16680,10 +18717,13 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16680
18717
|
overwrite = get_Bool(false, overwrite);
|
|
16681
18718
|
if (!_zip) throw Utils.Errors.NO_ZIP();
|
|
16682
18719
|
|
|
18720
|
+
const dirEntries = [];
|
|
16683
18721
|
_zip.entries.forEach(function (entry) {
|
|
16684
18722
|
var entryName = sanitize(targetPath, canonical(entry.entryName));
|
|
16685
18723
|
if (entry.isDirectory) {
|
|
16686
18724
|
filetools.makeDir(entryName);
|
|
18725
|
+
// defer restoring the directory permission until its files are written
|
|
18726
|
+
if (keepOriginalPermission) dirEntries.push({ path: entryName, attr: entry.header.fileAttr });
|
|
16687
18727
|
return;
|
|
16688
18728
|
}
|
|
16689
18729
|
var content = entry.getData(pass);
|
|
@@ -16694,11 +18734,15 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16694
18734
|
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;
|
|
16695
18735
|
filetools.writeFileTo(entryName, content, overwrite, fileAttr);
|
|
16696
18736
|
try {
|
|
18737
|
+
// best-effort: an invalid date in the archive or a filesystem that
|
|
18738
|
+
// rejects utimes must not fail extraction of already-written content (issue #379)
|
|
16697
18739
|
filetools.fs.utimesSync(entryName, entry.header.time, entry.header.time);
|
|
16698
18740
|
} catch (err) {
|
|
16699
|
-
|
|
18741
|
+
/* ignore timestamp failures */
|
|
16700
18742
|
}
|
|
16701
18743
|
});
|
|
18744
|
+
|
|
18745
|
+
applyDirAttributes(dirEntries);
|
|
16702
18746
|
},
|
|
16703
18747
|
|
|
16704
18748
|
/**
|
|
@@ -16749,20 +18793,41 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16749
18793
|
|
|
16750
18794
|
// Create directory entries first synchronously
|
|
16751
18795
|
// this prevents race condition and assures folders are there before writing files
|
|
18796
|
+
const deferredDirAttr = [];
|
|
16752
18797
|
for (const entry of dirEntries) {
|
|
16753
18798
|
const dirPath = getPath(entry);
|
|
16754
18799
|
// The reverse operation for attr depend on method addFile()
|
|
16755
18800
|
const dirAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;
|
|
16756
18801
|
try {
|
|
16757
18802
|
filetools.makeDir(dirPath);
|
|
16758
|
-
if (dirAttr) filetools.fs.chmodSync(dirPath, dirAttr);
|
|
16759
|
-
// in unix timestamp will change if files are later added to folder, but still
|
|
16760
|
-
filetools.fs.utimesSync(dirPath, entry.header.time, entry.header.time);
|
|
16761
18803
|
} catch (er) {
|
|
16762
18804
|
callback(getError("Unable to create folder", dirPath));
|
|
18805
|
+
continue;
|
|
18806
|
+
}
|
|
18807
|
+
// defer restoring the directory permission until its files are written:
|
|
18808
|
+
// a restrictive mode applied now would block writing them
|
|
18809
|
+
if (dirAttr) deferredDirAttr.push({ path: dirPath, attr: dirAttr });
|
|
18810
|
+
try {
|
|
18811
|
+
// in unix timestamp will change if files are later added to folder, but still.
|
|
18812
|
+
// best-effort: a utimes failure must not abort extraction (issue #379)
|
|
18813
|
+
filetools.fs.utimesSync(dirPath, entry.header.time, entry.header.time);
|
|
18814
|
+
} catch (er) {
|
|
18815
|
+
/* ignore timestamp failures */
|
|
16763
18816
|
}
|
|
16764
18817
|
}
|
|
16765
18818
|
|
|
18819
|
+
// restore directory permissions once every file has been extracted
|
|
18820
|
+
const done = (err) => {
|
|
18821
|
+
if (!err) {
|
|
18822
|
+
try {
|
|
18823
|
+
applyDirAttributes(deferredDirAttr);
|
|
18824
|
+
} catch (er) {
|
|
18825
|
+
return callback(getError("Unable to set folder permissions", er.path || ""));
|
|
18826
|
+
}
|
|
18827
|
+
}
|
|
18828
|
+
callback(err);
|
|
18829
|
+
};
|
|
18830
|
+
|
|
16766
18831
|
fileEntries.reverse().reduce(function (next, entry) {
|
|
16767
18832
|
return function (err) {
|
|
16768
18833
|
if (err) {
|
|
@@ -16780,21 +18845,19 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16780
18845
|
const fileAttr = keepOriginalPermission ? entry.header.fileAttr : undefined;
|
|
16781
18846
|
filetools.writeFileToAsync(filePath, content, overwrite, fileAttr, function (succ) {
|
|
16782
18847
|
if (!succ) {
|
|
16783
|
-
next(getError("Unable to write file", filePath));
|
|
18848
|
+
return next(getError("Unable to write file", filePath));
|
|
16784
18849
|
}
|
|
16785
|
-
filetools.fs.utimes(filePath, entry.header.time, entry.header.time, function (
|
|
16786
|
-
|
|
16787
|
-
|
|
16788
|
-
|
|
16789
|
-
next();
|
|
16790
|
-
}
|
|
18850
|
+
filetools.fs.utimes(filePath, entry.header.time, entry.header.time, function () {
|
|
18851
|
+
// best-effort: a utimes failure must not abort extraction
|
|
18852
|
+
// of already-written content (issue #379)
|
|
18853
|
+
next();
|
|
16791
18854
|
});
|
|
16792
18855
|
});
|
|
16793
18856
|
}
|
|
16794
18857
|
});
|
|
16795
18858
|
}
|
|
16796
18859
|
};
|
|
16797
|
-
},
|
|
18860
|
+
}, done)();
|
|
16798
18861
|
},
|
|
16799
18862
|
|
|
16800
18863
|
/**
|
|
@@ -16878,10 +18941,10 @@ module.exports = function (/**String*/ input, /** object */ options) {
|
|
|
16878
18941
|
|
|
16879
18942
|
/***/ }),
|
|
16880
18943
|
|
|
16881
|
-
/***/
|
|
18944
|
+
/***/ 88436:
|
|
16882
18945
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
16883
18946
|
|
|
16884
|
-
var Utils = __nccwpck_require__(
|
|
18947
|
+
var Utils = __nccwpck_require__(91373),
|
|
16885
18948
|
Constants = Utils.Constants;
|
|
16886
18949
|
|
|
16887
18950
|
/* The central directory file header */
|
|
@@ -16970,6 +19033,7 @@ module.exports = function () {
|
|
|
16970
19033
|
switch (val) {
|
|
16971
19034
|
case Constants.STORED:
|
|
16972
19035
|
this.version = 10;
|
|
19036
|
+
break;
|
|
16973
19037
|
case Constants.DEFLATED:
|
|
16974
19038
|
default:
|
|
16975
19039
|
this.version = 20;
|
|
@@ -16981,6 +19045,7 @@ module.exports = function () {
|
|
|
16981
19045
|
return Utils.fromDOS2Date(this.timeval);
|
|
16982
19046
|
},
|
|
16983
19047
|
set time(val) {
|
|
19048
|
+
val = new Date(val);
|
|
16984
19049
|
this.timeval = Utils.fromDate2DOS(val);
|
|
16985
19050
|
},
|
|
16986
19051
|
|
|
@@ -17103,6 +19168,8 @@ module.exports = function () {
|
|
|
17103
19168
|
_localHeader.version = data.readUInt16LE(Constants.LOCVER);
|
|
17104
19169
|
// general purpose bit flag
|
|
17105
19170
|
_localHeader.flags = data.readUInt16LE(Constants.LOCFLG);
|
|
19171
|
+
// desc flag
|
|
19172
|
+
_localHeader.flags_desc = (_localHeader.flags & Constants.FLG_DESC) > 0;
|
|
17106
19173
|
// compression method
|
|
17107
19174
|
_localHeader.method = data.readUInt16LE(Constants.LOCHOW);
|
|
17108
19175
|
// modification time (2 bytes time, 2 bytes date)
|
|
@@ -17169,7 +19236,11 @@ module.exports = function () {
|
|
|
17169
19236
|
// version needed to extract
|
|
17170
19237
|
data.writeUInt16LE(_version, Constants.LOCVER);
|
|
17171
19238
|
// general purpose bit flag
|
|
17172
|
-
data
|
|
19239
|
+
// clear bit 3 (data descriptor): we always write the real crc-32
|
|
19240
|
+
// and sizes into this local header, so no trailing descriptor is
|
|
19241
|
+
// emitted. Leaving the flag set would make the output unreadable
|
|
19242
|
+
// (see issue #555).
|
|
19243
|
+
data.writeUInt16LE(_flags & ~Constants.FLG_DESC, Constants.LOCFLG);
|
|
17173
19244
|
// compression method
|
|
17174
19245
|
data.writeUInt16LE(_method, Constants.LOCHOW);
|
|
17175
19246
|
// modification time (2 bytes time, 2 bytes date)
|
|
@@ -17197,7 +19268,9 @@ module.exports = function () {
|
|
|
17197
19268
|
// version needed to extract
|
|
17198
19269
|
data.writeUInt16LE(_version, Constants.CENVER);
|
|
17199
19270
|
// encrypt, decrypt flags
|
|
17200
|
-
data
|
|
19271
|
+
// clear bit 3 (data descriptor) to match the local header we emit
|
|
19272
|
+
// (real crc/sizes are written, no descriptor follows the data) — issue #555
|
|
19273
|
+
data.writeUInt16LE(_flags & ~Constants.FLG_DESC, Constants.CENFLG);
|
|
17201
19274
|
// compression method
|
|
17202
19275
|
data.writeUInt16LE(_method, Constants.CENHOW);
|
|
17203
19276
|
// modification time (2 bytes time, 2 bytes date)
|
|
@@ -17259,19 +19332,19 @@ module.exports = function () {
|
|
|
17259
19332
|
|
|
17260
19333
|
/***/ }),
|
|
17261
19334
|
|
|
17262
|
-
/***/
|
|
19335
|
+
/***/ 77837:
|
|
17263
19336
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
17264
19337
|
|
|
17265
|
-
exports.EntryHeader = __nccwpck_require__(
|
|
17266
|
-
exports.MainHeader = __nccwpck_require__(
|
|
19338
|
+
exports.EntryHeader = __nccwpck_require__(88436);
|
|
19339
|
+
exports.MainHeader = __nccwpck_require__(88889);
|
|
17267
19340
|
|
|
17268
19341
|
|
|
17269
19342
|
/***/ }),
|
|
17270
19343
|
|
|
17271
|
-
/***/
|
|
19344
|
+
/***/ 88889:
|
|
17272
19345
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
17273
19346
|
|
|
17274
|
-
var Utils = __nccwpck_require__(
|
|
19347
|
+
var Utils = __nccwpck_require__(91373),
|
|
17275
19348
|
Constants = Utils.Constants;
|
|
17276
19349
|
|
|
17277
19350
|
/* The entries in the end of central directory */
|
|
@@ -17282,6 +19355,8 @@ module.exports = function () {
|
|
|
17282
19355
|
_offset = 0,
|
|
17283
19356
|
_commentLength = 0;
|
|
17284
19357
|
|
|
19358
|
+
const needsZip64 = () => _volumeEntries > Constants.EF_ZIP64_OR_16 || _totalEntries > Constants.EF_ZIP64_OR_16 || _size > Constants.EF_ZIP64_OR_32 || _offset > Constants.EF_ZIP64_OR_32;
|
|
19359
|
+
|
|
17285
19360
|
return {
|
|
17286
19361
|
get diskEntries() {
|
|
17287
19362
|
return _volumeEntries;
|
|
@@ -17319,7 +19394,7 @@ module.exports = function () {
|
|
|
17319
19394
|
},
|
|
17320
19395
|
|
|
17321
19396
|
get mainHeaderSize() {
|
|
17322
|
-
return Constants.ENDHDR + _commentLength;
|
|
19397
|
+
return (needsZip64() ? Constants.ZIP64HDR + Constants.END64HDR : 0) + Constants.ENDHDR + _commentLength;
|
|
17323
19398
|
},
|
|
17324
19399
|
|
|
17325
19400
|
loadFromBinary: function (/*Buffer*/ data) {
|
|
@@ -17349,7 +19424,7 @@ module.exports = function () {
|
|
|
17349
19424
|
// total number of entries
|
|
17350
19425
|
_totalEntries = Utils.readBigUInt64LE(data, Constants.ZIP64TOT);
|
|
17351
19426
|
// central directory size in bytes
|
|
17352
|
-
_size = Utils.readBigUInt64LE(data, Constants.
|
|
19427
|
+
_size = Utils.readBigUInt64LE(data, Constants.ZIP64SIZB);
|
|
17353
19428
|
// offset of first CEN header
|
|
17354
19429
|
_offset = Utils.readBigUInt64LE(data, Constants.ZIP64OFF);
|
|
17355
19430
|
|
|
@@ -17358,22 +19433,67 @@ module.exports = function () {
|
|
|
17358
19433
|
},
|
|
17359
19434
|
|
|
17360
19435
|
toBinary: function () {
|
|
17361
|
-
|
|
19436
|
+
if (!needsZip64()) {
|
|
19437
|
+
var b = Buffer.alloc(Constants.ENDHDR + _commentLength);
|
|
19438
|
+
// "PK 05 06" signature
|
|
19439
|
+
b.writeUInt32LE(Constants.ENDSIG, 0);
|
|
19440
|
+
b.writeUInt32LE(0, 4);
|
|
19441
|
+
// number of entries on this volume
|
|
19442
|
+
b.writeUInt16LE(_volumeEntries, Constants.ENDSUB);
|
|
19443
|
+
// total number of entries
|
|
19444
|
+
b.writeUInt16LE(_totalEntries, Constants.ENDTOT);
|
|
19445
|
+
// central directory size in bytes
|
|
19446
|
+
b.writeUInt32LE(_size, Constants.ENDSIZ);
|
|
19447
|
+
// offset of first CEN header
|
|
19448
|
+
b.writeUInt32LE(_offset, Constants.ENDOFF);
|
|
19449
|
+
// zip file comment length
|
|
19450
|
+
b.writeUInt16LE(_commentLength, Constants.ENDCOM);
|
|
19451
|
+
// fill comment memory with spaces so no garbage is left there
|
|
19452
|
+
b.fill(" ", Constants.ENDHDR);
|
|
19453
|
+
|
|
19454
|
+
return b;
|
|
19455
|
+
}
|
|
19456
|
+
|
|
19457
|
+
var b = Buffer.alloc(this.mainHeaderSize);
|
|
19458
|
+
let offset = 0;
|
|
19459
|
+
|
|
19460
|
+
// Zip64 end of central directory record.
|
|
19461
|
+
b.writeUInt32LE(Constants.ZIP64SIG, offset);
|
|
19462
|
+
Utils.writeBigUInt64LE(b, Constants.ZIP64HDR - Constants.ZIP64LEAD, offset + Constants.ZIP64SIZE);
|
|
19463
|
+
b.writeUInt16LE(45, offset + Constants.ZIP64VEM);
|
|
19464
|
+
b.writeUInt16LE(45, offset + Constants.ZIP64VER);
|
|
19465
|
+
b.writeUInt32LE(0, offset + Constants.ZIP64DSK);
|
|
19466
|
+
b.writeUInt32LE(0, offset + Constants.ZIP64DSKDIR);
|
|
19467
|
+
Utils.writeBigUInt64LE(b, _volumeEntries, offset + Constants.ZIP64SUB);
|
|
19468
|
+
Utils.writeBigUInt64LE(b, _totalEntries, offset + Constants.ZIP64TOT);
|
|
19469
|
+
Utils.writeBigUInt64LE(b, _size, offset + Constants.ZIP64SIZB);
|
|
19470
|
+
Utils.writeBigUInt64LE(b, _offset, offset + Constants.ZIP64OFF);
|
|
19471
|
+
|
|
19472
|
+
const zip64EndOffset = _offset + _size;
|
|
19473
|
+
offset += Constants.ZIP64HDR;
|
|
19474
|
+
|
|
19475
|
+
// Zip64 end of central directory locator.
|
|
19476
|
+
b.writeUInt32LE(Constants.END64SIG, offset);
|
|
19477
|
+
b.writeUInt32LE(0, offset + Constants.END64START);
|
|
19478
|
+
Utils.writeBigUInt64LE(b, zip64EndOffset, offset + Constants.END64OFF);
|
|
19479
|
+
b.writeUInt32LE(1, offset + Constants.END64NUMDISKS);
|
|
19480
|
+
offset += Constants.END64HDR;
|
|
19481
|
+
|
|
17362
19482
|
// "PK 05 06" signature
|
|
17363
|
-
b.writeUInt32LE(Constants.ENDSIG,
|
|
17364
|
-
b.writeUInt32LE(0, 4);
|
|
19483
|
+
b.writeUInt32LE(Constants.ENDSIG, offset);
|
|
19484
|
+
b.writeUInt32LE(0, offset + 4);
|
|
17365
19485
|
// number of entries on this volume
|
|
17366
|
-
b.writeUInt16LE(_volumeEntries, Constants.ENDSUB);
|
|
19486
|
+
b.writeUInt16LE(Math.min(_volumeEntries, Constants.EF_ZIP64_OR_16), offset + Constants.ENDSUB);
|
|
17367
19487
|
// total number of entries
|
|
17368
|
-
b.writeUInt16LE(_totalEntries, Constants.ENDTOT);
|
|
19488
|
+
b.writeUInt16LE(Math.min(_totalEntries, Constants.EF_ZIP64_OR_16), offset + Constants.ENDTOT);
|
|
17369
19489
|
// central directory size in bytes
|
|
17370
|
-
b.writeUInt32LE(_size, Constants.ENDSIZ);
|
|
19490
|
+
b.writeUInt32LE(Math.min(_size, Constants.EF_ZIP64_OR_32), offset + Constants.ENDSIZ);
|
|
17371
19491
|
// offset of first CEN header
|
|
17372
|
-
b.writeUInt32LE(_offset, Constants.ENDOFF);
|
|
19492
|
+
b.writeUInt32LE(Math.min(_offset, Constants.EF_ZIP64_OR_32), offset + Constants.ENDOFF);
|
|
17373
19493
|
// zip file comment length
|
|
17374
|
-
b.writeUInt16LE(_commentLength, Constants.ENDCOM);
|
|
19494
|
+
b.writeUInt16LE(_commentLength, offset + Constants.ENDCOM);
|
|
17375
19495
|
// fill comment memory with spaces so no garbage is left there
|
|
17376
|
-
b.fill(" ", Constants.ENDHDR);
|
|
19496
|
+
b.fill(" ", offset + Constants.ENDHDR);
|
|
17377
19497
|
|
|
17378
19498
|
return b;
|
|
17379
19499
|
},
|
|
@@ -17405,7 +19525,7 @@ module.exports = function () {
|
|
|
17405
19525
|
|
|
17406
19526
|
/***/ }),
|
|
17407
19527
|
|
|
17408
|
-
/***/
|
|
19528
|
+
/***/ 49466:
|
|
17409
19529
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
17410
19530
|
|
|
17411
19531
|
module.exports = function (/*Buffer*/ inbuf) {
|
|
@@ -17445,20 +19565,20 @@ module.exports = function (/*Buffer*/ inbuf) {
|
|
|
17445
19565
|
|
|
17446
19566
|
/***/ }),
|
|
17447
19567
|
|
|
17448
|
-
/***/
|
|
19568
|
+
/***/ 70493:
|
|
17449
19569
|
/***/ ((__unused_webpack_module, exports, __nccwpck_require__) => {
|
|
17450
19570
|
|
|
17451
|
-
exports.Deflater = __nccwpck_require__(
|
|
17452
|
-
exports.Inflater = __nccwpck_require__(
|
|
17453
|
-
exports.ZipCrypto = __nccwpck_require__(
|
|
19571
|
+
exports.Deflater = __nccwpck_require__(49466);
|
|
19572
|
+
exports.Inflater = __nccwpck_require__(27298);
|
|
19573
|
+
exports.ZipCrypto = __nccwpck_require__(19687);
|
|
17454
19574
|
|
|
17455
19575
|
|
|
17456
19576
|
/***/ }),
|
|
17457
19577
|
|
|
17458
|
-
/***/
|
|
19578
|
+
/***/ 27298:
|
|
17459
19579
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
17460
19580
|
|
|
17461
|
-
const version = +(process
|
|
19581
|
+
const version = +(process?.versions?.node ?? "").split(".")[0] || 0;
|
|
17462
19582
|
|
|
17463
19583
|
module.exports = function (/*Buffer*/ inbuf, /*number*/ expectedLength) {
|
|
17464
19584
|
var zlib = __nccwpck_require__(43106);
|
|
@@ -17496,7 +19616,7 @@ module.exports = function (/*Buffer*/ inbuf, /*number*/ expectedLength) {
|
|
|
17496
19616
|
|
|
17497
19617
|
/***/ }),
|
|
17498
19618
|
|
|
17499
|
-
/***/
|
|
19619
|
+
/***/ 19687:
|
|
17500
19620
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
17501
19621
|
|
|
17502
19622
|
"use strict";
|
|
@@ -17505,7 +19625,7 @@ module.exports = function (/*Buffer*/ inbuf, /*number*/ expectedLength) {
|
|
|
17505
19625
|
// node crypt, we use it for generate salt
|
|
17506
19626
|
// eslint-disable-next-line node/no-unsupported-features/node-builtins
|
|
17507
19627
|
const { randomFillSync } = __nccwpck_require__(76982);
|
|
17508
|
-
const Errors = __nccwpck_require__(
|
|
19628
|
+
const Errors = __nccwpck_require__(9314);
|
|
17509
19629
|
|
|
17510
19630
|
// generate CRC32 lookup table
|
|
17511
19631
|
const crctable = new Uint32Array(256).map((t, crc) => {
|
|
@@ -17679,7 +19799,7 @@ module.exports = { decrypt, encrypt, _salter };
|
|
|
17679
19799
|
|
|
17680
19800
|
/***/ }),
|
|
17681
19801
|
|
|
17682
|
-
/***/
|
|
19802
|
+
/***/ 85604:
|
|
17683
19803
|
/***/ ((module) => {
|
|
17684
19804
|
|
|
17685
19805
|
module.exports = {
|
|
@@ -17828,7 +19948,7 @@ module.exports = {
|
|
|
17828
19948
|
|
|
17829
19949
|
/***/ }),
|
|
17830
19950
|
|
|
17831
|
-
/***/
|
|
19951
|
+
/***/ 95825:
|
|
17832
19952
|
/***/ ((module) => {
|
|
17833
19953
|
|
|
17834
19954
|
module.exports = {
|
|
@@ -17840,7 +19960,7 @@ module.exports = {
|
|
|
17840
19960
|
|
|
17841
19961
|
/***/ }),
|
|
17842
19962
|
|
|
17843
|
-
/***/
|
|
19963
|
+
/***/ 9314:
|
|
17844
19964
|
/***/ ((__unused_webpack_module, exports) => {
|
|
17845
19965
|
|
|
17846
19966
|
const errors = {
|
|
@@ -17910,7 +20030,7 @@ for (const msg of Object.keys(errors)) {
|
|
|
17910
20030
|
|
|
17911
20031
|
/***/ }),
|
|
17912
20032
|
|
|
17913
|
-
/***/
|
|
20033
|
+
/***/ 71560:
|
|
17914
20034
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
17915
20035
|
|
|
17916
20036
|
const pth = __nccwpck_require__(16928);
|
|
@@ -17993,25 +20113,25 @@ module.exports = function (/*String*/ path, /*Utils object*/ { fs }) {
|
|
|
17993
20113
|
|
|
17994
20114
|
/***/ }),
|
|
17995
20115
|
|
|
17996
|
-
/***/
|
|
20116
|
+
/***/ 91373:
|
|
17997
20117
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
17998
20118
|
|
|
17999
|
-
module.exports = __nccwpck_require__(
|
|
18000
|
-
module.exports.Constants = __nccwpck_require__(
|
|
18001
|
-
module.exports.Errors = __nccwpck_require__(
|
|
18002
|
-
module.exports.FileAttr = __nccwpck_require__(
|
|
18003
|
-
module.exports.decoder = __nccwpck_require__(
|
|
20119
|
+
module.exports = __nccwpck_require__(12056);
|
|
20120
|
+
module.exports.Constants = __nccwpck_require__(85604);
|
|
20121
|
+
module.exports.Errors = __nccwpck_require__(9314);
|
|
20122
|
+
module.exports.FileAttr = __nccwpck_require__(71560);
|
|
20123
|
+
module.exports.decoder = __nccwpck_require__(95825);
|
|
18004
20124
|
|
|
18005
20125
|
|
|
18006
20126
|
/***/ }),
|
|
18007
20127
|
|
|
18008
|
-
/***/
|
|
20128
|
+
/***/ 12056:
|
|
18009
20129
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
18010
20130
|
|
|
18011
20131
|
const fsystem = __nccwpck_require__(79896);
|
|
18012
20132
|
const pth = __nccwpck_require__(16928);
|
|
18013
|
-
const Constants = __nccwpck_require__(
|
|
18014
|
-
const Errors = __nccwpck_require__(
|
|
20133
|
+
const Constants = __nccwpck_require__(85604);
|
|
20134
|
+
const Errors = __nccwpck_require__(9314);
|
|
18015
20135
|
const isWin = typeof process === "object" && "win32" === process.platform;
|
|
18016
20136
|
|
|
18017
20137
|
const is_Obj = (obj) => typeof obj === "object" && obj !== null;
|
|
@@ -18059,7 +20179,11 @@ Utils.prototype.makeDir = function (/*String*/ folder) {
|
|
|
18059
20179
|
try {
|
|
18060
20180
|
stat = self.fs.statSync(resolvedPath);
|
|
18061
20181
|
} catch (e) {
|
|
18062
|
-
|
|
20182
|
+
if (e.message && e.message.startsWith('ENOENT')) {
|
|
20183
|
+
self.fs.mkdirSync(resolvedPath);
|
|
20184
|
+
} else {
|
|
20185
|
+
throw e;
|
|
20186
|
+
}
|
|
18063
20187
|
}
|
|
18064
20188
|
if (stat && stat.isFile()) throw Errors.FILE_IN_THE_WAY(`"${resolvedPath}"`);
|
|
18065
20189
|
});
|
|
@@ -18113,39 +20237,51 @@ Utils.prototype.writeFileToAsync = function (/*String*/ path, /*Buffer*/ content
|
|
|
18113
20237
|
if (exist && !overwrite) return callback(false);
|
|
18114
20238
|
|
|
18115
20239
|
self.fs.stat(path, function (err, stat) {
|
|
18116
|
-
if (exist && stat.isDirectory()) {
|
|
20240
|
+
if (exist && stat && stat.isDirectory()) {
|
|
18117
20241
|
return callback(false);
|
|
18118
20242
|
}
|
|
18119
20243
|
|
|
18120
20244
|
var folder = pth.dirname(path);
|
|
18121
20245
|
self.fs.exists(folder, function (exists) {
|
|
18122
|
-
if (!exists)
|
|
20246
|
+
if (!exists) {
|
|
20247
|
+
// makeDir is synchronous and can throw (e.g. EACCES); report failure
|
|
20248
|
+
// rather than letting it escape this callback as an uncaught exception
|
|
20249
|
+
try {
|
|
20250
|
+
self.makeDir(folder);
|
|
20251
|
+
} catch (e) {
|
|
20252
|
+
return callback(false);
|
|
20253
|
+
}
|
|
20254
|
+
}
|
|
20255
|
+
|
|
20256
|
+
// write the content to an open descriptor, then apply the attributes
|
|
20257
|
+
const writeToFd = function (fd) {
|
|
20258
|
+
self.fs.write(fd, content, 0, content.length, 0, function (writeErr) {
|
|
20259
|
+
self.fs.close(fd, function () {
|
|
20260
|
+
// surface write failures instead of silently reporting success (issue #402)
|
|
20261
|
+
if (writeErr) return callback(false);
|
|
20262
|
+
self.fs.chmod(path, attr || 0o666, function () {
|
|
20263
|
+
callback(true);
|
|
20264
|
+
});
|
|
20265
|
+
});
|
|
20266
|
+
});
|
|
20267
|
+
};
|
|
18123
20268
|
|
|
18124
20269
|
self.fs.open(path, "w", 0o666, function (err, fd) {
|
|
18125
20270
|
if (err) {
|
|
20271
|
+
// the target may exist but be read-only: make it writable and retry once
|
|
18126
20272
|
self.fs.chmod(path, 0o666, function () {
|
|
18127
|
-
self.fs.open(path, "w", 0o666, function (
|
|
18128
|
-
|
|
18129
|
-
|
|
18130
|
-
|
|
18131
|
-
|
|
18132
|
-
|
|
18133
|
-
});
|
|
18134
|
-
});
|
|
20273
|
+
self.fs.open(path, "w", 0o666, function (retryErr, fd) {
|
|
20274
|
+
// Previously the retry error was ignored and an undefined fd was
|
|
20275
|
+
// passed to fs.write, throwing an uncaught ERR_INVALID_ARG_TYPE that
|
|
20276
|
+
// crashed the process (issues #470, #459, #402). Report failure instead.
|
|
20277
|
+
if (retryErr || !fd) return callback(false);
|
|
20278
|
+
writeToFd(fd);
|
|
18135
20279
|
});
|
|
18136
20280
|
});
|
|
18137
20281
|
} else if (fd) {
|
|
18138
|
-
|
|
18139
|
-
self.fs.close(fd, function () {
|
|
18140
|
-
self.fs.chmod(path, attr || 0o666, function () {
|
|
18141
|
-
callback(true);
|
|
18142
|
-
});
|
|
18143
|
-
});
|
|
18144
|
-
});
|
|
20282
|
+
writeToFd(fd);
|
|
18145
20283
|
} else {
|
|
18146
|
-
|
|
18147
|
-
callback(true);
|
|
18148
|
-
});
|
|
20284
|
+
callback(false);
|
|
18149
20285
|
}
|
|
18150
20286
|
});
|
|
18151
20287
|
});
|
|
@@ -18156,7 +20292,7 @@ Utils.prototype.writeFileToAsync = function (/*String*/ path, /*Buffer*/ content
|
|
|
18156
20292
|
Utils.prototype.findFiles = function (/*String*/ path) {
|
|
18157
20293
|
const self = this;
|
|
18158
20294
|
|
|
18159
|
-
function findSync(/*String*/ dir, /*RegExp*/ pattern, /*Boolean*/ recursive) {
|
|
20295
|
+
function findSync(/*String*/ dir, /*RegExp*/ pattern, /*Boolean*/ recursive, /*Set*/ visited) {
|
|
18160
20296
|
if (typeof pattern === "boolean") {
|
|
18161
20297
|
recursive = pattern;
|
|
18162
20298
|
pattern = undefined;
|
|
@@ -18170,12 +20306,22 @@ Utils.prototype.findFiles = function (/*String*/ path) {
|
|
|
18170
20306
|
files.push(pth.normalize(path) + (stat.isDirectory() ? self.sep : ""));
|
|
18171
20307
|
}
|
|
18172
20308
|
|
|
18173
|
-
if (stat.isDirectory() && recursive)
|
|
20309
|
+
if (stat.isDirectory() && recursive) {
|
|
20310
|
+
// Descend by resolved real path and skip directories we have already
|
|
20311
|
+
// visited. This stops a symlink that points back to an ancestor from
|
|
20312
|
+
// recursing forever until the path fails with ELOOP / ENAMETOOLONG
|
|
20313
|
+
// (issue #541).
|
|
20314
|
+
const realDir = self.fs.realpathSync(path);
|
|
20315
|
+
if (!visited.has(realDir)) {
|
|
20316
|
+
visited.add(realDir);
|
|
20317
|
+
files = files.concat(findSync(path, pattern, recursive, visited));
|
|
20318
|
+
}
|
|
20319
|
+
}
|
|
18174
20320
|
});
|
|
18175
20321
|
return files;
|
|
18176
20322
|
}
|
|
18177
20323
|
|
|
18178
|
-
return findSync(path, undefined, true);
|
|
20324
|
+
return findSync(path, undefined, true, new Set([self.fs.realpathSync(path)]));
|
|
18179
20325
|
};
|
|
18180
20326
|
|
|
18181
20327
|
/**
|
|
@@ -18193,29 +20339,54 @@ Utils.prototype.findFiles = function (/*String*/ path) {
|
|
|
18193
20339
|
*/
|
|
18194
20340
|
Utils.prototype.findFilesAsync = function (dir, cb) {
|
|
18195
20341
|
const self = this;
|
|
18196
|
-
|
|
18197
|
-
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18201
|
-
|
|
18202
|
-
|
|
18203
|
-
|
|
18204
|
-
|
|
18205
|
-
|
|
20342
|
+
const results = [];
|
|
20343
|
+
let finished = false;
|
|
20344
|
+
const finish = function (err) {
|
|
20345
|
+
if (finished) return;
|
|
20346
|
+
finished = true;
|
|
20347
|
+
cb(err, err ? undefined : results);
|
|
20348
|
+
};
|
|
20349
|
+
|
|
20350
|
+
// Descend by resolved real path and skip directories already visited, so a
|
|
20351
|
+
// symlink pointing back to an ancestor cannot recurse forever (issue #541).
|
|
20352
|
+
const walk = function (dir, visited, done) {
|
|
20353
|
+
self.fs.readdir(dir, function (err, list) {
|
|
20354
|
+
if (err) return done(err);
|
|
20355
|
+
let pending = list.length;
|
|
20356
|
+
if (!pending) return done();
|
|
20357
|
+
list.forEach(function (name) {
|
|
20358
|
+
const file = pth.join(dir, name);
|
|
20359
|
+
self.fs.stat(file, function (err, stat) {
|
|
20360
|
+
if (err) return done(err);
|
|
20361
|
+
if (!stat) {
|
|
20362
|
+
if (!--pending) done();
|
|
20363
|
+
return;
|
|
20364
|
+
}
|
|
18206
20365
|
results.push(pth.normalize(file) + (stat.isDirectory() ? self.sep : ""));
|
|
18207
|
-
if (stat.isDirectory()) {
|
|
18208
|
-
|
|
18209
|
-
|
|
18210
|
-
results = results.concat(res);
|
|
18211
|
-
if (!--list_length) cb(null, results);
|
|
18212
|
-
});
|
|
18213
|
-
} else {
|
|
18214
|
-
if (!--list_length) cb(null, results);
|
|
20366
|
+
if (!stat.isDirectory()) {
|
|
20367
|
+
if (!--pending) done();
|
|
20368
|
+
return;
|
|
18215
20369
|
}
|
|
18216
|
-
|
|
20370
|
+
self.fs.realpath(file, function (err, realDir) {
|
|
20371
|
+
if (err) return done(err);
|
|
20372
|
+
if (visited.has(realDir)) {
|
|
20373
|
+
if (!--pending) done();
|
|
20374
|
+
return;
|
|
20375
|
+
}
|
|
20376
|
+
visited.add(realDir);
|
|
20377
|
+
walk(file, visited, function (err) {
|
|
20378
|
+
if (err) return done(err);
|
|
20379
|
+
if (!--pending) done();
|
|
20380
|
+
});
|
|
20381
|
+
});
|
|
20382
|
+
});
|
|
18217
20383
|
});
|
|
18218
20384
|
});
|
|
20385
|
+
};
|
|
20386
|
+
|
|
20387
|
+
self.fs.realpath(dir, function (err, realDir) {
|
|
20388
|
+
if (err) return finish(err);
|
|
20389
|
+
walk(dir, new Set([realDir]), finish);
|
|
18219
20390
|
});
|
|
18220
20391
|
};
|
|
18221
20392
|
|
|
@@ -18296,13 +20467,13 @@ Utils.findLast = function (arr, callback) {
|
|
|
18296
20467
|
return void 0;
|
|
18297
20468
|
};
|
|
18298
20469
|
|
|
18299
|
-
// make
|
|
20470
|
+
// make absolute paths taking prefix as root folder
|
|
18300
20471
|
Utils.sanitize = function (/*string*/ prefix, /*string*/ name) {
|
|
18301
20472
|
prefix = pth.resolve(pth.normalize(prefix));
|
|
18302
20473
|
var parts = name.split("/");
|
|
18303
20474
|
for (var i = 0, l = parts.length; i < l; i++) {
|
|
18304
20475
|
var path = pth.normalize(pth.join(prefix, parts.slice(i, l).join(pth.sep)));
|
|
18305
|
-
if (path.
|
|
20476
|
+
if (path === prefix || path.startsWith(prefix + pth.sep)) {
|
|
18306
20477
|
return path;
|
|
18307
20478
|
}
|
|
18308
20479
|
}
|
|
@@ -18322,10 +20493,16 @@ Utils.toBuffer = function toBuffer(/*buffer, Uint8Array, string*/ input, /* func
|
|
|
18322
20493
|
};
|
|
18323
20494
|
|
|
18324
20495
|
Utils.readBigUInt64LE = function (/*Buffer*/ buffer, /*int*/ index) {
|
|
18325
|
-
|
|
18326
|
-
|
|
20496
|
+
const lo = buffer.readUInt32LE(index);
|
|
20497
|
+
const hi = buffer.readUInt32LE(index + 4);
|
|
20498
|
+
return hi * 0x100000000 + lo;
|
|
20499
|
+
};
|
|
18327
20500
|
|
|
18328
|
-
|
|
20501
|
+
Utils.writeBigUInt64LE = function (/*Buffer*/ buffer, /*Number*/ value, /*int*/ index) {
|
|
20502
|
+
const lo = value >>> 0;
|
|
20503
|
+
const hi = Math.floor(value / 0x100000000) >>> 0;
|
|
20504
|
+
buffer.writeUInt32LE(lo, index);
|
|
20505
|
+
buffer.writeUInt32LE(hi, index + 4);
|
|
18329
20506
|
};
|
|
18330
20507
|
|
|
18331
20508
|
Utils.fromDOS2Date = function (val) {
|
|
@@ -18348,13 +20525,13 @@ Utils.crcTable = crcTable;
|
|
|
18348
20525
|
|
|
18349
20526
|
/***/ }),
|
|
18350
20527
|
|
|
18351
|
-
/***/
|
|
20528
|
+
/***/ 58851:
|
|
18352
20529
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
18353
20530
|
|
|
18354
|
-
var Utils = __nccwpck_require__(
|
|
18355
|
-
Headers = __nccwpck_require__(
|
|
20531
|
+
var Utils = __nccwpck_require__(91373),
|
|
20532
|
+
Headers = __nccwpck_require__(77837),
|
|
18356
20533
|
Constants = Utils.Constants,
|
|
18357
|
-
Methods = __nccwpck_require__(
|
|
20534
|
+
Methods = __nccwpck_require__(70493);
|
|
18358
20535
|
|
|
18359
20536
|
module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
18360
20537
|
var _centralHeader = new Headers.EntryHeader(),
|
|
@@ -18382,48 +20559,23 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
18382
20559
|
}
|
|
18383
20560
|
|
|
18384
20561
|
function crc32OK(data) {
|
|
18385
|
-
//
|
|
18386
|
-
|
|
18387
|
-
|
|
18388
|
-
|
|
18389
|
-
|
|
18390
|
-
|
|
18391
|
-
|
|
18392
|
-
|
|
18393
|
-
|
|
18394
|
-
|
|
18395
|
-
|
|
18396
|
-
|
|
18397
|
-
|
|
18398
|
-
|
|
18399
|
-
|
|
18400
|
-
// descriptor with signature
|
|
18401
|
-
descriptor.crc = input.readUInt32LE(dataEndOffset + Constants.EXTCRC);
|
|
18402
|
-
descriptor.compressedSize = input.readUInt32LE(dataEndOffset + Constants.EXTSIZ);
|
|
18403
|
-
descriptor.size = input.readUInt32LE(dataEndOffset + Constants.EXTLEN);
|
|
18404
|
-
} else if (input.readUInt16LE(dataEndOffset + 12) === 0x4b50) {
|
|
18405
|
-
// descriptor without signature (we check is new header starting where we expect)
|
|
18406
|
-
descriptor.crc = input.readUInt32LE(dataEndOffset + Constants.EXTCRC - 4);
|
|
18407
|
-
descriptor.compressedSize = input.readUInt32LE(dataEndOffset + Constants.EXTSIZ - 4);
|
|
18408
|
-
descriptor.size = input.readUInt32LE(dataEndOffset + Constants.EXTLEN - 4);
|
|
18409
|
-
} else {
|
|
18410
|
-
throw Utils.Errors.DESCRIPTOR_UNKNOWN();
|
|
18411
|
-
}
|
|
18412
|
-
|
|
18413
|
-
// check data integrity
|
|
18414
|
-
if (descriptor.compressedSize !== _centralHeader.compressedSize || descriptor.size !== _centralHeader.size || descriptor.crc !== _centralHeader.crc) {
|
|
18415
|
-
throw Utils.Errors.DESCRIPTOR_FAULTY();
|
|
18416
|
-
}
|
|
18417
|
-
if (Utils.crc32(data) !== descriptor.crc) {
|
|
18418
|
-
return false;
|
|
18419
|
-
}
|
|
20562
|
+
// When bit 3 (0x08) of the general-purpose flags is set, the crc-32 and
|
|
20563
|
+
// sizes were unknown when the local file header was written, so that
|
|
20564
|
+
// header carries placeholder zeros and the real values are repeated in a
|
|
20565
|
+
// data descriptor after the compressed data. adm-zip always parses the
|
|
20566
|
+
// central directory, whose header holds the authoritative crc-32 and
|
|
20567
|
+
// sizes, so we validate the payload against that value.
|
|
20568
|
+
//
|
|
20569
|
+
// Earlier versions instead located and parsed the trailing descriptor and
|
|
20570
|
+
// threw when it was absent or in an unexpected shape. Many valid archives
|
|
20571
|
+
// set the descriptor flag but write the real crc/sizes into the local and
|
|
20572
|
+
// central headers without emitting a descriptor (or write one we did not
|
|
20573
|
+
// recognise), so that strict handling rejected readable zips
|
|
20574
|
+
// (issues #533, #548, #554). Trusting the central-directory crc keeps the
|
|
20575
|
+
// integrity check while accepting those archives.
|
|
20576
|
+
const expectedCrc = _centralHeader.flags_desc || _centralHeader.localHeader.flags_desc ? _centralHeader.crc : _centralHeader.localHeader.crc;
|
|
18420
20577
|
|
|
18421
|
-
|
|
18422
|
-
// if bit 3 is set and any value in local header "zip64 Extended information" extra field are set 0 (place holder)
|
|
18423
|
-
// then 64-bit descriptor format is used instead of 32-bit
|
|
18424
|
-
// central header - "zip64 Extended information" extra field should store real values and not place holders
|
|
18425
|
-
}
|
|
18426
|
-
return true;
|
|
20578
|
+
return Utils.crc32(data) === expectedCrc;
|
|
18427
20579
|
}
|
|
18428
20580
|
|
|
18429
20581
|
function decompress(/*Boolean*/ async, /*Function*/ callback, /*String, Buffer*/ pass) {
|
|
@@ -18453,10 +20605,16 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
18453
20605
|
compressedData = Methods.ZipCrypto.decrypt(compressedData, _centralHeader, pass);
|
|
18454
20606
|
}
|
|
18455
20607
|
|
|
18456
|
-
var data
|
|
20608
|
+
var data;
|
|
18457
20609
|
|
|
18458
20610
|
switch (_centralHeader.method) {
|
|
18459
20611
|
case Utils.Constants.STORED:
|
|
20612
|
+
// STORED entries are not compressed, so the uncompressed output is
|
|
20613
|
+
// exactly the bytes present in the archive. Allocate from the real
|
|
20614
|
+
// data length rather than the attacker-declared central-directory
|
|
20615
|
+
// size, otherwise a tiny archive can declare a huge size and force a
|
|
20616
|
+
// multi-gigabyte allocation before any validation (CVE-2026-39244).
|
|
20617
|
+
data = Buffer.alloc(compressedData.length);
|
|
18460
20618
|
compressedData.copy(data);
|
|
18461
20619
|
if (!crc32OK(data)) {
|
|
18462
20620
|
if (async && callback) callback(data, Utils.Errors.BAD_CRC()); //si added error
|
|
@@ -18467,17 +20625,19 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
18467
20625
|
return data;
|
|
18468
20626
|
}
|
|
18469
20627
|
case Utils.Constants.DEFLATED:
|
|
20628
|
+
// Do not pre-allocate the declared uncompressed size. The inflater
|
|
20629
|
+
// grows its output buffer as zlib emits data and caps the total at
|
|
20630
|
+
// the declared size (maxOutputLength), so a bogus size can no longer
|
|
20631
|
+
// trigger an eager allocation before the data is read (CVE-2026-39244).
|
|
18470
20632
|
var inflater = new Methods.Inflater(compressedData, _centralHeader.size);
|
|
18471
20633
|
if (!async) {
|
|
18472
|
-
|
|
18473
|
-
result.copy(data, 0);
|
|
20634
|
+
data = inflater.inflate();
|
|
18474
20635
|
if (!crc32OK(data)) {
|
|
18475
20636
|
throw Utils.Errors.BAD_CRC(`"${decoder.decode(_entryName)}"`);
|
|
18476
20637
|
}
|
|
18477
20638
|
return data;
|
|
18478
20639
|
} else {
|
|
18479
20640
|
inflater.inflateAsync(function (result) {
|
|
18480
|
-
result.copy(result, 0);
|
|
18481
20641
|
if (callback) {
|
|
18482
20642
|
if (!crc32OK(result)) {
|
|
18483
20643
|
callback(result, Utils.Errors.BAD_CRC()); //si added error
|
|
@@ -18539,7 +20699,7 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
18539
20699
|
}
|
|
18540
20700
|
|
|
18541
20701
|
function readUInt64LE(buffer, offset) {
|
|
18542
|
-
return (buffer
|
|
20702
|
+
return Utils.readBigUInt64LE(buffer, offset);
|
|
18543
20703
|
}
|
|
18544
20704
|
|
|
18545
20705
|
function parseExtra(data) {
|
|
@@ -18633,10 +20793,12 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
18633
20793
|
},
|
|
18634
20794
|
|
|
18635
20795
|
get name() {
|
|
18636
|
-
|
|
20796
|
+
const n = decoder.decode(_entryName);
|
|
20797
|
+
// For directories the name is the last path segment; drop the trailing
|
|
20798
|
+
// separator first so "a/b/c/" yields "c" and not "" (issue #466).
|
|
18637
20799
|
return _isDirectory
|
|
18638
20800
|
? n
|
|
18639
|
-
.
|
|
20801
|
+
.replace(/[/\\]$/, "")
|
|
18640
20802
|
.split("/")
|
|
18641
20803
|
.pop()
|
|
18642
20804
|
: n.split("/").pop();
|
|
@@ -18760,16 +20922,19 @@ module.exports = function (/** object */ options, /*Buffer*/ input) {
|
|
|
18760
20922
|
|
|
18761
20923
|
/***/ }),
|
|
18762
20924
|
|
|
18763
|
-
/***/
|
|
20925
|
+
/***/ 46593:
|
|
18764
20926
|
/***/ ((module, __unused_webpack_exports, __nccwpck_require__) => {
|
|
18765
20927
|
|
|
18766
|
-
const ZipEntry = __nccwpck_require__(
|
|
18767
|
-
const Headers = __nccwpck_require__(
|
|
18768
|
-
const Utils = __nccwpck_require__(
|
|
20928
|
+
const ZipEntry = __nccwpck_require__(58851);
|
|
20929
|
+
const Headers = __nccwpck_require__(77837);
|
|
20930
|
+
const Utils = __nccwpck_require__(91373);
|
|
18769
20931
|
|
|
18770
20932
|
module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
18771
20933
|
var entryList = [],
|
|
18772
|
-
|
|
20934
|
+
// prototype-less: entry names come from untrusted input, so keys like
|
|
20935
|
+
// "__proto__" or "constructor" must be plain data, not touch the prototype
|
|
20936
|
+
// chain (which otherwise crashes addFile and hides such entries)
|
|
20937
|
+
entryTable = Object.create(null),
|
|
18773
20938
|
_comment = Buffer.alloc(0),
|
|
18774
20939
|
mainHeader = new Headers.MainHeader(),
|
|
18775
20940
|
loadedEntries = false;
|
|
@@ -18819,7 +20984,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
|
18819
20984
|
|
|
18820
20985
|
function readEntries() {
|
|
18821
20986
|
loadedEntries = true;
|
|
18822
|
-
entryTable =
|
|
20987
|
+
entryTable = Object.create(null);
|
|
18823
20988
|
if (mainHeader.diskEntries > (inBuffer.length - mainHeader.offset) / Utils.Constants.CENHDR) {
|
|
18824
20989
|
throw Utils.Errors.DISK_ENTRY_TOO_LARGE();
|
|
18825
20990
|
}
|
|
@@ -18896,7 +21061,14 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
|
18896
21061
|
|
|
18897
21062
|
function sortEntries() {
|
|
18898
21063
|
if (entryList.length > 1 && !noSort) {
|
|
18899
|
-
|
|
21064
|
+
// Decode + lowercase each name once rather than on every comparison:
|
|
21065
|
+
// the entryName getter re-decodes the underlying buffer on each access,
|
|
21066
|
+
// so the previous inline comparator did O(n log n) redundant decoding.
|
|
21067
|
+
// Ordering is unchanged (same localeCompare on the same keys).
|
|
21068
|
+
entryList = entryList
|
|
21069
|
+
.map((entry) => ({ entry, key: entry.entryName.toLowerCase() }))
|
|
21070
|
+
.sort((a, b) => a.key.localeCompare(b.key))
|
|
21071
|
+
.map((pair) => pair.entry);
|
|
18900
21072
|
}
|
|
18901
21073
|
}
|
|
18902
21074
|
|
|
@@ -19108,7 +21280,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
|
19108
21280
|
// write main header
|
|
19109
21281
|
const mh = mainHeader.toBinary();
|
|
19110
21282
|
if (_comment) {
|
|
19111
|
-
_comment.copy(mh,
|
|
21283
|
+
_comment.copy(mh, mh.length - _comment.length); // add zip file comment
|
|
19112
21284
|
}
|
|
19113
21285
|
mh.copy(outBuffer, dindex);
|
|
19114
21286
|
|
|
@@ -19186,7 +21358,7 @@ module.exports = function (/*Buffer|null*/ inBuffer, /** object */ options) {
|
|
|
19186
21358
|
|
|
19187
21359
|
const mh = mainHeader.toBinary();
|
|
19188
21360
|
if (_comment) {
|
|
19189
|
-
_comment.copy(mh,
|
|
21361
|
+
_comment.copy(mh, mh.length - _comment.length); // add zip file comment
|
|
19190
21362
|
}
|
|
19191
21363
|
|
|
19192
21364
|
mh.copy(outBuffer, dindex); // write main header
|
|
@@ -128150,7 +130322,7 @@ module.exports = {"version":"3.17.0"};
|
|
|
128150
130322
|
/***/ ((module) => {
|
|
128151
130323
|
|
|
128152
130324
|
"use strict";
|
|
128153
|
-
module.exports = /*#__PURE__*/JSON.parse('{"rE":"0.4.
|
|
130325
|
+
module.exports = /*#__PURE__*/JSON.parse('{"rE":"0.4.9-canary-807f2ef.0","h_":"ckb development network for your first try"}');
|
|
128154
130326
|
|
|
128155
130327
|
/***/ })
|
|
128156
130328
|
|