polkadot-cli 0.14.0 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/cli.mjs +1250 -543
- package/package.json +4 -2
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 = "
|
|
8
|
+
var version = "1.1.1";
|
|
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";
|
|
@@ -830,6 +830,7 @@ async function accountInspect(input, opts) {
|
|
|
830
830
|
import { createClient } from "polkadot-api";
|
|
831
831
|
import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat";
|
|
832
832
|
import { getWsProvider } from "polkadot-api/ws-provider";
|
|
833
|
+
import { WebSocket } from "ws";
|
|
833
834
|
|
|
834
835
|
// src/utils/errors.ts
|
|
835
836
|
class CliError extends Error {
|
|
@@ -891,7 +892,10 @@ async function createChainClient(chainName, chainConfig, rpcOverride) {
|
|
|
891
892
|
restoreConsole();
|
|
892
893
|
throw new ConnectionError(`No RPC endpoint configured for chain "${chainName}". Use --rpc or configure one with: dot chain add ${chainName} --rpc <url>`);
|
|
893
894
|
}
|
|
894
|
-
provider = withPolkadotSdkCompat(getWsProvider(rpc, {
|
|
895
|
+
provider = withPolkadotSdkCompat(getWsProvider(rpc, {
|
|
896
|
+
timeout: 1e4,
|
|
897
|
+
websocketClass: WebSocket
|
|
898
|
+
}));
|
|
895
899
|
}
|
|
896
900
|
const client = createClient(provider, {
|
|
897
901
|
getMetadata: async () => loadMetadata(chainName),
|
|
@@ -1333,135 +1337,450 @@ function suggestMessage(kind, input, candidates) {
|
|
|
1333
1337
|
return `Unknown ${kind} "${input}". Did you mean: ${suggestions.join(", ")}?`;
|
|
1334
1338
|
}
|
|
1335
1339
|
|
|
1336
|
-
// src/
|
|
1337
|
-
function
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
if (!parts[0] || !parts[1]) {
|
|
1348
|
-
throw new Error(`Invalid target "${input}". Expected format: Pallet.Item or Chain.Pallet (e.g. System.Account or kusama.System)`);
|
|
1349
|
-
}
|
|
1350
|
-
if (options.knownChains?.some((c) => c.toLowerCase() === parts[0].toLowerCase())) {
|
|
1351
|
-
return { chain: parts[0], pallet: parts[1] };
|
|
1352
|
-
}
|
|
1353
|
-
return { pallet: parts[0], item: parts[1] };
|
|
1354
|
-
case 3:
|
|
1355
|
-
if (!parts[0] || !parts[1] || !parts[2]) {
|
|
1356
|
-
throw new Error(`Invalid target "${input}". Expected format: Chain.Pallet.Item (e.g. kusama.System.Account)`);
|
|
1357
|
-
}
|
|
1358
|
-
return { chain: parts[0], pallet: parts[1], item: parts[2] };
|
|
1359
|
-
default:
|
|
1360
|
-
throw new Error(`Invalid target "${input}". Expected format: Pallet, Pallet.Item, or Chain.Pallet.Item`);
|
|
1340
|
+
// src/commands/focused-inspect.ts
|
|
1341
|
+
async function loadMeta(chainName, chainConfig, rpcOverride) {
|
|
1342
|
+
try {
|
|
1343
|
+
return await getOrFetchMetadata(chainName);
|
|
1344
|
+
} catch {
|
|
1345
|
+
console.error(`Fetching metadata from ${chainName}...`);
|
|
1346
|
+
const clientHandle = await createChainClient(chainName, chainConfig, rpcOverride);
|
|
1347
|
+
try {
|
|
1348
|
+
return await getOrFetchMetadata(chainName, clientHandle);
|
|
1349
|
+
} finally {
|
|
1350
|
+
clientHandle.destroy();
|
|
1361
1351
|
}
|
|
1362
1352
|
}
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1353
|
+
}
|
|
1354
|
+
function resolvePallet(meta, palletName) {
|
|
1355
|
+
const palletNames = getPalletNames(meta);
|
|
1356
|
+
const pallet = findPallet(meta, palletName);
|
|
1357
|
+
if (!pallet) {
|
|
1358
|
+
throw new Error(suggestMessage("pallet", palletName, palletNames));
|
|
1359
|
+
}
|
|
1360
|
+
return pallet;
|
|
1361
|
+
}
|
|
1362
|
+
async function handleCalls(target, opts) {
|
|
1363
|
+
if (!target) {
|
|
1364
|
+
const config2 = await loadConfig();
|
|
1365
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1366
|
+
const meta2 = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
1367
|
+
const pallets = listPallets(meta2);
|
|
1368
|
+
const withCalls = pallets.filter((p) => p.calls.length > 0);
|
|
1369
|
+
printHeading(`Pallets with calls on ${chainName2} (${withCalls.length})`);
|
|
1370
|
+
for (const p of withCalls) {
|
|
1371
|
+
printItem(p.name, `${p.calls.length} calls`);
|
|
1372
|
+
}
|
|
1373
|
+
console.log();
|
|
1374
|
+
return;
|
|
1375
|
+
}
|
|
1376
|
+
const config = await loadConfig();
|
|
1377
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1378
|
+
const meta = await loadMeta(chainName, chainConfig, opts.rpc);
|
|
1379
|
+
const dotIdx = target.indexOf(".");
|
|
1380
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1381
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1382
|
+
const pallet = resolvePallet(meta, palletName);
|
|
1383
|
+
if (!itemName) {
|
|
1384
|
+
if (pallet.calls.length === 0) {
|
|
1385
|
+
console.log(`No calls in ${pallet.name}.`);
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
printHeading(`${pallet.name} Calls`);
|
|
1389
|
+
for (const c of pallet.calls) {
|
|
1390
|
+
const args2 = describeCallArgs(meta, pallet.name, c.name);
|
|
1391
|
+
console.log(` ${CYAN}${c.name}${RESET}${DIM}${args2}${RESET}`);
|
|
1392
|
+
const summary = firstSentence(c.docs);
|
|
1393
|
+
if (summary) {
|
|
1394
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1367
1395
|
}
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1396
|
+
}
|
|
1397
|
+
console.log();
|
|
1398
|
+
return;
|
|
1399
|
+
}
|
|
1400
|
+
const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
|
|
1401
|
+
if (!callItem) {
|
|
1402
|
+
const names = pallet.calls.map((c) => c.name);
|
|
1403
|
+
throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
|
|
1404
|
+
}
|
|
1405
|
+
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
1406
|
+
const args = describeCallArgs(meta, pallet.name, callItem.name);
|
|
1407
|
+
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
1408
|
+
if (callItem.docs.length) {
|
|
1409
|
+
console.log();
|
|
1410
|
+
printDocs(callItem.docs);
|
|
1411
|
+
}
|
|
1412
|
+
console.log();
|
|
1413
|
+
}
|
|
1414
|
+
async function handleEvents(target, opts) {
|
|
1415
|
+
if (!target) {
|
|
1416
|
+
const config2 = await loadConfig();
|
|
1417
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1418
|
+
const meta2 = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
1419
|
+
const pallets = listPallets(meta2);
|
|
1420
|
+
const withEvents = pallets.filter((p) => p.events.length > 0);
|
|
1421
|
+
printHeading(`Pallets with events on ${chainName2} (${withEvents.length})`);
|
|
1422
|
+
for (const p of withEvents) {
|
|
1423
|
+
printItem(p.name, `${p.events.length} events`);
|
|
1424
|
+
}
|
|
1425
|
+
console.log();
|
|
1426
|
+
return;
|
|
1427
|
+
}
|
|
1428
|
+
const config = await loadConfig();
|
|
1429
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1430
|
+
const meta = await loadMeta(chainName, chainConfig, opts.rpc);
|
|
1431
|
+
const dotIdx = target.indexOf(".");
|
|
1432
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1433
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1434
|
+
const pallet = resolvePallet(meta, palletName);
|
|
1435
|
+
if (!itemName) {
|
|
1436
|
+
if (pallet.events.length === 0) {
|
|
1437
|
+
console.log(`No events in ${pallet.name}.`);
|
|
1438
|
+
return;
|
|
1439
|
+
}
|
|
1440
|
+
printHeading(`${pallet.name} Events`);
|
|
1441
|
+
for (const e of pallet.events) {
|
|
1442
|
+
const fields2 = describeEventFields(meta, pallet.name, e.name);
|
|
1443
|
+
console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields2}${RESET}`);
|
|
1444
|
+
const summary = firstSentence(e.docs);
|
|
1445
|
+
if (summary) {
|
|
1446
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1372
1447
|
}
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1448
|
+
}
|
|
1449
|
+
console.log();
|
|
1450
|
+
return;
|
|
1376
1451
|
}
|
|
1452
|
+
const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
1453
|
+
if (!eventItem) {
|
|
1454
|
+
const names = pallet.events.map((e) => e.name);
|
|
1455
|
+
throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
|
|
1456
|
+
}
|
|
1457
|
+
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
1458
|
+
const fields = describeEventFields(meta, pallet.name, eventItem.name);
|
|
1459
|
+
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
1460
|
+
if (eventItem.docs.length) {
|
|
1461
|
+
console.log();
|
|
1462
|
+
printDocs(eventItem.docs);
|
|
1463
|
+
}
|
|
1464
|
+
console.log();
|
|
1377
1465
|
}
|
|
1378
|
-
function
|
|
1379
|
-
if (target
|
|
1380
|
-
|
|
1466
|
+
async function handleErrors(target, opts) {
|
|
1467
|
+
if (!target) {
|
|
1468
|
+
const config2 = await loadConfig();
|
|
1469
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1470
|
+
const meta2 = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
1471
|
+
const pallets = listPallets(meta2);
|
|
1472
|
+
const withErrors = pallets.filter((p) => p.errors.length > 0);
|
|
1473
|
+
printHeading(`Pallets with errors on ${chainName2} (${withErrors.length})`);
|
|
1474
|
+
for (const p of withErrors) {
|
|
1475
|
+
printItem(p.name, `${p.errors.length} errors`);
|
|
1476
|
+
}
|
|
1477
|
+
console.log();
|
|
1478
|
+
return;
|
|
1381
1479
|
}
|
|
1382
|
-
|
|
1480
|
+
const config = await loadConfig();
|
|
1481
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1482
|
+
const meta = await loadMeta(chainName, chainConfig, opts.rpc);
|
|
1483
|
+
const dotIdx = target.indexOf(".");
|
|
1484
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1485
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1486
|
+
const pallet = resolvePallet(meta, palletName);
|
|
1487
|
+
if (!itemName) {
|
|
1488
|
+
if (pallet.errors.length === 0) {
|
|
1489
|
+
console.log(`No errors in ${pallet.name}.`);
|
|
1490
|
+
return;
|
|
1491
|
+
}
|
|
1492
|
+
printHeading(`${pallet.name} Errors`);
|
|
1493
|
+
for (const e of pallet.errors) {
|
|
1494
|
+
console.log(` ${CYAN}${e.name}${RESET}`);
|
|
1495
|
+
const summary = firstSentence(e.docs);
|
|
1496
|
+
if (summary) {
|
|
1497
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1498
|
+
}
|
|
1499
|
+
}
|
|
1500
|
+
console.log();
|
|
1501
|
+
return;
|
|
1502
|
+
}
|
|
1503
|
+
const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
1504
|
+
if (!errorItem) {
|
|
1505
|
+
const names = pallet.errors.map((e) => e.name);
|
|
1506
|
+
throw new Error(suggestMessage(`error in ${pallet.name}`, itemName, names));
|
|
1507
|
+
}
|
|
1508
|
+
printHeading(`${pallet.name}.${errorItem.name} (Error)`);
|
|
1509
|
+
if (errorItem.docs.length) {
|
|
1510
|
+
printDocs(errorItem.docs);
|
|
1511
|
+
}
|
|
1512
|
+
console.log();
|
|
1383
1513
|
}
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1514
|
+
async function handleStorage(target, opts) {
|
|
1515
|
+
if (!target) {
|
|
1516
|
+
const config2 = await loadConfig();
|
|
1517
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1518
|
+
const meta2 = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
1519
|
+
const pallets = listPallets(meta2);
|
|
1520
|
+
const withStorage = pallets.filter((p) => p.storage.length > 0);
|
|
1521
|
+
printHeading(`Pallets with storage on ${chainName2} (${withStorage.length})`);
|
|
1522
|
+
for (const p of withStorage) {
|
|
1523
|
+
printItem(p.name, `${p.storage.length} storage`);
|
|
1524
|
+
}
|
|
1525
|
+
console.log();
|
|
1526
|
+
return;
|
|
1527
|
+
}
|
|
1528
|
+
const config = await loadConfig();
|
|
1529
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1530
|
+
const meta = await loadMeta(chainName, chainConfig, opts.rpc);
|
|
1531
|
+
const dotIdx = target.indexOf(".");
|
|
1532
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1533
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1534
|
+
const pallet = resolvePallet(meta, palletName);
|
|
1535
|
+
if (!itemName) {
|
|
1536
|
+
if (pallet.storage.length === 0) {
|
|
1537
|
+
console.log(`No storage items in ${pallet.name}.`);
|
|
1396
1538
|
return;
|
|
1397
1539
|
}
|
|
1398
|
-
|
|
1399
|
-
const
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
try {
|
|
1408
|
-
meta = await getOrFetchMetadata(chainName);
|
|
1409
|
-
} catch {
|
|
1410
|
-
console.error(`Fetching metadata from ${chainName}...`);
|
|
1411
|
-
const clientHandle2 = await createChainClient(chainName, chainConfig, opts.rpc);
|
|
1412
|
-
try {
|
|
1413
|
-
meta = await getOrFetchMetadata(chainName, clientHandle2);
|
|
1414
|
-
} finally {
|
|
1415
|
-
clientHandle2.destroy();
|
|
1416
|
-
}
|
|
1540
|
+
printHeading(`${pallet.name} Storage`);
|
|
1541
|
+
for (const s of pallet.storage) {
|
|
1542
|
+
const valueType = describeType(meta.lookup, s.valueTypeId);
|
|
1543
|
+
let typeSuffix;
|
|
1544
|
+
if (s.keyTypeId != null) {
|
|
1545
|
+
const keyType = describeType(meta.lookup, s.keyTypeId);
|
|
1546
|
+
typeSuffix = `: ${keyType} → ${valueType} [map]`;
|
|
1547
|
+
} else {
|
|
1548
|
+
typeSuffix = `: ${valueType}`;
|
|
1417
1549
|
}
|
|
1418
|
-
|
|
1419
|
-
const
|
|
1420
|
-
if (
|
|
1421
|
-
|
|
1550
|
+
console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
|
|
1551
|
+
const summary = firstSentence(s.docs);
|
|
1552
|
+
if (summary) {
|
|
1553
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1422
1554
|
}
|
|
1423
|
-
|
|
1424
|
-
|
|
1555
|
+
}
|
|
1556
|
+
console.log();
|
|
1557
|
+
return;
|
|
1558
|
+
}
|
|
1559
|
+
const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
|
|
1560
|
+
if (!storageItem) {
|
|
1561
|
+
const names = pallet.storage.map((s) => s.name);
|
|
1562
|
+
throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
|
|
1563
|
+
}
|
|
1564
|
+
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
1565
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
1566
|
+
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
1567
|
+
if (storageItem.keyTypeId != null) {
|
|
1568
|
+
console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
|
|
1569
|
+
}
|
|
1570
|
+
if (storageItem.docs.length) {
|
|
1571
|
+
console.log();
|
|
1572
|
+
printDocs(storageItem.docs);
|
|
1573
|
+
}
|
|
1574
|
+
console.log();
|
|
1575
|
+
}
|
|
1576
|
+
async function showItemHelp(category, target, opts) {
|
|
1577
|
+
const config = await loadConfig();
|
|
1578
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1579
|
+
const meta = await loadMeta(chainName, chainConfig, opts.rpc);
|
|
1580
|
+
const dotIdx = target.indexOf(".");
|
|
1581
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1582
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1583
|
+
const pallet = resolvePallet(meta, palletName);
|
|
1584
|
+
if (!itemName) {
|
|
1585
|
+
switch (category) {
|
|
1586
|
+
case "tx":
|
|
1587
|
+
await handleCalls(target, opts);
|
|
1588
|
+
return;
|
|
1589
|
+
case "query":
|
|
1590
|
+
await handleStorage(target, opts);
|
|
1591
|
+
return;
|
|
1592
|
+
case "const":
|
|
1593
|
+
return;
|
|
1594
|
+
case "events":
|
|
1595
|
+
await handleEvents(target, opts);
|
|
1596
|
+
return;
|
|
1597
|
+
case "errors":
|
|
1598
|
+
await handleErrors(target, opts);
|
|
1425
1599
|
return;
|
|
1600
|
+
}
|
|
1601
|
+
}
|
|
1602
|
+
switch (category) {
|
|
1603
|
+
case "tx": {
|
|
1604
|
+
const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
|
|
1605
|
+
if (!callItem) {
|
|
1606
|
+
const names = pallet.calls.map((c) => c.name);
|
|
1607
|
+
throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
|
|
1426
1608
|
}
|
|
1427
|
-
printHeading(`${
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
console.log(` ${DIM}${summary}${RESET}`);
|
|
1434
|
-
}
|
|
1609
|
+
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
1610
|
+
const args = describeCallArgs(meta, pallet.name, callItem.name);
|
|
1611
|
+
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
1612
|
+
if (callItem.docs.length) {
|
|
1613
|
+
console.log();
|
|
1614
|
+
printDocs(callItem.docs);
|
|
1435
1615
|
}
|
|
1436
1616
|
console.log();
|
|
1617
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
1618
|
+
console.log(` dot tx.${pallet.name}.${callItem.name} --from <account>`);
|
|
1619
|
+
console.log(` dot tx.${pallet.name}.${callItem.name} --encode`);
|
|
1620
|
+
console.log();
|
|
1621
|
+
console.log(`${BOLD}Options:${RESET}`);
|
|
1622
|
+
console.log(` --from <name> Account to sign with`);
|
|
1623
|
+
console.log(` --dry-run Estimate fees without submitting`);
|
|
1624
|
+
console.log(` --encode Encode call to hex without signing`);
|
|
1625
|
+
console.log(` --ext <json> Custom signed extension values as JSON`);
|
|
1626
|
+
console.log();
|
|
1437
1627
|
return;
|
|
1438
1628
|
}
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
if (!palletInfo) {
|
|
1445
|
-
throw new Error(suggestMessage("pallet", pallet, palletNames));
|
|
1629
|
+
case "query": {
|
|
1630
|
+
const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
|
|
1631
|
+
if (!storageItem) {
|
|
1632
|
+
const names = pallet.storage.map((s) => s.name);
|
|
1633
|
+
throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
|
|
1446
1634
|
}
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1635
|
+
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
1636
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
1637
|
+
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
1638
|
+
if (storageItem.keyTypeId != null) {
|
|
1639
|
+
console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
|
|
1451
1640
|
}
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1641
|
+
if (storageItem.docs.length) {
|
|
1642
|
+
console.log();
|
|
1643
|
+
printDocs(storageItem.docs);
|
|
1644
|
+
}
|
|
1645
|
+
console.log();
|
|
1646
|
+
if (storageItem.keyTypeId != null) {
|
|
1647
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
1648
|
+
console.log(` dot query.${pallet.name}.${storageItem.name} <key>`);
|
|
1649
|
+
console.log(` dot query.${pallet.name}.${storageItem.name} # all entries`);
|
|
1650
|
+
} else {
|
|
1651
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
1652
|
+
console.log(` dot query.${pallet.name}.${storageItem.name}`);
|
|
1653
|
+
}
|
|
1654
|
+
console.log();
|
|
1655
|
+
console.log(`${BOLD}Options:${RESET}`);
|
|
1656
|
+
console.log(` --limit <n> Max entries for map queries (0 = unlimited, default: 100)`);
|
|
1657
|
+
console.log();
|
|
1658
|
+
return;
|
|
1459
1659
|
}
|
|
1460
|
-
|
|
1660
|
+
case "const": {
|
|
1661
|
+
const constItem = pallet.constants.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
|
|
1662
|
+
if (!constItem) {
|
|
1663
|
+
const names = pallet.constants.map((c) => c.name);
|
|
1664
|
+
throw new Error(suggestMessage(`constant in ${pallet.name}`, itemName, names));
|
|
1665
|
+
}
|
|
1666
|
+
printHeading(`${pallet.name}.${constItem.name} (Constant)`);
|
|
1667
|
+
console.log(` ${BOLD}Type:${RESET} ${describeType(meta.lookup, constItem.typeId)}`);
|
|
1668
|
+
if (constItem.docs.length) {
|
|
1669
|
+
console.log();
|
|
1670
|
+
printDocs(constItem.docs);
|
|
1671
|
+
}
|
|
1672
|
+
console.log();
|
|
1673
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
1674
|
+
console.log(` dot const.${pallet.name}.${constItem.name}`);
|
|
1675
|
+
console.log();
|
|
1676
|
+
return;
|
|
1677
|
+
}
|
|
1678
|
+
case "events": {
|
|
1679
|
+
const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
1680
|
+
if (!eventItem) {
|
|
1681
|
+
const names = pallet.events.map((e) => e.name);
|
|
1682
|
+
throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
|
|
1683
|
+
}
|
|
1684
|
+
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
1685
|
+
const fields = describeEventFields(meta, pallet.name, eventItem.name);
|
|
1686
|
+
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
1687
|
+
if (eventItem.docs.length) {
|
|
1688
|
+
console.log();
|
|
1689
|
+
printDocs(eventItem.docs);
|
|
1690
|
+
}
|
|
1691
|
+
console.log();
|
|
1692
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
1693
|
+
console.log(` dot events.${pallet.name}.${eventItem.name}`);
|
|
1694
|
+
console.log();
|
|
1695
|
+
return;
|
|
1696
|
+
}
|
|
1697
|
+
case "errors": {
|
|
1698
|
+
const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
1699
|
+
if (!errorItem) {
|
|
1700
|
+
const names = pallet.errors.map((e) => e.name);
|
|
1701
|
+
throw new Error(suggestMessage(`error in ${pallet.name}`, itemName, names));
|
|
1702
|
+
}
|
|
1703
|
+
printHeading(`${pallet.name}.${errorItem.name} (Error)`);
|
|
1704
|
+
if (errorItem.docs.length) {
|
|
1705
|
+
printDocs(errorItem.docs);
|
|
1706
|
+
}
|
|
1707
|
+
console.log();
|
|
1708
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
1709
|
+
console.log(` dot errors.${pallet.name}.${errorItem.name}`);
|
|
1710
|
+
console.log();
|
|
1711
|
+
return;
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
// src/commands/const.ts
|
|
1717
|
+
async function handleConst(target, opts) {
|
|
1718
|
+
if (!target) {
|
|
1719
|
+
const config2 = await loadConfig();
|
|
1720
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1721
|
+
const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
1722
|
+
const pallets = listPallets(meta);
|
|
1723
|
+
const withConsts = pallets.filter((p) => p.constants.length > 0);
|
|
1724
|
+
printHeading(`Pallets with constants on ${chainName2} (${withConsts.length})`);
|
|
1725
|
+
for (const p of withConsts) {
|
|
1726
|
+
printItem(p.name, `${p.constants.length} constants`);
|
|
1727
|
+
}
|
|
1728
|
+
console.log();
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
const dotIdx = target.indexOf(".");
|
|
1732
|
+
const pallet = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1733
|
+
const item = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1734
|
+
const config = await loadConfig();
|
|
1735
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1736
|
+
if (!item) {
|
|
1737
|
+
const meta = await loadMeta(chainName, chainConfig, opts.rpc);
|
|
1738
|
+
const palletNames = getPalletNames(meta);
|
|
1739
|
+
const palletInfo = findPallet(meta, pallet);
|
|
1740
|
+
if (!palletInfo) {
|
|
1741
|
+
throw new Error(suggestMessage("pallet", pallet, palletNames));
|
|
1742
|
+
}
|
|
1743
|
+
if (palletInfo.constants.length === 0) {
|
|
1744
|
+
console.log(`No constants in ${palletInfo.name}.`);
|
|
1745
|
+
return;
|
|
1746
|
+
}
|
|
1747
|
+
printHeading(`${palletInfo.name} Constants`);
|
|
1748
|
+
for (const c of palletInfo.constants) {
|
|
1749
|
+
const typeStr = describeType(meta.lookup, c.typeId);
|
|
1750
|
+
console.log(` ${CYAN}${c.name}${RESET}${DIM}: ${typeStr}${RESET}`);
|
|
1751
|
+
const summary = firstSentence(c.docs);
|
|
1752
|
+
if (summary) {
|
|
1753
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
console.log();
|
|
1757
|
+
return;
|
|
1758
|
+
}
|
|
1759
|
+
const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
|
|
1760
|
+
try {
|
|
1761
|
+
const meta = await getOrFetchMetadata(chainName, clientHandle);
|
|
1762
|
+
const palletNames = getPalletNames(meta);
|
|
1763
|
+
const palletInfo = findPallet(meta, pallet);
|
|
1764
|
+
if (!palletInfo) {
|
|
1765
|
+
throw new Error(suggestMessage("pallet", pallet, palletNames));
|
|
1766
|
+
}
|
|
1767
|
+
const constantItem = palletInfo.constants.find((c) => c.name.toLowerCase() === item.toLowerCase());
|
|
1768
|
+
if (!constantItem) {
|
|
1769
|
+
const constNames = palletInfo.constants.map((c) => c.name);
|
|
1770
|
+
throw new Error(suggestMessage(`constant in ${palletInfo.name}`, item, constNames));
|
|
1771
|
+
}
|
|
1772
|
+
const unsafeApi = clientHandle.client.getUnsafeApi();
|
|
1773
|
+
const runtimeToken = await unsafeApi.runtimeToken;
|
|
1774
|
+
const result = unsafeApi.constants[palletInfo.name][constantItem.name](runtimeToken);
|
|
1775
|
+
const format = opts.output ?? "pretty";
|
|
1776
|
+
printResult(result, format);
|
|
1777
|
+
} finally {
|
|
1778
|
+
clientHandle.destroy();
|
|
1779
|
+
}
|
|
1461
1780
|
}
|
|
1462
1781
|
|
|
1463
1782
|
// src/commands/focused-inspect.ts
|
|
1464
|
-
async function
|
|
1783
|
+
async function loadMeta2(chainName, chainConfig, rpcOverride) {
|
|
1465
1784
|
try {
|
|
1466
1785
|
return await getOrFetchMetadata(chainName);
|
|
1467
1786
|
} catch {
|
|
@@ -1474,7 +1793,7 @@ async function loadMeta(chainName, chainConfig, rpcOverride) {
|
|
|
1474
1793
|
}
|
|
1475
1794
|
}
|
|
1476
1795
|
}
|
|
1477
|
-
function
|
|
1796
|
+
function resolvePallet2(meta, palletName) {
|
|
1478
1797
|
const palletNames = getPalletNames(meta);
|
|
1479
1798
|
const pallet = findPallet(meta, palletName);
|
|
1480
1799
|
if (!pallet) {
|
|
@@ -1482,255 +1801,358 @@ function resolvePallet(meta, palletName) {
|
|
|
1482
1801
|
}
|
|
1483
1802
|
return pallet;
|
|
1484
1803
|
}
|
|
1485
|
-
function
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1804
|
+
async function handleCalls2(target, opts) {
|
|
1805
|
+
if (!target) {
|
|
1806
|
+
const config2 = await loadConfig();
|
|
1807
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1808
|
+
const meta2 = await loadMeta2(chainName2, chainConfig2, opts.rpc);
|
|
1809
|
+
const pallets = listPallets(meta2);
|
|
1810
|
+
const withCalls = pallets.filter((p) => p.calls.length > 0);
|
|
1811
|
+
printHeading(`Pallets with calls on ${chainName2} (${withCalls.length})`);
|
|
1812
|
+
for (const p of withCalls) {
|
|
1813
|
+
printItem(p.name, `${p.calls.length} calls`);
|
|
1494
1814
|
}
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
for (const c of pallet.calls) {
|
|
1509
|
-
const args2 = describeCallArgs(meta, pallet.name, c.name);
|
|
1510
|
-
console.log(` ${CYAN}${c.name}${RESET}${DIM}${args2}${RESET}`);
|
|
1511
|
-
const summary = firstSentence(c.docs);
|
|
1512
|
-
if (summary) {
|
|
1513
|
-
console.log(` ${DIM}${summary}${RESET}`);
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
console.log();
|
|
1815
|
+
console.log();
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
const config = await loadConfig();
|
|
1819
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1820
|
+
const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
|
|
1821
|
+
const dotIdx = target.indexOf(".");
|
|
1822
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1823
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1824
|
+
const pallet = resolvePallet2(meta, palletName);
|
|
1825
|
+
if (!itemName) {
|
|
1826
|
+
if (pallet.calls.length === 0) {
|
|
1827
|
+
console.log(`No calls in ${pallet.name}.`);
|
|
1517
1828
|
return;
|
|
1518
1829
|
}
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
const
|
|
1522
|
-
|
|
1830
|
+
printHeading(`${pallet.name} Calls`);
|
|
1831
|
+
for (const c of pallet.calls) {
|
|
1832
|
+
const args2 = describeCallArgs(meta, pallet.name, c.name);
|
|
1833
|
+
console.log(` ${CYAN}${c.name}${RESET}${DIM}${args2}${RESET}`);
|
|
1834
|
+
const summary = firstSentence(c.docs);
|
|
1835
|
+
if (summary) {
|
|
1836
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1837
|
+
}
|
|
1523
1838
|
}
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1839
|
+
console.log();
|
|
1840
|
+
return;
|
|
1841
|
+
}
|
|
1842
|
+
const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
|
|
1843
|
+
if (!callItem) {
|
|
1844
|
+
const names = pallet.calls.map((c) => c.name);
|
|
1845
|
+
throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
|
|
1846
|
+
}
|
|
1847
|
+
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
1848
|
+
const args = describeCallArgs(meta, pallet.name, callItem.name);
|
|
1849
|
+
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
1850
|
+
if (callItem.docs.length) {
|
|
1851
|
+
console.log();
|
|
1852
|
+
printDocs(callItem.docs);
|
|
1853
|
+
}
|
|
1854
|
+
console.log();
|
|
1855
|
+
}
|
|
1856
|
+
async function handleEvents2(target, opts) {
|
|
1857
|
+
if (!target) {
|
|
1858
|
+
const config2 = await loadConfig();
|
|
1859
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1860
|
+
const meta2 = await loadMeta2(chainName2, chainConfig2, opts.rpc);
|
|
1861
|
+
const pallets = listPallets(meta2);
|
|
1862
|
+
const withEvents = pallets.filter((p) => p.events.length > 0);
|
|
1863
|
+
printHeading(`Pallets with events on ${chainName2} (${withEvents.length})`);
|
|
1864
|
+
for (const p of withEvents) {
|
|
1865
|
+
printItem(p.name, `${p.events.length} events`);
|
|
1530
1866
|
}
|
|
1531
1867
|
console.log();
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1868
|
+
return;
|
|
1869
|
+
}
|
|
1870
|
+
const config = await loadConfig();
|
|
1871
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1872
|
+
const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
|
|
1873
|
+
const dotIdx = target.indexOf(".");
|
|
1874
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1875
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1876
|
+
const pallet = resolvePallet2(meta, palletName);
|
|
1877
|
+
if (!itemName) {
|
|
1878
|
+
if (pallet.events.length === 0) {
|
|
1879
|
+
console.log(`No events in ${pallet.name}.`);
|
|
1540
1880
|
return;
|
|
1541
1881
|
}
|
|
1542
|
-
|
|
1543
|
-
const
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
if (!parsed.item) {
|
|
1550
|
-
if (pallet.events.length === 0) {
|
|
1551
|
-
console.log(`No events in ${pallet.name}.`);
|
|
1552
|
-
return;
|
|
1882
|
+
printHeading(`${pallet.name} Events`);
|
|
1883
|
+
for (const e of pallet.events) {
|
|
1884
|
+
const fields2 = describeEventFields(meta, pallet.name, e.name);
|
|
1885
|
+
console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields2}${RESET}`);
|
|
1886
|
+
const summary = firstSentence(e.docs);
|
|
1887
|
+
if (summary) {
|
|
1888
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1553
1889
|
}
|
|
1554
|
-
printHeading(`${pallet.name} Events`);
|
|
1555
|
-
for (const e of pallet.events) {
|
|
1556
|
-
const fields2 = describeEventFields(meta, pallet.name, e.name);
|
|
1557
|
-
console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields2}${RESET}`);
|
|
1558
|
-
const summary = firstSentence(e.docs);
|
|
1559
|
-
if (summary) {
|
|
1560
|
-
console.log(` ${DIM}${summary}${RESET}`);
|
|
1561
|
-
}
|
|
1562
|
-
}
|
|
1563
|
-
console.log();
|
|
1564
|
-
return;
|
|
1565
|
-
}
|
|
1566
|
-
const eventItem = pallet.events.find((e) => e.name.toLowerCase() === parsed.item.toLowerCase());
|
|
1567
|
-
if (!eventItem) {
|
|
1568
|
-
const names = pallet.events.map((e) => e.name);
|
|
1569
|
-
throw new Error(suggestMessage(`event in ${pallet.name}`, parsed.item, names));
|
|
1570
1890
|
}
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1891
|
+
console.log();
|
|
1892
|
+
return;
|
|
1893
|
+
}
|
|
1894
|
+
const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
1895
|
+
if (!eventItem) {
|
|
1896
|
+
const names = pallet.events.map((e) => e.name);
|
|
1897
|
+
throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
|
|
1898
|
+
}
|
|
1899
|
+
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
1900
|
+
const fields = describeEventFields(meta, pallet.name, eventItem.name);
|
|
1901
|
+
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
1902
|
+
if (eventItem.docs.length) {
|
|
1903
|
+
console.log();
|
|
1904
|
+
printDocs(eventItem.docs);
|
|
1905
|
+
}
|
|
1906
|
+
console.log();
|
|
1907
|
+
}
|
|
1908
|
+
async function handleErrors2(target, opts) {
|
|
1909
|
+
if (!target) {
|
|
1910
|
+
const config2 = await loadConfig();
|
|
1911
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1912
|
+
const meta2 = await loadMeta2(chainName2, chainConfig2, opts.rpc);
|
|
1913
|
+
const pallets = listPallets(meta2);
|
|
1914
|
+
const withErrors = pallets.filter((p) => p.errors.length > 0);
|
|
1915
|
+
printHeading(`Pallets with errors on ${chainName2} (${withErrors.length})`);
|
|
1916
|
+
for (const p of withErrors) {
|
|
1917
|
+
printItem(p.name, `${p.errors.length} errors`);
|
|
1577
1918
|
}
|
|
1578
1919
|
console.log();
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
const config = await loadConfig();
|
|
1923
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1924
|
+
const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
|
|
1925
|
+
const dotIdx = target.indexOf(".");
|
|
1926
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1927
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1928
|
+
const pallet = resolvePallet2(meta, palletName);
|
|
1929
|
+
if (!itemName) {
|
|
1930
|
+
if (pallet.errors.length === 0) {
|
|
1931
|
+
console.log(`No errors in ${pallet.name}.`);
|
|
1587
1932
|
return;
|
|
1588
1933
|
}
|
|
1589
|
-
|
|
1590
|
-
const
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
const pallet = resolvePallet(meta, parsed.pallet);
|
|
1596
|
-
if (!parsed.item) {
|
|
1597
|
-
if (pallet.errors.length === 0) {
|
|
1598
|
-
console.log(`No errors in ${pallet.name}.`);
|
|
1599
|
-
return;
|
|
1600
|
-
}
|
|
1601
|
-
printHeading(`${pallet.name} Errors`);
|
|
1602
|
-
for (const e of pallet.errors) {
|
|
1603
|
-
console.log(` ${CYAN}${e.name}${RESET}`);
|
|
1604
|
-
const summary = firstSentence(e.docs);
|
|
1605
|
-
if (summary) {
|
|
1606
|
-
console.log(` ${DIM}${summary}${RESET}`);
|
|
1607
|
-
}
|
|
1934
|
+
printHeading(`${pallet.name} Errors`);
|
|
1935
|
+
for (const e of pallet.errors) {
|
|
1936
|
+
console.log(` ${CYAN}${e.name}${RESET}`);
|
|
1937
|
+
const summary = firstSentence(e.docs);
|
|
1938
|
+
if (summary) {
|
|
1939
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1608
1940
|
}
|
|
1609
|
-
console.log();
|
|
1610
|
-
return;
|
|
1611
|
-
}
|
|
1612
|
-
const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === parsed.item.toLowerCase());
|
|
1613
|
-
if (!errorItem) {
|
|
1614
|
-
const names = pallet.errors.map((e) => e.name);
|
|
1615
|
-
throw new Error(suggestMessage(`error in ${pallet.name}`, parsed.item, names));
|
|
1616
1941
|
}
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1942
|
+
console.log();
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
1946
|
+
if (!errorItem) {
|
|
1947
|
+
const names = pallet.errors.map((e) => e.name);
|
|
1948
|
+
throw new Error(suggestMessage(`error in ${pallet.name}`, itemName, names));
|
|
1949
|
+
}
|
|
1950
|
+
printHeading(`${pallet.name}.${errorItem.name} (Error)`);
|
|
1951
|
+
if (errorItem.docs.length) {
|
|
1952
|
+
printDocs(errorItem.docs);
|
|
1953
|
+
}
|
|
1954
|
+
console.log();
|
|
1955
|
+
}
|
|
1956
|
+
async function handleStorage2(target, opts) {
|
|
1957
|
+
if (!target) {
|
|
1958
|
+
const config2 = await loadConfig();
|
|
1959
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
1960
|
+
const meta2 = await loadMeta2(chainName2, chainConfig2, opts.rpc);
|
|
1961
|
+
const pallets = listPallets(meta2);
|
|
1962
|
+
const withStorage = pallets.filter((p) => p.storage.length > 0);
|
|
1963
|
+
printHeading(`Pallets with storage on ${chainName2} (${withStorage.length})`);
|
|
1964
|
+
for (const p of withStorage) {
|
|
1965
|
+
printItem(p.name, `${p.storage.length} storage`);
|
|
1620
1966
|
}
|
|
1621
1967
|
console.log();
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1968
|
+
return;
|
|
1969
|
+
}
|
|
1970
|
+
const config = await loadConfig();
|
|
1971
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
1972
|
+
const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
|
|
1973
|
+
const dotIdx = target.indexOf(".");
|
|
1974
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
1975
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
1976
|
+
const pallet = resolvePallet2(meta, palletName);
|
|
1977
|
+
if (!itemName) {
|
|
1978
|
+
if (pallet.storage.length === 0) {
|
|
1979
|
+
console.log(`No storage items in ${pallet.name}.`);
|
|
1630
1980
|
return;
|
|
1631
1981
|
}
|
|
1632
|
-
|
|
1633
|
-
const
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1982
|
+
printHeading(`${pallet.name} Storage`);
|
|
1983
|
+
for (const s of pallet.storage) {
|
|
1984
|
+
const valueType = describeType(meta.lookup, s.valueTypeId);
|
|
1985
|
+
let typeSuffix;
|
|
1986
|
+
if (s.keyTypeId != null) {
|
|
1987
|
+
const keyType = describeType(meta.lookup, s.keyTypeId);
|
|
1988
|
+
typeSuffix = `: ${keyType} → ${valueType} [map]`;
|
|
1989
|
+
} else {
|
|
1990
|
+
typeSuffix = `: ${valueType}`;
|
|
1991
|
+
}
|
|
1992
|
+
console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
|
|
1993
|
+
const summary = firstSentence(s.docs);
|
|
1994
|
+
if (summary) {
|
|
1995
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
console.log();
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
2001
|
+
const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
|
|
2002
|
+
if (!storageItem) {
|
|
2003
|
+
const names = pallet.storage.map((s) => s.name);
|
|
2004
|
+
throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
|
|
2005
|
+
}
|
|
2006
|
+
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
2007
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
2008
|
+
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
2009
|
+
if (storageItem.keyTypeId != null) {
|
|
2010
|
+
console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
|
|
2011
|
+
}
|
|
2012
|
+
if (storageItem.docs.length) {
|
|
2013
|
+
console.log();
|
|
2014
|
+
printDocs(storageItem.docs);
|
|
2015
|
+
}
|
|
2016
|
+
console.log();
|
|
2017
|
+
}
|
|
2018
|
+
async function showItemHelp2(category, target, opts) {
|
|
2019
|
+
const config = await loadConfig();
|
|
2020
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
2021
|
+
const meta = await loadMeta2(chainName, chainConfig, opts.rpc);
|
|
2022
|
+
const dotIdx = target.indexOf(".");
|
|
2023
|
+
const palletName = dotIdx === -1 ? target : target.slice(0, dotIdx);
|
|
2024
|
+
const itemName = dotIdx === -1 ? undefined : target.slice(dotIdx + 1);
|
|
2025
|
+
const pallet = resolvePallet2(meta, palletName);
|
|
2026
|
+
if (!itemName) {
|
|
2027
|
+
switch (category) {
|
|
2028
|
+
case "tx":
|
|
2029
|
+
await handleCalls2(target, opts);
|
|
2030
|
+
return;
|
|
2031
|
+
case "query":
|
|
2032
|
+
await handleStorage2(target, opts);
|
|
2033
|
+
return;
|
|
2034
|
+
case "const":
|
|
1642
2035
|
return;
|
|
2036
|
+
case "events":
|
|
2037
|
+
await handleEvents2(target, opts);
|
|
2038
|
+
return;
|
|
2039
|
+
case "errors":
|
|
2040
|
+
await handleErrors2(target, opts);
|
|
2041
|
+
return;
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
2044
|
+
switch (category) {
|
|
2045
|
+
case "tx": {
|
|
2046
|
+
const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
|
|
2047
|
+
if (!callItem) {
|
|
2048
|
+
const names = pallet.calls.map((c) => c.name);
|
|
2049
|
+
throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
|
|
1643
2050
|
}
|
|
1644
|
-
printHeading(`${pallet.name}
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
typeSuffix = `: ${keyType} → ${valueType} [map]`;
|
|
1651
|
-
} else {
|
|
1652
|
-
typeSuffix = `: ${valueType}`;
|
|
1653
|
-
}
|
|
1654
|
-
console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
|
|
1655
|
-
const summary = firstSentence(s.docs);
|
|
1656
|
-
if (summary) {
|
|
1657
|
-
console.log(` ${DIM}${summary}${RESET}`);
|
|
1658
|
-
}
|
|
2051
|
+
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
2052
|
+
const args = describeCallArgs(meta, pallet.name, callItem.name);
|
|
2053
|
+
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
2054
|
+
if (callItem.docs.length) {
|
|
2055
|
+
console.log();
|
|
2056
|
+
printDocs(callItem.docs);
|
|
1659
2057
|
}
|
|
1660
2058
|
console.log();
|
|
2059
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
2060
|
+
console.log(` dot tx.${pallet.name}.${callItem.name} --from <account>`);
|
|
2061
|
+
console.log(` dot tx.${pallet.name}.${callItem.name} --encode`);
|
|
2062
|
+
console.log();
|
|
2063
|
+
console.log(`${BOLD}Options:${RESET}`);
|
|
2064
|
+
console.log(` --from <name> Account to sign with`);
|
|
2065
|
+
console.log(` --dry-run Estimate fees without submitting`);
|
|
2066
|
+
console.log(` --encode Encode call to hex without signing`);
|
|
2067
|
+
console.log(` --ext <json> Custom signed extension values as JSON`);
|
|
2068
|
+
console.log();
|
|
1661
2069
|
return;
|
|
1662
2070
|
}
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
2071
|
+
case "query": {
|
|
2072
|
+
const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
|
|
2073
|
+
if (!storageItem) {
|
|
2074
|
+
const names = pallet.storage.map((s) => s.name);
|
|
2075
|
+
throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
|
|
2076
|
+
}
|
|
2077
|
+
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
2078
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
2079
|
+
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
2080
|
+
if (storageItem.keyTypeId != null) {
|
|
2081
|
+
console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
|
|
2082
|
+
}
|
|
2083
|
+
if (storageItem.docs.length) {
|
|
2084
|
+
console.log();
|
|
2085
|
+
printDocs(storageItem.docs);
|
|
2086
|
+
}
|
|
1675
2087
|
console.log();
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
});
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
2088
|
+
if (storageItem.keyTypeId != null) {
|
|
2089
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
2090
|
+
console.log(` dot query.${pallet.name}.${storageItem.name} <key>`);
|
|
2091
|
+
console.log(` dot query.${pallet.name}.${storageItem.name} # all entries`);
|
|
2092
|
+
} else {
|
|
2093
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
2094
|
+
console.log(` dot query.${pallet.name}.${storageItem.name}`);
|
|
2095
|
+
}
|
|
2096
|
+
console.log();
|
|
2097
|
+
console.log(`${BOLD}Options:${RESET}`);
|
|
2098
|
+
console.log(` --limit <n> Max entries for map queries (0 = unlimited, default: 100)`);
|
|
2099
|
+
console.log();
|
|
2100
|
+
return;
|
|
1689
2101
|
}
|
|
1690
|
-
const {
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
if (p.calls.length)
|
|
1702
|
-
counts2.push(`${p.calls.length} calls`);
|
|
1703
|
-
if (p.events.length)
|
|
1704
|
-
counts2.push(`${p.events.length} events`);
|
|
1705
|
-
if (p.errors.length)
|
|
1706
|
-
counts2.push(`${p.errors.length} errors`);
|
|
1707
|
-
printItem(p.name, counts2.join(", "));
|
|
2102
|
+
case "const": {
|
|
2103
|
+
const constItem = pallet.constants.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
|
|
2104
|
+
if (!constItem) {
|
|
2105
|
+
const names = pallet.constants.map((c) => c.name);
|
|
2106
|
+
throw new Error(suggestMessage(`constant in ${pallet.name}`, itemName, names));
|
|
2107
|
+
}
|
|
2108
|
+
printHeading(`${pallet.name}.${constItem.name} (Constant)`);
|
|
2109
|
+
console.log(` ${BOLD}Type:${RESET} ${describeType(meta.lookup, constItem.typeId)}`);
|
|
2110
|
+
if (constItem.docs.length) {
|
|
2111
|
+
console.log();
|
|
2112
|
+
printDocs(constItem.docs);
|
|
1708
2113
|
}
|
|
1709
2114
|
console.log();
|
|
2115
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
2116
|
+
console.log(` dot const.${pallet.name}.${constItem.name}`);
|
|
2117
|
+
console.log();
|
|
1710
2118
|
return;
|
|
1711
2119
|
}
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
2120
|
+
case "events": {
|
|
2121
|
+
const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
2122
|
+
if (!eventItem) {
|
|
2123
|
+
const names = pallet.events.map((e) => e.name);
|
|
2124
|
+
throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
|
|
2125
|
+
}
|
|
2126
|
+
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
2127
|
+
const fields = describeEventFields(meta, pallet.name, eventItem.name);
|
|
2128
|
+
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
2129
|
+
if (eventItem.docs.length) {
|
|
2130
|
+
console.log();
|
|
2131
|
+
printDocs(eventItem.docs);
|
|
2132
|
+
}
|
|
2133
|
+
console.log();
|
|
2134
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
2135
|
+
console.log(` dot events.${pallet.name}.${eventItem.name}`);
|
|
1716
2136
|
console.log();
|
|
2137
|
+
return;
|
|
1717
2138
|
}
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
console.log(`
|
|
2139
|
+
case "errors": {
|
|
2140
|
+
const errorItem = pallet.errors.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
2141
|
+
if (!errorItem) {
|
|
2142
|
+
const names = pallet.errors.map((e) => e.name);
|
|
2143
|
+
throw new Error(suggestMessage(`error in ${pallet.name}`, itemName, names));
|
|
2144
|
+
}
|
|
2145
|
+
printHeading(`${pallet.name}.${errorItem.name} (Error)`);
|
|
2146
|
+
if (errorItem.docs.length) {
|
|
2147
|
+
printDocs(errorItem.docs);
|
|
2148
|
+
}
|
|
2149
|
+
console.log();
|
|
2150
|
+
console.log(`${BOLD}Usage:${RESET}`);
|
|
2151
|
+
console.log(` dot errors.${pallet.name}.${errorItem.name}`);
|
|
2152
|
+
console.log();
|
|
2153
|
+
return;
|
|
1731
2154
|
}
|
|
1732
|
-
|
|
1733
|
-
});
|
|
2155
|
+
}
|
|
1734
2156
|
}
|
|
1735
2157
|
|
|
1736
2158
|
// src/core/hash.ts
|
|
@@ -1864,9 +2286,58 @@ function registerHashCommand(cli) {
|
|
|
1864
2286
|
});
|
|
1865
2287
|
}
|
|
1866
2288
|
|
|
2289
|
+
// src/utils/parse-target.ts
|
|
2290
|
+
function parseTarget(input, options) {
|
|
2291
|
+
const parts = input.split(".");
|
|
2292
|
+
if (options?.allowPalletOnly) {
|
|
2293
|
+
switch (parts.length) {
|
|
2294
|
+
case 1:
|
|
2295
|
+
if (!parts[0]) {
|
|
2296
|
+
throw new Error(`Invalid target "${input}". Expected format: Pallet or Pallet.Item (e.g. System or System.Account)`);
|
|
2297
|
+
}
|
|
2298
|
+
return { pallet: parts[0] };
|
|
2299
|
+
case 2:
|
|
2300
|
+
if (!parts[0] || !parts[1]) {
|
|
2301
|
+
throw new Error(`Invalid target "${input}". Expected format: Pallet.Item or Chain.Pallet (e.g. System.Account or kusama.System)`);
|
|
2302
|
+
}
|
|
2303
|
+
if (options.knownChains?.some((c) => c.toLowerCase() === parts[0].toLowerCase())) {
|
|
2304
|
+
return { chain: parts[0], pallet: parts[1] };
|
|
2305
|
+
}
|
|
2306
|
+
return { pallet: parts[0], item: parts[1] };
|
|
2307
|
+
case 3:
|
|
2308
|
+
if (!parts[0] || !parts[1] || !parts[2]) {
|
|
2309
|
+
throw new Error(`Invalid target "${input}". Expected format: Chain.Pallet.Item (e.g. kusama.System.Account)`);
|
|
2310
|
+
}
|
|
2311
|
+
return { chain: parts[0], pallet: parts[1], item: parts[2] };
|
|
2312
|
+
default:
|
|
2313
|
+
throw new Error(`Invalid target "${input}". Expected format: Pallet, Pallet.Item, or Chain.Pallet.Item`);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
switch (parts.length) {
|
|
2317
|
+
case 2:
|
|
2318
|
+
if (!parts[0] || !parts[1]) {
|
|
2319
|
+
throw new Error(`Invalid target "${input}". Expected format: Pallet.Item (e.g. System.Account)`);
|
|
2320
|
+
}
|
|
2321
|
+
return { pallet: parts[0], item: parts[1] };
|
|
2322
|
+
case 3:
|
|
2323
|
+
if (!parts[0] || !parts[1] || !parts[2]) {
|
|
2324
|
+
throw new Error(`Invalid target "${input}". Expected format: Chain.Pallet.Item (e.g. kusama.System.Account)`);
|
|
2325
|
+
}
|
|
2326
|
+
return { chain: parts[0], pallet: parts[1], item: parts[2] };
|
|
2327
|
+
default:
|
|
2328
|
+
throw new Error(`Invalid target "${input}". Expected format: Pallet.Item (e.g. System.Account)`);
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
function resolveTargetChain(target, chainFlag) {
|
|
2332
|
+
if (target.chain && chainFlag) {
|
|
2333
|
+
throw new Error(`Chain specified both as prefix ("${target.chain}") and as --chain flag ("${chainFlag}"). Use one or the other.`);
|
|
2334
|
+
}
|
|
2335
|
+
return target.chain ?? chainFlag;
|
|
2336
|
+
}
|
|
2337
|
+
|
|
1867
2338
|
// src/commands/inspect.ts
|
|
1868
2339
|
function registerInspectCommand(cli) {
|
|
1869
|
-
cli.command("inspect [target]", "Inspect chain metadata (pallets, storage, constants, calls, events, errors)").option("--chain <name>", "Target chain").option("--rpc <url>", "Override RPC endpoint").action(async (target, opts) => {
|
|
2340
|
+
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) => {
|
|
1870
2341
|
const config = await loadConfig();
|
|
1871
2342
|
const knownChains = Object.keys(config.chains);
|
|
1872
2343
|
let effectiveChain = opts.chain;
|
|
@@ -2386,77 +2857,101 @@ var PAPI_BUILTIN_EXTENSIONS = new Set([
|
|
|
2386
2857
|
var NO_DEFAULT = Symbol("no-default");
|
|
2387
2858
|
|
|
2388
2859
|
// src/commands/query.ts
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2860
|
+
async function handleQuery(target, keys, opts) {
|
|
2861
|
+
if (!target) {
|
|
2862
|
+
const config2 = await loadConfig();
|
|
2863
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
2864
|
+
const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
2865
|
+
const pallets = listPallets(meta);
|
|
2866
|
+
const withStorage = pallets.filter((p) => p.storage.length > 0);
|
|
2867
|
+
printHeading(`Pallets with storage on ${chainName2} (${withStorage.length})`);
|
|
2868
|
+
for (const p of withStorage) {
|
|
2869
|
+
printItem(p.name, `${p.storage.length} storage items`);
|
|
2870
|
+
}
|
|
2871
|
+
console.log();
|
|
2872
|
+
return;
|
|
2873
|
+
}
|
|
2874
|
+
const dotIdx = target.indexOf(".");
|
|
2875
|
+
if (dotIdx === -1) {
|
|
2876
|
+
const config2 = await loadConfig();
|
|
2877
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
2878
|
+
const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
2879
|
+
const pallet2 = resolvePallet(meta, palletName(target));
|
|
2880
|
+
if (pallet2.storage.length === 0) {
|
|
2881
|
+
console.log(`No storage items in ${pallet2.name}.`);
|
|
2405
2882
|
return;
|
|
2406
2883
|
}
|
|
2407
|
-
|
|
2408
|
-
const
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
const meta = await getOrFetchMetadata(chainName, clientHandle);
|
|
2417
|
-
const palletNames = getPalletNames(meta);
|
|
2418
|
-
const palletInfo = findPallet(meta, pallet);
|
|
2419
|
-
if (!palletInfo) {
|
|
2420
|
-
throw new Error(suggestMessage("pallet", pallet, palletNames));
|
|
2884
|
+
printHeading(`${pallet2.name} Storage`);
|
|
2885
|
+
for (const s of pallet2.storage) {
|
|
2886
|
+
const valueType = describeType(meta.lookup, s.valueTypeId);
|
|
2887
|
+
let typeSuffix;
|
|
2888
|
+
if (s.keyTypeId != null) {
|
|
2889
|
+
const keyType = describeType(meta.lookup, s.keyTypeId);
|
|
2890
|
+
typeSuffix = `: ${keyType} → ${valueType} [map]`;
|
|
2891
|
+
} else {
|
|
2892
|
+
typeSuffix = `: ${valueType}`;
|
|
2421
2893
|
}
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
}
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2894
|
+
console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
|
|
2895
|
+
const summary = firstSentence(s.docs);
|
|
2896
|
+
if (summary) {
|
|
2897
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
2898
|
+
}
|
|
2899
|
+
}
|
|
2900
|
+
console.log();
|
|
2901
|
+
return;
|
|
2902
|
+
}
|
|
2903
|
+
const pallet = target.slice(0, dotIdx);
|
|
2904
|
+
const item = target.slice(dotIdx + 1);
|
|
2905
|
+
const config = await loadConfig();
|
|
2906
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
|
|
2907
|
+
const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
|
|
2908
|
+
try {
|
|
2909
|
+
const meta = await getOrFetchMetadata(chainName, clientHandle);
|
|
2910
|
+
const palletNames = getPalletNames(meta);
|
|
2911
|
+
const palletInfo = findPallet(meta, pallet);
|
|
2912
|
+
if (!palletInfo) {
|
|
2913
|
+
throw new Error(suggestMessage("pallet", pallet, palletNames));
|
|
2914
|
+
}
|
|
2915
|
+
const storageItem = palletInfo.storage.find((s) => s.name.toLowerCase() === item.toLowerCase());
|
|
2916
|
+
if (!storageItem) {
|
|
2917
|
+
const storageNames = palletInfo.storage.map((s) => s.name);
|
|
2918
|
+
throw new Error(suggestMessage(`storage item in ${palletInfo.name}`, item, storageNames));
|
|
2919
|
+
}
|
|
2920
|
+
const unsafeApi = clientHandle.client.getUnsafeApi();
|
|
2921
|
+
const storageApi = unsafeApi.query[palletInfo.name][storageItem.name];
|
|
2922
|
+
const parsedKeys = parseStorageKeys(meta, palletInfo.name, storageItem, keys);
|
|
2923
|
+
const format = opts.output ?? "pretty";
|
|
2924
|
+
if (storageItem.type === "map" && parsedKeys.length === 0) {
|
|
2925
|
+
const entries = await storageApi.getEntries();
|
|
2926
|
+
const limit = Number(opts.limit);
|
|
2927
|
+
const truncated = limit > 0 && entries.length > limit;
|
|
2928
|
+
const display = truncated ? entries.slice(0, limit) : entries;
|
|
2929
|
+
printResult(display.map((e) => ({
|
|
2930
|
+
keys: e.keyArgs,
|
|
2931
|
+
value: e.value
|
|
2932
|
+
})), format);
|
|
2933
|
+
if (truncated) {
|
|
2934
|
+
console.error(`
|
|
2442
2935
|
${DIM}Showing ${limit} of ${entries.length} entries. Use --limit 0 for all.${RESET}`);
|
|
2443
|
-
}
|
|
2444
|
-
} else {
|
|
2445
|
-
const result = await storageApi.getValue(...parsedKeys);
|
|
2446
|
-
printResult(result, format);
|
|
2447
2936
|
}
|
|
2448
|
-
}
|
|
2449
|
-
|
|
2937
|
+
} else {
|
|
2938
|
+
const result = await storageApi.getValue(...parsedKeys);
|
|
2939
|
+
printResult(result, format);
|
|
2450
2940
|
}
|
|
2451
|
-
}
|
|
2941
|
+
} finally {
|
|
2942
|
+
clientHandle.destroy();
|
|
2943
|
+
}
|
|
2944
|
+
}
|
|
2945
|
+
function palletName(name) {
|
|
2946
|
+
return name;
|
|
2452
2947
|
}
|
|
2453
|
-
function parseStorageKeys(meta,
|
|
2948
|
+
function parseStorageKeys(meta, palletName2, storageItem, args) {
|
|
2454
2949
|
if (storageItem.type === "plain" || storageItem.keyTypeId == null) {
|
|
2455
2950
|
return args.map(parseValue);
|
|
2456
2951
|
}
|
|
2457
2952
|
if (args.length === 0)
|
|
2458
2953
|
return [];
|
|
2459
|
-
const storageEntry = meta.builder.buildStorage(
|
|
2954
|
+
const storageEntry = meta.builder.buildStorage(palletName2, storageItem.name);
|
|
2460
2955
|
const len = storageEntry.len;
|
|
2461
2956
|
const keyEntry = meta.lookup(storageItem.keyTypeId);
|
|
2462
2957
|
if (len === 1) {
|
|
@@ -2464,11 +2959,11 @@ function parseStorageKeys(meta, palletName, storageItem, args) {
|
|
|
2464
2959
|
return [parseTypedArg(meta, keyEntry, args[0])];
|
|
2465
2960
|
}
|
|
2466
2961
|
if (keyEntry.type === "struct") {
|
|
2467
|
-
const label = `${
|
|
2962
|
+
const label = `${palletName2}.${storageItem.name} key`;
|
|
2468
2963
|
return [parseStructArgs(meta, keyEntry.value, args, label)];
|
|
2469
2964
|
}
|
|
2470
2965
|
const typeDesc = describeType(meta.lookup, storageItem.keyTypeId);
|
|
2471
|
-
throw new Error(`${
|
|
2966
|
+
throw new Error(`${palletName2}.${storageItem.name} key expects ${typeDesc}
|
|
2472
2967
|
` + ` Pass 1 argument. Got ${args.length}.`);
|
|
2473
2968
|
}
|
|
2474
2969
|
if (args.length !== len) {
|
|
@@ -2478,7 +2973,7 @@ function parseStorageKeys(meta, palletName, storageItem, args) {
|
|
|
2478
2973
|
} else {
|
|
2479
2974
|
typeDesc = describeType(meta.lookup, storageItem.keyTypeId);
|
|
2480
2975
|
}
|
|
2481
|
-
throw new Error(`${
|
|
2976
|
+
throw new Error(`${palletName2}.${storageItem.name} expects ${len} key arg(s): (${typeDesc}). Got ${args.length}.`);
|
|
2482
2977
|
}
|
|
2483
2978
|
if (keyEntry.type === "tuple") {
|
|
2484
2979
|
const entries = keyEntry.value;
|
|
@@ -2490,156 +2985,180 @@ function parseStorageKeys(meta, palletName, storageItem, args) {
|
|
|
2490
2985
|
// src/commands/tx.ts
|
|
2491
2986
|
import { getViewBuilder as getViewBuilder2 } from "@polkadot-api/view-builder";
|
|
2492
2987
|
import { Binary as Binary3 } from "polkadot-api";
|
|
2493
|
-
function
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
console.log(" $ dot tx kusama.Balances.transferKeepAlive 5FHn... 1000000000000 --from alice");
|
|
2504
|
-
return;
|
|
2988
|
+
async function handleTx(target, args, opts) {
|
|
2989
|
+
if (!target) {
|
|
2990
|
+
const config2 = await loadConfig();
|
|
2991
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
2992
|
+
const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
2993
|
+
const pallets = listPallets(meta);
|
|
2994
|
+
const withCalls = pallets.filter((p) => p.calls.length > 0);
|
|
2995
|
+
printHeading(`Pallets with calls on ${chainName2} (${withCalls.length})`);
|
|
2996
|
+
for (const p of withCalls) {
|
|
2997
|
+
printItem(p.name, `${p.calls.length} calls`);
|
|
2505
2998
|
}
|
|
2506
|
-
|
|
2507
|
-
|
|
2999
|
+
console.log();
|
|
3000
|
+
return;
|
|
3001
|
+
}
|
|
3002
|
+
const isRawCall = /^0x[0-9a-fA-F]+$/.test(target);
|
|
3003
|
+
if (!isRawCall && target.indexOf(".") === -1) {
|
|
3004
|
+
const config2 = await loadConfig();
|
|
3005
|
+
const { name: chainName2, chain: chainConfig2 } = resolveChain(config2, opts.chain);
|
|
3006
|
+
const meta = await loadMeta(chainName2, chainConfig2, opts.rpc);
|
|
3007
|
+
const pallet2 = resolvePallet(meta, target);
|
|
3008
|
+
if (pallet2.calls.length === 0) {
|
|
3009
|
+
console.log(`No calls in ${pallet2.name}.`);
|
|
3010
|
+
return;
|
|
2508
3011
|
}
|
|
2509
|
-
|
|
2510
|
-
|
|
3012
|
+
printHeading(`${pallet2.name} Calls`);
|
|
3013
|
+
for (const c of pallet2.calls) {
|
|
3014
|
+
const callArgs = describeCallArgs(meta, pallet2.name, c.name);
|
|
3015
|
+
console.log(` ${CYAN}${c.name}${RESET}${DIM}${callArgs}${RESET}`);
|
|
3016
|
+
const summary = firstSentence(c.docs);
|
|
3017
|
+
if (summary) {
|
|
3018
|
+
console.log(` ${DIM}${summary}${RESET}`);
|
|
3019
|
+
}
|
|
2511
3020
|
}
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
3021
|
+
console.log();
|
|
3022
|
+
return;
|
|
3023
|
+
}
|
|
3024
|
+
if (!opts.from && !opts.encode) {
|
|
3025
|
+
if (isRawCall) {
|
|
3026
|
+
throw new Error("--from is required (or use --encode to output hex without signing)");
|
|
2515
3027
|
}
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
3028
|
+
await showItemHelp("tx", target, opts);
|
|
3029
|
+
return;
|
|
3030
|
+
}
|
|
3031
|
+
if (opts.encode && opts.dryRun) {
|
|
3032
|
+
throw new Error("--encode and --dry-run are mutually exclusive");
|
|
3033
|
+
}
|
|
3034
|
+
if (opts.encode && isRawCall) {
|
|
3035
|
+
throw new Error("--encode cannot be used with raw call hex (already encoded)");
|
|
3036
|
+
}
|
|
3037
|
+
const config = await loadConfig();
|
|
3038
|
+
const effectiveChain = opts.chain;
|
|
3039
|
+
let pallet;
|
|
3040
|
+
let callName;
|
|
3041
|
+
if (!isRawCall) {
|
|
3042
|
+
const dotIdx = target.indexOf(".");
|
|
3043
|
+
pallet = target.slice(0, dotIdx);
|
|
3044
|
+
callName = target.slice(dotIdx + 1);
|
|
3045
|
+
}
|
|
3046
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, effectiveChain);
|
|
3047
|
+
const signer = opts.encode ? undefined : await resolveAccountSigner(opts.from);
|
|
3048
|
+
let clientHandle;
|
|
3049
|
+
if (!opts.encode) {
|
|
3050
|
+
clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
|
|
3051
|
+
}
|
|
3052
|
+
try {
|
|
3053
|
+
let meta;
|
|
3054
|
+
if (clientHandle) {
|
|
3055
|
+
meta = await getOrFetchMetadata(chainName, clientHandle);
|
|
3056
|
+
} else {
|
|
3057
|
+
try {
|
|
3058
|
+
meta = await getOrFetchMetadata(chainName);
|
|
3059
|
+
} catch {
|
|
3060
|
+
clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
|
|
3061
|
+
meta = await getOrFetchMetadata(chainName, clientHandle);
|
|
3062
|
+
}
|
|
2523
3063
|
}
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
let clientHandle;
|
|
3064
|
+
let unsafeApi;
|
|
3065
|
+
let txOptions;
|
|
2527
3066
|
if (!opts.encode) {
|
|
2528
|
-
|
|
3067
|
+
const userExtOverrides = parseExtOption(opts.ext);
|
|
3068
|
+
const customSignedExtensions = buildCustomSignedExtensions(meta, userExtOverrides);
|
|
3069
|
+
txOptions = Object.keys(customSignedExtensions).length > 0 ? { customSignedExtensions } : undefined;
|
|
3070
|
+
unsafeApi = clientHandle?.client.getUnsafeApi();
|
|
2529
3071
|
}
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
try {
|
|
2536
|
-
meta = await getOrFetchMetadata(chainName);
|
|
2537
|
-
} catch {
|
|
2538
|
-
clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
|
|
2539
|
-
meta = await getOrFetchMetadata(chainName, clientHandle);
|
|
2540
|
-
}
|
|
2541
|
-
}
|
|
2542
|
-
let unsafeApi;
|
|
2543
|
-
let txOptions;
|
|
2544
|
-
if (!opts.encode) {
|
|
2545
|
-
const userExtOverrides = parseExtOption(opts.ext);
|
|
2546
|
-
const customSignedExtensions = buildCustomSignedExtensions(meta, userExtOverrides);
|
|
2547
|
-
txOptions = Object.keys(customSignedExtensions).length > 0 ? { customSignedExtensions } : undefined;
|
|
2548
|
-
unsafeApi = clientHandle?.client.getUnsafeApi();
|
|
2549
|
-
}
|
|
2550
|
-
let tx;
|
|
2551
|
-
let callHex;
|
|
2552
|
-
if (isRawCall) {
|
|
2553
|
-
if (args.length > 0) {
|
|
2554
|
-
throw new Error(`Extra arguments are not allowed when submitting a raw call hex.
|
|
3072
|
+
let tx;
|
|
3073
|
+
let callHex;
|
|
3074
|
+
if (isRawCall) {
|
|
3075
|
+
if (args.length > 0) {
|
|
3076
|
+
throw new Error(`Extra arguments are not allowed when submitting a raw call hex.
|
|
2555
3077
|
` + "Usage: dot tx 0x<call_hex> --from <account>");
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
const
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
const
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2577
|
-
const fullCall = new Uint8Array([location[0], location[1], ...encodedArgs]);
|
|
2578
|
-
console.log(Binary3.fromBytes(fullCall).asHex());
|
|
2579
|
-
return;
|
|
2580
|
-
}
|
|
2581
|
-
tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
|
|
2582
|
-
const encodedCall = await tx.getEncodedData();
|
|
2583
|
-
callHex = encodedCall.asHex();
|
|
2584
|
-
}
|
|
2585
|
-
const decodedStr = decodeCall(meta, callHex);
|
|
2586
|
-
if (opts.dryRun) {
|
|
2587
|
-
const signerAddress = toSs58(signer.publicKey);
|
|
2588
|
-
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
2589
|
-
console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
|
|
2590
|
-
console.log(` ${BOLD}Call:${RESET} ${callHex}`);
|
|
2591
|
-
console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
|
|
2592
|
-
try {
|
|
2593
|
-
const fees = await tx.getEstimatedFees(signer?.publicKey, txOptions);
|
|
2594
|
-
console.log(` ${BOLD}Estimated fees:${RESET} ${fees}`);
|
|
2595
|
-
} catch (err) {
|
|
2596
|
-
console.log(` ${BOLD}Estimated fees:${RESET} ${YELLOW}unable to estimate${RESET}`);
|
|
2597
|
-
console.log(` ${DIM}${err.message ?? err}${RESET}`);
|
|
2598
|
-
}
|
|
3078
|
+
}
|
|
3079
|
+
const callBinary = Binary3.fromHex(target);
|
|
3080
|
+
tx = await unsafeApi.txFromCallData(callBinary);
|
|
3081
|
+
callHex = target;
|
|
3082
|
+
} else {
|
|
3083
|
+
const palletNames = getPalletNames(meta);
|
|
3084
|
+
const palletInfo = findPallet(meta, pallet);
|
|
3085
|
+
if (!palletInfo) {
|
|
3086
|
+
throw new Error(suggestMessage("pallet", pallet, palletNames));
|
|
3087
|
+
}
|
|
3088
|
+
const callInfo = palletInfo.calls.find((c) => c.name.toLowerCase() === callName.toLowerCase());
|
|
3089
|
+
if (!callInfo) {
|
|
3090
|
+
const callNames = palletInfo.calls.map((c) => c.name);
|
|
3091
|
+
throw new Error(suggestMessage(`call in ${palletInfo.name}`, callName, callNames));
|
|
3092
|
+
}
|
|
3093
|
+
const callData = parseCallArgs(meta, palletInfo.name, callInfo.name, args);
|
|
3094
|
+
if (opts.encode) {
|
|
3095
|
+
const { codec, location } = meta.builder.buildCall(palletInfo.name, callInfo.name);
|
|
3096
|
+
const encodedArgs = codec.enc(callData);
|
|
3097
|
+
const fullCall = new Uint8Array([location[0], location[1], ...encodedArgs]);
|
|
3098
|
+
console.log(Binary3.fromBytes(fullCall).asHex());
|
|
2599
3099
|
return;
|
|
2600
3100
|
}
|
|
2601
|
-
|
|
2602
|
-
|
|
3101
|
+
tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
|
|
3102
|
+
const encodedCall = await tx.getEncodedData();
|
|
3103
|
+
callHex = encodedCall.asHex();
|
|
3104
|
+
}
|
|
3105
|
+
const decodedStr = decodeCall(meta, callHex);
|
|
3106
|
+
if (opts.dryRun) {
|
|
3107
|
+
const signerAddress = toSs58(signer.publicKey);
|
|
2603
3108
|
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
3109
|
+
console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
|
|
2604
3110
|
console.log(` ${BOLD}Call:${RESET} ${callHex}`);
|
|
2605
3111
|
console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
|
|
2606
|
-
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
console.log(` ${BOLD}Status:${RESET} ${RED}dispatch error${RESET}`);
|
|
2613
|
-
console.log(` ${BOLD}Error:${RESET} ${dispatchErrorMsg}`);
|
|
3112
|
+
try {
|
|
3113
|
+
const fees = await tx.getEstimatedFees(signer?.publicKey, txOptions);
|
|
3114
|
+
console.log(` ${BOLD}Estimated fees:${RESET} ${fees}`);
|
|
3115
|
+
} catch (err) {
|
|
3116
|
+
console.log(` ${BOLD}Estimated fees:${RESET} ${YELLOW}unable to estimate${RESET}`);
|
|
3117
|
+
console.log(` ${DIM}${err.message ?? err}${RESET}`);
|
|
2614
3118
|
}
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
3119
|
+
return;
|
|
3120
|
+
}
|
|
3121
|
+
const result = await watchTransaction(tx.signSubmitAndWatch(signer, txOptions));
|
|
3122
|
+
console.log();
|
|
3123
|
+
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
3124
|
+
console.log(` ${BOLD}Call:${RESET} ${callHex}`);
|
|
3125
|
+
console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
|
|
3126
|
+
console.log(` ${BOLD}Tx:${RESET} ${result.txHash}`);
|
|
3127
|
+
let dispatchErrorMsg;
|
|
3128
|
+
if (result.ok) {
|
|
3129
|
+
console.log(` ${BOLD}Status:${RESET} ${GREEN}ok${RESET}`);
|
|
3130
|
+
} else {
|
|
3131
|
+
dispatchErrorMsg = formatDispatchError(result.dispatchError);
|
|
3132
|
+
console.log(` ${BOLD}Status:${RESET} ${RED}dispatch error${RESET}`);
|
|
3133
|
+
console.log(` ${BOLD}Error:${RESET} ${dispatchErrorMsg}`);
|
|
3134
|
+
}
|
|
3135
|
+
if (result.events && result.events.length > 0) {
|
|
3136
|
+
console.log(` ${BOLD}Events:${RESET}`);
|
|
3137
|
+
for (const event of result.events) {
|
|
3138
|
+
const name = `${CYAN}${event.type}${RESET}.${CYAN}${event.value?.type ?? ""}${RESET}`;
|
|
3139
|
+
const payload = event.value?.value;
|
|
3140
|
+
if (payload && typeof payload === "object") {
|
|
3141
|
+
const fields = Object.entries(payload).map(([k, v]) => `${k}: ${formatEventValue(v)}`).join(", ");
|
|
3142
|
+
console.log(` ${name} { ${fields} }`);
|
|
3143
|
+
} else {
|
|
3144
|
+
console.log(` ${name}`);
|
|
2626
3145
|
}
|
|
2627
3146
|
}
|
|
2628
|
-
const rpcUrl = primaryRpc(opts.rpc ?? chainConfig.rpc);
|
|
2629
|
-
if (rpcUrl) {
|
|
2630
|
-
const blockHash = result.block.hash;
|
|
2631
|
-
console.log(` ${BOLD}Explorer:${RESET}`);
|
|
2632
|
-
console.log(` ${DIM}PolkadotJS${RESET} ${pjsAppsLink(rpcUrl, blockHash)}`);
|
|
2633
|
-
console.log(` ${DIM}PAPI${RESET} ${papiLink(rpcUrl, blockHash)}`);
|
|
2634
|
-
}
|
|
2635
|
-
console.log();
|
|
2636
|
-
if (!result.ok) {
|
|
2637
|
-
throw new CliError(`Transaction dispatch error: ${dispatchErrorMsg}`);
|
|
2638
|
-
}
|
|
2639
|
-
} finally {
|
|
2640
|
-
clientHandle?.destroy();
|
|
2641
3147
|
}
|
|
2642
|
-
|
|
3148
|
+
const rpcUrl = primaryRpc(opts.rpc ?? chainConfig.rpc);
|
|
3149
|
+
if (rpcUrl) {
|
|
3150
|
+
const blockHash = result.block.hash;
|
|
3151
|
+
console.log(` ${BOLD}Explorer:${RESET}`);
|
|
3152
|
+
console.log(` ${DIM}PolkadotJS${RESET} ${pjsAppsLink(rpcUrl, blockHash)}`);
|
|
3153
|
+
console.log(` ${DIM}PAPI${RESET} ${papiLink(rpcUrl, blockHash)}`);
|
|
3154
|
+
}
|
|
3155
|
+
console.log();
|
|
3156
|
+
if (!result.ok) {
|
|
3157
|
+
throw new CliError(`Transaction dispatch error: ${dispatchErrorMsg}`);
|
|
3158
|
+
}
|
|
3159
|
+
} finally {
|
|
3160
|
+
clientHandle?.destroy();
|
|
3161
|
+
}
|
|
2643
3162
|
}
|
|
2644
3163
|
function formatDispatchError(err) {
|
|
2645
3164
|
if (err.type === "Module" && err.value && typeof err.value === "object") {
|
|
@@ -2662,10 +3181,10 @@ function decodeCall(meta, callHex) {
|
|
|
2662
3181
|
try {
|
|
2663
3182
|
const viewBuilder = getViewBuilder2(meta.lookup);
|
|
2664
3183
|
const decoded = viewBuilder.callDecoder(callHex);
|
|
2665
|
-
const
|
|
3184
|
+
const palletName2 = decoded.pallet.value.name;
|
|
2666
3185
|
const callName = decoded.call.value.name;
|
|
2667
3186
|
const argsStr = formatDecodedArgs(decoded.args.value);
|
|
2668
|
-
return `${
|
|
3187
|
+
return `${palletName2}.${callName}${argsStr}`;
|
|
2669
3188
|
} catch {}
|
|
2670
3189
|
try {
|
|
2671
3190
|
return decodeCallFallback(meta, callHex);
|
|
@@ -2679,15 +3198,15 @@ function decodeCallFallback(meta, callHex) {
|
|
|
2679
3198
|
throw new Error("No RuntimeCall type ID");
|
|
2680
3199
|
const codec = meta.builder.buildDefinition(callTypeId);
|
|
2681
3200
|
const decoded = codec.dec(Binary3.fromHex(callHex).asBytes());
|
|
2682
|
-
const
|
|
3201
|
+
const palletName2 = decoded.type;
|
|
2683
3202
|
const call = decoded.value;
|
|
2684
3203
|
const callName = call.type;
|
|
2685
3204
|
const args = call.value;
|
|
2686
3205
|
if (args === undefined || args === null) {
|
|
2687
|
-
return `${
|
|
3206
|
+
return `${palletName2}.${callName}`;
|
|
2688
3207
|
}
|
|
2689
3208
|
const argsStr = formatRawDecoded(args);
|
|
2690
|
-
return `${
|
|
3209
|
+
return `${palletName2}.${callName} ${argsStr}`;
|
|
2691
3210
|
}
|
|
2692
3211
|
function formatRawDecoded(value) {
|
|
2693
3212
|
if (value === undefined || value === null)
|
|
@@ -2820,8 +3339,8 @@ function formatEventValue(v) {
|
|
|
2820
3339
|
}
|
|
2821
3340
|
return JSON.stringify(v, (_k, val) => typeof val === "bigint" ? val.toString() : val);
|
|
2822
3341
|
}
|
|
2823
|
-
function parseCallArgs(meta,
|
|
2824
|
-
const palletMeta = meta.unified.pallets.find((p) => p.name ===
|
|
3342
|
+
function parseCallArgs(meta, palletName2, callName, args) {
|
|
3343
|
+
const palletMeta = meta.unified.pallets.find((p) => p.name === palletName2);
|
|
2825
3344
|
if (!palletMeta?.calls)
|
|
2826
3345
|
return;
|
|
2827
3346
|
const callsEntry = meta.lookup(palletMeta.calls.type);
|
|
@@ -2832,22 +3351,22 @@ function parseCallArgs(meta, palletName, callName, args) {
|
|
|
2832
3351
|
return;
|
|
2833
3352
|
if (variant.type === "void") {
|
|
2834
3353
|
if (args.length > 0) {
|
|
2835
|
-
throw new Error(`${
|
|
3354
|
+
throw new Error(`${palletName2}.${callName} takes no arguments, but ${args.length} provided.`);
|
|
2836
3355
|
}
|
|
2837
3356
|
return;
|
|
2838
3357
|
}
|
|
2839
3358
|
if (variant.type === "struct") {
|
|
2840
|
-
return parseStructArgs2(meta, variant.value, args, `${
|
|
3359
|
+
return parseStructArgs2(meta, variant.value, args, `${palletName2}.${callName}`);
|
|
2841
3360
|
}
|
|
2842
3361
|
if (variant.type === "lookupEntry") {
|
|
2843
3362
|
const inner = variant.value;
|
|
2844
3363
|
if (inner.type === "struct") {
|
|
2845
|
-
return parseStructArgs2(meta, inner.value, args, `${
|
|
3364
|
+
return parseStructArgs2(meta, inner.value, args, `${palletName2}.${callName}`);
|
|
2846
3365
|
}
|
|
2847
3366
|
if (inner.type === "void")
|
|
2848
3367
|
return;
|
|
2849
3368
|
if (args.length !== 1) {
|
|
2850
|
-
throw new Error(`${
|
|
3369
|
+
throw new Error(`${palletName2}.${callName} takes 1 argument (${describeType(meta.lookup, inner.id)}), but ${args.length} provided.`);
|
|
2851
3370
|
}
|
|
2852
3371
|
try {
|
|
2853
3372
|
return parseTypedArg2(meta, inner, args[0]);
|
|
@@ -2859,7 +3378,7 @@ function parseCallArgs(meta, palletName, callName, args) {
|
|
|
2859
3378
|
if (variant.type === "tuple") {
|
|
2860
3379
|
const entries = variant.value;
|
|
2861
3380
|
if (args.length !== entries.length) {
|
|
2862
|
-
throw new Error(`${
|
|
3381
|
+
throw new Error(`${palletName2}.${callName} takes ${entries.length} arguments, but ${args.length} provided.`);
|
|
2863
3382
|
}
|
|
2864
3383
|
return entries.map((entry, i) => {
|
|
2865
3384
|
try {
|
|
@@ -3252,10 +3771,46 @@ function watchTransaction(observable) {
|
|
|
3252
3771
|
});
|
|
3253
3772
|
}
|
|
3254
3773
|
|
|
3774
|
+
// src/config/store.ts
|
|
3775
|
+
import { access as access3, mkdir as mkdir3, readFile as readFile3, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
|
|
3776
|
+
import { homedir as homedir2 } from "node:os";
|
|
3777
|
+
import { join as join3 } from "node:path";
|
|
3778
|
+
var DOT_DIR2 = join3(homedir2(), ".polkadot");
|
|
3779
|
+
var CONFIG_PATH2 = join3(DOT_DIR2, "config.json");
|
|
3780
|
+
var CHAINS_DIR2 = join3(DOT_DIR2, "chains");
|
|
3781
|
+
async function ensureDir3(dir) {
|
|
3782
|
+
await mkdir3(dir, { recursive: true });
|
|
3783
|
+
}
|
|
3784
|
+
async function fileExists3(path) {
|
|
3785
|
+
try {
|
|
3786
|
+
await access3(path);
|
|
3787
|
+
return true;
|
|
3788
|
+
} catch {
|
|
3789
|
+
return false;
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3792
|
+
async function loadConfig2() {
|
|
3793
|
+
await ensureDir3(DOT_DIR2);
|
|
3794
|
+
if (await fileExists3(CONFIG_PATH2)) {
|
|
3795
|
+
const saved = JSON.parse(await readFile3(CONFIG_PATH2, "utf-8"));
|
|
3796
|
+
return {
|
|
3797
|
+
...saved,
|
|
3798
|
+
chains: { ...DEFAULT_CONFIG.chains, ...saved.chains }
|
|
3799
|
+
};
|
|
3800
|
+
}
|
|
3801
|
+
await saveConfig2(DEFAULT_CONFIG);
|
|
3802
|
+
return DEFAULT_CONFIG;
|
|
3803
|
+
}
|
|
3804
|
+
async function saveConfig2(config) {
|
|
3805
|
+
await ensureDir3(DOT_DIR2);
|
|
3806
|
+
await writeFile3(CONFIG_PATH2, `${JSON.stringify(config, null, 2)}
|
|
3807
|
+
`);
|
|
3808
|
+
}
|
|
3809
|
+
|
|
3255
3810
|
// src/core/update-notifier.ts
|
|
3256
3811
|
import { readFileSync } from "node:fs";
|
|
3257
|
-
import { mkdir as
|
|
3258
|
-
import { join as
|
|
3812
|
+
import { mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
|
|
3813
|
+
import { join as join4 } from "node:path";
|
|
3259
3814
|
var CACHE_FILE = "update-check.json";
|
|
3260
3815
|
var STALE_MS = 24 * 60 * 60 * 1000;
|
|
3261
3816
|
var FETCH_TIMEOUT_MS = 5000;
|
|
@@ -3311,7 +3866,7 @@ function buildNotificationBox(current, latest) {
|
|
|
3311
3866
|
`);
|
|
3312
3867
|
}
|
|
3313
3868
|
function getCachePath() {
|
|
3314
|
-
return
|
|
3869
|
+
return join4(getConfigDir(), CACHE_FILE);
|
|
3315
3870
|
}
|
|
3316
3871
|
function readCache() {
|
|
3317
3872
|
try {
|
|
@@ -3323,8 +3878,8 @@ function readCache() {
|
|
|
3323
3878
|
}
|
|
3324
3879
|
async function writeCache(cache) {
|
|
3325
3880
|
try {
|
|
3326
|
-
await
|
|
3327
|
-
await
|
|
3881
|
+
await mkdir4(getConfigDir(), { recursive: true });
|
|
3882
|
+
await writeFile4(getCachePath(), `${JSON.stringify(cache)}
|
|
3328
3883
|
`);
|
|
3329
3884
|
} catch {}
|
|
3330
3885
|
}
|
|
@@ -3379,6 +3934,67 @@ class CliError2 extends Error {
|
|
|
3379
3934
|
}
|
|
3380
3935
|
}
|
|
3381
3936
|
|
|
3937
|
+
// src/utils/parse-dot-path.ts
|
|
3938
|
+
var CATEGORY_ALIASES = {
|
|
3939
|
+
query: "query",
|
|
3940
|
+
tx: "tx",
|
|
3941
|
+
const: "const",
|
|
3942
|
+
consts: "const",
|
|
3943
|
+
constants: "const",
|
|
3944
|
+
events: "events",
|
|
3945
|
+
event: "events",
|
|
3946
|
+
errors: "errors",
|
|
3947
|
+
error: "errors"
|
|
3948
|
+
};
|
|
3949
|
+
function matchCategory(segment) {
|
|
3950
|
+
return CATEGORY_ALIASES[segment.toLowerCase()];
|
|
3951
|
+
}
|
|
3952
|
+
function matchChain(segment, knownChains) {
|
|
3953
|
+
return knownChains.some((c) => c.toLowerCase() === segment.toLowerCase());
|
|
3954
|
+
}
|
|
3955
|
+
function parseDotPath(input, knownChains = []) {
|
|
3956
|
+
const parts = input.split(".");
|
|
3957
|
+
switch (parts.length) {
|
|
3958
|
+
case 1: {
|
|
3959
|
+
const cat = matchCategory(parts[0]);
|
|
3960
|
+
if (cat)
|
|
3961
|
+
return { category: cat };
|
|
3962
|
+
throw new Error(`Unknown command "${parts[0]}". Expected a category (query, tx, const, events, errors) or a named command.`);
|
|
3963
|
+
}
|
|
3964
|
+
case 2: {
|
|
3965
|
+
const cat = matchCategory(parts[0]);
|
|
3966
|
+
if (cat) {
|
|
3967
|
+
return { category: cat, pallet: parts[1] };
|
|
3968
|
+
}
|
|
3969
|
+
const cat2 = matchCategory(parts[1]);
|
|
3970
|
+
if (cat2 && matchChain(parts[0], knownChains)) {
|
|
3971
|
+
return { chain: parts[0], category: cat2 };
|
|
3972
|
+
}
|
|
3973
|
+
throw new Error(`Unknown command "${input}". Expected format: category.Pallet or Chain.category (e.g. query.System or polkadot.query)`);
|
|
3974
|
+
}
|
|
3975
|
+
case 3: {
|
|
3976
|
+
const cat = matchCategory(parts[0]);
|
|
3977
|
+
if (cat) {
|
|
3978
|
+
return { category: cat, pallet: parts[1], item: parts[2] };
|
|
3979
|
+
}
|
|
3980
|
+
const cat2 = matchCategory(parts[1]);
|
|
3981
|
+
if (cat2 && matchChain(parts[0], knownChains)) {
|
|
3982
|
+
return { chain: parts[0], category: cat2, pallet: parts[2] };
|
|
3983
|
+
}
|
|
3984
|
+
throw new Error(`Unknown command "${input}". Expected format: category.Pallet.Item or Chain.category.Pallet`);
|
|
3985
|
+
}
|
|
3986
|
+
case 4: {
|
|
3987
|
+
const cat = matchCategory(parts[1]);
|
|
3988
|
+
if (cat && matchChain(parts[0], knownChains)) {
|
|
3989
|
+
return { chain: parts[0], category: cat, pallet: parts[2], item: parts[3] };
|
|
3990
|
+
}
|
|
3991
|
+
throw new Error(`Unknown command "${input}". Expected format: Chain.category.Pallet.Item (e.g. polkadot.query.System.Account)`);
|
|
3992
|
+
}
|
|
3993
|
+
default:
|
|
3994
|
+
throw new Error(`Unknown command "${input}". Too many segments. Expected format: [Chain.]category[.Pallet[.Item]]`);
|
|
3995
|
+
}
|
|
3996
|
+
}
|
|
3997
|
+
|
|
3382
3998
|
// src/cli.ts
|
|
3383
3999
|
startBackgroundCheck(version);
|
|
3384
4000
|
var cli = cac("dot");
|
|
@@ -3390,14 +4006,105 @@ cli.option("--output <format>", "Output format: pretty or json", {
|
|
|
3390
4006
|
});
|
|
3391
4007
|
registerChainCommands(cli);
|
|
3392
4008
|
registerInspectCommand(cli);
|
|
3393
|
-
registerQueryCommand(cli);
|
|
3394
|
-
registerConstCommand(cli);
|
|
3395
|
-
registerFocusedInspectCommands(cli);
|
|
3396
4009
|
registerAccountCommands(cli);
|
|
3397
|
-
registerTxCommand(cli);
|
|
3398
4010
|
registerHashCommand(cli);
|
|
4011
|
+
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)", {
|
|
4012
|
+
default: 100
|
|
4013
|
+
}).action(async (dotpath, args, opts) => {
|
|
4014
|
+
if (!dotpath) {
|
|
4015
|
+
printHelp();
|
|
4016
|
+
return;
|
|
4017
|
+
}
|
|
4018
|
+
const config = await loadConfig2();
|
|
4019
|
+
const knownChains = Object.keys(config.chains);
|
|
4020
|
+
let parsed;
|
|
4021
|
+
try {
|
|
4022
|
+
parsed = parseDotPath(dotpath, knownChains);
|
|
4023
|
+
} catch {
|
|
4024
|
+
throw new CliError2(`Unknown command "${dotpath}". Run "dot --help" for available commands.`);
|
|
4025
|
+
}
|
|
4026
|
+
if (parsed.chain && opts.chain) {
|
|
4027
|
+
throw new CliError2(`Chain specified both as prefix ("${parsed.chain}") and as --chain flag ("${opts.chain}"). Use one or the other.`);
|
|
4028
|
+
}
|
|
4029
|
+
const effectiveChain = parsed.chain ?? opts.chain;
|
|
4030
|
+
const handlerOpts = { chain: effectiveChain, rpc: opts.rpc, output: opts.output };
|
|
4031
|
+
const target = parsed.pallet ? parsed.item ? `${parsed.pallet}.${parsed.item}` : parsed.pallet : undefined;
|
|
4032
|
+
if (cli.options.help && parsed.pallet && parsed.item) {
|
|
4033
|
+
await showItemHelp2(parsed.category, target, handlerOpts);
|
|
4034
|
+
return;
|
|
4035
|
+
}
|
|
4036
|
+
switch (parsed.category) {
|
|
4037
|
+
case "query":
|
|
4038
|
+
await handleQuery(target, args, { ...handlerOpts, limit: opts.limit });
|
|
4039
|
+
break;
|
|
4040
|
+
case "tx":
|
|
4041
|
+
if (parsed.pallet && /^0x[0-9a-fA-F]+$/.test(parsed.pallet)) {
|
|
4042
|
+
await handleTx(parsed.pallet, args, {
|
|
4043
|
+
...handlerOpts,
|
|
4044
|
+
from: opts.from,
|
|
4045
|
+
dryRun: opts.dryRun,
|
|
4046
|
+
encode: opts.encode,
|
|
4047
|
+
ext: opts.ext
|
|
4048
|
+
});
|
|
4049
|
+
} else {
|
|
4050
|
+
await handleTx(target, args, {
|
|
4051
|
+
...handlerOpts,
|
|
4052
|
+
from: opts.from,
|
|
4053
|
+
dryRun: opts.dryRun,
|
|
4054
|
+
encode: opts.encode,
|
|
4055
|
+
ext: opts.ext
|
|
4056
|
+
});
|
|
4057
|
+
}
|
|
4058
|
+
break;
|
|
4059
|
+
case "const":
|
|
4060
|
+
await handleConst(target, handlerOpts);
|
|
4061
|
+
break;
|
|
4062
|
+
case "events":
|
|
4063
|
+
await handleEvents2(target, handlerOpts);
|
|
4064
|
+
break;
|
|
4065
|
+
case "errors":
|
|
4066
|
+
await handleErrors2(target, handlerOpts);
|
|
4067
|
+
break;
|
|
4068
|
+
}
|
|
4069
|
+
});
|
|
3399
4070
|
cli.option("--help, -h", "Display this message");
|
|
3400
4071
|
cli.version(version);
|
|
4072
|
+
function printHelp() {
|
|
4073
|
+
console.log(`dot/${version} \u2014 Polkadot CLI`);
|
|
4074
|
+
console.log();
|
|
4075
|
+
console.log("Usage:");
|
|
4076
|
+
console.log(" dot <category>[.Pallet[.Item]] [args] [options]");
|
|
4077
|
+
console.log(" dot [Chain.]<category>[.Pallet[.Item]] [args] [options]");
|
|
4078
|
+
console.log();
|
|
4079
|
+
console.log("Categories:");
|
|
4080
|
+
console.log(" query Query on-chain storage");
|
|
4081
|
+
console.log(" tx Submit an extrinsic");
|
|
4082
|
+
console.log(" const Look up or list pallet constants");
|
|
4083
|
+
console.log(" events List or inspect pallet events");
|
|
4084
|
+
console.log(" errors List or inspect pallet errors");
|
|
4085
|
+
console.log();
|
|
4086
|
+
console.log("Examples:");
|
|
4087
|
+
console.log(" dot query.System.Account <addr> Query a storage item");
|
|
4088
|
+
console.log(" dot query.System List storage items in System");
|
|
4089
|
+
console.log(" dot tx.System.remark 0xdead --from alice");
|
|
4090
|
+
console.log(" dot const.Balances.ExistentialDeposit");
|
|
4091
|
+
console.log(" dot events.Balances List events in Balances");
|
|
4092
|
+
console.log(" dot polkadot.query.System.Number With chain prefix");
|
|
4093
|
+
console.log();
|
|
4094
|
+
console.log("Commands:");
|
|
4095
|
+
console.log(" inspect [target] Inspect chain metadata (alias: explore)");
|
|
4096
|
+
console.log(" chain Manage chain configurations");
|
|
4097
|
+
console.log(" account Manage accounts");
|
|
4098
|
+
console.log(" hash Hash utilities");
|
|
4099
|
+
console.log();
|
|
4100
|
+
console.log("Global options:");
|
|
4101
|
+
console.log(" --chain <name> Target chain (default from config)");
|
|
4102
|
+
console.log(" --rpc <url> Override RPC endpoint");
|
|
4103
|
+
console.log(" --light-client Use Smoldot light client");
|
|
4104
|
+
console.log(" --output <format> Output format: pretty or json");
|
|
4105
|
+
console.log(" --help, -h Display this message");
|
|
4106
|
+
console.log(" --version Show version");
|
|
4107
|
+
}
|
|
3401
4108
|
async function showUpdateAndExit(code) {
|
|
3402
4109
|
await waitForPendingCheck();
|
|
3403
4110
|
const note = getUpdateNotification(version);
|
|
@@ -3422,17 +4129,17 @@ async function main() {
|
|
|
3422
4129
|
if (cli.options.version) {
|
|
3423
4130
|
await showUpdateAndExit(0);
|
|
3424
4131
|
} else if (cli.options.help) {
|
|
3425
|
-
if (cli.
|
|
4132
|
+
if (cli.matchedCommand) {
|
|
3426
4133
|
const result = cli.runMatchedCommand();
|
|
3427
4134
|
if (result && typeof result.then === "function") {
|
|
3428
4135
|
await result.then(() => showUpdateAndExit(0), handleError);
|
|
3429
4136
|
}
|
|
3430
4137
|
} else {
|
|
3431
|
-
|
|
4138
|
+
printHelp();
|
|
3432
4139
|
await showUpdateAndExit(0);
|
|
3433
4140
|
}
|
|
3434
|
-
} else if (!cli.
|
|
3435
|
-
|
|
4141
|
+
} else if (!cli.matchedCommand) {
|
|
4142
|
+
printHelp();
|
|
3436
4143
|
await showUpdateAndExit(0);
|
|
3437
4144
|
} else {
|
|
3438
4145
|
const result = cli.runMatchedCommand();
|