polkadot-cli 1.16.0 → 1.18.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 +677 -171
  2. package/dist/cli.mjs +1924 -311
  3. package/package.json +2 -1
package/dist/cli.mjs CHANGED
@@ -240,6 +240,9 @@ function getMetadataPath(chainName) {
240
240
  function getMetadataFingerprintPath(chainName) {
241
241
  return join(getChainDir(chainName), "metadata.fingerprint.json");
242
242
  }
243
+ function getRpcMethodsPath(chainName) {
244
+ return join(getChainDir(chainName), "rpc-methods.json");
245
+ }
243
246
  function getConfigPath() {
244
247
  return join(getConfigDir(), "config.json");
245
248
  }
@@ -305,6 +308,31 @@ async function loadMetadataFingerprint(chainName) {
305
308
  return null;
306
309
  }
307
310
  }
311
+ async function loadRpcMethods(chainName) {
312
+ const path = getRpcMethodsPath(chainName);
313
+ if (!await fileExists(path))
314
+ return null;
315
+ try {
316
+ const parsed = JSON.parse(await readFile(path, "utf-8"));
317
+ if (parsed && Array.isArray(parsed.methods) && typeof parsed.version === "number" && typeof parsed.fetchedAt === "string") {
318
+ return parsed;
319
+ }
320
+ return null;
321
+ } catch {
322
+ return null;
323
+ }
324
+ }
325
+ async function saveRpcMethods(chainName, methods, version2) {
326
+ const dir = getChainDir(chainName);
327
+ await ensureDir(dir);
328
+ const cache = {
329
+ methods,
330
+ version: version2,
331
+ fetchedAt: new Date().toISOString()
332
+ };
333
+ await writeFile(getRpcMethodsPath(chainName), `${JSON.stringify(cache, null, 2)}
334
+ `);
335
+ }
308
336
  async function removeChainData(chainName) {
309
337
  const dir = getChainDir(chainName);
310
338
  await rm(dir, { recursive: true, force: true });
@@ -375,6 +403,15 @@ function isEnvSecret(secret) {
375
403
  function isWatchOnly(account) {
376
404
  return account.secret === undefined;
377
405
  }
406
+ function classifyAccount(account) {
407
+ if (account.source?.kind === "pallet")
408
+ return "pallet";
409
+ if (account.source?.kind === "parachain")
410
+ return "parachain";
411
+ if (account.secret !== undefined)
412
+ return "signer";
413
+ return "watch-only";
414
+ }
378
415
 
379
416
  // src/utils/fuzzy-match.ts
380
417
  function levenshtein(a, b) {
@@ -674,6 +711,11 @@ function printResult(data, format = "pretty") {
674
711
  function isJsonOutput(opts) {
675
712
  return opts.json === true || opts.output === "json";
676
713
  }
714
+ function writeStdout(text) {
715
+ return new Promise((resolve) => {
716
+ process.stdout.write(text, () => resolve());
717
+ });
718
+ }
677
719
  function printJsonLine(data) {
678
720
  console.log(JSON.stringify(data, replacer));
679
721
  }
@@ -853,6 +895,324 @@ var init_client = __esm(() => {
853
895
  init_errors();
854
896
  });
855
897
 
898
+ // src/core/pretty-type.ts
899
+ function visualWidth(s) {
900
+ return s.replace(ANSI_RE, "").length;
901
+ }
902
+ function paint(color, code, text) {
903
+ return color ? `${code}${text}${RESET2}` : text;
904
+ }
905
+ function defaultWidth() {
906
+ return process.stdout.columns ?? 80;
907
+ }
908
+ function resolveOpts(opts) {
909
+ return {
910
+ indent: opts.indent ?? 0,
911
+ prefix: opts.prefix ?? 0,
912
+ width: opts.width ?? defaultWidth(),
913
+ color: opts.color ?? isTTY
914
+ };
915
+ }
916
+ function compactEntry(entry, color) {
917
+ if (!entry)
918
+ return "";
919
+ switch (entry.type) {
920
+ case "primitive":
921
+ return paint(color, YELLOW2, entry.value);
922
+ case "compact": {
923
+ const inner = entry.isBig ? "u128" : "u64";
924
+ return `${paint(color, MAGENTA2, "Compact")}<${paint(color, YELLOW2, inner)}>`;
925
+ }
926
+ case "AccountId32":
927
+ return paint(color, GREEN2, "AccountId32");
928
+ case "bitSequence":
929
+ return paint(color, MAGENTA2, "BitSequence");
930
+ case "sequence":
931
+ return `${paint(color, MAGENTA2, "Vec")}<${compactEntry(entry.value, color)}>`;
932
+ case "array":
933
+ return `[${compactEntry(entry.value, color)}; ${entry.len}]`;
934
+ case "tuple":
935
+ return `(${entry.value.map((v) => compactEntry(v, color)).join(", ")})`;
936
+ case "struct": {
937
+ const fields = Object.entries(entry.value);
938
+ if (fields.length === 0)
939
+ return "{}";
940
+ const inner = fields.map(([k, v]) => `${paint(color, CYAN2, k)}: ${compactEntry(v, color)}`).join(", ");
941
+ return `{ ${inner} }`;
942
+ }
943
+ case "option":
944
+ return `${paint(color, MAGENTA2, "Option")}<${compactEntry(entry.value, color)}>`;
945
+ case "result":
946
+ return `${paint(color, MAGENTA2, "Result")}<${compactEntry(entry.value.ok, color)}, ${compactEntry(entry.value.ko, color)}>`;
947
+ case "enum": {
948
+ const variants = Object.keys(entry.value);
949
+ if (variants.length > ENUM_COMPACT_LIMIT) {
950
+ return `enum(${variants.length} variants)`;
951
+ }
952
+ return variants.map((v) => paint(color, GREEN2, v)).join(" | ");
953
+ }
954
+ case "void":
955
+ return "()";
956
+ case "lookupEntry":
957
+ return compactEntry(entry.value, color);
958
+ default:
959
+ return "unknown";
960
+ }
961
+ }
962
+ function expandEntry(entry, indent, width, color, prefix = 0) {
963
+ const compact = compactEntry(entry, color);
964
+ if (visualWidth(compact) + indent + prefix <= width)
965
+ return compact;
966
+ switch (entry.type) {
967
+ case "struct":
968
+ return expandStruct(entry.value, indent, width, color);
969
+ case "tuple":
970
+ return expandTuple(entry.value, indent, width, color);
971
+ case "sequence":
972
+ return wrapMultiline("Vec", "<", ">", entry.value, indent, width, color);
973
+ case "array": {
974
+ const inner = expandEntry(entry.value, indent + 1, width, color);
975
+ return `[${inner}; ${entry.len}]`;
976
+ }
977
+ case "option":
978
+ return wrapMultiline("Option", "<", ">", entry.value, indent, width, color);
979
+ case "result": {
980
+ const innerIndent = indent + 2;
981
+ const padding = " ".repeat(innerIndent);
982
+ const closePadding = " ".repeat(indent);
983
+ const ok = expandEntry(entry.value.ok, innerIndent, width, color);
984
+ const ko = expandEntry(entry.value.ko, innerIndent, width, color);
985
+ return `${paint(color, MAGENTA2, "Result")}<
986
+ ${padding}${ok},
987
+ ${padding}${ko}
988
+ ${closePadding}>`;
989
+ }
990
+ case "enum": {
991
+ const variants = Object.keys(entry.value);
992
+ if (variants.length > ENUM_COMPACT_LIMIT)
993
+ return `enum(${variants.length} variants)`;
994
+ return expandEnum(variants, indent, color);
995
+ }
996
+ case "lookupEntry":
997
+ return expandEntry(entry.value, indent, width, color);
998
+ default:
999
+ return compact;
1000
+ }
1001
+ }
1002
+ function expandStruct(fields, indent, width, color) {
1003
+ const entries = Object.entries(fields);
1004
+ if (entries.length === 0)
1005
+ return "{}";
1006
+ return renderFieldList(entries, "{", "}", indent, width, color);
1007
+ }
1008
+ function expandTuple(items, indent, width, color) {
1009
+ if (items.length === 0)
1010
+ return "()";
1011
+ const inner = " ".repeat(indent + 2);
1012
+ const close = " ".repeat(indent);
1013
+ const lines = items.map((v) => `${inner}${expandEntry(v, indent + 2, width, color)}`);
1014
+ return `(
1015
+ ${lines.join(`,
1016
+ `)},
1017
+ ${close})`;
1018
+ }
1019
+ function wrapMultiline(name, open, close, inner, indent, width, color) {
1020
+ const innerIndent = indent + 2;
1021
+ const padding = " ".repeat(innerIndent);
1022
+ const closePadding = " ".repeat(indent);
1023
+ const innerStr = expandEntry(inner, innerIndent, width, color);
1024
+ return `${paint(color, MAGENTA2, name)}${open}
1025
+ ${padding}${innerStr}
1026
+ ${closePadding}${close}`;
1027
+ }
1028
+ function expandEnum(variants, indent, color) {
1029
+ const prefix = `
1030
+ ${" ".repeat(indent)}| `;
1031
+ const [first, ...rest] = variants;
1032
+ const head = paint(color, GREEN2, first ?? "");
1033
+ if (rest.length === 0)
1034
+ return head;
1035
+ const tail = rest.map((v) => paint(color, GREEN2, v)).join(prefix);
1036
+ return `${head}${prefix}${tail}`;
1037
+ }
1038
+ function renderFieldList(fields, open, close, indent, width, color) {
1039
+ const innerIndent = indent + 2;
1040
+ const maxNameLen = Math.max(...fields.map(([k]) => k.length));
1041
+ const align = maxNameLen <= ALIGN_PADDING_LIMIT;
1042
+ const padTo = align ? maxNameLen : 0;
1043
+ const padding = " ".repeat(innerIndent);
1044
+ const closePadding = " ".repeat(indent);
1045
+ const lines = fields.map(([k, v]) => {
1046
+ const paddedName = align ? k.padEnd(padTo) : k;
1047
+ const fieldPrefix = (align ? padTo : k.length) + 2;
1048
+ const value = expandEntry(v, innerIndent, width, color, fieldPrefix);
1049
+ return `${padding}${paint(color, CYAN2, paddedName)}: ${value}`;
1050
+ });
1051
+ return `${open}
1052
+ ${lines.join(`,
1053
+ `)},
1054
+ ${closePadding}${close}`;
1055
+ }
1056
+ function prettyType(entry, opts = {}) {
1057
+ const { indent, prefix, width, color } = resolveOpts(opts);
1058
+ const compact = compactEntry(entry, color);
1059
+ if (visualWidth(compact) + indent + prefix <= width)
1060
+ return compact;
1061
+ return expandEntry(entry, indent, width, color);
1062
+ }
1063
+ function prettyTypeById(lookup, typeId, opts = {}) {
1064
+ try {
1065
+ const entry = lookup(typeId);
1066
+ if (!entry || typeof entry.type !== "string")
1067
+ return `type(${typeId})`;
1068
+ return prettyType(entry, opts);
1069
+ } catch {
1070
+ return `type(${typeId})`;
1071
+ }
1072
+ }
1073
+ function prettyCallArgs(meta, palletName, callName, opts = {}) {
1074
+ const fields = getCallFields(meta, palletName, callName);
1075
+ if (fields === null)
1076
+ return "";
1077
+ return renderArgsFromFields(fields, opts);
1078
+ }
1079
+ function prettyEventFields(meta, palletName, eventName, opts = {}) {
1080
+ const fields = getEventFields(meta, palletName, eventName);
1081
+ if (fields === null)
1082
+ return "";
1083
+ return renderArgsFromFields(fields, opts);
1084
+ }
1085
+ function prettyRuntimeApiArgs(lookup, inputs, opts = {}) {
1086
+ if (inputs.length === 0)
1087
+ return "()";
1088
+ const namedFields = inputs.map((i) => {
1089
+ let entry;
1090
+ try {
1091
+ entry = lookup(i.type);
1092
+ if (!entry || typeof entry.type !== "string")
1093
+ entry = { type: "unknown" };
1094
+ } catch {
1095
+ entry = { type: "unknown" };
1096
+ }
1097
+ return [i.name, entry];
1098
+ });
1099
+ return renderArgsFromFields({ kind: "named", fields: namedFields }, opts);
1100
+ }
1101
+ function unwrapVariant(variant) {
1102
+ if (!variant)
1103
+ return null;
1104
+ if (variant.type === "void")
1105
+ return { kind: "void" };
1106
+ if (variant.type === "struct") {
1107
+ return {
1108
+ kind: "named",
1109
+ fields: Object.entries(variant.value)
1110
+ };
1111
+ }
1112
+ if (variant.type === "tuple") {
1113
+ return { kind: "positional", types: variant.value };
1114
+ }
1115
+ if (variant.type === "lookupEntry") {
1116
+ const inner = variant.value;
1117
+ if (inner.type === "void")
1118
+ return { kind: "void" };
1119
+ if (inner.type === "struct") {
1120
+ return {
1121
+ kind: "named",
1122
+ fields: Object.entries(inner.value)
1123
+ };
1124
+ }
1125
+ return { kind: "single", type: inner };
1126
+ }
1127
+ return null;
1128
+ }
1129
+ function getCallFields(meta, palletName, callName) {
1130
+ try {
1131
+ const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
1132
+ if (!palletMeta?.calls)
1133
+ return null;
1134
+ const callsEntry = meta.lookup(palletMeta.calls.type);
1135
+ if (callsEntry.type !== "enum")
1136
+ return null;
1137
+ const variant = callsEntry.value[callName];
1138
+ return unwrapVariant(variant);
1139
+ } catch {
1140
+ return null;
1141
+ }
1142
+ }
1143
+ function getEventFields(meta, palletName, eventName) {
1144
+ try {
1145
+ const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
1146
+ if (!palletMeta?.events)
1147
+ return null;
1148
+ const eventsEntry = meta.lookup(palletMeta.events.type);
1149
+ if (eventsEntry.type !== "enum")
1150
+ return null;
1151
+ const variant = eventsEntry.value[eventName];
1152
+ return unwrapVariant(variant);
1153
+ } catch {
1154
+ return null;
1155
+ }
1156
+ }
1157
+ function renderArgsFromFields(fields, opts) {
1158
+ const { indent, prefix, width, color } = resolveOpts(opts);
1159
+ const lead = indent + prefix;
1160
+ switch (fields.kind) {
1161
+ case "void":
1162
+ return "()";
1163
+ case "named": {
1164
+ const compact = `(${fields.fields.map(([k, v]) => `${paint(color, CYAN2, k)}: ${compactEntry(v, color)}`).join(", ")})`;
1165
+ if (visualWidth(compact) + lead <= width)
1166
+ return compact;
1167
+ return renderFieldList(fields.fields, "(", ")", indent, width, color);
1168
+ }
1169
+ case "positional": {
1170
+ const compact = `(${fields.types.map((t) => compactEntry(t, color)).join(", ")})`;
1171
+ if (visualWidth(compact) + lead <= width)
1172
+ return compact;
1173
+ const innerIndent = indent + 2;
1174
+ const padding = " ".repeat(innerIndent);
1175
+ const closePadding = " ".repeat(indent);
1176
+ const lines = fields.types.map((t) => `${padding}${expandEntry(t, innerIndent, width, color)}`);
1177
+ return `(
1178
+ ${lines.join(`,
1179
+ `)},
1180
+ ${closePadding})`;
1181
+ }
1182
+ case "single": {
1183
+ const compact = `(${compactEntry(fields.type, color)})`;
1184
+ if (visualWidth(compact) + lead <= width)
1185
+ return compact;
1186
+ const inner = expandEntry(fields.type, indent + 2, width, color);
1187
+ return `(
1188
+ ${" ".repeat(indent + 2)}${inner},
1189
+ ${" ".repeat(indent)})`;
1190
+ }
1191
+ }
1192
+ }
1193
+ function compactTypeString(entry) {
1194
+ return compactEntry(entry, false);
1195
+ }
1196
+ function compactArgsString(fields) {
1197
+ if (fields === null)
1198
+ return "";
1199
+ switch (fields.kind) {
1200
+ case "void":
1201
+ return "()";
1202
+ case "named":
1203
+ return `(${fields.fields.map(([k, v]) => `${k}: ${compactEntry(v, false)}`).join(", ")})`;
1204
+ case "positional":
1205
+ return `(${fields.types.map((t) => compactEntry(t, false)).join(", ")})`;
1206
+ case "single":
1207
+ return `(${compactEntry(fields.type, false)})`;
1208
+ }
1209
+ }
1210
+ var RESET2 = "\x1B[0m", CYAN2 = "\x1B[36m", GREEN2 = "\x1B[32m", YELLOW2 = "\x1B[33m", MAGENTA2 = "\x1B[35m", ANSI_RE, ENUM_COMPACT_LIMIT = 24, ALIGN_PADDING_LIMIT = 16;
1211
+ var init_pretty_type = __esm(() => {
1212
+ init_output();
1213
+ ANSI_RE = /\x1b\[[0-9;]*m/g;
1214
+ });
1215
+
856
1216
  // src/core/metadata.ts
857
1217
  import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders";
858
1218
  import {
@@ -1067,114 +1427,18 @@ function describeRuntimeApiMethodArgs(meta, method) {
1067
1427
  function describeType(lookup, typeId) {
1068
1428
  try {
1069
1429
  const entry = lookup(typeId);
1070
- return formatLookupEntry(entry);
1430
+ if (!entry || typeof entry.type !== "string")
1431
+ return `type(${typeId})`;
1432
+ return compactTypeString(entry);
1071
1433
  } catch {
1072
1434
  return `type(${typeId})`;
1073
1435
  }
1074
1436
  }
1075
- function formatLookupEntry(entry) {
1076
- switch (entry.type) {
1077
- case "primitive":
1078
- return entry.value;
1079
- case "compact":
1080
- return `Compact<${formatLookupEntry(entry.isBig ? { type: "primitive", value: "u128" } : { type: "primitive", value: "u64" })}>`;
1081
- case "AccountId32":
1082
- return "AccountId32";
1083
- case "bitSequence":
1084
- return "BitSequence";
1085
- case "sequence":
1086
- return `Vec<${formatLookupEntry(entry.value)}>`;
1087
- case "array":
1088
- return `[${formatLookupEntry(entry.value)}; ${entry.len}]`;
1089
- case "tuple":
1090
- return `(${entry.value.map(formatLookupEntry).join(", ")})`;
1091
- case "struct":
1092
- return `{ ${Object.entries(entry.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ")} }`;
1093
- case "option":
1094
- return `Option<${formatLookupEntry(entry.value)}>`;
1095
- case "result":
1096
- return `Result<${formatLookupEntry(entry.value.ok)}, ${formatLookupEntry(entry.value.ko)}>`;
1097
- case "enum": {
1098
- const variants = Object.keys(entry.value);
1099
- if (variants.length <= 4)
1100
- return variants.join(" | ");
1101
- return `enum(${variants.length} variants)`;
1102
- }
1103
- default:
1104
- return "unknown";
1105
- }
1106
- }
1107
1437
  function describeCallArgs(meta, palletName, callName) {
1108
- try {
1109
- const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
1110
- if (!palletMeta?.calls)
1111
- return "";
1112
- const callsEntry = meta.lookup(palletMeta.calls.type);
1113
- if (callsEntry.type !== "enum")
1114
- return "";
1115
- const variant = callsEntry.value[callName];
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
- }
1438
+ return compactArgsString(getCallFields(meta, palletName, callName));
1142
1439
  }
1143
1440
  function describeEventFields(meta, palletName, eventName) {
1144
- try {
1145
- const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
1146
- if (!palletMeta?.events)
1147
- return "";
1148
- const eventsEntry = meta.lookup(palletMeta.events.type);
1149
- if (eventsEntry.type !== "enum")
1150
- return "";
1151
- const variant = eventsEntry.value[eventName];
1152
- if (!variant)
1153
- return "";
1154
- if (variant.type === "void")
1155
- return "()";
1156
- if (variant.type === "struct") {
1157
- const fields = Object.entries(variant.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
1158
- return `(${fields})`;
1159
- }
1160
- if (variant.type === "lookupEntry") {
1161
- const inner = variant.value;
1162
- if (inner.type === "void")
1163
- return "()";
1164
- if (inner.type === "struct") {
1165
- const fields = Object.entries(inner.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
1166
- return `(${fields})`;
1167
- }
1168
- return `(${formatLookupEntry(inner)})`;
1169
- }
1170
- if (variant.type === "tuple") {
1171
- const types = variant.value.map(formatLookupEntry).join(", ");
1172
- return `(${types})`;
1173
- }
1174
- return "";
1175
- } catch {
1176
- return "";
1177
- }
1441
+ return compactArgsString(getEventFields(meta, palletName, eventName));
1178
1442
  }
1179
1443
  function hexToBytes(hex) {
1180
1444
  const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
@@ -1188,6 +1452,7 @@ var METADATA_TIMEOUT_MS = 15000, optionalOpaqueBytes, v15Arg, PAPI_BUILTIN_EXTEN
1188
1452
  var init_metadata = __esm(() => {
1189
1453
  init_store();
1190
1454
  init_errors();
1455
+ init_pretty_type();
1191
1456
  optionalOpaqueBytes = Option(Bytes());
1192
1457
  v15Arg = toHex(u32.enc(15));
1193
1458
  PAPI_BUILTIN_EXTENSIONS = new Set([
@@ -1584,6 +1849,7 @@ var init_tx = __esm(() => {
1584
1849
  init_client();
1585
1850
  init_metadata();
1586
1851
  init_output();
1852
+ init_pretty_type();
1587
1853
  init_resolve_address();
1588
1854
  init_binary_display();
1589
1855
  init_errors();
@@ -1799,8 +2065,11 @@ async function handleCalls(target, opts) {
1799
2065
  }
1800
2066
  printHeading(`${pallet.name} Calls`);
1801
2067
  for (const c of pallet.calls) {
1802
- const args2 = describeCallArgs(meta, pallet.name, c.name);
1803
- console.log(` ${CYAN}${c.name}${RESET}${DIM}${args2}${RESET}`);
2068
+ const args2 = prettyCallArgs(meta, pallet.name, c.name, {
2069
+ indent: 2,
2070
+ prefix: c.name.length
2071
+ });
2072
+ console.log(` ${CYAN}${c.name}${RESET}${args2}`);
1804
2073
  const summary = firstSentence(c.docs);
1805
2074
  if (summary) {
1806
2075
  console.log(` ${DIM}${summary}${RESET}`);
@@ -1826,7 +2095,10 @@ async function handleCalls(target, opts) {
1826
2095
  return;
1827
2096
  }
1828
2097
  printHeading(`${pallet.name}.${callItem.name} (Call)`);
1829
- const args = describeCallArgs(meta, pallet.name, callItem.name);
2098
+ const args = prettyCallArgs(meta, pallet.name, callItem.name, {
2099
+ indent: 2,
2100
+ prefix: 6
2101
+ });
1830
2102
  console.log(` ${BOLD}Args:${RESET} ${args}`);
1831
2103
  if (callItem.docs.length) {
1832
2104
  console.log();
@@ -1885,8 +2157,11 @@ async function handleEvents(target, opts) {
1885
2157
  }
1886
2158
  printHeading(`${pallet.name} Events`);
1887
2159
  for (const e of pallet.events) {
1888
- const fields2 = describeEventFields(meta, pallet.name, e.name);
1889
- console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields2}${RESET}`);
2160
+ const fields2 = prettyEventFields(meta, pallet.name, e.name, {
2161
+ indent: 2,
2162
+ prefix: e.name.length
2163
+ });
2164
+ console.log(` ${CYAN}${e.name}${RESET}${fields2}`);
1890
2165
  const summary = firstSentence(e.docs);
1891
2166
  if (summary) {
1892
2167
  console.log(` ${DIM}${summary}${RESET}`);
@@ -1912,7 +2187,10 @@ async function handleEvents(target, opts) {
1912
2187
  return;
1913
2188
  }
1914
2189
  printHeading(`${pallet.name}.${eventItem.name} (Event)`);
1915
- const fields = describeEventFields(meta, pallet.name, eventItem.name);
2190
+ const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
2191
+ indent: 2,
2192
+ prefix: 8
2193
+ });
1916
2194
  console.log(` ${BOLD}Fields:${RESET} ${fields}`);
1917
2195
  if (eventItem.docs.length) {
1918
2196
  console.log();
@@ -2039,24 +2317,30 @@ async function handleStorage(target, opts) {
2039
2317
  chain: chainName,
2040
2318
  pallet: pallet.name,
2041
2319
  storage: pallet.storage.map((s) => {
2042
- const valueType = describeType(meta.lookup, s.valueTypeId);
2320
+ const valueType2 = describeType(meta.lookup, s.valueTypeId);
2043
2321
  const keyType = s.keyTypeId != null ? describeType(meta.lookup, s.keyTypeId) : undefined;
2044
- return { name: s.name, type: s.type, valueType, keyType, docs: firstSentence(s.docs) };
2322
+ return { name: s.name, type: s.type, valueType: valueType2, keyType, docs: firstSentence(s.docs) };
2045
2323
  })
2046
2324
  }));
2047
2325
  return;
2048
2326
  }
2049
2327
  printHeading(`${pallet.name} Storage`);
2050
2328
  for (const s of pallet.storage) {
2051
- const valueType = describeType(meta.lookup, s.valueTypeId);
2052
- let typeSuffix;
2053
- if (s.keyTypeId != null) {
2054
- const keyType = describeType(meta.lookup, s.keyTypeId);
2055
- typeSuffix = `: ${keyType} → ${valueType} [map]`;
2056
- } else {
2057
- typeSuffix = `: ${valueType}`;
2329
+ const isMap = s.keyTypeId != null;
2330
+ const tag = isMap ? `${DIM} [map]${RESET}` : "";
2331
+ console.log(` ${CYAN}${s.name}${RESET}${tag}`);
2332
+ if (isMap) {
2333
+ const keyType = prettyTypeById(meta.lookup, s.keyTypeId, {
2334
+ indent: 4,
2335
+ prefix: 5
2336
+ });
2337
+ console.log(` ${DIM}Key:${RESET} ${keyType}`);
2058
2338
  }
2059
- console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
2339
+ const valueType2 = prettyTypeById(meta.lookup, s.valueTypeId, {
2340
+ indent: 4,
2341
+ prefix: 7
2342
+ });
2343
+ console.log(` ${DIM}Value:${RESET} ${valueType2}`);
2060
2344
  const summary = firstSentence(s.docs);
2061
2345
  if (summary) {
2062
2346
  console.log(` ${DIM}${summary}${RESET}`);
@@ -2071,7 +2355,7 @@ async function handleStorage(target, opts) {
2071
2355
  throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
2072
2356
  }
2073
2357
  if (isJsonOutput(opts)) {
2074
- const valueType = describeType(meta.lookup, storageItem.valueTypeId);
2358
+ const valueType2 = describeType(meta.lookup, storageItem.valueTypeId);
2075
2359
  const keyType = storageItem.keyTypeId != null ? describeType(meta.lookup, storageItem.keyTypeId) : undefined;
2076
2360
  console.log(formatJson({
2077
2361
  chain: chainName,
@@ -2079,18 +2363,26 @@ async function handleStorage(target, opts) {
2079
2363
  item: storageItem.name,
2080
2364
  category: "storage",
2081
2365
  type: storageItem.type,
2082
- valueType,
2366
+ valueType: valueType2,
2083
2367
  keyType,
2084
2368
  docs: storageItem.docs
2085
2369
  }));
2086
2370
  return;
2087
2371
  }
2088
2372
  printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
2089
- console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
2090
- console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
2373
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
2091
2374
  if (storageItem.keyTypeId != null) {
2092
- console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
2375
+ const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
2376
+ indent: 2,
2377
+ prefix: 7
2378
+ });
2379
+ console.log(` ${BOLD}Key:${RESET} ${keyType}`);
2093
2380
  }
2381
+ const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
2382
+ indent: 2,
2383
+ prefix: 7
2384
+ });
2385
+ console.log(` ${BOLD}Value:${RESET} ${valueType}`);
2094
2386
  if (storageItem.docs.length) {
2095
2387
  console.log();
2096
2388
  printDocs(storageItem.docs);
@@ -2121,9 +2413,15 @@ async function showItemHelp(category, target, opts) {
2121
2413
  throw new Error(suggestMessage(`method in ${api.name}`, methodName, names));
2122
2414
  }
2123
2415
  printHeading(`${api.name}.${method.name} (Runtime API)`);
2124
- const argStr = describeRuntimeApiMethodArgs(meta, method);
2125
- const retStr = describeType(meta.lookup, method.output);
2126
- console.log(` ${BOLD}Args:${RESET} ${argStr}`);
2416
+ const argStr = prettyRuntimeApiArgs(meta.lookup, method.inputs, {
2417
+ indent: 2,
2418
+ prefix: 9
2419
+ });
2420
+ const retStr = prettyTypeById(meta.lookup, method.output, {
2421
+ indent: 2,
2422
+ prefix: 9
2423
+ });
2424
+ console.log(` ${BOLD}Args:${RESET} ${argStr}`);
2127
2425
  console.log(` ${BOLD}Returns:${RESET} ${retStr}`);
2128
2426
  if (method.docs.length) {
2129
2427
  console.log();
@@ -2166,7 +2464,10 @@ async function showItemHelp(category, target, opts) {
2166
2464
  throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
2167
2465
  }
2168
2466
  printHeading(`${pallet.name}.${callItem.name} (Call)`);
2169
- const args = describeCallArgs(meta, pallet.name, callItem.name);
2467
+ const args = prettyCallArgs(meta, pallet.name, callItem.name, {
2468
+ indent: 2,
2469
+ prefix: 6
2470
+ });
2170
2471
  console.log(` ${BOLD}Args:${RESET} ${args}`);
2171
2472
  if (callItem.docs.length) {
2172
2473
  console.log();
@@ -2193,11 +2494,19 @@ async function showItemHelp(category, target, opts) {
2193
2494
  throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
2194
2495
  }
2195
2496
  printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
2196
- console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
2197
- console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
2497
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
2198
2498
  if (storageItem.keyTypeId != null) {
2199
- console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
2499
+ const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
2500
+ indent: 2,
2501
+ prefix: 7
2502
+ });
2503
+ console.log(` ${BOLD}Key:${RESET} ${keyType}`);
2200
2504
  }
2505
+ const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
2506
+ indent: 2,
2507
+ prefix: 7
2508
+ });
2509
+ console.log(` ${BOLD}Value:${RESET} ${valueType}`);
2201
2510
  if (storageItem.docs.length) {
2202
2511
  console.log();
2203
2512
  printDocs(storageItem.docs);
@@ -2224,7 +2533,11 @@ async function showItemHelp(category, target, opts) {
2224
2533
  throw new Error(suggestMessage(`constant in ${pallet.name}`, itemName, names));
2225
2534
  }
2226
2535
  printHeading(`${pallet.name}.${constItem.name} (Constant)`);
2227
- console.log(` ${BOLD}Type:${RESET} ${describeType(meta.lookup, constItem.typeId)}`);
2536
+ const constType = prettyTypeById(meta.lookup, constItem.typeId, {
2537
+ indent: 2,
2538
+ prefix: 6
2539
+ });
2540
+ console.log(` ${BOLD}Type:${RESET} ${constType}`);
2228
2541
  if (constItem.docs.length) {
2229
2542
  console.log();
2230
2543
  printDocs(constItem.docs);
@@ -2242,7 +2555,10 @@ async function showItemHelp(category, target, opts) {
2242
2555
  throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
2243
2556
  }
2244
2557
  printHeading(`${pallet.name}.${eventItem.name} (Event)`);
2245
- const fields = describeEventFields(meta, pallet.name, eventItem.name);
2558
+ const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
2559
+ indent: 2,
2560
+ prefix: 8
2561
+ });
2246
2562
  console.log(` ${BOLD}Fields:${RESET} ${fields}`);
2247
2563
  if (eventItem.docs.length) {
2248
2564
  console.log();
@@ -2277,6 +2593,478 @@ var init_focused_inspect = __esm(() => {
2277
2593
  init_client();
2278
2594
  init_metadata();
2279
2595
  init_output();
2596
+ init_pretty_type();
2597
+ });
2598
+
2599
+ // src/data/rpc-registry.ts
2600
+ function inferFamily(method) {
2601
+ const prefix = method.split("_")[0];
2602
+ switch (prefix) {
2603
+ case "system":
2604
+ case "chain":
2605
+ case "state":
2606
+ case "author":
2607
+ case "payment":
2608
+ case "babe":
2609
+ case "grandpa":
2610
+ case "beefy":
2611
+ case "mmr":
2612
+ case "offchain":
2613
+ case "dev":
2614
+ return prefix;
2615
+ case "rpc":
2616
+ return "spec";
2617
+ case "chainHead":
2618
+ return "chainHead";
2619
+ case "chainSpec":
2620
+ return "chainSpec";
2621
+ case "transaction":
2622
+ return "transaction";
2623
+ case "archive":
2624
+ return "archive";
2625
+ default:
2626
+ return "other";
2627
+ }
2628
+ }
2629
+ var RPC_REGISTRY;
2630
+ var init_rpc_registry = __esm(() => {
2631
+ RPC_REGISTRY = {
2632
+ system_health: {
2633
+ description: "Node sync state (peers, isSyncing, shouldHavePeers).",
2634
+ family: "system",
2635
+ args: []
2636
+ },
2637
+ system_syncState: {
2638
+ description: "Block-level sync progress (startingBlock, currentBlock, highestBlock).",
2639
+ family: "system",
2640
+ args: []
2641
+ },
2642
+ system_version: {
2643
+ description: "Node software version string.",
2644
+ family: "system",
2645
+ args: []
2646
+ },
2647
+ system_name: {
2648
+ description: "Node implementation name.",
2649
+ family: "system",
2650
+ args: []
2651
+ },
2652
+ system_chain: {
2653
+ description: "Chain name as reported by the node.",
2654
+ family: "system",
2655
+ args: []
2656
+ },
2657
+ system_chainType: {
2658
+ description: "Chain type (Live, Development, Local).",
2659
+ family: "system",
2660
+ args: []
2661
+ },
2662
+ system_properties: {
2663
+ description: "Chain properties (ss58Format, tokenDecimals, tokenSymbol).",
2664
+ family: "system",
2665
+ args: []
2666
+ },
2667
+ system_peers: {
2668
+ description: "Connected peer details (peerId, roles, bestHash, bestNumber).",
2669
+ family: "system",
2670
+ args: []
2671
+ },
2672
+ system_localPeerId: {
2673
+ description: "Base58 PeerId of this node.",
2674
+ family: "system",
2675
+ args: []
2676
+ },
2677
+ system_localListenAddresses: {
2678
+ description: "Multiaddrs this node listens on.",
2679
+ family: "system",
2680
+ args: []
2681
+ },
2682
+ system_nodeRoles: {
2683
+ description: "Role(s) of the node (Authority, Full, Light, …).",
2684
+ family: "system",
2685
+ args: []
2686
+ },
2687
+ system_addLogFilter: {
2688
+ description: "Add a tracing/log filter directive at runtime.",
2689
+ family: "system",
2690
+ args: [{ name: "directives", type: "string" }],
2691
+ dangerous: true
2692
+ },
2693
+ system_resetLogFilter: {
2694
+ description: "Reset log filter to the default set at startup.",
2695
+ family: "system",
2696
+ args: [],
2697
+ dangerous: true
2698
+ },
2699
+ system_accountNextIndex: {
2700
+ description: "Next nonce for an account, including pending mempool extrinsics.",
2701
+ family: "system",
2702
+ args: [{ name: "address", type: "AccountId" }]
2703
+ },
2704
+ system_dryRun: {
2705
+ description: "Dry-run an extrinsic, returning its ApplyExtrinsicResult.",
2706
+ family: "system",
2707
+ args: [
2708
+ { name: "extrinsic", type: "hex" },
2709
+ { name: "at", type: "H256", optional: true }
2710
+ ]
2711
+ },
2712
+ chain_getBlock: {
2713
+ description: "Full block (header + extrinsics) by hash.",
2714
+ family: "chain",
2715
+ args: [{ name: "blockHash", type: "H256", optional: true, description: "latest if omitted" }]
2716
+ },
2717
+ chain_getBlockHash: {
2718
+ description: "Block hash by number, or latest if omitted.",
2719
+ family: "chain",
2720
+ args: [{ name: "blockNumber", type: "u32", optional: true }]
2721
+ },
2722
+ chain_getFinalizedHead: {
2723
+ description: "Hash of the latest finalized head.",
2724
+ family: "chain",
2725
+ args: []
2726
+ },
2727
+ chain_getHeader: {
2728
+ description: "Block header by hash, or latest if omitted.",
2729
+ family: "chain",
2730
+ args: [{ name: "blockHash", type: "H256", optional: true }]
2731
+ },
2732
+ chain_subscribeAllHeads: {
2733
+ description: "Subscribe to all imported headers.",
2734
+ family: "chain",
2735
+ args: [],
2736
+ subscription: true
2737
+ },
2738
+ chain_subscribeFinalizedHeads: {
2739
+ description: "Subscribe to finalized-head changes.",
2740
+ family: "chain",
2741
+ args: [],
2742
+ subscription: true
2743
+ },
2744
+ chain_subscribeNewHeads: {
2745
+ description: "Subscribe to best-block-head changes.",
2746
+ family: "chain",
2747
+ args: [],
2748
+ subscription: true
2749
+ },
2750
+ state_call: {
2751
+ description: "Invoke a runtime API method by name with raw SCALE-encoded arguments.",
2752
+ family: "state",
2753
+ args: [
2754
+ { name: "method", type: "string", description: "e.g. Core_version" },
2755
+ { name: "data", type: "hex", description: "SCALE-encoded args (0x for none)" },
2756
+ { name: "at", type: "H256", optional: true }
2757
+ ]
2758
+ },
2759
+ state_getMetadata: {
2760
+ description: "Raw SCALE-encoded runtime metadata at a block.",
2761
+ family: "state",
2762
+ args: [{ name: "at", type: "H256", optional: true }]
2763
+ },
2764
+ state_getRuntimeVersion: {
2765
+ description: "Runtime version at a block.",
2766
+ family: "state",
2767
+ args: [{ name: "at", type: "H256", optional: true }]
2768
+ },
2769
+ state_getStorage: {
2770
+ description: "Raw SCALE-encoded storage value at a key.",
2771
+ family: "state",
2772
+ args: [
2773
+ { name: "key", type: "StorageKey" },
2774
+ { name: "at", type: "H256", optional: true }
2775
+ ]
2776
+ },
2777
+ state_getStorageHash: {
2778
+ description: "Blake2 hash of the value at a storage key.",
2779
+ family: "state",
2780
+ args: [
2781
+ { name: "key", type: "StorageKey" },
2782
+ { name: "at", type: "H256", optional: true }
2783
+ ]
2784
+ },
2785
+ state_getStorageSize: {
2786
+ description: "Byte length of the value at a storage key.",
2787
+ family: "state",
2788
+ args: [
2789
+ { name: "key", type: "StorageKey" },
2790
+ { name: "at", type: "H256", optional: true }
2791
+ ]
2792
+ },
2793
+ state_getKeysPaged: {
2794
+ description: "Paginated key iteration under a prefix.",
2795
+ family: "state",
2796
+ args: [
2797
+ { name: "prefix", type: "StorageKey" },
2798
+ { name: "count", type: "u32" },
2799
+ { name: "startKey", type: "StorageKey", optional: true },
2800
+ { name: "at", type: "H256", optional: true }
2801
+ ]
2802
+ },
2803
+ state_queryStorageAt: {
2804
+ description: "Read multiple keys at a single block.",
2805
+ family: "state",
2806
+ args: [
2807
+ { name: "keys", type: "StorageKey[]" },
2808
+ { name: "at", type: "H256", optional: true }
2809
+ ]
2810
+ },
2811
+ state_traceBlock: {
2812
+ description: "Per-block storage access trace (heavy: archival/debug nodes only).",
2813
+ family: "state",
2814
+ args: [
2815
+ { name: "blockHash", type: "H256" },
2816
+ { name: "targets", type: "string", optional: true },
2817
+ { name: "storageKeys", type: "string", optional: true },
2818
+ { name: "methods", type: "string", optional: true }
2819
+ ]
2820
+ },
2821
+ state_subscribeRuntimeVersion: {
2822
+ description: "Subscribe to runtime upgrades.",
2823
+ family: "state",
2824
+ args: [],
2825
+ subscription: true
2826
+ },
2827
+ state_subscribeStorage: {
2828
+ description: "Subscribe to changes for a set of keys.",
2829
+ family: "state",
2830
+ args: [{ name: "keys", type: "StorageKey[]" }],
2831
+ subscription: true
2832
+ },
2833
+ author_pendingExtrinsics: {
2834
+ description: "Mempool snapshot — encoded extrinsics waiting to be included.",
2835
+ family: "author",
2836
+ args: []
2837
+ },
2838
+ author_submitExtrinsic: {
2839
+ description: "Submit a signed extrinsic to the mempool. Returns the tx hash.",
2840
+ family: "author",
2841
+ args: [{ name: "extrinsic", type: "hex" }],
2842
+ dangerous: true
2843
+ },
2844
+ author_removeExtrinsic: {
2845
+ description: "Remove specific extrinsics from the mempool by hash.",
2846
+ family: "author",
2847
+ args: [{ name: "bytesOrHash", type: "ExtrinsicOrHash[]" }],
2848
+ dangerous: true
2849
+ },
2850
+ author_hasKey: {
2851
+ description: "Whether the keystore has the public key for a given key type.",
2852
+ family: "author",
2853
+ args: [
2854
+ { name: "publicKey", type: "hex" },
2855
+ { name: "keyType", type: "string", description: "e.g. babe, gran, imon" }
2856
+ ]
2857
+ },
2858
+ author_hasSessionKeys: {
2859
+ description: "Whether the keystore has all keys for a session-keys blob.",
2860
+ family: "author",
2861
+ args: [{ name: "sessionKeys", type: "hex" }]
2862
+ },
2863
+ author_rotateKeys: {
2864
+ description: "Generate a new set of session keys and return the public-keys blob.",
2865
+ family: "author",
2866
+ args: [],
2867
+ dangerous: true
2868
+ },
2869
+ author_insertKey: {
2870
+ description: "Insert a key into the node keystore.",
2871
+ family: "author",
2872
+ args: [
2873
+ { name: "keyType", type: "string" },
2874
+ { name: "suri", type: "string" },
2875
+ { name: "publicKey", type: "hex" }
2876
+ ],
2877
+ dangerous: true
2878
+ },
2879
+ author_submitAndWatchExtrinsic: {
2880
+ description: "Submit an extrinsic and subscribe to its status updates.",
2881
+ family: "author",
2882
+ args: [{ name: "extrinsic", type: "hex" }],
2883
+ dangerous: true,
2884
+ subscription: true
2885
+ },
2886
+ payment_queryInfo: {
2887
+ description: "Pre-submission fee estimate (weight, partialFee, class).",
2888
+ family: "payment",
2889
+ args: [
2890
+ { name: "extrinsic", type: "hex" },
2891
+ { name: "at", type: "H256", optional: true }
2892
+ ]
2893
+ },
2894
+ payment_queryFeeDetails: {
2895
+ description: "Fee breakdown (baseFee, lenFee, adjustedWeightFee, tip).",
2896
+ family: "payment",
2897
+ args: [
2898
+ { name: "extrinsic", type: "hex" },
2899
+ { name: "at", type: "H256", optional: true }
2900
+ ]
2901
+ },
2902
+ babe_epochAuthorship: {
2903
+ description: "Slots this node is allowed to author in the current epoch.",
2904
+ family: "babe",
2905
+ args: []
2906
+ },
2907
+ grandpa_proveFinality: {
2908
+ description: "Finality proof up to a block (for light clients).",
2909
+ family: "grandpa",
2910
+ args: [{ name: "blockNumber", type: "u32" }]
2911
+ },
2912
+ grandpa_roundState: {
2913
+ description: "GRANDPA round state (best round, total weight, voters).",
2914
+ family: "grandpa",
2915
+ args: []
2916
+ },
2917
+ grandpa_subscribeJustifications: {
2918
+ description: "Subscribe to GRANDPA justifications.",
2919
+ family: "grandpa",
2920
+ args: [],
2921
+ subscription: true
2922
+ },
2923
+ beefy_getFinalizedHead: {
2924
+ description: "Latest BEEFY-finalized block hash.",
2925
+ family: "beefy",
2926
+ args: []
2927
+ },
2928
+ beefy_subscribeJustifications: {
2929
+ description: "Subscribe to BEEFY signed commitments.",
2930
+ family: "beefy",
2931
+ args: [],
2932
+ subscription: true
2933
+ },
2934
+ mmr_root: {
2935
+ description: "MMR root at a block.",
2936
+ family: "mmr",
2937
+ args: [{ name: "at", type: "H256", optional: true }]
2938
+ },
2939
+ mmr_generateProof: {
2940
+ description: "Generate an MMR proof for given leaf indices.",
2941
+ family: "mmr",
2942
+ args: [
2943
+ { name: "blockNumbers", type: "u32[]" },
2944
+ { name: "bestKnownBlockNumber", type: "u32", optional: true },
2945
+ { name: "at", type: "H256", optional: true }
2946
+ ]
2947
+ },
2948
+ mmr_verifyProof: {
2949
+ description: "Verify an MMR proof.",
2950
+ family: "mmr",
2951
+ args: [{ name: "proof", type: "MmrLeavesProof" }]
2952
+ },
2953
+ offchain_localStorageGet: {
2954
+ description: "Read from offchain-worker local storage (PERSISTENT or LOCAL kind).",
2955
+ family: "offchain",
2956
+ args: [
2957
+ { name: "kind", type: "string", description: "PERSISTENT or LOCAL" },
2958
+ { name: "key", type: "hex" }
2959
+ ]
2960
+ },
2961
+ offchain_localStorageSet: {
2962
+ description: "Write to offchain-worker local storage.",
2963
+ family: "offchain",
2964
+ args: [
2965
+ { name: "kind", type: "string" },
2966
+ { name: "key", type: "hex" },
2967
+ { name: "value", type: "hex" }
2968
+ ],
2969
+ dangerous: true
2970
+ },
2971
+ dev_newBlock: {
2972
+ description: "Manually trigger block production (manual-seal dev nodes).",
2973
+ family: "dev",
2974
+ args: [
2975
+ {
2976
+ name: "params",
2977
+ type: "json",
2978
+ optional: true,
2979
+ description: "{ create_empty?: bool, finalize?: bool }"
2980
+ }
2981
+ ],
2982
+ dangerous: true
2983
+ },
2984
+ dev_setHead: {
2985
+ description: "Set the chain head to a specific block (manual-seal dev nodes).",
2986
+ family: "dev",
2987
+ args: [{ name: "blockHash", type: "H256" }],
2988
+ dangerous: true
2989
+ },
2990
+ rpc_methods: {
2991
+ description: "List of JSON-RPC methods this node exposes.",
2992
+ family: "spec",
2993
+ args: []
2994
+ },
2995
+ chainSpec_v1_chainName: {
2996
+ description: "Chain name from the chain spec (no SCALE).",
2997
+ family: "chainSpec",
2998
+ args: []
2999
+ },
3000
+ chainSpec_v1_genesisHash: {
3001
+ description: "Genesis block hash.",
3002
+ family: "chainSpec",
3003
+ args: []
3004
+ },
3005
+ chainSpec_v1_properties: {
3006
+ description: "Chain properties from the chain spec.",
3007
+ family: "chainSpec",
3008
+ args: []
3009
+ },
3010
+ archive_v1_finalizedHeight: {
3011
+ description: "Latest finalized block number this archive node has.",
3012
+ family: "archive",
3013
+ args: []
3014
+ },
3015
+ archive_v1_genesisHash: {
3016
+ description: "Genesis block hash from the archive node.",
3017
+ family: "archive",
3018
+ args: []
3019
+ },
3020
+ archive_v1_hashByHeight: {
3021
+ description: "Block hashes at a height (canonical + forks).",
3022
+ family: "archive",
3023
+ args: [{ name: "height", type: "u32" }]
3024
+ },
3025
+ archive_v1_header: {
3026
+ description: "Header for an archived block.",
3027
+ family: "archive",
3028
+ args: [{ name: "blockHash", type: "H256" }]
3029
+ },
3030
+ archive_v1_body: {
3031
+ description: "Block body (extrinsics) for an archived block.",
3032
+ family: "archive",
3033
+ args: [{ name: "blockHash", type: "H256" }]
3034
+ },
3035
+ archive_v1_call: {
3036
+ description: "Invoke a runtime API at an archived block.",
3037
+ family: "archive",
3038
+ args: [
3039
+ { name: "blockHash", type: "H256" },
3040
+ { name: "function", type: "string" },
3041
+ { name: "callParameters", type: "hex" }
3042
+ ]
3043
+ },
3044
+ archive_v1_storage: {
3045
+ description: "Read storage at an archived block.",
3046
+ family: "archive",
3047
+ args: [
3048
+ { name: "blockHash", type: "H256" },
3049
+ { name: "items", type: "StorageItemInput[]" },
3050
+ { name: "childTrie", type: "string", optional: true }
3051
+ ],
3052
+ subscription: true
3053
+ },
3054
+ chainHead_v1_follow: {
3055
+ description: "Pin chainHead and stream block events. Requires a follow session.",
3056
+ family: "chainHead",
3057
+ args: [{ name: "withRuntime", type: "bool" }],
3058
+ subscription: true
3059
+ },
3060
+ transaction_v1_broadcast: {
3061
+ description: "Broadcast a signed extrinsic and watch its status.",
3062
+ family: "transaction",
3063
+ args: [{ name: "extrinsic", type: "hex" }],
3064
+ dangerous: true,
3065
+ subscription: true
3066
+ }
3067
+ };
2280
3068
  });
2281
3069
 
2282
3070
  // src/core/hash.ts
@@ -2462,11 +3250,8 @@ async function generateCompletions(currentWord, precedingWords) {
2462
3250
  if (firstArg === "hash") {
2463
3251
  return filterPrefix(getAlgorithmNames(), currentWord);
2464
3252
  }
2465
- if (firstArg === "parachain") {
2466
- if (prevWord === "--type") {
2467
- return filterPrefix(["child", "sibling"], currentWord);
2468
- }
2469
- return [];
3253
+ if (firstArg === "account" && prevWord === "--parachain-type") {
3254
+ return filterPrefix(["child", "sibling"], currentWord);
2470
3255
  }
2471
3256
  return completeDotpath(currentWord, config, knownChains, precedingWords);
2472
3257
  }
@@ -2509,6 +3294,9 @@ async function completeDotpath(currentWord, config, knownChains, precedingWords)
2509
3294
  if (category === "extensions") {
2510
3295
  return completeExtensionsCategory(first, numComplete, endsWithDot, currentWord, config, chainFromFlag);
2511
3296
  }
3297
+ if (category === "rpc") {
3298
+ return completeRpcCategory(first, numComplete, endsWithDot, currentWord, chainFromFlag);
3299
+ }
2512
3300
  if (numComplete === 1 && endsWithDot) {
2513
3301
  const chainName = chainFromFlag;
2514
3302
  if (!chainName)
@@ -2568,6 +3356,9 @@ async function completeDotpath(currentWord, config, knownChains, precedingWords)
2568
3356
  if (category === "extensions") {
2569
3357
  return completeExtensionsCategory(`${first}.${completeSegments[1]}`, numComplete - 1, endsWithDot, currentWord, config, chainName);
2570
3358
  }
3359
+ if (category === "rpc") {
3360
+ return completeRpcCategory(`${first}.${completeSegments[1]}`, numComplete - 1, endsWithDot, currentWord, chainName);
3361
+ }
2571
3362
  const pallets = await loadPallets(config, chainName);
2572
3363
  if (!pallets)
2573
3364
  return [];
@@ -2641,6 +3432,24 @@ async function completeExtensionsCategory(prefix, numComplete, endsWithDot, curr
2641
3432
  }
2642
3433
  return [];
2643
3434
  }
3435
+ async function completeRpcCategory(prefix, numComplete, endsWithDot, currentWord, chainNameOverride) {
3436
+ let names;
3437
+ if (chainNameOverride) {
3438
+ const cached = await loadRpcMethods(chainNameOverride);
3439
+ names = cached?.methods ?? Object.keys(RPC_REGISTRY);
3440
+ } else {
3441
+ names = Object.keys(RPC_REGISTRY);
3442
+ }
3443
+ if (numComplete === 1 && endsWithDot) {
3444
+ const candidates = names.map((n) => `${prefix}.${n}`);
3445
+ return filterPrefix(candidates, currentWord.slice(0, -1));
3446
+ }
3447
+ if (numComplete === 1 && !endsWithDot) {
3448
+ const candidates = names.map((n) => `${prefix}.${n}`);
3449
+ return filterPrefix(candidates, currentWord);
3450
+ }
3451
+ return [];
3452
+ }
2644
3453
  var CATEGORIES2, CATEGORY_ALIASES2, NAMED_COMMANDS, CHAIN_SUBCOMMANDS, ACCOUNT_SUBCOMMANDS, GLOBAL_OPTIONS, TX_OPTIONS, QUERY_OPTIONS;
2645
3454
  var init_complete = __esm(() => {
2646
3455
  init_accounts_store();
@@ -2648,7 +3457,17 @@ var init_complete = __esm(() => {
2648
3457
  init_accounts();
2649
3458
  init_hash();
2650
3459
  init_metadata();
2651
- CATEGORIES2 = ["query", "tx", "const", "events", "errors", "apis", "extensions"];
3460
+ init_rpc_registry();
3461
+ CATEGORIES2 = [
3462
+ "query",
3463
+ "tx",
3464
+ "const",
3465
+ "events",
3466
+ "errors",
3467
+ "apis",
3468
+ "extensions",
3469
+ "rpc"
3470
+ ];
2652
3471
  CATEGORY_ALIASES2 = {
2653
3472
  query: "query",
2654
3473
  tx: "tx",
@@ -2663,10 +3482,11 @@ var init_complete = __esm(() => {
2663
3482
  api: "apis",
2664
3483
  extensions: "extensions",
2665
3484
  extension: "extensions",
2666
- ext: "extensions"
3485
+ ext: "extensions",
3486
+ rpc: "rpc"
2667
3487
  };
2668
- NAMED_COMMANDS = ["chain", "account", "inspect", "hash", "sign", "parachain", "completions"];
2669
- CHAIN_SUBCOMMANDS = ["add", "remove", "update", "list"];
3488
+ NAMED_COMMANDS = ["chain", "account", "inspect", "hash", "sign", "completions"];
3489
+ CHAIN_SUBCOMMANDS = ["add", "info", "list", "remove", "update"];
2670
3490
  ACCOUNT_SUBCOMMANDS = [
2671
3491
  "add",
2672
3492
  "create",
@@ -2697,23 +3517,94 @@ var init_complete = __esm(() => {
2697
3517
  // src/cli.ts
2698
3518
  import cac from "cac";
2699
3519
  // package.json
2700
- var version = "1.16.0";
3520
+ var version = "1.18.0";
2701
3521
 
2702
3522
  // src/commands/account.ts
2703
3523
  init_accounts_store();
2704
3524
  init_accounts();
2705
3525
  init_output();
2706
3526
  import { readFile as readFile3, writeFile as writeFile3 } from "node:fs/promises";
3527
+
3528
+ // src/core/pallet.ts
3529
+ init_errors();
3530
+ var MODL_PREFIX = new Uint8Array([109, 111, 100, 108]);
3531
+ var PALLET_ID_BYTES = 8;
3532
+ function derivePalletAccount(palletId) {
3533
+ if (palletId.length !== PALLET_ID_BYTES) {
3534
+ throw new CliError(`PalletId must be exactly ${PALLET_ID_BYTES} bytes (got ${palletId.length}).`);
3535
+ }
3536
+ const result = new Uint8Array(32);
3537
+ result.set(MODL_PREFIX, 0);
3538
+ result.set(palletId, 4);
3539
+ return result;
3540
+ }
3541
+ function parsePalletId(input) {
3542
+ if (input.startsWith("0x") || input.startsWith("0X")) {
3543
+ const hex = input.slice(2);
3544
+ if (hex.length !== PALLET_ID_BYTES * 2) {
3545
+ throw new CliError(`Invalid PalletId hex "${input}". Must be 0x followed by exactly ${PALLET_ID_BYTES * 2} hex characters.`);
3546
+ }
3547
+ if (!/^[0-9a-fA-F]+$/.test(hex)) {
3548
+ throw new CliError(`Invalid PalletId hex "${input}". Contains non-hex characters.`);
3549
+ }
3550
+ const bytes2 = new Uint8Array(PALLET_ID_BYTES);
3551
+ for (let i = 0;i < PALLET_ID_BYTES; i++) {
3552
+ bytes2[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
3553
+ }
3554
+ return bytes2;
3555
+ }
3556
+ if (input.length !== PALLET_ID_BYTES) {
3557
+ throw new CliError(`Invalid PalletId "${input}". Must be ${PALLET_ID_BYTES} ASCII characters or 0x-prefixed hex.`);
3558
+ }
3559
+ const bytes = new Uint8Array(PALLET_ID_BYTES);
3560
+ for (let i = 0;i < PALLET_ID_BYTES; i++) {
3561
+ const code = input.charCodeAt(i);
3562
+ if (code > 127) {
3563
+ throw new CliError(`Invalid PalletId "${input}". ASCII form must contain only ASCII bytes.`);
3564
+ }
3565
+ bytes[i] = code;
3566
+ }
3567
+ return bytes;
3568
+ }
3569
+ function formatPalletId(palletId) {
3570
+ const allPrintable = palletId.every((b) => b >= 32 && b <= 126);
3571
+ if (allPrintable) {
3572
+ return Array.from(palletId, (b) => String.fromCharCode(b)).join("");
3573
+ }
3574
+ return `0x${Array.from(palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`;
3575
+ }
3576
+
3577
+ // src/core/parachain.ts
3578
+ var SOVEREIGN_ACCOUNT_TYPES = ["child", "sibling"];
3579
+ var PREFIXES = {
3580
+ child: new Uint8Array([112, 97, 114, 97]),
3581
+ sibling: new Uint8Array([115, 105, 98, 108])
3582
+ };
3583
+ function deriveSovereignAccount(paraId, type) {
3584
+ const result = new Uint8Array(32);
3585
+ result.set(PREFIXES[type], 0);
3586
+ new DataView(result.buffer).setUint32(4, paraId, true);
3587
+ return result;
3588
+ }
3589
+ function isValidParaId(value) {
3590
+ return Number.isInteger(value) && value >= 0 && value <= 4294967295;
3591
+ }
3592
+
3593
+ // src/commands/account.ts
2707
3594
  var ACCOUNT_HELP = `
2708
3595
  ${BOLD}Usage:${RESET}
2709
3596
  $ dot account add <name> <ss58|hex> Add a watch-only address (no secret)
2710
3597
  $ dot account add <name> --secret <s> [--path <derivation>] Import from BIP39 mnemonic
2711
3598
  $ dot account add <name> --env <VAR> [--path <derivation>] Import account backed by env variable
3599
+ $ dot account add <name> --parachain <id> --parachain-type <t> Derive a parachain sovereign (t = child|sibling)
3600
+ $ dot account add <name> --pallet-id <8 chars or 0x hex> Derive a pallet sovereign (e.g. py/trsry)
2712
3601
  $ dot account create|new <name> [--path <derivation>] Create a new account
2713
3602
  $ dot account import <file> Batch-import accounts from a file
2714
3603
  $ dot account export [names...] Export accounts to stdout
2715
3604
  $ dot account derive <source> <new-name> --path <derivation> Derive a child account
2716
3605
  $ dot account inspect <input> [--prefix <N>] [--show-secret] Inspect an account/address/key
3606
+ $ dot account inspect --pallet-id <id> [--prefix <N>] Derive a pallet sovereign (no save — script-friendly)
3607
+ $ dot account inspect --parachain <id> --parachain-type <t> Derive a parachain sovereign (no save — script-friendly)
2717
3608
  $ dot account list List all accounts
2718
3609
  $ dot account remove|delete <name> [name2] ... Remove stored account(s)
2719
3610
 
@@ -2721,6 +3612,10 @@ ${BOLD}Examples:${RESET}
2721
3612
  $ dot account add treasury 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
2722
3613
  $ dot account add treasury --secret "word1 word2 ... word12"
2723
3614
  $ dot account add ci-signer --env MY_SECRET --path //ci
3615
+ $ dot account add Treasury --pallet-id py/trsry
3616
+ $ dot account add Bounties --pallet-id 0x70792f626f756e74
3617
+ $ dot account add People --parachain 1004 --parachain-type child
3618
+ $ dot account add People-Sibling --parachain 1004 --parachain-type sibling
2724
3619
  $ dot account create my-validator
2725
3620
  $ dot account create my-staking --path //staking
2726
3621
  $ dot account create multi --path //polkadot//0/wallet
@@ -2736,6 +3631,8 @@ ${BOLD}Examples:${RESET}
2736
3631
  $ dot account inspect dave --show-secret
2737
3632
  $ dot account inspect 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
2738
3633
  $ dot account inspect 0xd435...a27d --prefix 0
3634
+ $ dot account inspect --pallet-id py/trsry --prefix 0
3635
+ $ dot account inspect --parachain 1004 --parachain-type child
2739
3636
  $ dot account list
2740
3637
  $ dot account remove my-validator stale-key
2741
3638
 
@@ -2744,7 +3641,7 @@ ${YELLOW}Note: Secrets are stored unencrypted in ~/.polkadot/accounts.json.
2744
3641
  Hex seed import (0x...) is not supported via CLI.${RESET}
2745
3642
  `.trimStart();
2746
3643
  function registerAccountCommands(cli) {
2747
- cli.command("account [action] [...names]", "Manage local accounts (create, import, list, remove, export)").alias("accounts").option("--secret <value>", "Secret key (mnemonic or hex seed) for import").option("--env <varName>", "Environment variable name holding the secret").option("--path <derivation>", "Derivation path (e.g. //staking, //polkadot//0/wallet)").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").option("--file <path>", "Input/output file for batch import/export").option("--overwrite", "Overwrite existing accounts on batch import").option("--dry-run", "Preview batch import without applying changes").option("--include-secrets", "Include secrets in export (redacted by default)").option("--watch-only", "Export only watch-only accounts").option("--show-secret", "Reveal the 64-byte sr25519 expanded private key (inspect only)").action(async (action, names, opts) => {
3644
+ cli.command("account [action] [...names]", "Manage local accounts (create, import, list, remove, export)").alias("accounts").option("--secret <value>", "Secret key (mnemonic or hex seed) for import").option("--env <varName>", "Environment variable name holding the secret").option("--path <derivation>", "Derivation path (e.g. //staking, //polkadot//0/wallet)").option("--parachain <id>", "Derive a parachain sovereign account (requires --parachain-type)").option("--parachain-type <type>", "Parachain sovereign type: child or sibling").option("--pallet-id <id>", "Derive a pallet sovereign account from an 8-byte PalletId").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").option("--file <path>", "Input/output file for batch import/export").option("--overwrite", "Overwrite existing accounts on batch import").option("--dry-run", "Preview batch import without applying changes").option("--include-secrets", "Include secrets in export (redacted by default)").option("--watch-only", "Export only watch-only accounts").option("--show-secret", "Reveal the 64-byte sr25519 expanded private key (inspect only)").action(async (action, names, opts) => {
2748
3645
  if (!action) {
2749
3646
  if (process.argv[2] === "accounts")
2750
3647
  return accountList(opts);
@@ -2756,8 +3653,13 @@ function registerAccountCommands(cli) {
2756
3653
  case "create":
2757
3654
  return accountCreate(names[0], opts);
2758
3655
  case "add":
2759
- if (opts.secret || opts.env)
3656
+ if (opts.secret || opts.env) {
3657
+ const hasDerivation = opts.parachain != null || opts.palletId != null || process.argv.includes("--parachain") || process.argv.includes("--pallet-id") || process.argv.some((a) => a.startsWith("--parachain=") || a.startsWith("--pallet-id="));
3658
+ if (hasDerivation) {
3659
+ throw new Error("Derivation flags (--parachain, --pallet-id) cannot be combined with --secret or --env. A derived sovereign account has no secret.");
3660
+ }
2760
3661
  return accountImport(names[0], opts);
3662
+ }
2761
3663
  return accountAddWatchOnly(names[0], names[1], opts);
2762
3664
  case "import":
2763
3665
  return accountBatchImport(names[0], opts);
@@ -2913,10 +3815,16 @@ async function accountAddWatchOnly(name, address, opts = {}) {
2913
3815
  console.error("Usage: dot account add <name> <ss58-address|0x-public-key>");
2914
3816
  process.exit(1);
2915
3817
  }
2916
- if (!address) {
3818
+ const sovereignSource = resolveSovereignSource(opts);
3819
+ if (sovereignSource && address) {
3820
+ throw new Error("Cannot combine a positional address with --parachain or --pallet-id. Pass either an address OR a derivation flag, not both.");
3821
+ }
3822
+ if (!sovereignSource && !address) {
2917
3823
  console.error(`Address is required.
2918
3824
  `);
2919
3825
  console.error("Usage: dot account add <name> <ss58-address|0x-public-key>");
3826
+ console.error(" dot account add <name> --parachain <id> --parachain-type <child|sibling>");
3827
+ console.error(" dot account add <name> --pallet-id <8 chars or 0x hex>");
2920
3828
  process.exit(1);
2921
3829
  }
2922
3830
  if (isDevAccount(name)) {
@@ -2927,7 +3835,10 @@ async function accountAddWatchOnly(name, address, opts = {}) {
2927
3835
  throw new Error(`Account "${name}" already exists.`);
2928
3836
  }
2929
3837
  let hexPub;
2930
- if (isHexPublicKey(address)) {
3838
+ if (sovereignSource) {
3839
+ const accountId = sovereignSource.kind === "parachain" ? deriveSovereignAccount(sovereignSource.paraId, sovereignSource.type) : derivePalletAccount(sovereignSource.palletId);
3840
+ hexPub = publicKeyToHex(accountId);
3841
+ } else if (isHexPublicKey(address)) {
2931
3842
  hexPub = address;
2932
3843
  } else {
2933
3844
  try {
@@ -2937,21 +3848,99 @@ async function accountAddWatchOnly(name, address, opts = {}) {
2937
3848
  throw new Error(`Invalid address "${address}". Expected an SS58 address or 0x-prefixed 32-byte hex public key.`);
2938
3849
  }
2939
3850
  }
3851
+ let persistedSource;
3852
+ if (sovereignSource?.kind === "pallet") {
3853
+ persistedSource = {
3854
+ kind: "pallet",
3855
+ palletId: `0x${Array.from(sovereignSource.palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`
3856
+ };
3857
+ } else if (sovereignSource?.kind === "parachain") {
3858
+ persistedSource = {
3859
+ kind: "parachain",
3860
+ paraId: sovereignSource.paraId,
3861
+ type: sovereignSource.type
3862
+ };
3863
+ }
2940
3864
  accountsFile.accounts.push({
2941
3865
  name,
2942
3866
  publicKey: hexPub,
2943
- derivationPath: ""
3867
+ derivationPath: "",
3868
+ ...persistedSource ? { source: persistedSource } : {}
2944
3869
  });
2945
3870
  await saveAccounts(accountsFile);
2946
3871
  if (isJsonOutput(opts)) {
2947
- console.log(formatJson({ name, address: toSs58(hexPub), watchOnly: true }));
3872
+ const payload = {
3873
+ name,
3874
+ address: toSs58(hexPub),
3875
+ watchOnly: true
3876
+ };
3877
+ if (sovereignSource?.kind === "parachain") {
3878
+ payload.derivation = {
3879
+ kind: "parachain",
3880
+ paraId: sovereignSource.paraId,
3881
+ type: sovereignSource.type
3882
+ };
3883
+ } else if (sovereignSource?.kind === "pallet") {
3884
+ payload.derivation = {
3885
+ kind: "pallet",
3886
+ palletId: formatPalletId(sovereignSource.palletId),
3887
+ palletIdHex: `0x${Array.from(sovereignSource.palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`
3888
+ };
3889
+ }
3890
+ console.log(formatJson(payload));
2948
3891
  return;
2949
3892
  }
2950
3893
  printHeading("Account Added (watch-only)");
2951
3894
  console.log(` ${BOLD}Name:${RESET} ${name}`);
2952
3895
  console.log(` ${BOLD}Address:${RESET} ${toSs58(hexPub)}`);
3896
+ if (sovereignSource?.kind === "parachain") {
3897
+ console.log(` ${BOLD}Source:${RESET} parachain ${sovereignSource.paraId} (${sovereignSource.type} sovereign)`);
3898
+ } else if (sovereignSource?.kind === "pallet") {
3899
+ const display = formatPalletId(sovereignSource.palletId);
3900
+ const hex = `0x${Array.from(sovereignSource.palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`;
3901
+ console.log(` ${BOLD}Source:${RESET} pallet ${display} (${hex})`);
3902
+ }
2953
3903
  console.log();
2954
3904
  }
3905
+ function rawArgValue(flag) {
3906
+ const argv = process.argv;
3907
+ for (let i = 0;i < argv.length; i++) {
3908
+ if (argv[i] === flag && i + 1 < argv.length)
3909
+ return argv[i + 1];
3910
+ const prefix = `${flag}=`;
3911
+ if (argv[i]?.startsWith(prefix))
3912
+ return argv[i].slice(prefix.length);
3913
+ }
3914
+ return;
3915
+ }
3916
+ function resolveSovereignSource(opts) {
3917
+ const rawPalletId = rawArgValue("--pallet-id") ?? opts.palletId;
3918
+ const rawParachain = rawArgValue("--parachain") ?? opts.parachain;
3919
+ if (rawParachain != null && rawPalletId != null) {
3920
+ throw new Error("--parachain and --pallet-id are mutually exclusive. Pass only one derivation flag.");
3921
+ }
3922
+ if (rawParachain != null) {
3923
+ const paraId = Number(rawParachain);
3924
+ if (!isValidParaId(paraId)) {
3925
+ throw new Error(`Invalid parachain ID "${rawParachain}". Must be a non-negative integer (0 to 4294967295).`);
3926
+ }
3927
+ if (!opts.parachainType) {
3928
+ throw new Error("--parachain-type is required when --parachain is given. Use --parachain-type child or --parachain-type sibling.");
3929
+ }
3930
+ const type = opts.parachainType.toLowerCase();
3931
+ if (type !== "child" && type !== "sibling") {
3932
+ throw new Error(`Unknown parachain account type "${opts.parachainType}". Valid types: child, sibling.`);
3933
+ }
3934
+ return { kind: "parachain", paraId, type };
3935
+ }
3936
+ if (rawPalletId != null) {
3937
+ return { kind: "pallet", palletId: parsePalletId(String(rawPalletId)) };
3938
+ }
3939
+ if (opts.parachainType != null) {
3940
+ throw new Error("--parachain-type requires --parachain.");
3941
+ }
3942
+ return;
3943
+ }
2955
3944
  async function accountDerive(sourceName, newName, opts) {
2956
3945
  if (!sourceName) {
2957
3946
  console.error(`Source account name is required.
@@ -3035,69 +4024,134 @@ async function accountDerive(sourceName, newName, opts) {
3035
4024
  console.log();
3036
4025
  }
3037
4026
  }
4027
+ function resolveAddress(account) {
4028
+ if (isWatchOnly(account)) {
4029
+ return account.publicKey ? toSs58(account.publicKey) : "n/a";
4030
+ }
4031
+ if (account.secret !== undefined && isEnvSecret(account.secret)) {
4032
+ const pubKey = account.publicKey || tryDerivePublicKey(account.secret.env, account.derivationPath) || "";
4033
+ return pubKey ? toSs58(pubKey) : "n/a";
4034
+ }
4035
+ return toSs58(account.publicKey);
4036
+ }
4037
+ function buildAttributes(account) {
4038
+ const attrs = [];
4039
+ if (account.derivationPath)
4040
+ attrs.push({ label: "path", value: account.derivationPath });
4041
+ if (account.secret !== undefined && isEnvSecret(account.secret)) {
4042
+ attrs.push({ label: "env", value: `$${account.secret.env}` });
4043
+ }
4044
+ if (account.source) {
4045
+ if (account.source.kind === "pallet") {
4046
+ const bytes = parsePalletId(account.source.palletId);
4047
+ attrs.push({
4048
+ label: "pallet-id",
4049
+ value: `${formatPalletId(bytes)} (${account.source.palletId})`
4050
+ });
4051
+ } else {
4052
+ attrs.push({ label: "parachain", value: String(account.source.paraId) });
4053
+ attrs.push({ label: "parachain-type", value: account.source.type });
4054
+ }
4055
+ }
4056
+ return attrs;
4057
+ }
4058
+ function buildRow(account) {
4059
+ return {
4060
+ account,
4061
+ kind: classifyAccount(account),
4062
+ address: resolveAddress(account),
4063
+ attributes: buildAttributes(account)
4064
+ };
4065
+ }
4066
+ var SECTION_ORDER = [
4067
+ { kind: "signer", title: "Signers" },
4068
+ { kind: "watch-only", title: "Watch-only" },
4069
+ { kind: "pallet", title: "Pallet Sovereigns" },
4070
+ { kind: "parachain", title: "Parachain Sovereigns" }
4071
+ ];
4072
+ function printAccountSection(title, rows) {
4073
+ if (rows.length === 0)
4074
+ return;
4075
+ const nameWidth = Math.max(...rows.map((r) => r.name.length));
4076
+ printHeading(title);
4077
+ for (const row of rows) {
4078
+ const namePad = row.name.padEnd(nameWidth);
4079
+ console.log(` ${CYAN}${namePad}${RESET} ${row.address}`);
4080
+ if (row.attributes.length === 0)
4081
+ continue;
4082
+ const labelWidth = Math.max(...row.attributes.map((a) => a.label.length)) + 1;
4083
+ for (let i = 0;i < row.attributes.length; i++) {
4084
+ const isLast = i === row.attributes.length - 1;
4085
+ const connector = isLast ? "└─" : "├─";
4086
+ const labelText = `${row.attributes[i].label}:`.padEnd(labelWidth + 1);
4087
+ console.log(` ${DIM}${connector}${RESET} ${DIM}${labelText}${RESET}${row.attributes[i].value}`);
4088
+ }
4089
+ }
4090
+ }
3038
4091
  async function accountList(opts = {}) {
3039
4092
  const accountsFile = await loadAccounts();
3040
4093
  if (isJsonOutput(opts)) {
3041
4094
  const dev = DEV_NAMES.map((name) => ({
3042
4095
  name: name.charAt(0).toUpperCase() + name.slice(1),
3043
- address: getDevAddress(name)
4096
+ address: getDevAddress(name),
4097
+ kind: "dev"
3044
4098
  }));
3045
4099
  const stored = accountsFile.accounts.map((account) => {
3046
- let address;
3047
- if (isWatchOnly(account)) {
3048
- address = account.publicKey ? toSs58(account.publicKey) : undefined;
3049
- } else if (account.secret !== undefined && isEnvSecret(account.secret)) {
3050
- let pubKey = account.publicKey;
3051
- if (!pubKey) {
3052
- pubKey = tryDerivePublicKey(account.secret.env, account.derivationPath) ?? "";
3053
- }
3054
- address = pubKey ? toSs58(pubKey) : undefined;
3055
- } else {
3056
- address = toSs58(account.publicKey);
3057
- }
3058
- return {
4100
+ const kind = classifyAccount(account);
4101
+ const entry = {
3059
4102
  name: account.name,
3060
- address,
3061
- derivationPath: account.derivationPath || undefined,
3062
- watchOnly: isWatchOnly(account),
3063
- env: account.secret !== undefined && isEnvSecret(account.secret) ? account.secret.env : undefined
4103
+ address: resolveAddress(account),
4104
+ kind,
4105
+ watchOnly: isWatchOnly(account)
3064
4106
  };
4107
+ if (account.derivationPath)
4108
+ entry.derivationPath = account.derivationPath;
4109
+ if (account.secret !== undefined && isEnvSecret(account.secret)) {
4110
+ entry.env = account.secret.env;
4111
+ }
4112
+ if (account.source) {
4113
+ if (account.source.kind === "pallet") {
4114
+ const bytes = parsePalletId(account.source.palletId);
4115
+ entry.source = {
4116
+ kind: "pallet",
4117
+ palletId: formatPalletId(bytes),
4118
+ palletIdHex: account.source.palletId
4119
+ };
4120
+ } else {
4121
+ entry.source = account.source;
4122
+ }
4123
+ }
4124
+ return entry;
3065
4125
  });
3066
4126
  console.log(formatJson({ dev, stored }));
3067
4127
  return;
3068
4128
  }
3069
- printHeading("Dev Accounts");
3070
- for (const name of DEV_NAMES) {
3071
- const display = name.charAt(0).toUpperCase() + name.slice(1);
3072
- const address = getDevAddress(name);
3073
- printItem(display, address);
4129
+ const devRows = DEV_NAMES.map((name) => ({
4130
+ name: name.charAt(0).toUpperCase() + name.slice(1),
4131
+ address: getDevAddress(name),
4132
+ attributes: []
4133
+ }));
4134
+ printAccountSection("Dev Accounts", devRows);
4135
+ const buckets = new Map;
4136
+ for (const account of accountsFile.accounts) {
4137
+ const row = buildRow(account);
4138
+ const arr = buckets.get(row.kind) ?? [];
4139
+ arr.push(row);
4140
+ buckets.set(row.kind, arr);
4141
+ }
4142
+ for (const { kind, title } of SECTION_ORDER) {
4143
+ const rows = buckets.get(kind);
4144
+ if (!rows || rows.length === 0)
4145
+ continue;
4146
+ printAccountSection(title, rows.map((r) => ({
4147
+ name: r.account.name,
4148
+ address: r.address,
4149
+ attributes: r.attributes
4150
+ })));
3074
4151
  }
3075
- if (accountsFile.accounts.length > 0) {
3076
- printHeading("Stored Accounts");
3077
- for (const account of accountsFile.accounts) {
3078
- let displayName = account.name;
3079
- if (account.derivationPath) {
3080
- displayName += ` (${account.derivationPath})`;
3081
- }
3082
- let address;
3083
- if (isWatchOnly(account)) {
3084
- displayName += " (watch-only)";
3085
- address = account.publicKey ? toSs58(account.publicKey) : "n/a";
3086
- } else if (account.secret !== undefined && isEnvSecret(account.secret)) {
3087
- displayName += ` (env: ${account.secret.env})`;
3088
- let pubKey = account.publicKey;
3089
- if (!pubKey) {
3090
- pubKey = tryDerivePublicKey(account.secret.env, account.derivationPath) ?? "";
3091
- }
3092
- address = pubKey ? toSs58(pubKey) : "n/a";
3093
- } else {
3094
- address = toSs58(account.publicKey);
3095
- }
3096
- printItem(displayName, address);
3097
- }
3098
- } else {
4152
+ if (accountsFile.accounts.length === 0) {
3099
4153
  printHeading("Stored Accounts");
3100
- console.log(" (none)");
4154
+ console.log(` ${DIM}(none)${RESET}`);
3101
4155
  }
3102
4156
  console.log();
3103
4157
  }
@@ -3145,10 +4199,20 @@ async function accountRemove(names, opts = {}) {
3145
4199
  }
3146
4200
  }
3147
4201
  async function accountInspect(input, opts) {
3148
- if (!input) {
4202
+ const sovereignSource = resolveSovereignSource({
4203
+ parachain: opts.parachain,
4204
+ parachainType: opts.parachainType,
4205
+ palletId: opts.palletId
4206
+ });
4207
+ if (sovereignSource && input) {
4208
+ throw new Error("Cannot combine a positional input with --parachain or --pallet-id. Pass either an existing-account input OR a derivation flag, not both.");
4209
+ }
4210
+ if (!sovereignSource && !input) {
3149
4211
  console.error(`Input is required.
3150
4212
  `);
3151
4213
  console.error("Usage: dot account inspect <name|ss58-address|0x-public-key> [--prefix <N>]");
4214
+ console.error(" dot account inspect --pallet-id <id> [--prefix <N>]");
4215
+ console.error(" dot account inspect --parachain <id> --parachain-type <child|sibling> [--prefix <N>]");
3152
4216
  process.exit(1);
3153
4217
  }
3154
4218
  const prefix = opts.prefix != null ? Number(opts.prefix) : 42;
@@ -3160,11 +4224,32 @@ async function accountInspect(input, opts) {
3160
4224
  let publicKeyHex;
3161
4225
  let bandersnatch;
3162
4226
  let hasSecret = false;
3163
- if (isDevAccount(input)) {
4227
+ let storedAccount;
4228
+ let isDev = false;
4229
+ let virtualSource;
4230
+ if (sovereignSource) {
4231
+ if (sovereignSource.kind === "pallet") {
4232
+ const accountId = derivePalletAccount(sovereignSource.palletId);
4233
+ publicKeyHex = publicKeyToHex(accountId);
4234
+ virtualSource = {
4235
+ kind: "pallet",
4236
+ palletIdHex: `0x${Array.from(sovereignSource.palletId, (b) => b.toString(16).padStart(2, "0")).join("")}`
4237
+ };
4238
+ } else {
4239
+ const accountId = deriveSovereignAccount(sovereignSource.paraId, sovereignSource.type);
4240
+ publicKeyHex = publicKeyToHex(accountId);
4241
+ virtualSource = {
4242
+ kind: "parachain",
4243
+ paraId: sovereignSource.paraId,
4244
+ type: sovereignSource.type
4245
+ };
4246
+ }
4247
+ } else if (isDevAccount(input)) {
3164
4248
  name = input.charAt(0).toUpperCase() + input.slice(1).toLowerCase();
3165
4249
  const devAddr = getDevAddress(input);
3166
4250
  publicKeyHex = publicKeyToHex(fromSs58(devAddr));
3167
4251
  hasSecret = true;
4252
+ isDev = true;
3168
4253
  } else {
3169
4254
  const accountsFile = await loadAccounts();
3170
4255
  const account = findAccount(accountsFile, input);
@@ -3172,6 +4257,7 @@ async function accountInspect(input, opts) {
3172
4257
  name = account.name;
3173
4258
  bandersnatch = account.bandersnatch;
3174
4259
  hasSecret = account.secret !== undefined;
4260
+ storedAccount = account;
3175
4261
  if (account.publicKey) {
3176
4262
  publicKeyHex = account.publicKey;
3177
4263
  } else if (account.secret !== undefined && isEnvSecret(account.secret)) {
@@ -3215,10 +4301,74 @@ async function accountInspect(input, opts) {
3215
4301
  process.exit(1);
3216
4302
  }
3217
4303
  }
4304
+ let kindLabel;
4305
+ let sourceLine;
4306
+ let derivationLine;
4307
+ let envLine;
4308
+ if (virtualSource?.kind === "pallet") {
4309
+ kindLabel = "pallet sovereign";
4310
+ const bytes = parsePalletId(virtualSource.palletIdHex);
4311
+ sourceLine = `PalletId ${formatPalletId(bytes)} (${virtualSource.palletIdHex})`;
4312
+ } else if (virtualSource?.kind === "parachain") {
4313
+ kindLabel = `parachain sovereign (${virtualSource.type})`;
4314
+ sourceLine = `parachain ${virtualSource.paraId}`;
4315
+ } else if (isDev) {
4316
+ kindLabel = "dev";
4317
+ } else if (storedAccount) {
4318
+ const k = classifyAccount(storedAccount);
4319
+ if (k === "pallet" && storedAccount.source?.kind === "pallet") {
4320
+ kindLabel = "pallet sovereign";
4321
+ const bytes = parsePalletId(storedAccount.source.palletId);
4322
+ sourceLine = `PalletId ${formatPalletId(bytes)} (${storedAccount.source.palletId})`;
4323
+ } else if (k === "parachain" && storedAccount.source?.kind === "parachain") {
4324
+ kindLabel = `parachain sovereign (${storedAccount.source.type})`;
4325
+ sourceLine = `parachain ${storedAccount.source.paraId}`;
4326
+ } else if (k === "signer") {
4327
+ kindLabel = "signer";
4328
+ } else {
4329
+ kindLabel = "watch-only";
4330
+ }
4331
+ if (storedAccount.derivationPath)
4332
+ derivationLine = storedAccount.derivationPath;
4333
+ if (storedAccount.secret !== undefined && isEnvSecret(storedAccount.secret)) {
4334
+ envLine = `$${storedAccount.secret.env}`;
4335
+ }
4336
+ }
3218
4337
  if (isJsonOutput(opts)) {
3219
4338
  const result = { publicKey: publicKeyHex, ss58, prefix };
3220
4339
  if (name)
3221
4340
  result.name = name;
4341
+ if (kindLabel)
4342
+ result.kind = kindLabel;
4343
+ if (virtualSource?.kind === "pallet") {
4344
+ const bytes = parsePalletId(virtualSource.palletIdHex);
4345
+ result.source = {
4346
+ kind: "pallet",
4347
+ palletId: formatPalletId(bytes),
4348
+ palletIdHex: virtualSource.palletIdHex
4349
+ };
4350
+ } else if (virtualSource?.kind === "parachain") {
4351
+ result.source = {
4352
+ kind: "parachain",
4353
+ paraId: virtualSource.paraId,
4354
+ type: virtualSource.type
4355
+ };
4356
+ } else if (storedAccount?.source) {
4357
+ if (storedAccount.source.kind === "pallet") {
4358
+ const bytes = parsePalletId(storedAccount.source.palletId);
4359
+ result.source = {
4360
+ kind: "pallet",
4361
+ palletId: formatPalletId(bytes),
4362
+ palletIdHex: storedAccount.source.palletId
4363
+ };
4364
+ } else {
4365
+ result.source = storedAccount.source;
4366
+ }
4367
+ }
4368
+ if (derivationLine)
4369
+ result.derivationPath = derivationLine;
4370
+ if (envLine)
4371
+ result.env = envLine.replace(/^\$/, "");
3222
4372
  if (bandersnatch && Object.keys(bandersnatch).length > 0)
3223
4373
  result.bandersnatch = bandersnatch;
3224
4374
  if (privateKeyHex)
@@ -3228,8 +4378,16 @@ async function accountInspect(input, opts) {
3228
4378
  printHeading("Account Info");
3229
4379
  if (name)
3230
4380
  console.log(` ${BOLD}Name:${RESET} ${name}`);
4381
+ if (kindLabel)
4382
+ console.log(` ${BOLD}Kind:${RESET} ${kindLabel}`);
3231
4383
  console.log(` ${BOLD}Public Key:${RESET} ${publicKeyHex}`);
3232
4384
  console.log(` ${BOLD}SS58:${RESET} ${ss58}`);
4385
+ if (sourceLine)
4386
+ console.log(` ${BOLD}Source:${RESET} ${sourceLine}`);
4387
+ if (derivationLine)
4388
+ console.log(` ${BOLD}Derivation:${RESET} ${derivationLine}`);
4389
+ if (envLine)
4390
+ console.log(` ${BOLD}Env:${RESET} ${envLine}`);
3233
4391
  if (bandersnatch && Object.keys(bandersnatch).length > 0) {
3234
4392
  const entries = Object.entries(bandersnatch);
3235
4393
  for (let i = 0;i < entries.length; i++) {
@@ -3533,6 +4691,53 @@ init_client();
3533
4691
  init_metadata();
3534
4692
  init_output();
3535
4693
  import { readFile as readFile4, writeFile as writeFile4 } from "node:fs/promises";
4694
+
4695
+ // src/core/rpc.ts
4696
+ init_errors();
4697
+ import { createClient as createSubstrateClient } from "@polkadot-api/substrate-client";
4698
+ import { getWsProvider as getWsProvider2 } from "polkadot-api/ws";
4699
+ function suppressProviderNoise2() {
4700
+ const origError = console.error;
4701
+ console.error = (...args) => {
4702
+ if (typeof args[0] === "string" && args[0].includes("Unable to connect"))
4703
+ return;
4704
+ origError(...args);
4705
+ };
4706
+ return () => {
4707
+ console.error = origError;
4708
+ };
4709
+ }
4710
+ async function rpcRequest(rpcUrl, method, params, timeoutMs = 30000) {
4711
+ const restoreConsole = suppressProviderNoise2();
4712
+ const provider = getWsProvider2(rpcUrl, { timeout: 1e4 });
4713
+ const client = createSubstrateClient(provider);
4714
+ const controller = new AbortController;
4715
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
4716
+ try {
4717
+ return await client.request(method, params, controller.signal);
4718
+ } catch (err) {
4719
+ if (err instanceof Error && /Unable to connect/i.test(err.message)) {
4720
+ throw new ConnectionError(`Could not reach RPC ${Array.isArray(rpcUrl) ? rpcUrl.join(", ") : rpcUrl}: ${err.message}`);
4721
+ }
4722
+ throw err;
4723
+ } finally {
4724
+ clearTimeout(timer);
4725
+ try {
4726
+ client.destroy();
4727
+ } catch {}
4728
+ setTimeout(restoreConsole, 100);
4729
+ }
4730
+ }
4731
+ async function fetchRpcMethods(rpcUrl) {
4732
+ const result = await rpcRequest(rpcUrl, "rpc_methods", []);
4733
+ if (!result || !Array.isArray(result.methods)) {
4734
+ throw new ConnectionError("Node returned an unexpected response for rpc_methods (no methods array).");
4735
+ }
4736
+ return { methods: result.methods, version: result.version ?? 1 };
4737
+ }
4738
+
4739
+ // src/commands/chain.ts
4740
+ init_rpc_registry();
3536
4741
  var CHAIN_HELP = `
3537
4742
  ${BOLD}Usage:${RESET}
3538
4743
  $ dot chain add <name> --rpc <url> Add a chain via WebSocket RPC
@@ -3540,6 +4745,8 @@ ${BOLD}Usage:${RESET}
3540
4745
  $ dot chain update <name> Re-fetch metadata for a chain
3541
4746
  $ dot chain update --all Re-fetch metadata for all configured chains
3542
4747
  $ dot chain list List configured chains
4748
+ $ dot chain info <name> Show details for a single chain
4749
+ $ dot chain <name> Shortcut for \`chain info <name>\`
3543
4750
  $ dot chain export [names...] Export chain configuration to stdout
3544
4751
  $ dot chain import <file> Import chain configuration from a file
3545
4752
 
@@ -3549,6 +4756,9 @@ ${BOLD}Examples:${RESET}
3549
4756
  $ dot chain add my-para --rpc wss://rpc.example.com --relay polkadot
3550
4757
  $ dot chain add my-para --rpc wss://rpc.example.com --relay polkadot --parachain-id 2000
3551
4758
  $ dot chain list
4759
+ $ dot chains -v
4760
+ $ dot chain info polkadot
4761
+ $ dot chain polkadot
3552
4762
  $ dot chain update kusama
3553
4763
  $ dot chain update --all
3554
4764
  $ dot chain remove kusama
@@ -3561,7 +4771,7 @@ ${BOLD}Examples:${RESET}
3561
4771
  $ dot chain import my-chains.json --no-metadata
3562
4772
  `.trimStart();
3563
4773
  function registerChainCommands(cli) {
3564
- cli.command("chain [action] [...names]", "Manage chains (add, remove, update, list, export, import)").alias("chains").option("--all", "Update/export all configured chains").option("--relay <name>", "Parent relay chain for this parachain").option("--parachain-id <id>", "Parachain ID (auto-detected if omitted with --relay)").option("--file <path>", "Output/input file for export/import").option("--overwrite", "Overwrite existing chains on import").option("--dry-run", "Preview import without applying changes").option("--no-metadata", "Skip automatic metadata fetch after import").action(async (action, names, opts) => {
4774
+ cli.command("chain [action] [...names]", "Manage chains (add, remove, update, list, export, import)").alias("chains").option("--all", "Update/export all configured chains").option("--relay <name>", "Parent relay chain for this parachain").option("--parachain-id <id>", "Parachain ID (auto-detected if omitted with --relay)").option("--file <path>", "Output/input file for export/import").option("--overwrite", "Overwrite existing chains on import").option("--dry-run", "Preview import without applying changes").option("--no-metadata", "Skip automatic metadata fetch after import").option("-v, --verbose", "Show RPC endpoints in `chains` list output").action(async (action, names, opts) => {
3565
4775
  if (!action) {
3566
4776
  if (process.argv[2] === "chains")
3567
4777
  return chainList(opts);
@@ -3575,20 +4785,39 @@ function registerChainCommands(cli) {
3575
4785
  return chainRemove(names[0], opts);
3576
4786
  case "list":
3577
4787
  return chainList(opts);
4788
+ case "info":
4789
+ return chainInfo(names[0], opts);
3578
4790
  case "update":
3579
4791
  return chainUpdate(names[0], opts);
3580
4792
  case "export":
3581
4793
  return chainExport(names, opts);
3582
4794
  case "import":
3583
4795
  return chainImport(names[0], opts);
3584
- default:
4796
+ default: {
4797
+ const config = await loadConfig();
4798
+ if (findChainName(config, action)) {
4799
+ return chainInfo(action, opts);
4800
+ }
3585
4801
  console.error(`Unknown action "${action}".
3586
4802
  `);
3587
4803
  console.log(CHAIN_HELP);
3588
4804
  process.exit(1);
4805
+ }
3589
4806
  }
3590
4807
  });
3591
4808
  }
4809
+ async function refreshRpcMethods(chainName, rpcUrl, silent = false) {
4810
+ try {
4811
+ const { methods, version: version2 } = await fetchRpcMethods(rpcUrl);
4812
+ await saveRpcMethods(chainName, methods, version2);
4813
+ } catch (err) {
4814
+ if (!silent) {
4815
+ const msg = err instanceof Error ? err.message : String(err);
4816
+ process.stderr.write(`${YELLOW}Warning:${RESET} could not fetch rpc_methods — ${msg}
4817
+ `);
4818
+ }
4819
+ }
4820
+ }
3592
4821
  async function chainAdd(name, opts) {
3593
4822
  if (!name) {
3594
4823
  console.error(`Chain name is required.
@@ -3617,6 +4846,7 @@ async function chainAdd(name, opts) {
3617
4846
  process.stderr.write(`Fetching metadata...
3618
4847
  `);
3619
4848
  await fetchMetadataFromChain(clientHandle, name);
4849
+ await refreshRpcMethods(name, opts.rpc);
3620
4850
  if (opts.relay) {
3621
4851
  const config2 = await loadConfig();
3622
4852
  const relayResolved = findChainName(config2, opts.relay);
@@ -3695,6 +4925,7 @@ async function chainList(opts = {}) {
3695
4925
  console.log(formatJson({ chains }));
3696
4926
  return;
3697
4927
  }
4928
+ const verbose = opts.verbose === true;
3698
4929
  printHeading("Configured Chains");
3699
4930
  const parachainsByRelay = new Map;
3700
4931
  const standalone = [];
@@ -3716,7 +4947,7 @@ async function chainList(opts = {}) {
3716
4947
  for (const relayName of relayNames) {
3717
4948
  const relayConfig = config.chains[relayName];
3718
4949
  if (relayConfig) {
3719
- printChainLine(" ", relayName, relayConfig);
4950
+ printChainLine(" ", relayName, relayConfig, "", verbose);
3720
4951
  }
3721
4952
  const paras = parachainsByRelay.get(relayName) ?? [];
3722
4953
  for (let i = 0;i < paras.length; i++) {
@@ -3724,17 +4955,21 @@ async function chainList(opts = {}) {
3724
4955
  const isLast = i === paras.length - 1;
3725
4956
  const prefix = isLast ? " └─ " : " ├─ ";
3726
4957
  const idSuffix = chainConfig.parachainId != null ? ` ${DIM}[${chainConfig.parachainId}]${RESET}` : "";
3727
- printChainLine(prefix, name, chainConfig, idSuffix);
4958
+ printChainLine(prefix, name, chainConfig, idSuffix, verbose);
3728
4959
  }
3729
4960
  console.log();
3730
4961
  }
3731
4962
  for (const [name, chainConfig] of standalone) {
3732
- printChainLine(" ", name, chainConfig);
4963
+ printChainLine(" ", name, chainConfig, "", verbose);
3733
4964
  }
3734
4965
  if (standalone.length > 0)
3735
4966
  console.log();
3736
4967
  }
3737
- function printChainLine(prefix, name, chainConfig, suffix = "") {
4968
+ function printChainLine(prefix, name, chainConfig, suffix = "", verbose = false) {
4969
+ if (!verbose) {
4970
+ console.log(`${prefix}${CYAN}${name}${RESET}${suffix}`);
4971
+ return;
4972
+ }
3738
4973
  const rpcs = Array.isArray(chainConfig.rpc) ? chainConfig.rpc : [chainConfig.rpc];
3739
4974
  console.log(`${prefix}${CYAN}${name}${RESET}${suffix} ${DIM}${rpcs[0]}${RESET}`);
3740
4975
  const indent = prefix.replace(/[^\s]/g, " ");
@@ -3742,6 +4977,79 @@ function printChainLine(prefix, name, chainConfig, suffix = "") {
3742
4977
  console.log(`${indent} ${DIM}${rpcs[i]}${RESET}`);
3743
4978
  }
3744
4979
  }
4980
+ async function chainInfo(name, opts = {}) {
4981
+ if (!name) {
4982
+ console.error("Usage: dot chain info <name>");
4983
+ process.exit(1);
4984
+ }
4985
+ const config = await loadConfig();
4986
+ const { name: resolved, chain } = resolveChain(config, name);
4987
+ const rpcs = Array.isArray(chain.rpc) ? chain.rpc : [chain.rpc];
4988
+ const parachains = Object.entries(config.chains).filter(([, c]) => c.relay === resolved).map(([n, c]) => ({ name: n, parachainId: c.parachainId }));
4989
+ const fingerprint = await loadMetadataFingerprint(resolved);
4990
+ const rpcCache = await loadRpcMethods(resolved);
4991
+ const rpcSummary = rpcCache ? {
4992
+ count: rpcCache.methods.length,
4993
+ fetchedAt: rpcCache.fetchedAt,
4994
+ byFamily: countByFamily(rpcCache.methods)
4995
+ } : null;
4996
+ if (isJsonOutput(opts)) {
4997
+ console.log(formatJson({
4998
+ name: resolved,
4999
+ rpc: rpcs,
5000
+ ...chain.relay && { relay: chain.relay },
5001
+ ...chain.parachainId != null && { parachainId: chain.parachainId },
5002
+ ...parachains.length > 0 && { parachains },
5003
+ metadata: fingerprint ? {
5004
+ specName: fingerprint.specName,
5005
+ specVersion: fingerprint.specVersion,
5006
+ fetchedAt: fingerprint.fetchedAt
5007
+ } : null,
5008
+ rpcMethods: rpcSummary
5009
+ }));
5010
+ return;
5011
+ }
5012
+ printHeading(resolved);
5013
+ console.log(` ${CYAN}rpc:${RESET}`);
5014
+ for (const rpc of rpcs) {
5015
+ console.log(` ${DIM}${rpc}${RESET}`);
5016
+ }
5017
+ if (chain.relay) {
5018
+ console.log(` ${CYAN}relay:${RESET} ${chain.relay}`);
5019
+ }
5020
+ if (chain.parachainId != null) {
5021
+ console.log(` ${CYAN}parachain id:${RESET} ${chain.parachainId}`);
5022
+ }
5023
+ if (parachains.length > 0) {
5024
+ console.log(` ${CYAN}parachains:${RESET}`);
5025
+ for (const p of parachains) {
5026
+ const idSuffix = p.parachainId != null ? ` ${DIM}[${p.parachainId}]${RESET}` : "";
5027
+ console.log(` ${p.name}${idSuffix}`);
5028
+ }
5029
+ }
5030
+ console.log(` ${CYAN}metadata:${RESET}`);
5031
+ if (fingerprint) {
5032
+ console.log(` ${fingerprint.specName} v${fingerprint.specVersion} ${DIM}(cached ${fingerprint.fetchedAt})${RESET}`);
5033
+ } else {
5034
+ console.log(` ${DIM}not cached — run \`dot chain update ${resolved}\`${RESET}`);
5035
+ }
5036
+ console.log(` ${CYAN}rpc methods:${RESET}`);
5037
+ if (rpcSummary) {
5038
+ const families = Object.entries(rpcSummary.byFamily).map(([f, n]) => `${f}: ${n}`).join(", ");
5039
+ console.log(` ${rpcSummary.count} ${DIM}(${families})${RESET}`);
5040
+ console.log(` ${DIM}cached ${rpcSummary.fetchedAt}${RESET}`);
5041
+ } else {
5042
+ console.log(` ${DIM}not cached — run \`dot chain update ${resolved}\`${RESET}`);
5043
+ }
5044
+ }
5045
+ function countByFamily(methods) {
5046
+ const counts = {};
5047
+ for (const m of methods) {
5048
+ const family = RPC_REGISTRY[m]?.family ?? inferFamily(m);
5049
+ counts[family] = (counts[family] ?? 0) + 1;
5050
+ }
5051
+ return counts;
5052
+ }
3745
5053
  async function chainUpdate(name, opts) {
3746
5054
  const config = await loadConfig();
3747
5055
  if (opts.all) {
@@ -3760,6 +5068,7 @@ async function chainUpdate(name, opts) {
3760
5068
  process.stderr.write(`Fetching metadata...
3761
5069
  `);
3762
5070
  await fetchMetadataFromChain(clientHandle, chainName);
5071
+ await refreshRpcMethods(chainName, opts.rpc ?? chainConfig.rpc);
3763
5072
  if (isJsonOutput(opts)) {
3764
5073
  console.log(formatJson({ action: "updated", chain: chainName }));
3765
5074
  } else {
@@ -3789,6 +5098,7 @@ async function updateChainsMetadata(config, chainNames) {
3789
5098
  const clientHandle = await createChainClient(chainName, chainConfig);
3790
5099
  try {
3791
5100
  await fetchMetadataFromChain(clientHandle, chainName);
5101
+ await refreshRpcMethods(chainName, chainConfig.rpc, true);
3792
5102
  } finally {
3793
5103
  clientHandle.destroy();
3794
5104
  }
@@ -4118,6 +5428,7 @@ init_store();
4118
5428
  init_client();
4119
5429
  init_metadata();
4120
5430
  init_output();
5431
+ init_pretty_type();
4121
5432
  async function loadMeta2(chainName, chainConfig, rpcOverride) {
4122
5433
  if (rpcOverride) {
4123
5434
  process.stderr.write(`Fetching metadata from ${chainName}...
@@ -4202,8 +5513,11 @@ async function handleCalls2(target, opts) {
4202
5513
  }
4203
5514
  printHeading(`${pallet.name} Calls`);
4204
5515
  for (const c of pallet.calls) {
4205
- const args2 = describeCallArgs(meta, pallet.name, c.name);
4206
- console.log(` ${CYAN}${c.name}${RESET}${DIM}${args2}${RESET}`);
5516
+ const args2 = prettyCallArgs(meta, pallet.name, c.name, {
5517
+ indent: 2,
5518
+ prefix: c.name.length
5519
+ });
5520
+ console.log(` ${CYAN}${c.name}${RESET}${args2}`);
4207
5521
  const summary = firstSentence(c.docs);
4208
5522
  if (summary) {
4209
5523
  console.log(` ${DIM}${summary}${RESET}`);
@@ -4229,7 +5543,10 @@ async function handleCalls2(target, opts) {
4229
5543
  return;
4230
5544
  }
4231
5545
  printHeading(`${pallet.name}.${callItem.name} (Call)`);
4232
- const args = describeCallArgs(meta, pallet.name, callItem.name);
5546
+ const args = prettyCallArgs(meta, pallet.name, callItem.name, {
5547
+ indent: 2,
5548
+ prefix: 6
5549
+ });
4233
5550
  console.log(` ${BOLD}Args:${RESET} ${args}`);
4234
5551
  if (callItem.docs.length) {
4235
5552
  console.log();
@@ -4288,8 +5605,11 @@ async function handleEvents2(target, opts) {
4288
5605
  }
4289
5606
  printHeading(`${pallet.name} Events`);
4290
5607
  for (const e of pallet.events) {
4291
- const fields2 = describeEventFields(meta, pallet.name, e.name);
4292
- console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields2}${RESET}`);
5608
+ const fields2 = prettyEventFields(meta, pallet.name, e.name, {
5609
+ indent: 2,
5610
+ prefix: e.name.length
5611
+ });
5612
+ console.log(` ${CYAN}${e.name}${RESET}${fields2}`);
4293
5613
  const summary = firstSentence(e.docs);
4294
5614
  if (summary) {
4295
5615
  console.log(` ${DIM}${summary}${RESET}`);
@@ -4315,7 +5635,10 @@ async function handleEvents2(target, opts) {
4315
5635
  return;
4316
5636
  }
4317
5637
  printHeading(`${pallet.name}.${eventItem.name} (Event)`);
4318
- const fields = describeEventFields(meta, pallet.name, eventItem.name);
5638
+ const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
5639
+ indent: 2,
5640
+ prefix: 8
5641
+ });
4319
5642
  console.log(` ${BOLD}Fields:${RESET} ${fields}`);
4320
5643
  if (eventItem.docs.length) {
4321
5644
  console.log();
@@ -4442,24 +5765,30 @@ async function handleStorage2(target, opts) {
4442
5765
  chain: chainName,
4443
5766
  pallet: pallet.name,
4444
5767
  storage: pallet.storage.map((s) => {
4445
- const valueType = describeType(meta.lookup, s.valueTypeId);
5768
+ const valueType2 = describeType(meta.lookup, s.valueTypeId);
4446
5769
  const keyType = s.keyTypeId != null ? describeType(meta.lookup, s.keyTypeId) : undefined;
4447
- return { name: s.name, type: s.type, valueType, keyType, docs: firstSentence(s.docs) };
5770
+ return { name: s.name, type: s.type, valueType: valueType2, keyType, docs: firstSentence(s.docs) };
4448
5771
  })
4449
5772
  }));
4450
5773
  return;
4451
5774
  }
4452
5775
  printHeading(`${pallet.name} Storage`);
4453
5776
  for (const s of pallet.storage) {
4454
- const valueType = describeType(meta.lookup, s.valueTypeId);
4455
- let typeSuffix;
4456
- if (s.keyTypeId != null) {
4457
- const keyType = describeType(meta.lookup, s.keyTypeId);
4458
- typeSuffix = `: ${keyType} → ${valueType} [map]`;
4459
- } else {
4460
- typeSuffix = `: ${valueType}`;
5777
+ const isMap = s.keyTypeId != null;
5778
+ const tag = isMap ? `${DIM} [map]${RESET}` : "";
5779
+ console.log(` ${CYAN}${s.name}${RESET}${tag}`);
5780
+ if (isMap) {
5781
+ const keyType = prettyTypeById(meta.lookup, s.keyTypeId, {
5782
+ indent: 4,
5783
+ prefix: 5
5784
+ });
5785
+ console.log(` ${DIM}Key:${RESET} ${keyType}`);
4461
5786
  }
4462
- console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
5787
+ const valueType2 = prettyTypeById(meta.lookup, s.valueTypeId, {
5788
+ indent: 4,
5789
+ prefix: 7
5790
+ });
5791
+ console.log(` ${DIM}Value:${RESET} ${valueType2}`);
4463
5792
  const summary = firstSentence(s.docs);
4464
5793
  if (summary) {
4465
5794
  console.log(` ${DIM}${summary}${RESET}`);
@@ -4474,7 +5803,7 @@ async function handleStorage2(target, opts) {
4474
5803
  throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
4475
5804
  }
4476
5805
  if (isJsonOutput(opts)) {
4477
- const valueType = describeType(meta.lookup, storageItem.valueTypeId);
5806
+ const valueType2 = describeType(meta.lookup, storageItem.valueTypeId);
4478
5807
  const keyType = storageItem.keyTypeId != null ? describeType(meta.lookup, storageItem.keyTypeId) : undefined;
4479
5808
  console.log(formatJson({
4480
5809
  chain: chainName,
@@ -4482,18 +5811,26 @@ async function handleStorage2(target, opts) {
4482
5811
  item: storageItem.name,
4483
5812
  category: "storage",
4484
5813
  type: storageItem.type,
4485
- valueType,
5814
+ valueType: valueType2,
4486
5815
  keyType,
4487
5816
  docs: storageItem.docs
4488
5817
  }));
4489
5818
  return;
4490
5819
  }
4491
5820
  printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
4492
- console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
4493
- console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
5821
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
4494
5822
  if (storageItem.keyTypeId != null) {
4495
- console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
5823
+ const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
5824
+ indent: 2,
5825
+ prefix: 7
5826
+ });
5827
+ console.log(` ${BOLD}Key:${RESET} ${keyType}`);
4496
5828
  }
5829
+ const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
5830
+ indent: 2,
5831
+ prefix: 7
5832
+ });
5833
+ console.log(` ${BOLD}Value:${RESET} ${valueType}`);
4497
5834
  if (storageItem.docs.length) {
4498
5835
  console.log();
4499
5836
  printDocs(storageItem.docs);
@@ -4524,9 +5861,15 @@ async function showItemHelp2(category, target, opts) {
4524
5861
  throw new Error(suggestMessage(`method in ${api.name}`, methodName, names));
4525
5862
  }
4526
5863
  printHeading(`${api.name}.${method.name} (Runtime API)`);
4527
- const argStr = describeRuntimeApiMethodArgs(meta, method);
4528
- const retStr = describeType(meta.lookup, method.output);
4529
- console.log(` ${BOLD}Args:${RESET} ${argStr}`);
5864
+ const argStr = prettyRuntimeApiArgs(meta.lookup, method.inputs, {
5865
+ indent: 2,
5866
+ prefix: 9
5867
+ });
5868
+ const retStr = prettyTypeById(meta.lookup, method.output, {
5869
+ indent: 2,
5870
+ prefix: 9
5871
+ });
5872
+ console.log(` ${BOLD}Args:${RESET} ${argStr}`);
4530
5873
  console.log(` ${BOLD}Returns:${RESET} ${retStr}`);
4531
5874
  if (method.docs.length) {
4532
5875
  console.log();
@@ -4569,7 +5912,10 @@ async function showItemHelp2(category, target, opts) {
4569
5912
  throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
4570
5913
  }
4571
5914
  printHeading(`${pallet.name}.${callItem.name} (Call)`);
4572
- const args = describeCallArgs(meta, pallet.name, callItem.name);
5915
+ const args = prettyCallArgs(meta, pallet.name, callItem.name, {
5916
+ indent: 2,
5917
+ prefix: 6
5918
+ });
4573
5919
  console.log(` ${BOLD}Args:${RESET} ${args}`);
4574
5920
  if (callItem.docs.length) {
4575
5921
  console.log();
@@ -4596,11 +5942,19 @@ async function showItemHelp2(category, target, opts) {
4596
5942
  throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
4597
5943
  }
4598
5944
  printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
4599
- console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
4600
- console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
5945
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
4601
5946
  if (storageItem.keyTypeId != null) {
4602
- console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
5947
+ const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
5948
+ indent: 2,
5949
+ prefix: 7
5950
+ });
5951
+ console.log(` ${BOLD}Key:${RESET} ${keyType}`);
4603
5952
  }
5953
+ const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
5954
+ indent: 2,
5955
+ prefix: 7
5956
+ });
5957
+ console.log(` ${BOLD}Value:${RESET} ${valueType}`);
4604
5958
  if (storageItem.docs.length) {
4605
5959
  console.log();
4606
5960
  printDocs(storageItem.docs);
@@ -4627,7 +5981,11 @@ async function showItemHelp2(category, target, opts) {
4627
5981
  throw new Error(suggestMessage(`constant in ${pallet.name}`, itemName, names));
4628
5982
  }
4629
5983
  printHeading(`${pallet.name}.${constItem.name} (Constant)`);
4630
- console.log(` ${BOLD}Type:${RESET} ${describeType(meta.lookup, constItem.typeId)}`);
5984
+ const constType = prettyTypeById(meta.lookup, constItem.typeId, {
5985
+ indent: 2,
5986
+ prefix: 6
5987
+ });
5988
+ console.log(` ${BOLD}Type:${RESET} ${constType}`);
4631
5989
  if (constItem.docs.length) {
4632
5990
  console.log();
4633
5991
  printDocs(constItem.docs);
@@ -4645,7 +6003,10 @@ async function showItemHelp2(category, target, opts) {
4645
6003
  throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
4646
6004
  }
4647
6005
  printHeading(`${pallet.name}.${eventItem.name} (Event)`);
4648
- const fields = describeEventFields(meta, pallet.name, eventItem.name);
6006
+ const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
6007
+ indent: 2,
6008
+ prefix: 8
6009
+ });
4649
6010
  console.log(` ${BOLD}Fields:${RESET} ${fields}`);
4650
6011
  if (eventItem.docs.length) {
4651
6012
  console.log();
@@ -4720,8 +6081,16 @@ async function handleExtensions(target, opts) {
4720
6081
  return;
4721
6082
  }
4722
6083
  printHeading(`${described.identifier} (Transaction Extension)`);
4723
- console.log(` ${BOLD}Value type:${RESET} ${described.valueType}`);
4724
- console.log(` ${BOLD}AdditionalSigned:${RESET} ${described.additionalSignedType}`);
6084
+ const valueType = prettyTypeById(meta.lookup, described.valueTypeId, {
6085
+ indent: 2,
6086
+ prefix: 18
6087
+ });
6088
+ const addSigType = prettyTypeById(meta.lookup, described.additionalSignedTypeId, {
6089
+ indent: 2,
6090
+ prefix: 18
6091
+ });
6092
+ console.log(` ${BOLD}Value type:${RESET} ${valueType}`);
6093
+ console.log(` ${BOLD}AdditionalSigned:${RESET} ${addSigType}`);
4725
6094
  console.log(` ${BOLD}Handled by:${RESET} ${described.isBuiltin ? "polkadot-api (builtin)" : "user (custom — provide via --ext)"}`);
4726
6095
  if (!described.isBuiltin) {
4727
6096
  console.log();
@@ -4805,6 +6174,7 @@ init_store();
4805
6174
  init_client();
4806
6175
  init_metadata();
4807
6176
  init_output();
6177
+ init_pretty_type();
4808
6178
 
4809
6179
  // src/utils/parse-target.ts
4810
6180
  function parseTarget(input, options) {
@@ -4981,15 +6351,21 @@ function registerInspectCommand(cli) {
4981
6351
  if (pallet2.storage.length) {
4982
6352
  console.log(` ${BOLD}Storage Items:${RESET}`);
4983
6353
  for (const s of pallet2.storage) {
4984
- const valueType = describeType(meta.lookup, s.valueTypeId);
4985
- let typeSuffix;
4986
- if (s.keyTypeId != null) {
4987
- const keyType = describeType(meta.lookup, s.keyTypeId);
4988
- typeSuffix = `: ${keyType} → ${valueType} [map]`;
4989
- } else {
4990
- typeSuffix = `: ${valueType}`;
6354
+ const isMap = s.keyTypeId != null;
6355
+ const tag = isMap ? `${DIM} [map]${RESET}` : "";
6356
+ console.log(` ${CYAN}${s.name}${RESET}${tag}`);
6357
+ if (isMap) {
6358
+ const keyType = prettyTypeById(meta.lookup, s.keyTypeId, {
6359
+ indent: 6,
6360
+ prefix: 7
6361
+ });
6362
+ console.log(` ${DIM}Key:${RESET} ${keyType}`);
4991
6363
  }
4992
- console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
6364
+ const valueType = prettyTypeById(meta.lookup, s.valueTypeId, {
6365
+ indent: 6,
6366
+ prefix: 7
6367
+ });
6368
+ console.log(` ${DIM}Value:${RESET} ${valueType}`);
4993
6369
  const summary = firstSentence(s.docs);
4994
6370
  if (summary) {
4995
6371
  console.log(` ${DIM}${summary}${RESET}`);
@@ -5000,8 +6376,11 @@ function registerInspectCommand(cli) {
5000
6376
  if (pallet2.constants.length) {
5001
6377
  console.log(` ${BOLD}Constants:${RESET}`);
5002
6378
  for (const c of pallet2.constants) {
5003
- const typeStr = describeType(meta.lookup, c.typeId);
5004
- console.log(` ${CYAN}${c.name}${RESET}${DIM}: ${typeStr}${RESET}`);
6379
+ const typeStr = prettyTypeById(meta.lookup, c.typeId, {
6380
+ indent: 4,
6381
+ prefix: c.name.length + 2
6382
+ });
6383
+ console.log(` ${CYAN}${c.name}${RESET}: ${typeStr}`);
5005
6384
  const summary = firstSentence(c.docs);
5006
6385
  if (summary) {
5007
6386
  console.log(` ${DIM}${summary}${RESET}`);
@@ -5012,8 +6391,11 @@ function registerInspectCommand(cli) {
5012
6391
  if (pallet2.calls.length) {
5013
6392
  console.log(` ${BOLD}Calls:${RESET}`);
5014
6393
  for (const c of pallet2.calls) {
5015
- const args = describeCallArgs(meta, pallet2.name, c.name);
5016
- console.log(` ${CYAN}${c.name}${RESET}${DIM}${args}${RESET}`);
6394
+ const args = prettyCallArgs(meta, pallet2.name, c.name, {
6395
+ indent: 4,
6396
+ prefix: c.name.length
6397
+ });
6398
+ console.log(` ${CYAN}${c.name}${RESET}${args}`);
5017
6399
  const summary = firstSentence(c.docs);
5018
6400
  if (summary) {
5019
6401
  console.log(` ${DIM}${summary}${RESET}`);
@@ -5024,8 +6406,11 @@ function registerInspectCommand(cli) {
5024
6406
  if (pallet2.events.length) {
5025
6407
  console.log(` ${BOLD}Events:${RESET}`);
5026
6408
  for (const e of pallet2.events) {
5027
- const fields = describeEventFields(meta, pallet2.name, e.name);
5028
- console.log(` ${CYAN}${e.name}${RESET}${DIM}${fields}${RESET}`);
6409
+ const fields = prettyEventFields(meta, pallet2.name, e.name, {
6410
+ indent: 4,
6411
+ prefix: e.name.length
6412
+ });
6413
+ console.log(` ${CYAN}${e.name}${RESET}${fields}`);
5029
6414
  const summary = firstSentence(e.docs);
5030
6415
  if (summary) {
5031
6416
  console.log(` ${DIM}${summary}${RESET}`);
@@ -5127,11 +6512,19 @@ function registerInspectCommand(cli) {
5127
6512
  const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
5128
6513
  if (storageItem) {
5129
6514
  printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
5130
- console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
5131
- console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
6515
+ console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
5132
6516
  if (storageItem.keyTypeId != null) {
5133
- console.log(` ${BOLD}Key:${RESET} ${describeType(meta.lookup, storageItem.keyTypeId)}`);
6517
+ const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
6518
+ indent: 2,
6519
+ prefix: 7
6520
+ });
6521
+ console.log(` ${BOLD}Key:${RESET} ${keyType}`);
5134
6522
  }
6523
+ const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
6524
+ indent: 2,
6525
+ prefix: 7
6526
+ });
6527
+ console.log(` ${BOLD}Value:${RESET} ${valueType}`);
5135
6528
  if (storageItem.docs.length) {
5136
6529
  console.log();
5137
6530
  printDocs(storageItem.docs);
@@ -5142,7 +6535,11 @@ function registerInspectCommand(cli) {
5142
6535
  const constantItem = pallet.constants.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
5143
6536
  if (constantItem) {
5144
6537
  printHeading(`${pallet.name}.${constantItem.name} (Constant)`);
5145
- console.log(` ${BOLD}Type:${RESET} ${describeType(meta.lookup, constantItem.typeId)}`);
6538
+ const typeStr = prettyTypeById(meta.lookup, constantItem.typeId, {
6539
+ indent: 2,
6540
+ prefix: 6
6541
+ });
6542
+ console.log(` ${BOLD}Type:${RESET} ${typeStr}`);
5146
6543
  if (constantItem.docs.length) {
5147
6544
  console.log();
5148
6545
  printDocs(constantItem.docs);
@@ -5153,7 +6550,10 @@ function registerInspectCommand(cli) {
5153
6550
  const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
5154
6551
  if (callItem) {
5155
6552
  printHeading(`${pallet.name}.${callItem.name} (Call)`);
5156
- const args = describeCallArgs(meta, pallet.name, callItem.name);
6553
+ const args = prettyCallArgs(meta, pallet.name, callItem.name, {
6554
+ indent: 2,
6555
+ prefix: 6
6556
+ });
5157
6557
  console.log(` ${BOLD}Args:${RESET} ${args}`);
5158
6558
  if (callItem.docs.length) {
5159
6559
  console.log();
@@ -5165,7 +6565,10 @@ function registerInspectCommand(cli) {
5165
6565
  const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
5166
6566
  if (eventItem) {
5167
6567
  printHeading(`${pallet.name}.${eventItem.name} (Event)`);
5168
- const fields = describeEventFields(meta, pallet.name, eventItem.name);
6568
+ const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
6569
+ indent: 2,
6570
+ prefix: 8
6571
+ });
5169
6572
  console.log(` ${BOLD}Fields:${RESET} ${fields}`);
5170
6573
  if (eventItem.docs.length) {
5171
6574
  console.log();
@@ -5240,11 +6643,6 @@ async function handleMetadata(chain, opts) {
5240
6643
  await writeStdout(`${formatJson(buildMetadataPayload(chainName, meta, fingerprint))}
5241
6644
  `);
5242
6645
  }
5243
- function writeStdout(text) {
5244
- return new Promise((resolve) => {
5245
- process.stdout.write(text, () => resolve());
5246
- });
5247
- }
5248
6646
  function registerMetadataCommand(cli) {
5249
6647
  cli.command("metadata <chain>", "Fetch chain metadata (decoded JSON; --raw for SCALE hex)").option("--raw", "Print SCALE-encoded metadata bytes as hex instead of decoded JSON").option("--cached", "Use cached metadata instead of fetching fresh from the chain").option("--rpc <url>", "Override RPC endpoint(s)").action((chain, opts) => handleMetadata(chain, opts));
5250
6648
  }
@@ -5252,24 +6650,6 @@ function registerMetadataCommand(cli) {
5252
6650
  // src/commands/parachain.ts
5253
6651
  init_accounts();
5254
6652
  init_output();
5255
-
5256
- // src/core/parachain.ts
5257
- var SOVEREIGN_ACCOUNT_TYPES = ["child", "sibling"];
5258
- var PREFIXES = {
5259
- child: new Uint8Array([112, 97, 114, 97]),
5260
- sibling: new Uint8Array([115, 105, 98, 108])
5261
- };
5262
- function deriveSovereignAccount(paraId, type) {
5263
- const result = new Uint8Array(32);
5264
- result.set(PREFIXES[type], 0);
5265
- new DataView(result.buffer).setUint32(4, paraId, true);
5266
- return result;
5267
- }
5268
- function isValidParaId(value) {
5269
- return Number.isInteger(value) && value >= 0 && value <= 4294967295;
5270
- }
5271
-
5272
- // src/commands/parachain.ts
5273
6653
  init_errors();
5274
6654
  function printParachainHelp() {
5275
6655
  console.log(`${BOLD}Usage:${RESET} dot parachain <paraId> [options]
@@ -5299,6 +6679,7 @@ function validateType(type) {
5299
6679
  }
5300
6680
  function registerParachainCommand(cli) {
5301
6681
  cli.command("parachain [paraId]", "Derive parachain sovereign accounts").option("--type <type>", "Account type: child, sibling (default: both)").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").action(async (paraIdStr, opts) => {
6682
+ console.error("Warning: `dot parachain` is deprecated; use `dot account inspect --parachain <id> --parachain-type <child|sibling>` instead. Will be removed in a future release.");
5302
6683
  if (!paraIdStr) {
5303
6684
  printParachainHelp();
5304
6685
  return;
@@ -5344,6 +6725,7 @@ init_store();
5344
6725
  init_client();
5345
6726
  init_metadata();
5346
6727
  init_output();
6728
+ init_pretty_type();
5347
6729
  init_focused_inspect();
5348
6730
  init_tx();
5349
6731
  async function handleQuery(target, keys, opts) {
@@ -5354,10 +6736,11 @@ async function handleQuery(target, keys, opts) {
5354
6736
  const pallets = listPallets(meta);
5355
6737
  const withStorage = pallets.filter((p) => p.storage.length > 0);
5356
6738
  if (isJsonOutput(opts)) {
5357
- console.log(formatJson({
6739
+ await writeStdout(`${formatJson({
5358
6740
  chain: chainName2,
5359
6741
  pallets: withStorage.map((p) => ({ name: p.name, storage: p.storage.length }))
5360
- }));
6742
+ })}
6743
+ `);
5361
6744
  return;
5362
6745
  }
5363
6746
  printHeading(`Pallets with storage on ${chainName2} (${withStorage.length})`);
@@ -5375,14 +6758,15 @@ async function handleQuery(target, keys, opts) {
5375
6758
  const pallet2 = resolvePallet(meta, palletName(target));
5376
6759
  if (pallet2.storage.length === 0) {
5377
6760
  if (isJsonOutput(opts)) {
5378
- console.log(formatJson({ chain: chainName2, pallet: pallet2.name, storage: [] }));
6761
+ await writeStdout(`${formatJson({ chain: chainName2, pallet: pallet2.name, storage: [] })}
6762
+ `);
5379
6763
  } else {
5380
6764
  console.log(`No storage items in ${pallet2.name}.`);
5381
6765
  }
5382
6766
  return;
5383
6767
  }
5384
6768
  if (isJsonOutput(opts)) {
5385
- console.log(formatJson({
6769
+ await writeStdout(`${formatJson({
5386
6770
  chain: chainName2,
5387
6771
  pallet: pallet2.name,
5388
6772
  storage: pallet2.storage.map((s) => {
@@ -5390,20 +6774,27 @@ async function handleQuery(target, keys, opts) {
5390
6774
  const keyType = s.keyTypeId != null ? describeType(meta.lookup, s.keyTypeId) : undefined;
5391
6775
  return { name: s.name, type: s.type, valueType, keyType, docs: firstSentence(s.docs) };
5392
6776
  })
5393
- }));
6777
+ })}
6778
+ `);
5394
6779
  return;
5395
6780
  }
5396
6781
  printHeading(`${pallet2.name} Storage`);
5397
6782
  for (const s of pallet2.storage) {
5398
- const valueType = describeType(meta.lookup, s.valueTypeId);
5399
- let typeSuffix;
5400
- if (s.keyTypeId != null) {
5401
- const keyType = describeType(meta.lookup, s.keyTypeId);
5402
- typeSuffix = `: ${keyType} → ${valueType} [map]`;
5403
- } else {
5404
- typeSuffix = `: ${valueType}`;
6783
+ const isMap = s.keyTypeId != null;
6784
+ const tag = isMap ? `${DIM} [map]${RESET}` : "";
6785
+ console.log(` ${CYAN}${s.name}${RESET}${tag}`);
6786
+ if (isMap) {
6787
+ const keyType = prettyTypeById(meta.lookup, s.keyTypeId, {
6788
+ indent: 4,
6789
+ prefix: 5
6790
+ });
6791
+ console.log(` ${DIM}Key:${RESET} ${keyType}`);
5405
6792
  }
5406
- console.log(` ${CYAN}${s.name}${RESET}${DIM}${typeSuffix}${RESET}`);
6793
+ const valueType = prettyTypeById(meta.lookup, s.valueTypeId, {
6794
+ indent: 4,
6795
+ prefix: 7
6796
+ });
6797
+ console.log(` ${DIM}Value:${RESET} ${valueType}`);
5407
6798
  const summary = firstSentence(s.docs);
5408
6799
  if (summary) {
5409
6800
  console.log(` ${DIM}${summary}${RESET}`);
@@ -5445,13 +6836,18 @@ async function handleQuery(target, keys, opts) {
5445
6836
  return;
5446
6837
  }
5447
6838
  const entries = await withStalenessSuggestion(chainName, clientHandle, () => storageApi.getEntries(...parsedKeys));
5448
- printResult(entries.map((e) => ({
6839
+ const rows = entries.map((e) => ({
5449
6840
  keys: e.keyArgs,
5450
6841
  value: e.value
5451
- })), format);
6842
+ }));
6843
+ const text = format === "json" ? formatJson(rows) : formatPretty(rows);
6844
+ await writeStdout(`${text}
6845
+ `);
5452
6846
  } else {
5453
6847
  const result = await withStalenessSuggestion(chainName, clientHandle, () => storageApi.getValue(...parsedKeys));
5454
- printResult(result, format);
6848
+ const text = format === "json" ? formatJson(result) : formatPretty(result);
6849
+ await writeStdout(`${text}
6850
+ `);
5455
6851
  }
5456
6852
  } finally {
5457
6853
  clientHandle.destroy();
@@ -5497,6 +6893,168 @@ async function parseStorageKeys(meta, palletName2, storageItem, args) {
5497
6893
  return Promise.all(args.map((arg) => parseTypedArg(meta, keyEntry, arg)));
5498
6894
  }
5499
6895
 
6896
+ // src/commands/rpc.ts
6897
+ init_store();
6898
+ init_output();
6899
+ init_rpc_registry();
6900
+ init_errors();
6901
+ var FAMILY_ORDER = [
6902
+ "system",
6903
+ "chain",
6904
+ "state",
6905
+ "author",
6906
+ "payment",
6907
+ "babe",
6908
+ "grandpa",
6909
+ "beefy",
6910
+ "mmr",
6911
+ "offchain",
6912
+ "dev",
6913
+ "spec",
6914
+ "chainHead",
6915
+ "chainSpec",
6916
+ "transaction",
6917
+ "archive",
6918
+ "other"
6919
+ ];
6920
+ async function getMethodList(chainName, rpcUrl, refresh) {
6921
+ if (!refresh) {
6922
+ const cached = await loadRpcMethods(chainName);
6923
+ if (cached) {
6924
+ return { methods: cached.methods, version: cached.version, fromCache: true };
6925
+ }
6926
+ }
6927
+ const fresh = await fetchRpcMethods(rpcUrl);
6928
+ await saveRpcMethods(chainName, fresh.methods, fresh.version);
6929
+ return { methods: fresh.methods, version: fresh.version, fromCache: false };
6930
+ }
6931
+ function groupByFamily(methods) {
6932
+ const groups = new Map;
6933
+ for (const m of methods) {
6934
+ const family = RPC_REGISTRY[m]?.family ?? inferFamily(m);
6935
+ const list = groups.get(family) ?? [];
6936
+ list.push(m);
6937
+ groups.set(family, list);
6938
+ }
6939
+ for (const list of groups.values())
6940
+ list.sort();
6941
+ return groups;
6942
+ }
6943
+ function formatArgs(info) {
6944
+ if (info.args.length === 0)
6945
+ return "(no args)";
6946
+ return info.args.map((a) => `<${a.name}: ${a.type}${a.optional ? "?" : ""}>`).join(" ");
6947
+ }
6948
+ function printMethodHelp(method, info) {
6949
+ console.log();
6950
+ console.log(`${BOLD}${method}${RESET}`);
6951
+ if (info) {
6952
+ if (info.dangerous) {
6953
+ console.log(` ${YELLOW}⚠️ WRITE / state-changing${RESET}`);
6954
+ }
6955
+ if (info.subscription) {
6956
+ console.log(` ${DIM}subscription — not callable as a one-shot${RESET}`);
6957
+ }
6958
+ console.log(` ${info.description}`);
6959
+ console.log();
6960
+ console.log(` ${DIM}Family:${RESET} ${info.family}`);
6961
+ console.log(` ${DIM}Args:${RESET} ${formatArgs(info)}`);
6962
+ if (info.args.some((a) => a.description)) {
6963
+ console.log();
6964
+ for (const a of info.args) {
6965
+ if (a.description) {
6966
+ console.log(` ${CYAN}${a.name}${RESET} ${DIM}${a.description}${RESET}`);
6967
+ }
6968
+ }
6969
+ }
6970
+ } else {
6971
+ console.log(` ${DIM}No curated metadata. Args are passed through as raw JSON-RPC params.${RESET}`);
6972
+ console.log(` ${DIM}Family:${RESET} ${inferFamily(method)} (inferred)`);
6973
+ }
6974
+ console.log();
6975
+ }
6976
+ async function listMethods(chainName, rpcUrl, opts) {
6977
+ const { methods, version: version2, fromCache } = await getMethodList(chainName, rpcUrl, opts.refresh ?? false);
6978
+ if (isJsonOutput(opts)) {
6979
+ console.log(formatJson({
6980
+ chain: chainName,
6981
+ version: version2,
6982
+ fromCache,
6983
+ methods: methods.map((m) => {
6984
+ const info = RPC_REGISTRY[m];
6985
+ return {
6986
+ method: m,
6987
+ family: info?.family ?? inferFamily(m),
6988
+ description: info?.description,
6989
+ dangerous: info?.dangerous ?? false,
6990
+ subscription: info?.subscription ?? false
6991
+ };
6992
+ })
6993
+ }));
6994
+ return;
6995
+ }
6996
+ printHeading(`RPC methods on ${chainName} (${methods.length})`);
6997
+ const groups = groupByFamily(methods);
6998
+ for (const family of FAMILY_ORDER) {
6999
+ const list = groups.get(family);
7000
+ if (!list || list.length === 0)
7001
+ continue;
7002
+ console.log(`${BOLD}${family}${RESET} ${DIM}(${list.length})${RESET}`);
7003
+ for (const m of list) {
7004
+ const info = RPC_REGISTRY[m];
7005
+ const tags = [];
7006
+ if (info?.dangerous)
7007
+ tags.push(`${YELLOW}⚠ write${RESET}`);
7008
+ if (info?.subscription)
7009
+ tags.push(`${DIM}sub${RESET}`);
7010
+ const suffix = tags.length > 0 ? ` ${tags.join(" ")}` : "";
7011
+ const desc = info?.description ? ` ${DIM}${info.description}${RESET}` : "";
7012
+ console.log(` ${CYAN}${m}${RESET}${suffix}${desc}`);
7013
+ }
7014
+ console.log();
7015
+ }
7016
+ if (!fromCache) {
7017
+ console.log(`${DIM}(fetched from node — cached for next run)${RESET}`);
7018
+ }
7019
+ }
7020
+ async function handleRpc(method, args, opts) {
7021
+ const config = await loadConfig();
7022
+ const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
7023
+ const rpcUrl = opts.rpc ?? chainConfig.rpc;
7024
+ if (!rpcUrl) {
7025
+ throw new CliError(`No RPC endpoint for chain "${chainName}". Pass --rpc or run \`dot chain add ${chainName} --rpc <url>\`.`);
7026
+ }
7027
+ if (!method) {
7028
+ await listMethods(chainName, rpcUrl, opts);
7029
+ return;
7030
+ }
7031
+ const info = RPC_REGISTRY[method];
7032
+ if (opts.help) {
7033
+ printMethodHelp(method, info);
7034
+ return;
7035
+ }
7036
+ const { methods: knownMethods } = await getMethodList(chainName, rpcUrl, opts.refresh ?? false);
7037
+ if (!knownMethods.includes(method)) {
7038
+ const hint = suggestMessage("method", method, knownMethods);
7039
+ throw new CliError(`Method "${method}" is not exposed by the node for "${chainName}".${hint ? ` ${hint}` : ""} ` + `Run \`dot ${chainName}.rpc --refresh\` if the node has been upgraded.`);
7040
+ }
7041
+ if (info?.subscription) {
7042
+ throw new CliError(`"${method}" is a subscription method (requires a follow session) and is not callable as a one-shot. ` + `Use a long-running client for streaming RPC.`);
7043
+ }
7044
+ if (!info && /(_subscribe|_unsubscribe)/.test(method)) {
7045
+ throw new CliError(`"${method}" looks like a subscription/unsubscription method and isn't supported as a one-shot. ` + `Pass --help to see what we know about it.`);
7046
+ }
7047
+ if (info) {
7048
+ const required = info.args.filter((a) => !a.optional).length;
7049
+ if (args.length < required) {
7050
+ throw new CliError(`"${method}" expects at least ${required} argument(s) (${formatArgs(info)}); got ${args.length}.`);
7051
+ }
7052
+ }
7053
+ const params = args.map(parseValue);
7054
+ const result = await rpcRequest(rpcUrl, method, params);
7055
+ printResult(result, isJsonOutput(opts) ? "json" : opts.output);
7056
+ }
7057
+
5500
7058
  // src/commands/sign.ts
5501
7059
  init_accounts();
5502
7060
  init_hash();
@@ -5598,6 +7156,7 @@ init_accounts();
5598
7156
  init_client();
5599
7157
  init_metadata();
5600
7158
  init_output();
7159
+ init_pretty_type();
5601
7160
  init_resolve_address();
5602
7161
  init_binary_display();
5603
7162
  init_errors();
@@ -5730,8 +7289,11 @@ async function handleTx(target, args, opts) {
5730
7289
  }
5731
7290
  printHeading(`${pallet2.name} Calls`);
5732
7291
  for (const c of pallet2.calls) {
5733
- const callArgs = describeCallArgs(meta, pallet2.name, c.name);
5734
- console.log(` ${CYAN}${c.name}${RESET}${DIM}${callArgs}${RESET}`);
7292
+ const callArgs = prettyCallArgs(meta, pallet2.name, c.name, {
7293
+ indent: 2,
7294
+ prefix: c.name.length
7295
+ });
7296
+ console.log(` ${CYAN}${c.name}${RESET}${callArgs}`);
5735
7297
  const summary = firstSentence(c.docs);
5736
7298
  if (summary) {
5737
7299
  console.log(` ${DIM}${summary}${RESET}`);
@@ -5882,6 +7444,7 @@ async function handleTx(target, args, opts) {
5882
7444
  callHex = Binary3.toHex(encodedCall);
5883
7445
  }
5884
7446
  const decodedStr = decodeCall(meta, callHex);
7447
+ const decodedObj = decodeCallObject(meta, callHex);
5885
7448
  if (opts.dryRun && opts.unsigned) {
5886
7449
  if (isJsonOutput(opts)) {
5887
7450
  console.log(formatJson({
@@ -5896,7 +7459,7 @@ async function handleTx(target, args, opts) {
5896
7459
  console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
5897
7460
  console.log(` ${BOLD}Type:${RESET} unsigned (bare)`);
5898
7461
  console.log(` ${BOLD}Call:${RESET} ${callHex}`);
5899
- console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
7462
+ printDecodedCall(decodedObj, decodedStr);
5900
7463
  console.log(` ${BOLD}Fees:${RESET} ${DIM}N/A (unsigned transaction)${RESET}`);
5901
7464
  return;
5902
7465
  }
@@ -5935,7 +7498,7 @@ async function handleTx(target, args, opts) {
5935
7498
  console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
5936
7499
  console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
5937
7500
  console.log(` ${BOLD}Call:${RESET} ${callHex}`);
5938
- console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
7501
+ printDecodedCall(decodedObj, decodedStr);
5939
7502
  if (nonce !== undefined)
5940
7503
  console.log(` ${BOLD}Nonce:${RESET} ${nonce}`);
5941
7504
  if (tip !== undefined)
@@ -6012,7 +7575,7 @@ async function handleTx(target, args, opts) {
6012
7575
  console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
6013
7576
  console.log(` ${BOLD}Type:${RESET} unsigned (bare)`);
6014
7577
  console.log(` ${BOLD}Call:${RESET} ${callHex}`);
6015
- console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
7578
+ printDecodedCall(decodedObj, decodedStr);
6016
7579
  console.log(` ${BOLD}Tx:${RESET} ${result2.txHash}`);
6017
7580
  if (result2.type === "broadcasted") {
6018
7581
  console.log(` ${BOLD}Status:${RESET} ${GREEN}broadcasted${RESET}`);
@@ -6091,7 +7654,7 @@ async function handleTx(target, args, opts) {
6091
7654
  console.log();
6092
7655
  console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
6093
7656
  console.log(` ${BOLD}Call:${RESET} ${callHex}`);
6094
- console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
7657
+ printDecodedCall(decodedObj, decodedStr);
6095
7658
  if (nonce !== undefined)
6096
7659
  console.log(` ${BOLD}Nonce:${RESET} ${nonce}`);
6097
7660
  if (tip !== undefined)
@@ -6178,6 +7741,39 @@ function decodeCall(meta, callHex) {
6178
7741
  return "(unable to decode)";
6179
7742
  }
6180
7743
  }
7744
+ function decodeCallObject(meta, callHex) {
7745
+ try {
7746
+ const callTypeId = meta.lookup.call;
7747
+ if (callTypeId == null)
7748
+ return null;
7749
+ const codec = meta.builder.buildDefinition(callTypeId);
7750
+ const decoded = codec.dec(Binary3.fromHex(callHex));
7751
+ return {
7752
+ palletName: decoded.type,
7753
+ callName: decoded.value.type,
7754
+ args: sanitizeForSerialization(decoded.value.value)
7755
+ };
7756
+ } catch {
7757
+ return null;
7758
+ }
7759
+ }
7760
+ function printDecodedCall(obj, fallback) {
7761
+ if (!obj) {
7762
+ console.log(` ${BOLD}Decode:${RESET} ${fallback}`);
7763
+ return;
7764
+ }
7765
+ const header = `${CYAN}${obj.palletName}${RESET}.${CYAN}${obj.callName}${RESET}`;
7766
+ const hasArgs = obj.args !== null && obj.args !== undefined && !(typeof obj.args === "object" && Object.keys(obj.args).length === 0);
7767
+ if (!hasArgs) {
7768
+ console.log(` ${BOLD}Decode:${RESET} ${header}`);
7769
+ return;
7770
+ }
7771
+ console.log(` ${BOLD}Decode:${RESET} ${header}`);
7772
+ const indented = formatPretty(obj.args).split(`
7773
+ `).map((l) => ` ${l}`).join(`
7774
+ `);
7775
+ console.log(indented);
7776
+ }
6181
7777
  function decodeCallFallback(meta, callHex) {
6182
7778
  const callTypeId = meta.lookup.call;
6183
7779
  if (callTypeId == null)
@@ -7321,13 +8917,13 @@ function isNewerVersion(current, latest) {
7321
8917
  return compareSemver(current, latest) < 0;
7322
8918
  }
7323
8919
  function buildNotificationBox(current, latest) {
7324
- const YELLOW2 = "\x1B[33m";
7325
- const GREEN2 = "\x1B[32m";
7326
- const CYAN2 = "\x1B[36m";
7327
- const RESET2 = "\x1B[0m";
8920
+ const YELLOW3 = "\x1B[33m";
8921
+ const GREEN3 = "\x1B[32m";
8922
+ const CYAN3 = "\x1B[36m";
8923
+ const RESET3 = "\x1B[0m";
7328
8924
  const BOLD2 = "\x1B[1m";
7329
- const line1 = `Update available! ${YELLOW2}${current}${RESET2} → ${GREEN2}${BOLD2}${latest}${RESET2}`;
7330
- const line2 = `Run ${CYAN2}npm i -g polkadot-cli${RESET2} to update`;
8925
+ const line1 = `Update available! ${YELLOW3}${current}${RESET3} → ${GREEN3}${BOLD2}${latest}${RESET3}`;
8926
+ const line2 = `Run ${CYAN3}npm i -g polkadot-cli${RESET3} to update`;
7331
8927
  const visibleLine1 = `Update available! ${current} → ${latest}`;
7332
8928
  const visibleLine2 = `Run npm i -g polkadot-cli to update`;
7333
8929
  const innerWidth = Math.max(visibleLine1.length, visibleLine2.length) + 4;
@@ -7458,7 +9054,8 @@ var CATEGORY_ALIASES = {
7458
9054
  api: "apis",
7459
9055
  extensions: "extensions",
7460
9056
  extension: "extensions",
7461
- ext: "extensions"
9057
+ ext: "extensions",
9058
+ rpc: "rpc"
7462
9059
  };
7463
9060
  function matchCategory(segment) {
7464
9061
  return CATEGORY_ALIASES[segment.toLowerCase()];
@@ -7473,7 +9070,7 @@ function parseDotPath(input, knownChains = []) {
7473
9070
  const cat = matchCategory(parts[0]);
7474
9071
  if (cat)
7475
9072
  return { category: cat };
7476
- throw new Error(`Unknown command "${parts[0]}". Expected a category (query, tx, const, events, errors, apis, extensions) or a named command.`);
9073
+ throw new Error(`Unknown command "${parts[0]}". Expected a category (query, tx, const, events, errors, apis, extensions, rpc) or a named command.`);
7477
9074
  }
7478
9075
  case 2: {
7479
9076
  const cat = matchCategory(parts[0]);
@@ -7555,6 +9152,7 @@ if (process.argv[2] === "__complete") {
7555
9152
  console.log(" errors List or inspect pallet errors");
7556
9153
  console.log(" apis Browse and call runtime APIs");
7557
9154
  console.log(" extensions List transaction extensions on a chain");
9155
+ console.log(" rpc Call raw JSON-RPC methods on a node");
7558
9156
  console.log();
7559
9157
  console.log("Examples:");
7560
9158
  console.log(" dot polkadot.query.System.Account <addr> Query a storage item");
@@ -7567,6 +9165,8 @@ if (process.argv[2] === "__complete") {
7567
9165
  console.log(" dot metadata polkadot Dump runtime metadata as JSON");
7568
9166
  console.log(" dot polkadot.extensions List transaction extensions");
7569
9167
  console.log(" dot polkadot.extensions.CheckMortality Inspect one extension");
9168
+ console.log(" dot polkadot.rpc List RPC methods on the node");
9169
+ console.log(" dot polkadot.rpc.system_health Call a JSON-RPC method");
7570
9170
  console.log(" dot query.System.Number --chain polkadot --chain flag form");
7571
9171
  console.log(" dot ./transfer.yaml --from alice Run from file (chain in YAML)");
7572
9172
  console.log(" dot tx.0x1f0003... --to-yaml --chain polkadot Decode hex call to YAML");
@@ -7580,7 +9180,7 @@ if (process.argv[2] === "__complete") {
7580
9180
  console.log(" account Manage accounts");
7581
9181
  console.log(" hash Hash utilities");
7582
9182
  console.log(" sign Sign a message with an account keypair");
7583
- console.log(" parachain Derive parachain sovereign accounts");
9183
+ console.log(" parachain Derive parachain sovereign accounts (deprecated \u2014 use `account inspect --parachain`)");
7584
9184
  console.log(" verifiable Derive Bandersnatch member key from mnemonic");
7585
9185
  console.log(" completions <sh> Generate shell completions (zsh, bash, fish)");
7586
9186
  console.log();
@@ -7611,7 +9211,7 @@ if (process.argv[2] === "__complete") {
7611
9211
  registerVerifiableCommands(cli);
7612
9212
  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("--to-yaml", "Decode call to YAML file format (for tx)").option("--to-json", "Decode call to JSON file format (for tx)").option("--ext <json>", "Custom signed extension values as JSON (for tx)").option("--asset <json>", "Pay fees in an alternative asset (XCM location JSON, for tx)").option("-w, --wait <level>", "Resolve at: broadcast, best-block (or best), finalized (for tx)", {
7613
9213
  default: "finalized"
7614
- }).option("--dump", "Dump all entries of a storage map (without specifying a key)").option("--var <kv>", "Template variable for file input (KEY=VALUE, repeatable)").option("--nonce <n>", "Custom nonce for manual tx sequencing (for tx)").option("--tip <amount>", "Tip to prioritize transaction (for tx)").option("--mortality <spec>", '"immortal" or period number (for tx)').option("--at <block>", 'Block hash, "best", or "finalized" to validate against (for tx)').option("--unsigned", "Submit as unsigned/bare transaction (no signer required, for tx)").action(async (dotpath, args, opts) => {
9214
+ }).option("--dump", "Dump all entries of a storage map (without specifying a key)").option("--var <kv>", "Template variable for file input (KEY=VALUE, repeatable)").option("--nonce <n>", "Custom nonce for manual tx sequencing (for tx)").option("--tip <amount>", "Tip to prioritize transaction (for tx)").option("--mortality <spec>", '"immortal" or period number (for tx)').option("--at <block>", 'Block hash, "best", or "finalized" to validate against (for tx)').option("--unsigned", "Submit as unsigned/bare transaction (no signer required, for tx)").option("--refresh", "Refresh the cached RPC method list from the node (for rpc)").action(async (dotpath, args, opts) => {
7615
9215
  if (!dotpath) {
7616
9216
  printHelp();
7617
9217
  return;
@@ -7674,9 +9274,10 @@ if (process.argv[2] === "__complete") {
7674
9274
  } catch {
7675
9275
  throw new CliError2(`Unknown command "${dotpath}". Run "dot --help" for available commands.`);
7676
9276
  }
9277
+ const isFlatCategory = parsed.category === "rpc" || parsed.category === "extensions";
7677
9278
  if (!parsed.pallet && args.length > 0) {
7678
9279
  parsed.pallet = args.shift();
7679
- if (!parsed.item && args.length > 0) {
9280
+ if (!isFlatCategory && !parsed.item && args.length > 0) {
7680
9281
  parsed.item = args.shift();
7681
9282
  }
7682
9283
  }
@@ -7743,6 +9344,18 @@ if (process.argv[2] === "__complete") {
7743
9344
  await handleExtensions(parsed.pallet, handlerOpts);
7744
9345
  break;
7745
9346
  }
9347
+ case "rpc": {
9348
+ if (parsed.item) {
9349
+ const suggestion = parsed.chain ? `dot ${parsed.chain}.rpc.${parsed.pallet}` : opts.chain ? `dot rpc.${parsed.pallet} --chain ${opts.chain}` : `dot rpc.${parsed.pallet} --chain <chain>`;
9350
+ throw new CliError2(`RPC methods have no sub-items. Try "${suggestion}".`);
9351
+ }
9352
+ await handleRpc(parsed.pallet, args, {
9353
+ ...handlerOpts,
9354
+ help: cli.options.help,
9355
+ refresh: opts.refresh
9356
+ });
9357
+ break;
9358
+ }
7746
9359
  }
7747
9360
  });
7748
9361
  cli.option("--help, -h", "Display this message");