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.
- package/README.md +39 -3
- package/dist/cli.mjs +1153 -719
- 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
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
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
|
-
|
|
135
|
+
};
|
|
136
|
+
BUILTIN_CHAIN_NAMES = new Set(Object.keys(DEFAULT_CONFIG.chains));
|
|
137
|
+
});
|
|
134
138
|
|
|
135
139
|
// src/config/store.ts
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
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
|
-
|
|
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/
|
|
370
|
-
|
|
371
|
-
var
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
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
|
|
392
|
-
|
|
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
|
|
395
|
-
|
|
396
|
-
if (!
|
|
397
|
-
|
|
398
|
-
|
|
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
|
|
401
|
-
return
|
|
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
|
|
404
|
-
if (
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
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
|
|
411
|
-
|
|
412
|
-
|
|
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
|
|
416
|
-
|
|
417
|
-
|
|
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
|
|
423
|
-
const
|
|
424
|
-
|
|
425
|
-
if (
|
|
426
|
-
|
|
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
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
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
|
-
|
|
442
|
-
|
|
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
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
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
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
}
|
|
903
|
-
}
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
}
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
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
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
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
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
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
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1524
|
+
});
|
|
1525
|
+
return {
|
|
1526
|
+
client,
|
|
1527
|
+
destroy: () => {
|
|
1528
|
+
client.destroy();
|
|
1529
|
+
restoreConsole();
|
|
1203
1530
|
}
|
|
1204
|
-
|
|
1205
|
-
} catch {
|
|
1206
|
-
return "";
|
|
1207
|
-
}
|
|
1531
|
+
};
|
|
1208
1532
|
}
|
|
1209
|
-
function
|
|
1210
|
-
const
|
|
1211
|
-
const
|
|
1212
|
-
|
|
1213
|
-
|
|
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
|
-
|
|
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}
|
|
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}
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
|
|
4096
|
-
|
|
4097
|
-
|
|
4098
|
-
|
|
4099
|
-
});
|
|
4100
|
-
|
|
4101
|
-
|
|
4102
|
-
|
|
4103
|
-
|
|
4104
|
-
|
|
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
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
|
|
4201
|
-
|
|
4202
|
-
|
|
4203
|
-
|
|
4204
|
-
|
|
4205
|
-
|
|
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
|
-
|
|
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
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
}
|
|
4225
|
-
|
|
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();
|