polkadot-cli 1.15.1 → 1.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +544 -147
- package/dist/cli.mjs +944 -242
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -16,7 +16,31 @@ var __export = (target, all) => {
|
|
|
16
16
|
var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
|
|
17
17
|
|
|
18
18
|
// src/utils/errors.ts
|
|
19
|
-
|
|
19
|
+
function isLikelyStaleMetadataError(err) {
|
|
20
|
+
const msg = err instanceof Error ? err.message : typeof err === "string" ? err : "";
|
|
21
|
+
if (!msg)
|
|
22
|
+
return false;
|
|
23
|
+
return STALE_METADATA_PATTERNS.some((re) => re.test(msg));
|
|
24
|
+
}
|
|
25
|
+
function formatRuntimeError(err) {
|
|
26
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
27
|
+
if (/wasm trap|wasm `?unreachable`? instruction|Execution aborted due to trap/i.test(msg)) {
|
|
28
|
+
const frames = Array.from(msg.matchAll(/\.wasm!([A-Za-z_]\w+)/g)).map((m) => m[1]);
|
|
29
|
+
const fn = [...frames].reverse().find((name) => !/^(?:__rustc|core::panicking|rust_begin_unwind|panic_fmt)/.test(name));
|
|
30
|
+
const where = fn?.includes("validate_transaction") ? "the runtime's validate_transaction step" : fn ? `runtime function ${fn}` : "the runtime";
|
|
31
|
+
return [
|
|
32
|
+
`The runtime rejected this transaction in ${where}.`,
|
|
33
|
+
" Cause: a runtime invariant failed — typically the call's arguments are out of range, reference an unknown id, or violate a precondition.",
|
|
34
|
+
" Tip: re-check the arguments and the signing account's permissions; --dry-run will surface the same error before signing."
|
|
35
|
+
].join(`
|
|
36
|
+
`);
|
|
37
|
+
}
|
|
38
|
+
if (/Invalid Transaction/i.test(msg)) {
|
|
39
|
+
return `Transaction rejected as invalid by the runtime: ${msg}`;
|
|
40
|
+
}
|
|
41
|
+
return msg;
|
|
42
|
+
}
|
|
43
|
+
var CliError, ConnectionError, MetadataError, STALE_METADATA_PATTERNS;
|
|
20
44
|
var init_errors = __esm(() => {
|
|
21
45
|
CliError = class CliError extends Error {
|
|
22
46
|
constructor(message) {
|
|
@@ -36,8 +60,28 @@ var init_errors = __esm(() => {
|
|
|
36
60
|
this.name = "MetadataError";
|
|
37
61
|
}
|
|
38
62
|
};
|
|
63
|
+
STALE_METADATA_PATTERNS = [
|
|
64
|
+
/wasm trap/i,
|
|
65
|
+
/wasm `?unreachable`? instruction/i,
|
|
66
|
+
/Execution aborted due to trap/i,
|
|
67
|
+
/codec/i,
|
|
68
|
+
/decod(e|ing)/i,
|
|
69
|
+
/Lookup failed/i,
|
|
70
|
+
/metadata.*mismatch/i
|
|
71
|
+
];
|
|
39
72
|
});
|
|
40
73
|
|
|
74
|
+
// src/utils/runtime-fingerprint.ts
|
|
75
|
+
function fingerprintsMatch(a, b) {
|
|
76
|
+
return a.codeHash === b.codeHash && a.specVersion === b.specVersion && a.transactionVersion === b.transactionVersion;
|
|
77
|
+
}
|
|
78
|
+
function isRuntimeFingerprint(value) {
|
|
79
|
+
if (!value || typeof value !== "object")
|
|
80
|
+
return false;
|
|
81
|
+
const v = value;
|
|
82
|
+
return typeof v.specName === "string" && typeof v.specVersion === "number" && typeof v.transactionVersion === "number" && typeof v.implName === "string" && typeof v.implVersion === "number" && typeof v.authoringVersion === "number" && typeof v.codeHash === "string" && typeof v.fetchedAt === "string";
|
|
83
|
+
}
|
|
84
|
+
|
|
41
85
|
// src/config/types.ts
|
|
42
86
|
function primaryRpc(rpc) {
|
|
43
87
|
return Array.isArray(rpc) ? rpc[0] : rpc;
|
|
@@ -193,6 +237,9 @@ function getChainDir(chainName) {
|
|
|
193
237
|
function getMetadataPath(chainName) {
|
|
194
238
|
return join(getChainDir(chainName), "metadata.bin");
|
|
195
239
|
}
|
|
240
|
+
function getMetadataFingerprintPath(chainName) {
|
|
241
|
+
return join(getChainDir(chainName), "metadata.fingerprint.json");
|
|
242
|
+
}
|
|
196
243
|
function getConfigPath() {
|
|
197
244
|
return join(getConfigDir(), "config.json");
|
|
198
245
|
}
|
|
@@ -238,10 +285,25 @@ async function loadMetadata(chainName) {
|
|
|
238
285
|
}
|
|
239
286
|
return null;
|
|
240
287
|
}
|
|
241
|
-
async function saveMetadata(chainName, data) {
|
|
288
|
+
async function saveMetadata(chainName, data, fingerprint) {
|
|
242
289
|
const dir = getChainDir(chainName);
|
|
243
290
|
await ensureDir(dir);
|
|
244
291
|
await writeFile(getMetadataPath(chainName), data);
|
|
292
|
+
if (fingerprint) {
|
|
293
|
+
await writeFile(getMetadataFingerprintPath(chainName), `${JSON.stringify(fingerprint, null, 2)}
|
|
294
|
+
`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
async function loadMetadataFingerprint(chainName) {
|
|
298
|
+
const path = getMetadataFingerprintPath(chainName);
|
|
299
|
+
if (!await fileExists(path))
|
|
300
|
+
return null;
|
|
301
|
+
try {
|
|
302
|
+
const parsed = JSON.parse(await readFile(path, "utf-8"));
|
|
303
|
+
return isRuntimeFingerprint(parsed) ? parsed : null;
|
|
304
|
+
} catch {
|
|
305
|
+
return null;
|
|
306
|
+
}
|
|
245
307
|
}
|
|
246
308
|
async function removeChainData(chainName) {
|
|
247
309
|
const dir = getChainDir(chainName);
|
|
@@ -612,6 +674,11 @@ function printResult(data, format = "pretty") {
|
|
|
612
674
|
function isJsonOutput(opts) {
|
|
613
675
|
return opts.json === true || opts.output === "json";
|
|
614
676
|
}
|
|
677
|
+
function writeStdout(text) {
|
|
678
|
+
return new Promise((resolve) => {
|
|
679
|
+
process.stdout.write(text, () => resolve());
|
|
680
|
+
});
|
|
681
|
+
}
|
|
615
682
|
function printJsonLine(data) {
|
|
616
683
|
console.log(JSON.stringify(data, replacer));
|
|
617
684
|
}
|
|
@@ -791,6 +858,324 @@ var init_client = __esm(() => {
|
|
|
791
858
|
init_errors();
|
|
792
859
|
});
|
|
793
860
|
|
|
861
|
+
// src/core/pretty-type.ts
|
|
862
|
+
function visualWidth(s) {
|
|
863
|
+
return s.replace(ANSI_RE, "").length;
|
|
864
|
+
}
|
|
865
|
+
function paint(color, code, text) {
|
|
866
|
+
return color ? `${code}${text}${RESET2}` : text;
|
|
867
|
+
}
|
|
868
|
+
function defaultWidth() {
|
|
869
|
+
return process.stdout.columns ?? 80;
|
|
870
|
+
}
|
|
871
|
+
function resolveOpts(opts) {
|
|
872
|
+
return {
|
|
873
|
+
indent: opts.indent ?? 0,
|
|
874
|
+
prefix: opts.prefix ?? 0,
|
|
875
|
+
width: opts.width ?? defaultWidth(),
|
|
876
|
+
color: opts.color ?? isTTY
|
|
877
|
+
};
|
|
878
|
+
}
|
|
879
|
+
function compactEntry(entry, color) {
|
|
880
|
+
if (!entry)
|
|
881
|
+
return "";
|
|
882
|
+
switch (entry.type) {
|
|
883
|
+
case "primitive":
|
|
884
|
+
return paint(color, YELLOW2, entry.value);
|
|
885
|
+
case "compact": {
|
|
886
|
+
const inner = entry.isBig ? "u128" : "u64";
|
|
887
|
+
return `${paint(color, MAGENTA2, "Compact")}<${paint(color, YELLOW2, inner)}>`;
|
|
888
|
+
}
|
|
889
|
+
case "AccountId32":
|
|
890
|
+
return paint(color, GREEN2, "AccountId32");
|
|
891
|
+
case "bitSequence":
|
|
892
|
+
return paint(color, MAGENTA2, "BitSequence");
|
|
893
|
+
case "sequence":
|
|
894
|
+
return `${paint(color, MAGENTA2, "Vec")}<${compactEntry(entry.value, color)}>`;
|
|
895
|
+
case "array":
|
|
896
|
+
return `[${compactEntry(entry.value, color)}; ${entry.len}]`;
|
|
897
|
+
case "tuple":
|
|
898
|
+
return `(${entry.value.map((v) => compactEntry(v, color)).join(", ")})`;
|
|
899
|
+
case "struct": {
|
|
900
|
+
const fields = Object.entries(entry.value);
|
|
901
|
+
if (fields.length === 0)
|
|
902
|
+
return "{}";
|
|
903
|
+
const inner = fields.map(([k, v]) => `${paint(color, CYAN2, k)}: ${compactEntry(v, color)}`).join(", ");
|
|
904
|
+
return `{ ${inner} }`;
|
|
905
|
+
}
|
|
906
|
+
case "option":
|
|
907
|
+
return `${paint(color, MAGENTA2, "Option")}<${compactEntry(entry.value, color)}>`;
|
|
908
|
+
case "result":
|
|
909
|
+
return `${paint(color, MAGENTA2, "Result")}<${compactEntry(entry.value.ok, color)}, ${compactEntry(entry.value.ko, color)}>`;
|
|
910
|
+
case "enum": {
|
|
911
|
+
const variants = Object.keys(entry.value);
|
|
912
|
+
if (variants.length > ENUM_COMPACT_LIMIT) {
|
|
913
|
+
return `enum(${variants.length} variants)`;
|
|
914
|
+
}
|
|
915
|
+
return variants.map((v) => paint(color, GREEN2, v)).join(" | ");
|
|
916
|
+
}
|
|
917
|
+
case "void":
|
|
918
|
+
return "()";
|
|
919
|
+
case "lookupEntry":
|
|
920
|
+
return compactEntry(entry.value, color);
|
|
921
|
+
default:
|
|
922
|
+
return "unknown";
|
|
923
|
+
}
|
|
924
|
+
}
|
|
925
|
+
function expandEntry(entry, indent, width, color, prefix = 0) {
|
|
926
|
+
const compact = compactEntry(entry, color);
|
|
927
|
+
if (visualWidth(compact) + indent + prefix <= width)
|
|
928
|
+
return compact;
|
|
929
|
+
switch (entry.type) {
|
|
930
|
+
case "struct":
|
|
931
|
+
return expandStruct(entry.value, indent, width, color);
|
|
932
|
+
case "tuple":
|
|
933
|
+
return expandTuple(entry.value, indent, width, color);
|
|
934
|
+
case "sequence":
|
|
935
|
+
return wrapMultiline("Vec", "<", ">", entry.value, indent, width, color);
|
|
936
|
+
case "array": {
|
|
937
|
+
const inner = expandEntry(entry.value, indent + 1, width, color);
|
|
938
|
+
return `[${inner}; ${entry.len}]`;
|
|
939
|
+
}
|
|
940
|
+
case "option":
|
|
941
|
+
return wrapMultiline("Option", "<", ">", entry.value, indent, width, color);
|
|
942
|
+
case "result": {
|
|
943
|
+
const innerIndent = indent + 2;
|
|
944
|
+
const padding = " ".repeat(innerIndent);
|
|
945
|
+
const closePadding = " ".repeat(indent);
|
|
946
|
+
const ok = expandEntry(entry.value.ok, innerIndent, width, color);
|
|
947
|
+
const ko = expandEntry(entry.value.ko, innerIndent, width, color);
|
|
948
|
+
return `${paint(color, MAGENTA2, "Result")}<
|
|
949
|
+
${padding}${ok},
|
|
950
|
+
${padding}${ko}
|
|
951
|
+
${closePadding}>`;
|
|
952
|
+
}
|
|
953
|
+
case "enum": {
|
|
954
|
+
const variants = Object.keys(entry.value);
|
|
955
|
+
if (variants.length > ENUM_COMPACT_LIMIT)
|
|
956
|
+
return `enum(${variants.length} variants)`;
|
|
957
|
+
return expandEnum(variants, indent, color);
|
|
958
|
+
}
|
|
959
|
+
case "lookupEntry":
|
|
960
|
+
return expandEntry(entry.value, indent, width, color);
|
|
961
|
+
default:
|
|
962
|
+
return compact;
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
function expandStruct(fields, indent, width, color) {
|
|
966
|
+
const entries = Object.entries(fields);
|
|
967
|
+
if (entries.length === 0)
|
|
968
|
+
return "{}";
|
|
969
|
+
return renderFieldList(entries, "{", "}", indent, width, color);
|
|
970
|
+
}
|
|
971
|
+
function expandTuple(items, indent, width, color) {
|
|
972
|
+
if (items.length === 0)
|
|
973
|
+
return "()";
|
|
974
|
+
const inner = " ".repeat(indent + 2);
|
|
975
|
+
const close = " ".repeat(indent);
|
|
976
|
+
const lines = items.map((v) => `${inner}${expandEntry(v, indent + 2, width, color)}`);
|
|
977
|
+
return `(
|
|
978
|
+
${lines.join(`,
|
|
979
|
+
`)},
|
|
980
|
+
${close})`;
|
|
981
|
+
}
|
|
982
|
+
function wrapMultiline(name, open, close, inner, indent, width, color) {
|
|
983
|
+
const innerIndent = indent + 2;
|
|
984
|
+
const padding = " ".repeat(innerIndent);
|
|
985
|
+
const closePadding = " ".repeat(indent);
|
|
986
|
+
const innerStr = expandEntry(inner, innerIndent, width, color);
|
|
987
|
+
return `${paint(color, MAGENTA2, name)}${open}
|
|
988
|
+
${padding}${innerStr}
|
|
989
|
+
${closePadding}${close}`;
|
|
990
|
+
}
|
|
991
|
+
function expandEnum(variants, indent, color) {
|
|
992
|
+
const prefix = `
|
|
993
|
+
${" ".repeat(indent)}| `;
|
|
994
|
+
const [first, ...rest] = variants;
|
|
995
|
+
const head = paint(color, GREEN2, first ?? "");
|
|
996
|
+
if (rest.length === 0)
|
|
997
|
+
return head;
|
|
998
|
+
const tail = rest.map((v) => paint(color, GREEN2, v)).join(prefix);
|
|
999
|
+
return `${head}${prefix}${tail}`;
|
|
1000
|
+
}
|
|
1001
|
+
function renderFieldList(fields, open, close, indent, width, color) {
|
|
1002
|
+
const innerIndent = indent + 2;
|
|
1003
|
+
const maxNameLen = Math.max(...fields.map(([k]) => k.length));
|
|
1004
|
+
const align = maxNameLen <= ALIGN_PADDING_LIMIT;
|
|
1005
|
+
const padTo = align ? maxNameLen : 0;
|
|
1006
|
+
const padding = " ".repeat(innerIndent);
|
|
1007
|
+
const closePadding = " ".repeat(indent);
|
|
1008
|
+
const lines = fields.map(([k, v]) => {
|
|
1009
|
+
const paddedName = align ? k.padEnd(padTo) : k;
|
|
1010
|
+
const fieldPrefix = (align ? padTo : k.length) + 2;
|
|
1011
|
+
const value = expandEntry(v, innerIndent, width, color, fieldPrefix);
|
|
1012
|
+
return `${padding}${paint(color, CYAN2, paddedName)}: ${value}`;
|
|
1013
|
+
});
|
|
1014
|
+
return `${open}
|
|
1015
|
+
${lines.join(`,
|
|
1016
|
+
`)},
|
|
1017
|
+
${closePadding}${close}`;
|
|
1018
|
+
}
|
|
1019
|
+
function prettyType(entry, opts = {}) {
|
|
1020
|
+
const { indent, prefix, width, color } = resolveOpts(opts);
|
|
1021
|
+
const compact = compactEntry(entry, color);
|
|
1022
|
+
if (visualWidth(compact) + indent + prefix <= width)
|
|
1023
|
+
return compact;
|
|
1024
|
+
return expandEntry(entry, indent, width, color);
|
|
1025
|
+
}
|
|
1026
|
+
function prettyTypeById(lookup, typeId, opts = {}) {
|
|
1027
|
+
try {
|
|
1028
|
+
const entry = lookup(typeId);
|
|
1029
|
+
if (!entry || typeof entry.type !== "string")
|
|
1030
|
+
return `type(${typeId})`;
|
|
1031
|
+
return prettyType(entry, opts);
|
|
1032
|
+
} catch {
|
|
1033
|
+
return `type(${typeId})`;
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
function prettyCallArgs(meta, palletName, callName, opts = {}) {
|
|
1037
|
+
const fields = getCallFields(meta, palletName, callName);
|
|
1038
|
+
if (fields === null)
|
|
1039
|
+
return "";
|
|
1040
|
+
return renderArgsFromFields(fields, opts);
|
|
1041
|
+
}
|
|
1042
|
+
function prettyEventFields(meta, palletName, eventName, opts = {}) {
|
|
1043
|
+
const fields = getEventFields(meta, palletName, eventName);
|
|
1044
|
+
if (fields === null)
|
|
1045
|
+
return "";
|
|
1046
|
+
return renderArgsFromFields(fields, opts);
|
|
1047
|
+
}
|
|
1048
|
+
function prettyRuntimeApiArgs(lookup, inputs, opts = {}) {
|
|
1049
|
+
if (inputs.length === 0)
|
|
1050
|
+
return "()";
|
|
1051
|
+
const namedFields = inputs.map((i) => {
|
|
1052
|
+
let entry;
|
|
1053
|
+
try {
|
|
1054
|
+
entry = lookup(i.type);
|
|
1055
|
+
if (!entry || typeof entry.type !== "string")
|
|
1056
|
+
entry = { type: "unknown" };
|
|
1057
|
+
} catch {
|
|
1058
|
+
entry = { type: "unknown" };
|
|
1059
|
+
}
|
|
1060
|
+
return [i.name, entry];
|
|
1061
|
+
});
|
|
1062
|
+
return renderArgsFromFields({ kind: "named", fields: namedFields }, opts);
|
|
1063
|
+
}
|
|
1064
|
+
function unwrapVariant(variant) {
|
|
1065
|
+
if (!variant)
|
|
1066
|
+
return null;
|
|
1067
|
+
if (variant.type === "void")
|
|
1068
|
+
return { kind: "void" };
|
|
1069
|
+
if (variant.type === "struct") {
|
|
1070
|
+
return {
|
|
1071
|
+
kind: "named",
|
|
1072
|
+
fields: Object.entries(variant.value)
|
|
1073
|
+
};
|
|
1074
|
+
}
|
|
1075
|
+
if (variant.type === "tuple") {
|
|
1076
|
+
return { kind: "positional", types: variant.value };
|
|
1077
|
+
}
|
|
1078
|
+
if (variant.type === "lookupEntry") {
|
|
1079
|
+
const inner = variant.value;
|
|
1080
|
+
if (inner.type === "void")
|
|
1081
|
+
return { kind: "void" };
|
|
1082
|
+
if (inner.type === "struct") {
|
|
1083
|
+
return {
|
|
1084
|
+
kind: "named",
|
|
1085
|
+
fields: Object.entries(inner.value)
|
|
1086
|
+
};
|
|
1087
|
+
}
|
|
1088
|
+
return { kind: "single", type: inner };
|
|
1089
|
+
}
|
|
1090
|
+
return null;
|
|
1091
|
+
}
|
|
1092
|
+
function getCallFields(meta, palletName, callName) {
|
|
1093
|
+
try {
|
|
1094
|
+
const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
|
|
1095
|
+
if (!palletMeta?.calls)
|
|
1096
|
+
return null;
|
|
1097
|
+
const callsEntry = meta.lookup(palletMeta.calls.type);
|
|
1098
|
+
if (callsEntry.type !== "enum")
|
|
1099
|
+
return null;
|
|
1100
|
+
const variant = callsEntry.value[callName];
|
|
1101
|
+
return unwrapVariant(variant);
|
|
1102
|
+
} catch {
|
|
1103
|
+
return null;
|
|
1104
|
+
}
|
|
1105
|
+
}
|
|
1106
|
+
function getEventFields(meta, palletName, eventName) {
|
|
1107
|
+
try {
|
|
1108
|
+
const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
|
|
1109
|
+
if (!palletMeta?.events)
|
|
1110
|
+
return null;
|
|
1111
|
+
const eventsEntry = meta.lookup(palletMeta.events.type);
|
|
1112
|
+
if (eventsEntry.type !== "enum")
|
|
1113
|
+
return null;
|
|
1114
|
+
const variant = eventsEntry.value[eventName];
|
|
1115
|
+
return unwrapVariant(variant);
|
|
1116
|
+
} catch {
|
|
1117
|
+
return null;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
function renderArgsFromFields(fields, opts) {
|
|
1121
|
+
const { indent, prefix, width, color } = resolveOpts(opts);
|
|
1122
|
+
const lead = indent + prefix;
|
|
1123
|
+
switch (fields.kind) {
|
|
1124
|
+
case "void":
|
|
1125
|
+
return "()";
|
|
1126
|
+
case "named": {
|
|
1127
|
+
const compact = `(${fields.fields.map(([k, v]) => `${paint(color, CYAN2, k)}: ${compactEntry(v, color)}`).join(", ")})`;
|
|
1128
|
+
if (visualWidth(compact) + lead <= width)
|
|
1129
|
+
return compact;
|
|
1130
|
+
return renderFieldList(fields.fields, "(", ")", indent, width, color);
|
|
1131
|
+
}
|
|
1132
|
+
case "positional": {
|
|
1133
|
+
const compact = `(${fields.types.map((t) => compactEntry(t, color)).join(", ")})`;
|
|
1134
|
+
if (visualWidth(compact) + lead <= width)
|
|
1135
|
+
return compact;
|
|
1136
|
+
const innerIndent = indent + 2;
|
|
1137
|
+
const padding = " ".repeat(innerIndent);
|
|
1138
|
+
const closePadding = " ".repeat(indent);
|
|
1139
|
+
const lines = fields.types.map((t) => `${padding}${expandEntry(t, innerIndent, width, color)}`);
|
|
1140
|
+
return `(
|
|
1141
|
+
${lines.join(`,
|
|
1142
|
+
`)},
|
|
1143
|
+
${closePadding})`;
|
|
1144
|
+
}
|
|
1145
|
+
case "single": {
|
|
1146
|
+
const compact = `(${compactEntry(fields.type, color)})`;
|
|
1147
|
+
if (visualWidth(compact) + lead <= width)
|
|
1148
|
+
return compact;
|
|
1149
|
+
const inner = expandEntry(fields.type, indent + 2, width, color);
|
|
1150
|
+
return `(
|
|
1151
|
+
${" ".repeat(indent + 2)}${inner},
|
|
1152
|
+
${" ".repeat(indent)})`;
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
function compactTypeString(entry) {
|
|
1157
|
+
return compactEntry(entry, false);
|
|
1158
|
+
}
|
|
1159
|
+
function compactArgsString(fields) {
|
|
1160
|
+
if (fields === null)
|
|
1161
|
+
return "";
|
|
1162
|
+
switch (fields.kind) {
|
|
1163
|
+
case "void":
|
|
1164
|
+
return "()";
|
|
1165
|
+
case "named":
|
|
1166
|
+
return `(${fields.fields.map(([k, v]) => `${k}: ${compactEntry(v, false)}`).join(", ")})`;
|
|
1167
|
+
case "positional":
|
|
1168
|
+
return `(${fields.types.map((t) => compactEntry(t, false)).join(", ")})`;
|
|
1169
|
+
case "single":
|
|
1170
|
+
return `(${compactEntry(fields.type, false)})`;
|
|
1171
|
+
}
|
|
1172
|
+
}
|
|
1173
|
+
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;
|
|
1174
|
+
var init_pretty_type = __esm(() => {
|
|
1175
|
+
init_output();
|
|
1176
|
+
ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
1177
|
+
});
|
|
1178
|
+
|
|
794
1179
|
// src/core/metadata.ts
|
|
795
1180
|
import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders";
|
|
796
1181
|
import {
|
|
@@ -809,28 +1194,52 @@ function parseMetadata(raw) {
|
|
|
809
1194
|
const builder = getDynamicBuilder(lookup);
|
|
810
1195
|
return { unified, lookup, builder, version: version2 };
|
|
811
1196
|
}
|
|
1197
|
+
async function getRuntimeFingerprint(clientHandle, chainName) {
|
|
1198
|
+
const { client } = clientHandle;
|
|
1199
|
+
const [version2, codeHash] = await Promise.all([
|
|
1200
|
+
withTimeout(client._request("state_getRuntimeVersion", []), chainName),
|
|
1201
|
+
withTimeout(client._request("state_getStorageHash", ["0x3a636f6465"]), chainName)
|
|
1202
|
+
]);
|
|
1203
|
+
return {
|
|
1204
|
+
specName: version2.specName,
|
|
1205
|
+
specVersion: version2.specVersion,
|
|
1206
|
+
transactionVersion: version2.transactionVersion,
|
|
1207
|
+
implName: version2.implName,
|
|
1208
|
+
implVersion: version2.implVersion,
|
|
1209
|
+
authoringVersion: version2.authoringVersion,
|
|
1210
|
+
codeHash,
|
|
1211
|
+
fetchedAt: new Date().toISOString()
|
|
1212
|
+
};
|
|
1213
|
+
}
|
|
812
1214
|
async function fetchMetadataFromChain(clientHandle, chainName) {
|
|
813
1215
|
const { client } = clientHandle;
|
|
1216
|
+
let bytes;
|
|
814
1217
|
try {
|
|
815
1218
|
const hex = await withTimeout(client._request("state_call", ["Metadata_metadata_at_version", v15Arg]), chainName);
|
|
816
1219
|
const raw = hexToBytes(hex);
|
|
817
1220
|
const decoded = optionalOpaqueBytes.dec(raw);
|
|
818
1221
|
if (decoded !== undefined) {
|
|
819
|
-
|
|
820
|
-
await saveMetadata(chainName, bytes);
|
|
821
|
-
return bytes;
|
|
1222
|
+
bytes = new Uint8Array(decoded);
|
|
822
1223
|
}
|
|
823
1224
|
} catch {}
|
|
1225
|
+
if (!bytes) {
|
|
1226
|
+
try {
|
|
1227
|
+
const hex = await withTimeout(client._request("state_getMetadata", []), chainName);
|
|
1228
|
+
bytes = hexToBytes(hex);
|
|
1229
|
+
} catch (err) {
|
|
1230
|
+
if (err instanceof ConnectionError)
|
|
1231
|
+
throw err;
|
|
1232
|
+
throw new ConnectionError(`Failed to fetch metadata for "${chainName}": ${err instanceof Error ? err.message : err}. ` + "Check that the RPC endpoint is correct and reachable.");
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1235
|
+
let fingerprint;
|
|
824
1236
|
try {
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
return bytes;
|
|
829
|
-
} catch (err) {
|
|
830
|
-
if (err instanceof ConnectionError)
|
|
831
|
-
throw err;
|
|
832
|
-
throw new ConnectionError(`Failed to fetch metadata for "${chainName}": ${err instanceof Error ? err.message : err}. ` + "Check that the RPC endpoint is correct and reachable.");
|
|
1237
|
+
fingerprint = await getRuntimeFingerprint(clientHandle, chainName);
|
|
1238
|
+
} catch {
|
|
1239
|
+
fingerprint = undefined;
|
|
833
1240
|
}
|
|
1241
|
+
await saveMetadata(chainName, bytes, fingerprint);
|
|
1242
|
+
return bytes;
|
|
834
1243
|
}
|
|
835
1244
|
function withTimeout(promise, chainName) {
|
|
836
1245
|
return Promise.race([
|
|
@@ -838,6 +1247,33 @@ function withTimeout(promise, chainName) {
|
|
|
838
1247
|
new Promise((_, reject) => setTimeout(() => reject(new ConnectionError(`Timed out fetching metadata for "${chainName}" after ${METADATA_TIMEOUT_MS / 1000}s. ` + "Check that the RPC endpoint is correct and reachable.")), METADATA_TIMEOUT_MS))
|
|
839
1248
|
]);
|
|
840
1249
|
}
|
|
1250
|
+
async function withStalenessSuggestion(chainName, clientHandle, task) {
|
|
1251
|
+
try {
|
|
1252
|
+
return await task();
|
|
1253
|
+
} catch (err) {
|
|
1254
|
+
if (process.env.DOT_TRUST_CACHED_METADATA === "1")
|
|
1255
|
+
throw err;
|
|
1256
|
+
if (!isLikelyStaleMetadataError(err))
|
|
1257
|
+
throw err;
|
|
1258
|
+
let live;
|
|
1259
|
+
try {
|
|
1260
|
+
live = await getRuntimeFingerprint(clientHandle, chainName);
|
|
1261
|
+
} catch {
|
|
1262
|
+
throw err;
|
|
1263
|
+
}
|
|
1264
|
+
const cached = await loadMetadataFingerprint(chainName);
|
|
1265
|
+
if (!cached)
|
|
1266
|
+
throw err;
|
|
1267
|
+
if (fingerprintsMatch(cached, live))
|
|
1268
|
+
throw err;
|
|
1269
|
+
const original = err instanceof Error ? formatRuntimeError(err) : String(err);
|
|
1270
|
+
const versionNote = cached.specVersion !== live.specVersion ? `spec ${cached.specVersion} → ${live.specVersion}` : `runtime code hash changed (same spec ${live.specVersion}; likely a node restart with new wasm)`;
|
|
1271
|
+
throw new CliError(`${original}
|
|
1272
|
+
|
|
1273
|
+
` + `⚠ Local metadata for "${chainName}" is out of date (${versionNote}).
|
|
1274
|
+
` + ` Run: dot chain update ${chainName}`);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
841
1277
|
async function getOrFetchMetadata(chainName, clientHandle) {
|
|
842
1278
|
let raw = await loadMetadata(chainName);
|
|
843
1279
|
if (!raw) {
|
|
@@ -954,114 +1390,18 @@ function describeRuntimeApiMethodArgs(meta, method) {
|
|
|
954
1390
|
function describeType(lookup, typeId) {
|
|
955
1391
|
try {
|
|
956
1392
|
const entry = lookup(typeId);
|
|
957
|
-
|
|
1393
|
+
if (!entry || typeof entry.type !== "string")
|
|
1394
|
+
return `type(${typeId})`;
|
|
1395
|
+
return compactTypeString(entry);
|
|
958
1396
|
} catch {
|
|
959
1397
|
return `type(${typeId})`;
|
|
960
1398
|
}
|
|
961
1399
|
}
|
|
962
|
-
function formatLookupEntry(entry) {
|
|
963
|
-
switch (entry.type) {
|
|
964
|
-
case "primitive":
|
|
965
|
-
return entry.value;
|
|
966
|
-
case "compact":
|
|
967
|
-
return `Compact<${formatLookupEntry(entry.isBig ? { type: "primitive", value: "u128" } : { type: "primitive", value: "u64" })}>`;
|
|
968
|
-
case "AccountId32":
|
|
969
|
-
return "AccountId32";
|
|
970
|
-
case "bitSequence":
|
|
971
|
-
return "BitSequence";
|
|
972
|
-
case "sequence":
|
|
973
|
-
return `Vec<${formatLookupEntry(entry.value)}>`;
|
|
974
|
-
case "array":
|
|
975
|
-
return `[${formatLookupEntry(entry.value)}; ${entry.len}]`;
|
|
976
|
-
case "tuple":
|
|
977
|
-
return `(${entry.value.map(formatLookupEntry).join(", ")})`;
|
|
978
|
-
case "struct":
|
|
979
|
-
return `{ ${Object.entries(entry.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ")} }`;
|
|
980
|
-
case "option":
|
|
981
|
-
return `Option<${formatLookupEntry(entry.value)}>`;
|
|
982
|
-
case "result":
|
|
983
|
-
return `Result<${formatLookupEntry(entry.value.ok)}, ${formatLookupEntry(entry.value.ko)}>`;
|
|
984
|
-
case "enum": {
|
|
985
|
-
const variants = Object.keys(entry.value);
|
|
986
|
-
if (variants.length <= 4)
|
|
987
|
-
return variants.join(" | ");
|
|
988
|
-
return `enum(${variants.length} variants)`;
|
|
989
|
-
}
|
|
990
|
-
default:
|
|
991
|
-
return "unknown";
|
|
992
|
-
}
|
|
993
|
-
}
|
|
994
1400
|
function describeCallArgs(meta, palletName, callName) {
|
|
995
|
-
|
|
996
|
-
const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
|
|
997
|
-
if (!palletMeta?.calls)
|
|
998
|
-
return "";
|
|
999
|
-
const callsEntry = meta.lookup(palletMeta.calls.type);
|
|
1000
|
-
if (callsEntry.type !== "enum")
|
|
1001
|
-
return "";
|
|
1002
|
-
const variant = callsEntry.value[callName];
|
|
1003
|
-
if (!variant)
|
|
1004
|
-
return "";
|
|
1005
|
-
if (variant.type === "void")
|
|
1006
|
-
return "()";
|
|
1007
|
-
if (variant.type === "struct") {
|
|
1008
|
-
const fields = Object.entries(variant.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
|
|
1009
|
-
return `(${fields})`;
|
|
1010
|
-
}
|
|
1011
|
-
if (variant.type === "lookupEntry") {
|
|
1012
|
-
const inner = variant.value;
|
|
1013
|
-
if (inner.type === "void")
|
|
1014
|
-
return "()";
|
|
1015
|
-
if (inner.type === "struct") {
|
|
1016
|
-
const fields = Object.entries(inner.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
|
|
1017
|
-
return `(${fields})`;
|
|
1018
|
-
}
|
|
1019
|
-
return `(${formatLookupEntry(inner)})`;
|
|
1020
|
-
}
|
|
1021
|
-
if (variant.type === "tuple") {
|
|
1022
|
-
const types = variant.value.map(formatLookupEntry).join(", ");
|
|
1023
|
-
return `(${types})`;
|
|
1024
|
-
}
|
|
1025
|
-
return "";
|
|
1026
|
-
} catch {
|
|
1027
|
-
return "";
|
|
1028
|
-
}
|
|
1401
|
+
return compactArgsString(getCallFields(meta, palletName, callName));
|
|
1029
1402
|
}
|
|
1030
1403
|
function describeEventFields(meta, palletName, eventName) {
|
|
1031
|
-
|
|
1032
|
-
const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
|
|
1033
|
-
if (!palletMeta?.events)
|
|
1034
|
-
return "";
|
|
1035
|
-
const eventsEntry = meta.lookup(palletMeta.events.type);
|
|
1036
|
-
if (eventsEntry.type !== "enum")
|
|
1037
|
-
return "";
|
|
1038
|
-
const variant = eventsEntry.value[eventName];
|
|
1039
|
-
if (!variant)
|
|
1040
|
-
return "";
|
|
1041
|
-
if (variant.type === "void")
|
|
1042
|
-
return "()";
|
|
1043
|
-
if (variant.type === "struct") {
|
|
1044
|
-
const fields = Object.entries(variant.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
|
|
1045
|
-
return `(${fields})`;
|
|
1046
|
-
}
|
|
1047
|
-
if (variant.type === "lookupEntry") {
|
|
1048
|
-
const inner = variant.value;
|
|
1049
|
-
if (inner.type === "void")
|
|
1050
|
-
return "()";
|
|
1051
|
-
if (inner.type === "struct") {
|
|
1052
|
-
const fields = Object.entries(inner.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
|
|
1053
|
-
return `(${fields})`;
|
|
1054
|
-
}
|
|
1055
|
-
return `(${formatLookupEntry(inner)})`;
|
|
1056
|
-
}
|
|
1057
|
-
if (variant.type === "tuple") {
|
|
1058
|
-
const types = variant.value.map(formatLookupEntry).join(", ");
|
|
1059
|
-
return `(${types})`;
|
|
1060
|
-
}
|
|
1061
|
-
return "";
|
|
1062
|
-
} catch {
|
|
1063
|
-
return "";
|
|
1064
|
-
}
|
|
1404
|
+
return compactArgsString(getEventFields(meta, palletName, eventName));
|
|
1065
1405
|
}
|
|
1066
1406
|
function hexToBytes(hex) {
|
|
1067
1407
|
const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
|
|
@@ -1075,6 +1415,7 @@ var METADATA_TIMEOUT_MS = 15000, optionalOpaqueBytes, v15Arg, PAPI_BUILTIN_EXTEN
|
|
|
1075
1415
|
var init_metadata = __esm(() => {
|
|
1076
1416
|
init_store();
|
|
1077
1417
|
init_errors();
|
|
1418
|
+
init_pretty_type();
|
|
1078
1419
|
optionalOpaqueBytes = Option(Bytes());
|
|
1079
1420
|
v15Arg = toHex(u32.enc(15));
|
|
1080
1421
|
PAPI_BUILTIN_EXTENSIONS = new Set([
|
|
@@ -1471,6 +1812,7 @@ var init_tx = __esm(() => {
|
|
|
1471
1812
|
init_client();
|
|
1472
1813
|
init_metadata();
|
|
1473
1814
|
init_output();
|
|
1815
|
+
init_pretty_type();
|
|
1474
1816
|
init_resolve_address();
|
|
1475
1817
|
init_binary_display();
|
|
1476
1818
|
init_errors();
|
|
@@ -1686,8 +2028,11 @@ async function handleCalls(target, opts) {
|
|
|
1686
2028
|
}
|
|
1687
2029
|
printHeading(`${pallet.name} Calls`);
|
|
1688
2030
|
for (const c of pallet.calls) {
|
|
1689
|
-
const args2 =
|
|
1690
|
-
|
|
2031
|
+
const args2 = prettyCallArgs(meta, pallet.name, c.name, {
|
|
2032
|
+
indent: 2,
|
|
2033
|
+
prefix: c.name.length
|
|
2034
|
+
});
|
|
2035
|
+
console.log(` ${CYAN}${c.name}${RESET}${args2}`);
|
|
1691
2036
|
const summary = firstSentence(c.docs);
|
|
1692
2037
|
if (summary) {
|
|
1693
2038
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -1713,7 +2058,10 @@ async function handleCalls(target, opts) {
|
|
|
1713
2058
|
return;
|
|
1714
2059
|
}
|
|
1715
2060
|
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
1716
|
-
const args =
|
|
2061
|
+
const args = prettyCallArgs(meta, pallet.name, callItem.name, {
|
|
2062
|
+
indent: 2,
|
|
2063
|
+
prefix: 6
|
|
2064
|
+
});
|
|
1717
2065
|
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
1718
2066
|
if (callItem.docs.length) {
|
|
1719
2067
|
console.log();
|
|
@@ -1772,8 +2120,11 @@ async function handleEvents(target, opts) {
|
|
|
1772
2120
|
}
|
|
1773
2121
|
printHeading(`${pallet.name} Events`);
|
|
1774
2122
|
for (const e of pallet.events) {
|
|
1775
|
-
const fields2 =
|
|
1776
|
-
|
|
2123
|
+
const fields2 = prettyEventFields(meta, pallet.name, e.name, {
|
|
2124
|
+
indent: 2,
|
|
2125
|
+
prefix: e.name.length
|
|
2126
|
+
});
|
|
2127
|
+
console.log(` ${CYAN}${e.name}${RESET}${fields2}`);
|
|
1777
2128
|
const summary = firstSentence(e.docs);
|
|
1778
2129
|
if (summary) {
|
|
1779
2130
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -1799,7 +2150,10 @@ async function handleEvents(target, opts) {
|
|
|
1799
2150
|
return;
|
|
1800
2151
|
}
|
|
1801
2152
|
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
1802
|
-
const fields =
|
|
2153
|
+
const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
|
|
2154
|
+
indent: 2,
|
|
2155
|
+
prefix: 8
|
|
2156
|
+
});
|
|
1803
2157
|
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
1804
2158
|
if (eventItem.docs.length) {
|
|
1805
2159
|
console.log();
|
|
@@ -1926,24 +2280,30 @@ async function handleStorage(target, opts) {
|
|
|
1926
2280
|
chain: chainName,
|
|
1927
2281
|
pallet: pallet.name,
|
|
1928
2282
|
storage: pallet.storage.map((s) => {
|
|
1929
|
-
const
|
|
2283
|
+
const valueType2 = describeType(meta.lookup, s.valueTypeId);
|
|
1930
2284
|
const keyType = s.keyTypeId != null ? describeType(meta.lookup, s.keyTypeId) : undefined;
|
|
1931
|
-
return { name: s.name, type: s.type, valueType, keyType, docs: firstSentence(s.docs) };
|
|
2285
|
+
return { name: s.name, type: s.type, valueType: valueType2, keyType, docs: firstSentence(s.docs) };
|
|
1932
2286
|
})
|
|
1933
2287
|
}));
|
|
1934
2288
|
return;
|
|
1935
2289
|
}
|
|
1936
2290
|
printHeading(`${pallet.name} Storage`);
|
|
1937
2291
|
for (const s of pallet.storage) {
|
|
1938
|
-
const
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
2292
|
+
const isMap = s.keyTypeId != null;
|
|
2293
|
+
const tag = isMap ? `${DIM} [map]${RESET}` : "";
|
|
2294
|
+
console.log(` ${CYAN}${s.name}${RESET}${tag}`);
|
|
2295
|
+
if (isMap) {
|
|
2296
|
+
const keyType = prettyTypeById(meta.lookup, s.keyTypeId, {
|
|
2297
|
+
indent: 4,
|
|
2298
|
+
prefix: 5
|
|
2299
|
+
});
|
|
2300
|
+
console.log(` ${DIM}Key:${RESET} ${keyType}`);
|
|
1945
2301
|
}
|
|
1946
|
-
|
|
2302
|
+
const valueType2 = prettyTypeById(meta.lookup, s.valueTypeId, {
|
|
2303
|
+
indent: 4,
|
|
2304
|
+
prefix: 7
|
|
2305
|
+
});
|
|
2306
|
+
console.log(` ${DIM}Value:${RESET} ${valueType2}`);
|
|
1947
2307
|
const summary = firstSentence(s.docs);
|
|
1948
2308
|
if (summary) {
|
|
1949
2309
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -1958,7 +2318,7 @@ async function handleStorage(target, opts) {
|
|
|
1958
2318
|
throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
|
|
1959
2319
|
}
|
|
1960
2320
|
if (isJsonOutput(opts)) {
|
|
1961
|
-
const
|
|
2321
|
+
const valueType2 = describeType(meta.lookup, storageItem.valueTypeId);
|
|
1962
2322
|
const keyType = storageItem.keyTypeId != null ? describeType(meta.lookup, storageItem.keyTypeId) : undefined;
|
|
1963
2323
|
console.log(formatJson({
|
|
1964
2324
|
chain: chainName,
|
|
@@ -1966,18 +2326,26 @@ async function handleStorage(target, opts) {
|
|
|
1966
2326
|
item: storageItem.name,
|
|
1967
2327
|
category: "storage",
|
|
1968
2328
|
type: storageItem.type,
|
|
1969
|
-
valueType,
|
|
2329
|
+
valueType: valueType2,
|
|
1970
2330
|
keyType,
|
|
1971
2331
|
docs: storageItem.docs
|
|
1972
2332
|
}));
|
|
1973
2333
|
return;
|
|
1974
2334
|
}
|
|
1975
2335
|
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
1976
|
-
console.log(` ${BOLD}Type:${RESET}
|
|
1977
|
-
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
2336
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
1978
2337
|
if (storageItem.keyTypeId != null) {
|
|
1979
|
-
|
|
2338
|
+
const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
|
|
2339
|
+
indent: 2,
|
|
2340
|
+
prefix: 7
|
|
2341
|
+
});
|
|
2342
|
+
console.log(` ${BOLD}Key:${RESET} ${keyType}`);
|
|
1980
2343
|
}
|
|
2344
|
+
const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
|
|
2345
|
+
indent: 2,
|
|
2346
|
+
prefix: 7
|
|
2347
|
+
});
|
|
2348
|
+
console.log(` ${BOLD}Value:${RESET} ${valueType}`);
|
|
1981
2349
|
if (storageItem.docs.length) {
|
|
1982
2350
|
console.log();
|
|
1983
2351
|
printDocs(storageItem.docs);
|
|
@@ -2008,9 +2376,15 @@ async function showItemHelp(category, target, opts) {
|
|
|
2008
2376
|
throw new Error(suggestMessage(`method in ${api.name}`, methodName, names));
|
|
2009
2377
|
}
|
|
2010
2378
|
printHeading(`${api.name}.${method.name} (Runtime API)`);
|
|
2011
|
-
const argStr =
|
|
2012
|
-
|
|
2013
|
-
|
|
2379
|
+
const argStr = prettyRuntimeApiArgs(meta.lookup, method.inputs, {
|
|
2380
|
+
indent: 2,
|
|
2381
|
+
prefix: 9
|
|
2382
|
+
});
|
|
2383
|
+
const retStr = prettyTypeById(meta.lookup, method.output, {
|
|
2384
|
+
indent: 2,
|
|
2385
|
+
prefix: 9
|
|
2386
|
+
});
|
|
2387
|
+
console.log(` ${BOLD}Args:${RESET} ${argStr}`);
|
|
2014
2388
|
console.log(` ${BOLD}Returns:${RESET} ${retStr}`);
|
|
2015
2389
|
if (method.docs.length) {
|
|
2016
2390
|
console.log();
|
|
@@ -2053,7 +2427,10 @@ async function showItemHelp(category, target, opts) {
|
|
|
2053
2427
|
throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
|
|
2054
2428
|
}
|
|
2055
2429
|
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
2056
|
-
const args =
|
|
2430
|
+
const args = prettyCallArgs(meta, pallet.name, callItem.name, {
|
|
2431
|
+
indent: 2,
|
|
2432
|
+
prefix: 6
|
|
2433
|
+
});
|
|
2057
2434
|
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
2058
2435
|
if (callItem.docs.length) {
|
|
2059
2436
|
console.log();
|
|
@@ -2080,11 +2457,19 @@ async function showItemHelp(category, target, opts) {
|
|
|
2080
2457
|
throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
|
|
2081
2458
|
}
|
|
2082
2459
|
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
2083
|
-
console.log(` ${BOLD}Type:${RESET}
|
|
2084
|
-
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
2460
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
2085
2461
|
if (storageItem.keyTypeId != null) {
|
|
2086
|
-
|
|
2462
|
+
const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
|
|
2463
|
+
indent: 2,
|
|
2464
|
+
prefix: 7
|
|
2465
|
+
});
|
|
2466
|
+
console.log(` ${BOLD}Key:${RESET} ${keyType}`);
|
|
2087
2467
|
}
|
|
2468
|
+
const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
|
|
2469
|
+
indent: 2,
|
|
2470
|
+
prefix: 7
|
|
2471
|
+
});
|
|
2472
|
+
console.log(` ${BOLD}Value:${RESET} ${valueType}`);
|
|
2088
2473
|
if (storageItem.docs.length) {
|
|
2089
2474
|
console.log();
|
|
2090
2475
|
printDocs(storageItem.docs);
|
|
@@ -2111,7 +2496,11 @@ async function showItemHelp(category, target, opts) {
|
|
|
2111
2496
|
throw new Error(suggestMessage(`constant in ${pallet.name}`, itemName, names));
|
|
2112
2497
|
}
|
|
2113
2498
|
printHeading(`${pallet.name}.${constItem.name} (Constant)`);
|
|
2114
|
-
|
|
2499
|
+
const constType = prettyTypeById(meta.lookup, constItem.typeId, {
|
|
2500
|
+
indent: 2,
|
|
2501
|
+
prefix: 6
|
|
2502
|
+
});
|
|
2503
|
+
console.log(` ${BOLD}Type:${RESET} ${constType}`);
|
|
2115
2504
|
if (constItem.docs.length) {
|
|
2116
2505
|
console.log();
|
|
2117
2506
|
printDocs(constItem.docs);
|
|
@@ -2129,7 +2518,10 @@ async function showItemHelp(category, target, opts) {
|
|
|
2129
2518
|
throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
|
|
2130
2519
|
}
|
|
2131
2520
|
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
2132
|
-
const fields =
|
|
2521
|
+
const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
|
|
2522
|
+
indent: 2,
|
|
2523
|
+
prefix: 8
|
|
2524
|
+
});
|
|
2133
2525
|
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
2134
2526
|
if (eventItem.docs.length) {
|
|
2135
2527
|
console.log();
|
|
@@ -2164,6 +2556,7 @@ var init_focused_inspect = __esm(() => {
|
|
|
2164
2556
|
init_client();
|
|
2165
2557
|
init_metadata();
|
|
2166
2558
|
init_output();
|
|
2559
|
+
init_pretty_type();
|
|
2167
2560
|
});
|
|
2168
2561
|
|
|
2169
2562
|
// src/core/hash.ts
|
|
@@ -2553,7 +2946,7 @@ var init_complete = __esm(() => {
|
|
|
2553
2946
|
ext: "extensions"
|
|
2554
2947
|
};
|
|
2555
2948
|
NAMED_COMMANDS = ["chain", "account", "inspect", "hash", "sign", "parachain", "completions"];
|
|
2556
|
-
CHAIN_SUBCOMMANDS = ["add", "
|
|
2949
|
+
CHAIN_SUBCOMMANDS = ["add", "info", "list", "remove", "update"];
|
|
2557
2950
|
ACCOUNT_SUBCOMMANDS = [
|
|
2558
2951
|
"add",
|
|
2559
2952
|
"create",
|
|
@@ -2584,7 +2977,7 @@ var init_complete = __esm(() => {
|
|
|
2584
2977
|
// src/cli.ts
|
|
2585
2978
|
import cac from "cac";
|
|
2586
2979
|
// package.json
|
|
2587
|
-
var version = "1.
|
|
2980
|
+
var version = "1.17.0";
|
|
2588
2981
|
|
|
2589
2982
|
// src/commands/account.ts
|
|
2590
2983
|
init_accounts_store();
|
|
@@ -3427,6 +3820,8 @@ ${BOLD}Usage:${RESET}
|
|
|
3427
3820
|
$ dot chain update <name> Re-fetch metadata for a chain
|
|
3428
3821
|
$ dot chain update --all Re-fetch metadata for all configured chains
|
|
3429
3822
|
$ dot chain list List configured chains
|
|
3823
|
+
$ dot chain info <name> Show details for a single chain
|
|
3824
|
+
$ dot chain <name> Shortcut for \`chain info <name>\`
|
|
3430
3825
|
$ dot chain export [names...] Export chain configuration to stdout
|
|
3431
3826
|
$ dot chain import <file> Import chain configuration from a file
|
|
3432
3827
|
|
|
@@ -3436,6 +3831,9 @@ ${BOLD}Examples:${RESET}
|
|
|
3436
3831
|
$ dot chain add my-para --rpc wss://rpc.example.com --relay polkadot
|
|
3437
3832
|
$ dot chain add my-para --rpc wss://rpc.example.com --relay polkadot --parachain-id 2000
|
|
3438
3833
|
$ dot chain list
|
|
3834
|
+
$ dot chains -v
|
|
3835
|
+
$ dot chain info polkadot
|
|
3836
|
+
$ dot chain polkadot
|
|
3439
3837
|
$ dot chain update kusama
|
|
3440
3838
|
$ dot chain update --all
|
|
3441
3839
|
$ dot chain remove kusama
|
|
@@ -3448,7 +3846,7 @@ ${BOLD}Examples:${RESET}
|
|
|
3448
3846
|
$ dot chain import my-chains.json --no-metadata
|
|
3449
3847
|
`.trimStart();
|
|
3450
3848
|
function registerChainCommands(cli) {
|
|
3451
|
-
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) => {
|
|
3849
|
+
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) => {
|
|
3452
3850
|
if (!action) {
|
|
3453
3851
|
if (process.argv[2] === "chains")
|
|
3454
3852
|
return chainList(opts);
|
|
@@ -3462,17 +3860,24 @@ function registerChainCommands(cli) {
|
|
|
3462
3860
|
return chainRemove(names[0], opts);
|
|
3463
3861
|
case "list":
|
|
3464
3862
|
return chainList(opts);
|
|
3863
|
+
case "info":
|
|
3864
|
+
return chainInfo(names[0], opts);
|
|
3465
3865
|
case "update":
|
|
3466
3866
|
return chainUpdate(names[0], opts);
|
|
3467
3867
|
case "export":
|
|
3468
3868
|
return chainExport(names, opts);
|
|
3469
3869
|
case "import":
|
|
3470
3870
|
return chainImport(names[0], opts);
|
|
3471
|
-
default:
|
|
3871
|
+
default: {
|
|
3872
|
+
const config = await loadConfig();
|
|
3873
|
+
if (findChainName(config, action)) {
|
|
3874
|
+
return chainInfo(action, opts);
|
|
3875
|
+
}
|
|
3472
3876
|
console.error(`Unknown action "${action}".
|
|
3473
3877
|
`);
|
|
3474
3878
|
console.log(CHAIN_HELP);
|
|
3475
3879
|
process.exit(1);
|
|
3880
|
+
}
|
|
3476
3881
|
}
|
|
3477
3882
|
});
|
|
3478
3883
|
}
|
|
@@ -3582,6 +3987,7 @@ async function chainList(opts = {}) {
|
|
|
3582
3987
|
console.log(formatJson({ chains }));
|
|
3583
3988
|
return;
|
|
3584
3989
|
}
|
|
3990
|
+
const verbose = opts.verbose === true;
|
|
3585
3991
|
printHeading("Configured Chains");
|
|
3586
3992
|
const parachainsByRelay = new Map;
|
|
3587
3993
|
const standalone = [];
|
|
@@ -3603,7 +4009,7 @@ async function chainList(opts = {}) {
|
|
|
3603
4009
|
for (const relayName of relayNames) {
|
|
3604
4010
|
const relayConfig = config.chains[relayName];
|
|
3605
4011
|
if (relayConfig) {
|
|
3606
|
-
printChainLine(" ", relayName, relayConfig);
|
|
4012
|
+
printChainLine(" ", relayName, relayConfig, "", verbose);
|
|
3607
4013
|
}
|
|
3608
4014
|
const paras = parachainsByRelay.get(relayName) ?? [];
|
|
3609
4015
|
for (let i = 0;i < paras.length; i++) {
|
|
@@ -3611,17 +4017,21 @@ async function chainList(opts = {}) {
|
|
|
3611
4017
|
const isLast = i === paras.length - 1;
|
|
3612
4018
|
const prefix = isLast ? " └─ " : " ├─ ";
|
|
3613
4019
|
const idSuffix = chainConfig.parachainId != null ? ` ${DIM}[${chainConfig.parachainId}]${RESET}` : "";
|
|
3614
|
-
printChainLine(prefix, name, chainConfig, idSuffix);
|
|
4020
|
+
printChainLine(prefix, name, chainConfig, idSuffix, verbose);
|
|
3615
4021
|
}
|
|
3616
4022
|
console.log();
|
|
3617
4023
|
}
|
|
3618
4024
|
for (const [name, chainConfig] of standalone) {
|
|
3619
|
-
printChainLine(" ", name, chainConfig);
|
|
4025
|
+
printChainLine(" ", name, chainConfig, "", verbose);
|
|
3620
4026
|
}
|
|
3621
4027
|
if (standalone.length > 0)
|
|
3622
4028
|
console.log();
|
|
3623
4029
|
}
|
|
3624
|
-
function printChainLine(prefix, name, chainConfig, suffix = "") {
|
|
4030
|
+
function printChainLine(prefix, name, chainConfig, suffix = "", verbose = false) {
|
|
4031
|
+
if (!verbose) {
|
|
4032
|
+
console.log(`${prefix}${CYAN}${name}${RESET}${suffix}`);
|
|
4033
|
+
return;
|
|
4034
|
+
}
|
|
3625
4035
|
const rpcs = Array.isArray(chainConfig.rpc) ? chainConfig.rpc : [chainConfig.rpc];
|
|
3626
4036
|
console.log(`${prefix}${CYAN}${name}${RESET}${suffix} ${DIM}${rpcs[0]}${RESET}`);
|
|
3627
4037
|
const indent = prefix.replace(/[^\s]/g, " ");
|
|
@@ -3629,6 +4039,56 @@ function printChainLine(prefix, name, chainConfig, suffix = "") {
|
|
|
3629
4039
|
console.log(`${indent} ${DIM}${rpcs[i]}${RESET}`);
|
|
3630
4040
|
}
|
|
3631
4041
|
}
|
|
4042
|
+
async function chainInfo(name, opts = {}) {
|
|
4043
|
+
if (!name) {
|
|
4044
|
+
console.error("Usage: dot chain info <name>");
|
|
4045
|
+
process.exit(1);
|
|
4046
|
+
}
|
|
4047
|
+
const config = await loadConfig();
|
|
4048
|
+
const { name: resolved, chain } = resolveChain(config, name);
|
|
4049
|
+
const rpcs = Array.isArray(chain.rpc) ? chain.rpc : [chain.rpc];
|
|
4050
|
+
const parachains = Object.entries(config.chains).filter(([, c]) => c.relay === resolved).map(([n, c]) => ({ name: n, parachainId: c.parachainId }));
|
|
4051
|
+
const fingerprint = await loadMetadataFingerprint(resolved);
|
|
4052
|
+
if (isJsonOutput(opts)) {
|
|
4053
|
+
console.log(formatJson({
|
|
4054
|
+
name: resolved,
|
|
4055
|
+
rpc: rpcs,
|
|
4056
|
+
...chain.relay && { relay: chain.relay },
|
|
4057
|
+
...chain.parachainId != null && { parachainId: chain.parachainId },
|
|
4058
|
+
...parachains.length > 0 && { parachains },
|
|
4059
|
+
metadata: fingerprint ? {
|
|
4060
|
+
specName: fingerprint.specName,
|
|
4061
|
+
specVersion: fingerprint.specVersion,
|
|
4062
|
+
fetchedAt: fingerprint.fetchedAt
|
|
4063
|
+
} : null
|
|
4064
|
+
}));
|
|
4065
|
+
return;
|
|
4066
|
+
}
|
|
4067
|
+
printHeading(resolved);
|
|
4068
|
+
console.log(` ${CYAN}rpc:${RESET}`);
|
|
4069
|
+
for (const rpc of rpcs) {
|
|
4070
|
+
console.log(` ${DIM}${rpc}${RESET}`);
|
|
4071
|
+
}
|
|
4072
|
+
if (chain.relay) {
|
|
4073
|
+
console.log(` ${CYAN}relay:${RESET} ${chain.relay}`);
|
|
4074
|
+
}
|
|
4075
|
+
if (chain.parachainId != null) {
|
|
4076
|
+
console.log(` ${CYAN}parachain id:${RESET} ${chain.parachainId}`);
|
|
4077
|
+
}
|
|
4078
|
+
if (parachains.length > 0) {
|
|
4079
|
+
console.log(` ${CYAN}parachains:${RESET}`);
|
|
4080
|
+
for (const p of parachains) {
|
|
4081
|
+
const idSuffix = p.parachainId != null ? ` ${DIM}[${p.parachainId}]${RESET}` : "";
|
|
4082
|
+
console.log(` ${p.name}${idSuffix}`);
|
|
4083
|
+
}
|
|
4084
|
+
}
|
|
4085
|
+
console.log(` ${CYAN}metadata:${RESET}`);
|
|
4086
|
+
if (fingerprint) {
|
|
4087
|
+
console.log(` ${fingerprint.specName} v${fingerprint.specVersion} ${DIM}(cached ${fingerprint.fetchedAt})${RESET}`);
|
|
4088
|
+
} else {
|
|
4089
|
+
console.log(` ${DIM}not cached — run \`dot chain update ${resolved}\`${RESET}`);
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
3632
4092
|
async function chainUpdate(name, opts) {
|
|
3633
4093
|
const config = await loadConfig();
|
|
3634
4094
|
if (opts.all) {
|
|
@@ -4005,6 +4465,7 @@ init_store();
|
|
|
4005
4465
|
init_client();
|
|
4006
4466
|
init_metadata();
|
|
4007
4467
|
init_output();
|
|
4468
|
+
init_pretty_type();
|
|
4008
4469
|
async function loadMeta2(chainName, chainConfig, rpcOverride) {
|
|
4009
4470
|
if (rpcOverride) {
|
|
4010
4471
|
process.stderr.write(`Fetching metadata from ${chainName}...
|
|
@@ -4089,8 +4550,11 @@ async function handleCalls2(target, opts) {
|
|
|
4089
4550
|
}
|
|
4090
4551
|
printHeading(`${pallet.name} Calls`);
|
|
4091
4552
|
for (const c of pallet.calls) {
|
|
4092
|
-
const args2 =
|
|
4093
|
-
|
|
4553
|
+
const args2 = prettyCallArgs(meta, pallet.name, c.name, {
|
|
4554
|
+
indent: 2,
|
|
4555
|
+
prefix: c.name.length
|
|
4556
|
+
});
|
|
4557
|
+
console.log(` ${CYAN}${c.name}${RESET}${args2}`);
|
|
4094
4558
|
const summary = firstSentence(c.docs);
|
|
4095
4559
|
if (summary) {
|
|
4096
4560
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -4116,7 +4580,10 @@ async function handleCalls2(target, opts) {
|
|
|
4116
4580
|
return;
|
|
4117
4581
|
}
|
|
4118
4582
|
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
4119
|
-
const args =
|
|
4583
|
+
const args = prettyCallArgs(meta, pallet.name, callItem.name, {
|
|
4584
|
+
indent: 2,
|
|
4585
|
+
prefix: 6
|
|
4586
|
+
});
|
|
4120
4587
|
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
4121
4588
|
if (callItem.docs.length) {
|
|
4122
4589
|
console.log();
|
|
@@ -4175,8 +4642,11 @@ async function handleEvents2(target, opts) {
|
|
|
4175
4642
|
}
|
|
4176
4643
|
printHeading(`${pallet.name} Events`);
|
|
4177
4644
|
for (const e of pallet.events) {
|
|
4178
|
-
const fields2 =
|
|
4179
|
-
|
|
4645
|
+
const fields2 = prettyEventFields(meta, pallet.name, e.name, {
|
|
4646
|
+
indent: 2,
|
|
4647
|
+
prefix: e.name.length
|
|
4648
|
+
});
|
|
4649
|
+
console.log(` ${CYAN}${e.name}${RESET}${fields2}`);
|
|
4180
4650
|
const summary = firstSentence(e.docs);
|
|
4181
4651
|
if (summary) {
|
|
4182
4652
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -4202,7 +4672,10 @@ async function handleEvents2(target, opts) {
|
|
|
4202
4672
|
return;
|
|
4203
4673
|
}
|
|
4204
4674
|
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
4205
|
-
const fields =
|
|
4675
|
+
const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
|
|
4676
|
+
indent: 2,
|
|
4677
|
+
prefix: 8
|
|
4678
|
+
});
|
|
4206
4679
|
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
4207
4680
|
if (eventItem.docs.length) {
|
|
4208
4681
|
console.log();
|
|
@@ -4329,24 +4802,30 @@ async function handleStorage2(target, opts) {
|
|
|
4329
4802
|
chain: chainName,
|
|
4330
4803
|
pallet: pallet.name,
|
|
4331
4804
|
storage: pallet.storage.map((s) => {
|
|
4332
|
-
const
|
|
4805
|
+
const valueType2 = describeType(meta.lookup, s.valueTypeId);
|
|
4333
4806
|
const keyType = s.keyTypeId != null ? describeType(meta.lookup, s.keyTypeId) : undefined;
|
|
4334
|
-
return { name: s.name, type: s.type, valueType, keyType, docs: firstSentence(s.docs) };
|
|
4807
|
+
return { name: s.name, type: s.type, valueType: valueType2, keyType, docs: firstSentence(s.docs) };
|
|
4335
4808
|
})
|
|
4336
4809
|
}));
|
|
4337
4810
|
return;
|
|
4338
4811
|
}
|
|
4339
4812
|
printHeading(`${pallet.name} Storage`);
|
|
4340
4813
|
for (const s of pallet.storage) {
|
|
4341
|
-
const
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
|
|
4347
|
-
|
|
4814
|
+
const isMap = s.keyTypeId != null;
|
|
4815
|
+
const tag = isMap ? `${DIM} [map]${RESET}` : "";
|
|
4816
|
+
console.log(` ${CYAN}${s.name}${RESET}${tag}`);
|
|
4817
|
+
if (isMap) {
|
|
4818
|
+
const keyType = prettyTypeById(meta.lookup, s.keyTypeId, {
|
|
4819
|
+
indent: 4,
|
|
4820
|
+
prefix: 5
|
|
4821
|
+
});
|
|
4822
|
+
console.log(` ${DIM}Key:${RESET} ${keyType}`);
|
|
4348
4823
|
}
|
|
4349
|
-
|
|
4824
|
+
const valueType2 = prettyTypeById(meta.lookup, s.valueTypeId, {
|
|
4825
|
+
indent: 4,
|
|
4826
|
+
prefix: 7
|
|
4827
|
+
});
|
|
4828
|
+
console.log(` ${DIM}Value:${RESET} ${valueType2}`);
|
|
4350
4829
|
const summary = firstSentence(s.docs);
|
|
4351
4830
|
if (summary) {
|
|
4352
4831
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -4361,7 +4840,7 @@ async function handleStorage2(target, opts) {
|
|
|
4361
4840
|
throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
|
|
4362
4841
|
}
|
|
4363
4842
|
if (isJsonOutput(opts)) {
|
|
4364
|
-
const
|
|
4843
|
+
const valueType2 = describeType(meta.lookup, storageItem.valueTypeId);
|
|
4365
4844
|
const keyType = storageItem.keyTypeId != null ? describeType(meta.lookup, storageItem.keyTypeId) : undefined;
|
|
4366
4845
|
console.log(formatJson({
|
|
4367
4846
|
chain: chainName,
|
|
@@ -4369,18 +4848,26 @@ async function handleStorage2(target, opts) {
|
|
|
4369
4848
|
item: storageItem.name,
|
|
4370
4849
|
category: "storage",
|
|
4371
4850
|
type: storageItem.type,
|
|
4372
|
-
valueType,
|
|
4851
|
+
valueType: valueType2,
|
|
4373
4852
|
keyType,
|
|
4374
4853
|
docs: storageItem.docs
|
|
4375
4854
|
}));
|
|
4376
4855
|
return;
|
|
4377
4856
|
}
|
|
4378
4857
|
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
4379
|
-
console.log(` ${BOLD}Type:${RESET}
|
|
4380
|
-
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
4858
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
4381
4859
|
if (storageItem.keyTypeId != null) {
|
|
4382
|
-
|
|
4860
|
+
const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
|
|
4861
|
+
indent: 2,
|
|
4862
|
+
prefix: 7
|
|
4863
|
+
});
|
|
4864
|
+
console.log(` ${BOLD}Key:${RESET} ${keyType}`);
|
|
4383
4865
|
}
|
|
4866
|
+
const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
|
|
4867
|
+
indent: 2,
|
|
4868
|
+
prefix: 7
|
|
4869
|
+
});
|
|
4870
|
+
console.log(` ${BOLD}Value:${RESET} ${valueType}`);
|
|
4384
4871
|
if (storageItem.docs.length) {
|
|
4385
4872
|
console.log();
|
|
4386
4873
|
printDocs(storageItem.docs);
|
|
@@ -4411,9 +4898,15 @@ async function showItemHelp2(category, target, opts) {
|
|
|
4411
4898
|
throw new Error(suggestMessage(`method in ${api.name}`, methodName, names));
|
|
4412
4899
|
}
|
|
4413
4900
|
printHeading(`${api.name}.${method.name} (Runtime API)`);
|
|
4414
|
-
const argStr =
|
|
4415
|
-
|
|
4416
|
-
|
|
4901
|
+
const argStr = prettyRuntimeApiArgs(meta.lookup, method.inputs, {
|
|
4902
|
+
indent: 2,
|
|
4903
|
+
prefix: 9
|
|
4904
|
+
});
|
|
4905
|
+
const retStr = prettyTypeById(meta.lookup, method.output, {
|
|
4906
|
+
indent: 2,
|
|
4907
|
+
prefix: 9
|
|
4908
|
+
});
|
|
4909
|
+
console.log(` ${BOLD}Args:${RESET} ${argStr}`);
|
|
4417
4910
|
console.log(` ${BOLD}Returns:${RESET} ${retStr}`);
|
|
4418
4911
|
if (method.docs.length) {
|
|
4419
4912
|
console.log();
|
|
@@ -4456,7 +4949,10 @@ async function showItemHelp2(category, target, opts) {
|
|
|
4456
4949
|
throw new Error(suggestMessage(`call in ${pallet.name}`, itemName, names));
|
|
4457
4950
|
}
|
|
4458
4951
|
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
4459
|
-
const args =
|
|
4952
|
+
const args = prettyCallArgs(meta, pallet.name, callItem.name, {
|
|
4953
|
+
indent: 2,
|
|
4954
|
+
prefix: 6
|
|
4955
|
+
});
|
|
4460
4956
|
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
4461
4957
|
if (callItem.docs.length) {
|
|
4462
4958
|
console.log();
|
|
@@ -4483,11 +4979,19 @@ async function showItemHelp2(category, target, opts) {
|
|
|
4483
4979
|
throw new Error(suggestMessage(`storage item in ${pallet.name}`, itemName, names));
|
|
4484
4980
|
}
|
|
4485
4981
|
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
4486
|
-
console.log(` ${BOLD}Type:${RESET}
|
|
4487
|
-
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
4982
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
4488
4983
|
if (storageItem.keyTypeId != null) {
|
|
4489
|
-
|
|
4984
|
+
const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
|
|
4985
|
+
indent: 2,
|
|
4986
|
+
prefix: 7
|
|
4987
|
+
});
|
|
4988
|
+
console.log(` ${BOLD}Key:${RESET} ${keyType}`);
|
|
4490
4989
|
}
|
|
4990
|
+
const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
|
|
4991
|
+
indent: 2,
|
|
4992
|
+
prefix: 7
|
|
4993
|
+
});
|
|
4994
|
+
console.log(` ${BOLD}Value:${RESET} ${valueType}`);
|
|
4491
4995
|
if (storageItem.docs.length) {
|
|
4492
4996
|
console.log();
|
|
4493
4997
|
printDocs(storageItem.docs);
|
|
@@ -4514,7 +5018,11 @@ async function showItemHelp2(category, target, opts) {
|
|
|
4514
5018
|
throw new Error(suggestMessage(`constant in ${pallet.name}`, itemName, names));
|
|
4515
5019
|
}
|
|
4516
5020
|
printHeading(`${pallet.name}.${constItem.name} (Constant)`);
|
|
4517
|
-
|
|
5021
|
+
const constType = prettyTypeById(meta.lookup, constItem.typeId, {
|
|
5022
|
+
indent: 2,
|
|
5023
|
+
prefix: 6
|
|
5024
|
+
});
|
|
5025
|
+
console.log(` ${BOLD}Type:${RESET} ${constType}`);
|
|
4518
5026
|
if (constItem.docs.length) {
|
|
4519
5027
|
console.log();
|
|
4520
5028
|
printDocs(constItem.docs);
|
|
@@ -4532,7 +5040,10 @@ async function showItemHelp2(category, target, opts) {
|
|
|
4532
5040
|
throw new Error(suggestMessage(`event in ${pallet.name}`, itemName, names));
|
|
4533
5041
|
}
|
|
4534
5042
|
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
4535
|
-
const fields =
|
|
5043
|
+
const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
|
|
5044
|
+
indent: 2,
|
|
5045
|
+
prefix: 8
|
|
5046
|
+
});
|
|
4536
5047
|
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
4537
5048
|
if (eventItem.docs.length) {
|
|
4538
5049
|
console.log();
|
|
@@ -4607,8 +5118,16 @@ async function handleExtensions(target, opts) {
|
|
|
4607
5118
|
return;
|
|
4608
5119
|
}
|
|
4609
5120
|
printHeading(`${described.identifier} (Transaction Extension)`);
|
|
4610
|
-
|
|
4611
|
-
|
|
5121
|
+
const valueType = prettyTypeById(meta.lookup, described.valueTypeId, {
|
|
5122
|
+
indent: 2,
|
|
5123
|
+
prefix: 18
|
|
5124
|
+
});
|
|
5125
|
+
const addSigType = prettyTypeById(meta.lookup, described.additionalSignedTypeId, {
|
|
5126
|
+
indent: 2,
|
|
5127
|
+
prefix: 18
|
|
5128
|
+
});
|
|
5129
|
+
console.log(` ${BOLD}Value type:${RESET} ${valueType}`);
|
|
5130
|
+
console.log(` ${BOLD}AdditionalSigned:${RESET} ${addSigType}`);
|
|
4612
5131
|
console.log(` ${BOLD}Handled by:${RESET} ${described.isBuiltin ? "polkadot-api (builtin)" : "user (custom — provide via --ext)"}`);
|
|
4613
5132
|
if (!described.isBuiltin) {
|
|
4614
5133
|
console.log();
|
|
@@ -4692,6 +5211,7 @@ init_store();
|
|
|
4692
5211
|
init_client();
|
|
4693
5212
|
init_metadata();
|
|
4694
5213
|
init_output();
|
|
5214
|
+
init_pretty_type();
|
|
4695
5215
|
|
|
4696
5216
|
// src/utils/parse-target.ts
|
|
4697
5217
|
function parseTarget(input, options) {
|
|
@@ -4868,15 +5388,21 @@ function registerInspectCommand(cli) {
|
|
|
4868
5388
|
if (pallet2.storage.length) {
|
|
4869
5389
|
console.log(` ${BOLD}Storage Items:${RESET}`);
|
|
4870
5390
|
for (const s of pallet2.storage) {
|
|
4871
|
-
const
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
|
|
4877
|
-
|
|
5391
|
+
const isMap = s.keyTypeId != null;
|
|
5392
|
+
const tag = isMap ? `${DIM} [map]${RESET}` : "";
|
|
5393
|
+
console.log(` ${CYAN}${s.name}${RESET}${tag}`);
|
|
5394
|
+
if (isMap) {
|
|
5395
|
+
const keyType = prettyTypeById(meta.lookup, s.keyTypeId, {
|
|
5396
|
+
indent: 6,
|
|
5397
|
+
prefix: 7
|
|
5398
|
+
});
|
|
5399
|
+
console.log(` ${DIM}Key:${RESET} ${keyType}`);
|
|
4878
5400
|
}
|
|
4879
|
-
|
|
5401
|
+
const valueType = prettyTypeById(meta.lookup, s.valueTypeId, {
|
|
5402
|
+
indent: 6,
|
|
5403
|
+
prefix: 7
|
|
5404
|
+
});
|
|
5405
|
+
console.log(` ${DIM}Value:${RESET} ${valueType}`);
|
|
4880
5406
|
const summary = firstSentence(s.docs);
|
|
4881
5407
|
if (summary) {
|
|
4882
5408
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -4887,8 +5413,11 @@ function registerInspectCommand(cli) {
|
|
|
4887
5413
|
if (pallet2.constants.length) {
|
|
4888
5414
|
console.log(` ${BOLD}Constants:${RESET}`);
|
|
4889
5415
|
for (const c of pallet2.constants) {
|
|
4890
|
-
const typeStr =
|
|
4891
|
-
|
|
5416
|
+
const typeStr = prettyTypeById(meta.lookup, c.typeId, {
|
|
5417
|
+
indent: 4,
|
|
5418
|
+
prefix: c.name.length + 2
|
|
5419
|
+
});
|
|
5420
|
+
console.log(` ${CYAN}${c.name}${RESET}: ${typeStr}`);
|
|
4892
5421
|
const summary = firstSentence(c.docs);
|
|
4893
5422
|
if (summary) {
|
|
4894
5423
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -4899,8 +5428,11 @@ function registerInspectCommand(cli) {
|
|
|
4899
5428
|
if (pallet2.calls.length) {
|
|
4900
5429
|
console.log(` ${BOLD}Calls:${RESET}`);
|
|
4901
5430
|
for (const c of pallet2.calls) {
|
|
4902
|
-
const args =
|
|
4903
|
-
|
|
5431
|
+
const args = prettyCallArgs(meta, pallet2.name, c.name, {
|
|
5432
|
+
indent: 4,
|
|
5433
|
+
prefix: c.name.length
|
|
5434
|
+
});
|
|
5435
|
+
console.log(` ${CYAN}${c.name}${RESET}${args}`);
|
|
4904
5436
|
const summary = firstSentence(c.docs);
|
|
4905
5437
|
if (summary) {
|
|
4906
5438
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -4911,8 +5443,11 @@ function registerInspectCommand(cli) {
|
|
|
4911
5443
|
if (pallet2.events.length) {
|
|
4912
5444
|
console.log(` ${BOLD}Events:${RESET}`);
|
|
4913
5445
|
for (const e of pallet2.events) {
|
|
4914
|
-
const fields =
|
|
4915
|
-
|
|
5446
|
+
const fields = prettyEventFields(meta, pallet2.name, e.name, {
|
|
5447
|
+
indent: 4,
|
|
5448
|
+
prefix: e.name.length
|
|
5449
|
+
});
|
|
5450
|
+
console.log(` ${CYAN}${e.name}${RESET}${fields}`);
|
|
4916
5451
|
const summary = firstSentence(e.docs);
|
|
4917
5452
|
if (summary) {
|
|
4918
5453
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -5014,11 +5549,19 @@ function registerInspectCommand(cli) {
|
|
|
5014
5549
|
const storageItem = pallet.storage.find((s) => s.name.toLowerCase() === itemName.toLowerCase());
|
|
5015
5550
|
if (storageItem) {
|
|
5016
5551
|
printHeading(`${pallet.name}.${storageItem.name} (Storage)`);
|
|
5017
|
-
console.log(` ${BOLD}Type:${RESET}
|
|
5018
|
-
console.log(` ${BOLD}Value:${RESET} ${describeType(meta.lookup, storageItem.valueTypeId)}`);
|
|
5552
|
+
console.log(` ${BOLD}Type:${RESET} ${storageItem.type}`);
|
|
5019
5553
|
if (storageItem.keyTypeId != null) {
|
|
5020
|
-
|
|
5554
|
+
const keyType = prettyTypeById(meta.lookup, storageItem.keyTypeId, {
|
|
5555
|
+
indent: 2,
|
|
5556
|
+
prefix: 7
|
|
5557
|
+
});
|
|
5558
|
+
console.log(` ${BOLD}Key:${RESET} ${keyType}`);
|
|
5021
5559
|
}
|
|
5560
|
+
const valueType = prettyTypeById(meta.lookup, storageItem.valueTypeId, {
|
|
5561
|
+
indent: 2,
|
|
5562
|
+
prefix: 7
|
|
5563
|
+
});
|
|
5564
|
+
console.log(` ${BOLD}Value:${RESET} ${valueType}`);
|
|
5022
5565
|
if (storageItem.docs.length) {
|
|
5023
5566
|
console.log();
|
|
5024
5567
|
printDocs(storageItem.docs);
|
|
@@ -5029,7 +5572,11 @@ function registerInspectCommand(cli) {
|
|
|
5029
5572
|
const constantItem = pallet.constants.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
|
|
5030
5573
|
if (constantItem) {
|
|
5031
5574
|
printHeading(`${pallet.name}.${constantItem.name} (Constant)`);
|
|
5032
|
-
|
|
5575
|
+
const typeStr = prettyTypeById(meta.lookup, constantItem.typeId, {
|
|
5576
|
+
indent: 2,
|
|
5577
|
+
prefix: 6
|
|
5578
|
+
});
|
|
5579
|
+
console.log(` ${BOLD}Type:${RESET} ${typeStr}`);
|
|
5033
5580
|
if (constantItem.docs.length) {
|
|
5034
5581
|
console.log();
|
|
5035
5582
|
printDocs(constantItem.docs);
|
|
@@ -5040,7 +5587,10 @@ function registerInspectCommand(cli) {
|
|
|
5040
5587
|
const callItem = pallet.calls.find((c) => c.name.toLowerCase() === itemName.toLowerCase());
|
|
5041
5588
|
if (callItem) {
|
|
5042
5589
|
printHeading(`${pallet.name}.${callItem.name} (Call)`);
|
|
5043
|
-
const args =
|
|
5590
|
+
const args = prettyCallArgs(meta, pallet.name, callItem.name, {
|
|
5591
|
+
indent: 2,
|
|
5592
|
+
prefix: 6
|
|
5593
|
+
});
|
|
5044
5594
|
console.log(` ${BOLD}Args:${RESET} ${args}`);
|
|
5045
5595
|
if (callItem.docs.length) {
|
|
5046
5596
|
console.log();
|
|
@@ -5052,7 +5602,10 @@ function registerInspectCommand(cli) {
|
|
|
5052
5602
|
const eventItem = pallet.events.find((e) => e.name.toLowerCase() === itemName.toLowerCase());
|
|
5053
5603
|
if (eventItem) {
|
|
5054
5604
|
printHeading(`${pallet.name}.${eventItem.name} (Event)`);
|
|
5055
|
-
const fields =
|
|
5605
|
+
const fields = prettyEventFields(meta, pallet.name, eventItem.name, {
|
|
5606
|
+
indent: 2,
|
|
5607
|
+
prefix: 8
|
|
5608
|
+
});
|
|
5056
5609
|
console.log(` ${BOLD}Fields:${RESET} ${fields}`);
|
|
5057
5610
|
if (eventItem.docs.length) {
|
|
5058
5611
|
console.log();
|
|
@@ -5081,6 +5634,56 @@ function registerInspectCommand(cli) {
|
|
|
5081
5634
|
});
|
|
5082
5635
|
}
|
|
5083
5636
|
|
|
5637
|
+
// src/commands/metadata.ts
|
|
5638
|
+
init_store();
|
|
5639
|
+
init_client();
|
|
5640
|
+
init_metadata();
|
|
5641
|
+
init_output();
|
|
5642
|
+
init_errors();
|
|
5643
|
+
function buildMetadataPayload(chainName, meta, fingerprint) {
|
|
5644
|
+
return {
|
|
5645
|
+
chain: chainName,
|
|
5646
|
+
runtime: { ...fingerprint ?? {}, metadataVersion: meta.version },
|
|
5647
|
+
pallets: listPallets(meta),
|
|
5648
|
+
runtimeApis: listRuntimeApis(meta),
|
|
5649
|
+
transactionExtensions: getSignedExtensions(meta)
|
|
5650
|
+
};
|
|
5651
|
+
}
|
|
5652
|
+
async function handleMetadata(chain, opts) {
|
|
5653
|
+
const config = await loadConfig();
|
|
5654
|
+
const { name: chainName, chain: chainConfig } = resolveChain(config, chain);
|
|
5655
|
+
let rawBytes;
|
|
5656
|
+
if (opts.cached) {
|
|
5657
|
+
rawBytes = await loadMetadata(chainName);
|
|
5658
|
+
if (!rawBytes) {
|
|
5659
|
+
throw new CliError(`No cached metadata for "${chainName}". Run \`dot chain update ${chainName}\` first, or omit --cached to fetch fresh.`);
|
|
5660
|
+
}
|
|
5661
|
+
} else {
|
|
5662
|
+
const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
|
|
5663
|
+
try {
|
|
5664
|
+
await fetchMetadataFromChain(clientHandle, chainName);
|
|
5665
|
+
} finally {
|
|
5666
|
+
clientHandle.destroy();
|
|
5667
|
+
}
|
|
5668
|
+
rawBytes = await loadMetadata(chainName);
|
|
5669
|
+
if (!rawBytes) {
|
|
5670
|
+
throw new CliError(`Failed to load metadata for "${chainName}" after fetch.`);
|
|
5671
|
+
}
|
|
5672
|
+
}
|
|
5673
|
+
if (opts.raw) {
|
|
5674
|
+
await writeStdout(`0x${Buffer.from(rawBytes).toString("hex")}
|
|
5675
|
+
`);
|
|
5676
|
+
return;
|
|
5677
|
+
}
|
|
5678
|
+
const meta = parseMetadata(rawBytes);
|
|
5679
|
+
const fingerprint = await loadMetadataFingerprint(chainName);
|
|
5680
|
+
await writeStdout(`${formatJson(buildMetadataPayload(chainName, meta, fingerprint))}
|
|
5681
|
+
`);
|
|
5682
|
+
}
|
|
5683
|
+
function registerMetadataCommand(cli) {
|
|
5684
|
+
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));
|
|
5685
|
+
}
|
|
5686
|
+
|
|
5084
5687
|
// src/commands/parachain.ts
|
|
5085
5688
|
init_accounts();
|
|
5086
5689
|
init_output();
|
|
@@ -5176,6 +5779,7 @@ init_store();
|
|
|
5176
5779
|
init_client();
|
|
5177
5780
|
init_metadata();
|
|
5178
5781
|
init_output();
|
|
5782
|
+
init_pretty_type();
|
|
5179
5783
|
init_focused_inspect();
|
|
5180
5784
|
init_tx();
|
|
5181
5785
|
async function handleQuery(target, keys, opts) {
|
|
@@ -5186,10 +5790,11 @@ async function handleQuery(target, keys, opts) {
|
|
|
5186
5790
|
const pallets = listPallets(meta);
|
|
5187
5791
|
const withStorage = pallets.filter((p) => p.storage.length > 0);
|
|
5188
5792
|
if (isJsonOutput(opts)) {
|
|
5189
|
-
|
|
5793
|
+
await writeStdout(`${formatJson({
|
|
5190
5794
|
chain: chainName2,
|
|
5191
5795
|
pallets: withStorage.map((p) => ({ name: p.name, storage: p.storage.length }))
|
|
5192
|
-
})
|
|
5796
|
+
})}
|
|
5797
|
+
`);
|
|
5193
5798
|
return;
|
|
5194
5799
|
}
|
|
5195
5800
|
printHeading(`Pallets with storage on ${chainName2} (${withStorage.length})`);
|
|
@@ -5207,14 +5812,15 @@ async function handleQuery(target, keys, opts) {
|
|
|
5207
5812
|
const pallet2 = resolvePallet(meta, palletName(target));
|
|
5208
5813
|
if (pallet2.storage.length === 0) {
|
|
5209
5814
|
if (isJsonOutput(opts)) {
|
|
5210
|
-
|
|
5815
|
+
await writeStdout(`${formatJson({ chain: chainName2, pallet: pallet2.name, storage: [] })}
|
|
5816
|
+
`);
|
|
5211
5817
|
} else {
|
|
5212
5818
|
console.log(`No storage items in ${pallet2.name}.`);
|
|
5213
5819
|
}
|
|
5214
5820
|
return;
|
|
5215
5821
|
}
|
|
5216
5822
|
if (isJsonOutput(opts)) {
|
|
5217
|
-
|
|
5823
|
+
await writeStdout(`${formatJson({
|
|
5218
5824
|
chain: chainName2,
|
|
5219
5825
|
pallet: pallet2.name,
|
|
5220
5826
|
storage: pallet2.storage.map((s) => {
|
|
@@ -5222,20 +5828,27 @@ async function handleQuery(target, keys, opts) {
|
|
|
5222
5828
|
const keyType = s.keyTypeId != null ? describeType(meta.lookup, s.keyTypeId) : undefined;
|
|
5223
5829
|
return { name: s.name, type: s.type, valueType, keyType, docs: firstSentence(s.docs) };
|
|
5224
5830
|
})
|
|
5225
|
-
})
|
|
5831
|
+
})}
|
|
5832
|
+
`);
|
|
5226
5833
|
return;
|
|
5227
5834
|
}
|
|
5228
5835
|
printHeading(`${pallet2.name} Storage`);
|
|
5229
5836
|
for (const s of pallet2.storage) {
|
|
5230
|
-
const
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5837
|
+
const isMap = s.keyTypeId != null;
|
|
5838
|
+
const tag = isMap ? `${DIM} [map]${RESET}` : "";
|
|
5839
|
+
console.log(` ${CYAN}${s.name}${RESET}${tag}`);
|
|
5840
|
+
if (isMap) {
|
|
5841
|
+
const keyType = prettyTypeById(meta.lookup, s.keyTypeId, {
|
|
5842
|
+
indent: 4,
|
|
5843
|
+
prefix: 5
|
|
5844
|
+
});
|
|
5845
|
+
console.log(` ${DIM}Key:${RESET} ${keyType}`);
|
|
5237
5846
|
}
|
|
5238
|
-
|
|
5847
|
+
const valueType = prettyTypeById(meta.lookup, s.valueTypeId, {
|
|
5848
|
+
indent: 4,
|
|
5849
|
+
prefix: 7
|
|
5850
|
+
});
|
|
5851
|
+
console.log(` ${DIM}Value:${RESET} ${valueType}`);
|
|
5239
5852
|
const summary = firstSentence(s.docs);
|
|
5240
5853
|
if (summary) {
|
|
5241
5854
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -5276,14 +5889,19 @@ async function handleQuery(target, keys, opts) {
|
|
|
5276
5889
|
console.log(`${DIM}Hint: use --dump to fetch all entries${RESET}`);
|
|
5277
5890
|
return;
|
|
5278
5891
|
}
|
|
5279
|
-
const entries = await storageApi.getEntries(...parsedKeys);
|
|
5280
|
-
|
|
5892
|
+
const entries = await withStalenessSuggestion(chainName, clientHandle, () => storageApi.getEntries(...parsedKeys));
|
|
5893
|
+
const rows = entries.map((e) => ({
|
|
5281
5894
|
keys: e.keyArgs,
|
|
5282
5895
|
value: e.value
|
|
5283
|
-
}))
|
|
5896
|
+
}));
|
|
5897
|
+
const text = format === "json" ? formatJson(rows) : formatPretty(rows);
|
|
5898
|
+
await writeStdout(`${text}
|
|
5899
|
+
`);
|
|
5284
5900
|
} else {
|
|
5285
|
-
const result = await storageApi.getValue(...parsedKeys);
|
|
5286
|
-
|
|
5901
|
+
const result = await withStalenessSuggestion(chainName, clientHandle, () => storageApi.getValue(...parsedKeys));
|
|
5902
|
+
const text = format === "json" ? formatJson(result) : formatPretty(result);
|
|
5903
|
+
await writeStdout(`${text}
|
|
5904
|
+
`);
|
|
5287
5905
|
}
|
|
5288
5906
|
} finally {
|
|
5289
5907
|
clientHandle.destroy();
|
|
@@ -5430,6 +6048,7 @@ init_accounts();
|
|
|
5430
6048
|
init_client();
|
|
5431
6049
|
init_metadata();
|
|
5432
6050
|
init_output();
|
|
6051
|
+
init_pretty_type();
|
|
5433
6052
|
init_resolve_address();
|
|
5434
6053
|
init_binary_display();
|
|
5435
6054
|
init_errors();
|
|
@@ -5562,8 +6181,11 @@ async function handleTx(target, args, opts) {
|
|
|
5562
6181
|
}
|
|
5563
6182
|
printHeading(`${pallet2.name} Calls`);
|
|
5564
6183
|
for (const c of pallet2.calls) {
|
|
5565
|
-
const callArgs =
|
|
5566
|
-
|
|
6184
|
+
const callArgs = prettyCallArgs(meta, pallet2.name, c.name, {
|
|
6185
|
+
indent: 2,
|
|
6186
|
+
prefix: c.name.length
|
|
6187
|
+
});
|
|
6188
|
+
console.log(` ${CYAN}${c.name}${RESET}${callArgs}`);
|
|
5567
6189
|
const summary = firstSentence(c.docs);
|
|
5568
6190
|
if (summary) {
|
|
5569
6191
|
console.log(` ${DIM}${summary}${RESET}`);
|
|
@@ -5714,6 +6336,7 @@ async function handleTx(target, args, opts) {
|
|
|
5714
6336
|
callHex = Binary3.toHex(encodedCall);
|
|
5715
6337
|
}
|
|
5716
6338
|
const decodedStr = decodeCall(meta, callHex);
|
|
6339
|
+
const decodedObj = decodeCallObject(meta, callHex);
|
|
5717
6340
|
if (opts.dryRun && opts.unsigned) {
|
|
5718
6341
|
if (isJsonOutput(opts)) {
|
|
5719
6342
|
console.log(formatJson({
|
|
@@ -5728,17 +6351,18 @@ async function handleTx(target, args, opts) {
|
|
|
5728
6351
|
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
5729
6352
|
console.log(` ${BOLD}Type:${RESET} unsigned (bare)`);
|
|
5730
6353
|
console.log(` ${BOLD}Call:${RESET} ${callHex}`);
|
|
5731
|
-
|
|
6354
|
+
printDecodedCall(decodedObj, decodedStr);
|
|
5732
6355
|
console.log(` ${BOLD}Fees:${RESET} ${DIM}N/A (unsigned transaction)${RESET}`);
|
|
5733
6356
|
return;
|
|
5734
6357
|
}
|
|
5735
6358
|
if (opts.dryRun) {
|
|
5736
6359
|
const signerAddress = toSs58(signer.publicKey);
|
|
5737
6360
|
let estimatedFees;
|
|
6361
|
+
let estimationError;
|
|
5738
6362
|
try {
|
|
5739
|
-
estimatedFees = String(await tx.getEstimatedFees(signer?.publicKey, txOptions));
|
|
5740
|
-
} catch {
|
|
5741
|
-
|
|
6363
|
+
estimatedFees = String(await withStalenessSuggestion(chainName, clientHandle, () => tx.getEstimatedFees(signer?.publicKey, txOptions)));
|
|
6364
|
+
} catch (err) {
|
|
6365
|
+
estimationError = err instanceof Error ? err.message : String(err);
|
|
5742
6366
|
}
|
|
5743
6367
|
if (isJsonOutput(opts)) {
|
|
5744
6368
|
const result2 = {
|
|
@@ -5748,6 +6372,8 @@ async function handleTx(target, args, opts) {
|
|
|
5748
6372
|
decoded: decodedStr,
|
|
5749
6373
|
estimatedFees
|
|
5750
6374
|
};
|
|
6375
|
+
if (estimationError !== undefined)
|
|
6376
|
+
result2.estimationError = estimationError;
|
|
5751
6377
|
if (nonce !== undefined)
|
|
5752
6378
|
result2.nonce = nonce;
|
|
5753
6379
|
if (tip !== undefined)
|
|
@@ -5764,7 +6390,7 @@ async function handleTx(target, args, opts) {
|
|
|
5764
6390
|
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
5765
6391
|
console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
|
|
5766
6392
|
console.log(` ${BOLD}Call:${RESET} ${callHex}`);
|
|
5767
|
-
|
|
6393
|
+
printDecodedCall(decodedObj, decodedStr);
|
|
5768
6394
|
if (nonce !== undefined)
|
|
5769
6395
|
console.log(` ${BOLD}Nonce:${RESET} ${nonce}`);
|
|
5770
6396
|
if (tip !== undefined)
|
|
@@ -5779,6 +6405,12 @@ async function handleTx(target, args, opts) {
|
|
|
5779
6405
|
console.log(` ${BOLD}Estimated fees:${RESET} ${estimatedFees}`);
|
|
5780
6406
|
} else {
|
|
5781
6407
|
console.log(` ${BOLD}Estimated fees:${RESET} ${YELLOW}unable to estimate${RESET}`);
|
|
6408
|
+
if (estimationError) {
|
|
6409
|
+
const formatted = formatRuntimeError(estimationError).replace(/\n/g, `
|
|
6410
|
+
`);
|
|
6411
|
+
console.log(` ${YELLOW}⚠${RESET} ${formatted}`);
|
|
6412
|
+
console.log(` ${DIM}Submitting this transaction is likely to fail.${RESET}`);
|
|
6413
|
+
}
|
|
5782
6414
|
}
|
|
5783
6415
|
return;
|
|
5784
6416
|
}
|
|
@@ -5798,7 +6430,7 @@ async function handleTx(target, args, opts) {
|
|
|
5798
6430
|
}
|
|
5799
6431
|
const observable = clientHandle.client.submitAndWatch(generalTx, at);
|
|
5800
6432
|
if (isJsonOutput(opts)) {
|
|
5801
|
-
const result3 = await watchTransactionJson(observable, waitLevel, { unsigned: true });
|
|
6433
|
+
const result3 = await withStalenessSuggestion(chainName, clientHandle, () => watchTransactionJson(observable, waitLevel, { unsigned: true }));
|
|
5802
6434
|
const rpcUrl3 = primaryRpc(opts.rpc ?? chainConfig.rpc);
|
|
5803
6435
|
if (result3.type === "broadcasted") {
|
|
5804
6436
|
printJsonLine({ event: "broadcasted", txHash: result3.txHash });
|
|
@@ -5830,12 +6462,12 @@ async function handleTx(target, args, opts) {
|
|
|
5830
6462
|
}
|
|
5831
6463
|
return;
|
|
5832
6464
|
}
|
|
5833
|
-
const result2 = await watchTransaction(observable, waitLevel, { unsigned: true });
|
|
6465
|
+
const result2 = await withStalenessSuggestion(chainName, clientHandle, () => watchTransaction(observable, waitLevel, { unsigned: true }));
|
|
5834
6466
|
console.log();
|
|
5835
6467
|
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
5836
6468
|
console.log(` ${BOLD}Type:${RESET} unsigned (bare)`);
|
|
5837
6469
|
console.log(` ${BOLD}Call:${RESET} ${callHex}`);
|
|
5838
|
-
|
|
6470
|
+
printDecodedCall(decodedObj, decodedStr);
|
|
5839
6471
|
console.log(` ${BOLD}Tx:${RESET} ${result2.txHash}`);
|
|
5840
6472
|
if (result2.type === "broadcasted") {
|
|
5841
6473
|
console.log(` ${BOLD}Status:${RESET} ${GREEN}broadcasted${RESET}`);
|
|
@@ -5879,7 +6511,7 @@ async function handleTx(target, args, opts) {
|
|
|
5879
6511
|
return;
|
|
5880
6512
|
}
|
|
5881
6513
|
if (isJsonOutput(opts)) {
|
|
5882
|
-
const result2 = await watchTransactionJson(tx.signSubmitAndWatch(signer, txOptions), waitLevel);
|
|
6514
|
+
const result2 = await withStalenessSuggestion(chainName, clientHandle, () => watchTransactionJson(tx.signSubmitAndWatch(signer, txOptions), waitLevel));
|
|
5883
6515
|
const rpcUrl2 = primaryRpc(opts.rpc ?? chainConfig.rpc);
|
|
5884
6516
|
if (result2.type === "broadcasted") {
|
|
5885
6517
|
printJsonLine({ event: "broadcasted", txHash: result2.txHash });
|
|
@@ -5910,11 +6542,11 @@ async function handleTx(target, args, opts) {
|
|
|
5910
6542
|
}
|
|
5911
6543
|
return;
|
|
5912
6544
|
}
|
|
5913
|
-
const result = await watchTransaction(tx.signSubmitAndWatch(signer, txOptions), waitLevel);
|
|
6545
|
+
const result = await withStalenessSuggestion(chainName, clientHandle, () => watchTransaction(tx.signSubmitAndWatch(signer, txOptions), waitLevel));
|
|
5914
6546
|
console.log();
|
|
5915
6547
|
console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
|
|
5916
6548
|
console.log(` ${BOLD}Call:${RESET} ${callHex}`);
|
|
5917
|
-
|
|
6549
|
+
printDecodedCall(decodedObj, decodedStr);
|
|
5918
6550
|
if (nonce !== undefined)
|
|
5919
6551
|
console.log(` ${BOLD}Nonce:${RESET} ${nonce}`);
|
|
5920
6552
|
if (tip !== undefined)
|
|
@@ -6001,6 +6633,39 @@ function decodeCall(meta, callHex) {
|
|
|
6001
6633
|
return "(unable to decode)";
|
|
6002
6634
|
}
|
|
6003
6635
|
}
|
|
6636
|
+
function decodeCallObject(meta, callHex) {
|
|
6637
|
+
try {
|
|
6638
|
+
const callTypeId = meta.lookup.call;
|
|
6639
|
+
if (callTypeId == null)
|
|
6640
|
+
return null;
|
|
6641
|
+
const codec = meta.builder.buildDefinition(callTypeId);
|
|
6642
|
+
const decoded = codec.dec(Binary3.fromHex(callHex));
|
|
6643
|
+
return {
|
|
6644
|
+
palletName: decoded.type,
|
|
6645
|
+
callName: decoded.value.type,
|
|
6646
|
+
args: sanitizeForSerialization(decoded.value.value)
|
|
6647
|
+
};
|
|
6648
|
+
} catch {
|
|
6649
|
+
return null;
|
|
6650
|
+
}
|
|
6651
|
+
}
|
|
6652
|
+
function printDecodedCall(obj, fallback) {
|
|
6653
|
+
if (!obj) {
|
|
6654
|
+
console.log(` ${BOLD}Decode:${RESET} ${fallback}`);
|
|
6655
|
+
return;
|
|
6656
|
+
}
|
|
6657
|
+
const header = `${CYAN}${obj.palletName}${RESET}.${CYAN}${obj.callName}${RESET}`;
|
|
6658
|
+
const hasArgs = obj.args !== null && obj.args !== undefined && !(typeof obj.args === "object" && Object.keys(obj.args).length === 0);
|
|
6659
|
+
if (!hasArgs) {
|
|
6660
|
+
console.log(` ${BOLD}Decode:${RESET} ${header}`);
|
|
6661
|
+
return;
|
|
6662
|
+
}
|
|
6663
|
+
console.log(` ${BOLD}Decode:${RESET} ${header}`);
|
|
6664
|
+
const indented = formatPretty(obj.args).split(`
|
|
6665
|
+
`).map((l) => ` ${l}`).join(`
|
|
6666
|
+
`);
|
|
6667
|
+
console.log(indented);
|
|
6668
|
+
}
|
|
6004
6669
|
function decodeCallFallback(meta, callHex) {
|
|
6005
6670
|
const callTypeId = meta.lookup.call;
|
|
6006
6671
|
if (callTypeId == null)
|
|
@@ -7144,13 +7809,13 @@ function isNewerVersion(current, latest) {
|
|
|
7144
7809
|
return compareSemver(current, latest) < 0;
|
|
7145
7810
|
}
|
|
7146
7811
|
function buildNotificationBox(current, latest) {
|
|
7147
|
-
const
|
|
7148
|
-
const
|
|
7149
|
-
const
|
|
7150
|
-
const
|
|
7812
|
+
const YELLOW3 = "\x1B[33m";
|
|
7813
|
+
const GREEN3 = "\x1B[32m";
|
|
7814
|
+
const CYAN3 = "\x1B[36m";
|
|
7815
|
+
const RESET3 = "\x1B[0m";
|
|
7151
7816
|
const BOLD2 = "\x1B[1m";
|
|
7152
|
-
const line1 = `Update available! ${
|
|
7153
|
-
const line2 = `Run ${
|
|
7817
|
+
const line1 = `Update available! ${YELLOW3}${current}${RESET3} → ${GREEN3}${BOLD2}${latest}${RESET3}`;
|
|
7818
|
+
const line2 = `Run ${CYAN3}npm i -g polkadot-cli${RESET3} to update`;
|
|
7154
7819
|
const visibleLine1 = `Update available! ${current} → ${latest}`;
|
|
7155
7820
|
const visibleLine2 = `Run npm i -g polkadot-cli to update`;
|
|
7156
7821
|
const innerWidth = Math.max(visibleLine1.length, visibleLine2.length) + 4;
|
|
@@ -7237,6 +7902,34 @@ class CliError2 extends Error {
|
|
|
7237
7902
|
this.name = "CliError";
|
|
7238
7903
|
}
|
|
7239
7904
|
}
|
|
7905
|
+
var PAPI_CLEANUP_PATTERNS = [
|
|
7906
|
+
/^Not connected$/,
|
|
7907
|
+
/DisjointError/,
|
|
7908
|
+
/ChainHead.*(aborted|stopped)/i
|
|
7909
|
+
];
|
|
7910
|
+
function isPapiCleanupError(err) {
|
|
7911
|
+
if (!(err instanceof Error))
|
|
7912
|
+
return false;
|
|
7913
|
+
return PAPI_CLEANUP_PATTERNS.some((re) => re.test(err.message));
|
|
7914
|
+
}
|
|
7915
|
+
function formatRuntimeError2(err) {
|
|
7916
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
7917
|
+
if (/wasm trap|wasm `?unreachable`? instruction|Execution aborted due to trap/i.test(msg)) {
|
|
7918
|
+
const frames = Array.from(msg.matchAll(/\.wasm!([A-Za-z_]\w+)/g)).map((m) => m[1]);
|
|
7919
|
+
const fn = [...frames].reverse().find((name) => !/^(?:__rustc|core::panicking|rust_begin_unwind|panic_fmt)/.test(name));
|
|
7920
|
+
const where = fn?.includes("validate_transaction") ? "the runtime's validate_transaction step" : fn ? `runtime function ${fn}` : "the runtime";
|
|
7921
|
+
return [
|
|
7922
|
+
`The runtime rejected this transaction in ${where}.`,
|
|
7923
|
+
" Cause: a runtime invariant failed — typically the call's arguments are out of range, reference an unknown id, or violate a precondition.",
|
|
7924
|
+
" Tip: re-check the arguments and the signing account's permissions; --dry-run will surface the same error before signing."
|
|
7925
|
+
].join(`
|
|
7926
|
+
`);
|
|
7927
|
+
}
|
|
7928
|
+
if (/Invalid Transaction/i.test(msg)) {
|
|
7929
|
+
return `Transaction rejected as invalid by the runtime: ${msg}`;
|
|
7930
|
+
}
|
|
7931
|
+
return msg;
|
|
7932
|
+
}
|
|
7240
7933
|
|
|
7241
7934
|
// src/utils/parse-dot-path.ts
|
|
7242
7935
|
var CATEGORY_ALIASES = {
|
|
@@ -7359,6 +8052,7 @@ if (process.argv[2] === "__complete") {
|
|
|
7359
8052
|
console.log(" dot polkadot.const.Balances.ExistentialDeposit");
|
|
7360
8053
|
console.log(" dot polkadot.events.Balances List events in Balances");
|
|
7361
8054
|
console.log(" dot polkadot.apis.Core.version Call a runtime API");
|
|
8055
|
+
console.log(" dot metadata polkadot Dump runtime metadata as JSON");
|
|
7362
8056
|
console.log(" dot polkadot.extensions List transaction extensions");
|
|
7363
8057
|
console.log(" dot polkadot.extensions.CheckMortality Inspect one extension");
|
|
7364
8058
|
console.log(" dot query.System.Number --chain polkadot --chain flag form");
|
|
@@ -7369,6 +8063,7 @@ if (process.argv[2] === "__complete") {
|
|
|
7369
8063
|
console.log();
|
|
7370
8064
|
console.log("Commands:");
|
|
7371
8065
|
console.log(" inspect [target] Inspect chain metadata (alias: explore)");
|
|
8066
|
+
console.log(" metadata <chain> Dump runtime metadata as JSON (--raw for SCALE hex)");
|
|
7372
8067
|
console.log(" chain Manage chain configurations");
|
|
7373
8068
|
console.log(" account Manage accounts");
|
|
7374
8069
|
console.log(" hash Hash utilities");
|
|
@@ -7395,6 +8090,7 @@ if (process.argv[2] === "__complete") {
|
|
|
7395
8090
|
cli.option("--json", "Output as JSON (shorthand for --output json)");
|
|
7396
8091
|
registerChainCommands(cli);
|
|
7397
8092
|
registerInspectCommand(cli);
|
|
8093
|
+
registerMetadataCommand(cli);
|
|
7398
8094
|
registerAccountCommands(cli);
|
|
7399
8095
|
registerHashCommand(cli);
|
|
7400
8096
|
registerSignCommand(cli);
|
|
@@ -7551,12 +8247,18 @@ if (process.argv[2] === "__complete") {
|
|
|
7551
8247
|
if (err instanceof CliError2) {
|
|
7552
8248
|
console.error(`Error: ${err.message}`);
|
|
7553
8249
|
} else if (err instanceof Error) {
|
|
7554
|
-
console.error(`Error: ${err
|
|
8250
|
+
console.error(`Error: ${formatRuntimeError2(err)}`);
|
|
7555
8251
|
} else {
|
|
7556
8252
|
console.error("An unexpected error occurred:", err);
|
|
7557
8253
|
}
|
|
7558
8254
|
return showUpdateAndExit(1);
|
|
7559
8255
|
}
|
|
8256
|
+
process.on("unhandledRejection", (reason) => {
|
|
8257
|
+
if (isPapiCleanupError(reason))
|
|
8258
|
+
return;
|
|
8259
|
+
console.error(`Error: ${formatRuntimeError2(reason)}`);
|
|
8260
|
+
process.exit(1);
|
|
8261
|
+
});
|
|
7560
8262
|
async function main() {
|
|
7561
8263
|
try {
|
|
7562
8264
|
cli.parse(process.argv, { run: false });
|