polkadot-cli 0.2.1 → 0.5.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 +64 -37
  2. package/dist/cli.mjs +301 -44
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # polkadot-cli
2
2
 
3
- A command-line tool for interacting with Polkadot-ecosystem chains. Query storage, look up constants, inspect metadata, manage accounts, and submit extrinsics — all from your terminal.
3
+ A command-line tool for interacting with Polkadot-ecosystem chains. Manage chains and accounts, query storage, look up constants, inspect metadata, and submit extrinsics — all from your terminal.
4
4
 
5
5
  Ships with Polkadot as the default chain. Add any Substrate-based chain by pointing to its RPC endpoint.
6
6
 
@@ -14,6 +14,48 @@ This installs the `dot` command globally.
14
14
 
15
15
  ## Usage
16
16
 
17
+ ### Manage chains
18
+
19
+ ```bash
20
+ # Add a chain
21
+ dot chain add kusama --rpc wss://kusama-rpc.polkadot.io
22
+ dot chain add westend --light-client
23
+
24
+ # List configured chains
25
+ dot chain list
26
+
27
+ # Re-fetch metadata after a runtime upgrade
28
+ dot chain update # updates default chain
29
+ dot chain update kusama # updates a specific chain
30
+
31
+ # Set default chain
32
+ dot chain default kusama
33
+
34
+ # Remove a chain
35
+ dot chain remove westend
36
+ ```
37
+
38
+ ### Manage accounts
39
+
40
+ Dev accounts (Alice, Bob, Charlie, Dave, Eve, Ferdie) are always available for testnets. Create or import your own accounts for any chain.
41
+
42
+ ```bash
43
+ # List all accounts (dev + stored)
44
+ dot account list
45
+
46
+ # Create a new account (generates a mnemonic)
47
+ dot account create my-validator
48
+
49
+ # Import from a BIP39 mnemonic
50
+ dot account import treasury --secret "word1 word2 ... word12"
51
+
52
+ # Import from a hex seed
53
+ dot account import raw-key --secret 0xabcdef...
54
+
55
+ # Remove an account
56
+ dot account remove my-validator
57
+ ```
58
+
17
59
  ### Query storage
18
60
 
19
61
  ```bash
@@ -52,30 +94,9 @@ dot inspect System
52
94
  dot inspect System.Account
53
95
  ```
54
96
 
55
- ### Manage accounts
56
-
57
- Dev accounts (Alice, Bob, Charlie, Dave, Eve, Ferdie) are always available for testnets. Create or import your own accounts for any chain.
58
-
59
- ```bash
60
- # List all accounts (dev + stored)
61
- dot account list
62
-
63
- # Create a new account (generates a mnemonic)
64
- dot account create my-validator
65
-
66
- # Import from a BIP39 mnemonic
67
- dot account import treasury --secret "word1 word2 ... word12"
68
-
69
- # Import from a hex seed
70
- dot account import raw-key --secret 0xabcdef...
71
-
72
- # Remove an account
73
- dot account remove my-validator
74
- ```
75
-
76
97
  ### Submit extrinsics
77
98
 
78
- Build, sign, and submit transactions. Arguments are parsed from metadata the CLI knows the expected types for each call.
99
+ Build, sign, and submit transactions. Pass a `Pallet.Call` with arguments, or a raw SCALE-encoded call hex (e.g. from a multisig proposal or governance). Both forms display a decoded human-readable representation of the call.
79
100
 
80
101
  ```bash
81
102
  # Simple remark
@@ -87,29 +108,35 @@ dot tx Balances.transferKeepAlive 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694
87
108
  # Estimate fees without submitting
88
109
  dot tx Balances.transferKeepAlive 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty 1000000000000 --from alice --dry-run
89
110
 
111
+ # Submit a raw SCALE-encoded call (e.g. from a multisig proposal or another tool)
112
+ dot tx 0x0503008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 --from alice
113
+
90
114
  # Batch multiple transfers with Utility.batchAll
91
115
  dot tx Utility.batchAll '[{"type":"Balances","value":{"type":"transfer_keep_alive","value":{"dest":"5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty","value":1000000000000}}},{"type":"Balances","value":{"type":"transfer_keep_alive","value":{"dest":"5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y","value":2000000000000}}}]' --from alice
92
116
  ```
93
117
 
94
- ### Manage chains
118
+ Both dry-run and submission display the encoded call hex and a decoded human-readable form:
95
119
 
