polkadot-cli 1.9.0 → 1.11.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 +38 -2
  2. package/dist/cli.mjs +131 -29
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -478,8 +478,10 @@ dot tx Balances.transferKeepAlive 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694
478
478
  # Submit a raw SCALE-encoded call (e.g. from a multisig proposal or another tool)
479
479
  dot tx 0x0503008eaf04151687736326c9fea17e25fc5287613693c912909cb226aa4794f26a48 --from alice
480
480
 
481
- # Batch multiple transfers with Utility.batchAll
482
- 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
481
+ # Batch multiple transfers with Utility.batchAll (comma-separated encoded calls)
482
+ A=$(dot tx Balances.transfer_keep_alive 5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty 1000000000000 --encode)
483
+ B=$(dot tx Balances.transfer_keep_alive 5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y 2000000000000 --encode)
484
+ dot tx Utility.batchAll $A,$B --from alice
483
485
  ```
484
486
 
485
487
  #### Enum shorthand
@@ -617,6 +619,40 @@ For manual override, use `--ext` with a JSON object:
617
619
  dot tx System.remark 0xdeadbeef --from alice --ext '{"MyExtension":{"value":"..."}}'
618
620
  ```
619
621
 
622
+ #### Transaction options
623
+
624
+ Override low-level transaction parameters. Useful for rapid-fire submission (custom nonce), priority fees (tip), or controlling transaction lifetime (mortality).
625
+
626
+ | Flag | Value | Description |
627
+ |------|-------|-------------|
628
+ | `--nonce <n>` | non-negative integer | Override the auto-detected nonce |
629
+ | `--tip <amount>` | non-negative integer (planck) | Priority tip for the transaction pool |
630
+ | `--mortality <spec>` | `immortal` or period (min 4) | Transaction mortality window |
631
+ | `--at <block>` | `best`, `finalized`, or 0x-prefixed block hash | Block state to validate against |
632
+
633
+ ```bash
634
+ # Fire-and-forget: submit two txs in rapid succession with manual nonces
635
+ dot tx System.remark 0xdead --from alice --nonce 0 --wait broadcast
636
+ dot tx System.remark 0xbeef --from alice --nonce 1 --wait broadcast
637
+
638
+ # Add a priority tip (in planck)
639
+ dot tx Balances.transferKeepAlive 5FHneW46... 1000000000000 --from alice --tip 1000000
640
+
641
+ # Submit an immortal transaction (no expiry)
642
+ dot tx System.remark 0xdead --from alice --mortality immortal
643
+
644
+ # Set a custom mortality period (rounds up to nearest power of two)
645
+ dot tx System.remark 0xdead --from alice --mortality 128
646
+
647
+ # Validate against the best (not finalized) block
648
+ dot tx System.remark 0xdead --from alice --at best
649
+
650
+ # Combine: rapid-fire with tip and broadcast-only
651
+ dot tx System.remark 0xdead --from alice --nonce 5 --tip 500000 --wait broadcast
652
+ ```
653
+
654
+ When set, nonce / tip / mortality / at are shown in both `--dry-run` and submission output. These flags are silently ignored with `--encode`, `--yaml`, and `--json` (which return before signing).
655
+
620
656
  ### File-based commands
621
657
 
622
658
  Run any `dot` command from a YAML or JSON file. Especially useful for complex calls like XCM messages that are hard to construct inline.
package/dist/cli.mjs CHANGED
@@ -1023,8 +1023,12 @@ function typeHint(entry, meta) {
1023
1023
  case "tuple":
1024
1024
  return "a JSON array";
1025
1025
  case "sequence":
1026
- case "array":
1027
- return "a JSON array or hex-encoded bytes";
1026
+ case "array": {
1027
+ const inner = resolved.value;
1028
+ if (inner?.type === "primitive" && inner.value === "u8")
1029
+ return "hex-encoded bytes or text";
1030
+ return "a JSON array, comma-separated values, or hex-encoded bytes";
1031
+ }
1028
1032
  default:
1029
1033
  return describeType(meta.lookup, entry.id);
1030
1034
  }
@@ -1233,6 +1237,10 @@ async function parseTypedArg(meta, entry, arg) {
1233
1237
  return normalizeValue(meta.lookup, entry, JSON.parse(arg));
1234
1238
  } catch {}
