polkadot-cli 1.21.0 → 1.22.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 +47 -2
  2. package/dist/cli.mjs +110 -34
  3. package/package.json +6 -7
package/README.md CHANGED
@@ -97,7 +97,8 @@ dot chain add kusama --rpc wss://kusama-rpc.polkadot.io
97
97
  dot chain add kusama --rpc wss://kusama-rpc.polkadot.io --rpc wss://kusama-rpc.dwellir.com
98
98
 
99
99
  # Add a parachain under a relay (auto-detects parachain ID)
100
- dot chain add local-asset-hub --rpc ws://localhost:9945 --relay local-relay
100
+ # Name parachains `{relay}-{parachain}` see "Naming convention" below
101
+ dot chain add local-relay-asset-hub --rpc ws://localhost:9945 --relay local-relay
101
102
 
102
103
  # Add a parachain with explicit parachain ID
103
104
  dot chain add my-para --rpc wss://rpc.example.com --relay polkadot --parachain-id 2000
@@ -119,6 +120,24 @@ dot chain update --all # updates all configured chains in parallel
119
120
  dot chain remove kusama
120
121
  ```
121
122
 
123
+ #### Naming convention
124
+
125
+ Name chains `{relay}-{parachain}`: the parent relay's name, a hyphen, then the parachain's role. Every preconfigured chain already follows this pattern (`polkadot-asset-hub`, `polkadot-bridge-hub`, `paseo-people`, …), and reusing it for chains you add keeps the relay/parachain topology readable.
126
+
127
+ | Chain kind | Recommended name | Examples |
128
+ |------------|------------------|----------|
129
+ | Relay chain | `{relay}` | `polkadot`, `kusama`, `paseo` |
130
+ | Parachain | `{relay}-{parachain}` | `polkadot-asset-hub`, `kusama-bridge-hub`, `paseo-people` |
131
+
132
+ The relay prefix is what keeps chains distinct: parachain IDs collide across relays (Asset Hub is `1000` on both Polkadot and Paseo), so the name — not the ID — is how you select a chain (`dot polkadot-asset-hub.query…`). A relay-prefixed name also mirrors the `dot chain list` tree, which groups parachains under their relay.
133
+
134
+ ```bash
135
+ # Recommended — relay-prefixed name
136
+ dot chain add kusama-asset-hub --rpc wss://asset-hub-kusama-rpc.polkadot.io --relay kusama --parachain-id 1000
137
+ ```
138
+
139
+ Use lowercase, hyphen-separated names (chain names resolve case-insensitively).
140
+
122
141
  #### Chain topology
123
142
 
124
143
  `dot chain list` displays chains as a tree, grouping parachains under their parent relay:
@@ -297,9 +316,10 @@ dot account derive treasury treasury-staking --path //staking
297
316
  # Use it — the env var is read at signing time
298
317
  MY_SECRET="word1 word2 ..." dot polkadot.tx.System.remark 0xdead --from ci-signer
299
318
 
300
- # Remove one or more accounts
319
+ # Remove one or more accounts (delete and rm are aliases for remove)
301
320
  dot account remove my-validator
302
321
  dot account delete my-validator stale-key
322
+ dot account rm my-validator stale-key
303
323
 
304
324
  # Export accounts (secrets redacted by default)
305
325
  dot account export
@@ -1200,6 +1220,13 @@ dot polkadot.tx.Balances.transfer_keep_alive bob 1000000000000 --from alice --dr
1200
1220
  # Submit (omit --dry-run)
1201
1221
  dot polkadot.tx.System.remark 0xdeadbeef --from alice
1202
1222
 
1223
+ # Force every tx to dry-run via the global DOT_DRY_RUN env var — a safety net
1224
+ # for scripts and demos. A hint is printed to stderr; the command behaves
1225
+ # exactly as if --dry-run had been passed.
1226
+ DOT_DRY_RUN=1 dot polkadot.tx.System.remark 0xdeadbeef --from alice
1227
+ # stderr: ⚠ DOT_DRY_RUN is set — extrinsics will be simulated, not submitted.
1228
+ # stdout: (the dry-run output above — no broadcast)
1229
+
1203
1230
  # Submit a raw SCALE-encoded call (e.g. from a multisig proposal or another tool)
1204
1231
  dot polkadot.tx 0x000010deadbeef --from alice --dry-run
1205
1232
 
@@ -2192,6 +2219,24 @@ cd - && rm -rf "$tmp" # nothing ever touched ~/.polkadot
2192
2219
 
2193
2220
  For secrets that should never hit disk at all, combine workspaces with `--env` secret sources (see [Manage accounts](#manage-accounts)).
2194
2221
 
2222
+ ### `DOT_DRY_RUN` — force every extrinsic to dry-run
2223
+
2224
+ Set `DOT_DRY_RUN` to a truthy value (`1`, `true`, `yes`, or `on`, case-insensitive) to make **every** extrinsic-submitting command behave as if `--dry-run` had been passed: the transaction is simulated (call decoded, fees estimated) and **never broadcast**. This is a global safety net for scripts, demos, and CI dry-runs where you want to be sure nothing lands on-chain.
2225
+
2226
+ When active, the CLI prints a one-line hint to **stderr** (so it never corrupts `--json` or piped stdout):
2227
+
2228
+ ```bash
2229
+ DOT_DRY_RUN=1 dot polkadot.tx.Balances.transfer_keep_alive bob 1000000000000 --from alice
2230
+ # stderr: ⚠ DOT_DRY_RUN is set — extrinsics will be simulated, not submitted.
2231
+ # stdout: the usual dry-run report (Chain / From / Call / Decode / Estimated fees)
2232
+
2233
+ # Set it for a whole shell session as a safety net:
2234
+ export DOT_DRY_RUN=1
2235
+ dot polkadot.tx.System.remark 0xdeadbeef --from alice # simulated, not submitted
2236
+ ```
2237
+
2238
+ **Precedence:** an explicit per-command flag always wins. `--dry-run` forces a dry-run; `--no-dry-run` forces a real submission even when `DOT_DRY_RUN` is set. The env var only supplies the default when no flag is given. Decode-only paths (`--encode`, `--to-yaml`, `--to-json`) never submit anything, so `DOT_DRY_RUN` leaves them untouched.
2239
+
2195
2240
  ### `DOT_TRUST_CACHED_METADATA` — skip the staleness check
2196
2241
 
2197
2242
  Set `DOT_TRUST_CACHED_METADATA=1` to disable the post-failure stale-metadata check on `dot tx`, `dot tx --dry-run`, and `dot query`. When set, errors propagate exactly as the runtime / RPC reported them, with no extra `state_getRuntimeVersion` / `state_getStorageHash` round-trip. Useful in CI loops where you've just refreshed metadata manually and don't want the overhead.
package/dist/cli.mjs CHANGED
@@ -917,6 +917,31 @@ var init_output = __esm(() => {
917
917
  SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
918
918
  });
919
919
 
920
+ // src/platform/cli.ts
921
+ function withHelp(command, printHelp) {
922
+ command[HELP_PRINTER] = printHelp ?? (() => command.outputHelp());
923
+ return command;
924
+ }
925
+ function readRawOptionValue(name, argv = process.argv) {
926
+ const flag = `--${name}`;
927
+ const prefix = `${flag}=`;
928
+ let value;
929
+ for (let i = 0;i < argv.length; i++) {
930
+ const arg = argv[i];
931
+ if (arg === "--")
932
+ break;
933
+ if (arg === flag && i + 1 < argv.length)
934
+ value = argv[i + 1];
935
+ else if (arg.startsWith(prefix))
936
+ value = arg.slice(prefix.length);
937
+ }
938
+ return value;
939
+ }
940
+ var HELP_PRINTER;
941
+ var init_cli = __esm(() => {
942
+ HELP_PRINTER = Symbol.for("polkadot-cli.helpPrinter");
943
+ });
944
+
920
945
  // src/features/verifiable/lib.ts
921
946
  var exports_lib = {};
922
947
  __export(exports_lib, {
@@ -3490,23 +3515,6 @@ var init_input = __esm(() => {
3490
3515
  init_hash();
3491
3516
  });
3492
3517
 
3493
- // src/platform/cli.ts
3494
- function readRawOptionValue(name, argv = process.argv) {
3495
- const flag = `--${name}`;
3496
- const prefix = `${flag}=`;
3497
- let value;
3498
- for (let i = 0;i < argv.length; i++) {
3499
- const arg = argv[i];
3500
- if (arg === "--")
3501
- break;
3502
- if (arg === flag && i + 1 < argv.length)
3503
- value = argv[i + 1];
3504
- else if (arg.startsWith(prefix))
3505
- value = arg.slice(prefix.length);
3506
- }
3507
- return value;
3508
- }
3509
-
3510
3518
  // src/platform/index.ts
3511
3519
  var init_platform = __esm(() => {
3512
3520
  init_accounts_store();
@@ -3515,6 +3523,7 @@ var init_platform = __esm(() => {
3515
3523
  init_input();
3516
3524
  init_output();
3517
3525
  init_errors();
3526
+ init_cli();
3518
3527
  });
3519
3528
 
3520
3529
  // src/features/verifiable/commands.ts
@@ -4207,7 +4216,7 @@ var init_complete = __esm(() => {
4207
4216
  // src/cli.ts
4208
4217
  import cac from "cac";
4209
4218
  // package.json
4210
- var version = "1.21.0";
4219
+ var version = "1.22.0";
4211
4220
 
4212
4221
  // src/commands/account.ts
4213
4222
  init_accounts_store();
@@ -4341,6 +4350,7 @@ function isValidParaId(value) {
4341
4350
  }
4342
4351
 
4343
4352
  // src/commands/account.ts
4353
+ init_cli();
4344
4354
  var ACCOUNT_HELP = `
