polkadot-cli 1.2.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +39 -3
  2. package/dist/cli.mjs +1153 -719
  3. package/package.json +1 -1
package/dist/cli.mjs CHANGED
@@ -1,141 +1,145 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
+ var __defProp = Object.defineProperty;
4
+ var __returnValue = (v) => v;
5
+ function __exportSetter(name, newValue) {
6
+ this[name] = __returnValue.bind(null, newValue);
7
+ }
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, {
11
+ get: all[name],
12
+ enumerable: true,
13
+ configurable: true,
14
+ set: __exportSetter.bind(all, name)
15
+ });
16
+ };
17
+ var __esm = (fn, res) => () => (fn && (res = fn(fn = 0)), res);
3
18
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
4
19
 
5
- // src/cli.ts
6
- import cac from "cac";
7
- // package.json
8
- var version = "1.2.0";
9
-
10
- // src/config/accounts-store.ts
11
- import { access as access2, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
12
- import { join as join2 } from "node:path";
13
-
14
- // src/config/store.ts
15
- import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
16
- import { homedir } from "node:os";
17
- import { join } from "node:path";
18
-
19
20
  // src/config/types.ts
20
21
  function primaryRpc(rpc) {
21
22
  return Array.isArray(rpc) ? rpc[0] : rpc;
22
23
  }
23
- var DEFAULT_CONFIG = {
24
- defaultChain: "polkadot",
25
- chains: {
26
- polkadot: {
27
- rpc: [
28
- "wss://polkadot.ibp.network",
29
- "wss://polkadot.dotters.network",
30
- "wss://polkadot-rpc.n.dwellir.com",
31
- "wss://polkadot-rpc.publicnode.com",
32
- "wss://rpc-polkadot.luckyfriday.io",
33
- "wss://polkadot.api.onfinality.io/public-ws",
34
- "wss://rpc-polkadot.helixstreet.io",
35
- "wss://polkadot-rpc-tn.dwellir.com",
36
- "wss://polkadot.public.curie.radiumblock.co/ws",
37
- "wss://rpc-polkadot.stakeworld.io",
38
- "wss://polkadot.rpc.subquery.network/public/ws",
39
- "wss://rpc.polkadot.io"
40
- ]
41
- },
42
- "polkadot-asset-hub": {
43
- rpc: [
44
- "wss://polkadot-asset-hub-rpc.polkadot.io",
45
- "wss://asset-hub-polkadot.ibp.network",
46
- "wss://asset-hub-polkadot.dotters.network",
47
- "wss://asset-hub-polkadot-rpc.n.dwellir.com",
48
- "wss://rpc-asset-hub-polkadot.luckyfriday.io",
49
- "wss://statemint.api.onfinality.io/public-ws",
50
- "wss://statemint-rpc-tn.dwellir.com",
51
- "wss://statemint.public.curie.radiumblock.co/ws",
52
- "wss://asset-hub-polkadot.rpc.permanence.io"
53
- ]
54
- },
55
- "polkadot-bridge-hub": {
56
- rpc: [
57
- "wss://polkadot-bridge-hub-rpc.polkadot.io",
58
- "wss://bridge-hub-polkadot.ibp.network",
59
- "wss://bridge-hub-polkadot.dotters.network",
60
- "wss://bridge-hub-polkadot-rpc.n.dwellir.com",
61
- "wss://rpc-bridge-hub-polkadot.luckyfriday.io",
62
- "wss://bridgehub-polkadot.api.onfinality.io/public-ws",
63
- "wss://polkadot-bridge-hub-rpc-tn.dwellir.com",
64
- "wss://bridgehub-polkadot.public.curie.radiumblock.co/ws"
65
- ]
66
- },
67
- "polkadot-collectives": {
68
- rpc: [
69
- "wss://polkadot-collectives-rpc.polkadot.io",
70
- "wss://collectives-polkadot.ibp.network",
71
- "wss://collectives-polkadot.dotters.network",
72
- "wss://collectives-polkadot-rpc.n.dwellir.com",
73
- "wss://rpc-collectives-polkadot.luckyfriday.io",
74
- "wss://collectives.api.onfinality.io/public-ws",
75
- "wss://polkadot-collectives-rpc-tn.dwellir.com",
76
- "wss://collectives.public.curie.radiumblock.co/ws"
77
- ]
78
- },
79
- "polkadot-coretime": {
80
- rpc: [
81
- "wss://polkadot-coretime-rpc.polkadot.io",
82
- "wss://coretime-polkadot.ibp.network",
83
- "wss://coretime-polkadot.dotters.network",
84
- "wss://coretime-polkadot-rpc.n.dwellir.com",
85
- "wss://rpc-coretime-polkadot.luckyfriday.io",
86
- "wss://coretime-polkadot.api.onfinality.io/public-ws"
87
- ]
88
- },
89
- "polkadot-people": {
90
- rpc: [
91
- "wss://polkadot-people-rpc.polkadot.io",
92
- "wss://people-polkadot.ibp.network",
93
- "wss://people-polkadot.dotters.network",
94
- "wss://people-polkadot-rpc.n.dwellir.com",
95
- "wss://rpc-people-polkadot.luckyfriday.io",
96
- "wss://people-polkadot.api.onfinality.io/public-ws"
97
- ]
98
- },
99
- paseo: {
100
- rpc: [
101
- "wss://paseo.ibp.network",
102
- "wss://paseo.dotters.network",
103
- "wss://paseo-rpc.n.dwellir.com",
104
- "wss://paseo.rpc.amforc.com"
105
- ]
106
- },
107
- "paseo-asset-hub": {
108
- rpc: [
109
- "wss://asset-hub-paseo.ibp.network",
110
- "wss://asset-hub-paseo.dotters.network",
111
- "wss://asset-hub-paseo-rpc.n.dwellir.com",
112
- "wss://sys.turboflakes.io/asset-hub-paseo"
113
- ]
114
- },
115
- "paseo-bridge-hub": {
116
- rpc: ["wss://bridge-hub-paseo.ibp.network", "wss://bridge-hub-paseo.dotters.network"]
117
- },
118
- "paseo-collectives": {
119
- rpc: ["wss://collectives-paseo.ibp.network", "wss://collectives-paseo.dotters.network"]
120
- },
121
- "paseo-coretime": {
122
- rpc: ["wss://coretime-paseo.ibp.network", "wss://coretime-paseo.dotters.network"]
123
- },
124
- "paseo-people": {
125
- rpc: [
126
- "wss://people-paseo.ibp.network",
127
- "wss://people-paseo.dotters.network",
128
- "wss://people-paseo.rpc.amforc.com"
129
- ]
24
+ var DEFAULT_CONFIG, BUILTIN_CHAIN_NAMES;
25
+ var init_types = __esm(() => {
26
+ DEFAULT_CONFIG = {
27
+ defaultChain: "polkadot",
28
+ chains: {
29
+ polkadot: {
30
+ rpc: [
31
+ "wss://polkadot.ibp.network",
32
+ "wss://polkadot.dotters.network",
33
+ "wss://polkadot-rpc.n.dwellir.com",
34
+ "wss://polkadot-rpc.publicnode.com",
35
+ "wss://rpc-polkadot.luckyfriday.io",
36
+ "wss://polkadot.api.onfinality.io/public-ws",
37
+ "wss://rpc-polkadot.helixstreet.io",
38
+ "wss://polkadot-rpc-tn.dwellir.com",
39
+ "wss://polkadot.public.curie.radiumblock.co/ws",
40
+ "wss://rpc-polkadot.stakeworld.io",
41
+ "wss://polkadot.rpc.subquery.network/public/ws",
42
+ "wss://rpc.polkadot.io"
43
+ ]
44
+ },
45
+ "polkadot-asset-hub": {
46
+ rpc: [
47
+ "wss://polkadot-asset-hub-rpc.polkadot.io",
48
+ "wss://asset-hub-polkadot.ibp.network",
49
+ "wss://asset-hub-polkadot.dotters.network",
50
+ "wss://asset-hub-polkadot-rpc.n.dwellir.com",
51
+ "wss://rpc-asset-hub-polkadot.luckyfriday.io",
52
+ "wss://statemint.api.onfinality.io/public-ws",
53
+ "wss://statemint-rpc-tn.dwellir.com",
54
+ "wss://statemint.public.curie.radiumblock.co/ws",
55
+ "wss://asset-hub-polkadot.rpc.permanence.io"
56
+ ]
57
+ },
58
+ "polkadot-bridge-hub": {
59
+ rpc: [
60
+ "wss://polkadot-bridge-hub-rpc.polkadot.io",
61
+ "wss://bridge-hub-polkadot.ibp.network",
62
+ "wss://bridge-hub-polkadot.dotters.network",
63
+ "wss://bridge-hub-polkadot-rpc.n.dwellir.com",
64
+ "wss://rpc-bridge-hub-polkadot.luckyfriday.io",
65
+ "wss://bridgehub-polkadot.api.onfinality.io/public-ws",
66
+ "wss://polkadot-bridge-hub-rpc-tn.dwellir.com",
67
+ "wss://bridgehub-polkadot.public.curie.radiumblock.co/ws"
68
+ ]
69
+ },
70
+ "polkadot-collectives": {
71
+ rpc: [
72
+ "wss://polkadot-collectives-rpc.polkadot.io",
73
+ "wss://collectives-polkadot.ibp.network",
74
+ "wss://collectives-polkadot.dotters.network",
75
+ "wss://collectives-polkadot-rpc.n.dwellir.com",
76
+ "wss://rpc-collectives-polkadot.luckyfriday.io",
77
+ "wss://collectives.api.onfinality.io/public-ws",
78
+ "wss://polkadot-collectives-rpc-tn.dwellir.com",
79
+ "wss://collectives.public.curie.radiumblock.co/ws"
80
+ ]
81
+ },
82
+ "polkadot-coretime": {
83
+ rpc: [
84
+ "wss://polkadot-coretime-rpc.polkadot.io",
85
+ "wss://coretime-polkadot.ibp.network",
86
+ "wss://coretime-polkadot.dotters.network",
87
+ "wss://coretime-polkadot-rpc.n.dwellir.com",
88
+ "wss://rpc-coretime-polkadot.luckyfriday.io",
89
+ "wss://coretime-polkadot.api.onfinality.io/public-ws"
90
+ ]
91
+ },
92
+ "polkadot-people": {
93
+ rpc: [
94
+ "wss://polkadot-people-rpc.polkadot.io",
95
+ "wss://people-polkadot.ibp.network",
96
+ "wss://people-polkadot.dotters.network",
97
+ "wss://people-polkadot-rpc.n.dwellir.com",
98
+ "wss://rpc-people-polkadot.luckyfriday.io",
99
+ "wss://people-polkadot.api.onfinality.io/public-ws"
100
+ ]
101
+ },
102
+ paseo: {
103
+ rpc: [
104
+ "wss://paseo.ibp.network",
105
+ "wss://paseo.dotters.network",
106
+ "wss://paseo-rpc.n.dwellir.com",
107
+ "wss://paseo.rpc.amforc.com"
108
+ ]
109
+ },
110
+ "paseo-asset-hub": {
111
+ rpc: [
112
+ "wss://asset-hub-paseo.ibp.network",
113
+ "wss://asset-hub-paseo.dotters.network",
114
+ "wss://asset-hub-paseo-rpc.n.dwellir.com",
115
+ "wss://sys.turboflakes.io/asset-hub-paseo"
116
+ ]
117
+ },
118
+ "paseo-bridge-hub": {
119
+ rpc: ["wss://bridge-hub-paseo.ibp.network", "wss://bridge-hub-paseo.dotters.network"]
120
+ },
121
+ "paseo-collectives": {
122
+ rpc: ["wss://collectives-paseo.ibp.network", "wss://collectives-paseo.dotters.network"]
123
+ },
124
+ "paseo-coretime": {
125
+ rpc: ["wss://coretime-paseo.ibp.network", "wss://coretime-paseo.dotters.network"]
126
+ },
127
+ "paseo-people": {
128
+ rpc: [
129
+ "wss://people-paseo.ibp.network",
130
+ "wss://people-paseo.dotters.network",
131
+ "wss://people-paseo.rpc.amforc.com"
132
+ ]
133
+ }
130
134
  }
131
- }
132
- };
133
- var BUILTIN_CHAIN_NAMES = new Set(Object.keys(DEFAULT_CONFIG.chains));
135
+ };
136
+ BUILTIN_CHAIN_NAMES = new Set(Object.keys(DEFAULT_CONFIG.chains));
137
+ });
134
138
 
135
139
  // src/config/store.ts
136
- var DOT_DIR = join(homedir(), ".polkadot");
137
- var CONFIG_PATH = join(DOT_DIR, "config.json");
138
- var CHAINS_DIR = join(DOT_DIR, "chains");
140
+ import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
141
+ import { homedir } from "node:os";
142
+ import { join } from "node:path";
139
143
  function getConfigDir() {
140
144
  return DOT_DIR;
141
145
  }
@@ -203,9 +207,17 @@ function resolveChain(config, chainFlag) {
203
207
  }
204
208
  return { name, chain: config.chains[name] };
205
209
  }
210
+ var DOT_DIR, CONFIG_PATH, CHAINS_DIR;
211
+ var init_store = __esm(() => {
212
+ init_types();
213
+ DOT_DIR = join(homedir(), ".polkadot");
214
+ CONFIG_PATH = join(DOT_DIR, "config.json");
215
+ CHAINS_DIR = join(DOT_DIR, "chains");
216
+ });
206
217
 
207
218
  // src/config/accounts-store.ts
208
- var ACCOUNTS_PATH = join2(getConfigDir(), "accounts.json");
219
+ import { access as access2, mkdir as mkdir2, readFile as readFile2, writeFile as writeFile2 } from "node:fs/promises";
220
+ import { join as join2 } from "node:path";
209
221
  async function ensureDir2(dir) {
210
222
  await mkdir2(dir, { recursive: true });
211
223
  }
@@ -233,6 +245,11 @@ async function saveAccounts(file) {
233
245
  function findAccount(file, name) {
234
246
  return file.accounts.find((a) => a.name.toLowerCase() === name.toLowerCase());
235
247
  }
248
+ var ACCOUNTS_PATH;
249
+ var init_accounts_store = __esm(() => {
250
+ init_store();
251
+ ACCOUNTS_PATH = join2(getConfigDir(), "accounts.json");
252
+ });
236
253
 
237
254
  // src/config/accounts-types.ts
238
255
  function isEnvSecret(secret) {
@@ -254,7 +271,6 @@ import {
254
271
  validateMnemonic
255
272
  } from "@polkadot-labs/hdkd-helpers";
256
273
  import { getPolkadotSigner } from "polkadot-api/signer";
257
- var DEV_NAMES = ["alice", "bob", "charlie", "dave", "eve", "ferdie"];
258
274
  function isDevAccount(name) {
259
275
  return DEV_NAMES.includes(name.toLowerCase());
260
276
  }
@@ -365,92 +381,651 @@ async function resolveAccountSigner(name) {
365
381
  const keypair = isHexSeed ? deriveFromHexSeed(secret, account.derivationPath) : deriveFromMnemonic(secret, account.derivationPath);
366
382
  return getPolkadotSigner(keypair.publicKey, "Sr25519", keypair.sign);
367
383
  }
384
+ var DEV_NAMES;
385
+ var init_accounts = __esm(() => {
386
+ init_accounts_store();
387
+ DEV_NAMES = ["alice", "bob", "charlie", "dave", "eve", "ferdie"];
388
+ });
368
389
 
369
- // src/core/output.ts
370
- import { Binary } from "polkadot-api";
371
- var isTTY = process.stdout.isTTY ?? false;
372
- var RESET = isTTY ? "\x1B[0m" : "";
373
- var CYAN = isTTY ? "\x1B[36m" : "";
374
- var GREEN = isTTY ? "\x1B[32m" : "";
375
- var RED = isTTY ? "\x1B[31m" : "";
376
- var YELLOW = isTTY ? "\x1B[33m" : "";
377
- var MAGENTA = isTTY ? "\x1B[35m" : "";
378
- var DIM = isTTY ? "\x1B[2m" : "";
379
- var BOLD = isTTY ? "\x1B[1m" : "";
380
- function replacer(_key, value) {
381
- if (typeof value === "bigint")
382
- return value.toString();
383
- if (value instanceof Binary) {
384
- const text = value.asText();
385
- return text.includes("�") ? value.asHex() : text;
386
- }
387
- if (value instanceof Uint8Array)
388
- return `0x${Buffer.from(value).toString("hex")}`;
389
- return value;
390
+ // src/utils/errors.ts
391
+ var CliError, ConnectionError, MetadataError;
392
+ var init_errors = __esm(() => {
393
+ CliError = class CliError extends Error {
394
+ constructor(message) {
395
+ super(message);
396
+ this.name = "CliError";
397
+ }
398
+ };
399
+ ConnectionError = class ConnectionError extends CliError {
400
+ constructor(message) {
401
+ super(message);
402
+ this.name = "ConnectionError";
403
+ }
404
+ };
405
+ MetadataError = class MetadataError extends CliError {
406
+ constructor(message) {
407
+ super(message);
408
+ this.name = "MetadataError";
409
+ }
410
+ };
411
+ });
412
+
413
+ // src/core/metadata.ts
414
+ import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders";
415
+ import { decAnyMetadata, unifyMetadata } from "@polkadot-api/substrate-bindings";
416
+ function parseMetadata(raw) {
417
+ const decoded = decAnyMetadata(raw);
418
+ const unified = unifyMetadata(decoded);
419
+ const lookup = getLookupFn(unified);
420
+ const builder = getDynamicBuilder(lookup);
421
+ return { unified, lookup, builder };
390
422
  }
391
- function formatJson(data) {
392
- return JSON.stringify(data, replacer, 2);
423
+ async function fetchMetadataFromChain(clientHandle, chainName) {
424
+ const { client } = clientHandle;
425
+ try {
426
+ const hex = await Promise.race([
427
+ client._request("state_getMetadata", []),
428
+ 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))
429
+ ]);
430
+ const bytes = hexToBytes(hex);
431
+ await saveMetadata(chainName, bytes);
432
+ return bytes;
433
+ } catch (err) {
434
+ if (err instanceof ConnectionError)
435
+ throw err;
436
+ throw new ConnectionError(`Failed to fetch metadata for "${chainName}": ${err instanceof Error ? err.message : err}. ` + "Check that the RPC endpoint is correct and reachable.");
437
+ }
393
438
  }
394
- function formatPretty(data) {
395
- const json = JSON.stringify(data, replacer, 2);
396
- if (!json)
397
- return "undefined";
398
- return colorizeJson(json);
439
+ async function getOrFetchMetadata(chainName, clientHandle) {
440
+ let raw = await loadMetadata(chainName);
441
+ if (!raw) {
442
+ if (!clientHandle) {
443
+ throw new MetadataError(`No cached metadata for chain "${chainName}". Run a command that connects to the chain first, ` + `e.g.: dot chain add ${chainName} --rpc <url>`);
444
+ }
445
+ raw = await fetchMetadataFromChain(clientHandle, chainName);
446
+ }
447
+ return parseMetadata(raw);
399
448
  }
400
- function colorizeJson(json) {
401
- return json.replace(/("(?:\\.|[^"\\])*")\s*:/g, `${CYAN}$1${RESET}:`).replace(/:\s*("(?:\\.|[^"\\])*")/g, (match, str) => match.replace(str, `${GREEN}${str}${RESET}`)).replace(/:\s*(\d+(?:\.\d+)?)/g, (match, num) => match.replace(num, `${YELLOW}${num}${RESET}`)).replace(/:\s*(true|false)/g, (match, bool) => match.replace(bool, `${MAGENTA}${bool}${RESET}`)).replace(/:\s*(null)/g, (match, n) => match.replace(n, `${DIM}${n}${RESET}`));
449
+ function listPallets(meta) {
450
+ return meta.unified.pallets.map((p) => ({
451
+ name: p.name,
452
+ index: p.index,
453
+ docs: p.docs ?? [],
454
+ storage: (p.storage?.items ?? []).map((s) => ({
455
+ name: s.name,
456
+ docs: s.docs ?? [],
457
+ type: s.type.tag,
458
+ keyTypeId: s.type.tag === "map" ? s.type.value.key : null,
459
+ valueTypeId: s.type.tag === "plain" ? s.type.value : s.type.value.value
460
+ })),
461
+ constants: (p.constants ?? []).map((c) => ({
462
+ name: c.name,
463
+ docs: c.docs ?? [],
464
+ typeId: c.type
465
+ })),
466
+ calls: extractEnumVariants(meta, p.calls),
467
+ events: extractEnumVariants(meta, p.events),
468
+ errors: extractEnumVariants(meta, p.errors).map(({ name, docs }) => ({ name, docs }))
469
+ }));
402
470
  }
403
- function printResult(data, format = "pretty") {
404
- if (format === "json") {
405
- console.log(formatJson(data));
406
- } else {
407
- console.log(formatPretty(data));
471
+ function extractEnumVariants(meta, ref) {
472
+ if (!ref)
473
+ return [];
474
+ try {
475
+ const entry = meta.lookup(ref.type);
476
+ if (entry.type !== "enum")
477
+ return [];
478
+ return Object.entries(entry.value).map(([name, variant]) => ({
479
+ name,
480
+ docs: entry.innerDocs?.[name] ?? [],
481
+ typeId: resolveVariantTypeId(variant)
482
+ }));
483
+ } catch {
484
+ return [];
408
485
  }
409
486
  }
410
- function printHeading(text) {
411
- console.log(`
412
- ${BOLD}${text}${RESET}
413
- `);
487
+ function resolveVariantTypeId(variant) {
488
+ if (variant.type === "lookupEntry")
489
+ return variant.value?.id ?? null;
490
+ if (variant.type === "struct")
491
+ return null;
492
+ if (variant.type === "void" || variant.type === "empty")
493
+ return null;
494
+ return null;
414
495
  }
415
- function printItem(name, description) {
416
- if (description) {
417
- console.log(` ${CYAN}${name}${RESET} ${DIM}${description}${RESET}`);
418
- } else {
419
- console.log(` ${CYAN}${name}${RESET}`);
420
- }
496
+ function findPallet(meta, palletName) {
497
+ const pallets = listPallets(meta);
498
+ return pallets.find((p) => p.name.toLowerCase() === palletName.toLowerCase());
421
499
  }
422
- function printDocs(docs) {
423
- const text = docs.join(`
424
- `).trim();
425
- if (text) {
426
- console.log(` ${DIM}${text}${RESET}`);
500
+ function getSignedExtensions(meta) {
501
+ const byVersion = meta.unified.extrinsic.signedExtensions;
502
+ const versionKeys = Object.keys(byVersion);
503
+ if (versionKeys.length === 0)
504
+ return [];
505
+ return byVersion[Number(versionKeys[0])] ?? [];
506
+ }
507
+ function getPalletNames(meta) {
508
+ return meta.unified.pallets.map((p) => p.name);
509
+ }
510
+ function describeType(lookup, typeId) {
511
+ try {
512
+ const entry = lookup(typeId);
513
+ return formatLookupEntry(entry);
514
+ } catch {
515
+ return `type(${typeId})`;
427
516
  }
428
517
  }
429
- var CHECK_MARK = "✓";
430
- var SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
431
-
432
- class Spinner {
433
- timer = null;
434
- frame = 0;
435
- start(msg) {
436
- this.stop();
437
- if (!isTTY) {
438
- console.error(msg);
439
- return;
518
+ function formatLookupEntry(entry) {
519
+ switch (entry.type) {
520
+ case "primitive":
521
+ return entry.value;
522
+ case "compact":
523
+ return `Compact<${formatLookupEntry(entry.isBig ? { type: "primitive", value: "u128" } : { type: "primitive", value: "u64" })}>`;
524
+ case "AccountId32":
525
+ return "AccountId32";
526
+ case "bitSequence":
527
+ return "BitSequence";
528
+ case "sequence":
529
+ return `Vec<${formatLookupEntry(entry.value)}>`;
530
+ case "array":
531
+ return `[${formatLookupEntry(entry.value)}; ${entry.len}]`;
532
+ case "tuple":
533
+ return `(${entry.value.map(formatLookupEntry).join(", ")})`;
534
+ case "struct":
535
+ return `{ ${Object.entries(entry.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ")} }`;
536
+ case "option":
537
+ return `Option<${formatLookupEntry(entry.value)}>`;
538
+ case "result":
539
+ return `Result<${formatLookupEntry(entry.value.ok)}, ${formatLookupEntry(entry.value.ko)}>`;
540
+ case "enum": {
541
+ const variants = Object.keys(entry.value);
542
+ if (variants.length <= 4)
543
+ return variants.join(" | ");
544
+ return `enum(${variants.length} variants)`;
440
545
  }
441
- process.stdout.write(`${SPINNER_FRAMES[0]} ${msg}`);
442
- this.timer = setInterval(() => {
443
- this.frame = (this.frame + 1) % SPINNER_FRAMES.length;
444
- process.stdout.write(`\r\x1B[K${SPINNER_FRAMES[this.frame]} ${msg}`);
445
- }, 80);
546
+ default:
547
+ return "unknown";
446
548
  }
447
- stop() {
448
- if (this.timer !== null) {
449
- clearInterval(this.timer);
450
- this.timer = null;
451
- this.frame = 0;
452
- if (isTTY)
453
- process.stdout.write("\r\x1B[K");
549
+ }
550
+ function describeCallArgs(meta, palletName, callName) {
551
+ try {
552
+ const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
553
+ if (!palletMeta?.calls)
554
+ return "";
555
+ const callsEntry = meta.lookup(palletMeta.calls.type);
556
+ if (callsEntry.type !== "enum")
557
+ return "";
558
+ const variant = callsEntry.value[callName];
559
+ if (!variant)
560
+ return "";
561
+ if (variant.type === "void")
562
+ return "()";
563
+ if (variant.type === "struct") {
564
+ const fields = Object.entries(variant.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
565
+ return `(${fields})`;
566
+ }
567
+ if (variant.type === "lookupEntry") {
568
+ const inner = variant.value;
569
+ if (inner.type === "void")
570
+ return "()";
571
+ if (inner.type === "struct") {
572
+ const fields = Object.entries(inner.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
573
+ return `(${fields})`;
574
+ }
575
+ return `(${formatLookupEntry(inner)})`;
576
+ }
577
+ if (variant.type === "tuple") {
578
+ const types = variant.value.map(formatLookupEntry).join(", ");
579
+ return `(${types})`;
580
+ }
581
+ return "";
582
+ } catch {
583
+ return "";
584
+ }
585
+ }
586
+ function describeEventFields(meta, palletName, eventName) {
587
+ try {
588
+ const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
589
+ if (!palletMeta?.events)
590
+ return "";
591
+ const eventsEntry = meta.lookup(palletMeta.events.type);
592
+ if (eventsEntry.type !== "enum")
593
+ return "";
594
+ const variant = eventsEntry.value[eventName];
595
+ if (!variant)
596
+ return "";
597
+ if (variant.type === "void")
598
+ return "()";
599
+ if (variant.type === "struct") {
600
+ const fields = Object.entries(variant.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
601
+ return `(${fields})`;
602
+ }
603
+ if (variant.type === "lookupEntry") {
604
+ const inner = variant.value;
605
+ if (inner.type === "void")
606
+ return "()";
607
+ if (inner.type === "struct") {
608
+ const fields = Object.entries(inner.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
609
+ return `(${fields})`;
610
+ }
611
+ return `(${formatLookupEntry(inner)})`;
612
+ }
613
+ if (variant.type === "tuple") {
614
+ const types = variant.value.map(formatLookupEntry).join(", ");
615
+ return `(${types})`;
616
+ }
617
+ return "";
618
+ } catch {
619
+ return "";
620
+ }
621
+ }
622
+ function hexToBytes(hex) {
623
+ const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
624
+ const bytes = new Uint8Array(clean.length / 2);
625
+ for (let i = 0;i < clean.length; i += 2) {
626
+ bytes[i / 2] = parseInt(clean.substring(i, i + 2), 16);
627
+ }
628
+ return bytes;
629
+ }
630
+ var METADATA_TIMEOUT_MS = 15000;
631
+ var init_metadata = __esm(() => {
632
+ init_store();
633
+ init_errors();
634
+ });
635
+
636
+ // src/core/hash.ts
637
+ import { blake2b } from "@noble/hashes/blake2.js";
638
+ import { sha256 } from "@noble/hashes/sha2.js";
639
+ import { keccak_256 } from "@noble/hashes/sha3.js";
640
+ import { bytesToHex, hexToBytes as hexToBytes2 } from "@noble/hashes/utils.js";
641
+ function computeHash(algorithm, data) {
642
+ const algo = ALGORITHMS[algorithm];
643
+ if (!algo) {
644
+ throw new Error(`Unknown algorithm: ${algorithm}`);
645
+ }
646
+ return algo.compute(data);
647
+ }
648
+ function parseInputData(input) {
649
+ if (input.startsWith("0x")) {
650
+ const hex = input.slice(2);
651
+ if (hex.length % 2 !== 0) {
652
+ throw new Error(`Invalid hex input: odd number of characters`);
653
+ }
654
+ return hexToBytes2(hex);
655
+ }
656
+ return new TextEncoder().encode(input);
657
+ }
658
+ function toHex(bytes) {
659
+ return `0x${bytesToHex(bytes)}`;
660
+ }
661
+ function isValidAlgorithm(name) {
662
+ return name in ALGORITHMS;
663
+ }
664
+ function getAlgorithmNames() {
665
+ return Object.keys(ALGORITHMS);
666
+ }
667
+ var ALGORITHMS;
668
+ var init_hash = __esm(() => {
669
+ ALGORITHMS = {
670
+ blake2b256: {
671
+ compute: (data) => blake2b(data, { dkLen: 32 }),
672
+ outputLen: 32,
673
+ description: "BLAKE2b with 256-bit output"
674
+ },
675
+ blake2b128: {
676
+ compute: (data) => blake2b(data, { dkLen: 16 }),
677
+ outputLen: 16,
678
+ description: "BLAKE2b with 128-bit output"
679
+ },
680
+ keccak256: {
681
+ compute: (data) => keccak_256(data),
682
+ outputLen: 32,
683
+ description: "Keccak-256 (Ethereum-compatible)"
684
+ },
685
+ sha256: {
686
+ compute: (data) => sha256(data),
687
+ outputLen: 32,
688
+ description: "SHA-256"
689
+ }
690
+ };
691
+ });
692
+
693
+ // src/completions/complete.ts
694
+ var exports_complete = {};
695
+ __export(exports_complete, {
696
+ generateCompletions: () => generateCompletions
697
+ });
698
+ function matchCategory2(s) {
699
+ return CATEGORY_ALIASES2[s.toLowerCase()];
700
+ }
701
+ async function loadPallets(_config, chainName) {
702
+ const raw = await loadMetadata(chainName);
703
+ if (!raw)
704
+ return null;
705
+ const meta = parseMetadata(raw);
706
+ return listPallets(meta);
707
+ }
708
+ function filterPallets(pallets, category) {
709
+ switch (category) {
710
+ case "query":
711
+ return pallets.filter((p) => p.storage.length > 0);
712
+ case "tx":
713
+ return pallets.filter((p) => p.calls.length > 0);
714
+ case "const":
715
+ return pallets.filter((p) => p.constants.length > 0);
716
+ case "events":
717
+ return pallets.filter((p) => p.events.length > 0);
718
+ case "errors":
719
+ return pallets.filter((p) => p.errors.length > 0);
720
+ default:
721
+ return pallets;
722
+ }
723
+ }
724
+ function getItemNames(pallet, category) {
725
+ switch (category) {
726
+ case "query":
727
+ return pallet.storage.map((s) => s.name);
728
+ case "tx":
729
+ return pallet.calls.map((c) => c.name);
730
+ case "const":
731
+ return pallet.constants.map((c) => c.name);
732
+ case "events":
733
+ return pallet.events.map((e) => e.name);
734
+ case "errors":
735
+ return pallet.errors.map((e) => e.name);
736
+ default:
737
+ return [];
738
+ }
739
+ }
740
+ function resolveChainFromArgs(precedingWords, _config) {
741
+ for (let i = 0;i < precedingWords.length - 1; i++) {
742
+ if (precedingWords[i] === "--chain") {
743
+ return precedingWords[i + 1];
744
+ }
745
+ }
746
+ return;
747
+ }
748
+ function filterPrefix(candidates, prefix) {
749
+ if (!prefix)
750
+ return candidates;
751
+ const lower = prefix.toLowerCase();
752
+ return candidates.filter((c) => c.toLowerCase().startsWith(lower));
753
+ }
754
+ async function generateCompletions(currentWord, precedingWords) {
755
+ const config = await loadConfig();
756
+ const knownChains = Object.keys(config.chains);
757
+ const prevWord = precedingWords[precedingWords.length - 1];
758
+ if (prevWord === "--chain") {
759
+ return filterPrefix(knownChains, currentWord);
760
+ }
761
+ if (prevWord === "--output") {
762
+ return filterPrefix(["pretty", "json"], currentWord);
763
+ }
764
+ if (prevWord === "--from") {
765
+ const accounts = await loadAccounts();
766
+ const names = [...DEV_NAMES, ...accounts.accounts.map((a) => a.name)];
767
+ return filterPrefix(names, currentWord);
768
+ }
769
+ if (currentWord.startsWith("--")) {
770
+ const activeCategory = detectCategory(precedingWords, knownChains);
771
+ const options = [...GLOBAL_OPTIONS];
772
+ if (activeCategory === "tx")
773
+ options.push(...TX_OPTIONS);
774
+ if (activeCategory === "query")
775
+ options.push(...QUERY_OPTIONS);
776
+ return filterPrefix(options, currentWord);
777
+ }
778
+ const firstArg = precedingWords.find((w) => !w.startsWith("-"));
779
+ if (firstArg === "chain") {
780
+ return filterPrefix(CHAIN_SUBCOMMANDS, currentWord);
781
+ }
782
+ if (firstArg === "account") {
783
+ return filterPrefix(ACCOUNT_SUBCOMMANDS, currentWord);
784
+ }
785
+ if (firstArg === "hash") {
786
+ return filterPrefix(getAlgorithmNames(), currentWord);
787
+ }
788
+ return completeDotpath(currentWord, config, knownChains, precedingWords);
789
+ }
790
+ function detectCategory(words, _knownChains) {
791
+ for (const w of words) {
792
+ if (w.startsWith("-"))
793
+ continue;
794
+ const parts = w.split(".");
795
+ for (const part of parts) {
796
+ const cat = matchCategory2(part);
797
+ if (cat)
798
+ return cat;
799
+ }
800
+ }
801
+ return;
802
+ }
803
+ async function completeDotpath(currentWord, config, knownChains, precedingWords) {
804
+ const endsWithDot = currentWord.endsWith(".");
805
+ const parts = currentWord.split(".");
806
+ const completeSegments = parts.slice(0, -1);
807
+ const partial = endsWithDot ? "" : parts[parts.length - 1] ?? "";
808
+ const numComplete = completeSegments.length;
809
+ if (numComplete === 0 && !endsWithDot) {
810
+ const candidates = [
811
+ ...CATEGORIES.map((c) => `${c}.`),
812
+ ...knownChains.map((c) => `${c}.`),
813
+ ...NAMED_COMMANDS
814
+ ];
815
+ return filterPrefix(candidates, partial);
816
+ }
817
+ const first = completeSegments[0] ?? "";
818
+ const firstIsCategory = matchCategory2(first) !== undefined;
819
+ const firstIsChain = knownChains.some((c) => c.toLowerCase() === first.toLowerCase());
820
+ const chainFromFlag = resolveChainFromArgs(precedingWords, config);
821
+ if (firstIsCategory) {
822
+ const category = matchCategory2(first);
823
+ if (numComplete === 1 && endsWithDot) {
824
+ const chainName = chainFromFlag ?? config.defaultChain;
825
+ const pallets = await loadPallets(config, chainName);
826
+ if (!pallets)
827
+ return [];
828
+ const filtered = filterPallets(pallets, category);
829
+ const candidates = filtered.map((p) => `${first}.${p.name}.`);
830
+ return filterPrefix(candidates, currentWord.slice(0, -1));
831
+ }
832
+ if (numComplete === 1 && !endsWithDot) {
833
+ const chainName = chainFromFlag ?? config.defaultChain;
834
+ const pallets = await loadPallets(config, chainName);
835
+ if (!pallets)
836
+ return [];
837
+ const filtered = filterPallets(pallets, category);
838
+ const candidates = filtered.map((p) => `${first}.${p.name}.`);
839
+ return filterPrefix(candidates, currentWord);
840
+ }
841
+ if (numComplete === 2) {
842
+ const palletName2 = completeSegments[1];
843
+ const chainName = chainFromFlag ?? config.defaultChain;
844
+ const pallets = await loadPallets(config, chainName);
845
+ if (!pallets)
846
+ return [];
847
+ const pallet = pallets.find((p) => p.name.toLowerCase() === palletName2.toLowerCase());
848
+ if (!pallet)
849
+ return [];
850
+ const items = getItemNames(pallet, category);
851
+ const candidates = items.map((i) => `${first}.${palletName2}.${i}`);
852
+ return filterPrefix(candidates, endsWithDot ? currentWord.slice(0, -1) : currentWord);
853
+ }
854
+ return [];
855
+ }
856
+ if (firstIsChain) {
857
+ const chainName = first;
858
+ if (numComplete === 1 && endsWithDot) {
859
+ const candidates = CATEGORIES.map((c) => `${first}.${c}.`);
860
+ return filterPrefix(candidates, currentWord.slice(0, -1));
861
+ }
862
+ if (numComplete === 1 && !endsWithDot) {
863
+ const candidates = CATEGORIES.map((c) => `${first}.${c}.`);
864
+ return filterPrefix(candidates, currentWord);
865
+ }
866
+ if (numComplete === 2) {
867
+ const category = matchCategory2(completeSegments[1]);
868
+ if (!category)
869
+ return [];
870
+ const pallets = await loadPallets(config, chainName);
871
+ if (!pallets)
872
+ return [];
873
+ const filtered = filterPallets(pallets, category);
874
+ const prefix = `${first}.${completeSegments[1]}`;
875
+ const candidates = filtered.map((p) => `${prefix}.${p.name}.`);
876
+ return filterPrefix(candidates, endsWithDot ? currentWord.slice(0, -1) : currentWord);
877
+ }
878
+ if (numComplete === 3) {
879
+ const category = matchCategory2(completeSegments[1]);
880
+ if (!category)
881
+ return [];
882
+ const palletName2 = completeSegments[2];
883
+ const pallets = await loadPallets(config, chainName);
884
+ if (!pallets)
885
+ return [];
886
+ const pallet = pallets.find((p) => p.name.toLowerCase() === palletName2.toLowerCase());
887
+ if (!pallet)
888
+ return [];
889
+ const items = getItemNames(pallet, category);
890
+ const prefix = `${first}.${completeSegments[1]}.${palletName2}`;
891
+ const candidates = items.map((i) => `${prefix}.${i}`);
892
+ return filterPrefix(candidates, endsWithDot ? currentWord.slice(0, -1) : currentWord);
893
+ }
894
+ return [];
895
+ }
896
+ return [];
897
+ }
898
+ var CATEGORIES, CATEGORY_ALIASES2, NAMED_COMMANDS, CHAIN_SUBCOMMANDS, ACCOUNT_SUBCOMMANDS, GLOBAL_OPTIONS, TX_OPTIONS, QUERY_OPTIONS;
899
+ var init_complete = __esm(() => {
900
+ init_accounts_store();
901
+ init_store();
902
+ init_accounts();
903
+ init_hash();
904
+ init_metadata();
905
+ CATEGORIES = ["query", "tx", "const", "events", "errors"];
906
+ CATEGORY_ALIASES2 = {
907
+ query: "query",
908
+ tx: "tx",
909
+ const: "const",
910
+ consts: "const",
911
+ constants: "const",
912
+ events: "events",
913
+ event: "events",
914
+ errors: "errors",
915
+ error: "errors"
916
+ };
917
+ NAMED_COMMANDS = ["chain", "account", "inspect", "hash", "completions"];
918
+ CHAIN_SUBCOMMANDS = ["add", "remove", "update", "list", "default"];
919
+ ACCOUNT_SUBCOMMANDS = [
920
+ "add",
921
+ "create",
922
+ "new",
923
+ "import",
924
+ "derive",
925
+ "list",
926
+ "remove",
927
+ "delete",
928
+ "inspect"
929
+ ];
930
+ GLOBAL_OPTIONS = ["--chain", "--rpc", "--light-client", "--output", "--help", "--version"];
931
+ TX_OPTIONS = ["--from", "--dry-run", "--encode", "--ext"];
932
+ QUERY_OPTIONS = ["--limit"];
933
+ });
934
+
935
+ // src/cli.ts
936
+ import cac from "cac";
937
+ // package.json
938
+ var version = "1.4.0";
939
+
940
+ // src/commands/account.ts
941
+ init_accounts_store();
942
+ init_accounts();
943
+
944
+ // src/core/output.ts
945
+ import { Binary } from "polkadot-api";
946
+ var isTTY = process.stdout.isTTY ?? false;
947
+ var RESET = isTTY ? "\x1B[0m" : "";
948
+ var CYAN = isTTY ? "\x1B[36m" : "";
949
+ var GREEN = isTTY ? "\x1B[32m" : "";
950
+ var RED = isTTY ? "\x1B[31m" : "";
951
+ var YELLOW = isTTY ? "\x1B[33m" : "";
952
+ var MAGENTA = isTTY ? "\x1B[35m" : "";
953
+ var DIM = isTTY ? "\x1B[2m" : "";
954
+ var BOLD = isTTY ? "\x1B[1m" : "";
955
+ function replacer(_key, value) {
956
+ if (typeof value === "bigint")
957
+ return value.toString();
958
+ if (value instanceof Binary) {
959
+ const text = value.asText();
960
+ return text.includes("�") ? value.asHex() : text;
961
+ }
962
+ if (value instanceof Uint8Array)
963
+ return `0x${Buffer.from(value).toString("hex")}`;
964
+ return value;
965
+ }
966
+ function formatJson(data) {
967
+ return JSON.stringify(data, replacer, 2);
968
+ }
969
+ function formatPretty(data) {
970
+ const json = JSON.stringify(data, replacer, 2);
971
+ if (!json)
972
+ return "undefined";
973
+ return colorizeJson(json);
974
+ }
975
+ function colorizeJson(json) {
976
+ return json.replace(/("(?:\\.|[^"\\])*")\s*:/g, `${CYAN}$1${RESET}:`).replace(/:\s*("(?:\\.|[^"\\])*")/g, (match, str) => match.replace(str, `${GREEN}${str}${RESET}`)).replace(/:\s*(\d+(?:\.\d+)?)/g, (match, num) => match.replace(num, `${YELLOW}${num}${RESET}`)).replace(/:\s*(true|false)/g, (match, bool) => match.replace(bool, `${MAGENTA}${bool}${RESET}`)).replace(/:\s*(null)/g, (match, n) => match.replace(n, `${DIM}${n}${RESET}`));
977
+ }
978
+ function printResult(data, format = "pretty") {
979
+ if (format === "json") {
980
+ console.log(formatJson(data));
981
+ } else {
982
+ console.log(formatPretty(data));
983
+ }
984
+ }
985
+ function printHeading(text) {
986
+ console.log(`
987
+ ${BOLD}${text}${RESET}
988
+ `);
989
+ }
990
+ function printItem(name, description) {
991
+ if (description) {
992
+ console.log(` ${CYAN}${name}${RESET} ${DIM}${description}${RESET}`);
993
+ } else {
994
+ console.log(` ${CYAN}${name}${RESET}`);
995
+ }
996
+ }
997
+ function printDocs(docs) {
998
+ const text = docs.join(`
999
+ `).trim();
1000
+ if (text) {
1001
+ console.log(` ${DIM}${text}${RESET}`);
1002
+ }
1003
+ }
1004
+ var CHECK_MARK = "✓";
1005
+ var SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
1006
+
1007
+ class Spinner {
1008
+ timer = null;
1009
+ frame = 0;
1010
+ start(msg) {
1011
+ this.stop();
1012
+ if (!isTTY) {
1013
+ console.error(msg);
1014
+ return;
1015
+ }
1016
+ process.stdout.write(`${SPINNER_FRAMES[0]} ${msg}`);
1017
+ this.timer = setInterval(() => {
1018
+ this.frame = (this.frame + 1) % SPINNER_FRAMES.length;
1019
+ process.stdout.write(`\r\x1B[K${SPINNER_FRAMES[this.frame]} ${msg}`);
1020
+ }, 80);
1021
+ }
1022
+ stop() {
1023
+ if (this.timer !== null) {
1024
+ clearInterval(this.timer);
1025
+ this.timer = null;
1026
+ this.frame = 0;
1027
+ if (isTTY)
1028
+ process.stdout.write("\r\x1B[K");
454
1029
  }
455
1030
  }
456
1031
  succeed(msg) {
@@ -888,334 +1463,98 @@ async function accountInspect(input, opts) {
888
1463
  }
889
1464
  }
890
1465
 
1466
+ // src/commands/chain.ts
1467
+ init_store();
1468
+ init_types();
1469
+
891
1470
  // src/core/client.ts
1471
+ init_store();
1472
+ init_errors();
892
1473
  import { createClient } from "polkadot-api";
893
1474
  import { withPolkadotSdkCompat } from "polkadot-api/polkadot-sdk-compat";
894
1475
  import { getWsProvider } from "polkadot-api/ws-provider";
895
1476
  import { WebSocket } from "ws";
896
-
897
- // src/utils/errors.ts
898
- class CliError extends Error {
899
- constructor(message) {
900
- super(message);
901
- this.name = "CliError";
902
- }
903
- }
904
-
905
- class ConnectionError extends CliError {
906
- constructor(message) {
907
- super(message);
908
- this.name = "ConnectionError";
909
- }
910
- }
911
-
912
- class MetadataError extends CliError {
913
- constructor(message) {
914
- super(message);
915
- this.name = "MetadataError";
916
- }
917
- }
918
-
919
- // src/core/client.ts
920
- var KNOWN_CHAIN_SPECS = {
921
- polkadot: { spec: "polkadot-api/chains/polkadot" },
922
- kusama: { spec: "polkadot-api/chains/ksmcc3" },
923
- westend: { spec: "polkadot-api/chains/westend2" },
924
- paseo: { spec: "polkadot-api/chains/paseo" },
925
- "polkadot-asset-hub": { spec: "polkadot-api/chains/polkadot_asset_hub", relay: "polkadot" },
926
- "polkadot-bridge-hub": { spec: "polkadot-api/chains/polkadot_bridge_hub", relay: "polkadot" },
927
- "polkadot-collectives": { spec: "polkadot-api/chains/polkadot_collectives", relay: "polkadot" },
928
- "polkadot-coretime": { spec: "polkadot-api/chains/polkadot_coretime", relay: "polkadot" },
929
- "polkadot-people": { spec: "polkadot-api/chains/polkadot_people", relay: "polkadot" },
930
- "paseo-asset-hub": { spec: "polkadot-api/chains/paseo_asset_hub", relay: "paseo" },
931
- "paseo-coretime": { spec: "polkadot-api/chains/paseo_coretime", relay: "paseo" },
932
- "paseo-people": { spec: "polkadot-api/chains/paseo_people", relay: "paseo" }
933
- };
934
- function suppressWsNoise() {
935
- const orig = console.error;
936
- console.error = (...args) => {
937
- if (typeof args[0] === "string" && args[0].includes("Unable to connect"))
938
- return;
939
- orig(...args);
940
- };
941
- return () => {
942
- console.error = orig;
943
- };
944
- }
945
- async function createChainClient(chainName, chainConfig, rpcOverride) {
946
- const useLight = !rpcOverride && chainConfig.lightClient;
947
- const restoreConsole = suppressWsNoise();
948
- let provider;
949
- if (useLight) {
950
- provider = await createSmoldotProvider(chainName);
951
- } else {
952
- const rpc = rpcOverride ?? chainConfig.rpc;
953
- if (!rpc) {
954
- restoreConsole();
955
- throw new ConnectionError(`No RPC endpoint configured for chain "${chainName}". Use --rpc or configure one with: dot chain add ${chainName} --rpc <url>`);
956
- }
957
- provider = withPolkadotSdkCompat(getWsProvider(rpc, {
958
- timeout: 1e4,
959
- websocketClass: WebSocket
960
- }));
961
- }
962
- const client = createClient(provider, {
963
- getMetadata: async () => loadMetadata(chainName),
964
- setMetadata: async (_codeHash, metadata) => {
965
- await saveMetadata(chainName, metadata);
966
- }
967
- });
968
- return {
969
- client,
970
- destroy: () => {
971
- client.destroy();
972
- restoreConsole();
973
- }
974
- };
975
- }
976
- async function createSmoldotProvider(chainName) {
977
- const { start } = await import("polkadot-api/smoldot");
978
- const { getSmProvider } = await import("polkadot-api/sm-provider");
979
- const entry = KNOWN_CHAIN_SPECS[chainName];
980
- if (!entry) {
981
- throw new ConnectionError(`Light client is only supported for known chains: ${Object.keys(KNOWN_CHAIN_SPECS).join(", ")}. Use --rpc to connect to "${chainName}" instead.`);
982
- }
983
- const { chainSpec } = await import(entry.spec);
984
- const smoldot = start();
985
- if (entry.relay) {
986
- const relayEntry = KNOWN_CHAIN_SPECS[entry.relay];
987
- if (!relayEntry) {
988
- throw new ConnectionError(`Relay chain "${entry.relay}" not found in known chain specs.`);
989
- }
990
- const { chainSpec: relaySpec } = await import(relayEntry.spec);
991
- const relayChain = await smoldot.addChain({ chainSpec: relaySpec, disableJsonRpc: true });
992
- const chain2 = await smoldot.addChain({ chainSpec, potentialRelayChains: [relayChain] });
993
- return getSmProvider(chain2);
994
- }
995
- const chain = await smoldot.addChain({ chainSpec });
996
- return getSmProvider(chain);
997
- }
998
-
999
- // src/core/metadata.ts
1000
- import { getDynamicBuilder, getLookupFn } from "@polkadot-api/metadata-builders";
1001
- import { decAnyMetadata, unifyMetadata } from "@polkadot-api/substrate-bindings";
1002
- var METADATA_TIMEOUT_MS = 15000;
1003
- function parseMetadata(raw) {
1004
- const decoded = decAnyMetadata(raw);
1005
- const unified = unifyMetadata(decoded);
1006
- const lookup = getLookupFn(unified);
1007
- const builder = getDynamicBuilder(lookup);
1008
- return { unified, lookup, builder };
1009
- }
1010
- async function fetchMetadataFromChain(clientHandle, chainName) {
1011
- const { client } = clientHandle;
1012
- try {
1013
- const hex = await Promise.race([
1014
- client._request("state_getMetadata", []),
1015
- 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))
1016
- ]);
1017
- const bytes = hexToBytes(hex);
1018
- await saveMetadata(chainName, bytes);
1019
- return bytes;
1020
- } catch (err) {
1021
- if (err instanceof ConnectionError)
1022
- throw err;
1023
- throw new ConnectionError(`Failed to fetch metadata for "${chainName}": ${err instanceof Error ? err.message : err}. ` + "Check that the RPC endpoint is correct and reachable.");
1024
- }
1025
- }
1026
- async function getOrFetchMetadata(chainName, clientHandle) {
1027
- let raw = await loadMetadata(chainName);
1028
- if (!raw) {
1029
- if (!clientHandle) {
1030
- throw new MetadataError(`No cached metadata for chain "${chainName}". Run a command that connects to the chain first, ` + `e.g.: dot chain add ${chainName} --rpc <url>`);
1031
- }
1032
- raw = await fetchMetadataFromChain(clientHandle, chainName);
1033
- }
1034
- return parseMetadata(raw);
1035
- }
1036
- function listPallets(meta) {
1037
- return meta.unified.pallets.map((p) => ({
1038
- name: p.name,
1039
- index: p.index,
1040
- docs: p.docs ?? [],
1041
- storage: (p.storage?.items ?? []).map((s) => ({
1042
- name: s.name,
1043
- docs: s.docs ?? [],
1044
- type: s.type.tag,
1045
- keyTypeId: s.type.tag === "map" ? s.type.value.key : null,
1046
- valueTypeId: s.type.tag === "plain" ? s.type.value : s.type.value.value
1047
- })),
1048
- constants: (p.constants ?? []).map((c) => ({
1049
- name: c.name,
1050
- docs: c.docs ?? [],
1051
- typeId: c.type
1052
- })),
1053
- calls: extractEnumVariants(meta, p.calls),
1054
- events: extractEnumVariants(meta, p.events),
1055
- errors: extractEnumVariants(meta, p.errors).map(({ name, docs }) => ({ name, docs }))
1056
- }));
1057
- }
1058
- function extractEnumVariants(meta, ref) {
1059
- if (!ref)
1060
- return [];
1061
- try {
1062
- const entry = meta.lookup(ref.type);
1063
- if (entry.type !== "enum")
1064
- return [];
1065
- return Object.entries(entry.value).map(([name, variant]) => ({
1066
- name,
1067
- docs: entry.innerDocs?.[name] ?? [],
1068
- typeId: resolveVariantTypeId(variant)
1069
- }));
1070
- } catch {
1071
- return [];
1072
- }
1073
- }
1074
- function resolveVariantTypeId(variant) {
1075
- if (variant.type === "lookupEntry")
1076
- return variant.value?.id ?? null;
1077
- if (variant.type === "struct")
1078
- return null;
1079
- if (variant.type === "void" || variant.type === "empty")
1080
- return null;
1081
- return null;
1082
- }
1083
- function findPallet(meta, palletName) {
1084
- const pallets = listPallets(meta);
1085
- return pallets.find((p) => p.name.toLowerCase() === palletName.toLowerCase());
1086
- }
1087
- function getSignedExtensions(meta) {
1088
- const byVersion = meta.unified.extrinsic.signedExtensions;
1089
- const versionKeys = Object.keys(byVersion);
1090
- if (versionKeys.length === 0)
1091
- return [];
1092
- return byVersion[Number(versionKeys[0])] ?? [];
1093
- }
1094
- function getPalletNames(meta) {
1095
- return meta.unified.pallets.map((p) => p.name);
1096
- }
1097
- function describeType(lookup, typeId) {
1098
- try {
1099
- const entry = lookup(typeId);
1100
- return formatLookupEntry(entry);
1101
- } catch {
1102
- return `type(${typeId})`;
1103
- }
1104
- }
1105
- function formatLookupEntry(entry) {
1106
- switch (entry.type) {
1107
- case "primitive":
1108
- return entry.value;
1109
- case "compact":
1110
- return `Compact<${formatLookupEntry(entry.isBig ? { type: "primitive", value: "u128" } : { type: "primitive", value: "u64" })}>`;
1111
- case "AccountId32":
1112
- return "AccountId32";
1113
- case "bitSequence":
1114
- return "BitSequence";
1115
- case "sequence":
1116
- return `Vec<${formatLookupEntry(entry.value)}>`;
1117
- case "array":
1118
- return `[${formatLookupEntry(entry.value)}; ${entry.len}]`;
1119
- case "tuple":
1120
- return `(${entry.value.map(formatLookupEntry).join(", ")})`;
1121
- case "struct":
1122
- return `{ ${Object.entries(entry.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ")} }`;
1123
- case "option":
1124
- return `Option<${formatLookupEntry(entry.value)}>`;
1125
- case "result":
1126
- return `Result<${formatLookupEntry(entry.value.ok)}, ${formatLookupEntry(entry.value.ko)}>`;
1127
- case "enum": {
1128
- const variants = Object.keys(entry.value);
1129
- if (variants.length <= 4)
1130
- return variants.join(" | ");
1131
- return `enum(${variants.length} variants)`;
1132
- }
1133
- default:
1134
- return "unknown";
1135
- }
1136
- }
1137
- function describeCallArgs(meta, palletName, callName) {
1138
- try {
1139
- const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
1140
- if (!palletMeta?.calls)
1141
- return "";
1142
- const callsEntry = meta.lookup(palletMeta.calls.type);
1143
- if (callsEntry.type !== "enum")
1144
- return "";
1145
- const variant = callsEntry.value[callName];
1146
- if (!variant)
1147
- return "";
1148
- if (variant.type === "void")
1149
- return "()";
1150
- if (variant.type === "struct") {
1151
- const fields = Object.entries(variant.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
1152
- return `(${fields})`;
1153
- }
1154
- if (variant.type === "lookupEntry") {
1155
- const inner = variant.value;
1156
- if (inner.type === "void")
1157
- return "()";
1158
- if (inner.type === "struct") {
1159
- const fields = Object.entries(inner.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
1160
- return `(${fields})`;
1161
- }
1162
- return `(${formatLookupEntry(inner)})`;
1163
- }
1164
- if (variant.type === "tuple") {
1165
- const types = variant.value.map(formatLookupEntry).join(", ");
1166
- return `(${types})`;
1167
- }
1168
- return "";
1169
- } catch {
1170
- return "";
1171
- }
1477
+ var KNOWN_CHAIN_SPECS = {
1478
+ polkadot: { spec: "polkadot-api/chains/polkadot" },
1479
+ kusama: { spec: "polkadot-api/chains/ksmcc3" },
1480
+ westend: { spec: "polkadot-api/chains/westend2" },
1481
+ paseo: { spec: "polkadot-api/chains/paseo" },
1482
+ "polkadot-asset-hub": { spec: "polkadot-api/chains/polkadot_asset_hub", relay: "polkadot" },
1483
+ "polkadot-bridge-hub": { spec: "polkadot-api/chains/polkadot_bridge_hub", relay: "polkadot" },
1484
+ "polkadot-collectives": { spec: "polkadot-api/chains/polkadot_collectives", relay: "polkadot" },
1485
+ "polkadot-coretime": { spec: "polkadot-api/chains/polkadot_coretime", relay: "polkadot" },
1486
+ "polkadot-people": { spec: "polkadot-api/chains/polkadot_people", relay: "polkadot" },
1487
+ "paseo-asset-hub": { spec: "polkadot-api/chains/paseo_asset_hub", relay: "paseo" },
1488
+ "paseo-coretime": { spec: "polkadot-api/chains/paseo_coretime", relay: "paseo" },
1489
+ "paseo-people": { spec: "polkadot-api/chains/paseo_people", relay: "paseo" }
1490
+ };
1491
+ function suppressWsNoise() {
1492
+ const orig = console.error;
1493
+ console.error = (...args) => {
1494
+ if (typeof args[0] === "string" && args[0].includes("Unable to connect"))
1495
+ return;
1496
+ orig(...args);
1497
+ };
1498
+ return () => {
1499
+ console.error = orig;
1500
+ };
1172
1501
  }
1173
- function describeEventFields(meta, palletName, eventName) {
1174
- try {
1175
- const palletMeta = meta.unified.pallets.find((p) => p.name === palletName);
1176
- if (!palletMeta?.events)
1177
- return "";
1178
- const eventsEntry = meta.lookup(palletMeta.events.type);
1179
- if (eventsEntry.type !== "enum")
1180
- return "";
1181
- const variant = eventsEntry.value[eventName];
1182
- if (!variant)
1183
- return "";
1184
- if (variant.type === "void")
1185
- return "()";
1186
- if (variant.type === "struct") {
1187
- const fields = Object.entries(variant.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
1188
- return `(${fields})`;
1502
+ async function createChainClient(chainName, chainConfig, rpcOverride) {
1503
+ const useLight = !rpcOverride && chainConfig.lightClient;
1504
+ const restoreConsole = suppressWsNoise();
1505
+ let provider;
1506
+ if (useLight) {
1507
+ provider = await createSmoldotProvider(chainName);
1508
+ } else {
1509
+ const rpc = rpcOverride ?? chainConfig.rpc;
1510
+ if (!rpc) {
1511
+ restoreConsole();
1512
+ throw new ConnectionError(`No RPC endpoint configured for chain "${chainName}". Use --rpc or configure one with: dot chain add ${chainName} --rpc <url>`);
1189
1513
  }
1190
- if (variant.type === "lookupEntry") {
1191
- const inner = variant.value;
1192
- if (inner.type === "void")
1193
- return "()";
1194
- if (inner.type === "struct") {
1195
- const fields = Object.entries(inner.value).map(([k, v]) => `${k}: ${formatLookupEntry(v)}`).join(", ");
1196
- return `(${fields})`;
1197
- }
1198
- return `(${formatLookupEntry(inner)})`;
1514
+ provider = withPolkadotSdkCompat(getWsProvider(rpc, {
1515
+ timeout: 1e4,
1516
+ websocketClass: WebSocket
1517
+ }));
1518
+ }
1519
+ const client = createClient(provider, {
1520
+ getMetadata: async () => loadMetadata(chainName),
1521
+ setMetadata: async (_codeHash, metadata) => {
1522
+ await saveMetadata(chainName, metadata);
1199
1523
  }
1200
- if (variant.type === "tuple") {
1201
- const types = variant.value.map(formatLookupEntry).join(", ");
1202
- return `(${types})`;
1524
+ });
1525
+ return {
1526
+ client,
1527
+ destroy: () => {
1528
+ client.destroy();
1529
+ restoreConsole();
1203
1530
  }
1204
- return "";
1205
- } catch {
1206
- return "";
1207
- }
1531
+ };
1208
1532
  }
1209
- function hexToBytes(hex) {
1210
- const clean = hex.startsWith("0x") ? hex.slice(2) : hex;
1211
- const bytes = new Uint8Array(clean.length / 2);
1212
- for (let i = 0;i < clean.length; i += 2) {
1213
- bytes[i / 2] = parseInt(clean.substring(i, i + 2), 16);
1533
+ async function createSmoldotProvider(chainName) {
1534
+ const { start } = await import("polkadot-api/smoldot");
1535
+ const { getSmProvider } = await import("polkadot-api/sm-provider");
1536
+ const entry = KNOWN_CHAIN_SPECS[chainName];
1537
+ if (!entry) {
1538
+ throw new ConnectionError(`Light client is only supported for known chains: ${Object.keys(KNOWN_CHAIN_SPECS).join(", ")}. Use --rpc to connect to "${chainName}" instead.`);
1214
1539
  }
1215
- return bytes;
1540
+ const { chainSpec } = await import(entry.spec);
1541
+ const smoldot = start();
1542
+ if (entry.relay) {
1543
+ const relayEntry = KNOWN_CHAIN_SPECS[entry.relay];
1544
+ if (!relayEntry) {
1545
+ throw new ConnectionError(`Relay chain "${entry.relay}" not found in known chain specs.`);
1546
+ }
1547
+ const { chainSpec: relaySpec } = await import(relayEntry.spec);
1548
+ const relayChain = await smoldot.addChain({ chainSpec: relaySpec, disableJsonRpc: true });
1549
+ const chain2 = await smoldot.addChain({ chainSpec, potentialRelayChains: [relayChain] });
1550
+ return getSmProvider(chain2);
1551
+ }
1552
+ const chain = await smoldot.addChain({ chainSpec });
1553
+ return getSmProvider(chain);
1216
1554
  }
1217
1555
 
1218
1556
  // src/commands/chain.ts
1557
+ init_metadata();
1219
1558
  var CHAIN_HELP = `
1220
1559
  ${BOLD}Usage:${RESET}
1221
1560
  $ dot chain add <name> --rpc <url> Add a chain via WebSocket RPC
@@ -1363,6 +1702,94 @@ async function chainDefault(name) {
1363
1702
  console.log(`Default chain set to "${resolved}".`);
1364
1703
  }
1365
1704
 
1705
+ // src/commands/completions.ts
1706
+ var ZSH_SCRIPT = `_dot_completions() {
1707
+ emulate -L zsh
1708
+ local -a completions
1709
+ local current_word="\${words[CURRENT]}"
1710
+ local preceding=("\${words[2,CURRENT-1]}")
1711
+
1712
+ # Build args: -- <current_word> <preceding_words...>
1713
+ local args=("__complete" "--" "\${current_word}")
1714
+ args+=("\${preceding[@]}")
1715
+
1716
+ local output
1717
+ output="$(dot "\${args[@]}" 2>/dev/null)"
1718
+ [[ -z "$output" ]] && return
1719
+
1720
+ completions=("\${(@f)output}")
1721
+
1722
+ compadd -S '' -- "\${completions[@]}"
1723
+ }
1724
+
1725
+ compdef _dot_completions dot`;
1726
+ var BASH_SCRIPT = `_dot_completions() {
1727
+ local current_word="\${COMP_WORDS[COMP_CWORD]}"
1728
+ local preceding=("\${COMP_WORDS[@]:1:COMP_CWORD-1}")
1729
+
1730
+ # Build args: -- <current_word> <preceding_words...>
1731
+ local args=("__complete" "--" "\${current_word}")
1732
+ args+=("\${preceding[@]}")
1733
+
1734
+ local IFS=$'\\n'
1735
+ local completions
1736
+ completions=($(dot "\${args[@]}" 2>/dev/null))
1737
+
1738
+ [[ \${#completions[@]} -eq 0 ]] && return
1739
+
1740
+ compopt -o nospace
1741
+ COMPREPLY=("\${completions[@]}")
1742
+ }
1743
+
1744
+ complete -F _dot_completions dot`;
1745
+ var FISH_SCRIPT = `function __dot_complete
1746
+ set -l tokens (commandline -opc)
1747
+ set -l current (commandline -ct)
1748
+
1749
+ set -l args "__complete" "--" "$current"
1750
+ for t in $tokens[2..-1]
1751
+ set -a args "$t"
1752
+ end
1753
+
1754
+ dot $args 2>/dev/null
1755
+ end
1756
+
1757
+ complete -c dot -f -a '(__dot_complete)'`;
1758
+ var SETUP_INSTRUCTIONS = {
1759
+ zsh: `# Add this to your ~/.zshrc:
1760
+ # eval "$(dot completions zsh)"
1761
+ # Then restart your shell or run: source ~/.zshrc`,
1762
+ bash: `# Add this to your ~/.bashrc:
1763
+ # eval "$(dot completions bash)"
1764
+ # Then restart your shell or run: source ~/.bashrc`,
1765
+ fish: `# Save this to ~/.config/fish/completions/dot.fish:
1766
+ # dot completions fish > ~/.config/fish/completions/dot.fish`
1767
+ };
1768
+ var SCRIPTS = {
1769
+ zsh: ZSH_SCRIPT,
1770
+ bash: BASH_SCRIPT,
1771
+ fish: FISH_SCRIPT
1772
+ };
1773
+ function registerCompletionsCommand(cli) {
1774
+ cli.command("completions <shell>", "Generate shell completion script (zsh, bash, fish)").action((shell) => {
1775
+ const script = SCRIPTS[shell];
1776
+ if (!script) {
1777
+ console.error(`Unsupported shell "${shell}". Supported: ${Object.keys(SCRIPTS).join(", ")}`);
1778
+ process.exit(1);
1779
+ }
1780
+ const instructions = SETUP_INSTRUCTIONS[shell];
1781
+ if (instructions) {
1782
+ process.stderr.write(`${instructions}
1783
+ `);
1784
+ }
1785
+ console.log(script);
1786
+ });
1787
+ }
1788
+
1789
+ // src/commands/const.ts
1790
+ init_store();
1791
+ init_metadata();
1792
+
1366
1793
  // src/utils/fuzzy-match.ts
1367
1794
  function levenshtein(a, b) {
1368
1795
  const la = a.length;
@@ -1400,6 +1827,8 @@ function suggestMessage(kind, input, candidates) {
1400
1827
  }
1401
1828
 
1402
1829
  // src/commands/focused-inspect.ts
1830
+ init_store();
1831
+ init_metadata();
1403
1832
  async function loadMeta(chainName, chainConfig, rpcOverride) {
1404
1833
  try {
1405
1834
  return await getOrFetchMetadata(chainName);
@@ -1708,13 +2137,14 @@ async function showItemHelp(category, target, opts) {
1708
2137
  if (storageItem.keyTypeId != null) {
1709
2138
  console.log(`${BOLD}Usage:${RESET}`);
1710
2139
  console.log(` dot query.${pallet.name}.${storageItem.name} <key>`);
1711
- console.log(` dot query.${pallet.name}.${storageItem.name} # all entries`);
2140
+ console.log(` dot query.${pallet.name}.${storageItem.name} --dump # all entries`);
1712
2141
  } else {
1713
2142
  console.log(`${BOLD}Usage:${RESET}`);
1714
2143
  console.log(` dot query.${pallet.name}.${storageItem.name}`);
1715
2144
  }
1716
2145
  console.log();
1717
2146
  console.log(`${BOLD}Options:${RESET}`);
2147
+ console.log(` --dump Dump all entries of a map (required for keyless map queries)`);
1718
2148
  console.log(` --limit <n> Max entries for map queries (0 = unlimited, default: 100)`);
1719
2149
  console.log();
1720
2150
  return;
@@ -1842,6 +2272,8 @@ async function handleConst(target, opts) {
1842
2272
  }
1843
2273
 
1844
2274
  // src/commands/focused-inspect.ts
2275
+ init_store();
2276
+ init_metadata();
1845
2277
  async function loadMeta2(chainName, chainConfig, rpcOverride) {
1846
2278
  try {
1847
2279
  return await getOrFetchMetadata(chainName);
@@ -2150,13 +2582,14 @@ async function showItemHelp2(category, target, opts) {
2150
2582
  if (storageItem.keyTypeId != null) {
2151
2583
  console.log(`${BOLD}Usage:${RESET}`);
2152
2584
  console.log(` dot query.${pallet.name}.${storageItem.name} <key>`);
2153
- console.log(` dot query.${pallet.name}.${storageItem.name} # all entries`);
2585
+ console.log(` dot query.${pallet.name}.${storageItem.name} --dump # all entries`);
2154
2586
  } else {
2155
2587
  console.log(`${BOLD}Usage:${RESET}`);
2156
2588
  console.log(` dot query.${pallet.name}.${storageItem.name}`);
2157
2589
  }
2158
2590
  console.log();
2159
2591
  console.log(`${BOLD}Options:${RESET}`);
2592
+ console.log(` --dump Dump all entries of a map (required for keyless map queries)`);
2160
2593
  console.log(` --limit <n> Max entries for map queries (0 = unlimited, default: 100)`);
2161
2594
  console.log();
2162
2595
  return;
@@ -2217,61 +2650,9 @@ async function showItemHelp2(category, target, opts) {
2217
2650
  }
2218
2651
  }
2219
2652
 
2220
- // src/core/hash.ts
2221
- import { blake2b } from "@noble/hashes/blake2.js";
2222
- import { sha256 } from "@noble/hashes/sha2.js";
2223
- import { keccak_256 } from "@noble/hashes/sha3.js";
2224
- import { bytesToHex, hexToBytes as hexToBytes2 } from "@noble/hashes/utils.js";
2225
- var ALGORITHMS = {
2226
- blake2b256: {
2227
- compute: (data) => blake2b(data, { dkLen: 32 }),
2228
- outputLen: 32,
2229
- description: "BLAKE2b with 256-bit output"
2230
- },
2231
- blake2b128: {
2232
- compute: (data) => blake2b(data, { dkLen: 16 }),
2233
- outputLen: 16,
2234
- description: "BLAKE2b with 128-bit output"
2235
- },
2236
- keccak256: {
2237
- compute: (data) => keccak_256(data),
2238
- outputLen: 32,
2239
- description: "Keccak-256 (Ethereum-compatible)"
2240
- },
2241
- sha256: {
2242
- compute: (data) => sha256(data),
2243
- outputLen: 32,
2244
- description: "SHA-256"
2245
- }
2246
- };
2247
- function computeHash(algorithm, data) {
2248
- const algo = ALGORITHMS[algorithm];
2249
- if (!algo) {
2250
- throw new Error(`Unknown algorithm: ${algorithm}`);
2251
- }
2252
- return algo.compute(data);
2253
- }
2254
- function parseInputData(input) {
2255
- if (input.startsWith("0x")) {
2256
- const hex = input.slice(2);
2257
- if (hex.length % 2 !== 0) {
2258
- throw new Error(`Invalid hex input: odd number of characters`);
2259
- }
2260
- return hexToBytes2(hex);
2261
- }
2262
- return new TextEncoder().encode(input);
2263
- }
2264
- function toHex(bytes) {
2265
- return `0x${bytesToHex(bytes)}`;
2266
- }
2267
- function isValidAlgorithm(name) {
2268
- return name in ALGORITHMS;
2269
- }
2270
- function getAlgorithmNames() {
2271
- return Object.keys(ALGORITHMS);
2272
- }
2273
-
2274
2653
  // src/commands/hash.ts
2654
+ init_hash();
2655
+ init_errors();
2275
2656
  async function resolveInput(data, opts) {
2276
2657
  const sources = [data !== undefined, !!opts.file, !!opts.stdin].filter(Boolean).length;
2277
2658
  if (sources > 1) {
@@ -2348,6 +2729,10 @@ function registerHashCommand(cli) {
2348
2729
  });
2349
2730
  }
2350
2731
 
2732
+ // src/commands/inspect.ts
2733
+ init_store();
2734
+ init_metadata();
2735
+
2351
2736
  // src/utils/parse-target.ts
2352
2737
  function parseTarget(input, options) {
2353
2738
  const parts = input.split(".");
@@ -2598,6 +2983,10 @@ function registerInspectCommand(cli) {
2598
2983
  });
2599
2984
  }
2600
2985
 
2986
+ // src/commands/query.ts
2987
+ init_store();
2988
+ init_metadata();
2989
+
2601
2990
  // src/utils/parse-value.ts
2602
2991
  function parseValue(arg) {
2603
2992
  if (/^\d+$/.test(arg))
@@ -2619,6 +3008,9 @@ function parseValue(arg) {
2619
3008
  }
2620
3009
 
2621
3010
  // src/commands/tx.ts
3011
+ init_store();
3012
+ init_types();
3013
+ init_accounts();
2622
3014
  import { getViewBuilder } from "@polkadot-api/view-builder";
2623
3015
  import { Binary as Binary2 } from "polkadot-api";
2624
3016
 
@@ -2626,7 +3018,12 @@ import { Binary as Binary2 } from "polkadot-api";
2626
3018
  var pjsAppsLink = (rpc, hash) => `https://polkadot.js.org/apps/?rpc=${encodeURIComponent(rpc)}#/explorer/query/${hash}`;
2627
3019
  var papiLink = (rpc, hash) => `https://dev.papi.how/explorer/${hash}#networkId=custom&endpoint=${encodeURIComponent(rpc)}`;
2628
3020
 
3021
+ // src/commands/tx.ts
3022
+ init_metadata();
3023
+
2629
3024
  // src/core/resolve-address.ts
3025
+ init_accounts_store();
3026
+ init_accounts();
2630
3027
  async function resolveAccountAddress(input) {
2631
3028
  if (isDevAccount(input)) {
2632
3029
  return getDevAddress(input);
@@ -2654,6 +3051,7 @@ async function resolveAccountAddress(input) {
2654
3051
  }
2655
3052
 
2656
3053
  // src/commands/tx.ts
3054
+ init_errors();
2657
3055
  async function parseStructArgs(meta, fields, args, callLabel) {
2658
3056
  const fieldNames = Object.keys(fields);
2659
3057
  if (args.length !== fieldNames.length) {
@@ -2865,7 +3263,8 @@ async function parseTypedArg(meta, entry, arg) {
2865
3263
  const matched = variants.find((v) => v.toLowerCase() === arg.toLowerCase());
2866
3264
  if (matched) {
2867
3265
  const variant = entry.value[matched];
2868
- if (variant.type === "void") {
3266
+ const resolved = variant.type === "lookupEntry" ? variant.value : variant;
3267
+ if (resolved.type === "void") {
2869
3268
  return { type: matched };
2870
3269
  }
2871
3270
  }
@@ -3013,6 +3412,12 @@ async function handleQuery(target, keys, opts) {
3013
3412
  const parsedKeys = await parseStorageKeys(meta, palletInfo.name, storageItem, keys);
3014
3413
  const format = opts.output ?? "pretty";
3015
3414
  if (storageItem.type === "map" && parsedKeys.length === 0) {
3415
+ if (!opts.dump) {
3416
+ clientHandle.destroy();
3417
+ await showItemHelp("query", target, { chain: opts.chain, rpc: opts.rpc });
3418
+ console.log(`${DIM}Hint: use --dump to fetch all entries${RESET}`);
3419
+ return;
3420
+ }
3016
3421
  const entries = await storageApi.getEntries();
3017
3422
  const limit = Number(opts.limit);
3018
3423
  const truncated = limit > 0 && entries.length > limit;
@@ -3074,8 +3479,13 @@ async function parseStorageKeys(meta, palletName2, storageItem, args) {
3074
3479
  }
3075
3480
 
3076
3481
  // src/commands/tx.ts
3482
+ init_store();
3483
+ init_types();
3484
+ init_accounts();
3077
3485
  import { getViewBuilder as getViewBuilder2 } from "@polkadot-api/view-builder";
3078
3486
  import { Binary as Binary3 } from "polkadot-api";
3487
+ init_metadata();
3488
+ init_errors();
3079
3489
  async function handleTx(target, args, opts) {
3080
3490
  if (!target) {
3081
3491
  const config2 = await loadConfig();
@@ -3693,7 +4103,8 @@ async function parseTypedArg2(meta, entry, arg) {
3693
4103
  const matched = variants.find((v) => v.toLowerCase() === arg.toLowerCase());
3694
4104
  if (matched) {
3695
4105
  const variant = entry.value[matched];
3696
- if (variant.type === "void") {
4106
+ const resolved = variant.type === "lookupEntry" ? variant.value : variant;
4107
+ if (resolved.type === "void") {
3697
4108
  return { type: matched };
3698
4109
  }
3699
4110
  }
@@ -3865,6 +4276,7 @@ function watchTransaction(observable) {
3865
4276
  }
3866
4277
 
3867
4278
  // src/config/store.ts
4279
+ init_types();
3868
4280
  import { access as access3, mkdir as mkdir3, readFile as readFile3, rm as rm2, writeFile as writeFile3 } from "node:fs/promises";
3869
4281
  import { homedir as homedir2 } from "node:os";
3870
4282
  import { join as join3 } from "node:path";
@@ -3901,6 +4313,7 @@ async function saveConfig2(config) {
3901
4313
  }
3902
4314
 
3903
4315
  // src/core/update-notifier.ts
4316
+ init_store();
3904
4317
  import { readFileSync } from "node:fs";
3905
4318
  import { mkdir as mkdir4, writeFile as writeFile4 } from "node:fs/promises";
3906
4319
  import { join as join4 } from "node:path";
@@ -4089,159 +4502,180 @@ function parseDotPath(input, knownChains = []) {
4089
4502
  }
4090
4503
 
4091
4504
  // src/cli.ts
4092
- startBackgroundCheck(version);
4093
- var cli = cac("dot");
4094
- cli.option("--chain <name>", "Target chain (default from config)");
4095
- cli.option("--rpc <url>", "Override RPC endpoint for this call");
4096
- cli.option("--light-client", "Use Smoldot light client instead of WebSocket");
4097
- cli.option("--output <format>", "Output format: pretty or json", {
4098
- default: "pretty"
4099
- });
4100
- registerChainCommands(cli);
4101
- registerInspectCommand(cli);
4102
- registerAccountCommands(cli);
4103
- registerHashCommand(cli);
4104
- cli.command("[dotpath] [...args]").option("--from <name>", "Account to sign with (for tx)").option("--dry-run", "Estimate fees without submitting (for tx)").option("--encode", "Encode call to hex without signing (for tx)").option("--ext <json>", "Custom signed extension values as JSON (for tx)").option("--limit <n>", "Max entries to return for map queries (0 = unlimited)", {
4105
- default: 100
4106
- }).action(async (dotpath, args, opts) => {
4107
- if (!dotpath) {
4108
- printHelp();
4109
- return;
4110
- }
4111
- const config = await loadConfig2();
4112
- const knownChains = Object.keys(config.chains);
4113
- let parsed;
4114
- try {
4115
- parsed = parseDotPath(dotpath, knownChains);
4116
- } catch {
4117
- throw new CliError2(`Unknown command "${dotpath}". Run "dot --help" for available commands.`);
4118
- }
4119
- if (parsed.chain && opts.chain) {
4120
- throw new CliError2(`Chain specified both as prefix ("${parsed.chain}") and as --chain flag ("${opts.chain}"). Use one or the other.`);
4121
- }
4122
- const effectiveChain = parsed.chain ?? opts.chain;
4123
- const handlerOpts = { chain: effectiveChain, rpc: opts.rpc, output: opts.output };
4124
- const target = parsed.pallet ? parsed.item ? `${parsed.pallet}.${parsed.item}` : parsed.pallet : undefined;
4125
- if (cli.options.help && parsed.pallet && parsed.item) {
4126
- await showItemHelp2(parsed.category, target, handlerOpts);
4127
- return;
4128
- }
4129
- switch (parsed.category) {
4130
- case "query":
4131
- await handleQuery(target, args, { ...handlerOpts, limit: opts.limit });
4132
- break;
4133
- case "tx":
4134
- if (parsed.pallet && /^0x[0-9a-fA-F]+$/.test(parsed.pallet)) {
4135
- await handleTx(parsed.pallet, args, {
4136
- ...handlerOpts,
4137
- from: opts.from,
4138
- dryRun: opts.dryRun,
4139
- encode: opts.encode,
4140
- ext: opts.ext
4141
- });
4142
- } else {
4143
- await handleTx(target, args, {
4144
- ...handlerOpts,
4145
- from: opts.from,
4146
- dryRun: opts.dryRun,
4147
- encode: opts.encode,
4148
- ext: opts.ext
4149
- });
4505
+ if (process.argv[2] === "__complete") {
4506
+ (async () => {
4507
+ try {
4508
+ const dashDashIndex = process.argv.indexOf("--");
4509
+ const completionArgs = dashDashIndex >= 0 ? process.argv.slice(dashDashIndex + 1) : [];
4510
+ const currentWord = completionArgs[0] ?? "";
4511
+ const precedingWords = completionArgs.slice(1);
4512
+ const { generateCompletions: generateCompletions2 } = await Promise.resolve().then(() => (init_complete(), exports_complete));
4513
+ const results = await generateCompletions2(currentWord, precedingWords);
4514
+ if (results.length > 0) {
4515
+ process.stdout.write(`${results.join(`
4516
+ `)}
4517
+ `);
4150
4518
  }
4151
- break;
4152
- case "const":
4153
- await handleConst(target, handlerOpts);
4154
- break;
4155
- case "events":
4156
- await handleEvents2(target, handlerOpts);
4157
- break;
4158
- case "errors":
4159
- await handleErrors2(target, handlerOpts);
4160
- break;
4161
- }
4162
- });
4163
- cli.option("--help, -h", "Display this message");
4164
- cli.version(version);
4165
- function printHelp() {
4166
- console.log(`dot/${version} \u2014 Polkadot CLI`);
4167
- console.log();
4168
- console.log("Usage:");
4169
- console.log(" dot <category>[.Pallet[.Item]] [args] [options]");
4170
- console.log(" dot [Chain.]<category>[.Pallet[.Item]] [args] [options]");
4171
- console.log();
4172
- console.log("Categories:");
4173
- console.log(" query Query on-chain storage");
4174
- console.log(" tx Submit an extrinsic");
4175
- console.log(" const Look up or list pallet constants");
4176
- console.log(" events List or inspect pallet events");
4177
- console.log(" errors List or inspect pallet errors");
4178
- console.log();
4179
- console.log("Examples:");
4180
- console.log(" dot query.System.Account <addr> Query a storage item");
4181
- console.log(" dot query.System List storage items in System");
4182
- console.log(" dot tx.System.remark 0xdead --from alice");
4183
- console.log(" dot const.Balances.ExistentialDeposit");
4184
- console.log(" dot events.Balances List events in Balances");
4185
- console.log(" dot polkadot.query.System.Number With chain prefix");
4186
- console.log();
4187
- console.log("Commands:");
4188
- console.log(" inspect [target] Inspect chain metadata (alias: explore)");
4189
- console.log(" chain Manage chain configurations");
4190
- console.log(" account Manage accounts");
4191
- console.log(" hash Hash utilities");
4192
- console.log();
4193
- console.log("Global options:");
4194
- console.log(" --chain <name> Target chain (default from config)");
4195
- console.log(" --rpc <url> Override RPC endpoint");
4196
- console.log(" --light-client Use Smoldot light client");
4197
- console.log(" --output <format> Output format: pretty or json");
4198
- console.log(" --help, -h Display this message");
4199
- console.log(" --version Show version");
4200
- }
4201
- async function showUpdateAndExit(code) {
4202
- await waitForPendingCheck();
4203
- const note = getUpdateNotification(version);
4204
- if (note)
4205
- process.stderr.write(`${note}
4519
+ } catch {}
4520
+ process.exit(0);
4521
+ })();
4522
+ } else {
4523
+ let printHelp = function() {
4524
+ console.log(`dot/${version} \u2014 Polkadot CLI`);
4525
+ console.log();
4526
+ console.log("Usage:");
4527
+ console.log(" dot <category>[.Pallet[.Item]] [args] [options]");
4528
+ console.log(" dot [Chain.]<category>[.Pallet[.Item]] [args] [options]");
4529
+ console.log();
4530
+ console.log("Categories:");
4531
+ console.log(" query Query on-chain storage");
4532
+ console.log(" tx Submit an extrinsic");
4533
+ console.log(" const Look up or list pallet constants");
4534
+ console.log(" events List or inspect pallet events");
4535
+ console.log(" errors List or inspect pallet errors");
4536
+ console.log();
4537
+ console.log("Examples:");
4538
+ console.log(" dot query.System.Account <addr> Query a storage item");
4539
+ console.log(" dot query.System List storage items in System");
4540
+ console.log(" dot tx.System.remark 0xdead --from alice");
4541
+ console.log(" dot const.Balances.ExistentialDeposit");
4542
+ console.log(" dot events.Balances List events in Balances");
4543
+ console.log(" dot polkadot.query.System.Number With chain prefix");
4544
+ console.log();
4545
+ console.log("Commands:");
4546
+ console.log(" inspect [target] Inspect chain metadata (alias: explore)");
4547
+ console.log(" chain Manage chain configurations");
4548
+ console.log(" account Manage accounts");
4549
+ console.log(" hash Hash utilities");
4550
+ console.log(" completions <sh> Generate shell completions (zsh, bash, fish)");
4551
+ console.log();
4552
+ console.log("Global options:");
4553
+ console.log(" --chain <name> Target chain (default from config)");
4554
+ console.log(" --rpc <url> Override RPC endpoint");
4555
+ console.log(" --light-client Use Smoldot light client");
4556
+ console.log(" --output <format> Output format: pretty or json");
4557
+ console.log(" --help, -h Display this message");
4558
+ console.log(" --version Show version");
4559
+ };
4560
+ startBackgroundCheck(version);
4561
+ const cli = cac("dot");
4562
+ cli.option("--chain <name>", "Target chain (default from config)");
4563
+ cli.option("--rpc <url>", "Override RPC endpoint for this call");
4564
+ cli.option("--light-client", "Use Smoldot light client instead of WebSocket");
4565
+ cli.option("--output <format>", "Output format: pretty or json", {
4566
+ default: "pretty"
4567
+ });
4568
+ registerChainCommands(cli);
4569
+ registerInspectCommand(cli);
4570
+ registerAccountCommands(cli);
4571
+ registerHashCommand(cli);
4572
+ registerCompletionsCommand(cli);
4573
+ cli.command("[dotpath] [...args]").option("--from <name>", "Account to sign with (for tx)").option("--dry-run", "Estimate fees without submitting (for tx)").option("--encode", "Encode call to hex without signing (for tx)").option("--ext <json>", "Custom signed extension values as JSON (for tx)").option("--limit <n>", "Max entries to return for map queries (0 = unlimited)", {
4574
+ default: 100
4575
+ }).option("--dump", "Dump all entries of a storage map (without specifying a key)").action(async (dotpath, args, opts) => {
4576
+ if (!dotpath) {
4577
+ printHelp();
4578
+ return;
4579
+ }
4580
+ const config = await loadConfig2();
4581
+ const knownChains = Object.keys(config.chains);
4582
+ let parsed;
4583
+ try {
4584
+ parsed = parseDotPath(dotpath, knownChains);
4585
+ } catch {
4586
+ throw new CliError2(`Unknown command "${dotpath}". Run "dot --help" for available commands.`);
4587
+ }
4588
+ if (parsed.chain && opts.chain) {
4589
+ throw new CliError2(`Chain specified both as prefix ("${parsed.chain}") and as --chain flag ("${opts.chain}"). Use one or the other.`);
4590
+ }
4591
+ const effectiveChain = parsed.chain ?? opts.chain;
4592
+ const handlerOpts = { chain: effectiveChain, rpc: opts.rpc, output: opts.output };
4593
+ const target = parsed.pallet ? parsed.item ? `${parsed.pallet}.${parsed.item}` : parsed.pallet : undefined;
4594
+ if (cli.options.help && parsed.pallet && parsed.item) {
4595
+ await showItemHelp2(parsed.category, target, handlerOpts);
4596
+ return;
4597
+ }
4598
+ switch (parsed.category) {
4599
+ case "query":
4600
+ await handleQuery(target, args, { ...handlerOpts, limit: opts.limit, dump: opts.dump });
4601
+ break;
4602
+ case "tx":
4603
+ if (parsed.pallet && /^0x[0-9a-fA-F]+$/.test(parsed.pallet)) {
4604
+ await handleTx(parsed.pallet, args, {
4605
+ ...handlerOpts,
4606
+ from: opts.from,
4607
+ dryRun: opts.dryRun,
4608
+ encode: opts.encode,
4609
+ ext: opts.ext
4610
+ });
4611
+ } else {
4612
+ await handleTx(target, args, {
4613
+ ...handlerOpts,
4614
+ from: opts.from,
4615
+ dryRun: opts.dryRun,
4616
+ encode: opts.encode,
4617
+ ext: opts.ext
4618
+ });
4619
+ }
4620
+ break;
4621
+ case "const":
4622
+ await handleConst(target, handlerOpts);
4623
+ break;
4624
+ case "events":
4625
+ await handleEvents2(target, handlerOpts);
4626
+ break;
4627
+ case "errors":
4628
+ await handleErrors2(target, handlerOpts);
4629
+ break;
4630
+ }
4631
+ });
4632
+ cli.option("--help, -h", "Display this message");
4633
+ cli.version(version);
4634
+ async function showUpdateAndExit(code) {
4635
+ await waitForPendingCheck();
4636
+ const note = getUpdateNotification(version);
4637
+ if (note)
4638
+ process.stderr.write(`${note}
4206
4639
  `);
4207
- process.exit(code);
4208
- }
4209
- async function handleError(err) {
4210
- if (err instanceof CliError2) {
4211
- console.error(`Error: ${err.message}`);
4212
- } else if (err instanceof Error) {
4213
- console.error(`Error: ${err.message}`);
4214
- } else {
4215
- console.error("An unexpected error occurred:", err);
4640
+ process.exit(code);
4216
4641
  }
4217
- return showUpdateAndExit(1);
4218
- }
4219
- async function main() {
4220
- try {
4221
- cli.parse(process.argv, { run: false });
4222
- if (cli.options.version) {
4223
- await showUpdateAndExit(0);
4224
- } else if (cli.options.help) {
4225
- if (cli.matchedCommand) {
4642
+ async function handleError(err) {
4643
+ if (err instanceof CliError2) {
4644
+ console.error(`Error: ${err.message}`);
4645
+ } else if (err instanceof Error) {
4646
+ console.error(`Error: ${err.message}`);
4647
+ } else {
4648
+ console.error("An unexpected error occurred:", err);
4649
+ }
4650
+ return showUpdateAndExit(1);
4651
+ }
4652
+ async function main() {
4653
+ try {
4654
+ cli.parse(process.argv, { run: false });
4655
+ if (cli.options.version) {
4656
+ await showUpdateAndExit(0);
4657
+ } else if (cli.options.help) {
4658
+ if (cli.matchedCommand) {
4659
+ const result = cli.runMatchedCommand();
4660
+ if (result && typeof result.then === "function") {
4661
+ await result.then(() => showUpdateAndExit(0), handleError);
4662
+ }
4663
+ } else {
4664
+ printHelp();
4665
+ await showUpdateAndExit(0);
4666
+ }
4667
+ } else if (!cli.matchedCommand) {
4668
+ printHelp();
4669
+ await showUpdateAndExit(0);
4670
+ } else {
4226
4671
  const result = cli.runMatchedCommand();
4227
4672
  if (result && typeof result.then === "function") {
4228
4673
  await result.then(() => showUpdateAndExit(0), handleError);
4229
4674
  }
4230
- } else {
4231
- printHelp();
4232
- await showUpdateAndExit(0);
4233
- }
4234
- } else if (!cli.matchedCommand) {
4235
- printHelp();
4236
- await showUpdateAndExit(0);
4237
- } else {
4238
- const result = cli.runMatchedCommand();
4239
- if (result && typeof result.then === "function") {
4240
- await result.then(() => showUpdateAndExit(0), handleError);
4241
4675
  }
4676
+ } catch (err) {
4677
+ await handleError(err);
4242
4678
  }
4243
- } catch (err) {
4244
- await handleError(err);
4245
4679
  }
4680
+ main();
4246
4681
  }
4247
- main();