1235
1239
  }
1240
+ if (arg.includes(",")) {
1241
+ const elements = arg.split(",");
1242
+ return Promise.all(elements.map((el) => parseTypedArg(meta, inner, el.trim())));
1243
+ }
1236
1244
  if (/^0x[0-9a-fA-F]*$/.test(arg))
1237
1245
  return Binary2.fromHex(arg);
1238
1246
  return parseValue(arg);
@@ -2172,14 +2180,24 @@ var init_complete = __esm(() => {
2172
2180
  "inspect"
2173
2181
  ];
2174
2182
  GLOBAL_OPTIONS = ["--chain", "--rpc", "--light-client", "--output", "--help", "--version"];
2175
- TX_OPTIONS = ["--from", "--dry-run", "--encode", "--ext", "--wait"];
2183
+ TX_OPTIONS = [
2184
+ "--from",
2185
+ "--dry-run",
2186
+ "--encode",
2187
+ "--ext",
2188
+ "--wait",
2189
+ "--nonce",
2190
+ "--tip",
2191
+ "--mortality",
2192
+ "--at"
2193
+ ];
2176
2194
  QUERY_OPTIONS = ["--limit"];
2177
2195
  });
2178
2196
 
2179
2197
  // src/cli.ts
2180
2198
  import cac from "cac";
2181
2199
  // package.json
2182
- var version = "1.9.0";
2200
+ var version = "1.11.0";
2183
2201
 
2184
2202
  // src/commands/account.ts
2185
2203
  init_accounts_store();
@@ -4043,6 +4061,50 @@ function parseWaitLevel(raw) {
4043
4061
  throw new CliError(`Invalid --wait value "${raw}". Valid: broadcast, best-block, best, finalized`);
4044
4062
  }
4045
4063
  }