4345
4355
  ${BOLD}Usage:${RESET}
4346
4356
  $ dot account add <name> <ss58|hex> Add a watch-only address (no secret)
@@ -4357,7 +4367,7 @@ ${BOLD}Usage:${RESET}
4357
4367
  $ dot account inspect --pallet-id <id> [--prefix <N>] Derive a pallet sovereign (no save — script-friendly)
4358
4368
  $ dot account inspect --parachain <id> --parachain-type <t> Derive a parachain sovereign (no save — script-friendly)
4359
4369
  $ dot account list List all accounts
4360
- $ dot account remove|delete <name> [name2] ... Remove stored account(s)
4370
+ $ dot account remove|delete|rm <name> [name2] ... Remove stored account(s)
4361
4371
 
4362
4372
  ${BOLD}Examples:${RESET}
4363
4373
  $ dot account add treasury 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
@@ -4395,7 +4405,7 @@ ${YELLOW}Note: Secrets are stored unencrypted in ~/.polkadot/accounts.json.
4395
4405
  Raw private keys cannot be HD-derived, so --path is rejected for them.${RESET}
4396
4406
  `.trimStart();
4397
4407
  function registerAccountCommands(cli) {
4398
- cli.command("account [action] [...names]", "Manage local accounts (create, import, list, remove, export)").alias("accounts").option("--secret <value>", "Secret for import: BIP39 mnemonic, 0x 32-byte hex seed, or 0x 64-byte raw private key").option("--env <varName>", "Environment variable name holding the secret").option("--path <derivation>", "Derivation path (e.g. //staking, //polkadot//0/wallet)").option("--parachain <id>", "Derive a parachain sovereign account (requires --parachain-type)").option("--parachain-type <type>", "Parachain sovereign type: child or sibling").option("--pallet-id <id>", "Derive a pallet sovereign account from an 8-byte PalletId").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").option("--file <path>", "Input/output file for batch import/export").option("--overwrite", "Overwrite existing accounts on batch import").option("--dry-run", "Preview batch import without applying changes").option("--include-secrets", "Include secrets in export (redacted by default)").option("--watch-only", "Export only watch-only accounts").option("--show-secret", "Reveal the 64-byte sr25519 expanded private key (inspect only)").action(async (action, names, opts) => {
4408
+ const command = cli.command("account [action] [...names]", "Manage local accounts (create, import, list, remove, export)").alias("accounts").option("--secret <value>", "Secret for import: BIP39 mnemonic, 0x 32-byte hex seed, or 0x 64-byte raw private key").option("--env <varName>", "Environment variable name holding the secret").option("--path <derivation>", "Derivation path (e.g. //staking, //polkadot//0/wallet)").option("--parachain <id>", "Derive a parachain sovereign account (requires --parachain-type)").option("--parachain-type <type>", "Parachain sovereign type: child or sibling").option("--pallet-id <id>", "Derive a pallet sovereign account from an 8-byte PalletId").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").option("--file <path>", "Input/output file for batch import/export").option("--overwrite", "Overwrite existing accounts on batch import").option("--dry-run", "Preview batch import without applying changes").option("--include-secrets", "Include secrets in export (redacted by default)").option("--watch-only", "Export only watch-only accounts").option("--show-secret", "Reveal the 64-byte sr25519 expanded private key (inspect only)").action(async (action, names, opts) => {
4399
4409
  if (!action) {
4400
4410
  if (process.argv[2] === "accounts")
4401
4411
  return accountList(opts);
@@ -4428,6 +4438,7 @@ function registerAccountCommands(cli) {
4428
4438
  return accountList(opts);
4429
4439
  case "delete":
4430
4440
  case "remove":
4441
+ case "rm":
4431
4442
  return accountRemove(names, opts);
4432
4443
  case "inspect":
4433
4444
  return accountInspect(names[0], opts);
@@ -4435,6 +4446,7 @@ function registerAccountCommands(cli) {
4435
4446
  return accountInspect(action, opts);
4436
4447
  }
4437
4448
  });
4449
+ withHelp(command, () => console.log(ACCOUNT_HELP));
4438
4450
  }
4439
4451
  async function accountCreate(name, opts) {
4440
4452
  if (!name) {
@@ -5528,6 +5540,7 @@ async function fetchRpcMethods(rpcUrl) {
5528
5540
 
5529
5541
  // src/commands/chain.ts
5530
5542
  init_rpc_registry();
5543
+ init_cli();
5531
5544
  var CHAIN_HELP = `
