polkadot-cli 0.13.0 → 1.1.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.
Files changed (3) hide show
  1. package/README.md +79 -5
  2. package/dist/cli.mjs +1443 -317
  3. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -5,7 +5,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
5
5
  // src/cli.ts
6
6
  import cac from "cac";
7
7
  // package.json
8
- var version = "0.13.0";
8
+ var version = "1.1.0";
9
9
 
10
10
  // src/config/accounts-store.ts
11
11
  import { access as access2, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
@@ -429,7 +429,7 @@ class Spinner {
429
429
  start(msg) {
430
430
  this.stop();
431
431
  if (!isTTY) {
432
- console.log(msg);
432
+ console.error(msg);
433
433
  return;
434
434
  }
435
435
  process.stdout.write(`${SPINNER_FRAMES[0]} ${msg}`);
@@ -449,9 +449,16 @@ class Spinner {
449
449
  }
450
450
  succeed(msg) {
451
451
  this.stop();
452
- console.log(`${GREEN}${CHECK_MARK}${RESET} ${msg}`);
452
+ console.error(`${GREEN}${CHECK_MARK}${RESET} ${msg}`);
453
453
  }
454
454
  }
455
+ function firstSentence(docs) {
456
+ const text = docs.join(" ").trim();
457
+ if (!text)
458
+ return "";
459
+ const match = text.match(/^.*?(?<![ei]\.g|[ei]\.[eg])(?<!\betc)[.!?](?:\s|$)/);
460
+ return match ? match[0].trim() : text;
461
+ }
455
462
 
456
463
  // src/commands/account.ts
457
464
  var ACCOUNT_HELP = `
@@ -977,26 +984,28 @@ function listPallets(meta) {
977
984
  docs: c.docs ?? [],
978
985
  typeId: c.type
979
986
  })),
980
- calls: extractCalls(meta, p.calls)
987
+ calls: extractEnumVariants(meta, p.calls),
988
+ events: extractEnumVariants(meta, p.events),
989
+ errors: extractEnumVariants(meta, p.errors).map(({ name, docs }) => ({ name, docs }))
981
990
  }));
982
991
  }
983
- function extractCalls(meta, callsRef) {
984
- if (!callsRef)
992
+ function extractEnumVariants(meta, ref) {
993
+ if (!ref)
985
994
  return [];
986
995
  try {
987
- const entry = meta.lookup(callsRef.type);
996
+ const entry = meta.lookup(ref.type);
988
997
  if (entry.type !== "enum")
989
998
  return [];
990
999
  return Object.entries(entry.value).map(([name, variant]) => ({
991
1000
  name,
992
- docs: variant.docs ?? [],
993
- typeId: resolveCallTypeId(variant)
1001
+ docs: entry.innerDocs?.[name] ?? [],
1002
+ typeId: resolveVariantTypeId(variant)
994
1003
  }));
995
1004
  } catch {
996
1005
  return [];
997
1006
  }
998
1007
  }
999
- function resolveCallTypeId(variant) {
1008
+ function resolveVariantTypeId(variant) {
1000
1009
  if (variant.type === "lookupEntry")
1001
1010
  return variant.value?.id ?? null;
1002
1011
  if (variant.type === "struct")
@@ -1095,6 +1104,42 @@ function describeCallArgs(meta, palletName, callName) {
1095
1104
  return "";
1096
1105
  }
1097
1106
  }
1107
+ function describeEventFields(meta, palletName, eventName) {
1108
+ try {
1109
+ const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
1110
+ if (!palletMeta?.events)
1111
+ return "";
1112
+ const eventsEntry = meta.lookup(palletMeta.events.type);
1113
+ if (eventsEntry.type !== "enum")
1114
+ return "";
1115
+ const variant = eventsEntry.value[eventName];
1116
+ if (!variant)
1117
+ return "";
1118
+ if (variant.type === "void")
1119
+ return "()";
1120
+ if (variant.type === "struct") {
1121
+ const fields = Object.entries(variant.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
1122
+ return `(${fields})`;
1123
+ }
1124
+ if (variant.type === "lookupEntry") {
1125
+ const inner = variant.value;
1126
+ if (inner.type === "void")
1127
+ return "()";
1128
+ if (inner.type === "struct") {
1129
+ const fields = Object.entries(inner.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
1130
+ return `(${fields})`;
1131
+ }
1132
+ return `(${formatLookupEntry(inner)})`;
1133
+ }
1134
+ if (variant.type === "tuple") {
1135
+ const types = variant.value.map(formatLookupEntry).join(", ");
1136
+ return `(${types})`;
1137
+ }
1138
+ return "";
1139
+ } catch {
1140
+ return "";
1141
+ }
1142
+ }
1098
1143
  function hexToBytes(hex) {
1099
1144
  const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
1100
1145
  const bytes = new Uint8Array(clean.length / 2);
@@ -1170,10 +1215,10 @@ async function chainAdd(name, opts) {
1170
1215
  rpc: opts.rpc ?? "",
1171
1216
  ...opts.lightClient ? { lightClient: true } : {}
1172
1217
  };
1173
- console.log(`Connecting to ${name}...`);
1218
+ console.error(`Connecting to ${name}...`);
1174
1219
  const clientHandle = await createChainClient(name, chainConfig, opts.rpc);
1175
1220
  try {
1176
- console.log("Fetching metadata...");
1221
+ console.error("Fetching metadata...");
1177
1222
  await fetchMetadataFromChain(clientHandle, name);
1178
1223
  const config = await loadConfig();
1179
1224
  config.chains[name] = chainConfig;
@@ -1226,10 +1271,10 @@ async function chainList() {
1226
1271
  async function chainUpdate(name, opts) {
1227
1272
  const config = await loadConfig();
1228
1273
  const { name: chainName, chain: chainConfig } = resolveChain(config, name);
1229
- console.log(`Connecting to ${chainName}...`);
1274
+ console.error(`Connecting to ${chainName}...`);
1230
1275
  const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
1231
1276
  try {
1232
- console.log("Fetching metadata...");
1277
+ console.error("Fetching metadata...");
1233
1278
  await fetchMetadataFromChain(clientHandle, chainName);
1234
1279
  console.log(`Metadata for "${chainName}" updated.`);
1235
1280
  } finally {
@@ -1288,96 +1333,822 @@ function suggestMessage(kind, input, candidates) {
1288
1333
  return `Unknown ${kind} "${input}". Did you mean: ${suggestions.join(", ")}?`;
1289
1334
  }
1290
1335
 
1291
- // src/utils/parse-target.ts
1292
- function parseTarget(input, options) {
1293
- const parts = input.split(".");
1294
- if (options?.allowPalletOnly) {
1295
- switch (parts.length) {
1296
- case 1:
1297
- if (!parts[0]) {
1298
- throw new Error(`Invalid target "${input}". Expected format: Pallet or Pallet.Item (e.g. System or System.Account)`);
1299
- }
1300
- return { pallet: parts[0] };
1301
- case 2:
1302
- if (!parts[0] || !parts[1]) {
1303
- throw new Error(`Invalid target "${input}". Expected format: Pallet.Item or Chain.Pallet (e.g. System.Account or kusama.System)`);
1304
- }
1305
- if (options.knownChains?.some((c) => c.toLowerCase() === parts[0].toLowerCase())) {
1306
- return { chain: parts[0], pallet: parts[1] };
1307
- }
1308
- return { pallet: parts[0], item: parts[1] };
1309
- case 3:
1310
- if (!parts[0] || !parts[1] || !parts[2]) {
1311
- throw new Error(`Invalid target "${input}". Expected format: Chain.Pallet.Item (e.g. kusama.System.Account)`);
1312
- }
1313
- return { chain: parts[0], pallet: parts[1], item: parts[2] };
1314
- default:
1315
- throw new Error(`Invalid target "${input}". Expected format: Pallet, Pallet.Item, or Chain.Pallet.Item`);
1336
+ // src/commands/focused-inspect.ts
1337
+ async function loadMeta(chainName, chainConfig, rpcOverride) {
1338
+ try {
1339
+ return await getOrFetchMetadata(chainName);
1340
+ } catch {
1341
+ console.error(`Fetching metadata from ${chainName}...`);
1342
+ const clientHandle = await createChainClient(chainName, chainConfig, rpcOverride);
1343
+ try {
1344
+ return await getOrFetchMetadata(chainName, clientHandle);
1345
+ } finally {
1346
+ clientHandle.destroy();
1316
1347
  }
1317
1348
  }
1318
- switch (parts.length) {
1319
- case 2:
1320
- if (!parts[0] || !parts[1]) {
1321
- throw new Error(`Invalid target "${input}". Expected format: Pallet.Item (e.g. System.Account)`);
1349
+ }
1350
+ function resolvePallet(meta, palletName) {
1351
+ const palletNames = getPalletNames(meta);
1352
+ const pallet = findPallet(meta, palletName);
1353
+ if (!pallet) {
1354
+ throw new Error(suggestMessage("pallet", palletName, palletNames));
1355
+ }
1356
+ return pallet;
1357
+ }
1358
+ async function handleCalls(target, opts) {
1359
+ if (!target) {
1360
+ const config2 = await loadConfig();
1361
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1362
+ const meta2 = await loadMeta(chainName2, chainConfig2, opts.rpc);
1363
+ const pallets = listPallets(meta2);
1364
+ const withCalls = pallets.filter((p) => p.calls.length > 0);
1365
+ printHeading(`Pallets with calls on ${chainName2} (${withCalls.length})`);
1366
+ for (const p of withCalls) {
1367
+ printItem(p.name, `${p.calls.length} calls`);
1368
+ }
1369
+ console.log();
1370
+ return;
1371
+ }
1372
+ const config = await loadConfig();
1373
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1374
+ const meta = await loadMeta(chainName, chainConfig, opts.rpc);
1375
+ const dotIdx = target.indexOf(".");
1376
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1377
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1378
+ const pallet = resolvePallet(meta, palletName);
1379
+ if (!itemName) {
1380
+ if (pallet.calls.length === 0) {
1381
+ console.log(`No calls in ${pallet.name}.`);
1382
+ return;
1383
+ }
1384
+ printHeading(`${pallet.name} Calls`);
1385
+ for (const c of pallet.calls) {
1386
+ const args2 = describeCallArgs(meta, pallet.name, c.name);
1387
+ console.log(` ${CYAN}${c.name}${RESET}${DIM}${args2}${RESET}`);
1388
+ const summary = firstSentence(c.docs);
1389
+ if (summary) {
1390
+ console.log(` ${DIM}${summary}${RESET}`);
1322
1391
  }
1323
- return { pallet: parts[0], item: parts[1] };
1324
- case 3:
1325
- if (!parts[0] || !parts[1] || !parts[2]) {
1326
- throw new Error(`Invalid target "${input}". Expected format: Chain.Pallet.Item (e.g. kusama.System.Account)`);
1392
+ }
1393
+ console.log();
1394
+ return;
1395
+ }
1396
+ const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
1397
+ if (!callItem) {
1398
+ const names = pallet.calls.map((c) => c.name);
1399
+ throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
1400
+ }
1401
+ printHeading(`${pallet.name}.${callItem.name} (Call)`);
1402
+ const args = describeCallArgs(meta, pallet.name, callItem.name);
1403
+ console.log(` ${BOLD}Args:${RESET} ${args}`);
1404
+ if (callItem.docs.length) {
1405
+ console.log();
1406
+ printDocs(callItem.docs);
1407
+ }
1408
+ console.log();
1409
+ }
1410
+ async function handleEvents(target, opts) {
1411
+ if (!target) {
1412
+ const config2 = await loadConfig();
1413
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1414
+ const meta2 = await loadMeta(chainName2, chainConfig2, opts.rpc);
1415
+ const pallets = listPallets(meta2);
1416
+ const withEvents = pallets.filter((p) => p.events.length > 0);
1417
+ printHeading(`Pallets with events on ${chainName2} (${withEvents.length})`);
1418
+ for (const p of withEvents) {
1419
+ printItem(p.name, `${p.events.length} events`);
1420
+ }
1421
+ console.log();
1422
+ return;
1423
+ }
1424
+ const config = await loadConfig();
1425
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1426
+ const meta = await loadMeta(chainName, chainConfig, opts.rpc);
1427
+ const dotIdx = target.indexOf(".");
1428
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1429
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1430
+ const pallet = resolvePallet(meta, palletName);
1431
+ if (!itemName) {
1432
+ if (pallet.events.length === 0) {
1433
+ console.log(`No events in ${pallet.name}.`);
1434
+ return;
1435
+ }
1436
+ printHeading(`${pallet.name} Events`);
1437
+ for (const e of pallet.events) {
1438
+ const fields2 = describeEventFields(meta, pallet.name, e.name);
1439
+ console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields2}${RESET}`);
1440
+ const summary = firstSentence(e.docs);
1441
+ if (summary) {
1442
+ console.log(` ${DIM}${summary}${RESET}`);
1327
1443
  }
1328
- return { chain: parts[0], pallet: parts[1], item: parts[2] };
1329
- default:
1330
- throw new Error(`Invalid target "${input}". Expected format: Pallet.Item (e.g. System.Account)`);
1444
+ }
1445
+ console.log();
1446
+ return;
1447
+ }
1448
+ const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
1449
+ if (!eventItem) {
1450
+ const names = pallet.events.map((e) => e.name);
1451
+ throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
1331
1452
  }