4064
+ function parseNonceOption(raw) {
4065
+ if (raw === undefined)
4066
+ return;
4067
+ const n = Number(raw);
4068
+ if (!Number.isInteger(n) || n < 0) {
4069
+ throw new CliError(`Invalid --nonce value "${raw}". Must be a non-negative integer.`);
4070
+ }
4071
+ return n;
4072
+ }
4073
+ function parseTipOption(raw) {
4074
+ if (raw === undefined)
4075
+ return;
4076
+ try {
4077
+ const t = BigInt(raw);
4078
+ if (t < 0n) {
4079
+ throw new CliError(`Invalid --tip value "${raw}". Must be a non-negative integer.`);
4080
+ }
4081
+ return t;
4082
+ } catch (err) {
4083
+ if (err instanceof CliError)
4084
+ throw err;
4085
+ throw new CliError(`Invalid --tip value "${raw}". Must be a non-negative integer.`);
4086
+ }
4087
+ }
4088
+ function parseMortalityOption(raw) {
4089
+ if (raw === undefined)
4090
+ return;
4091
+ if (raw === "immortal")
4092
+ return { mortal: false };
4093
+ const n = Number(raw);
4094
+ if (!Number.isInteger(n) || n < 4) {
4095
+ throw new CliError(`Invalid --mortality value "${raw}". Use "immortal" or a period number (minimum 4).`);
4096
+ }
4097
+ return { mortal: true, period: n };
4098
+ }
4099
+ function parseAtOption(raw) {
4100
+ if (raw === undefined)
4101
+ return;
4102
+ if (raw === "best" || raw === "finalized")
4103
+ return raw;
4104
+ if (/^0x[0-9a-fA-F]{64}$/.test(raw))
4105
+ return raw;
4106
+ throw new CliError(`Invalid --at value "${raw}". Use "best", "finalized", or a 0x-prefixed 32-byte block hash.`);
4107
+ }
4046
4108
  async function handleTx(target, args, opts) {
4047
4109
  if (!target) {
4048
4110
  const config2 = await loadConfig();
@@ -4131,10 +4193,25 @@ async function handleTx(target, args, opts) {
4131
4193
  }
4132
4194
  let unsafeApi;
4133
4195
  let txOptions;
4196
+ const nonce = parseNonceOption(opts.nonce);
4197
+ const tip = parseTipOption(opts.tip);
4198
+ const mortality = parseMortalityOption(opts.mortality);
4199
+ const at = parseAtOption(opts.at);
4134
4200
  if (!decodeOnly) {
4135
4201
  const userExtOverrides = parseExtOption(opts.ext);
4136
4202
  const customSignedExtensions = buildCustomSignedExtensions(meta, userExtOverrides);
4137
- txOptions = Object.keys(customSignedExtensions).length > 0 ? { customSignedExtensions } : undefined;
4203
+ const built = {};
4204
+ if (Object.keys(customSignedExtensions).length > 0)
4205
+ built.customSignedExtensions = customSignedExtensions;
4206
+ if (nonce !== undefined)
4207
+ built.nonce = nonce;
4208
+ if (tip !== undefined)
4209
+ built.tip = tip;
4210
+ if (mortality !== undefined)
4211
+ built.mortality = mortality;
4212
+ if (at !== undefined)
4213
+ built.at = at;
4214
+ txOptions = Object.keys(built).length > 0 ? built : undefined;
4138
4215
  unsafeApi = clientHandle?.client.getUnsafeApi();
4139
4216
  }
4140
4217
  let tx;
@@ -4189,6 +4266,14 @@ async function handleTx(target, args, opts) {
4189
4266
  console.log(` ${BOLD}From:${RESET} ${opts.from} (${signerAddress})`);
4190
4267
  console.log(` ${BOLD}Call:${RESET} ${callHex}`);
4191
4268
  console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
4269
+ if (nonce !== undefined)
4270
+ console.log(` ${BOLD}Nonce:${RESET} ${nonce}`);
4271
+ if (tip !== undefined)
4272
+ console.log(` ${BOLD}Tip:${RESET} ${tip}`);
4273
+ if (mortality !== undefined)
4274
+ console.log(` ${BOLD}Mortality:${RESET} ${mortality.mortal ? `mortal (period ${mortality.period})` : "immortal"}`);
4275
+ if (at !== undefined)
4276
+ console.log(` ${BOLD}At:${RESET} ${at}`);
4192
4277
  try {
4193
4278
  const fees = await tx.getEstimatedFees(signer?.publicKey, txOptions);
4194
4279
  console.log(` ${BOLD}Estimated fees:${RESET} ${fees}`);
@@ -4204,6 +4289,14 @@ async function handleTx(target, args, opts) {
4204
4289
  console.log(` ${BOLD}Chain:${RESET} ${chainName}`);
4205
4290
  console.log(` ${BOLD}Call:${RESET} ${callHex}`);
4206
4291
  console.log(` ${BOLD}Decode:${RESET} ${decodedStr}`);
4292
+ if (nonce !== undefined)
4293
+ console.log(` ${BOLD}Nonce:${RESET} ${nonce}`);
4294
+ if (tip !== undefined)
4295
+ console.log(` ${BOLD}Tip:${RESET} ${tip}`);
4296
+ if (mortality !== undefined)
4297
+ console.log(` ${BOLD}Mortality:${RESET} ${mortality.mortal ? `mortal (period ${mortality.period})` : "immortal"}`);
4298
+ if (at !== undefined)
4299
+ console.log(` ${BOLD}At:${RESET} ${at}`);
4207
4300
  console.log(` ${BOLD}Tx:${RESET} ${result.txHash}`);
4208
4301
  if (result.type === "broadcasted") {
4209
4302
  console.log(` ${BOLD}Status:${RESET} ${GREEN}broadcasted${RESET}`);
@@ -4565,8 +4658,12 @@ function typeHint2(entry, meta) {
4565
4658
  case "tuple":
4566
4659
  return "a JSON array";
4567
4660
  case "sequence":
4568
- case "array":
4569
- return "a JSON array or hex-encoded bytes";
4661
+ case "array": {
4662
+ const inner = resolved.value;
4663
+ if (inner?.type === "primitive" && inner.value === "u8")
4664
+ return "hex-encoded bytes or text";
4665
+ return "a JSON array, comma-separated values, or hex-encoded bytes";
4666
+ }
4570
4667
  default:
4571
4668
  return describeType(meta.lookup, entry.id);
4572
4669
  }
@@ -4795,6 +4892,10 @@ async function parseTypedArg2(meta, entry, arg) {
4795
4892
  return normalizeValue2(meta.lookup, entry, JSON.parse(arg));
4796
4893
  } catch {}
4797
4894
  }
4895
+ if (arg.includes(",")) {
4896
+ const elements = arg.split(",");
4897
+ return Promise.all(elements.map((el) => parseTypedArg2(meta, inner, el.trim())));
4898
+ }
4798
4899
  if (/^0x[0-9a-fA-F]*$/.test(arg))
4799
4900
  return Binary3.fromHex(arg);
4800
4901
  return parseValue(arg);
@@ -5421,7 +5522,7 @@ if (process.argv[2] === "__complete") {
5421
5522
  default: "finalized"
5422
5523
  }).option("--limit <n>", "Max entries to return for map queries (0 = unlimited)", {
5423
5524
  default: 100
5424
- }).option("--dump", "Dump all entries of a storage map (without specifying a key)").option("--var <kv>", "Template variable for file input (KEY=VALUE, repeatable)").action(async (dotpath, args, opts) => {
5525
+ }).option("--dump", "Dump all entries of a storage map (without specifying a key)").option("--var <kv>", "Template variable for file input (KEY=VALUE, repeatable)").option("--nonce <n>", "Custom nonce for manual tx sequencing (for tx)").option("--tip <amount>", "Tip to prioritize transaction (for tx)").option("--mortality <spec>", '"immortal" or period number (for tx)').option("--at <block>", 'Block hash, "best", or "finalized" to validate against (for tx)').action(async (dotpath, args, opts) => {
5425
5526
  if (!dotpath) {
5426
5527
  printHelp();
5427
5528
  return;
@@ -5443,6 +5544,10 @@ if (process.argv[2] === "__complete") {
5443
5544
  json: opts.json,
5444
5545
  ext: opts.ext,
5445
5546
  wait: opts.wait,
5547
+ nonce: opts.nonce,
5548
+ tip: opts.tip,
5549
+ mortality: opts.mortality,
5550
+ at: opts.at,
5446
5551
  parsedArgs: cmd.args
5447
5552
  });
5448
5553
  break;
@@ -5494,31 +5599,28 @@ if (process.argv[2] === "__complete") {
5494
5599
  case "query":
5495
5600
  await handleQuery(target, args, { ...handlerOpts, limit: opts.limit, dump: opts.dump });
5496
5601
  break;
5497
- case "tx":
5602
+ case "tx": {
5603
+ const txOpts = {
5604
+ ...handlerOpts,
5605
+ from: opts.from,
5606
+ dryRun: opts.dryRun,
5607
+ encode: opts.encode,
5608
+ yaml: opts.yaml,
5609
+ json: opts.json,
5610
+ ext: opts.ext,
5611
+ wait: opts.wait,
5612
+ nonce: opts.nonce,
5613
+ tip: opts.tip,
5614
+ mortality: opts.mortality,
5615
+ at: opts.at
5616
+ };
5498
5617
  if (parsed.pallet && /^0x[0-9a-fA-F]+$/.test(parsed.pallet)) {
5499
- await handleTx(parsed.pallet, args, {
5500
- ...handlerOpts,
5501
- from: opts.from,
5502
- dryRun: opts.dryRun,
5503
- encode: opts.encode,
5504
- yaml: opts.yaml,
5505
- json: opts.json,
5506
- ext: opts.ext,
5507
- wait: opts.wait
5508
- });
5618
+ await handleTx(parsed.pallet, args, txOpts);
5509
5619
  } else {
5510
- await handleTx(target, args, {
5511
- ...handlerOpts,
5512
- from: opts.from,
5513
- dryRun: opts.dryRun,
5514
- encode: opts.encode,
5515
- yaml: opts.yaml,
5516
- json: opts.json,
5517
- ext: opts.ext,
5518
- wait: opts.wait
5519
- });
5620
+ await handleTx(target, args, txOpts);
5520
5621
  }
5521
5622
  break;
5623
+ }
5522
5624
  case "const":
5523
5625
  await handleConst(target, handlerOpts);
5524
5626
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polkadot-cli",
3
- "version": "1.9.0",
3
+ "version": "1.11.0",
4
4
  "description": "CLI tool for querying Polkadot-ecosystem on-chain state",
5
5
  "type": "module",
6
6
  "bin": {