5532
5545
  ${BOLD}Usage:${RESET}
5533
5546
  $ dot chain add <name> --rpc <url> Add a chain via WebSocket RPC
@@ -5561,7 +5574,7 @@ ${BOLD}Examples:${RESET}
5561
5574
  $ dot chain import my-chains.json --no-metadata
5562
5575
  `.trimStart();
5563
5576
  function registerChainCommands(cli) {
5564
- cli.command("chain [action] [...names]", "Manage chains (add, remove, update, list, export, import)").alias("chains").option("--all", "Update/export all configured chains").option("--relay <name>", "Parent relay chain for this parachain").option("--parachain-id <id>", "Parachain ID (auto-detected if omitted with --relay)").option("--file <path>", "Output/input file for export/import").option("--overwrite", "Overwrite existing chains on import").option("--dry-run", "Preview import without applying changes").option("--no-metadata", "Skip automatic metadata fetch after import").option("-v, --verbose", "Show RPC endpoints in `chains` list output").action(async (action, names, opts) => {
5577
+ const command = cli.command("chain [action] [...names]", "Manage chains (add, remove, update, list, export, import)").alias("chains").option("--all", "Update/export all configured chains").option("--relay <name>", "Parent relay chain for this parachain").option("--parachain-id <id>", "Parachain ID (auto-detected if omitted with --relay)").option("--file <path>", "Output/input file for export/import").option("--overwrite", "Overwrite existing chains on import").option("--dry-run", "Preview import without applying changes").option("--no-metadata", "Skip automatic metadata fetch after import").option("-v, --verbose", "Show RPC endpoints in `chains` list output").action(async (action, names, opts) => {
5565
5578
  if (!action) {
5566
5579
  if (process.argv[2] === "chains")
5567
5580
  return chainList(opts);
@@ -5595,6 +5608,7 @@ function registerChainCommands(cli) {
5595
5608
  }
5596
5609
  }
5597
5610
  });
5611
+ withHelp(command, () => console.log(CHAIN_HELP));
5598
5612
  }
5599
5613
  async function refreshRpcMethods(chainName, rpcUrl, silent = false) {
5600
5614
  try {
@@ -6036,6 +6050,7 @@ async function chainImport(filePath, opts) {
6036
6050
  }
6037
6051
 
6038
6052
  // src/commands/completions.ts
6053
+ init_cli();
6039
6054
  var ZSH_SCRIPT = `_dot_completions() {
6040
6055
  emulate -L zsh
6041
6056
  local -a completions
@@ -6104,7 +6119,7 @@ var SCRIPTS = {
6104
6119
  fish: FISH_SCRIPT
6105
6120
  };
6106
6121
  function registerCompletionsCommand(cli) {
6107
- cli.command("completions <shell>", "Generate shell completion script (zsh, bash, fish)").action((shell) => {
6122
+ const command = cli.command("completions <shell>", "Generate shell completion script (zsh, bash, fish)").action((shell) => {
6108
6123
  const script = SCRIPTS[shell];
6109
6124
  if (!script) {
6110
6125
  console.error(`Unsupported shell "${shell}". Supported: ${Object.keys(SCRIPTS).join(", ")}`);
@@ -6117,6 +6132,7 @@ function registerCompletionsCommand(cli) {
6117
6132
  }
6118
6133
  console.log(script);
6119
6134
  });
6135
+ withHelp(command);
6120
6136
  }
6121
6137
 
6122
6138
  // src/commands/const.ts
@@ -6894,6 +6910,7 @@ async function handleExtensions(target, opts) {
6894
6910
  init_hash();
6895
6911
  init_input();
6896
6912
  init_output();
6913
+ init_cli();
6897
6914
  init_errors();
6898
6915
  function printAlgorithmHelp() {
6899
6916
  console.log(`${BOLD}Usage:${RESET} dot hash <algorithm> <data> [options]
@@ -6915,7 +6932,7 @@ ${BOLD}Examples:${RESET}`);
6915
6932
  console.log(` ${DIM}$ echo -n "hello" | dot hash sha256 --stdin${RESET}`);
6916
6933
  }
6917
6934
  function registerHashCommand(cli) {
6918
- cli.command("hash [algorithm] [data]", "Compute cryptographic hashes").option("--file <path>", "Hash file contents (raw bytes)").option("--stdin", "Read data from stdin").action(async (algorithm, data, opts) => {
6935
+ const command = cli.command("hash [algorithm] [data]", "Compute cryptographic hashes").option("--file <path>", "Hash file contents (raw bytes)").option("--stdin", "Read data from stdin").action(async (algorithm, data, opts) => {
6919
6936
  if (!algorithm) {
6920
6937
  printAlgorithmHelp();
6921
6938
  return;
@@ -6936,6 +6953,7 @@ function registerHashCommand(cli) {
6936
6953
  console.log(hexHash);
6937
6954
  }
6938
6955
  });
6956
+ withHelp(command, printAlgorithmHelp);
6939
6957
  }
6940
6958
 
6941
6959
  // src/commands/inspect.ts
@@ -6944,6 +6962,7 @@ init_client();
6944
6962
  init_metadata();
6945
6963
  init_output();
6946
6964
  init_pretty_type();
6965
+ init_cli();
6947
6966
 
6948
6967
  // src/utils/parse-target.ts
6949
6968
  function parseTarget(input, options) {
@@ -6996,7 +7015,7 @@ function resolveTargetChain(target, chainFlag) {
6996
7015
 
6997
7016
  // src/commands/inspect.ts
6998
7017
  function registerInspectCommand(cli) {
6999
- cli.command("inspect [target]", "Inspect chain metadata (pallets, storage, constants, calls, events, errors)").alias("explore").option("--chain <name>", "Target chain").option("--rpc <url>", "Override RPC endpoint").action(async (target, opts) => {
7018
+ const command = cli.command("inspect [target]", "Inspect chain metadata (pallets, storage, constants, calls, events, errors)").alias("explore").option("--chain <name>", "Target chain").option("--rpc <url>", "Override RPC endpoint").action(async (target, opts) => {
7000
7019
  const config = await loadConfig();
7001
7020
  const knownChains = Object.keys(config.chains);
7002
7021
  let effectiveChain = opts.chain;
@@ -7364,6 +7383,7 @@ function registerInspectCommand(cli) {
7364
7383
  ];
7365
7384
  throw new Error(suggestMessage(`item in ${pallet.name}`, itemName, allItems));
7366
7385
  });
7386
+ withHelp(command);
7367
7387
  }
7368
7388
 
7369
7389
  // src/commands/metadata.ts
@@ -7371,6 +7391,7 @@ init_store();
7371
7391
  init_client();
7372
7392
  init_metadata();
7373
7393
  init_output();
7394
+ init_cli();
7374
7395
  init_errors();
7375
7396
  function buildMetadataPayload(chainName, meta, fingerprint) {
7376
7397
  return {
@@ -7413,12 +7434,14 @@ async function handleMetadata(chain, opts) {
7413
7434
  `);
7414
7435
  }
7415
7436
  function registerMetadataCommand(cli) {
7416
- cli.command("metadata <chain>", "Fetch chain metadata (decoded JSON; --raw for SCALE hex)").option("--raw", "Print SCALE-encoded metadata bytes as hex instead of decoded JSON").option("--cached", "Use cached metadata instead of fetching fresh from the chain").option("--rpc <url>", "Override RPC endpoint(s)").action((chain, opts) => handleMetadata(chain, opts));
7437
+ const command = cli.command("metadata <chain>", "Fetch chain metadata (decoded JSON; --raw for SCALE hex)").option("--raw", "Print SCALE-encoded metadata bytes as hex instead of decoded JSON").option("--cached", "Use cached metadata instead of fetching fresh from the chain").option("--rpc <url>", "Override RPC endpoint(s)").action((chain, opts) => handleMetadata(chain, opts));
7438
+ withHelp(command);
7417
7439
  }
7418
7440
 
7419
7441
  // src/commands/parachain.ts
7420
7442
  init_accounts();
7421
7443
  init_output();
7444
+ init_cli();
7422
7445
  init_errors();
7423
7446
  function printParachainHelp() {
7424
7447
  console.log(`${BOLD}Usage:${RESET} dot parachain <paraId> [options]
@@ -7447,7 +7470,7 @@ function validateType(type) {
7447
7470
  throw new CliError(`Unknown account type "${type}". Valid types: child, sibling.`);
7448
7471
  }
7449
7472
  function registerParachainCommand(cli) {
7450
- cli.command("parachain [paraId]", "Derive parachain sovereign accounts").option("--type <type>", "Account type: child, sibling (default: both)").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").action(async (paraIdStr, opts) => {
7473
+ const command = cli.command("parachain [paraId]", "Derive parachain sovereign accounts").option("--type <type>", "Account type: child, sibling (default: both)").option("--prefix <number>", "SS58 prefix for address encoding (default: 42)").action(async (paraIdStr, opts) => {
7451
7474
  console.error("Warning: `dot parachain` is deprecated; use `dot account inspect --parachain <id> --parachain-type <child|sibling>` instead. Will be removed in a future release.");
7452
7475
  if (!paraIdStr) {
7453
7476
  printParachainHelp();
@@ -7487,6 +7510,7 @@ function registerParachainCommand(cli) {
7487
7510
  }
7488
7511
  }
7489
7512
  });
7513
+ withHelp(command, printParachainHelp);
7490
7514
  }
7491
7515
 
7492
7516
  // src/commands/query.ts
@@ -7831,6 +7855,7 @@ init_accounts();
7831
7855
  init_hash();
7832
7856
  init_input();
7833
7857
  init_output();
7858
+ init_cli();
7834
7859
  init_errors();
7835
7860
  var SUPPORTED_TYPES = ["sr25519"];
7836
7861
  function isSupportedType(type) {
@@ -7863,7 +7888,7 @@ ${BOLD}Examples:${RESET}`);
7863
7888
  console.log(` ${DIM}$ dot sign "hello" --from alice --output json${RESET}`);
7864
7889
  }
7865
7890
  function registerSignCommand(cli) {
7866
- cli.command("sign [message]", "Sign a message with an account keypair").option("--from <name>", "Account to sign with").option("--type <algo>", "Signature type (default: sr25519)").option("--file <path>", "Sign file contents (raw bytes)").option("--stdin", "Read data from stdin").action(async (message, opts) => {
7891
+ const command = cli.command("sign [message]", "Sign a message with an account keypair").option("--from <name>", "Account to sign with").option("--type <algo>", "Signature type (default: sr25519)").option("--file <path>", "Sign file contents (raw bytes)").option("--stdin", "Read data from stdin").action(async (message, opts) => {
7867
7892
  if (!message && !opts.file && !opts.stdin) {
7868
7893
  printSignHelp();
7869
7894
  return;
@@ -7897,6 +7922,7 @@ function registerSignCommand(cli) {
7897
7922
  console.log(` ${BOLD}Enum:${RESET} ${result.enum}`);
7898
7923
  }
7899
7924
  });
7925
+ withHelp(command, printSignHelp);
7900
7926
  }
7901
7927
 
7902
7928
  // src/commands/tx.ts
@@ -9354,6 +9380,7 @@ function watchTransactionJson(observable, level, options) {
9354
9380
  init_store();
9355
9381
  init_workspace();
9356
9382
  init_output();
9383
+ init_cli();
9357
9384
  init_errors();
9358
9385
  import { mkdir as mkdir3, stat } from "node:fs/promises";
9359
9386
  import { homedir as homedir3 } from "node:os";
@@ -9407,8 +9434,10 @@ Source: ${SOURCE_LABELS[resolved.source]}
9407
9434
  `);
9408
9435
  }
9409
9436
  function registerWorkspaceCommands(cli) {
9410
- cli.command("init", "Initialize a local .polkadot workspace in the current directory").action(() => handleInit());
9411
- cli.command("which", "Show the active config root (workspace, DOT_HOME, or global)").action((opts) => handleWhich(opts));
9437
+ const initCommand = cli.command("init", "Initialize a local .polkadot workspace in the current directory").action(() => handleInit());
9438
+ withHelp(initCommand);
9439
+ const whichCommand = cli.command("which", "Show the active config root (workspace, DOT_HOME, or global)").action((opts) => handleWhich(opts));
9440
+ withHelp(whichCommand);
9412
9441
  }
9413
9442
 
9414
9443
  // src/config/store.ts
@@ -9469,6 +9498,30 @@ async function saveConfig2(config) {
9469
9498
  `);
9470
9499
  }
9471
9500
 
9501
+ // src/core/dry-run.ts
9502
+ init_output();
9503
+ function isGlobalDryRun() {
9504
+ const raw = process.env.DOT_DRY_RUN?.trim().toLowerCase();
9505
+ if (raw === undefined || raw === "")
9506
+ return false;
9507
+ return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
9508
+ }
9509
+ function resolveDryRun(explicitFlag, decodeOnly = false) {
9510
+ if (explicitFlag !== undefined)
9511
+ return explicitFlag;
9512
+ if (decodeOnly)
9513
+ return false;
9514
+ return isGlobalDryRun();
9515
+ }
9516
+ var hintPrinted = false;
9517
+ function printGlobalDryRunHint() {
9518
+ if (hintPrinted)
9519
+ return;
9520
+ hintPrinted = true;
9521
+ process.stderr.write(`${YELLOW}${BOLD}⚠ DOT_DRY_RUN is set${RESET}${YELLOW} — extrinsics will be simulated, not submitted.${RESET}
9522
+ `);
9523
+ }
9524
+
9472
9525
  // src/core/file-loader.ts
9473
9526
  init_errors();
9474
9527
  import { access as access4, readFile as readFile7 } from "node:fs/promises";
@@ -9796,7 +9849,7 @@ var RAW_STRING_FLAGS = [
9796
9849
  ["member", "member"]
9797
9850
  ];
9798
9851
  function registerVerifiableCommands(cli) {
9799
- cli.command("verifiable [action] [...rest]", "Bandersnatch member keys, ring-VRF proofs, signing and verification").option("--entropy-key <key>", "Entropy-derivation key (omit = lite, 'candidate' = full)").option("--context <value>", "32-byte ring/proof context (alias/prove/verify)").option("--message <data>", "Message to sign/bind/verify (text or 0x hex)").option("--file <path>", "Read message from a file (raw bytes)").option("--stdin", "Read message from stdin").option("--members <hex|file>", "SCALE-encoded Vec<[u8;32]> ring (prove/verify)").option("--root <hex>", "768-byte ring root/commitment (verify)").option("--proof <hex>", "Ring-VRF proof bytes (verify)").option("--signature <hex>", "Bandersnatch signature (verify-sig)").option("--member <hex>", "32-byte member public key (verify-sig)").option("--ring-exponent <n>", "Ring exponent: 9 (default), 10, or 14").action(async (action, rest, opts) => {
9852
+ const command = cli.command("verifiable [action] [...rest]", "Bandersnatch member keys, ring-VRF proofs, signing and verification").option("--entropy-key <key>", "Entropy-derivation key (omit = lite, 'candidate' = full)").option("--context <value>", "32-byte ring/proof context (alias/prove/verify)").option("--message <data>", "Message to sign/bind/verify (text or 0x hex)").option("--file <path>", "Read message from a file (raw bytes)").option("--stdin", "Read message from stdin").option("--members <hex|file>", "SCALE-encoded Vec<[u8;32]> ring (prove/verify)").option("--root <hex>", "768-byte ring root/commitment (verify)").option("--proof <hex>", "Ring-VRF proof bytes (verify)").option("--signature <hex>", "Bandersnatch signature (verify-sig)").option("--member <hex>", "32-byte member public key (verify-sig)").option("--ring-exponent <n>", "Ring exponent: 9 (default), 10, or 14").action(async (action, rest, opts) => {
9800
9853
  if (!action) {
9801
9854
  console.log(VERIFIABLE_HELP);
9802
9855
  return;
@@ -9809,9 +9862,19 @@ function registerVerifiableCommands(cli) {
9809
9862
  const { runVerifiable: runVerifiable2 } = await Promise.resolve().then(() => (init_commands(), exports_commands));
9810
9863
  return runVerifiable2(action, rest, opts);
9811
9864
  });
9865
+ withHelp(command, () => console.log(VERIFIABLE_HELP));
9812
9866
  }
9813
9867
 
9814
9868
  // src/platform/cli.ts
9869
+ var HELP_PRINTER2 = Symbol.for("polkadot-cli.helpPrinter");
9870
+ function printMatchedCommandHelp(cli) {
9871
+ const matched = cli.matchedCommand;
9872
+ const printer = matched?.[HELP_PRINTER2];
9873
+ if (!printer)
9874
+ return false;
9875
+ printer();
9876
+ return true;
9877
+ }
9815
9878
  function registerGlobalOptions(cli) {
9816
9879
  cli.option("--chain <name>", "Target chain (required)");
9817
9880
  cli.option("--rpc <url>", "Override RPC endpoint for this call");
@@ -10060,12 +10123,17 @@ if (process.argv[2] === "__complete") {
10060
10123
  };
10061
10124
  const target2 = `${cmd.pallet}.${cmd.item}`;
10062
10125
  switch (cmd.category) {
10063
- case "tx":
10126
+ case "tx": {
10127
+ const fileDecodeOnly = Boolean(opts.encode || opts.toYaml || opts.toJson);
10128
+ const fileDryRun = resolveDryRun(opts.dryRun, fileDecodeOnly);
10129
+ if (fileDryRun && isGlobalDryRun() && opts.dryRun === undefined) {
10130
+ printGlobalDryRunHint();
10131
+ }
10064
10132
  await handleTx(target2, args, {
10065
10133
  ...handlerOpts2,
10066
10134
  from: opts.from,
10067
10135
  unsigned: opts.unsigned ?? cmd.unsigned,
10068
- dryRun: opts.dryRun,
10136
+ dryRun: fileDryRun,
10069
10137
  encode: opts.encode,
10070
10138
  toYaml: opts.toYaml,
10071
10139
  toJson: opts.toJson,
@@ -10079,6 +10147,7 @@ if (process.argv[2] === "__complete") {
10079
10147
  parsedArgs: cmd.args
10080
10148
  });
10081
10149
  break;
10150
+ }
10082
10151
  case "query":
10083
10152
  await handleQuery(target2, args, {
10084
10153
  ...handlerOpts2,
@@ -10135,11 +10204,16 @@ if (process.argv[2] === "__complete") {
10135
10204
  await handleQuery(target, args, { ...handlerOpts, dump: opts.dump, at: atRaw });
10136
10205
  break;
10137
10206
  case "tx": {
10207
+ const decodeOnly = Boolean(opts.encode || opts.toYaml || opts.toJson);
10208
+ const dryRun = resolveDryRun(opts.dryRun, decodeOnly);
10209
+ if (dryRun && isGlobalDryRun() && opts.dryRun === undefined) {
10210
+ printGlobalDryRunHint();
10211
+ }
10138
10212
  const txOpts = {
10139
10213
  ...handlerOpts,
10140
10214
  from: opts.from,
10141
10215
  unsigned: opts.unsigned,
10142
- dryRun: opts.dryRun,
10216
+ dryRun,
10143
10217
  encode: opts.encode,
10144
10218
  toYaml: opts.toYaml,
10145
10219
  toJson: opts.toJson,
@@ -10224,7 +10298,9 @@ if (process.argv[2] === "__complete") {
10224
10298
  if (cli.options.version) {
10225
10299
  await showUpdateAndExit(0);
10226
10300
  } else if (cli.options.help) {
10227
- if (cli.matchedCommand) {
10301
+ if (printMatchedCommandHelp(cli)) {
10302
+ await showUpdateAndExit(0);
10303
+ } else if (cli.matchedCommand) {
10228
10304
  const result = cli.runMatchedCommand();
10229
10305
  if (result && typeof result.then === "function") {
10230
10306
  await result.then(() => showUpdateAndExit(0), handleError);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polkadot-cli",
3
- "version": "1.21.0",
3
+ "version": "1.22.0",
4
4
  "description": "CLI tool for querying Polkadot-ecosystem on-chain state",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,8 +21,7 @@
21
21
  "test:coverage": "bun test --concurrent --coverage --coverage-reporter=lcov --coverage-dir=coverage",
22
22
  "prepare": "husky",
23
23
  "changeset": "changeset",
24
- "version": "changeset version",
25
- "release": "changeset publish"
24
+ "version": "changeset version"
26
25
  },
27
26
  "license": "MIT",
28
27
  "keywords": [
@@ -34,7 +33,7 @@
34
33
  ],
35
34
  "repository": {
36
35
  "type": "git",
37
- "url": "git+https://github.com/peetzweg/polkadot-cli.git"
36
+ "url": "git+https://github.com/paritytech/polkadot-cli.git"
38
37
  },
39
38
  "dependencies": {
40
39
  "@noble/hashes": "^2.0.1",
@@ -45,9 +44,9 @@
45
44
  "@polkadot-labs/hdkd": "^0.0.28",
46
45
  "@polkadot-labs/hdkd-helpers": "^0.0.29",
47
46
  "@scure/sr25519": "^1.0.0",
48
- "cac": "^6.7.14",
49
- "polkadot-api": "^2.1.4",
50
- "verifiablejs": "1.3.0",
47
+ "cac": "^7.0.0",
48
+ "polkadot-api": "^2.1.7",
49
+ "verifiablejs": "1.4.0",
51
50
  "yaml": "^2.8.3"
52
51
  },
53
52
  "devDependencies": {