polkadot-cli 0.8.0 → 0.9.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 +40 -1
- package/dist/cli.mjs +78 -29
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -94,19 +94,37 @@ dot query System.Account 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
|
94
94
|
# All map entries (default limit: 100)
|
|
95
95
|
dot query System.Account --limit 10
|
|
96
96
|
|
|
97
|
-
# Pipe to jq
|
|
97
|
+
# Pipe to jq — stdout is clean JSON, no extra text
|
|
98
98
|
dot query System.Account --limit 5 | jq '.[0].value.data.free'
|
|
99
|
+
dot query System.Number --output json | jq '.+1'
|
|
99
100
|
|
|
100
101
|
# Query a specific chain using chain prefix
|
|
101
102
|
dot query kusama.System.Account 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
|
|
102
103
|
```
|
|
103
104
|
|
|
105
|
+
#### Output formatting
|
|
106
|
+
|
|
107
|
+
Query results automatically convert on-chain types for readability:
|
|
108
|
+
|
|
109
|
+
- **BigInt** values (e.g. balances) render as decimal strings
|
|
110
|
+
- **Binary** fields (e.g. token `name`, `symbol`) render as text when valid UTF-8, or as `0x`-prefixed hex otherwise
|
|
111
|
+
- **Uint8Array** values render as `0x`-prefixed hex
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Token metadata — symbol and name display as text, not {}
|
|
115
|
+
dot query assethub-paseo.Assets.Metadata 50000413
|
|
116
|
+
# { "deposit": "6693666000", "name": "Paseo Token", "symbol": "PAS", ... }
|
|
117
|
+
```
|
|
118
|
+
|
|
104
119
|
### Look up constants
|
|
105
120
|
|
|
106
121
|
```bash
|
|
107
122
|
dot const Balances.ExistentialDeposit
|
|
108
123
|
dot const System.SS58Prefix --chain kusama
|
|
109
124
|
dot const kusama.Balances.ExistentialDeposit
|
|
125
|
+
|
|
126
|
+
# Pipe to jq — stdout is clean JSON, no extra text
|
|
127
|
+
dot const Balances.ExistentialDeposit --output json | jq
|
|
110
128
|
```
|
|
111
129
|
|
|
112
130
|
### Inspect metadata
|
|
@@ -149,6 +167,27 @@ dot tx 0x0503008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48
|
|
|
149
167
|
dot tx Utility.batchAll '[{"type":"Balances","value":{"type":"transfer_keep_alive","value":{"dest":"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty","value":1000000000000}}},{"type":"Balances","value":{"type":"transfer_keep_alive","value":{"dest":"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y","value":2000000000000}}}]' --from alice
|
|
150
168
|
```
|
|
151
169
|
|
|
170
|
+
#### Enum shorthand
|
|
171
|
+
|
|
172
|
+
Enum arguments accept a concise `Variant(value)` syntax instead of verbose JSON:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
# Instead of: '{"type":"system","value":{"type":"Authorized"}}'
|
|
176
|
+
dot tx Utility.dispatch_as 'system(Authorized)' $(dot tx System.remark 0xcafe --encode) --from alice
|
|
177
|
+
|
|
178
|
+
# Nested enums work too
|
|
179
|
+
dot tx Utility.dispatch_as 'system(Signed(5FHneW46...))' <call> --from alice
|
|
180
|
+
|
|
181
|
+
# Void variants — empty parens or just the name
|
|
182
|
+
dot tx ... 'Root()' ...
|
|
183
|
+
dot tx ... 'Root' ...
|
|
184
|
+
|
|
185
|
+
# JSON inside parens for struct values
|
|
186
|
+
dot tx ... 'AccountId32({"id":"0xd435..."})' ...
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Variant matching is case-insensitive (`system` resolves to `system`, `authorized` to `Authorized`). All existing formats (JSON objects, hex, SS58 addresses) continue to work unchanged.
|
|
190
|
+
|
|
152
191
|
#### Encode call data
|
|
153
192
|
|
|
154
193
|
Encode a call to hex without signing or submitting. Useful for preparing calls to pass to `Sudo.sudo`, multisig proposals, or governance. Works offline from cached metadata and does not require `--from`.
|
package/dist/cli.mjs
CHANGED
|
@@ -5,7 +5,7 @@ var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
|
5
5
|
// src/cli.ts
|
|
6
6
|
import cac from "cac";
|
|
7
7
|
// package.json
|
|
8
|
-
var version = "0.
|
|
8
|
+
var version = "0.9.0";
|
|
9
9
|
|
|
10
10
|
// src/config/accounts-store.ts
|
|
11
11
|
import { access as access2, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
|
|
@@ -212,6 +212,7 @@ async function resolveAccountSigner(name) {
|
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
// src/core/output.ts
|
|
215
|
+
import { Binary } from "polkadot-api";
|
|
215
216
|
var isTTY = process.stdout.isTTY ?? false;
|
|
216
217
|
var RESET = isTTY ? "\x1B[0m" : "";
|
|
217
218
|
var CYAN = isTTY ? "\x1B[36m" : "";
|
|
@@ -224,6 +225,10 @@ var BOLD = isTTY ? "\x1B[1m" : "";
|
|
|
224
225
|
function replacer(_key, value) {
|
|
225
226
|
if (typeof value === "bigint")
|
|
226
227
|
return value.toString();
|
|
228
|
+
if (value instanceof Binary) {
|
|
229
|
+
const text = value.asText();
|
|
230
|
+
return text.includes("�") ? value.asHex() : text;
|
|
231
|
+
}
|
|
227
232
|
if (value instanceof Uint8Array)
|
|
228
233
|
return `0x${Buffer.from(value).toString("hex")}`;
|
|
229
234
|
return value;
|
|
@@ -932,12 +937,6 @@ function registerConstCommand(cli) {
|
|
|
932
937
|
const runtimeToken = await unsafeApi.runtimeToken;
|
|
933
938
|
const result = unsafeApi.constants[palletInfo.name][constantItem.name](runtimeToken);
|
|
934
939
|
const format = opts.output ?? "pretty";
|
|
935
|
-
if (format === "json") {
|
|
936
|
-
console.error(`chain: ${chainName}`);
|
|
937
|
-
} else {
|
|
938
|
-
console.log(`${DIM}chain: ${chainName}${RESET}
|
|
939
|
-
`);
|
|
940
|
-
}
|
|
941
940
|
printResult(result, format);
|
|
942
941
|
} finally {
|
|
943
942
|
clientHandle.destroy();
|
|
@@ -1207,7 +1206,7 @@ function parseValue(arg) {
|
|
|
1207
1206
|
|
|
1208
1207
|
// src/commands/tx.ts
|
|
1209
1208
|
import { getViewBuilder } from "@polkadot-api/view-builder";
|
|
1210
|
-
import { Binary } from "polkadot-api";
|
|
1209
|
+
import { Binary as Binary2 } from "polkadot-api";
|
|
1211
1210
|
|
|
1212
1211
|
// src/core/explorers.ts
|
|
1213
1212
|
var pjsAppsLink = (rpc, hash) => `https://polkadot.js.org/apps/?rpc=${encodeURIComponent(rpc)}#/explorer/query/${hash}`;
|
|
@@ -1279,8 +1278,8 @@ function normalizeValue(lookup, entry, value) {
|
|
|
1279
1278
|
}
|
|
1280
1279
|
if (innerResolved.type === "primitive" && innerResolved.value === "u8" && typeof value === "string") {
|
|
1281
1280
|
if (/^0x[0-9a-fA-F]*$/.test(value))
|
|
1282
|
-
return
|
|
1283
|
-
return
|
|
1281
|
+
return Binary2.fromHex(value);
|
|
1282
|
+
return Binary2.fromText(value);
|
|
1284
1283
|
}
|
|
1285
1284
|
if (Array.isArray(value)) {
|
|
1286
1285
|
const innerEntry = resolved.value;
|
|
@@ -1335,7 +1334,20 @@ function normalizeValue(lookup, entry, value) {
|
|
|
1335
1334
|
return value;
|
|
1336
1335
|
}
|
|
1337
1336
|
}
|
|
1337
|
+
function parseEnumShorthand(arg) {
|
|
1338
|
+
if (arg.startsWith("{") || arg.startsWith("[") || arg.startsWith("0x"))
|
|
1339
|
+
return null;
|
|
1340
|
+
const firstParen = arg.indexOf("(");
|
|
1341
|
+
if (firstParen === -1 || !arg.endsWith(")"))
|
|
1342
|
+
return null;
|
|
1343
|
+
const variant = arg.slice(0, firstParen);
|
|
1344
|
+
if (!/^[a-zA-Z_]\w*$/.test(variant))
|
|
1345
|
+
return null;
|
|
1346
|
+
return { variant, inner: arg.slice(firstParen + 1, -1) };
|
|
1347
|
+
}
|
|
1338
1348
|
function parseTypedArg(meta, entry, arg) {
|
|
1349
|
+
if (entry.type === "lookupEntry")
|
|
1350
|
+
return parseTypedArg(meta, entry.value, arg);
|
|
1339
1351
|
switch (entry.type) {
|
|
1340
1352
|
case "primitive":
|
|
1341
1353
|
return parsePrimitive(entry.value, arg);
|
|
@@ -1353,7 +1365,7 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
1353
1365
|
case "enum": {
|
|
1354
1366
|
if (/^0x[0-9a-fA-F]+$/.test(arg) && meta.lookup.call != null && entry.id === meta.lookup.call) {
|
|
1355
1367
|
const callCodec = meta.builder.buildDefinition(meta.lookup.call);
|
|
1356
|
-
return callCodec.dec(
|
|
1368
|
+
return callCodec.dec(Binary2.fromHex(arg).asBytes());
|
|
1357
1369
|
}
|
|
1358
1370
|
if (arg.startsWith("{")) {
|
|
1359
1371
|
try {
|
|
@@ -1361,6 +1373,19 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
1361
1373
|
} catch {}
|
|
1362
1374
|
}
|
|
1363
1375
|
const variants = Object.keys(entry.value);
|
|
1376
|
+
const shorthand = parseEnumShorthand(arg);
|
|
1377
|
+
if (shorthand) {
|
|
1378
|
+
const matched2 = variants.find((v) => v.toLowerCase() === shorthand.variant.toLowerCase());
|
|
1379
|
+
if (matched2) {
|
|
1380
|
+
const variantDef = entry.value[matched2];
|
|
1381
|
+
const resolvedDef = variantDef.type === "lookupEntry" ? variantDef.value : variantDef;
|
|
1382
|
+
if (resolvedDef.type === "void" || shorthand.inner === "") {
|
|
1383
|
+
return { type: matched2 };
|
|
1384
|
+
}
|
|
1385
|
+
const innerValue = parseTypedArg(meta, variantDef, shorthand.inner);
|
|
1386
|
+
return normalizeValue(meta.lookup, entry, { type: matched2, value: innerValue });
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1364
1389
|
if (variants.includes("Id")) {
|
|
1365
1390
|
const idVariant = entry.value.Id;
|
|
1366
1391
|
const innerType = idVariant.type === "lookupEntry" ? idVariant.value : idVariant;
|
|
@@ -1382,8 +1407,8 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
1382
1407
|
const inner = entry.value;
|
|
1383
1408
|
if (inner.type === "primitive" && inner.value === "u8") {
|
|
1384
1409
|
if (/^0x[0-9a-fA-F]*$/.test(arg))
|
|
1385
|
-
return
|
|
1386
|
-
return
|
|
1410
|
+
return Binary2.fromHex(arg);
|
|
1411
|
+
return Binary2.fromText(arg);
|
|
1387
1412
|
}
|
|
1388
1413
|
if (arg.startsWith("[")) {
|
|
1389
1414
|
try {
|
|
@@ -1391,7 +1416,7 @@ function parseTypedArg(meta, entry, arg) {
|
|
|
1391
1416
|
} catch {}
|
|
1392
1417
|
}
|
|
1393
1418
|
if (/^0x[0-9a-fA-F]*$/.test(arg))
|
|
1394
|
-
return
|
|
1419
|
+
return Binary2.fromHex(arg);
|
|
1395
1420
|
return parseValue(arg);
|
|
1396
1421
|
}
|
|
1397
1422
|
case "struct":
|
|
@@ -1496,12 +1521,6 @@ function registerQueryCommand(cli) {
|
|
|
1496
1521
|
const storageApi = unsafeApi.query[palletInfo.name][storageItem.name];
|
|
1497
1522
|
const parsedKeys = parseStorageKeys(meta, palletInfo.name, storageItem, keys);
|
|
1498
1523
|
const format = opts.output ?? "pretty";
|
|
1499
|
-
if (format === "json") {
|
|
1500
|
-
console.error(`chain: ${chainName}`);
|
|
1501
|
-
} else {
|
|
1502
|
-
console.log(`${DIM}chain: ${chainName}${RESET}
|
|
1503
|
-
`);
|
|
1504
|
-
}
|
|
1505
1524
|
if (storageItem.type === "map" && parsedKeys.length === 0) {
|
|
1506
1525
|
const entries = await storageApi.getEntries();
|
|
1507
1526
|
const limit = Number(opts.limit);
|
|
@@ -1563,7 +1582,7 @@ function parseStorageKeys(meta, palletName, storageItem, args) {
|
|
|
1563
1582
|
|
|
1564
1583
|
// src/commands/tx.ts
|
|
1565
1584
|
import { getViewBuilder as getViewBuilder2 } from "@polkadot-api/view-builder";
|
|
1566
|
-
import { Binary as
|
|
1585
|
+
import { Binary as Binary3 } from "polkadot-api";
|
|
1567
1586
|
function registerTxCommand(cli) {
|
|
1568
1587
|
cli.command("tx [target] [...args]", "Submit an extrinsic (e.g. Balances.transferKeepAlive <dest> <amount>)").option("--from <name>", "Account to sign with (required)").option("--dry-run", "Estimate fees without submitting").option("--encode", "Encode call to hex without signing or submitting").option("--ext <json>", `Custom signed extension values as JSON, e.g. '{"ExtName":{"value":...}}'`).action(async (target, args, opts) => {
|
|
1569
1588
|
if (!target) {
|
|
@@ -1628,7 +1647,7 @@ function registerTxCommand(cli) {
|
|
|
1628
1647
|
throw new Error(`Extra arguments are not allowed when submitting a raw call hex.
|
|
1629
1648
|
` + "Usage: dot tx 0x<call_hex> --from <account>");
|
|
1630
1649
|
}
|
|
1631
|
-
const callBinary =
|
|
1650
|
+
const callBinary = Binary3.fromHex(target);
|
|
1632
1651
|
tx = await unsafeApi.txFromCallData(callBinary);
|
|
1633
1652
|
callHex = target;
|
|
1634
1653
|
} else {
|
|
@@ -1649,7 +1668,7 @@ function registerTxCommand(cli) {
|
|
|
1649
1668
|
const { codec, location } = meta.builder.buildCall(palletInfo.name, callInfo.name);
|
|
1650
1669
|
const encodedArgs = codec.enc(callData);
|
|
1651
1670
|
const fullCall = new Uint8Array([location[0], location[1], ...encodedArgs]);
|
|
1652
|
-
console.log(
|
|
1671
|
+
console.log(Binary3.fromBytes(fullCall).asHex());
|
|
1653
1672
|
return;
|
|
1654
1673
|
}
|
|
1655
1674
|
tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
|
|
@@ -1832,6 +1851,10 @@ function formatEventValue(v) {
|
|
|
1832
1851
|
return v.toString();
|
|
1833
1852
|
if (v === null || v === undefined)
|
|
1834
1853
|
return "null";
|
|
1854
|
+
if (v instanceof Binary3) {
|
|
1855
|
+
const text = v.asText();
|
|
1856
|
+
return text.includes("�") ? v.asHex() : text;
|
|
1857
|
+
}
|
|
1835
1858
|
return JSON.stringify(v, (_k, val) => typeof val === "bigint" ? val.toString() : val);
|
|
1836
1859
|
}
|
|
1837
1860
|
function parseCallArgs(meta, palletName, callName, args) {
|
|
@@ -1939,8 +1962,8 @@ function normalizeValue2(lookup, entry, value) {
|
|
|
1939
1962
|
}
|
|
1940
1963
|
if (innerResolved.type === "primitive" && innerResolved.value === "u8" && typeof value === "string") {
|
|
1941
1964
|
if (/^0x[0-9a-fA-F]*$/.test(value))
|
|
1942
|
-
return
|
|
1943
|
-
return
|
|
1965
|
+
return Binary3.fromHex(value);
|
|
1966
|
+
return Binary3.fromText(value);
|
|
1944
1967
|
}
|
|
1945
1968
|
if (Array.isArray(value)) {
|
|
1946
1969
|
const innerEntry = resolved.value;
|
|
@@ -1995,7 +2018,20 @@ function normalizeValue2(lookup, entry, value) {
|
|
|
1995
2018
|
return value;
|
|
1996
2019
|
}
|
|
1997
2020
|
}
|
|
2021
|
+
function parseEnumShorthand2(arg) {
|
|
2022
|
+
if (arg.startsWith("{") || arg.startsWith("[") || arg.startsWith("0x"))
|
|
2023
|
+
return null;
|
|
2024
|
+
const firstParen = arg.indexOf("(");
|
|
2025
|
+
if (firstParen === -1 || !arg.endsWith(")"))
|
|
2026
|
+
return null;
|
|
2027
|
+
const variant = arg.slice(0, firstParen);
|
|
2028
|
+
if (!/^[a-zA-Z_]\w*$/.test(variant))
|
|
2029
|
+
return null;
|
|
2030
|
+
return { variant, inner: arg.slice(firstParen + 1, -1) };
|
|
2031
|
+
}
|
|
1998
2032
|
function parseTypedArg2(meta, entry, arg) {
|
|
2033
|
+
if (entry.type === "lookupEntry")
|
|
2034
|
+
return parseTypedArg2(meta, entry.value, arg);
|
|
1999
2035
|
switch (entry.type) {
|
|
2000
2036
|
case "primitive":
|
|
2001
2037
|
return parsePrimitive2(entry.value, arg);
|
|
@@ -2013,7 +2049,7 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
2013
2049
|
case "enum": {
|
|
2014
2050
|
if (/^0x[0-9a-fA-F]+$/.test(arg) && meta.lookup.call != null && entry.id === meta.lookup.call) {
|
|
2015
2051
|
const callCodec = meta.builder.buildDefinition(meta.lookup.call);
|
|
2016
|
-
return callCodec.dec(
|
|
2052
|
+
return callCodec.dec(Binary3.fromHex(arg).asBytes());
|
|
2017
2053
|
}
|
|
2018
2054
|
if (arg.startsWith("{")) {
|
|
2019
2055
|
try {
|
|
@@ -2021,6 +2057,19 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
2021
2057
|
} catch {}
|
|
2022
2058
|
}
|
|
2023
2059
|
const variants = Object.keys(entry.value);
|
|
2060
|
+
const shorthand = parseEnumShorthand2(arg);
|
|
2061
|
+
if (shorthand) {
|
|
2062
|
+
const matched2 = variants.find((v) => v.toLowerCase() === shorthand.variant.toLowerCase());
|
|
2063
|
+
if (matched2) {
|
|
2064
|
+
const variantDef = entry.value[matched2];
|
|
2065
|
+
const resolvedDef = variantDef.type === "lookupEntry" ? variantDef.value : variantDef;
|
|
2066
|
+
if (resolvedDef.type === "void" || shorthand.inner === "") {
|
|
2067
|
+
return { type: matched2 };
|
|
2068
|
+
}
|
|
2069
|
+
const innerValue = parseTypedArg2(meta, variantDef, shorthand.inner);
|
|
2070
|
+
return normalizeValue2(meta.lookup, entry, { type: matched2, value: innerValue });
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2024
2073
|
if (variants.includes("Id")) {
|
|
2025
2074
|
const idVariant = entry.value.Id;
|
|
2026
2075
|
const innerType = idVariant.type === "lookupEntry" ? idVariant.value : idVariant;
|
|
@@ -2042,8 +2091,8 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
2042
2091
|
const inner = entry.value;
|
|
2043
2092
|
if (inner.type === "primitive" && inner.value === "u8") {
|
|
2044
2093
|
if (/^0x[0-9a-fA-F]*$/.test(arg))
|
|
2045
|
-
return
|
|
2046
|
-
return
|
|
2094
|
+
return Binary3.fromHex(arg);
|
|
2095
|
+
return Binary3.fromText(arg);
|
|
2047
2096
|
}
|
|
2048
2097
|
if (arg.startsWith("[")) {
|
|
2049
2098
|
try {
|
|
@@ -2051,7 +2100,7 @@ function parseTypedArg2(meta, entry, arg) {
|
|
|
2051
2100
|
} catch {}
|
|
2052
2101
|
}
|
|
2053
2102
|
if (/^0x[0-9a-fA-F]*$/.test(arg))
|
|
2054
|
-
return
|
|
2103
|
+
return Binary3.fromHex(arg);
|
|
2055
2104
|
return parseValue(arg);
|
|
2056
2105
|
}
|
|
2057
2106
|
case "struct":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "polkadot-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "CLI tool for querying Polkadot-ecosystem on-chain state",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"typecheck": "tsc --noEmit",
|
|
18
18
|
"lint": "biome check .",
|
|
19
19
|
"lint:fix": "biome check --write .",
|
|
20
|
-
"test": "bun test",
|
|
21
|
-
"test:coverage": "bun test --coverage --coverage-reporter=lcov --coverage-dir=coverage",
|
|
20
|
+
"test": "bun test --concurrent",
|
|
21
|
+
"test:coverage": "bun test --concurrent --coverage --coverage-reporter=lcov --coverage-dir=coverage",
|
|
22
22
|
"prepare": "husky",
|
|
23
23
|
"changeset": "changeset",
|
|
24
24
|
"version": "changeset version",
|