1453
+ printHeading(`${pallet.name}.${eventItem.name} (Event)`);
1454
+ const fields = describeEventFields(meta, pallet.name, eventItem.name);
1455
+ console.log(` ${BOLD}Fields:${RESET} ${fields}`);
1456
+ if (eventItem.docs.length) {
1457
+ console.log();
1458
+ printDocs(eventItem.docs);
1459
+ }
1460
+ console.log();
1332
1461
  }
1333
- function resolveTargetChain(target, chainFlag) {
1334
- if (target.chain && chainFlag) {
1335
- throw new Error(`Chain specified both as prefix ("${target.chain}") and as --chain flag ("${chainFlag}"). Use one or the other.`);
1462
+ async function handleErrors(target, opts) {
1463
+ if (!target) {
1464
+ const config2 = await loadConfig();
1465
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1466
+ const meta2 = await loadMeta(chainName2, chainConfig2, opts.rpc);
1467
+ const pallets = listPallets(meta2);
1468
+ const withErrors = pallets.filter((p) => p.errors.length > 0);
1469
+ printHeading(`Pallets with errors on ${chainName2} (${withErrors.length})`);
1470
+ for (const p of withErrors) {
1471
+ printItem(p.name, `${p.errors.length} errors`);
1472
+ }
1473
+ console.log();
1474
+ return;
1475
+ }
1476
+ const config = await loadConfig();
1477
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1478
+ const meta = await loadMeta(chainName, chainConfig, opts.rpc);
1479
+ const dotIdx = target.indexOf(".");
1480
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1481
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1482
+ const pallet = resolvePallet(meta, palletName);
1483
+ if (!itemName) {
1484
+ if (pallet.errors.length === 0) {
1485
+ console.log(`No errors in ${pallet.name}.`);
1486
+ return;
1487
+ }
1488
+ printHeading(`${pallet.name} Errors`);
1489
+ for (const e of pallet.errors) {
1490
+ console.log(` ${CYAN}${e.name}${RESET}`);
1491
+ const summary = firstSentence(e.docs);
1492
+ if (summary) {
1493
+ console.log(` ${DIM}${summary}${RESET}`);
1494
+ }
1495
+ }
1496
+ console.log();
1497
+ return;
1498
+ }
1499
+ const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
1500
+ if (!errorItem) {
1501
+ const names = pallet.errors.map((e) => e.name);
1502
+ throw new Error(suggestMessage(`error in ${pallet.name}`, itemName, names));
1503
+ }
1504
+ printHeading(`${pallet.name}.${errorItem.name} (Error)`);
1505
+ if (errorItem.docs.length) {
1506
+ printDocs(errorItem.docs);
1507
+ }
1508
+ console.log();
1509
+ }
1510
+ async function handleStorage(target, opts) {
1511
+ if (!target) {
1512
+ const config2 = await loadConfig();
1513
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1514
+ const meta2 = await loadMeta(chainName2, chainConfig2, opts.rpc);
1515
+ const pallets = listPallets(meta2);
1516
+ const withStorage = pallets.filter((p) => p.storage.length > 0);
1517
+ printHeading(`Pallets with storage on ${chainName2} (${withStorage.length})`);
1518
+ for (const p of withStorage) {
1519
+ printItem(p.name, `${p.storage.length} storage`);
1520
+ }
1521
+ console.log();
1522
+ return;
1523
+ }
1524
+ const config = await loadConfig();
1525
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1526
+ const meta = await loadMeta(chainName, chainConfig, opts.rpc);
1527
+ const dotIdx = target.indexOf(".");
1528
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1529
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1530
+ const pallet = resolvePallet(meta, palletName);
1531
+ if (!itemName) {
1532
+ if (pallet.storage.length === 0) {
1533
+ console.log(`No storage items in ${pallet.name}.`);
1534
+ return;
1535
+ }
1536
+ printHeading(`${pallet.name} Storage`);
1537
+ for (const s of pallet.storage) {
1538
+ const valueType = describeType(meta.lookup, s.valueTypeId);
1539
+ let typeSuffix;
1540
+ if (s.keyTypeId != null) {
1541
+ const keyType = describeType(meta.lookup, s.keyTypeId);
1542
+ typeSuffix = `: ${keyType} → ${valueType} [map]`;
1543
+ } else {
1544
+ typeSuffix = `: ${valueType}`;
1545
+ }
1546
+ console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
1547
+ const summary = firstSentence(s.docs);
1548
+ if (summary) {
1549
+ console.log(` ${DIM}${summary}${RESET}`);
1550
+ }
1551
+ }
1552
+ console.log();
1553
+ return;
1554
+ }
1555
+ const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
1556
+ if (!storageItem) {
1557
+ const names = pallet.storage.map((s) => s.name);
1558
+ throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
1559
+ }
1560
+ printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
1561
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
1562
+ console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
1563
+ if (storageItem.keyTypeId != null) {
1564
+ console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
1565
+ }
1566
+ if (storageItem.docs.length) {
1567
+ console.log();
1568
+ printDocs(storageItem.docs);
1569
+ }
1570
+ console.log();
1571
+ }
1572
+ async function showItemHelp(category, target, opts) {
1573
+ const config = await loadConfig();
1574
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1575
+ const meta = await loadMeta(chainName, chainConfig, opts.rpc);
1576
+ const dotIdx = target.indexOf(".");
1577
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1578
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1579
+ const pallet = resolvePallet(meta, palletName);
1580
+ if (!itemName) {
1581
+ switch (category) {
1582
+ case "tx":
1583
+ await handleCalls(target, opts);
1584
+ return;
1585
+ case "query":
1586
+ await handleStorage(target, opts);
1587
+ return;
1588
+ case "const":
1589
+ return;
1590
+ case "events":
1591
+ await handleEvents(target, opts);
1592
+ return;
1593
+ case "errors":
1594
+ await handleErrors(target, opts);
1595
+ return;
1596
+ }
1597
+ }
1598
+ switch (category) {
1599
+ case "tx": {
1600
+ const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
1601
+ if (!callItem) {
1602
+ const names = pallet.calls.map((c) => c.name);
1603
+ throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
1604
+ }
1605
+ printHeading(`${pallet.name}.${callItem.name} (Call)`);
1606
+ const args = describeCallArgs(meta, pallet.name, callItem.name);
1607
+ console.log(` ${BOLD}Args:${RESET} ${args}`);
1608
+ if (callItem.docs.length) {
1609
+ console.log();
1610
+ printDocs(callItem.docs);
1611
+ }
1612
+ console.log();
1613
+ console.log(`${BOLD}Usage:${RESET}`);
1614
+ console.log(` dot tx.${pallet.name}.${callItem.name} --from <account>`);
1615
+ console.log(` dot tx.${pallet.name}.${callItem.name} --encode`);
1616
+ console.log();
1617
+ console.log(`${BOLD}Options:${RESET}`);
1618
+ console.log(` --from <name> Account to sign with`);
1619
+ console.log(` --dry-run Estimate fees without submitting`);
1620
+ console.log(` --encode Encode call to hex without signing`);
1621
+ console.log(` --ext <json> Custom signed extension values as JSON`);
1622
+ console.log();
1623
+ return;
1624
+ }
1625
+ case "query": {
1626
+ const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
1627
+ if (!storageItem) {
1628
+ const names = pallet.storage.map((s) => s.name);
1629
+ throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
1630
+ }
1631
+ printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
1632
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
1633
+ console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
1634
+ if (storageItem.keyTypeId != null) {
1635
+ console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
1636
+ }
1637
+ if (storageItem.docs.length) {
1638
+ console.log();
1639
+ printDocs(storageItem.docs);
1640
+ }
1641
+ console.log();
1642
+ if (storageItem.keyTypeId != null) {
1643
+ console.log(`${BOLD}Usage:${RESET}`);
1644
+ console.log(` dot query.${pallet.name}.${storageItem.name} <key>`);
1645
+ console.log(` dot query.${pallet.name}.${storageItem.name} # all entries`);
1646
+ } else {
1647
+ console.log(`${BOLD}Usage:${RESET}`);
1648
+ console.log(` dot query.${pallet.name}.${storageItem.name}`);
1649
+ }
1650
+ console.log();
1651
+ console.log(`${BOLD}Options:${RESET}`);
1652
+ console.log(` --limit <n> Max entries for map queries (0 = unlimited, default: 100)`);
1653
+ console.log();
1654
+ return;
1655
+ }
1656
+ case "const": {
1657
+ const constItem = pallet.constants.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
1658
+ if (!constItem) {
1659
+ const names = pallet.constants.map((c) => c.name);
1660
+ throw new Error(suggestMessage(`constant in ${pallet.name}`, itemName, names));
1661
+ }
1662
+ printHeading(`${pallet.name}.${constItem.name} (Constant)`);
1663
+ console.log(` ${BOLD}Type:${RESET} ${describeType(meta.lookup, constItem.typeId)}`);
1664
+ if (constItem.docs.length) {
1665
+ console.log();
1666
+ printDocs(constItem.docs);
1667
+ }
1668
+ console.log();
1669
+ console.log(`${BOLD}Usage:${RESET}`);
1670
+ console.log(` dot const.${pallet.name}.${constItem.name}`);
1671
+ console.log();
1672
+ return;
1673
+ }
1674
+ case "events": {
1675
+ const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
1676
+ if (!eventItem) {
1677
+ const names = pallet.events.map((e) => e.name);
1678
+ throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
1679
+ }
1680
+ printHeading(`${pallet.name}.${eventItem.name} (Event)`);
1681
+ const fields = describeEventFields(meta, pallet.name, eventItem.name);
1682
+ console.log(` ${BOLD}Fields:${RESET} ${fields}`);
1683
+ if (eventItem.docs.length) {
1684
+ console.log();
1685
+ printDocs(eventItem.docs);
1686
+ }
1687
+ console.log();
1688
+ console.log(`${BOLD}Usage:${RESET}`);
1689
+ console.log(` dot events.${pallet.name}.${eventItem.name}`);
1690
+ console.log();
1691
+ return;
1692
+ }
1693
+ case "errors": {
1694
+ const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
1695
+ if (!errorItem) {
1696
+ const names = pallet.errors.map((e) => e.name);
1697
+ throw new Error(suggestMessage(`error in ${pallet.name}`, itemName, names));
1698
+ }
1699
+ printHeading(`${pallet.name}.${errorItem.name} (Error)`);
1700
+ if (errorItem.docs.length) {
1701
+ printDocs(errorItem.docs);
1702
+ }
1703
+ console.log();
1704
+ console.log(`${BOLD}Usage:${RESET}`);
1705
+ console.log(` dot errors.${pallet.name}.${errorItem.name}`);
1706
+ console.log();
1707
+ return;
1708
+ }
1336
1709
  }
1337
- return target.chain ?? chainFlag;
1338
1710
  }
1339
1711
 
1340
1712
  // src/commands/const.ts
1341
- function registerConstCommand(cli) {
1342
- cli.command("const [target]", "Look up a pallet constant (e.g. Balances.ExistentialDeposit)").action(async (target, opts) => {
1343
- if (!target) {
1344
- console.log("Usage: dot const <[Chain.]Pallet.Constant> [--chain <name>] [--output json]");
1345
- console.log("");
1346
- console.log("Examples:");
1347
- console.log(" $ dot const Balances.ExistentialDeposit");
1348
- console.log(" $ dot const System.SS58Prefix --chain kusama");
1349
- console.log(" $ dot const kusama.Balances.ExistentialDeposit # chain prefix");
1713
+ async function handleConst(target, opts) {
1714
+ if (!target) {
1715
+ const config2 = await loadConfig();
1716
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1717
+ const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
1718
+ const pallets = listPallets(meta);
1719
+ const withConsts = pallets.filter((p) => p.constants.length > 0);
1720
+ printHeading(`Pallets with constants on ${chainName2} (${withConsts.length})`);
1721
+ for (const p of withConsts) {
1722
+ printItem(p.name, `${p.constants.length} constants`);
1723
+ }
1724
+ console.log();
1725
+ return;
1726
+ }
1727
+ const dotIdx = target.indexOf(".");
1728
+ const pallet = dotIdx === -1 ? target : target.slice(0, dotIdx);
1729
+ const item = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1730
+ const config = await loadConfig();
1731
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1732
+ if (!item) {
1733
+ const meta = await loadMeta(chainName, chainConfig, opts.rpc);
1734
+ const palletNames = getPalletNames(meta);
1735
+ const palletInfo = findPallet(meta, pallet);
1736
+ if (!palletInfo) {
1737
+ throw new Error(suggestMessage("pallet", pallet, palletNames));
1738
+ }
1739
+ if (palletInfo.constants.length === 0) {
1740
+ console.log(`No constants in ${palletInfo.name}.`);
1741
+ return;
1742
+ }
1743
+ printHeading(`${palletInfo.name} Constants`);
1744
+ for (const c of palletInfo.constants) {
1745
+ const typeStr = describeType(meta.lookup, c.typeId);
1746
+ console.log(` ${CYAN}${c.name}${RESET}${DIM}: ${typeStr}${RESET}`);
1747
+ const summary = firstSentence(c.docs);
1748
+ if (summary) {
1749
+ console.log(` ${DIM}${summary}${RESET}`);
1750
+ }
1751
+ }
1752
+ console.log();
1753
+ return;
1754
+ }
1755
+ const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
1756
+ try {
1757
+ const meta = await getOrFetchMetadata(chainName, clientHandle);
1758
+ const palletNames = getPalletNames(meta);
1759
+ const palletInfo = findPallet(meta, pallet);
1760
+ if (!palletInfo) {
1761
+ throw new Error(suggestMessage("pallet", pallet, palletNames));
1762
+ }
1763
+ const constantItem = palletInfo.constants.find((c) => c.name.toLowerCase() === item.toLowerCase());
1764
+ if (!constantItem) {
1765
+ const constNames = palletInfo.constants.map((c) => c.name);
1766
+ throw new Error(suggestMessage(`constant in ${palletInfo.name}`, item, constNames));
1767
+ }
1768
+ const unsafeApi = clientHandle.client.getUnsafeApi();
1769
+ const runtimeToken = await unsafeApi.runtimeToken;
1770
+ const result = unsafeApi.constants[palletInfo.name][constantItem.name](runtimeToken);
1771
+ const format = opts.output ?? "pretty";
1772
+ printResult(result, format);
1773
+ } finally {
1774
+ clientHandle.destroy();
1775
+ }
1776
+ }
1777
+
1778
+ // src/commands/focused-inspect.ts
1779
+ async function loadMeta2(chainName, chainConfig, rpcOverride) {
1780
+ try {
1781
+ return await getOrFetchMetadata(chainName);
1782
+ } catch {
1783
+ console.error(`Fetching metadata from ${chainName}...`);
1784
+ const clientHandle = await createChainClient(chainName, chainConfig, rpcOverride);
1785
+ try {
1786
+ return await getOrFetchMetadata(chainName, clientHandle);
1787
+ } finally {
1788
+ clientHandle.destroy();
1789
+ }
1790
+ }
1791
+ }
1792
+ function resolvePallet2(meta, palletName) {
1793
+ const palletNames = getPalletNames(meta);
1794
+ const pallet = findPallet(meta, palletName);
1795
+ if (!pallet) {
1796
+ throw new Error(suggestMessage("pallet", palletName, palletNames));
1797
+ }
1798
+ return pallet;
1799
+ }
1800
+ async function handleCalls2(target, opts) {
1801
+ if (!target) {
1802
+ const config2 = await loadConfig();
1803
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1804
+ const meta2 = await loadMeta2(chainName2, chainConfig2, opts.rpc);
1805
+ const pallets = listPallets(meta2);
1806
+ const withCalls = pallets.filter((p) => p.calls.length > 0);
1807
+ printHeading(`Pallets with calls on ${chainName2} (${withCalls.length})`);
1808
+ for (const p of withCalls) {
1809
+ printItem(p.name, `${p.calls.length} calls`);
1810
+ }
1811
+ console.log();
1812
+ return;
1813
+ }
1814
+ const config = await loadConfig();
1815
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1816
+ const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
1817
+ const dotIdx = target.indexOf(".");
1818
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1819
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1820
+ const pallet = resolvePallet2(meta, palletName);
1821
+ if (!itemName) {
1822
+ if (pallet.calls.length === 0) {
1823
+ console.log(`No calls in ${pallet.name}.`);
1824
+ return;
1825
+ }
1826
+ printHeading(`${pallet.name} Calls`);
1827
+ for (const c of pallet.calls) {
1828
+ const args2 = describeCallArgs(meta, pallet.name, c.name);
1829
+ console.log(` ${CYAN}${c.name}${RESET}${DIM}${args2}${RESET}`);
1830
+ const summary = firstSentence(c.docs);
1831
+ if (summary) {
1832
+ console.log(` ${DIM}${summary}${RESET}`);
1833
+ }
1834
+ }
1835
+ console.log();
1836
+ return;
1837
+ }
1838
+ const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
1839
+ if (!callItem) {
1840
+ const names = pallet.calls.map((c) => c.name);
1841
+ throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
1842
+ }
1843
+ printHeading(`${pallet.name}.${callItem.name} (Call)`);
1844
+ const args = describeCallArgs(meta, pallet.name, callItem.name);
1845
+ console.log(` ${BOLD}Args:${RESET} ${args}`);
1846
+ if (callItem.docs.length) {
1847
+ console.log();
1848
+ printDocs(callItem.docs);
1849
+ }
1850
+ console.log();
1851
+ }
1852
+ async function handleEvents2(target, opts) {
1853
+ if (!target) {
1854
+ const config2 = await loadConfig();
1855
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1856
+ const meta2 = await loadMeta2(chainName2, chainConfig2, opts.rpc);
1857
+ const pallets = listPallets(meta2);
1858
+ const withEvents = pallets.filter((p) => p.events.length > 0);
1859
+ printHeading(`Pallets with events on ${chainName2} (${withEvents.length})`);
1860
+ for (const p of withEvents) {
1861
+ printItem(p.name, `${p.events.length} events`);
1862
+ }
1863
+ console.log();
1864
+ return;
1865
+ }
1866
+ const config = await loadConfig();
1867
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1868
+ const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
1869
+ const dotIdx = target.indexOf(".");
1870
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1871
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1872
+ const pallet = resolvePallet2(meta, palletName);
1873
+ if (!itemName) {
1874
+ if (pallet.events.length === 0) {
1875
+ console.log(`No events in ${pallet.name}.`);
1876
+ return;
1877
+ }
1878
+ printHeading(`${pallet.name} Events`);
1879
+ for (const e of pallet.events) {
1880
+ const fields2 = describeEventFields(meta, pallet.name, e.name);
1881
+ console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields2}${RESET}`);
1882
+ const summary = firstSentence(e.docs);
1883
+ if (summary) {
1884
+ console.log(` ${DIM}${summary}${RESET}`);
1885
+ }
1886
+ }
1887
+ console.log();
1888
+ return;
1889
+ }
1890
+ const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
1891
+ if (!eventItem) {
1892
+ const names = pallet.events.map((e) => e.name);
1893
+ throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
1894
+ }
1895
+ printHeading(`${pallet.name}.${eventItem.name} (Event)`);
1896
+ const fields = describeEventFields(meta, pallet.name, eventItem.name);
1897
+ console.log(` ${BOLD}Fields:${RESET} ${fields}`);
1898
+ if (eventItem.docs.length) {
1899
+ console.log();
1900
+ printDocs(eventItem.docs);
1901
+ }
1902
+ console.log();
1903
+ }
1904
+ async function handleErrors2(target, opts) {
1905
+ if (!target) {
1906
+ const config2 = await loadConfig();
1907
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1908
+ const meta2 = await loadMeta2(chainName2, chainConfig2, opts.rpc);
1909
+ const pallets = listPallets(meta2);
1910
+ const withErrors = pallets.filter((p) => p.errors.length > 0);
1911
+ printHeading(`Pallets with errors on ${chainName2} (${withErrors.length})`);
1912
+ for (const p of withErrors) {
1913
+ printItem(p.name, `${p.errors.length} errors`);
1914
+ }
1915
+ console.log();
1916
+ return;
1917
+ }
1918
+ const config = await loadConfig();
1919
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1920
+ const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
1921
+ const dotIdx = target.indexOf(".");
1922
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1923
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1924
+ const pallet = resolvePallet2(meta, palletName);
1925
+ if (!itemName) {
1926
+ if (pallet.errors.length === 0) {
1927
+ console.log(`No errors in ${pallet.name}.`);
1928
+ return;
1929
+ }
1930
+ printHeading(`${pallet.name} Errors`);
1931
+ for (const e of pallet.errors) {
1932
+ console.log(` ${CYAN}${e.name}${RESET}`);
1933
+ const summary = firstSentence(e.docs);
1934
+ if (summary) {
1935
+ console.log(` ${DIM}${summary}${RESET}`);
1936
+ }
1937
+ }
1938
+ console.log();
1939
+ return;
1940
+ }
1941
+ const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
1942
+ if (!errorItem) {
1943
+ const names = pallet.errors.map((e) => e.name);
1944
+ throw new Error(suggestMessage(`error in ${pallet.name}`, itemName, names));
1945
+ }
1946
+ printHeading(`${pallet.name}.${errorItem.name} (Error)`);
1947
+ if (errorItem.docs.length) {
1948
+ printDocs(errorItem.docs);
1949
+ }
1950
+ console.log();
1951
+ }
1952
+ async function handleStorage2(target, opts) {
1953
+ if (!target) {
1954
+ const config2 = await loadConfig();
1955
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
1956
+ const meta2 = await loadMeta2(chainName2, chainConfig2, opts.rpc);
1957
+ const pallets = listPallets(meta2);
1958
+ const withStorage = pallets.filter((p) => p.storage.length > 0);
1959
+ printHeading(`Pallets with storage on ${chainName2} (${withStorage.length})`);
1960
+ for (const p of withStorage) {
1961
+ printItem(p.name, `${p.storage.length} storage`);
1962
+ }
1963
+ console.log();
1964
+ return;
1965
+ }
1966
+ const config = await loadConfig();
1967
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1968
+ const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
1969
+ const dotIdx = target.indexOf(".");
1970
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
1971
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
1972
+ const pallet = resolvePallet2(meta, palletName);
1973
+ if (!itemName) {
1974
+ if (pallet.storage.length === 0) {
1975
+ console.log(`No storage items in ${pallet.name}.`);
1976
+ return;
1977
+ }
1978
+ printHeading(`${pallet.name} Storage`);
1979
+ for (const s of pallet.storage) {
1980
+ const valueType = describeType(meta.lookup, s.valueTypeId);
1981
+ let typeSuffix;
1982
+ if (s.keyTypeId != null) {
1983
+ const keyType = describeType(meta.lookup, s.keyTypeId);
1984
+ typeSuffix = `: ${keyType} → ${valueType} [map]`;
1985
+ } else {
1986
+ typeSuffix = `: ${valueType}`;
1987
+ }
1988
+ console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
1989
+ const summary = firstSentence(s.docs);
1990
+ if (summary) {
1991
+ console.log(` ${DIM}${summary}${RESET}`);
1992
+ }
1993
+ }
1994
+ console.log();
1995
+ return;
1996
+ }
1997
+ const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
1998
+ if (!storageItem) {
1999
+ const names = pallet.storage.map((s) => s.name);
2000
+ throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
2001
+ }
2002
+ printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
2003
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
2004
+ console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
2005
+ if (storageItem.keyTypeId != null) {
2006
+ console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
2007
+ }
2008
+ if (storageItem.docs.length) {
2009
+ console.log();
2010
+ printDocs(storageItem.docs);
2011
+ }
2012
+ console.log();
2013
+ }
2014
+ async function showItemHelp2(category, target, opts) {
2015
+ const config = await loadConfig();
2016
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
2017
+ const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
2018
+ const dotIdx = target.indexOf(".");
2019
+ const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
2020
+ const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
2021
+ const pallet = resolvePallet2(meta, palletName);
2022
+ if (!itemName) {
2023
+ switch (category) {
2024
+ case "tx":
2025
+ await handleCalls2(target, opts);
2026
+ return;
2027
+ case "query":
2028
+ await handleStorage2(target, opts);
2029
+ return;
2030
+ case "const":
2031
+ return;
2032
+ case "events":
2033
+ await handleEvents2(target, opts);
2034
+ return;
2035
+ case "errors":
2036
+ await handleErrors2(target, opts);
2037
+ return;
2038
+ }
2039
+ }
2040
+ switch (category) {
2041
+ case "tx": {
2042
+ const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
2043
+ if (!callItem) {
2044
+ const names = pallet.calls.map((c) => c.name);
2045
+ throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
2046
+ }
2047
+ printHeading(`${pallet.name}.${callItem.name} (Call)`);
2048
+ const args = describeCallArgs(meta, pallet.name, callItem.name);
2049
+ console.log(` ${BOLD}Args:${RESET} ${args}`);
2050
+ if (callItem.docs.length) {
2051
+ console.log();
2052
+ printDocs(callItem.docs);
2053
+ }
2054
+ console.log();
2055
+ console.log(`${BOLD}Usage:${RESET}`);
2056
+ console.log(` dot tx.${pallet.name}.${callItem.name} --from <account>`);
2057
+ console.log(` dot tx.${pallet.name}.${callItem.name} --encode`);
2058
+ console.log();
2059
+ console.log(`${BOLD}Options:${RESET}`);
2060
+ console.log(` --from <name> Account to sign with`);
2061
+ console.log(` --dry-run Estimate fees without submitting`);
2062
+ console.log(` --encode Encode call to hex without signing`);
2063
+ console.log(` --ext <json> Custom signed extension values as JSON`);
2064
+ console.log();
2065
+ return;
2066
+ }
2067
+ case "query": {
2068
+ const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
2069
+ if (!storageItem) {
2070
+ const names = pallet.storage.map((s) => s.name);
2071
+ throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
2072
+ }
2073
+ printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
2074
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
2075
+ console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
2076
+ if (storageItem.keyTypeId != null) {
2077
+ console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
2078
+ }
2079
+ if (storageItem.docs.length) {
2080
+ console.log();
2081
+ printDocs(storageItem.docs);
2082
+ }
2083
+ console.log();
2084
+ if (storageItem.keyTypeId != null) {
2085
+ console.log(`${BOLD}Usage:${RESET}`);
2086
+ console.log(` dot query.${pallet.name}.${storageItem.name} <key>`);
2087
+ console.log(` dot query.${pallet.name}.${storageItem.name} # all entries`);
2088
+ } else {
2089
+ console.log(`${BOLD}Usage:${RESET}`);
2090
+ console.log(` dot query.${pallet.name}.${storageItem.name}`);
2091
+ }
2092
+ console.log();
2093
+ console.log(`${BOLD}Options:${RESET}`);
2094
+ console.log(` --limit <n> Max entries for map queries (0 = unlimited, default: 100)`);
2095
+ console.log();
2096
+ return;
2097
+ }
2098
+ case "const": {
2099
+ const constItem = pallet.constants.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
2100
+ if (!constItem) {
2101
+ const names = pallet.constants.map((c) => c.name);
2102
+ throw new Error(suggestMessage(`constant in ${pallet.name}`, itemName, names));
2103
+ }
2104
+ printHeading(`${pallet.name}.${constItem.name} (Constant)`);
2105
+ console.log(` ${BOLD}Type:${RESET} ${describeType(meta.lookup, constItem.typeId)}`);
2106
+ if (constItem.docs.length) {
2107
+ console.log();
2108
+ printDocs(constItem.docs);
2109
+ }
2110
+ console.log();
2111
+ console.log(`${BOLD}Usage:${RESET}`);
2112
+ console.log(` dot const.${pallet.name}.${constItem.name}`);
2113
+ console.log();
2114
+ return;
2115
+ }
2116
+ case "events": {
2117
+ const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
2118
+ if (!eventItem) {
2119
+ const names = pallet.events.map((e) => e.name);
2120
+ throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
2121
+ }
2122
+ printHeading(`${pallet.name}.${eventItem.name} (Event)`);
2123
+ const fields = describeEventFields(meta, pallet.name, eventItem.name);
2124
+ console.log(` ${BOLD}Fields:${RESET} ${fields}`);
2125
+ if (eventItem.docs.length) {
2126
+ console.log();
2127
+ printDocs(eventItem.docs);
2128
+ }
2129
+ console.log();
2130
+ console.log(`${BOLD}Usage:${RESET}`);
2131
+ console.log(` dot events.${pallet.name}.${eventItem.name}`);
2132
+ console.log();
1350
2133
  return;
1351
2134
  }
1352
- const config = await loadConfig();
1353
- const knownChains = Object.keys(config.chains);
1354
- const parsed = parseTarget(target, { knownChains });
1355
- const effectiveChain = resolveTargetChain(parsed, opts.chain);
1356
- const { name: chainName, chain: chainConfig } = resolveChain(config, effectiveChain);
1357
- const pallet = parsed.pallet;
1358
- const item = parsed.item;
1359
- const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
1360
- try {
1361
- const meta = await getOrFetchMetadata(chainName, clientHandle);
1362
- const palletNames = getPalletNames(meta);
1363
- const palletInfo = findPallet(meta, pallet);
1364
- if (!palletInfo) {
1365
- throw new Error(suggestMessage("pallet", pallet, palletNames));
2135
+ case "errors": {
2136
+ const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
2137
+ if (!errorItem) {
2138
+ const names = pallet.errors.map((e) => e.name);
2139
+ throw new Error(suggestMessage(`error in ${pallet.name}`, itemName, names));
1366
2140
  }
1367
- const constantItem = palletInfo.constants.find((c) => c.name.toLowerCase() === item.toLowerCase());
1368
- if (!constantItem) {
1369
- const constNames = palletInfo.constants.map((c) => c.name);
1370
- throw new Error(suggestMessage(`constant in ${palletInfo.name}`, item, constNames));
2141
+ printHeading(`${pallet.name}.${errorItem.name} (Error)`);
2142
+ if (errorItem.docs.length) {
2143
+ printDocs(errorItem.docs);
1371
2144
  }
1372
- const unsafeApi = clientHandle.client.getUnsafeApi();
1373
- const runtimeToken = await unsafeApi.runtimeToken;
1374
- const result = unsafeApi.constants[palletInfo.name][constantItem.name](runtimeToken);
1375
- const format = opts.output ?? "pretty";
1376
- printResult(result, format);
1377
- } finally {
1378
- clientHandle.destroy();
2145
+ console.log();
2146
+ console.log(`${BOLD}Usage:${RESET}`);
2147
+ console.log(` dot errors.${pallet.name}.${errorItem.name}`);
2148
+ console.log();
2149
+ return;
1379
2150
  }
1380
- });
2151
+ }
1381
2152
  }
1382
2153
 
1383
2154
  // src/core/hash.ts
@@ -1511,9 +2282,58 @@ function registerHashCommand(cli) {
1511
2282
  });
1512
2283
  }
1513
2284
 
2285
+ // src/utils/parse-target.ts
2286
+ function parseTarget(input, options) {
2287
+ const parts = input.split(".");
2288
+ if (options?.allowPalletOnly) {
2289
+ switch (parts.length) {
2290
+ case 1:
2291
+ if (!parts[0]) {
2292
+ throw new Error(`Invalid target "${input}". Expected format: Pallet or Pallet.Item (e.g. System or System.Account)`);
2293
+ }
2294
+ return { pallet: parts[0] };
2295
+ case 2:
2296
+ if (!parts[0] || !parts[1]) {
2297
+ throw new Error(`Invalid target "${input}". Expected format: Pallet.Item or Chain.Pallet (e.g. System.Account or kusama.System)`);
2298
+ }
2299
+ if (options.knownChains?.some((c) => c.toLowerCase() === parts[0].toLowerCase())) {
2300
+ return { chain: parts[0], pallet: parts[1] };
2301
+ }
2302
+ return { pallet: parts[0], item: parts[1] };
2303
+ case 3:
2304
+ if (!parts[0] || !parts[1] || !parts[2]) {
2305
+ throw new Error(`Invalid target "${input}". Expected format: Chain.Pallet.Item (e.g. kusama.System.Account)`);
2306
+ }
2307
+ return { chain: parts[0], pallet: parts[1], item: parts[2] };
2308
+ default:
2309
+ throw new Error(`Invalid target "${input}". Expected format: Pallet, Pallet.Item, or Chain.Pallet.Item`);
2310
+ }
2311
+ }
2312
+ switch (parts.length) {
2313
+ case 2:
2314
+ if (!parts[0] || !parts[1]) {
2315
+ throw new Error(`Invalid target "${input}". Expected format: Pallet.Item (e.g. System.Account)`);
2316
+ }
2317
+ return { pallet: parts[0], item: parts[1] };
2318
+ case 3:
2319
+ if (!parts[0] || !parts[1] || !parts[2]) {
2320
+ throw new Error(`Invalid target "${input}". Expected format: Chain.Pallet.Item (e.g. kusama.System.Account)`);
2321
+ }
2322
+ return { chain: parts[0], pallet: parts[1], item: parts[2] };
2323
+ default:
2324
+ throw new Error(`Invalid target "${input}". Expected format: Pallet.Item (e.g. System.Account)`);
2325
+ }
2326
+ }
2327
+ function resolveTargetChain(target, chainFlag) {
2328
+ if (target.chain && chainFlag) {
2329
+ throw new Error(`Chain specified both as prefix ("${target.chain}") and as --chain flag ("${chainFlag}"). Use one or the other.`);
2330
+ }
2331
+ return target.chain ?? chainFlag;
2332
+ }
2333
+
1514
2334
  // src/commands/inspect.ts
1515
2335
  function registerInspectCommand(cli) {
1516
- cli.command("inspect [target]", "Inspect chain metadata (pallets, storage, constants)").option("--chain <name>", "Target chain").option("--rpc <url>", "Override RPC endpoint").action(async (target, opts) => {
2336
+ cli.command("inspect [target]", "Inspect chain metadata (pallets, storage, constants, calls, events, errors)").alias("explore").option("--chain <name>", "Target chain").option("--rpc <url>", "Override RPC endpoint").action(async (target, opts) => {
1517
2337
  const config = await loadConfig();
1518
2338
  const knownChains = Object.keys(config.chains);
1519
2339
  let effectiveChain = opts.chain;
@@ -1530,7 +2350,7 @@ function registerInspectCommand(cli) {
1530
2350
  try {
1531
2351
  meta = await getOrFetchMetadata(chainName);
1532
2352
  } catch {
1533
- console.log(`Fetching metadata from ${chainName}...`);
2353
+ console.error(`Fetching metadata from ${chainName}...`);
1534
2354
  const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
1535
2355
  try {
1536
2356
  meta = await getOrFetchMetadata(chainName, clientHandle);
@@ -1549,6 +2369,10 @@ function registerInspectCommand(cli) {
1549
2369
  counts.push(`${p.constants.length} constants`);
1550
2370
  if (p.calls.length)
1551
2371
  counts.push(`${p.calls.length} calls`);
2372
+ if (p.events.length)
2373
+ counts.push(`${p.events.length} events`);
2374
+ if (p.errors.length)
2375
+ counts.push(`${p.errors.length} errors`);
1552
2376
  printItem(p.name, counts.join(", "));
1553
2377
  }
1554
2378
  console.log();
@@ -1568,24 +2392,66 @@ function registerInspectCommand(cli) {
1568
2392
  if (pallet2.storage.length) {
1569
2393
  console.log(` ${BOLD}Storage Items:${RESET}`);
1570
2394
  for (const s of pallet2.storage) {
1571
- const doc = s.docs[0] ? ` — ${s.docs[0].slice(0, 80)}` : "";
1572
- console.log(` ${CYAN}${s.name}${RESET}${DIM}${doc}${RESET}`);
2395
+ const valueType = describeType(meta.lookup, s.valueTypeId);
2396
+ let typeSuffix;
2397
+ if (s.keyTypeId != null) {
2398
+ const keyType = describeType(meta.lookup, s.keyTypeId);
2399
+ typeSuffix = `: ${keyType} → ${valueType} [map]`;
2400
+ } else {
2401
+ typeSuffix = `: ${valueType}`;
2402
+ }
2403
+ console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
2404
+ const summary = firstSentence(s.docs);
2405
+ if (summary) {
2406
+ console.log(` ${DIM}${summary}${RESET}`);
2407
+ }
1573
2408
  }
1574
2409
  console.log();
1575
2410
  }
1576
2411
  if (pallet2.constants.length) {
1577
2412
  console.log(` ${BOLD}Constants:${RESET}`);
1578
2413
  for (const c of pallet2.constants) {
1579
- const doc = c.docs[0] ? ` — ${c.docs[0].slice(0, 80)}` : "";
1580
- console.log(` ${CYAN}${c.name}${RESET}${DIM}${doc}${RESET}`);
2414
+ const typeStr = describeType(meta.lookup, c.typeId);
2415
+ console.log(` ${CYAN}${c.name}${RESET}${DIM}: ${typeStr}${RESET}`);
2416
+ const summary = firstSentence(c.docs);
2417
+ if (summary) {
2418
+ console.log(` ${DIM}${summary}${RESET}`);
2419
+ }
1581
2420
  }
1582
2421
  console.log();
1583
2422
  }
1584
2423
  if (pallet2.calls.length) {
1585
2424
  console.log(` ${BOLD}Calls:${RESET}`);
1586
2425
  for (const c of pallet2.calls) {
1587
- const doc = c.docs[0] ? ` — ${c.docs[0].slice(0, 80)}` : "";
1588
- console.log(` ${CYAN}${c.name}${RESET}${DIM}${doc}${RESET}`);
2426
+ const args = describeCallArgs(meta, pallet2.name, c.name);
2427
+ console.log(` ${CYAN}${c.name}${RESET}${DIM}${args}${RESET}`);
2428
+ const summary = firstSentence(c.docs);
2429
+ if (summary) {
2430
+ console.log(` ${DIM}${summary}${RESET}`);
2431
+ }
2432
+ }
2433
+ console.log();
2434
+ }
2435
+ if (pallet2.events.length) {
2436
+ console.log(` ${BOLD}Events:${RESET}`);
2437
+ for (const e of pallet2.events) {
2438
+ const fields = describeEventFields(meta, pallet2.name, e.name);
2439
+ console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields}${RESET}`);
2440
+ const summary = firstSentence(e.docs);
2441
+ if (summary) {
2442
+ console.log(` ${DIM}${summary}${RESET}`);
2443
+ }
2444
+ }
2445
+ console.log();
2446
+ }
2447
+ if (pallet2.errors.length) {
2448
+ console.log(` ${BOLD}Errors:${RESET}`);
2449
+ for (const e of pallet2.errors) {
2450
+ console.log(` ${CYAN}${e.name}${RESET}`);
2451
+ const summary = firstSentence(e.docs);
2452
+ if (summary) {
2453
+ console.log(` ${DIM}${summary}${RESET}`);
2454
+ }
1589
2455
  }
1590
2456
  console.log();
1591
2457
  }
@@ -1634,10 +2500,33 @@ function registerInspectCommand(cli) {
1634
2500
  console.log();
1635
2501
  return;
1636
2502
  }
2503
+ const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
2504
+ if (eventItem) {
2505
+ printHeading(`${pallet.name}.${eventItem.name} (Event)`);
2506
+ const fields = describeEventFields(meta, pallet.name, eventItem.name);
2507
+ console.log(` ${BOLD}Fields:${RESET} ${fields}`);
2508
+ if (eventItem.docs.length) {
2509
+ console.log();
2510
+ printDocs(eventItem.docs);
2511
+ }
2512
+ console.log();
2513
+ return;
2514
+ }
2515
+ const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
2516
+ if (errorItem) {
2517
+ printHeading(`${pallet.name}.${errorItem.name} (Error)`);
2518
+ if (errorItem.docs.length) {
2519
+ printDocs(errorItem.docs);
2520
+ }
2521
+ console.log();
2522
+ return;
2523
+ }
1637
2524
  const allItems = [
1638
2525
  ...pallet.storage.map((s) => s.name),
1639
2526
  ...pallet.constants.map((c) => c.name),
1640
- ...pallet.calls.map((c) => c.name)
2527
+ ...pallet.calls.map((c) => c.name),
2528
+ ...pallet.events.map((e) => e.name),
2529
+ ...pallet.errors.map((e) => e.name)
1641
2530
  ];
1642
2531
  throw new Error(suggestMessage(`item in ${pallet.name}`, itemName, allItems));
1643
2532
  });
@@ -1964,77 +2853,101 @@ var PAPI_BUILTIN_EXTENSIONS = new Set([
1964
2853
  var NO_DEFAULT = Symbol("no-default");
1965
2854
 
1966
2855
  // src/commands/query.ts
1967
- var DEFAULT_LIMIT = 100;
1968
- function registerQueryCommand(cli) {
1969
- cli.command("query [target] [...keys]", "Query on-chain storage (e.g. System.Number, System.Account <addr>)").option("--limit <n>", "Max entries to return for map queries (0 = unlimited)", {
1970
- default: DEFAULT_LIMIT
1971
- }).action(async (target, keys, opts) => {
1972
- if (!target) {
1973
- console.log("Usage: dot query <[Chain.]Pallet.Item> [...keys] [--chain <name>] [--output json]");
1974
- console.log("");
1975
- console.log("Examples:");
1976
- console.log(" $ dot query System.Number # plain storage value");
1977
- console.log(" $ dot query System.Account 5Grw... # single map entry");
1978
- console.log(" $ dot query System.Account # all entries (limit 100)");
1979
- console.log(" $ dot query System.Account --limit 10 # first 10 entries");
1980
- console.log(" $ dot query System.Account --limit 0 # all entries (no limit)");
1981
- console.log(" $ dot query Assets.Metadata 42 --chain asset-hub");
1982
- console.log(" $ dot query kusama.System.Account 5Grw... # chain prefix");
2856
+ async function handleQuery(target, keys, opts) {
2857
+ if (!target) {
2858
+ const config2 = await loadConfig();
2859
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
2860
+ const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
2861
+ const pallets = listPallets(meta);
2862
+ const withStorage = pallets.filter((p) => p.storage.length > 0);
2863
+ printHeading(`Pallets with storage on ${chainName2} (${withStorage.length})`);
2864
+ for (const p of withStorage) {
2865
+ printItem(p.name, `${p.storage.length} storage items`);
2866
+ }
2867
+ console.log();
2868
+ return;
2869
+ }
2870
+ const dotIdx = target.indexOf(".");
2871
+ if (dotIdx === -1) {
2872
+ const config2 = await loadConfig();
2873
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
2874
+ const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
2875
+ const pallet2 = resolvePallet(meta, palletName(target));
2876
+ if (pallet2.storage.length === 0) {
2877
+ console.log(`No storage items in ${pallet2.name}.`);
1983
2878
  return;
1984
2879
  }
1985
- const config = await loadConfig();
1986
- const knownChains = Object.keys(config.chains);
1987
- const parsed = parseTarget(target, { knownChains });
1988
- const effectiveChain = resolveTargetChain(parsed, opts.chain);
1989
- const { name: chainName, chain: chainConfig } = resolveChain(config, effectiveChain);
1990
- const pallet = parsed.pallet;
1991
- const item = parsed.item;
1992
- const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
1993
- try {
1994
- const meta = await getOrFetchMetadata(chainName, clientHandle);
1995
- const palletNames = getPalletNames(meta);
1996
- const palletInfo = findPallet(meta, pallet);
1997
- if (!palletInfo) {
1998
- throw new Error(suggestMessage("pallet", pallet, palletNames));
2880
+ printHeading(`${pallet2.name} Storage`);
2881
+ for (const s of pallet2.storage) {
2882
+ const valueType = describeType(meta.lookup, s.valueTypeId);
2883
+ let typeSuffix;
2884
+ if (s.keyTypeId != null) {
2885
+ const keyType = describeType(meta.lookup, s.keyTypeId);
2886
+ typeSuffix = `: ${keyType} → ${valueType} [map]`;
2887
+ } else {
2888
+ typeSuffix = `: ${valueType}`;
1999
2889
  }
2000
- const storageItem = palletInfo.storage.find((s) => s.name.toLowerCase() === item.toLowerCase());
2001
- if (!storageItem) {
2002
- const storageNames = palletInfo.storage.map((s) => s.name);
2003
- throw new Error(suggestMessage(`storage item in ${palletInfo.name}`, item, storageNames));
2004
- }
2005
- const unsafeApi = clientHandle.client.getUnsafeApi();
2006
- const storageApi = unsafeApi.query[palletInfo.name][storageItem.name];
2007
- const parsedKeys = parseStorageKeys(meta, palletInfo.name, storageItem, keys);
2008
- const format = opts.output ?? "pretty";
2009
- if (storageItem.type === "map" && parsedKeys.length === 0) {
2010
- const entries = await storageApi.getEntries();
2011
- const limit = Number(opts.limit);
2012
- const truncated = limit > 0 && entries.length > limit;
2013
- const display = truncated ? entries.slice(0, limit) : entries;
2014
- printResult(display.map((e) => ({
2015
- keys: e.keyArgs,
2016
- value: e.value
2017
- })), format);
2018
- if (truncated) {
2019
- console.error(`
2890
+ console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
2891
+ const summary = firstSentence(s.docs);
2892
+ if (summary) {
2893
+ console.log(` ${DIM}${summary}${RESET}`);
2894
+ }
2895
+ }
2896
+ console.log();
2897
+ return;
2898
+ }
2899
+ const pallet = target.slice(0, dotIdx);
2900
+ const item = target.slice(dotIdx + 1);
2901
+ const config = await loadConfig();
2902
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
2903
+ const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
2904
+ try {
2905
+ const meta = await getOrFetchMetadata(chainName, clientHandle);
2906
+ const palletNames = getPalletNames(meta);
2907
+ const palletInfo = findPallet(meta, pallet);
2908
+ if (!palletInfo) {
2909
+ throw new Error(suggestMessage("pallet", pallet, palletNames));
2910
+ }
2911
+ const storageItem = palletInfo.storage.find((s) => s.name.toLowerCase() === item.toLowerCase());
2912
+ if (!storageItem) {
2913
+ const storageNames = palletInfo.storage.map((s) => s.name);
2914
+ throw new Error(suggestMessage(`storage item in ${palletInfo.name}`, item, storageNames));
2915
+ }
2916
+ const unsafeApi = clientHandle.client.getUnsafeApi();
2917
+ const storageApi = unsafeApi.query[palletInfo.name][storageItem.name];
2918
+ const parsedKeys = parseStorageKeys(meta, palletInfo.name, storageItem, keys);
2919
+ const format = opts.output ?? "pretty";
2920
+ if (storageItem.type === "map" && parsedKeys.length === 0) {
2921
+ const entries = await storageApi.getEntries();
2922
+ const limit = Number(opts.limit);
2923
+ const truncated = limit > 0 && entries.length > limit;
2924
+ const display = truncated ? entries.slice(0, limit) : entries;
2925
+ printResult(display.map((e) => ({
2926
+ keys: e.keyArgs,
2927
+ value: e.value
2928
+ })), format);
2929
+ if (truncated) {
2930
+ console.error(`
2020
2931
  ${DIM}Showing ${limit} of ${entries.length} entries. Use --limit 0 for all.${RESET}`);
2021
- }
2022
- } else {
2023
- const result = await storageApi.getValue(...parsedKeys);
2024
- printResult(result, format);
2025
2932
  }
2026
- } finally {
2027
- clientHandle.destroy();
2933
+ } else {
2934
+ const result = await storageApi.getValue(...parsedKeys);
2935
+ printResult(result, format);
2028
2936
  }
2029
- });
2937
+ } finally {
2938
+ clientHandle.destroy();
2939
+ }
2940
+ }
2941
+ function palletName(name) {
2942
+ return name;
2030
2943
  }
2031
- function parseStorageKeys(meta, palletName, storageItem, args) {
2944
+ function parseStorageKeys(meta, palletName2, storageItem, args) {
2032
2945
  if (storageItem.type === "plain" || storageItem.keyTypeId == null) {
2033
2946
  return args.map(parseValue);
2034
2947
  }
2035
2948
  if (args.length === 0)
2036
2949
  return [];
2037
- const storageEntry = meta.builder.buildStorage(palletName, storageItem.name);
2950
+ const storageEntry = meta.builder.buildStorage(palletName2, storageItem.name);
2038
2951
  const len = storageEntry.len;
2039
2952
  const keyEntry = meta.lookup(storageItem.keyTypeId);
2040
2953
  if (len === 1) {
@@ -2042,11 +2955,11 @@ function parseStorageKeys(meta, palletName, storageItem, args) {
2042
2955
  return [parseTypedArg(meta, keyEntry, args[0])];
2043
2956
  }
2044
2957
  if (keyEntry.type === "struct") {
2045
- const label = `${palletName}.${storageItem.name} key`;
2958
+ const label = `${palletName2}.${storageItem.name} key`;
2046
2959
  return [parseStructArgs(meta, keyEntry.value, args, label)];
2047
2960
  }
2048
2961
  const typeDesc = describeType(meta.lookup, storageItem.keyTypeId);
2049
- throw new Error(`${palletName}.${storageItem.name} key expects ${typeDesc}
2962
+ throw new Error(`${palletName2}.${storageItem.name} key expects ${typeDesc}
2050
2963
  ` + ` Pass 1 argument. Got ${args.length}.`);
2051
2964
  }
2052
2965
  if (args.length !== len) {
@@ -2056,7 +2969,7 @@ function parseStorageKeys(meta, palletName, storageItem, args) {
2056
2969
  } else {
2057
2970
  typeDesc = describeType(meta.lookup, storageItem.keyTypeId);
2058
2971
  }
2059
- throw new Error(`${palletName}.${storageItem.name} expects ${len} key arg(s): (${typeDesc}). Got ${args.length}.`);
2972
+ throw new Error(`${palletName2}.${storageItem.name} expects ${len} key arg(s): (${typeDesc}). Got ${args.length}.`);
2060
2973
  }
2061
2974
  if (keyEntry.type === "tuple") {
2062
2975
  const entries = keyEntry.value;
@@ -2068,156 +2981,180 @@ function parseStorageKeys(meta, palletName, storageItem, args) {
2068
2981
  // src/commands/tx.ts
2069
2982
  import { getViewBuilder as getViewBuilder2 } from "@polkadot-api/view-builder";
2070
2983
  import { Binary as Binary3 } from "polkadot-api";
2071
- function registerTxCommand(cli) {
2072
- cli.command("tx [target] [...args]", "Submit an extrinsic (e.g. Balances.transferKeepAlive <dest> <amount>)").option("--from <name>", "Account to sign with (required)").option("--dry-run", "Estimate fees without submitting").option("--encode", "Encode call to hex without signing or submitting").option("--ext <json>", `Custom signed extension values as JSON, e.g. '{"ExtName":{"value":...}}'`).action(async (target, args, opts) => {
2073
- if (!target) {
2074
- console.log("Usage: dot tx <[Chain.]Pallet.Call|0xCallHex> [...args] --from <account> [--dry-run] [--encode]");
2075
- console.log("");
2076
- console.log("Examples:");
2077
- console.log(" $ dot tx Balances.transferKeepAlive 5FHn... 1000000000000 --from alice");
2078
- console.log(" $ dot tx System.remark 0xdeadbeef --from alice --dry-run");
2079
- console.log(" $ dot tx 0x0001076465616462656566 --from alice");
2080
- console.log(" $ dot tx Assets.force_create 4 owner true 10 --encode --chain people");
2081
- console.log(" $ dot tx kusama.Balances.transferKeepAlive 5FHn... 1000000000000 --from alice");
2082
- return;
2984
+ async function handleTx(target, args, opts) {
2985
+ if (!target) {
2986
+ const config2 = await loadConfig();
2987
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
2988
+ const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
2989
+ const pallets = listPallets(meta);
2990
+ const withCalls = pallets.filter((p) => p.calls.length > 0);
2991
+ printHeading(`Pallets with calls on ${chainName2} (${withCalls.length})`);
2992
+ for (const p of withCalls) {
2993
+ printItem(p.name, `${p.calls.length} calls`);
2083
2994
  }
2084
- if (!opts.from && !opts.encode) {
2085
- throw new Error("--from is required (or use --encode to output hex without signing)");
2995
+ console.log();
2996
+ return;
2997
+ }
2998
+ const isRawCall = /^0x[0-9a-fA-F]+$/.test(target);
2999
+ if (!isRawCall && target.indexOf(".") === -1) {
3000
+ const config2 = await loadConfig();
3001
+ const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
3002
+ const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
3003
+ const pallet2 = resolvePallet(meta, target);
3004
+ if (pallet2.calls.length === 0) {
3005
+ console.log(`No calls in ${pallet2.name}.`);
3006
+ return;
2086
3007
  }
2087
- if (opts.encode && opts.dryRun) {
2088
- throw new Error("--encode and --dry-run are mutually exclusive");
3008
+ printHeading(`${pallet2.name} Calls`);
3009
+ for (const c of pallet2.calls) {
3010
+ const callArgs = describeCallArgs(meta, pallet2.name, c.name);
3011
+ console.log(` ${CYAN}${c.name}${RESET}${DIM}${callArgs}${RESET}`);
3012
+ const summary = firstSentence(c.docs);
3013
+ if (summary) {
3014
+ console.log(` ${DIM}${summary}${RESET}`);
3015
+ }
2089
3016
  }
2090
- const isRawCall = /^0x[0-9a-fA-F]+$/.test(target);
2091
- if (opts.encode && isRawCall) {
2092
- throw new Error("--encode cannot be used with raw call hex (already encoded)");
3017
+ console.log();
3018
+ return;
3019
+ }
3020
+ if (!opts.from && !opts.encode) {
3021
+ if (isRawCall) {
3022
+ throw new Error("--from is required (or use --encode to output hex without signing)");
2093
3023
  }
2094
- const config = await loadConfig();
2095
- let effectiveChain = opts.chain;
2096
- let parsedTarget;
2097
- if (!isRawCall) {
2098
- const knownChains = Object.keys(config.chains);
2099
- parsedTarget = parseTarget(target, { knownChains });
2100
- effectiveChain = resolveTargetChain(parsedTarget, opts.chain);
3024
+ await showItemHelp("tx", target, opts);
3025
+ return;
3026
+ }
3027
+ if (opts.encode && opts.dryRun) {
3028
+ throw new Error("--encode and --dry-run are mutually exclusive");
3029
+ }
3030
+ if (opts.encode && isRawCall) {
3031
+ throw new Error("--encode cannot be used with raw call hex (already encoded)");
3032
+ }
3033
+ const config = await loadConfig();
3034
+ const effectiveChain = opts.chain;
3035
+ let pallet;
3036
+ let callName;
3037
+ if (!isRawCall) {
3038
+ const dotIdx = target.indexOf(".");
3039
+ pallet = target.slice(0, dotIdx);
3040
+ callName = target.slice(dotIdx + 1);
3041
+ }
3042
+ const { name: chainName, chain: chainConfig } = resolveChain(config, effectiveChain);
3043
+ const signer = opts.encode ? undefined : await resolveAccountSigner(opts.from);
3044
+ let clientHandle;
3045
+ if (!opts.encode) {
3046
+ clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
3047
+ }
3048
+ try {
3049
+ let meta;
3050
+ if (clientHandle) {
3051
+ meta = await getOrFetchMetadata(chainName, clientHandle);
3052
+ } else {
3053
+ try {
3054
+ meta = await getOrFetchMetadata(chainName);
3055
+ } catch {
3056
+ clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
3057
+ meta = await getOrFetchMetadata(chainName, clientHandle);
3058
+ }
2101
3059
  }
2102
- const { name: chainName, chain: chainConfig } = resolveChain(config, effectiveChain);
2103
- const signer = opts.encode ? undefined : await resolveAccountSigner(opts.from);
2104
- let clientHandle;
3060
+ let unsafeApi;
3061
+ let txOptions;
2105
3062
  if (!opts.encode) {
2106
- clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
3063
+ const userExtOverrides = parseExtOption(opts.ext);
3064
+ const customSignedExtensions = buildCustomSignedExtensions(meta, userExtOverrides);
3065
+ txOptions = Object.keys(customSignedExtensions).length > 0 ? { customSignedExtensions } : undefined;
3066
+ unsafeApi = clientHandle?.client.getUnsafeApi();
2107
3067
  }
2108
- try {
2109
- let meta;
2110
- if (clientHandle) {
2111
- meta = await getOrFetchMetadata(chainName, clientHandle);
2112
- } else {
2113
- try {
2114
- meta = await getOrFetchMetadata(chainName);
2115
- } catch {
2116
- clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
2117
- meta = await getOrFetchMetadata(chainName, clientHandle);
2118
- }
2119
- }
2120
- let unsafeApi;
2121
- let txOptions;
2122
- if (!opts.encode) {
2123
- const userExtOverrides = parseExtOption(opts.ext);
2124
- const customSignedExtensions = buildCustomSignedExtensions(meta, userExtOverrides);
2125
- txOptions = Object.keys(customSignedExtensions).length > 0 ? { customSignedExtensions } : undefined;
2126
- unsafeApi = clientHandle?.client.getUnsafeApi();
2127
- }
2128
- let tx;
2129
- let callHex;
2130
- if (isRawCall) {
2131
- if (args.length > 0) {
2132
- throw new Error(`Extra arguments are not allowed when submitting a raw call hex.
3068
+ let tx;
3069
+ let callHex;
3070
+ if (isRawCall) {
3071
+ if (args.length > 0) {
3072
+ throw new Error(`Extra arguments are not allowed when submitting a raw call hex.
2133
3073
  ` + "Usage: dot tx 0x<call_hex> --from <account>");
2134
- }
2135
- const callBinary = Binary3.fromHex(target);
2136
- tx = await unsafeApi.txFromCallData(callBinary);
2137
- callHex = target;
2138
- } else {
2139
- const pallet = parsedTarget.pallet;
2140
- const callName = parsedTarget.item;
2141
- const palletNames = getPalletNames(meta);
2142
- const palletInfo = findPallet(meta, pallet);
2143
- if (!palletInfo) {
2144
- throw new Error(suggestMessage("pallet", pallet, palletNames));
2145
- }
2146
- const callInfo = palletInfo.calls.find((c) => c.name.toLowerCase() === callName.toLowerCase());
2147
- if (!callInfo) {
2148
- const callNames = palletInfo.calls.map((c) => c.name);
2149
- throw new Error(suggestMessage(`call in ${palletInfo.name}`, callName, callNames));
2150
- }
2151
- const callData = parseCallArgs(meta, palletInfo.name, callInfo.name, args);
2152
- if (opts.encode) {
2153
- const { codec, location } = meta.builder.buildCall(palletInfo.name, callInfo.name);
2154
- const encodedArgs = codec.enc(callData);
2155
- const fullCall = new Uint8Array([location[0], location[1], ...encodedArgs]);
2156
- console.log(Binary3.fromBytes(fullCall).asHex());
2157
- return;
2158
- }
2159
- tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
2160
- const encodedCall = await tx.getEncodedData();
2161
- callHex = encodedCall.asHex();
2162
- }
2163
- const decodedStr = decodeCall(meta, callHex);
2164
- if (opts.dryRun) {
2165
- const signerAddress = toSs58(signer.publicKey);
2166
- console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
2167
- console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
2168
- console.log(` ${BOLD}Call:${RESET} ${callHex}`);
2169
- console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
2170
- try {
2171
- const fees = await tx.getEstimatedFees(signer?.publicKey, txOptions);
2172
- console.log(` ${BOLD}Estimated fees:${RESET} ${fees}`);
2173
- } catch (err) {
2174
- console.log(` ${BOLD}Estimated fees:${RESET} ${YELLOW}unable to estimate${RESET}`);
2175
- console.log(` ${DIM}${err.message ?? err}${RESET}`);
2176
- }
3074
+ }
3075
+ const callBinary = Binary3.fromHex(target);
3076
+ tx = await unsafeApi.txFromCallData(callBinary);
3077
+ callHex = target;
3078
+ } else {
3079
+ const palletNames = getPalletNames(meta);
3080
+ const palletInfo = findPallet(meta, pallet);
3081
+ if (!palletInfo) {
3082
+ throw new Error(suggestMessage("pallet", pallet, palletNames));
3083
+ }
3084
+ const callInfo = palletInfo.calls.find((c) => c.name.toLowerCase() === callName.toLowerCase());
3085
+ if (!callInfo) {
3086
+ const callNames = palletInfo.calls.map((c) => c.name);
3087
+ throw new Error(suggestMessage(`call in ${palletInfo.name}`, callName, callNames));
3088
+ }
3089
+ const callData = parseCallArgs(meta, palletInfo.name, callInfo.name, args);
3090
+ if (opts.encode) {
3091
+ const { codec, location } = meta.builder.buildCall(palletInfo.name, callInfo.name);
3092
+ const encodedArgs = codec.enc(callData);
3093
+ const fullCall = new Uint8Array([location[0], location[1], ...encodedArgs]);
3094
+ console.log(Binary3.fromBytes(fullCall).asHex());
2177
3095
  return;
2178
3096
  }
2179
- const result = await watchTransaction(tx.signSubmitAndWatch(signer, txOptions));
2180
- console.log();
3097
+ tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
3098
+ const encodedCall = await tx.getEncodedData();
3099
+ callHex = encodedCall.asHex();
3100
+ }
3101
+ const decodedStr = decodeCall(meta, callHex);
3102
+ if (opts.dryRun) {
3103
+ const signerAddress = toSs58(signer.publicKey);
2181
3104
  console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
3105
+ console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
2182
3106
  console.log(` ${BOLD}Call:${RESET} ${callHex}`);
2183
3107
  console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
2184
- console.log(` ${BOLD}Tx:${RESET} ${result.txHash}`);
2185
- let dispatchErrorMsg;
2186
- if (result.ok) {
2187
- console.log(` ${BOLD}Status:${RESET} ${GREEN}ok${RESET}`);
2188
- } else {
2189
- dispatchErrorMsg = formatDispatchError(result.dispatchError);
2190
- console.log(` ${BOLD}Status:${RESET} ${RED}dispatch error${RESET}`);
2191
- console.log(` ${BOLD}Error:${RESET} ${dispatchErrorMsg}`);
3108
+ try {
3109
+ const fees = await tx.getEstimatedFees(signer?.publicKey, txOptions);
3110
+ console.log(` ${BOLD}Estimated fees:${RESET} ${fees}`);
3111
+ } catch (err) {
3112
+ console.log(` ${BOLD}Estimated fees:${RESET} ${YELLOW}unable to estimate${RESET}`);
3113
+ console.log(` ${DIM}${err.message ?? err}${RESET}`);
2192
3114
  }
2193
- if (result.events && result.events.length > 0) {
2194
- console.log(` ${BOLD}Events:${RESET}`);
2195
- for (const event of result.events) {
2196
- const name = `${CYAN}${event.type}${RESET}.${CYAN}${event.value?.type ?? ""}${RESET}`;
2197
- const payload = event.value?.value;
2198
- if (payload && typeof payload === "object") {
2199
- const fields = Object.entries(payload).map(([k, v]) => `${k}: ${formatEventValue(v)}`).join(", ");
2200
- console.log(` ${name} { ${fields} }`);
2201
- } else {
2202
- console.log(` ${name}`);
2203
- }
3115
+ return;
3116
+ }
3117
+ const result = await watchTransaction(tx.signSubmitAndWatch(signer, txOptions));
3118
+ console.log();
3119
+ console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
3120
+ console.log(` ${BOLD}Call:${RESET} ${callHex}`);
3121
+ console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
3122
+ console.log(` ${BOLD}Tx:${RESET} ${result.txHash}`);
3123
+ let dispatchErrorMsg;
3124
+ if (result.ok) {
3125
+ console.log(` ${BOLD}Status:${RESET} ${GREEN}ok${RESET}`);
3126
+ } else {
3127
+ dispatchErrorMsg = formatDispatchError(result.dispatchError);
3128
+ console.log(` ${BOLD}Status:${RESET} ${RED}dispatch error${RESET}`);
3129
+ console.log(` ${BOLD}Error:${RESET} ${dispatchErrorMsg}`);
3130
+ }
3131
+ if (result.events && result.events.length > 0) {
3132
+ console.log(` ${BOLD}Events:${RESET}`);
3133
+ for (const event of result.events) {
3134
+ const name = `${CYAN}${event.type}${RESET}.${CYAN}${event.value?.type ?? ""}${RESET}`;
3135
+ const payload = event.value?.value;
3136
+ if (payload && typeof payload === "object") {
3137
+ const fields = Object.entries(payload).map(([k, v]) => `${k}: ${formatEventValue(v)}`).join(", ");
3138
+ console.log(` ${name} { ${fields} }`);
3139
+ } else {
3140
+ console.log(` ${name}`);
2204
3141
  }
2205
3142
  }
2206
- const rpcUrl = primaryRpc(opts.rpc ?? chainConfig.rpc);
2207
- if (rpcUrl) {
2208
- const blockHash = result.block.hash;
2209
- console.log(` ${BOLD}Explorer:${RESET}`);
2210
- console.log(` ${DIM}PolkadotJS${RESET} ${pjsAppsLink(rpcUrl, blockHash)}`);
2211
- console.log(` ${DIM}PAPI${RESET} ${papiLink(rpcUrl, blockHash)}`);
2212
- }
2213
- console.log();
2214
- if (!result.ok) {
2215
- throw new CliError(`Transaction dispatch error: ${dispatchErrorMsg}`);
2216
- }
2217
- } finally {
2218
- clientHandle?.destroy();
2219
3143
  }
2220
- });
3144
+ const rpcUrl = primaryRpc(opts.rpc ?? chainConfig.rpc);
3145
+ if (rpcUrl) {
3146
+ const blockHash = result.block.hash;
3147
+ console.log(` ${BOLD}Explorer:${RESET}`);
3148
+ console.log(` ${DIM}PolkadotJS${RESET} ${pjsAppsLink(rpcUrl, blockHash)}`);
3149
+ console.log(` ${DIM}PAPI${RESET} ${papiLink(rpcUrl, blockHash)}`);
3150
+ }
3151
+ console.log();
3152
+ if (!result.ok) {
3153
+ throw new CliError(`Transaction dispatch error: ${dispatchErrorMsg}`);
3154
+ }
3155
+ } finally {
3156
+ clientHandle?.destroy();
3157
+ }
2221
3158
  }
2222
3159
  function formatDispatchError(err) {
2223
3160
  if (err.type === "Module" && err.value && typeof err.value === "object") {
@@ -2240,10 +3177,10 @@ function decodeCall(meta, callHex) {
2240
3177
  try {
2241
3178
  const viewBuilder = getViewBuilder2(meta.lookup);
2242
3179
  const decoded = viewBuilder.callDecoder(callHex);
2243
- const palletName = decoded.pallet.value.name;
3180
+ const palletName2 = decoded.pallet.value.name;
2244
3181
  const callName = decoded.call.value.name;
2245
3182
  const argsStr = formatDecodedArgs(decoded.args.value);
2246
- return `${palletName}.${callName}${argsStr}`;
3183
+ return `${palletName2}.${callName}${argsStr}`;
2247
3184
  } catch {}
2248
3185
  try {
2249
3186
  return decodeCallFallback(meta, callHex);
@@ -2257,15 +3194,15 @@ function decodeCallFallback(meta, callHex) {
2257
3194
  throw new Error("No RuntimeCall type ID");
2258
3195
  const codec = meta.builder.buildDefinition(callTypeId);
2259
3196
  const decoded = codec.dec(Binary3.fromHex(callHex).asBytes());
2260
- const palletName = decoded.type;
3197
+ const palletName2 = decoded.type;
2261
3198
  const call = decoded.value;
2262
3199
  const callName = call.type;
2263
3200
  const args = call.value;
2264
3201
  if (args === undefined || args === null) {
2265
- return `${palletName}.${callName}`;
3202
+ return `${palletName2}.${callName}`;
2266
3203
  }
2267
3204
  const argsStr = formatRawDecoded(args);
2268
- return `${palletName}.${callName} ${argsStr}`;
3205
+ return `${palletName2}.${callName} ${argsStr}`;
2269
3206
  }
2270
3207
  function formatRawDecoded(value) {
2271
3208
  if (value === undefined || value === null)
@@ -2398,8 +3335,8 @@ function formatEventValue(v) {
2398
3335
  }
2399
3336
  return JSON.stringify(v, (_k, val) => typeof val === "bigint" ? val.toString() : val);
2400
3337
  }
2401
- function parseCallArgs(meta, palletName, callName, args) {
2402
- const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
3338
+ function parseCallArgs(meta, palletName2, callName, args) {
3339
+ const palletMeta = meta.unified.pallets.find((p) => p.name === palletName2);
2403
3340
  if (!palletMeta?.calls)
2404
3341
  return;
2405
3342
  const callsEntry = meta.lookup(palletMeta.calls.type);
@@ -2410,22 +3347,22 @@ function parseCallArgs(meta, palletName, callName, args) {
2410
3347
  return;
2411
3348
  if (variant.type === "void") {
2412
3349
  if (args.length > 0) {
2413
- throw new Error(`${palletName}.${callName} takes no arguments, but ${args.length} provided.`);
3350
+ throw new Error(`${palletName2}.${callName} takes no arguments, but ${args.length} provided.`);
2414
3351
  }
2415
3352
  return;
2416
3353
  }
2417
3354
  if (variant.type === "struct") {
2418
- return parseStructArgs2(meta, variant.value, args, `${palletName}.${callName}`);
3355
+ return parseStructArgs2(meta, variant.value, args, `${palletName2}.${callName}`);
2419
3356
  }
2420
3357
  if (variant.type === "lookupEntry") {
2421
3358
  const inner = variant.value;
2422
3359
  if (inner.type === "struct") {
2423
- return parseStructArgs2(meta, inner.value, args, `${palletName}.${callName}`);
3360
+ return parseStructArgs2(meta, inner.value, args, `${palletName2}.${callName}`);
2424
3361
  }
2425
3362
  if (inner.type === "void")
2426
3363
  return;
2427
3364
  if (args.length !== 1) {
2428
- throw new Error(`${palletName}.${callName} takes 1 argument (${describeType(meta.lookup, inner.id)}), but ${args.length} provided.`);
3365
+ throw new Error(`${palletName2}.${callName} takes 1 argument (${describeType(meta.lookup, inner.id)}), but ${args.length} provided.`);
2429
3366
  }
2430
3367
  try {
2431
3368
  return parseTypedArg2(meta, inner, args[0]);
@@ -2437,7 +3374,7 @@ function parseCallArgs(meta, palletName, callName, args) {
2437
3374
  if (variant.type === "tuple") {
2438
3375
  const entries = variant.value;
2439
3376
  if (args.length !== entries.length) {
2440
- throw new Error(`${palletName}.${callName} takes ${entries.length} arguments, but ${args.length} provided.`);
3377
+ throw new Error(`${palletName2}.${callName} takes ${entries.length} arguments, but ${args.length} provided.`);
2441
3378
  }
2442
3379
  return entries.map((entry, i) => {
2443
3380
  try {
@@ -2830,10 +3767,46 @@ function watchTransaction(observable) {
2830
3767
  });
2831
3768
  }
2832
3769
 
3770
+ // src/config/store.ts
3771
+ import { access as access3, mkdir as mkdir3, readFile as readFile3, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
3772
+ import { homedir as homedir2 } from "node:os";
3773
+ import { join as join3 } from "node:path";
3774
+ var DOT_DIR2 = join3(homedir2(), ".polkadot");
3775
+ var CONFIG_PATH2 = join3(DOT_DIR2, "config.json");
3776
+ var CHAINS_DIR2 = join3(DOT_DIR2, "chains");
3777
+ async function ensureDir3(dir) {
3778
+ await mkdir3(dir, { recursive: true });
3779
+ }
3780
+ async function fileExists3(path) {
3781
+ try {
3782
+ await access3(path);
3783
+ return true;
3784
+ } catch {
3785
+ return false;
3786
+ }
3787
+ }
3788
+ async function loadConfig2() {
3789
+ await ensureDir3(DOT_DIR2);
3790
+ if (await fileExists3(CONFIG_PATH2)) {
3791
+ const saved = JSON.parse(await readFile3(CONFIG_PATH2, "utf-8"));
3792
+ return {
3793
+ ...saved,
3794
+ chains: { ...DEFAULT_CONFIG.chains, ...saved.chains }
3795
+ };
3796
+ }
3797
+ await saveConfig2(DEFAULT_CONFIG);
3798
+ return DEFAULT_CONFIG;
3799
+ }
3800
+ async function saveConfig2(config) {
3801
+ await ensureDir3(DOT_DIR2);
3802
+ await writeFile3(CONFIG_PATH2, `${JSON.stringify(config, null, 2)}
3803
+ `);
3804
+ }
3805
+
2833
3806
  // src/core/update-notifier.ts
2834
3807
  import { readFileSync } from "node:fs";
2835
- import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
2836
- import { join as join3 } from "node:path";
3808
+ import { mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
3809
+ import { join as join4 } from "node:path";
2837
3810
  var CACHE_FILE = "update-check.json";
2838
3811
  var STALE_MS = 24 * 60 * 60 * 1000;
2839
3812
  var FETCH_TIMEOUT_MS = 5000;
@@ -2889,7 +3862,7 @@ function buildNotificationBox(current, latest) {
2889
3862
  `);
2890
3863
  }
2891
3864
  function getCachePath() {
2892
- return join3(getConfigDir(), CACHE_FILE);
3865
+ return join4(getConfigDir(), CACHE_FILE);
2893
3866
  }
2894
3867
  function readCache() {
2895
3868
  try {
@@ -2901,8 +3874,8 @@ function readCache() {
2901
3874
  }
2902
3875
  async function writeCache(cache) {
2903
3876
  try {
2904
- await mkdir3(getConfigDir(), { recursive: true });
2905
- await writeFile3(getCachePath(), `${JSON.stringify(cache)}
3877
+ await mkdir4(getConfigDir(), { recursive: true });
3878
+ await writeFile4(getCachePath(), `${JSON.stringify(cache)}
2906
3879
  `);
2907
3880
  } catch {}
2908
3881
  }
@@ -2957,6 +3930,67 @@ class CliError2 extends Error {
2957
3930
  }
2958
3931
  }
2959
3932
 
3933
+ // src/utils/parse-dot-path.ts
3934
+ var CATEGORY_ALIASES = {
3935
+ query: "query",
3936
+ tx: "tx",
3937
+ const: "const",
3938
+ consts: "const",
3939
+ constants: "const",
3940
+ events: "events",
3941
+ event: "events",
3942
+ errors: "errors",
3943
+ error: "errors"
3944
+ };
3945
+ function matchCategory(segment) {
3946
+ return CATEGORY_ALIASES[segment.toLowerCase()];
3947
+ }
3948
+ function matchChain(segment, knownChains) {
3949
+ return knownChains.some((c) => c.toLowerCase() === segment.toLowerCase());
3950
+ }
3951
+ function parseDotPath(input, knownChains = []) {
3952
+ const parts = input.split(".");
3953
+ switch (parts.length) {
3954
+ case 1: {
3955
+ const cat = matchCategory(parts[0]);
3956
+ if (cat)
3957
+ return { category: cat };
3958
+ throw new Error(`Unknown command "${parts[0]}". Expected a category (query, tx, const, events, errors) or a named command.`);
3959
+ }
3960
+ case 2: {
3961
+ const cat = matchCategory(parts[0]);
3962
+ if (cat) {
3963
+ return { category: cat, pallet: parts[1] };
3964
+ }
3965
+ const cat2 = matchCategory(parts[1]);
3966
+ if (cat2 && matchChain(parts[0], knownChains)) {
3967
+ return { chain: parts[0], category: cat2 };
3968
+ }
3969
+ throw new Error(`Unknown command "${input}". Expected format: category.Pallet or Chain.category (e.g. query.System or polkadot.query)`);
3970
+ }
3971
+ case 3: {
3972
+ const cat = matchCategory(parts[0]);
3973
+ if (cat) {
3974
+ return { category: cat, pallet: parts[1], item: parts[2] };
3975
+ }
3976
+ const cat2 = matchCategory(parts[1]);
3977
+ if (cat2 && matchChain(parts[0], knownChains)) {
3978
+ return { chain: parts[0], category: cat2, pallet: parts[2] };
3979
+ }
3980
+ throw new Error(`Unknown command "${input}". Expected format: category.Pallet.Item or Chain.category.Pallet`);
3981
+ }
3982
+ case 4: {
3983
+ const cat = matchCategory(parts[1]);
3984
+ if (cat && matchChain(parts[0], knownChains)) {
3985
+ return { chain: parts[0], category: cat, pallet: parts[2], item: parts[3] };
3986
+ }
3987
+ throw new Error(`Unknown command "${input}". Expected format: Chain.category.Pallet.Item (e.g. polkadot.query.System.Account)`);
3988
+ }
3989
+ default:
3990
+ throw new Error(`Unknown command "${input}". Too many segments. Expected format: [Chain.]category[.Pallet[.Item]]`);
3991
+ }
3992
+ }
3993
+
2960
3994
  // src/cli.ts
2961
3995
  startBackgroundCheck(version);
2962
3996
  var cli = cac("dot");
@@ -2968,13 +4002,105 @@ cli.option("--output <format>", "Output format: pretty or json", {
2968
4002
  });
2969
4003
  registerChainCommands(cli);
2970
4004
  registerInspectCommand(cli);
2971
- registerQueryCommand(cli);
2972
- registerConstCommand(cli);
2973
4005
  registerAccountCommands(cli);
2974
- registerTxCommand(cli);
2975
4006
  registerHashCommand(cli);
4007
+ cli.command("[dotpath] [...args]").option("--from <name>", "Account to sign with (for tx)").option("--dry-run", "Estimate fees without submitting (for tx)").option("--encode", "Encode call to hex without signing (for tx)").option("--ext <json>", "Custom signed extension values as JSON (for tx)").option("--limit <n>", "Max entries to return for map queries (0 = unlimited)", {
4008
+ default: 100
4009
+ }).action(async (dotpath, args, opts) => {
4010
+ if (!dotpath) {
4011
+ printHelp();
4012
+ return;
4013
+ }
4014
+ const config = await loadConfig2();
4015
+ const knownChains = Object.keys(config.chains);
4016
+ let parsed;
4017
+ try {
4018
+ parsed = parseDotPath(dotpath, knownChains);
4019
+ } catch {
4020
+ throw new CliError2(`Unknown command "${dotpath}". Run "dot --help" for available commands.`);
4021
+ }
4022
+ if (parsed.chain && opts.chain) {
4023
+ throw new CliError2(`Chain specified both as prefix ("${parsed.chain}") and as --chain flag ("${opts.chain}"). Use one or the other.`);
4024
+ }
4025
+ const effectiveChain = parsed.chain ?? opts.chain;
4026
+ const handlerOpts = { chain: effectiveChain, rpc: opts.rpc, output: opts.output };
4027
+ const target = parsed.pallet ? parsed.item ? `${parsed.pallet}.${parsed.item}` : parsed.pallet : undefined;
4028
+ if (cli.options.help && parsed.pallet && parsed.item) {
4029
+ await showItemHelp2(parsed.category, target, handlerOpts);
4030
+ return;
4031
+ }
4032
+ switch (parsed.category) {
4033
+ case "query":
4034
+ await handleQuery(target, args, { ...handlerOpts, limit: opts.limit });
4035
+ break;
4036
+ case "tx":
4037
+ if (parsed.pallet && /^0x[0-9a-fA-F]+$/.test(parsed.pallet)) {
4038
+ await handleTx(parsed.pallet, args, {
4039
+ ...handlerOpts,
4040
+ from: opts.from,
4041
+ dryRun: opts.dryRun,
4042
+ encode: opts.encode,
4043
+ ext: opts.ext
4044
+ });
4045
+ } else {
4046
+ await handleTx(target, args, {
4047
+ ...handlerOpts,
4048
+ from: opts.from,
4049
+ dryRun: opts.dryRun,
4050
+ encode: opts.encode,
4051
+ ext: opts.ext
4052
+ });
4053
+ }
4054
+ break;
4055
+ case "const":
4056
+ await handleConst(target, handlerOpts);
4057
+ break;
4058
+ case "events":
4059
+ await handleEvents2(target, handlerOpts);
4060
+ break;
4061
+ case "errors":
4062
+ await handleErrors2(target, handlerOpts);
4063
+ break;
4064
+ }
4065
+ });
2976
4066
  cli.option("--help, -h", "Display this message");
2977
4067
  cli.version(version);
4068
+ function printHelp() {
4069
+ console.log(`dot/${version} \u2014 Polkadot CLI`);
4070
+ console.log();
4071
+ console.log("Usage:");
4072
+ console.log(" dot <category>[.Pallet[.Item]] [args] [options]");
4073
+ console.log(" dot [Chain.]<category>[.Pallet[.Item]] [args] [options]");
4074
+ console.log();
4075
+ console.log("Categories:");
4076
+ console.log(" query Query on-chain storage");
4077
+ console.log(" tx Submit an extrinsic");
4078
+ console.log(" const Look up or list pallet constants");
4079
+ console.log(" events List or inspect pallet events");
4080
+ console.log(" errors List or inspect pallet errors");
4081
+ console.log();
4082
+ console.log("Examples:");
4083
+ console.log(" dot query.System.Account <addr> Query a storage item");
4084
+ console.log(" dot query.System List storage items in System");
4085
+ console.log(" dot tx.System.remark 0xdead --from alice");
4086
+ console.log(" dot const.Balances.ExistentialDeposit");
4087
+ console.log(" dot events.Balances List events in Balances");
4088
+ console.log(" dot polkadot.query.System.Number With chain prefix");
4089
+ console.log();
4090
+ console.log("Commands:");
4091
+ console.log(" inspect [target] Inspect chain metadata (alias: explore)");
4092
+ console.log(" chain Manage chain configurations");
4093
+ console.log(" account Manage accounts");
4094
+ console.log(" hash Hash utilities");
4095
+ console.log();
4096
+ console.log("Global options:");
4097
+ console.log(" --chain <name> Target chain (default from config)");
4098
+ console.log(" --rpc <url> Override RPC endpoint");
4099
+ console.log(" --light-client Use Smoldot light client");
4100
+ console.log(" --output <format> Output format: pretty or json");
4101
+ console.log(" --help, -h Display this message");
4102
+ console.log(" --version Show version");
4103
+ }
2978
4104
  async function showUpdateAndExit(code) {
2979
4105
  await waitForPendingCheck();
2980
4106
  const note = getUpdateNotification(version);
@@ -2999,17 +4125,17 @@ async function main() {
2999
4125
  if (cli.options.version) {
3000
4126
  await showUpdateAndExit(0);
3001
4127
  } else if (cli.options.help) {
3002
- if (cli.matchedCommandName) {
4128
+ if (cli.matchedCommand) {
3003
4129
  const result = cli.runMatchedCommand();
3004
4130
  if (result && typeof result.then === "function") {
3005
4131
  await result.then(() => showUpdateAndExit(0), handleError);
3006
4132
  }
3007
4133
  } else {
3008
- cli.outputHelp();
4134
+ printHelp();
3009
4135
  await showUpdateAndExit(0);
3010
4136
  }
3011
- } else if (!cli.matchedCommandName) {
3012
- cli.outputHelp();
4137
+ } else if (!cli.matchedCommand) {
4138
+ printHelp();
3013
4139
  await showUpdateAndExit(0);
3014
4140
  } else {
3015
4141
  const result = cli.runMatchedCommand();