96
- ```bash
97
- # Add a chain
98
- dot chain add kusama --rpc wss://kusama-rpc.polkadot.io
99
- dot chain add westend --light-client
120
+ ```
121
+ Call: 0x0001076465616462656566
122
+ Decode: System.remark(remark: 0xdeadbeef)
123
+ Tx: 0xabc123...
124
+ Block: #12345678 (0xdef...)
125
+ Status: ok
126
+ ```
100
127
 
101
- # List configured chains
102
- dot chain list
128
+ #### Custom signed extensions
103
129
 
104
- # Re-fetch metadata after a runtime upgrade
105
- dot chain update # updates default chain
106
- dot chain update kusama # updates a specific chain
130
+ Chains with non-standard signed extensions (e.g. `people-preview`) are auto-handled:
107
131
 
108
- # Set default chain
109
- dot chain default kusama
132
+ - `void` empty bytes
133
+ - `Option<T>` `None`
134
+ - enum with `Disabled` variant → `Disabled`
110
135
 
111
- # Remove a chain
112
- dot chain remove westend
136
+ For manual override, use `--ext` with a JSON object:
137
+
138
+ ```bash
139
+ dot tx System.remark 0xdeadbeef --from alice --ext '{"MyExtension":{"value":"..."}}'
113
140
  ```
114
141
 
115
142
  ### Global options
package/dist/cli.mjs CHANGED
@@ -1,21 +1,5 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
- var __create = Object.create;
4
- var __getProtoOf = Object.getPrototypeOf;
5
- var __defProp = Object.defineProperty;
6
- var __getOwnPropNames = Object.getOwnPropertyNames;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __toESM = (mod, isNodeMode, target) => {
9
- target = mod != null ? __create(__getProtoOf(mod)) : {};
10
- const to = isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target;
11
- for (let key of __getOwnPropNames(mod))
12
- if (!__hasOwnProp.call(to, key))
13
- __defProp(to, key, {
14
- get: () => mod[key],
15
- enumerable: true
16
- });
17
- return to;
18
- };
19
3
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
20
4
 
21
5
  // src/cli.ts
@@ -275,6 +259,13 @@ function findPallet(meta, palletName) {
275
259
  const pallets = listPallets(meta);
276
260
  return pallets.find((p) => p.name.toLowerCase() === palletName.toLowerCase());
277
261
  }
262
+ function getSignedExtensions(meta) {
263
+ const byVersion = meta.unified.extrinsic.signedExtensions;
264
+ const versionKeys = Object.keys(byVersion);
265
+ if (versionKeys.length === 0)
266
+ return [];
267
+ return byVersion[Number(versionKeys[0])] ?? [];
268
+ }
278
269
  function getPalletNames(meta) {
279
270
  return meta.unified.pallets.map((p) => p.name);
280
271
  }
@@ -381,6 +372,38 @@ function printDocs(docs) {
381
372
  console.log(` ${DIM}${text}${RESET}`);
382
373
  }
383
374
  }
375
+ var CHECK_MARK = "✓";
376
+ var SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
377
+
378
+ class Spinner {
379
+ timer = null;
380
+ frame = 0;
381
+ start(msg) {
382
+ this.stop();
383
+ if (!isTTY) {
384
+ console.log(msg);
385
+ return;
386
+ }
387
+ process.stdout.write(`${SPINNER_FRAMES[0]} ${msg}`);
388
+ this.timer = setInterval(() => {
389
+ this.frame = (this.frame + 1) % SPINNER_FRAMES.length;
390
+ process.stdout.write(`\r\x1B[K${SPINNER_FRAMES[this.frame]} ${msg}`);
391
+ }, 80);
392
+ }
393
+ stop() {
394
+ if (this.timer !== null) {
395
+ clearInterval(this.timer);
396
+ this.timer = null;
397
+ this.frame = 0;
398
+ if (isTTY)
399
+ process.stdout.write("\r\x1B[K");
400
+ }
401
+ }
402
+ succeed(msg) {
403
+ this.stop();
404
+ console.log(`${GREEN}${CHECK_MARK}${RESET} ${msg}`);
405
+ }
406
+ }
384
407
 
385
408
  // src/commands/chain.ts
386
409
  var CHAIN_HELP = `
@@ -1061,41 +1084,70 @@ async function accountRemove(name) {
1061
1084
 
1062
1085
  // src/commands/tx.ts
1063
1086
  import { Binary } from "polkadot-api";
1087
+ import { getViewBuilder } from "@polkadot-api/view-builder";
1088
+
1089
+ // src/core/explorers.ts
1090
+ var pjsAppsLink = (rpc, hash) => `https://polkadot.js.org/apps/?rpc=${encodeURIComponent(rpc)}#/explorer/query/${hash}`;
1091
+ var papiLink = (rpc, hash) => `https://dev.papi.how/explorer/${hash}#networkId=custom&endpoint=${encodeURIComponent(rpc)}`;
1092
+
1093
+ // src/commands/tx.ts
1064
1094
  function registerTxCommand(cli) {
1065
- cli.command("tx [target] [...args]", "Submit an extrinsic (e.g. Balances.transferKeepAlive <dest> <amount>)").option("--from <name>", "Account to sign with (required)").option("--dry-run", "Estimate fees without submitting").action(async (target, args, opts) => {
1095
+ cli.command("tx [target] [...args]", "Submit an extrinsic (e.g. Balances.transferKeepAlive <dest> <amount>)").option("--from <name>", "Account to sign with (required)").option("--dry-run", "Estimate fees without submitting").option("--ext <json>", `Custom signed extension values as JSON, e.g. '{"ExtName":{"value":...}}'`).action(async (target, args, opts) => {
1066
1096
  if (!target || !opts.from) {
1067
- console.log("Usage: dot tx <Pallet.Call> [...args] --from <account> [--dry-run]");
1097
+ console.log("Usage: dot tx <Pallet.Call|0xCallHex> [...args] --from <account> [--dry-run]");
1068
1098
  console.log("");
1069
1099
  console.log("Examples:");
1070
1100
  console.log(" $ dot tx Balances.transferKeepAlive 5FHn... 1000000000000 --from alice");
1071
1101
  console.log(" $ dot tx System.remark 0xdeadbeef --from alice --dry-run");
1102
+ console.log(" $ dot tx 0x0001076465616462656566 --from alice");
1072
1103
  return;
1073
1104
  }
1105
+ const isRawCall = /^0x[0-9a-fA-F]+$/.test(target);
1074
1106
  const config = await loadConfig();
1075
1107
  const { name: chainName, chain: chainConfig } = resolveChain(config, opts.chain);
1076
- const { pallet, item: callName } = parseTarget(target);
1077
1108
  const signer = await resolveAccountSigner(opts.from);
1078
1109
  const clientHandle = await createChainClient(chainName, chainConfig, opts.rpc);
1079
1110
  try {
1080
1111
  const meta = await getOrFetchMetadata(chainName, clientHandle);
1081
- const palletNames = getPalletNames(meta);
1082
- const palletInfo = findPallet(meta, pallet);
1083
- if (!palletInfo) {
1084
- throw new Error(suggestMessage("pallet", pallet, palletNames));
1085
- }
1086
- const callInfo = palletInfo.calls.find((c) => c.name.toLowerCase() === callName.toLowerCase());
1087
- if (!callInfo) {
1088
- const callNames = palletInfo.calls.map((c) => c.name);
1089
- throw new Error(suggestMessage(`call in ${palletInfo.name}`, callName, callNames));
1090
- }
1091
- const callData = parseCallArgs(meta, palletInfo.name, callInfo.name, args);
1112
+ const userExtOverrides = parseExtOption(opts.ext);
1113
+ const customSignedExtensions = buildCustomSignedExtensions(meta, userExtOverrides);
1114
+ const txOptions = Object.keys(customSignedExtensions).length > 0 ? { customSignedExtensions } : undefined;
1092
1115
  const unsafeApi = clientHandle.client.getUnsafeApi();
1093
- const tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
1116
+ let tx;
1117
+ let callHex;
1118
+ if (isRawCall) {
1119
+ if (args.length > 0) {
1120
+ throw new Error(`Extra arguments are not allowed when submitting a raw call hex.
1121
+ ` + "Usage: dot tx 0x<call_hex> --from <account>");
1122
+ }
1123
+ const callBinary = Binary.fromHex(target);
1124
+ tx = await unsafeApi.txFromCallData(callBinary);
1125
+ callHex = target;
1126
+ } else {
1127
+ const { pallet, item: callName } = parseTarget(target);
1128
+ const palletNames = getPalletNames(meta);
1129
+ const palletInfo = findPallet(meta, pallet);
1130
+ if (!palletInfo) {
1131
+ throw new Error(suggestMessage("pallet", pallet, palletNames));
1132
+ }
1133
+ const callInfo = palletInfo.calls.find((c) => c.name.toLowerCase() === callName.toLowerCase());
1134
+ if (!callInfo) {
1135
+ const callNames = palletInfo.calls.map((c) => c.name);
1136
+ throw new Error(suggestMessage(`call in ${palletInfo.name}`, callName, callNames));
1137
+ }
1138
+ const callData = parseCallArgs(meta, palletInfo.name, callInfo.name, args);
1139
+ tx = unsafeApi.tx[palletInfo.name][callInfo.name](callData);
1140
+ const encodedCall = await tx.getEncodedData();
1141
+ callHex = encodedCall.asHex();
1142
+ }
1143
+ const decodedStr = decodeCall(meta, callHex);
1094
1144
  if (opts.dryRun) {
1095
1145
  const signerAddress = toSs58(signer.publicKey);
1096
- console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
1146
+ console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
1147
+ console.log(` ${BOLD}Call:${RESET} ${callHex}`);
1148
+ console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
1097
1149
  try {
1098
- const fees = await tx.getEstimatedFees(signer.publicKey);
1150
+ const fees = await tx.getEstimatedFees(signer.publicKey, txOptions);
1099
1151
  console.log(` ${BOLD}Estimated fees:${RESET} ${fees}`);
1100
1152
  } catch (err) {
1101
1153
  console.log(` ${BOLD}Estimated fees:${RESET} ${YELLOW}unable to estimate${RESET}`);
@@ -1103,18 +1155,17 @@ function registerTxCommand(cli) {
1103
1155
  }
1104
1156
  return;
1105
1157
  }
1106
- console.log("Signing and submitting...");
1107
- const result = await tx.signAndSubmit(signer);
1158
+ const result = await watchTransaction(tx.signSubmitAndWatch(signer, txOptions));
1108
1159
  console.log();
1160
+ console.log(` ${BOLD}Call:${RESET} ${callHex}`);
1161
+ console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
1109
1162
  console.log(` ${BOLD}Tx:${RESET} ${result.txHash}`);
1110
- if (result.block) {
1111
- console.log(` ${BOLD}Block:${RESET} #${result.block.number} (${result.block.hash})`);
1112
- }
1113
- if (result.dispatchError) {
1163
+ console.log(` ${BOLD}Block:${RESET} #${result.block.number} (${result.block.hash})`);
1164
+ if (result.ok) {
1165
+ console.log(` ${BOLD}Status:${RESET} ${GREEN}ok${RESET}`);
1166
+ } else {
1114
1167
  console.log(` ${BOLD}Status:${RESET} ${YELLOW}dispatch error${RESET}`);
1115
1168
  console.log(` ${BOLD}Error:${RESET} ${result.dispatchError.type}${result.dispatchError.value ? ": " + JSON.stringify(result.dispatchError.value) : ""}`);
1116
- } else {
1117
- console.log(` ${BOLD}Status:${RESET} ${GREEN}ok${RESET}`);
1118
1169
  }
1119
1170
  if (result.events && result.events.length > 0) {
1120
1171
  console.log(` ${BOLD}Events:${RESET}`);
@@ -1129,12 +1180,108 @@ function registerTxCommand(cli) {
1129
1180
  }
1130
1181
  }
1131
1182
  }
1183
+ const rpcUrl = opts.rpc ?? chainConfig.rpc;
1184
+ if (rpcUrl) {
1185
+ const blockHash = result.block.hash;
1186
+ console.log(` ${BOLD}Explorer:${RESET}`);
1187
+ console.log(` ${DIM}PolkadotJS${RESET} ${pjsAppsLink(rpcUrl, blockHash)}`);
1188
+ console.log(` ${DIM}PAPI${RESET} ${papiLink(rpcUrl, blockHash)}`);
1189
+ }
1132
1190
  console.log();
1133
1191
  } finally {
1134
1192
  clientHandle.destroy();
1135
1193
  }
1136
1194
  });
1137
1195
  }
1196
+ function decodeCall(meta, callHex) {
1197
+ try {
1198
+ const viewBuilder = getViewBuilder(meta.lookup);
1199
+ const decoded = viewBuilder.callDecoder(callHex);
1200
+ const palletName = decoded.pallet.value.name;
1201
+ const callName = decoded.call.value.name;
1202
+ const argsStr = formatDecodedArgs(decoded.args.value);
1203
+ return `${palletName}.${callName}${argsStr}`;
1204
+ } catch {
1205
+ return "(unable to decode)";
1206
+ }
1207
+ }
1208
+ function formatDecodedArgs(decoded) {
1209
+ return formatDecoded(decoded);
1210
+ }
1211
+ function formatDecoded(d) {
1212
+ switch (d.codec) {
1213
+ case "_void":
1214
+ return "";
1215
+ case "bool":
1216
+ return d.value.toString();
1217
+ case "str":
1218
+ case "char":
1219
+ return d.value;
1220
+ case "u8":
1221
+ case "u16":
1222
+ case "u32":
1223
+ case "i8":
1224
+ case "i16":
1225
+ case "i32":
1226
+ case "compactNumber":
1227
+ return d.value.toString();
1228
+ case "u64":
1229
+ case "u128":
1230
+ case "u256":
1231
+ case "i64":
1232
+ case "i128":
1233
+ case "i256":
1234
+ case "compactBn":
1235
+ return d.value.toString();
1236
+ case "bitSequence":
1237
+ return `0x${Buffer.from(d.value.bytes).toString("hex")}`;
1238
+ case "AccountId":
1239
+ return d.value.address;
1240
+ case "ethAccount":
1241
+ return d.value;
1242
+ case "Bytes":
1243
+ return d.value;
1244
+ case "BytesArray":
1245
+ return d.value;
1246
+ case "Enum": {
1247
+ const inner = formatDecoded(d.value.value);
1248
+ if (!inner)
1249
+ return d.value.type;
1250
+ return `${d.value.type}(${inner})`;
1251
+ }
1252
+ case "Struct": {
1253
+ const entries = Object.entries(d.value);
1254
+ if (entries.length === 0)
1255
+ return " {}";
1256
+ const fields = entries.map(([k, v]) => `${k}: ${formatDecoded(v)}`).join(", ");
1257
+ return ` { ${fields} }`;
1258
+ }
1259
+ case "Tuple": {
1260
+ const items = d.value.map(formatDecoded).join(", ");
1261
+ return `(${items})`;
1262
+ }
1263
+ case "Option": {
1264
+ if (d.value.codec === "_void")
1265
+ return "None";
1266
+ return formatDecoded(d.value);
1267
+ }
1268
+ case "Result": {
1269
+ if (d.value.success) {
1270
+ return `Ok(${formatDecoded(d.value.value)})`;
1271
+ }
1272
+ return `Err(${formatDecoded(d.value.value)})`;
1273
+ }
1274
+ case "Sequence":
1275
+ case "Array": {
1276
+ const items = d.value.map(formatDecoded);
1277
+ if (items.length === 0)
1278
+ return "[]";
1279
+ return `[${items.join(", ")}]`;
1280
+ }
1281
+ default:
1282
+ return String(d.value ?? "");
1283
+ }
1284
+ }
1138
1285
  function formatEventValue(v) {
1139
1286
  if (typeof v === "bigint")
1140
1287
  return v.toString();
@@ -1301,6 +1448,110 @@ function parsePrimitive(prim, arg) {
1301
1448
  return parseValue(arg);
1302
1449
  }
1303
1450
  }
1451
+ var PAPI_BUILTIN_EXTENSIONS = new Set([
1452
+ "CheckNonZeroSender",
1453
+ "CheckSpecVersion",
1454
+ "CheckTxVersion",
1455
+ "CheckGenesis",
1456
+ "CheckMortality",
1457
+ "CheckNonce",
1458
+ "CheckWeight",
1459
+ "ChargeTransactionPayment",
1460
+ "ChargeAssetTxPayment",
1461
+ "CheckMetadataHash",
1462
+ "StorageWeightReclaim",
1463
+ "PrevalidateAttests"
1464
+ ]);
1465
+ function parseExtOption(ext) {
1466
+ if (!ext)
1467
+ return {};
1468
+ try {
1469
+ const parsed = JSON.parse(ext);
1470
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
1471
+ throw new Error(`--ext must be a JSON object, e.g. '{"ExtName":{"value":...}}'`);
1472
+ }
1473
+ return parsed;
1474
+ } catch (err) {
1475
+ if (err.message?.startsWith("--ext"))
1476
+ throw err;
1477
+ throw new Error(`Failed to parse --ext JSON: ${err.message}
1478
+ ` + `Expected format: '{"ExtName":{"value":...}}'`);
1479
+ }
1480
+ }
1481
+ var NO_DEFAULT = Symbol("no-default");
1482
+ function buildCustomSignedExtensions(meta, userOverrides) {
1483
+ const result = {};
1484
+ const extensions = getSignedExtensions(meta);
1485
+ for (const ext of extensions) {
1486
+ if (PAPI_BUILTIN_EXTENSIONS.has(ext.identifier))
1487
+ continue;
1488
+ if (ext.identifier in userOverrides) {
1489
+ result[ext.identifier] = userOverrides[ext.identifier];
1490
+ continue;
1491
+ }
1492
+ const valueEntry = meta.lookup(ext.type);
1493
+ const addEntry = meta.lookup(ext.additionalSigned);
1494
+ const value = autoDefaultForType(valueEntry);
1495
+ const add = autoDefaultForType(addEntry);
1496
+ if (value !== NO_DEFAULT || add !== NO_DEFAULT) {
1497
+ result[ext.identifier] = {
1498
+ ...value !== NO_DEFAULT ? { value } : {},
1499
+ ...add !== NO_DEFAULT ? { additionalSigned: add } : {}
1500
+ };
1501
+ }
1502
+ }
1503
+ return result;
1504
+ }
1505
+ function autoDefaultForType(entry) {
1506
+ if (entry.type === "void")
1507
+ return new Uint8Array([]);
1508
+ if (entry.type === "option")
1509
+ return;
1510
+ if (entry.type === "enum") {
1511
+ const variants = entry.value;
1512
+ if ("Disabled" in variants) {
1513
+ return { type: "Disabled", value: undefined };
1514
+ }
1515
+ }
1516
+ return NO_DEFAULT;
1517
+ }
1518
+ function watchTransaction(observable) {
1519
+ const spinner = new Spinner;
1520
+ return new Promise((resolve, reject) => {
1521
+ spinner.start("Signing...");
1522
+ observable.subscribe({
1523
+ next(event) {
1524
+ switch (event.type) {
1525
+ case "signed":
1526
+ spinner.succeed("Signed");
1527
+ console.log(` ${BOLD}Tx:${RESET} ${event.txHash}`);
1528
+ spinner.start("Broadcasting...");
1529
+ break;
1530
+ case "broadcasted":
1531
+ spinner.succeed("Broadcasted");
1532
+ spinner.start("In best block...");
1533
+ break;
1534
+ case "txBestBlocksState":
1535
+ if (event.found) {
1536
+ spinner.succeed(`In best block #${event.block.number}`);
1537
+ spinner.start("Finalizing...");
1538
+ } else {
1539
+ spinner.start("In best block...");
1540
+ }
1541
+ break;
1542
+ case "finalized":
1543
+ spinner.stop();
1544
+ resolve(event);
1545
+ break;
1546
+ }
1547
+ },
1548
+ error(err) {
1549
+ spinner.stop();
1550
+ reject(err);
1551
+ }
1552
+ });
1553
+ });
1554
+ }
1304
1555
 
1305
1556
  // src/utils/errors.ts
1306
1557
  class CliError2 extends Error {
@@ -1309,6 +1560,8 @@ class CliError2 extends Error {
1309
1560
  this.name = "CliError";
1310
1561
  }
1311
1562
  }
1563
+ // package.json
1564
+ var version = "0.5.0";
1312
1565
 
1313
1566
  // src/cli.ts
1314
1567
  var cli = cac("dot");
@@ -1325,7 +1578,7 @@ registerConstCommand(cli);
1325
1578
  registerAccountCommands(cli);
1326
1579
  registerTxCommand(cli);
1327
1580
  cli.help();
1328
- cli.version("0.2.1");
1581
+ cli.version(version);
1329
1582
  function handleError(err) {
1330
1583
  if (err instanceof CliError2) {
1331
1584
  console.error(`Error: ${err.message}`);
@@ -1336,11 +1589,15 @@ function handleError(err) {
1336
1589
  }
1337
1590
  process.exit(1);
1338
1591
  }
1339
- process.on("unhandledRejection", handleError);
1340
1592
  try {
1341
- cli.parse();
1593
+ cli.parse(process.argv, { run: false });
1342
1594
  if (!cli.matchedCommandName && !cli.options.help && !cli.options.version) {
1343
1595
  cli.outputHelp();
1596
+ } else {
1597
+ const result = cli.runMatchedCommand();
1598
+ if (result && typeof result.then === "function") {
1599
+ result.then(() => process.exit(0), handleError);
1600
+ }
1344
1601
  }
1345
1602
  } catch (err) {
1346
1603
  handleError(err);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polkadot-cli",
3
- "version": "0.2.1",
3
+ "version": "0.5.0",
4
4
  "description": "CLI tool for querying Polkadot-ecosystem on-chain state",
5
5
  "type": "module",
6
6
  "bin": {